From 622bccd1fec06785bec59eb468804252b214f572 Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Wed, 8 Sep 2021 11:23:23 +0100 Subject: [PATCH 1/3] We can actually specify an old OS version perfectly well in the universal cross file, and it'll work for both slices (the ARM one will just get 11 instead). So do that, and document it. Also print out the target in the config summary. --- README.md | 20 +++++++------------- cross/macos-universal.txt | 6 +++--- cross/macos-x86_64.txt | 4 ++-- meson.build | 38 +++++++++++++++++++++++++------------- 4 files changed, 37 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index a1ccc21..c017f07 100644 --- a/README.md +++ b/README.md @@ -258,17 +258,11 @@ this: $ meson build --cross-file cross/macos-universal.txt && ninja -C build ``` -However, the resulting binary will be marked as loadable on macOS 11+ -only, even for Intel, which is probably not what you want (ideally the -Intel slice would support older versions of the OS). A Makefile that -handles this explicitly is also provided: - -``` -$ make -f otherbuilds/Makefile.macos-universal -``` - -This produces only a static library, but it's a universal binary that -is compatible with macOS 10.7 onwards on the Intel side. +Note that the universal cross file also sets the minimum OS version to +the earliest supported macOS versions for both architectures. (Note +that actual compatibility will also depend on how any dependent +libraries have been compiled.) You can edit this in the +`cross/macos-universal.txt` file if you want a specific target. See "FFT and resampler selection" below for further build options. @@ -284,7 +278,7 @@ commercial terms. Ensure the Xcode command-line tools are installed, and ``` -$ meson build_ios --cross-file cross/ios.txt && ninja -C build +$ meson build_ios --cross-file cross/ios.txt && ninja -C build_ios ``` The output files will be found in the `build_ios` directory. @@ -292,7 +286,7 @@ The output files will be found in the `build_ios` directory. To build for the simulator, ``` -$ meson build_sim --cross-file cross/ios-simulator.txt && ninja -C build +$ meson build_sim --cross-file cross/ios-simulator.txt && ninja -C build_sim ``` The output files will be found in the `build_sim` directory. diff --git a/cross/macos-universal.txt b/cross/macos-universal.txt index 728980f..0242fa5 100644 --- a/cross/macos-universal.txt +++ b/cross/macos-universal.txt @@ -14,8 +14,8 @@ strip = 'strip' pkgconfig = 'pkg-config' [built-in options] -c_args = ['-arch', 'arm64', '-arch', 'x86_64'] -cpp_args = ['-arch', 'arm64', '-arch', 'x86_64'] -cpp_link_args = ['-arch', 'arm64', '-arch', 'x86_64'] +c_args = ['-arch', 'arm64', '-arch', 'x86_64', '-mmacosx-version-min=10.7'] +cpp_args = ['-arch', 'arm64', '-arch', 'x86_64', '-stdlib=libc++', '-mmacosx-version-min=10.7'] +cpp_link_args = ['-arch', 'arm64', '-arch', 'x86_64', '-stdlib=libc++', '-mmacosx-version-min=10.7'] diff --git a/cross/macos-x86_64.txt b/cross/macos-x86_64.txt index fb1a10d..64197a8 100644 --- a/cross/macos-x86_64.txt +++ b/cross/macos-x86_64.txt @@ -15,6 +15,6 @@ pkgconfig = 'pkg-config' [built-in options] c_args = ['-arch', 'x86_64'] -cpp_args = ['-arch', 'x86_64'] -cpp_link_args = ['-arch', 'x86_64'] +cpp_args = ['-arch', 'x86_64', '-stdlib=libc++'] +cpp_link_args = ['-arch', 'x86_64', '-stdlib=libc++'] diff --git a/meson.build b/meson.build index 38b70e2..35700cd 100644 --- a/meson.build +++ b/meson.build @@ -327,31 +327,43 @@ if system == 'darwin' '-exported_symbols_list', meson.source_root() / 'vamp/vamp-plugin.list' ] - have_version_min = false - foreach arg: get_option('cpp_args') - if arg.contains('version-min') - have_version_min = true - endif - endforeach - if architecture == 'aarch64' arch_flags += [ '-arch', 'arm64', ] - if not have_version_min - arch_flags += [ '-mmacosx-version-min=11' ] - endif elif architecture == 'x86_64' arch_flags += [ '-arch', 'x86_64', ] - if not have_version_min - arch_flags += [ '-mmacosx-version-min=10.13' ] - endif else # begin architecture != 'aarch64' or 'x86_64' error('Build for architecture ' + architecture + ' is not supported on this platform') endif # end architecture + have_version_min = false + foreach arg: get_option('cpp_args') + if arg.contains('version-min') + have_version_min = true + bits = arg.split('=') + if bits.length() > 1 + config_summary += { 'Target OS': bits[1] + '+' } + else + config_summary += { 'Target OS': '(unknown)' } + endif + endif + endforeach + + if not have_version_min + message('Using default minimum target OS version') + message('(consider specifying this in cross-file if earlier target is desired)') + if architecture == 'aarch64' + arch_flags += [ '-mmacosx-version-min=11' ] + config_summary += { 'Target OS': '11+' } + else + arch_flags += [ '-mmacosx-version-min=10.13' ] + config_summary += { 'Target OS': '10.13+' } + endif + endif + elif system == 'windows' feature_defines += ['-D_WIN32', '-DNOMINMAX', '-D_USE_MATH_DEFINES', '-DGETOPT_API='] if cpp.get_id() == 'msvc' From 77552e82b1b2a2853f3a03e5760ac6f7e2a9ba0d Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Fri, 10 Sep 2021 08:39:33 +0100 Subject: [PATCH 2/3] Improve docs for processing modes --- rubberband/RubberBandStretcher.h | 50 +++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/rubberband/RubberBandStretcher.h b/rubberband/RubberBandStretcher.h index 64ab048..8416ab2 100644 --- a/rubberband/RubberBandStretcher.h +++ b/rubberband/RubberBandStretcher.h @@ -44,7 +44,22 @@ * * The Rubber Band API is contained in the single class * RubberBand::RubberBandStretcher. - * + * + * The Rubber Band stretcher supports two processing modes, offline + * and real-time. The choice of mode is fixed on construction. In + * offline mode, you must provide the audio block-by-block in two + * passes: in the first pass calling study(), in the second pass + * calling process() and receiving the output via retrieve(). In + * real-time mode there is no study pass, just a single streaming pass + * in which the audio is passed to process() and output received via + * retrieve(). + * + * In real-time mode you can change the time and pitch ratios at any + * time, but in offline mode they are fixed and cannot be changed + * after the study pass has begun. (However, see setKeyFrameMap() for + * a way to do pre-planned variable time stretching in offline mode.) + * Offline mode typically produces slightly more precise results. + * * Threading notes for real-time applications: * * Multiple instances of RubberBandStretcher may be created and used @@ -332,11 +347,28 @@ public: /** * Construct a time and pitch stretcher object to run at the given - * sample rate, with the given number of channels. Processing - * options and the time and pitch scaling ratios may be provided. - * The time and pitch ratios may be changed after construction, - * but most of the options may not. See the option documentation - * above for more details. + * sample rate, with the given number of channels. + * + * Initial time and pitch scaling ratios and other processing + * options may be provided. In particular, the behaviour of the + * stretcher depends strongly on whether offline or real-time mode + * is selected on construction (via OptionProcessOffline or + * OptionProcessRealTime option - offline is the default). + * + * In offline mode, you must provide the audio block-by-block in + * two passes: in the first pass calling study(), in the second + * pass calling process() and receiving the output via + * retrieve(). In real-time mode there is no study pass, just a + * single streaming pass in which the audio is passed to process() + * and output received via retrieve(). + * + * In real-time mode you can change the time and pitch ratios at + * any time, but in offline mode they are fixed and cannot be + * changed after the study pass has begun. (However, see + * setKeyFrameMap() for a way to do pre-planned variable time + * stretching in offline mode.) + * + * See the option documentation above for more details. */ RubberBandStretcher(size_t sampleRate, size_t channels, @@ -635,8 +667,10 @@ public: /** * Obtain some processed output data from the stretcher. Up to - * "samples" samples will be stored in the output arrays (one per - * channel for de-interleaved audio data) pointed to by "output". + * "samples" samples will be stored in each of the output arrays + * (one per channel for de-interleaved audio data) pointed to by + * "output". The number of sample frames available to be + * retrieved can be queried beforehand with a call to available(). * The return value is the actual number of sample frames * retrieved. * From cbf41915a8165dd61a1bbec81479e44b0b52663c Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Thu, 30 Sep 2021 15:27:23 +0100 Subject: [PATCH 3/3] Small grammar tweak --- rubberband/RubberBandStretcher.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rubberband/RubberBandStretcher.h b/rubberband/RubberBandStretcher.h index 8416ab2..bb0362e 100644 --- a/rubberband/RubberBandStretcher.h +++ b/rubberband/RubberBandStretcher.h @@ -50,9 +50,9 @@ * offline mode, you must provide the audio block-by-block in two * passes: in the first pass calling study(), in the second pass * calling process() and receiving the output via retrieve(). In - * real-time mode there is no study pass, just a single streaming pass - * in which the audio is passed to process() and output received via - * retrieve(). + * real-time mode, there is no study pass, just a single streaming + * pass in which the audio is passed to process() and output received + * via retrieve(). * * In real-time mode you can change the time and pitch ratios at any * time, but in offline mode they are fixed and cannot be changed @@ -358,7 +358,7 @@ public: * In offline mode, you must provide the audio block-by-block in * two passes: in the first pass calling study(), in the second * pass calling process() and receiving the output via - * retrieve(). In real-time mode there is no study pass, just a + * retrieve(). In real-time mode, there is no study pass, just a * single streaming pass in which the audio is passed to process() * and output received via retrieve(). *