From 3b505b2ee4c1ded67fee19dfefe28faf659e9808 Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Mon, 8 Mar 2021 13:51:10 +0000 Subject: [PATCH 01/21] Update version and add notes for v1.9.1 --- CHANGELOG | 20 ++++++++++++++++++++ meson.build | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 2cf4d9c..601f945 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,24 @@ +Changes in Rubber Band v1.9.1 + + * Switch build system from Makefiles and Visual Studio project to + Meson/Ninja for all platforms. There are still Makefiles and VS + projects included in otherbuilds/ for those who wish to use them to + build the static library directly + * Make various fixes to improve sound quality when pitch-shifting + dynamically in real-time (requires libsamplerate) + * Fix floating-point exception when a very very long stretch factor + is presented + * Move the two directories that together provide the .NET interface + (rubberband-sharp and rubberband-dll) into their own subdir (dotnet) + * Ensure the library builds and runs correctly on ARM Mac (Apple + Silicon, M1), and also on Windows using the Visual C++ Clang + front-end + +The API is unchanged and the library is binary compatible with +version 1.7. + + Changes in Rubber Band v1.9 * Fix incorrect numbering of pitch speed/quality flags in the diff --git a/meson.build b/meson.build index 4f2172c..0d81506 100644 --- a/meson.build +++ b/meson.build @@ -2,7 +2,7 @@ project( 'Rubber Band Library', 'c', 'cpp', - version: '1.9.0', + version: '1.9.1', license: 'GPL-2.0-or-later', default_options: [ # All Rubber Band code is actually C++98, but some compilers no @@ -15,7 +15,7 @@ project( meson_version: '>= 0.53.0' ) -rubberband_dynamic_library_version = '2.1.2' +rubberband_dynamic_library_version = '2.1.3' system = build_machine.system() architecture = host_machine.cpu_family() From f393627944eb36be8b64f5545f6bb64906d26dec Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Mon, 8 Mar 2021 17:17:56 +0000 Subject: [PATCH 02/21] Further version updates --- Doxyfile | 2 +- rubberband/RubberBandStretcher.h | 2 +- rubberband/rubberband-c.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doxyfile b/Doxyfile index 2510ab2..9bd8e0f 100644 --- a/Doxyfile +++ b/Doxyfile @@ -31,7 +31,7 @@ PROJECT_NAME = "Rubber Band Library" # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 1.9.0 +PROJECT_NUMBER = 1.9.1 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. diff --git a/rubberband/RubberBandStretcher.h b/rubberband/RubberBandStretcher.h index ff79e84..bdf3bed 100644 --- a/rubberband/RubberBandStretcher.h +++ b/rubberband/RubberBandStretcher.h @@ -24,7 +24,7 @@ #ifndef RUBBERBAND_STRETCHER_H #define RUBBERBAND_STRETCHER_H -#define RUBBERBAND_VERSION "1.9.0" +#define RUBBERBAND_VERSION "1.9.1" #define RUBBERBAND_API_MAJOR_VERSION 2 #define RUBBERBAND_API_MINOR_VERSION 6 diff --git a/rubberband/rubberband-c.h b/rubberband/rubberband-c.h index f1d2931..c77d59f 100644 --- a/rubberband/rubberband-c.h +++ b/rubberband/rubberband-c.h @@ -28,7 +28,7 @@ extern "C" { #endif -#define RUBBERBAND_VERSION "1.9.0" +#define RUBBERBAND_VERSION "1.9.1" #define RUBBERBAND_API_MAJOR_VERSION 2 #define RUBBERBAND_API_MINOR_VERSION 6 From b81d62bb98c920b33e55b8a7a449cdb1bfd002e3 Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Tue, 9 Mar 2021 12:29:40 +0000 Subject: [PATCH 03/21] Update KissFFT code --- src/kissfft/COPYING | 14 ++-- src/kissfft/_kiss_fft_guts.h | 100 ++++++++++++++++------------- src/kissfft/kiss_fft.c | 121 ++++++++++++++++++++--------------- src/kissfft/kiss_fft.h | 67 +++++++++++++++---- src/kissfft/kiss_fftr.c | 60 ++++++++--------- src/kissfft/kiss_fftr.h | 16 +++-- 6 files changed, 227 insertions(+), 151 deletions(-) diff --git a/src/kissfft/COPYING b/src/kissfft/COPYING index b22325a..6b4b622 100644 --- a/src/kissfft/COPYING +++ b/src/kissfft/COPYING @@ -1,11 +1,11 @@ -Copyright (c) 2003-2004 Mark Borgerding +Copyright (c) 2003-2010 Mark Borgerding . All rights reserved. -All rights reserved. +KISS FFT is provided under: -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + SPDX-License-Identifier: BSD-3-Clause - * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. +Being under the terms of the BSD 3-clause "New" or "Revised" License, +according with: + + LICENSES/BSD-3-Clause -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/kissfft/_kiss_fft_guts.h b/src/kissfft/_kiss_fft_guts.h index ce04663..4bd8d1c 100644 --- a/src/kissfft/_kiss_fft_guts.h +++ b/src/kissfft/_kiss_fft_guts.h @@ -1,29 +1,25 @@ /* -Copyright (c) 2003-2004, Mark Borgerding - -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef KISS_FFT_GUTS_H -#define KISS_FFT_GUTS_H + * Copyright (c) 2003-2010, Mark Borgerding. All rights reserved. + * This file is part of KISS FFT - https://github.com/mborgerding/kissfft + * + * SPDX-License-Identifier: BSD-3-Clause + * See COPYING file for more information. + */ /* kiss_fft.h defines kiss_fft_scalar as either short or a float type and defines typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */ + +#ifndef _kiss_fft_guts_h +#define _kiss_fft_guts_h + #include "kiss_fft.h" +#include "kiss_fft_log.h" #include #define MAXFACTORS 32 -/* e.g. an fft of length 128 has 4 factors +/* e.g. an fft of length 128 has 4 factors as far as kissfft is concerned 4*4*4*2 */ @@ -45,22 +41,23 @@ struct kiss_fft_state{ C_ADDTO( res , a) : res += a * */ #ifdef FIXED_POINT +#include #if (FIXED_POINT==32) # define FRACBITS 31 # define SAMPPROD int64_t -#define SAMP_MAX 2147483647 +#define SAMP_MAX INT32_MAX +#define SAMP_MIN INT32_MIN #else # define FRACBITS 15 -# define SAMPPROD int32_t -#define SAMP_MAX 32767 +# define SAMPPROD int32_t +#define SAMP_MAX INT16_MAX +#define SAMP_MIN INT16_MIN #endif -#define SAMP_MIN -SAMP_MAX - #if defined(CHECK_OVERFLOW) # define CHECK_OVERFLOW_OP(a,op,b) \ - if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \ - fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); } + if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \ + KISS_FFT_WARNING("overflow (%d " #op" %d) = %ld", (a),(b),(SAMPPROD)(a) op (SAMPPROD)(b)); } #endif @@ -74,11 +71,11 @@ struct kiss_fft_state{ (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0) # define DIVSCALAR(x,k) \ - (x) = sround( smul( x, SAMP_MAX/k ) ) + (x) = sround( smul( x, SAMP_MAX/k ) ) # define C_FIXDIV(c,div) \ - do { DIVSCALAR( (c).r , div); \ - DIVSCALAR( (c).i , div); }while (0) + do { DIVSCALAR( (c).r , div); \ + DIVSCALAR( (c).i , div); }while (0) # define C_MULBYSCALAR( c, s ) \ do{ (c).r = sround( smul( (c).r , s ) ) ;\ @@ -102,28 +99,28 @@ struct kiss_fft_state{ #define C_ADD( res, a,b)\ do { \ - CHECK_OVERFLOW_OP((a).r,+,(b).r)\ - CHECK_OVERFLOW_OP((a).i,+,(b).i)\ - (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \ + CHECK_OVERFLOW_OP((a).r,+,(b).r)\ + CHECK_OVERFLOW_OP((a).i,+,(b).i)\ + (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \ }while(0) #define C_SUB( res, a,b)\ do { \ - CHECK_OVERFLOW_OP((a).r,-,(b).r)\ - CHECK_OVERFLOW_OP((a).i,-,(b).i)\ - (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \ + CHECK_OVERFLOW_OP((a).r,-,(b).r)\ + CHECK_OVERFLOW_OP((a).i,-,(b).i)\ + (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \ }while(0) #define C_ADDTO( res , a)\ do { \ - CHECK_OVERFLOW_OP((res).r,+,(a).r)\ - CHECK_OVERFLOW_OP((res).i,+,(a).i)\ - (res).r += (a).r; (res).i += (a).i;\ + CHECK_OVERFLOW_OP((res).r,+,(a).r)\ + CHECK_OVERFLOW_OP((res).i,+,(a).i)\ + (res).r += (a).r; (res).i += (a).i;\ }while(0) #define C_SUBFROM( res , a)\ do {\ - CHECK_OVERFLOW_OP((res).r,-,(a).r)\ - CHECK_OVERFLOW_OP((res).i,-,(a).i)\ - (res).r -= (a).r; (res).i -= (a).i; \ + CHECK_OVERFLOW_OP((res).r,-,(a).r)\ + CHECK_OVERFLOW_OP((res).i,-,(a).i)\ + (res).r -= (a).r; (res).i -= (a).i; \ }while(0) @@ -138,18 +135,33 @@ struct kiss_fft_state{ #else # define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase) # define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase) -# define HALF_OF(x) ((x)*.5) +# define HALF_OF(x) ((x)*((kiss_fft_scalar).5)) #endif #define kf_cexp(x,phase) \ - do{ \ - (x)->r = KISS_FFT_COS(phase);\ - (x)->i = KISS_FFT_SIN(phase);\ - }while(0) + do{ \ + (x)->r = KISS_FFT_COS(phase);\ + (x)->i = KISS_FFT_SIN(phase);\ + }while(0) /* a debugging function */ #define pcpx(c)\ - fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) ) + KISS_FFT_DEBUG("%g + %gi\n",(double)((c)->r),(double)((c)->i)) + +#ifdef KISS_FFT_USE_ALLOCA +// define this to allow use of alloca instead of malloc for temporary buffers +// Temporary buffers are used in two case: +// 1. FFT sizes that have "bad" factors. i.e. not 2,3 and 5 +// 2. "in-place" FFTs. Notice the quotes, since kissfft does not really do an in-place transform. +#include +#define KISS_FFT_TMP_ALLOC(nbytes) alloca(nbytes) +#define KISS_FFT_TMP_FREE(ptr) +#else +#define KISS_FFT_TMP_ALLOC(nbytes) KISS_FFT_MALLOC(nbytes) +#define KISS_FFT_TMP_FREE(ptr) KISS_FFT_FREE(ptr) #endif + +#endif /* _kiss_fft_guts_h */ + diff --git a/src/kissfft/kiss_fft.c b/src/kissfft/kiss_fft.c index 79c9392..58c24a0 100644 --- a/src/kissfft/kiss_fft.c +++ b/src/kissfft/kiss_fft.c @@ -1,16 +1,10 @@ /* -Copyright (c) 2003-2004, Mark Borgerding - -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2003-2010, Mark Borgerding. All rights reserved. + * This file is part of KISS FFT - https://github.com/mborgerding/kissfft + * + * SPDX-License-Identifier: BSD-3-Clause + * See COPYING file for more information. + */ #include "_kiss_fft_guts.h" @@ -18,21 +12,6 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND fixed or floating point complex numbers. It also delares the kf_ internal functions. */ -static kiss_fft_cpx *scratchbuf=NULL; -static size_t nscratchbuf=0; -static kiss_fft_cpx *tmpbuf=NULL; -static size_t ntmpbuf=0; - -#define CHECKBUF(buf,nbuf,n) \ - do { \ - if ( nbuf < (size_t)(n) ) {\ - free(buf); \ - buf = (kiss_fft_cpx*)KISS_FFT_MALLOC(sizeof(kiss_fft_cpx)*(n)); \ - nbuf = (size_t)(n); \ - } \ - }while(0) - - static void kf_bfly2( kiss_fft_cpx * Fout, const size_t fstride, @@ -69,6 +48,7 @@ static void kf_bfly4( const size_t m2=2*m; const size_t m3=3*m; + tw3 = tw2 = tw1 = st->twiddles; do { @@ -222,29 +202,34 @@ static void kf_bfly_generic( kiss_fft_cpx t; int Norig = st->nfft; - CHECKBUF(scratchbuf,nscratchbuf,p); + kiss_fft_cpx * scratch = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC(sizeof(kiss_fft_cpx)*p); + if (scratch == NULL){ + KISS_FFT_ERROR("Memory allocation failed."); + return; + } for ( u=0; u=Norig) twidx-=Norig; - C_MUL(t,scratchbuf[q] , twiddles[twidx] ); + C_MUL(t,scratch[q] , twiddles[twidx] ); C_ADDTO( Fout[ k ] ,t); } k += m; } } + KISS_FFT_TMP_FREE(scratch); } static @@ -262,6 +247,30 @@ void kf_work( const int m=*factors++; /* stage's fft length/p */ const kiss_fft_cpx * Fout_end = Fout + p*m; +#ifdef _OPENMP + // use openmp extensions at the + // top-level (not recursive) + if (fstride==1 && p<=5 && m!=1) + { + int k; + + // execute the p different work units in different threads +# pragma omp parallel for + for (k=0;knfft); + //NOTE: this is not really an in-place FFT algorithm. + //It just performs an out-of-place FFT into a temp buffer + if (fout == NULL){ + KISS_FFT_ERROR("fout buffer NULL."); + return; + } + + kiss_fft_cpx * tmpbuf = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC( sizeof(kiss_fft_cpx)*st->nfft); + if (tmpbuf == NULL){ + KISS_FFT_ERROR("Memory allocation error."); + return; + } + + + kf_work(tmpbuf,fin,1,in_stride, st->factors,st); memcpy(fout,tmpbuf,sizeof(kiss_fft_cpx)*st->nfft); + KISS_FFT_TMP_FREE(tmpbuf); }else{ kf_work( fout, fin, 1,in_stride, st->factors,st ); } @@ -371,17 +400,9 @@ void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout) } -/* not really necessary to call, but if someone is doing in-place ffts, they may want to free the - buffers from CHECKBUF - */ void kiss_fft_cleanup(void) { - free(scratchbuf); - scratchbuf = NULL; - nscratchbuf=0; - free(tmpbuf); - tmpbuf=NULL; - ntmpbuf=0; + // nothing needed any more } int kiss_fft_next_fast_size(int n) diff --git a/src/kissfft/kiss_fft.h b/src/kissfft/kiss_fft.h index f8e523e..dce1034 100644 --- a/src/kissfft/kiss_fft.h +++ b/src/kissfft/kiss_fft.h @@ -1,12 +1,32 @@ +/* + * Copyright (c) 2003-2010, Mark Borgerding. All rights reserved. + * This file is part of KISS FFT - https://github.com/mborgerding/kissfft + * + * SPDX-License-Identifier: BSD-3-Clause + * See COPYING file for more information. + */ + #ifndef KISS_FFT_H #define KISS_FFT_H #include #include #include -#include -#ifndef __APPLE__ -#include +#include + +// Define KISS_FFT_SHARED macro to properly export symbols +#ifdef KISS_FFT_SHARED +# ifdef _WIN32 +# ifdef KISS_FFT_BUILD +# define KISS_FFT_API __declspec(dllexport) +# else +# define KISS_FFT_API __declspec(dllimport) +# endif +# else +# define KISS_FFT_API __attribute__ ((visibility ("default"))) +# endif +#else +# define KISS_FFT_API #endif #ifdef __cplusplus @@ -26,17 +46,32 @@ extern "C" { in the tools/ directory. */ +/* User may override KISS_FFT_MALLOC and/or KISS_FFT_FREE. */ #ifdef USE_SIMD # include # define kiss_fft_scalar __m128 -#define KISS_FFT_MALLOC(nbytes) memalign(16,nbytes) -#else -#define KISS_FFT_MALLOC malloc -#endif +# ifndef KISS_FFT_MALLOC +# define KISS_FFT_MALLOC(nbytes) _mm_malloc(nbytes,16) +# define KISS_FFT_ALIGN_CHECK(ptr) +# define KISS_FFT_ALIGN_SIZE_UP(size) ((size + 15UL) & ~0xFUL) +# endif +# ifndef KISS_FFT_FREE +# define KISS_FFT_FREE _mm_free +# endif +#else +# define KISS_FFT_ALIGN_CHECK(ptr) +# define KISS_FFT_ALIGN_SIZE_UP(size) (size) +# ifndef KISS_FFT_MALLOC +# define KISS_FFT_MALLOC malloc +# endif +# ifndef KISS_FFT_FREE +# define KISS_FFT_FREE free +# endif +#endif #ifdef FIXED_POINT -#include +#include # if (FIXED_POINT == 32) # define kiss_fft_scalar int32_t # else @@ -79,7 +114,7 @@ typedef struct kiss_fft_state* kiss_fft_cfg; * buffer size in *lenmem. * */ -kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem); +kiss_fft_cfg KISS_FFT_API kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem); /* * kiss_fft(cfg,in_out_buf) @@ -91,28 +126,32 @@ kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem) * Note that each element is complex and can be accessed like f[k].r and f[k].i * */ -void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); +void KISS_FFT_API kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); /* A more generic version of the above function. It reads its input from every Nth sample. * */ -void kiss_fft_stride(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int fin_stride); +void KISS_FFT_API kiss_fft_stride(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int fin_stride); /* If kiss_fft_alloc allocated a buffer, it is one contiguous buffer and can be simply free()d when no longer needed*/ -#define kiss_fft_free free +#define kiss_fft_free KISS_FFT_FREE /* Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up your compiler output to call this before you exit. */ -void kiss_fft_cleanup(void); +void KISS_FFT_API kiss_fft_cleanup(void); /* * Returns the smallest integer k, such that k>=n and k has only "fast" factors (2,3,5) */ -int kiss_fft_next_fast_size(int n); +int KISS_FFT_API kiss_fft_next_fast_size(int n); + +/* for real ffts, we need an even size */ +#define kiss_fftr_next_fast_size_real(n) \ + (kiss_fft_next_fast_size( ((n)+1)>>1)<<1) #ifdef __cplusplus } diff --git a/src/kissfft/kiss_fftr.c b/src/kissfft/kiss_fftr.c index 5bc669d..778a9a6 100644 --- a/src/kissfft/kiss_fftr.c +++ b/src/kissfft/kiss_fftr.c @@ -1,16 +1,10 @@ /* -Copyright (c) 2003-2004, Mark Borgerding - -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2003-2004, Mark Borgerding. All rights reserved. + * This file is part of KISS FFT - https://github.com/mborgerding/kissfft + * + * SPDX-License-Identifier: BSD-3-Clause + * See COPYING file for more information. + */ #include "kiss_fftr.h" #include "_kiss_fft_guts.h" @@ -19,25 +13,27 @@ struct kiss_fftr_state{ kiss_fft_cfg substate; kiss_fft_cpx * tmpbuf; kiss_fft_cpx * super_twiddles; -#ifdef USE_SIMD - long pad; -#endif +#ifdef USE_SIMD + void * pad; +#endif }; kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem) { + KISS_FFT_ALIGN_CHECK(mem) + int i; kiss_fftr_cfg st = NULL; - size_t subsize, memneeded; + size_t subsize = 0, memneeded; if (nfft & 1) { - fprintf(stderr,"Real FFT optimization must be even.\n"); + KISS_FFT_ERROR("Real FFT optimization must be even."); return NULL; } nfft >>= 1; kiss_fft_alloc (nfft, inverse_fft, NULL, &subsize); - memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 2); + memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 3 / 2); if (lenmem == NULL) { st = (kiss_fftr_cfg) KISS_FFT_MALLOC (memneeded); @@ -54,9 +50,9 @@ kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenme st->super_twiddles = st->tmpbuf + nfft; kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize); - for (i = 0; i < nfft; ++i) { + for (i = 0; i < nfft/2; ++i) { double phase = - -3.14159265358979323846264338327 * ((double) i / nfft + .5); + -3.14159265358979323846264338327 * ((double) (i+1) / nfft + .5); if (inverse_fft) phase *= -1; kf_cexp (st->super_twiddles+i,phase); @@ -71,8 +67,8 @@ void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *fr kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc; if ( st->substate->inverse) { - fprintf(stderr,"kiss fft usage error: improper alloc\n"); - exit(1); + KISS_FFT_ERROR("kiss fft usage error: improper alloc"); + return;/* The caller did not call the correct function */ } ncfft = st->substate->nfft; @@ -83,12 +79,12 @@ void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *fr * contains the sum of the even-numbered elements of the input time sequence * The imag part is the sum of the odd-numbered elements * - * The sum of tdc.r and tdc.i is the sum of the input time sequence. + * The sum of tdc.r and tdc.i is the sum of the input time sequence. * yielding DC of input time sequence - * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... + * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... * yielding Nyquist bin of input time sequence */ - + tdc.r = st->tmpbuf[0].r; tdc.i = st->tmpbuf[0].i; C_FIXDIV(tdc,2); @@ -96,14 +92,14 @@ void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *fr CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i); freqdata[0].r = tdc.r + tdc.i; freqdata[ncfft].r = tdc.r - tdc.i; -#ifdef USE_SIMD +#ifdef USE_SIMD freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0); #else freqdata[ncfft].i = freqdata[0].i = 0; #endif for ( k=1;k <= ncfft/2 ; ++k ) { - fpk = st->tmpbuf[k]; + fpk = st->tmpbuf[k]; fpnk.r = st->tmpbuf[ncfft-k].r; fpnk.i = - st->tmpbuf[ncfft-k].i; C_FIXDIV(fpk,2); @@ -111,7 +107,7 @@ void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *fr C_ADD( f1k, fpk , fpnk ); C_SUB( f2k, fpk , fpnk ); - C_MUL( tw , f2k , st->super_twiddles[k]); + C_MUL( tw , f2k , st->super_twiddles[k-1]); freqdata[k].r = HALF_OF(f1k.r + tw.r); freqdata[k].i = HALF_OF(f1k.i + tw.i); @@ -126,8 +122,8 @@ void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *t int k, ncfft; if (st->substate->inverse == 0) { - fprintf (stderr, "kiss fft usage error: improper alloc\n"); - exit (1); + KISS_FFT_ERROR("kiss fft usage error: improper alloc"); + return;/* The caller did not call the correct function */ } ncfft = st->substate->nfft; @@ -146,10 +142,10 @@ void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *t C_ADD (fek, fk, fnkc); C_SUB (tmp, fk, fnkc); - C_MUL (fok, tmp, st->super_twiddles[k]); + C_MUL (fok, tmp, st->super_twiddles[k-1]); C_ADD (st->tmpbuf[k], fek, fok); C_SUB (st->tmpbuf[ncfft - k], fek, fok); -#ifdef USE_SIMD +#ifdef USE_SIMD st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0); #else st->tmpbuf[ncfft - k].i *= -1; diff --git a/src/kissfft/kiss_fftr.h b/src/kissfft/kiss_fftr.h index 72e5a57..7fd73d2 100644 --- a/src/kissfft/kiss_fftr.h +++ b/src/kissfft/kiss_fftr.h @@ -1,3 +1,11 @@ +/* + * Copyright (c) 2003-2004, Mark Borgerding. All rights reserved. + * This file is part of KISS FFT - https://github.com/mborgerding/kissfft + * + * SPDX-License-Identifier: BSD-3-Clause + * See COPYING file for more information. + */ + #ifndef KISS_FTR_H #define KISS_FTR_H @@ -18,7 +26,7 @@ extern "C" { typedef struct kiss_fftr_state *kiss_fftr_cfg; -kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem, size_t * lenmem); +kiss_fftr_cfg KISS_FFT_API kiss_fftr_alloc(int nfft,int inverse_fft,void * mem, size_t * lenmem); /* nfft must be even @@ -26,19 +34,19 @@ kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem, size_t * lenm */ -void kiss_fftr(kiss_fftr_cfg cfg,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata); +void KISS_FFT_API kiss_fftr(kiss_fftr_cfg cfg,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata); /* input timedata has nfft scalar points output freqdata has nfft/2+1 complex points */ -void kiss_fftri(kiss_fftr_cfg cfg,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata); +void KISS_FFT_API kiss_fftri(kiss_fftr_cfg cfg,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata); /* input freqdata has nfft/2+1 complex points output timedata has nfft scalar points */ -#define kiss_fftr_free free +#define kiss_fftr_free KISS_FFT_FREE #ifdef __cplusplus } From ee9128020dccdf64dae5853e4bd98d84a61d57fe Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Tue, 9 Mar 2021 13:05:24 +0000 Subject: [PATCH 04/21] Additional kissfft source file --- src/kissfft/kiss_fft_log.h | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/kissfft/kiss_fft_log.h diff --git a/src/kissfft/kiss_fft_log.h b/src/kissfft/kiss_fft_log.h new file mode 100644 index 0000000..b5b631a --- /dev/null +++ b/src/kissfft/kiss_fft_log.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2003-2010, Mark Borgerding. All rights reserved. + * This file is part of KISS FFT - https://github.com/mborgerding/kissfft + * + * SPDX-License-Identifier: BSD-3-Clause + * See COPYING file for more information. + */ + +#ifndef kiss_fft_log_h +#define kiss_fft_log_h + +#define ERROR 1 +#define WARNING 2 +#define INFO 3 +#define DEBUG 4 + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) + +#if defined(NDEBUG) +# define KISS_FFT_LOG_MSG(severity, ...) ((void)0) +#else +# define KISS_FFT_LOG_MSG(severity, ...) \ + fprintf(stderr, "[" #severity "] " __FILE__ ":" TOSTRING(__LINE__) " "); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n") +#endif + +#define KISS_FFT_ERROR(...) KISS_FFT_LOG_MSG(ERROR, __VA_ARGS__) +#define KISS_FFT_WARNING(...) KISS_FFT_LOG_MSG(WARNING, __VA_ARGS__) +#define KISS_FFT_INFO(...) KISS_FFT_LOG_MSG(INFO, __VA_ARGS__) +#define KISS_FFT_DEBUG(...) KISS_FFT_LOG_MSG(DEBUG, __VA_ARGS__) + + + +#endif /* kiss_fft_log_h */ \ No newline at end of file From e79658b04f2084acbed3db7e86b6723e1b4b8c0d Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Tue, 9 Mar 2021 17:21:08 +0000 Subject: [PATCH 05/21] Fix incorrect cases in double-only/float-only cases --- src/dsp/FFT.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/dsp/FFT.cpp b/src/dsp/FFT.cpp index ba9d8fd..f6f0d97 100644 --- a/src/dsp/FFT.cpp +++ b/src/dsp/FFT.cpp @@ -1865,8 +1865,8 @@ public: dbuf[i] = realIn[i]; } fftw_execute(m_dplanf); - v_cartesian_interleaved_to_polar(magOut, phaseOut, - (double *)m_dpacked, m_size/2+1); + v_cartesian_interleaved_to_polar + (magOut, phaseOut, (fft_double_type *)m_dpacked, m_size/2+1); } void forwardMagnitude(const double *R__ realIn, double *R__ magOut) { @@ -1926,8 +1926,8 @@ public: fbuf[i] = realIn[i]; } fftwf_execute(m_fplanf); - v_cartesian_interleaved_to_polar(magOut, phaseOut, - (float *)m_fpacked, m_size/2+1); + v_cartesian_interleaved_to_polar + (magOut, phaseOut, (fft_float_type *)m_fpacked, m_size/2+1); } void forwardMagnitude(const float *R__ realIn, float *R__ magOut) { @@ -1964,7 +1964,7 @@ public: void inverseInterleaved(const double *R__ complexIn, double *R__ realOut) { if (!m_dplanf) initDouble(); - v_convert((double *)m_dpacked, complexIn, m_size + 2); + v_convert((fft_double_type *)m_dpacked, complexIn, m_size + 2); fftw_execute(m_dplani); const int sz = m_size; fft_double_type *const R__ dbuf = m_dbuf; @@ -2034,7 +2034,7 @@ public: void inverseInterleaved(const float *R__ complexIn, float *R__ realOut) { if (!m_fplanf) initFloat(); - v_copy((float *)m_fpacked, complexIn, m_size + 2); + v_convert((fft_float_type *)m_fpacked, complexIn, m_size + 2); fftwf_execute(m_fplani); const int sz = m_size; fft_float_type *const R__ fbuf = m_fbuf; From b463cf5565ed3655c7904bc6da4d72f074f02705 Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Tue, 9 Mar 2021 17:22:41 +0000 Subject: [PATCH 06/21] Fix wrong accumulator type - this fix makes the detector a little more sensitive, which is not necessarily good, but the previous accidental behaviour exaggerated the difference in results between float and double precision ffts --- src/audiocurves/HighFrequencyAudioCurve.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/audiocurves/HighFrequencyAudioCurve.cpp b/src/audiocurves/HighFrequencyAudioCurve.cpp index 52b4d2b..a948ba1 100644 --- a/src/audiocurves/HighFrequencyAudioCurve.cpp +++ b/src/audiocurves/HighFrequencyAudioCurve.cpp @@ -58,14 +58,14 @@ HighFrequencyAudioCurve::processFloat(const float *R__ mag, int) double HighFrequencyAudioCurve::processDouble(const double *R__ mag, int) { - float result = 0.0; + double result = 0.0; const int sz = m_lastPerceivedBin; for (int n = 0; n <= sz; ++n) { result = result + mag[n] * n; } - + return result; } From fcc952e81a7b607c5e949f0d74498fc11a6f8a9a Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Tue, 9 Mar 2021 17:29:21 +0000 Subject: [PATCH 07/21] A few helper functions --- src/dsp/FFT.cpp | 40 +++++++----------------- src/system/VectorOpsComplex.h | 57 +++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 29 deletions(-) diff --git a/src/dsp/FFT.cpp b/src/dsp/FFT.cpp index f6f0d97..eb5c8f6 100644 --- a/src/dsp/FFT.cpp +++ b/src/dsp/FFT.cpp @@ -1851,7 +1851,7 @@ public: dbuf[i] = realIn[i]; } fftw_execute(m_dplanf); - v_convert(complexOut, (fft_double_type *)m_dpacked, sz + 2); + v_convert(complexOut, (const fft_double_type *)m_dpacked, sz + 2); } void forwardPolar(const double *R__ realIn, double *R__ magOut, double *R__ phaseOut) { @@ -1866,7 +1866,7 @@ public: } fftw_execute(m_dplanf); v_cartesian_interleaved_to_polar - (magOut, phaseOut, (fft_double_type *)m_dpacked, m_size/2+1); + (magOut, phaseOut, (const fft_double_type *)m_dpacked, m_size/2+1); } void forwardMagnitude(const double *R__ realIn, double *R__ magOut) { @@ -1880,11 +1880,8 @@ public: dbuf[i] = realIn[i]; } fftw_execute(m_dplanf); - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - magOut[i] = sqrt(m_dpacked[i][0] * m_dpacked[i][0] + - m_dpacked[i][1] * m_dpacked[i][1]); - } + v_cartesian_interleaved_to_magnitudes + (magOut, (const fft_double_type *)m_dpacked, m_size/2+1); } void forward(const float *R__ realIn, float *R__ realOut, float *R__ imagOut) { @@ -1912,7 +1909,7 @@ public: fbuf[i] = realIn[i]; } fftwf_execute(m_fplanf); - v_convert(complexOut, (fft_float_type *)m_fpacked, sz + 2); + v_convert(complexOut, (const fft_float_type *)m_fpacked, sz + 2); } void forwardPolar(const float *R__ realIn, float *R__ magOut, float *R__ phaseOut) { @@ -1941,11 +1938,8 @@ public: fbuf[i] = realIn[i]; } fftwf_execute(m_fplanf); - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - magOut[i] = sqrtf(m_fpacked[i][0] * m_fpacked[i][0] + - m_fpacked[i][1] * m_fpacked[i][1]); - } + v_cartesian_interleaved_to_magnitudes + (magOut, (const fft_float_type *)m_fpacked, m_size/2+1); } void inverse(const double *R__ realIn, const double *R__ imagIn, double *R__ realOut) { @@ -1978,14 +1972,8 @@ public: void inversePolar(const double *R__ magIn, const double *R__ phaseIn, double *R__ realOut) { if (!m_dplanf) initDouble(); - const int hs = m_size/2; - fftw_complex *const R__ dpacked = m_dpacked; - for (int i = 0; i <= hs; ++i) { - dpacked[i][0] = magIn[i] * cos(phaseIn[i]); - } - for (int i = 0; i <= hs; ++i) { - dpacked[i][1] = magIn[i] * sin(phaseIn[i]); - } + v_polar_to_cartesian_interleaved + ((fft_double_type *)m_dpacked, magIn, phaseIn, m_size/2+1); fftw_execute(m_dplani); const int sz = m_size; fft_double_type *const R__ dbuf = m_dbuf; @@ -2048,14 +2036,8 @@ public: void inversePolar(const float *R__ magIn, const float *R__ phaseIn, float *R__ realOut) { if (!m_fplanf) initFloat(); - const int hs = m_size/2; - fftwf_complex *const R__ fpacked = m_fpacked; - for (int i = 0; i <= hs; ++i) { - fpacked[i][0] = magIn[i] * cosf(phaseIn[i]); - } - for (int i = 0; i <= hs; ++i) { - fpacked[i][1] = magIn[i] * sinf(phaseIn[i]); - } + v_polar_to_cartesian_interleaved + ((fft_float_type *)m_fpacked, magIn, phaseIn, m_size/2+1); fftwf_execute(m_fplani); const int sz = m_size; fft_float_type *const R__ fbuf = m_fbuf; diff --git a/src/system/VectorOpsComplex.h b/src/system/VectorOpsComplex.h index 8d4161b..aca2a37 100644 --- a/src/system/VectorOpsComplex.h +++ b/src/system/VectorOpsComplex.h @@ -246,6 +246,63 @@ void v_cartesian_to_polar_interleaved_inplace(T *const R__ srcdst, } } +template // S source, T target +void v_cartesian_to_magnitudes(T *const R__ mag, + const S *const R__ real, + const S *const R__ imag, + const int count) +{ + for (int i = 0; i < count; ++i) { + mag[i] = T(sqrt(real[i] * real[i] + imag[i] * imag[i])); + } +} + +template // S source, T target +void v_cartesian_interleaved_to_magnitudes(T *const R__ mag, + const S *const R__ src, + const int count) +{ + for (int i = 0; i < count; ++i) { + mag[i] = T(sqrt(src[i*2] * src[i*2] + src[i*2+1] * src[i*2+1])); + } +} + +#ifdef HAVE_IPP +template<> +inline void v_cartesian_to_magnitudes(float *const R__ mag, + const float *const R__ real, + const float *const R__ imag, + const int count) +{ + ippsMagnitude_32f(real, imag, mag, count); +} + +template<> +inline void v_cartesian_to_magnitudes(double *const R__ mag, + const double *const R__ real, + const double *const R__ imag, + const int count) +{ + ippsMagnitude_64f(real, imag, mag, count); +} + +template<> +inline void v_cartesian_interleaved_to_magnitudes(float *const R__ mag, + const float *const R__ src, + const int count) +{ + ippsMagnitude_32fc((const Ipp32fc *)src, mag, count); +} + +template<> +inline void v_cartesian_interleaved_to_magnitudes(double *const R__ mag, + const double *const R__ src, + const int count) +{ + ippsMagnitude_64fc((const Ipp64fc *)src, mag, count); +} +#endif + } #endif From 8b2a4d6aa1ead0c4a11decbad5d82e7dc6ce43db Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Tue, 9 Mar 2021 18:41:46 +0000 Subject: [PATCH 08/21] Clarify architecture notes --- README.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 14b6fca..cb085ef 100644 --- a/README.md +++ b/README.md @@ -225,25 +225,28 @@ $ make -f otherbuilds/Makefile.linux Ensure the Xcode command-line tools are installed, and ideally also install libsamplerate and libsndfile. -To build for the native architecture of the build machine: +To build for the default architecture: ``` $ meson build && ninja -C build ``` -To build for Intel (x86_64) regardless of the native architecture: +Which architecture is the default may depend on the version of Meson +and/or the current shell. To force a particular architecture you can +use a Meson cross-file, as follows. -``` -$ meson build --cross-file cross/macos-x86_64.txt && ninja -C build -``` - -To build for Apple Silicon (arm64) regardless of the native -architecture: +To build for Apple Silicon (arm64): ``` $ meson build --cross-file cross/macos-arm64.txt && ninja -C build ``` +To build for Intel (x86_64): + +``` +$ meson build --cross-file cross/macos-x86_64.txt && ninja -C build +``` + You can build a universal binary library for both architectures like this: From 5897dfbc5bfc7c1b249f658cc54241c78e9850ac Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Wed, 10 Mar 2021 08:06:45 +0000 Subject: [PATCH 09/21] Install headers! --- meson.build | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/meson.build b/meson.build index 0d81506..3238f2e 100644 --- a/meson.build +++ b/meson.build @@ -419,6 +419,13 @@ else message('Not building Rubber Band Library dynamic library: no_shared option set') endif +install_headers( + [ 'rubberband/RubberBandStretcher.h', + 'rubberband/rubberband-c.h' + ], + subdir: 'rubberband' +) + if have_ladspa target_summary += { 'LADSPA plugin': [ true, 'Name: ' + rubberband_ladspa_name ] } message('Will build LADSPA plugin') From 7705c6409e5514c939afb992763a44e90354797e Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Wed, 10 Mar 2021 18:10:10 +0000 Subject: [PATCH 10/21] Fix some nominal memory leaks --- main/main.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/main/main.cpp b/main/main.cpp index f22383e..4209970 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -628,9 +628,17 @@ int main(int argc, char **argv) } } + delete[] fbuf; + + for (size_t i = 0; i < channels; ++i) delete[] ibuf[i]; + delete[] ibuf; + sf_close(sndfile); sf_close(sndfileOut); + free(fileName); + free(fileNameOut); + if (!quiet) { cerr << "in: " << countIn << ", out: " << countOut << ", ratio: " << float(countOut)/float(countIn) << ", ideal output: " << lrint(countIn * ratio) << ", error: " << abs(lrint(countIn * ratio) - int(countOut)) << endl; @@ -656,7 +664,7 @@ int main(int argc, char **argv) } RubberBand::Profiler::dump(); - + return 0; } From 09e5bd29bf6eb33c4d975f0339c419e207843b31 Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Thu, 11 Mar 2021 16:14:40 +0000 Subject: [PATCH 11/21] Protect profiler map with a mutex --- src/base/Profiler.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/base/Profiler.cpp b/src/base/Profiler.cpp index b1305b3..d96b571 100644 --- a/src/base/Profiler.cpp +++ b/src/base/Profiler.cpp @@ -23,6 +23,8 @@ #include "Profiler.h" +#include "system/Thread.h" + #include #include #include @@ -45,9 +47,13 @@ Profiler::m_profiles; Profiler::WorstCallMap Profiler::m_worstCalls; +static Mutex profileMutex; + void Profiler::add(const char *id, float ms) { + profileMutex.lock(); + ProfileMap::iterator pmi = m_profiles.find(id); if (pmi != m_profiles.end()) { ++pmi->second.first; @@ -62,6 +68,8 @@ Profiler::add(const char *id, float ms) } else { m_worstCalls[id] = ms; } + + profileMutex.unlock(); } void @@ -74,6 +82,8 @@ Profiler::dump() std::string Profiler::getReport() { + profileMutex.lock(); + static const int buflen = 256; char buffer[buflen]; std::string report; @@ -167,6 +177,8 @@ Profiler::getReport() report += buffer; } + profileMutex.unlock(); + return report; } From 59f57e73462b34e15496ff9718eb8649721c2335 Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Thu, 11 Mar 2021 16:15:01 +0000 Subject: [PATCH 12/21] Typo fixes --- rubberband/RubberBandStretcher.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rubberband/RubberBandStretcher.h b/rubberband/RubberBandStretcher.h index bdf3bed..0d88583 100644 --- a/rubberband/RubberBandStretcher.h +++ b/rubberband/RubberBandStretcher.h @@ -186,7 +186,7 @@ public: * one processing thread per audio channel in offline mode if * the stretcher is able to determine that more than one CPU is * available, and one thread only in realtime mode. This is the - * defafult. + * default. * * \li \c OptionThreadingNever - Never use more than one thread. * @@ -464,7 +464,7 @@ public: /** * Change an OptionPitch configuration setting. This may be * called at any time in RealTime mode. It may not be called in - * Offline mode (for which the transients option is fixed on + * Offline mode (for which the pitch option is fixed on * construction). */ void setPitchOption(Options options); From a5cb3a6b4ad5b9916e7e37bc4487abb385ac8788 Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Thu, 11 Mar 2021 16:15:10 +0000 Subject: [PATCH 13/21] Add some profiler entries --- src/dsp/FFT.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/dsp/FFT.cpp b/src/dsp/FFT.cpp index eb5c8f6..41c80db 100644 --- a/src/dsp/FFT.cpp +++ b/src/dsp/FFT.cpp @@ -3240,6 +3240,7 @@ FFT::~FFT() void FFT::forward(const double *R__ realIn, double *R__ realOut, double *R__ imagOut) { + Profiler profiler("FFT::forward"); CHECK_NOT_NULL(realIn); CHECK_NOT_NULL(realOut); CHECK_NOT_NULL(imagOut); @@ -3249,6 +3250,7 @@ FFT::forward(const double *R__ realIn, double *R__ realOut, double *R__ imagOut) void FFT::forwardInterleaved(const double *R__ realIn, double *R__ complexOut) { + Profiler profiler("FFT::forwardInterleaved"); CHECK_NOT_NULL(realIn); CHECK_NOT_NULL(complexOut); d->forwardInterleaved(realIn, complexOut); @@ -3257,6 +3259,7 @@ FFT::forwardInterleaved(const double *R__ realIn, double *R__ complexOut) void FFT::forwardPolar(const double *R__ realIn, double *R__ magOut, double *R__ phaseOut) { + Profiler profiler("FFT::forwardPolar"); CHECK_NOT_NULL(realIn); CHECK_NOT_NULL(magOut); CHECK_NOT_NULL(phaseOut); @@ -3266,6 +3269,7 @@ FFT::forwardPolar(const double *R__ realIn, double *R__ magOut, double *R__ phas void FFT::forwardMagnitude(const double *R__ realIn, double *R__ magOut) { + Profiler profiler("FFT::forwardMagnitude"); CHECK_NOT_NULL(realIn); CHECK_NOT_NULL(magOut); d->forwardMagnitude(realIn, magOut); @@ -3274,6 +3278,7 @@ FFT::forwardMagnitude(const double *R__ realIn, double *R__ magOut) void FFT::forward(const float *R__ realIn, float *R__ realOut, float *R__ imagOut) { + Profiler profiler("FFT::forward[float]"); CHECK_NOT_NULL(realIn); CHECK_NOT_NULL(realOut); CHECK_NOT_NULL(imagOut); @@ -3283,6 +3288,7 @@ FFT::forward(const float *R__ realIn, float *R__ realOut, float *R__ imagOut) void FFT::forwardInterleaved(const float *R__ realIn, float *R__ complexOut) { + Profiler profiler("FFT::forwardInterleaved[float]"); CHECK_NOT_NULL(realIn); CHECK_NOT_NULL(complexOut); d->forwardInterleaved(realIn, complexOut); @@ -3291,6 +3297,7 @@ FFT::forwardInterleaved(const float *R__ realIn, float *R__ complexOut) void FFT::forwardPolar(const float *R__ realIn, float *R__ magOut, float *R__ phaseOut) { + Profiler profiler("FFT::forwardPolar[float]"); CHECK_NOT_NULL(realIn); CHECK_NOT_NULL(magOut); CHECK_NOT_NULL(phaseOut); @@ -3300,6 +3307,7 @@ FFT::forwardPolar(const float *R__ realIn, float *R__ magOut, float *R__ phaseOu void FFT::forwardMagnitude(const float *R__ realIn, float *R__ magOut) { + Profiler profiler("FFT::forwardMagnitude[float]"); CHECK_NOT_NULL(realIn); CHECK_NOT_NULL(magOut); d->forwardMagnitude(realIn, magOut); @@ -3308,6 +3316,7 @@ FFT::forwardMagnitude(const float *R__ realIn, float *R__ magOut) void FFT::inverse(const double *R__ realIn, const double *R__ imagIn, double *R__ realOut) { + Profiler profiler("FFT::inverse"); CHECK_NOT_NULL(realIn); CHECK_NOT_NULL(imagIn); CHECK_NOT_NULL(realOut); @@ -3317,6 +3326,7 @@ FFT::inverse(const double *R__ realIn, const double *R__ imagIn, double *R__ rea void FFT::inverseInterleaved(const double *R__ complexIn, double *R__ realOut) { + Profiler profiler("FFT::inverseInterleaved"); CHECK_NOT_NULL(complexIn); CHECK_NOT_NULL(realOut); d->inverseInterleaved(complexIn, realOut); @@ -3325,6 +3335,7 @@ FFT::inverseInterleaved(const double *R__ complexIn, double *R__ realOut) void FFT::inversePolar(const double *R__ magIn, const double *R__ phaseIn, double *R__ realOut) { + Profiler profiler("FFT::inversePolar"); CHECK_NOT_NULL(magIn); CHECK_NOT_NULL(phaseIn); CHECK_NOT_NULL(realOut); @@ -3334,6 +3345,7 @@ FFT::inversePolar(const double *R__ magIn, const double *R__ phaseIn, double *R_ void FFT::inverseCepstral(const double *R__ magIn, double *R__ cepOut) { + Profiler profiler("FFT::inverseCepstral"); CHECK_NOT_NULL(magIn); CHECK_NOT_NULL(cepOut); d->inverseCepstral(magIn, cepOut); @@ -3342,6 +3354,7 @@ FFT::inverseCepstral(const double *R__ magIn, double *R__ cepOut) void FFT::inverse(const float *R__ realIn, const float *R__ imagIn, float *R__ realOut) { + Profiler profiler("FFT::inverse[float]"); CHECK_NOT_NULL(realIn); CHECK_NOT_NULL(imagIn); CHECK_NOT_NULL(realOut); @@ -3351,6 +3364,7 @@ FFT::inverse(const float *R__ realIn, const float *R__ imagIn, float *R__ realOu void FFT::inverseInterleaved(const float *R__ complexIn, float *R__ realOut) { + Profiler profiler("FFT::inverseInterleaved[float]"); CHECK_NOT_NULL(complexIn); CHECK_NOT_NULL(realOut); d->inverseInterleaved(complexIn, realOut); @@ -3359,6 +3373,7 @@ FFT::inverseInterleaved(const float *R__ complexIn, float *R__ realOut) void FFT::inversePolar(const float *R__ magIn, const float *R__ phaseIn, float *R__ realOut) { + Profiler profiler("FFT::inversePolar[float]"); CHECK_NOT_NULL(magIn); CHECK_NOT_NULL(phaseIn); CHECK_NOT_NULL(realOut); @@ -3368,6 +3383,7 @@ FFT::inversePolar(const float *R__ magIn, const float *R__ phaseIn, float *R__ r void FFT::inverseCepstral(const float *R__ magIn, float *R__ cepOut) { + Profiler profiler("FFT::inverseCepstral[float]"); CHECK_NOT_NULL(magIn); CHECK_NOT_NULL(cepOut); d->inverseCepstral(magIn, cepOut); From 91274b3fd56c8f28bbb71d27805527c4306c47a5 Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Fri, 12 Mar 2021 09:52:54 +0000 Subject: [PATCH 14/21] Build and install JNI if header and Java compiler are found --- meson.build | 62 ++++++++++++++++++++++++++---- src/jni/RubberBandStretcherJNI.cpp | 4 +- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/meson.build b/meson.build index 3238f2e..c76fec4 100644 --- a/meson.build +++ b/meson.build @@ -90,12 +90,21 @@ general_include_dirs = [ # Scan for any dependencies we may use later; all are optional +extra_include_args = [] +foreach d: get_option('extra_include_dirs') + extra_include_args += [ '-I' + d ] +endforeach + fftw3_dep = dependency('fftw3', version: '>= 3.0.0', required: false) samplerate_dep = dependency('samplerate', version: '>= 0.1.8', required: false) sndfile_dep = dependency('sndfile', version: '>= 1.0.16', required: false) vamp_dep = dependency('vamp-sdk', version: '>= 2.9', required: false) thread_dep = dependency('threads') -have_ladspa = cpp.has_header('ladspa.h') +have_ladspa = cpp.has_header('ladspa.h', args: extra_include_args) +have_jni = cpp.has_header('jni.h', args: extra_include_args) + +javac = find_program('javac') +jar = find_program('jar') # Check FFT and resampler options and set up dependencies and paths @@ -131,11 +140,6 @@ if resampler == 'auto' endif endif -extra_include_args = [] -foreach d: get_option('extra_include_dirs') - extra_include_args += [ '-I' + d ] -endforeach - if fft == 'kissfft' config_summary += { 'FFT': 'KissFFT' } message('For FFT: using KissFFT') @@ -362,6 +366,7 @@ if system == 'windows' rubberband_program_name = 'rubberband-program' rubberband_ladspa_name = 'ladspa-rubberband' rubberband_vamp_name = 'vamp-rubberband' + rubberband_jni_name = 'rubberband-jni' # Meson likes libxxx.a even on Windows, and so might we for a # new library, but not here platform_static_name_prefix = '' @@ -372,13 +377,14 @@ else rubberband_program_name = 'rubberband' rubberband_ladspa_name = 'ladspa-rubberband' rubberband_vamp_name = 'vamp-rubberband' + rubberband_jni_name = 'rubberband-jni' platform_static_name_prefix = 'lib' platform_static_name_suffix = 'a' endif # And the build targets: Static and dynamic libraries, command-line -# utility, LADSPA plugin, Vamp plugin +# utility, LADSPA plugin, Vamp plugin, JNI library message('Will build Rubber Band Library static library') target_summary += { 'Static library': [ true, 'Name: ' + rubberband_static_name ] } @@ -419,6 +425,48 @@ else message('Not building Rubber Band Library dynamic library: no_shared option set') endif +if have_jni and javac.found() and jar.found() + target_summary += { 'JNI library': [ true, 'Name: ' + rubberband_jni_name ] } + message('Will build Java Native Interface') + rubberband_jni = shared_library( + rubberband_jni_name, + jni_sources, + include_directories: general_include_dirs, + cpp_args: general_compile_args, + c_args: general_compile_args, + link_args: [ + arch_flags, + feature_libraries, + ], + dependencies: [ + rubberband_static_dep, + general_dependencies, + ], + # NB the JNI library is not versioned + install: true, + ) + rubberband_class = custom_target( + 'rubberband_class', + input: 'com/breakfastquay/rubberband/RubberBandStretcher.java', + output: 'RubberBandStretcher.class', + command: [ javac, '@INPUT@', '-d', '@OUTDIR@' ], + ) + rubberband_jar = custom_target( + 'rubberband_jar', + input: rubberband_class, + output: 'rubberband.jar', + command: [ jar, 'cvf', '@OUTPUT@', 'com/breakfastquay/rubberband/@INPUT@' ], + build_by_default: true, + ) +else + target_summary += { 'JNI library': false } + if not have_jni + message('Not building Java Native Interface: jni.h header not found') + else + message('Not building Java Native Interface: Java compiler not found') + endif +endif + install_headers( [ 'rubberband/RubberBandStretcher.h', 'rubberband/rubberband-c.h' diff --git a/src/jni/RubberBandStretcherJNI.cpp b/src/jni/RubberBandStretcherJNI.cpp index 79baecb..1d50979 100644 --- a/src/jni/RubberBandStretcherJNI.cpp +++ b/src/jni/RubberBandStretcherJNI.cpp @@ -329,7 +329,6 @@ Java_com_breakfastquay_rubberband_RubberBandStretcher_study(JNIEnv *env, jobject int channels = env->GetArrayLength(data); float **arr = allocate(channels); float **input = allocate(channels); - int samples = 0; for (int c = 0; c < channels; ++c) { jfloatArray cdata = (jfloatArray)env->GetObjectArrayElement(data, c); arr[c] = env->GetFloatArrayElements(cdata, 0); @@ -350,7 +349,6 @@ Java_com_breakfastquay_rubberband_RubberBandStretcher_process(JNIEnv *env, jobje int channels = env->GetArrayLength(data); float **arr = allocate(channels); float **input = allocate(channels); - int samples = 0; for (int c = 0; c < channels; ++c) { jfloatArray cdata = (jfloatArray)env->GetObjectArrayElement(data, c); arr[c] = env->GetFloatArrayElements(cdata, 0); @@ -383,7 +381,7 @@ Java_com_breakfastquay_rubberband_RubberBandStretcher_retrieve(JNIEnv *env, jobj float **outbuf = allocate_channels(channels, n); size_t retrieved = stretcher->retrieve(outbuf, n); - for (int c = 0; c < channels; ++c) { + for (size_t c = 0; c < channels; ++c) { jfloatArray cdata = (jfloatArray)env->GetObjectArrayElement(output, c); env->SetFloatArrayRegion(cdata, offset, retrieved, outbuf[c]); } From 7d2160cefae92d0f5f10fa4097aa29aaa6f2654e Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Fri, 12 Mar 2021 09:54:56 +0000 Subject: [PATCH 15/21] Oops, these are not required. Thank you, CI --- meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index c76fec4..65ee113 100644 --- a/meson.build +++ b/meson.build @@ -103,8 +103,8 @@ thread_dep = dependency('threads') have_ladspa = cpp.has_header('ladspa.h', args: extra_include_args) have_jni = cpp.has_header('jni.h', args: extra_include_args) -javac = find_program('javac') -jar = find_program('jar') +javac = find_program('javac', required: false) +jar = find_program('jar', required: false) # Check FFT and resampler options and set up dependencies and paths From ead8998668cf5c8465a0229deda1bff4bbe4a3db Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Fri, 12 Mar 2021 10:37:42 +0000 Subject: [PATCH 16/21] Source package build script --- otherbuilds/deploy/source.sh | 59 ++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100755 otherbuilds/deploy/source.sh diff --git a/otherbuilds/deploy/source.sh b/otherbuilds/deploy/source.sh new file mode 100755 index 0000000..c2ccf48 --- /dev/null +++ b/otherbuilds/deploy/source.sh @@ -0,0 +1,59 @@ +#!/bin/bash +set -eu +version=$(grep '^ *version:' meson.build | head -1 | sed "s/^.*'\([0-9][0-9.]*\)'.*$/\1/") +check() { + text="$1" + echo -n "$text [yN] " + read yn + case "$yn" in [Yy]) ;; *) echo "Exiting"; exit 3 ;; esac +} +echo +echo "Preparing to make source package for Rubber Band v$version..." +echo +grep '^ *version:' meson.build | head -1 +check "Is the above version number (in meson.build) correct?" +echo +echo "The dynamic library version should have a point increment for each" +echo "release, a minor increment for backward-compatible ABI changes, and" +echo "a major increment for incompatible ABI changes." +echo +grep 'rubberband_dynamic_library_version' meson.build | head -1 +check "Is the above library version (from meson.build) correct?" +echo +echo "The API major version should increment for incompatible API changes," +echo "and the minor version should increment for backward-compatible API" +echo "changes." +echo +grep 'RUBBERBAND.*VERSION' rubberband/RubberBandStretcher.h +check "Are the above version and API versions (from the C++ header) correct?" +echo +echo "The C header should contain the same versions as the C++ header." +echo +grep 'RUBBERBAND.*VERSION' rubberband/rubberband-c.h +check "Are the above version and API versions (from the C header) correct?" +echo +grep '^PROJECT_NUMBER' Doxyfile +check "Is the above version (from Doxyfile) correct?" + +echo +echo "Going ahead..." +mkdir -p packages +output="packages/rubberband-$version.tar.bz2" +hg archive "$output" + +echo "Checking that the package compiles..." +tmpdir=$(mktemp -d) +cleanup() { + rm -rf "$tmpdir" +} +trap cleanup 0 +prevdir=$(pwd) +( cd "$tmpdir" + tar xvf "$prevdir/$output" + cd "rubberband-$version" + meson build + ninja -C build +) + +echo +echo "Checked, package is in $output" From 11caa57cd39e6dd6e6df322e249b865ed0a62623 Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Fri, 12 Mar 2021 11:20:47 +0000 Subject: [PATCH 17/21] Mac packaging script --- cross/macos-arm64.txt | 1 + cross/macos-universal.txt | 1 + cross/macos-x86_64.txt | 1 + otherbuilds/deploy/macos.sh | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 36 insertions(+) create mode 100755 otherbuilds/deploy/macos.sh diff --git a/cross/macos-arm64.txt b/cross/macos-arm64.txt index 1a7c322..a03cf36 100644 --- a/cross/macos-arm64.txt +++ b/cross/macos-arm64.txt @@ -11,6 +11,7 @@ needs_exe_wrapper = false c = 'cc' cpp = 'c++' strip = 'strip' +pkgconfig = 'pkg-config' [built-in options] c_args = ['-arch', 'arm64'] diff --git a/cross/macos-universal.txt b/cross/macos-universal.txt index eb7970e..728980f 100644 --- a/cross/macos-universal.txt +++ b/cross/macos-universal.txt @@ -11,6 +11,7 @@ needs_exe_wrapper = false c = 'cc' cpp = 'c++' strip = 'strip' +pkgconfig = 'pkg-config' [built-in options] c_args = ['-arch', 'arm64', '-arch', 'x86_64'] diff --git a/cross/macos-x86_64.txt b/cross/macos-x86_64.txt index ad979a4..fb1a10d 100644 --- a/cross/macos-x86_64.txt +++ b/cross/macos-x86_64.txt @@ -11,6 +11,7 @@ needs_exe_wrapper = false c = 'cc' cpp = 'c++' strip = 'strip' +pkgconfig = 'pkg-config' [built-in options] c_args = ['-arch', 'x86_64'] diff --git a/otherbuilds/deploy/macos.sh b/otherbuilds/deploy/macos.sh new file mode 100755 index 0000000..425b5eb --- /dev/null +++ b/otherbuilds/deploy/macos.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -eu +if [ ! -f ../rba/deploy/macos/notarize.sh ]; then + echo "need notarize script in ../rba/deploy/macos" +fi +version=$(grep '^ *version:' meson.build | head -1 | sed "s/^.*'\([0-9][0-9.]*\)'.*$/\1/") +echo +echo "Packaging command-line utility for Mac for Rubber Band v$version..." +echo +rm -rf build +PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/ meson build --cross-file ./cross/macos-universal.txt +ninja -C build +./build/rubberband -V +key="Developer ID Application: Particular Programs Ltd (73F996B92S)" +mkdir -p packages +( cd build + codesign -s "$key" -fv --options runtime rubberband + zipfile="rubberband-$version-gpl-executable-macos.zip" + rm -f "$zipfile" + ditto -c -k rubberband "$zipfile" + ../../rba/deploy/macos/notarize.sh "$zipfile" com.breakfastquay.rubberband +) +package_dir="rubberband-$version-gpl-executable-macos" +rm -rf "$package_dir" +mkdir "$package_dir" +cp build/rubberband "$package_dir" +cp CHANGELOG README.md COPYING "$package_dir" +tar cvjf "$package_dir.tar.bz2" "$package_dir" +mv "$package_dir.tar.bz2" packages/ +rm -rf "$package_dir" +echo +echo "Done, package is in packages/$package_dir.tar.bz2" + From afbb105f4ada241ae9f7777c19db683ffb15f4aa Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Fri, 12 Mar 2021 11:35:08 +0000 Subject: [PATCH 18/21] Omit deploy dir from package --- otherbuilds/deploy/source.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/otherbuilds/deploy/source.sh b/otherbuilds/deploy/source.sh index c2ccf48..0278fed 100755 --- a/otherbuilds/deploy/source.sh +++ b/otherbuilds/deploy/source.sh @@ -39,7 +39,7 @@ echo echo "Going ahead..." mkdir -p packages output="packages/rubberband-$version.tar.bz2" -hg archive "$output" +hg archive --exclude otherbuilds/deploy "$output" echo "Checking that the package compiles..." tmpdir=$(mktemp -d) From b2b95759543f410567127c77350dc5d0b1abd232 Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Fri, 12 Mar 2021 12:03:24 +0000 Subject: [PATCH 19/21] Windows deployment bits --- README.md | 7 +++++ otherbuilds/deploy/win.bat | 54 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 otherbuilds/deploy/win.bat diff --git a/README.md b/README.md index cb085ef..d18a9d4 100644 --- a/README.md +++ b/README.md @@ -320,6 +320,13 @@ The Rubber Band code is compatible with both the traditional Visual C++ compiler (`cl`) and the Clang front-end (`clang`), and the build system will use whichever appears (first) in your path. +To build against a specific Visual C++ runtime, use the built-in Meson +option `b_vscrt`: + +``` +> meson build -Db_vscrt=mt +``` + See "FFT and resampler selection" below for further build options. Alternatively, if you only need the static library and prefer a Visual diff --git a/otherbuilds/deploy/win.bat b/otherbuilds/deploy/win.bat new file mode 100644 index 0000000..84e9f2e --- /dev/null +++ b/otherbuilds/deploy/win.bat @@ -0,0 +1,54 @@ + +echo on + +set STARTPWD=%CD% +set ORIGINALPATH=%PATH% +set PATH=C:\Program Files (x86)\Windows Kits\10\bin\x64;%PATH% + +set vcvarsall="C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" + +if not exist %vcvarsall% ( +@ echo "Could not find MSVC vars batch file" +@ exit /b 2 +) + +set VERSION=%1 +shift +if "%VERSION%" == "" ( +@echo "Usage: win.bat " +exit /b 1 +) + +@echo Building version %VERSION% + +call %vcvarsall% amd64 +if errorlevel 1 exit /b %errorlevel% + +del /q /s build + +meson build --buildtype release "-Dextra_include_dirs=C:\Program Files\libsndfile\include" "-Dextra_lib_dirs=C:\Program Files\libsndfile\lib" "-Db_vscrt=mt" +if errorlevel 1 exit /b %errorlevel% + +ninja -C build +if errorlevel 1 exit /b %errorlevel% + +cd build +ren rubberband-program.exe rubberband.exe +set NAME=Christopher Cannam +signtool sign /v /n "%NAME%" /t http://time.certum.pl /fd sha1 /a rubberband.exe +if errorlevel 1 exit /b %errorlevel% + +cd .. +set DIR=rubberband-%VERSION%-gpl-executable-windows +del /q /s %DIR% +mkdir %DIR% +copy build\rubberband.exe %DIR% +copy "c:\Program Files\libsndfile\bin\sndfile.dll" %DIR% +copy COPYING %DIR% +copy README.md %DIR% +copy CHANGELOG %DIR% + +set PATH=%ORIGINALPATH% +cd %STARTPWD% +@echo Done, now test and zip the directory %DIR% + From 59c34f9b3663ce35fd1a32bcc08f37b942b969d6 Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Fri, 12 Mar 2021 13:48:32 +0000 Subject: [PATCH 20/21] Added tag v1.9.1 for changeset 7af7a76bbb1d --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 70cb1f3..9259db4 100644 --- a/.hgtags +++ b/.hgtags @@ -11,3 +11,4 @@ efbc861f9b9460068c48a250232d343ffa7d5726 v1.7 d4911a276d96f6232a68c6b8448056d3946043b9 v1.8.1 fa6a54be7e6bf0c5adffd19ccec622481a8140a5 v1.8.2 37b18c17c042eafc39483ffb58837de844ba3289 v1.9 +7af7a76bbb1dc75f630555e22ca8f6ae9da79529 v1.9.1 From 109c321370e092a5659d03ee2d9f30669f794f2b Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Wed, 7 Apr 2021 11:03:33 +0100 Subject: [PATCH 21/21] Draw system from host rather than build machine (fixing cross-compilation failures, I am told) --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 65ee113..d32902c 100644 --- a/meson.build +++ b/meson.build @@ -17,7 +17,7 @@ project( rubberband_dynamic_library_version = '2.1.3' -system = build_machine.system() +system = host_machine.system() architecture = host_machine.cpu_family() cpp = meson.get_compiler('cpp')