Update from main repo.
* Add a more reliable transient detection mode, and make the mode selectable using OptionDetectorXXX flags -- the new method is the default * Band-limit transient detectors to avoid being distracted by inaudible garbage * Add a key-frame mapping facility for variable stretch ratio management during offline stretches
This commit is contained in:
18
CHANGELOG
18
CHANGELOG
@@ -1,4 +1,20 @@
|
|||||||
|
|
||||||
|
Changed in Rubber Band v1.5
|
||||||
|
|
||||||
|
* Add a more reliable transient detection mode, and make the mode
|
||||||
|
selectable using OptionDetectorXXX flags -- the new method is
|
||||||
|
the default
|
||||||
|
* Band-limit transient detectors to avoid being distracted by
|
||||||
|
inaudible garbage
|
||||||
|
* Add a key-frame mapping facility for variable stretch ratio
|
||||||
|
management during offline stretches
|
||||||
|
|
||||||
|
The library is binary compatible with version 1.4 for forward
|
||||||
|
compatibility (a function and an enum have been added, but no existing
|
||||||
|
entry points have changed). Code written to use 1.5 is not
|
||||||
|
necessarily compatible with 1.4.
|
||||||
|
|
||||||
|
|
||||||
Changes in Rubber Band v1.4
|
Changes in Rubber Band v1.4
|
||||||
|
|
||||||
* Fix a hang when faced with some very peculiar stretch factors
|
* Fix a hang when faced with some very peculiar stretch factors
|
||||||
@@ -20,7 +36,7 @@ The library is binary compatible with version 1.2.
|
|||||||
|
|
||||||
Changes in Rubber Band v1.2
|
Changes in Rubber Band v1.2
|
||||||
|
|
||||||
* Added an initial "formant preservation" option when pitch shifting
|
* Add an initial "formant preservation" option when pitch shifting
|
||||||
* Real-time pitch shifting now uses a faster method by default, with
|
* Real-time pitch shifting now uses a faster method by default, with
|
||||||
less variation in CPU usage
|
less variation in CPU usage
|
||||||
* The code is more amenable to compiler auto-vectorization (through
|
* The code is more amenable to compiler auto-vectorization (through
|
||||||
|
|||||||
11
Makefile.in
11
Makefile.in
@@ -56,13 +56,15 @@ LIBRARY_INCLUDES := \
|
|||||||
src/base/RingBuffer.h \
|
src/base/RingBuffer.h \
|
||||||
src/base/Scavenger.h \
|
src/base/Scavenger.h \
|
||||||
src/dsp/AudioCurveCalculator.h \
|
src/dsp/AudioCurveCalculator.h \
|
||||||
|
src/dsp/CompoundAudioCurve.h \
|
||||||
|
src/dsp/ConstantAudioCurve.h \
|
||||||
|
src/dsp/HighFrequencyAudioCurve.h \
|
||||||
|
src/dsp/PercussiveAudioCurve.h \
|
||||||
|
src/dsp/SilentAudioCurve.h \
|
||||||
src/dsp/SpectralDifferenceAudioCurve.h \
|
src/dsp/SpectralDifferenceAudioCurve.h \
|
||||||
src/dsp/Resampler.h \
|
src/dsp/Resampler.h \
|
||||||
src/dsp/HighFrequencyAudioCurve.h \
|
|
||||||
src/dsp/SilentAudioCurve.h \
|
|
||||||
src/dsp/FFT.h \
|
src/dsp/FFT.h \
|
||||||
src/dsp/PercussiveAudioCurve.h \
|
src/dsp/MovingMedian.h \
|
||||||
src/dsp/ConstantAudioCurve.h \
|
|
||||||
src/dsp/Window.h \
|
src/dsp/Window.h \
|
||||||
src/system/Allocators.h \
|
src/system/Allocators.h \
|
||||||
src/system/Thread.h \
|
src/system/Thread.h \
|
||||||
@@ -76,6 +78,7 @@ LIBRARY_SOURCES := \
|
|||||||
src/StretchCalculator.cpp \
|
src/StretchCalculator.cpp \
|
||||||
src/base/Profiler.cpp \
|
src/base/Profiler.cpp \
|
||||||
src/dsp/AudioCurveCalculator.cpp \
|
src/dsp/AudioCurveCalculator.cpp \
|
||||||
|
src/dsp/CompoundAudioCurve.cpp \
|
||||||
src/dsp/SpectralDifferenceAudioCurve.cpp \
|
src/dsp/SpectralDifferenceAudioCurve.cpp \
|
||||||
src/dsp/HighFrequencyAudioCurve.cpp \
|
src/dsp/HighFrequencyAudioCurve.cpp \
|
||||||
src/dsp/SilentAudioCurve.cpp \
|
src/dsp/SilentAudioCurve.cpp \
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Rubber Band
|
|||||||
|
|
||||||
An audio time-stretching and pitch-shifting library and utility program.
|
An audio time-stretching and pitch-shifting library and utility program.
|
||||||
|
|
||||||
Copyright 2008-2009 Chris Cannam, cannam@all-day-breakfast.com.
|
Copyright 2007-2010 Chris Cannam, cannam@all-day-breakfast.com.
|
||||||
|
|
||||||
Distributed under the GNU General Public License.
|
Distributed under the GNU General Public License.
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ shifts it up in pitch by one octave, and writes the output to output.wav.
|
|||||||
|
|
||||||
Several further options are available: run "rubberband -h" for help.
|
Several further options are available: run "rubberband -h" for help.
|
||||||
In particular, different types of music may benefit from different
|
In particular, different types of music may benefit from different
|
||||||
"crispness" options (-c <n> where <n> is from 0 to 5).
|
"crispness" options (-c <n> where <n> is from 0 to 6).
|
||||||
|
|
||||||
|
|
||||||
Using the Rubber Band library
|
Using the Rubber Band library
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
|
|||||||
127
main/main.cpp
127
main/main.cpp
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -20,6 +20,9 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
#include "system/sysutils.h"
|
#include "system/sysutils.h"
|
||||||
|
|
||||||
@@ -87,12 +90,20 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
bool haveRatio = false;
|
bool haveRatio = false;
|
||||||
|
|
||||||
|
std::string mapfile;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
NoTransients,
|
NoTransients,
|
||||||
BandLimitedTransients,
|
BandLimitedTransients,
|
||||||
Transients
|
Transients
|
||||||
} transients = Transients;
|
} transients = Transients;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CompoundDetector,
|
||||||
|
PercussiveDetector,
|
||||||
|
SoftDetector
|
||||||
|
} detector = CompoundDetector;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
int optionIndex = 0;
|
int optionIndex = 0;
|
||||||
|
|
||||||
@@ -116,13 +127,18 @@ int main(int argc, char **argv)
|
|||||||
{ "window-long", 0, 0, '3' },
|
{ "window-long", 0, 0, '3' },
|
||||||
{ "window-short", 0, 0, '4' },
|
{ "window-short", 0, 0, '4' },
|
||||||
{ "bl-transients", 0, 0, '8' },
|
{ "bl-transients", 0, 0, '8' },
|
||||||
|
{ "detector-perc", 0, 0, '5' },
|
||||||
|
{ "detector-soft", 0, 0, '6' },
|
||||||
{ "pitch-hq", 0, 0, '%' },
|
{ "pitch-hq", 0, 0, '%' },
|
||||||
{ "threads", 0, 0, '@' },
|
{ "threads", 0, 0, '@' },
|
||||||
{ "quiet", 0, 0, 'q' },
|
{ "quiet", 0, 0, 'q' },
|
||||||
|
{ "timemap", 1, 0, 'M' },
|
||||||
{ 0, 0, 0, 0 }
|
{ 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
c = getopt_long(argc, argv, "t:p:d:RPFc:f:T:D:qhV", longOpts, &optionIndex);
|
c = getopt_long(argc, argv,
|
||||||
|
"t:p:d:RPFc:f:T:D:qhVM:",
|
||||||
|
longOpts, &optionIndex);
|
||||||
if (c == -1) break;
|
if (c == -1) break;
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
@@ -143,10 +159,13 @@ int main(int argc, char **argv)
|
|||||||
case '2': lamination = false; crispchanged = true; break;
|
case '2': lamination = false; crispchanged = true; break;
|
||||||
case '3': longwin = true; crispchanged = true; break;
|
case '3': longwin = true; crispchanged = true; break;
|
||||||
case '4': shortwin = true; crispchanged = true; break;
|
case '4': shortwin = true; crispchanged = true; break;
|
||||||
|
case '5': detector = PercussiveDetector; crispchanged = true; break;
|
||||||
|
case '6': detector = SoftDetector; crispchanged = true; break;
|
||||||
case '8': transients = BandLimitedTransients; crispchanged = true; break;
|
case '8': transients = BandLimitedTransients; crispchanged = true; break;
|
||||||
case '%': hqpitch = true; break;
|
case '%': hqpitch = true; break;
|
||||||
case 'c': crispness = atoi(optarg); break;
|
case 'c': crispness = atoi(optarg); break;
|
||||||
case 'q': quiet = true; break;
|
case 'q': quiet = true; break;
|
||||||
|
case 'M': mapfile = optarg; break;
|
||||||
default: help = true; break;
|
default: help = true; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,7 +179,7 @@ int main(int argc, char **argv)
|
|||||||
cerr << endl;
|
cerr << endl;
|
||||||
cerr << "Rubber Band" << endl;
|
cerr << "Rubber Band" << endl;
|
||||||
cerr << "An audio time-stretching and pitch-shifting library and utility program." << endl;
|
cerr << "An audio time-stretching and pitch-shifting library and utility program." << endl;
|
||||||
cerr << "Copyright 2009 Chris Cannam. Distributed under the GNU General Public License." << endl;
|
cerr << "Copyright 2010 Chris Cannam. Distributed under the GNU General Public License." << endl;
|
||||||
cerr << endl;
|
cerr << endl;
|
||||||
cerr << " Usage: " << argv[0] << " [options] <infile.wav> <outfile.wav>" << endl;
|
cerr << " Usage: " << argv[0] << " [options] <infile.wav> <outfile.wav>" << endl;
|
||||||
cerr << endl;
|
cerr << endl;
|
||||||
@@ -174,10 +193,17 @@ int main(int argc, char **argv)
|
|||||||
cerr << " -p<X>, --pitch <X> Raise pitch by X semitones, or" << endl;
|
cerr << " -p<X>, --pitch <X> Raise pitch by X semitones, or" << endl;
|
||||||
cerr << " -f<X>, --frequency <X> Change frequency by multiple X" << endl;
|
cerr << " -f<X>, --frequency <X> Change frequency by multiple X" << endl;
|
||||||
cerr << endl;
|
cerr << endl;
|
||||||
|
cerr << " -M<F>, --timemap <F> Use file F as the source for key frame map" << endl;
|
||||||
|
cerr << endl;
|
||||||
|
cerr << "A map file consists of a series of lines each having two numbers separated" << endl;
|
||||||
|
cerr << "by a single space. These are source and target sample frame numbers for fixed" << endl;
|
||||||
|
cerr << "time points within the audio data, defining a varying stretch factor through" << endl;
|
||||||
|
cerr << "the audio. You must specify an overall stretch factor using e.g. -t as well." << endl;
|
||||||
|
cerr << endl;
|
||||||
cerr << "The following options provide a simple way to adjust the sound. See below" << endl;
|
cerr << "The following options provide a simple way to adjust the sound. See below" << endl;
|
||||||
cerr << "for more details." << endl;
|
cerr << "for more details." << endl;
|
||||||
cerr << endl;
|
cerr << endl;
|
||||||
cerr << " -c<N>, --crisp <N> Crispness (N = 0,1,2,3,4,5); default 4 (see below)" << 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 << " -F, --formant Enable formant preservation when pitch shifting" << endl;
|
||||||
cerr << endl;
|
cerr << endl;
|
||||||
cerr << "The remaining options fine-tune the processing mode and stretch algorithm." << endl;
|
cerr << "The remaining options fine-tune the processing mode and stretch algorithm." << endl;
|
||||||
@@ -194,6 +220,8 @@ int main(int argc, char **argv)
|
|||||||
cerr << " --no-lamination Disable phase lamination" << endl;
|
cerr << " --no-lamination Disable phase lamination" << endl;
|
||||||
cerr << " --window-long Use longer processing window (actual size may vary)" << endl;
|
cerr << " --window-long Use longer processing window (actual size may vary)" << endl;
|
||||||
cerr << " --window-short Use shorter processing window" << endl;
|
cerr << " --window-short Use shorter processing window" << endl;
|
||||||
|
cerr << " --detector-perc Use percussive transient detector (as in pre-1.5)" << endl;
|
||||||
|
cerr << " --detector-soft Use soft transient detector" << endl;
|
||||||
cerr << " --pitch-hq In RT mode, use a slower, higher quality pitch shift" << endl;
|
cerr << " --pitch-hq In RT mode, use a slower, higher quality pitch shift" << endl;
|
||||||
cerr << endl;
|
cerr << endl;
|
||||||
cerr << " -d<N>, --debug <N> Select debug level (N = 0,1,2,3); default 0, full 3" << endl;
|
cerr << " -d<N>, --debug <N> Select debug level (N = 0,1,2,3); default 0, full 3" << endl;
|
||||||
@@ -205,11 +233,12 @@ int main(int argc, char **argv)
|
|||||||
cerr << endl;
|
cerr << endl;
|
||||||
cerr << "\"Crispness\" levels:" << endl;
|
cerr << "\"Crispness\" levels:" << endl;
|
||||||
cerr << " -c 0 equivalent to --no-transients --no-lamination --window-long" << endl;
|
cerr << " -c 0 equivalent to --no-transients --no-lamination --window-long" << endl;
|
||||||
cerr << " -c 1 equivalent to --no-transients --no-lamination" << endl;
|
cerr << " -c 1 equivalent to --detector-soft --no-lamination --window-long (for piano)" << endl;
|
||||||
cerr << " -c 2 equivalent to --no-transients" << endl;
|
cerr << " -c 2 equivalent to --no-transients --no-lamination" << endl;
|
||||||
cerr << " -c 3 equivalent to --bl-transients" << endl;
|
cerr << " -c 3 equivalent to --no-transients" << endl;
|
||||||
cerr << " -c 4 default processing options" << endl;
|
cerr << " -c 4 equivalent to --bl-transients" << endl;
|
||||||
cerr << " -c 5 equivalent to --no-lamination --window-short (may be good for drums)" << endl;
|
cerr << " -c 5 default processing options" << endl;
|
||||||
|
cerr << " -c 6 equivalent to --no-lamination --window-short (may be good for drums)" << endl;
|
||||||
cerr << endl;
|
cerr << endl;
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
@@ -220,28 +249,68 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (crispness) {
|
switch (crispness) {
|
||||||
case -1: crispness = 4; break;
|
case -1: crispness = 5; break;
|
||||||
case 0: transients = NoTransients; lamination = false; longwin = true; shortwin = false; break;
|
case 0: detector = CompoundDetector; transients = NoTransients; lamination = false; longwin = true; shortwin = false; break;
|
||||||
case 1: transients = NoTransients; lamination = false; longwin = false; shortwin = false; break;
|
case 1: detector = SoftDetector; transients = Transients; lamination = false; longwin = true; shortwin = false; break;
|
||||||
case 2: transients = NoTransients; lamination = true; longwin = false; shortwin = false; break;
|
case 2: detector = CompoundDetector; transients = NoTransients; lamination = false; longwin = false; shortwin = false; break;
|
||||||
case 3: transients = BandLimitedTransients; lamination = true; longwin = false; shortwin = false; break;
|
case 3: detector = CompoundDetector; transients = NoTransients; lamination = true; longwin = false; shortwin = false; break;
|
||||||
case 4: transients = Transients; lamination = true; longwin = false; shortwin = false; break;
|
case 4: detector = CompoundDetector; transients = BandLimitedTransients; lamination = true; longwin = false; shortwin = false; break;
|
||||||
case 5: transients = Transients; lamination = false; longwin = false; shortwin = true; break;
|
case 5: detector = CompoundDetector; transients = Transients; lamination = true; longwin = false; shortwin = false; break;
|
||||||
|
case 6: detector = CompoundDetector; transients = Transients; lamination = false; longwin = false; shortwin = true; break;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
cerr << "Using crispness level: " << crispness << " (";
|
cerr << "Using crispness level: " << crispness << " (";
|
||||||
switch (crispness) {
|
switch (crispness) {
|
||||||
case 0: cerr << "Mushy"; break;
|
case 0: cerr << "Mushy"; break;
|
||||||
case 1: cerr << "Smooth"; break;
|
case 1: cerr << "Piano"; break;
|
||||||
case 2: cerr << "Balanced multitimbral mixture"; break;
|
case 2: cerr << "Smooth"; break;
|
||||||
case 3: cerr << "Unpitched percussion with stable notes"; break;
|
case 3: cerr << "Balanced multitimbral mixture"; break;
|
||||||
case 4: cerr << "Crisp monophonic instrumental"; break;
|
case 4: cerr << "Unpitched percussion with stable notes"; break;
|
||||||
case 5: cerr << "Unpitched solo percussion"; break;
|
case 5: cerr << "Crisp monophonic instrumental"; break;
|
||||||
|
case 6: cerr << "Unpitched solo percussion"; break;
|
||||||
}
|
}
|
||||||
cerr << ")" << endl;
|
cerr << ")" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::map<size_t, size_t> mapping;
|
||||||
|
|
||||||
|
if (mapfile != "") {
|
||||||
|
std::ifstream ifile(mapfile.c_str());
|
||||||
|
if (!ifile.is_open()) {
|
||||||
|
cerr << "ERROR: Failed to open time map file \"" << mapfile << "\""
|
||||||
|
<< endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
std::string line;
|
||||||
|
int lineno = 0;
|
||||||
|
while (!ifile.eof()) {
|
||||||
|
std::getline(ifile, line);
|
||||||
|
while (line.length() > 0 && line[0] == ' ') line = line.substr(1);
|
||||||
|
if (line == "") {
|
||||||
|
++lineno;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string::size_type i = line.find_first_of(" ");
|
||||||
|
if (i == std::string::npos) {
|
||||||
|
cerr << "ERROR: Time map file \"" << mapfile
|
||||||
|
<< "\" is malformed at line " << lineno << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
size_t source = atoi(line.substr(0, i).c_str());
|
||||||
|
while (i < line.length() && line[i] == ' ') ++i;
|
||||||
|
size_t target = atoi(line.substr(i).c_str());
|
||||||
|
mapping[source] = target;
|
||||||
|
cerr << "adding mapping from " << source << " to " << target << endl;
|
||||||
|
++lineno;
|
||||||
|
}
|
||||||
|
ifile.close();
|
||||||
|
|
||||||
|
if (!quiet) {
|
||||||
|
cerr << "Read " << mapping.size() << " line(s) from map file" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char *fileName = strdup(argv[optind++]);
|
char *fileName = strdup(argv[optind++]);
|
||||||
char *fileNameOut = strdup(argv[optind++]);
|
char *fileNameOut = strdup(argv[optind++]);
|
||||||
|
|
||||||
@@ -317,6 +386,18 @@ int main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (detector) {
|
||||||
|
case CompoundDetector:
|
||||||
|
options |= RubberBandStretcher::OptionDetectorCompound;
|
||||||
|
break;
|
||||||
|
case PercussiveDetector:
|
||||||
|
options |= RubberBandStretcher::OptionDetectorPercussive;
|
||||||
|
break;
|
||||||
|
case SoftDetector:
|
||||||
|
options |= RubberBandStretcher::OptionDetectorSoft;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (pitchshift != 0.0) {
|
if (pitchshift != 0.0) {
|
||||||
frequencyshift *= pow(2.0, pitchshift / 12);
|
frequencyshift *= pow(2.0, pitchshift / 12);
|
||||||
}
|
}
|
||||||
@@ -389,6 +470,10 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
frame = 0;
|
frame = 0;
|
||||||
percent = 0;
|
percent = 0;
|
||||||
|
|
||||||
|
if (!mapping.empty()) {
|
||||||
|
ts.setKeyFrameMap(mapping);
|
||||||
|
}
|
||||||
|
|
||||||
size_t countIn = 0, countOut = 0;
|
size_t countIn = 0, countOut = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -15,11 +15,12 @@
|
|||||||
#ifndef _RUBBERBANDSTRETCHER_H_
|
#ifndef _RUBBERBANDSTRETCHER_H_
|
||||||
#define _RUBBERBANDSTRETCHER_H_
|
#define _RUBBERBANDSTRETCHER_H_
|
||||||
|
|
||||||
#define RUBBERBAND_VERSION "1.4.0-gpl"
|
#define RUBBERBAND_VERSION "1.5.0-gpl"
|
||||||
#define RUBBERBAND_API_MAJOR_VERSION 2
|
#define RUBBERBAND_API_MAJOR_VERSION 2
|
||||||
#define RUBBERBAND_API_MINOR_VERSION 1
|
#define RUBBERBAND_API_MINOR_VERSION 3
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @mainpage RubberBand
|
* @mainpage RubberBand
|
||||||
@@ -123,7 +124,25 @@ public:
|
|||||||
* but may be less clear than with either of the other
|
* but may be less clear than with either of the other
|
||||||
* transients flags.
|
* transients flags.
|
||||||
*
|
*
|
||||||
* 4. Flags prefixed \c OptionPhase control the adjustment of
|
* 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.
|
||||||
|
*
|
||||||
|
* \li \c OptionDetectorCompound - Use a general-purpose
|
||||||
|
* transient detector which is likely to be good for most
|
||||||
|
* situations.
|
||||||
|
*
|
||||||
|
* \li \c OptionDetectorPercussive - Detect percussive
|
||||||
|
* transients. Note that this was the default and only option
|
||||||
|
* in Rubber Band versions prior to 1.5.
|
||||||
|
*
|
||||||
|
* \li \c OptionDetectorSoft - Use an onset detector with less
|
||||||
|
* of a bias toward percussive transients. This may give better
|
||||||
|
* results with certain material (e.g. relatively monophonic
|
||||||
|
* piano music).
|
||||||
|
*
|
||||||
|
* 5. Flags prefixed \c OptionPhase control the adjustment of
|
||||||
* component frequency phases from one analysis window to the next
|
* component frequency phases from one analysis window to the next
|
||||||
* during non-transient segments. These options may be changed at
|
* during non-transient segments. These options may be changed at
|
||||||
* any time.
|
* any time.
|
||||||
@@ -138,7 +157,7 @@ public:
|
|||||||
* frequency bin independently from its neighbours. This
|
* frequency bin independently from its neighbours. This
|
||||||
* usually results in a slightly softer, phasier sound.
|
* usually results in a slightly softer, phasier sound.
|
||||||
*
|
*
|
||||||
* 5. Flags prefixed \c OptionThreading control the threading
|
* 6. Flags prefixed \c OptionThreading control the threading
|
||||||
* model of the stretcher. These options may not be changed after
|
* model of the stretcher. These options may not be changed after
|
||||||
* construction.
|
* construction.
|
||||||
*
|
*
|
||||||
@@ -154,7 +173,7 @@ public:
|
|||||||
* situation where \c OptionThreadingAuto would do so, except omit
|
* situation where \c OptionThreadingAuto would do so, except omit
|
||||||
* the check for multiple CPUs and instead assume it to be true.
|
* the check for multiple CPUs and instead assume it to be true.
|
||||||
*
|
*
|
||||||
* 6. Flags prefixed \c OptionWindow control the window size for
|
* 7. Flags prefixed \c OptionWindow control the window size for
|
||||||
* FFT processing. The window size actually used will depend on
|
* FFT processing. The window size actually used will depend on
|
||||||
* many factors, but it can be influenced. These options may not
|
* many factors, but it can be influenced. These options may not
|
||||||
* be changed after construction.
|
* be changed after construction.
|
||||||
@@ -172,7 +191,7 @@ public:
|
|||||||
* likely to result in a smoother sound at the expense of
|
* likely to result in a smoother sound at the expense of
|
||||||
* clarity and timing.
|
* clarity and timing.
|
||||||
*
|
*
|
||||||
* 7. Flags prefixed \c OptionFormant control the handling of
|
* 8. Flags prefixed \c OptionFormant control the handling of
|
||||||
* formant shape (spectral envelope) when pitch-shifting. These
|
* formant shape (spectral envelope) when pitch-shifting. These
|
||||||
* options may be changed at any time.
|
* options may be changed at any time.
|
||||||
*
|
*
|
||||||
@@ -185,7 +204,7 @@ public:
|
|||||||
* note frequency without so substantially affecting the
|
* note frequency without so substantially affecting the
|
||||||
* perceived pitch profile of the voice or instrument.
|
* perceived pitch profile of the voice or instrument.
|
||||||
*
|
*
|
||||||
* 8. Flags prefixed \c OptionPitch control the method used for
|
* 9. Flags prefixed \c OptionPitch control the method used for
|
||||||
* pitch shifting. These options may be changed at any time.
|
* pitch shifting. These options may be changed at any time.
|
||||||
* They are only effective in realtime mode; in offline mode, the
|
* They are only effective in realtime mode; in offline mode, the
|
||||||
* pitch-shift method is fixed.
|
* pitch-shift method is fixed.
|
||||||
@@ -219,6 +238,10 @@ public:
|
|||||||
OptionTransientsMixed = 0x00000100,
|
OptionTransientsMixed = 0x00000100,
|
||||||
OptionTransientsSmooth = 0x00000200,
|
OptionTransientsSmooth = 0x00000200,
|
||||||
|
|
||||||
|
OptionDetectorCompound = 0x00000000,
|
||||||
|
OptionDetectorPercussive = 0x00000400,
|
||||||
|
OptionDetectorSoft = 0x00000800,
|
||||||
|
|
||||||
OptionPhaseLaminar = 0x00000000,
|
OptionPhaseLaminar = 0x00000000,
|
||||||
OptionPhaseIndependent = 0x00002000,
|
OptionPhaseIndependent = 0x00002000,
|
||||||
|
|
||||||
@@ -348,6 +371,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setTransientsOption(Options options);
|
void setTransientsOption(Options options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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).
|
||||||
|
*/
|
||||||
|
void setDetectorOption(Options options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change an OptionPhase configuration setting. This may be
|
* Change an OptionPhase configuration setting. This may be
|
||||||
* called at any time in any mode.
|
* called at any time in any mode.
|
||||||
@@ -416,6 +447,32 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setMaxProcessSize(size_t samples);
|
void setMaxProcessSize(size_t samples);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a set of mappings from "before" to "after" sample
|
||||||
|
* numbers so as to enforce a particular stretch profile. The
|
||||||
|
* argument is a map from audio sample frame number in the source
|
||||||
|
* material, to the corresponding sample frame number in the
|
||||||
|
* stretched output. The mapping should be for key frames only,
|
||||||
|
* with a "reasonable" gap between mapped samples.
|
||||||
|
*
|
||||||
|
* This function cannot be used in RealTime mode.
|
||||||
|
*
|
||||||
|
* This function may not be called after the first call to
|
||||||
|
* process(). It should be called after the time and pitch ratios
|
||||||
|
* have been set; the results of changing the time and pitch
|
||||||
|
* ratios after calling this function are undefined. Calling
|
||||||
|
* reset() will clear this mapping.
|
||||||
|
*
|
||||||
|
* The key frame map only affects points within the material; it
|
||||||
|
* does not determine the overall stretch ratio (that is, the
|
||||||
|
* ratio between the output material's duration and the source
|
||||||
|
* material's duration). You need to provide this ratio
|
||||||
|
* separately to setTimeRatio(), otherwise the results may be
|
||||||
|
* truncated or extended in unexpected ways regardless of the
|
||||||
|
* extent of the frame numbers found in the key frame map.
|
||||||
|
*/
|
||||||
|
void setKeyFrameMap(const std::map<size_t, size_t> &);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide a block of "samples" sample frames for the stretcher to
|
* Provide a block of "samples" sample frames for the stretcher to
|
||||||
* study and calculate a stretch profile from.
|
* study and calculate a stretch profile from.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -19,9 +19,9 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define RUBBERBAND_VERSION "1.4.0-gpl"
|
#define RUBBERBAND_VERSION "1.5.0-gpl"
|
||||||
#define RUBBERBAND_API_MAJOR_VERSION 2
|
#define RUBBERBAND_API_MAJOR_VERSION 2
|
||||||
#define RUBBERBAND_API_MINOR_VERSION 1
|
#define RUBBERBAND_API_MINOR_VERSION 3
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a C-linkage interface to the Rubber Band time stretcher.
|
* This is a C-linkage interface to the Rubber Band time stretcher.
|
||||||
@@ -48,6 +48,10 @@ enum RubberBandOption {
|
|||||||
RubberBandOptionTransientsMixed = 0x00000100,
|
RubberBandOptionTransientsMixed = 0x00000100,
|
||||||
RubberBandOptionTransientsSmooth = 0x00000200,
|
RubberBandOptionTransientsSmooth = 0x00000200,
|
||||||
|
|
||||||
|
RubberBandOptionDetectorCompound = 0x00000000,
|
||||||
|
RubberBandOptionDetectorPercussive = 0x00000400,
|
||||||
|
RubberBandOptionDetectorSoft = 0x00000800,
|
||||||
|
|
||||||
RubberBandOptionPhaseLaminar = 0x00000000,
|
RubberBandOptionPhaseLaminar = 0x00000000,
|
||||||
RubberBandOptionPhaseIndependent = 0x00002000,
|
RubberBandOptionPhaseIndependent = 0x00002000,
|
||||||
|
|
||||||
@@ -91,6 +95,7 @@ extern double rubberband_get_pitch_scale(const RubberBandState);
|
|||||||
extern unsigned int rubberband_get_latency(const RubberBandState);
|
extern unsigned int rubberband_get_latency(const RubberBandState);
|
||||||
|
|
||||||
extern void rubberband_set_transients_option(RubberBandState, RubberBandOptions options);
|
extern void rubberband_set_transients_option(RubberBandState, RubberBandOptions options);
|
||||||
|
extern void rubberband_set_detector_option(RubberBandState, RubberBandOptions options);
|
||||||
extern void rubberband_set_phase_option(RubberBandState, RubberBandOptions options);
|
extern void rubberband_set_phase_option(RubberBandState, RubberBandOptions options);
|
||||||
extern void rubberband_set_formant_option(RubberBandState, RubberBandOptions options);
|
extern void rubberband_set_formant_option(RubberBandState, RubberBandOptions options);
|
||||||
extern void rubberband_set_pitch_option(RubberBandState, RubberBandOptions options);
|
extern void rubberband_set_pitch_option(RubberBandState, RubberBandOptions options);
|
||||||
@@ -100,6 +105,7 @@ extern void rubberband_set_expected_input_duration(RubberBandState, unsigned int
|
|||||||
extern unsigned int rubberband_get_samples_required(const RubberBandState);
|
extern unsigned int rubberband_get_samples_required(const RubberBandState);
|
||||||
|
|
||||||
extern void rubberband_set_max_process_size(RubberBandState, unsigned int samples);
|
extern void rubberband_set_max_process_size(RubberBandState, unsigned int samples);
|
||||||
|
extern void rubberband_set_key_frame_map(RubberBandState, unsigned int keyframecount, unsigned int *from, unsigned int *to);
|
||||||
|
|
||||||
extern void rubberband_study(RubberBandState, const float *const *input, unsigned int samples, int final);
|
extern void rubberband_study(RubberBandState, const float *const *input, unsigned int samples, int final);
|
||||||
extern void rubberband_process(RubberBandState, const float *const *input, unsigned int samples, int final);
|
extern void rubberband_process(RubberBandState, const float *const *input, unsigned int samples, int final);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -74,6 +74,12 @@ RubberBandStretcher::setTransientsOption(Options options)
|
|||||||
m_d->setTransientsOption(options);
|
m_d->setTransientsOption(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RubberBandStretcher::setDetectorOption(Options options)
|
||||||
|
{
|
||||||
|
m_d->setDetectorOption(options);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RubberBandStretcher::setPhaseOption(Options options)
|
RubberBandStretcher::setPhaseOption(Options options)
|
||||||
{
|
{
|
||||||
@@ -104,6 +110,12 @@ RubberBandStretcher::setMaxProcessSize(size_t samples)
|
|||||||
m_d->setMaxProcessSize(samples);
|
m_d->setMaxProcessSize(samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RubberBandStretcher::setKeyFrameMap(const std::map<size_t, size_t> &mapping)
|
||||||
|
{
|
||||||
|
m_d->setKeyFrameMap(mapping);
|
||||||
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
RubberBandStretcher::getSamplesRequired() const
|
RubberBandStretcher::getSamplesRequired() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -45,6 +45,21 @@ 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>
|
std::vector<int>
|
||||||
StretchCalculator::calculate(double ratio, size_t inputDuration,
|
StretchCalculator::calculate(double ratio, size_t inputDuration,
|
||||||
const std::vector<float> &phaseResetDf,
|
const std::vector<float> &phaseResetDf,
|
||||||
@@ -52,11 +67,9 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
|||||||
{
|
{
|
||||||
assert(phaseResetDf.size() == stretchDf.size());
|
assert(phaseResetDf.size() == stretchDf.size());
|
||||||
|
|
||||||
m_lastPeaks = findPeaks(phaseResetDf);
|
m_peaks = findPeaks(phaseResetDf);
|
||||||
std::vector<Peak> &peaks = m_lastPeaks;
|
|
||||||
size_t totalCount = phaseResetDf.size();
|
|
||||||
|
|
||||||
std::vector<int> increments;
|
size_t totalCount = phaseResetDf.size();
|
||||||
|
|
||||||
size_t outputDuration = lrint(inputDuration * ratio);
|
size_t outputDuration = lrint(inputDuration * ratio);
|
||||||
|
|
||||||
@@ -68,14 +81,13 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
|||||||
|
|
||||||
if (m_debugLevel > 0) {
|
if (m_debugLevel > 0) {
|
||||||
std::cerr << " (rounded up to " << outputDuration << ")";
|
std::cerr << " (rounded up to " << outputDuration << ")";
|
||||||
std::cerr << ", df size " << phaseResetDf.size() << std::endl;
|
std::cerr << ", df size " << phaseResetDf.size() << ", increment "
|
||||||
|
<< m_increment << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<size_t> fixedAudioChunks;
|
std::vector<Peak> peaks; // peak position (in chunks) and hardness
|
||||||
for (size_t i = 0; i < peaks.size(); ++i) {
|
std::vector<size_t> targets; // targets for mapping peaks (in samples)
|
||||||
fixedAudioChunks.push_back
|
mapPeaks(peaks, targets, outputDuration, totalCount);
|
||||||
(lrint((double(peaks[i].chunk) * outputDuration) / totalCount));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_debugLevel > 1) {
|
if (m_debugLevel > 1) {
|
||||||
std::cerr << "have " << peaks.size() << " fixed positions" << std::endl;
|
std::cerr << "have " << peaks.size() << " fixed positions" << std::endl;
|
||||||
@@ -93,6 +105,8 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
|||||||
|
|
||||||
size_t regionTotalChunks = 0;
|
size_t regionTotalChunks = 0;
|
||||||
|
|
||||||
|
std::vector<int> increments;
|
||||||
|
|
||||||
for (size_t i = 0; i <= peaks.size(); ++i) {
|
for (size_t i = 0; i <= peaks.size(); ++i) {
|
||||||
|
|
||||||
size_t regionStart, regionStartChunk, regionEnd, regionEndChunk;
|
size_t regionStart, regionStartChunk, regionEnd, regionEndChunk;
|
||||||
@@ -103,17 +117,23 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
|||||||
regionStart = 0;
|
regionStart = 0;
|
||||||
} else {
|
} else {
|
||||||
regionStartChunk = peaks[i-1].chunk;
|
regionStartChunk = peaks[i-1].chunk;
|
||||||
regionStart = fixedAudioChunks[i-1];
|
regionStart = targets[i-1];
|
||||||
phaseReset = peaks[i-1].hard;
|
phaseReset = peaks[i-1].hard;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == peaks.size()) {
|
if (i == peaks.size()) {
|
||||||
|
// std::cerr << "note: i (=" << i << ") == peaks.size(); regionEndChunk " << regionEndChunk << " -> " << totalCount << ", regionEnd " << regionEnd << " -> " << outputDuration << std::endl;
|
||||||
regionEndChunk = totalCount;
|
regionEndChunk = totalCount;
|
||||||
regionEnd = outputDuration;
|
regionEnd = outputDuration;
|
||||||
} else {
|
} else {
|
||||||
regionEndChunk = peaks[i].chunk;
|
regionEndChunk = peaks[i].chunk;
|
||||||
regionEnd = fixedAudioChunks[i];
|
regionEnd = targets[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (regionStartChunk > totalCount) regionStartChunk = totalCount;
|
||||||
|
if (regionStart > outputDuration) regionStart = outputDuration;
|
||||||
|
if (regionEndChunk > totalCount) regionEndChunk = totalCount;
|
||||||
|
if (regionEnd > outputDuration) regionEnd = outputDuration;
|
||||||
|
|
||||||
size_t regionDuration = regionEnd - regionStart;
|
size_t regionDuration = regionEnd - regionStart;
|
||||||
regionTotalChunks += regionDuration;
|
regionTotalChunks += regionDuration;
|
||||||
@@ -125,7 +145,7 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_debugLevel > 1) {
|
if (m_debugLevel > 1) {
|
||||||
std::cerr << "distributeRegion from " << regionStartChunk << " to " << regionEndChunk << " (chunks " << regionStart << " to " << regionEnd << ")" << std::endl;
|
std::cerr << "distributeRegion from " << regionStartChunk << " to " << regionEndChunk << " (samples " << regionStart << " to " << regionEnd << ")" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
dfRegion = smoothDF(dfRegion);
|
dfRegion = smoothDF(dfRegion);
|
||||||
@@ -149,7 +169,7 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (totalForRegion != regionDuration) {
|
if (totalForRegion != regionDuration) {
|
||||||
std::cerr << "*** WARNING: distributeRegion returned wrong duration " << totalForRegion << ", expected " << regionDuration << std::endl;
|
std::cerr << "*** ERROR: distributeRegion returned wrong duration " << totalForRegion << ", expected " << regionDuration << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
totalOutput += totalForRegion;
|
totalOutput += totalForRegion;
|
||||||
@@ -163,6 +183,131 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
|||||||
return increments;
|
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 setLockPoints 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()) {
|
||||||
|
|
||||||
|
// std::cerr << "mi->first is " << mi->first << ", second is " << mi->second <<std::endl;
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
std::cerr << "NOTE: ignoring mapping from chunk " << sourceStartChunk << " to sample " << targetStartSample << "\n(source or target chunk exceeds total count, or end is not later than start)" << std::endl;
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (m_debugLevel > 1) {
|
||||||
|
std::cerr << "mapped chunk " << sourceStartChunk << " (frame " << sourceStartChunk * m_increment << ") -> " << targetStartSample << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_debugLevel > 1) {
|
||||||
|
std::cerr << " peak chunk " << pchunk << " (frame " << pchunk * m_increment << ") -> " << target << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
peaks.push_back(p);
|
||||||
|
targets.push_back(target);
|
||||||
|
++peakidx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
StretchCalculator::calculateSingle(double ratio,
|
StretchCalculator::calculateSingle(double ratio,
|
||||||
float df,
|
float df,
|
||||||
@@ -182,7 +327,7 @@ StretchCalculator::calculateSingle(double ratio,
|
|||||||
// works well in common situations.
|
// works well in common situations.
|
||||||
|
|
||||||
float transientThreshold = 0.35f;
|
float transientThreshold = 0.35f;
|
||||||
if (ratio > 1) transientThreshold = 0.25f;
|
// if (ratio > 1) transientThreshold = 0.25f;
|
||||||
|
|
||||||
if (m_useHardPeaks && df > m_prevDf * 1.1f && df > transientThreshold) {
|
if (m_useHardPeaks && df > m_prevDf * 1.1f && df > transientThreshold) {
|
||||||
isTransient = true;
|
isTransient = true;
|
||||||
@@ -200,8 +345,7 @@ StretchCalculator::calculateSingle(double ratio,
|
|||||||
|
|
||||||
if (isTransient && m_transientAmnesty == 0) {
|
if (isTransient && m_transientAmnesty == 0) {
|
||||||
if (m_debugLevel > 1) {
|
if (m_debugLevel > 1) {
|
||||||
std::cerr << "StretchCalculator::calculateSingle: transient"
|
std::cerr << "StretchCalculator::calculateSingle: transient (df " << df << ", threshold " << transientThreshold << ")" << std::endl;
|
||||||
<< std::endl;
|
|
||||||
}
|
}
|
||||||
m_divergence += increment - (increment * ratio);
|
m_divergence += increment - (increment * ratio);
|
||||||
|
|
||||||
@@ -626,7 +770,7 @@ StretchCalculator::distributeRegion(const std::vector<float> &dfIn,
|
|||||||
long toAllot = long(duration) - long(m_increment * df.size());
|
long toAllot = long(duration) - long(m_increment * df.size());
|
||||||
|
|
||||||
if (m_debugLevel > 1) {
|
if (m_debugLevel > 1) {
|
||||||
std::cerr << "region of " << df.size() << " chunks, output duration " << duration << ", toAllot " << toAllot << std::endl;
|
std::cerr << "region of " << df.size() << " chunks, output duration " << duration << ", increment " << m_increment << ", toAllot " << toAllot << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t totalIncrement = 0;
|
size_t totalIncrement = 0;
|
||||||
@@ -651,22 +795,24 @@ StretchCalculator::distributeRegion(const std::vector<float> &dfIn,
|
|||||||
|
|
||||||
// then we need to adjust and accommodate
|
// then we need to adjust and accommodate
|
||||||
|
|
||||||
bool acceptableSquashRange = false;
|
|
||||||
|
|
||||||
double totalDisplacement = 0;
|
double totalDisplacement = 0;
|
||||||
double maxDisplacement = 0; // min displacement will be 0 by definition
|
double maxDisplacement = 0; // min displacement will be 0 by definition
|
||||||
|
|
||||||
maxDf = 0;
|
maxDf = 0;
|
||||||
float adj = 0;
|
float adj = 0;
|
||||||
|
|
||||||
|
bool tooShort = true, tooLong = true;
|
||||||
const int acceptableIterations = 10;
|
const int acceptableIterations = 10;
|
||||||
int iteration = 0;
|
int iteration = 0;
|
||||||
|
int prevExtreme = 0;
|
||||||
while (!acceptableSquashRange && iteration < acceptableIterations) {
|
bool better = false;
|
||||||
|
|
||||||
|
while ((tooLong || tooShort) && iteration < acceptableIterations) {
|
||||||
|
|
||||||
++iteration;
|
++iteration;
|
||||||
|
|
||||||
acceptableSquashRange = true;
|
tooLong = false;
|
||||||
|
tooShort = false;
|
||||||
calculateDisplacements(df, maxDf, totalDisplacement, maxDisplacement,
|
calculateDisplacements(df, maxDf, totalDisplacement, maxDisplacement,
|
||||||
adj);
|
adj);
|
||||||
|
|
||||||
@@ -678,35 +824,61 @@ StretchCalculator::distributeRegion(const std::vector<float> &dfIn,
|
|||||||
// Not usually a problem, in fact
|
// Not usually a problem, in fact
|
||||||
// std::cerr << "WARNING: totalDisplacement == 0 (duration " << duration << ", " << df.size() << " values in df)" << std::endl;
|
// std::cerr << "WARNING: totalDisplacement == 0 (duration " << duration << ", " << df.size() << " values in df)" << std::endl;
|
||||||
if (!df.empty() && adj == 0) {
|
if (!df.empty() && adj == 0) {
|
||||||
acceptableSquashRange = false;
|
tooLong = true; tooShort = true;
|
||||||
adj = 1;
|
adj = 1;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int extremeIncrement = m_increment + lrint((toAllot * maxDisplacement) / totalDisplacement);
|
int extremeIncrement = m_increment +
|
||||||
if (ratio < 1.0) {
|
lrint((toAllot * maxDisplacement) / totalDisplacement);
|
||||||
if (extremeIncrement > lrint(ceil(m_increment * ratio))) {
|
|
||||||
std::cerr << "WARNING: extreme increment " << extremeIncrement << " > " << m_increment * ratio << std::endl;
|
|
||||||
} else if (extremeIncrement < (m_increment * ratio) / 2) {
|
|
||||||
if (m_debugLevel > 0) {
|
|
||||||
std::cerr << "NOTE: extreme increment " << extremeIncrement << " < " << (m_increment * ratio) / 2 << ", adjusting" << std::endl;
|
|
||||||
}
|
|
||||||
acceptableSquashRange = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (extremeIncrement > m_increment * ratio * 2) {
|
|
||||||
if (m_debugLevel > 0) {
|
|
||||||
std::cerr << "NOTE: extreme increment " << extremeIncrement << " > " << m_increment * ratio * 2 << ", adjusting" << std::endl;
|
|
||||||
|
|
||||||
|
if (extremeIncrement < 0) {
|
||||||
|
if (m_debugLevel > 0) {
|
||||||
|
std::cerr << "NOTE: extreme increment " << extremeIncrement << " < 0, adjusting" << std::endl;
|
||||||
|
}
|
||||||
|
tooShort = true;
|
||||||
|
} else {
|
||||||
|
if (ratio < 1.0) {
|
||||||
|
if (extremeIncrement > lrint(ceil(m_increment * ratio))) {
|
||||||
|
std::cerr << "WARNING: extreme increment "
|
||||||
|
<< extremeIncrement << " > "
|
||||||
|
<< m_increment * ratio << std::endl;
|
||||||
|
} else if (extremeIncrement < (m_increment * ratio) / 2) {
|
||||||
|
if (m_debugLevel > 0) {
|
||||||
|
std::cerr << "NOTE: extreme increment "
|
||||||
|
<< extremeIncrement << " < "
|
||||||
|
<< (m_increment * ratio) / 2
|
||||||
|
<< ", adjusting" << std::endl;
|
||||||
|
}
|
||||||
|
tooShort = true;
|
||||||
|
if (iteration > 0) {
|
||||||
|
better = (extremeIncrement > prevExtreme);
|
||||||
|
}
|
||||||
|
prevExtreme = extremeIncrement;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (extremeIncrement > m_increment * ratio * 2) {
|
||||||
|
if (m_debugLevel > 0) {
|
||||||
|
std::cerr << "NOTE: extreme increment "
|
||||||
|
<< extremeIncrement << " > "
|
||||||
|
<< m_increment * ratio * 2
|
||||||
|
<< ", adjusting" << std::endl;
|
||||||
|
}
|
||||||
|
tooLong = true;
|
||||||
|
if (iteration > 0) {
|
||||||
|
better = (extremeIncrement < prevExtreme);
|
||||||
|
}
|
||||||
|
prevExtreme = extremeIncrement;
|
||||||
|
} else if (extremeIncrement < lrint(floor(m_increment * ratio))) {
|
||||||
|
std::cerr << "WARNING: extreme increment "
|
||||||
|
<< extremeIncrement << " < "
|
||||||
|
<< m_increment * ratio << std::endl;
|
||||||
}
|
}
|
||||||
acceptableSquashRange = false;
|
|
||||||
} else if (extremeIncrement < lrint(floor(m_increment * ratio))) {
|
|
||||||
std::cerr << "WARNING: extreme increment " << extremeIncrement << " < " << m_increment * ratio << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!acceptableSquashRange) {
|
if (tooLong || tooShort) {
|
||||||
// Need to make maxDisplacement smaller as a proportion of
|
// Need to make maxDisplacement smaller as a proportion of
|
||||||
// the total displacement, yet ensure that the
|
// the total displacement, yet ensure that the
|
||||||
// displacements still sum to the total.
|
// displacements still sum to the total.
|
||||||
@@ -714,9 +886,24 @@ StretchCalculator::distributeRegion(const std::vector<float> &dfIn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!acceptableSquashRange) {
|
if (tooLong) {
|
||||||
std::cerr << "WARNING: No acceptable displacement adjustment found, using defaults:\nthis region will probably sound bad" << std::endl;
|
if (better) {
|
||||||
adj = 0;
|
// we were iterating in the right direction, so
|
||||||
|
// leave things as they are (and undo that last tweak)
|
||||||
|
std::cerr << "WARNING: No acceptable displacement adjustment found, using latest values:\nthis region could sound bad" << std::endl;
|
||||||
|
adj -= maxDf/10;
|
||||||
|
} else {
|
||||||
|
std::cerr << "WARNING: No acceptable displacement adjustment found, using defaults:\nthis region could sound bad" << std::endl;
|
||||||
|
adj = 1;
|
||||||
|
calculateDisplacements(df, maxDf, totalDisplacement, maxDisplacement,
|
||||||
|
adj);
|
||||||
|
}
|
||||||
|
} else if (tooShort) {
|
||||||
|
std::cerr << "WARNING: No acceptable displacement adjustment found, using flat distribution:\nthis region could sound bad" << std::endl;
|
||||||
|
adj = 1;
|
||||||
|
for (size_t i = 0; i < df.size(); ++i) {
|
||||||
|
df[i] = 1.f;
|
||||||
|
}
|
||||||
calculateDisplacements(df, maxDf, totalDisplacement, maxDisplacement,
|
calculateDisplacements(df, maxDf, totalDisplacement, maxDisplacement,
|
||||||
adj);
|
adj);
|
||||||
}
|
}
|
||||||
@@ -728,6 +915,9 @@ StretchCalculator::distributeRegion(const std::vector<float> &dfIn,
|
|||||||
else displacement += adj;
|
else displacement += adj;
|
||||||
|
|
||||||
if (i == 0 && phaseReset) {
|
if (i == 0 && phaseReset) {
|
||||||
|
if (m_debugLevel > 2) {
|
||||||
|
std::cerr << "Phase reset at first chunk" << std::endl;
|
||||||
|
}
|
||||||
if (df.size() == 1) {
|
if (df.size() == 1) {
|
||||||
increments.push_back(duration);
|
increments.push_back(duration);
|
||||||
totalIncrement += duration;
|
totalIncrement += duration;
|
||||||
@@ -749,19 +939,23 @@ StretchCalculator::distributeRegion(const std::vector<float> &dfIn,
|
|||||||
|
|
||||||
int increment = m_increment + allotment;
|
int increment = m_increment + allotment;
|
||||||
|
|
||||||
if (increment <= 0) {
|
if (increment < 0) {
|
||||||
// this is a serious problem, the allocation is quite
|
// this is a serious problem, the allocation is quite
|
||||||
// wrong if it allows increment to diverge so far from the
|
// wrong if it allows increment to diverge so far from the
|
||||||
// input increment
|
// input increment (though it can happen legitimately if
|
||||||
|
// asked to squash very violently)
|
||||||
std::cerr << "*** WARNING: increment " << increment << " <= 0, rounding to zero" << std::endl;
|
std::cerr << "*** WARNING: increment " << increment << " <= 0, rounding to zero" << std::endl;
|
||||||
|
|
||||||
|
toAllot += m_increment;
|
||||||
increment = 0;
|
increment = 0;
|
||||||
allotment = increment - m_increment;
|
|
||||||
|
} else {
|
||||||
|
toAllot -= allotment;
|
||||||
}
|
}
|
||||||
|
|
||||||
increments.push_back(increment);
|
increments.push_back(increment);
|
||||||
totalIncrement += increment;
|
totalIncrement += increment;
|
||||||
|
|
||||||
toAllot -= allotment;
|
|
||||||
totalDisplacement -= displacement;
|
totalDisplacement -= displacement;
|
||||||
|
|
||||||
if (m_debugLevel > 2) {
|
if (m_debugLevel > 2) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace RubberBand
|
namespace RubberBand
|
||||||
{
|
{
|
||||||
@@ -28,6 +29,15 @@ public:
|
|||||||
StretchCalculator(size_t sampleRate, size_t inputIncrement, bool useHardPeaks);
|
StretchCalculator(size_t sampleRate, size_t inputIncrement, bool useHardPeaks);
|
||||||
virtual ~StretchCalculator();
|
virtual ~StretchCalculator();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a set of mappings from "before" to "after" sample
|
||||||
|
* numbers so as to enforce a particular stretch profile. This
|
||||||
|
* must be called before calculate(). The argument is a map from
|
||||||
|
* audio sample frame number in the source material to the
|
||||||
|
* corresponding sample frame number in the stretched output.
|
||||||
|
*/
|
||||||
|
void setKeyFrameMap(const std::map<size_t, size_t> &mapping);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate phase increments for a region of audio, given the
|
* Calculate phase increments for a region of audio, given the
|
||||||
* overall target stretch ratio, input duration in audio samples,
|
* overall target stretch ratio, input duration in audio samples,
|
||||||
@@ -35,9 +45,9 @@ public:
|
|||||||
* (lockAudioCurve) and for allocating stretches to relatively
|
* (lockAudioCurve) and for allocating stretches to relatively
|
||||||
* less prominent points (stretchAudioCurve).
|
* less prominent points (stretchAudioCurve).
|
||||||
*/
|
*/
|
||||||
virtual std::vector<int> calculate(double ratio, size_t inputDuration,
|
std::vector<int> calculate(double ratio, size_t inputDuration,
|
||||||
const std::vector<float> &lockAudioCurve,
|
const std::vector<float> &lockAudioCurve,
|
||||||
const std::vector<float> &stretchAudioCurve);
|
const std::vector<float> &stretchAudioCurve);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the phase increment for a single audio block, given
|
* Calculate the phase increment for a single audio block, given
|
||||||
@@ -49,8 +59,8 @@ public:
|
|||||||
* If increment is non-zero, use it for the input increment for
|
* If increment is non-zero, use it for the input increment for
|
||||||
* this block in preference to m_increment.
|
* this block in preference to m_increment.
|
||||||
*/
|
*/
|
||||||
virtual int calculateSingle(double ratio, float curveValue,
|
int calculateSingle(double ratio, float curveValue,
|
||||||
size_t increment = 0);
|
size_t increment = 0);
|
||||||
|
|
||||||
void setUseHardPeaks(bool use) { m_useHardPeaks = use; }
|
void setUseHardPeaks(bool use) { m_useHardPeaks = use; }
|
||||||
|
|
||||||
@@ -62,13 +72,16 @@ public:
|
|||||||
size_t chunk;
|
size_t chunk;
|
||||||
bool hard;
|
bool hard;
|
||||||
};
|
};
|
||||||
std::vector<Peak> getLastCalculatedPeaks() const { return m_lastPeaks; }
|
std::vector<Peak> getLastCalculatedPeaks() const { return m_peaks; }
|
||||||
|
|
||||||
std::vector<float> smoothDF(const std::vector<float> &df);
|
std::vector<float> smoothDF(const std::vector<float> &df);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<Peak> findPeaks(const std::vector<float> &audioCurve);
|
std::vector<Peak> findPeaks(const std::vector<float> &audioCurve);
|
||||||
|
|
||||||
|
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,
|
std::vector<int> distributeRegion(const std::vector<float> ®ionCurve,
|
||||||
size_t outputDuration, float ratio,
|
size_t outputDuration, float ratio,
|
||||||
bool phaseReset);
|
bool phaseReset);
|
||||||
@@ -89,8 +102,9 @@ protected:
|
|||||||
int m_transientAmnesty; // only in RT mode; handled differently offline
|
int m_transientAmnesty; // only in RT mode; handled differently offline
|
||||||
int m_debugLevel;
|
int m_debugLevel;
|
||||||
bool m_useHardPeaks;
|
bool m_useHardPeaks;
|
||||||
|
|
||||||
std::vector<Peak> m_lastPeaks;
|
std::map<size_t, size_t> m_keyFrameMap;
|
||||||
|
std::vector<Peak> m_peaks;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -21,11 +21,11 @@
|
|||||||
|
|
||||||
//#define EXPERIMENT 1
|
//#define EXPERIMENT 1
|
||||||
|
|
||||||
namespace RubberBand { class Resampler; }
|
|
||||||
|
|
||||||
namespace RubberBand
|
namespace RubberBand
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class Resampler;
|
||||||
|
|
||||||
class RubberBandStretcher::Impl::ChannelData
|
class RubberBandStretcher::Impl::ChannelData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "dsp/SpectralDifferenceAudioCurve.h"
|
#include "dsp/SpectralDifferenceAudioCurve.h"
|
||||||
#include "dsp/SilentAudioCurve.h"
|
#include "dsp/SilentAudioCurve.h"
|
||||||
#include "dsp/ConstantAudioCurve.h"
|
#include "dsp/ConstantAudioCurve.h"
|
||||||
|
#include "dsp/CompoundAudioCurve.h"
|
||||||
#include "dsp/Resampler.h"
|
#include "dsp/Resampler.h"
|
||||||
|
|
||||||
#include "StretchCalculator.h"
|
#include "StretchCalculator.h"
|
||||||
@@ -81,9 +82,11 @@ RubberBandStretcher::Impl::Impl(size_t sampleRate,
|
|||||||
m_studyFFT(0),
|
m_studyFFT(0),
|
||||||
m_spaceAvailable("space"),
|
m_spaceAvailable("space"),
|
||||||
m_inputDuration(0),
|
m_inputDuration(0),
|
||||||
|
m_detectorType(CompoundAudioCurve::CompoundDetector),
|
||||||
m_silentHistory(0),
|
m_silentHistory(0),
|
||||||
m_lastProcessOutputIncrements(16),
|
m_lastProcessOutputIncrements(16),
|
||||||
m_lastProcessPhaseResetDf(16),
|
m_lastProcessPhaseResetDf(16),
|
||||||
|
m_emergencyScavenger(10, 4),
|
||||||
m_phaseResetAudioCurve(0),
|
m_phaseResetAudioCurve(0),
|
||||||
m_stretchAudioCurve(0),
|
m_stretchAudioCurve(0),
|
||||||
m_silentAudioCurve(0),
|
m_silentAudioCurve(0),
|
||||||
@@ -105,7 +108,7 @@ RubberBandStretcher::Impl::Impl(size_t sampleRate,
|
|||||||
// Window size will vary according to the audio sample rate, but
|
// Window size will vary according to the audio sample rate, but
|
||||||
// we don't let it drop below the 48k default
|
// we don't let it drop below the 48k default
|
||||||
m_rateMultiple = float(m_sampleRate) / 48000.f;
|
m_rateMultiple = float(m_sampleRate) / 48000.f;
|
||||||
if (m_rateMultiple < 1.f) m_rateMultiple = 1.f;
|
// if (m_rateMultiple < 1.f) m_rateMultiple = 1.f;
|
||||||
m_baseWindowSize = roundUp(int(m_defaultWindowSize * m_rateMultiple));
|
m_baseWindowSize = roundUp(int(m_defaultWindowSize * m_rateMultiple));
|
||||||
|
|
||||||
if ((options & OptionWindowShort) || (options & OptionWindowLong)) {
|
if ((options & OptionWindowShort) || (options & OptionWindowLong)) {
|
||||||
@@ -205,6 +208,12 @@ RubberBandStretcher::Impl::reset()
|
|||||||
m_threadSet.clear();
|
m_threadSet.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_emergencyScavenger.scavenge();
|
||||||
|
|
||||||
|
if (m_stretchCalculator) {
|
||||||
|
m_stretchCalculator->setKeyFrameMap(std::map<size_t, size_t>());
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t c = 0; c < m_channels; ++c) {
|
for (size_t c = 0; c < m_channels; ++c) {
|
||||||
m_channelData[c]->reset();
|
m_channelData[c]->reset();
|
||||||
}
|
}
|
||||||
@@ -299,6 +308,24 @@ RubberBandStretcher::Impl::setMaxProcessSize(size_t samples)
|
|||||||
reconfigure();
|
reconfigure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RubberBandStretcher::Impl::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;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_mode == Processing) {
|
||||||
|
cerr << "RubberBandStretcher::Impl::setKeyFrameMap: Cannot specify key frame map after process() has begun" << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_stretchCalculator) {
|
||||||
|
m_stretchCalculator->setKeyFrameMap(mapping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
RubberBandStretcher::Impl::getFrequencyCutoff(int n) const
|
RubberBandStretcher::Impl::getFrequencyCutoff(int n) const
|
||||||
{
|
{
|
||||||
@@ -399,7 +426,7 @@ RubberBandStretcher::Impl::calculateSizes()
|
|||||||
float windowIncrRatio = 4.5;
|
float windowIncrRatio = 4.5;
|
||||||
if (r == 1.0) windowIncrRatio = 4;
|
if (r == 1.0) windowIncrRatio = 4;
|
||||||
else if (rsb) windowIncrRatio = 4.5;
|
else if (rsb) windowIncrRatio = 4.5;
|
||||||
else windowIncrRatio = 6;
|
else windowIncrRatio = 8;
|
||||||
|
|
||||||
outputIncrement = int(windowSize / windowIncrRatio);
|
outputIncrement = int(windowSize / windowIncrRatio);
|
||||||
inputIncrement = int(outputIncrement / r);
|
inputIncrement = int(outputIncrement / r);
|
||||||
@@ -598,21 +625,22 @@ RubberBandStretcher::Impl::configure()
|
|||||||
// modes
|
// modes
|
||||||
|
|
||||||
delete m_phaseResetAudioCurve;
|
delete m_phaseResetAudioCurve;
|
||||||
m_phaseResetAudioCurve = new PercussiveAudioCurve
|
m_phaseResetAudioCurve = new CompoundAudioCurve
|
||||||
(m_sampleRate, m_windowSize);
|
(CompoundAudioCurve::Parameters(m_sampleRate, m_windowSize));
|
||||||
|
m_phaseResetAudioCurve->setType(m_detectorType);
|
||||||
|
|
||||||
delete m_silentAudioCurve;
|
delete m_silentAudioCurve;
|
||||||
m_silentAudioCurve = new SilentAudioCurve
|
m_silentAudioCurve = new SilentAudioCurve
|
||||||
(m_sampleRate, m_windowSize);
|
(SilentAudioCurve::Parameters(m_sampleRate, m_windowSize));
|
||||||
|
|
||||||
if (!m_realtime) {
|
if (!m_realtime) {
|
||||||
delete m_stretchAudioCurve;
|
delete m_stretchAudioCurve;
|
||||||
if (!(m_options & OptionStretchPrecise)) {
|
if (!(m_options & OptionStretchPrecise)) {
|
||||||
m_stretchAudioCurve = new SpectralDifferenceAudioCurve
|
m_stretchAudioCurve = new SpectralDifferenceAudioCurve
|
||||||
(m_sampleRate, m_windowSize);
|
(SpectralDifferenceAudioCurve::Parameters(m_sampleRate, m_windowSize));
|
||||||
} else {
|
} else {
|
||||||
m_stretchAudioCurve = new ConstantAudioCurve
|
m_stretchAudioCurve = new ConstantAudioCurve
|
||||||
(m_sampleRate, m_windowSize);
|
(ConstantAudioCurve::Parameters(m_sampleRate, m_windowSize));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -735,6 +763,30 @@ RubberBandStretcher::Impl::setTransientsOption(Options options)
|
|||||||
(!(m_options & OptionTransientsSmooth));
|
(!(m_options & OptionTransientsSmooth));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RubberBandStretcher::Impl::setDetectorOption(Options options)
|
||||||
|
{
|
||||||
|
if (!m_realtime) {
|
||||||
|
cerr << "RubberBandStretcher::Impl::setDetectorOption: Not permissible in non-realtime mode" << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int mask = (OptionDetectorPercussive | OptionDetectorCompound | 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 (dt == m_detectorType) return;
|
||||||
|
m_detectorType = dt;
|
||||||
|
|
||||||
|
if (m_phaseResetAudioCurve) {
|
||||||
|
m_phaseResetAudioCurve->setType(m_detectorType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RubberBandStretcher::Impl::setPhaseOption(Options options)
|
RubberBandStretcher::Impl::setPhaseOption(Options options)
|
||||||
{
|
{
|
||||||
@@ -955,6 +1007,17 @@ RubberBandStretcher::Impl::calculateStretch()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double prdm = 0, sdm = 0;
|
||||||
|
if (!m_phaseResetDf.empty()) {
|
||||||
|
for (int i = 0; i < m_phaseResetDf.size(); ++i) prdm += m_phaseResetDf[i];
|
||||||
|
prdm /= m_phaseResetDf.size();
|
||||||
|
}
|
||||||
|
if (!m_stretchDf.empty()) {
|
||||||
|
for (int i = 0; i < 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
|
std::vector<int> increments = m_stretchCalculator->calculate
|
||||||
(getEffectiveRatio(),
|
(getEffectiveRatio(),
|
||||||
inputDuration,
|
inputDuration,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "dsp/Window.h"
|
#include "dsp/Window.h"
|
||||||
#include "dsp/FFT.h"
|
#include "dsp/FFT.h"
|
||||||
|
#include "dsp/CompoundAudioCurve.h"
|
||||||
|
|
||||||
#include "base/RingBuffer.h"
|
#include "base/RingBuffer.h"
|
||||||
#include "system/Thread.h"
|
#include "system/Thread.h"
|
||||||
@@ -28,11 +29,10 @@
|
|||||||
|
|
||||||
using namespace RubberBand;
|
using namespace RubberBand;
|
||||||
|
|
||||||
namespace RubberBand { class AudioCurveCalculator; }
|
|
||||||
|
|
||||||
namespace RubberBand
|
namespace RubberBand
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class AudioCurveCalculator;
|
||||||
class StretchCalculator;
|
class StretchCalculator;
|
||||||
|
|
||||||
class RubberBandStretcher::Impl
|
class RubberBandStretcher::Impl
|
||||||
@@ -52,12 +52,14 @@ public:
|
|||||||
size_t getLatency() const;
|
size_t getLatency() const;
|
||||||
|
|
||||||
void setTransientsOption(Options);
|
void setTransientsOption(Options);
|
||||||
|
void setDetectorOption(Options);
|
||||||
void setPhaseOption(Options);
|
void setPhaseOption(Options);
|
||||||
void setFormantOption(Options);
|
void setFormantOption(Options);
|
||||||
void setPitchOption(Options);
|
void setPitchOption(Options);
|
||||||
|
|
||||||
void setExpectedInputDuration(size_t samples);
|
void setExpectedInputDuration(size_t samples);
|
||||||
void setMaxProcessSize(size_t samples);
|
void setMaxProcessSize(size_t samples);
|
||||||
|
void setKeyFrameMap(const std::map<size_t, size_t> &);
|
||||||
|
|
||||||
size_t getSamplesRequired() const;
|
size_t getSamplesRequired() const;
|
||||||
|
|
||||||
@@ -168,6 +170,7 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
size_t m_inputDuration;
|
size_t m_inputDuration;
|
||||||
|
CompoundAudioCurve::Type m_detectorType;
|
||||||
std::vector<float> m_phaseResetDf;
|
std::vector<float> m_phaseResetDf;
|
||||||
std::vector<float> m_stretchDf;
|
std::vector<float> m_stretchDf;
|
||||||
std::vector<bool> m_silence;
|
std::vector<bool> m_silence;
|
||||||
@@ -180,8 +183,9 @@ protected:
|
|||||||
|
|
||||||
mutable RingBuffer<int> m_lastProcessOutputIncrements;
|
mutable RingBuffer<int> m_lastProcessOutputIncrements;
|
||||||
mutable RingBuffer<float> m_lastProcessPhaseResetDf;
|
mutable RingBuffer<float> m_lastProcessPhaseResetDf;
|
||||||
|
Scavenger<RingBuffer<float> > m_emergencyScavenger;
|
||||||
|
|
||||||
AudioCurveCalculator *m_phaseResetAudioCurve;
|
CompoundAudioCurve *m_phaseResetAudioCurve;
|
||||||
AudioCurveCalculator *m_stretchAudioCurve;
|
AudioCurveCalculator *m_stretchAudioCurve;
|
||||||
AudioCurveCalculator *m_silentAudioCurve;
|
AudioCurveCalculator *m_silentAudioCurve;
|
||||||
StretchCalculator *m_stretchCalculator;
|
StretchCalculator *m_stretchCalculator;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -198,6 +198,8 @@ RubberBandStretcher::Impl::processChunks(size_t c, bool &any, bool &last)
|
|||||||
// buffer for channel c. This requires that the increments have
|
// buffer for channel c. This requires that the increments have
|
||||||
// already been calculated.
|
// already been calculated.
|
||||||
|
|
||||||
|
// This is the normal process method in offline mode.
|
||||||
|
|
||||||
ChannelData &cd = *m_channelData[c];
|
ChannelData &cd = *m_channelData[c];
|
||||||
|
|
||||||
last = false;
|
last = false;
|
||||||
@@ -216,14 +218,36 @@ RubberBandStretcher::Impl::processChunks(size_t c, bool &any, bool &last)
|
|||||||
size_t got = cd.inbuf->peek(cd.fltbuf, m_windowSize);
|
size_t got = cd.inbuf->peek(cd.fltbuf, m_windowSize);
|
||||||
assert(got == m_windowSize || cd.inputSize >= 0);
|
assert(got == m_windowSize || cd.inputSize >= 0);
|
||||||
cd.inbuf->skip(m_increment);
|
cd.inbuf->skip(m_increment);
|
||||||
analyseChunk(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool phaseReset = false;
|
bool phaseReset = false;
|
||||||
size_t phaseIncrement, shiftIncrement;
|
size_t phaseIncrement, shiftIncrement;
|
||||||
getIncrements(c, phaseIncrement, shiftIncrement, phaseReset);
|
getIncrements(c, phaseIncrement, shiftIncrement, phaseReset);
|
||||||
|
|
||||||
last = processChunkForChannel(c, phaseIncrement, shiftIncrement, phaseReset);
|
if (shiftIncrement <= m_windowSize) {
|
||||||
|
analyseChunk(c);
|
||||||
|
last = processChunkForChannel
|
||||||
|
(c, phaseIncrement, shiftIncrement, phaseReset);
|
||||||
|
} else {
|
||||||
|
size_t bit = m_windowSize/4;
|
||||||
|
if (m_debugLevel > 1) {
|
||||||
|
cerr << "channel " << c << " breaking down overlong increment " << shiftIncrement << " into " << bit << "-size bits" << endl;
|
||||||
|
}
|
||||||
|
analyseChunk(c);
|
||||||
|
float *tmp = (float *)alloca(m_windowSize * sizeof(float));
|
||||||
|
v_copy(tmp, cd.fltbuf, m_windowSize);
|
||||||
|
for (size_t i = 0; i < shiftIncrement; i += bit) {
|
||||||
|
v_copy(cd.fltbuf, tmp, m_windowSize);
|
||||||
|
size_t thisIncrement = bit;
|
||||||
|
if (i + thisIncrement > shiftIncrement) {
|
||||||
|
thisIncrement = shiftIncrement - i;
|
||||||
|
}
|
||||||
|
last = processChunkForChannel
|
||||||
|
(c, phaseIncrement + i, thisIncrement, phaseReset);
|
||||||
|
phaseReset = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cd.chunkCount++;
|
cd.chunkCount++;
|
||||||
if (m_debugLevel > 2) {
|
if (m_debugLevel > 2) {
|
||||||
cerr << "channel " << c << ": last = " << last << ", chunkCount = " << cd.chunkCount << endl;
|
cerr << "channel " << c << ": last = " << last << ", chunkCount = " << cd.chunkCount << endl;
|
||||||
@@ -240,6 +264,8 @@ RubberBandStretcher::Impl::processOneChunk()
|
|||||||
// enough data on each channel for at least one chunk. This is
|
// enough data on each channel for at least one chunk. This is
|
||||||
// able to calculate increments as it goes along.
|
// able to calculate increments as it goes along.
|
||||||
|
|
||||||
|
// This is the normal process method in RT mode.
|
||||||
|
|
||||||
for (size_t c = 0; c < m_channels; ++c) {
|
for (size_t c = 0; c < m_channels; ++c) {
|
||||||
if (!testInbufReadSpace(c)) return false;
|
if (!testInbufReadSpace(c)) return false;
|
||||||
ChannelData &cd = *m_channelData[c];
|
ChannelData &cd = *m_channelData[c];
|
||||||
@@ -383,29 +409,31 @@ RubberBandStretcher::Impl::processChunkForChannel(size_t c,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_threaded) {
|
int required = shiftIncrement;
|
||||||
|
|
||||||
int required = shiftIncrement;
|
if (m_pitchScale != 1.0) {
|
||||||
|
required = int(required / m_pitchScale) + 1;
|
||||||
if (m_pitchScale != 1.0) {
|
|
||||||
required = int(required / m_pitchScale) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cd.outbuf->getWriteSpace() < required) {
|
|
||||||
if (m_debugLevel > 0) {
|
|
||||||
cerr << "Buffer overrun on output for channel " << c << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
//!!! 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 from the buffer so as to make more space,
|
|
||||||
// because the client thread is probably stuck in a
|
|
||||||
// process() call waiting for us to stow away enough input
|
|
||||||
// increments to allow the process() call to complete.
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ws = cd.outbuf->getWriteSpace();
|
||||||
|
if (ws < required) {
|
||||||
|
if (m_debugLevel > 0) {
|
||||||
|
cerr << "Buffer overrun on output for channel " << c << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// from the buffer so as to make more space, because the
|
||||||
|
// client thread (if we are threaded at all) is probably stuck
|
||||||
|
// in a process() call waiting for us to stow away enough
|
||||||
|
// input increments to allow the process() call to complete.
|
||||||
|
// This is an unhappy situation.
|
||||||
|
|
||||||
|
RingBuffer<float> *oldbuf = cd.outbuf;
|
||||||
|
cd.outbuf = oldbuf->resized(oldbuf->getSize() + (required - ws));
|
||||||
|
m_emergencyScavenger.claim(oldbuf);
|
||||||
|
}
|
||||||
|
|
||||||
writeChunk(c, shiftIncrement, last);
|
writeChunk(c, shiftIncrement, last);
|
||||||
return last;
|
return last;
|
||||||
}
|
}
|
||||||
@@ -589,12 +617,12 @@ RubberBandStretcher::Impl::getIncrements(size_t channel,
|
|||||||
if (shiftIncrement < 0) {
|
if (shiftIncrement < 0) {
|
||||||
shiftIncrement = -shiftIncrement;
|
shiftIncrement = -shiftIncrement;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if (shiftIncrement >= int(m_windowSize)) {
|
if (shiftIncrement >= int(m_windowSize)) {
|
||||||
cerr << "*** ERROR: RubberBandStretcher::Impl::processChunks: shiftIncrement " << shiftIncrement << " >= windowSize " << m_windowSize << " at " << cd.chunkCount << " (of " << m_outputIncrements.size() << ")" << endl;
|
cerr << "*** ERROR: RubberBandStretcher::Impl::processChunks: shiftIncrement " << shiftIncrement << " >= windowSize " << m_windowSize << " at " << cd.chunkCount << " (of " << m_outputIncrements.size() << ")" << endl;
|
||||||
shiftIncrement = m_windowSize;
|
shiftIncrement = m_windowSize;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
phaseIncrementRtn = phaseIncrement;
|
phaseIncrementRtn = phaseIncrement;
|
||||||
shiftIncrementRtn = shiftIncrement;
|
shiftIncrementRtn = shiftIncrement;
|
||||||
if (cd.chunkCount == 0) phaseReset = true; // don't mess with the first chunk
|
if (cd.chunkCount == 0) phaseReset = true; // don't mess with the first chunk
|
||||||
@@ -781,7 +809,7 @@ RubberBandStretcher::Impl::modifyChunk(size_t channel,
|
|||||||
cd.unwrappedPhase[i] = outphase;
|
cd.unwrappedPhase[i] = outphase;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_debugLevel > 1) {
|
if (m_debugLevel > 2) {
|
||||||
cerr << "mean inheritance distance = " << distacc / count << endl;
|
cerr << "mean inheritance distance = " << distacc / count << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -14,18 +14,50 @@
|
|||||||
|
|
||||||
#include "AudioCurveCalculator.h"
|
#include "AudioCurveCalculator.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace RubberBand
|
namespace RubberBand
|
||||||
{
|
{
|
||||||
|
|
||||||
AudioCurveCalculator::AudioCurveCalculator(size_t sampleRate, size_t windowSize) :
|
static const int MaxPerceivedFreq = 16000;
|
||||||
m_sampleRate(sampleRate),
|
|
||||||
m_windowSize(windowSize)
|
AudioCurveCalculator::AudioCurveCalculator(Parameters parameters) :
|
||||||
|
m_sampleRate(parameters.sampleRate),
|
||||||
|
m_windowSize(parameters.windowSize)
|
||||||
{
|
{
|
||||||
|
recalculateLastPerceivedBin();
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioCurveCalculator::~AudioCurveCalculator()
|
AudioCurveCalculator::~AudioCurveCalculator()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioCurveCalculator::setSampleRate(int newRate)
|
||||||
|
{
|
||||||
|
m_sampleRate = newRate;
|
||||||
|
recalculateLastPerceivedBin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioCurveCalculator::setWindowSize(int newSize)
|
||||||
|
{
|
||||||
|
m_windowSize = newSize;
|
||||||
|
recalculateLastPerceivedBin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioCurveCalculator::recalculateLastPerceivedBin()
|
||||||
|
{
|
||||||
|
if (m_sampleRate == 0) {
|
||||||
|
m_lastPerceivedBin = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_lastPerceivedBin = ((MaxPerceivedFreq * m_windowSize) / m_sampleRate);
|
||||||
|
if (m_lastPerceivedBin > m_windowSize/2) {
|
||||||
|
m_lastPerceivedBin = m_windowSize/2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -26,28 +26,51 @@ namespace RubberBand
|
|||||||
class AudioCurveCalculator
|
class AudioCurveCalculator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AudioCurveCalculator(size_t sampleRate, size_t windowSize);
|
struct Parameters {
|
||||||
|
Parameters(int _sampleRate, int _windowSize) :
|
||||||
|
sampleRate(_sampleRate),
|
||||||
|
windowSize(_windowSize)
|
||||||
|
{ }
|
||||||
|
int sampleRate;
|
||||||
|
int windowSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
AudioCurveCalculator(Parameters parameters);
|
||||||
virtual ~AudioCurveCalculator();
|
virtual ~AudioCurveCalculator();
|
||||||
|
|
||||||
size_t getSampleRate() const { return m_sampleRate; }
|
int getSampleRate() const { return m_sampleRate; }
|
||||||
size_t getWindowSize() const { return m_windowSize; }
|
int getWindowSize() const { return m_windowSize; }
|
||||||
|
|
||||||
virtual void setWindowSize(size_t newSize) = 0;
|
virtual void setSampleRate(int newRate);
|
||||||
|
virtual void setWindowSize(int newSize);
|
||||||
|
|
||||||
|
Parameters getParameters() const {
|
||||||
|
return Parameters(m_sampleRate, m_windowSize);
|
||||||
|
}
|
||||||
|
void setParameters(Parameters p) {
|
||||||
|
setSampleRate(p.sampleRate);
|
||||||
|
setWindowSize(p.windowSize);
|
||||||
|
}
|
||||||
|
|
||||||
// You may not mix calls to the various process functions on a
|
// You may not mix calls to the various process functions on a
|
||||||
// given instance
|
// given instance
|
||||||
|
|
||||||
|
|
||||||
virtual float processFloat(const float *R__ mag, size_t increment) = 0;
|
virtual float processFloat(const float *R__ mag, int increment) = 0;
|
||||||
virtual double processDouble(const double *R__ mag, size_t increment) = 0;
|
virtual double processDouble(const double *R__ mag, int increment) = 0;
|
||||||
|
|
||||||
virtual void reset() = 0;
|
virtual void reset() = 0;
|
||||||
|
|
||||||
|
virtual const char *getUnit() const { return ""; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t m_sampleRate;
|
int m_sampleRate;
|
||||||
size_t m_windowSize;
|
int m_windowSize;
|
||||||
|
int m_lastPerceivedBin;
|
||||||
|
void recalculateLastPerceivedBin();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
164
src/dsp/CompoundAudioCurve.cpp
Normal file
164
src/dsp/CompoundAudioCurve.cpp
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Rubber Band
|
||||||
|
An audio time-stretching and pitch-shifting library.
|
||||||
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CompoundAudioCurve.h"
|
||||||
|
|
||||||
|
#include "MovingMedian.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace RubberBand
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
CompoundAudioCurve::CompoundAudioCurve(Parameters parameters) :
|
||||||
|
AudioCurveCalculator(parameters),
|
||||||
|
m_percussive(parameters),
|
||||||
|
m_hf(parameters),
|
||||||
|
m_hfFilter(new MovingMedian<double>(19, 85)),
|
||||||
|
m_hfDerivFilter(new MovingMedian<double>(19, 90)),
|
||||||
|
m_lastHf(0.0),
|
||||||
|
m_lastResult(0.0),
|
||||||
|
m_risingCount(0)
|
||||||
|
{
|
||||||
|
std::cerr << "CompoundAudioCurve::CompoundAudioCurve: window "
|
||||||
|
<< parameters.windowSize << ", rate " << parameters.sampleRate
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompoundAudioCurve::~CompoundAudioCurve()
|
||||||
|
{
|
||||||
|
delete m_hfFilter;
|
||||||
|
delete m_hfDerivFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CompoundAudioCurve::setType(Type type)
|
||||||
|
{
|
||||||
|
std::cerr << "CompoundAudioCurve::setType to " << type << std::endl;
|
||||||
|
m_type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CompoundAudioCurve::reset()
|
||||||
|
{
|
||||||
|
m_percussive.reset();
|
||||||
|
m_hf.reset();
|
||||||
|
m_hfFilter->reset();
|
||||||
|
m_hfDerivFilter->reset();
|
||||||
|
m_lastHf = 0.0;
|
||||||
|
m_lastResult = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CompoundAudioCurve::setWindowSize(int newSize)
|
||||||
|
{
|
||||||
|
m_percussive.setWindowSize(newSize);
|
||||||
|
m_hf.setWindowSize(newSize);
|
||||||
|
m_windowSize = newSize;
|
||||||
|
m_lastHf = 0.0;
|
||||||
|
m_lastResult = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
CompoundAudioCurve::processFloat(const float *R__ mag, int increment)
|
||||||
|
{
|
||||||
|
float percussive = 0.f;
|
||||||
|
float hf = 0.f;
|
||||||
|
switch (m_type) {
|
||||||
|
case PercussiveDetector:
|
||||||
|
percussive = m_percussive.processFloat(mag, increment);
|
||||||
|
break;
|
||||||
|
case CompoundDetector:
|
||||||
|
percussive = m_percussive.processFloat(mag, increment);
|
||||||
|
hf = m_hf.processFloat(mag, increment);
|
||||||
|
break;
|
||||||
|
case SoftDetector:
|
||||||
|
hf = m_hf.processFloat(mag, increment);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return processFiltering(percussive, hf);
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
CompoundAudioCurve::processDouble(const double *R__ mag, int increment)
|
||||||
|
{
|
||||||
|
double percussive = 0.0;
|
||||||
|
double hf = 0.0;
|
||||||
|
switch (m_type) {
|
||||||
|
case PercussiveDetector:
|
||||||
|
percussive = m_percussive.processDouble(mag, increment);
|
||||||
|
break;
|
||||||
|
case CompoundDetector:
|
||||||
|
percussive = m_percussive.processDouble(mag, increment);
|
||||||
|
hf = m_hf.processDouble(mag, increment);
|
||||||
|
break;
|
||||||
|
case SoftDetector:
|
||||||
|
hf = m_hf.processDouble(mag, increment);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return processFiltering(percussive, hf);
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
CompoundAudioCurve::processFiltering(double percussive, double hf)
|
||||||
|
{
|
||||||
|
if (m_type == PercussiveDetector) {
|
||||||
|
if (percussive > 0.35) {
|
||||||
|
return 1.0;
|
||||||
|
} else {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double rv = 0.f;
|
||||||
|
|
||||||
|
double hfDeriv = hf - m_lastHf;
|
||||||
|
|
||||||
|
m_hfFilter->push(hf);
|
||||||
|
m_hfDerivFilter->push(hfDeriv);
|
||||||
|
|
||||||
|
double hfFiltered = m_hfFilter->get();
|
||||||
|
double hfDerivFiltered = m_hfDerivFilter->get();
|
||||||
|
|
||||||
|
m_lastHf = hf;
|
||||||
|
|
||||||
|
double result = 0.f;
|
||||||
|
|
||||||
|
double hfExcess = hf - hfFiltered;
|
||||||
|
|
||||||
|
if (hfExcess > 0.0) {
|
||||||
|
result = hfDeriv - hfDerivFiltered;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_type != SoftDetector && percussive > 0.35 && hfExcess > 0.0) {
|
||||||
|
rv = 1.0;
|
||||||
|
m_risingCount = 0;
|
||||||
|
} else {
|
||||||
|
if (result < m_lastResult) {
|
||||||
|
if (m_risingCount > 3 && m_lastResult > 0) rv = 0.5;
|
||||||
|
m_risingCount = 0;
|
||||||
|
} else {
|
||||||
|
m_risingCount ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lastResult = result;
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
65
src/dsp/CompoundAudioCurve.h
Normal file
65
src/dsp/CompoundAudioCurve.h
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Rubber Band
|
||||||
|
An audio time-stretching and pitch-shifting library.
|
||||||
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _COMPOUND_AUDIO_CURVE_H_
|
||||||
|
#define _COMPOUND_AUDIO_CURVE_H_
|
||||||
|
|
||||||
|
#include "AudioCurveCalculator.h"
|
||||||
|
#include "PercussiveAudioCurve.h"
|
||||||
|
#include "HighFrequencyAudioCurve.h"
|
||||||
|
#include "SampleFilter.h"
|
||||||
|
|
||||||
|
namespace RubberBand
|
||||||
|
{
|
||||||
|
|
||||||
|
class CompoundAudioCurve : public AudioCurveCalculator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CompoundAudioCurve(Parameters parameters);
|
||||||
|
|
||||||
|
virtual ~CompoundAudioCurve();
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
PercussiveDetector,
|
||||||
|
CompoundDetector,
|
||||||
|
SoftDetector
|
||||||
|
};
|
||||||
|
virtual void setType(Type);
|
||||||
|
|
||||||
|
virtual void setWindowSize(int newSize);
|
||||||
|
|
||||||
|
virtual float processFloat(const float *R__ mag, int increment);
|
||||||
|
virtual double processDouble(const double *R__ mag, int increment);
|
||||||
|
|
||||||
|
virtual void reset();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
PercussiveAudioCurve m_percussive;
|
||||||
|
HighFrequencyAudioCurve m_hf;
|
||||||
|
|
||||||
|
SampleFilter<double> *m_hfFilter;
|
||||||
|
SampleFilter<double> *m_hfDerivFilter;
|
||||||
|
|
||||||
|
Type m_type;
|
||||||
|
|
||||||
|
double m_lastHf;
|
||||||
|
double m_lastResult;
|
||||||
|
int m_risingCount;
|
||||||
|
|
||||||
|
double processFiltering(double percussive, double hf);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -17,8 +17,9 @@
|
|||||||
namespace RubberBand
|
namespace RubberBand
|
||||||
{
|
{
|
||||||
|
|
||||||
ConstantAudioCurve::ConstantAudioCurve(size_t sampleRate, size_t windowSize) :
|
|
||||||
AudioCurveCalculator(sampleRate, windowSize)
|
ConstantAudioCurve::ConstantAudioCurve(Parameters parameters) :
|
||||||
|
AudioCurveCalculator(parameters)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,20 +32,14 @@ ConstantAudioCurve::reset()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
ConstantAudioCurve::setWindowSize(size_t newSize)
|
|
||||||
{
|
|
||||||
m_windowSize = newSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
float
|
float
|
||||||
ConstantAudioCurve::processFloat(const float *R__, size_t)
|
ConstantAudioCurve::processFloat(const float *R__, int)
|
||||||
{
|
{
|
||||||
return 1.f;
|
return 1.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
ConstantAudioCurve::processDouble(const double *R__, size_t)
|
ConstantAudioCurve::processDouble(const double *R__, int)
|
||||||
{
|
{
|
||||||
return 1.0;
|
return 1.0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -23,13 +23,11 @@ namespace RubberBand
|
|||||||
class ConstantAudioCurve : public AudioCurveCalculator
|
class ConstantAudioCurve : public AudioCurveCalculator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConstantAudioCurve(size_t sampleRate, size_t windowSize);
|
ConstantAudioCurve(Parameters parameters);
|
||||||
virtual ~ConstantAudioCurve();
|
virtual ~ConstantAudioCurve();
|
||||||
|
|
||||||
virtual void setWindowSize(size_t newSize);
|
virtual float processFloat(const float *R__ mag, int increment);
|
||||||
|
virtual double processDouble(const double *R__ mag, int increment);
|
||||||
virtual float processFloat(const float *R__ mag, size_t increment);
|
|
||||||
virtual double processDouble(const double *R__ mag, size_t increment);
|
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -17,8 +17,9 @@
|
|||||||
namespace RubberBand
|
namespace RubberBand
|
||||||
{
|
{
|
||||||
|
|
||||||
HighFrequencyAudioCurve::HighFrequencyAudioCurve(size_t sampleRate, size_t windowSize) :
|
|
||||||
AudioCurveCalculator(sampleRate, windowSize)
|
HighFrequencyAudioCurve::HighFrequencyAudioCurve(Parameters parameters) :
|
||||||
|
AudioCurveCalculator(parameters)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,18 +32,12 @@ HighFrequencyAudioCurve::reset()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
HighFrequencyAudioCurve::setWindowSize(size_t newSize)
|
|
||||||
{
|
|
||||||
m_windowSize = newSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
float
|
float
|
||||||
HighFrequencyAudioCurve::processFloat(const float *R__ mag, size_t increment)
|
HighFrequencyAudioCurve::processFloat(const float *R__ mag, int increment)
|
||||||
{
|
{
|
||||||
float result = 0.0;
|
float result = 0.0;
|
||||||
|
|
||||||
const int sz = m_windowSize / 2;
|
const int sz = m_lastPerceivedBin;
|
||||||
|
|
||||||
for (int n = 0; n <= sz; ++n) {
|
for (int n = 0; n <= sz; ++n) {
|
||||||
result = result + mag[n] * n;
|
result = result + mag[n] * n;
|
||||||
@@ -52,11 +47,11 @@ HighFrequencyAudioCurve::processFloat(const float *R__ mag, size_t increment)
|
|||||||
}
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
HighFrequencyAudioCurve::processDouble(const double *R__ mag, size_t increment)
|
HighFrequencyAudioCurve::processDouble(const double *R__ mag, int increment)
|
||||||
{
|
{
|
||||||
float result = 0.0;
|
float result = 0.0;
|
||||||
|
|
||||||
const int sz = m_windowSize / 2;
|
const int sz = m_lastPerceivedBin;
|
||||||
|
|
||||||
for (int n = 0; n <= sz; ++n) {
|
for (int n = 0; n <= sz; ++n) {
|
||||||
result = result + mag[n] * n;
|
result = result + mag[n] * n;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -23,15 +23,14 @@ namespace RubberBand
|
|||||||
class HighFrequencyAudioCurve : public AudioCurveCalculator
|
class HighFrequencyAudioCurve : public AudioCurveCalculator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HighFrequencyAudioCurve(size_t sampleRate, size_t windowSize);
|
HighFrequencyAudioCurve(Parameters parameters);
|
||||||
|
|
||||||
virtual ~HighFrequencyAudioCurve();
|
virtual ~HighFrequencyAudioCurve();
|
||||||
|
|
||||||
virtual void setWindowSize(size_t newSize);
|
virtual float processFloat(const float *R__ mag, int increment);
|
||||||
|
virtual double processDouble(const double *R__ mag, int increment);
|
||||||
virtual float processFloat(const float *R__ mag, size_t increment);
|
|
||||||
virtual double processDouble(const double *R__ mag, size_t increment);
|
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
virtual const char *getUnit() const { return "Vbin"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
95
src/dsp/MovingMedian.h
Normal file
95
src/dsp/MovingMedian.h
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Rubber Band
|
||||||
|
An audio time-stretching and pitch-shifting library.
|
||||||
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _MOVING_MEDIAN_H_
|
||||||
|
#define _MOVING_MEDIAN_H_
|
||||||
|
|
||||||
|
#include "SampleFilter.h"
|
||||||
|
|
||||||
|
#include "system/Allocators.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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
|
||||||
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -18,12 +18,13 @@
|
|||||||
#include "system/VectorOps.h"
|
#include "system/VectorOps.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <iostream>
|
||||||
namespace RubberBand
|
namespace RubberBand
|
||||||
{
|
{
|
||||||
|
|
||||||
PercussiveAudioCurve::PercussiveAudioCurve(size_t sampleRate, size_t windowSize) :
|
|
||||||
AudioCurveCalculator(sampleRate, windowSize)
|
PercussiveAudioCurve::PercussiveAudioCurve(Parameters parameters) :
|
||||||
|
AudioCurveCalculator(parameters)
|
||||||
{
|
{
|
||||||
m_prevMag = allocate_and_zero<double>(m_windowSize/2 + 1);
|
m_prevMag = allocate_and_zero<double>(m_windowSize/2 + 1);
|
||||||
}
|
}
|
||||||
@@ -40,26 +41,29 @@ PercussiveAudioCurve::reset()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PercussiveAudioCurve::setWindowSize(size_t newSize)
|
PercussiveAudioCurve::setWindowSize(int newSize)
|
||||||
{
|
{
|
||||||
m_prevMag = reallocate(m_prevMag, m_windowSize, newSize);
|
m_prevMag = reallocate(m_prevMag, m_windowSize, newSize);
|
||||||
m_windowSize = newSize;
|
AudioCurveCalculator::setWindowSize(newSize);
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
PercussiveAudioCurve::processFloat(const float *R__ mag, size_t increment)
|
PercussiveAudioCurve::processFloat(const float *R__ mag, int increment)
|
||||||
{
|
{
|
||||||
static float threshold = powf(10.f, 0.15f); // 3dB rise in square of magnitude
|
static float threshold = powf(10.f, 0.15f); // 3dB rise in square of magnitude
|
||||||
static float zeroThresh = powf(10.f, -8);
|
static float zeroThresh = powf(10.f, -8);
|
||||||
|
|
||||||
size_t count = 0;
|
int count = 0;
|
||||||
size_t nonZeroCount = 0;
|
int nonZeroCount = 0;
|
||||||
|
|
||||||
const int sz = m_windowSize / 2;
|
const int sz = m_lastPerceivedBin;
|
||||||
|
|
||||||
for (int n = 1; n <= sz; ++n) {
|
for (int n = 1; n <= sz; ++n) {
|
||||||
bool above = ((mag[n] / m_prevMag[n]) >= threshold);
|
float v = 0.f;
|
||||||
|
if (m_prevMag[n] > zeroThresh) v = mag[n] / m_prevMag[n];
|
||||||
|
else if (mag[n] > zeroThresh) v = threshold;
|
||||||
|
bool above = (v >= threshold);
|
||||||
if (above) ++count;
|
if (above) ++count;
|
||||||
if (mag[n] > zeroThresh) ++nonZeroCount;
|
if (mag[n] > zeroThresh) ++nonZeroCount;
|
||||||
}
|
}
|
||||||
@@ -71,18 +75,21 @@ PercussiveAudioCurve::processFloat(const float *R__ mag, size_t increment)
|
|||||||
}
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
PercussiveAudioCurve::processDouble(const double *R__ mag, size_t increment)
|
PercussiveAudioCurve::processDouble(const double *R__ mag, int increment)
|
||||||
{
|
{
|
||||||
static double threshold = powf(10., 0.15); // 3dB rise in square of magnitude
|
static double threshold = powf(10., 0.15); // 3dB rise in square of magnitude
|
||||||
static double zeroThresh = powf(10., -8);
|
static double zeroThresh = powf(10., -8);
|
||||||
|
|
||||||
size_t count = 0;
|
int count = 0;
|
||||||
size_t nonZeroCount = 0;
|
int nonZeroCount = 0;
|
||||||
|
|
||||||
const int sz = m_windowSize / 2;
|
const int sz = m_lastPerceivedBin;
|
||||||
|
|
||||||
for (int n = 1; n <= sz; ++n) {
|
for (int n = 1; n <= sz; ++n) {
|
||||||
bool above = ((mag[n] / m_prevMag[n]) >= threshold);
|
double v = 0.0;
|
||||||
|
if (m_prevMag[n] > zeroThresh) v = mag[n] / m_prevMag[n];
|
||||||
|
else if (mag[n] > zeroThresh) v = threshold;
|
||||||
|
bool above = (v >= threshold);
|
||||||
if (above) ++count;
|
if (above) ++count;
|
||||||
if (mag[n] > zeroThresh) ++nonZeroCount;
|
if (mag[n] > zeroThresh) ++nonZeroCount;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -23,17 +23,18 @@ namespace RubberBand
|
|||||||
class PercussiveAudioCurve : public AudioCurveCalculator
|
class PercussiveAudioCurve : public AudioCurveCalculator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PercussiveAudioCurve(size_t sampleRate, size_t windowSize);
|
PercussiveAudioCurve(Parameters parameters);
|
||||||
|
|
||||||
virtual ~PercussiveAudioCurve();
|
virtual ~PercussiveAudioCurve();
|
||||||
|
|
||||||
virtual void setWindowSize(size_t newSize);
|
virtual void setWindowSize(int newSize);
|
||||||
|
|
||||||
virtual float processFloat(const float *R__ mag, size_t increment);
|
virtual float processFloat(const float *R__ mag, int increment);
|
||||||
virtual double processDouble(const double *R__ mag, size_t increment);
|
virtual double processDouble(const double *R__ mag, int increment);
|
||||||
|
|
||||||
|
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
virtual const char *getUnit() const { return "bin/total"; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
double *R__ m_prevMag;
|
double *R__ m_prevMag;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -39,6 +39,12 @@ public:
|
|||||||
int incount,
|
int incount,
|
||||||
float ratio,
|
float ratio,
|
||||||
bool final) = 0;
|
bool final) = 0;
|
||||||
|
|
||||||
|
virtual int resampleInterleaved(const float *const R__ in,
|
||||||
|
float *const R__ out,
|
||||||
|
int incount,
|
||||||
|
float ratio,
|
||||||
|
bool final) = 0;
|
||||||
|
|
||||||
virtual int getChannelCount() const = 0;
|
virtual int getChannelCount() const = 0;
|
||||||
|
|
||||||
@@ -62,6 +68,12 @@ public:
|
|||||||
float ratio,
|
float ratio,
|
||||||
bool final);
|
bool final);
|
||||||
|
|
||||||
|
int resampleInterleaved(const float *const R__ in,
|
||||||
|
float *const R__ out,
|
||||||
|
int incount,
|
||||||
|
float ratio,
|
||||||
|
bool final = false);
|
||||||
|
|
||||||
int getChannelCount() const { return m_channels; }
|
int getChannelCount() const { return m_channels; }
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
@@ -145,11 +157,7 @@ D_SRC::resample(const float *const R__ *const R__ in,
|
|||||||
m_iout = reallocate<float>(m_iout, m_ioutsize, outcount * m_channels);
|
m_iout = reallocate<float>(m_iout, m_ioutsize, outcount * m_channels);
|
||||||
m_ioutsize = outcount * m_channels;
|
m_ioutsize = outcount * m_channels;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < incount; ++i) {
|
v_interleave(m_iin, in, m_channels, incount);
|
||||||
for (int c = 0; c < m_channels; ++c) {
|
|
||||||
m_iin[i * m_channels + c] = in[c][i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data.data_in = m_iin;
|
data.data_in = m_iin;
|
||||||
data.data_out = m_iout;
|
data.data_out = m_iout;
|
||||||
}
|
}
|
||||||
@@ -168,11 +176,39 @@ D_SRC::resample(const float *const R__ *const R__ in,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_channels > 1) {
|
if (m_channels > 1) {
|
||||||
for (int i = 0; i < data.output_frames_gen; ++i) {
|
v_deinterleave(out, m_iout, m_channels, data.output_frames_gen);
|
||||||
for (int c = 0; c < m_channels; ++c) {
|
}
|
||||||
out[c][i] = m_iout[i * m_channels + c];
|
|
||||||
}
|
m_lastRatio = ratio;
|
||||||
}
|
|
||||||
|
return data.output_frames_gen;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
D_SRC::resampleInterleaved(const float *const R__ in,
|
||||||
|
float *const R__ out,
|
||||||
|
int incount,
|
||||||
|
float ratio,
|
||||||
|
bool final)
|
||||||
|
{
|
||||||
|
SRC_DATA data;
|
||||||
|
|
||||||
|
int outcount = lrintf(ceilf(incount * ratio));
|
||||||
|
|
||||||
|
data.data_in = const_cast<float *>(in);
|
||||||
|
data.data_out = out;
|
||||||
|
|
||||||
|
data.input_frames = incount;
|
||||||
|
data.output_frames = outcount;
|
||||||
|
data.src_ratio = ratio;
|
||||||
|
data.end_of_input = (final ? 1 : 0);
|
||||||
|
|
||||||
|
int err = src_process(m_src, &data);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
std::cerr << "Resampler::process: libsamplerate error: "
|
||||||
|
<< src_strerror(err) << std::endl;
|
||||||
|
throw Resampler::ImplementationError; //!!! of course, need to catch this!
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lastRatio = ratio;
|
m_lastRatio = ratio;
|
||||||
@@ -252,6 +288,15 @@ Resampler::resample(const float *const R__ *const R__ in,
|
|||||||
return d->resample(in, out, incount, ratio, final);
|
return d->resample(in, out, incount, ratio, final);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
Resampler::resampleInterleaved(const float *const R__ in,
|
||||||
|
float *const R__ out,
|
||||||
|
int incount, float ratio, bool final)
|
||||||
|
{
|
||||||
|
Profiler profiler("Resampler::resample");
|
||||||
|
return d->resampleInterleaved(in, out, incount, ratio, final);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
Resampler::getChannelCount() const
|
Resampler::getChannelCount() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -37,12 +37,29 @@ public:
|
|||||||
int debugLevel = 0);
|
int debugLevel = 0);
|
||||||
~Resampler();
|
~Resampler();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resample the given multi-channel buffers, where incount is the
|
||||||
|
* number of frames in the input buffers. Returns the number of
|
||||||
|
* frames written to the output buffers.
|
||||||
|
*/
|
||||||
int resample(const float *const R__ *const R__ in,
|
int resample(const float *const R__ *const R__ in,
|
||||||
float *const R__ *const R__ out,
|
float *const R__ *const R__ out,
|
||||||
int incount,
|
int incount,
|
||||||
float ratio,
|
float ratio,
|
||||||
bool final = false);
|
bool final = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resample the given interleaved buffer, where incount is the
|
||||||
|
* number of frames in the input buffer (i.e. it has incount *
|
||||||
|
* getChannelCount() samples). Returns the number of frames
|
||||||
|
* written to the output buffer.
|
||||||
|
*/
|
||||||
|
int resampleInterleaved(const float *const R__ in,
|
||||||
|
float *const R__ out,
|
||||||
|
int incount,
|
||||||
|
float ratio,
|
||||||
|
bool final = false);
|
||||||
|
|
||||||
int getChannelCount() const;
|
int getChannelCount() const;
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|||||||
50
src/dsp/SampleFilter.h
Normal file
50
src/dsp/SampleFilter.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Rubber Band
|
||||||
|
An audio time-stretching and pitch-shifting library.
|
||||||
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SAMPLE_FILTER_H_
|
||||||
|
#define _SAMPLE_FILTER_H_
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace RubberBand
|
||||||
|
{
|
||||||
|
|
||||||
|
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 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 &);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -19,8 +19,9 @@
|
|||||||
namespace RubberBand
|
namespace RubberBand
|
||||||
{
|
{
|
||||||
|
|
||||||
SilentAudioCurve::SilentAudioCurve(size_t sampleRate, size_t windowSize) :
|
|
||||||
AudioCurveCalculator(sampleRate, windowSize)
|
SilentAudioCurve::SilentAudioCurve(Parameters parameters) :
|
||||||
|
AudioCurveCalculator(parameters)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,16 +34,10 @@ SilentAudioCurve::reset()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
SilentAudioCurve::setWindowSize(size_t newSize)
|
|
||||||
{
|
|
||||||
m_windowSize = newSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
float
|
float
|
||||||
SilentAudioCurve::processFloat(const float *R__ mag, size_t)
|
SilentAudioCurve::processFloat(const float *R__ mag, int)
|
||||||
{
|
{
|
||||||
const int hs = m_windowSize / 2;
|
const int hs = m_lastPerceivedBin;
|
||||||
static float threshold = powf(10.f, -6);
|
static float threshold = powf(10.f, -6);
|
||||||
|
|
||||||
for (int i = 0; i <= hs; ++i) {
|
for (int i = 0; i <= hs; ++i) {
|
||||||
@@ -53,9 +48,9 @@ SilentAudioCurve::processFloat(const float *R__ mag, size_t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
SilentAudioCurve::processDouble(const double *R__ mag, size_t)
|
SilentAudioCurve::processDouble(const double *R__ mag, int)
|
||||||
{
|
{
|
||||||
const int hs = m_windowSize / 2;
|
const int hs = m_lastPerceivedBin;
|
||||||
static double threshold = pow(10.0, -6);
|
static double threshold = pow(10.0, -6);
|
||||||
|
|
||||||
for (int i = 0; i <= hs; ++i) {
|
for (int i = 0; i <= hs; ++i) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -23,14 +23,13 @@ namespace RubberBand
|
|||||||
class SilentAudioCurve : public AudioCurveCalculator
|
class SilentAudioCurve : public AudioCurveCalculator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SilentAudioCurve(size_t sampleRate, size_t windowSize);
|
SilentAudioCurve(Parameters parameters);
|
||||||
virtual ~SilentAudioCurve();
|
virtual ~SilentAudioCurve();
|
||||||
|
|
||||||
virtual void setWindowSize(size_t newSize);
|
virtual float processFloat(const float *R__ mag, int increment);
|
||||||
|
virtual double processDouble(const double *R__ mag, int increment);
|
||||||
virtual float processFloat(const float *R__ mag, size_t increment);
|
|
||||||
virtual double processDouble(const double *R__ mag, size_t increment);
|
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
virtual const char *getUnit() const { return "bool"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -20,12 +20,13 @@
|
|||||||
namespace RubberBand
|
namespace RubberBand
|
||||||
{
|
{
|
||||||
|
|
||||||
SpectralDifferenceAudioCurve::SpectralDifferenceAudioCurve(size_t sampleRate, size_t windowSize) :
|
|
||||||
AudioCurveCalculator(sampleRate, windowSize)
|
SpectralDifferenceAudioCurve::SpectralDifferenceAudioCurve(Parameters parameters) :
|
||||||
|
AudioCurveCalculator(parameters)
|
||||||
{
|
{
|
||||||
m_mag = allocate<double>(m_windowSize/2 + 1);
|
m_mag = allocate<double>(m_lastPerceivedBin + 1);
|
||||||
m_tmpbuf = allocate<double>(m_windowSize/2 + 1);
|
m_tmpbuf = allocate<double>(m_lastPerceivedBin + 1);
|
||||||
v_zero(m_mag, m_windowSize/2 + 1);
|
v_zero(m_mag, m_lastPerceivedBin + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
SpectralDifferenceAudioCurve::~SpectralDifferenceAudioCurve()
|
SpectralDifferenceAudioCurve::~SpectralDifferenceAudioCurve()
|
||||||
@@ -37,26 +38,26 @@ SpectralDifferenceAudioCurve::~SpectralDifferenceAudioCurve()
|
|||||||
void
|
void
|
||||||
SpectralDifferenceAudioCurve::reset()
|
SpectralDifferenceAudioCurve::reset()
|
||||||
{
|
{
|
||||||
v_zero(m_mag, m_windowSize/2 + 1);
|
v_zero(m_mag, m_lastPerceivedBin + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SpectralDifferenceAudioCurve::setWindowSize(size_t newSize)
|
SpectralDifferenceAudioCurve::setWindowSize(int newSize)
|
||||||
{
|
{
|
||||||
deallocate(m_tmpbuf);
|
deallocate(m_tmpbuf);
|
||||||
deallocate(m_mag);
|
deallocate(m_mag);
|
||||||
m_windowSize = newSize;
|
AudioCurveCalculator::setWindowSize(newSize);
|
||||||
m_mag = allocate<double>(m_windowSize/2 + 1);
|
m_mag = allocate<double>(m_lastPerceivedBin + 1);
|
||||||
m_tmpbuf = allocate<double>(m_windowSize/2 + 1);
|
m_tmpbuf = allocate<double>(m_lastPerceivedBin + 1);
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
SpectralDifferenceAudioCurve::processFloat(const float *R__ mag, size_t increment)
|
SpectralDifferenceAudioCurve::processFloat(const float *R__ mag, int increment)
|
||||||
{
|
{
|
||||||
double result = 0.0;
|
double result = 0.0;
|
||||||
|
|
||||||
const int hs1 = m_windowSize/2 + 1;
|
const int hs1 = m_lastPerceivedBin + 1;
|
||||||
|
|
||||||
v_convert(m_tmpbuf, mag, hs1);
|
v_convert(m_tmpbuf, mag, hs1);
|
||||||
v_square(m_tmpbuf, hs1);
|
v_square(m_tmpbuf, hs1);
|
||||||
@@ -73,11 +74,11 @@ SpectralDifferenceAudioCurve::processFloat(const float *R__ mag, size_t incremen
|
|||||||
}
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
SpectralDifferenceAudioCurve::processDouble(const double *R__ mag, size_t increment)
|
SpectralDifferenceAudioCurve::processDouble(const double *R__ mag, int increment)
|
||||||
{
|
{
|
||||||
double result = 0.0;
|
double result = 0.0;
|
||||||
|
|
||||||
const int hs1 = m_windowSize/2 + 1;
|
const int hs1 = m_lastPerceivedBin + 1;
|
||||||
|
|
||||||
v_convert(m_tmpbuf, mag, hs1);
|
v_convert(m_tmpbuf, mag, hs1);
|
||||||
v_square(m_tmpbuf, hs1);
|
v_square(m_tmpbuf, hs1);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -24,15 +24,16 @@ namespace RubberBand
|
|||||||
class SpectralDifferenceAudioCurve : public AudioCurveCalculator
|
class SpectralDifferenceAudioCurve : public AudioCurveCalculator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SpectralDifferenceAudioCurve(size_t sampleRate, size_t windowSize);
|
SpectralDifferenceAudioCurve(Parameters parameters);
|
||||||
|
|
||||||
virtual ~SpectralDifferenceAudioCurve();
|
virtual ~SpectralDifferenceAudioCurve();
|
||||||
|
|
||||||
virtual void setWindowSize(size_t newSize);
|
virtual void setWindowSize(int newSize);
|
||||||
|
|
||||||
virtual float processFloat(const float *R__ mag, size_t increment);
|
virtual float processFloat(const float *R__ mag, int increment);
|
||||||
virtual double processDouble(const double *R__ mag, size_t increment);
|
virtual double processDouble(const double *R__ mag, int increment);
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
virtual const char *getUnit() const { return "V"; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
double *R__ m_mag;
|
double *R__ m_mag;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -153,7 +153,7 @@ void Window<T>::encache()
|
|||||||
m_cache = mult;
|
m_cache = mult;
|
||||||
|
|
||||||
m_area = 0;
|
m_area = 0;
|
||||||
for (int i = 0; i < n; ++i) {
|
for (i = 0; i < n; ++i) {
|
||||||
m_area += m_cache[i];
|
m_area += m_cache[i];
|
||||||
}
|
}
|
||||||
m_area /= n;
|
m_area /= n;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -74,6 +74,11 @@ void rubberband_set_transients_option(RubberBandState state, RubberBandOptions o
|
|||||||
state->m_s->setTransientsOption(options);
|
state->m_s->setTransientsOption(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rubberband_set_detector_option(RubberBandState state, RubberBandOptions options)
|
||||||
|
{
|
||||||
|
state->m_s->setDetectorOption(options);
|
||||||
|
}
|
||||||
|
|
||||||
void rubberband_set_phase_option(RubberBandState state, RubberBandOptions options)
|
void rubberband_set_phase_option(RubberBandState state, RubberBandOptions options)
|
||||||
{
|
{
|
||||||
state->m_s->setPhaseOption(options);
|
state->m_s->setPhaseOption(options);
|
||||||
@@ -104,6 +109,15 @@ void rubberband_set_max_process_size(RubberBandState state, unsigned int samples
|
|||||||
state->m_s->setMaxProcessSize(samples);
|
state->m_s->setMaxProcessSize(samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rubberband_set_key_frame_map(RubberBandState state, unsigned int keyframecount, unsigned int *from, unsigned int *to)
|
||||||
|
{
|
||||||
|
std::map<size_t, size_t> kfm;
|
||||||
|
for (unsigned int i = 0; i < keyframecount; ++i) {
|
||||||
|
kfm[from[i]] = to[i];
|
||||||
|
}
|
||||||
|
state->m_s->setKeyFrameMap(kfm);
|
||||||
|
}
|
||||||
|
|
||||||
void rubberband_study(RubberBandState state, const float *const *input, unsigned int samples, int final)
|
void rubberband_study(RubberBandState state, const float *const *input, unsigned int samples, int final)
|
||||||
{
|
{
|
||||||
state->m_s->study(input, samples, final != 0);
|
state->m_s->study(input, samples, final != 0);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -134,13 +134,32 @@ T **reallocate_channels(T **ptr,
|
|||||||
try {
|
try {
|
||||||
newptr = allocate_channels<T>(channels, count);
|
newptr = allocate_channels<T>(channels, count);
|
||||||
} catch (std::bad_alloc) {
|
} catch (std::bad_alloc) {
|
||||||
if (ptr) deallocate_channels<T>(ptr);
|
if (ptr) deallocate_channels<T>(ptr, channels);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
if (oldcount && ptr) {
|
if (oldcount && ptr) {
|
||||||
v_copy_channels(newptr, ptr, channels, oldcount < count ? oldcount : count);
|
v_copy_channels(newptr, ptr, channels, oldcount < count ? oldcount : count);
|
||||||
}
|
}
|
||||||
if (ptr) deallocate_channels<T>(ptr);
|
if (ptr) deallocate_channels<T>(ptr, channels);
|
||||||
|
return newptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T **reallocate_and_zero_extend_channels(T **ptr,
|
||||||
|
size_t oldchannels, size_t oldcount,
|
||||||
|
size_t channels, size_t count)
|
||||||
|
{
|
||||||
|
T **newptr = 0;
|
||||||
|
try {
|
||||||
|
newptr = allocate_and_zero_channels<T>(channels, count);
|
||||||
|
} catch (std::bad_alloc) {
|
||||||
|
if (ptr) deallocate_channels<T>(ptr, channels);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
if (oldcount && ptr) {
|
||||||
|
v_copy_channels(newptr, ptr, channels, oldcount < count ? oldcount : count);
|
||||||
|
}
|
||||||
|
if (ptr) deallocate_channels<T>(ptr, channels);
|
||||||
return newptr;
|
return newptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -80,8 +80,8 @@ inline float princargf(float a) { return modf(a + (float)M_PI, -2.f * (float)M_P
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#define MLOCK(a,b) ::mlock((char *)(a),(b))
|
#define MLOCK(a,b) ::mlock((char *)(a),(b))
|
||||||
#define MUNLOCK(a,b) (::munlock((char *)(a),(b)) ? (::perror("munlock failed"), 0) : 0)
|
#define MUNLOCK(a,b) (::munlock((char *)(a),(b)) ? (::perror("munlock failed"), 0) : 0)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
@@ -300,7 +300,7 @@ RubberBandVampPlugin::getParameterDescriptors() const
|
|||||||
d.isQuantized = true;
|
d.isQuantized = true;
|
||||||
d.quantizeStep = 1;
|
d.quantizeStep = 1;
|
||||||
d.valueNames.clear();
|
d.valueNames.clear();
|
||||||
d.valueNames.push_back("Peak Locked");
|
d.valueNames.push_back("Laminar");
|
||||||
d.valueNames.push_back("Independent");
|
d.valueNames.push_back("Independent");
|
||||||
list.push_back(d);
|
list.push_back(d);
|
||||||
|
|
||||||
@@ -405,8 +405,6 @@ RubberBandVampPlugin::initialise(size_t channels, size_t stepSize, size_t blockS
|
|||||||
void
|
void
|
||||||
RubberBandVampPlugin::reset()
|
RubberBandVampPlugin::reset()
|
||||||
{
|
{
|
||||||
// delete m_stretcher; //!!! or just if (m_stretcher) m_stretcher->reset();
|
|
||||||
// m_stretcher = new RubberBand::RubberBandStretcher(lrintf(m_inputSampleRate), channels);
|
|
||||||
if (m_d->m_stretcher) m_d->m_stretcher->reset();
|
if (m_d->m_stretcher) m_d->m_stretcher->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,9 +453,7 @@ RubberBandVampPlugin::Impl::getRemainingFeaturesOffline()
|
|||||||
|
|
||||||
int rate = m_sampleRate;
|
int rate = m_sampleRate;
|
||||||
|
|
||||||
RubberBand::StretchCalculator sc(rate,
|
RubberBand::StretchCalculator sc(rate, m_stretcher->getInputIncrement(), true);
|
||||||
m_stretcher->getInputIncrement(),
|
|
||||||
true);
|
|
||||||
|
|
||||||
size_t inputIncrement = m_stretcher->getInputIncrement();
|
size_t inputIncrement = m_stretcher->getInputIncrement();
|
||||||
std::vector<int> outputIncrements = m_stretcher->getOutputIncrements();
|
std::vector<int> outputIncrements = m_stretcher->getOutputIncrements();
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/*
|
/*
|
||||||
Rubber Band
|
Rubber Band
|
||||||
An audio time-stretching and pitch-shifting library.
|
An audio time-stretching and pitch-shifting library.
|
||||||
Copyright 2007-2009 Chris Cannam.
|
Copyright 2007-2010 Chris Cannam.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
|
|||||||
Reference in New Issue
Block a user