Merge from branch r3
This commit is contained in:
@@ -16,7 +16,11 @@ build_script:
|
||||
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||
- meson build "-Dextra_include_dirs=C:\Program Files\libsndfile\include" "-Dextra_lib_dirs=C:\Program Files\libsndfile\lib"
|
||||
- ninja -C build
|
||||
- meson test -C build
|
||||
# Test the VC++ static library build, which is separate
|
||||
- msbuild otherbuilds\rubberband-library.vcxproj /t:Build /p:Configuration=Release
|
||||
# And test the .NET FFI interface build, which is again separate
|
||||
# Test the .NET FFI interface build, which is again separate
|
||||
- msbuild dotnet\rubberband.sln /t:Restore;Build
|
||||
# And test the single-file build
|
||||
- cl main\main.cpp single\RubberBandSingle.cpp .\src\ext\getopt\getopt.c src\ext\getopt\getopt_long.c "C:\Program Files\libsndfile\lib\sndfile.lib" /O2 /std:c++14 /D_USE_MATH_DEFINES /DNOMINMAX /EHs /I"C:\Program Files\libsndfile\include" /link /out:test_single.exe
|
||||
|
||||
|
||||
19
.build.yml
19
.build.yml
@@ -7,6 +7,7 @@ packages:
|
||||
- ladspa-sdk
|
||||
- lv2-dev
|
||||
- vamp-plugin-sdk
|
||||
- libboost-test-dev
|
||||
- meson
|
||||
- ninja-build
|
||||
sources:
|
||||
@@ -15,9 +16,27 @@ tasks:
|
||||
- setup: |
|
||||
cd rubberband
|
||||
meson build
|
||||
meson build_speex -Dresampler=speex
|
||||
meson build_libsamplerate -Dresampler=libsamplerate
|
||||
meson build_fftw -Dfft=fftw
|
||||
meson build_kissfft -Dfft=kissfft
|
||||
- build: |
|
||||
cd rubberband
|
||||
ninja -C build
|
||||
meson test -C build
|
||||
build/rubberband -V
|
||||
ninja -C build_speex
|
||||
meson test -C build_speex
|
||||
build_speex/rubberband -V
|
||||
ninja -C build_libsamplerate
|
||||
meson test -C build_libsamplerate
|
||||
build_libsamplerate/rubberband -V
|
||||
ninja -C build_fftw
|
||||
meson test -C build_fftw
|
||||
build_fftw/rubberband -V
|
||||
ninja -C build_kissfft
|
||||
meson test -C build_kissfft
|
||||
build_kissfft/rubberband -V
|
||||
./otherbuilds/check.sh
|
||||
triggers:
|
||||
- action: email
|
||||
|
||||
2
.github/workflows/macos-ios.yml
vendored
2
.github/workflows/macos-ios.yml
vendored
@@ -21,6 +21,8 @@ jobs:
|
||||
run: ninja -C build_macos
|
||||
- name: make ios
|
||||
run: ninja -C build_ios
|
||||
- name: unit test macos
|
||||
run: meson test -C build_macos
|
||||
- name: check otherbuilds
|
||||
run: otherbuilds/check.sh
|
||||
|
||||
|
||||
@@ -26,3 +26,7 @@ build
|
||||
build_*
|
||||
build-*
|
||||
UpgradeLog*
|
||||
out-*/
|
||||
playlist-out/*
|
||||
formant-out-*/
|
||||
out*.wav
|
||||
|
||||
7
.hgtags
7
.hgtags
@@ -16,3 +16,10 @@ fa6a54be7e6bf0c5adffd19ccec622481a8140a5 v1.8.2
|
||||
4a6f7059b6b77fb34a9f29037f3ece47755e99a0 v2.0.0
|
||||
190ba65557c06823ef576d5d62b99e2d27771759 v2.0.1
|
||||
4e2177c66756fecacccf211df5f8a97d01070ef0 v2.0.2
|
||||
590cb5c496f868d9806db5205bfe22ddeb7f5767 v3.0.0-beta1
|
||||
acc04c20175ebc3f8138c4e14c9108cb33024fb1 v3.0.0-beta2
|
||||
acc04c20175ebc3f8138c4e14c9108cb33024fb1 v3.0.0-beta2
|
||||
ed9acf241b1076e84ba0b41dc9d8edd904f69f25 v3.0.0-beta2
|
||||
58b588a580a126adb16de96f8eade96111758085 v3.0.0-beta3
|
||||
58b588a580a126adb16de96f8eade96111758085 v3.0.0-beta3
|
||||
78a701fb6daa670fc49648816f040a70689c86a7 v3.0.0-beta3
|
||||
|
||||
23
CHANGELOG
23
CHANGELOG
@@ -1,4 +1,27 @@
|
||||
|
||||
Changes in Rubber Band v3.0.0
|
||||
|
||||
* Introduce a new processing engine, the R3 (Finer) engine, which
|
||||
typically produces higher-quality output than the existing R2
|
||||
engine but at significantly higher CPU cost. The R2 engine is
|
||||
still the default, and R3 can be selected using the new
|
||||
OptionEngineFiner option on construction. See the documentation
|
||||
for more details.
|
||||
* Add ability to provide a custom set of log callbacks, so that
|
||||
debug and warning logs can be routed to the application's log
|
||||
stream and/or handled in a realtime-safe way
|
||||
* Add option to shift formant independently of pitch (R3 engine
|
||||
only)
|
||||
|
||||
The library is both binary and API compatible all the way back to
|
||||
version 1.2 for forward compatibility, but not backward compatibility,
|
||||
as several new functions and enum values have been added. Code
|
||||
written to use 3.0 is not necessarily compatible with 2.x or 1.x, but
|
||||
code written to use any earlier version can update to 3.0 without
|
||||
modification (and it will continue to use the same processing engine
|
||||
if the calling code is unchanged).
|
||||
|
||||
|
||||
Changes in Rubber Band v2.0.2
|
||||
|
||||
* Fix a crash in certain configurations when using mid-side
|
||||
|
||||
524
COMPILING.md
Normal file
524
COMPILING.md
Normal file
@@ -0,0 +1,524 @@
|
||||
|
||||
# Compiling Rubber Band Library
|
||||
|
||||
## Contents of this file
|
||||
|
||||
1. General instructions
|
||||
2. Building on Linux
|
||||
3. Building on macOS
|
||||
4. Building for iOS
|
||||
5. Building on Windows
|
||||
6. Building for Android and Java integration
|
||||
7. FFT and resampler selection
|
||||
8. Other supported #defines
|
||||
9. Copyright notes for bundled libraries
|
||||
|
||||
|
||||
## 1. General instructions
|
||||
|
||||
**Full configurable build.** The primary supported build system for
|
||||
Rubber Band on all platforms is Meson (https://mesonbuild.com). The
|
||||
Meson build system can be used to build all targets (static and
|
||||
dynamic library, command-line utility, and plugins) and to
|
||||
cross-compile. See below for details.
|
||||
|
||||
**Single-file build.** If you want to include Rubber Band in a C++
|
||||
project and would prefer not to build it as a separate library, there
|
||||
is a single `.cpp` file at `single/RubberBandSingle.cpp` which can be
|
||||
added to your project as-is. It produces a single compilation-unit
|
||||
build using the built-in FFT and resampler implementations with no
|
||||
further library dependencies. See the comments at the top of that file
|
||||
for more information.
|
||||
|
||||
**Other build options.** If you only need a static library and don't
|
||||
wish to use Meson, some alternative build files (Makefiles and Visual
|
||||
C++ projects) are included in the `otherbuilds` directory. See the
|
||||
platform-specific build sections below for more details.
|
||||
|
||||
To build with Meson, ensure Meson and Ninja are installed and run:
|
||||
|
||||
```
|
||||
$ meson build && ninja -C build
|
||||
```
|
||||
|
||||
This checks for necessary dependencies, reports what it finds, and if
|
||||
all is well, builds the code into a subdirectory called `build`. It
|
||||
will build everything it can find the requisite dependencies for:
|
||||
static and dynamic libraries, LADSPA, LV2, and Vamp plugins, and
|
||||
command-line utility.
|
||||
|
||||
Some configuration options are provided, described in the
|
||||
`meson_options.txt` file. To set one of these, add a `-D` option to
|
||||
Meson:
|
||||
|
||||
```
|
||||
$ meson build -Dipp_path=/opt/intel/ipp
|
||||
```
|
||||
|
||||
The options are documented in the library- and platform-specific
|
||||
sections below.
|
||||
|
||||
Rubber Band Library is written entirely in C++ and requires a C++11
|
||||
compiler. It is unlikely to make any difference (performance or
|
||||
otherwise) which C++ standard you compile with, as long as it's no
|
||||
older than C++11.
|
||||
|
||||
If you are building this software using either of the Speex or KissFFT
|
||||
library options, please be sure to review the terms for those
|
||||
libraries in `src/speex/COPYING` and `src/kissfft/COPYING` as
|
||||
applicable.
|
||||
|
||||
|
||||
## 2. Building on Linux
|
||||
|
||||
Optionally, if you want the command-line tool and plugins to be built,
|
||||
first install libsndfile and the LADSPA, LV2, and Vamp plugin headers
|
||||
so they can be found using `pkg-config`. Then
|
||||
|
||||
```
|
||||
$ meson build && ninja -C build
|
||||
```
|
||||
|
||||
See "FFT and resampler selection" below for further build options.
|
||||
|
||||
Alternatively, if you only need the static library and prefer a
|
||||
Makefile, try
|
||||
|
||||
```
|
||||
$ make -f otherbuilds/Makefile.linux
|
||||
```
|
||||
|
||||
|
||||
## 3. Building on macOS
|
||||
|
||||
Ensure the Xcode command-line tools are installed, and if you want the
|
||||
command-line tool to be built, also install libsndfile.
|
||||
|
||||
To build for the default architecture:
|
||||
|
||||
```
|
||||
$ meson build && ninja -C build
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
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:
|
||||
|
||||
```
|
||||
$ meson build --cross-file cross/macos-universal.txt && ninja -C build
|
||||
```
|
||||
|
||||
Note that the universal cross file also sets the minimum OS version to
|
||||
the earliest supported macOS versions for both architectures. (In
|
||||
practice, compatibility will also depend on how the 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.
|
||||
|
||||
Note that you cannot legally distribute applications using Rubber Band
|
||||
in the Mac App Store, unless you have first obtained a commercial
|
||||
licence for Rubber Band Library. GPL code is not permitted in the app
|
||||
store. See https://breakfastquay.com/technology/license.html for
|
||||
commercial terms.
|
||||
|
||||
|
||||
## 4. Building for iOS
|
||||
|
||||
Ensure the Xcode command-line tools are installed, and
|
||||
|
||||
```
|
||||
$ meson build_ios --cross-file cross/ios.txt && ninja -C build_ios
|
||||
```
|
||||
|
||||
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_sim
|
||||
```
|
||||
|
||||
The output files will be found in the `build_sim` directory.
|
||||
|
||||
See "FFT and resampler selection" below for further build options.
|
||||
|
||||
Note that you cannot legally distribute applications using Rubber Band
|
||||
in the iOS App Store, unless you have a first obtained a commercial
|
||||
licence for Rubber Band Library. GPL code is not permitted in the app
|
||||
store. See https://breakfastquay.com/technology/license.html for
|
||||
commercial terms.
|
||||
|
||||
|
||||
## 5. Building on Windows
|
||||
|
||||
If you only need to build the static library for integration into your
|
||||
project, and you prefer a Visual Studio project file, you can find a
|
||||
simple one in `otherbuilds\rubberband-library.vcxproj`.
|
||||
|
||||
The rest of this section describes the "full" build system, which uses
|
||||
Meson just as on the other platforms. So to build this way, start by
|
||||
ensuring Meson and Ninja are installed and available. Then, in a
|
||||
terminal window with the compiler tools available in the path (e.g. a
|
||||
Visual Studio command-line prompt for the relevant build architecture)
|
||||
run
|
||||
|
||||
```
|
||||
> meson build
|
||||
> ninja -C build
|
||||
```
|
||||
|
||||
The output files will be found in the `build` directory.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
## 6. Building for Android and Java integration
|
||||
|
||||
Currently only a very old Android NDK build file is provided, as
|
||||
`otherbuilds/Android.mk`. This includes compile definitions for a
|
||||
shared library built for ARM architectures which can be loaded from a
|
||||
Java application using the Java native interface (i.e. the Android
|
||||
NDK).
|
||||
|
||||
The Java side of the interface can be found in
|
||||
`com/breakfastquay/rubberband/RubberBandStretcher.java`.
|
||||
|
||||
See
|
||||
https://hg.sr.ht/~breakfastquay/rubberband-android-simple-sample
|
||||
for a very trivial example of integration with Android Java code.
|
||||
|
||||
The supplied `.mk` file uses KissFFT and the Speex resampler.
|
||||
|
||||
|
||||
## 7. FFT and resampler selection
|
||||
|
||||
Rubber Band requires the selection of library code for FFT calculation
|
||||
and resampling. Several libraries are supported. The selection is
|
||||
controlled (in Meson) using `-D` options and (in the code itself)
|
||||
using preprocessor flags set by the build system. These options and
|
||||
flags are detailed in the tables below.
|
||||
|
||||
At least one resampler implementation and one FFT implementation must
|
||||
be enabled. It is technically possible to enable more than one, but
|
||||
it's confusing and not often useful.
|
||||
|
||||
If you are building this software using the bundled Speex or KissFFT
|
||||
library code, please be sure to review the terms for those libraries
|
||||
in `src/speex/COPYING` and `src/kissfft/COPYING` as applicable.
|
||||
|
||||
If you are proposing to package Rubber Band for a Linux distribution,
|
||||
please select either the built-in FFT or FFTW, and either the built-in
|
||||
resampler or libsamplerate.
|
||||
|
||||
### FFT libraries supported
|
||||
|
||||
```
|
||||
Library Build option CPP define Notes
|
||||
---- ------------ ---------- -----
|
||||
|
||||
Built-in -Dfft=builtin -DUSE_BUILTIN_FFT
|
||||
Default except on macOS/iOS.
|
||||
Can be distributed with either
|
||||
the Rubber Band GPL or
|
||||
commercial licence.
|
||||
|
||||
Accelerate -Dfft=vdsp -DHAVE_VDSP Default on macOS/iOS.
|
||||
Best option on these platforms.
|
||||
|
||||
FFTW3 -Dfft=fftw -DHAVE_FFTW3 GPL.
|
||||
A bit faster than built-in,
|
||||
a bit slower than Accelerate.
|
||||
|
||||
KissFFT -Dfft=kissfft -DHAVE_KISSFFT
|
||||
Single precision.
|
||||
Only indicated for use with
|
||||
single-precision sample type
|
||||
(see below).
|
||||
Bundled, can be distributed with
|
||||
either the Rubber Band GPL or
|
||||
commercial licence.
|
||||
|
||||
Intel IPP -Dfft=ipp -DHAVE_IPP Proprietary, can only be used with
|
||||
Rubber Band commercial licence.
|
||||
```
|
||||
|
||||
### Resampler libraries supported
|
||||
|
||||
```
|
||||
Library Build option CPP define Notes
|
||||
---- ------------ ---------- -----
|
||||
|
||||
Built-in -Dfft=builtin -DUSE_BQRESAMPLER
|
||||
Default.
|
||||
Can be distributed with either
|
||||
the Rubber Band GPL or
|
||||
commercial licence. Intended to
|
||||
give best quality for time-varying
|
||||
pitch shifts in real-time mode.
|
||||
Newer than, and not as well-tested
|
||||
as, libsamplerate.
|
||||
|
||||
libsamplerate -DHAVE_LIBSAMPLERATE
|
||||
-Dresampler=libsamplerate Good choice in most cases.
|
||||
|
||||
Speex -DUSE_SPEEX
|
||||
-Dresampler=speex Can be distributed with
|
||||
either the Rubber Band GPL or
|
||||
commercial licence.
|
||||
```
|
||||
|
||||
## 8. Other supported #defines
|
||||
|
||||
Other known preprocessor symbols are as follows. (Usually the supplied
|
||||
build files will handle these for you.)
|
||||
|
||||
-DLACK_BAD_ALLOC
|
||||
Define on systems lacking std::bad_alloc in the C++ library.
|
||||
|
||||
-DLACK_POSIX_MEMALIGN
|
||||
Define on systems lacking posix_memalign.
|
||||
|
||||
-DUSE_OWN_ALIGNED_MALLOC
|
||||
Define on systems lacking any aligned malloc implementation.
|
||||
|
||||
-DLACK_SINCOS
|
||||
Define on systems lacking sincos().
|
||||
|
||||
-DNO_EXCEPTIONS
|
||||
Build without use of C++ exceptions.
|
||||
|
||||
-DNO_THREADING
|
||||
Build without any multithread support.
|
||||
|
||||
-DUSE_PTHREADS
|
||||
Use the pthreads library (required unless NO_THREADING or on Windows)
|
||||
|
||||
-DPROCESS_SAMPLE_TYPE=float
|
||||
Select single precision for internal calculations. The default is
|
||||
double precision. Consider in conjunction with single-precision
|
||||
KissFFT for mobile architectures with slower double-precision
|
||||
support.
|
||||
|
||||
-DUSE_POMMIER_MATHFUN
|
||||
Select the Julien Pommier implementations of trig functions for ARM
|
||||
NEON or x86 SSE architectures. These are usually faster but may be
|
||||
of lower precision than system implementations. Consider using this
|
||||
for 32-bit mobile architectures.
|
||||
|
||||
|
||||
## 9. Copyright notes for bundled libraries
|
||||
|
||||
### 5a. Speex
|
||||
|
||||
```
|
||||
[files in src/speex]
|
||||
|
||||
Copyright 2002-2007 Xiph.org Foundation
|
||||
Copyright 2002-2007 Jean-Marc Valin
|
||||
Copyright 2005-2007 Analog Devices Inc.
|
||||
Copyright 2005-2007 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO)
|
||||
Copyright 1993, 2002, 2006 David Rowe
|
||||
Copyright 2003 EpicGames
|
||||
Copyright 1992-1994 Jutta Degener, Carsten Bormann
|
||||
|
||||
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 name of the Xiph.org Foundation nor the names of its
|
||||
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 FOUNDATION 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.
|
||||
```
|
||||
|
||||
### 5b. KissFFT
|
||||
|
||||
```
|
||||
[files in src/kissfft]
|
||||
|
||||
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.
|
||||
```
|
||||
|
||||
### 5c. Pommier math functions
|
||||
|
||||
```
|
||||
[files in src/pommier]
|
||||
|
||||
Copyright (C) 2011 Julien Pommier
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
```
|
||||
|
||||
### 5d. float_cast
|
||||
|
||||
```
|
||||
[files in src/float_cast]
|
||||
|
||||
Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this file for any
|
||||
purpose is hereby granted without fee, provided that the above copyright
|
||||
and this permission notice appear in all copies. No representations are
|
||||
made about the suitability of this software for any purpose. It is
|
||||
provided "as is" without express or implied warranty.
|
||||
```
|
||||
|
||||
### 5e. getopt
|
||||
|
||||
```
|
||||
[files in src/getopt, used by command-line tool on some platforms]
|
||||
|
||||
Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
All rights reserved.
|
||||
|
||||
This code is derived from software contributed to The NetBSD Foundation
|
||||
by Dieter Baron and Thomas Klausner.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. 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.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the NetBSD
|
||||
Foundation, Inc. and its contributors.
|
||||
4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
|
||||
```
|
||||
|
||||
### 5f. rubberband-sharp
|
||||
|
||||
```
|
||||
[files in rubberband-dll and rubberband-sharp]
|
||||
|
||||
Copyright 2018-2019 Jonathan Gilbert
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
||||
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Jonathan Gilbert
|
||||
shall not be used in advertising or otherwise to promote the sale,
|
||||
use or other dealings in this Software without prior written
|
||||
authorization.
|
||||
```
|
||||
2
Doxyfile
2
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 = 2.0.2
|
||||
PROJECT_NUMBER = 3.0.0
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# base path where the generated documentation will be put.
|
||||
|
||||
569
README.md
569
README.md
@@ -53,7 +53,8 @@ responsibility to ensure that you redistribute these only in
|
||||
accordance with their own licence terms, regardless of the conditions
|
||||
under which you are redistributing the Rubber Band code itself. The
|
||||
licences for some relevant library code are as follows, to the best of
|
||||
our knowledge. See also the end of this README for detailed terms.
|
||||
our knowledge. See also the file [COMPILING.md](COMPILING.md) for more
|
||||
details.
|
||||
|
||||
* FFTW3 - GPL; proprietary licence needed for redistribution
|
||||
* Intel IPP - Proprietary; licence needed for redistribution
|
||||
@@ -63,20 +64,17 @@ our knowledge. See also the end of this README for detailed terms.
|
||||
* Pommier math functions - BSD-like
|
||||
|
||||
|
||||
## Compiling Rubber Band Library
|
||||
|
||||
Please refer to the file [COMPILING.md](COMPILING.md) for details of
|
||||
how to configure and build the library.
|
||||
|
||||
|
||||
## Contents of this README
|
||||
|
||||
1. Code components
|
||||
2. Using the Rubber Band command-line tool
|
||||
3. Using Rubber Band Library
|
||||
4. Compiling Rubber Band:
|
||||
a. Building on Linux
|
||||
b. Building on macOS
|
||||
c. Building for iOS
|
||||
d. Building on Windows
|
||||
e. Building for Android and Java integration
|
||||
f. FFT and resampler selection
|
||||
g. Other supported #defines
|
||||
5. Copyright notes for bundled libraries
|
||||
|
||||
|
||||
## 1. Code components
|
||||
@@ -87,7 +85,8 @@ Rubber Band consists of:
|
||||
be used by your applications. The headers for this are in the
|
||||
`rubberband/` directory, and the source code is in `src/`.
|
||||
The Rubber Band Library may also depend upon external resampler
|
||||
and FFT code; see section 4 below for details.
|
||||
and FFT code, if so configured; see section 7 of COMPILING.md for
|
||||
details.
|
||||
|
||||
* The Rubber Band command-line tool. This is in `main/main.cpp`.
|
||||
This program uses Rubber Band Library and also requires libsndfile
|
||||
@@ -106,7 +105,7 @@ Rubber Band consists of:
|
||||
|
||||
## 2. Using the Rubber Band command-line tool
|
||||
|
||||
The Rubber Band command-line tool builds as `bin/rubberband`. The
|
||||
The Rubber Band command-line tool builds as `build/rubberband`. The
|
||||
basic incantation is
|
||||
|
||||
```
|
||||
@@ -124,8 +123,25 @@ duration, shifts it up in pitch by a whole tone, and writes the output
|
||||
to `output.wav`.
|
||||
|
||||
Several further options are available: run `rubberband -h` for help.
|
||||
In particular, different types of music may benefit from different
|
||||
"crispness" options (`-c` flag, with a numerical argument from 0 to 6).
|
||||
|
||||
The most important are the options `-2` and `-3`. These select between
|
||||
two different processing engines, known as the R2 (Faster) engine and
|
||||
the R3 (Finer) engine. The R3 engine produces higher-quality results
|
||||
than R2 for most material, especially complex mixes, vocals and other
|
||||
sounds that have soft onsets and smooth pitch changes, and music with
|
||||
substantial bass content. However, it uses much more CPU than the R2
|
||||
engine.
|
||||
|
||||
The R2 engine was the only method available in Rubber Band Library up
|
||||
to versions 2.x, and for compatibility it remains the default (in the
|
||||
case that neither `-2` nor `-3` is requested explicitly) whenever the
|
||||
command-line tool is invoked as `rubberband`. The R3 engine is the
|
||||
default if the tool is invoked as `rubberband-r3`.
|
||||
|
||||
Many further options are available, most of which only have an effect
|
||||
when using the R2 engine. In particular, different types of music may
|
||||
benefit from different "crispness" options (`-c` flag, with a
|
||||
numerical argument from 0 to 6).
|
||||
|
||||
|
||||
## 3. Using Rubber Band Library
|
||||
@@ -150,520 +166,19 @@ provides a good example of how to use Rubber Band in offline mode; the
|
||||
pitch shifter plugin (`ladspa-lv2/RubberBandPitchShifter.cpp`) may be
|
||||
used as an example of Rubber Band in real-time mode.
|
||||
|
||||
IMPORTANT: Please ensure you have read and understood the licensing
|
||||
terms for Rubber Band before using it in your application. This
|
||||
library is provided under the GNU General Public License, which means
|
||||
that any application that uses it must also be published under the GPL
|
||||
or a compatible licence (i.e. with its full source code also available
|
||||
for modification and redistribution) unless you have separately
|
||||
acquired a commercial licence from the author.
|
||||
**IMPORTANT:** Please ensure you have read and understood the
|
||||
licensing terms for Rubber Band before using it in your application.
|
||||
This library is provided under the GNU General Public License, which
|
||||
means that any application that uses it must also be published under
|
||||
the GPL or a compatible licence (i.e. with its full source code also
|
||||
available for modification and redistribution) unless you have
|
||||
separately acquired a commercial licence from the author.
|
||||
|
||||
|
||||
## 4. Compiling Rubber Band Library
|
||||
## 4. Further documentation
|
||||
|
||||
**Full configurable build.** The primary supported build system for
|
||||
Rubber Band on all platforms is Meson (https://mesonbuild.com). The
|
||||
Meson build system can be used to build all targets (static and
|
||||
dynamic library, command-line utility, and plugins) and to
|
||||
cross-compile. See below for details.
|
||||
* The [API documentation](https://breakfastquay.com/rubberband/code-doc/index.html) is thorough and we encourage you to read it
|
||||
* [Conceptual notes and examples](https://breakfastquay.com/rubberband/integration.html) for integration into an application
|
||||
* [Help text](https://breakfastquay.com/rubberband/usage.txt) of the command-line application
|
||||
* [Rubber Band Library home page](https://breakfastquay.com/rubberband/)
|
||||
|
||||
**Single-file build.** If you want to include Rubber Band in a C++
|
||||
project and would prefer not to build it as a separate library, there
|
||||
is a single `.cpp` file at `single/RubberBandSingle.cpp` which can be
|
||||
added to your project as-is. It produces a single compilation-unit
|
||||
build using the built-in FFT and resampler implementations with no
|
||||
further library dependencies. See the comments at the top of that file
|
||||
for more information.
|
||||
|
||||
**Other build options.** If you only need a static library and don't
|
||||
wish to use Meson, some alternative build files (Makefiles and Visual
|
||||
C++ projects) are included in the `otherbuilds` directory. See the
|
||||
platform-specific build sections below for more details.
|
||||
|
||||
To build with Meson, ensure Meson and Ninja are installed and run:
|
||||
|
||||
```
|
||||
$ meson build && ninja -C build
|
||||
```
|
||||
|
||||
This checks for necessary dependencies, reports what it finds, and if
|
||||
all is well, builds the code into a subdirectory called `build`. It
|
||||
will build everything it can find the requisite dependencies for:
|
||||
static and dynamic libraries, LADSPA, LV2, and Vamp plugins, and
|
||||
command-line utility.
|
||||
|
||||
Some configuration options are provided, described in the
|
||||
`meson_options.txt` file. To set one of these, add a `-D` option to
|
||||
Meson:
|
||||
|
||||
```
|
||||
$ meson build -Dipp_path=/opt/intel/ipp
|
||||
```
|
||||
|
||||
The options are documented in the library- and platform-specific
|
||||
sections below.
|
||||
|
||||
Rubber Band Library is written entirely in C++ and requires a C++11
|
||||
compiler. It is unlikely to make any difference (performance or
|
||||
otherwise) which C++ standard you compile with, as long as it's no
|
||||
older than C++11.
|
||||
|
||||
If you are building this software using either of the Speex or KissFFT
|
||||
library options, please be sure to review the terms for those
|
||||
libraries in `src/speex/COPYING` and `src/kissfft/COPYING` as
|
||||
applicable.
|
||||
|
||||
|
||||
### 4a. Building on Linux
|
||||
|
||||
Optionally, if you want the command-line tool and plugins to be built,
|
||||
first install libsndfile and the LADSPA, LV2, and Vamp plugin headers
|
||||
so they can be found using `pkg-config`. Then
|
||||
|
||||
```
|
||||
$ meson build && ninja -C build
|
||||
```
|
||||
|
||||
See "FFT and resampler selection" below for further build options.
|
||||
|
||||
Alternatively, if you only need the static library and prefer a
|
||||
Makefile, try
|
||||
|
||||
```
|
||||
$ make -f otherbuilds/Makefile.linux
|
||||
```
|
||||
|
||||
|
||||
### 4b. Building on macOS
|
||||
|
||||
Ensure the Xcode command-line tools are installed, and if you want the
|
||||
command-line tool to be built, also install libsndfile.
|
||||
|
||||
To build for the default architecture:
|
||||
|
||||
```
|
||||
$ meson build && ninja -C build
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
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:
|
||||
|
||||
```
|
||||
$ meson build --cross-file cross/macos-universal.txt && ninja -C build
|
||||
```
|
||||
|
||||
Note that the universal cross file also sets the minimum OS version to
|
||||
the earliest supported macOS versions for both architectures. (In
|
||||
practice, compatibility will also depend on how the 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.
|
||||
|
||||
Note that you cannot legally distribute applications using Rubber Band
|
||||
in the Mac App Store, unless you have first obtained a commercial
|
||||
licence for Rubber Band Library. GPL code is not permitted in the app
|
||||
store. See https://breakfastquay.com/technology/license.html for
|
||||
commercial terms.
|
||||
|
||||
|
||||
### 4c. Building for iOS
|
||||
|
||||
Ensure the Xcode command-line tools are installed, and
|
||||
|
||||
```
|
||||
$ meson build_ios --cross-file cross/ios.txt && ninja -C build_ios
|
||||
```
|
||||
|
||||
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_sim
|
||||
```
|
||||
|
||||
The output files will be found in the `build_sim` directory.
|
||||
|
||||
See "FFT and resampler selection" below for further build options.
|
||||
|
||||
Note that you cannot legally distribute applications using Rubber Band
|
||||
in the iOS App Store, unless you have a first obtained a commercial
|
||||
licence for Rubber Band Library. GPL code is not permitted in the app
|
||||
store. See https://breakfastquay.com/technology/license.html for
|
||||
commercial terms.
|
||||
|
||||
|
||||
### 4d. Building on Windows
|
||||
|
||||
If you only need to build the static library for integration into your
|
||||
project, and you prefer a Visual Studio project file, you can find a
|
||||
simple one in `otherbuilds\rubberband-library.vcxproj`.
|
||||
|
||||
The rest of this section describes the "full" build system, which uses
|
||||
Meson just as on the other platforms. So to build this way, start by
|
||||
ensuring Meson and Ninja are installed and available. Then, in a
|
||||
terminal window with the compiler tools available in the path (e.g. a
|
||||
Visual Studio command-line prompt for the relevant build architecture)
|
||||
run
|
||||
|
||||
```
|
||||
> meson build
|
||||
> ninja -C build
|
||||
```
|
||||
|
||||
The output files will be found in the `build` directory.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
### 4e. Building for Android and Java integration
|
||||
|
||||
Currently only a very old Android NDK build file is provided, as
|
||||
`otherbuilds/Android.mk`. This includes compile definitions for a
|
||||
shared library built for ARM architectures which can be loaded from a
|
||||
Java application using the Java native interface (i.e. the Android
|
||||
NDK).
|
||||
|
||||
The Java side of the interface can be found in
|
||||
`com/breakfastquay/rubberband/RubberBandStretcher.java`.
|
||||
|
||||
See
|
||||
https://hg.sr.ht/~breakfastquay/rubberband-android-simple-sample
|
||||
for a very trivial example of integration with Android Java code.
|
||||
|
||||
The supplied `.mk` file uses KissFFT and the Speex resampler.
|
||||
|
||||
|
||||
### 4f. FFT and resampler selection
|
||||
|
||||
Rubber Band requires the selection of library code for FFT calculation
|
||||
and resampling. Several libraries are supported. The selection is
|
||||
controlled (in Meson) using `-D` options and (in the code itself)
|
||||
using preprocessor flags set by the build system. These options and
|
||||
flags are detailed in the tables below.
|
||||
|
||||
At least one resampler implementation and one FFT implementation must
|
||||
be enabled. It is technically possible to enable more than one, but
|
||||
it's confusing and not often useful.
|
||||
|
||||
If you are building this software using the bundled Speex or KissFFT
|
||||
library code, please be sure to review the terms for those libraries
|
||||
in `src/speex/COPYING` and `src/kissfft/COPYING` as applicable.
|
||||
|
||||
If you are proposing to package Rubber Band for a Linux distribution,
|
||||
please select either the built-in FFT or FFTW, and either the built-in
|
||||
resampler or libsamplerate.
|
||||
|
||||
#### FFT libraries supported
|
||||
|
||||
```
|
||||
Library Build option CPP define Notes
|
||||
---- ------------ ---------- -----
|
||||
|
||||
Built-in -Dfft=builtin -DUSE_BUILTIN_FFT
|
||||
Default except on macOS/iOS.
|
||||
Can be distributed with either
|
||||
the Rubber Band GPL or
|
||||
commercial licence.
|
||||
|
||||
Accelerate -Dfft=vdsp -DHAVE_VDSP Default on macOS/iOS.
|
||||
Best option on these platforms.
|
||||
|
||||
FFTW3 -Dfft=fftw -DHAVE_FFTW3 GPL.
|
||||
A bit faster than built-in,
|
||||
a bit slower than Accelerate.
|
||||
|
||||
KissFFT -Dfft=kissfft -DHAVE_KISSFFT
|
||||
Single precision.
|
||||
Only indicated for use with
|
||||
single-precision sample type
|
||||
(see below).
|
||||
Bundled, can be distributed with
|
||||
either the Rubber Band GPL or
|
||||
commercial licence.
|
||||
|
||||
Intel IPP -Dfft=ipp -DHAVE_IPP Proprietary, can only be used with
|
||||
Rubber Band commercial licence.
|
||||
```
|
||||
|
||||
#### Resampler libraries supported
|
||||
|
||||
```
|
||||
Library Build option CPP define Notes
|
||||
---- ------------ ---------- -----
|
||||
|
||||
Built-in -Dfft=builtin -DUSE_BQRESAMPLER
|
||||
Default.
|
||||
Can be distributed with either
|
||||
the Rubber Band GPL or
|
||||
commercial licence. Intended to
|
||||
give best quality for time-varying
|
||||
pitch shifts in real-time mode.
|
||||
Newer than, and not as well-tested
|
||||
as, libsamplerate.
|
||||
|
||||
libsamplerate -DHAVE_LIBSAMPLERATE
|
||||
-Dresampler=libsamplerate Good choice in most cases.
|
||||
|
||||
Speex -DUSE_SPEEX
|
||||
-Dresampler=speex Can be distributed with
|
||||
either the Rubber Band GPL or
|
||||
commercial licence.
|
||||
```
|
||||
|
||||
### 4g. Other supported #defines
|
||||
|
||||
Other known preprocessor symbols are as follows. (Usually the supplied
|
||||
build files will handle these for you.)
|
||||
|
||||
-DLACK_BAD_ALLOC
|
||||
Define on systems lacking std::bad_alloc in the C++ library.
|
||||
|
||||
-DLACK_POSIX_MEMALIGN
|
||||
Define on systems lacking posix_memalign.
|
||||
|
||||
-DUSE_OWN_ALIGNED_MALLOC
|
||||
Define on systems lacking any aligned malloc implementation.
|
||||
|
||||
-DLACK_SINCOS
|
||||
Define on systems lacking sincos().
|
||||
|
||||
-DNO_EXCEPTIONS
|
||||
Build without use of C++ exceptions.
|
||||
|
||||
-DNO_THREADING
|
||||
Build without any multithread support.
|
||||
|
||||
-DUSE_PTHREADS
|
||||
Use the pthreads library (required unless NO_THREADING or on Windows)
|
||||
|
||||
-DPROCESS_SAMPLE_TYPE=float
|
||||
Select single precision for internal calculations. The default is
|
||||
double precision. Consider in conjunction with single-precision
|
||||
KissFFT for mobile architectures with slower double-precision
|
||||
support.
|
||||
|
||||
-DUSE_POMMIER_MATHFUN
|
||||
Select the Julien Pommier implementations of trig functions for ARM
|
||||
NEON or x86 SSE architectures. These are usually faster but may be
|
||||
of lower precision than system implementations. Consider using this
|
||||
for 32-bit mobile architectures.
|
||||
|
||||
|
||||
## 5. Copyright notes for bundled libraries
|
||||
|
||||
### 5a. Speex
|
||||
|
||||
```
|
||||
[files in src/speex]
|
||||
|
||||
Copyright 2002-2007 Xiph.org Foundation
|
||||
Copyright 2002-2007 Jean-Marc Valin
|
||||
Copyright 2005-2007 Analog Devices Inc.
|
||||
Copyright 2005-2007 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO)
|
||||
Copyright 1993, 2002, 2006 David Rowe
|
||||
Copyright 2003 EpicGames
|
||||
Copyright 1992-1994 Jutta Degener, Carsten Bormann
|
||||
|
||||
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 name of the Xiph.org Foundation nor the names of its
|
||||
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 FOUNDATION 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.
|
||||
```
|
||||
|
||||
### 5b. KissFFT
|
||||
|
||||
```
|
||||
[files in src/kissfft]
|
||||
|
||||
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.
|
||||
```
|
||||
|
||||
### 5c. Pommier math functions
|
||||
|
||||
```
|
||||
[files in src/pommier]
|
||||
|
||||
Copyright (C) 2011 Julien Pommier
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
```
|
||||
|
||||
### 5d. float_cast
|
||||
|
||||
```
|
||||
[files in src/float_cast]
|
||||
|
||||
Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this file for any
|
||||
purpose is hereby granted without fee, provided that the above copyright
|
||||
and this permission notice appear in all copies. No representations are
|
||||
made about the suitability of this software for any purpose. It is
|
||||
provided "as is" without express or implied warranty.
|
||||
```
|
||||
|
||||
### 5e. getopt
|
||||
|
||||
```
|
||||
[files in src/getopt, used by command-line tool on some platforms]
|
||||
|
||||
Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
All rights reserved.
|
||||
|
||||
This code is derived from software contributed to The NetBSD Foundation
|
||||
by Dieter Baron and Thomas Klausner.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. 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.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by the NetBSD
|
||||
Foundation, Inc. and its contributors.
|
||||
4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
|
||||
```
|
||||
|
||||
### 5f. rubberband-sharp
|
||||
|
||||
```
|
||||
[files in rubberband-dll and rubberband-sharp]
|
||||
|
||||
Copyright 2018-2019 Jonathan Gilbert
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
||||
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Jonathan Gilbert
|
||||
shall not be used in advertising or otherwise to promote the sale,
|
||||
use or other dealings in this Software without prior written
|
||||
authorization.
|
||||
```
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..;..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>__MSVC__;WIN32;_DEBUG;_LIB;NOMINMAX;_USE_MATH_DEFINES;USE_BUILTIN_FFT;USE_SPEEX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>__MSVC__;WIN32;_DEBUG;_LIB;NOMINMAX;_USE_MATH_DEFINES;USE_BUILTIN_FFT;USE_BQRESAMPLER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
@@ -91,7 +91,7 @@
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..;..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>__MSVC__;WIN32;_DEBUG;_LIB;NOMINMAX;_USE_MATH_DEFINES;USE_BUILTIN_FFT;USE_SPEEX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>__MSVC__;WIN32;_DEBUG;_LIB;NOMINMAX;_USE_MATH_DEFINES;USE_BUILTIN_FFT;USE_BQRESAMPLER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
@@ -109,7 +109,7 @@
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<AdditionalIncludeDirectories>..;..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>__MSVC__;WIN32;NDEBUG;_LIB;NOMINMAX;_USE_MATH_DEFINES;USE_BUILTIN_FFT;NO_TIMING;USE_SPEEX;NO_THREAD_CHECKS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>__MSVC__;WIN32;NDEBUG;_LIB;NOMINMAX;_USE_MATH_DEFINES;USE_BUILTIN_FFT;NO_TIMING;USE_BQRESAMPLER;NO_THREAD_CHECKS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
|
||||
@@ -127,7 +127,7 @@
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<AdditionalIncludeDirectories>..;..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>__MSVC__;WIN32;NDEBUG;_LIB;NOMINMAX;_USE_MATH_DEFINES;USE_BUILTIN_FFT;NO_TIMING;USE_SPEEX;NO_THREAD_CHECKS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>__MSVC__;WIN32;NDEBUG;_LIB;NOMINMAX;_USE_MATH_DEFINES;USE_BUILTIN_FFT;NO_TIMING;USE_BQRESAMPLER;NO_THREAD_CHECKS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
|
||||
@@ -139,55 +139,26 @@
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\rubberband\rubberband-c.h" />
|
||||
<ClInclude Include="..\rubberband\RubberBandStretcher.h" />
|
||||
<ClInclude Include="..\src\audiocurves\CompoundAudioCurve.h" />
|
||||
<ClInclude Include="..\src\audiocurves\ConstantAudioCurve.h" />
|
||||
<ClInclude Include="..\src\audiocurves\HighFrequencyAudioCurve.h" />
|
||||
<ClInclude Include="..\src\audiocurves\PercussiveAudioCurve.h" />
|
||||
<ClInclude Include="..\src\audiocurves\SilentAudioCurve.h" />
|
||||
<ClInclude Include="..\src\audiocurves\SpectralDifferenceAudioCurve.h" />
|
||||
<ClInclude Include="..\src\base\Profiler.h" />
|
||||
<ClInclude Include="..\src\base\RingBuffer.h" />
|
||||
<ClInclude Include="..\src\base\Scavenger.h" />
|
||||
<ClInclude Include="..\src\dsp\AudioCurveCalculator.h" />
|
||||
<ClInclude Include="..\src\dsp\FFT.h" />
|
||||
<ClInclude Include="..\src\dsp\MovingMedian.h" />
|
||||
<ClInclude Include="..\src\dsp\Resampler.h" />
|
||||
<ClInclude Include="..\src\dsp\SampleFilter.h" />
|
||||
<ClInclude Include="..\src\dsp\SincWindow.h" />
|
||||
<ClInclude Include="..\src\dsp\Window.h" />
|
||||
<ClInclude Include="..\src\float_cast\float_cast.h" />
|
||||
<ClInclude Include="..\src\speex\speex_resampler.h" />
|
||||
<ClInclude Include="..\src\StretchCalculator.h" />
|
||||
<ClInclude Include="..\src\StretcherChannelData.h" />
|
||||
<ClInclude Include="..\src\StretcherImpl.h" />
|
||||
<ClInclude Include="..\src\system\Allocators.h" />
|
||||
<ClInclude Include="..\src\system\sysutils.h" />
|
||||
<ClInclude Include="..\src\system\Thread.h" />
|
||||
<ClInclude Include="..\src\system\VectorOps.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\src\audiocurves\CompoundAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\audiocurves\ConstantAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\audiocurves\HighFrequencyAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\audiocurves\PercussiveAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\audiocurves\SilentAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\audiocurves\SpectralDifferenceAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\base\Profiler.cpp" />
|
||||
<ClCompile Include="..\src\dsp\AudioCurveCalculator.cpp" />
|
||||
<ClCompile Include="..\src\dsp\FFT.cpp" />
|
||||
<ClCompile Include="..\src\dsp\Resampler.cpp" />
|
||||
<ClCompile Include="..\src\rubberband-c.cpp" />
|
||||
<ClCompile Include="..\src\RubberBandStretcher.cpp" />
|
||||
<ClCompile Include="..\src\speex\resample.c" />
|
||||
<ClCompile Include="..\src\StretchCalculator.cpp" />
|
||||
<ClCompile Include="..\src\StretcherChannelData.cpp" />
|
||||
<ClCompile Include="..\src\StretcherImpl.cpp" />
|
||||
<ClCompile Include="..\src\StretcherProcess.cpp" />
|
||||
<ClCompile Include="..\src\system\Allocators.cpp" />
|
||||
<ClCompile Include="..\src\system\sysutils.cpp" />
|
||||
<ClCompile Include="..\src\system\Thread.cpp" />
|
||||
<ClCompile Include="..\src\faster\AudioCurveCalculator.cpp" />
|
||||
<ClCompile Include="..\src\faster\CompoundAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\faster\HighFrequencyAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\faster\SilentAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\faster\PercussiveAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\faster\StretcherChannelData.cpp" />
|
||||
<ClCompile Include="..\src\faster\R2Stretcher.cpp" />
|
||||
<ClCompile Include="..\src\faster\StretcherProcess.cpp" />
|
||||
<ClCompile Include="..\src\common\BQResampler.cpp" />
|
||||
<ClCompile Include="..\src\common\Profiler.cpp" />
|
||||
<ClCompile Include="..\src\common\Resampler.cpp" />
|
||||
<ClCompile Include="..\src\common\FFT.cpp" />
|
||||
<ClCompile Include="..\src\common\Log.cpp" />
|
||||
<ClCompile Include="..\src\common\Allocators.cpp" />
|
||||
<ClCompile Include="..\src\common\StretchCalculator.cpp" />
|
||||
<ClCompile Include="..\src\common\sysutils.cpp" />
|
||||
<ClCompile Include="..\src\common\Thread.cpp" />
|
||||
<ClCompile Include="..\src\finer\R3Stretcher.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#include <lv2.h>
|
||||
#endif
|
||||
|
||||
#include "base/RingBuffer.h"
|
||||
#include "common/RingBuffer.h"
|
||||
|
||||
namespace RubberBand {
|
||||
class RubberBandStretcher;
|
||||
|
||||
646
ladspa-lv2/RubberBandR3PitchShifter.cpp
Normal file
646
ladspa-lv2/RubberBandR3PitchShifter.cpp
Normal file
@@ -0,0 +1,646 @@
|
||||
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||
|
||||
/*
|
||||
Rubber Band Library
|
||||
An audio time-stretching and pitch-shifting library.
|
||||
Copyright 2007-2022 Particular Programs Ltd.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version. See the file
|
||||
COPYING included with this distribution for more information.
|
||||
|
||||
Alternatively, if you have a valid commercial licence for the
|
||||
Rubber Band Library obtained by agreement with the copyright
|
||||
holders, you may redistribute and/or modify it under the terms
|
||||
described in that licence.
|
||||
|
||||
If you wish to distribute code using the Rubber Band Library
|
||||
under terms other than those of the GNU General Public License,
|
||||
you must obtain a valid commercial licence before doing so.
|
||||
*/
|
||||
|
||||
#include "RubberBandR3PitchShifter.h"
|
||||
|
||||
#include "RubberBandStretcher.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
using namespace RubberBand;
|
||||
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::min;
|
||||
|
||||
#ifdef RB_PLUGIN_LADSPA
|
||||
|
||||
const char *const
|
||||
RubberBandR3PitchShifter::portNamesMono[PortCountMono] =
|
||||
{
|
||||
"latency",
|
||||
"Cents",
|
||||
"Semitones",
|
||||
"Octaves",
|
||||
"Formant Preserving",
|
||||
"Wet-Dry Mix",
|
||||
"Input",
|
||||
"Output"
|
||||
};
|
||||
|
||||
const char *const
|
||||
RubberBandR3PitchShifter::portNamesStereo[PortCountStereo] =
|
||||
{
|
||||
"latency",
|
||||
"Cents",
|
||||
"Semitones",
|
||||
"Octaves",
|
||||
"Formant Preserving",
|
||||
"Wet-Dry Mix",
|
||||
"Input L",
|
||||
"Output L",
|
||||
"Input R",
|
||||
"Output R"
|
||||
};
|
||||
|
||||
const LADSPA_PortDescriptor
|
||||
RubberBandR3PitchShifter::portsMono[PortCountMono] =
|
||||
{
|
||||
LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL,
|
||||
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
|
||||
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
|
||||
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
|
||||
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
|
||||
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
|
||||
LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO,
|
||||
LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO
|
||||
};
|
||||
|
||||
const LADSPA_PortDescriptor
|
||||
RubberBandR3PitchShifter::portsStereo[PortCountStereo] =
|
||||
{
|
||||
LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL,
|
||||
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
|
||||
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
|
||||
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
|
||||
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
|
||||
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
|
||||
LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO,
|
||||
LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
|
||||
LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO,
|
||||
LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO
|
||||
};
|
||||
|
||||
const LADSPA_PortRangeHint
|
||||
RubberBandR3PitchShifter::hintsMono[PortCountMono] =
|
||||
{
|
||||
{ 0, 0, 0 }, // latency
|
||||
{ LADSPA_HINT_DEFAULT_0 | // cents
|
||||
LADSPA_HINT_BOUNDED_BELOW |
|
||||
LADSPA_HINT_BOUNDED_ABOVE,
|
||||
-100.0, 100.0 },
|
||||
{ LADSPA_HINT_DEFAULT_0 | // semitones
|
||||
LADSPA_HINT_BOUNDED_BELOW |
|
||||
LADSPA_HINT_BOUNDED_ABOVE |
|
||||
LADSPA_HINT_INTEGER,
|
||||
-12.0, 12.0 },
|
||||
{ LADSPA_HINT_DEFAULT_0 | // octaves
|
||||
LADSPA_HINT_BOUNDED_BELOW |
|
||||
LADSPA_HINT_BOUNDED_ABOVE |
|
||||
LADSPA_HINT_INTEGER,
|
||||
-2.0, 2.0 },
|
||||
{ LADSPA_HINT_DEFAULT_0 | // formant preserving
|
||||
LADSPA_HINT_BOUNDED_BELOW |
|
||||
LADSPA_HINT_BOUNDED_ABOVE |
|
||||
LADSPA_HINT_TOGGLED,
|
||||
0.0, 1.0 },
|
||||
{ LADSPA_HINT_DEFAULT_0 | // wet-dry mix
|
||||
LADSPA_HINT_BOUNDED_BELOW |
|
||||
LADSPA_HINT_BOUNDED_ABOVE,
|
||||
0.0, 1.0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
const LADSPA_PortRangeHint
|
||||
RubberBandR3PitchShifter::hintsStereo[PortCountStereo] =
|
||||
{
|
||||
{ 0, 0, 0 }, // latency
|
||||
{ LADSPA_HINT_DEFAULT_0 | // cents
|
||||
LADSPA_HINT_BOUNDED_BELOW |
|
||||
LADSPA_HINT_BOUNDED_ABOVE,
|
||||
-100.0, 100.0 },
|
||||
{ LADSPA_HINT_DEFAULT_0 | // semitones
|
||||
LADSPA_HINT_BOUNDED_BELOW |
|
||||
LADSPA_HINT_BOUNDED_ABOVE |
|
||||
LADSPA_HINT_INTEGER,
|
||||
-12.0, 12.0 },
|
||||
{ LADSPA_HINT_DEFAULT_0 | // octaves
|
||||
LADSPA_HINT_BOUNDED_BELOW |
|
||||
LADSPA_HINT_BOUNDED_ABOVE |
|
||||
LADSPA_HINT_INTEGER,
|
||||
-2.0, 2.0 },
|
||||
{ LADSPA_HINT_DEFAULT_0 | // formant preserving
|
||||
LADSPA_HINT_BOUNDED_BELOW |
|
||||
LADSPA_HINT_BOUNDED_ABOVE |
|
||||
LADSPA_HINT_TOGGLED,
|
||||
0.0, 1.0 },
|
||||
{ LADSPA_HINT_DEFAULT_0 | // wet-dry mix
|
||||
LADSPA_HINT_BOUNDED_BELOW |
|
||||
LADSPA_HINT_BOUNDED_ABOVE,
|
||||
0.0, 1.0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
const LADSPA_Properties
|
||||
RubberBandR3PitchShifter::properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
|
||||
|
||||
const LADSPA_Descriptor
|
||||
RubberBandR3PitchShifter::ladspaDescriptorMono =
|
||||
{
|
||||
29790, // "Unique" ID
|
||||
"rubberband-r3-pitchshifter-mono", // Label
|
||||
properties,
|
||||
"Rubber Band R3 Mono Pitch Shifter", // Name
|
||||
"Breakfast Quay",
|
||||
"GPL",
|
||||
PortCountMono,
|
||||
portsMono,
|
||||
portNamesMono,
|
||||
hintsMono,
|
||||
nullptr, // Implementation data
|
||||
instantiate,
|
||||
connectPort,
|
||||
activate,
|
||||
run,
|
||||
nullptr, // Run adding
|
||||
nullptr, // Set run adding gain
|
||||
deactivate,
|
||||
cleanup
|
||||
};
|
||||
|
||||
const LADSPA_Descriptor
|
||||
RubberBandR3PitchShifter::ladspaDescriptorStereo =
|
||||
{
|
||||
97920, // "Unique" ID
|
||||
"rubberband-r3-pitchshifter-stereo", // Label
|
||||
properties,
|
||||
"Rubber Band R3 Stereo Pitch Shifter", // Name
|
||||
"Breakfast Quay",
|
||||
"GPL",
|
||||
PortCountStereo,
|
||||
portsStereo,
|
||||
portNamesStereo,
|
||||
hintsStereo,
|
||||
nullptr, // Implementation data
|
||||
instantiate,
|
||||
connectPort,
|
||||
activate,
|
||||
run,
|
||||
nullptr, // Run adding
|
||||
nullptr, // Set run adding gain
|
||||
deactivate,
|
||||
cleanup
|
||||
};
|
||||
|
||||
const LADSPA_Descriptor *
|
||||
RubberBandR3PitchShifter::getDescriptor(unsigned long index)
|
||||
{
|
||||
if (index == 0) return &ladspaDescriptorMono;
|
||||
if (index == 1) return &ladspaDescriptorStereo;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
const LV2_Descriptor
|
||||
RubberBandR3PitchShifter::lv2DescriptorMono =
|
||||
{
|
||||
"http://breakfastquay.com/rdf/lv2-rubberband-r3#mono",
|
||||
instantiate,
|
||||
connectPort,
|
||||
activate,
|
||||
run,
|
||||
deactivate,
|
||||
cleanup,
|
||||
nullptr
|
||||
};
|
||||
|
||||
const LV2_Descriptor
|
||||
RubberBandR3PitchShifter::lv2DescriptorStereo =
|
||||
{
|
||||
"http://breakfastquay.com/rdf/lv2-rubberband-r3#stereo",
|
||||
instantiate,
|
||||
connectPort,
|
||||
activate,
|
||||
run,
|
||||
deactivate,
|
||||
cleanup,
|
||||
nullptr
|
||||
};
|
||||
|
||||
const LV2_Descriptor *
|
||||
RubberBandR3PitchShifter::getDescriptor(uint32_t index)
|
||||
{
|
||||
if (index == 0) return &lv2DescriptorMono;
|
||||
if (index == 1) return &lv2DescriptorStereo;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
RubberBandR3PitchShifter::RubberBandR3PitchShifter(int sampleRate, size_t channels) :
|
||||
m_latency(nullptr),
|
||||
m_cents(nullptr),
|
||||
m_semitones(nullptr),
|
||||
m_octaves(nullptr),
|
||||
m_formant(nullptr),
|
||||
m_wetDry(nullptr),
|
||||
m_ratio(1.0),
|
||||
m_prevRatio(1.0),
|
||||
m_currentFormant(false),
|
||||
m_blockSize(1024),
|
||||
m_reserve(8192),
|
||||
m_bufsize(0),
|
||||
m_minfill(0),
|
||||
m_stretcher(new RubberBandStretcher
|
||||
(sampleRate, channels,
|
||||
RubberBandStretcher::OptionProcessRealTime |
|
||||
RubberBandStretcher::OptionEngineFiner)),
|
||||
m_sampleRate(sampleRate),
|
||||
m_channels(channels)
|
||||
{
|
||||
m_input = new float *[m_channels];
|
||||
m_output = new float *[m_channels];
|
||||
|
||||
m_outputBuffer = new RingBuffer<float> *[m_channels];
|
||||
m_delayMixBuffer = new RingBuffer<float> *[m_channels];
|
||||
m_scratch = new float *[m_channels];
|
||||
m_inptrs = new float *[m_channels];
|
||||
|
||||
m_bufsize = m_blockSize + m_reserve + 8192;
|
||||
|
||||
for (size_t c = 0; c < m_channels; ++c) {
|
||||
|
||||
m_input[c] = 0;
|
||||
m_output[c] = 0;
|
||||
|
||||
m_outputBuffer[c] = new RingBuffer<float>(m_bufsize);
|
||||
m_delayMixBuffer[c] = new RingBuffer<float>(m_bufsize);
|
||||
|
||||
m_scratch[c] = new float[m_bufsize];
|
||||
for (size_t i = 0; i < m_bufsize; ++i) {
|
||||
m_scratch[c][i] = 0.f;
|
||||
}
|
||||
|
||||
m_inptrs[c] = 0;
|
||||
}
|
||||
|
||||
activateImpl();
|
||||
}
|
||||
|
||||
RubberBandR3PitchShifter::~RubberBandR3PitchShifter()
|
||||
{
|
||||
delete m_stretcher;
|
||||
for (size_t c = 0; c < m_channels; ++c) {
|
||||
delete m_outputBuffer[c];
|
||||
delete m_delayMixBuffer[c];
|
||||
delete[] m_scratch[c];
|
||||
}
|
||||
delete[] m_outputBuffer;
|
||||
delete[] m_delayMixBuffer;
|
||||
delete[] m_inptrs;
|
||||
delete[] m_scratch;
|
||||
delete[] m_output;
|
||||
delete[] m_input;
|
||||
}
|
||||
|
||||
#ifdef RB_PLUGIN_LADSPA
|
||||
|
||||
LADSPA_Handle
|
||||
RubberBandR3PitchShifter::instantiate(const LADSPA_Descriptor *desc, unsigned long rate)
|
||||
{
|
||||
if (desc->PortCount == ladspaDescriptorMono.PortCount) {
|
||||
return new RubberBandR3PitchShifter(rate, 1);
|
||||
} else if (desc->PortCount == ladspaDescriptorStereo.PortCount) {
|
||||
return new RubberBandR3PitchShifter(rate, 2);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
LV2_Handle
|
||||
RubberBandR3PitchShifter::instantiate(const LV2_Descriptor *desc, double rate,
|
||||
const char *, const LV2_Feature *const *)
|
||||
{
|
||||
if (rate < 1.0) {
|
||||
std::cerr << "RubberBandR3PitchShifter::instantiate: invalid sample rate "
|
||||
<< rate << " provided" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
size_t srate = size_t(round(rate));
|
||||
if (std::string(desc->URI) == lv2DescriptorMono.URI) {
|
||||
return new RubberBandR3PitchShifter(srate, 1);
|
||||
} else if (std::string(desc->URI) == lv2DescriptorStereo.URI) {
|
||||
return new RubberBandR3PitchShifter(srate, 2);
|
||||
} else {
|
||||
std::cerr << "RubberBandR3PitchShifter::instantiate: unrecognised URI "
|
||||
<< desc->URI << " requested" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef RB_PLUGIN_LADSPA
|
||||
void
|
||||
RubberBandR3PitchShifter::connectPort(LADSPA_Handle handle,
|
||||
unsigned long port, LADSPA_Data *location)
|
||||
#else
|
||||
void
|
||||
RubberBandR3PitchShifter::connectPort(LV2_Handle handle,
|
||||
uint32_t port, void *location)
|
||||
#endif
|
||||
{
|
||||
RubberBandR3PitchShifter *shifter = (RubberBandR3PitchShifter *)handle;
|
||||
|
||||
float **ports[PortCountStereo] = {
|
||||
&shifter->m_latency,
|
||||
&shifter->m_cents,
|
||||
&shifter->m_semitones,
|
||||
&shifter->m_octaves,
|
||||
&shifter->m_formant,
|
||||
&shifter->m_wetDry,
|
||||
&shifter->m_input[0],
|
||||
&shifter->m_output[0],
|
||||
&shifter->m_input[1],
|
||||
&shifter->m_output[1]
|
||||
};
|
||||
|
||||
if (shifter->m_channels == 1) {
|
||||
if (port >= PortCountMono) return;
|
||||
} else {
|
||||
if (port >= PortCountStereo) return;
|
||||
}
|
||||
|
||||
*ports[port] = (float *)location;
|
||||
|
||||
if (shifter->m_latency) {
|
||||
*(shifter->m_latency) = shifter->getLatency();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RB_PLUGIN_LADSPA
|
||||
void
|
||||
RubberBandR3PitchShifter::activate(LADSPA_Handle handle)
|
||||
#else
|
||||
void
|
||||
RubberBandR3PitchShifter::activate(LV2_Handle handle)
|
||||
#endif
|
||||
{
|
||||
RubberBandR3PitchShifter *shifter = (RubberBandR3PitchShifter *)handle;
|
||||
shifter->activateImpl();
|
||||
}
|
||||
|
||||
#ifdef RB_PLUGIN_LADSPA
|
||||
void
|
||||
RubberBandR3PitchShifter::run(LADSPA_Handle handle, unsigned long samples)
|
||||
#else
|
||||
void
|
||||
RubberBandR3PitchShifter::run(LV2_Handle handle, uint32_t samples)
|
||||
#endif
|
||||
{
|
||||
RubberBandR3PitchShifter *shifter = (RubberBandR3PitchShifter *)handle;
|
||||
shifter->runImpl(samples);
|
||||
}
|
||||
|
||||
#ifdef RB_PLUGIN_LADSPA
|
||||
void
|
||||
RubberBandR3PitchShifter::deactivate(LADSPA_Handle handle)
|
||||
#else
|
||||
void
|
||||
RubberBandR3PitchShifter::deactivate(LV2_Handle handle)
|
||||
#endif
|
||||
{
|
||||
activate(handle); // both functions just reset the plugin
|
||||
}
|
||||
|
||||
#ifdef RB_PLUGIN_LADSPA
|
||||
void
|
||||
RubberBandR3PitchShifter::cleanup(LADSPA_Handle handle)
|
||||
#else
|
||||
void
|
||||
RubberBandR3PitchShifter::cleanup(LV2_Handle handle)
|
||||
#endif
|
||||
{
|
||||
delete (RubberBandR3PitchShifter *)handle;
|
||||
}
|
||||
|
||||
int
|
||||
RubberBandR3PitchShifter::getLatency() const
|
||||
{
|
||||
return m_reserve;
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandR3PitchShifter::activateImpl()
|
||||
{
|
||||
updateRatio();
|
||||
m_prevRatio = m_ratio;
|
||||
m_stretcher->reset();
|
||||
m_stretcher->setPitchScale(m_ratio);
|
||||
|
||||
for (size_t c = 0; c < m_channels; ++c) {
|
||||
m_outputBuffer[c]->reset();
|
||||
}
|
||||
|
||||
for (size_t c = 0; c < m_channels; ++c) {
|
||||
m_delayMixBuffer[c]->reset();
|
||||
m_delayMixBuffer[c]->zero(getLatency());
|
||||
}
|
||||
|
||||
for (size_t c = 0; c < m_channels; ++c) {
|
||||
for (size_t i = 0; i < m_bufsize; ++i) {
|
||||
m_scratch[c][i] = 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
m_minfill = 0;
|
||||
|
||||
m_stretcher->process(m_scratch, m_reserve, false);
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandR3PitchShifter::updateRatio()
|
||||
{
|
||||
// The octaves, semitones, and cents parameters are supposed to be
|
||||
// integral: we want to enforce that, just to avoid
|
||||
// inconsistencies between hosts if some respect the hints more
|
||||
// than others
|
||||
|
||||
#ifdef RB_PLUGIN_LADSPA
|
||||
|
||||
// But we don't want to change the long-standing behaviour of the
|
||||
// LADSPA plugin, so let's leave this as-is and only do "the right
|
||||
// thing" for LV2
|
||||
double oct = (m_octaves ? *m_octaves : 0.0);
|
||||
oct += (m_semitones ? *m_semitones : 0.0) / 12;
|
||||
oct += (m_cents ? *m_cents : 0.0) / 1200;
|
||||
m_ratio = pow(2.0, oct);
|
||||
|
||||
#else
|
||||
|
||||
// LV2
|
||||
|
||||
double octaves = round(m_octaves ? *m_octaves : 0.0);
|
||||
if (octaves < -2.0) octaves = -2.0;
|
||||
if (octaves > 2.0) octaves = 2.0;
|
||||
|
||||
double semitones = round(m_semitones ? *m_semitones : 0.0);
|
||||
if (semitones < -12.0) semitones = -12.0;
|
||||
if (semitones > 12.0) semitones = 12.0;
|
||||
|
||||
double cents = round(m_cents ? *m_cents : 0.0);
|
||||
if (cents < -100.0) cents = -100.0;
|
||||
if (cents > 100.0) cents = 100.0;
|
||||
|
||||
m_ratio = pow(2.0,
|
||||
octaves +
|
||||
semitones / 12.0 +
|
||||
cents / 1200.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandR3PitchShifter::updateFormant()
|
||||
{
|
||||
if (!m_formant) return;
|
||||
|
||||
bool f = (*m_formant > 0.5f);
|
||||
if (f == m_currentFormant) return;
|
||||
|
||||
RubberBandStretcher *s = m_stretcher;
|
||||
|
||||
s->setFormantOption(f ?
|
||||
RubberBandStretcher::OptionFormantPreserved :
|
||||
RubberBandStretcher::OptionFormantShifted);
|
||||
|
||||
m_currentFormant = f;
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandR3PitchShifter::runImpl(uint32_t insamples)
|
||||
{
|
||||
for (size_t c = 0; c < m_channels; ++c) {
|
||||
m_delayMixBuffer[c]->write(m_input[c], insamples);
|
||||
}
|
||||
|
||||
size_t offset = 0;
|
||||
|
||||
// We have to break up the input into chunks like this because
|
||||
// insamples could be arbitrarily large and our output buffer is
|
||||
// of limited size
|
||||
|
||||
while (offset < insamples) {
|
||||
|
||||
size_t block = m_blockSize;
|
||||
if (offset + block > insamples) {
|
||||
block = insamples - offset;
|
||||
}
|
||||
|
||||
runImpl(block, offset);
|
||||
|
||||
offset += block;
|
||||
}
|
||||
|
||||
float mix = 0.0;
|
||||
if (m_wetDry) mix = *m_wetDry;
|
||||
|
||||
for (size_t c = 0; c < m_channels; ++c) {
|
||||
if (mix > 0.0) {
|
||||
for (size_t i = 0; i < insamples; ++i) {
|
||||
float dry = m_delayMixBuffer[c]->readOne();
|
||||
m_output[c][i] *= (1.0 - mix);
|
||||
m_output[c][i] += dry * mix;
|
||||
}
|
||||
} else {
|
||||
m_delayMixBuffer[c]->skip(insamples);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandR3PitchShifter::runImpl(uint32_t insamples, uint32_t offset)
|
||||
{
|
||||
updateRatio();
|
||||
if (m_ratio != m_prevRatio) {
|
||||
m_stretcher->setPitchScale(m_ratio);
|
||||
m_prevRatio = m_ratio;
|
||||
}
|
||||
|
||||
if (m_latency) {
|
||||
*m_latency = getLatency();
|
||||
}
|
||||
|
||||
updateFormant();
|
||||
|
||||
const int samples = insamples;
|
||||
int processed = 0;
|
||||
size_t outTotal = 0;
|
||||
|
||||
while (processed < samples) {
|
||||
|
||||
// never feed more than the minimum necessary number of
|
||||
// samples at a time; ensures nothing will overflow internally
|
||||
// and we don't need to call setMaxProcessSize
|
||||
|
||||
int toCauseProcessing = m_stretcher->getSamplesRequired();
|
||||
int inchunk = min(samples - processed, toCauseProcessing);
|
||||
|
||||
for (size_t c = 0; c < m_channels; ++c) {
|
||||
m_inptrs[c] = &(m_input[c][offset + processed]);
|
||||
}
|
||||
|
||||
m_stretcher->process(m_inptrs, inchunk, false);
|
||||
|
||||
processed += inchunk;
|
||||
|
||||
int avail = m_stretcher->available();
|
||||
int writable = m_outputBuffer[0]->getWriteSpace();
|
||||
|
||||
int outchunk = avail;
|
||||
if (outchunk > writable) {
|
||||
cerr << "RubberBandR3PitchShifter::runImpl: buffer is not large enough: size = " << m_outputBuffer[0]->getSize() << ", chunk = " << outchunk << ", space = " << writable << " (buffer contains " << m_outputBuffer[0]->getReadSpace() << " unread)" << endl;
|
||||
outchunk = writable;
|
||||
}
|
||||
|
||||
size_t actual = m_stretcher->retrieve(m_scratch, outchunk);
|
||||
outTotal += actual;
|
||||
|
||||
for (size_t c = 0; c < m_channels; ++c) {
|
||||
m_outputBuffer[c]->write(m_scratch[c], actual);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t c = 0; c < m_channels; ++c) {
|
||||
int toRead = m_outputBuffer[c]->getReadSpace();
|
||||
if (toRead < samples && c == 0) {
|
||||
cerr << "RubberBandR3PitchShifter::runImpl: buffer underrun: required = " << samples << ", available = " << toRead << endl;
|
||||
}
|
||||
int chunk = min(toRead, samples);
|
||||
m_outputBuffer[c]->read(&(m_output[c][offset]), chunk);
|
||||
}
|
||||
|
||||
size_t fill = m_outputBuffer[0]->getReadSpace();
|
||||
if (fill < m_minfill || m_minfill == 0) {
|
||||
m_minfill = fill;
|
||||
// cerr << "minfill = " << m_minfill << endl;
|
||||
}
|
||||
}
|
||||
|
||||
149
ladspa-lv2/RubberBandR3PitchShifter.h
Normal file
149
ladspa-lv2/RubberBandR3PitchShifter.h
Normal file
@@ -0,0 +1,149 @@
|
||||
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||
|
||||
/*
|
||||
Rubber Band Library
|
||||
An audio time-stretching and pitch-shifting library.
|
||||
Copyright 2007-2022 Particular Programs Ltd.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version. See the file
|
||||
COPYING included with this distribution for more information.
|
||||
|
||||
Alternatively, if you have a valid commercial licence for the
|
||||
Rubber Band Library obtained by agreement with the copyright
|
||||
holders, you may redistribute and/or modify it under the terms
|
||||
described in that licence.
|
||||
|
||||
If you wish to distribute code using the Rubber Band Library
|
||||
under terms other than those of the GNU General Public License,
|
||||
you must obtain a valid commercial licence before doing so.
|
||||
*/
|
||||
|
||||
#ifndef RUBBERBAND_R3_PITCH_SHIFTER_H
|
||||
#define RUBBERBAND_R3_PITCH_SHIFTER_H
|
||||
|
||||
#ifdef RB_PLUGIN_LADSPA
|
||||
#ifdef RB_PLUGIN_LV2
|
||||
#error "Only one of RB_PLUGIN_LADSPA and RB_PLUGIN_LV2 may be defined at once"
|
||||
#endif
|
||||
#else
|
||||
#ifndef RB_PLUGIN_LV2
|
||||
#error "Including code must define either RB_PLUGIN_LADSPA or RB_PLUGIN_LV2"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef RB_PLUGIN_LADSPA
|
||||
#include <ladspa.h>
|
||||
#else
|
||||
#include <lv2.h>
|
||||
#endif
|
||||
|
||||
#include "common/RingBuffer.h"
|
||||
|
||||
namespace RubberBand {
|
||||
class RubberBandStretcher;
|
||||
}
|
||||
|
||||
class RubberBandR3PitchShifter
|
||||
{
|
||||
public:
|
||||
#ifdef RB_PLUGIN_LADSPA
|
||||
static const LADSPA_Descriptor *getDescriptor(unsigned long index);
|
||||
#else
|
||||
static const LV2_Descriptor *getDescriptor(uint32_t index);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
RubberBandR3PitchShifter(int sampleRate, size_t channels);
|
||||
~RubberBandR3PitchShifter();
|
||||
|
||||
enum {
|
||||
LatencyPort = 0,
|
||||
CentsPort = 1,
|
||||
SemitonesPort = 2,
|
||||
OctavesPort = 3,
|
||||
FormantPort = 4,
|
||||
WetDryPort = 5,
|
||||
InputPort1 = 6,
|
||||
OutputPort1 = 7,
|
||||
PortCountMono = OutputPort1 + 1,
|
||||
InputPort2 = 8,
|
||||
OutputPort2 = 9,
|
||||
PortCountStereo = OutputPort2 + 1
|
||||
};
|
||||
|
||||
#ifdef RB_PLUGIN_LADSPA
|
||||
static const char *const portNamesMono[PortCountMono];
|
||||
static const LADSPA_PortDescriptor portsMono[PortCountMono];
|
||||
static const LADSPA_PortRangeHint hintsMono[PortCountMono];
|
||||
|
||||
static const char *const portNamesStereo[PortCountStereo];
|
||||
static const LADSPA_PortDescriptor portsStereo[PortCountStereo];
|
||||
static const LADSPA_PortRangeHint hintsStereo[PortCountStereo];
|
||||
|
||||
static const LADSPA_Properties properties;
|
||||
|
||||
static const LADSPA_Descriptor ladspaDescriptorMono;
|
||||
static const LADSPA_Descriptor ladspaDescriptorStereo;
|
||||
|
||||
static LADSPA_Handle instantiate(const LADSPA_Descriptor *, unsigned long);
|
||||
static void connectPort(LADSPA_Handle, unsigned long, LADSPA_Data *);
|
||||
static void activate(LADSPA_Handle);
|
||||
static void run(LADSPA_Handle, unsigned long);
|
||||
static void deactivate(LADSPA_Handle);
|
||||
static void cleanup(LADSPA_Handle);
|
||||
|
||||
#else
|
||||
|
||||
static const LV2_Descriptor lv2DescriptorMono;
|
||||
static const LV2_Descriptor lv2DescriptorStereo;
|
||||
|
||||
static LV2_Handle instantiate(const LV2_Descriptor *, double,
|
||||
const char *, const LV2_Feature *const *);
|
||||
static void connectPort(LV2_Handle, uint32_t, void *);
|
||||
static void activate(LV2_Handle);
|
||||
static void run(LV2_Handle, uint32_t);
|
||||
static void deactivate(LV2_Handle);
|
||||
static void cleanup(LV2_Handle);
|
||||
|
||||
#endif
|
||||
|
||||
void activateImpl();
|
||||
void runImpl(uint32_t count);
|
||||
void runImpl(uint32_t count, uint32_t offset);
|
||||
void updateRatio();
|
||||
void updateFormant();
|
||||
|
||||
int getLatency() const;
|
||||
|
||||
float **m_input;
|
||||
float **m_output;
|
||||
float *m_latency;
|
||||
float *m_cents;
|
||||
float *m_semitones;
|
||||
float *m_octaves;
|
||||
float *m_formant;
|
||||
float *m_wetDry;
|
||||
double m_ratio;
|
||||
double m_prevRatio;
|
||||
bool m_currentFormant;
|
||||
|
||||
size_t m_blockSize;
|
||||
size_t m_reserve;
|
||||
size_t m_bufsize;
|
||||
size_t m_minfill;
|
||||
|
||||
RubberBand::RubberBandStretcher *m_stretcher;
|
||||
RubberBand::RingBuffer<float> **m_outputBuffer;
|
||||
RubberBand::RingBuffer<float> **m_delayMixBuffer;
|
||||
float **m_scratch;
|
||||
float **m_inptrs;
|
||||
|
||||
int m_sampleRate;
|
||||
size_t m_channels;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,2 +1,4 @@
|
||||
ladspa:ladspa-rubberband:rubberband-pitchshifter-mono::Frequency > Pitch shifters
|
||||
ladspa:ladspa-rubberband:rubberband-pitchshifter-stereo::Frequency > Pitch shifters
|
||||
ladspa:ladspa-rubberband:rubberband-r3-pitchshifter-mono::Frequency > Pitch shifters
|
||||
ladspa:ladspa-rubberband:rubberband-r3-pitchshifter-stereo::Frequency > Pitch shifters
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#define RB_PLUGIN_LADSPA 1
|
||||
#undef RB_PLUGIN_LV2
|
||||
#include "RubberBandPitchShifter.cpp"
|
||||
#include "RubberBandR3PitchShifter.cpp"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -31,7 +32,11 @@ extern "C" {
|
||||
|
||||
const LADSPA_Descriptor *ladspa_descriptor(unsigned long index)
|
||||
{
|
||||
if (index < 2) {
|
||||
return RubberBandPitchShifter::getDescriptor(index);
|
||||
} else {
|
||||
return RubberBandR3PitchShifter::getDescriptor(index - 2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#define RB_PLUGIN_LV2 1
|
||||
#undef RB_PLUGIN_LADSPA
|
||||
#include "RubberBandPitchShifter.cpp"
|
||||
#include "RubberBandR3PitchShifter.cpp"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -32,7 +33,11 @@ extern "C" {
|
||||
LV2_SYMBOL_EXPORT
|
||||
const LV2_Descriptor *lv2_descriptor(uint32_t index)
|
||||
{
|
||||
if (index < 2) {
|
||||
return RubberBandPitchShifter::getDescriptor(index);
|
||||
} else {
|
||||
return RubberBandR3PitchShifter::getDescriptor(index - 2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -78,6 +78,16 @@
|
||||
lv2:maximum 1 ;
|
||||
lv2:portProperty lv2:integer, lv2:toggled .
|
||||
|
||||
:formantPortR3
|
||||
a lv2:ControlPort, lv2:InputPort ;
|
||||
lv2:index 4 ;
|
||||
lv2:symbol "formant" ;
|
||||
lv2:name "Formant Preserving" ;
|
||||
lv2:default 0 ;
|
||||
lv2:minimum 0 ;
|
||||
lv2:maximum 1 ;
|
||||
lv2:portProperty lv2:integer, lv2:toggled .
|
||||
|
||||
:wetDryPort
|
||||
a lv2:ControlPort, lv2:InputPort ;
|
||||
lv2:index 6 ;
|
||||
@@ -87,6 +97,15 @@
|
||||
lv2:minimum 0 ;
|
||||
lv2:maximum 1 .
|
||||
|
||||
:wetDryPortR3
|
||||
a lv2:ControlPort, lv2:InputPort ;
|
||||
lv2:index 5 ;
|
||||
lv2:symbol "wetdry" ;
|
||||
lv2:name "Wet-Dry Mix" ;
|
||||
lv2:default 0 ;
|
||||
lv2:minimum 0 ;
|
||||
lv2:maximum 1 .
|
||||
|
||||
rubberband:mono_in_group
|
||||
a pg:MonoGroup, pg:InputGroup ;
|
||||
lv2:symbol "mono_in" ;
|
||||
@@ -146,6 +165,44 @@ rubberband:mono
|
||||
lv2:designation pg:center ;
|
||||
] .
|
||||
|
||||
rubberband:r3mono
|
||||
a doap:Project, lv2:Plugin, lv2:PitchPlugin ;
|
||||
doap:name "Rubber Band R3 Mono Pitch Shifter" ;
|
||||
doap:license <http://usefulinc.com/doap/licenses/gpl> ;
|
||||
foaf:maker :maker ;
|
||||
doap:developer :maker ;
|
||||
doap:maintainer :maker ;
|
||||
# Minor version will be 2x the Rubber Band API minor version,
|
||||
# but this is an initial test release, so 0
|
||||
lv2:minorVersion 0 ;
|
||||
lv2:microVersion 0 ;
|
||||
lv2:optionalFeature lv2:hardRTCapable ;
|
||||
pg:mainInput rubberband:mono_in_group ;
|
||||
pg:mainOutput rubberband:mono_out_group ;
|
||||
dc:replaces <urn:ladspa:29790> ;
|
||||
lv2:port :latencyPort ,
|
||||
:centsPort ,
|
||||
:semitonesPort ,
|
||||
:octavesPort ,
|
||||
:formantPortR3 ,
|
||||
:wetDryPortR3 ,
|
||||
[ a lv2:AudioPort, lv2:InputPort ;
|
||||
lv2:index 6 ;
|
||||
lv2:symbol "input" ;
|
||||
lv2:name "Input" ;
|
||||
lv2:shortName "Input" ;
|
||||
pg:group rubberband:mono_in_group ;
|
||||
lv2:designation pg:center ;
|
||||
], [
|
||||
a lv2:AudioPort, lv2:OutputPort ;
|
||||
lv2:index 7 ;
|
||||
lv2:symbol "output" ;
|
||||
lv2:name "Output" ;
|
||||
lv2:shortName "Output" ;
|
||||
pg:group rubberband:mono_out_group ;
|
||||
lv2:designation pg:center ;
|
||||
] .
|
||||
|
||||
rubberband:stereo
|
||||
a doap:Project, lv2:Plugin, lv2:PitchPlugin ;
|
||||
doap:name "Rubber Band Stereo Pitch Shifter" ;
|
||||
@@ -200,3 +257,56 @@ rubberband:stereo
|
||||
lv2:designation pg:right ;
|
||||
] .
|
||||
|
||||
rubberband:r3stereo
|
||||
a doap:Project, lv2:Plugin, lv2:PitchPlugin ;
|
||||
doap:name "Rubber Band R3 Stereo Pitch Shifter" ;
|
||||
doap:license <http://usefulinc.com/doap/licenses/gpl> ;
|
||||
foaf:maker :maker ;
|
||||
doap:developer :maker ;
|
||||
doap:maintainer :maker ;
|
||||
# Minor version will be 2x the Rubber Band API minor version,
|
||||
# but this is an initial test release, so 0
|
||||
lv2:minorVersion 0 ;
|
||||
lv2:microVersion 0 ;
|
||||
lv2:optionalFeature lv2:hardRTCapable ;
|
||||
pg:mainInput rubberband:stereo_in_group ;
|
||||
pg:mainOutput rubberband:stereo_out_group ;
|
||||
dc:replaces <urn:ladspa:97920> ;
|
||||
lv2:port :latencyPort ,
|
||||
:centsPort ,
|
||||
:semitonesPort ,
|
||||
:octavesPort ,
|
||||
:formantPortR3 ,
|
||||
:wetDryPortR3 ,
|
||||
[ a lv2:AudioPort, lv2:InputPort ;
|
||||
lv2:index 6 ;
|
||||
lv2:symbol "input_l" ;
|
||||
lv2:name "Input L" ;
|
||||
lv2:shortName "Input L" ;
|
||||
pg:group rubberband:stereo_in_group ;
|
||||
lv2:designation pg:left ;
|
||||
], [
|
||||
a lv2:AudioPort, lv2:OutputPort ;
|
||||
lv2:index 7 ;
|
||||
lv2:symbol "output_l" ;
|
||||
lv2:name "Output L" ;
|
||||
lv2:shortName "Output L" ;
|
||||
pg:group rubberband:stereo_out_group ;
|
||||
lv2:designation pg:left ;
|
||||
], [ a lv2:AudioPort, lv2:InputPort ;
|
||||
lv2:index 8 ;
|
||||
lv2:symbol "input_r" ;
|
||||
lv2:name "Input R" ;
|
||||
lv2:shortName "Input R" ;
|
||||
pg:group rubberband:stereo_in_group ;
|
||||
lv2:designation pg:right ;
|
||||
], [
|
||||
a lv2:AudioPort, lv2:OutputPort ;
|
||||
lv2:index 9 ;
|
||||
lv2:symbol "output_r" ;
|
||||
lv2:name "Output R" ;
|
||||
lv2:shortName "Output R" ;
|
||||
pg:group rubberband:stereo_out_group ;
|
||||
lv2:designation pg:right ;
|
||||
] .
|
||||
|
||||
|
||||
@@ -7,8 +7,18 @@ rubberband:mono
|
||||
lv2:binary <lv2-rubberband.so> ;
|
||||
rdfs:seeAlso <lv2-rubberband.ttl> .
|
||||
|
||||
rubberband:r3mono
|
||||
a lv2:Plugin ;
|
||||
lv2:binary <lv2-rubberband.so> ;
|
||||
rdfs:seeAlso <lv2-rubberband.ttl> .
|
||||
|
||||
rubberband:stereo
|
||||
a lv2:Plugin ;
|
||||
lv2:binary <lv2-rubberband.so> ;
|
||||
rdfs:seeAlso <lv2-rubberband.ttl> .
|
||||
|
||||
rubberband:r3stereo
|
||||
a lv2:Plugin ;
|
||||
lv2:binary <lv2-rubberband.so> ;
|
||||
rdfs:seeAlso <lv2-rubberband.ttl> .
|
||||
|
||||
|
||||
177
main/main.cpp
177
main/main.cpp
@@ -33,24 +33,26 @@
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "../src/system/sysutils.h"
|
||||
#include "../src/common/sysutils.h"
|
||||
#include "../src/common/Profiler.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "../src/getopt/getopt.h"
|
||||
#include "../src/ext/getopt/getopt.h"
|
||||
#else
|
||||
#include <getopt.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "../src/base/Profiler.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
using RubberBand::gettimeofday;
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
using RubberBand::usleep;
|
||||
#include <windows.h>
|
||||
static void usleep(unsigned long usec) {
|
||||
::Sleep(usec == 0 ? 0 : usec < 1000 ? 1 : usec / 1000);
|
||||
}
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
@@ -82,15 +84,13 @@ double tempo_convert(const char *str)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
|
||||
double ratio = 1.0;
|
||||
double duration = 0.0;
|
||||
double pitchshift = 0.0;
|
||||
double frequencyshift = 1.0;
|
||||
int debug = 0;
|
||||
bool realtime = false;
|
||||
bool precise = true;
|
||||
bool precisiongiven = false;
|
||||
int threading = 0;
|
||||
bool lamination = true;
|
||||
bool longwin = false;
|
||||
@@ -101,7 +101,10 @@ int main(int argc, char **argv)
|
||||
bool together = false;
|
||||
bool crispchanged = false;
|
||||
int crispness = -1;
|
||||
bool faster = false;
|
||||
bool finer = false;
|
||||
bool help = false;
|
||||
bool fullHelp = false;
|
||||
bool version = false;
|
||||
bool quiet = false;
|
||||
|
||||
@@ -126,11 +129,22 @@ int main(int argc, char **argv)
|
||||
|
||||
bool ignoreClipping = false;
|
||||
|
||||
std::string myName(argv[0]);
|
||||
|
||||
bool isR3 =
|
||||
((myName.size() > 3 &&
|
||||
myName.substr(myName.size() - 3, 3) == "-r3") ||
|
||||
(myName.size() > 7 &&
|
||||
myName.substr(myName.size() - 7, 7) == "-r3.exe") ||
|
||||
(myName.size() > 7 &&
|
||||
myName.substr(myName.size() - 7, 7) == "-R3.EXE"));
|
||||
|
||||
while (1) {
|
||||
int optionIndex = 0;
|
||||
|
||||
static struct option longOpts[] = {
|
||||
{ "help", 0, 0, 'h' },
|
||||
{ "full-help", 0, 0, 'H' },
|
||||
{ "version", 0, 0, 'V' },
|
||||
{ "time", 1, 0, 't' },
|
||||
{ "tempo", 1, 0, 'T' },
|
||||
@@ -146,10 +160,10 @@ int main(int argc, char **argv)
|
||||
{ "formant", 0, 0, 'F' },
|
||||
{ "no-threads", 0, 0, '0' },
|
||||
{ "no-transients", 0, 0, '1' },
|
||||
{ "no-lamination", 0, 0, '2' },
|
||||
{ "no-lamination", 0, 0, '.' },
|
||||
{ "centre-focus", 0, 0, '7' },
|
||||
{ "window-long", 0, 0, '3' },
|
||||
{ "window-short", 0, 0, '4' },
|
||||
{ "window-long", 0, 0, '>' },
|
||||
{ "window-short", 0, 0, '<' },
|
||||
{ "bl-transients", 0, 0, '8' },
|
||||
{ "detector-perc", 0, 0, '5' },
|
||||
{ "detector-soft", 0, 0, '6' },
|
||||
@@ -161,16 +175,19 @@ int main(int argc, char **argv)
|
||||
{ "freqmap", 1, 0, 'Q' },
|
||||
{ "pitchmap", 1, 0, 'C' },
|
||||
{ "ignore-clipping", 0, 0, 'i' },
|
||||
{ "fast", 0, 0, '2' },
|
||||
{ "fine", 0, 0, '3' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv,
|
||||
"t:p:d:RLPFc:f:T:D:qhVM:",
|
||||
int optionChar = getopt_long(argc, argv,
|
||||
"t:p:d:RLPFc:f:T:D:qhHVM:23",
|
||||
longOpts, &optionIndex);
|
||||
if (c == -1) break;
|
||||
if (optionChar == -1) break;
|
||||
|
||||
switch (c) {
|
||||
switch (optionChar) {
|
||||
case 'h': help = true; break;
|
||||
case 'H': fullHelp = true; break;
|
||||
case 'V': version = true; break;
|
||||
case 't': ratio *= atof(optarg); haveRatio = true; break;
|
||||
case 'T': ratio *= tempo_convert(optarg); haveRatio = true; break;
|
||||
@@ -179,15 +196,15 @@ int main(int argc, char **argv)
|
||||
case 'f': frequencyshift = atof(optarg); haveRatio = true; break;
|
||||
case 'd': debug = atoi(optarg); break;
|
||||
case 'R': realtime = true; break;
|
||||
case 'L': precise = false; break;
|
||||
case 'P': precise = true; break;
|
||||
case 'L': precisiongiven = true; break;
|
||||
case 'P': precisiongiven = true; break;
|
||||
case 'F': formant = true; break;
|
||||
case '0': threading = 1; break;
|
||||
case '@': threading = 2; break;
|
||||
case '1': transients = NoTransients; crispchanged = true; break;
|
||||
case '2': lamination = false; crispchanged = true; break;
|
||||
case '3': longwin = true; crispchanged = true; break;
|
||||
case '4': shortwin = true; crispchanged = true; break;
|
||||
case '.': lamination = false; crispchanged = true; break;
|
||||
case '>': longwin = true; crispchanged = true; break;
|
||||
case '<': shortwin = true; crispchanged = true; break;
|
||||
case '5': detector = PercussiveDetector; crispchanged = true; break;
|
||||
case '6': detector = SoftDetector; crispchanged = true; break;
|
||||
case '7': together = true; break;
|
||||
@@ -200,6 +217,8 @@ int main(int argc, char **argv)
|
||||
case 'Q': freqMapFile = optarg; freqOrPitchMapSpecified = true; break;
|
||||
case 'C': pitchMapFile = optarg; freqOrPitchMapSpecified = true; break;
|
||||
case 'i': ignoreClipping = true; break;
|
||||
case '2': faster = true; break;
|
||||
case '3': finer = true; break;
|
||||
default: help = true; break;
|
||||
}
|
||||
}
|
||||
@@ -218,15 +237,15 @@ int main(int argc, char **argv)
|
||||
realtime = true;
|
||||
}
|
||||
|
||||
if (help || !haveRatio || optind + 2 != argc) {
|
||||
if (help || fullHelp || !haveRatio || optind + 2 != argc) {
|
||||
cerr << endl;
|
||||
cerr << "Rubber Band" << endl;
|
||||
cerr << "An audio time-stretching and pitch-shifting library and utility program." << endl;
|
||||
cerr << "Copyright 2007-2022 Particular Programs Ltd." << endl;
|
||||
cerr << endl;
|
||||
cerr << " Usage: " << argv[0] << " [options] <infile.wav> <outfile.wav>" << endl;
|
||||
cerr << " Usage: " << myName << " [options] <infile.wav> <outfile.wav>" << endl;
|
||||
cerr << endl;
|
||||
cerr << "You must specify at least one of the following time and pitch ratio options." << endl;
|
||||
cerr << "You must specify at least one of the following time and pitch ratio options:" << endl;
|
||||
cerr << endl;
|
||||
cerr << " -t<X>, --time <X> Stretch to X times original duration, or" << endl;
|
||||
cerr << " -T<X>, --tempo <X> Change tempo by multiple X (same as --time 1/X), or" << endl;
|
||||
@@ -237,7 +256,7 @@ int main(int argc, char **argv)
|
||||
cerr << " -f<X>, --frequency <X> Change frequency by multiple X" << endl;
|
||||
cerr << endl;
|
||||
cerr << "The following options provide ways of making the time and frequency ratios" << endl;
|
||||
cerr << "change during the audio." << endl;
|
||||
cerr << "change during the audio:" << endl;
|
||||
cerr << endl;
|
||||
cerr << " -M<F>, --timemap <F> Use file F as the source for time map" << endl;
|
||||
cerr << endl;
|
||||
@@ -265,20 +284,42 @@ int main(int argc, char **argv)
|
||||
cerr << " lists frequency multipliers rather than pitch offsets (like the difference" << endl;
|
||||
cerr << " between pitch and frequency options above)." << endl;
|
||||
cerr << endl;
|
||||
cerr << "The following options provide a simple way to adjust the sound. See below" << endl;
|
||||
cerr << "for more details." << endl;
|
||||
cerr << "The following options affect the sound manipulation and quality:" << endl;
|
||||
cerr << endl;
|
||||
cerr << " -2, --fast Use the R2 (faster) engine" << endl;
|
||||
cerr << endl;
|
||||
cerr << " This is the default (for backward compatibility) when this tool is invoked" << endl;
|
||||
cerr << " as \"rubberband\". It was the only engine available in versions prior to v3.0." << endl;
|
||||
cerr << endl;
|
||||
cerr << " -3, --fine Use the R3 (finer) engine" << endl;
|
||||
cerr << endl;
|
||||
cerr << " This is the default when this tool is invoked as \"rubberband-r3\". It almost" << endl;
|
||||
cerr << " always produces better results than the R2 engine, but with significantly" << endl;
|
||||
cerr << " higher CPU load." << endl;
|
||||
cerr << endl;
|
||||
cerr << " -c<N>, --crisp <N> Crispness (N = 0,1,2,3,4,5,6); default 5 (see below)" << endl;
|
||||
cerr << " -F, --formant Enable formant preservation when pitch shifting" << endl;
|
||||
cerr << endl;
|
||||
cerr << " This option attempts to keep the formant envelope unchanged when changing" << endl;
|
||||
cerr << " the pitch, retaining the original timbre of vocals and instruments in a" << endl;
|
||||
cerr << " recognisable way." << endl;
|
||||
cerr << endl;
|
||||
if (fullHelp || !isR3) {
|
||||
cerr << " -c<N>, --crisp <N> Crispness (N = 0,1,2,3,4,5,6); default 5" << endl;
|
||||
cerr << endl;
|
||||
cerr << " This option only has an effect when using the R2 (faster) engine. See below" << endl;
|
||||
cerr << " for details of the different levels." << endl;
|
||||
cerr << endl;
|
||||
}
|
||||
if (fullHelp) {
|
||||
cerr << "The remaining options fine-tune the processing mode and stretch algorithm." << endl;
|
||||
cerr << "These are mostly included for test purposes; the default settings and standard" << endl;
|
||||
cerr << "crispness parameter are intended to provide the best sounding set of options" << endl;
|
||||
cerr << "for most situations. The default is to use none of these options." << endl;
|
||||
cerr << endl;
|
||||
cerr << " -L, --loose Relax timing in hope of better transient preservation" << endl;
|
||||
cerr << " -P, --precise Ignored: The opposite of -L, this is default from 1.6" << endl;
|
||||
cerr << " -R, --realtime Select realtime mode (implies --no-threads)" << endl;
|
||||
cerr << " -R, --realtime Select realtime mode (implies --no-threads)." << endl;
|
||||
cerr << " This utility does not do realtime stream processing;" << endl;
|
||||
cerr << " the option merely selects realtime mode for the" << endl;
|
||||
cerr << " stretcher it uses" << endl;
|
||||
cerr << " --no-threads No extra threads regardless of CPU and channel count" << endl;
|
||||
cerr << " --threads Assume multi-CPU even if only one CPU is identified" << endl;
|
||||
cerr << " --no-transients Disable phase resynchronisation at transients" << endl;
|
||||
@@ -294,14 +335,21 @@ int main(int argc, char **argv)
|
||||
cerr << " (at a cost in width and individual channel quality)" << endl;
|
||||
cerr << " --ignore-clipping Ignore clipping at output; the default is to restart" << endl;
|
||||
cerr << " with reduced gain if clipping occurs" << endl;
|
||||
cerr << " -L, --loose [Accepted for compatibility but ignored; always off]" << endl;
|
||||
cerr << " -P, --precise [Accepted for compatibility but ignored; always on]" << endl;
|
||||
cerr << endl;
|
||||
cerr << " -d<N>, --debug <N> Select debug level (N = 0,1,2,3); default 0, full 3" << endl;
|
||||
cerr << " (N.B. debug level 3 includes audible ticks in output)" << endl;
|
||||
cerr << endl;
|
||||
}
|
||||
cerr << "The following options are for output control and administration:" << endl;
|
||||
cerr << endl;
|
||||
cerr << " -q, --quiet Suppress progress output" << endl;
|
||||
cerr << endl;
|
||||
cerr << " -V, --version Show version number and exit" << endl;
|
||||
cerr << " -h, --help Show this help" << endl;
|
||||
cerr << " -h, --help Show the normal help output" << endl;
|
||||
cerr << " -H, --full-help Show the full help output" << endl;
|
||||
cerr << endl;
|
||||
if (fullHelp) {
|
||||
cerr << "\"Crispness\" levels:" << endl;
|
||||
cerr << " -c 0 equivalent to --no-transients --no-lamination --window-long" << endl;
|
||||
cerr << " -c 1 equivalent to --detector-soft --no-lamination --window-long (for piano)" << endl;
|
||||
@@ -311,6 +359,11 @@ int main(int argc, char **argv)
|
||||
cerr << " -c 5 default processing options" << endl;
|
||||
cerr << " -c 6 equivalent to --no-lamination --window-short (may be good for drums)" << endl;
|
||||
cerr << endl;
|
||||
} else {
|
||||
cerr << "Numerous other options are available, mostly for tuning the behaviour of" << endl;
|
||||
cerr << "the R2 engine. Run \"" << myName << " --full-help\" for details." << endl;
|
||||
cerr << endl;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -319,6 +372,23 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (faster && finer) {
|
||||
cerr << "WARNING: Both fast (R2) and fine (R3) engines selected, will use default for" << endl;
|
||||
cerr << " this tool (" << (isR3 ? "fine" : "fast") << ")" << endl;
|
||||
faster = false;
|
||||
finer = false;
|
||||
}
|
||||
|
||||
if (isR3) {
|
||||
if (!faster) {
|
||||
finer = true;
|
||||
}
|
||||
} else {
|
||||
if (!finer) {
|
||||
faster = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (crispness >= 0 && crispchanged) {
|
||||
cerr << "WARNING: Both crispness option and transients, lamination or window options" << endl;
|
||||
cerr << " provided -- crispness will override these other options" << endl;
|
||||
@@ -330,6 +400,11 @@ int main(int argc, char **argv)
|
||||
hqpitch = false;
|
||||
}
|
||||
|
||||
if (precisiongiven) {
|
||||
cerr << "NOTE: The -L/--loose and -P/--precise options are both ignored -- precise" << endl;
|
||||
cerr << " became the default in v1.6 and loose was removed in v3.0" << endl;
|
||||
}
|
||||
|
||||
switch (crispness) {
|
||||
case -1: crispness = 5; break;
|
||||
case 0: detector = CompoundDetector; transients = NoTransients; lamination = false; longwin = true; shortwin = false; break;
|
||||
@@ -342,6 +417,10 @@ int main(int argc, char **argv)
|
||||
};
|
||||
|
||||
if (!quiet) {
|
||||
if (finer) {
|
||||
cerr << "Using R3 (finer) engine" << endl;
|
||||
} else {
|
||||
cerr << "Using R2 (faster) engine" << endl;
|
||||
cerr << "Using crispness level: " << crispness << " (";
|
||||
switch (crispness) {
|
||||
case 0: cerr << "Mushy"; break;
|
||||
@@ -354,6 +433,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
cerr << ")" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::map<size_t, size_t> timeMap;
|
||||
if (timeMapFile != "") {
|
||||
@@ -492,8 +572,11 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
RubberBandStretcher::Options options = 0;
|
||||
if (finer) {
|
||||
options = RubberBandStretcher::OptionEngineFiner;
|
||||
}
|
||||
|
||||
if (realtime) options |= RubberBandStretcher::OptionProcessRealTime;
|
||||
if (precise) options |= RubberBandStretcher::OptionStretchPrecise;
|
||||
if (!lamination) options |= RubberBandStretcher::OptionPhaseIndependent;
|
||||
if (longwin) options |= RubberBandStretcher::OptionWindowLong;
|
||||
if (shortwin) options |= RubberBandStretcher::OptionWindowShort;
|
||||
@@ -782,19 +865,21 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (clipping) {
|
||||
const float mingain = 0.75f;
|
||||
if (gain < mingain) {
|
||||
cerr << "NOTE: Clipping detected at output sample "
|
||||
<< countOut << ", but not reducing gain as it would "
|
||||
<< "mean dropping below minimum " << mingain << endl;
|
||||
gain = mingain;
|
||||
ignoreClipping = true;
|
||||
} else {
|
||||
if (!quiet) {
|
||||
cerr << "NOTE: Clipping detected at output sample "
|
||||
<< countOut << ", restarting with "
|
||||
<< "reduced gain of " << gain
|
||||
<< " (supply --ignore-clipping to avoid this)" << endl;
|
||||
<< " (supply --ignore-clipping to avoid this)"
|
||||
<< endl;
|
||||
}
|
||||
const float mingain = 0.75f;
|
||||
if (gain < mingain) {
|
||||
cerr << "WARNING: Clipped values were implausibly high: "
|
||||
<< "something wrong with input or process - "
|
||||
<< "not reducing gain below " << mingain << endl;
|
||||
gain = mingain;
|
||||
ignoreClipping = true;
|
||||
}
|
||||
successful = false;
|
||||
break;
|
||||
@@ -900,7 +985,11 @@ int main(int argc, char **argv)
|
||||
|
||||
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;
|
||||
cerr << "in: " << countIn << ", out: " << countOut
|
||||
<< ", ratio: " << float(countOut)/float(countIn)
|
||||
<< ", ideal output: " << lrint(countIn * ratio)
|
||||
<< ", error: " << abs(lrint(countIn * ratio) - int(countOut))
|
||||
<< endl;
|
||||
|
||||
#ifdef _WIN32
|
||||
RubberBand::
|
||||
@@ -916,7 +1005,9 @@ int main(int argc, char **argv)
|
||||
etv.tv_usec -= tv.tv_usec;
|
||||
|
||||
double sec = double(etv.tv_sec) + (double(etv.tv_usec) / 1000000.0);
|
||||
cerr << "elapsed time: " << sec << " sec, in frames/sec: " << countIn/sec << ", out frames/sec: " << countOut/sec << endl;
|
||||
cerr << "elapsed time: " << sec << " sec, in frames/sec: "
|
||||
<< int64_t(countIn/sec) << ", out frames/sec: "
|
||||
<< int64_t(countOut/sec) << endl;
|
||||
}
|
||||
|
||||
RubberBand::Profiler::dump();
|
||||
|
||||
136
meson.build
136
meson.build
@@ -2,10 +2,11 @@
|
||||
project(
|
||||
'Rubber Band Library',
|
||||
'c', 'cpp',
|
||||
version: '2.0.2',
|
||||
version: '3.0.0-beta3',
|
||||
license: 'GPL-2.0-or-later',
|
||||
default_options: [
|
||||
'cpp_std=c++14',
|
||||
'cpp_std=c++11',
|
||||
'warning_level=3',
|
||||
'buildtype=release',
|
||||
'default_library=both',
|
||||
'b_ndebug=if-release',
|
||||
@@ -33,23 +34,23 @@ public_headers = [
|
||||
library_sources = [
|
||||
'src/rubberband-c.cpp',
|
||||
'src/RubberBandStretcher.cpp',
|
||||
'src/StretcherProcess.cpp',
|
||||
'src/StretchCalculator.cpp',
|
||||
'src/base/Profiler.cpp',
|
||||
'src/dsp/AudioCurveCalculator.cpp',
|
||||
'src/audiocurves/CompoundAudioCurve.cpp',
|
||||
'src/audiocurves/SpectralDifferenceAudioCurve.cpp',
|
||||
'src/audiocurves/HighFrequencyAudioCurve.cpp',
|
||||
'src/audiocurves/SilentAudioCurve.cpp',
|
||||
'src/audiocurves/ConstantAudioCurve.cpp',
|
||||
'src/audiocurves/PercussiveAudioCurve.cpp',
|
||||
'src/dsp/Resampler.cpp',
|
||||
'src/dsp/FFT.cpp',
|
||||
'src/system/Allocators.cpp',
|
||||
'src/system/sysutils.cpp',
|
||||
'src/system/Thread.cpp',
|
||||
'src/StretcherChannelData.cpp',
|
||||
'src/StretcherImpl.cpp',
|
||||
'src/faster/AudioCurveCalculator.cpp',
|
||||
'src/faster/CompoundAudioCurve.cpp',
|
||||
'src/faster/HighFrequencyAudioCurve.cpp',
|
||||
'src/faster/SilentAudioCurve.cpp',
|
||||
'src/faster/PercussiveAudioCurve.cpp',
|
||||
'src/faster/R2Stretcher.cpp',
|
||||
'src/faster/StretcherChannelData.cpp',
|
||||
'src/faster/StretcherProcess.cpp',
|
||||
'src/common/Allocators.cpp',
|
||||
'src/common/FFT.cpp',
|
||||
'src/common/Log.cpp',
|
||||
'src/common/Profiler.cpp',
|
||||
'src/common/Resampler.cpp',
|
||||
'src/common/StretchCalculator.cpp',
|
||||
'src/common/sysutils.cpp',
|
||||
'src/common/Thread.cpp',
|
||||
'src/finer/R3Stretcher.cpp',
|
||||
]
|
||||
|
||||
jni_sources = [
|
||||
@@ -66,8 +67,8 @@ program_sources = [
|
||||
|
||||
if system == 'windows'
|
||||
program_sources += [
|
||||
'src/getopt/getopt.c',
|
||||
'src/getopt/getopt_long.c'
|
||||
'src/ext/getopt/getopt.c',
|
||||
'src/ext/getopt/getopt_long.c'
|
||||
]
|
||||
endif
|
||||
|
||||
@@ -84,6 +85,19 @@ lv2_sources = [
|
||||
'ladspa-lv2/libmain-lv2.cpp',
|
||||
]
|
||||
|
||||
unit_test_sources = [
|
||||
'src/test/TestAllocators.cpp',
|
||||
'src/test/TestFFT.cpp',
|
||||
'src/test/TestResampler.cpp',
|
||||
'src/test/TestVectorOpsComplex.cpp',
|
||||
'src/test/TestVectorOps.cpp',
|
||||
'src/test/TestSignalBits.cpp',
|
||||
'src/test/TestStretchCalculator.cpp',
|
||||
'src/test/TestStretcher.cpp',
|
||||
'src/test/TestBinClassifier.cpp',
|
||||
'src/test/test.cpp',
|
||||
]
|
||||
|
||||
general_include_dirs = [
|
||||
'rubberband',
|
||||
'src',
|
||||
@@ -101,6 +115,7 @@ 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)
|
||||
boost_unit_test_dep = dependency('boost', modules: ['unit_test_framework'], version: '>= 1.73', required: false)
|
||||
thread_dep = dependency('threads')
|
||||
have_ladspa = cpp.has_header('ladspa.h', args: extra_include_args)
|
||||
have_lv2 = cpp.has_header('lv2.h', args: extra_include_args)
|
||||
@@ -157,9 +172,9 @@ elif fft == 'kissfft'
|
||||
if fftw3_dep.found()
|
||||
message('(to use FFTW instead, reconfigure with -Dfft=fftw)')
|
||||
endif
|
||||
feature_sources += ['src/kissfft/kiss_fft.c', 'src/kissfft/kiss_fftr.c']
|
||||
feature_sources += ['src/ext/kissfft/kiss_fft.c', 'src/ext/kissfft/kiss_fftr.c']
|
||||
feature_defines += ['-DHAVE_KISSFFT']
|
||||
general_include_dirs += 'src/kissfft'
|
||||
general_include_dirs += 'src/ext/kissfft'
|
||||
|
||||
elif fft == 'fftw'
|
||||
if fftw3_dep.found()
|
||||
@@ -204,7 +219,7 @@ if resampler == 'builtin'
|
||||
if samplerate_dep.found()
|
||||
message('(to use libsamplerate instead, reconfigure with -Dresampler=libsamplerate)')
|
||||
endif
|
||||
library_sources += 'src/dsp/BQResampler.cpp'
|
||||
library_sources += 'src/common/BQResampler.cpp'
|
||||
feature_defines += ['-DUSE_BQRESAMPLER']
|
||||
|
||||
elif resampler == 'libsamplerate'
|
||||
@@ -226,7 +241,7 @@ elif resampler == 'speex'
|
||||
config_summary += { 'Resampler': 'Speex' }
|
||||
message('For resampler: using Speex')
|
||||
message('(consider libsamplerate if time-varying pitch shift is required)')
|
||||
feature_sources += ['src/speex/resample.c']
|
||||
feature_sources += ['src/ext/speex/resample.c']
|
||||
feature_defines += ['-DUSE_SPEEX']
|
||||
|
||||
elif resampler == 'ipp'
|
||||
@@ -313,6 +328,8 @@ if not sndfile_dep.found()
|
||||
endif
|
||||
have_sndfile = sndfile_dep.found()
|
||||
|
||||
have_boost_unit_test = boost_unit_test_dep.found()
|
||||
|
||||
|
||||
# General platform and compiler expectations
|
||||
|
||||
@@ -427,18 +444,22 @@ if cpp.get_id() == 'msvc'
|
||||
endif
|
||||
rubberband_library_name = 'rubberband'
|
||||
rubberband_program_name = 'rubberband-program'
|
||||
rubberband_program_name_r3 = 'rubberband-program-r3'
|
||||
rubberband_ladspa_name = 'ladspa-rubberband'
|
||||
rubberband_lv2_name = 'lv2-rubberband'
|
||||
rubberband_vamp_name = 'vamp-rubberband'
|
||||
rubberband_jni_name = 'rubberband-jni'
|
||||
unit_tests_name = 'tests'
|
||||
else
|
||||
rubberband_library_name = 'rubberband'
|
||||
rubberband_dynamic_name = 'rubberband'
|
||||
rubberband_program_name = 'rubberband'
|
||||
rubberband_program_name_r3 = 'rubberband-r3'
|
||||
rubberband_ladspa_name = 'ladspa-rubberband'
|
||||
rubberband_lv2_name = 'lv2-rubberband'
|
||||
rubberband_vamp_name = 'vamp-rubberband'
|
||||
rubberband_jni_name = 'rubberband-jni'
|
||||
unit_tests_name = 'tests'
|
||||
endif
|
||||
|
||||
rubberband_objlib = static_library(
|
||||
@@ -663,8 +684,8 @@ else
|
||||
endif
|
||||
|
||||
if have_sndfile
|
||||
target_summary += { 'Command-line utility': [ true, 'Name: ' + rubberband_program_name ] }
|
||||
message('Will build command-line utility')
|
||||
message('Will build command-line utilities')
|
||||
target_summary += { 'Command-line utility (R2)': [ true, 'Name: ' + rubberband_program_name ] }
|
||||
rubberband_program = executable(
|
||||
rubberband_program_name,
|
||||
program_sources,
|
||||
@@ -682,9 +703,66 @@ if have_sndfile
|
||||
],
|
||||
install: true,
|
||||
)
|
||||
target_summary += { 'Command-line utility (R3)': [ true, 'Name: ' + rubberband_program_name_r3 ] }
|
||||
rubberband_program_r3 = executable(
|
||||
rubberband_program_name_r3,
|
||||
program_sources,
|
||||
include_directories: general_include_dirs,
|
||||
cpp_args: general_compile_args,
|
||||
c_args: general_compile_args,
|
||||
link_args: [
|
||||
arch_flags,
|
||||
feature_libraries,
|
||||
],
|
||||
dependencies: [
|
||||
rubberband_objlib_dep,
|
||||
general_dependencies,
|
||||
sndfile_dep,
|
||||
],
|
||||
install: true,
|
||||
)
|
||||
else
|
||||
target_summary += { 'Command-line utility': false }
|
||||
message('Not building command-line utility: libsndfile dependency not found')
|
||||
message('Not building command-line utilities: libsndfile dependency not found')
|
||||
target_summary += { 'Command-line utility (R2)': false }
|
||||
target_summary += { 'Command-line utility (R3)': false }
|
||||
endif
|
||||
|
||||
if have_boost_unit_test
|
||||
target_summary += { 'Unit tests': [ true, 'Name: ' + unit_tests_name ] }
|
||||
message('Will build unit tests: use "meson test -C <builddir>" to run them')
|
||||
unit_tests = executable(
|
||||
unit_tests_name,
|
||||
unit_test_sources,
|
||||
cpp_args: general_compile_args,
|
||||
c_args: general_compile_args,
|
||||
link_args: [
|
||||
arch_flags,
|
||||
feature_libraries,
|
||||
],
|
||||
dependencies: [
|
||||
rubberband_objlib_dep,
|
||||
general_dependencies,
|
||||
boost_unit_test_dep,
|
||||
],
|
||||
install: false,
|
||||
build_by_default: false
|
||||
)
|
||||
general_test_args = [ '--log_level=message' ]
|
||||
test('Allocators',
|
||||
unit_tests, args: [ '--run_test=TestAllocators', general_test_args ])
|
||||
test('FFT',
|
||||
unit_tests, args: [ '--run_test=TestFFT', general_test_args ])
|
||||
test('Resampler',
|
||||
unit_tests, args: [ '--run_test=TestResampler', general_test_args ])
|
||||
test('VectorOps',
|
||||
unit_tests, args: [ '--run_test=TestVectorOps', general_test_args ])
|
||||
test('VectorOpsComplex',
|
||||
unit_tests, args: [ '--run_test=TestVectorOpsComplex', general_test_args ])
|
||||
test('SignalBits',
|
||||
unit_tests, args: [ '--run_test=TestSignalBits', general_test_args ])
|
||||
else
|
||||
target_summary += { 'Unit tests': false }
|
||||
message('Not building unit tests: boost_unit_test_framework dependency not found')
|
||||
endif
|
||||
|
||||
pkg.generate(
|
||||
|
||||
@@ -11,52 +11,39 @@ RUBBERBAND_JNI_FILES := \
|
||||
$(RUBBERBAND_SRC_PATH)/jni/RubberBandStretcherJNI.cpp
|
||||
|
||||
RUBBERBAND_SRC_FILES := \
|
||||
$(RUBBERBAND_SRC_PATH)/base/Profiler.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/system/Thread.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/system/Allocators.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/system/sysutils.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/system/VectorOpsComplex.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/StretcherChannelData.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/dsp/AudioCurveCalculator.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/dsp/FFT.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/dsp/Resampler.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/audiocurves/SilentAudioCurve.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/audiocurves/CompoundAudioCurve.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/audiocurves/HighFrequencyAudioCurve.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/audiocurves/SpectralDifferenceAudioCurve.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/audiocurves/ConstantAudioCurve.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/audiocurves/PercussiveAudioCurve.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/StretcherImpl.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/StretcherProcess.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/StretchCalculator.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/RubberBandStretcher.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/rubberband-c.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/speex/resample.c
|
||||
$(RUBBERBAND_SRC_PATH)/RubberBandStretcher.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/faster/AudioCurveCalculator.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/faster/CompoundAudioCurve.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/faster/HighFrequencyAudioCurve.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/faster/SilentAudioCurve.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/faster/PercussiveAudioCurve.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/faster/StretcherChannelData.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/faster/StretcherImpl.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/faster/StretcherProcess.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/common/BQResampler.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/common/Profiler.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/common/Resampler.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/common/FFT.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/common/Allocators.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/common/StretchCalculator.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/common/sysutils.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/common/Thread.cpp \
|
||||
$(RUBBERBAND_SRC_PATH)/finer/R3StretcherImpl.cpp
|
||||
|
||||
LOCAL_SRC_FILES += \
|
||||
$(RUBBERBAND_JNI_FILES) \
|
||||
$(RUBBERBAND_SRC_FILES)
|
||||
|
||||
LOCAL_SRC_FILES += \
|
||||
$(RUBBERBAND_SRC_PATH)/kissfft/kiss_fft.c \
|
||||
$(RUBBERBAND_SRC_PATH)/kissfft/kiss_fftr.c
|
||||
|
||||
LOCAL_CFLAGS_DEBUG := \
|
||||
-g \
|
||||
-mfloat-abi=softfp \
|
||||
-DWANT_TIMING \
|
||||
-DFFT_MEASUREMENT
|
||||
|
||||
LOCAL_CFLAGS_RELEASE := \
|
||||
-O3 \
|
||||
-mfpu=neon \
|
||||
-mfloat-abi=softfp \
|
||||
-ffast-math \
|
||||
-ftree-vectorize \
|
||||
-freciprocal-math \
|
||||
-fsingle-precision-constant \
|
||||
-D__ARM_ARCH_7__ \
|
||||
-DUSE_POMMIER_MATHFUN \
|
||||
-DNO_TIMING \
|
||||
-DNO_TIMING_COMPLETE_NOOP
|
||||
|
||||
@@ -64,9 +51,8 @@ LOCAL_CFLAGS := \
|
||||
-Wall \
|
||||
-I$(RUBBERBAND_PATH) \
|
||||
-I$(RUBBERBAND_SRC_PATH) \
|
||||
-DUSE_SPEEX \
|
||||
-DUSE_KISSFFT \
|
||||
-DPROCESS_SAMPLE_TYPE=float \
|
||||
-DUSE_BQRESAMPLER \
|
||||
-DUSE_BUILTIN_FFT \
|
||||
-DLACK_POSIX_MEMALIGN \
|
||||
-DUSE_OWN_ALIGNED_MALLOC \
|
||||
-DLACK_SINCOS \
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
|
||||
CXX := clang++
|
||||
CXX := clang++ -stdlib=libc++ -std=c++11
|
||||
CC := clang
|
||||
|
||||
OPTFLAGS := -DNDEBUG -ffast-math -freciprocal-math -O3 -ftree-vectorize
|
||||
OPTFLAGS := -DNDEBUG -ffast-math -O3 -ftree-vectorize
|
||||
|
||||
# For the device
|
||||
ARCHFLAGS_DEV := -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk -miphoneos-version-min=6 -stdlib=libc++ -arch armv7 -arch arm64 -fembed-bitcode
|
||||
ARCHFLAGS_DEV := -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk -miphoneos-version-min=6 -arch armv7 -arch arm64 -fembed-bitcode
|
||||
|
||||
# Or for the simulator
|
||||
ARCHFLAGS_SIM := -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk -miphoneos-version-min=6 -stdlib=libc++ -arch i386 -arch x86_64 -fembed-bitcode
|
||||
ARCHFLAGS_SIM := -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk -miphoneos-version-min=6 -arch x86_64 -fembed-bitcode
|
||||
|
||||
CXXFLAGS_ANY := $(OPTFLAGS) -I. -Isrc -Irubberband -DMALLOC_IS_ALIGNED -DHAVE_VDSP -DUSE_SPEEX -DUSE_POMMIER_MATHFUN -DNO_THREADING -DNO_THREAD_CHECKS -DNO_TIMING -DNO_TIMING_COMPLETE_NOOP -DNDEBUG
|
||||
CXXFLAGS_ANY := $(OPTFLAGS) -I. -Isrc -Irubberband -DUSE_BQRESAMPLER -DHAVE_VDSP -DNO_THREAD_CHECKS -DUSE_PTHREADS -DNO_TIMING -DMALLOC_IS_ALIGNED -DNDEBUG
|
||||
|
||||
CXXFLAGS_DEV := $(ARCHFLAGS_DEV) $(CXXFLAGS_ANY)
|
||||
CXXFLAGS_SIM := $(ARCHFLAGS_SIM) $(CXXFLAGS_ANY)
|
||||
@@ -36,59 +36,27 @@ PUBLIC_INCLUDES := \
|
||||
rubberband/rubberband-c.h \
|
||||
rubberband/RubberBandStretcher.h
|
||||
|
||||
LIBRARY_INCLUDES := \
|
||||
src/StretcherChannelData.h \
|
||||
src/float_cast/float_cast.h \
|
||||
src/StretcherImpl.h \
|
||||
src/StretchCalculator.h \
|
||||
src/base/Profiler.h \
|
||||
src/base/RingBuffer.h \
|
||||
src/base/Scavenger.h \
|
||||
src/dsp/AudioCurveCalculator.h \
|
||||
src/audiocurves/CompoundAudioCurve.h \
|
||||
src/audiocurves/ConstantAudioCurve.h \
|
||||
src/audiocurves/HighFrequencyAudioCurve.h \
|
||||
src/audiocurves/PercussiveAudioCurve.h \
|
||||
src/audiocurves/SilentAudioCurve.h \
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.h \
|
||||
src/dsp/Resampler.h \
|
||||
src/dsp/FFT.h \
|
||||
src/dsp/MovingMedian.h \
|
||||
src/dsp/SincWindow.h \
|
||||
src/dsp/Window.h \
|
||||
src/system/Allocators.h \
|
||||
src/system/Thread.h \
|
||||
src/system/VectorOps.h \
|
||||
src/system/VectorOpsComplex.h \
|
||||
src/system/sysutils.h
|
||||
|
||||
LIBRARY_SOURCES := \
|
||||
src/rubberband-c.cpp \
|
||||
src/RubberBandStretcher.cpp \
|
||||
src/StretcherProcess.cpp \
|
||||
src/StretchCalculator.cpp \
|
||||
src/base/Profiler.cpp \
|
||||
src/dsp/AudioCurveCalculator.cpp \
|
||||
src/audiocurves/CompoundAudioCurve.cpp \
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.cpp \
|
||||
src/audiocurves/HighFrequencyAudioCurve.cpp \
|
||||
src/audiocurves/SilentAudioCurve.cpp \
|
||||
src/audiocurves/ConstantAudioCurve.cpp \
|
||||
src/audiocurves/PercussiveAudioCurve.cpp \
|
||||
src/dsp/Resampler.cpp \
|
||||
src/dsp/FFT.cpp \
|
||||
src/system/Allocators.cpp \
|
||||
src/system/sysutils.cpp \
|
||||
src/system/Thread.cpp \
|
||||
src/system/VectorOpsComplex.cpp \
|
||||
src/StretcherChannelData.cpp \
|
||||
src/StretcherImpl.cpp
|
||||
|
||||
# For Speex resampler -- comment these lines out if not specifying USE_SPEEX
|
||||
LIBRARY_INCLUDES := $(LIBRARY_INCLUDES) \
|
||||
src/speex/speex_resampler.h
|
||||
LIBRARY_SOURCES := $(LIBRARY_SOURCES) \
|
||||
src/speex/resample.c
|
||||
src/faster/AudioCurveCalculator.cpp \
|
||||
src/faster/CompoundAudioCurve.cpp \
|
||||
src/faster/HighFrequencyAudioCurve.cpp \
|
||||
src/faster/SilentAudioCurve.cpp \
|
||||
src/faster/PercussiveAudioCurve.cpp \
|
||||
src/faster/R2Stretcher.cpp \
|
||||
src/faster/StretcherChannelData.cpp \
|
||||
src/faster/StretcherProcess.cpp \
|
||||
src/common/Allocators.cpp \
|
||||
src/common/BQResampler.cpp \
|
||||
src/common/FFT.cpp \
|
||||
src/common/Log.cpp \
|
||||
src/common/Profiler.cpp \
|
||||
src/common/Resampler.cpp \
|
||||
src/common/StretchCalculator.cpp \
|
||||
src/common/sysutils.cpp \
|
||||
src/common/Thread.cpp \
|
||||
src/finer/R3Stretcher.cpp
|
||||
|
||||
LIBRARY_OBJECTS_DEV := $(LIBRARY_SOURCES:.cpp=.dev.o)
|
||||
LIBRARY_OBJECTS_DEV := $(LIBRARY_OBJECTS_DEV:.c=.dev.o)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
|
||||
CXX := g++
|
||||
CXX := g++ -std=c++11
|
||||
CC := gcc
|
||||
|
||||
OPTFLAGS := -DNDEBUG -ffast-math -O3 -ftree-vectorize
|
||||
|
||||
ARCHFLAGS :=
|
||||
|
||||
CXXFLAGS := -std=c++11 $(ARCHFLAGS) $(OPTFLAGS) -I. -Isrc -Irubberband -DHAVE_LIBSAMPLERATE -DUSE_BUILTIN_FFT -DNO_THREAD_CHECKS -DUSE_PTHREADS -DNO_TIMING -DHAVE_POSIX_MEMALIGN -DNDEBUG
|
||||
CXXFLAGS := $(ARCHFLAGS) $(OPTFLAGS) -I. -Isrc -Irubberband -DUSE_BQRESAMPLER -DUSE_BUILTIN_FFT -DNO_THREAD_CHECKS -DUSE_PTHREADS -DNO_TIMING -DHAVE_POSIX_MEMALIGN -DNDEBUG
|
||||
|
||||
CFLAGS := $(ARCHFLAGS) $(OPTFLAGS)
|
||||
|
||||
@@ -25,51 +25,27 @@ PUBLIC_INCLUDES := \
|
||||
rubberband/rubberband-c.h \
|
||||
rubberband/RubberBandStretcher.h
|
||||
|
||||
LIBRARY_INCLUDES := \
|
||||
src/StretcherChannelData.h \
|
||||
src/float_cast/float_cast.h \
|
||||
src/StretcherImpl.h \
|
||||
src/StretchCalculator.h \
|
||||
src/base/Profiler.h \
|
||||
src/base/RingBuffer.h \
|
||||
src/base/Scavenger.h \
|
||||
src/dsp/AudioCurveCalculator.h \
|
||||
src/audiocurves/CompoundAudioCurve.h \
|
||||
src/audiocurves/ConstantAudioCurve.h \
|
||||
src/audiocurves/HighFrequencyAudioCurve.h \
|
||||
src/audiocurves/PercussiveAudioCurve.h \
|
||||
src/audiocurves/SilentAudioCurve.h \
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.h \
|
||||
src/dsp/Resampler.h \
|
||||
src/dsp/FFT.h \
|
||||
src/dsp/MovingMedian.h \
|
||||
src/dsp/SincWindow.h \
|
||||
src/dsp/Window.h \
|
||||
src/system/Allocators.h \
|
||||
src/system/Thread.h \
|
||||
src/system/VectorOps.h \
|
||||
src/system/sysutils.h
|
||||
|
||||
LIBRARY_SOURCES := \
|
||||
src/rubberband-c.cpp \
|
||||
src/RubberBandStretcher.cpp \
|
||||
src/StretcherProcess.cpp \
|
||||
src/StretchCalculator.cpp \
|
||||
src/base/Profiler.cpp \
|
||||
src/dsp/AudioCurveCalculator.cpp \
|
||||
src/audiocurves/CompoundAudioCurve.cpp \
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.cpp \
|
||||
src/audiocurves/HighFrequencyAudioCurve.cpp \
|
||||
src/audiocurves/SilentAudioCurve.cpp \
|
||||
src/audiocurves/ConstantAudioCurve.cpp \
|
||||
src/audiocurves/PercussiveAudioCurve.cpp \
|
||||
src/dsp/Resampler.cpp \
|
||||
src/dsp/FFT.cpp \
|
||||
src/system/Allocators.cpp \
|
||||
src/system/sysutils.cpp \
|
||||
src/system/Thread.cpp \
|
||||
src/StretcherChannelData.cpp \
|
||||
src/StretcherImpl.cpp
|
||||
src/faster/AudioCurveCalculator.cpp \
|
||||
src/faster/CompoundAudioCurve.cpp \
|
||||
src/faster/HighFrequencyAudioCurve.cpp \
|
||||
src/faster/SilentAudioCurve.cpp \
|
||||
src/faster/PercussiveAudioCurve.cpp \
|
||||
src/faster/R2Stretcher.cpp \
|
||||
src/faster/StretcherChannelData.cpp \
|
||||
src/faster/StretcherProcess.cpp \
|
||||
src/common/Allocators.cpp \
|
||||
src/common/BQResampler.cpp \
|
||||
src/common/FFT.cpp \
|
||||
src/common/Log.cpp \
|
||||
src/common/Profiler.cpp \
|
||||
src/common/Resampler.cpp \
|
||||
src/common/StretchCalculator.cpp \
|
||||
src/common/sysutils.cpp \
|
||||
src/common/Thread.cpp \
|
||||
src/finer/R3Stretcher.cpp
|
||||
|
||||
LIBRARY_OBJECTS := $(LIBRARY_SOURCES:.cpp=.o)
|
||||
LIBRARY_OBJECTS := $(LIBRARY_OBJECTS:.c=.o)
|
||||
@@ -94,88 +70,138 @@ depend:
|
||||
|
||||
src/rubberband-c.o: rubberband/rubberband-c.h
|
||||
src/rubberband-c.o: rubberband/RubberBandStretcher.h
|
||||
src/RubberBandStretcher.o: src/StretcherImpl.h
|
||||
src/RubberBandStretcher.o: rubberband/RubberBandStretcher.h src/dsp/Window.h
|
||||
src/RubberBandStretcher.o: src/dsp/SincWindow.h src/dsp/FFT.h
|
||||
src/RubberBandStretcher.o: src/audiocurves/CompoundAudioCurve.h
|
||||
src/RubberBandStretcher.o: src/dsp/AudioCurveCalculator.h
|
||||
src/RubberBandStretcher.o: src/audiocurves/PercussiveAudioCurve.h
|
||||
src/RubberBandStretcher.o: src/audiocurves/HighFrequencyAudioCurve.h
|
||||
src/RubberBandStretcher.o: src/dsp/SampleFilter.h src/base/RingBuffer.h
|
||||
src/RubberBandStretcher.o: src/base/Scavenger.h src/system/Thread.h
|
||||
src/RubberBandStretcher.o: src/system/sysutils.h
|
||||
src/StretcherProcess.o: src/StretcherImpl.h rubberband/RubberBandStretcher.h
|
||||
src/StretcherProcess.o: src/dsp/Window.h src/dsp/SincWindow.h src/dsp/FFT.h
|
||||
src/StretcherProcess.o: src/audiocurves/CompoundAudioCurve.h
|
||||
src/StretcherProcess.o: src/dsp/AudioCurveCalculator.h
|
||||
src/StretcherProcess.o: src/audiocurves/PercussiveAudioCurve.h
|
||||
src/StretcherProcess.o: src/audiocurves/HighFrequencyAudioCurve.h
|
||||
src/StretcherProcess.o: src/dsp/SampleFilter.h src/base/RingBuffer.h
|
||||
src/StretcherProcess.o: src/base/Scavenger.h src/system/Thread.h
|
||||
src/StretcherProcess.o: src/system/sysutils.h src/audiocurves/PercussiveAudioCurve.h
|
||||
src/StretcherProcess.o: src/audiocurves/HighFrequencyAudioCurve.h
|
||||
src/StretcherProcess.o: src/audiocurves/ConstantAudioCurve.h src/StretchCalculator.h
|
||||
src/StretcherProcess.o: src/StretcherChannelData.h src/dsp/Resampler.h
|
||||
src/StretcherProcess.o: src/base/Profiler.h src/system/VectorOps.h
|
||||
src/StretcherProcess.o: src/system/sysutils.h
|
||||
src/StretchCalculator.o: src/StretchCalculator.h src/system/sysutils.h
|
||||
src/base/Profiler.o: src/base/Profiler.h src/system/sysutils.h
|
||||
src/dsp/AudioCurveCalculator.o: src/dsp/AudioCurveCalculator.h
|
||||
src/audiocurves/CompoundAudioCurve.o: src/audiocurves/CompoundAudioCurve.h
|
||||
src/audiocurves/CompoundAudioCurve.o: src/dsp/AudioCurveCalculator.h
|
||||
src/audiocurves/CompoundAudioCurve.o: src/audiocurves/PercussiveAudioCurve.h
|
||||
src/audiocurves/CompoundAudioCurve.o: src/audiocurves/HighFrequencyAudioCurve.h
|
||||
src/audiocurves/CompoundAudioCurve.o: src/dsp/SampleFilter.h src/dsp/MovingMedian.h
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.o: src/audiocurves/SpectralDifferenceAudioCurve.h
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.o: src/dsp/AudioCurveCalculator.h
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.o: src/dsp/Window.h
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.o: src/system/sysutils.h
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.o: src/system/VectorOps.h
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.o: src/system/sysutils.h
|
||||
src/audiocurves/HighFrequencyAudioCurve.o: src/audiocurves/HighFrequencyAudioCurve.h
|
||||
src/audiocurves/HighFrequencyAudioCurve.o: src/dsp/AudioCurveCalculator.h
|
||||
src/audiocurves/SilentAudioCurve.o: src/audiocurves/SilentAudioCurve.h
|
||||
src/audiocurves/SilentAudioCurve.o: src/dsp/AudioCurveCalculator.h
|
||||
src/audiocurves/ConstantAudioCurve.o: src/audiocurves/ConstantAudioCurve.h
|
||||
src/audiocurves/ConstantAudioCurve.o: src/dsp/AudioCurveCalculator.h
|
||||
src/audiocurves/PercussiveAudioCurve.o: src/audiocurves/PercussiveAudioCurve.h
|
||||
src/audiocurves/PercussiveAudioCurve.o: src/dsp/AudioCurveCalculator.h
|
||||
src/audiocurves/PercussiveAudioCurve.o: src/system/VectorOps.h src/system/sysutils.h
|
||||
src/dsp/Resampler.o: src/dsp/Resampler.h src/system/sysutils.h
|
||||
src/dsp/Resampler.o: src/base/Profiler.h
|
||||
src/dsp/FFT.o: src/dsp/FFT.h src/system/sysutils.h src/system/Thread.h
|
||||
src/dsp/FFT.o: src/base/Profiler.h src/system/VectorOps.h
|
||||
src/dsp/FFT.o: src/system/sysutils.h
|
||||
src/system/Allocators.o: src/system/Allocators.h src/system/VectorOps.h
|
||||
src/system/Allocators.o: src/system/sysutils.h
|
||||
src/system/sysutils.o: src/system/sysutils.h
|
||||
src/system/Thread.o: src/system/Thread.h
|
||||
src/StretcherChannelData.o: src/StretcherChannelData.h src/StretcherImpl.h
|
||||
src/StretcherChannelData.o: rubberband/RubberBandStretcher.h src/dsp/Window.h
|
||||
src/StretcherChannelData.o: src/dsp/SincWindow.h src/dsp/FFT.h
|
||||
src/StretcherChannelData.o: src/audiocurves/CompoundAudioCurve.h
|
||||
src/StretcherChannelData.o: src/dsp/AudioCurveCalculator.h
|
||||
src/StretcherChannelData.o: src/audiocurves/PercussiveAudioCurve.h
|
||||
src/StretcherChannelData.o: src/audiocurves/HighFrequencyAudioCurve.h
|
||||
src/StretcherChannelData.o: src/dsp/SampleFilter.h src/base/RingBuffer.h
|
||||
src/StretcherChannelData.o: src/base/Scavenger.h src/system/Thread.h
|
||||
src/StretcherChannelData.o: src/system/sysutils.h src/dsp/Resampler.h
|
||||
src/StretcherChannelData.o: src/system/Allocators.h src/system/VectorOps.h
|
||||
src/StretcherChannelData.o: src/system/sysutils.h
|
||||
src/StretcherImpl.o: src/StretcherImpl.h rubberband/RubberBandStretcher.h
|
||||
src/StretcherImpl.o: src/dsp/Window.h src/dsp/SincWindow.h src/dsp/FFT.h
|
||||
src/StretcherImpl.o: src/audiocurves/CompoundAudioCurve.h
|
||||
src/StretcherImpl.o: src/dsp/AudioCurveCalculator.h
|
||||
src/StretcherImpl.o: src/audiocurves/PercussiveAudioCurve.h
|
||||
src/StretcherImpl.o: src/audiocurves/HighFrequencyAudioCurve.h src/dsp/SampleFilter.h
|
||||
src/StretcherImpl.o: src/base/RingBuffer.h src/base/Scavenger.h
|
||||
src/StretcherImpl.o: src/system/Thread.h src/system/sysutils.h
|
||||
src/StretcherImpl.o: src/audiocurves/PercussiveAudioCurve.h
|
||||
src/StretcherImpl.o: src/audiocurves/HighFrequencyAudioCurve.h
|
||||
src/StretcherImpl.o: src/audiocurves/SpectralDifferenceAudioCurve.h src/dsp/Window.h
|
||||
src/StretcherImpl.o: src/system/VectorOps.h src/system/sysutils.h
|
||||
src/StretcherImpl.o: src/audiocurves/SilentAudioCurve.h src/audiocurves/ConstantAudioCurve.h
|
||||
src/StretcherImpl.o: src/dsp/Resampler.h src/StretchCalculator.h
|
||||
src/StretcherImpl.o: src/StretcherChannelData.h src/base/Profiler.h
|
||||
main/main.o: rubberband/RubberBandStretcher.h src/system/sysutils.h
|
||||
main/main.o: src/base/Profiler.h
|
||||
src/RubberBandStretcher.o: src/faster/R2Stretcher.h
|
||||
src/RubberBandStretcher.o: rubberband/RubberBandStretcher.h
|
||||
src/RubberBandStretcher.o: src/common/Window.h src/common/sysutils.h
|
||||
src/RubberBandStretcher.o: src/common/VectorOps.h src/common/Allocators.h
|
||||
src/RubberBandStretcher.o: src/common/FFT.h src/common/RingBuffer.h
|
||||
src/RubberBandStretcher.o: src/common/Scavenger.h src/common/Thread.h
|
||||
src/RubberBandStretcher.o: src/common/Thread.h src/common/Log.h
|
||||
src/RubberBandStretcher.o: src/common/sysutils.h src/faster/SincWindow.h
|
||||
src/RubberBandStretcher.o: src/common/VectorOps.h src/common/Allocators.h
|
||||
src/RubberBandStretcher.o: src/faster/CompoundAudioCurve.h
|
||||
src/RubberBandStretcher.o: src/faster/PercussiveAudioCurve.h
|
||||
src/RubberBandStretcher.o: src/faster/AudioCurveCalculator.h
|
||||
src/RubberBandStretcher.o: src/faster/HighFrequencyAudioCurve.h
|
||||
src/RubberBandStretcher.o: src/common/SampleFilter.h src/finer/R3Stretcher.h
|
||||
src/RubberBandStretcher.o: src/finer/BinSegmenter.h src/finer/BinClassifier.h
|
||||
src/RubberBandStretcher.o: src/common/MovingMedian.h
|
||||
src/RubberBandStretcher.o: src/common/SampleFilter.h src/common/FixedVector.h
|
||||
src/RubberBandStretcher.o: src/common/SingleThreadRingBuffer.h
|
||||
src/RubberBandStretcher.o: src/common/HistogramFilter.h src/common/mathmisc.h
|
||||
src/RubberBandStretcher.o: src/finer/Guide.h src/finer/Peak.h
|
||||
src/RubberBandStretcher.o: src/finer/PhaseAdvance.h
|
||||
src/RubberBandStretcher.o: src/common/StretchCalculator.h src/common/Log.h
|
||||
src/RubberBandStretcher.o: src/common/Resampler.h src/common/FixedVector.h
|
||||
src/RubberBandStretcher.o: src/common/VectorOpsComplex.h
|
||||
src/faster/AudioCurveCalculator.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/AudioCurveCalculator.o: src/common/sysutils.h
|
||||
src/faster/CompoundAudioCurve.o: src/faster/CompoundAudioCurve.h
|
||||
src/faster/CompoundAudioCurve.o: src/faster/PercussiveAudioCurve.h
|
||||
src/faster/CompoundAudioCurve.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/sysutils.h
|
||||
src/faster/CompoundAudioCurve.o: src/faster/HighFrequencyAudioCurve.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/SampleFilter.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/MovingMedian.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/SampleFilter.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/FixedVector.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/Allocators.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/VectorOps.h src/common/sysutils.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/SingleThreadRingBuffer.h
|
||||
src/faster/HighFrequencyAudioCurve.o: src/faster/HighFrequencyAudioCurve.h
|
||||
src/faster/HighFrequencyAudioCurve.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/HighFrequencyAudioCurve.o: src/common/sysutils.h
|
||||
src/faster/SilentAudioCurve.o: src/faster/SilentAudioCurve.h
|
||||
src/faster/SilentAudioCurve.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/SilentAudioCurve.o: src/common/sysutils.h
|
||||
src/faster/PercussiveAudioCurve.o: src/faster/PercussiveAudioCurve.h
|
||||
src/faster/PercussiveAudioCurve.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/PercussiveAudioCurve.o: src/common/sysutils.h
|
||||
src/faster/PercussiveAudioCurve.o: src/common/Allocators.h
|
||||
src/faster/PercussiveAudioCurve.o: src/common/VectorOps.h
|
||||
src/faster/R2Stretcher.o: src/faster/R2Stretcher.h
|
||||
src/faster/R2Stretcher.o: rubberband/RubberBandStretcher.h
|
||||
src/faster/R2Stretcher.o: src/common/Window.h src/common/sysutils.h
|
||||
src/faster/R2Stretcher.o: src/common/VectorOps.h src/common/Allocators.h
|
||||
src/faster/R2Stretcher.o: src/common/FFT.h src/common/RingBuffer.h
|
||||
src/faster/R2Stretcher.o: src/common/Scavenger.h src/common/Thread.h
|
||||
src/faster/R2Stretcher.o: src/common/Thread.h src/common/Log.h
|
||||
src/faster/R2Stretcher.o: src/common/sysutils.h src/faster/SincWindow.h
|
||||
src/faster/R2Stretcher.o: src/common/VectorOps.h src/common/Allocators.h
|
||||
src/faster/R2Stretcher.o: src/faster/CompoundAudioCurve.h
|
||||
src/faster/R2Stretcher.o: src/faster/PercussiveAudioCurve.h
|
||||
src/faster/R2Stretcher.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/R2Stretcher.o: src/faster/HighFrequencyAudioCurve.h
|
||||
src/faster/R2Stretcher.o: src/common/SampleFilter.h
|
||||
src/faster/R2Stretcher.o: src/faster/SilentAudioCurve.h
|
||||
src/faster/R2Stretcher.o: src/faster/StretcherChannelData.h
|
||||
src/faster/R2Stretcher.o: src/common/StretchCalculator.h src/common/Log.h
|
||||
src/faster/R2Stretcher.o: src/common/Resampler.h src/common/Profiler.h
|
||||
src/faster/StretcherChannelData.o: src/faster/StretcherChannelData.h
|
||||
src/faster/StretcherChannelData.o: src/faster/R2Stretcher.h
|
||||
src/faster/StretcherChannelData.o: rubberband/RubberBandStretcher.h
|
||||
src/faster/StretcherChannelData.o: src/common/Window.h src/common/sysutils.h
|
||||
src/faster/StretcherChannelData.o: src/common/VectorOps.h
|
||||
src/faster/StretcherChannelData.o: src/common/Allocators.h src/common/FFT.h
|
||||
src/faster/StretcherChannelData.o: src/common/RingBuffer.h
|
||||
src/faster/StretcherChannelData.o: src/common/Scavenger.h src/common/Thread.h
|
||||
src/faster/StretcherChannelData.o: src/common/Thread.h src/common/Log.h
|
||||
src/faster/StretcherChannelData.o: src/common/sysutils.h
|
||||
src/faster/StretcherChannelData.o: src/faster/SincWindow.h
|
||||
src/faster/StretcherChannelData.o: src/common/VectorOps.h
|
||||
src/faster/StretcherChannelData.o: src/common/Allocators.h
|
||||
src/faster/StretcherChannelData.o: src/faster/CompoundAudioCurve.h
|
||||
src/faster/StretcherChannelData.o: src/faster/PercussiveAudioCurve.h
|
||||
src/faster/StretcherChannelData.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/StretcherChannelData.o: src/faster/HighFrequencyAudioCurve.h
|
||||
src/faster/StretcherChannelData.o: src/common/SampleFilter.h
|
||||
src/faster/StretcherChannelData.o: src/common/Resampler.h
|
||||
src/faster/StretcherProcess.o: src/faster/R2Stretcher.h
|
||||
src/faster/StretcherProcess.o: rubberband/RubberBandStretcher.h
|
||||
src/faster/StretcherProcess.o: src/common/Window.h src/common/sysutils.h
|
||||
src/faster/StretcherProcess.o: src/common/VectorOps.h src/common/Allocators.h
|
||||
src/faster/StretcherProcess.o: src/common/FFT.h src/common/RingBuffer.h
|
||||
src/faster/StretcherProcess.o: src/common/Scavenger.h src/common/Thread.h
|
||||
src/faster/StretcherProcess.o: src/common/Thread.h src/common/Log.h
|
||||
src/faster/StretcherProcess.o: src/common/sysutils.h src/faster/SincWindow.h
|
||||
src/faster/StretcherProcess.o: src/common/VectorOps.h src/common/Allocators.h
|
||||
src/faster/StretcherProcess.o: src/faster/CompoundAudioCurve.h
|
||||
src/faster/StretcherProcess.o: src/faster/PercussiveAudioCurve.h
|
||||
src/faster/StretcherProcess.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/StretcherProcess.o: src/faster/HighFrequencyAudioCurve.h
|
||||
src/faster/StretcherProcess.o: src/common/SampleFilter.h
|
||||
src/faster/StretcherProcess.o: src/faster/StretcherChannelData.h
|
||||
src/faster/StretcherProcess.o: src/common/StretchCalculator.h
|
||||
src/faster/StretcherProcess.o: src/common/Log.h src/common/Resampler.h
|
||||
src/faster/StretcherProcess.o: src/common/Profiler.h src/common/mathmisc.h
|
||||
src/common/Allocators.o: src/common/Allocators.h src/common/VectorOps.h
|
||||
src/common/Allocators.o: src/common/sysutils.h
|
||||
src/common/BQResampler.o: src/common/BQResampler.h src/common/Allocators.h
|
||||
src/common/BQResampler.o: src/common/VectorOps.h src/common/sysutils.h
|
||||
src/common/FFT.o: src/common/FFT.h src/common/sysutils.h src/common/Thread.h
|
||||
src/common/FFT.o: src/common/Profiler.h src/common/Allocators.h
|
||||
src/common/FFT.o: src/common/VectorOps.h src/common/VectorOpsComplex.h
|
||||
src/common/Log.o: src/common/Log.h
|
||||
src/common/Profiler.o: src/common/Profiler.h src/common/sysutils.h
|
||||
src/common/Profiler.o: src/common/Thread.h
|
||||
src/common/Resampler.o: src/common/Resampler.h src/common/sysutils.h
|
||||
src/common/Resampler.o: src/common/Allocators.h src/common/VectorOps.h
|
||||
src/common/StretchCalculator.o: src/common/StretchCalculator.h
|
||||
src/common/StretchCalculator.o: src/common/Log.h src/common/sysutils.h
|
||||
src/common/sysutils.o: src/common/sysutils.h
|
||||
src/common/Thread.o: src/common/Thread.h
|
||||
src/finer/R3Stretcher.o: src/finer/R3Stretcher.h src/finer/BinSegmenter.h
|
||||
src/finer/R3Stretcher.o: src/finer/BinClassifier.h src/common/Allocators.h
|
||||
src/finer/R3Stretcher.o: src/common/MovingMedian.h src/common/SampleFilter.h
|
||||
src/finer/R3Stretcher.o: src/common/FixedVector.h src/common/Allocators.h
|
||||
src/finer/R3Stretcher.o: src/common/VectorOps.h src/common/sysutils.h
|
||||
src/finer/R3Stretcher.o: src/common/SingleThreadRingBuffer.h
|
||||
src/finer/R3Stretcher.o: src/common/RingBuffer.h src/common/HistogramFilter.h
|
||||
src/finer/R3Stretcher.o: src/common/mathmisc.h src/finer/Guide.h
|
||||
src/finer/R3Stretcher.o: src/common/Log.h src/finer/Peak.h
|
||||
src/finer/R3Stretcher.o: src/finer/PhaseAdvance.h
|
||||
src/finer/R3Stretcher.o: src/common/StretchCalculator.h src/common/Log.h
|
||||
src/finer/R3Stretcher.o: src/common/Resampler.h src/common/FFT.h
|
||||
src/finer/R3Stretcher.o: src/common/FixedVector.h src/common/Window.h
|
||||
src/finer/R3Stretcher.o: src/common/VectorOpsComplex.h
|
||||
src/finer/R3Stretcher.o: rubberband/RubberBandStretcher.h
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
|
||||
CXX := clang++ -stdlib=libc++
|
||||
CXX := clang++ -stdlib=libc++ -std=c++11
|
||||
CC := clang
|
||||
|
||||
OPTFLAGS := -DNDEBUG -ffast-math -O3 -ftree-vectorize
|
||||
|
||||
ARCHFLAGS := -mmacosx-version-min=10.7
|
||||
|
||||
CXXFLAGS := $(ARCHFLAGS) $(OPTFLAGS) -I. -Isrc -Irubberband -I/usr/local/include -DUSE_PTHREADS -DMALLOC_IS_ALIGNED -DHAVE_VDSP -DUSE_SPEEX -DNO_THREAD_CHECKS -DNO_TIMING
|
||||
CXXFLAGS := $(ARCHFLAGS) $(OPTFLAGS) -I. -Isrc -Irubberband -DUSE_BQRESAMPLER -DHAVE_VDSP -DNO_THREAD_CHECKS -DUSE_PTHREADS -DNO_TIMING -DMALLOC_IS_ALIGNED -DNDEBUG
|
||||
|
||||
CFLAGS := $(ARCHFLAGS) $(OPTFLAGS)
|
||||
|
||||
@@ -25,59 +25,27 @@ PUBLIC_INCLUDES := \
|
||||
rubberband/rubberband-c.h \
|
||||
rubberband/RubberBandStretcher.h
|
||||
|
||||
LIBRARY_INCLUDES := \
|
||||
src/StretcherChannelData.h \
|
||||
src/float_cast/float_cast.h \
|
||||
src/StretcherImpl.h \
|
||||
src/StretchCalculator.h \
|
||||
src/base/Profiler.h \
|
||||
src/base/RingBuffer.h \
|
||||
src/base/Scavenger.h \
|
||||
src/dsp/AudioCurveCalculator.h \
|
||||
src/audiocurves/CompoundAudioCurve.h \
|
||||
src/audiocurves/ConstantAudioCurve.h \
|
||||
src/audiocurves/HighFrequencyAudioCurve.h \
|
||||
src/audiocurves/PercussiveAudioCurve.h \
|
||||
src/audiocurves/SilentAudioCurve.h \
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.h \
|
||||
src/dsp/Resampler.h \
|
||||
src/dsp/FFT.h \
|
||||
src/dsp/MovingMedian.h \
|
||||
src/dsp/SincWindow.h \
|
||||
src/dsp/Window.h \
|
||||
src/system/Allocators.h \
|
||||
src/system/Thread.h \
|
||||
src/system/VectorOps.h \
|
||||
src/system/VectorOpsComplex.h \
|
||||
src/system/sysutils.h
|
||||
|
||||
LIBRARY_SOURCES := \
|
||||
src/rubberband-c.cpp \
|
||||
src/RubberBandStretcher.cpp \
|
||||
src/StretcherProcess.cpp \
|
||||
src/StretchCalculator.cpp \
|
||||
src/base/Profiler.cpp \
|
||||
src/dsp/AudioCurveCalculator.cpp \
|
||||
src/audiocurves/CompoundAudioCurve.cpp \
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.cpp \
|
||||
src/audiocurves/HighFrequencyAudioCurve.cpp \
|
||||
src/audiocurves/SilentAudioCurve.cpp \
|
||||
src/audiocurves/ConstantAudioCurve.cpp \
|
||||
src/audiocurves/PercussiveAudioCurve.cpp \
|
||||
src/dsp/Resampler.cpp \
|
||||
src/dsp/FFT.cpp \
|
||||
src/system/Allocators.cpp \
|
||||
src/system/sysutils.cpp \
|
||||
src/system/Thread.cpp \
|
||||
src/system/VectorOpsComplex.cpp \
|
||||
src/StretcherChannelData.cpp \
|
||||
src/StretcherImpl.cpp
|
||||
|
||||
# For Speex resampler -- comment these lines out if not specifying USE_SPEEX
|
||||
LIBRARY_INCLUDES := $(LIBRARY_INCLUDES) \
|
||||
src/speex/speex_resampler.h
|
||||
LIBRARY_SOURCES := $(LIBRARY_SOURCES) \
|
||||
src/speex/resample.c
|
||||
src/faster/AudioCurveCalculator.cpp \
|
||||
src/faster/CompoundAudioCurve.cpp \
|
||||
src/faster/HighFrequencyAudioCurve.cpp \
|
||||
src/faster/SilentAudioCurve.cpp \
|
||||
src/faster/PercussiveAudioCurve.cpp \
|
||||
src/faster/R2Stretcher.cpp \
|
||||
src/faster/StretcherChannelData.cpp \
|
||||
src/faster/StretcherProcess.cpp \
|
||||
src/common/Allocators.cpp \
|
||||
src/common/BQResampler.cpp \
|
||||
src/common/FFT.cpp \
|
||||
src/common/Log.cpp \
|
||||
src/common/Profiler.cpp \
|
||||
src/common/Resampler.cpp \
|
||||
src/common/StretchCalculator.cpp \
|
||||
src/common/sysutils.cpp \
|
||||
src/common/Thread.cpp \
|
||||
src/finer/R3Stretcher.cpp
|
||||
|
||||
LIBRARY_OBJECTS := $(LIBRARY_SOURCES:.cpp=.o)
|
||||
LIBRARY_OBJECTS := $(LIBRARY_OBJECTS:.c=.o)
|
||||
@@ -103,71 +71,138 @@ depend:
|
||||
|
||||
src/rubberband-c.o: rubberband/rubberband-c.h
|
||||
src/rubberband-c.o: rubberband/RubberBandStretcher.h
|
||||
src/RubberBandStretcher.o: src/StretcherImpl.h
|
||||
src/RubberBandStretcher.o: rubberband/RubberBandStretcher.h src/dsp/Window.h
|
||||
src/RubberBandStretcher.o: src/dsp/FFT.h src/base/RingBuffer.h
|
||||
src/RubberBandStretcher.o: src/base/Scavenger.h src/system/Thread.h
|
||||
src/RubberBandStretcher.o: src/system/Thread.h src/system/sysutils.h
|
||||
src/StretcherProcess.o: src/StretcherImpl.h rubberband/RubberBandStretcher.h
|
||||
src/StretcherProcess.o: src/dsp/Window.h src/dsp/FFT.h src/base/RingBuffer.h
|
||||
src/StretcherProcess.o: src/base/Scavenger.h src/system/Thread.h
|
||||
src/StretcherProcess.o: src/system/Thread.h src/system/sysutils.h
|
||||
src/StretcherProcess.o: src/audiocurves/PercussiveAudioCurve.h
|
||||
src/StretcherProcess.o: src/dsp/AudioCurveCalculator.h
|
||||
src/StretcherProcess.o: src/audiocurves/HighFrequencyAudioCurve.h
|
||||
src/StretcherProcess.o: src/audiocurves/ConstantAudioCurve.h src/StretchCalculator.h
|
||||
src/StretcherProcess.o: src/StretcherChannelData.h src/dsp/Resampler.h
|
||||
src/StretcherProcess.o: src/base/Profiler.h src/system/VectorOps.h
|
||||
src/StretcherProcess.o: src/system/sysutils.h
|
||||
src/StretchCalculator.o: src/StretchCalculator.h src/system/sysutils.h
|
||||
src/system/Thread.o: src/system/Thread.h
|
||||
src/base/Profiler.o: src/base/Profiler.h src/system/sysutils.h
|
||||
src/dsp/AudioCurveCalculator.o: src/dsp/AudioCurveCalculator.h
|
||||
src/dsp/AudioCurveCalculator.o: src/system/sysutils.h
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.o: src/audiocurves/SpectralDifferenceAudioCurve.h
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.o: src/dsp/AudioCurveCalculator.h
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.o: src/system/sysutils.h
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.o: src/dsp/Window.h
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.o: src/system/VectorOps.h
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.o: src/system/sysutils.h
|
||||
src/audiocurves/HighFrequencyAudioCurve.o: src/audiocurves/HighFrequencyAudioCurve.h
|
||||
src/audiocurves/HighFrequencyAudioCurve.o: src/dsp/AudioCurveCalculator.h
|
||||
src/audiocurves/HighFrequencyAudioCurve.o: src/system/sysutils.h
|
||||
src/audiocurves/SilentAudioCurve.o: src/audiocurves/SilentAudioCurve.h
|
||||
src/audiocurves/SilentAudioCurve.o: src/dsp/AudioCurveCalculator.h
|
||||
src/audiocurves/SilentAudioCurve.o: src/system/sysutils.h
|
||||
src/audiocurves/ConstantAudioCurve.o: src/audiocurves/ConstantAudioCurve.h
|
||||
src/audiocurves/ConstantAudioCurve.o: src/dsp/AudioCurveCalculator.h
|
||||
src/audiocurves/ConstantAudioCurve.o: src/system/sysutils.h
|
||||
src/audiocurves/PercussiveAudioCurve.o: src/audiocurves/PercussiveAudioCurve.h
|
||||
src/audiocurves/PercussiveAudioCurve.o: src/dsp/AudioCurveCalculator.h
|
||||
src/audiocurves/PercussiveAudioCurve.o: src/system/sysutils.h src/system/VectorOps.h
|
||||
src/audiocurves/PercussiveAudioCurve.o: src/system/sysutils.h
|
||||
src/dsp/Resampler.o: src/dsp/Resampler.h src/system/sysutils.h
|
||||
src/dsp/Resampler.o: src/base/Profiler.h
|
||||
src/dsp/FFT.o: src/dsp/FFT.h src/system/sysutils.h src/system/Thread.h
|
||||
src/dsp/FFT.o: src/base/Profiler.h src/system/VectorOps.h
|
||||
src/dsp/FFT.o: src/system/sysutils.h
|
||||
src/system/Allocators.o: src/system/Allocators.h src/system/VectorOps.h
|
||||
src/system/Allocators.o: src/system/sysutils.h
|
||||
src/system/sysutils.o: src/system/sysutils.h
|
||||
src/StretcherChannelData.o: src/StretcherChannelData.h src/StretcherImpl.h
|
||||
src/StretcherChannelData.o: rubberband/RubberBandStretcher.h src/dsp/Window.h
|
||||
src/StretcherChannelData.o: src/dsp/FFT.h src/base/RingBuffer.h
|
||||
src/StretcherChannelData.o: src/base/Scavenger.h src/system/Thread.h
|
||||
src/StretcherChannelData.o: src/system/Thread.h src/system/sysutils.h
|
||||
src/StretcherChannelData.o: src/dsp/Resampler.h src/system/Allocators.h
|
||||
src/StretcherChannelData.o: src/system/VectorOps.h src/system/sysutils.h
|
||||
src/StretcherImpl.o: src/StretcherImpl.h rubberband/RubberBandStretcher.h
|
||||
src/StretcherImpl.o: src/dsp/Window.h src/dsp/FFT.h src/base/RingBuffer.h
|
||||
src/StretcherImpl.o: src/base/Scavenger.h src/system/Thread.h src/system/Thread.h
|
||||
src/StretcherImpl.o: src/system/sysutils.h src/audiocurves/PercussiveAudioCurve.h
|
||||
src/StretcherImpl.o: src/dsp/AudioCurveCalculator.h
|
||||
src/StretcherImpl.o: src/audiocurves/HighFrequencyAudioCurve.h
|
||||
src/StretcherImpl.o: src/audiocurves/SpectralDifferenceAudioCurve.h src/dsp/Window.h
|
||||
src/StretcherImpl.o: src/system/VectorOps.h src/system/sysutils.h
|
||||
src/StretcherImpl.o: src/audiocurves/SilentAudioCurve.h src/audiocurves/ConstantAudioCurve.h
|
||||
src/StretcherImpl.o: src/dsp/Resampler.h src/StretchCalculator.h
|
||||
src/StretcherImpl.o: src/StretcherChannelData.h src/base/Profiler.h
|
||||
main/main.o: rubberband/RubberBandStretcher.h src/system/sysutils.h
|
||||
main/main.o: src/base/Profiler.h
|
||||
src/RubberBandStretcher.o: src/faster/R2Stretcher.h
|
||||
src/RubberBandStretcher.o: rubberband/RubberBandStretcher.h
|
||||
src/RubberBandStretcher.o: src/common/Window.h src/common/sysutils.h
|
||||
src/RubberBandStretcher.o: src/common/VectorOps.h src/common/Allocators.h
|
||||
src/RubberBandStretcher.o: src/common/FFT.h src/common/RingBuffer.h
|
||||
src/RubberBandStretcher.o: src/common/Scavenger.h src/common/Thread.h
|
||||
src/RubberBandStretcher.o: src/common/Thread.h src/common/Log.h
|
||||
src/RubberBandStretcher.o: src/common/sysutils.h src/faster/SincWindow.h
|
||||
src/RubberBandStretcher.o: src/common/VectorOps.h src/common/Allocators.h
|
||||
src/RubberBandStretcher.o: src/faster/CompoundAudioCurve.h
|
||||
src/RubberBandStretcher.o: src/faster/PercussiveAudioCurve.h
|
||||
src/RubberBandStretcher.o: src/faster/AudioCurveCalculator.h
|
||||
src/RubberBandStretcher.o: src/faster/HighFrequencyAudioCurve.h
|
||||
src/RubberBandStretcher.o: src/common/SampleFilter.h src/finer/R3Stretcher.h
|
||||
src/RubberBandStretcher.o: src/finer/BinSegmenter.h src/finer/BinClassifier.h
|
||||
src/RubberBandStretcher.o: src/common/MovingMedian.h
|
||||
src/RubberBandStretcher.o: src/common/SampleFilter.h src/common/FixedVector.h
|
||||
src/RubberBandStretcher.o: src/common/SingleThreadRingBuffer.h
|
||||
src/RubberBandStretcher.o: src/common/HistogramFilter.h src/common/mathmisc.h
|
||||
src/RubberBandStretcher.o: src/finer/Guide.h src/finer/Peak.h
|
||||
src/RubberBandStretcher.o: src/finer/PhaseAdvance.h
|
||||
src/RubberBandStretcher.o: src/common/StretchCalculator.h src/common/Log.h
|
||||
src/RubberBandStretcher.o: src/common/Resampler.h src/common/FixedVector.h
|
||||
src/RubberBandStretcher.o: src/common/VectorOpsComplex.h
|
||||
src/faster/AudioCurveCalculator.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/AudioCurveCalculator.o: src/common/sysutils.h
|
||||
src/faster/CompoundAudioCurve.o: src/faster/CompoundAudioCurve.h
|
||||
src/faster/CompoundAudioCurve.o: src/faster/PercussiveAudioCurve.h
|
||||
src/faster/CompoundAudioCurve.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/sysutils.h
|
||||
src/faster/CompoundAudioCurve.o: src/faster/HighFrequencyAudioCurve.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/SampleFilter.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/MovingMedian.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/SampleFilter.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/FixedVector.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/Allocators.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/VectorOps.h src/common/sysutils.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/SingleThreadRingBuffer.h
|
||||
src/faster/HighFrequencyAudioCurve.o: src/faster/HighFrequencyAudioCurve.h
|
||||
src/faster/HighFrequencyAudioCurve.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/HighFrequencyAudioCurve.o: src/common/sysutils.h
|
||||
src/faster/SilentAudioCurve.o: src/faster/SilentAudioCurve.h
|
||||
src/faster/SilentAudioCurve.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/SilentAudioCurve.o: src/common/sysutils.h
|
||||
src/faster/PercussiveAudioCurve.o: src/faster/PercussiveAudioCurve.h
|
||||
src/faster/PercussiveAudioCurve.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/PercussiveAudioCurve.o: src/common/sysutils.h
|
||||
src/faster/PercussiveAudioCurve.o: src/common/Allocators.h
|
||||
src/faster/PercussiveAudioCurve.o: src/common/VectorOps.h
|
||||
src/faster/R2Stretcher.o: src/faster/R2Stretcher.h
|
||||
src/faster/R2Stretcher.o: rubberband/RubberBandStretcher.h
|
||||
src/faster/R2Stretcher.o: src/common/Window.h src/common/sysutils.h
|
||||
src/faster/R2Stretcher.o: src/common/VectorOps.h src/common/Allocators.h
|
||||
src/faster/R2Stretcher.o: src/common/FFT.h src/common/RingBuffer.h
|
||||
src/faster/R2Stretcher.o: src/common/Scavenger.h src/common/Thread.h
|
||||
src/faster/R2Stretcher.o: src/common/Thread.h src/common/Log.h
|
||||
src/faster/R2Stretcher.o: src/common/sysutils.h src/faster/SincWindow.h
|
||||
src/faster/R2Stretcher.o: src/common/VectorOps.h src/common/Allocators.h
|
||||
src/faster/R2Stretcher.o: src/faster/CompoundAudioCurve.h
|
||||
src/faster/R2Stretcher.o: src/faster/PercussiveAudioCurve.h
|
||||
src/faster/R2Stretcher.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/R2Stretcher.o: src/faster/HighFrequencyAudioCurve.h
|
||||
src/faster/R2Stretcher.o: src/common/SampleFilter.h
|
||||
src/faster/R2Stretcher.o: src/faster/SilentAudioCurve.h
|
||||
src/faster/R2Stretcher.o: src/faster/StretcherChannelData.h
|
||||
src/faster/R2Stretcher.o: src/common/StretchCalculator.h src/common/Log.h
|
||||
src/faster/R2Stretcher.o: src/common/Resampler.h src/common/Profiler.h
|
||||
src/faster/StretcherChannelData.o: src/faster/StretcherChannelData.h
|
||||
src/faster/StretcherChannelData.o: src/faster/R2Stretcher.h
|
||||
src/faster/StretcherChannelData.o: rubberband/RubberBandStretcher.h
|
||||
src/faster/StretcherChannelData.o: src/common/Window.h src/common/sysutils.h
|
||||
src/faster/StretcherChannelData.o: src/common/VectorOps.h
|
||||
src/faster/StretcherChannelData.o: src/common/Allocators.h src/common/FFT.h
|
||||
src/faster/StretcherChannelData.o: src/common/RingBuffer.h
|
||||
src/faster/StretcherChannelData.o: src/common/Scavenger.h src/common/Thread.h
|
||||
src/faster/StretcherChannelData.o: src/common/Thread.h src/common/Log.h
|
||||
src/faster/StretcherChannelData.o: src/common/sysutils.h
|
||||
src/faster/StretcherChannelData.o: src/faster/SincWindow.h
|
||||
src/faster/StretcherChannelData.o: src/common/VectorOps.h
|
||||
src/faster/StretcherChannelData.o: src/common/Allocators.h
|
||||
src/faster/StretcherChannelData.o: src/faster/CompoundAudioCurve.h
|
||||
src/faster/StretcherChannelData.o: src/faster/PercussiveAudioCurve.h
|
||||
src/faster/StretcherChannelData.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/StretcherChannelData.o: src/faster/HighFrequencyAudioCurve.h
|
||||
src/faster/StretcherChannelData.o: src/common/SampleFilter.h
|
||||
src/faster/StretcherChannelData.o: src/common/Resampler.h
|
||||
src/faster/StretcherProcess.o: src/faster/R2Stretcher.h
|
||||
src/faster/StretcherProcess.o: rubberband/RubberBandStretcher.h
|
||||
src/faster/StretcherProcess.o: src/common/Window.h src/common/sysutils.h
|
||||
src/faster/StretcherProcess.o: src/common/VectorOps.h src/common/Allocators.h
|
||||
src/faster/StretcherProcess.o: src/common/FFT.h src/common/RingBuffer.h
|
||||
src/faster/StretcherProcess.o: src/common/Scavenger.h src/common/Thread.h
|
||||
src/faster/StretcherProcess.o: src/common/Thread.h src/common/Log.h
|
||||
src/faster/StretcherProcess.o: src/common/sysutils.h src/faster/SincWindow.h
|
||||
src/faster/StretcherProcess.o: src/common/VectorOps.h src/common/Allocators.h
|
||||
src/faster/StretcherProcess.o: src/faster/CompoundAudioCurve.h
|
||||
src/faster/StretcherProcess.o: src/faster/PercussiveAudioCurve.h
|
||||
src/faster/StretcherProcess.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/StretcherProcess.o: src/faster/HighFrequencyAudioCurve.h
|
||||
src/faster/StretcherProcess.o: src/common/SampleFilter.h
|
||||
src/faster/StretcherProcess.o: src/faster/StretcherChannelData.h
|
||||
src/faster/StretcherProcess.o: src/common/StretchCalculator.h
|
||||
src/faster/StretcherProcess.o: src/common/Log.h src/common/Resampler.h
|
||||
src/faster/StretcherProcess.o: src/common/Profiler.h src/common/mathmisc.h
|
||||
src/common/Allocators.o: src/common/Allocators.h src/common/VectorOps.h
|
||||
src/common/Allocators.o: src/common/sysutils.h
|
||||
src/common/BQResampler.o: src/common/BQResampler.h src/common/Allocators.h
|
||||
src/common/BQResampler.o: src/common/VectorOps.h src/common/sysutils.h
|
||||
src/common/FFT.o: src/common/FFT.h src/common/sysutils.h src/common/Thread.h
|
||||
src/common/FFT.o: src/common/Profiler.h src/common/Allocators.h
|
||||
src/common/FFT.o: src/common/VectorOps.h src/common/VectorOpsComplex.h
|
||||
src/common/Log.o: src/common/Log.h
|
||||
src/common/Profiler.o: src/common/Profiler.h src/common/sysutils.h
|
||||
src/common/Profiler.o: src/common/Thread.h
|
||||
src/common/Resampler.o: src/common/Resampler.h src/common/sysutils.h
|
||||
src/common/Resampler.o: src/common/Allocators.h src/common/VectorOps.h
|
||||
src/common/StretchCalculator.o: src/common/StretchCalculator.h
|
||||
src/common/StretchCalculator.o: src/common/Log.h src/common/sysutils.h
|
||||
src/common/sysutils.o: src/common/sysutils.h
|
||||
src/common/Thread.o: src/common/Thread.h
|
||||
src/finer/R3Stretcher.o: src/finer/R3Stretcher.h src/finer/BinSegmenter.h
|
||||
src/finer/R3Stretcher.o: src/finer/BinClassifier.h src/common/Allocators.h
|
||||
src/finer/R3Stretcher.o: src/common/MovingMedian.h src/common/SampleFilter.h
|
||||
src/finer/R3Stretcher.o: src/common/FixedVector.h src/common/Allocators.h
|
||||
src/finer/R3Stretcher.o: src/common/VectorOps.h src/common/sysutils.h
|
||||
src/finer/R3Stretcher.o: src/common/SingleThreadRingBuffer.h
|
||||
src/finer/R3Stretcher.o: src/common/RingBuffer.h src/common/HistogramFilter.h
|
||||
src/finer/R3Stretcher.o: src/common/mathmisc.h src/finer/Guide.h
|
||||
src/finer/R3Stretcher.o: src/common/Log.h src/finer/Peak.h
|
||||
src/finer/R3Stretcher.o: src/finer/PhaseAdvance.h
|
||||
src/finer/R3Stretcher.o: src/common/StretchCalculator.h src/common/Log.h
|
||||
src/finer/R3Stretcher.o: src/common/Resampler.h src/common/FFT.h
|
||||
src/finer/R3Stretcher.o: src/common/FixedVector.h src/common/Window.h
|
||||
src/finer/R3Stretcher.o: src/common/VectorOpsComplex.h
|
||||
src/finer/R3Stretcher.o: rubberband/RubberBandStretcher.h
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
|
||||
CXX := clang++ -stdlib=libc++
|
||||
CXX := clang++ -stdlib=libc++ -std=c++11
|
||||
CC := clang
|
||||
|
||||
OPTFLAGS := -DNDEBUG -ffast-math -O3 -ftree-vectorize
|
||||
|
||||
ARCHFLAGS := -arch arm64 -arch x86_64 -mmacosx-version-min=10.7
|
||||
|
||||
CXXFLAGS := $(ARCHFLAGS) $(OPTFLAGS) -I. -Isrc -Irubberband -I/usr/local/include -DUSE_PTHREADS -DMALLOC_IS_ALIGNED -DHAVE_VDSP -DUSE_SPEEX -DNO_THREAD_CHECKS -DNO_TIMING
|
||||
CXXFLAGS := $(ARCHFLAGS) $(OPTFLAGS) -I. -Isrc -Irubberband -DUSE_BQRESAMPLER -DHAVE_VDSP -DNO_THREAD_CHECKS -DUSE_PTHREADS -DNO_TIMING -DMALLOC_IS_ALIGNED -DNDEBUG
|
||||
|
||||
CFLAGS := $(ARCHFLAGS) $(OPTFLAGS)
|
||||
|
||||
@@ -18,68 +18,34 @@ LIBNAME := librubberband
|
||||
STATIC_TARGET := lib/$(LIBNAME).a
|
||||
|
||||
default: $(STATIC_TARGET)
|
||||
|
||||
all: $(STATIC_TARGET)
|
||||
|
||||
static: $(STATIC_TARGET)
|
||||
|
||||
PUBLIC_INCLUDES := \
|
||||
rubberband/rubberband-c.h \
|
||||
rubberband/RubberBandStretcher.h
|
||||
|
||||
LIBRARY_INCLUDES := \
|
||||
src/StretcherChannelData.h \
|
||||
src/float_cast/float_cast.h \
|
||||
src/StretcherImpl.h \
|
||||
src/StretchCalculator.h \
|
||||
src/base/Profiler.h \
|
||||
src/base/RingBuffer.h \
|
||||
src/base/Scavenger.h \
|
||||
src/dsp/AudioCurveCalculator.h \
|
||||
src/audiocurves/CompoundAudioCurve.h \
|
||||
src/audiocurves/ConstantAudioCurve.h \
|
||||
src/audiocurves/HighFrequencyAudioCurve.h \
|
||||
src/audiocurves/PercussiveAudioCurve.h \
|
||||
src/audiocurves/SilentAudioCurve.h \
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.h \
|
||||
src/dsp/Resampler.h \
|
||||
src/dsp/FFT.h \
|
||||
src/dsp/MovingMedian.h \
|
||||
src/dsp/SincWindow.h \
|
||||
src/dsp/Window.h \
|
||||
src/system/Allocators.h \
|
||||
src/system/Thread.h \
|
||||
src/system/VectorOps.h \
|
||||
src/system/VectorOpsComplex.h \
|
||||
src/system/sysutils.h
|
||||
|
||||
LIBRARY_SOURCES := \
|
||||
src/rubberband-c.cpp \
|
||||
src/RubberBandStretcher.cpp \
|
||||
src/StretcherProcess.cpp \
|
||||
src/StretchCalculator.cpp \
|
||||
src/base/Profiler.cpp \
|
||||
src/dsp/AudioCurveCalculator.cpp \
|
||||
src/audiocurves/CompoundAudioCurve.cpp \
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.cpp \
|
||||
src/audiocurves/HighFrequencyAudioCurve.cpp \
|
||||
src/audiocurves/SilentAudioCurve.cpp \
|
||||
src/audiocurves/ConstantAudioCurve.cpp \
|
||||
src/audiocurves/PercussiveAudioCurve.cpp \
|
||||
src/dsp/Resampler.cpp \
|
||||
src/dsp/FFT.cpp \
|
||||
src/system/Allocators.cpp \
|
||||
src/system/sysutils.cpp \
|
||||
src/system/Thread.cpp \
|
||||
src/system/VectorOpsComplex.cpp \
|
||||
src/StretcherChannelData.cpp \
|
||||
src/StretcherImpl.cpp
|
||||
|
||||
# For Speex resampler -- comment these lines out if not specifying USE_SPEEX
|
||||
LIBRARY_INCLUDES := $(LIBRARY_INCLUDES) \
|
||||
src/speex/speex_resampler.h
|
||||
LIBRARY_SOURCES := $(LIBRARY_SOURCES) \
|
||||
src/speex/resample.c
|
||||
src/faster/AudioCurveCalculator.cpp \
|
||||
src/faster/CompoundAudioCurve.cpp \
|
||||
src/faster/HighFrequencyAudioCurve.cpp \
|
||||
src/faster/SilentAudioCurve.cpp \
|
||||
src/faster/PercussiveAudioCurve.cpp \
|
||||
src/faster/R2Stretcher.cpp \
|
||||
src/faster/StretcherChannelData.cpp \
|
||||
src/faster/StretcherProcess.cpp \
|
||||
src/common/Allocators.cpp \
|
||||
src/common/BQResampler.cpp \
|
||||
src/common/FFT.cpp \
|
||||
src/common/Log.cpp \
|
||||
src/common/Profiler.cpp \
|
||||
src/common/Resampler.cpp \
|
||||
src/common/StretchCalculator.cpp \
|
||||
src/common/sysutils.cpp \
|
||||
src/common/Thread.cpp \
|
||||
src/finer/R3Stretcher.cpp
|
||||
|
||||
LIBRARY_OBJECTS := $(LIBRARY_SOURCES:.cpp=.o)
|
||||
LIBRARY_OBJECTS := $(LIBRARY_OBJECTS:.c=.o)
|
||||
@@ -105,71 +71,138 @@ depend:
|
||||
|
||||
src/rubberband-c.o: rubberband/rubberband-c.h
|
||||
src/rubberband-c.o: rubberband/RubberBandStretcher.h
|
||||
src/RubberBandStretcher.o: src/StretcherImpl.h
|
||||
src/RubberBandStretcher.o: rubberband/RubberBandStretcher.h src/dsp/Window.h
|
||||
src/RubberBandStretcher.o: src/dsp/FFT.h src/base/RingBuffer.h
|
||||
src/RubberBandStretcher.o: src/base/Scavenger.h src/system/Thread.h
|
||||
src/RubberBandStretcher.o: src/system/Thread.h src/system/sysutils.h
|
||||
src/StretcherProcess.o: src/StretcherImpl.h rubberband/RubberBandStretcher.h
|
||||
src/StretcherProcess.o: src/dsp/Window.h src/dsp/FFT.h src/base/RingBuffer.h
|
||||
src/StretcherProcess.o: src/base/Scavenger.h src/system/Thread.h
|
||||
src/StretcherProcess.o: src/system/Thread.h src/system/sysutils.h
|
||||
src/StretcherProcess.o: src/audiocurves/PercussiveAudioCurve.h
|
||||
src/StretcherProcess.o: src/dsp/AudioCurveCalculator.h
|
||||
src/StretcherProcess.o: src/audiocurves/HighFrequencyAudioCurve.h
|
||||
src/StretcherProcess.o: src/audiocurves/ConstantAudioCurve.h src/StretchCalculator.h
|
||||
src/StretcherProcess.o: src/StretcherChannelData.h src/dsp/Resampler.h
|
||||
src/StretcherProcess.o: src/base/Profiler.h src/system/VectorOps.h
|
||||
src/StretcherProcess.o: src/system/sysutils.h
|
||||
src/StretchCalculator.o: src/StretchCalculator.h src/system/sysutils.h
|
||||
src/system/Thread.o: src/system/Thread.h
|
||||
src/base/Profiler.o: src/base/Profiler.h src/system/sysutils.h
|
||||
src/dsp/AudioCurveCalculator.o: src/dsp/AudioCurveCalculator.h
|
||||
src/dsp/AudioCurveCalculator.o: src/system/sysutils.h
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.o: src/audiocurves/SpectralDifferenceAudioCurve.h
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.o: src/dsp/AudioCurveCalculator.h
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.o: src/system/sysutils.h
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.o: src/dsp/Window.h
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.o: src/system/VectorOps.h
|
||||
src/audiocurves/SpectralDifferenceAudioCurve.o: src/system/sysutils.h
|
||||
src/audiocurves/HighFrequencyAudioCurve.o: src/audiocurves/HighFrequencyAudioCurve.h
|
||||
src/audiocurves/HighFrequencyAudioCurve.o: src/dsp/AudioCurveCalculator.h
|
||||
src/audiocurves/HighFrequencyAudioCurve.o: src/system/sysutils.h
|
||||
src/audiocurves/SilentAudioCurve.o: src/audiocurves/SilentAudioCurve.h
|
||||
src/audiocurves/SilentAudioCurve.o: src/dsp/AudioCurveCalculator.h
|
||||
src/audiocurves/SilentAudioCurve.o: src/system/sysutils.h
|
||||
src/audiocurves/ConstantAudioCurve.o: src/audiocurves/ConstantAudioCurve.h
|
||||
src/audiocurves/ConstantAudioCurve.o: src/dsp/AudioCurveCalculator.h
|
||||
src/audiocurves/ConstantAudioCurve.o: src/system/sysutils.h
|
||||
src/audiocurves/PercussiveAudioCurve.o: src/audiocurves/PercussiveAudioCurve.h
|
||||
src/audiocurves/PercussiveAudioCurve.o: src/dsp/AudioCurveCalculator.h
|
||||
src/audiocurves/PercussiveAudioCurve.o: src/system/sysutils.h src/system/VectorOps.h
|
||||
src/audiocurves/PercussiveAudioCurve.o: src/system/sysutils.h
|
||||
src/dsp/Resampler.o: src/dsp/Resampler.h src/system/sysutils.h
|
||||
src/dsp/Resampler.o: src/base/Profiler.h
|
||||
src/dsp/FFT.o: src/dsp/FFT.h src/system/sysutils.h src/system/Thread.h
|
||||
src/dsp/FFT.o: src/base/Profiler.h src/system/VectorOps.h
|
||||
src/dsp/FFT.o: src/system/sysutils.h
|
||||
src/system/Allocators.o: src/system/Allocators.h src/system/VectorOps.h
|
||||
src/system/Allocators.o: src/system/sysutils.h
|
||||
src/system/sysutils.o: src/system/sysutils.h
|
||||
src/StretcherChannelData.o: src/StretcherChannelData.h src/StretcherImpl.h
|
||||
src/StretcherChannelData.o: rubberband/RubberBandStretcher.h src/dsp/Window.h
|
||||
src/StretcherChannelData.o: src/dsp/FFT.h src/base/RingBuffer.h
|
||||
src/StretcherChannelData.o: src/base/Scavenger.h src/system/Thread.h
|
||||
src/StretcherChannelData.o: src/system/Thread.h src/system/sysutils.h
|
||||
src/StretcherChannelData.o: src/dsp/Resampler.h src/system/Allocators.h
|
||||
src/StretcherChannelData.o: src/system/VectorOps.h src/system/sysutils.h
|
||||
src/StretcherImpl.o: src/StretcherImpl.h rubberband/RubberBandStretcher.h
|
||||
src/StretcherImpl.o: src/dsp/Window.h src/dsp/FFT.h src/base/RingBuffer.h
|
||||
src/StretcherImpl.o: src/base/Scavenger.h src/system/Thread.h src/system/Thread.h
|
||||
src/StretcherImpl.o: src/system/sysutils.h src/audiocurves/PercussiveAudioCurve.h
|
||||
src/StretcherImpl.o: src/dsp/AudioCurveCalculator.h
|
||||
src/StretcherImpl.o: src/audiocurves/HighFrequencyAudioCurve.h
|
||||
src/StretcherImpl.o: src/audiocurves/SpectralDifferenceAudioCurve.h src/dsp/Window.h
|
||||
src/StretcherImpl.o: src/system/VectorOps.h src/system/sysutils.h
|
||||
src/StretcherImpl.o: src/audiocurves/SilentAudioCurve.h src/audiocurves/ConstantAudioCurve.h
|
||||
src/StretcherImpl.o: src/dsp/Resampler.h src/StretchCalculator.h
|
||||
src/StretcherImpl.o: src/StretcherChannelData.h src/base/Profiler.h
|
||||
main/main.o: rubberband/RubberBandStretcher.h src/system/sysutils.h
|
||||
main/main.o: src/base/Profiler.h
|
||||
src/RubberBandStretcher.o: src/faster/R2Stretcher.h
|
||||
src/RubberBandStretcher.o: rubberband/RubberBandStretcher.h
|
||||
src/RubberBandStretcher.o: src/common/Window.h src/common/sysutils.h
|
||||
src/RubberBandStretcher.o: src/common/VectorOps.h src/common/Allocators.h
|
||||
src/RubberBandStretcher.o: src/common/FFT.h src/common/RingBuffer.h
|
||||
src/RubberBandStretcher.o: src/common/Scavenger.h src/common/Thread.h
|
||||
src/RubberBandStretcher.o: src/common/Thread.h src/common/Log.h
|
||||
src/RubberBandStretcher.o: src/common/sysutils.h src/faster/SincWindow.h
|
||||
src/RubberBandStretcher.o: src/common/VectorOps.h src/common/Allocators.h
|
||||
src/RubberBandStretcher.o: src/faster/CompoundAudioCurve.h
|
||||
src/RubberBandStretcher.o: src/faster/PercussiveAudioCurve.h
|
||||
src/RubberBandStretcher.o: src/faster/AudioCurveCalculator.h
|
||||
src/RubberBandStretcher.o: src/faster/HighFrequencyAudioCurve.h
|
||||
src/RubberBandStretcher.o: src/common/SampleFilter.h src/finer/R3Stretcher.h
|
||||
src/RubberBandStretcher.o: src/finer/BinSegmenter.h src/finer/BinClassifier.h
|
||||
src/RubberBandStretcher.o: src/common/MovingMedian.h
|
||||
src/RubberBandStretcher.o: src/common/SampleFilter.h src/common/FixedVector.h
|
||||
src/RubberBandStretcher.o: src/common/SingleThreadRingBuffer.h
|
||||
src/RubberBandStretcher.o: src/common/HistogramFilter.h src/common/mathmisc.h
|
||||
src/RubberBandStretcher.o: src/finer/Guide.h src/finer/Peak.h
|
||||
src/RubberBandStretcher.o: src/finer/PhaseAdvance.h
|
||||
src/RubberBandStretcher.o: src/common/StretchCalculator.h src/common/Log.h
|
||||
src/RubberBandStretcher.o: src/common/Resampler.h src/common/FixedVector.h
|
||||
src/RubberBandStretcher.o: src/common/VectorOpsComplex.h
|
||||
src/faster/AudioCurveCalculator.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/AudioCurveCalculator.o: src/common/sysutils.h
|
||||
src/faster/CompoundAudioCurve.o: src/faster/CompoundAudioCurve.h
|
||||
src/faster/CompoundAudioCurve.o: src/faster/PercussiveAudioCurve.h
|
||||
src/faster/CompoundAudioCurve.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/sysutils.h
|
||||
src/faster/CompoundAudioCurve.o: src/faster/HighFrequencyAudioCurve.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/SampleFilter.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/MovingMedian.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/SampleFilter.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/FixedVector.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/Allocators.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/VectorOps.h src/common/sysutils.h
|
||||
src/faster/CompoundAudioCurve.o: src/common/SingleThreadRingBuffer.h
|
||||
src/faster/HighFrequencyAudioCurve.o: src/faster/HighFrequencyAudioCurve.h
|
||||
src/faster/HighFrequencyAudioCurve.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/HighFrequencyAudioCurve.o: src/common/sysutils.h
|
||||
src/faster/SilentAudioCurve.o: src/faster/SilentAudioCurve.h
|
||||
src/faster/SilentAudioCurve.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/SilentAudioCurve.o: src/common/sysutils.h
|
||||
src/faster/PercussiveAudioCurve.o: src/faster/PercussiveAudioCurve.h
|
||||
src/faster/PercussiveAudioCurve.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/PercussiveAudioCurve.o: src/common/sysutils.h
|
||||
src/faster/PercussiveAudioCurve.o: src/common/Allocators.h
|
||||
src/faster/PercussiveAudioCurve.o: src/common/VectorOps.h
|
||||
src/faster/R2Stretcher.o: src/faster/R2Stretcher.h
|
||||
src/faster/R2Stretcher.o: rubberband/RubberBandStretcher.h
|
||||
src/faster/R2Stretcher.o: src/common/Window.h src/common/sysutils.h
|
||||
src/faster/R2Stretcher.o: src/common/VectorOps.h src/common/Allocators.h
|
||||
src/faster/R2Stretcher.o: src/common/FFT.h src/common/RingBuffer.h
|
||||
src/faster/R2Stretcher.o: src/common/Scavenger.h src/common/Thread.h
|
||||
src/faster/R2Stretcher.o: src/common/Thread.h src/common/Log.h
|
||||
src/faster/R2Stretcher.o: src/common/sysutils.h src/faster/SincWindow.h
|
||||
src/faster/R2Stretcher.o: src/common/VectorOps.h src/common/Allocators.h
|
||||
src/faster/R2Stretcher.o: src/faster/CompoundAudioCurve.h
|
||||
src/faster/R2Stretcher.o: src/faster/PercussiveAudioCurve.h
|
||||
src/faster/R2Stretcher.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/R2Stretcher.o: src/faster/HighFrequencyAudioCurve.h
|
||||
src/faster/R2Stretcher.o: src/common/SampleFilter.h
|
||||
src/faster/R2Stretcher.o: src/faster/SilentAudioCurve.h
|
||||
src/faster/R2Stretcher.o: src/faster/StretcherChannelData.h
|
||||
src/faster/R2Stretcher.o: src/common/StretchCalculator.h src/common/Log.h
|
||||
src/faster/R2Stretcher.o: src/common/Resampler.h src/common/Profiler.h
|
||||
src/faster/StretcherChannelData.o: src/faster/StretcherChannelData.h
|
||||
src/faster/StretcherChannelData.o: src/faster/R2Stretcher.h
|
||||
src/faster/StretcherChannelData.o: rubberband/RubberBandStretcher.h
|
||||
src/faster/StretcherChannelData.o: src/common/Window.h src/common/sysutils.h
|
||||
src/faster/StretcherChannelData.o: src/common/VectorOps.h
|
||||
src/faster/StretcherChannelData.o: src/common/Allocators.h src/common/FFT.h
|
||||
src/faster/StretcherChannelData.o: src/common/RingBuffer.h
|
||||
src/faster/StretcherChannelData.o: src/common/Scavenger.h src/common/Thread.h
|
||||
src/faster/StretcherChannelData.o: src/common/Thread.h src/common/Log.h
|
||||
src/faster/StretcherChannelData.o: src/common/sysutils.h
|
||||
src/faster/StretcherChannelData.o: src/faster/SincWindow.h
|
||||
src/faster/StretcherChannelData.o: src/common/VectorOps.h
|
||||
src/faster/StretcherChannelData.o: src/common/Allocators.h
|
||||
src/faster/StretcherChannelData.o: src/faster/CompoundAudioCurve.h
|
||||
src/faster/StretcherChannelData.o: src/faster/PercussiveAudioCurve.h
|
||||
src/faster/StretcherChannelData.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/StretcherChannelData.o: src/faster/HighFrequencyAudioCurve.h
|
||||
src/faster/StretcherChannelData.o: src/common/SampleFilter.h
|
||||
src/faster/StretcherChannelData.o: src/common/Resampler.h
|
||||
src/faster/StretcherProcess.o: src/faster/R2Stretcher.h
|
||||
src/faster/StretcherProcess.o: rubberband/RubberBandStretcher.h
|
||||
src/faster/StretcherProcess.o: src/common/Window.h src/common/sysutils.h
|
||||
src/faster/StretcherProcess.o: src/common/VectorOps.h src/common/Allocators.h
|
||||
src/faster/StretcherProcess.o: src/common/FFT.h src/common/RingBuffer.h
|
||||
src/faster/StretcherProcess.o: src/common/Scavenger.h src/common/Thread.h
|
||||
src/faster/StretcherProcess.o: src/common/Thread.h src/common/Log.h
|
||||
src/faster/StretcherProcess.o: src/common/sysutils.h src/faster/SincWindow.h
|
||||
src/faster/StretcherProcess.o: src/common/VectorOps.h src/common/Allocators.h
|
||||
src/faster/StretcherProcess.o: src/faster/CompoundAudioCurve.h
|
||||
src/faster/StretcherProcess.o: src/faster/PercussiveAudioCurve.h
|
||||
src/faster/StretcherProcess.o: src/faster/AudioCurveCalculator.h
|
||||
src/faster/StretcherProcess.o: src/faster/HighFrequencyAudioCurve.h
|
||||
src/faster/StretcherProcess.o: src/common/SampleFilter.h
|
||||
src/faster/StretcherProcess.o: src/faster/StretcherChannelData.h
|
||||
src/faster/StretcherProcess.o: src/common/StretchCalculator.h
|
||||
src/faster/StretcherProcess.o: src/common/Log.h src/common/Resampler.h
|
||||
src/faster/StretcherProcess.o: src/common/Profiler.h src/common/mathmisc.h
|
||||
src/common/Allocators.o: src/common/Allocators.h src/common/VectorOps.h
|
||||
src/common/Allocators.o: src/common/sysutils.h
|
||||
src/common/BQResampler.o: src/common/BQResampler.h src/common/Allocators.h
|
||||
src/common/BQResampler.o: src/common/VectorOps.h src/common/sysutils.h
|
||||
src/common/FFT.o: src/common/FFT.h src/common/sysutils.h src/common/Thread.h
|
||||
src/common/FFT.o: src/common/Profiler.h src/common/Allocators.h
|
||||
src/common/FFT.o: src/common/VectorOps.h src/common/VectorOpsComplex.h
|
||||
src/common/Log.o: src/common/Log.h
|
||||
src/common/Profiler.o: src/common/Profiler.h src/common/sysutils.h
|
||||
src/common/Profiler.o: src/common/Thread.h
|
||||
src/common/Resampler.o: src/common/Resampler.h src/common/sysutils.h
|
||||
src/common/Resampler.o: src/common/Allocators.h src/common/VectorOps.h
|
||||
src/common/StretchCalculator.o: src/common/StretchCalculator.h
|
||||
src/common/StretchCalculator.o: src/common/Log.h src/common/sysutils.h
|
||||
src/common/sysutils.o: src/common/sysutils.h
|
||||
src/common/Thread.o: src/common/Thread.h
|
||||
src/finer/R3Stretcher.o: src/finer/R3Stretcher.h src/finer/BinSegmenter.h
|
||||
src/finer/R3Stretcher.o: src/finer/BinClassifier.h src/common/Allocators.h
|
||||
src/finer/R3Stretcher.o: src/common/MovingMedian.h src/common/SampleFilter.h
|
||||
src/finer/R3Stretcher.o: src/common/FixedVector.h src/common/Allocators.h
|
||||
src/finer/R3Stretcher.o: src/common/VectorOps.h src/common/sysutils.h
|
||||
src/finer/R3Stretcher.o: src/common/SingleThreadRingBuffer.h
|
||||
src/finer/R3Stretcher.o: src/common/RingBuffer.h src/common/HistogramFilter.h
|
||||
src/finer/R3Stretcher.o: src/common/mathmisc.h src/finer/Guide.h
|
||||
src/finer/R3Stretcher.o: src/common/Log.h src/finer/Peak.h
|
||||
src/finer/R3Stretcher.o: src/finer/PhaseAdvance.h
|
||||
src/finer/R3Stretcher.o: src/common/StretchCalculator.h src/common/Log.h
|
||||
src/finer/R3Stretcher.o: src/common/Resampler.h src/common/FFT.h
|
||||
src/finer/R3Stretcher.o: src/common/FixedVector.h src/common/Window.h
|
||||
src/finer/R3Stretcher.o: src/common/VectorOpsComplex.h
|
||||
src/finer/R3Stretcher.o: rubberband/RubberBandStretcher.h
|
||||
|
||||
@@ -5,17 +5,17 @@ if [ ! -d /Applications ]; then
|
||||
# Assumed to be Linux
|
||||
|
||||
echo " *** Building static library using Linux-specific Makefile"
|
||||
# make -f otherbuilds/Makefile.linux clean
|
||||
make -f otherbuilds/Makefile.linux clean
|
||||
make -f otherbuilds/Makefile.linux
|
||||
|
||||
echo " *** Linking against static library"
|
||||
g++ main/main.cpp lib/librubberband.a -I. -Isrc -o test -lsndfile -lsamplerate -lpthread
|
||||
g++ -std=c++11 main/main.cpp lib/librubberband.a -I. -Isrc -o test -lsndfile -lpthread
|
||||
|
||||
echo " *** Running build from Linux-specific Makefile"
|
||||
./test -V
|
||||
|
||||
echo " *** Building with single-file source"
|
||||
g++ main/main.cpp single/RubberBandSingle.cpp -o test_single -lsndfile
|
||||
g++ -O3 -std=c++11 main/main.cpp single/RubberBandSingle.cpp -o test_single -lsndfile
|
||||
|
||||
echo " *** Running build from single-file source"
|
||||
./test_single -V
|
||||
@@ -29,13 +29,13 @@ else
|
||||
make -f otherbuilds/Makefile.macos
|
||||
|
||||
echo " *** Linking against static library"
|
||||
c++ main/main.cpp lib/librubberband.a -I. -Isrc -o test -lsndfile -lsamplerate -framework Accelerate
|
||||
c++ -std=c++11 main/main.cpp lib/librubberband.a -I. -Isrc -o test -lsndfile -framework Accelerate
|
||||
|
||||
echo " *** Running build from macOS-specific Makefile"
|
||||
./test -V
|
||||
|
||||
echo " *** Building with single-file source"
|
||||
c++ main/main.cpp single/RubberBandSingle.cpp -o test_single -lsndfile -framework Accelerate
|
||||
c++ -O3 -std=c++11 main/main.cpp single/RubberBandSingle.cpp -o test_single -lsndfile -framework Accelerate
|
||||
|
||||
echo " *** Running build from single-file source"
|
||||
./test_single -V
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
set -eu
|
||||
version=$(grep '^ *version:' meson.build | head -1 | sed "s/^.*'\([0-9][0-9.]*\)'.*$/\1/")
|
||||
version=$(meson introspect --projectinfo meson.build -i | grep '"version"' | sed -e 's/^.*: "//' -e 's/".*$//')
|
||||
check() {
|
||||
text="$1"
|
||||
echo -n "$text [yN] "
|
||||
@@ -45,6 +45,15 @@ echo "The CHANGELOG should start with a list of changes for this release."
|
||||
head -3 CHANGELOG
|
||||
check "The first three lines of the CHANGELOG are above. Are they correct?"
|
||||
|
||||
hgid=$(hg id | awk '{ print $1; }')
|
||||
case "$hgid" in
|
||||
*+) echo "ERROR: Working copy has been modified, please review and commit"
|
||||
echo "as appropriate before continuing"
|
||||
exit 1
|
||||
;;
|
||||
*);;
|
||||
esac
|
||||
|
||||
echo
|
||||
check "All version checks passed. Continue?"
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ if errorlevel 1 exit /b %errorlevel%
|
||||
|
||||
cd build
|
||||
ren rubberband-program.exe rubberband.exe
|
||||
ren rubberband-program-r3.exe rubberband-r3.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%
|
||||
@@ -43,6 +44,7 @@ set DIR=rubberband-%VERSION%-gpl-executable-windows
|
||||
del /q /s %DIR%
|
||||
mkdir %DIR%
|
||||
copy build\rubberband.exe %DIR%
|
||||
copy build\rubberband-r3.exe %DIR%
|
||||
copy "c:\Program Files\libsndfile\bin\sndfile.dll" %DIR%
|
||||
copy COPYING %DIR%\COPYING.txt
|
||||
copy README.md %DIR%\README.txt
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..;..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>__MSVC__;WIN32;_DEBUG;_LIB;NOMINMAX;_USE_MATH_DEFINES;USE_BUILTIN_FFT;USE_SPEEX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>__MSVC__;WIN32;_DEBUG;_LIB;NOMINMAX;_USE_MATH_DEFINES;USE_BUILTIN_FFT;USE_BQRESAMPLER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
@@ -91,7 +91,7 @@
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..;..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>__MSVC__;WIN32;_DEBUG;_LIB;NOMINMAX;_USE_MATH_DEFINES;USE_BUILTIN_FFT;USE_SPEEX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>__MSVC__;WIN32;_DEBUG;_LIB;NOMINMAX;_USE_MATH_DEFINES;USE_BUILTIN_FFT;USE_BQRESAMPLER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
@@ -109,7 +109,7 @@
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<AdditionalIncludeDirectories>..;..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>__MSVC__;WIN32;NDEBUG;_LIB;NOMINMAX;_USE_MATH_DEFINES;USE_BUILTIN_FFT;NO_TIMING;USE_SPEEX;NO_THREAD_CHECKS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>__MSVC__;WIN32;NDEBUG;_LIB;NOMINMAX;_USE_MATH_DEFINES;USE_BUILTIN_FFT;NO_TIMING;USE_BQRESAMPLER;NO_THREAD_CHECKS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
|
||||
@@ -127,7 +127,7 @@
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<AdditionalIncludeDirectories>..;..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>__MSVC__;WIN32;NDEBUG;_LIB;NOMINMAX;_USE_MATH_DEFINES;USE_BUILTIN_FFT;NO_TIMING;USE_SPEEX;NO_THREAD_CHECKS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>__MSVC__;WIN32;NDEBUG;_LIB;NOMINMAX;_USE_MATH_DEFINES;USE_BUILTIN_FFT;NO_TIMING;USE_BQRESAMPLER;NO_THREAD_CHECKS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
|
||||
@@ -139,55 +139,26 @@
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\rubberband\rubberband-c.h" />
|
||||
<ClInclude Include="..\rubberband\RubberBandStretcher.h" />
|
||||
<ClInclude Include="..\src\audiocurves\CompoundAudioCurve.h" />
|
||||
<ClInclude Include="..\src\audiocurves\ConstantAudioCurve.h" />
|
||||
<ClInclude Include="..\src\audiocurves\HighFrequencyAudioCurve.h" />
|
||||
<ClInclude Include="..\src\audiocurves\PercussiveAudioCurve.h" />
|
||||
<ClInclude Include="..\src\audiocurves\SilentAudioCurve.h" />
|
||||
<ClInclude Include="..\src\audiocurves\SpectralDifferenceAudioCurve.h" />
|
||||
<ClInclude Include="..\src\base\Profiler.h" />
|
||||
<ClInclude Include="..\src\base\RingBuffer.h" />
|
||||
<ClInclude Include="..\src\base\Scavenger.h" />
|
||||
<ClInclude Include="..\src\dsp\AudioCurveCalculator.h" />
|
||||
<ClInclude Include="..\src\dsp\FFT.h" />
|
||||
<ClInclude Include="..\src\dsp\MovingMedian.h" />
|
||||
<ClInclude Include="..\src\dsp\Resampler.h" />
|
||||
<ClInclude Include="..\src\dsp\SampleFilter.h" />
|
||||
<ClInclude Include="..\src\dsp\SincWindow.h" />
|
||||
<ClInclude Include="..\src\dsp\Window.h" />
|
||||
<ClInclude Include="..\src\float_cast\float_cast.h" />
|
||||
<ClInclude Include="..\src\speex\speex_resampler.h" />
|
||||
<ClInclude Include="..\src\StretchCalculator.h" />
|
||||
<ClInclude Include="..\src\StretcherChannelData.h" />
|
||||
<ClInclude Include="..\src\StretcherImpl.h" />
|
||||
<ClInclude Include="..\src\system\Allocators.h" />
|
||||
<ClInclude Include="..\src\system\sysutils.h" />
|
||||
<ClInclude Include="..\src\system\Thread.h" />
|
||||
<ClInclude Include="..\src\system\VectorOps.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\src\audiocurves\CompoundAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\audiocurves\ConstantAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\audiocurves\HighFrequencyAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\audiocurves\PercussiveAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\audiocurves\SilentAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\audiocurves\SpectralDifferenceAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\base\Profiler.cpp" />
|
||||
<ClCompile Include="..\src\dsp\AudioCurveCalculator.cpp" />
|
||||
<ClCompile Include="..\src\dsp\FFT.cpp" />
|
||||
<ClCompile Include="..\src\dsp\Resampler.cpp" />
|
||||
<ClCompile Include="..\src\rubberband-c.cpp" />
|
||||
<ClCompile Include="..\src\RubberBandStretcher.cpp" />
|
||||
<ClCompile Include="..\src\speex\resample.c" />
|
||||
<ClCompile Include="..\src\StretchCalculator.cpp" />
|
||||
<ClCompile Include="..\src\StretcherChannelData.cpp" />
|
||||
<ClCompile Include="..\src\StretcherImpl.cpp" />
|
||||
<ClCompile Include="..\src\StretcherProcess.cpp" />
|
||||
<ClCompile Include="..\src\system\Allocators.cpp" />
|
||||
<ClCompile Include="..\src\system\sysutils.cpp" />
|
||||
<ClCompile Include="..\src\system\Thread.cpp" />
|
||||
<ClCompile Include="..\src\faster\AudioCurveCalculator.cpp" />
|
||||
<ClCompile Include="..\src\faster\CompoundAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\faster\HighFrequencyAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\faster\SilentAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\faster\PercussiveAudioCurve.cpp" />
|
||||
<ClCompile Include="..\src\faster\StretcherChannelData.cpp" />
|
||||
<ClCompile Include="..\src\faster\R2Stretcher.cpp" />
|
||||
<ClCompile Include="..\src\faster\StretcherProcess.cpp" />
|
||||
<ClCompile Include="..\src\common\BQResampler.cpp" />
|
||||
<ClCompile Include="..\src\common\Profiler.cpp" />
|
||||
<ClCompile Include="..\src\common\Resampler.cpp" />
|
||||
<ClCompile Include="..\src\common\FFT.cpp" />
|
||||
<ClCompile Include="..\src\common\Log.cpp" />
|
||||
<ClCompile Include="..\src\common\Allocators.cpp" />
|
||||
<ClCompile Include="..\src\common\StretchCalculator.cpp" />
|
||||
<ClCompile Include="..\src\common\sysutils.cpp" />
|
||||
<ClCompile Include="..\src\common\Thread.cpp" />
|
||||
<ClCompile Include="..\src\finer\R3Stretcher.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
#ifndef RUBBERBAND_STRETCHER_H
|
||||
#define RUBBERBAND_STRETCHER_H
|
||||
|
||||
#define RUBBERBAND_VERSION "2.0.2"
|
||||
#define RUBBERBAND_VERSION "3.0.0"
|
||||
#define RUBBERBAND_API_MAJOR_VERSION 2
|
||||
#define RUBBERBAND_API_MINOR_VERSION 6
|
||||
#define RUBBERBAND_API_MINOR_VERSION 7
|
||||
|
||||
#undef RUBBERBAND_DLLEXPORT
|
||||
#ifdef _MSC_VER
|
||||
@@ -37,51 +37,89 @@
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <cstddef>
|
||||
|
||||
/**
|
||||
* @mainpage RubberBand
|
||||
*
|
||||
* 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
|
||||
* in separate threads concurrently. However, for any single instance
|
||||
* of RubberBandStretcher, you may not call process() more than once
|
||||
* concurrently, and you may not change the time or pitch ratio while
|
||||
* a process() call is being executed (if the stretcher was created in
|
||||
* "real-time mode"; in "offline mode" you can't change the ratios
|
||||
* during use anyway).
|
||||
*
|
||||
* So you can run process() in its own thread if you like, but if you
|
||||
* want to change ratios dynamically from a different thread, you will
|
||||
* need some form of mutex in your code. Changing the time or pitch
|
||||
* ratio is real-time safe except in extreme circumstances, so for
|
||||
* most applications that may change these dynamically it probably
|
||||
* makes most sense to do so from the same thread as calls process(),
|
||||
* even if that is a real-time thread.
|
||||
*/
|
||||
|
||||
namespace RubberBand
|
||||
{
|
||||
|
||||
/**
|
||||
* @mainpage RubberBand
|
||||
*
|
||||
* ### Summary
|
||||
*
|
||||
* The Rubber Band Library API is contained in the single class
|
||||
* RubberBand::RubberBandStretcher.
|
||||
*
|
||||
* The Rubber Band stretcher supports two processing modes, offline
|
||||
* and real-time, and two processing "engines", known as the R2 or
|
||||
* Faster engine and the R3 or Finer engine. The choices of processing
|
||||
* mode and engine are fixed on construction: see
|
||||
* RubberBandStretcher::RubberBandStretcher. The two engines work
|
||||
* identically in API terms, and both of them support both offline and
|
||||
* real-time modes as described below.
|
||||
*
|
||||
* ### Offline mode
|
||||
*
|
||||
* In offline mode, you must provide the audio block-by-block in
|
||||
* two passes. In the first pass, call RubberBandStretcher::study() on
|
||||
* each block; in the second pass, call RubberBandStretcher::process()
|
||||
* on each block and receive the output via
|
||||
* RubberBandStretcher::retrieve().
|
||||
*
|
||||
* In offline mode, the time and pitch ratios are fixed as soon as the
|
||||
* study pass has begun and cannot be changed afterwards. (But see
|
||||
* RubberBandStretcher::setKeyFrameMap() for a way to do pre-planned
|
||||
* variable time stretching in offline mode.) Offline mode also
|
||||
* performs latency compensation so that the stretched result has an
|
||||
* exact start and duration.
|
||||
*
|
||||
* ### Real-time mode
|
||||
*
|
||||
* In \b real-time mode, there is no study pass, just a single
|
||||
* streaming pass in which the audio is passed to
|
||||
* RubberBandStretcher::process() and output received via
|
||||
* RubberBandStretcher::retrieve().
|
||||
*
|
||||
* In real-time mode you can change the time and pitch ratios at any
|
||||
* time.
|
||||
*
|
||||
* You may need to perform latency compensation in real-time mode; see
|
||||
* RubberBandStretcher::getLatency() for details.
|
||||
*
|
||||
* Rubber Band Library is RT-safe when used in real-time mode with
|
||||
* "normal" processing parameters. That is, it performs no allocation,
|
||||
* locking, or blocking operations after initialisation during normal
|
||||
* use, even when the time and pitch ratios change. There are certain
|
||||
* exceptions that include error states and extremely rapid changes
|
||||
* between extreme ratios, as well as the case in which more frames
|
||||
* are passed to RubberBandStretcher::process() than the values
|
||||
* returned by RubberBandStretcher::getSamplesRequired() or set using
|
||||
* RubberBandStretcher::setMaxProcessSize(), when buffer reallocation
|
||||
* may occur. See the latter function's documentation for
|
||||
* details. Note that offline mode is never RT-safe.
|
||||
*
|
||||
* ### Thread safety
|
||||
*
|
||||
* Multiple instances of RubberBandStretcher may be created and used
|
||||
* in separate threads concurrently. However, for any single instance
|
||||
* of RubberBandStretcher, you may not call
|
||||
* RubberBandStretcher::process() more than once concurrently, and you
|
||||
* may not change the time or pitch ratio while a
|
||||
* RubberBandStretcher::process() call is being executed (if the
|
||||
* stretcher was created in "real-time mode"; in "offline mode" you
|
||||
* can't change the ratios during use anyway).
|
||||
*
|
||||
* So you can run RubberBandStretcher::process() in its own thread if
|
||||
* you like, but if you want to change ratios dynamically from a
|
||||
* different thread, you will need some form of mutex in your code.
|
||||
* Changing the time or pitch ratio is real-time safe except in
|
||||
* extreme circumstances, so for most applications that may change
|
||||
* these dynamically it probably makes most sense to do so from the
|
||||
* same thread as calls RubberBandStretcher::process(), even if that
|
||||
* is a real-time thread.
|
||||
*/
|
||||
class RUBBERBAND_DLLEXPORT
|
||||
RubberBandStretcher
|
||||
{
|
||||
@@ -109,33 +147,43 @@ public:
|
||||
* non-real-time operation on seekable files: Offline; real-time
|
||||
* or streaming operation: RealTime.
|
||||
*
|
||||
* 2. Flags prefixed \c OptionStretch control the profile used for
|
||||
* variable timestretching. Rubber Band always adjusts the
|
||||
* stretch profile to minimise stretching of busy broadband
|
||||
* transient sounds, but the degree to which it does so is
|
||||
* adjustable. These options may not be changed after
|
||||
* construction.
|
||||
* 2. Flags prefixed \c OptionEngine select the core Rubber Band
|
||||
* processing engine to be used. These options may not be changed
|
||||
* after construction.
|
||||
*
|
||||
* \li \c OptionStretchElastic - Only meaningful in offline
|
||||
* mode, and the default in that mode. The audio will be
|
||||
* stretched at a variable rate, aimed at preserving the quality
|
||||
* of transient sounds as much as possible. The timings of low
|
||||
* activity regions between transients may be less exact than
|
||||
* when the precise flag is set.
|
||||
* \li \c OptionEngineFaster - Use the Rubber Band Library R2
|
||||
* (Faster) engine. This is the engine implemented in Rubber
|
||||
* Band Library v1.x and v2.x, and it remains the default in
|
||||
* newer versions. It uses substantially less CPU than the R3
|
||||
* engine and there are still many situations in which it is
|
||||
* likely to be the more appropriate choice.
|
||||
*
|
||||
* \li \c OptionStretchPrecise - Although still using a variable
|
||||
* stretch rate, the audio will be stretched so as to maintain
|
||||
* as close as possible to a linear stretch ratio throughout.
|
||||
* Timing may be better than when using \c OptionStretchElastic, at
|
||||
* slight cost to the sound quality of transients. This setting
|
||||
* is always used when running in real-time mode.
|
||||
* \li \c OptionEngineFiner - Use the Rubber Band Library R3
|
||||
* (Finer) engine. This engine was introduced in Rubber Band
|
||||
* Library v3.0. It produces higher-quality results than the R2
|
||||
* engine for most material, especially complex mixes, vocals
|
||||
* and other sounds that have soft onsets and smooth pitch
|
||||
* changes, and music with substantial bass content. However, it
|
||||
* uses much more CPU power than the R2 engine.
|
||||
*
|
||||
* Important note: Consider calling getEngineVersion() after
|
||||
* construction to make sure the engine you requested is
|
||||
* active. That's not because engine selection can fail, but
|
||||
* because Rubber Band Library ignores any unknown options
|
||||
* supplied on construction - so a program that requests the R3
|
||||
* engine but ends up linked against an older version of the
|
||||
* library (prior to v3.0) will silently use the R2 engine
|
||||
* instead. Calling the v3.0 function getEngineVersion() will
|
||||
* ensure a link failure in this situation instead, and supply a
|
||||
* reassuring run-time check.
|
||||
*
|
||||
* 3. Flags prefixed \c OptionTransients control the component
|
||||
* frequency phase-reset mechanism that may be used at transient
|
||||
* points to provide clarity and realism to percussion and other
|
||||
* significant transient sounds. These options may be changed
|
||||
* after construction when running in real-time mode, but not when
|
||||
* running in offline mode.
|
||||
* frequency phase-reset mechanism in the R2 engine, that may be
|
||||
* used at transient points to provide clarity and realism to
|
||||
* percussion and other significant transient sounds. These
|
||||
* options have no effect when using the R3 engine. These options
|
||||
* may be changed after construction when running in real-time
|
||||
* mode, but not when running in offline mode.
|
||||
*
|
||||
* \li \c OptionTransientsCrisp - Reset component phases at the
|
||||
* peak of each transient (the start of a significant note or
|
||||
@@ -160,9 +208,10 @@ public:
|
||||
* transients flags.
|
||||
*
|
||||
* 4. Flags prefixed \c OptionDetector control the type of
|
||||
* transient detector used. These options may be changed
|
||||
* after construction when running in real-time mode, but not when
|
||||
* running in offline mode.
|
||||
* transient detector used in the R2 engine. These options have
|
||||
* no effect when using the R3 engine. These options may be
|
||||
* changed after construction when running in real-time mode, but
|
||||
* not when running in offline mode.
|
||||
*
|
||||
* \li \c OptionDetectorCompound - Use a general-purpose
|
||||
* transient detector which is likely to be good for most
|
||||
@@ -178,9 +227,10 @@ public:
|
||||
* piano music).
|
||||
*
|
||||
* 5. Flags prefixed \c OptionPhase control the adjustment of
|
||||
* component frequency phases from one analysis window to the next
|
||||
* during non-transient segments. These options may be changed at
|
||||
* any time.
|
||||
* component frequency phases in the R2 engine from one analysis
|
||||
* window to the next during non-transient segments. These
|
||||
* options have no effect when using the R3 engine. These options
|
||||
* may be changed at any time.
|
||||
*
|
||||
* \li \c OptionPhaseLaminar - Adjust phases when stretching in
|
||||
* such a way as to try to retain the continuity of phase
|
||||
@@ -197,11 +247,13 @@ public:
|
||||
* construction.
|
||||
*
|
||||
* \li \c OptionThreadingAuto - Permit the stretcher to
|
||||
* determine its own threading model. Usually this means using
|
||||
* 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
|
||||
* default.
|
||||
* determine its own threading model. In the R2 engine this
|
||||
* means using 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. The R3 engine does not currently have a multi-threaded
|
||||
* mode, but if one is introduced in future, this option may use
|
||||
* it. This is the default.
|
||||
*
|
||||
* \li \c OptionThreadingNever - Never use more than one thread.
|
||||
*
|
||||
@@ -210,9 +262,10 @@ public:
|
||||
* the check for multiple CPUs and instead assume it to be true.
|
||||
*
|
||||
* 7. Flags prefixed \c OptionWindow control the window size for
|
||||
* FFT processing. The window size actually used will depend on
|
||||
* many factors, but it can be influenced. These options may not
|
||||
* be changed after construction.
|
||||
* FFT processing in the R2 engine. (The window size actually
|
||||
* used will depend on many factors, but it can be influenced.)
|
||||
* These options have no effect when using the R3 engine. These
|
||||
* options may not be changed after construction.
|
||||
*
|
||||
* \li \c OptionWindowStandard - Use the default window size.
|
||||
* The actual size will vary depending on other parameters.
|
||||
@@ -228,8 +281,9 @@ public:
|
||||
* clarity and timing.
|
||||
*
|
||||
* 8. Flags prefixed \c OptionSmoothing control the use of
|
||||
* window-presum FFT and time-domain smoothing. These options may
|
||||
* not be changed after construction.
|
||||
* window-presum FFT and time-domain smoothing in the R2
|
||||
* engine. These options have no effect when using the R3 engine.
|
||||
* These options may not be changed after construction.
|
||||
*
|
||||
* \li \c OptionSmoothingOff - Do not use time-domain smoothing.
|
||||
* This is the default.
|
||||
@@ -242,7 +296,8 @@ public:
|
||||
*
|
||||
* 9. Flags prefixed \c OptionFormant control the handling of
|
||||
* formant shape (spectral envelope) when pitch-shifting. These
|
||||
* options may be changed at any time.
|
||||
* options affect both the R2 and R3 engines. These options may
|
||||
* be changed at any time.
|
||||
*
|
||||
* \li \c OptionFormantShifted - Apply no special formant
|
||||
* processing. The spectral envelope will be pitch shifted as
|
||||
@@ -254,9 +309,10 @@ public:
|
||||
* perceived pitch profile of the voice or instrument.
|
||||
*
|
||||
* 10. Flags prefixed \c OptionPitch control the method used for
|
||||
* pitch shifting. These options may be changed at any time.
|
||||
* They are only effective in realtime mode; in offline mode, the
|
||||
* pitch-shift method is fixed.
|
||||
* pitch shifting in the R2 engine. These options have no effect
|
||||
* when using the R3 engine. These options may be changed at any
|
||||
* time. They are only effective in realtime mode; in offline
|
||||
* mode, the pitch-shift method is fixed.
|
||||
*
|
||||
* \li \c OptionPitchHighSpeed - Use a method with a CPU cost
|
||||
* that is relatively moderate and predictable. This may
|
||||
@@ -274,9 +330,10 @@ public:
|
||||
* 1.0 pitch scale in real-time; it also consumes more CPU than
|
||||
* the others in the case where the pitch scale is exactly 1.0.
|
||||
*
|
||||
* 11. Flags prefixed \c OptionChannels control the method used for
|
||||
* processing two-channel audio. These options may not be changed
|
||||
* after construction.
|
||||
* 11. Flags prefixed \c OptionChannels control the method used
|
||||
* for processing two-channel audio in the R2 engine. These
|
||||
* options have no effect when using the R3 engine. These options
|
||||
* may not be changed after construction.
|
||||
*
|
||||
* \li \c OptionChannelsApart - Each channel is processed
|
||||
* individually, though timing is synchronised and phases are
|
||||
@@ -293,15 +350,18 @@ public:
|
||||
* setting). This usually leads to better focus in the centre
|
||||
* but a loss of stereo space and width. Any channels beyond
|
||||
* the first two are processed individually.
|
||||
*
|
||||
* Finally, flags prefixed \c OptionStretch are obsolete flags
|
||||
* provided for backward compatibility only. They are ignored by
|
||||
* the stretcher.
|
||||
*/
|
||||
|
||||
enum Option {
|
||||
|
||||
OptionProcessOffline = 0x00000000,
|
||||
OptionProcessRealTime = 0x00000001,
|
||||
|
||||
OptionStretchElastic = 0x00000000,
|
||||
OptionStretchPrecise = 0x00000010,
|
||||
OptionStretchElastic = 0x00000000, // obsolete
|
||||
OptionStretchPrecise = 0x00000010, // obsolete
|
||||
|
||||
OptionTransientsCrisp = 0x00000000,
|
||||
OptionTransientsMixed = 0x00000100,
|
||||
@@ -333,11 +393,18 @@ public:
|
||||
OptionPitchHighConsistency = 0x04000000,
|
||||
|
||||
OptionChannelsApart = 0x00000000,
|
||||
OptionChannelsTogether = 0x10000000
|
||||
OptionChannelsTogether = 0x10000000,
|
||||
|
||||
OptionEngineFaster = 0x00000000,
|
||||
OptionEngineFiner = 0x20000000
|
||||
|
||||
// n.b. Options is int, so we must stop before 0x80000000
|
||||
};
|
||||
|
||||
/**
|
||||
* A bitwise OR of values from the RubberBandStretcher::Option
|
||||
* enum.
|
||||
*/
|
||||
typedef int Options;
|
||||
|
||||
enum PresetOption {
|
||||
@@ -345,6 +412,37 @@ public:
|
||||
PercussiveOptions = 0x00102000
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface for log callbacks that may optionally be provided to
|
||||
* the stretcher on construction.
|
||||
*
|
||||
* If a Logger is provided, the stretcher will call one of these
|
||||
* functions instead of sending output to \c cerr when there is
|
||||
* something to report. This allows debug output to be diverted to
|
||||
* an application's logging facilities, and/or handled in an
|
||||
* RT-safe way. See setDebugLevel() for details about how and when
|
||||
* RubberBandStretcher reports something in this way.
|
||||
*
|
||||
* The message text passed to each of these log functions is a
|
||||
* C-style string with no particular guaranteed lifespan. If you
|
||||
* need to retain it, copy it before returning. Do not free it.
|
||||
*
|
||||
* @see setDebugLevel
|
||||
* @see setDefaultDebugLevel
|
||||
*/
|
||||
struct Logger {
|
||||
/// Receive a log message with no numeric values.
|
||||
virtual void log(const char *) = 0;
|
||||
|
||||
/// Receive a log message and one accompanying numeric value.
|
||||
virtual void log(const char *, double) = 0;
|
||||
|
||||
/// Receive a log message and two accompanying numeric values.
|
||||
virtual void log(const char *, double, double) = 0;
|
||||
|
||||
virtual ~Logger() { }
|
||||
};
|
||||
|
||||
/**
|
||||
* Construct a time and pitch stretcher object to run at the given
|
||||
* sample rate, with the given number of channels.
|
||||
@@ -375,6 +473,30 @@ public:
|
||||
Options options = DefaultOptions,
|
||||
double initialTimeRatio = 1.0,
|
||||
double initialPitchScale = 1.0);
|
||||
|
||||
/**
|
||||
* Construct a time and pitch stretcher object with a custom debug
|
||||
* logger. This may be useful for debugging if the default logger
|
||||
* output (which simply goes to \c cerr) is not visible in the
|
||||
* runtime environment, or if the application has a standard or
|
||||
* more realtime-appropriate logging mechanism.
|
||||
*
|
||||
* See the documentation for the other constructor above for
|
||||
* details of the arguments other than the logger.
|
||||
*
|
||||
* Note that although the supplied logger gets to decide what to
|
||||
* do with log messages, the separately-set debug level (see
|
||||
* setDebugLevel() and setDefaultDebugLevel()) still determines
|
||||
* whether any given debug message is sent to the logger in the
|
||||
* first place.
|
||||
*/
|
||||
RubberBandStretcher(size_t sampleRate,
|
||||
size_t channels,
|
||||
std::shared_ptr<Logger> logger,
|
||||
Options options = DefaultOptions,
|
||||
double initialTimeRatio = 1.0,
|
||||
double initialPitchScale = 1.0);
|
||||
|
||||
~RubberBandStretcher();
|
||||
|
||||
/**
|
||||
@@ -384,6 +506,15 @@ public:
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* Return the active internal engine version, according to the \c
|
||||
* OptionEngine flag supplied on construction. This will return 2
|
||||
* for the R2 (Faster) engine or 3 for the R3 (Finer) engine.
|
||||
*
|
||||
* This function was added in Rubber Band Library v3.0.
|
||||
*/
|
||||
int getEngineVersion() const;
|
||||
|
||||
/**
|
||||
* Set the time ratio for the stretcher. This is the ratio of
|
||||
* stretched to unstretched duration -- not tempo. For example, a
|
||||
@@ -434,6 +565,36 @@ public:
|
||||
*/
|
||||
void setPitchScale(double scale);
|
||||
|
||||
/**
|
||||
* Set a pitch scale for the vocal formant envelope separately
|
||||
* from the overall pitch scale. This is a ratio of target
|
||||
* frequency to source frequency. For example, a ratio of 2.0
|
||||
* would shift the formant envelope up by one octave; 0.5 down by
|
||||
* one octave; or 1.0 leave the formant unaffected.
|
||||
*
|
||||
* By default this is set to the special value of 0.0, which
|
||||
* causes the scale to be calculated automatically. It will be
|
||||
* treated as 1.0 / the pitch scale if OptionFormantPreserved is
|
||||
* specified, or 1.0 for OptionFormantShifted.
|
||||
*
|
||||
* Conversely, if this is set to a value other than the default
|
||||
* 0.0, formant shifting will happen regardless of the state of
|
||||
* the OptionFormantPreserved/OptionFormantShifted option.
|
||||
*
|
||||
* This function is provided for special effects only. You do not
|
||||
* need to call it for ordinary pitch shifting, with or without
|
||||
* formant preservation - just specify or omit the
|
||||
* OptionFormantPreserved option as appropriate. Use this function
|
||||
* only if you want to shift formants by a distance other than
|
||||
* that of the overall pitch shift.
|
||||
*
|
||||
* This function is supported only in the R3 (OptionEngineFiner)
|
||||
* engine. It has no effect in R2 (OptionEngineFaster).
|
||||
*
|
||||
* This function was added in Rubber Band Library v3.0.
|
||||
*/
|
||||
void setFormantScale(double scale);
|
||||
|
||||
/**
|
||||
* Return the last time ratio value that was set (either on
|
||||
* construction or with setTimeRatio()).
|
||||
@@ -446,6 +607,18 @@ public:
|
||||
*/
|
||||
double getPitchScale() const;
|
||||
|
||||
/**
|
||||
* Return the last formant scaling ratio that was set with
|
||||
* setFormantScale, or 0.0 if the default automatic scaling is in
|
||||
* effect.
|
||||
*
|
||||
* This function is supported only in the R3 (OptionEngineFiner)
|
||||
* engine. It always returns 0.0 in R2 (OptionEngineFaster).
|
||||
*
|
||||
* This function was added in Rubber Band Library v3.0.
|
||||
*/
|
||||
double getFormantScale() const;
|
||||
|
||||
/**
|
||||
* Return the output delay or latency of the stretcher. This is
|
||||
* the number of audio samples that one would have to discard at
|
||||
@@ -466,11 +639,17 @@ public:
|
||||
*/
|
||||
size_t getLatency() const;
|
||||
|
||||
/**
|
||||
* Return the number of channels this stretcher was constructed
|
||||
* with.
|
||||
*/
|
||||
size_t getChannelCount() const;
|
||||
|
||||
/**
|
||||
* Change an OptionTransients 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
|
||||
* construction).
|
||||
* construction). This has no effect when using the R3 engine.
|
||||
*/
|
||||
void setTransientsOption(Options options);
|
||||
|
||||
@@ -478,13 +657,14 @@ public:
|
||||
* Change an OptionDetector configuration setting. This may be
|
||||
* called at any time in RealTime mode. It may not be called in
|
||||
* Offline mode (for which the detector option is fixed on
|
||||
* construction).
|
||||
* construction). This has no effect when using the R3 engine.
|
||||
*/
|
||||
void setDetectorOption(Options options);
|
||||
|
||||
/**
|
||||
* Change an OptionPhase configuration setting. This may be
|
||||
* called at any time in any mode.
|
||||
* called at any time in any mode. This has no effect when using
|
||||
* the R3 engine.
|
||||
*
|
||||
* Note that if running multi-threaded in Offline mode, the change
|
||||
* may not take effect immediately if processing is already under
|
||||
@@ -506,7 +686,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 pitch option is fixed on
|
||||
* construction).
|
||||
* construction). This has no effect when using the R3 engine.
|
||||
*/
|
||||
void setPitchOption(Options options);
|
||||
|
||||
@@ -711,7 +891,8 @@ public:
|
||||
/**
|
||||
* Retrieve the value of the internal input block increment value.
|
||||
*
|
||||
* This function is provided for diagnostic purposes only.
|
||||
* This function is provided for diagnostic purposes only and
|
||||
* supported only with the R2 engine.
|
||||
*/
|
||||
size_t getInputIncrement() const;
|
||||
|
||||
@@ -722,7 +903,8 @@ public:
|
||||
* retrieve any output increments that have accumulated since the
|
||||
* last call to getOutputIncrements, to a limit of 16.
|
||||
*
|
||||
* This function is provided for diagnostic purposes only.
|
||||
* This function is provided for diagnostic purposes only and
|
||||
* supported only with the R2 engine.
|
||||
*/
|
||||
std::vector<int> getOutputIncrements() const;
|
||||
|
||||
@@ -733,7 +915,8 @@ public:
|
||||
* retrieve any phase reset points that have accumulated since the
|
||||
* last call to getPhaseResetCurve, to a limit of 16.
|
||||
*
|
||||
* This function is provided for diagnostic purposes only.
|
||||
* This function is provided for diagnostic purposes only and
|
||||
* supported only with the R2 engine.
|
||||
*/
|
||||
std::vector<float> getPhaseResetCurve() const;
|
||||
|
||||
@@ -743,31 +926,52 @@ public:
|
||||
* provided the stretch profile has been calculated. In realtime
|
||||
* mode, return an empty sequence.
|
||||
*
|
||||
* This function is provided for diagnostic purposes only.
|
||||
* This function is provided for diagnostic purposes only and
|
||||
* supported only with the R2 engine.
|
||||
*/
|
||||
std::vector<int> getExactTimePoints() const;
|
||||
|
||||
/**
|
||||
* Return the number of channels this stretcher was constructed
|
||||
* with.
|
||||
*/
|
||||
size_t getChannelCount() const;
|
||||
|
||||
/**
|
||||
* Force the stretcher to calculate a stretch profile. Normally
|
||||
* this happens automatically for the first process() call in
|
||||
* offline mode.
|
||||
*
|
||||
* This function is provided for diagnostic purposes only.
|
||||
* This function is provided for diagnostic purposes only and
|
||||
* supported only with the R2 engine.
|
||||
*/
|
||||
void calculateStretch();
|
||||
|
||||
/**
|
||||
* Set the level of debug output. The value may be from 0 (errors
|
||||
* only) to 3 (very verbose, with audible ticks in the output at
|
||||
* phase reset points). The default is whatever has been set
|
||||
* using setDefaultDebugLevel, or 0 if that function has not been
|
||||
* Set the level of debug output. The supported values are:
|
||||
*
|
||||
* 0. Report errors only.
|
||||
*
|
||||
* 1. Report some information on construction and ratio
|
||||
* change. Nothing is reported during normal processing unless
|
||||
* something changes.
|
||||
*
|
||||
* 2. Report a significant amount of information about ongoing
|
||||
* stretch calculations during normal processing.
|
||||
*
|
||||
* 3. Report a large amount of information and also (in the R2
|
||||
* engine) add audible ticks to the output at phase reset
|
||||
* points. This is seldom useful.
|
||||
*
|
||||
* The default is whatever has been set using
|
||||
* setDefaultDebugLevel(), or 0 if that function has not been
|
||||
* called.
|
||||
*
|
||||
* All output goes to \c cerr unless a custom
|
||||
* RubberBandStretcher::Logger has been provided on
|
||||
* construction. Because writing to \c cerr is not RT-safe, only
|
||||
* debug level 0 is RT-safe in normal use by default. Debug levels
|
||||
* 0 and 1 use only C-string constants as debug messages, so they
|
||||
* are RT-safe if your custom logger is RT-safe. Levels 2 and 3
|
||||
* are not guaranteed to be RT-safe in any conditions as they may
|
||||
* construct messages by allocation.
|
||||
*
|
||||
* @see Logger
|
||||
* @see setDefaultDebugLevel
|
||||
*/
|
||||
void setDebugLevel(int level);
|
||||
|
||||
@@ -782,6 +986,9 @@ public:
|
||||
protected:
|
||||
class Impl;
|
||||
Impl *m_d;
|
||||
|
||||
RubberBandStretcher(const RubberBandStretcher &) =delete;
|
||||
RubberBandStretcher &operator=(const RubberBandStretcher &) =delete;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -28,9 +28,9 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RUBBERBAND_VERSION "2.0.2"
|
||||
#define RUBBERBAND_VERSION "3.0.0"
|
||||
#define RUBBERBAND_API_MAJOR_VERSION 2
|
||||
#define RUBBERBAND_API_MINOR_VERSION 6
|
||||
#define RUBBERBAND_API_MINOR_VERSION 7
|
||||
|
||||
#undef RB_EXTERN
|
||||
#ifdef _MSC_VER
|
||||
@@ -57,8 +57,8 @@ enum RubberBandOption {
|
||||
RubberBandOptionProcessOffline = 0x00000000,
|
||||
RubberBandOptionProcessRealTime = 0x00000001,
|
||||
|
||||
RubberBandOptionStretchElastic = 0x00000000,
|
||||
RubberBandOptionStretchPrecise = 0x00000010,
|
||||
RubberBandOptionStretchElastic = 0x00000000, // obsolete
|
||||
RubberBandOptionStretchPrecise = 0x00000010, // obsolete
|
||||
|
||||
RubberBandOptionTransientsCrisp = 0x00000000,
|
||||
RubberBandOptionTransientsMixed = 0x00000100,
|
||||
@@ -90,7 +90,10 @@ enum RubberBandOption {
|
||||
RubberBandOptionPitchHighConsistency = 0x04000000,
|
||||
|
||||
RubberBandOptionChannelsApart = 0x00000000,
|
||||
RubberBandOptionChannelsTogether = 0x10000000
|
||||
RubberBandOptionChannelsTogether = 0x10000000,
|
||||
|
||||
RubberBandOptionEngineFaster = 0x00000000,
|
||||
RubberBandOptionEngineFiner = 0x20000000
|
||||
};
|
||||
|
||||
typedef int RubberBandOptions;
|
||||
@@ -108,12 +111,17 @@ RB_EXTERN void rubberband_delete(RubberBandState);
|
||||
|
||||
RB_EXTERN void rubberband_reset(RubberBandState);
|
||||
|
||||
RB_EXTERN int rubberband_get_engine_version(RubberBandState);
|
||||
|
||||
RB_EXTERN void rubberband_set_time_ratio(RubberBandState, double ratio);
|
||||
RB_EXTERN void rubberband_set_pitch_scale(RubberBandState, double scale);
|
||||
|
||||
RB_EXTERN double rubberband_get_time_ratio(const RubberBandState);
|
||||
RB_EXTERN double rubberband_get_pitch_scale(const RubberBandState);
|
||||
|
||||
RB_EXTERN void rubberband_set_formant_scale(RubberBandState, double scale);
|
||||
RB_EXTERN double rubberband_get_formant_scale(const RubberBandState);
|
||||
|
||||
RB_EXTERN unsigned int rubberband_get_latency(const RubberBandState);
|
||||
|
||||
RB_EXTERN void rubberband_set_transients_option(RubberBandState, RubberBandOptions options);
|
||||
|
||||
@@ -56,25 +56,25 @@
|
||||
#define USE_BUILTIN_FFT 1
|
||||
#endif
|
||||
|
||||
#include "../src/audiocurves/CompoundAudioCurve.cpp"
|
||||
#include "../src/audiocurves/SpectralDifferenceAudioCurve.cpp"
|
||||
#include "../src/audiocurves/HighFrequencyAudioCurve.cpp"
|
||||
#include "../src/audiocurves/SilentAudioCurve.cpp"
|
||||
#include "../src/audiocurves/ConstantAudioCurve.cpp"
|
||||
#include "../src/audiocurves/PercussiveAudioCurve.cpp"
|
||||
#include "../src/base/Profiler.cpp"
|
||||
#include "../src/dsp/AudioCurveCalculator.cpp"
|
||||
#include "../src/dsp/FFT.cpp"
|
||||
#include "../src/dsp/Resampler.cpp"
|
||||
#include "../src/dsp/BQResampler.cpp"
|
||||
#include "../src/system/Allocators.cpp"
|
||||
#include "../src/system/sysutils.cpp"
|
||||
#include "../src/system/Thread.cpp"
|
||||
#include "../src/RubberBandStretcher.cpp"
|
||||
#include "../src/StretchCalculator.cpp"
|
||||
#include "../src/StretcherChannelData.cpp"
|
||||
#include "../src/StretcherImpl.cpp"
|
||||
#include "../src/StretcherProcess.cpp"
|
||||
#include "../src/faster/AudioCurveCalculator.cpp"
|
||||
#include "../src/faster/CompoundAudioCurve.cpp"
|
||||
#include "../src/faster/HighFrequencyAudioCurve.cpp"
|
||||
#include "../src/faster/SilentAudioCurve.cpp"
|
||||
#include "../src/faster/PercussiveAudioCurve.cpp"
|
||||
#include "../src/common/Log.cpp"
|
||||
#include "../src/common/Profiler.cpp"
|
||||
#include "../src/common/FFT.cpp"
|
||||
#include "../src/common/Resampler.cpp"
|
||||
#include "../src/common/BQResampler.cpp"
|
||||
#include "../src/common/Allocators.cpp"
|
||||
#include "../src/common/StretchCalculator.cpp"
|
||||
#include "../src/common/sysutils.cpp"
|
||||
#include "../src/common/Thread.cpp"
|
||||
#include "../src/faster/StretcherChannelData.cpp"
|
||||
#include "../src/faster/R2Stretcher.cpp"
|
||||
#include "../src/faster/StretcherProcess.cpp"
|
||||
#include "../src/finer/R3Stretcher.cpp"
|
||||
|
||||
#include "../src/RubberBandStretcher.cpp"
|
||||
#include "../src/rubberband-c.cpp"
|
||||
|
||||
|
||||
@@ -21,18 +21,336 @@
|
||||
you must obtain a valid commercial licence before doing so.
|
||||
*/
|
||||
|
||||
#include "StretcherImpl.h"
|
||||
#include "faster/R2Stretcher.h"
|
||||
#include "finer/R3Stretcher.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace RubberBand {
|
||||
|
||||
class RubberBandStretcher::Impl
|
||||
{
|
||||
R2Stretcher *m_r2;
|
||||
R3Stretcher *m_r3;
|
||||
|
||||
class CerrLogger : public RubberBandStretcher::Logger {
|
||||
public:
|
||||
void log(const char *message) override {
|
||||
std::cerr << "RubberBand: " << message << "\n";
|
||||
}
|
||||
void log(const char *message, double arg0) override {
|
||||
auto prec = std::cerr.precision();
|
||||
std::cerr.precision(10);
|
||||
std::cerr << "RubberBand: " << message << ": " << arg0 << "\n";
|
||||
std::cerr.precision(prec);
|
||||
}
|
||||
void log(const char *message, double arg0, double arg1) override {
|
||||
auto prec = std::cerr.precision();
|
||||
std::cerr.precision(10);
|
||||
std::cerr << "RubberBand: " << message
|
||||
<< ": (" << arg0 << ", " << arg1 << ")" << "\n";
|
||||
std::cerr.precision(prec);
|
||||
}
|
||||
};
|
||||
|
||||
Log makeRBLog(std::shared_ptr<RubberBandStretcher::Logger> logger) {
|
||||
if (logger) {
|
||||
return Log(
|
||||
[=](const char *message) {
|
||||
logger->log(message);
|
||||
},
|
||||
[=](const char *message, double arg0) {
|
||||
logger->log(message, arg0);
|
||||
},
|
||||
[=](const char *message, double arg0, double arg1) {
|
||||
logger->log(message, arg0, arg1);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
return makeRBLog(std::shared_ptr<RubberBandStretcher::Logger>
|
||||
(new CerrLogger()));
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
Impl(size_t sampleRate, size_t channels, Options options,
|
||||
std::shared_ptr<RubberBandStretcher::Logger> logger,
|
||||
double initialTimeRatio, double initialPitchScale) :
|
||||
m_r2 (!(options & OptionEngineFiner) ?
|
||||
new R2Stretcher(sampleRate, channels, options,
|
||||
initialTimeRatio, initialPitchScale,
|
||||
makeRBLog(logger))
|
||||
: nullptr),
|
||||
m_r3 ((options & OptionEngineFiner) ?
|
||||
new R3Stretcher(R3Stretcher::Parameters
|
||||
(double(sampleRate), channels, options),
|
||||
initialTimeRatio, initialPitchScale,
|
||||
makeRBLog(logger))
|
||||
: nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
~Impl()
|
||||
{
|
||||
delete m_r2;
|
||||
delete m_r3;
|
||||
}
|
||||
|
||||
int getEngineVersion() const
|
||||
{
|
||||
if (m_r3) return 3;
|
||||
else return 2;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
if (m_r2) m_r2->reset();
|
||||
else m_r3->reset();
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
void
|
||||
setTimeRatio(double ratio)
|
||||
{
|
||||
if (m_r2) m_r2->setTimeRatio(ratio);
|
||||
else m_r3->setTimeRatio(ratio);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
void
|
||||
setPitchScale(double scale)
|
||||
{
|
||||
if (m_r2) m_r2->setPitchScale(scale);
|
||||
else m_r3->setPitchScale(scale);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
void
|
||||
setFormantScale(double scale)
|
||||
{
|
||||
//!!!
|
||||
if (m_r3) m_r3->setFormantScale(scale);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
double
|
||||
getTimeRatio() const
|
||||
{
|
||||
if (m_r2) return m_r2->getTimeRatio();
|
||||
else return m_r3->getTimeRatio();
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
double
|
||||
getPitchScale() const
|
||||
{
|
||||
if (m_r2) return m_r2->getPitchScale();
|
||||
else return m_r3->getPitchScale();
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
double
|
||||
getFormantScale() const
|
||||
{
|
||||
//!!!
|
||||
if (m_r2) return 0.0;
|
||||
else return m_r3->getFormantScale();
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
size_t
|
||||
getLatency() const
|
||||
{
|
||||
if (m_r2) return m_r2->getLatency();
|
||||
else return m_r3->getLatency();
|
||||
}
|
||||
|
||||
//!!! review all these
|
||||
|
||||
RTENTRY__
|
||||
void
|
||||
setTransientsOption(Options options)
|
||||
{
|
||||
if (m_r2) m_r2->setTransientsOption(options);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
void
|
||||
setDetectorOption(Options options)
|
||||
{
|
||||
if (m_r2) m_r2->setDetectorOption(options);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
void
|
||||
setPhaseOption(Options options)
|
||||
{
|
||||
if (m_r2) m_r2->setPhaseOption(options);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
void
|
||||
setFormantOption(Options options)
|
||||
{
|
||||
if (m_r2) m_r2->setFormantOption(options);
|
||||
else if (m_r3) m_r3->setFormantOption(options);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
void
|
||||
setPitchOption(Options options)
|
||||
{
|
||||
if (m_r2) m_r2->setPitchOption(options);
|
||||
}
|
||||
|
||||
void
|
||||
setExpectedInputDuration(size_t samples)
|
||||
{
|
||||
if (m_r2) m_r2->setExpectedInputDuration(samples);
|
||||
//!!! perhaps also for R3
|
||||
}
|
||||
|
||||
void
|
||||
setMaxProcessSize(size_t samples)
|
||||
{
|
||||
if (m_r2) m_r2->setMaxProcessSize(samples);
|
||||
else m_r3->setMaxProcessSize(samples);
|
||||
}
|
||||
|
||||
void
|
||||
setKeyFrameMap(const std::map<size_t, size_t> &mapping)
|
||||
{
|
||||
if (m_r2) m_r2->setKeyFrameMap(mapping);
|
||||
else m_r3->setKeyFrameMap(mapping);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
size_t
|
||||
getSamplesRequired() const
|
||||
{
|
||||
if (m_r2) return m_r2->getSamplesRequired();
|
||||
else return m_r3->getSamplesRequired();
|
||||
}
|
||||
|
||||
void
|
||||
study(const float *const *input, size_t samples,
|
||||
bool final)
|
||||
{
|
||||
if (m_r2) m_r2->study(input, samples, final);
|
||||
else m_r3->study(input, samples, final);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
void
|
||||
process(const float *const *input, size_t samples,
|
||||
bool final)
|
||||
{
|
||||
if (m_r2) m_r2->process(input, samples, final);
|
||||
else m_r3->process(input, samples, final);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
int
|
||||
available() const
|
||||
{
|
||||
if (m_r2) return m_r2->available();
|
||||
else return m_r3->available();
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
size_t
|
||||
retrieve(float *const *output, size_t samples) const
|
||||
{
|
||||
if (m_r2) return m_r2->retrieve(output, samples);
|
||||
else return m_r3->retrieve(output, samples);
|
||||
}
|
||||
|
||||
float
|
||||
getFrequencyCutoff(int n) const
|
||||
{
|
||||
if (m_r2) return m_r2->getFrequencyCutoff(n);
|
||||
else return {};
|
||||
}
|
||||
|
||||
void
|
||||
setFrequencyCutoff(int n, float f)
|
||||
{
|
||||
if (m_r2) m_r2->setFrequencyCutoff(n, f);
|
||||
}
|
||||
|
||||
size_t
|
||||
getInputIncrement() const
|
||||
{
|
||||
if (m_r2) return m_r2->getInputIncrement();
|
||||
else return {};
|
||||
}
|
||||
|
||||
std::vector<int>
|
||||
getOutputIncrements() const
|
||||
{
|
||||
if (m_r2) return m_r2->getOutputIncrements();
|
||||
else return {};
|
||||
}
|
||||
|
||||
std::vector<float>
|
||||
getPhaseResetCurve() const
|
||||
{
|
||||
if (m_r2) return m_r2->getPhaseResetCurve();
|
||||
else return {};
|
||||
}
|
||||
|
||||
std::vector<int>
|
||||
getExactTimePoints() const
|
||||
{
|
||||
if (m_r2) return m_r2->getExactTimePoints();
|
||||
else return {};
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
size_t
|
||||
getChannelCount() const
|
||||
{
|
||||
if (m_r2) return m_r2->getChannelCount();
|
||||
else return m_r3->getChannelCount();
|
||||
}
|
||||
|
||||
void
|
||||
calculateStretch()
|
||||
{
|
||||
if (m_r2) m_r2->calculateStretch();
|
||||
}
|
||||
|
||||
void
|
||||
setDebugLevel(int level)
|
||||
{
|
||||
if (m_r2) m_r2->setDebugLevel(level);
|
||||
else m_r3->setDebugLevel(level);
|
||||
}
|
||||
|
||||
static void
|
||||
setDefaultDebugLevel(int level)
|
||||
{
|
||||
Log::setDefaultDebugLevel(level);
|
||||
}
|
||||
};
|
||||
|
||||
RubberBandStretcher::RubberBandStretcher(size_t sampleRate,
|
||||
size_t channels,
|
||||
Options options,
|
||||
double initialTimeRatio,
|
||||
double initialPitchScale) :
|
||||
m_d(new Impl(sampleRate, channels, options,
|
||||
m_d(new Impl(sampleRate, channels, options, nullptr,
|
||||
initialTimeRatio, initialPitchScale))
|
||||
{
|
||||
}
|
||||
|
||||
RubberBandStretcher::RubberBandStretcher(size_t sampleRate,
|
||||
size_t channels,
|
||||
std::shared_ptr<Logger> logger,
|
||||
Options options,
|
||||
double initialTimeRatio,
|
||||
double initialPitchScale) :
|
||||
m_d(new Impl(sampleRate, channels, options, logger,
|
||||
initialTimeRatio, initialPitchScale))
|
||||
{
|
||||
}
|
||||
@@ -48,60 +366,90 @@ RubberBandStretcher::reset()
|
||||
m_d->reset();
|
||||
}
|
||||
|
||||
int
|
||||
RubberBandStretcher::getEngineVersion() const
|
||||
{
|
||||
return m_d->getEngineVersion();
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
void
|
||||
RubberBandStretcher::setTimeRatio(double ratio)
|
||||
{
|
||||
m_d->setTimeRatio(ratio);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
void
|
||||
RubberBandStretcher::setPitchScale(double scale)
|
||||
{
|
||||
m_d->setPitchScale(scale);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
void
|
||||
RubberBandStretcher::setFormantScale(double scale)
|
||||
{
|
||||
m_d->setFormantScale(scale);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
double
|
||||
RubberBandStretcher::getTimeRatio() const
|
||||
{
|
||||
return m_d->getTimeRatio();
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
double
|
||||
RubberBandStretcher::getPitchScale() const
|
||||
{
|
||||
return m_d->getPitchScale();
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
double
|
||||
RubberBandStretcher::getFormantScale() const
|
||||
{
|
||||
return m_d->getFormantScale();
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
size_t
|
||||
RubberBandStretcher::getLatency() const
|
||||
{
|
||||
return m_d->getLatency();
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
void
|
||||
RubberBandStretcher::setTransientsOption(Options options)
|
||||
{
|
||||
m_d->setTransientsOption(options);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
void
|
||||
RubberBandStretcher::setDetectorOption(Options options)
|
||||
{
|
||||
m_d->setDetectorOption(options);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
void
|
||||
RubberBandStretcher::setPhaseOption(Options options)
|
||||
{
|
||||
m_d->setPhaseOption(options);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
void
|
||||
RubberBandStretcher::setFormantOption(Options options)
|
||||
{
|
||||
m_d->setFormantOption(options);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
void
|
||||
RubberBandStretcher::setPitchOption(Options options)
|
||||
{
|
||||
@@ -126,6 +474,7 @@ RubberBandStretcher::setKeyFrameMap(const std::map<size_t, size_t> &mapping)
|
||||
m_d->setKeyFrameMap(mapping);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
size_t
|
||||
RubberBandStretcher::getSamplesRequired() const
|
||||
{
|
||||
@@ -139,6 +488,7 @@ RubberBandStretcher::study(const float *const *input, size_t samples,
|
||||
m_d->study(input, samples, final);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
void
|
||||
RubberBandStretcher::process(const float *const *input, size_t samples,
|
||||
bool final)
|
||||
@@ -146,12 +496,14 @@ RubberBandStretcher::process(const float *const *input, size_t samples,
|
||||
m_d->process(input, samples, final);
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
int
|
||||
RubberBandStretcher::available() const
|
||||
{
|
||||
return m_d->available();
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
size_t
|
||||
RubberBandStretcher::retrieve(float *const *output, size_t samples) const
|
||||
{
|
||||
@@ -194,6 +546,7 @@ RubberBandStretcher::getExactTimePoints() const
|
||||
return m_d->getExactTimePoints();
|
||||
}
|
||||
|
||||
RTENTRY__
|
||||
size_t
|
||||
RubberBandStretcher::getChannelCount() const
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,107 +0,0 @@
|
||||
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||
|
||||
/*
|
||||
Rubber Band Library
|
||||
An audio time-stretching and pitch-shifting library.
|
||||
Copyright 2007-2022 Particular Programs Ltd.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version. See the file
|
||||
COPYING included with this distribution for more information.
|
||||
|
||||
Alternatively, if you have a valid commercial licence for the
|
||||
Rubber Band Library obtained by agreement with the copyright
|
||||
holders, you may redistribute and/or modify it under the terms
|
||||
described in that licence.
|
||||
|
||||
If you wish to distribute code using the Rubber Band Library
|
||||
under terms other than those of the GNU General Public License,
|
||||
you must obtain a valid commercial licence before doing so.
|
||||
*/
|
||||
|
||||
#include "SpectralDifferenceAudioCurve.h"
|
||||
|
||||
#include "../system/Allocators.h"
|
||||
#include "../system/VectorOps.h"
|
||||
|
||||
namespace RubberBand
|
||||
{
|
||||
|
||||
|
||||
SpectralDifferenceAudioCurve::SpectralDifferenceAudioCurve(Parameters parameters) :
|
||||
AudioCurveCalculator(parameters)
|
||||
{
|
||||
m_mag = allocate<double>(m_lastPerceivedBin + 1);
|
||||
m_tmpbuf = allocate<double>(m_lastPerceivedBin + 1);
|
||||
v_zero(m_mag, m_lastPerceivedBin + 1);
|
||||
}
|
||||
|
||||
SpectralDifferenceAudioCurve::~SpectralDifferenceAudioCurve()
|
||||
{
|
||||
deallocate(m_mag);
|
||||
deallocate(m_tmpbuf);
|
||||
}
|
||||
|
||||
void
|
||||
SpectralDifferenceAudioCurve::reset()
|
||||
{
|
||||
v_zero(m_mag, m_lastPerceivedBin + 1);
|
||||
}
|
||||
|
||||
void
|
||||
SpectralDifferenceAudioCurve::setFftSize(int newSize)
|
||||
{
|
||||
deallocate(m_tmpbuf);
|
||||
deallocate(m_mag);
|
||||
AudioCurveCalculator::setFftSize(newSize);
|
||||
m_mag = allocate<double>(m_lastPerceivedBin + 1);
|
||||
m_tmpbuf = allocate<double>(m_lastPerceivedBin + 1);
|
||||
reset();
|
||||
}
|
||||
|
||||
float
|
||||
SpectralDifferenceAudioCurve::processFloat(const float *R__ mag, int)
|
||||
{
|
||||
double result = 0.0;
|
||||
|
||||
const int hs1 = m_lastPerceivedBin + 1;
|
||||
|
||||
v_convert(m_tmpbuf, mag, hs1);
|
||||
v_square(m_tmpbuf, hs1);
|
||||
v_subtract(m_mag, m_tmpbuf, hs1);
|
||||
v_abs(m_mag, hs1);
|
||||
v_sqrt(m_mag, hs1);
|
||||
|
||||
for (int i = 0; i < hs1; ++i) {
|
||||
result += m_mag[i];
|
||||
}
|
||||
|
||||
v_copy(m_mag, m_tmpbuf, hs1);
|
||||
return result;
|
||||
}
|
||||
|
||||
double
|
||||
SpectralDifferenceAudioCurve::processDouble(const double *R__ mag, int)
|
||||
{
|
||||
double result = 0.0;
|
||||
|
||||
const int hs1 = m_lastPerceivedBin + 1;
|
||||
|
||||
v_convert(m_tmpbuf, mag, hs1);
|
||||
v_square(m_tmpbuf, hs1);
|
||||
v_subtract(m_mag, m_tmpbuf, hs1);
|
||||
v_abs(m_mag, hs1);
|
||||
v_sqrt(m_mag, hs1);
|
||||
|
||||
for (int i = 0; i < hs1; ++i) {
|
||||
result += m_mag[i];
|
||||
}
|
||||
|
||||
v_copy(m_mag, m_tmpbuf, hs1);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "../system/Allocators.h"
|
||||
#include "../system/VectorOps.h"
|
||||
#include "Allocators.h"
|
||||
#include "VectorOps.h"
|
||||
|
||||
#define BQ_R__ R__
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "../system/Allocators.h"
|
||||
#include "../system/VectorOps.h"
|
||||
#include "Allocators.h"
|
||||
#include "VectorOps.h"
|
||||
|
||||
namespace RubberBand {
|
||||
|
||||
@@ -22,11 +22,11 @@
|
||||
*/
|
||||
|
||||
#include "FFT.h"
|
||||
#include "../system/Thread.h"
|
||||
#include "../base/Profiler.h"
|
||||
#include "../system/Allocators.h"
|
||||
#include "../system/VectorOps.h"
|
||||
#include "../system/VectorOpsComplex.h"
|
||||
#include "Thread.h"
|
||||
#include "Profiler.h"
|
||||
#include "Allocators.h"
|
||||
#include "VectorOps.h"
|
||||
#include "VectorOpsComplex.h"
|
||||
|
||||
// Define USE_FFTW_WISDOM if you are defining HAVE_FFTW3 and you want
|
||||
// to use FFTW_MEASURE mode with persistent wisdom files. This will
|
||||
@@ -24,7 +24,7 @@
|
||||
#ifndef RUBBERBAND_FFT_H
|
||||
#define RUBBERBAND_FFT_H
|
||||
|
||||
#include "../system/sysutils.h"
|
||||
#include "sysutils.h"
|
||||
|
||||
#include <string>
|
||||
#include <set>
|
||||
@@ -21,23 +21,26 @@
|
||||
you must obtain a valid commercial licence before doing so.
|
||||
*/
|
||||
|
||||
#ifndef RUBBERBAND_CONSTANT_AUDIO_CURVE_H
|
||||
#define RUBBERBAND_CONSTANT_AUDIO_CURVE_H
|
||||
#ifndef RUBBERBAND_FIXED_VECTOR_H
|
||||
#define RUBBERBAND_FIXED_VECTOR_H
|
||||
|
||||
#include "../dsp/AudioCurveCalculator.h"
|
||||
#include "Allocators.h"
|
||||
#include <vector>
|
||||
|
||||
namespace RubberBand
|
||||
{
|
||||
|
||||
class ConstantAudioCurve : public AudioCurveCalculator
|
||||
template <typename T>
|
||||
class FixedVector : public std::vector<T, StlAllocator<T>>
|
||||
{
|
||||
public:
|
||||
ConstantAudioCurve(Parameters parameters);
|
||||
virtual ~ConstantAudioCurve();
|
||||
using std::vector<T, StlAllocator<T>>::vector;
|
||||
|
||||
virtual float processFloat(const float *R__ mag, int increment);
|
||||
virtual double processDouble(const double *R__ mag, int increment);
|
||||
virtual void reset();
|
||||
private:
|
||||
FixedVector(const FixedVector &) =delete;
|
||||
FixedVector(FixedVector &&) =delete;
|
||||
FixedVector &operator=(const FixedVector &) =delete;
|
||||
FixedVector &operator=(FixedVector &&) =delete;
|
||||
};
|
||||
|
||||
}
|
||||
194
src/common/HistogramFilter.h
Normal file
194
src/common/HistogramFilter.h
Normal file
@@ -0,0 +1,194 @@
|
||||
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||
|
||||
/*
|
||||
Rubber Band Library
|
||||
An audio time-stretching and pitch-shifting library.
|
||||
Copyright 2007-2022 Particular Programs Ltd.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version. See the file
|
||||
COPYING included with this distribution for more information.
|
||||
|
||||
Alternatively, if you have a valid commercial licence for the
|
||||
Rubber Band Library obtained by agreement with the copyright
|
||||
holders, you may redistribute and/or modify it under the terms
|
||||
described in that licence.
|
||||
|
||||
If you wish to distribute code using the Rubber Band Library
|
||||
under terms other than those of the GNU General Public License,
|
||||
you must obtain a valid commercial licence before doing so.
|
||||
*/
|
||||
|
||||
#ifndef RUBBERBAND_HISTOGRAM_FILTER_H
|
||||
#define RUBBERBAND_HISTOGRAM_FILTER_H
|
||||
|
||||
#include "SingleThreadRingBuffer.h"
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
namespace RubberBand {
|
||||
|
||||
/**
|
||||
* A median or modal filter implemented using a histogram. The values
|
||||
* must come from a compact set of integers within [0,n) where n is
|
||||
* specified in the constructor. Pushing a value updates the
|
||||
* histogram, after which you can get either the median or the mode.
|
||||
* You can call drop() to drop the oldest value without pushing a new
|
||||
* one, for example to drain the filter at the tail of the sequence.
|
||||
*/
|
||||
class HistogramFilter
|
||||
{
|
||||
public:
|
||||
HistogramFilter(int nValues, int filterLength) :
|
||||
m_buffer(filterLength),
|
||||
m_histogram(nValues, 0),
|
||||
m_mode(-1) { }
|
||||
~HistogramFilter() { }
|
||||
|
||||
int getFilterLength() const {
|
||||
return m_buffer.getSize();
|
||||
}
|
||||
|
||||
int getNValues() const {
|
||||
return int(m_histogram.size());
|
||||
}
|
||||
|
||||
void reset() {
|
||||
m_buffer.reset();
|
||||
for (int i = 0; i < getNValues(); ++i) {
|
||||
m_histogram[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void push(int value) {
|
||||
if (m_buffer.getWriteSpace() == 0) {
|
||||
int toDrop = m_buffer.readOne();
|
||||
--m_histogram[toDrop];
|
||||
}
|
||||
m_buffer.writeOne(value);
|
||||
int height = ++m_histogram[value];
|
||||
if (m_mode >= 0 && height >= m_histogram[m_mode]) {
|
||||
if (height > m_histogram[m_mode] || value < m_mode) {
|
||||
m_mode = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void drop() {
|
||||
if (m_buffer.getReadSpace() > 0) {
|
||||
int toDrop = m_buffer.readOne();
|
||||
--m_histogram[toDrop];
|
||||
if (toDrop == m_mode) {
|
||||
m_mode = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Return the median of the values in the filter currently. If
|
||||
* the median lies between two values, return the first of them.
|
||||
*/
|
||||
int getMedian() const {
|
||||
int half = (m_buffer.getReadSpace() + 1) / 2;
|
||||
int acc = 0;
|
||||
int nvalues = getNValues();
|
||||
for (int i = 0; i < nvalues; ++i) {
|
||||
acc += m_histogram[i];
|
||||
if (acc >= half) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return the modal value, that is, the value that occurs the
|
||||
* most often in the filter currently. If multiple values occur
|
||||
* an equal number of times, return the smallest of them.
|
||||
*/
|
||||
int getMode() const {
|
||||
if (m_mode >= 0) {
|
||||
return m_mode;
|
||||
}
|
||||
int max = 0;
|
||||
int mode = 0;
|
||||
int nvalues = getNValues();
|
||||
for (int i = 0; i < nvalues; ++i) {
|
||||
int h = m_histogram[i];
|
||||
if (i == 0 || h > max) {
|
||||
max = h;
|
||||
mode = i;
|
||||
}
|
||||
}
|
||||
m_mode = mode;
|
||||
return mode;
|
||||
}
|
||||
|
||||
// Convenience function that filters an array in-place. Filter is
|
||||
// a median filter unless modal is true. Array has length n.
|
||||
// Modifies both the filter and the array.
|
||||
//
|
||||
static void filter(HistogramFilter &f, int *v, int n, bool modal = false) {
|
||||
f.reset();
|
||||
int flen = f.getFilterLength();
|
||||
int i = -(flen / 2);
|
||||
int j = 0;
|
||||
while (i != n) {
|
||||
if (j < n) {
|
||||
f.push(v[j]);
|
||||
} else if (j >= flen) {
|
||||
f.drop();
|
||||
}
|
||||
if (i >= 0) {
|
||||
int m = modal ? f.getMode() : f.getMedian();
|
||||
v[i] = m;
|
||||
}
|
||||
++i;
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
// As above but with a vector argument
|
||||
//
|
||||
static void filter(HistogramFilter &f, std::vector<int> &v, bool modal = false) {
|
||||
filter(f, v.data(), v.size(), modal);
|
||||
}
|
||||
|
||||
// Convenience function that median-filters an array
|
||||
// in-place. Array has length n. Modifies both the filter and the
|
||||
// array.
|
||||
//
|
||||
static void medianFilter(HistogramFilter &f, int *v, int n) {
|
||||
filter(f, v, n, false);
|
||||
}
|
||||
|
||||
// As above but with a vector argument
|
||||
//
|
||||
static void medianFilter(HistogramFilter &f, std::vector<int> &v) {
|
||||
medianFilter(f, v.data(), v.size());
|
||||
}
|
||||
|
||||
// Convenience function that modal-filters an array
|
||||
// in-place. Array has length n. Modifies both the filter and the
|
||||
// array.
|
||||
//
|
||||
static void modalFilter(HistogramFilter &f, int *v, int n) {
|
||||
filter(f, v, n, true);
|
||||
}
|
||||
|
||||
// As above but with a vector argument
|
||||
//
|
||||
static void modalFilter(HistogramFilter &f, std::vector<int> &v) {
|
||||
modalFilter(f, v.data(), v.size());
|
||||
}
|
||||
|
||||
private:
|
||||
SingleThreadRingBuffer<int> m_buffer;
|
||||
std::vector<int> m_histogram;
|
||||
mutable int m_mode;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -21,37 +21,11 @@
|
||||
you must obtain a valid commercial licence before doing so.
|
||||
*/
|
||||
|
||||
#include "ConstantAudioCurve.h"
|
||||
#include "Log.h"
|
||||
|
||||
namespace RubberBand
|
||||
{
|
||||
|
||||
|
||||
ConstantAudioCurve::ConstantAudioCurve(Parameters parameters) :
|
||||
AudioCurveCalculator(parameters)
|
||||
{
|
||||
}
|
||||
|
||||
ConstantAudioCurve::~ConstantAudioCurve()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ConstantAudioCurve::reset()
|
||||
{
|
||||
}
|
||||
|
||||
float
|
||||
ConstantAudioCurve::processFloat(const float *R__, int)
|
||||
{
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
double
|
||||
ConstantAudioCurve::processDouble(const double *R__, int)
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
int Log::m_defaultDebugLevel = 0;
|
||||
|
||||
}
|
||||
|
||||
72
src/common/Log.h
Normal file
72
src/common/Log.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||
|
||||
/*
|
||||
Rubber Band Library
|
||||
An audio time-stretching and pitch-shifting library.
|
||||
Copyright 2007-2022 Particular Programs Ltd.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version. See the file
|
||||
COPYING included with this distribution for more information.
|
||||
|
||||
Alternatively, if you have a valid commercial licence for the
|
||||
Rubber Band Library obtained by agreement with the copyright
|
||||
holders, you may redistribute and/or modify it under the terms
|
||||
described in that licence.
|
||||
|
||||
If you wish to distribute code using the Rubber Band Library
|
||||
under terms other than those of the GNU General Public License,
|
||||
you must obtain a valid commercial licence before doing so.
|
||||
*/
|
||||
|
||||
#ifndef RUBBERBAND_LOG_H
|
||||
#define RUBBERBAND_LOG_H
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
|
||||
namespace RubberBand {
|
||||
|
||||
class Log {
|
||||
public:
|
||||
Log(std::function<void(const char *)> _log0,
|
||||
std::function<void(const char *, double)> _log1,
|
||||
std::function<void(const char *, double, double)> _log2) :
|
||||
m_log0(_log0),
|
||||
m_log1(_log1),
|
||||
m_log2(_log2),
|
||||
m_debugLevel(m_defaultDebugLevel) { }
|
||||
|
||||
Log(const Log &other) =default;
|
||||
Log(Log &&other) =default;
|
||||
Log &operator=(const Log &other) =default;
|
||||
Log &operator=(Log &&other) =default;
|
||||
|
||||
void setDebugLevel(int level) { m_debugLevel = level; }
|
||||
int getDebugLevel() const { return m_debugLevel; }
|
||||
|
||||
static void setDefaultDebugLevel(int level) { m_defaultDebugLevel = level; }
|
||||
|
||||
void log(int level, const char *message) const {
|
||||
if (level <= m_debugLevel) m_log0(message);
|
||||
}
|
||||
void log(int level, const char *message, double arg0) const {
|
||||
if (level <= m_debugLevel) m_log1(message, arg0);
|
||||
}
|
||||
void log(int level, const char *message, double arg0, double arg1) const {
|
||||
if (level <= m_debugLevel) m_log2(message, arg0, arg1);
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void(const char *)> m_log0;
|
||||
std::function<void(const char *, double)> m_log1;
|
||||
std::function<void(const char *, double, double)> m_log2;
|
||||
int m_debugLevel;
|
||||
static int m_defaultDebugLevel;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
256
src/common/MovingMedian.h
Normal file
256
src/common/MovingMedian.h
Normal file
@@ -0,0 +1,256 @@
|
||||
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||
|
||||
/*
|
||||
Rubber Band Library
|
||||
An audio time-stretching and pitch-shifting library.
|
||||
Copyright 2007-2022 Particular Programs Ltd.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version. See the file
|
||||
COPYING included with this distribution for more information.
|
||||
|
||||
Alternatively, if you have a valid commercial licence for the
|
||||
Rubber Band Library obtained by agreement with the copyright
|
||||
holders, you may redistribute and/or modify it under the terms
|
||||
described in that licence.
|
||||
|
||||
If you wish to distribute code using the Rubber Band Library
|
||||
under terms other than those of the GNU General Public License,
|
||||
you must obtain a valid commercial licence before doing so.
|
||||
*/
|
||||
|
||||
#ifndef RUBBERBAND_MOVING_MEDIAN_H
|
||||
#define RUBBERBAND_MOVING_MEDIAN_H
|
||||
|
||||
#include "SampleFilter.h"
|
||||
#include "FixedVector.h"
|
||||
#include "Allocators.h"
|
||||
#include "SingleThreadRingBuffer.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
namespace RubberBand
|
||||
{
|
||||
|
||||
/**
|
||||
* A median or modal filter implemented using sorting, for continuous
|
||||
* values. Pushing a value updates the sorted record, after which you
|
||||
* can get() the median. You can call drop() to drop the oldest value
|
||||
* without pushing a new one, for example to drain the filter at the
|
||||
* tail of the sequence.
|
||||
*/
|
||||
template <typename T>
|
||||
class MovingMedian : public SampleFilter<T>
|
||||
{
|
||||
static constexpr float fifty = 50.f;
|
||||
|
||||
public:
|
||||
MovingMedian(int filterLength, float percentile = fifty) :
|
||||
m_buffer(filterLength),
|
||||
m_sortspace(filterLength, {}),
|
||||
m_fill(0),
|
||||
m_percentile(percentile)
|
||||
{ }
|
||||
|
||||
~MovingMedian() { }
|
||||
|
||||
MovingMedian(const MovingMedian &) =default;
|
||||
MovingMedian &operator=(const MovingMedian &) =default;
|
||||
|
||||
int getSize() const {
|
||||
return m_buffer.getSize();
|
||||
}
|
||||
|
||||
void setPercentile(float p) {
|
||||
m_percentile = p;
|
||||
}
|
||||
|
||||
void push(T value) {
|
||||
if (value != value) {
|
||||
std::cerr << "WARNING: MovingMedian: NaN encountered" << std::endl;
|
||||
value = T();
|
||||
}
|
||||
if (m_fill == getSize()) {
|
||||
T toDrop = m_buffer.readOne();
|
||||
dropAndPut(toDrop, value);
|
||||
} else {
|
||||
put(value);
|
||||
}
|
||||
m_buffer.writeOne(value);
|
||||
}
|
||||
|
||||
void drop() {
|
||||
if (m_fill > 0) {
|
||||
T toDrop = m_buffer.readOne();
|
||||
drop(toDrop);
|
||||
}
|
||||
}
|
||||
|
||||
/** Return the median of the values in the filter currently. If
|
||||
* the median lies between two values, return the first of them.
|
||||
*/
|
||||
T get() const {
|
||||
int n = m_fill - 1;
|
||||
if (m_percentile == fifty) { // exact default value
|
||||
return m_sortspace[n / 2];
|
||||
} else {
|
||||
int index = int(floorf(float(n) * m_percentile / 100.f));
|
||||
if (index >= m_fill) index = m_fill - 1;
|
||||
return m_sortspace[index];
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
m_buffer.reset();
|
||||
v_zero(m_sortspace.data(), m_sortspace.size());
|
||||
m_fill = 0;
|
||||
}
|
||||
|
||||
// Convenience function that applies a given filter to an array
|
||||
// in-place. Array has length n. Modifies both the filter and the
|
||||
// array.
|
||||
//
|
||||
static void filter(MovingMedian<T> &f, T *v, int n) {
|
||||
f.reset();
|
||||
int flen = f.getSize();
|
||||
int i = -(flen / 2);
|
||||
int j = 0;
|
||||
while (i != n) {
|
||||
if (j < n) {
|
||||
f.push(v[j]);
|
||||
} else if (j >= flen) {
|
||||
f.drop();
|
||||
}
|
||||
if (i >= 0) {
|
||||
v[i] = f.get();
|
||||
}
|
||||
++i;
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
// As above but with a vector argument
|
||||
//
|
||||
static void filter(MovingMedian<T> &mm, std::vector<T> &v) {
|
||||
filter(mm, v.data(), v.size());
|
||||
}
|
||||
|
||||
private:
|
||||
SingleThreadRingBuffer<T> m_buffer;
|
||||
std::vector<T> m_sortspace;
|
||||
int m_fill;
|
||||
float m_percentile;
|
||||
|
||||
void dropAndPut(const T &toDrop, const T &toPut) {
|
||||
// precondition: sorted contains getSize values, one of which is toDrop
|
||||
// postcondition: sorted contains getSize values, one of which is toPut
|
||||
// (and one instance of toDrop has been removed)
|
||||
|
||||
// This implementation was timed for rather short filters (no
|
||||
// longer than maybe 16 items). Two binary searches plus a
|
||||
// memmove should be faster for longer ones.
|
||||
|
||||
const int n = m_fill;
|
||||
T *sorted = m_sortspace.data();
|
||||
int dropIx;
|
||||
if (toDrop <= *sorted) {
|
||||
// this is quite a common short-circuit in situations
|
||||
// where many values can be (the equivalent of) 0
|
||||
dropIx = 0;
|
||||
} else {
|
||||
dropIx = std::lower_bound(sorted, sorted + n, toDrop) - sorted;
|
||||
}
|
||||
if (toPut > toDrop) {
|
||||
int i = dropIx;
|
||||
while (i+1 < n) {
|
||||
if (sorted[i+1] > toPut) {
|
||||
break;
|
||||
}
|
||||
sorted[i] = sorted[i+1];
|
||||
++i;
|
||||
}
|
||||
sorted[i] = toPut;
|
||||
} else if (toPut < toDrop) {
|
||||
int i = dropIx;
|
||||
while (true) {
|
||||
if (--i < 0 || sorted[i] < toPut) {
|
||||
break;
|
||||
}
|
||||
sorted[i+1] = sorted[i];
|
||||
}
|
||||
sorted[i+1] = toPut;
|
||||
}
|
||||
}
|
||||
|
||||
void put(const T &toPut) {
|
||||
// precondition: sorted contains m_fill values, m_fill < m_length,
|
||||
// packed at the start
|
||||
// postcondition: m_fill is incremented, sorted contains m_fill values,
|
||||
// packed at the start, one of which is toPut
|
||||
int n = m_fill;
|
||||
T *sorted = m_sortspace.data();
|
||||
int putIx = std::lower_bound(sorted, sorted + n, toPut) - sorted;
|
||||
if (putIx < n) {
|
||||
v_move(sorted + putIx + 1, sorted + putIx, n - putIx);
|
||||
}
|
||||
sorted[putIx] = toPut;
|
||||
++m_fill;
|
||||
}
|
||||
|
||||
void drop(const T &toDrop) {
|
||||
// precondition: sorted contains m_fill values, m_fill > 0, <= m_length,
|
||||
// packed at the start, one of which is toDrop
|
||||
// postcondition: m_fill decremented, sorted contains m_fill values,
|
||||
// packed at the start, none of which is toDrop
|
||||
int n = m_fill;
|
||||
T *sorted = m_sortspace.data();
|
||||
int dropIx = std::lower_bound(sorted, sorted + n, toDrop) - sorted;
|
||||
if (dropIx < n - 1) {
|
||||
v_move(sorted + dropIx, sorted + dropIx + 1, n - dropIx - 1);
|
||||
}
|
||||
--m_fill;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class MovingMedianStack
|
||||
{
|
||||
public:
|
||||
MovingMedianStack(int nfilters, int size) :
|
||||
m_stack(nfilters, { size })
|
||||
{
|
||||
}
|
||||
|
||||
~MovingMedianStack() {
|
||||
}
|
||||
|
||||
int getSize() const {
|
||||
return m_stack[0].getSize();
|
||||
}
|
||||
|
||||
void push(int filter, T value) {
|
||||
m_stack[filter].push(value);
|
||||
}
|
||||
|
||||
T get(int filter) const {
|
||||
return m_stack[filter].get();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
for (auto &f: m_stack) {
|
||||
f.reset();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<MovingMedian<T>> m_stack;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#include "Profiler.h"
|
||||
|
||||
#include "../system/Thread.h"
|
||||
#include "Thread.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
@@ -42,7 +42,7 @@
|
||||
#ifdef PROFILE_CLOCKS
|
||||
#include <time.h>
|
||||
#else
|
||||
#include "../system/sysutils.h"
|
||||
#include "sysutils.h"
|
||||
#ifndef _WIN32
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
@@ -23,8 +23,8 @@
|
||||
|
||||
#include "Resampler.h"
|
||||
|
||||
#include "../system/Allocators.h"
|
||||
#include "../system/VectorOps.h"
|
||||
#include "Allocators.h"
|
||||
#include "VectorOps.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
@@ -54,7 +54,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef USE_SPEEX
|
||||
#include "../speex/speex_resampler.h"
|
||||
#include "../ext/speex/speex_resampler.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_BQRESAMPLER
|
||||
@@ -24,7 +24,7 @@
|
||||
#ifndef RUBBERBAND_RESAMPLER_H
|
||||
#define RUBBERBAND_RESAMPLER_H
|
||||
|
||||
#include "../system/sysutils.h"
|
||||
#include "sysutils.h"
|
||||
|
||||
namespace RubberBand {
|
||||
|
||||
@@ -172,6 +172,9 @@ public:
|
||||
protected:
|
||||
Impl *d;
|
||||
int m_method;
|
||||
|
||||
Resampler(const Resampler &) =delete;
|
||||
Resampler &operator=(const Resampler &) =delete;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -28,8 +28,8 @@
|
||||
|
||||
//#define DEBUG_RINGBUFFER 1
|
||||
|
||||
#include "../system/sysutils.h"
|
||||
#include "../system/Allocators.h"
|
||||
#include "sysutils.h"
|
||||
#include "Allocators.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@@ -44,7 +44,6 @@ namespace RubberBand {
|
||||
* RingBuffer is thread-safe provided only one thread writes and only
|
||||
* one thread reads.
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
class RingBuffer
|
||||
{
|
||||
@@ -138,8 +137,13 @@ public:
|
||||
* necessary to empty the buffer. If fewer than n are available,
|
||||
* the remainder will be zeroed out. Returns the number of
|
||||
* samples actually read.
|
||||
*
|
||||
* This is a template function, taking an argument S for the target
|
||||
* sample type, which is permitted to differ from T if the two
|
||||
* types are compatible for arithmetic operations.
|
||||
*/
|
||||
int peek(T *const R__ destination, int n) const;
|
||||
template <typename S>
|
||||
int peek(S *const R__ destination, int n) const;
|
||||
|
||||
/**
|
||||
* Read one sample from the buffer, if available, without
|
||||
@@ -384,8 +388,9 @@ RingBuffer<T>::readOne()
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename S>
|
||||
int
|
||||
RingBuffer<T>::peek(T *const R__ destination, int n) const
|
||||
RingBuffer<T>::peek(S *const R__ destination, int n) const
|
||||
{
|
||||
int w = m_writer;
|
||||
int r = m_reader;
|
||||
@@ -394,7 +399,6 @@ RingBuffer<T>::peek(T *const R__ destination, int n) const
|
||||
if (n > available) {
|
||||
std::cerr << "WARNING: RingBuffer::peek: " << n << " requested, only "
|
||||
<< available << " available" << std::endl;
|
||||
memset(destination + available, 0, (n - available) * sizeof(T));
|
||||
n = available;
|
||||
}
|
||||
if (n == 0) return n;
|
||||
@@ -403,10 +407,10 @@ RingBuffer<T>::peek(T *const R__ destination, int n) const
|
||||
const T *const R__ bufbase = m_buffer + r;
|
||||
|
||||
if (here >= n) {
|
||||
v_copy(destination, bufbase, n);
|
||||
v_convert(destination, bufbase, n);
|
||||
} else {
|
||||
v_copy(destination, bufbase, here);
|
||||
v_copy(destination + here, m_buffer, n - here);
|
||||
v_convert(destination, bufbase, here);
|
||||
v_convert(destination + here, m_buffer, n - here);
|
||||
}
|
||||
|
||||
return n;
|
||||
@@ -33,24 +33,11 @@ template <typename T>
|
||||
class SampleFilter
|
||||
{
|
||||
public:
|
||||
SampleFilter(int size) : m_size(size) {
|
||||
assert(m_size > 0);
|
||||
}
|
||||
|
||||
virtual ~SampleFilter() { }
|
||||
|
||||
int getSize() const { return m_size; }
|
||||
|
||||
virtual int getSize() const = 0;
|
||||
virtual void push(T) = 0;
|
||||
virtual T get() const = 0;
|
||||
virtual void reset() = 0;
|
||||
|
||||
protected:
|
||||
const int m_size;
|
||||
|
||||
private:
|
||||
SampleFilter(const SampleFilter &);
|
||||
SampleFilter &operator=(const SampleFilter &);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -33,9 +33,9 @@
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "../system/Thread.h"
|
||||
#include "../system/sysutils.h"
|
||||
#include "../system/Allocators.h"
|
||||
#include "Thread.h"
|
||||
#include "sysutils.h"
|
||||
#include "Allocators.h"
|
||||
|
||||
//#define DEBUG_SCAVENGER 1
|
||||
|
||||
149
src/common/SingleThreadRingBuffer.h
Normal file
149
src/common/SingleThreadRingBuffer.h
Normal file
@@ -0,0 +1,149 @@
|
||||
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||
|
||||
/*
|
||||
Rubber Band Library
|
||||
An audio time-stretching and pitch-shifting library.
|
||||
Copyright 2007-2022 Particular Programs Ltd.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version. See the file
|
||||
COPYING included with this distribution for more information.
|
||||
|
||||
Alternatively, if you have a valid commercial licence for the
|
||||
Rubber Band Library obtained by agreement with the copyright
|
||||
holders, you may redistribute and/or modify it under the terms
|
||||
described in that licence.
|
||||
|
||||
If you wish to distribute code using the Rubber Band Library
|
||||
under terms other than those of the GNU General Public License,
|
||||
you must obtain a valid commercial licence before doing so.
|
||||
*/
|
||||
|
||||
#ifndef RUBBERBAND_SINGLE_THREAD_RINGBUFFER_H
|
||||
#define RUBBERBAND_SINGLE_THREAD_RINGBUFFER_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace RubberBand {
|
||||
|
||||
/**
|
||||
* SingleThreadRingBuffer implements a ring buffer to be used to store
|
||||
* a sample type T, for reading and writing within a single
|
||||
* thread. SingleThreadRingBuffer is a simple container, not a
|
||||
* thread-safe lock-free structure: use RingBuffer for the situation
|
||||
* with reader and writer in separate threads. Currently this
|
||||
* implementation only supports reading and writing a single sample at
|
||||
* a time.
|
||||
*/
|
||||
template <typename T>
|
||||
class SingleThreadRingBuffer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create a ring buffer with room to write n samples.
|
||||
*
|
||||
* Note that the internal storage size will actually be n+1
|
||||
* samples, as one element is unavailable for administrative
|
||||
* reasons. Since the ring buffer performs best if its size is a
|
||||
* power of two, this means n should ideally be some power of two
|
||||
* minus one.
|
||||
*/
|
||||
SingleThreadRingBuffer(int n) :
|
||||
m_buffer(n + 1, T()),
|
||||
m_writer(0),
|
||||
m_reader(0),
|
||||
m_size(n + 1) { }
|
||||
|
||||
SingleThreadRingBuffer() :
|
||||
m_buffer(1, T()),
|
||||
m_writer(0),
|
||||
m_reader(0),
|
||||
m_size(1) { }
|
||||
|
||||
SingleThreadRingBuffer (const SingleThreadRingBuffer &other) =default;
|
||||
SingleThreadRingBuffer &operator=(const SingleThreadRingBuffer &other) =default;
|
||||
|
||||
virtual ~SingleThreadRingBuffer() { }
|
||||
|
||||
/**
|
||||
* Return the total capacity of the ring buffer in samples.
|
||||
* (This is the argument n passed to the constructor.)
|
||||
*/
|
||||
int getSize() const {
|
||||
return m_size - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset read and write pointers, thus emptying the buffer.
|
||||
*/
|
||||
void reset() {
|
||||
m_writer = m_reader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the amount of data available for reading, in samples.
|
||||
*/
|
||||
int getReadSpace() const {
|
||||
if (m_writer > m_reader) return m_writer - m_reader;
|
||||
else if (m_writer < m_reader) return (m_writer + m_size) - m_reader;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the amount of space available for writing, in samples.
|
||||
*/
|
||||
int getWriteSpace() const {
|
||||
int space = (m_reader + m_size - m_writer - 1);
|
||||
if (space >= m_size) space -= m_size;
|
||||
return space;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read one sample from the buffer. If no sample is available,
|
||||
* silently return zero.
|
||||
*/
|
||||
T readOne() {
|
||||
if (m_writer == m_reader) {
|
||||
return {};
|
||||
}
|
||||
auto value = m_buffer[m_reader];
|
||||
if (++m_reader == m_size) m_reader = 0;
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretend to read one sample from the buffer, without actually
|
||||
* returning it (i.e. discard the next sample).
|
||||
*/
|
||||
void skipOne() {
|
||||
if (m_writer == m_reader) {
|
||||
return;
|
||||
}
|
||||
if (++m_reader == m_size) m_reader = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write one sample to the buffer. If insufficient space is
|
||||
* available, the sample will not be written. Returns the number
|
||||
* of samples actually written, i.e. 0 or 1.
|
||||
*/
|
||||
int writeOne(const T &value) {
|
||||
if (getWriteSpace() == 0) return 0;
|
||||
m_buffer[m_writer] = value;
|
||||
if (++m_writer == m_size) m_writer = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::vector<T> m_buffer;
|
||||
int m_writer;
|
||||
int m_reader;
|
||||
int m_size;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
791
src/common/StretchCalculator.cpp
Normal file
791
src/common/StretchCalculator.cpp
Normal file
@@ -0,0 +1,791 @@
|
||||
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||
|
||||
/*
|
||||
Rubber Band Library
|
||||
An audio time-stretching and pitch-shifting library.
|
||||
Copyright 2007-2022 Particular Programs Ltd.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version. See the file
|
||||
COPYING included with this distribution for more information.
|
||||
|
||||
Alternatively, if you have a valid commercial licence for the
|
||||
Rubber Band Library obtained by agreement with the copyright
|
||||
holders, you may redistribute and/or modify it under the terms
|
||||
described in that licence.
|
||||
|
||||
If you wish to distribute code using the Rubber Band Library
|
||||
under terms other than those of the GNU General Public License,
|
||||
you must obtain a valid commercial licence before doing so.
|
||||
*/
|
||||
|
||||
#include "StretchCalculator.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#include "sysutils.h"
|
||||
|
||||
namespace RubberBand
|
||||
{
|
||||
|
||||
StretchCalculator::StretchCalculator(size_t sampleRate,
|
||||
size_t inputIncrement,
|
||||
bool useHardPeaks,
|
||||
Log log) :
|
||||
m_sampleRate(sampleRate),
|
||||
m_increment(inputIncrement),
|
||||
m_prevDf(0),
|
||||
m_prevRatio(1.0),
|
||||
m_prevTimeRatio(1.0),
|
||||
m_justReset(true),
|
||||
m_transientAmnesty(0),
|
||||
m_debugLevel(0),
|
||||
m_useHardPeaks(useHardPeaks),
|
||||
m_inFrameCounter(0),
|
||||
m_frameCheckpoint(0, 0),
|
||||
m_outFrameCounter(0),
|
||||
m_log(log)
|
||||
{
|
||||
m_log.log(2, "StretchCalculator: useHardPeaks", useHardPeaks);
|
||||
}
|
||||
|
||||
StretchCalculator::~StretchCalculator()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
StretchCalculator::setKeyFrameMap(const std::map<size_t, size_t> &mapping)
|
||||
{
|
||||
m_keyFrameMap = mapping;
|
||||
|
||||
// Ensure we always have a 0 -> 0 mapping. If there's nothing in
|
||||
// the map at all, don't need to worry about this (empty map is
|
||||
// handled separately anyway)
|
||||
if (!m_keyFrameMap.empty()) {
|
||||
if (m_keyFrameMap.find(0) == m_keyFrameMap.end()) {
|
||||
m_keyFrameMap[0] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int>
|
||||
StretchCalculator::calculate(double ratio, size_t inputDuration,
|
||||
const std::vector<float> &phaseResetDf)
|
||||
{
|
||||
m_peaks = findPeaks(phaseResetDf);
|
||||
|
||||
size_t totalCount = phaseResetDf.size();
|
||||
|
||||
size_t outputDuration = lrint(inputDuration * ratio);
|
||||
|
||||
m_log.log(1, "StretchCalculator::calculate: inputDuration and ratio", inputDuration, ratio);
|
||||
|
||||
outputDuration = lrint((phaseResetDf.size() * m_increment) * ratio);
|
||||
|
||||
m_log.log(1, "StretchCalculator::calculate: outputDuration rounds up from and to", inputDuration * ratio, outputDuration);
|
||||
m_log.log(1, "StretchCalculator::calculate: df size and increment", phaseResetDf.size(), m_increment);
|
||||
|
||||
std::vector<Peak> peaks; // peak position (in chunks) and hardness
|
||||
std::vector<size_t> targets; // targets for mapping peaks (in samples)
|
||||
mapPeaks(peaks, targets, outputDuration, totalCount);
|
||||
|
||||
m_log.log(2, "have fixed positions", peaks.size());
|
||||
|
||||
size_t totalInput = 0, totalOutput = 0;
|
||||
|
||||
std::vector<int> increments;
|
||||
|
||||
for (size_t i = 0; i <= peaks.size(); ++i) {
|
||||
|
||||
size_t regionStart, regionStartChunk, regionEnd, regionEndChunk;
|
||||
bool phaseReset = false;
|
||||
|
||||
if (i == 0) {
|
||||
regionStartChunk = 0;
|
||||
regionStart = 0;
|
||||
} else {
|
||||
regionStartChunk = peaks[i-1].chunk;
|
||||
regionStart = targets[i-1];
|
||||
phaseReset = peaks[i-1].hard;
|
||||
}
|
||||
|
||||
if (i == peaks.size()) {
|
||||
regionEndChunk = totalCount;
|
||||
regionEnd = outputDuration;
|
||||
} else {
|
||||
regionEndChunk = peaks[i].chunk;
|
||||
regionEnd = targets[i];
|
||||
}
|
||||
|
||||
if (regionStartChunk > totalCount) regionStartChunk = totalCount;
|
||||
if (regionStart > outputDuration) regionStart = outputDuration;
|
||||
if (regionEndChunk > totalCount) regionEndChunk = totalCount;
|
||||
if (regionEnd > outputDuration) regionEnd = outputDuration;
|
||||
|
||||
if (regionEndChunk < regionStartChunk) regionEndChunk = regionStartChunk;
|
||||
if (regionEnd < regionStart) regionEnd = regionStart;
|
||||
|
||||
size_t regionDuration = regionEnd - regionStart;
|
||||
|
||||
size_t nchunks = regionEndChunk - regionStartChunk;
|
||||
|
||||
m_log.log(2, "region from and to (chunks)", regionStartChunk, regionEndChunk);
|
||||
m_log.log(2, "region from and to (samples)", regionStart, regionEnd);
|
||||
|
||||
if (nchunks == 0) {
|
||||
m_log.log(2, "note: nchunks == 0");
|
||||
continue;
|
||||
}
|
||||
|
||||
double per = double(regionDuration) / double(nchunks);
|
||||
double acc = 0.0;
|
||||
size_t nremaining = nchunks;
|
||||
size_t totalForRegion = 0;
|
||||
|
||||
if (phaseReset) {
|
||||
size_t incr;
|
||||
if (nchunks > 1) {
|
||||
incr = m_increment;
|
||||
if (incr > regionDuration) {
|
||||
incr = regionDuration;
|
||||
}
|
||||
} else {
|
||||
incr = regionDuration;
|
||||
}
|
||||
increments.push_back(- int64_t(incr));
|
||||
per = double(regionDuration - incr) / double(nchunks - 1);
|
||||
acc += incr;
|
||||
totalForRegion += incr;
|
||||
totalInput += m_increment;
|
||||
nremaining = nremaining - 1;
|
||||
}
|
||||
|
||||
if (nremaining > 0) {
|
||||
for (size_t j = 0; j+1 < nremaining; ++j) {
|
||||
acc += per;
|
||||
size_t incr = size_t(round(acc - totalForRegion));
|
||||
increments.push_back(incr);
|
||||
totalForRegion += incr;
|
||||
totalInput += m_increment;
|
||||
}
|
||||
if (regionDuration > totalForRegion) {
|
||||
size_t final = regionDuration - totalForRegion;
|
||||
increments.push_back(final);
|
||||
totalForRegion += final;
|
||||
totalInput += m_increment;
|
||||
}
|
||||
}
|
||||
|
||||
totalOutput += totalForRegion;
|
||||
}
|
||||
|
||||
m_log.log(1, "total input (frames, chunks)", totalInput, totalInput / m_increment);
|
||||
m_log.log(1, "total output and achieved ratio", totalOutput, double(totalOutput)/double(totalInput));
|
||||
m_log.log(1, "ideal output", totalInput * ratio);
|
||||
|
||||
return increments;
|
||||
}
|
||||
|
||||
void
|
||||
StretchCalculator::mapPeaks(std::vector<Peak> &peaks,
|
||||
std::vector<size_t> &targets,
|
||||
size_t outputDuration,
|
||||
size_t totalCount)
|
||||
{
|
||||
// outputDuration is in audio samples; totalCount is in chunks
|
||||
|
||||
if (m_keyFrameMap.empty()) {
|
||||
// "normal" behaviour -- fixed points are strictly in
|
||||
// proportion
|
||||
peaks = m_peaks;
|
||||
for (size_t i = 0; i < peaks.size(); ++i) {
|
||||
targets.push_back
|
||||
(lrint((double(peaks[i].chunk) * outputDuration) / totalCount));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// We have been given a set of source -> target sample frames in
|
||||
// m_keyFrameMap. We want to ensure that (to the nearest chunk) these
|
||||
// are followed exactly, and any fixed points that we calculated
|
||||
// ourselves are interpolated in linear proportion in between.
|
||||
|
||||
size_t peakidx = 0;
|
||||
std::map<size_t, size_t>::const_iterator mi = m_keyFrameMap.begin();
|
||||
|
||||
// NB we know for certain we have a mapping from 0 -> 0 (or at
|
||||
// least, some mapping for source sample 0) because that is
|
||||
// enforced in setKeyFrameMap above. However, we aren't guaranteed
|
||||
// to have a mapping for the total duration -- we will usually
|
||||
// need to assume it maps to the normal duration * ratio sample
|
||||
|
||||
while (mi != m_keyFrameMap.end()) {
|
||||
|
||||
// The map we've been given is from sample to sample, but
|
||||
// we can only map from chunk to sample. We should perhaps
|
||||
// adjust the target sample to compensate for the discrepancy
|
||||
// between the chunk position and the exact requested source
|
||||
// sample. But we aren't doing that yet.
|
||||
|
||||
size_t sourceStartChunk = mi->first / m_increment;
|
||||
size_t sourceEndChunk = totalCount;
|
||||
|
||||
size_t targetStartSample = mi->second;
|
||||
size_t targetEndSample = outputDuration;
|
||||
|
||||
++mi;
|
||||
if (mi != m_keyFrameMap.end()) {
|
||||
sourceEndChunk = mi->first / m_increment;
|
||||
targetEndSample = mi->second;
|
||||
}
|
||||
|
||||
if (sourceStartChunk >= totalCount ||
|
||||
sourceStartChunk >= sourceEndChunk ||
|
||||
targetStartSample >= outputDuration ||
|
||||
targetStartSample >= targetEndSample) {
|
||||
m_log.log(0, "NOTE: ignoring key-frame mapping from chunk to sample", sourceStartChunk, targetStartSample);
|
||||
m_log.log(0, "(source or target chunk exceeds total count, or end is not later than start)");
|
||||
continue;
|
||||
}
|
||||
|
||||
// one peak and target for the mapping, then one for each of
|
||||
// the computed peaks that appear before the following mapping
|
||||
|
||||
Peak p;
|
||||
p.chunk = sourceStartChunk;
|
||||
p.hard = false; // mappings are in time only, not phase reset points
|
||||
peaks.push_back(p);
|
||||
targets.push_back(targetStartSample);
|
||||
|
||||
m_log.log(2, "mapped key-frame chunk to frame", sourceStartChunk, targetStartSample);
|
||||
|
||||
while (peakidx < m_peaks.size()) {
|
||||
|
||||
size_t pchunk = m_peaks[peakidx].chunk;
|
||||
|
||||
if (pchunk < sourceStartChunk) {
|
||||
// shouldn't happen, should have been dealt with
|
||||
// already -- but no harm in ignoring it explicitly
|
||||
++peakidx;
|
||||
continue;
|
||||
}
|
||||
if (pchunk == sourceStartChunk) {
|
||||
// convert that last peak to a hard one, after all
|
||||
peaks[peaks.size()-1].hard = true;
|
||||
++peakidx;
|
||||
continue;
|
||||
}
|
||||
if (pchunk >= sourceEndChunk) {
|
||||
// leave the rest for after the next mapping
|
||||
break;
|
||||
}
|
||||
p.chunk = pchunk;
|
||||
p.hard = m_peaks[peakidx].hard;
|
||||
|
||||
double proportion =
|
||||
double(pchunk - sourceStartChunk) /
|
||||
double(sourceEndChunk - sourceStartChunk);
|
||||
|
||||
size_t target =
|
||||
targetStartSample +
|
||||
lrint(proportion *
|
||||
(targetEndSample - targetStartSample));
|
||||
|
||||
if (target <= targets[targets.size()-1] + m_increment) {
|
||||
// peaks will become too close together afterwards, ignore
|
||||
++peakidx;
|
||||
continue;
|
||||
}
|
||||
|
||||
m_log.log(2, "mapped peak chunk to frame", pchunk, target);
|
||||
|
||||
peaks.push_back(p);
|
||||
targets.push_back(target);
|
||||
++peakidx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int64_t
|
||||
StretchCalculator::expectedOutFrame(int64_t inFrame, double timeRatio)
|
||||
{
|
||||
int64_t checkpointedAt = m_frameCheckpoint.first;
|
||||
int64_t checkpointed = m_frameCheckpoint.second;
|
||||
return int64_t(round(checkpointed + (inFrame - checkpointedAt) * timeRatio));
|
||||
}
|
||||
|
||||
int
|
||||
StretchCalculator::calculateSingle(double timeRatio,
|
||||
double effectivePitchRatio,
|
||||
float df,
|
||||
size_t inIncrement,
|
||||
size_t analysisWindowSize,
|
||||
size_t synthesisWindowSize,
|
||||
bool alignFrameStarts)
|
||||
{
|
||||
double ratio = timeRatio / effectivePitchRatio;
|
||||
|
||||
int increment = int(inIncrement);
|
||||
if (increment == 0) increment = m_increment;
|
||||
|
||||
int outIncrement = lrint(increment * ratio); // the normal case
|
||||
bool isTransient = false;
|
||||
|
||||
// We want to ensure, as close as possible, that the phase reset
|
||||
// points appear at the right audio frame numbers. To this end we
|
||||
// track the incoming frame number, its corresponding expected
|
||||
// output frame number, and the actual output frame number
|
||||
// projected based on the ratios provided.
|
||||
//
|
||||
// There are two subtleties:
|
||||
//
|
||||
// (1) on a ratio change, we need to checkpoint the expected
|
||||
// output frame number reached so far and start counting again
|
||||
// with the new ratio. We could do this with a reset to zero, but
|
||||
// it's easier to reason about absolute input/output frame
|
||||
// matches, so for the moment at least we're doing this by
|
||||
// explicitly checkpointing the current numbers (hence the use of
|
||||
// the above expectedOutFrame() function which refers to the
|
||||
// last checkpointed values).
|
||||
//
|
||||
// (2) in the case of a pitch shift in a configuration where
|
||||
// resampling occurs after stretching, all of our output
|
||||
// increments will be effectively modified by resampling after we
|
||||
// return. This is why we separate out timeRatio and
|
||||
// effectivePitchRatio arguments - the former is the ratio that
|
||||
// has already been applied and the latter is the ratio that will
|
||||
// be applied by any subsequent resampling step (which will be 1.0
|
||||
// / pitchScale if resampling is happening after stretching). So
|
||||
// the overall ratio is timeRatio / effectivePitchRatio.
|
||||
|
||||
bool ratioChanged = (!m_justReset) && (ratio != m_prevRatio);
|
||||
m_justReset = false;
|
||||
|
||||
if (ratioChanged) {
|
||||
// Reset our frame counters from the ratio change.
|
||||
|
||||
// m_outFrameCounter tracks the frames counted at output from
|
||||
// this function, which normally precedes resampling - hence
|
||||
// the use of timeRatio rather than ratio here
|
||||
|
||||
m_log.log(2, "StretchCalculator: ratio changed from and to", m_prevRatio, ratio);
|
||||
|
||||
int64_t toCheckpoint = expectedOutFrame
|
||||
(m_inFrameCounter, m_prevTimeRatio);
|
||||
m_frameCheckpoint =
|
||||
std::pair<int64_t, int64_t>(m_inFrameCounter, toCheckpoint);
|
||||
}
|
||||
|
||||
m_prevRatio = ratio;
|
||||
m_prevTimeRatio = timeRatio;
|
||||
|
||||
if (m_log.getDebugLevel() > 2) {
|
||||
std::ostringstream os;
|
||||
os << "StretchCalculator::calculateSingle: timeRatio = "
|
||||
<< timeRatio << ", effectivePitchRatio = "
|
||||
<< effectivePitchRatio << " (that's 1.0 / "
|
||||
<< (1.0 / effectivePitchRatio)
|
||||
<< "), ratio = " << ratio << ", df = " << df
|
||||
<< ", inIncrement = " << inIncrement
|
||||
<< ", default outIncrement = " << outIncrement
|
||||
<< ", analysisWindowSize = " << analysisWindowSize
|
||||
<< ", synthesisWindowSize = " << synthesisWindowSize
|
||||
<< "\n";
|
||||
|
||||
os << "inFrameCounter = " << m_inFrameCounter
|
||||
<< ", outFrameCounter = " << m_outFrameCounter
|
||||
<< "\n";
|
||||
|
||||
os << "The next sample out is input sample " << m_inFrameCounter << "\n";
|
||||
m_log.log(3, os.str().c_str());
|
||||
}
|
||||
|
||||
int64_t intended, projected;
|
||||
if (alignFrameStarts) { // R3
|
||||
intended = expectedOutFrame(m_inFrameCounter, timeRatio);
|
||||
projected =
|
||||
int64_t(round(m_outFrameCounter));
|
||||
} else { // R2
|
||||
intended = expectedOutFrame
|
||||
(m_inFrameCounter + analysisWindowSize/4, timeRatio);
|
||||
projected =
|
||||
int64_t(round(m_outFrameCounter +
|
||||
(synthesisWindowSize/4 * effectivePitchRatio)));
|
||||
}
|
||||
|
||||
int64_t divergence = projected - intended;
|
||||
|
||||
m_log.log(3, "for current frame + quarter frame: intended vs projected", intended, projected);
|
||||
m_log.log(3, "divergence", divergence);
|
||||
|
||||
// In principle, the threshold depends on chunk size: larger chunk
|
||||
// sizes need higher thresholds. Since chunk size depends on
|
||||
// ratio, I suppose we could in theory calculate the threshold
|
||||
// from the ratio directly. For the moment we're happy if it
|
||||
// works well in common situations.
|
||||
|
||||
float transientThreshold = 0.35f;
|
||||
// if (ratio > 1) transientThreshold = 0.25f;
|
||||
|
||||
if (m_useHardPeaks && df > m_prevDf * 1.1f && df > transientThreshold) {
|
||||
if (divergence > 1000 || divergence < -1000) {
|
||||
m_log.log(2, "StretchCalculator::calculateSingle: transient, but we're not permitting it because the divergence is too great", divergence);
|
||||
} else {
|
||||
isTransient = true;
|
||||
}
|
||||
}
|
||||
|
||||
m_log.log(3, "df and prevDf", df, m_prevDf);
|
||||
|
||||
m_prevDf = df;
|
||||
|
||||
if (m_transientAmnesty > 0) {
|
||||
if (isTransient) {
|
||||
m_log.log(2, "StretchCalculator::calculateSingle: transient, but we have an amnesty: df and threshold", df, transientThreshold);
|
||||
isTransient = false;
|
||||
}
|
||||
--m_transientAmnesty;
|
||||
}
|
||||
|
||||
if (isTransient) {
|
||||
m_log.log(2, "StretchCalculator::calculateSingle: transient: df and threshold", df, transientThreshold);
|
||||
|
||||
// as in offline mode, 0.05 sec approx min between transients
|
||||
m_transientAmnesty =
|
||||
lrint(ceil(double(m_sampleRate) / (20 * double(increment))));
|
||||
|
||||
outIncrement = increment;
|
||||
|
||||
} else {
|
||||
|
||||
double recovery = 0.0;
|
||||
if (divergence > 1000 || divergence < -1000) {
|
||||
recovery = divergence / ((m_sampleRate / 10.0) / increment);
|
||||
} else if (divergence > 100 || divergence < -100) {
|
||||
recovery = divergence / ((m_sampleRate / 20.0) / increment);
|
||||
} else {
|
||||
recovery = divergence / 4.0;
|
||||
}
|
||||
|
||||
int incr = lrint(outIncrement - recovery);
|
||||
|
||||
int level = (divergence != 0 ? 2 : 3);
|
||||
m_log.log(level, "divergence and recovery", divergence, recovery);
|
||||
m_log.log(level, "outIncrement and adjusted incr", outIncrement, incr);
|
||||
|
||||
int minIncr = lrint(increment * ratio * 0.3);
|
||||
int maxIncr = lrint(increment * ratio * 2);
|
||||
|
||||
if (incr < minIncr) {
|
||||
incr = minIncr;
|
||||
} else if (incr > maxIncr) {
|
||||
incr = maxIncr;
|
||||
}
|
||||
|
||||
m_log.log(level, "clamped into", minIncr, maxIncr);
|
||||
m_log.log(level, "giving incr", incr);
|
||||
|
||||
if (incr < 0) {
|
||||
m_log.log(0, "WARNING: internal error: incr < 0 in calculateSingle");
|
||||
outIncrement = 0;
|
||||
} else {
|
||||
outIncrement = incr;
|
||||
}
|
||||
}
|
||||
|
||||
m_log.log(2, "StretchCalculator::calculateSingle: returning isTransient and outIncrement", isTransient, outIncrement);
|
||||
|
||||
m_inFrameCounter += inIncrement;
|
||||
m_outFrameCounter += outIncrement * effectivePitchRatio;
|
||||
|
||||
if (isTransient) {
|
||||
return -outIncrement;
|
||||
} else {
|
||||
return outIncrement;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StretchCalculator::reset()
|
||||
{
|
||||
m_prevDf = 0;
|
||||
m_prevRatio = 1.0;
|
||||
m_prevTimeRatio = 1.0;
|
||||
m_inFrameCounter = 0;
|
||||
m_frameCheckpoint = std::pair<int64_t, int64_t>(0, 0);
|
||||
m_outFrameCounter = 0.0;
|
||||
m_transientAmnesty = 0;
|
||||
m_keyFrameMap.clear();
|
||||
|
||||
m_justReset = true;
|
||||
}
|
||||
|
||||
std::vector<StretchCalculator::Peak>
|
||||
StretchCalculator::findPeaks(const std::vector<float> &rawDf)
|
||||
{
|
||||
std::vector<float> df = smoothDF(rawDf);
|
||||
|
||||
// We distinguish between "soft" and "hard" peaks. A soft peak is
|
||||
// simply the result of peak-picking on the smoothed onset
|
||||
// detection function, and it represents any (strong-ish) onset.
|
||||
// We aim to ensure always that soft peaks are placed at the
|
||||
// correct position in time. A hard peak is where there is a very
|
||||
// rapid rise in detection function, and it presumably represents
|
||||
// a more broadband, noisy transient. For these we perform a
|
||||
// phase reset (if in the appropriate mode), and we locate the
|
||||
// reset at the first point where we notice enough of a rapid
|
||||
// rise, rather than necessarily at the peak itself, in order to
|
||||
// preserve the shape of the transient.
|
||||
|
||||
std::set<size_t> hardPeakCandidates;
|
||||
std::set<size_t> softPeakCandidates;
|
||||
|
||||
if (m_useHardPeaks) {
|
||||
|
||||
// 0.05 sec approx min between hard peaks
|
||||
size_t hardPeakAmnesty = lrint(ceil(double(m_sampleRate) /
|
||||
(20 * double(m_increment))));
|
||||
size_t prevHardPeak = 0;
|
||||
|
||||
m_log.log(2, "hardPeakAmnesty", hardPeakAmnesty);
|
||||
|
||||
for (size_t i = 1; i + 1 < df.size(); ++i) {
|
||||
|
||||
if (df[i] < 0.1) continue;
|
||||
if (df[i] <= df[i-1] * 1.1) continue;
|
||||
if (df[i] < 0.22) continue;
|
||||
|
||||
if (!hardPeakCandidates.empty() &&
|
||||
i < prevHardPeak + hardPeakAmnesty) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool hard = (df[i] > 0.4);
|
||||
|
||||
if (hard) {
|
||||
m_log.log(2, "hard peak, df > absolute 0.4: chunk and df", i, df[i]);
|
||||
}
|
||||
|
||||
if (!hard) {
|
||||
hard = (df[i] > df[i-1] * 1.4);
|
||||
|
||||
if (hard) {
|
||||
m_log.log(2, "hard peak, single rise of 40%: chunk and df", i, df[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hard && i > 1) {
|
||||
hard = (df[i] > df[i-1] * 1.2 &&
|
||||
df[i-1] > df[i-2] * 1.2);
|
||||
|
||||
if (hard) {
|
||||
m_log.log(2, "hard peak, two rises of 20%: chunk and df", i, df[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hard && i > 2) {
|
||||
// have already established that df[i] > df[i-1] * 1.1
|
||||
hard = (df[i] > 0.3 &&
|
||||
df[i-1] > df[i-2] * 1.1 &&
|
||||
df[i-2] > df[i-3] * 1.1);
|
||||
|
||||
if (hard) {
|
||||
m_log.log(2, "hard peak, three rises of 10%: chunk and df", i, df[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hard) continue;
|
||||
|
||||
size_t peakLocation = i;
|
||||
|
||||
if (i + 1 < rawDf.size() &&
|
||||
rawDf[i + 1] > rawDf[i] * 1.4) {
|
||||
|
||||
++peakLocation;
|
||||
|
||||
m_log.log(2, "big rise next, pushing hard peak forward to", peakLocation);
|
||||
}
|
||||
|
||||
hardPeakCandidates.insert(peakLocation);
|
||||
prevHardPeak = peakLocation;
|
||||
}
|
||||
}
|
||||
|
||||
size_t medianmaxsize = lrint(ceil(double(m_sampleRate) /
|
||||
double(m_increment))); // 1 sec ish
|
||||
|
||||
m_log.log(2, "mediansize", medianmaxsize);
|
||||
if (medianmaxsize < 7) {
|
||||
medianmaxsize = 7;
|
||||
m_log.log(2, "adjusted mediansize", medianmaxsize);
|
||||
}
|
||||
|
||||
int minspacing = lrint(ceil(double(m_sampleRate) /
|
||||
(20 * double(m_increment)))); // 0.05 sec ish
|
||||
|
||||
std::deque<float> medianwin;
|
||||
std::vector<float> sorted;
|
||||
int softPeakAmnesty = 0;
|
||||
|
||||
for (size_t i = 0; i < medianmaxsize/2; ++i) {
|
||||
medianwin.push_back(0);
|
||||
}
|
||||
for (size_t i = 0; i < medianmaxsize/2 && i < df.size(); ++i) {
|
||||
medianwin.push_back(df[i]);
|
||||
}
|
||||
|
||||
size_t lastSoftPeak = 0;
|
||||
|
||||
for (size_t i = 0; i < df.size(); ++i) {
|
||||
|
||||
size_t mediansize = medianmaxsize;
|
||||
|
||||
if (medianwin.size() < mediansize) {
|
||||
mediansize = medianwin.size();
|
||||
}
|
||||
|
||||
size_t middle = medianmaxsize / 2;
|
||||
if (middle >= mediansize) middle = mediansize-1;
|
||||
|
||||
size_t nextDf = i + mediansize - middle;
|
||||
|
||||
if (mediansize < 2) {
|
||||
if (mediansize > medianmaxsize) { // absurd, but never mind that
|
||||
medianwin.pop_front();
|
||||
}
|
||||
if (nextDf < df.size()) {
|
||||
medianwin.push_back(df[nextDf]);
|
||||
} else {
|
||||
medianwin.push_back(0);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
sorted.clear();
|
||||
for (size_t j = 0; j < mediansize; ++j) {
|
||||
sorted.push_back(medianwin[j]);
|
||||
}
|
||||
std::sort(sorted.begin(), sorted.end());
|
||||
|
||||
size_t n = 90; // percentile above which we pick peaks
|
||||
size_t index = (sorted.size() * n) / 100;
|
||||
if (index >= sorted.size()) index = sorted.size()-1;
|
||||
if (index == sorted.size()-1 && index > 0) --index;
|
||||
float thresh = sorted[index];
|
||||
|
||||
if (medianwin[middle] > thresh &&
|
||||
medianwin[middle] > medianwin[middle-1] &&
|
||||
medianwin[middle] > medianwin[middle+1] &&
|
||||
softPeakAmnesty == 0) {
|
||||
|
||||
size_t maxindex = middle;
|
||||
float maxval = medianwin[middle];
|
||||
|
||||
for (size_t j = middle+1; j < mediansize; ++j) {
|
||||
if (medianwin[j] > maxval) {
|
||||
maxval = medianwin[j];
|
||||
maxindex = j;
|
||||
} else if (medianwin[j] < medianwin[middle]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
size_t peak = i + maxindex - middle;
|
||||
|
||||
if (softPeakCandidates.empty() || lastSoftPeak != peak) {
|
||||
m_log.log(2, "soft peak: chunk and median df", peak, medianwin[middle]);
|
||||
if (peak >= df.size()) {
|
||||
m_log.log(2, "peak is beyond end");
|
||||
} else {
|
||||
softPeakCandidates.insert(peak);
|
||||
lastSoftPeak = peak;
|
||||
}
|
||||
}
|
||||
|
||||
softPeakAmnesty = minspacing + maxindex - middle;
|
||||
m_log.log(3, "amnesty", softPeakAmnesty);
|
||||
|
||||
} else if (softPeakAmnesty > 0) --softPeakAmnesty;
|
||||
|
||||
if (mediansize >= medianmaxsize) {
|
||||
medianwin.pop_front();
|
||||
}
|
||||
if (nextDf < df.size()) {
|
||||
medianwin.push_back(df[nextDf]);
|
||||
} else {
|
||||
medianwin.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Peak> peaks;
|
||||
|
||||
while (!hardPeakCandidates.empty() || !softPeakCandidates.empty()) {
|
||||
|
||||
bool haveHardPeak = !hardPeakCandidates.empty();
|
||||
bool haveSoftPeak = !softPeakCandidates.empty();
|
||||
|
||||
size_t hardPeak = (haveHardPeak ? *hardPeakCandidates.begin() : 0);
|
||||
size_t softPeak = (haveSoftPeak ? *softPeakCandidates.begin() : 0);
|
||||
|
||||
Peak peak;
|
||||
peak.hard = false;
|
||||
peak.chunk = softPeak;
|
||||
|
||||
bool ignore = false;
|
||||
|
||||
if (haveHardPeak &&
|
||||
(!haveSoftPeak || hardPeak <= softPeak)) {
|
||||
m_log.log(3, "hard peak", hardPeak);
|
||||
peak.hard = true;
|
||||
peak.chunk = hardPeak;
|
||||
hardPeakCandidates.erase(hardPeakCandidates.begin());
|
||||
} else {
|
||||
m_log.log(3, "soft peak", softPeak);
|
||||
if (!peaks.empty() &&
|
||||
peaks[peaks.size()-1].hard &&
|
||||
peaks[peaks.size()-1].chunk + 3 >= softPeak) {
|
||||
m_log.log(3, "ignoring, as we just had a hard peak");
|
||||
ignore = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (haveSoftPeak && peak.chunk == softPeak) {
|
||||
softPeakCandidates.erase(softPeakCandidates.begin());
|
||||
}
|
||||
|
||||
if (!ignore) {
|
||||
peaks.push_back(peak);
|
||||
}
|
||||
}
|
||||
|
||||
return peaks;
|
||||
}
|
||||
|
||||
std::vector<float>
|
||||
StretchCalculator::smoothDF(const std::vector<float> &df)
|
||||
{
|
||||
std::vector<float> smoothedDF;
|
||||
|
||||
for (size_t i = 0; i < df.size(); ++i) {
|
||||
// three-value moving mean window for simple smoothing
|
||||
float total = 0.f, count = 0;
|
||||
if (i > 0) { total += df[i-1]; ++count; }
|
||||
total += df[i]; ++count;
|
||||
if (i+1 < df.size()) { total += df[i+1]; ++count; }
|
||||
float mean = total / count;
|
||||
smoothedDF.push_back(mean);
|
||||
}
|
||||
|
||||
return smoothedDF;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,13 +30,18 @@
|
||||
#include <map>
|
||||
#include <cstdint>
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
namespace RubberBand
|
||||
{
|
||||
|
||||
class StretchCalculator
|
||||
{
|
||||
public:
|
||||
StretchCalculator(size_t sampleRate, size_t inputIncrement, bool useHardPeaks);
|
||||
StretchCalculator(size_t sampleRate,
|
||||
size_t inputIncrement,
|
||||
bool useHardPeaks,
|
||||
Log log);
|
||||
virtual ~StretchCalculator();
|
||||
|
||||
/**
|
||||
@@ -51,13 +56,10 @@ public:
|
||||
/**
|
||||
* Calculate phase increments for a region of audio, given the
|
||||
* overall target stretch ratio, input duration in audio samples,
|
||||
* and the audio curves to use for identifying phase lock points
|
||||
* (lockAudioCurve) and for allocating stretches to relatively
|
||||
* less prominent points (stretchAudioCurve).
|
||||
* and the audio curves to use for identifying phase lock points.
|
||||
*/
|
||||
std::vector<int> calculate(double ratio, size_t inputDuration,
|
||||
const std::vector<float> &lockAudioCurve,
|
||||
const std::vector<float> &stretchAudioCurve);
|
||||
const std::vector<float> &lockAudioCurve);
|
||||
|
||||
/**
|
||||
* Calculate the phase increment for a single audio block, given
|
||||
@@ -74,7 +76,8 @@ public:
|
||||
float curveValue,
|
||||
size_t increment,
|
||||
size_t analysisWindowSize,
|
||||
size_t synthesisWindowSize);
|
||||
size_t synthesisWindowSize,
|
||||
bool alignFrameStarts);
|
||||
|
||||
void setUseHardPeaks(bool use) { m_useHardPeaks = use; }
|
||||
|
||||
@@ -96,21 +99,12 @@ protected:
|
||||
void mapPeaks(std::vector<Peak> &peaks, std::vector<size_t> &targets,
|
||||
size_t outputDuration, size_t totalCount);
|
||||
|
||||
std::vector<int> distributeRegion(const std::vector<float> ®ionCurve,
|
||||
size_t outputDuration, float ratio,
|
||||
bool phaseReset);
|
||||
|
||||
void calculateDisplacements(const std::vector<float> &df,
|
||||
float &maxDf,
|
||||
double &totalDisplacement,
|
||||
double &maxDisplacement,
|
||||
float adj) const;
|
||||
|
||||
size_t m_sampleRate;
|
||||
size_t m_increment;
|
||||
float m_prevDf;
|
||||
double m_prevRatio;
|
||||
double m_prevTimeRatio;
|
||||
bool m_justReset;
|
||||
int m_transientAmnesty; // only in RT mode; handled differently offline
|
||||
int m_debugLevel;
|
||||
bool m_useHardPeaks;
|
||||
@@ -118,6 +112,7 @@ protected:
|
||||
std::pair<int64_t, int64_t> m_frameCheckpoint;
|
||||
int64_t expectedOutFrame(int64_t inFrame, double timeRatio);
|
||||
double m_outFrameCounter;
|
||||
Log m_log;
|
||||
|
||||
std::map<size_t, size_t> m_keyFrameMap;
|
||||
std::vector<Peak> m_peaks;
|
||||
@@ -33,8 +33,6 @@ namespace RubberBand {
|
||||
template<typename T>
|
||||
inline void c_phasor(T *real, T *imag, T phase)
|
||||
{
|
||||
//!!! IPP contains ippsSinCos_xxx in ippvm.h -- these are
|
||||
//!!! fixed-accuracy, test and compare
|
||||
#if defined HAVE_VDSP
|
||||
int one = 1;
|
||||
if (sizeof(T) == sizeof(float)) {
|
||||
@@ -28,9 +28,9 @@
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
|
||||
#include "../system/sysutils.h"
|
||||
#include "../system/VectorOps.h"
|
||||
#include "../system/Allocators.h"
|
||||
#include "sysutils.h"
|
||||
#include "VectorOps.h"
|
||||
#include "Allocators.h"
|
||||
|
||||
namespace RubberBand {
|
||||
|
||||
@@ -38,12 +38,14 @@ enum WindowType {
|
||||
RectangularWindow,
|
||||
BartlettWindow,
|
||||
HammingWindow,
|
||||
HanningWindow,
|
||||
HannWindow,
|
||||
BlackmanWindow,
|
||||
GaussianWindow,
|
||||
ParzenWindow,
|
||||
NuttallWindow,
|
||||
BlackmanHarrisWindow
|
||||
BlackmanHarrisWindow,
|
||||
NiemitaloForwardWindow,
|
||||
NiemitaloReverseWindow
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@@ -79,6 +81,10 @@ public:
|
||||
v_multiply(dst, src, m_cache, m_size);
|
||||
}
|
||||
|
||||
inline void cutAndAdd(const T *const R__ src, T *const R__ dst) const {
|
||||
v_multiply_and_add(dst, src, m_cache, m_size);
|
||||
}
|
||||
|
||||
inline void add(T *const R__ dst, T scale) const {
|
||||
v_add_with_gain(dst, m_cache, scale, m_size);
|
||||
}
|
||||
@@ -105,7 +111,7 @@ protected:
|
||||
T m_area;
|
||||
|
||||
void encache();
|
||||
void cosinewin(T *, T, T, T, T);
|
||||
void cosinewin(T *, double, double, double, double);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@@ -136,7 +142,7 @@ void Window<T>::encache()
|
||||
cosinewin(m_cache, 0.54, 0.46, 0.0, 0.0);
|
||||
break;
|
||||
|
||||
case HanningWindow:
|
||||
case HannWindow:
|
||||
cosinewin(m_cache, 0.50, 0.50, 0.0, 0.0);
|
||||
break;
|
||||
|
||||
@@ -174,6 +180,64 @@ void Window<T>::encache()
|
||||
case BlackmanHarrisWindow:
|
||||
cosinewin(m_cache, 0.35875, 0.48829, 0.14128, 0.01168);
|
||||
break;
|
||||
|
||||
case NiemitaloForwardWindow:
|
||||
case NiemitaloReverseWindow:
|
||||
{
|
||||
/* Interesting asymmetric window proposed by Olli Niemitalo.
|
||||
https://dsp.stackexchange.com/questions/2337/fft-with-asymmetric-windowing
|
||||
(Olli also writes "I cross-license all of my code and
|
||||
images in Stack Exchange under CC0 1.0" -
|
||||
https://dsp.stackexchange.com/users/15347/olli-niemitalo)
|
||||
*/
|
||||
int quarter = n/4;
|
||||
int eighth = n/8;
|
||||
int k = 0;
|
||||
for (int i = 0; i < n - eighth - quarter; ++i) {
|
||||
T x = 2.0 * M_PI *
|
||||
(((T(k + quarter) + 0.5) / T(n)) - 1.75);
|
||||
m_cache[k++] =
|
||||
2.57392230162633461887
|
||||
- 1.58661480271141974718 * cos(x)
|
||||
+ 3.80257516644523141380 * sin(x)
|
||||
- 1.93437090055110760822 * cos(2.0 * x)
|
||||
- 3.27163999159752183488 * sin(2.0 * x)
|
||||
+ 3.26617449847621266201 * cos(3.0 * x)
|
||||
- 0.30335261753524439543 * sin(3.0 * x)
|
||||
- 0.92126091064427817479 * cos(4.0 * x)
|
||||
+ 2.33100177294084742741 * sin(4.0 * x)
|
||||
- 1.19953922321306438725 * cos(5.0 * x)
|
||||
- 1.25098147932225423062 * sin(5.0 * x)
|
||||
+ 0.99132076607048635886 * cos(6.0 * x)
|
||||
- 0.34506787787355830410 * sin(6.0 * x)
|
||||
- 0.04028033685700077582 * cos(7.0 * x)
|
||||
+ 0.55461815542612269425 * sin(7.0 * x)
|
||||
- 0.21882110175036428856 * cos(8.0 * x)
|
||||
- 0.10756484378756643594 * sin(8.0 * x)
|
||||
+ 0.06025986430527170007 * cos(9.0 * x)
|
||||
- 0.05777077835678736534 * sin(9.0 * x)
|
||||
+ 0.00920984524892982936 * cos(10.0 * x)
|
||||
+ 0.01501989089735343216 * sin(10.0 * x);
|
||||
}
|
||||
for (int i = 0; i < eighth; ++i) {
|
||||
int j = eighth - 1 - i;
|
||||
m_cache[k++] =
|
||||
(1.0 - m_cache[n/2 - 1 - j] * m_cache[n/2 + j]) /
|
||||
m_cache[n/4 + j];
|
||||
}
|
||||
for (int i = 0; i < quarter; ++i) {
|
||||
m_cache[k++] = 0.0;
|
||||
}
|
||||
|
||||
if (m_type == NiemitaloReverseWindow) {
|
||||
for (int i = 0; i < n/2; ++i) {
|
||||
T tmp = m_cache[i];
|
||||
m_cache[i] = m_cache[n - i - 1];
|
||||
m_cache[n - i - 1] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
m_area = 0;
|
||||
@@ -184,14 +248,14 @@ void Window<T>::encache()
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Window<T>::cosinewin(T *mult, T a0, T a1, T a2, T a3)
|
||||
void Window<T>::cosinewin(T *mult, double a0, double a1, double a2, double a3)
|
||||
{
|
||||
int n = int(m_size);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
mult[i] *= (a0
|
||||
mult[i] = T(mult[i] * (a0
|
||||
- a1 * cos(2 * M_PI * i / n)
|
||||
+ a2 * cos(4 * M_PI * i / n)
|
||||
- a3 * cos(6 * M_PI * i / n));
|
||||
- a3 * cos(6 * M_PI * i / n)));
|
||||
}
|
||||
}
|
||||
|
||||
56
src/common/mathmisc.h
Normal file
56
src/common/mathmisc.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||
|
||||
/*
|
||||
Rubber Band Library
|
||||
An audio time-stretching and pitch-shifting library.
|
||||
Copyright 2007-2022 Particular Programs Ltd.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version. See the file
|
||||
COPYING included with this distribution for more information.
|
||||
|
||||
Alternatively, if you have a valid commercial licence for the
|
||||
Rubber Band Library obtained by agreement with the copyright
|
||||
holders, you may redistribute and/or modify it under the terms
|
||||
described in that licence.
|
||||
|
||||
If you wish to distribute code using the Rubber Band Library
|
||||
under terms other than those of the GNU General Public License,
|
||||
you must obtain a valid commercial licence before doing so.
|
||||
*/
|
||||
|
||||
#ifndef RUBBERBAND_MATHMISC_H
|
||||
#define RUBBERBAND_MATHMISC_H
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif // M_PI
|
||||
|
||||
namespace RubberBand {
|
||||
|
||||
inline double mod(double x, double y) {
|
||||
return x - (y * floor(x / y));
|
||||
}
|
||||
inline float modf(float x, float y) {
|
||||
return x - (y * float(floor(x / y)));
|
||||
}
|
||||
|
||||
inline double princarg(double a) {
|
||||
return mod(a + M_PI, -2.0 * M_PI) + M_PI;
|
||||
}
|
||||
inline float princargf(float a) {
|
||||
return modf(a + (float)M_PI, -2.f * (float)M_PI) + (float)M_PI;
|
||||
}
|
||||
|
||||
inline int binForFrequency(double f, int fftSize, double sampleRate) {
|
||||
return int(round(f * double(fftSize) / sampleRate));
|
||||
}
|
||||
inline double frequencyForBin(int b, int fftSize, double sampleRate) {
|
||||
return (double(b) * sampleRate) / double(fftSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#else /* !_WIN32 */
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#ifdef __APPLE__
|
||||
#include <sys/sysctl.h>
|
||||
@@ -165,11 +164,6 @@ void gettimeofday(struct timeval *tv, void *tz)
|
||||
tv->tv_sec = (long)((now.ns100 - 116444736000000000LL) / 10000000LL);
|
||||
}
|
||||
|
||||
void usleep(unsigned long usec)
|
||||
{
|
||||
::Sleep(usec == 0 ? 0 : usec < 1000 ? 1 : usec / 1000);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void system_specific_initialise()
|
||||
@@ -209,31 +203,6 @@ void system_specific_application_initialise()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ProcessStatus
|
||||
system_get_process_status(int pid)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
|
||||
if (!handle) {
|
||||
return ProcessNotRunning;
|
||||
} else {
|
||||
CloseHandle(handle);
|
||||
return ProcessRunning;
|
||||
}
|
||||
#else
|
||||
if (kill(getpid(), 0) == 0) {
|
||||
if (kill(pid, 0) == 0) {
|
||||
return ProcessRunning;
|
||||
} else {
|
||||
return ProcessNotRunning;
|
||||
}
|
||||
} else {
|
||||
return UnknownProcessStatus;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void system_memorybarrier()
|
||||
{
|
||||
@@ -45,6 +45,12 @@
|
||||
# define R__
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
# define RTENTRY__ __attribute__((annotate("realtime")))
|
||||
#else
|
||||
# define RTENTRY__
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# include <malloc.h>
|
||||
# include <process.h>
|
||||
@@ -82,33 +88,22 @@
|
||||
|
||||
namespace RubberBand {
|
||||
|
||||
#ifdef PROCESS_SAMPLE_TYPE
|
||||
typedef PROCESS_SAMPLE_TYPE process_t;
|
||||
#else
|
||||
typedef double process_t;
|
||||
#endif
|
||||
|
||||
extern const char *system_get_platform_tag();
|
||||
extern bool system_is_multiprocessor();
|
||||
extern void system_specific_initialise();
|
||||
extern void system_specific_application_initialise();
|
||||
|
||||
enum ProcessStatus { ProcessRunning, ProcessNotRunning, UnknownProcessStatus };
|
||||
extern ProcessStatus system_get_process_status(int pid);
|
||||
|
||||
#ifdef _WIN32
|
||||
struct timeval { long tv_sec; long tv_usec; };
|
||||
void gettimeofday(struct timeval *p, void *tz);
|
||||
#endif // _WIN32
|
||||
|
||||
#ifdef _MSC_VER
|
||||
void usleep(unsigned long);
|
||||
#endif // _MSC_VER
|
||||
|
||||
inline double mod(double x, double y) { return x - (y * floor(x / y)); }
|
||||
inline float modf(float x, float y) { return x - (y * float(floor(x / y))); }
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif // M_PI
|
||||
|
||||
inline double princarg(double a) { return mod(a + M_PI, -2.0 * M_PI) + M_PI; }
|
||||
inline float princargf(float a) { return modf(a + (float)M_PI, -2.f * (float)M_PI) + (float)M_PI; }
|
||||
|
||||
} // end namespace
|
||||
|
||||
// The following should be functions in the RubberBand namespace, really
|
||||
@@ -124,11 +119,6 @@ extern void system_memorybarrier();
|
||||
}
|
||||
#define MBARRIER() RubberBand::system_memorybarrier()
|
||||
|
||||
#define DLOPEN(a,b) LoadLibrary((a).toStdWString().c_str())
|
||||
#define DLSYM(a,b) GetProcAddress((HINSTANCE)(a),(b))
|
||||
#define DLCLOSE(a) FreeLibrary((HINSTANCE)(a))
|
||||
#define DLERROR() ""
|
||||
|
||||
#else // !_WIN32
|
||||
|
||||
#include <sys/mman.h>
|
||||
@@ -157,11 +147,6 @@ extern void system_memorybarrier();
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define DLOPEN(a,b) dlopen((a).toStdString().c_str(),(b))
|
||||
#define DLSYM(a,b) dlsym((a),(b))
|
||||
#define DLCLOSE(a) dlclose((a))
|
||||
#define DLERROR() dlerror()
|
||||
|
||||
#endif // !_WIN32
|
||||
|
||||
#ifdef NO_THREADING
|
||||
@@ -1,110 +0,0 @@
|
||||
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||
|
||||
/*
|
||||
Rubber Band Library
|
||||
An audio time-stretching and pitch-shifting library.
|
||||
Copyright 2007-2022 Particular Programs Ltd.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version. See the file
|
||||
COPYING included with this distribution for more information.
|
||||
|
||||
Alternatively, if you have a valid commercial licence for the
|
||||
Rubber Band Library obtained by agreement with the copyright
|
||||
holders, you may redistribute and/or modify it under the terms
|
||||
described in that licence.
|
||||
|
||||
If you wish to distribute code using the Rubber Band Library
|
||||
under terms other than those of the GNU General Public License,
|
||||
you must obtain a valid commercial licence before doing so.
|
||||
*/
|
||||
|
||||
#ifndef RUBBERBAND_MOVING_MEDIAN_H
|
||||
#define RUBBERBAND_MOVING_MEDIAN_H
|
||||
|
||||
#include "SampleFilter.h"
|
||||
|
||||
#include "../system/Allocators.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace RubberBand
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
class MovingMedian : public SampleFilter<T>
|
||||
{
|
||||
typedef SampleFilter<T> P;
|
||||
|
||||
public:
|
||||
MovingMedian(int size, float percentile = 50.f) :
|
||||
SampleFilter<T>(size),
|
||||
m_frame(allocate_and_zero<T>(size)),
|
||||
m_sorted(allocate_and_zero<T>(size)),
|
||||
m_sortend(m_sorted + P::m_size - 1) {
|
||||
setPercentile(percentile);
|
||||
}
|
||||
|
||||
~MovingMedian() {
|
||||
deallocate(m_frame);
|
||||
deallocate(m_sorted);
|
||||
}
|
||||
|
||||
void setPercentile(float p) {
|
||||
m_index = int((P::m_size * p) / 100.f);
|
||||
if (m_index >= P::m_size) m_index = P::m_size-1;
|
||||
if (m_index < 0) m_index = 0;
|
||||
}
|
||||
|
||||
void push(T value) {
|
||||
if (value != value) {
|
||||
std::cerr << "WARNING: MovingMedian: NaN encountered" << std::endl;
|
||||
value = T();
|
||||
}
|
||||
drop(m_frame[0]);
|
||||
v_move(m_frame, m_frame+1, P::m_size-1);
|
||||
m_frame[P::m_size-1] = value;
|
||||
put(value);
|
||||
}
|
||||
|
||||
T get() const {
|
||||
return m_sorted[m_index];
|
||||
}
|
||||
|
||||
void reset() {
|
||||
v_zero(m_frame, P::m_size);
|
||||
v_zero(m_sorted, P::m_size);
|
||||
}
|
||||
|
||||
private:
|
||||
T *const m_frame;
|
||||
T *const m_sorted;
|
||||
T *const m_sortend;
|
||||
int m_index;
|
||||
|
||||
void put(T value) {
|
||||
// precondition: m_sorted contains m_size-1 values, packed at start
|
||||
// postcondition: m_sorted contains m_size values, one of which is value
|
||||
T *index = std::lower_bound(m_sorted, m_sortend, value);
|
||||
v_move(index + 1, index, m_sortend - index);
|
||||
*index = value;
|
||||
}
|
||||
|
||||
void drop(T value) {
|
||||
// precondition: m_sorted contains m_size values, one of which is value
|
||||
// postcondition: m_sorted contains m_size-1 values, packed at start
|
||||
T *index = std::lower_bound(m_sorted, m_sortend + 1, value);
|
||||
assert(*index == value);
|
||||
v_move(index, index + 1, m_sortend - index);
|
||||
*m_sortend = T(0);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "../system/sysutils.h"
|
||||
#include "../common/sysutils.h"
|
||||
|
||||
namespace RubberBand
|
||||
{
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#include "CompoundAudioCurve.h"
|
||||
|
||||
#include "../dsp/MovingMedian.h"
|
||||
#include "../common/MovingMedian.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#include "PercussiveAudioCurve.h"
|
||||
#include "HighFrequencyAudioCurve.h"
|
||||
#include "../dsp/SampleFilter.h"
|
||||
#include "../common/SampleFilter.h"
|
||||
|
||||
namespace RubberBand
|
||||
{
|
||||
@@ -24,7 +24,7 @@
|
||||
#ifndef RUBBERBAND_HIGHFREQUENCY_AUDIO_CURVE_H
|
||||
#define RUBBERBAND_HIGHFREQUENCY_AUDIO_CURVE_H
|
||||
|
||||
#include "../dsp/AudioCurveCalculator.h"
|
||||
#include "AudioCurveCalculator.h"
|
||||
|
||||
namespace RubberBand
|
||||
{
|
||||
@@ -23,8 +23,8 @@
|
||||
|
||||
#include "PercussiveAudioCurve.h"
|
||||
|
||||
#include "../system/Allocators.h"
|
||||
#include "../system/VectorOps.h"
|
||||
#include "../common/Allocators.h"
|
||||
#include "../common/VectorOps.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
@@ -24,7 +24,7 @@
|
||||
#ifndef RUBBERBAND_PERCUSSIVE_AUDIO_CURVE_H
|
||||
#define RUBBERBAND_PERCUSSIVE_AUDIO_CURVE_H
|
||||
|
||||
#include "../dsp/AudioCurveCalculator.h"
|
||||
#include "AudioCurveCalculator.h"
|
||||
|
||||
namespace RubberBand
|
||||
{
|
||||
@@ -21,23 +21,18 @@
|
||||
you must obtain a valid commercial licence before doing so.
|
||||
*/
|
||||
|
||||
#include "StretcherImpl.h"
|
||||
#include "R2Stretcher.h"
|
||||
|
||||
#include "audiocurves/PercussiveAudioCurve.h"
|
||||
#include "audiocurves/HighFrequencyAudioCurve.h"
|
||||
#include "audiocurves/SpectralDifferenceAudioCurve.h"
|
||||
#include "audiocurves/SilentAudioCurve.h"
|
||||
#include "audiocurves/ConstantAudioCurve.h"
|
||||
#include "audiocurves/CompoundAudioCurve.h"
|
||||
|
||||
#include "dsp/Resampler.h"
|
||||
|
||||
#include "StretchCalculator.h"
|
||||
#include "PercussiveAudioCurve.h"
|
||||
#include "HighFrequencyAudioCurve.h"
|
||||
#include "SilentAudioCurve.h"
|
||||
#include "CompoundAudioCurve.h"
|
||||
#include "StretcherChannelData.h"
|
||||
|
||||
#include "base/Profiler.h"
|
||||
|
||||
#include "system/sysutils.h"
|
||||
#include "../common/StretchCalculator.h"
|
||||
#include "../common/Resampler.h"
|
||||
#include "../common/Profiler.h"
|
||||
#include "../common/sysutils.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
@@ -45,10 +40,6 @@
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace RubberBand;
|
||||
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::vector;
|
||||
using std::map;
|
||||
using std::set;
|
||||
@@ -58,21 +49,19 @@ using std::min;
|
||||
namespace RubberBand {
|
||||
|
||||
const size_t
|
||||
RubberBandStretcher::Impl::m_defaultIncrement = 256;
|
||||
R2Stretcher::m_defaultIncrement = 256;
|
||||
|
||||
const size_t
|
||||
RubberBandStretcher::Impl::m_defaultFftSize = 2048;
|
||||
|
||||
int
|
||||
RubberBandStretcher::Impl::m_defaultDebugLevel = 0;
|
||||
R2Stretcher::m_defaultFftSize = 2048;
|
||||
|
||||
static bool _initialised = false;
|
||||
|
||||
RubberBandStretcher::Impl::Impl(size_t sampleRate,
|
||||
R2Stretcher::R2Stretcher(size_t sampleRate,
|
||||
size_t channels,
|
||||
Options options,
|
||||
RubberBandStretcher::Options options,
|
||||
double initialTimeRatio,
|
||||
double initialPitchScale) :
|
||||
double initialPitchScale,
|
||||
Log log) :
|
||||
m_sampleRate(sampleRate),
|
||||
m_channels(channels),
|
||||
m_timeRatio(initialTimeRatio),
|
||||
@@ -89,7 +78,7 @@ RubberBandStretcher::Impl::Impl(size_t sampleRate,
|
||||
#endif
|
||||
m_realtime(false),
|
||||
m_options(options),
|
||||
m_debugLevel(m_defaultDebugLevel),
|
||||
m_log(log),
|
||||
m_mode(JustCreated),
|
||||
m_awindow(0),
|
||||
m_afilter(0),
|
||||
@@ -105,7 +94,6 @@ RubberBandStretcher::Impl::Impl(size_t sampleRate,
|
||||
m_lastProcessPhaseResetDf(16),
|
||||
m_emergencyScavenger(10, 4),
|
||||
m_phaseResetAudioCurve(0),
|
||||
m_stretchAudioCurve(0),
|
||||
m_silentAudioCurve(0),
|
||||
m_stretchCalculator(0),
|
||||
m_freq0(600),
|
||||
@@ -118,9 +106,10 @@ RubberBandStretcher::Impl::Impl(size_t sampleRate,
|
||||
_initialised = true;
|
||||
}
|
||||
|
||||
if (m_debugLevel > 0) {
|
||||
cerr << "RubberBandStretcher::Impl::Impl: rate = " << m_sampleRate << ", options = " << options << endl;
|
||||
}
|
||||
m_log.log(1, "R2Stretcher::R2Stretcher: rate, options",
|
||||
m_sampleRate, options);
|
||||
m_log.log(1, "R2Stretcher::R2Stretcher: initial time ratio and pitch scale",
|
||||
m_timeRatio, m_pitchScale);
|
||||
|
||||
// Window size will vary according to the audio sample rate, but
|
||||
// we don't let it drop below the 48k default
|
||||
@@ -128,19 +117,17 @@ RubberBandStretcher::Impl::Impl(size_t sampleRate,
|
||||
// if (m_rateMultiple < 1.f) m_rateMultiple = 1.f;
|
||||
m_baseFftSize = roundUp(int(m_defaultFftSize * m_rateMultiple));
|
||||
|
||||
if ((options & OptionWindowShort) || (options & OptionWindowLong)) {
|
||||
if ((options & OptionWindowShort) && (options & OptionWindowLong)) {
|
||||
cerr << "RubberBandStretcher::Impl::Impl: Cannot specify OptionWindowLong and OptionWindowShort together; falling back to OptionWindowStandard" << endl;
|
||||
} else if (options & OptionWindowShort) {
|
||||
if ((options & RubberBandStretcher::OptionWindowShort) ||
|
||||
(options & RubberBandStretcher::OptionWindowLong)) {
|
||||
if ((options & RubberBandStretcher::OptionWindowShort) &&
|
||||
(options & RubberBandStretcher::OptionWindowLong)) {
|
||||
m_log.log(0, "R2Stretcher::R2Stretcher: Cannot specify OptionWindowLong and OptionWindowShort together; falling back to OptionWindowStandard");
|
||||
} else if (options & RubberBandStretcher::OptionWindowShort) {
|
||||
m_baseFftSize = m_baseFftSize / 2;
|
||||
if (m_debugLevel > 0) {
|
||||
cerr << "setting baseFftSize to " << m_baseFftSize << endl;
|
||||
}
|
||||
} else if (options & OptionWindowLong) {
|
||||
m_log.log(1, "setting baseFftSize", m_baseFftSize);
|
||||
} else if (options & RubberBandStretcher::OptionWindowLong) {
|
||||
m_baseFftSize = m_baseFftSize * 2;
|
||||
if (m_debugLevel > 0) {
|
||||
cerr << "setting baseFftSize to " << m_baseFftSize << endl;
|
||||
}
|
||||
m_log.log(1, "setting baseFftSize", m_baseFftSize);
|
||||
}
|
||||
m_fftSize = m_baseFftSize;
|
||||
m_aWindowSize = m_baseFftSize;
|
||||
@@ -149,13 +136,8 @@ RubberBandStretcher::Impl::Impl(size_t sampleRate,
|
||||
m_maxProcessSize = m_aWindowSize;
|
||||
}
|
||||
|
||||
if (m_options & OptionProcessRealTime) {
|
||||
|
||||
if (m_options & RubberBandStretcher::OptionProcessRealTime) {
|
||||
m_realtime = true;
|
||||
|
||||
if (!(m_options & OptionStretchPrecise)) {
|
||||
m_options |= OptionStretchPrecise;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NO_THREADING
|
||||
@@ -165,15 +147,15 @@ RubberBandStretcher::Impl::Impl(size_t sampleRate,
|
||||
|
||||
if (m_realtime) {
|
||||
m_threaded = false;
|
||||
} else if (m_options & OptionThreadingNever) {
|
||||
} else if (m_options & RubberBandStretcher::OptionThreadingNever) {
|
||||
m_threaded = false;
|
||||
} else if (!(m_options & OptionThreadingAlways) &&
|
||||
} else if (!(m_options & RubberBandStretcher::OptionThreadingAlways) &&
|
||||
!system_is_multiprocessor()) {
|
||||
m_threaded = false;
|
||||
}
|
||||
|
||||
if (m_threaded && m_debugLevel > 0) {
|
||||
cerr << "Going multithreaded..." << endl;
|
||||
if (m_threaded) {
|
||||
m_log.log(1, "Going multithreaded...");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -181,16 +163,14 @@ RubberBandStretcher::Impl::Impl(size_t sampleRate,
|
||||
configure();
|
||||
}
|
||||
|
||||
RubberBandStretcher::Impl::~Impl()
|
||||
R2Stretcher::~R2Stretcher()
|
||||
{
|
||||
#ifndef NO_THREADING
|
||||
if (m_threaded) {
|
||||
MutexLocker locker(&m_threadSetMutex);
|
||||
for (set<ProcessThread *>::iterator i = m_threadSet.begin();
|
||||
i != m_threadSet.end(); ++i) {
|
||||
if (m_debugLevel > 0) {
|
||||
cerr << "RubberBandStretcher::~RubberBandStretcher: joining (channel " << *i << ")" << endl;
|
||||
}
|
||||
m_log.log(1, "RubberBandStretcher::~RubberBandStretcher: joining for channel", (*i)->channel());
|
||||
(*i)->abandon();
|
||||
(*i)->wait();
|
||||
delete *i;
|
||||
@@ -203,7 +183,6 @@ RubberBandStretcher::Impl::~Impl()
|
||||
}
|
||||
|
||||
delete m_phaseResetAudioCurve;
|
||||
delete m_stretchAudioCurve;
|
||||
delete m_silentAudioCurve;
|
||||
delete m_stretchCalculator;
|
||||
delete m_studyFFT;
|
||||
@@ -219,16 +198,14 @@ RubberBandStretcher::Impl::~Impl()
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::reset()
|
||||
R2Stretcher::reset()
|
||||
{
|
||||
#ifndef NO_THREADING
|
||||
if (m_threaded) {
|
||||
m_threadSetMutex.lock();
|
||||
for (set<ProcessThread *>::iterator i = m_threadSet.begin();
|
||||
i != m_threadSet.end(); ++i) {
|
||||
if (m_debugLevel > 0) {
|
||||
cerr << "RubberBandStretcher::~RubberBandStretcher: joining (channel " << *i << ")" << endl;
|
||||
}
|
||||
m_log.log(1, "RubberBandStretcher::~RubberBandStretcher: joining for channel", (*i)->channel());
|
||||
(*i)->abandon();
|
||||
(*i)->wait();
|
||||
delete *i;
|
||||
@@ -249,7 +226,6 @@ RubberBandStretcher::Impl::reset()
|
||||
|
||||
m_mode = JustCreated;
|
||||
if (m_phaseResetAudioCurve) m_phaseResetAudioCurve->reset();
|
||||
if (m_stretchAudioCurve) m_stretchAudioCurve->reset();
|
||||
if (m_silentAudioCurve) m_silentAudioCurve->reset();
|
||||
m_inputDuration = 0;
|
||||
m_silentHistory = 0;
|
||||
@@ -262,11 +238,11 @@ RubberBandStretcher::Impl::reset()
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::setTimeRatio(double ratio)
|
||||
R2Stretcher::setTimeRatio(double ratio)
|
||||
{
|
||||
if (!m_realtime) {
|
||||
if (m_mode == Studying || m_mode == Processing) {
|
||||
cerr << "RubberBandStretcher::Impl::setTimeRatio: Cannot set ratio while studying or processing in non-RT mode" << endl;
|
||||
m_log.log(0, "R2Stretcher::setTimeRatio: Cannot set ratio while studying or processing in non-RT mode");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -278,11 +254,11 @@ RubberBandStretcher::Impl::setTimeRatio(double ratio)
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::setPitchScale(double fs)
|
||||
R2Stretcher::setPitchScale(double fs)
|
||||
{
|
||||
if (!m_realtime) {
|
||||
if (m_mode == Studying || m_mode == Processing) {
|
||||
cerr << "RubberBandStretcher::Impl::setPitchScale: Cannot set ratio while studying or processing in non-RT mode" << endl;
|
||||
m_log.log(0, "R2Stretcher::setPitchScale: Cannot set ratio while studying or processing in non-RT mode");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -296,7 +272,7 @@ RubberBandStretcher::Impl::setPitchScale(double fs)
|
||||
|
||||
reconfigure();
|
||||
|
||||
if (!(m_options & OptionPitchHighConsistency) &&
|
||||
if (!(m_options & RubberBandStretcher::OptionPitchHighConsistency) &&
|
||||
(was1 || resampleBeforeStretching() != rbs) &&
|
||||
m_pitchScale != 1.f) {
|
||||
|
||||
@@ -310,19 +286,19 @@ RubberBandStretcher::Impl::setPitchScale(double fs)
|
||||
}
|
||||
|
||||
double
|
||||
RubberBandStretcher::Impl::getTimeRatio() const
|
||||
R2Stretcher::getTimeRatio() const
|
||||
{
|
||||
return m_timeRatio;
|
||||
}
|
||||
|
||||
double
|
||||
RubberBandStretcher::Impl::getPitchScale() const
|
||||
R2Stretcher::getPitchScale() const
|
||||
{
|
||||
return m_pitchScale;
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::setExpectedInputDuration(size_t samples)
|
||||
R2Stretcher::setExpectedInputDuration(size_t samples)
|
||||
{
|
||||
if (samples == m_expectedInputDuration) return;
|
||||
m_expectedInputDuration = samples;
|
||||
@@ -331,7 +307,7 @@ RubberBandStretcher::Impl::setExpectedInputDuration(size_t samples)
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::setMaxProcessSize(size_t samples)
|
||||
R2Stretcher::setMaxProcessSize(size_t samples)
|
||||
{
|
||||
if (samples <= m_maxProcessSize) return;
|
||||
m_maxProcessSize = samples;
|
||||
@@ -340,15 +316,15 @@ RubberBandStretcher::Impl::setMaxProcessSize(size_t samples)
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::setKeyFrameMap(const std::map<size_t, size_t> &
|
||||
R2Stretcher::setKeyFrameMap(const std::map<size_t, size_t> &
|
||||
mapping)
|
||||
{
|
||||
if (m_realtime) {
|
||||
cerr << "RubberBandStretcher::Impl::setKeyFrameMap: Cannot specify key frame map in RT mode" << endl;
|
||||
m_log.log(0, "R2Stretcher::setKeyFrameMap: Cannot specify key frame map in RT mode");
|
||||
return;
|
||||
}
|
||||
if (m_mode == Processing) {
|
||||
cerr << "RubberBandStretcher::Impl::setKeyFrameMap: Cannot specify key frame map after process() has begun" << endl;
|
||||
m_log.log(0, "R2Stretcher::setKeyFrameMap: Cannot specify key frame map after process() has begun");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -358,7 +334,7 @@ RubberBandStretcher::Impl::setKeyFrameMap(const std::map<size_t, size_t> &
|
||||
}
|
||||
|
||||
float
|
||||
RubberBandStretcher::Impl::getFrequencyCutoff(int n) const
|
||||
R2Stretcher::getFrequencyCutoff(int n) const
|
||||
{
|
||||
switch (n) {
|
||||
case 0: return m_freq0;
|
||||
@@ -369,7 +345,7 @@ RubberBandStretcher::Impl::getFrequencyCutoff(int n) const
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::setFrequencyCutoff(int n, float f)
|
||||
R2Stretcher::setFrequencyCutoff(int n, float f)
|
||||
{
|
||||
switch (n) {
|
||||
case 0: m_freq0 = f; break;
|
||||
@@ -379,7 +355,7 @@ RubberBandStretcher::Impl::setFrequencyCutoff(int n, float f)
|
||||
}
|
||||
|
||||
double
|
||||
RubberBandStretcher::Impl::getEffectiveRatio() const
|
||||
R2Stretcher::getEffectiveRatio() const
|
||||
{
|
||||
// Returns the ratio that the internal time stretcher needs to
|
||||
// achieve, not the resulting duration ratio of the output (which
|
||||
@@ -396,7 +372,7 @@ RubberBandStretcher::Impl::getEffectiveRatio() const
|
||||
}
|
||||
|
||||
size_t
|
||||
RubberBandStretcher::Impl::roundUp(size_t value)
|
||||
R2Stretcher::roundUp(size_t value)
|
||||
{
|
||||
if (!(value & (value - 1))) return value;
|
||||
int bits = 0;
|
||||
@@ -406,7 +382,7 @@ RubberBandStretcher::Impl::roundUp(size_t value)
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::calculateSizes()
|
||||
R2Stretcher::calculateSizes()
|
||||
{
|
||||
size_t inputIncrement = m_defaultIncrement;
|
||||
size_t windowSize = m_baseFftSize;
|
||||
@@ -416,12 +392,12 @@ RubberBandStretcher::Impl::calculateSizes()
|
||||
// This special case is likelier than one might hope, because
|
||||
// of naive initialisations in programs that set it from a
|
||||
// variable
|
||||
std::cerr << "RubberBandStretcher: WARNING: Pitch scale must be greater than zero!\nResetting it from " << m_pitchScale << " to the default of 1.0: no pitch change will occur" << std::endl;
|
||||
m_log.log(0, "WARNING: Pitch scale must be greater than zero! Resetting it to default, no pitch shift will happen", m_pitchScale);
|
||||
m_pitchScale = 1.0;
|
||||
}
|
||||
if (m_timeRatio <= 0.0) {
|
||||
// Likewise
|
||||
std::cerr << "RubberBandStretcher: WARNING: Time ratio must be greater than zero!\nResetting it from " << m_timeRatio << " to the default of 1.0: no time stretch will occur" << std::endl;
|
||||
m_log.log(0, "WARNING: Time ratio must be greater than zero! Resetting it to default, no time stretch will happen", m_timeRatio);
|
||||
m_timeRatio = 1.0;
|
||||
}
|
||||
|
||||
@@ -474,7 +450,7 @@ RubberBandStretcher::Impl::calculateSizes()
|
||||
if (windowSize < minwin) windowSize = minwin;
|
||||
|
||||
if (rsb) {
|
||||
// cerr << "adjusting window size from " << windowSize;
|
||||
size_t oldWindowSize = windowSize;
|
||||
size_t newWindowSize = roundUp(lrint(windowSize / m_pitchScale));
|
||||
if (newWindowSize < 512) newWindowSize = 512;
|
||||
size_t div = windowSize / newWindowSize;
|
||||
@@ -483,7 +459,8 @@ RubberBandStretcher::Impl::calculateSizes()
|
||||
outputIncrement /= div;
|
||||
windowSize /= div;
|
||||
}
|
||||
// cerr << " to " << windowSize << " (inputIncrement = " << inputIncrement << ", outputIncrement = " << outputIncrement << ")" << endl;
|
||||
m_log.log(2, "adjusting window size from/to", oldWindowSize, windowSize);
|
||||
m_log.log(2, "input and output increments", inputIncrement, outputIncrement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,7 +503,7 @@ RubberBandStretcher::Impl::calculateSizes()
|
||||
|
||||
m_fftSize = windowSize;
|
||||
|
||||
if (m_options & OptionSmoothingOn) {
|
||||
if (m_options & RubberBandStretcher::OptionSmoothingOn) {
|
||||
m_aWindowSize = windowSize * 2;
|
||||
m_sWindowSize = windowSize * 2;
|
||||
} else {
|
||||
@@ -543,10 +520,11 @@ RubberBandStretcher::Impl::calculateSizes()
|
||||
// twice the basic output increment (i.e. input increment times
|
||||
// ratio) for any chunk.
|
||||
|
||||
if (m_debugLevel > 0) {
|
||||
cerr << "calculateSizes: time ratio = " << m_timeRatio << ", pitch scale = " << m_pitchScale << ", effective ratio = " << getEffectiveRatio() << endl;
|
||||
cerr << "calculateSizes: analysis window size = " << m_aWindowSize << ", synthesis window size = " << m_sWindowSize << ", fft size = " << m_fftSize << ", increment = " << m_increment << " (approx output increment = " << int(lrint(m_increment * getEffectiveRatio())) << ")" << endl;
|
||||
}
|
||||
m_log.log(1, "calculateSizes: time ratio and pitch scale", m_timeRatio, m_pitchScale);
|
||||
m_log.log(1, "effective ratio", getEffectiveRatio());
|
||||
m_log.log(1, "analysis and synthesis window sizes", m_aWindowSize, m_sWindowSize);
|
||||
m_log.log(1, "fft size", m_fftSize);
|
||||
m_log.log(1, "input increment and mean output increment", m_increment, m_increment * getEffectiveRatio());
|
||||
|
||||
if (std::max(m_aWindowSize, m_sWindowSize) > m_maxProcessSize) {
|
||||
m_maxProcessSize = std::max(m_aWindowSize, m_sWindowSize);
|
||||
@@ -574,17 +552,18 @@ RubberBandStretcher::Impl::calculateSizes()
|
||||
#endif
|
||||
}
|
||||
|
||||
if (m_debugLevel > 0) {
|
||||
cerr << "calculateSizes: outbuf size = " << m_outbufSize << endl;
|
||||
}
|
||||
m_log.log(1, "calculateSizes: outbuf size", m_outbufSize);
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::configure()
|
||||
R2Stretcher::configure()
|
||||
{
|
||||
if (m_debugLevel > 0) {
|
||||
std::cerr << "configure[" << this << "]: realtime = " << m_realtime << ", pitch scale = "
|
||||
<< m_pitchScale << ", channels = " << m_channels << std::endl;
|
||||
if (m_realtime) {
|
||||
m_log.log(1, "configure, realtime: pitch scale and channels",
|
||||
m_pitchScale, m_channels);
|
||||
} else {
|
||||
m_log.log(1, "configure, offline: pitch scale and channels",
|
||||
m_pitchScale, m_channels);
|
||||
}
|
||||
|
||||
size_t prevFftSize = m_fftSize;
|
||||
@@ -629,7 +608,7 @@ RubberBandStretcher::Impl::configure()
|
||||
for (set<size_t>::const_iterator i = windowSizes.begin();
|
||||
i != windowSizes.end(); ++i) {
|
||||
if (m_windows.find(*i) == m_windows.end()) {
|
||||
m_windows[*i] = new Window<float>(HanningWindow, *i);
|
||||
m_windows[*i] = new Window<float>(HannWindow, *i);
|
||||
}
|
||||
if (m_sincs.find(*i) == m_sincs.end()) {
|
||||
m_sincs[*i] = new SincWindow<float>(*i, *i);
|
||||
@@ -639,9 +618,8 @@ RubberBandStretcher::Impl::configure()
|
||||
m_afilter = m_sincs[m_aWindowSize];
|
||||
m_swindow = m_windows[m_sWindowSize];
|
||||
|
||||
if (m_debugLevel > 0) {
|
||||
cerr << "Window area: " << m_awindow->getArea() << "; synthesis window area: " << m_swindow->getArea() << endl;
|
||||
}
|
||||
m_log.log(1, "analysis and synthesis window areas",
|
||||
m_awindow->getArea(), m_swindow->getArea());
|
||||
}
|
||||
|
||||
if (windowSizeChanged || outbufSizeChanged) {
|
||||
@@ -662,12 +640,12 @@ RubberBandStretcher::Impl::configure()
|
||||
|
||||
if (!m_realtime && fftSizeChanged) {
|
||||
delete m_studyFFT;
|
||||
m_studyFFT = new FFT(m_fftSize, m_debugLevel);
|
||||
m_studyFFT = new FFT(m_fftSize, m_log.getDebugLevel());
|
||||
m_studyFFT->initFloat();
|
||||
}
|
||||
|
||||
if (m_pitchScale != 1.0 ||
|
||||
(m_options & OptionPitchHighConsistency) ||
|
||||
(m_options & RubberBandStretcher::OptionPitchHighConsistency) ||
|
||||
m_realtime) {
|
||||
|
||||
for (size_t c = 0; c < m_channels; ++c) {
|
||||
@@ -687,7 +665,8 @@ RubberBandStretcher::Impl::configure()
|
||||
}
|
||||
|
||||
params.maxBufferSize = 4096 * 16;
|
||||
params.debugLevel = (m_debugLevel > 0 ? m_debugLevel-1 : 0);
|
||||
int myLevel = m_log.getDebugLevel();
|
||||
params.debugLevel = (myLevel > 0 ? myLevel-1 : 0);
|
||||
|
||||
m_channelData[c]->resampler = new Resampler(params, 1);
|
||||
|
||||
@@ -701,10 +680,6 @@ RubberBandStretcher::Impl::configure()
|
||||
}
|
||||
}
|
||||
|
||||
// stretchAudioCurve is unused in RT mode; phaseResetAudioCurve,
|
||||
// silentAudioCurve and stretchCalculator however are used in all
|
||||
// modes
|
||||
|
||||
delete m_phaseResetAudioCurve;
|
||||
m_phaseResetAudioCurve = new CompoundAudioCurve
|
||||
(CompoundAudioCurve::Parameters(m_sampleRate, m_fftSize));
|
||||
@@ -714,23 +689,13 @@ RubberBandStretcher::Impl::configure()
|
||||
m_silentAudioCurve = new SilentAudioCurve
|
||||
(SilentAudioCurve::Parameters(m_sampleRate, m_fftSize));
|
||||
|
||||
if (!m_realtime) {
|
||||
delete m_stretchAudioCurve;
|
||||
if (!(m_options & OptionStretchPrecise)) {
|
||||
m_stretchAudioCurve = new SpectralDifferenceAudioCurve
|
||||
(SpectralDifferenceAudioCurve::Parameters(m_sampleRate, m_fftSize));
|
||||
} else {
|
||||
m_stretchAudioCurve = new ConstantAudioCurve
|
||||
(ConstantAudioCurve::Parameters(m_sampleRate, m_fftSize));
|
||||
}
|
||||
}
|
||||
|
||||
delete m_stretchCalculator;
|
||||
m_stretchCalculator = new StretchCalculator
|
||||
(m_sampleRate, m_increment,
|
||||
!(m_options & OptionTransientsSmooth));
|
||||
!(m_options & RubberBandStretcher::OptionTransientsSmooth),
|
||||
m_log);
|
||||
|
||||
m_stretchCalculator->setDebugLevel(m_debugLevel);
|
||||
m_stretchCalculator->setDebugLevel(m_log.getDebugLevel());
|
||||
m_inputDuration = 0;
|
||||
|
||||
// Prepare the inbufs with half a chunk of emptiness. The centre
|
||||
@@ -745,19 +710,18 @@ RubberBandStretcher::Impl::configure()
|
||||
// want gaps when the ratio changes.
|
||||
|
||||
if (!m_realtime) {
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "Not real time mode: prefilling with " << m_aWindowSize/2 << " samples" << endl;
|
||||
}
|
||||
m_log.log(1, "offline mode: prefilling with", m_aWindowSize/2);
|
||||
for (size_t c = 0; c < m_channels; ++c) {
|
||||
m_channelData[c]->reset();
|
||||
m_channelData[c]->inbuf->zero(m_aWindowSize/2);
|
||||
}
|
||||
} else {
|
||||
m_log.log(1, "realtime mode: no prefill");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::reconfigure()
|
||||
R2Stretcher::reconfigure()
|
||||
{
|
||||
if (!m_realtime) {
|
||||
if (m_mode == Studying) {
|
||||
@@ -765,7 +729,6 @@ RubberBandStretcher::Impl::reconfigure()
|
||||
// the df vectors
|
||||
calculateStretch();
|
||||
m_phaseResetDf.clear();
|
||||
m_stretchDf.clear();
|
||||
m_silence.clear();
|
||||
m_inputDuration = 0;
|
||||
}
|
||||
@@ -792,17 +755,17 @@ RubberBandStretcher::Impl::reconfigure()
|
||||
m_sWindowSize != prevSWindowSize) {
|
||||
|
||||
if (m_windows.find(m_aWindowSize) == m_windows.end()) {
|
||||
std::cerr << "WARNING: reconfigure(): window allocation (size " << m_aWindowSize << ") required in RT mode" << std::endl;
|
||||
m_log.log(0, "WARNING: reconfigure(): window allocation required in realtime mode, size", m_aWindowSize);
|
||||
m_windows[m_aWindowSize] = new Window<float>
|
||||
(HanningWindow, m_aWindowSize);
|
||||
(HannWindow, m_aWindowSize);
|
||||
m_sincs[m_aWindowSize] = new SincWindow<float>
|
||||
(m_aWindowSize, m_aWindowSize);
|
||||
}
|
||||
|
||||
if (m_windows.find(m_sWindowSize) == m_windows.end()) {
|
||||
std::cerr << "WARNING: reconfigure(): window allocation (size " << m_sWindowSize << ") required in RT mode" << std::endl;
|
||||
m_log.log(0, "WARNING: reconfigure(): window allocation required in realtime mode, size", m_sWindowSize);
|
||||
m_windows[m_sWindowSize] = new Window<float>
|
||||
(HanningWindow, m_sWindowSize);
|
||||
(HannWindow, m_sWindowSize);
|
||||
m_sincs[m_sWindowSize] = new SincWindow<float>
|
||||
(m_sWindowSize, m_sWindowSize);
|
||||
}
|
||||
@@ -831,14 +794,15 @@ RubberBandStretcher::Impl::reconfigure()
|
||||
|
||||
if (m_channelData[c]->resampler) continue;
|
||||
|
||||
std::cerr << "WARNING: reconfigure(): resampler construction required in RT mode" << std::endl;
|
||||
m_log.log(0, "WARNING: reconfigure(): resampler construction required in RT mode");
|
||||
|
||||
Resampler::Parameters params;
|
||||
params.quality = Resampler::FastestTolerable;
|
||||
params.dynamism = Resampler::RatioOftenChanging;
|
||||
params.ratioChange = Resampler::SmoothRatioChange;
|
||||
params.maxBufferSize = m_sWindowSize;
|
||||
params.debugLevel = (m_debugLevel > 0 ? m_debugLevel-1 : 0);
|
||||
int myLevel = m_log.getDebugLevel();
|
||||
params.debugLevel = (myLevel > 0 ? myLevel-1 : 0);
|
||||
|
||||
m_channelData[c]->resampler = new Resampler(params, 1);
|
||||
|
||||
@@ -854,59 +818,61 @@ RubberBandStretcher::Impl::reconfigure()
|
||||
if (m_fftSize != prevFftSize) {
|
||||
m_phaseResetAudioCurve->setFftSize(m_fftSize);
|
||||
m_silentAudioCurve->setFftSize(m_fftSize);
|
||||
if (m_stretchAudioCurve) {
|
||||
m_stretchAudioCurve->setFftSize(m_fftSize);
|
||||
}
|
||||
somethingChanged = true;
|
||||
}
|
||||
|
||||
if (m_debugLevel > 0) {
|
||||
if (somethingChanged) {
|
||||
std::cerr << "reconfigure: at least one parameter changed" << std::endl;
|
||||
m_log.log(1, "reconfigure: at least one parameter changed");
|
||||
} else {
|
||||
std::cerr << "reconfigure: nothing changed" << std::endl;
|
||||
}
|
||||
m_log.log(1, "reconfigure: nothing changed");
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
RubberBandStretcher::Impl::getLatency() const
|
||||
R2Stretcher::getLatency() const
|
||||
{
|
||||
if (!m_realtime) return 0;
|
||||
return lrint((m_aWindowSize/2) / m_pitchScale);
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::setTransientsOption(Options options)
|
||||
R2Stretcher::setTransientsOption(RubberBandStretcher::Options options)
|
||||
{
|
||||
if (!m_realtime) {
|
||||
cerr << "RubberBandStretcher::Impl::setTransientsOption: Not permissible in non-realtime mode" << endl;
|
||||
m_log.log(0, "R2Stretcher::setTransientsOption: Not permissible in non-realtime mode");
|
||||
return;
|
||||
}
|
||||
int mask = (OptionTransientsMixed | OptionTransientsSmooth | OptionTransientsCrisp);
|
||||
int mask = (RubberBandStretcher::OptionTransientsMixed |
|
||||
RubberBandStretcher::OptionTransientsSmooth |
|
||||
RubberBandStretcher::OptionTransientsCrisp);
|
||||
m_options &= ~mask;
|
||||
options &= mask;
|
||||
m_options |= options;
|
||||
|
||||
m_stretchCalculator->setUseHardPeaks
|
||||
(!(m_options & OptionTransientsSmooth));
|
||||
(!(m_options & RubberBandStretcher::OptionTransientsSmooth));
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::setDetectorOption(Options options)
|
||||
R2Stretcher::setDetectorOption(RubberBandStretcher::Options options)
|
||||
{
|
||||
if (!m_realtime) {
|
||||
cerr << "RubberBandStretcher::Impl::setDetectorOption: Not permissible in non-realtime mode" << endl;
|
||||
m_log.log(0, "R2Stretcher::setDetectorOption: Not permissible in non-realtime mode");
|
||||
return;
|
||||
}
|
||||
int mask = (OptionDetectorPercussive | OptionDetectorCompound | OptionDetectorSoft);
|
||||
int mask = (RubberBandStretcher::OptionDetectorPercussive |
|
||||
RubberBandStretcher::OptionDetectorCompound |
|
||||
RubberBandStretcher::OptionDetectorSoft);
|
||||
m_options &= ~mask;
|
||||
options &= mask;
|
||||
m_options |= options;
|
||||
|
||||
CompoundAudioCurve::Type dt = CompoundAudioCurve::CompoundDetector;
|
||||
if (m_options & OptionDetectorPercussive) dt = CompoundAudioCurve::PercussiveDetector;
|
||||
else if (m_options & OptionDetectorSoft) dt = CompoundAudioCurve::SoftDetector;
|
||||
if (m_options & RubberBandStretcher::OptionDetectorPercussive) {
|
||||
dt = CompoundAudioCurve::PercussiveDetector;
|
||||
} else if (m_options & RubberBandStretcher::OptionDetectorSoft) {
|
||||
dt = CompoundAudioCurve::SoftDetector;
|
||||
}
|
||||
|
||||
if (dt == m_detectorType) return;
|
||||
m_detectorType = dt;
|
||||
@@ -917,36 +883,38 @@ RubberBandStretcher::Impl::setDetectorOption(Options options)
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::setPhaseOption(Options options)
|
||||
R2Stretcher::setPhaseOption(RubberBandStretcher::Options options)
|
||||
{
|
||||
int mask = (OptionPhaseLaminar | OptionPhaseIndependent);
|
||||
int mask = (RubberBandStretcher::OptionPhaseLaminar |
|
||||
RubberBandStretcher::OptionPhaseIndependent);
|
||||
m_options &= ~mask;
|
||||
options &= mask;
|
||||
m_options |= options;
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::setFormantOption(Options options)
|
||||
R2Stretcher::setFormantOption(RubberBandStretcher::Options options)
|
||||
{
|
||||
int mask = (OptionFormantShifted | OptionFormantPreserved);
|
||||
int mask = (RubberBandStretcher::OptionFormantShifted |
|
||||
RubberBandStretcher::OptionFormantPreserved);
|
||||
m_options &= ~mask;
|
||||
options &= mask;
|
||||
m_options |= options;
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::setPitchOption(Options options)
|
||||
R2Stretcher::setPitchOption(RubberBandStretcher::Options options)
|
||||
{
|
||||
if (!m_realtime) {
|
||||
cerr << "RubberBandStretcher::Impl::setPitchOption: Pitch option is not used in non-RT mode" << endl;
|
||||
m_log.log(0, "R2Stretcher::setPitchOption: Pitch option is not used in non-RT mode");
|
||||
return;
|
||||
}
|
||||
|
||||
Options prior = m_options;
|
||||
RubberBandStretcher::Options prior = m_options;
|
||||
|
||||
int mask = (OptionPitchHighQuality |
|
||||
OptionPitchHighSpeed |
|
||||
OptionPitchHighConsistency);
|
||||
int mask = (RubberBandStretcher::OptionPitchHighQuality |
|
||||
RubberBandStretcher::OptionPitchHighSpeed |
|
||||
RubberBandStretcher::OptionPitchHighConsistency);
|
||||
m_options &= ~mask;
|
||||
options &= mask;
|
||||
m_options |= options;
|
||||
@@ -955,19 +923,17 @@ RubberBandStretcher::Impl::setPitchOption(Options options)
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool final)
|
||||
R2Stretcher::study(const float *const *input, size_t samples, bool final)
|
||||
{
|
||||
Profiler profiler("RubberBandStretcher::Impl::study");
|
||||
Profiler profiler("R2Stretcher::study");
|
||||
|
||||
if (m_realtime) {
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "RubberBandStretcher::Impl::study: Not meaningful in realtime mode" << endl;
|
||||
}
|
||||
m_log.log(0, "R2Stretcher::study: Not meaningful in realtime mode");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_mode == Processing || m_mode == Finished) {
|
||||
cerr << "RubberBandStretcher::Impl::study: Cannot study after processing" << endl;
|
||||
m_log.log(0, "R2Stretcher::study: Cannot study after processing");
|
||||
return;
|
||||
}
|
||||
m_mode = Studying;
|
||||
@@ -1010,7 +976,8 @@ RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool
|
||||
|
||||
if (writable == 0) {
|
||||
// warn
|
||||
cerr << "WARNING: writable == 0 (consumed = " << consumed << ", samples = " << samples << ")" << endl;
|
||||
m_log.log(0, "WARNING: writable == 0: consumed, samples",
|
||||
consumed, samples);
|
||||
} else {
|
||||
inbuf.write(mixdown + consumed, writable);
|
||||
consumed += writable;
|
||||
@@ -1069,13 +1036,10 @@ RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool
|
||||
|
||||
// cout << m_phaseResetDf.size() << " [" << final << "] -> " << df << " \t: ";
|
||||
|
||||
df = m_stretchAudioCurve->processFloat(cd.fltbuf, m_increment);
|
||||
m_stretchDf.push_back(df);
|
||||
|
||||
df = m_silentAudioCurve->processFloat(cd.fltbuf, m_increment);
|
||||
bool silent = (df > 0.f);
|
||||
if (silent && m_debugLevel > 1) {
|
||||
cerr << "silence found at " << m_inputDuration << endl;
|
||||
if (silent) {
|
||||
m_log.log(2, "silence at", m_inputDuration);
|
||||
}
|
||||
m_silence.push_back(silent);
|
||||
|
||||
@@ -1089,7 +1053,6 @@ RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool
|
||||
// extra afterwards.
|
||||
|
||||
m_inputDuration += m_increment;
|
||||
// cerr << "incr input duration by increment: " << m_increment << " -> " << m_inputDuration << endl;
|
||||
inbuf.skip(m_increment);
|
||||
}
|
||||
}
|
||||
@@ -1097,8 +1060,6 @@ RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool
|
||||
if (final) {
|
||||
int rs = inbuf.getReadSpace();
|
||||
m_inputDuration += rs;
|
||||
// cerr << "incr input duration by read space: " << rs << " -> " << m_inputDuration << endl;
|
||||
|
||||
if (m_inputDuration > m_aWindowSize/2) { // deducting the extra
|
||||
m_inputDuration -= m_aWindowSize/2;
|
||||
}
|
||||
@@ -1108,7 +1069,7 @@ RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool
|
||||
}
|
||||
|
||||
vector<int>
|
||||
RubberBandStretcher::Impl::getOutputIncrements() const
|
||||
R2Stretcher::getOutputIncrements() const
|
||||
{
|
||||
if (!m_realtime) {
|
||||
return m_outputIncrements;
|
||||
@@ -1122,7 +1083,7 @@ RubberBandStretcher::Impl::getOutputIncrements() const
|
||||
}
|
||||
|
||||
vector<float>
|
||||
RubberBandStretcher::Impl::getPhaseResetCurve() const
|
||||
R2Stretcher::getPhaseResetCurve() const
|
||||
{
|
||||
if (!m_realtime) {
|
||||
return m_phaseResetDf;
|
||||
@@ -1136,7 +1097,7 @@ RubberBandStretcher::Impl::getPhaseResetCurve() const
|
||||
}
|
||||
|
||||
vector<int>
|
||||
RubberBandStretcher::Impl::getExactTimePoints() const
|
||||
R2Stretcher::getExactTimePoints() const
|
||||
{
|
||||
std::vector<int> points;
|
||||
if (!m_realtime) {
|
||||
@@ -1150,41 +1111,23 @@ RubberBandStretcher::Impl::getExactTimePoints() const
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::calculateStretch()
|
||||
R2Stretcher::calculateStretch()
|
||||
{
|
||||
Profiler profiler("RubberBandStretcher::Impl::calculateStretch");
|
||||
Profiler profiler("R2Stretcher::calculateStretch");
|
||||
|
||||
size_t inputDuration = m_inputDuration;
|
||||
|
||||
if (!m_realtime && m_expectedInputDuration > 0) {
|
||||
if (m_expectedInputDuration != inputDuration) {
|
||||
std::cerr << "RubberBandStretcher: WARNING: Actual study() duration differs from duration set by setExpectedInputDuration (" << m_inputDuration << " vs " << m_expectedInputDuration << ", diff = " << (m_expectedInputDuration - m_inputDuration) << "), using the latter for calculation" << std::endl;
|
||||
m_log.log(0, "WARNING: Actual study() duration differs from duration set by setExpectedInputDuration - using the latter for calculation", m_inputDuration, m_expectedInputDuration);
|
||||
inputDuration = m_expectedInputDuration;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
double prdm = 0, sdm = 0;
|
||||
if (!m_phaseResetDf.empty()) {
|
||||
for (int i = 0; i < (int)m_phaseResetDf.size(); ++i) {
|
||||
prdm += m_phaseResetDf[i];
|
||||
}
|
||||
prdm /= m_phaseResetDf.size();
|
||||
}
|
||||
if (!m_stretchDf.empty()) {
|
||||
for (int i = 0; i < (int)m_stretchDf.size(); ++i) {
|
||||
sdm += m_stretchDf[i];
|
||||
}
|
||||
sdm /= m_stretchDf.size();
|
||||
}
|
||||
std::cerr << "phase reset df mean = " << prdm << ", stretch df mean = " << sdm << std::endl;
|
||||
*/
|
||||
|
||||
std::vector<int> increments = m_stretchCalculator->calculate
|
||||
(getEffectiveRatio(),
|
||||
inputDuration,
|
||||
m_phaseResetDf,
|
||||
m_stretchDf);
|
||||
m_phaseResetDf);
|
||||
|
||||
int history = 0;
|
||||
for (size_t i = 0; i < increments.size(); ++i) {
|
||||
@@ -1193,10 +1136,7 @@ RubberBandStretcher::Impl::calculateStretch()
|
||||
else history = 0;
|
||||
if (history >= int(m_aWindowSize / m_increment) && increments[i] >= 0) {
|
||||
increments[i] = -increments[i];
|
||||
if (m_debugLevel > 1) {
|
||||
std::cerr << "phase reset on silence (silent history == "
|
||||
<< history << ")" << std::endl;
|
||||
}
|
||||
m_log.log(2, "phase reset on silence: silent history", history);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1211,16 +1151,18 @@ RubberBandStretcher::Impl::calculateStretch()
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::setDebugLevel(int level)
|
||||
R2Stretcher::setDebugLevel(int level)
|
||||
{
|
||||
m_debugLevel = level;
|
||||
if (m_stretchCalculator) m_stretchCalculator->setDebugLevel(level);
|
||||
m_log.setDebugLevel(level);
|
||||
if (m_stretchCalculator) {
|
||||
m_stretchCalculator->setDebugLevel(level);
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
RubberBandStretcher::Impl::getSamplesRequired() const
|
||||
R2Stretcher::getSamplesRequired() const
|
||||
{
|
||||
Profiler profiler("RubberBandStretcher::Impl::getSamplesRequired");
|
||||
Profiler profiler("R2Stretcher::getSamplesRequired");
|
||||
|
||||
size_t reqd = 0;
|
||||
|
||||
@@ -1235,9 +1177,7 @@ RubberBandStretcher::Impl::getSamplesRequired() const
|
||||
size_t rs = inbuf.getReadSpace();
|
||||
size_t ws = outbuf.getReadSpace();
|
||||
|
||||
if (m_debugLevel > 2) {
|
||||
cerr << "getSamplesRequired: ws = " << ws << ", rs = " << rs << ", m_aWindowSize = " << m_aWindowSize << endl;
|
||||
}
|
||||
m_log.log(3, "getSamplesRequired: ws and rs ", ws, rs);
|
||||
|
||||
// We should never return zero in non-threaded modes if
|
||||
// available() would also return zero, i.e. if ws == 0. If we
|
||||
@@ -1269,12 +1209,12 @@ RubberBandStretcher::Impl::getSamplesRequired() const
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::process(const float *const *input, size_t samples, bool final)
|
||||
R2Stretcher::process(const float *const *input, size_t samples, bool final)
|
||||
{
|
||||
Profiler profiler("RubberBandStretcher::Impl::process");
|
||||
Profiler profiler("R2Stretcher::process");
|
||||
|
||||
if (m_mode == Finished) {
|
||||
cerr << "RubberBandStretcher::Impl::process: Cannot process again after final chunk" << endl;
|
||||
m_log.log(0, "R2Stretcher::process: Cannot process again after final chunk");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1287,9 +1227,7 @@ RubberBandStretcher::Impl::process(const float *const *input, size_t samples, bo
|
||||
if (!m_realtime) {
|
||||
// See note in configure() above. Of course, we should
|
||||
// never enter Studying unless we are non-RT anyway
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "Not real time mode: prefilling" << endl;
|
||||
}
|
||||
m_log.log(1, "offline mode: prefilling with", m_aWindowSize/2);
|
||||
for (size_t c = 0; c < m_channels; ++c) {
|
||||
m_channelData[c]->reset();
|
||||
m_channelData[c]->inbuf->zero(m_aWindowSize/2);
|
||||
@@ -1307,9 +1245,7 @@ RubberBandStretcher::Impl::process(const float *const *input, size_t samples, bo
|
||||
thread->start();
|
||||
}
|
||||
|
||||
if (m_debugLevel > 0) {
|
||||
cerr << m_channels << " threads created" << endl;
|
||||
}
|
||||
m_log.log(1, "created threads", m_channels);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1341,12 +1277,10 @@ RubberBandStretcher::Impl::process(const float *const *input, size_t samples, bo
|
||||
final);
|
||||
if (consumed[c] < samples) {
|
||||
allConsumed = false;
|
||||
// cerr << "process: waiting on input consumption for channel " << c << endl;
|
||||
} else {
|
||||
if (final) {
|
||||
m_channelData[c]->inputSize = m_channelData[c]->inCount;
|
||||
}
|
||||
// cerr << "process: happy with channel " << c << endl;
|
||||
}
|
||||
if (
|
||||
#ifndef NO_THREADING
|
||||
@@ -1379,14 +1313,10 @@ RubberBandStretcher::Impl::process(const float *const *input, size_t samples, bo
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_debugLevel > 1) {
|
||||
if (!allConsumed) cerr << "process looping" << endl;
|
||||
}
|
||||
m_log.log(2, "process looping");
|
||||
}
|
||||
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "process returning" << endl;
|
||||
}
|
||||
m_log.log(2, "process returning");
|
||||
|
||||
if (final) m_mode = Finished;
|
||||
}
|
||||
@@ -24,42 +24,36 @@
|
||||
#ifndef RUBBERBAND_STRETCHERIMPL_H
|
||||
#define RUBBERBAND_STRETCHERIMPL_H
|
||||
|
||||
#include "../rubberband/RubberBandStretcher.h"
|
||||
#include "../../rubberband/RubberBandStretcher.h"
|
||||
|
||||
#include "dsp/Window.h"
|
||||
#include "dsp/SincWindow.h"
|
||||
#include "dsp/FFT.h"
|
||||
#include "../common/Window.h"
|
||||
#include "../common/FFT.h"
|
||||
#include "../common/RingBuffer.h"
|
||||
#include "../common/Scavenger.h"
|
||||
#include "../common/Thread.h"
|
||||
#include "../common/Log.h"
|
||||
#include "../common/sysutils.h"
|
||||
|
||||
#include "audiocurves/CompoundAudioCurve.h"
|
||||
|
||||
#include "base/RingBuffer.h"
|
||||
#include "base/Scavenger.h"
|
||||
#include "system/Thread.h"
|
||||
#include "system/sysutils.h"
|
||||
#include "SincWindow.h"
|
||||
#include "CompoundAudioCurve.h"
|
||||
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace RubberBand;
|
||||
|
||||
namespace RubberBand
|
||||
{
|
||||
|
||||
#ifdef PROCESS_SAMPLE_TYPE
|
||||
typedef PROCESS_SAMPLE_TYPE process_t;
|
||||
#else
|
||||
typedef double process_t;
|
||||
#endif
|
||||
|
||||
class AudioCurveCalculator;
|
||||
class StretchCalculator;
|
||||
|
||||
class RubberBandStretcher::Impl
|
||||
class R2Stretcher
|
||||
{
|
||||
public:
|
||||
Impl(size_t sampleRate, size_t channels, Options options,
|
||||
double initialTimeRatio, double initialPitchScale);
|
||||
~Impl();
|
||||
R2Stretcher(size_t sampleRate, size_t channels,
|
||||
RubberBandStretcher::Options options,
|
||||
double initialTimeRatio, double initialPitchScale,
|
||||
Log log);
|
||||
~R2Stretcher();
|
||||
|
||||
void reset();
|
||||
void setTimeRatio(double ratio);
|
||||
@@ -70,11 +64,11 @@ public:
|
||||
|
||||
size_t getLatency() const;
|
||||
|
||||
void setTransientsOption(Options);
|
||||
void setDetectorOption(Options);
|
||||
void setPhaseOption(Options);
|
||||
void setFormantOption(Options);
|
||||
void setPitchOption(Options);
|
||||
void setTransientsOption(RubberBandStretcher::Options);
|
||||
void setDetectorOption(RubberBandStretcher::Options);
|
||||
void setPhaseOption(RubberBandStretcher::Options);
|
||||
void setFormantOption(RubberBandStretcher::Options);
|
||||
void setPitchOption(RubberBandStretcher::Options);
|
||||
|
||||
void setExpectedInputDuration(size_t samples);
|
||||
void setMaxProcessSize(size_t samples);
|
||||
@@ -106,7 +100,6 @@ public:
|
||||
void calculateStretch();
|
||||
|
||||
void setDebugLevel(int level);
|
||||
static void setDefaultDebugLevel(int level) { m_defaultDebugLevel = level; }
|
||||
|
||||
protected:
|
||||
size_t m_sampleRate;
|
||||
@@ -181,8 +174,8 @@ protected:
|
||||
#endif
|
||||
|
||||
bool m_realtime;
|
||||
Options m_options;
|
||||
int m_debugLevel;
|
||||
RubberBandStretcher::Options m_options;
|
||||
Log m_log;
|
||||
|
||||
enum ProcessMode {
|
||||
JustCreated,
|
||||
@@ -206,12 +199,13 @@ protected:
|
||||
class ProcessThread : public Thread
|
||||
{
|
||||
public:
|
||||
ProcessThread(Impl *s, size_t c);
|
||||
ProcessThread(R2Stretcher *s, size_t c);
|
||||
void run();
|
||||
void signalDataAvailable();
|
||||
void abandon();
|
||||
size_t channel() { return m_channel; }
|
||||
private:
|
||||
Impl *m_s;
|
||||
R2Stretcher *m_s;
|
||||
size_t m_channel;
|
||||
Condition m_dataAvailable;
|
||||
bool m_abandoning;
|
||||
@@ -221,18 +215,18 @@ protected:
|
||||
typedef std::set<ProcessThread *> ThreadSet;
|
||||
ThreadSet m_threadSet;
|
||||
|
||||
#if defined HAVE_IPP && !defined USE_SPEEX
|
||||
#if defined(HAVE_IPP) && !defined(NO_THREADING) && !defined(USE_BQRESAMPLER) && !defined(USE_SPEEX) && !defined(HAVE_LIBSAMPLERATE)
|
||||
// Exasperatingly, the IPP polyphase resampler does not appear to
|
||||
// be thread-safe as advertised -- a good reason to prefer the
|
||||
// Speex alternative
|
||||
// be thread-safe as advertised -- a good reason to prefer any of
|
||||
// the alternatives
|
||||
#define STRETCHER_IMPL_RESAMPLER_MUTEX_REQUIRED 1
|
||||
Mutex m_resamplerMutex;
|
||||
#endif
|
||||
#endif
|
||||
#endif // ! NO_THREADING
|
||||
|
||||
size_t m_inputDuration;
|
||||
CompoundAudioCurve::Type m_detectorType;
|
||||
std::vector<float> m_phaseResetDf;
|
||||
std::vector<float> m_stretchDf;
|
||||
std::vector<bool> m_silence;
|
||||
int m_silentHistory;
|
||||
|
||||
@@ -246,7 +240,6 @@ protected:
|
||||
Scavenger<RingBuffer<float> > m_emergencyScavenger;
|
||||
|
||||
CompoundAudioCurve *m_phaseResetAudioCurve;
|
||||
AudioCurveCalculator *m_stretchAudioCurve;
|
||||
AudioCurveCalculator *m_silentAudioCurve;
|
||||
StretchCalculator *m_stretchCalculator;
|
||||
|
||||
@@ -260,7 +253,6 @@ protected:
|
||||
void writeOutput(RingBuffer<float> &to, float *from,
|
||||
size_t qty, size_t &outCount, size_t theoreticalOut);
|
||||
|
||||
static int m_defaultDebugLevel;
|
||||
static const size_t m_defaultIncrement;
|
||||
static const size_t m_defaultFftSize;
|
||||
};
|
||||
@@ -24,7 +24,7 @@
|
||||
#ifndef RUBBERBAND_SILENT_AUDIO_CURVE_H
|
||||
#define RUBBERBAND_SILENT_AUDIO_CURVE_H
|
||||
|
||||
#include "../dsp/AudioCurveCalculator.h"
|
||||
#include "AudioCurveCalculator.h"
|
||||
|
||||
namespace RubberBand
|
||||
{
|
||||
@@ -29,9 +29,9 @@
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
|
||||
#include "../system/sysutils.h"
|
||||
#include "../system/VectorOps.h"
|
||||
#include "../system/Allocators.h"
|
||||
#include "../common/sysutils.h"
|
||||
#include "../common/VectorOps.h"
|
||||
#include "../common/Allocators.h"
|
||||
|
||||
namespace RubberBand {
|
||||
|
||||
@@ -23,16 +23,15 @@
|
||||
|
||||
#include "StretcherChannelData.h"
|
||||
|
||||
#include "dsp/Resampler.h"
|
||||
|
||||
#include "system/Allocators.h"
|
||||
#include "../common/Resampler.h"
|
||||
#include "../common/Allocators.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace RubberBand
|
||||
{
|
||||
|
||||
RubberBandStretcher::Impl::ChannelData::ChannelData(size_t windowSize,
|
||||
R2Stretcher::ChannelData::ChannelData(size_t windowSize,
|
||||
size_t fftSize,
|
||||
size_t outbufSize)
|
||||
{
|
||||
@@ -40,7 +39,7 @@ RubberBandStretcher::Impl::ChannelData::ChannelData(size_t windowSize,
|
||||
construct(s, windowSize, fftSize, outbufSize);
|
||||
}
|
||||
|
||||
RubberBandStretcher::Impl::ChannelData::ChannelData(const std::set<size_t> &sizes,
|
||||
R2Stretcher::ChannelData::ChannelData(const std::set<size_t> &sizes,
|
||||
size_t initialWindowSize,
|
||||
size_t initialFftSize,
|
||||
size_t outbufSize)
|
||||
@@ -49,7 +48,7 @@ RubberBandStretcher::Impl::ChannelData::ChannelData(const std::set<size_t> &size
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &sizes,
|
||||
R2Stretcher::ChannelData::construct(const std::set<size_t> &sizes,
|
||||
size_t initialWindowSize,
|
||||
size_t initialFftSize,
|
||||
size_t outbufSize)
|
||||
@@ -57,8 +56,6 @@ RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &sizes,
|
||||
size_t maxSize = initialWindowSize * 2;
|
||||
if (initialFftSize > maxSize) maxSize = initialFftSize;
|
||||
|
||||
// std::cerr << "ChannelData::construct: initialWindowSize = " << initialWindowSize << ", initialFftSize = " << initialFftSize << ", outbufSize = " << outbufSize << std::endl;
|
||||
|
||||
// std::set is ordered by value
|
||||
std::set<size_t>::const_iterator i = sizes.end();
|
||||
if (i != sizes.begin()) {
|
||||
@@ -69,8 +66,6 @@ RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &sizes,
|
||||
// max possible size of the real "half" of freq data
|
||||
size_t realSize = maxSize / 2 + 1;
|
||||
|
||||
// std::cerr << "ChannelData::construct([" << sizes.size() << "], " << maxSize << ", " << realSize << ", " << outbufSize << ")" << std::endl;
|
||||
|
||||
if (outbufSize < maxSize) outbufSize = maxSize;
|
||||
|
||||
inbuf = new RingBuffer<float>(maxSize);
|
||||
@@ -115,11 +110,9 @@ RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &sizes,
|
||||
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::ChannelData::setSizes(size_t windowSize,
|
||||
R2Stretcher::ChannelData::setSizes(size_t windowSize,
|
||||
size_t fftSize)
|
||||
{
|
||||
// std::cerr << "ChannelData::setSizes: windowSize = " << windowSize << ", fftSize = " << fftSize << std::endl;
|
||||
|
||||
size_t maxSize = 2 * std::max(windowSize, fftSize);
|
||||
size_t realSize = maxSize / 2 + 1;
|
||||
size_t oldMax = inbuf->getSize();
|
||||
@@ -207,12 +200,10 @@ RubberBandStretcher::Impl::ChannelData::setSizes(size_t windowSize,
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::ChannelData::setOutbufSize(size_t outbufSize)
|
||||
R2Stretcher::ChannelData::setOutbufSize(size_t outbufSize)
|
||||
{
|
||||
size_t oldSize = outbuf->getSize();
|
||||
|
||||
// std::cerr << "ChannelData::setOutbufSize(" << outbufSize << ") [from " << oldSize << "]" << std::endl;
|
||||
|
||||
if (oldSize < outbufSize) {
|
||||
|
||||
//!!! at this point we need a lock in case a different client
|
||||
@@ -225,13 +216,13 @@ RubberBandStretcher::Impl::ChannelData::setOutbufSize(size_t outbufSize)
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::ChannelData::setResampleBufSize(size_t sz)
|
||||
R2Stretcher::ChannelData::setResampleBufSize(size_t sz)
|
||||
{
|
||||
resamplebuf = reallocate_and_zero<float>(resamplebuf, resamplebufSize, sz);
|
||||
resamplebufSize = sz;
|
||||
}
|
||||
|
||||
RubberBandStretcher::Impl::ChannelData::~ChannelData()
|
||||
R2Stretcher::ChannelData::~ChannelData()
|
||||
{
|
||||
delete resampler;
|
||||
|
||||
@@ -260,7 +251,7 @@ RubberBandStretcher::Impl::ChannelData::~ChannelData()
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::ChannelData::reset()
|
||||
R2Stretcher::ChannelData::reset()
|
||||
{
|
||||
inbuf->reset();
|
||||
outbuf->reset();
|
||||
@@ -24,7 +24,7 @@
|
||||
#ifndef RUBBERBAND_STRETCHERCHANNELDATA_H
|
||||
#define RUBBERBAND_STRETCHERCHANNELDATA_H
|
||||
|
||||
#include "StretcherImpl.h"
|
||||
#include "R2Stretcher.h"
|
||||
|
||||
#include <set>
|
||||
#include <atomic>
|
||||
@@ -34,7 +34,7 @@ namespace RubberBand
|
||||
|
||||
class Resampler;
|
||||
|
||||
class RubberBandStretcher::Impl::ChannelData
|
||||
class R2Stretcher::ChannelData
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@@ -21,19 +21,15 @@
|
||||
you must obtain a valid commercial licence before doing so.
|
||||
*/
|
||||
|
||||
#include "StretcherImpl.h"
|
||||
|
||||
#include "audiocurves/PercussiveAudioCurve.h"
|
||||
#include "audiocurves/HighFrequencyAudioCurve.h"
|
||||
#include "audiocurves/ConstantAudioCurve.h"
|
||||
|
||||
#include "StretchCalculator.h"
|
||||
#include "R2Stretcher.h"
|
||||
#include "StretcherChannelData.h"
|
||||
|
||||
#include "dsp/Resampler.h"
|
||||
#include "base/Profiler.h"
|
||||
#include "system/VectorOps.h"
|
||||
#include "system/sysutils.h"
|
||||
#include "../common/StretchCalculator.h"
|
||||
#include "../common/Resampler.h"
|
||||
#include "../common/Profiler.h"
|
||||
#include "../common/VectorOps.h"
|
||||
#include "../common/sysutils.h"
|
||||
#include "../common/mathmisc.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
@@ -44,14 +40,11 @@
|
||||
|
||||
using namespace RubberBand;
|
||||
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
||||
namespace RubberBand {
|
||||
|
||||
#ifndef NO_THREADING
|
||||
|
||||
RubberBandStretcher::Impl::ProcessThread::ProcessThread(Impl *s, size_t c) :
|
||||
R2Stretcher::ProcessThread::ProcessThread(R2Stretcher *s, size_t c) :
|
||||
m_s(s),
|
||||
m_channel(c),
|
||||
m_dataAvailable(std::string("data ") + char('A' + c)),
|
||||
@@ -59,22 +52,15 @@ RubberBandStretcher::Impl::ProcessThread::ProcessThread(Impl *s, size_t c) :
|
||||
{ }
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::ProcessThread::run()
|
||||
R2Stretcher::ProcessThread::run()
|
||||
{
|
||||
if (m_s->m_debugLevel > 1) {
|
||||
cerr << "thread " << m_channel << " getting going" << endl;
|
||||
}
|
||||
m_s->m_log.log(2, "thread getting going for channel", m_channel);
|
||||
|
||||
ChannelData &cd = *m_s->m_channelData[m_channel];
|
||||
|
||||
while (cd.inputSize == -1 ||
|
||||
cd.inbuf->getReadSpace() > 0) {
|
||||
|
||||
// if (cd.inputSize != -1) {
|
||||
// cerr << "inputSize == " << cd.inputSize
|
||||
// << ", readSpace == " << cd.inbuf->getReadSpace() << endl;
|
||||
// }
|
||||
|
||||
bool any = false, last = false;
|
||||
m_s->processChunks(m_channel, any, last);
|
||||
|
||||
@@ -93,9 +79,7 @@ RubberBandStretcher::Impl::ProcessThread::run()
|
||||
m_dataAvailable.unlock();
|
||||
|
||||
if (m_abandoning) {
|
||||
if (m_s->m_debugLevel > 1) {
|
||||
cerr << "thread " << m_channel << " abandoning" << endl;
|
||||
}
|
||||
m_s->m_log.log(2, "thread abandoning for channel", m_channel);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -106,13 +90,11 @@ RubberBandStretcher::Impl::ProcessThread::run()
|
||||
m_s->m_spaceAvailable.signal();
|
||||
m_s->m_spaceAvailable.unlock();
|
||||
|
||||
if (m_s->m_debugLevel > 1) {
|
||||
cerr << "thread " << m_channel << " done" << endl;
|
||||
}
|
||||
m_s->m_log.log(2, "thread done for channel", m_channel);
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::ProcessThread::signalDataAvailable()
|
||||
R2Stretcher::ProcessThread::signalDataAvailable()
|
||||
{
|
||||
m_dataAvailable.lock();
|
||||
m_dataAvailable.signal();
|
||||
@@ -120,7 +102,7 @@ RubberBandStretcher::Impl::ProcessThread::signalDataAvailable()
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::ProcessThread::abandon()
|
||||
R2Stretcher::ProcessThread::abandon()
|
||||
{
|
||||
m_abandoning = true;
|
||||
}
|
||||
@@ -128,16 +110,16 @@ RubberBandStretcher::Impl::ProcessThread::abandon()
|
||||
#endif
|
||||
|
||||
bool
|
||||
RubberBandStretcher::Impl::resampleBeforeStretching() const
|
||||
R2Stretcher::resampleBeforeStretching() const
|
||||
{
|
||||
// We can't resample before stretching in offline mode, because
|
||||
// the stretch calculation is based on doing it the other way
|
||||
// around. It would take more work (and testing) to enable this.
|
||||
if (!m_realtime) return false;
|
||||
|
||||
if (m_options & OptionPitchHighQuality) {
|
||||
if (m_options & RubberBandStretcher::OptionPitchHighQuality) {
|
||||
return (m_pitchScale < 1.0); // better sound
|
||||
} else if (m_options & OptionPitchHighConsistency) {
|
||||
} else if (m_options & RubberBandStretcher::OptionPitchHighConsistency) {
|
||||
return false;
|
||||
} else {
|
||||
return (m_pitchScale > 1.0); // better performance
|
||||
@@ -145,7 +127,7 @@ RubberBandStretcher::Impl::resampleBeforeStretching() const
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::prepareChannelMS(size_t c,
|
||||
R2Stretcher::prepareChannelMS(size_t c,
|
||||
const float *const *inputs,
|
||||
size_t offset,
|
||||
size_t samples,
|
||||
@@ -165,13 +147,13 @@ RubberBandStretcher::Impl::prepareChannelMS(size_t c,
|
||||
}
|
||||
|
||||
size_t
|
||||
RubberBandStretcher::Impl::consumeChannel(size_t c,
|
||||
R2Stretcher::consumeChannel(size_t c,
|
||||
const float *const *inputs,
|
||||
size_t offset,
|
||||
size_t samples,
|
||||
bool final)
|
||||
{
|
||||
Profiler profiler("RubberBandStretcher::Impl::consumeChannel");
|
||||
Profiler profiler("R2Stretcher::consumeChannel");
|
||||
|
||||
ChannelData &cd = *m_channelData[c];
|
||||
RingBuffer<float> &inbuf = *cd.inbuf;
|
||||
@@ -183,13 +165,14 @@ RubberBandStretcher::Impl::consumeChannel(size_t c,
|
||||
|
||||
const float *input = 0;
|
||||
|
||||
bool useMidSide = ((m_options & OptionChannelsTogether) &&
|
||||
bool useMidSide =
|
||||
((m_options & RubberBandStretcher::OptionChannelsTogether) &&
|
||||
(m_channels >= 2) &&
|
||||
(c < 2));
|
||||
|
||||
if (resampling) {
|
||||
|
||||
Profiler profiler2("RubberBandStretcher::Impl::resample");
|
||||
Profiler profiler2("R2Stretcher::resample");
|
||||
|
||||
toWrite = int(ceil(samples / m_pitchScale));
|
||||
if (writable < toWrite) {
|
||||
@@ -208,17 +191,14 @@ RubberBandStretcher::Impl::consumeChannel(size_t c,
|
||||
|
||||
size_t reqSize = int(ceil(samples / m_pitchScale));
|
||||
if (reqSize > cd.resamplebufSize) {
|
||||
cerr << "WARNING: RubberBandStretcher::Impl::consumeChannel: resizing resampler buffer from "
|
||||
<< cd.resamplebufSize << " to " << reqSize << endl;
|
||||
m_log.log(0, "WARNING: R2Stretcher::consumeChannel: resizing resampler buffer from and to", cd.resamplebufSize, reqSize);
|
||||
cd.setResampleBufSize(reqSize);
|
||||
}
|
||||
|
||||
#ifndef NO_THREADING
|
||||
#if defined HAVE_IPP && !defined USE_SPEEX
|
||||
#if defined(STRETCHER_IMPL_RESAMPLER_MUTEX_REQUIRED)
|
||||
if (m_threaded) {
|
||||
m_resamplerMutex.lock();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (useMidSide) {
|
||||
@@ -235,12 +215,10 @@ RubberBandStretcher::Impl::consumeChannel(size_t c,
|
||||
1.0 / m_pitchScale,
|
||||
final);
|
||||
|
||||
#ifndef NO_THREADING
|
||||
#if defined HAVE_IPP && !defined USE_SPEEX
|
||||
#if defined(STRETCHER_IMPL_RESAMPLER_MUTEX_REQUIRED)
|
||||
if (m_threaded) {
|
||||
m_resamplerMutex.unlock();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -273,9 +251,9 @@ RubberBandStretcher::Impl::consumeChannel(size_t c,
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::processChunks(size_t c, bool &any, bool &last)
|
||||
R2Stretcher::processChunks(size_t c, bool &any, bool &last)
|
||||
{
|
||||
Profiler profiler("RubberBandStretcher::Impl::processChunks");
|
||||
Profiler profiler("R2Stretcher::processChunks");
|
||||
|
||||
// Process as many chunks as there are available on the input
|
||||
// buffer for channel c. This requires that the increments have
|
||||
@@ -293,9 +271,7 @@ RubberBandStretcher::Impl::processChunks(size_t c, bool &any, bool &last)
|
||||
while (!last) {
|
||||
|
||||
if (!testInbufReadSpace(c)) {
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "processChunks: out of input" << endl;
|
||||
}
|
||||
m_log.log(2, "processChunks: out of input");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -318,9 +294,7 @@ RubberBandStretcher::Impl::processChunks(size_t c, bool &any, bool &last)
|
||||
(c, phaseIncrement, shiftIncrement, phaseReset);
|
||||
} else {
|
||||
size_t bit = m_aWindowSize/4;
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "channel " << c << " breaking down overlong increment " << shiftIncrement << " into " << bit << "-size bits" << endl;
|
||||
}
|
||||
m_log.log(2, "breaking down overlong increment into chunks from and to", shiftIncrement, bit);
|
||||
if (!tmp) tmp = allocate<float>(m_aWindowSize);
|
||||
analyseChunk(c);
|
||||
v_copy(tmp, cd.fltbuf, m_aWindowSize);
|
||||
@@ -337,18 +311,17 @@ RubberBandStretcher::Impl::processChunks(size_t c, bool &any, bool &last)
|
||||
}
|
||||
|
||||
cd.chunkCount++;
|
||||
if (m_debugLevel > 2) {
|
||||
cerr << "channel " << c << ": last = " << last << ", chunkCount = " << cd.chunkCount << endl;
|
||||
}
|
||||
m_log.log(3, "channel/last", c, last);
|
||||
m_log.log(3, "channel/chunkCount", c, cd.chunkCount);
|
||||
}
|
||||
|
||||
if (tmp) deallocate(tmp);
|
||||
}
|
||||
|
||||
bool
|
||||
RubberBandStretcher::Impl::processOneChunk()
|
||||
R2Stretcher::processOneChunk()
|
||||
{
|
||||
Profiler profiler("RubberBandStretcher::Impl::processOneChunk");
|
||||
Profiler profiler("R2Stretcher::processOneChunk");
|
||||
|
||||
// Process a single chunk for all channels, provided there is
|
||||
// enough data on each channel for at least one chunk. This is
|
||||
@@ -358,9 +331,7 @@ RubberBandStretcher::Impl::processOneChunk()
|
||||
|
||||
for (size_t c = 0; c < m_channels; ++c) {
|
||||
if (!testInbufReadSpace(c)) {
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "processOneChunk: out of input" << endl;
|
||||
}
|
||||
m_log.log(2, "processOneChunk: out of input");
|
||||
return false;
|
||||
}
|
||||
ChannelData &cd = *m_channelData[c];
|
||||
@@ -389,9 +360,9 @@ RubberBandStretcher::Impl::processOneChunk()
|
||||
}
|
||||
|
||||
bool
|
||||
RubberBandStretcher::Impl::testInbufReadSpace(size_t c)
|
||||
R2Stretcher::testInbufReadSpace(size_t c)
|
||||
{
|
||||
Profiler profiler("RubberBandStretcher::Impl::testInbufReadSpace");
|
||||
Profiler profiler("R2Stretcher::testInbufReadSpace");
|
||||
|
||||
ChannelData &cd = *m_channelData[c];
|
||||
RingBuffer<float> &inbuf = *cd.inbuf;
|
||||
@@ -412,11 +383,7 @@ RubberBandStretcher::Impl::testInbufReadSpace(size_t c)
|
||||
#ifndef NO_THREADING
|
||||
if (!m_threaded) {
|
||||
#endif
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "Note: RubberBandStretcher: read space < chunk size ("
|
||||
<< inbuf.getReadSpace() << " < " << m_aWindowSize
|
||||
<< ") when not all input written, on processChunks for channel " << c << endl;
|
||||
}
|
||||
m_log.log(2, "Note: read space < chunk size when not all input written", inbuf.getReadSpace(), m_aWindowSize);
|
||||
|
||||
#ifndef NO_THREADING
|
||||
}
|
||||
@@ -425,18 +392,10 @@ RubberBandStretcher::Impl::testInbufReadSpace(size_t c)
|
||||
}
|
||||
|
||||
if (rs == 0) {
|
||||
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "read space = 0, giving up" << endl;
|
||||
}
|
||||
m_log.log(2, "read space = 0, giving up");
|
||||
return false;
|
||||
|
||||
} else if (rs < m_aWindowSize/2) {
|
||||
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "read space = " << rs << ", setting draining true" << endl;
|
||||
}
|
||||
|
||||
m_log.log(2, "setting draining true with read space", rs);
|
||||
cd.draining = true;
|
||||
}
|
||||
}
|
||||
@@ -445,21 +404,21 @@ RubberBandStretcher::Impl::testInbufReadSpace(size_t c)
|
||||
}
|
||||
|
||||
bool
|
||||
RubberBandStretcher::Impl::processChunkForChannel(size_t c,
|
||||
R2Stretcher::processChunkForChannel(size_t c,
|
||||
size_t phaseIncrement,
|
||||
size_t shiftIncrement,
|
||||
bool phaseReset)
|
||||
{
|
||||
Profiler profiler("RubberBandStretcher::Impl::processChunkForChannel");
|
||||
Profiler profiler("R2Stretcher::processChunkForChannel");
|
||||
|
||||
// Process a single chunk on a single channel. This assumes
|
||||
// enough input data is available; caller must have tested this
|
||||
// using e.g. testInbufReadSpace first. Return true if this is
|
||||
// the last chunk on the channel.
|
||||
|
||||
if (phaseReset && (m_debugLevel > 1)) {
|
||||
cerr << "processChunkForChannel: phase reset found, incrs "
|
||||
<< phaseIncrement << ":" << shiftIncrement << endl;
|
||||
if (phaseReset) {
|
||||
m_log.log(2, "processChunkForChannel: phase reset found, increments",
|
||||
phaseIncrement, shiftIncrement);
|
||||
}
|
||||
|
||||
ChannelData &cd = *m_channelData[c];
|
||||
@@ -482,7 +441,7 @@ RubberBandStretcher::Impl::processChunkForChannel(size_t c,
|
||||
modifyChunk(c, phaseIncrement, phaseReset);
|
||||
synthesiseChunk(c, shiftIncrement); // reads from cd.mag, cd.phase
|
||||
|
||||
if (m_debugLevel > 2) {
|
||||
if (m_log.getDebugLevel() > 2) {
|
||||
if (phaseReset) {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
cd.accumulator[i] = 1.2f - (i % 3) * 1.2f;
|
||||
@@ -494,19 +453,13 @@ RubberBandStretcher::Impl::processChunkForChannel(size_t c,
|
||||
bool last = false;
|
||||
|
||||
if (cd.draining) {
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "draining: accumulator fill = " << cd.accumulatorFill << " (shiftIncrement = " << shiftIncrement << ")" << endl;
|
||||
}
|
||||
m_log.log(2, "draining: accumulator fill and shift increment", cd.accumulatorFill, shiftIncrement);
|
||||
if (shiftIncrement == 0) {
|
||||
cerr << "WARNING: draining: shiftIncrement == 0, can't handle that in this context: setting to " << m_increment << endl;
|
||||
m_log.log(0, "WARNING: draining: shiftIncrement == 0, can't handle that in this context: setting to", m_increment);
|
||||
shiftIncrement = m_increment;
|
||||
}
|
||||
if (cd.accumulatorFill <= shiftIncrement) {
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "reducing shift increment from " << shiftIncrement
|
||||
<< " to " << cd.accumulatorFill
|
||||
<< " and marking as last" << endl;
|
||||
}
|
||||
m_log.log(2, "draining: marking as last and reducing shift increment from and to", shiftIncrement, cd.accumulatorFill);
|
||||
shiftIncrement = cd.accumulatorFill;
|
||||
last = true;
|
||||
}
|
||||
@@ -520,9 +473,7 @@ RubberBandStretcher::Impl::processChunkForChannel(size_t c,
|
||||
|
||||
int ws = cd.outbuf->getWriteSpace();
|
||||
if (ws < required) {
|
||||
if (m_debugLevel > 0) {
|
||||
cerr << "Buffer overrun on output for channel " << c << endl;
|
||||
}
|
||||
m_log.log(1, "Buffer overrun on output for channel", c);
|
||||
|
||||
// The only correct thing we can do here is resize the buffer.
|
||||
// We can't wait for the client thread to read some data out
|
||||
@@ -535,11 +486,9 @@ RubberBandStretcher::Impl::processChunkForChannel(size_t c,
|
||||
RingBuffer<float> *oldbuf = cd.outbuf;
|
||||
cd.outbuf = oldbuf->resized(oldbuf->getSize() * 2);
|
||||
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "(Write space was " << ws << ", needed " << required
|
||||
<< ": resized output buffer from " << oldbuf->getSize()
|
||||
<< " to " << cd.outbuf->getSize() << ")" << endl;
|
||||
}
|
||||
m_log.log(2, "write space and space needed", ws, required);
|
||||
m_log.log(2, "resized output buffer from and to", oldbuf->getSize(),
|
||||
cd.outbuf->getSize());
|
||||
|
||||
m_emergencyScavenger.claim(oldbuf);
|
||||
}
|
||||
@@ -549,13 +498,11 @@ RubberBandStretcher::Impl::processChunkForChannel(size_t c,
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn,
|
||||
R2Stretcher::calculateIncrements(size_t &phaseIncrementRtn,
|
||||
size_t &shiftIncrementRtn,
|
||||
bool &phaseReset)
|
||||
{
|
||||
Profiler profiler("RubberBandStretcher::Impl::calculateIncrements");
|
||||
|
||||
// cerr << "calculateIncrements" << endl;
|
||||
Profiler profiler("R2Stretcher::calculateIncrements");
|
||||
|
||||
// Calculate the next upcoming phase and shift increment, on the
|
||||
// basis that both channels are in sync. This is in contrast to
|
||||
@@ -579,7 +526,7 @@ RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn,
|
||||
size_t bc = cd.chunkCount;
|
||||
for (size_t c = 1; c < m_channels; ++c) {
|
||||
if (m_channelData[c]->chunkCount != bc) {
|
||||
cerr << "ERROR: RubberBandStretcher::Impl::calculateIncrements: Channels are not in sync" << endl;
|
||||
m_log.log(0, "ERROR: R2Stretcher::calculateIncrements: Channels are not in sync");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -634,7 +581,7 @@ RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn,
|
||||
|
||||
int incr = m_stretchCalculator->calculateSingle
|
||||
(m_timeRatio, effectivePitchRatio, df, m_increment,
|
||||
m_aWindowSize, m_sWindowSize);
|
||||
m_aWindowSize, m_sWindowSize, false);
|
||||
|
||||
if (m_lastProcessPhaseResetDf.getWriteSpace() > 0) {
|
||||
m_lastProcessPhaseResetDf.write(&df, 1);
|
||||
@@ -676,20 +623,17 @@ RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn,
|
||||
|
||||
if (m_silentHistory >= int(m_aWindowSize / m_increment) && !phaseReset) {
|
||||
phaseReset = true;
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "calculateIncrements: phase reset on silence (silent history == "
|
||||
<< m_silentHistory << ")" << endl;
|
||||
}
|
||||
m_log.log(2, "calculateIncrements: phase reset on silence: silent history", m_silentHistory);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RubberBandStretcher::Impl::getIncrements(size_t channel,
|
||||
R2Stretcher::getIncrements(size_t channel,
|
||||
size_t &phaseIncrementRtn,
|
||||
size_t &shiftIncrementRtn,
|
||||
bool &phaseReset)
|
||||
{
|
||||
Profiler profiler("RubberBandStretcher::Impl::getIncrements");
|
||||
Profiler profiler("R2Stretcher::getIncrements");
|
||||
|
||||
if (channel >= m_channels) {
|
||||
phaseIncrementRtn = m_increment;
|
||||
@@ -718,9 +662,6 @@ RubberBandStretcher::Impl::getIncrements(size_t channel,
|
||||
bool gotData = true;
|
||||
|
||||
if (cd.chunkCount >= m_outputIncrements.size()) {
|
||||
// cerr << "WARNING: RubberBandStretcher::Impl::getIncrements:"
|
||||
// << " chunk count " << cd.chunkCount << " >= "
|
||||
// << m_outputIncrements.size() << endl;
|
||||
if (m_outputIncrements.size() == 0) {
|
||||
phaseIncrementRtn = m_increment;
|
||||
shiftIncrementRtn = m_increment;
|
||||
@@ -747,12 +688,12 @@ RubberBandStretcher::Impl::getIncrements(size_t channel,
|
||||
if (shiftIncrement < 0) {
|
||||
shiftIncrement = -shiftIncrement;
|
||||
}
|
||||
/*
|
||||
if (shiftIncrement >= int(m_windowSize)) {
|
||||
cerr << "*** ERROR: RubberBandStretcher::Impl::processChunks: shiftIncrement " << shiftIncrement << " >= windowSize " << m_windowSize << " at " << cd.chunkCount << " (of " << m_outputIncrements.size() << ")" << endl;
|
||||
shiftIncrement = m_windowSize;
|
||||
|
||||
if (shiftIncrement >= int(m_aWindowSize)) {
|
||||
m_log.log(1, "WARNING: shiftIncrement >= analysis window size", shiftIncrement, m_aWindowSize);
|
||||
m_log.log(1, "at chunk of total", cd.chunkCount, m_outputIncrements.size());
|
||||
}
|
||||
*/
|
||||
|
||||
phaseIncrementRtn = phaseIncrement;
|
||||
shiftIncrementRtn = shiftIncrement;
|
||||
if (cd.chunkCount == 0) phaseReset = true; // don't mess with the first chunk
|
||||
@@ -760,9 +701,9 @@ RubberBandStretcher::Impl::getIncrements(size_t channel,
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::analyseChunk(size_t channel)
|
||||
R2Stretcher::analyseChunk(size_t channel)
|
||||
{
|
||||
Profiler profiler("RubberBandStretcher::Impl::analyseChunk");
|
||||
Profiler profiler("R2Stretcher::analyseChunk");
|
||||
|
||||
ChannelData &cd = *m_channelData[channel];
|
||||
|
||||
@@ -781,16 +722,16 @@ RubberBandStretcher::Impl::analyseChunk(size_t channel)
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::modifyChunk(size_t channel,
|
||||
R2Stretcher::modifyChunk(size_t channel,
|
||||
size_t outputIncrement,
|
||||
bool phaseReset)
|
||||
{
|
||||
Profiler profiler("RubberBandStretcher::Impl::modifyChunk");
|
||||
Profiler profiler("R2Stretcher::modifyChunk");
|
||||
|
||||
ChannelData &cd = *m_channelData[channel];
|
||||
|
||||
if (phaseReset && m_debugLevel > 1) {
|
||||
cerr << "phase reset: leaving phases unmodified" << endl;
|
||||
if (phaseReset) {
|
||||
m_log.log(2, "phase reset: leaving phases unmodified");
|
||||
}
|
||||
|
||||
const process_t rate = process_t(m_sampleRate);
|
||||
@@ -798,8 +739,8 @@ RubberBandStretcher::Impl::modifyChunk(size_t channel,
|
||||
|
||||
bool unchanged = cd.unchanged && (outputIncrement == m_increment);
|
||||
bool fullReset = phaseReset;
|
||||
bool laminar = !(m_options & OptionPhaseIndependent);
|
||||
bool bandlimited = (m_options & OptionTransientsMixed);
|
||||
bool laminar = !(m_options & RubberBandStretcher::OptionPhaseIndependent);
|
||||
bool bandlimited = (m_options & RubberBandStretcher::OptionTransientsMixed);
|
||||
int bandlow = lrint((150 * m_fftSize) / rate);
|
||||
int bandhigh = lrint((1000 * m_fftSize) / rate);
|
||||
|
||||
@@ -911,23 +852,21 @@ RubberBandStretcher::Impl::modifyChunk(size_t channel,
|
||||
cd.unwrappedPhase[i] = outphase;
|
||||
}
|
||||
|
||||
if (m_debugLevel > 2) {
|
||||
cerr << "mean inheritance distance = " << distacc / count << endl;
|
||||
}
|
||||
m_log.log(3, "mean inheritance distance", distacc / count);
|
||||
|
||||
if (fullReset) unchanged = true;
|
||||
cd.unchanged = unchanged;
|
||||
|
||||
if (unchanged && m_debugLevel > 1) {
|
||||
cerr << "frame unchanged on channel " << channel << endl;
|
||||
if (unchanged) {
|
||||
m_log.log(2, "frame unchanged on channel", channel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::formantShiftChunk(size_t channel)
|
||||
R2Stretcher::formantShiftChunk(size_t channel)
|
||||
{
|
||||
Profiler profiler("RubberBandStretcher::Impl::formantShiftChunk");
|
||||
Profiler profiler("R2Stretcher::formantShiftChunk");
|
||||
|
||||
ChannelData &cd = *m_channelData[channel];
|
||||
|
||||
@@ -943,8 +882,6 @@ RubberBandStretcher::Impl::formantShiftChunk(size_t channel)
|
||||
|
||||
const int cutoff = m_sampleRate / 700;
|
||||
|
||||
// cerr <<"cutoff = "<< cutoff << ", m_sampleRate/cutoff = " << m_sampleRate/cutoff << endl;
|
||||
|
||||
dblbuf[0] /= 2;
|
||||
dblbuf[cutoff-1] /= 2;
|
||||
|
||||
@@ -985,13 +922,12 @@ RubberBandStretcher::Impl::formantShiftChunk(size_t channel)
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::synthesiseChunk(size_t channel,
|
||||
R2Stretcher::synthesiseChunk(size_t channel,
|
||||
size_t shiftIncrement)
|
||||
{
|
||||
Profiler profiler("RubberBandStretcher::Impl::synthesiseChunk");
|
||||
Profiler profiler("R2Stretcher::synthesiseChunk");
|
||||
|
||||
|
||||
if ((m_options & OptionFormantPreserved) &&
|
||||
if ((m_options & RubberBandStretcher::OptionFormantPreserved) &&
|
||||
(m_pitchScale != 1.0)) {
|
||||
formantShiftChunk(channel);
|
||||
}
|
||||
@@ -1057,9 +993,9 @@ RubberBandStretcher::Impl::synthesiseChunk(size_t channel,
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, bool last)
|
||||
R2Stretcher::writeChunk(size_t channel, size_t shiftIncrement, bool last)
|
||||
{
|
||||
Profiler profiler("RubberBandStretcher::Impl::writeChunk");
|
||||
Profiler profiler("R2Stretcher::writeChunk");
|
||||
|
||||
ChannelData &cd = *m_channelData[channel];
|
||||
|
||||
@@ -1069,8 +1005,10 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo
|
||||
const int sz = cd.accumulatorFill;
|
||||
const int si = shiftIncrement;
|
||||
|
||||
if (m_debugLevel > 2) {
|
||||
cerr << "writeChunk(" << channel << ", " << shiftIncrement << ", " << last << ")" << endl;
|
||||
m_log.log(3, "writeChunk: channel and shiftIncrement",
|
||||
channel, shiftIncrement);
|
||||
if (last) {
|
||||
m_log.log(3, "writeChunk: last true");
|
||||
}
|
||||
|
||||
v_divide(accumulator, windowAccumulator, si);
|
||||
@@ -1085,10 +1023,11 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo
|
||||
bool resampledAlready = resampleBeforeStretching();
|
||||
|
||||
if (!resampledAlready &&
|
||||
(m_pitchScale != 1.0 || m_options & OptionPitchHighConsistency) &&
|
||||
(m_pitchScale != 1.0 ||
|
||||
(m_options & RubberBandStretcher::OptionPitchHighConsistency)) &&
|
||||
cd.resampler) {
|
||||
|
||||
Profiler profiler2("RubberBandStretcher::Impl::resample");
|
||||
Profiler profiler2("R2Stretcher::resample");
|
||||
|
||||
size_t reqSize = int(ceil(si / m_pitchScale));
|
||||
if (reqSize > cd.resamplebufSize) {
|
||||
@@ -1097,17 +1036,14 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo
|
||||
// first place. But we retain this check in case the
|
||||
// pitch scale has changed since then, or the stretch
|
||||
// calculator has gone mad, or something.
|
||||
cerr << "WARNING: RubberBandStretcher::Impl::writeChunk: resizing resampler buffer from "
|
||||
<< cd.resamplebufSize << " to " << reqSize << endl;
|
||||
m_log.log(0, "WARNING: R2Stretcher::writeChunk: resizing resampler buffer from and to", cd.resamplebufSize, reqSize);
|
||||
cd.setResampleBufSize(reqSize);
|
||||
}
|
||||
|
||||
#ifndef NO_THREADING
|
||||
#if defined HAVE_IPP && !defined USE_SPEEX
|
||||
#if defined(STRETCHER_IMPL_RESAMPLER_MUTEX_REQUIRED)
|
||||
if (m_threaded) {
|
||||
m_resamplerMutex.lock();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
size_t outframes = cd.resampler->resample(&cd.resamplebuf,
|
||||
@@ -1117,12 +1053,10 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo
|
||||
1.0 / m_pitchScale,
|
||||
last);
|
||||
|
||||
#ifndef NO_THREADING
|
||||
#if defined HAVE_IPP && !defined USE_SPEEX
|
||||
#if defined(STRETCHER_IMPL_RESAMPLER_MUTEX_REQUIRED)
|
||||
if (m_threaded) {
|
||||
m_resamplerMutex.unlock();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
writeOutput(*cd.outbuf, cd.resamplebuf,
|
||||
@@ -1144,18 +1078,16 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo
|
||||
} else {
|
||||
cd.accumulatorFill = 0;
|
||||
if (cd.draining) {
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "RubberBandStretcher::Impl::processChunks: setting outputComplete to true" << endl;
|
||||
}
|
||||
m_log.log(2, "processChunks: setting outputComplete to true");
|
||||
cd.outputComplete = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::Impl::writeOutput(RingBuffer<float> &to, float *from, size_t qty, size_t &outCount, size_t theoreticalOut)
|
||||
R2Stretcher::writeOutput(RingBuffer<float> &to, float *from, size_t qty, size_t &outCount, size_t theoreticalOut)
|
||||
{
|
||||
Profiler profiler("RubberBandStretcher::Impl::writeOutput");
|
||||
Profiler profiler("R2Stretcher::writeOutput");
|
||||
|
||||
// In non-RT mode, we don't want to write the first startSkip
|
||||
// samples, because the first chunk is centred on the start of the
|
||||
@@ -1172,31 +1104,23 @@ RubberBandStretcher::Impl::writeOutput(RingBuffer<float> &to, float *from, size_
|
||||
// this is the normal case
|
||||
|
||||
if (theoreticalOut > 0) {
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "theoreticalOut = " << theoreticalOut
|
||||
<< ", outCount = " << outCount
|
||||
<< ", startSkip = " << startSkip
|
||||
<< ", qty = " << qty << endl;
|
||||
}
|
||||
m_log.log(2, "theoreticalOut and outCount",
|
||||
theoreticalOut, outCount);
|
||||
m_log.log(2, "startSkip and qty",
|
||||
startSkip, qty);
|
||||
if (outCount - startSkip <= theoreticalOut &&
|
||||
outCount - startSkip + qty > theoreticalOut) {
|
||||
qty = theoreticalOut - (outCount - startSkip);
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "reduce qty to " << qty << endl;
|
||||
}
|
||||
m_log.log(2, "reducing qty to", qty);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_debugLevel > 2) {
|
||||
cerr << "writing " << qty << endl;
|
||||
}
|
||||
m_log.log(3, "writing", qty);
|
||||
|
||||
size_t written = to.write(from, qty);
|
||||
|
||||
if (written < qty) {
|
||||
cerr << "WARNING: RubberBandStretcher::Impl::writeOutput: "
|
||||
<< "Buffer overrun on output: wrote " << written
|
||||
<< " of " << qty << " samples" << endl;
|
||||
m_log.log(0, "WARNING: writeOutput: buffer overrun: wanted to write and able to write", qty, written);
|
||||
}
|
||||
|
||||
outCount += written;
|
||||
@@ -1206,30 +1130,24 @@ RubberBandStretcher::Impl::writeOutput(RingBuffer<float> &to, float *from, size_
|
||||
// the rest of this is only used during the first startSkip samples
|
||||
|
||||
if (outCount + qty <= startSkip) {
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "qty = " << qty << ", startSkip = "
|
||||
<< startSkip << ", outCount = " << outCount
|
||||
<< ", discarding" << endl;
|
||||
}
|
||||
m_log.log(2, "discarding with startSkip", startSkip);
|
||||
m_log.log(2, "qty and outCount", qty, outCount);
|
||||
outCount += qty;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t off = startSkip - outCount;
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "qty = " << qty << ", startSkip = "
|
||||
<< startSkip << ", outCount = " << outCount
|
||||
<< ", writing " << qty - off
|
||||
<< " from start offset " << off << endl;
|
||||
}
|
||||
m_log.log(2, "shortening with startSkip", startSkip);
|
||||
m_log.log(2, "qty and outCount", qty, outCount);
|
||||
m_log.log(2, "start offset and number written", off, qty - off);
|
||||
to.write(from + off, qty - off);
|
||||
outCount += qty;
|
||||
}
|
||||
|
||||
int
|
||||
RubberBandStretcher::Impl::available() const
|
||||
R2Stretcher::available() const
|
||||
{
|
||||
Profiler profiler("RubberBandStretcher::Impl::available");
|
||||
Profiler profiler("R2Stretcher::available");
|
||||
|
||||
#ifndef NO_THREADING
|
||||
if (m_threaded) {
|
||||
@@ -1245,15 +1163,12 @@ RubberBandStretcher::Impl::available() const
|
||||
#endif
|
||||
for (size_t c = 0; c < m_channels; ++c) {
|
||||
if (m_channelData[c]->inputSize >= 0) {
|
||||
// cerr << "available: m_done true" << endl;
|
||||
if (m_channelData[c]->inbuf->getReadSpace() > 0) {
|
||||
if (m_debugLevel > 1) {
|
||||
cerr << "calling processChunks(" << c << ") from available" << endl;
|
||||
}
|
||||
m_log.log(2, "calling processChunks from available, channel" , c);
|
||||
//!!! do we ever actually do this? if so, this method should not be const
|
||||
// ^^^ yes, we do sometimes -- e.g. when fed a very short file
|
||||
bool any = false, last = false;
|
||||
((RubberBandStretcher::Impl *)this)->processChunks(c, any, last);
|
||||
((R2Stretcher *)this)->processChunks(c, any, last);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1268,9 +1183,7 @@ RubberBandStretcher::Impl::available() const
|
||||
for (size_t i = 0; i < m_channels; ++i) {
|
||||
size_t availIn = m_channelData[i]->inbuf->getReadSpace();
|
||||
size_t availOut = m_channelData[i]->outbuf->getReadSpace();
|
||||
if (m_debugLevel > 2) {
|
||||
cerr << "available on channel " << i << ": " << availOut << " (waiting: " << availIn << ")" << endl;
|
||||
}
|
||||
m_log.log(3, "available in and out", availIn, availOut);
|
||||
if (i == 0 || availOut < min) min = availOut;
|
||||
if (!m_channelData[i]->outputComplete) consumed = false;
|
||||
if (m_channelData[i]->resampler) haveResamplers = true;
|
||||
@@ -1284,9 +1197,9 @@ RubberBandStretcher::Impl::available() const
|
||||
}
|
||||
|
||||
size_t
|
||||
RubberBandStretcher::Impl::retrieve(float *const *output, size_t samples) const
|
||||
R2Stretcher::retrieve(float *const *output, size_t samples) const
|
||||
{
|
||||
Profiler profiler("RubberBandStretcher::Impl::retrieve");
|
||||
Profiler profiler("R2Stretcher::retrieve");
|
||||
|
||||
size_t got = samples;
|
||||
|
||||
@@ -1294,15 +1207,14 @@ RubberBandStretcher::Impl::retrieve(float *const *output, size_t samples) const
|
||||
size_t gotHere = m_channelData[c]->outbuf->read(output[c], got);
|
||||
if (gotHere < got) {
|
||||
if (c > 0) {
|
||||
if (m_debugLevel > 0) {
|
||||
cerr << "RubberBandStretcher::Impl::retrieve: WARNING: channel imbalance detected" << endl;
|
||||
}
|
||||
m_log.log(0, "R2Stretcher::retrieve: WARNING: channel imbalance detected");
|
||||
}
|
||||
got = gotHere;
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_options & OptionChannelsTogether) && (m_channels >= 2)) {
|
||||
if ((m_options & RubberBandStretcher::OptionChannelsTogether) &&
|
||||
(m_channels >= 2)) {
|
||||
for (size_t i = 0; i < got; ++i) {
|
||||
float mid = output[0][i];
|
||||
float side = output[1][i];
|
||||
149
src/finer/BinClassifier.h
Normal file
149
src/finer/BinClassifier.h
Normal file
@@ -0,0 +1,149 @@
|
||||
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||
|
||||
/*
|
||||
Rubber Band Library
|
||||
An audio time-stretching and pitch-shifting library.
|
||||
Copyright 2007-2022 Particular Programs Ltd.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version. See the file
|
||||
COPYING included with this distribution for more information.
|
||||
|
||||
Alternatively, if you have a valid commercial licence for the
|
||||
Rubber Band Library obtained by agreement with the copyright
|
||||
holders, you may redistribute and/or modify it under the terms
|
||||
described in that licence.
|
||||
|
||||
If you wish to distribute code using the Rubber Band Library
|
||||
under terms other than those of the GNU General Public License,
|
||||
you must obtain a valid commercial licence before doing so.
|
||||
*/
|
||||
|
||||
#ifndef RUBBERBAND_BIN_CLASSIFIER_H
|
||||
#define RUBBERBAND_BIN_CLASSIFIER_H
|
||||
|
||||
#include "../common/Allocators.h"
|
||||
#include "../common/MovingMedian.h"
|
||||
#include "../common/RingBuffer.h"
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace RubberBand {
|
||||
|
||||
class BinClassifier
|
||||
{
|
||||
public:
|
||||
enum class Classification {
|
||||
Harmonic = 0,
|
||||
Percussive = 1,
|
||||
Residual = 2
|
||||
};
|
||||
|
||||
struct Parameters {
|
||||
int binCount;
|
||||
int horizontalFilterLength;
|
||||
int horizontalFilterLag;
|
||||
int verticalFilterLength;
|
||||
double harmonicThreshold;
|
||||
double percussiveThreshold;
|
||||
Parameters(int _binCount, int _horizontalFilterLength,
|
||||
int _horizontalFilterLag, int _verticalFilterLength,
|
||||
double _harmonicThreshold, double _percussiveThreshold) :
|
||||
binCount(_binCount),
|
||||
horizontalFilterLength(_horizontalFilterLength),
|
||||
horizontalFilterLag(_horizontalFilterLag),
|
||||
verticalFilterLength(_verticalFilterLength),
|
||||
harmonicThreshold(_harmonicThreshold),
|
||||
percussiveThreshold(_percussiveThreshold) { }
|
||||
};
|
||||
|
||||
BinClassifier(Parameters parameters) :
|
||||
m_parameters(parameters),
|
||||
m_hFilters(new MovingMedianStack<double>(m_parameters.binCount,
|
||||
m_parameters.horizontalFilterLength)),
|
||||
m_vFilter(new MovingMedian<double>(m_parameters.verticalFilterLength)),
|
||||
m_vfQueue(parameters.horizontalFilterLag)
|
||||
{
|
||||
int n = m_parameters.binCount;
|
||||
|
||||
m_hf = allocate_and_zero<double>(n);
|
||||
m_vf = allocate_and_zero<double>(n);
|
||||
|
||||
for (int i = 0; i < m_parameters.horizontalFilterLag; ++i) {
|
||||
double *entry = allocate_and_zero<double>(n);
|
||||
m_vfQueue.write(&entry, 1);
|
||||
}
|
||||
}
|
||||
|
||||
~BinClassifier()
|
||||
{
|
||||
while (m_vfQueue.getReadSpace() > 0) {
|
||||
double *entry = m_vfQueue.readOne();
|
||||
deallocate(entry);
|
||||
}
|
||||
|
||||
deallocate(m_hf);
|
||||
deallocate(m_vf);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_hFilters->reset();
|
||||
}
|
||||
|
||||
void classify(const double *const mag, // input, of at least binCount bins
|
||||
Classification *classification) // output, of binCount bins
|
||||
{
|
||||
const int n = m_parameters.binCount;
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
m_hFilters->push(i, mag[i]);
|
||||
m_hf[i] = m_hFilters->get(i);
|
||||
}
|
||||
|
||||
v_copy(m_vf, mag, n);
|
||||
MovingMedian<double>::filter(*m_vFilter, m_vf, n);
|
||||
|
||||
if (m_parameters.horizontalFilterLag > 0) {
|
||||
double *lagged = m_vfQueue.readOne();
|
||||
m_vfQueue.write(&m_vf, 1);
|
||||
m_vf = lagged;
|
||||
}
|
||||
|
||||
double eps = 1.0e-7;
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
Classification c;
|
||||
if (double(m_hf[i]) / (double(m_vf[i]) + eps) >
|
||||
m_parameters.harmonicThreshold) {
|
||||
c = Classification::Harmonic;
|
||||
} else if (double(m_vf[i]) / (double(m_hf[i]) + eps) >
|
||||
m_parameters.percussiveThreshold) {
|
||||
c = Classification::Percussive;
|
||||
} else {
|
||||
c = Classification::Residual;
|
||||
}
|
||||
classification[i] = c;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
Parameters m_parameters;
|
||||
std::unique_ptr<MovingMedianStack<double>> m_hFilters;
|
||||
std::unique_ptr<MovingMedian<double>> m_vFilter;
|
||||
// We manage the queued frames through pointer swapping, hence
|
||||
// bare pointers here
|
||||
double *m_hf;
|
||||
double *m_vf;
|
||||
RingBuffer<double *> m_vfQueue;
|
||||
|
||||
BinClassifier(const BinClassifier &) =delete;
|
||||
BinClassifier &operator=(const BinClassifier &) =delete;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user