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
|
||||
|
||||
* 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
|
||||
|
||||
* 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
|
||||
less variation in CPU usage
|
||||
* 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/Scavenger.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/Resampler.h \
|
||||
src/dsp/HighFrequencyAudioCurve.h \
|
||||
src/dsp/SilentAudioCurve.h \
|
||||
src/dsp/FFT.h \
|
||||
src/dsp/PercussiveAudioCurve.h \
|
||||
src/dsp/ConstantAudioCurve.h \
|
||||
src/dsp/MovingMedian.h \
|
||||
src/dsp/Window.h \
|
||||
src/system/Allocators.h \
|
||||
src/system/Thread.h \
|
||||
@@ -76,6 +78,7 @@ LIBRARY_SOURCES := \
|
||||
src/StretchCalculator.cpp \
|
||||
src/base/Profiler.cpp \
|
||||
src/dsp/AudioCurveCalculator.cpp \
|
||||
src/dsp/CompoundAudioCurve.cpp \
|
||||
src/dsp/SpectralDifferenceAudioCurve.cpp \
|
||||
src/dsp/HighFrequencyAudioCurve.cpp \
|
||||
src/dsp/SilentAudioCurve.cpp \
|
||||
|
||||
@@ -4,7 +4,7 @@ Rubber Band
|
||||
|
||||
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.
|
||||
|
||||
@@ -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.
|
||||
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
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
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
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -20,6 +20,9 @@
|
||||
#include <time.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "system/sysutils.h"
|
||||
|
||||
@@ -87,12 +90,20 @@ int main(int argc, char **argv)
|
||||
|
||||
bool haveRatio = false;
|
||||
|
||||
std::string mapfile;
|
||||
|
||||
enum {
|
||||
NoTransients,
|
||||
BandLimitedTransients,
|
||||
Transients
|
||||
} transients = Transients;
|
||||
|
||||
enum {
|
||||
CompoundDetector,
|
||||
PercussiveDetector,
|
||||
SoftDetector
|
||||
} detector = CompoundDetector;
|
||||
|
||||
while (1) {
|
||||
int optionIndex = 0;
|
||||
|
||||
@@ -116,13 +127,18 @@ int main(int argc, char **argv)
|
||||
{ "window-long", 0, 0, '3' },
|
||||
{ "window-short", 0, 0, '4' },
|
||||
{ "bl-transients", 0, 0, '8' },
|
||||
{ "detector-perc", 0, 0, '5' },
|
||||
{ "detector-soft", 0, 0, '6' },
|
||||
{ "pitch-hq", 0, 0, '%' },
|
||||
{ "threads", 0, 0, '@' },
|
||||
{ "quiet", 0, 0, 'q' },
|
||||
{ "timemap", 1, 0, 'M' },
|
||||
{ 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;
|
||||
|
||||
switch (c) {
|
||||
@@ -143,10 +159,13 @@ int main(int argc, char **argv)
|
||||
case '2': lamination = false; crispchanged = true; break;
|
||||
case '3': longwin = 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 '%': hqpitch = true; break;
|
||||
case 'c': crispness = atoi(optarg); break;
|
||||
case 'q': quiet = true; break;
|
||||
case 'M': mapfile = optarg; break;
|
||||
default: help = true; break;
|
||||
}
|
||||
}
|
||||
@@ -160,7 +179,7 @@ int main(int argc, char **argv)
|
||||
cerr << endl;
|
||||
cerr << "Rubber Band" << 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 << " Usage: " << argv[0] << " [options] <infile.wav> <outfile.wav>" << 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 << " -f<X>, --frequency <X> Change frequency by multiple X" << 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 << "for more details." << 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 << 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 << " --window-long Use longer processing window (actual size may vary)" << 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 << 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 << "\"Crispness\" levels:" << 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 2 equivalent to --no-transients" << endl;
|
||||
cerr << " -c 3 equivalent to --bl-transients" << endl;
|
||||
cerr << " -c 4 default processing options" << endl;
|
||||
cerr << " -c 5 equivalent to --no-lamination --window-short (may be good for drums)" << endl;
|
||||
cerr << " -c 1 equivalent to --detector-soft --no-lamination --window-long (for piano)" << endl;
|
||||
cerr << " -c 2 equivalent to --no-transients --no-lamination" << endl;
|
||||
cerr << " -c 3 equivalent to --no-transients" << endl;
|
||||
cerr << " -c 4 equivalent to --bl-transients" << 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;
|
||||
return 2;
|
||||
}
|
||||
@@ -220,28 +249,68 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
switch (crispness) {
|
||||
case -1: crispness = 4; break;
|
||||
case 0: transients = NoTransients; lamination = false; longwin = true; shortwin = false; break;
|
||||
case 1: transients = NoTransients; lamination = false; longwin = false; shortwin = false; break;
|
||||
case 2: transients = NoTransients; lamination = true; longwin = false; shortwin = false; break;
|
||||
case 3: transients = BandLimitedTransients; lamination = true; longwin = false; shortwin = false; break;
|
||||
case 4: transients = Transients; lamination = true; longwin = false; shortwin = false; break;
|
||||
case 5: transients = Transients; lamination = false; longwin = false; shortwin = true; break;
|
||||
case -1: crispness = 5; break;
|
||||
case 0: detector = CompoundDetector; transients = NoTransients; lamination = false; longwin = true; shortwin = false; break;
|
||||
case 1: detector = SoftDetector; transients = Transients; lamination = false; longwin = true; shortwin = false; break;
|
||||
case 2: detector = CompoundDetector; transients = NoTransients; lamination = false; longwin = false; shortwin = false; break;
|
||||
case 3: detector = CompoundDetector; transients = NoTransients; lamination = true; longwin = false; shortwin = false; break;
|
||||
case 4: detector = CompoundDetector; transients = BandLimitedTransients; lamination = true; longwin = false; shortwin = false; 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) {
|
||||
cerr << "Using crispness level: " << crispness << " (";
|
||||
switch (crispness) {
|
||||
case 0: cerr << "Mushy"; break;
|
||||
case 1: cerr << "Smooth"; break;
|
||||
case 2: cerr << "Balanced multitimbral mixture"; break;
|
||||
case 3: cerr << "Unpitched percussion with stable notes"; break;
|
||||
case 4: cerr << "Crisp monophonic instrumental"; break;
|
||||
case 5: cerr << "Unpitched solo percussion"; break;
|
||||
case 1: cerr << "Piano"; break;
|
||||
case 2: cerr << "Smooth"; break;
|
||||
case 3: cerr << "Balanced multitimbral mixture"; break;
|
||||
case 4: cerr << "Unpitched percussion with stable notes"; break;
|
||||
case 5: cerr << "Crisp monophonic instrumental"; break;
|
||||
case 6: cerr << "Unpitched solo percussion"; break;
|
||||
}
|
||||
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 *fileNameOut = strdup(argv[optind++]);
|
||||
|
||||
@@ -317,6 +386,18 @@ int main(int argc, char **argv)
|
||||
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) {
|
||||
frequencyshift *= pow(2.0, pitchshift / 12);
|
||||
}
|
||||
@@ -390,6 +471,10 @@ int main(int argc, char **argv)
|
||||
frame = 0;
|
||||
percent = 0;
|
||||
|
||||
if (!mapping.empty()) {
|
||||
ts.setKeyFrameMap(mapping);
|
||||
}
|
||||
|
||||
size_t countIn = 0, countOut = 0;
|
||||
|
||||
while (frame < sfinfo.frames) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -15,11 +15,12 @@
|
||||
#ifndef _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_MINOR_VERSION 1
|
||||
#define RUBBERBAND_API_MINOR_VERSION 3
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
/**
|
||||
* @mainpage RubberBand
|
||||
@@ -123,7 +124,25 @@ public:
|
||||
* but may be less clear than with either of the other
|
||||
* 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
|
||||
* during non-transient segments. These options may be changed at
|
||||
* any time.
|
||||
@@ -138,7 +157,7 @@ public:
|
||||
* frequency bin independently from its neighbours. This
|
||||
* 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
|
||||
* construction.
|
||||
*
|
||||
@@ -154,7 +173,7 @@ public:
|
||||
* situation where \c OptionThreadingAuto would do so, except omit
|
||||
* 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
|
||||
* many factors, but it can be influenced. These options may not
|
||||
* be changed after construction.
|
||||
@@ -172,7 +191,7 @@ public:
|
||||
* likely to result in a smoother sound at the expense of
|
||||
* 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
|
||||
* options may be changed at any time.
|
||||
*
|
||||
@@ -185,7 +204,7 @@ public:
|
||||
* note frequency without so substantially affecting the
|
||||
* 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.
|
||||
* They are only effective in realtime mode; in offline mode, the
|
||||
* pitch-shift method is fixed.
|
||||
@@ -219,6 +238,10 @@ public:
|
||||
OptionTransientsMixed = 0x00000100,
|
||||
OptionTransientsSmooth = 0x00000200,
|
||||
|
||||
OptionDetectorCompound = 0x00000000,
|
||||
OptionDetectorPercussive = 0x00000400,
|
||||
OptionDetectorSoft = 0x00000800,
|
||||
|
||||
OptionPhaseLaminar = 0x00000000,
|
||||
OptionPhaseIndependent = 0x00002000,
|
||||
|
||||
@@ -348,6 +371,14 @@ public:
|
||||
*/
|
||||
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
|
||||
* called at any time in any mode.
|
||||
@@ -416,6 +447,32 @@ public:
|
||||
*/
|
||||
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
|
||||
* study and calculate a stretch profile from.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -19,9 +19,9 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RUBBERBAND_VERSION "1.4.0-gpl"
|
||||
#define RUBBERBAND_VERSION "1.5.0-gpl"
|
||||
#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.
|
||||
@@ -48,6 +48,10 @@ enum RubberBandOption {
|
||||
RubberBandOptionTransientsMixed = 0x00000100,
|
||||
RubberBandOptionTransientsSmooth = 0x00000200,
|
||||
|
||||
RubberBandOptionDetectorCompound = 0x00000000,
|
||||
RubberBandOptionDetectorPercussive = 0x00000400,
|
||||
RubberBandOptionDetectorSoft = 0x00000800,
|
||||
|
||||
RubberBandOptionPhaseLaminar = 0x00000000,
|
||||
RubberBandOptionPhaseIndependent = 0x00002000,
|
||||
|
||||
@@ -91,6 +95,7 @@ extern double rubberband_get_pitch_scale(const RubberBandState);
|
||||
extern unsigned int rubberband_get_latency(const RubberBandState);
|
||||
|
||||
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_formant_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 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_process(RubberBandState, const float *const *input, unsigned int samples, int final);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -74,6 +74,12 @@ RubberBandStretcher::setTransientsOption(Options options)
|
||||
m_d->setTransientsOption(options);
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::setDetectorOption(Options options)
|
||||
{
|
||||
m_d->setDetectorOption(options);
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::setPhaseOption(Options options)
|
||||
{
|
||||
@@ -104,6 +110,12 @@ RubberBandStretcher::setMaxProcessSize(size_t samples)
|
||||
m_d->setMaxProcessSize(samples);
|
||||
}
|
||||
|
||||
void
|
||||
RubberBandStretcher::setKeyFrameMap(const std::map<size_t, size_t> &mapping)
|
||||
{
|
||||
m_d->setKeyFrameMap(mapping);
|
||||
}
|
||||
|
||||
size_t
|
||||
RubberBandStretcher::getSamplesRequired() const
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
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>
|
||||
StretchCalculator::calculate(double ratio, size_t inputDuration,
|
||||
const std::vector<float> &phaseResetDf,
|
||||
@@ -52,11 +67,9 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
||||
{
|
||||
assert(phaseResetDf.size() == stretchDf.size());
|
||||
|
||||
m_lastPeaks = findPeaks(phaseResetDf);
|
||||
std::vector<Peak> &peaks = m_lastPeaks;
|
||||
size_t totalCount = phaseResetDf.size();
|
||||
m_peaks = findPeaks(phaseResetDf);
|
||||
|
||||
std::vector<int> increments;
|
||||
size_t totalCount = phaseResetDf.size();
|
||||
|
||||
size_t outputDuration = lrint(inputDuration * ratio);
|
||||
|
||||
@@ -68,14 +81,13 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
||||
|
||||
if (m_debugLevel > 0) {
|
||||
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;
|
||||
for (size_t i = 0; i < peaks.size(); ++i) {
|
||||
fixedAudioChunks.push_back
|
||||
(lrint((double(peaks[i].chunk) * outputDuration) / totalCount));
|
||||
}
|
||||
std::vector<Peak> peaks; // peak position (in chunks) and hardness
|
||||
std::vector<size_t> targets; // targets for mapping peaks (in samples)
|
||||
mapPeaks(peaks, targets, outputDuration, totalCount);
|
||||
|
||||
if (m_debugLevel > 1) {
|
||||
std::cerr << "have " << peaks.size() << " fixed positions" << std::endl;
|
||||
@@ -93,6 +105,8 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
||||
|
||||
size_t regionTotalChunks = 0;
|
||||
|
||||
std::vector<int> increments;
|
||||
|
||||
for (size_t i = 0; i <= peaks.size(); ++i) {
|
||||
|
||||
size_t regionStart, regionStartChunk, regionEnd, regionEndChunk;
|
||||
@@ -103,18 +117,24 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
||||
regionStart = 0;
|
||||
} else {
|
||||
regionStartChunk = peaks[i-1].chunk;
|
||||
regionStart = fixedAudioChunks[i-1];
|
||||
regionStart = targets[i-1];
|
||||
phaseReset = peaks[i-1].hard;
|
||||
}
|
||||
|
||||
if (i == peaks.size()) {
|
||||
// std::cerr << "note: i (=" << i << ") == peaks.size(); regionEndChunk " << regionEndChunk << " -> " << totalCount << ", regionEnd " << regionEnd << " -> " << outputDuration << std::endl;
|
||||
regionEndChunk = totalCount;
|
||||
regionEnd = outputDuration;
|
||||
} else {
|
||||
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;
|
||||
regionTotalChunks += regionDuration;
|
||||
|
||||
@@ -125,7 +145,7 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -149,7 +169,7 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -163,6 +183,131 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
||||
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
|
||||
StretchCalculator::calculateSingle(double ratio,
|
||||
float df,
|
||||
@@ -182,7 +327,7 @@ StretchCalculator::calculateSingle(double ratio,
|
||||
// works well in common situations.
|
||||
|
||||
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) {
|
||||
isTransient = true;
|
||||
@@ -200,8 +345,7 @@ StretchCalculator::calculateSingle(double ratio,
|
||||
|
||||
if (isTransient && m_transientAmnesty == 0) {
|
||||
if (m_debugLevel > 1) {
|
||||
std::cerr << "StretchCalculator::calculateSingle: transient"
|
||||
<< std::endl;
|
||||
std::cerr << "StretchCalculator::calculateSingle: transient (df " << df << ", threshold " << transientThreshold << ")" << std::endl;
|
||||
}
|
||||
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());
|
||||
|
||||
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;
|
||||
@@ -651,22 +795,24 @@ StretchCalculator::distributeRegion(const std::vector<float> &dfIn,
|
||||
|
||||
// then we need to adjust and accommodate
|
||||
|
||||
bool acceptableSquashRange = false;
|
||||
|
||||
double totalDisplacement = 0;
|
||||
double maxDisplacement = 0; // min displacement will be 0 by definition
|
||||
|
||||
maxDf = 0;
|
||||
float adj = 0;
|
||||
|
||||
bool tooShort = true, tooLong = true;
|
||||
const int acceptableIterations = 10;
|
||||
int iteration = 0;
|
||||
int prevExtreme = 0;
|
||||
bool better = false;
|
||||
|
||||
while (!acceptableSquashRange && iteration < acceptableIterations) {
|
||||
while ((tooLong || tooShort) && iteration < acceptableIterations) {
|
||||
|
||||
++iteration;
|
||||
|
||||
acceptableSquashRange = true;
|
||||
tooLong = false;
|
||||
tooShort = false;
|
||||
calculateDisplacements(df, maxDf, totalDisplacement, maxDisplacement,
|
||||
adj);
|
||||
|
||||
@@ -678,35 +824,61 @@ StretchCalculator::distributeRegion(const std::vector<float> &dfIn,
|
||||
// Not usually a problem, in fact
|
||||
// std::cerr << "WARNING: totalDisplacement == 0 (duration " << duration << ", " << df.size() << " values in df)" << std::endl;
|
||||
if (!df.empty() && adj == 0) {
|
||||
acceptableSquashRange = false;
|
||||
tooLong = true; tooShort = true;
|
||||
adj = 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
int extremeIncrement = m_increment + lrint((toAllot * maxDisplacement) / totalDisplacement);
|
||||
int extremeIncrement = m_increment +
|
||||
lrint((toAllot * maxDisplacement) / totalDisplacement);
|
||||
|
||||
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;
|
||||
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;
|
||||
std::cerr << "NOTE: extreme increment "
|
||||
<< extremeIncrement << " < "
|
||||
<< (m_increment * ratio) / 2
|
||||
<< ", adjusting" << std::endl;
|
||||
}
|
||||
acceptableSquashRange = false;
|
||||
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;
|
||||
|
||||
std::cerr << "NOTE: extreme increment "
|
||||
<< extremeIncrement << " > "
|
||||
<< m_increment * ratio * 2
|
||||
<< ", adjusting" << std::endl;
|
||||
}
|
||||
acceptableSquashRange = false;
|
||||
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;
|
||||
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
|
||||
// the total displacement, yet ensure that the
|
||||
// displacements still sum to the total.
|
||||
@@ -714,9 +886,24 @@ StretchCalculator::distributeRegion(const std::vector<float> &dfIn,
|
||||
}
|
||||
}
|
||||
|
||||
if (!acceptableSquashRange) {
|
||||
std::cerr << "WARNING: No acceptable displacement adjustment found, using defaults:\nthis region will probably sound bad" << std::endl;
|
||||
adj = 0;
|
||||
if (tooLong) {
|
||||
if (better) {
|
||||
// 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,
|
||||
adj);
|
||||
}
|
||||
@@ -728,6 +915,9 @@ StretchCalculator::distributeRegion(const std::vector<float> &dfIn,
|
||||
else displacement += adj;
|
||||
|
||||
if (i == 0 && phaseReset) {
|
||||
if (m_debugLevel > 2) {
|
||||
std::cerr << "Phase reset at first chunk" << std::endl;
|
||||
}
|
||||
if (df.size() == 1) {
|
||||
increments.push_back(duration);
|
||||
totalIncrement += duration;
|
||||
@@ -749,19 +939,23 @@ StretchCalculator::distributeRegion(const std::vector<float> &dfIn,
|
||||
|
||||
int increment = m_increment + allotment;
|
||||
|
||||
if (increment <= 0) {
|
||||
if (increment < 0) {
|
||||
// this is a serious problem, the allocation is quite
|
||||
// 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;
|
||||
|
||||
toAllot += m_increment;
|
||||
increment = 0;
|
||||
allotment = increment - m_increment;
|
||||
|
||||
} else {
|
||||
toAllot -= allotment;
|
||||
}
|
||||
|
||||
increments.push_back(increment);
|
||||
totalIncrement += increment;
|
||||
|
||||
toAllot -= allotment;
|
||||
totalDisplacement -= displacement;
|
||||
|
||||
if (m_debugLevel > 2) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace RubberBand
|
||||
{
|
||||
@@ -28,6 +29,15 @@ public:
|
||||
StretchCalculator(size_t sampleRate, size_t inputIncrement, bool useHardPeaks);
|
||||
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
|
||||
* overall target stretch ratio, input duration in audio samples,
|
||||
@@ -35,7 +45,7 @@ public:
|
||||
* (lockAudioCurve) and for allocating stretches to relatively
|
||||
* 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> &stretchAudioCurve);
|
||||
|
||||
@@ -49,7 +59,7 @@ public:
|
||||
* If increment is non-zero, use it for the input increment for
|
||||
* this block in preference to m_increment.
|
||||
*/
|
||||
virtual int calculateSingle(double ratio, float curveValue,
|
||||
int calculateSingle(double ratio, float curveValue,
|
||||
size_t increment = 0);
|
||||
|
||||
void setUseHardPeaks(bool use) { m_useHardPeaks = use; }
|
||||
@@ -62,13 +72,16 @@ public:
|
||||
size_t chunk;
|
||||
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);
|
||||
|
||||
protected:
|
||||
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,
|
||||
size_t outputDuration, float ratio,
|
||||
bool phaseReset);
|
||||
@@ -90,7 +103,8 @@ protected:
|
||||
int m_debugLevel;
|
||||
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
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -21,11 +21,11 @@
|
||||
|
||||
//#define EXPERIMENT 1
|
||||
|
||||
namespace RubberBand { class Resampler; }
|
||||
|
||||
namespace RubberBand
|
||||
{
|
||||
|
||||
class Resampler;
|
||||
|
||||
class RubberBandStretcher::Impl::ChannelData
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "dsp/SpectralDifferenceAudioCurve.h"
|
||||
#include "dsp/SilentAudioCurve.h"
|
||||
#include "dsp/ConstantAudioCurve.h"
|
||||
#include "dsp/CompoundAudioCurve.h"
|
||||
#include "dsp/Resampler.h"
|
||||
|
||||
#include "StretchCalculator.h"
|
||||
@@ -81,9 +82,11 @@ RubberBandStretcher::Impl::Impl(size_t sampleRate,
|
||||
m_studyFFT(0),
|
||||
m_spaceAvailable("space"),
|
||||
m_inputDuration(0),
|
||||
m_detectorType(CompoundAudioCurve::CompoundDetector),
|
||||
m_silentHistory(0),
|
||||
m_lastProcessOutputIncrements(16),
|
||||
m_lastProcessPhaseResetDf(16),
|
||||
m_emergencyScavenger(10, 4),
|
||||
m_phaseResetAudioCurve(0),
|
||||
m_stretchAudioCurve(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
|
||||
// we don't let it drop below the 48k default
|
||||
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));
|
||||
|
||||
if ((options & OptionWindowShort) || (options & OptionWindowLong)) {
|
||||
@@ -205,6 +208,12 @@ RubberBandStretcher::Impl::reset()
|
||||
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) {
|
||||
m_channelData[c]->reset();
|
||||
}
|
||||
@@ -299,6 +308,24 @@ RubberBandStretcher::Impl::setMaxProcessSize(size_t samples)
|
||||
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
|
||||
RubberBandStretcher::Impl::getFrequencyCutoff(int n) const
|
||||
{
|
||||
@@ -399,7 +426,7 @@ RubberBandStretcher::Impl::calculateSizes()
|
||||
float windowIncrRatio = 4.5;
|
||||
if (r == 1.0) windowIncrRatio = 4;
|
||||
else if (rsb) windowIncrRatio = 4.5;
|
||||
else windowIncrRatio = 6;
|
||||
else windowIncrRatio = 8;
|
||||
|
||||
outputIncrement = int(windowSize / windowIncrRatio);
|
||||
inputIncrement = int(outputIncrement / r);
|
||||
@@ -598,21 +625,22 @@ RubberBandStretcher::Impl::configure()
|
||||
// modes
|
||||
|
||||
delete m_phaseResetAudioCurve;
|
||||
m_phaseResetAudioCurve = new PercussiveAudioCurve
|
||||
(m_sampleRate, m_windowSize);
|
||||
m_phaseResetAudioCurve = new CompoundAudioCurve
|
||||
(CompoundAudioCurve::Parameters(m_sampleRate, m_windowSize));
|
||||
m_phaseResetAudioCurve->setType(m_detectorType);
|
||||
|
||||
delete m_silentAudioCurve;
|
||||
m_silentAudioCurve = new SilentAudioCurve
|
||||
(m_sampleRate, m_windowSize);
|
||||
(SilentAudioCurve::Parameters(m_sampleRate, m_windowSize));
|
||||
|
||||
if (!m_realtime) {
|
||||
delete m_stretchAudioCurve;
|
||||
if (!(m_options & OptionStretchPrecise)) {
|
||||
m_stretchAudioCurve = new SpectralDifferenceAudioCurve
|
||||
(m_sampleRate, m_windowSize);
|
||||
(SpectralDifferenceAudioCurve::Parameters(m_sampleRate, m_windowSize));
|
||||
} else {
|
||||
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));
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
(getEffectiveRatio(),
|
||||
inputDuration,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "dsp/Window.h"
|
||||
#include "dsp/FFT.h"
|
||||
#include "dsp/CompoundAudioCurve.h"
|
||||
|
||||
#include "base/RingBuffer.h"
|
||||
#include "system/Thread.h"
|
||||
@@ -28,11 +29,10 @@
|
||||
|
||||
using namespace RubberBand;
|
||||
|
||||
namespace RubberBand { class AudioCurveCalculator; }
|
||||
|
||||
namespace RubberBand
|
||||
{
|
||||
|
||||
class AudioCurveCalculator;
|
||||
class StretchCalculator;
|
||||
|
||||
class RubberBandStretcher::Impl
|
||||
@@ -52,12 +52,14 @@ public:
|
||||
size_t getLatency() const;
|
||||
|
||||
void setTransientsOption(Options);
|
||||
void setDetectorOption(Options);
|
||||
void setPhaseOption(Options);
|
||||
void setFormantOption(Options);
|
||||
void setPitchOption(Options);
|
||||
|
||||
void setExpectedInputDuration(size_t samples);
|
||||
void setMaxProcessSize(size_t samples);
|
||||
void setKeyFrameMap(const std::map<size_t, size_t> &);
|
||||
|
||||
size_t getSamplesRequired() const;
|
||||
|
||||
@@ -168,6 +170,7 @@ protected:
|
||||
|
||||
|
||||
size_t m_inputDuration;
|
||||
CompoundAudioCurve::Type m_detectorType;
|
||||
std::vector<float> m_phaseResetDf;
|
||||
std::vector<float> m_stretchDf;
|
||||
std::vector<bool> m_silence;
|
||||
@@ -180,8 +183,9 @@ protected:
|
||||
|
||||
mutable RingBuffer<int> m_lastProcessOutputIncrements;
|
||||
mutable RingBuffer<float> m_lastProcessPhaseResetDf;
|
||||
Scavenger<RingBuffer<float> > m_emergencyScavenger;
|
||||
|
||||
AudioCurveCalculator *m_phaseResetAudioCurve;
|
||||
CompoundAudioCurve *m_phaseResetAudioCurve;
|
||||
AudioCurveCalculator *m_stretchAudioCurve;
|
||||
AudioCurveCalculator *m_silentAudioCurve;
|
||||
StretchCalculator *m_stretchCalculator;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
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
|
||||
// already been calculated.
|
||||
|
||||
// This is the normal process method in offline mode.
|
||||
|
||||
ChannelData &cd = *m_channelData[c];
|
||||
|
||||
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);
|
||||
assert(got == m_windowSize || cd.inputSize >= 0);
|
||||
cd.inbuf->skip(m_increment);
|
||||
analyseChunk(c);
|
||||
}
|
||||
|
||||
bool phaseReset = false;
|
||||
size_t phaseIncrement, shiftIncrement;
|
||||
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++;
|
||||
if (m_debugLevel > 2) {
|
||||
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
|
||||
// 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) {
|
||||
if (!testInbufReadSpace(c)) return false;
|
||||
ChannelData &cd = *m_channelData[c];
|
||||
@@ -383,27 +409,29 @@ RubberBandStretcher::Impl::processChunkForChannel(size_t c,
|
||||
}
|
||||
}
|
||||
|
||||
if (m_threaded) {
|
||||
|
||||
int required = shiftIncrement;
|
||||
|
||||
if (m_pitchScale != 1.0) {
|
||||
required = int(required / m_pitchScale) + 1;
|
||||
}
|
||||
|
||||
if (cd.outbuf->getWriteSpace() < required) {
|
||||
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 is probably stuck in a
|
||||
// process() call waiting for us to stow away enough input
|
||||
// increments to allow the process() call to complete.
|
||||
// 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);
|
||||
@@ -589,12 +617,12 @@ RubberBandStretcher::Impl::getIncrements(size_t channel,
|
||||
if (shiftIncrement < 0) {
|
||||
shiftIncrement = -shiftIncrement;
|
||||
}
|
||||
|
||||
/*
|
||||
if (shiftIncrement >= int(m_windowSize)) {
|
||||
cerr << "*** ERROR: RubberBandStretcher::Impl::processChunks: shiftIncrement " << shiftIncrement << " >= windowSize " << m_windowSize << " at " << cd.chunkCount << " (of " << m_outputIncrements.size() << ")" << endl;
|
||||
shiftIncrement = m_windowSize;
|
||||
}
|
||||
|
||||
*/
|
||||
phaseIncrementRtn = phaseIncrement;
|
||||
shiftIncrementRtn = shiftIncrement;
|
||||
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;
|
||||
}
|
||||
|
||||
if (m_debugLevel > 1) {
|
||||
if (m_debugLevel > 2) {
|
||||
cerr << "mean inheritance distance = " << distacc / count << endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -14,18 +14,50 @@
|
||||
|
||||
#include "AudioCurveCalculator.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace RubberBand
|
||||
{
|
||||
|
||||
AudioCurveCalculator::AudioCurveCalculator(size_t sampleRate, size_t windowSize) :
|
||||
m_sampleRate(sampleRate),
|
||||
m_windowSize(windowSize)
|
||||
static const int MaxPerceivedFreq = 16000;
|
||||
|
||||
AudioCurveCalculator::AudioCurveCalculator(Parameters parameters) :
|
||||
m_sampleRate(parameters.sampleRate),
|
||||
m_windowSize(parameters.windowSize)
|
||||
{
|
||||
recalculateLastPerceivedBin();
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -26,28 +26,51 @@ namespace RubberBand
|
||||
class AudioCurveCalculator
|
||||
{
|
||||
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();
|
||||
|
||||
size_t getSampleRate() const { return m_sampleRate; }
|
||||
size_t getWindowSize() const { return m_windowSize; }
|
||||
int getSampleRate() const { return m_sampleRate; }
|
||||
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
|
||||
// given instance
|
||||
|
||||
|
||||
virtual float processFloat(const float *R__ mag, size_t increment) = 0;
|
||||
virtual double processDouble(const double *R__ mag, size_t increment) = 0;
|
||||
virtual float processFloat(const float *R__ mag, int increment) = 0;
|
||||
virtual double processDouble(const double *R__ mag, int increment) = 0;
|
||||
|
||||
virtual void reset() = 0;
|
||||
|
||||
virtual const char *getUnit() const { return ""; }
|
||||
|
||||
protected:
|
||||
size_t m_sampleRate;
|
||||
size_t m_windowSize;
|
||||
int m_sampleRate;
|
||||
int m_windowSize;
|
||||
int m_lastPerceivedBin;
|
||||
void recalculateLastPerceivedBin();
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#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
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -17,8 +17,9 @@
|
||||
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
|
||||
ConstantAudioCurve::processFloat(const float *R__, size_t)
|
||||
ConstantAudioCurve::processFloat(const float *R__, int)
|
||||
{
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
double
|
||||
ConstantAudioCurve::processDouble(const double *R__, size_t)
|
||||
ConstantAudioCurve::processDouble(const double *R__, int)
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -23,13 +23,11 @@ namespace RubberBand
|
||||
class ConstantAudioCurve : public AudioCurveCalculator
|
||||
{
|
||||
public:
|
||||
ConstantAudioCurve(size_t sampleRate, size_t windowSize);
|
||||
ConstantAudioCurve(Parameters parameters);
|
||||
virtual ~ConstantAudioCurve();
|
||||
|
||||
virtual void setWindowSize(size_t newSize);
|
||||
|
||||
virtual float processFloat(const float *R__ mag, size_t increment);
|
||||
virtual double processDouble(const double *R__ mag, size_t increment);
|
||||
virtual float processFloat(const float *R__ mag, int increment);
|
||||
virtual double processDouble(const double *R__ mag, int increment);
|
||||
virtual void reset();
|
||||
};
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -17,8 +17,9 @@
|
||||
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
|
||||
HighFrequencyAudioCurve::processFloat(const float *R__ mag, size_t increment)
|
||||
HighFrequencyAudioCurve::processFloat(const float *R__ mag, int increment)
|
||||
{
|
||||
float result = 0.0;
|
||||
|
||||
const int sz = m_windowSize / 2;
|
||||
const int sz = m_lastPerceivedBin;
|
||||
|
||||
for (int n = 0; n <= sz; ++n) {
|
||||
result = result + mag[n] * n;
|
||||
@@ -52,11 +47,11 @@ HighFrequencyAudioCurve::processFloat(const float *R__ mag, size_t increment)
|
||||
}
|
||||
|
||||
double
|
||||
HighFrequencyAudioCurve::processDouble(const double *R__ mag, size_t increment)
|
||||
HighFrequencyAudioCurve::processDouble(const double *R__ mag, int increment)
|
||||
{
|
||||
float result = 0.0;
|
||||
|
||||
const int sz = m_windowSize / 2;
|
||||
const int sz = m_lastPerceivedBin;
|
||||
|
||||
for (int n = 0; n <= sz; ++n) {
|
||||
result = result + mag[n] * n;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -23,15 +23,14 @@ namespace RubberBand
|
||||
class HighFrequencyAudioCurve : public AudioCurveCalculator
|
||||
{
|
||||
public:
|
||||
HighFrequencyAudioCurve(size_t sampleRate, size_t windowSize);
|
||||
HighFrequencyAudioCurve(Parameters parameters);
|
||||
|
||||
virtual ~HighFrequencyAudioCurve();
|
||||
|
||||
virtual void setWindowSize(size_t newSize);
|
||||
|
||||
virtual float processFloat(const float *R__ mag, size_t increment);
|
||||
virtual double processDouble(const double *R__ mag, size_t increment);
|
||||
virtual float processFloat(const float *R__ mag, int increment);
|
||||
virtual double processDouble(const double *R__ mag, int increment);
|
||||
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
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -18,12 +18,13 @@
|
||||
#include "system/VectorOps.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <iostream>
|
||||
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);
|
||||
}
|
||||
@@ -40,26 +41,29 @@ PercussiveAudioCurve::reset()
|
||||
}
|
||||
|
||||
void
|
||||
PercussiveAudioCurve::setWindowSize(size_t newSize)
|
||||
PercussiveAudioCurve::setWindowSize(int newSize)
|
||||
{
|
||||
m_prevMag = reallocate(m_prevMag, m_windowSize, newSize);
|
||||
m_windowSize = newSize;
|
||||
AudioCurveCalculator::setWindowSize(newSize);
|
||||
reset();
|
||||
}
|
||||
|
||||
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 zeroThresh = powf(10.f, -8);
|
||||
|
||||
size_t count = 0;
|
||||
size_t nonZeroCount = 0;
|
||||
int count = 0;
|
||||
int nonZeroCount = 0;
|
||||
|
||||
const int sz = m_windowSize / 2;
|
||||
const int sz = m_lastPerceivedBin;
|
||||
|
||||
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 (mag[n] > zeroThresh) ++nonZeroCount;
|
||||
}
|
||||
@@ -71,18 +75,21 @@ PercussiveAudioCurve::processFloat(const float *R__ mag, size_t increment)
|
||||
}
|
||||
|
||||
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 zeroThresh = powf(10., -8);
|
||||
|
||||
size_t count = 0;
|
||||
size_t nonZeroCount = 0;
|
||||
int count = 0;
|
||||
int nonZeroCount = 0;
|
||||
|
||||
const int sz = m_windowSize / 2;
|
||||
const int sz = m_lastPerceivedBin;
|
||||
|
||||
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 (mag[n] > zeroThresh) ++nonZeroCount;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -23,17 +23,18 @@ namespace RubberBand
|
||||
class PercussiveAudioCurve : public AudioCurveCalculator
|
||||
{
|
||||
public:
|
||||
PercussiveAudioCurve(size_t sampleRate, size_t windowSize);
|
||||
PercussiveAudioCurve(Parameters parameters);
|
||||
|
||||
virtual ~PercussiveAudioCurve();
|
||||
|
||||
virtual void setWindowSize(size_t newSize);
|
||||
virtual void setWindowSize(int newSize);
|
||||
|
||||
virtual float processFloat(const float *R__ mag, size_t increment);
|
||||
virtual double processDouble(const double *R__ mag, size_t increment);
|
||||
virtual float processFloat(const float *R__ mag, int increment);
|
||||
virtual double processDouble(const double *R__ mag, int increment);
|
||||
|
||||
|
||||
virtual void reset();
|
||||
virtual const char *getUnit() const { return "bin/total"; }
|
||||
|
||||
protected:
|
||||
double *R__ m_prevMag;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -40,6 +40,12 @@ public:
|
||||
float ratio,
|
||||
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 void reset() = 0;
|
||||
@@ -62,6 +68,12 @@ public:
|
||||
float ratio,
|
||||
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; }
|
||||
|
||||
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_ioutsize = outcount * m_channels;
|
||||
}
|
||||
for (int i = 0; i < incount; ++i) {
|
||||
for (int c = 0; c < m_channels; ++c) {
|
||||
m_iin[i * m_channels + c] = in[c][i];
|
||||
}
|
||||
}
|
||||
v_interleave(m_iin, in, m_channels, incount);
|
||||
data.data_in = m_iin;
|
||||
data.data_out = m_iout;
|
||||
}
|
||||
@@ -168,11 +176,39 @@ D_SRC::resample(const float *const R__ *const R__ in,
|
||||
}
|
||||
|
||||
if (m_channels > 1) {
|
||||
for (int i = 0; i < data.output_frames_gen; ++i) {
|
||||
for (int c = 0; c < m_channels; ++c) {
|
||||
out[c][i] = m_iout[i * m_channels + c];
|
||||
}
|
||||
v_deinterleave(out, m_iout, m_channels, data.output_frames_gen);
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -252,6 +288,15 @@ Resampler::resample(const float *const R__ *const R__ in,
|
||||
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
|
||||
Resampler::getChannelCount() const
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -37,12 +37,29 @@ public:
|
||||
int debugLevel = 0);
|
||||
~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,
|
||||
float *const R__ *const R__ out,
|
||||
int incount,
|
||||
float ratio,
|
||||
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;
|
||||
|
||||
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
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -19,8 +19,9 @@
|
||||
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
|
||||
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);
|
||||
|
||||
for (int i = 0; i <= hs; ++i) {
|
||||
@@ -53,9 +48,9 @@ SilentAudioCurve::processFloat(const float *R__ mag, size_t)
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
for (int i = 0; i <= hs; ++i) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -23,14 +23,13 @@ namespace RubberBand
|
||||
class SilentAudioCurve : public AudioCurveCalculator
|
||||
{
|
||||
public:
|
||||
SilentAudioCurve(size_t sampleRate, size_t windowSize);
|
||||
SilentAudioCurve(Parameters parameters);
|
||||
virtual ~SilentAudioCurve();
|
||||
|
||||
virtual void setWindowSize(size_t newSize);
|
||||
|
||||
virtual float processFloat(const float *R__ mag, size_t increment);
|
||||
virtual double processDouble(const double *R__ mag, size_t increment);
|
||||
virtual float processFloat(const float *R__ mag, int increment);
|
||||
virtual double processDouble(const double *R__ mag, int increment);
|
||||
virtual void reset();
|
||||
virtual const char *getUnit() const { return "bool"; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -20,12 +20,13 @@
|
||||
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_tmpbuf = allocate<double>(m_windowSize/2 + 1);
|
||||
v_zero(m_mag, m_windowSize/2 + 1);
|
||||
m_mag = allocate<double>(m_lastPerceivedBin + 1);
|
||||
m_tmpbuf = allocate<double>(m_lastPerceivedBin + 1);
|
||||
v_zero(m_mag, m_lastPerceivedBin + 1);
|
||||
}
|
||||
|
||||
SpectralDifferenceAudioCurve::~SpectralDifferenceAudioCurve()
|
||||
@@ -37,26 +38,26 @@ SpectralDifferenceAudioCurve::~SpectralDifferenceAudioCurve()
|
||||
void
|
||||
SpectralDifferenceAudioCurve::reset()
|
||||
{
|
||||
v_zero(m_mag, m_windowSize/2 + 1);
|
||||
v_zero(m_mag, m_lastPerceivedBin + 1);
|
||||
}
|
||||
|
||||
void
|
||||
SpectralDifferenceAudioCurve::setWindowSize(size_t newSize)
|
||||
SpectralDifferenceAudioCurve::setWindowSize(int newSize)
|
||||
{
|
||||
deallocate(m_tmpbuf);
|
||||
deallocate(m_mag);
|
||||
m_windowSize = newSize;
|
||||
m_mag = allocate<double>(m_windowSize/2 + 1);
|
||||
m_tmpbuf = allocate<double>(m_windowSize/2 + 1);
|
||||
AudioCurveCalculator::setWindowSize(newSize);
|
||||
m_mag = allocate<double>(m_lastPerceivedBin + 1);
|
||||
m_tmpbuf = allocate<double>(m_lastPerceivedBin + 1);
|
||||
reset();
|
||||
}
|
||||
|
||||
float
|
||||
SpectralDifferenceAudioCurve::processFloat(const float *R__ mag, size_t increment)
|
||||
SpectralDifferenceAudioCurve::processFloat(const float *R__ mag, int increment)
|
||||
{
|
||||
double result = 0.0;
|
||||
|
||||
const int hs1 = m_windowSize/2 + 1;
|
||||
const int hs1 = m_lastPerceivedBin + 1;
|
||||
|
||||
v_convert(m_tmpbuf, mag, hs1);
|
||||
v_square(m_tmpbuf, hs1);
|
||||
@@ -73,11 +74,11 @@ SpectralDifferenceAudioCurve::processFloat(const float *R__ mag, size_t incremen
|
||||
}
|
||||
|
||||
double
|
||||
SpectralDifferenceAudioCurve::processDouble(const double *R__ mag, size_t increment)
|
||||
SpectralDifferenceAudioCurve::processDouble(const double *R__ mag, int increment)
|
||||
{
|
||||
double result = 0.0;
|
||||
|
||||
const int hs1 = m_windowSize/2 + 1;
|
||||
const int hs1 = m_lastPerceivedBin + 1;
|
||||
|
||||
v_convert(m_tmpbuf, mag, hs1);
|
||||
v_square(m_tmpbuf, hs1);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -24,15 +24,16 @@ namespace RubberBand
|
||||
class SpectralDifferenceAudioCurve : public AudioCurveCalculator
|
||||
{
|
||||
public:
|
||||
SpectralDifferenceAudioCurve(size_t sampleRate, size_t windowSize);
|
||||
SpectralDifferenceAudioCurve(Parameters parameters);
|
||||
|
||||
virtual ~SpectralDifferenceAudioCurve();
|
||||
|
||||
virtual void setWindowSize(size_t newSize);
|
||||
virtual void setWindowSize(int newSize);
|
||||
|
||||
virtual float processFloat(const float *R__ mag, size_t increment);
|
||||
virtual double processDouble(const double *R__ mag, size_t increment);
|
||||
virtual float processFloat(const float *R__ mag, int increment);
|
||||
virtual double processDouble(const double *R__ mag, int increment);
|
||||
virtual void reset();
|
||||
virtual const char *getUnit() const { return "V"; }
|
||||
|
||||
protected:
|
||||
double *R__ m_mag;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -153,7 +153,7 @@ void Window<T>::encache()
|
||||
m_cache = mult;
|
||||
|
||||
m_area = 0;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
for (i = 0; i < n; ++i) {
|
||||
m_area += m_cache[i];
|
||||
}
|
||||
m_area /= n;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
void rubberband_set_detector_option(RubberBandState state, RubberBandOptions options)
|
||||
{
|
||||
state->m_s->setDetectorOption(options);
|
||||
}
|
||||
|
||||
void rubberband_set_phase_option(RubberBandState state, RubberBandOptions 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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
state->m_s->study(input, samples, final != 0);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -134,13 +134,32 @@ T **reallocate_channels(T **ptr,
|
||||
try {
|
||||
newptr = allocate_channels<T>(channels, count);
|
||||
} catch (std::bad_alloc) {
|
||||
if (ptr) deallocate_channels<T>(ptr);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
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
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <stdio.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define MLOCK(a,b) ::mlock((char *)(a),(b))
|
||||
#define MUNLOCK(a,b) (::munlock((char *)(a),(b)) ? (::perror("munlock failed"), 0) : 0)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@@ -300,7 +300,7 @@ RubberBandVampPlugin::getParameterDescriptors() const
|
||||
d.isQuantized = true;
|
||||
d.quantizeStep = 1;
|
||||
d.valueNames.clear();
|
||||
d.valueNames.push_back("Peak Locked");
|
||||
d.valueNames.push_back("Laminar");
|
||||
d.valueNames.push_back("Independent");
|
||||
list.push_back(d);
|
||||
|
||||
@@ -405,8 +405,6 @@ RubberBandVampPlugin::initialise(size_t channels, size_t stepSize, size_t blockS
|
||||
void
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -455,9 +453,7 @@ RubberBandVampPlugin::Impl::getRemainingFeaturesOffline()
|
||||
|
||||
int rate = m_sampleRate;
|
||||
|
||||
RubberBand::StretchCalculator sc(rate,
|
||||
m_stretcher->getInputIncrement(),
|
||||
true);
|
||||
RubberBand::StretchCalculator sc(rate, m_stretcher->getInputIncrement(), true);
|
||||
|
||||
size_t inputIncrement = m_stretcher->getInputIncrement();
|
||||
std::vector<int> outputIncrements = m_stretcher->getOutputIncrements();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
Rubber Band
|
||||
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
|
||||
modify it under the terms of the GNU General Public License as
|
||||
|
||||
Reference in New Issue
Block a user