Remove elastic/loose processing support
This commit is contained in:
@@ -90,7 +90,7 @@ int main(int argc, char **argv)
|
|||||||
double frequencyshift = 1.0;
|
double frequencyshift = 1.0;
|
||||||
int debug = 0;
|
int debug = 0;
|
||||||
bool realtime = false;
|
bool realtime = false;
|
||||||
bool precise = true;
|
bool precisiongiven = false;
|
||||||
int threading = 0;
|
int threading = 0;
|
||||||
bool lamination = true;
|
bool lamination = true;
|
||||||
bool longwin = false;
|
bool longwin = false;
|
||||||
@@ -179,8 +179,8 @@ int main(int argc, char **argv)
|
|||||||
case 'f': frequencyshift = atof(optarg); haveRatio = true; break;
|
case 'f': frequencyshift = atof(optarg); haveRatio = true; break;
|
||||||
case 'd': debug = atoi(optarg); break;
|
case 'd': debug = atoi(optarg); break;
|
||||||
case 'R': realtime = true; break;
|
case 'R': realtime = true; break;
|
||||||
case 'L': precise = false; break;
|
case 'L': precisiongiven = true; break;
|
||||||
case 'P': precise = true; break;
|
case 'P': precisiongiven = true; break;
|
||||||
case 'F': formant = true; break;
|
case 'F': formant = true; break;
|
||||||
case '0': threading = 1; break;
|
case '0': threading = 1; break;
|
||||||
case '@': threading = 2; break;
|
case '@': threading = 2; break;
|
||||||
@@ -276,9 +276,10 @@ int main(int argc, char **argv)
|
|||||||
cerr << "crispness parameter are intended to provide the best sounding set of options" << endl;
|
cerr << "crispness parameter are intended to provide the best sounding set of options" << endl;
|
||||||
cerr << "for most situations. The default is to use none of these options." << endl;
|
cerr << "for most situations. The default is to use none of these options." << endl;
|
||||||
cerr << endl;
|
cerr << endl;
|
||||||
cerr << " -L, --loose Relax timing in hope of better transient preservation" << endl;
|
cerr << " -R, --realtime Select realtime mode (implies --no-threads)." << endl;
|
||||||
cerr << " -P, --precise Ignored: The opposite of -L, this is default from 1.6" << endl;
|
cerr << " This utility does not do realtime stream processing;" << endl;
|
||||||
cerr << " -R, --realtime Select realtime mode (implies --no-threads)" << endl;
|
cerr << " the option merely selects realtime mode for the" << endl;
|
||||||
|
cerr << " stretcher it uses" << endl;
|
||||||
cerr << " --no-threads No extra threads regardless of CPU and channel count" << endl;
|
cerr << " --no-threads No extra threads regardless of CPU and channel count" << endl;
|
||||||
cerr << " --threads Assume multi-CPU even if only one CPU is identified" << endl;
|
cerr << " --threads Assume multi-CPU even if only one CPU is identified" << endl;
|
||||||
cerr << " --no-transients Disable phase resynchronisation at transients" << endl;
|
cerr << " --no-transients Disable phase resynchronisation at transients" << endl;
|
||||||
@@ -294,6 +295,8 @@ int main(int argc, char **argv)
|
|||||||
cerr << " (at a cost in width and individual channel quality)" << endl;
|
cerr << " (at a cost in width and individual channel quality)" << endl;
|
||||||
cerr << " --ignore-clipping Ignore clipping at output; the default is to restart" << endl;
|
cerr << " --ignore-clipping Ignore clipping at output; the default is to restart" << endl;
|
||||||
cerr << " with reduced gain if clipping occurs" << endl;
|
cerr << " with reduced gain if clipping occurs" << endl;
|
||||||
|
cerr << " -L, --loose [Accepted for compatibility but ignored; always off]" << endl;
|
||||||
|
cerr << " -P, --precise [Accepted for compatibility but ignored; always on]" << endl;
|
||||||
cerr << endl;
|
cerr << endl;
|
||||||
cerr << " -d<N>, --debug <N> Select debug level (N = 0,1,2,3); default 0, full 3" << endl;
|
cerr << " -d<N>, --debug <N> Select debug level (N = 0,1,2,3); default 0, full 3" << endl;
|
||||||
cerr << " (N.B. debug level 3 includes audible ticks in output)" << endl;
|
cerr << " (N.B. debug level 3 includes audible ticks in output)" << endl;
|
||||||
@@ -330,6 +333,11 @@ int main(int argc, char **argv)
|
|||||||
hqpitch = false;
|
hqpitch = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (precisiongiven) {
|
||||||
|
cerr << "NOTE: The -L/--loose and -P/--precise options are both ignored -- precise" << endl;
|
||||||
|
cerr << " became the default in v1.6 and loose was removed in v3.0" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
switch (crispness) {
|
switch (crispness) {
|
||||||
case -1: crispness = 5; break;
|
case -1: crispness = 5; break;
|
||||||
case 0: detector = CompoundDetector; transients = NoTransients; lamination = false; longwin = true; shortwin = false; break;
|
case 0: detector = CompoundDetector; transients = NoTransients; lamination = false; longwin = true; shortwin = false; break;
|
||||||
@@ -493,7 +501,6 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
RubberBandStretcher::Options options = 0;
|
RubberBandStretcher::Options options = 0;
|
||||||
if (realtime) options |= RubberBandStretcher::OptionProcessRealTime;
|
if (realtime) options |= RubberBandStretcher::OptionProcessRealTime;
|
||||||
if (precise) options |= RubberBandStretcher::OptionStretchPrecise;
|
|
||||||
if (!lamination) options |= RubberBandStretcher::OptionPhaseIndependent;
|
if (!lamination) options |= RubberBandStretcher::OptionPhaseIndependent;
|
||||||
if (longwin) options |= RubberBandStretcher::OptionWindowLong;
|
if (longwin) options |= RubberBandStretcher::OptionWindowLong;
|
||||||
if (shortwin) options |= RubberBandStretcher::OptionWindowShort;
|
if (shortwin) options |= RubberBandStretcher::OptionWindowShort;
|
||||||
|
|||||||
@@ -38,10 +38,8 @@ library_sources = [
|
|||||||
'src/base/Profiler.cpp',
|
'src/base/Profiler.cpp',
|
||||||
'src/dsp/AudioCurveCalculator.cpp',
|
'src/dsp/AudioCurveCalculator.cpp',
|
||||||
'src/audiocurves/CompoundAudioCurve.cpp',
|
'src/audiocurves/CompoundAudioCurve.cpp',
|
||||||
'src/audiocurves/SpectralDifferenceAudioCurve.cpp',
|
|
||||||
'src/audiocurves/HighFrequencyAudioCurve.cpp',
|
'src/audiocurves/HighFrequencyAudioCurve.cpp',
|
||||||
'src/audiocurves/SilentAudioCurve.cpp',
|
'src/audiocurves/SilentAudioCurve.cpp',
|
||||||
'src/audiocurves/ConstantAudioCurve.cpp',
|
|
||||||
'src/audiocurves/PercussiveAudioCurve.cpp',
|
'src/audiocurves/PercussiveAudioCurve.cpp',
|
||||||
'src/dsp/Resampler.cpp',
|
'src/dsp/Resampler.cpp',
|
||||||
'src/dsp/FFT.cpp',
|
'src/dsp/FFT.cpp',
|
||||||
|
|||||||
@@ -109,27 +109,6 @@ public:
|
|||||||
* non-real-time operation on seekable files: Offline; real-time
|
* non-real-time operation on seekable files: Offline; real-time
|
||||||
* or streaming operation: RealTime.
|
* or streaming operation: RealTime.
|
||||||
*
|
*
|
||||||
* 2. Flags prefixed \c OptionStretch control the profile used for
|
|
||||||
* variable timestretching. Rubber Band always adjusts the
|
|
||||||
* stretch profile to minimise stretching of busy broadband
|
|
||||||
* transient sounds, but the degree to which it does so is
|
|
||||||
* adjustable. These options may not be changed after
|
|
||||||
* construction.
|
|
||||||
*
|
|
||||||
* \li \c OptionStretchElastic - Only meaningful in offline
|
|
||||||
* mode, and the default in that mode. The audio will be
|
|
||||||
* stretched at a variable rate, aimed at preserving the quality
|
|
||||||
* of transient sounds as much as possible. The timings of low
|
|
||||||
* activity regions between transients may be less exact than
|
|
||||||
* when the precise flag is set.
|
|
||||||
*
|
|
||||||
* \li \c OptionStretchPrecise - Although still using a variable
|
|
||||||
* stretch rate, the audio will be stretched so as to maintain
|
|
||||||
* as close as possible to a linear stretch ratio throughout.
|
|
||||||
* Timing may be better than when using \c OptionStretchElastic, at
|
|
||||||
* slight cost to the sound quality of transients. This setting
|
|
||||||
* is always used when running in real-time mode.
|
|
||||||
*
|
|
||||||
* 3. Flags prefixed \c OptionTransients control the component
|
* 3. Flags prefixed \c OptionTransients control the component
|
||||||
* frequency phase-reset mechanism that may be used at transient
|
* frequency phase-reset mechanism that may be used at transient
|
||||||
* points to provide clarity and realism to percussion and other
|
* points to provide clarity and realism to percussion and other
|
||||||
@@ -293,6 +272,10 @@ public:
|
|||||||
* setting). This usually leads to better focus in the centre
|
* setting). This usually leads to better focus in the centre
|
||||||
* but a loss of stereo space and width. Any channels beyond
|
* but a loss of stereo space and width. Any channels beyond
|
||||||
* the first two are processed individually.
|
* the first two are processed individually.
|
||||||
|
*
|
||||||
|
* Finally, flags prefixed \c OptionStretch are obsolete flags
|
||||||
|
* provided for backward compatibility only. They are ignored by
|
||||||
|
* the stretcher.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum Option {
|
enum Option {
|
||||||
@@ -300,8 +283,8 @@ public:
|
|||||||
OptionProcessOffline = 0x00000000,
|
OptionProcessOffline = 0x00000000,
|
||||||
OptionProcessRealTime = 0x00000001,
|
OptionProcessRealTime = 0x00000001,
|
||||||
|
|
||||||
OptionStretchElastic = 0x00000000,
|
OptionStretchElastic = 0x00000000, // obsolete
|
||||||
OptionStretchPrecise = 0x00000010,
|
OptionStretchPrecise = 0x00000010, // obsolete
|
||||||
|
|
||||||
OptionTransientsCrisp = 0x00000000,
|
OptionTransientsCrisp = 0x00000000,
|
||||||
OptionTransientsMixed = 0x00000100,
|
OptionTransientsMixed = 0x00000100,
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ enum RubberBandOption {
|
|||||||
RubberBandOptionProcessOffline = 0x00000000,
|
RubberBandOptionProcessOffline = 0x00000000,
|
||||||
RubberBandOptionProcessRealTime = 0x00000001,
|
RubberBandOptionProcessRealTime = 0x00000001,
|
||||||
|
|
||||||
RubberBandOptionStretchElastic = 0x00000000,
|
RubberBandOptionStretchElastic = 0x00000000, // obsolete
|
||||||
RubberBandOptionStretchPrecise = 0x00000010,
|
RubberBandOptionStretchPrecise = 0x00000010, // obsolete
|
||||||
|
|
||||||
RubberBandOptionTransientsCrisp = 0x00000000,
|
RubberBandOptionTransientsCrisp = 0x00000000,
|
||||||
RubberBandOptionTransientsMixed = 0x00000100,
|
RubberBandOptionTransientsMixed = 0x00000100,
|
||||||
|
|||||||
@@ -74,11 +74,8 @@ StretchCalculator::setKeyFrameMap(const std::map<size_t, size_t> &mapping)
|
|||||||
|
|
||||||
std::vector<int>
|
std::vector<int>
|
||||||
StretchCalculator::calculate(double ratio, size_t inputDuration,
|
StretchCalculator::calculate(double ratio, size_t inputDuration,
|
||||||
const std::vector<float> &phaseResetDf,
|
const std::vector<float> &phaseResetDf)
|
||||||
const std::vector<float> &stretchDf)
|
|
||||||
{
|
{
|
||||||
assert(phaseResetDf.size() == stretchDf.size());
|
|
||||||
|
|
||||||
m_peaks = findPeaks(phaseResetDf);
|
m_peaks = findPeaks(phaseResetDf);
|
||||||
|
|
||||||
size_t totalCount = phaseResetDf.size();
|
size_t totalCount = phaseResetDf.size();
|
||||||
@@ -107,16 +104,6 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
|||||||
|
|
||||||
size_t totalInput = 0, totalOutput = 0;
|
size_t totalInput = 0, totalOutput = 0;
|
||||||
|
|
||||||
// For each region between two consecutive time sync points, we
|
|
||||||
// want to take the number of output chunks to be allocated and
|
|
||||||
// the detection function values within the range, and produce a
|
|
||||||
// series of increments that sum to the number of output chunks,
|
|
||||||
// such that each increment is displaced from the input increment
|
|
||||||
// by an amount inversely proportional to the magnitude of the
|
|
||||||
// stretch detection function at that input step.
|
|
||||||
|
|
||||||
size_t regionTotalChunks = 0;
|
|
||||||
|
|
||||||
std::vector<int> increments;
|
std::vector<int> increments;
|
||||||
|
|
||||||
for (size_t i = 0; i <= peaks.size(); ++i) {
|
for (size_t i = 0; i <= peaks.size(); ++i) {
|
||||||
@@ -141,47 +128,61 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
|||||||
regionEndChunk = peaks[i].chunk;
|
regionEndChunk = peaks[i].chunk;
|
||||||
regionEnd = targets[i];
|
regionEnd = targets[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (regionStartChunk > totalCount) regionStartChunk = totalCount;
|
if (regionStartChunk > totalCount) regionStartChunk = totalCount;
|
||||||
if (regionStart > outputDuration) regionStart = outputDuration;
|
if (regionStart > outputDuration) regionStart = outputDuration;
|
||||||
if (regionEndChunk > totalCount) regionEndChunk = totalCount;
|
if (regionEndChunk > totalCount) regionEndChunk = totalCount;
|
||||||
if (regionEnd > outputDuration) regionEnd = outputDuration;
|
if (regionEnd > outputDuration) regionEnd = outputDuration;
|
||||||
|
|
||||||
|
if (regionEndChunk < regionStartChunk) regionEndChunk = regionStartChunk;
|
||||||
|
if (regionEnd < regionStart) regionEnd = regionStart;
|
||||||
|
|
||||||
size_t regionDuration = regionEnd - regionStart;
|
size_t regionDuration = regionEnd - regionStart;
|
||||||
regionTotalChunks += regionDuration;
|
|
||||||
|
|
||||||
std::vector<float> dfRegion;
|
size_t nchunks = regionEndChunk - regionStartChunk;
|
||||||
|
|
||||||
for (size_t j = regionStartChunk; j != regionEndChunk; ++j) {
|
if (nchunks == 0) {
|
||||||
dfRegion.push_back(stretchDf[j]);
|
//!!!
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_debugLevel > 1) {
|
double per = double(regionDuration) / double(nchunks);
|
||||||
std::cerr << "distributeRegion from " << regionStartChunk << " to " << regionEndChunk << " (samples " << regionStart << " to " << regionEnd << ")" << std::endl;
|
double acc = 0.0;
|
||||||
}
|
size_t nremaining = nchunks;
|
||||||
|
|
||||||
dfRegion = smoothDF(dfRegion);
|
|
||||||
|
|
||||||
std::vector<int> regionIncrements = distributeRegion
|
|
||||||
(dfRegion, regionDuration, ratio, phaseReset);
|
|
||||||
|
|
||||||
size_t totalForRegion = 0;
|
size_t totalForRegion = 0;
|
||||||
|
|
||||||
for (size_t j = 0; j < regionIncrements.size(); ++j) {
|
if (phaseReset) {
|
||||||
|
size_t incr;
|
||||||
int incr = regionIncrements[j];
|
if (nchunks > 1) {
|
||||||
|
incr = m_increment;
|
||||||
if (j == 0 && phaseReset) increments.push_back(-incr);
|
if (incr > regionDuration) {
|
||||||
else increments.push_back(incr);
|
incr = regionDuration;
|
||||||
|
}
|
||||||
if (incr > 0) totalForRegion += incr;
|
} else {
|
||||||
else totalForRegion += -incr;
|
incr = regionDuration;
|
||||||
|
}
|
||||||
|
increments.push_back(- int64_t(incr));
|
||||||
|
per = double(regionDuration - incr) / double(nchunks - 1);
|
||||||
|
acc += incr;
|
||||||
|
totalForRegion += incr;
|
||||||
totalInput += m_increment;
|
totalInput += m_increment;
|
||||||
|
nremaining = nremaining - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalForRegion != regionDuration) {
|
if (nremaining > 0) {
|
||||||
std::cerr << "*** ERROR: distributeRegion returned wrong duration " << totalForRegion << ", expected " << regionDuration << std::endl;
|
for (size_t j = 0; j+1 < nremaining; ++j) {
|
||||||
|
acc += per;
|
||||||
|
size_t incr = size_t(round(acc - totalForRegion));
|
||||||
|
increments.push_back(incr);
|
||||||
|
totalForRegion += incr;
|
||||||
|
totalInput += m_increment;
|
||||||
|
}
|
||||||
|
if (regionDuration > totalForRegion) {
|
||||||
|
size_t final = regionDuration - totalForRegion;
|
||||||
|
increments.push_back(final);
|
||||||
|
totalForRegion += final;
|
||||||
|
totalInput += m_increment;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
totalOutput += totalForRegion;
|
totalOutput += totalForRegion;
|
||||||
@@ -189,7 +190,6 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
|||||||
|
|
||||||
if (m_debugLevel > 0) {
|
if (m_debugLevel > 0) {
|
||||||
std::cerr << "total input increment = " << totalInput << " (= " << totalInput / m_increment << " chunks), output = " << totalOutput << ", ratio = " << double(totalOutput)/double(totalInput) << ", ideal output " << size_t(ceil(totalInput * ratio)) << std::endl;
|
std::cerr << "total input increment = " << totalInput << " (= " << totalInput / m_increment << " chunks), output = " << totalOutput << ", ratio = " << double(totalOutput)/double(totalInput) << ", ideal output " << size_t(ceil(totalInput * ratio)) << std::endl;
|
||||||
std::cerr << "(region total = " << regionTotalChunks << ")" << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return increments;
|
return increments;
|
||||||
@@ -861,285 +861,5 @@ StretchCalculator::smoothDF(const std::vector<float> &df)
|
|||||||
return smoothedDF;
|
return smoothedDF;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int>
|
|
||||||
StretchCalculator::distributeRegion(const std::vector<float> &dfIn,
|
|
||||||
size_t duration, float ratio, bool phaseReset)
|
|
||||||
{
|
|
||||||
std::vector<float> df(dfIn);
|
|
||||||
std::vector<int> increments;
|
|
||||||
|
|
||||||
// The peak for the stretch detection function may appear after
|
|
||||||
// the peak that we're using to calculate the start of the region.
|
|
||||||
// We don't want that. If we find a peak in the first half of
|
|
||||||
// the region, we should set all the values up to that point to
|
|
||||||
// the same value as the peak.
|
|
||||||
|
|
||||||
// (This might not be subtle enough, especially if the region is
|
|
||||||
// long -- we want a bound that corresponds to acoustic perception
|
|
||||||
// of the audible bounce.)
|
|
||||||
|
|
||||||
for (size_t i = 1; i < df.size()/2; ++i) {
|
|
||||||
if (df[i] < df[i-1]) {
|
|
||||||
if (m_debugLevel > 1) {
|
|
||||||
std::cerr << "stretch peak offset: " << i-1 << " (peak " << df[i-1] << ")" << std::endl;
|
|
||||||
}
|
|
||||||
for (size_t j = 0; j < i-1; ++j) {
|
|
||||||
df[j] = df[i-1];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float maxDf = 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < df.size(); ++i) {
|
|
||||||
if (i == 0 || df[i] > maxDf) maxDf = df[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// We want to try to ensure the last 100ms or so (if possible) are
|
|
||||||
// tending back towards the maximum df, so that the stretchiness
|
|
||||||
// reduces at the end of the stretched region.
|
|
||||||
|
|
||||||
int reducedRegion = lrint((0.1 * m_sampleRate) / m_increment);
|
|
||||||
if (reducedRegion > int(df.size()/5)) reducedRegion = df.size()/5;
|
|
||||||
|
|
||||||
for (int i = 0; i < reducedRegion; ++i) {
|
|
||||||
size_t index = df.size() - reducedRegion + i;
|
|
||||||
df[index] = df[index] + ((maxDf - df[index]) * i) / reducedRegion;
|
|
||||||
}
|
|
||||||
|
|
||||||
long toAllot = long(duration) - long(m_increment * df.size());
|
|
||||||
|
|
||||||
if (m_debugLevel > 1) {
|
|
||||||
std::cerr << "region of " << df.size() << " chunks, output duration " << duration << ", increment " << m_increment << ", toAllot " << toAllot << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t totalIncrement = 0;
|
|
||||||
|
|
||||||
// We place limits on the amount of displacement per chunk. if
|
|
||||||
// ratio < 0, no increment should be larger than increment*ratio
|
|
||||||
// or smaller than increment*ratio/2; if ratio > 0, none should be
|
|
||||||
// smaller than increment*ratio or larger than increment*ratio*2.
|
|
||||||
// We need to enforce this in the assignment of displacements to
|
|
||||||
// allotments, not by trying to respond if something turns out
|
|
||||||
// wrong.
|
|
||||||
|
|
||||||
// Note that the ratio is only provided to this function for the
|
|
||||||
// purposes of establishing this bound to the displacement.
|
|
||||||
|
|
||||||
// so if
|
|
||||||
// maxDisplacement / totalDisplacement > increment * ratio*2 - increment
|
|
||||||
// (for ratio > 1)
|
|
||||||
// or
|
|
||||||
// maxDisplacement / totalDisplacement < increment * ratio/2
|
|
||||||
// (for ratio < 1)
|
|
||||||
|
|
||||||
// then we need to adjust and accommodate
|
|
||||||
|
|
||||||
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 ((tooLong || tooShort) && iteration < acceptableIterations) {
|
|
||||||
|
|
||||||
++iteration;
|
|
||||||
|
|
||||||
tooLong = false;
|
|
||||||
tooShort = false;
|
|
||||||
calculateDisplacements(df, maxDf, totalDisplacement, maxDisplacement,
|
|
||||||
adj);
|
|
||||||
|
|
||||||
if (m_debugLevel > 1) {
|
|
||||||
std::cerr << "totalDisplacement " << totalDisplacement << ", max " << maxDisplacement << " (maxDf " << maxDf << ", df count " << df.size() << ")" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (totalDisplacement == 0) {
|
|
||||||
// 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) {
|
|
||||||
tooLong = true; tooShort = true;
|
|
||||||
adj = 1;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
} else if (extremeIncrement < (m_increment * ratio) / 2) {
|
|
||||||
if (m_debugLevel > 0) {
|
|
||||||
std::cerr << "NOTE: extreme increment "
|
|
||||||
<< extremeIncrement << " < "
|
|
||||||
<< (m_increment * ratio) / 2
|
|
||||||
<< ", adjusting" << std::endl;
|
|
||||||
}
|
|
||||||
tooShort = true;
|
|
||||||
if (iteration > 0) {
|
|
||||||
better = (extremeIncrement > prevExtreme);
|
|
||||||
}
|
|
||||||
prevExtreme = extremeIncrement;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (extremeIncrement > m_increment * ratio * 2) {
|
|
||||||
if (m_debugLevel > 0) {
|
|
||||||
std::cerr << "NOTE: extreme increment "
|
|
||||||
<< extremeIncrement << " > "
|
|
||||||
<< m_increment * ratio * 2
|
|
||||||
<< ", adjusting" << std::endl;
|
|
||||||
}
|
|
||||||
tooLong = true;
|
|
||||||
if (iteration > 0) {
|
|
||||||
better = (extremeIncrement < prevExtreme);
|
|
||||||
}
|
|
||||||
prevExtreme = extremeIncrement;
|
|
||||||
} else if (extremeIncrement < lrint(floor(m_increment * ratio))) {
|
|
||||||
std::cerr << "WARNING: extreme increment "
|
|
||||||
<< extremeIncrement << " < "
|
|
||||||
<< m_increment * ratio << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
|
||||||
adj += maxDf/10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < df.size(); ++i) {
|
|
||||||
|
|
||||||
double displacement = maxDf - df[i];
|
|
||||||
if (displacement < 0) displacement -= adj;
|
|
||||||
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;
|
|
||||||
} else {
|
|
||||||
increments.push_back(m_increment);
|
|
||||||
totalIncrement += m_increment;
|
|
||||||
}
|
|
||||||
totalDisplacement -= displacement;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
double theoreticalAllotment = 0;
|
|
||||||
|
|
||||||
if (totalDisplacement != 0) {
|
|
||||||
theoreticalAllotment = (toAllot * displacement) / totalDisplacement;
|
|
||||||
}
|
|
||||||
int allotment = lrint(theoreticalAllotment);
|
|
||||||
if (i + 1 == df.size()) allotment = toAllot;
|
|
||||||
|
|
||||||
int increment = m_increment + allotment;
|
|
||||||
|
|
||||||
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 (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;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
toAllot -= allotment;
|
|
||||||
}
|
|
||||||
|
|
||||||
increments.push_back(increment);
|
|
||||||
totalIncrement += increment;
|
|
||||||
|
|
||||||
totalDisplacement -= displacement;
|
|
||||||
|
|
||||||
if (m_debugLevel > 2) {
|
|
||||||
std::cerr << "df " << df[i] << ", smoothed " << df[i] << ", disp " << displacement << ", allot " << theoreticalAllotment << ", incr " << increment << ", remain " << toAllot << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_debugLevel > 2) {
|
|
||||||
std::cerr << "total increment: " << totalIncrement << ", left over: " << toAllot << " to allot, displacement " << totalDisplacement << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (totalIncrement != duration) {
|
|
||||||
std::cerr << "*** WARNING: calculated output duration " << totalIncrement << " != expected " << duration << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return increments;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
StretchCalculator::calculateDisplacements(const std::vector<float> &df,
|
|
||||||
float &maxDf,
|
|
||||||
double &totalDisplacement,
|
|
||||||
double &maxDisplacement,
|
|
||||||
float adj) const
|
|
||||||
{
|
|
||||||
totalDisplacement = maxDisplacement = 0;
|
|
||||||
|
|
||||||
maxDf = 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < df.size(); ++i) {
|
|
||||||
if (i == 0 || df[i] > maxDf) maxDf = df[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < df.size(); ++i) {
|
|
||||||
double displacement = maxDf - df[i];
|
|
||||||
if (displacement < 0) displacement -= adj;
|
|
||||||
else displacement += adj;
|
|
||||||
totalDisplacement += displacement;
|
|
||||||
if (i == 0 || displacement > maxDisplacement) {
|
|
||||||
maxDisplacement = displacement;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,13 +51,10 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Calculate phase increments for a region of audio, given the
|
* Calculate phase increments for a region of audio, given the
|
||||||
* overall target stretch ratio, input duration in audio samples,
|
* overall target stretch ratio, input duration in audio samples,
|
||||||
* and the audio curves to use for identifying phase lock points
|
* and the audio curves to use for identifying phase lock points.
|
||||||
* (lockAudioCurve) and for allocating stretches to relatively
|
|
||||||
* less prominent points (stretchAudioCurve).
|
|
||||||
*/
|
*/
|
||||||
std::vector<int> calculate(double ratio, size_t inputDuration,
|
std::vector<int> calculate(double ratio, size_t inputDuration,
|
||||||
const std::vector<float> &lockAudioCurve,
|
const std::vector<float> &lockAudioCurve);
|
||||||
const std::vector<float> &stretchAudioCurve);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the phase increment for a single audio block, given
|
* Calculate the phase increment for a single audio block, given
|
||||||
@@ -96,16 +93,6 @@ protected:
|
|||||||
void mapPeaks(std::vector<Peak> &peaks, std::vector<size_t> &targets,
|
void mapPeaks(std::vector<Peak> &peaks, std::vector<size_t> &targets,
|
||||||
size_t outputDuration, size_t totalCount);
|
size_t outputDuration, size_t totalCount);
|
||||||
|
|
||||||
std::vector<int> distributeRegion(const std::vector<float> ®ionCurve,
|
|
||||||
size_t outputDuration, float ratio,
|
|
||||||
bool phaseReset);
|
|
||||||
|
|
||||||
void calculateDisplacements(const std::vector<float> &df,
|
|
||||||
float &maxDf,
|
|
||||||
double &totalDisplacement,
|
|
||||||
double &maxDisplacement,
|
|
||||||
float adj) const;
|
|
||||||
|
|
||||||
size_t m_sampleRate;
|
size_t m_sampleRate;
|
||||||
size_t m_increment;
|
size_t m_increment;
|
||||||
float m_prevDf;
|
float m_prevDf;
|
||||||
|
|||||||
@@ -25,9 +25,7 @@
|
|||||||
|
|
||||||
#include "audiocurves/PercussiveAudioCurve.h"
|
#include "audiocurves/PercussiveAudioCurve.h"
|
||||||
#include "audiocurves/HighFrequencyAudioCurve.h"
|
#include "audiocurves/HighFrequencyAudioCurve.h"
|
||||||
#include "audiocurves/SpectralDifferenceAudioCurve.h"
|
|
||||||
#include "audiocurves/SilentAudioCurve.h"
|
#include "audiocurves/SilentAudioCurve.h"
|
||||||
#include "audiocurves/ConstantAudioCurve.h"
|
|
||||||
#include "audiocurves/CompoundAudioCurve.h"
|
#include "audiocurves/CompoundAudioCurve.h"
|
||||||
|
|
||||||
#include "dsp/Resampler.h"
|
#include "dsp/Resampler.h"
|
||||||
@@ -105,7 +103,6 @@ RubberBandStretcher::Impl::Impl(size_t sampleRate,
|
|||||||
m_lastProcessPhaseResetDf(16),
|
m_lastProcessPhaseResetDf(16),
|
||||||
m_emergencyScavenger(10, 4),
|
m_emergencyScavenger(10, 4),
|
||||||
m_phaseResetAudioCurve(0),
|
m_phaseResetAudioCurve(0),
|
||||||
m_stretchAudioCurve(0),
|
|
||||||
m_silentAudioCurve(0),
|
m_silentAudioCurve(0),
|
||||||
m_stretchCalculator(0),
|
m_stretchCalculator(0),
|
||||||
m_freq0(600),
|
m_freq0(600),
|
||||||
@@ -150,12 +147,7 @@ RubberBandStretcher::Impl::Impl(size_t sampleRate,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_options & OptionProcessRealTime) {
|
if (m_options & OptionProcessRealTime) {
|
||||||
|
|
||||||
m_realtime = true;
|
m_realtime = true;
|
||||||
|
|
||||||
if (!(m_options & OptionStretchPrecise)) {
|
|
||||||
m_options |= OptionStretchPrecise;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_THREADING
|
#ifndef NO_THREADING
|
||||||
@@ -203,7 +195,6 @@ RubberBandStretcher::Impl::~Impl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
delete m_phaseResetAudioCurve;
|
delete m_phaseResetAudioCurve;
|
||||||
delete m_stretchAudioCurve;
|
|
||||||
delete m_silentAudioCurve;
|
delete m_silentAudioCurve;
|
||||||
delete m_stretchCalculator;
|
delete m_stretchCalculator;
|
||||||
delete m_studyFFT;
|
delete m_studyFFT;
|
||||||
@@ -249,7 +240,6 @@ RubberBandStretcher::Impl::reset()
|
|||||||
|
|
||||||
m_mode = JustCreated;
|
m_mode = JustCreated;
|
||||||
if (m_phaseResetAudioCurve) m_phaseResetAudioCurve->reset();
|
if (m_phaseResetAudioCurve) m_phaseResetAudioCurve->reset();
|
||||||
if (m_stretchAudioCurve) m_stretchAudioCurve->reset();
|
|
||||||
if (m_silentAudioCurve) m_silentAudioCurve->reset();
|
if (m_silentAudioCurve) m_silentAudioCurve->reset();
|
||||||
m_inputDuration = 0;
|
m_inputDuration = 0;
|
||||||
m_silentHistory = 0;
|
m_silentHistory = 0;
|
||||||
@@ -701,10 +691,6 @@ RubberBandStretcher::Impl::configure()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// stretchAudioCurve is unused in RT mode; phaseResetAudioCurve,
|
|
||||||
// silentAudioCurve and stretchCalculator however are used in all
|
|
||||||
// modes
|
|
||||||
|
|
||||||
delete m_phaseResetAudioCurve;
|
delete m_phaseResetAudioCurve;
|
||||||
m_phaseResetAudioCurve = new CompoundAudioCurve
|
m_phaseResetAudioCurve = new CompoundAudioCurve
|
||||||
(CompoundAudioCurve::Parameters(m_sampleRate, m_fftSize));
|
(CompoundAudioCurve::Parameters(m_sampleRate, m_fftSize));
|
||||||
@@ -714,17 +700,6 @@ RubberBandStretcher::Impl::configure()
|
|||||||
m_silentAudioCurve = new SilentAudioCurve
|
m_silentAudioCurve = new SilentAudioCurve
|
||||||
(SilentAudioCurve::Parameters(m_sampleRate, m_fftSize));
|
(SilentAudioCurve::Parameters(m_sampleRate, m_fftSize));
|
||||||
|
|
||||||
if (!m_realtime) {
|
|
||||||
delete m_stretchAudioCurve;
|
|
||||||
if (!(m_options & OptionStretchPrecise)) {
|
|
||||||
m_stretchAudioCurve = new SpectralDifferenceAudioCurve
|
|
||||||
(SpectralDifferenceAudioCurve::Parameters(m_sampleRate, m_fftSize));
|
|
||||||
} else {
|
|
||||||
m_stretchAudioCurve = new ConstantAudioCurve
|
|
||||||
(ConstantAudioCurve::Parameters(m_sampleRate, m_fftSize));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delete m_stretchCalculator;
|
delete m_stretchCalculator;
|
||||||
m_stretchCalculator = new StretchCalculator
|
m_stretchCalculator = new StretchCalculator
|
||||||
(m_sampleRate, m_increment,
|
(m_sampleRate, m_increment,
|
||||||
@@ -765,7 +740,6 @@ RubberBandStretcher::Impl::reconfigure()
|
|||||||
// the df vectors
|
// the df vectors
|
||||||
calculateStretch();
|
calculateStretch();
|
||||||
m_phaseResetDf.clear();
|
m_phaseResetDf.clear();
|
||||||
m_stretchDf.clear();
|
|
||||||
m_silence.clear();
|
m_silence.clear();
|
||||||
m_inputDuration = 0;
|
m_inputDuration = 0;
|
||||||
}
|
}
|
||||||
@@ -854,9 +828,6 @@ RubberBandStretcher::Impl::reconfigure()
|
|||||||
if (m_fftSize != prevFftSize) {
|
if (m_fftSize != prevFftSize) {
|
||||||
m_phaseResetAudioCurve->setFftSize(m_fftSize);
|
m_phaseResetAudioCurve->setFftSize(m_fftSize);
|
||||||
m_silentAudioCurve->setFftSize(m_fftSize);
|
m_silentAudioCurve->setFftSize(m_fftSize);
|
||||||
if (m_stretchAudioCurve) {
|
|
||||||
m_stretchAudioCurve->setFftSize(m_fftSize);
|
|
||||||
}
|
|
||||||
somethingChanged = true;
|
somethingChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1069,9 +1040,6 @@ RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool
|
|||||||
|
|
||||||
// cout << m_phaseResetDf.size() << " [" << final << "] -> " << df << " \t: ";
|
// cout << m_phaseResetDf.size() << " [" << final << "] -> " << df << " \t: ";
|
||||||
|
|
||||||
df = m_stretchAudioCurve->processFloat(cd.fltbuf, m_increment);
|
|
||||||
m_stretchDf.push_back(df);
|
|
||||||
|
|
||||||
df = m_silentAudioCurve->processFloat(cd.fltbuf, m_increment);
|
df = m_silentAudioCurve->processFloat(cd.fltbuf, m_increment);
|
||||||
bool silent = (df > 0.f);
|
bool silent = (df > 0.f);
|
||||||
if (silent && m_debugLevel > 1) {
|
if (silent && m_debugLevel > 1) {
|
||||||
@@ -1163,28 +1131,10 @@ RubberBandStretcher::Impl::calculateStretch()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
double prdm = 0, sdm = 0;
|
|
||||||
if (!m_phaseResetDf.empty()) {
|
|
||||||
for (int i = 0; i < (int)m_phaseResetDf.size(); ++i) {
|
|
||||||
prdm += m_phaseResetDf[i];
|
|
||||||
}
|
|
||||||
prdm /= m_phaseResetDf.size();
|
|
||||||
}
|
|
||||||
if (!m_stretchDf.empty()) {
|
|
||||||
for (int i = 0; i < (int)m_stretchDf.size(); ++i) {
|
|
||||||
sdm += m_stretchDf[i];
|
|
||||||
}
|
|
||||||
sdm /= m_stretchDf.size();
|
|
||||||
}
|
|
||||||
std::cerr << "phase reset df mean = " << prdm << ", stretch df mean = " << sdm << std::endl;
|
|
||||||
*/
|
|
||||||
|
|
||||||
std::vector<int> increments = m_stretchCalculator->calculate
|
std::vector<int> increments = m_stretchCalculator->calculate
|
||||||
(getEffectiveRatio(),
|
(getEffectiveRatio(),
|
||||||
inputDuration,
|
inputDuration,
|
||||||
m_phaseResetDf,
|
m_phaseResetDf);
|
||||||
m_stretchDf);
|
|
||||||
|
|
||||||
int history = 0;
|
int history = 0;
|
||||||
for (size_t i = 0; i < increments.size(); ++i) {
|
for (size_t i = 0; i < increments.size(); ++i) {
|
||||||
|
|||||||
@@ -220,19 +220,19 @@ protected:
|
|||||||
mutable Mutex m_threadSetMutex;
|
mutable Mutex m_threadSetMutex;
|
||||||
typedef std::set<ProcessThread *> ThreadSet;
|
typedef std::set<ProcessThread *> ThreadSet;
|
||||||
ThreadSet m_threadSet;
|
ThreadSet m_threadSet;
|
||||||
|
|
||||||
#if defined HAVE_IPP && !defined USE_SPEEX
|
#if defined(HAVE_IPP) && !defined(NO_THREADING) && !defined(USE_BQRESAMPLER) && !defined(USE_SPEEX) && !defined(HAVE_LIBSAMPLERATE)
|
||||||
// Exasperatingly, the IPP polyphase resampler does not appear to
|
// Exasperatingly, the IPP polyphase resampler does not appear to
|
||||||
// be thread-safe as advertised -- a good reason to prefer the
|
// be thread-safe as advertised -- a good reason to prefer any of
|
||||||
// Speex alternative
|
// the alternatives
|
||||||
|
#define STRETCHER_IMPL_RESAMPLER_MUTEX_REQUIRED 1
|
||||||
Mutex m_resamplerMutex;
|
Mutex m_resamplerMutex;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif // ! NO_THREADING
|
||||||
|
|
||||||
size_t m_inputDuration;
|
size_t m_inputDuration;
|
||||||
CompoundAudioCurve::Type m_detectorType;
|
CompoundAudioCurve::Type m_detectorType;
|
||||||
std::vector<float> m_phaseResetDf;
|
std::vector<float> m_phaseResetDf;
|
||||||
std::vector<float> m_stretchDf;
|
|
||||||
std::vector<bool> m_silence;
|
std::vector<bool> m_silence;
|
||||||
int m_silentHistory;
|
int m_silentHistory;
|
||||||
|
|
||||||
@@ -246,7 +246,6 @@ protected:
|
|||||||
Scavenger<RingBuffer<float> > m_emergencyScavenger;
|
Scavenger<RingBuffer<float> > m_emergencyScavenger;
|
||||||
|
|
||||||
CompoundAudioCurve *m_phaseResetAudioCurve;
|
CompoundAudioCurve *m_phaseResetAudioCurve;
|
||||||
AudioCurveCalculator *m_stretchAudioCurve;
|
|
||||||
AudioCurveCalculator *m_silentAudioCurve;
|
AudioCurveCalculator *m_silentAudioCurve;
|
||||||
StretchCalculator *m_stretchCalculator;
|
StretchCalculator *m_stretchCalculator;
|
||||||
|
|
||||||
|
|||||||
@@ -22,11 +22,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "StretcherImpl.h"
|
#include "StretcherImpl.h"
|
||||||
|
|
||||||
#include "audiocurves/PercussiveAudioCurve.h"
|
|
||||||
#include "audiocurves/HighFrequencyAudioCurve.h"
|
|
||||||
#include "audiocurves/ConstantAudioCurve.h"
|
|
||||||
|
|
||||||
#include "StretchCalculator.h"
|
#include "StretchCalculator.h"
|
||||||
#include "StretcherChannelData.h"
|
#include "StretcherChannelData.h"
|
||||||
|
|
||||||
@@ -213,12 +208,10 @@ RubberBandStretcher::Impl::consumeChannel(size_t c,
|
|||||||
cd.setResampleBufSize(reqSize);
|
cd.setResampleBufSize(reqSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_THREADING
|
#if defined(STRETCHER_IMPL_RESAMPLER_MUTEX_REQUIRED)
|
||||||
#if defined HAVE_IPP && !defined USE_SPEEX
|
|
||||||
if (m_threaded) {
|
if (m_threaded) {
|
||||||
m_resamplerMutex.lock();
|
m_resamplerMutex.lock();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (useMidSide) {
|
if (useMidSide) {
|
||||||
@@ -235,12 +228,10 @@ RubberBandStretcher::Impl::consumeChannel(size_t c,
|
|||||||
1.0 / m_pitchScale,
|
1.0 / m_pitchScale,
|
||||||
final);
|
final);
|
||||||
|
|
||||||
#ifndef NO_THREADING
|
#if defined(STRETCHER_IMPL_RESAMPLER_MUTEX_REQUIRED)
|
||||||
#if defined HAVE_IPP && !defined USE_SPEEX
|
|
||||||
if (m_threaded) {
|
if (m_threaded) {
|
||||||
m_resamplerMutex.unlock();
|
m_resamplerMutex.unlock();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1102,12 +1093,11 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo
|
|||||||
cd.setResampleBufSize(reqSize);
|
cd.setResampleBufSize(reqSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_THREADING
|
|
||||||
#if defined HAVE_IPP && !defined USE_SPEEX
|
#if defined(STRETCHER_IMPL_RESAMPLER_MUTEX_REQUIRED)
|
||||||
if (m_threaded) {
|
if (m_threaded) {
|
||||||
m_resamplerMutex.lock();
|
m_resamplerMutex.lock();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_t outframes = cd.resampler->resample(&cd.resamplebuf,
|
size_t outframes = cd.resampler->resample(&cd.resamplebuf,
|
||||||
@@ -1117,12 +1107,10 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo
|
|||||||
1.0 / m_pitchScale,
|
1.0 / m_pitchScale,
|
||||||
last);
|
last);
|
||||||
|
|
||||||
#ifndef NO_THREADING
|
#if defined(STRETCHER_IMPL_RESAMPLER_MUTEX_REQUIRED)
|
||||||
#if defined HAVE_IPP && !defined USE_SPEEX
|
|
||||||
if (m_threaded) {
|
if (m_threaded) {
|
||||||
m_resamplerMutex.unlock();
|
m_resamplerMutex.unlock();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
writeOutput(*cd.outbuf, cd.resamplebuf,
|
writeOutput(*cd.outbuf, cd.resamplebuf,
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
|
||||||
|
|
||||||
/*
|
|
||||||
Rubber Band Library
|
|
||||||
An audio time-stretching and pitch-shifting library.
|
|
||||||
Copyright 2007-2022 Particular Programs Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation; either version 2 of the
|
|
||||||
License, or (at your option) any later version. See the file
|
|
||||||
COPYING included with this distribution for more information.
|
|
||||||
|
|
||||||
Alternatively, if you have a valid commercial licence for the
|
|
||||||
Rubber Band Library obtained by agreement with the copyright
|
|
||||||
holders, you may redistribute and/or modify it under the terms
|
|
||||||
described in that licence.
|
|
||||||
|
|
||||||
If you wish to distribute code using the Rubber Band Library
|
|
||||||
under terms other than those of the GNU General Public License,
|
|
||||||
you must obtain a valid commercial licence before doing so.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ConstantAudioCurve.h"
|
|
||||||
|
|
||||||
namespace RubberBand
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
ConstantAudioCurve::ConstantAudioCurve(Parameters parameters) :
|
|
||||||
AudioCurveCalculator(parameters)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ConstantAudioCurve::~ConstantAudioCurve()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ConstantAudioCurve::reset()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
float
|
|
||||||
ConstantAudioCurve::processFloat(const float *R__, int)
|
|
||||||
{
|
|
||||||
return 1.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
double
|
|
||||||
ConstantAudioCurve::processDouble(const double *R__, int)
|
|
||||||
{
|
|
||||||
return 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
|
||||||
|
|
||||||
/*
|
|
||||||
Rubber Band Library
|
|
||||||
An audio time-stretching and pitch-shifting library.
|
|
||||||
Copyright 2007-2022 Particular Programs Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation; either version 2 of the
|
|
||||||
License, or (at your option) any later version. See the file
|
|
||||||
COPYING included with this distribution for more information.
|
|
||||||
|
|
||||||
Alternatively, if you have a valid commercial licence for the
|
|
||||||
Rubber Band Library obtained by agreement with the copyright
|
|
||||||
holders, you may redistribute and/or modify it under the terms
|
|
||||||
described in that licence.
|
|
||||||
|
|
||||||
If you wish to distribute code using the Rubber Band Library
|
|
||||||
under terms other than those of the GNU General Public License,
|
|
||||||
you must obtain a valid commercial licence before doing so.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef RUBBERBAND_CONSTANT_AUDIO_CURVE_H
|
|
||||||
#define RUBBERBAND_CONSTANT_AUDIO_CURVE_H
|
|
||||||
|
|
||||||
#include "../dsp/AudioCurveCalculator.h"
|
|
||||||
|
|
||||||
namespace RubberBand
|
|
||||||
{
|
|
||||||
|
|
||||||
class ConstantAudioCurve : public AudioCurveCalculator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ConstantAudioCurve(Parameters parameters);
|
|
||||||
virtual ~ConstantAudioCurve();
|
|
||||||
|
|
||||||
virtual float processFloat(const float *R__ mag, int increment);
|
|
||||||
virtual double processDouble(const double *R__ mag, int increment);
|
|
||||||
virtual void reset();
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
|
||||||
|
|
||||||
/*
|
|
||||||
Rubber Band Library
|
|
||||||
An audio time-stretching and pitch-shifting library.
|
|
||||||
Copyright 2007-2022 Particular Programs Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation; either version 2 of the
|
|
||||||
License, or (at your option) any later version. See the file
|
|
||||||
COPYING included with this distribution for more information.
|
|
||||||
|
|
||||||
Alternatively, if you have a valid commercial licence for the
|
|
||||||
Rubber Band Library obtained by agreement with the copyright
|
|
||||||
holders, you may redistribute and/or modify it under the terms
|
|
||||||
described in that licence.
|
|
||||||
|
|
||||||
If you wish to distribute code using the Rubber Band Library
|
|
||||||
under terms other than those of the GNU General Public License,
|
|
||||||
you must obtain a valid commercial licence before doing so.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "SpectralDifferenceAudioCurve.h"
|
|
||||||
|
|
||||||
#include "../system/Allocators.h"
|
|
||||||
#include "../system/VectorOps.h"
|
|
||||||
|
|
||||||
namespace RubberBand
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
SpectralDifferenceAudioCurve::SpectralDifferenceAudioCurve(Parameters parameters) :
|
|
||||||
AudioCurveCalculator(parameters)
|
|
||||||
{
|
|
||||||
m_mag = allocate<double>(m_lastPerceivedBin + 1);
|
|
||||||
m_tmpbuf = allocate<double>(m_lastPerceivedBin + 1);
|
|
||||||
v_zero(m_mag, m_lastPerceivedBin + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
SpectralDifferenceAudioCurve::~SpectralDifferenceAudioCurve()
|
|
||||||
{
|
|
||||||
deallocate(m_mag);
|
|
||||||
deallocate(m_tmpbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SpectralDifferenceAudioCurve::reset()
|
|
||||||
{
|
|
||||||
v_zero(m_mag, m_lastPerceivedBin + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SpectralDifferenceAudioCurve::setFftSize(int newSize)
|
|
||||||
{
|
|
||||||
deallocate(m_tmpbuf);
|
|
||||||
deallocate(m_mag);
|
|
||||||
AudioCurveCalculator::setFftSize(newSize);
|
|
||||||
m_mag = allocate<double>(m_lastPerceivedBin + 1);
|
|
||||||
m_tmpbuf = allocate<double>(m_lastPerceivedBin + 1);
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
float
|
|
||||||
SpectralDifferenceAudioCurve::processFloat(const float *R__ mag, int)
|
|
||||||
{
|
|
||||||
double result = 0.0;
|
|
||||||
|
|
||||||
const int hs1 = m_lastPerceivedBin + 1;
|
|
||||||
|
|
||||||
v_convert(m_tmpbuf, mag, hs1);
|
|
||||||
v_square(m_tmpbuf, hs1);
|
|
||||||
v_subtract(m_mag, m_tmpbuf, hs1);
|
|
||||||
v_abs(m_mag, hs1);
|
|
||||||
v_sqrt(m_mag, hs1);
|
|
||||||
|
|
||||||
for (int i = 0; i < hs1; ++i) {
|
|
||||||
result += m_mag[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
v_copy(m_mag, m_tmpbuf, hs1);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
double
|
|
||||||
SpectralDifferenceAudioCurve::processDouble(const double *R__ mag, int)
|
|
||||||
{
|
|
||||||
double result = 0.0;
|
|
||||||
|
|
||||||
const int hs1 = m_lastPerceivedBin + 1;
|
|
||||||
|
|
||||||
v_convert(m_tmpbuf, mag, hs1);
|
|
||||||
v_square(m_tmpbuf, hs1);
|
|
||||||
v_subtract(m_mag, m_tmpbuf, hs1);
|
|
||||||
v_abs(m_mag, hs1);
|
|
||||||
v_sqrt(m_mag, hs1);
|
|
||||||
|
|
||||||
for (int i = 0; i < hs1; ++i) {
|
|
||||||
result += m_mag[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
v_copy(m_mag, m_tmpbuf, hs1);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
|
||||||
|
|
||||||
/*
|
|
||||||
Rubber Band Library
|
|
||||||
An audio time-stretching and pitch-shifting library.
|
|
||||||
Copyright 2007-2022 Particular Programs Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation; either version 2 of the
|
|
||||||
License, or (at your option) any later version. See the file
|
|
||||||
COPYING included with this distribution for more information.
|
|
||||||
|
|
||||||
Alternatively, if you have a valid commercial licence for the
|
|
||||||
Rubber Band Library obtained by agreement with the copyright
|
|
||||||
holders, you may redistribute and/or modify it under the terms
|
|
||||||
described in that licence.
|
|
||||||
|
|
||||||
If you wish to distribute code using the Rubber Band Library
|
|
||||||
under terms other than those of the GNU General Public License,
|
|
||||||
you must obtain a valid commercial licence before doing so.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef RUBBERBAND_SPECTRALDIFFERENCE_AUDIO_CURVE_H
|
|
||||||
#define RUBBERBAND_SPECTRALDIFFERENCE_AUDIO_CURVE_H
|
|
||||||
|
|
||||||
#include "../dsp/AudioCurveCalculator.h"
|
|
||||||
#include "../dsp/Window.h"
|
|
||||||
|
|
||||||
namespace RubberBand
|
|
||||||
{
|
|
||||||
|
|
||||||
class SpectralDifferenceAudioCurve : public AudioCurveCalculator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SpectralDifferenceAudioCurve(Parameters parameters);
|
|
||||||
|
|
||||||
virtual ~SpectralDifferenceAudioCurve();
|
|
||||||
|
|
||||||
virtual void setFftSize(int newSize);
|
|
||||||
|
|
||||||
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;
|
|
||||||
double *R__ m_tmpbuf;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
Reference in New Issue
Block a user