diff --git a/main/main.cpp b/main/main.cpp index 78e841d..90f75dc 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -90,7 +90,7 @@ int main(int argc, char **argv) double frequencyshift = 1.0; int debug = 0; bool realtime = false; - bool precise = true; + bool precisiongiven = false; int threading = 0; bool lamination = true; bool longwin = false; @@ -179,8 +179,8 @@ int main(int argc, char **argv) case 'f': frequencyshift = atof(optarg); haveRatio = true; break; case 'd': debug = atoi(optarg); break; case 'R': realtime = true; break; - case 'L': precise = false; break; - case 'P': precise = true; break; + case 'L': precisiongiven = true; break; + case 'P': precisiongiven = true; break; case 'F': formant = true; break; case '0': threading = 1; break; case '@': threading = 2; break; @@ -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 << "for most situations. The default is to use none of these options." << endl; cerr << endl; - cerr << " -L, --loose Relax timing in hope of better transient preservation" << endl; - cerr << " -P, --precise Ignored: The opposite of -L, this is default from 1.6" << endl; - cerr << " -R, --realtime Select realtime mode (implies --no-threads)" << endl; + cerr << " -R, --realtime Select realtime mode (implies --no-threads)." << endl; + cerr << " This utility does not do realtime stream processing;" << endl; + cerr << " the option merely selects realtime mode for the" << endl; + cerr << " stretcher it uses" << endl; cerr << " --no-threads No extra threads regardless of CPU and channel count" << endl; cerr << " --threads Assume multi-CPU even if only one CPU is identified" << endl; cerr << " --no-transients Disable phase resynchronisation at transients" << endl; @@ -294,6 +295,8 @@ int main(int argc, char **argv) cerr << " (at a cost in width and individual channel quality)" << endl; cerr << " --ignore-clipping Ignore clipping at output; the default is to restart" << endl; cerr << " with reduced gain if clipping occurs" << endl; + cerr << " -L, --loose [Accepted for compatibility but ignored; always off]" << endl; + cerr << " -P, --precise [Accepted for compatibility but ignored; always on]" << endl; cerr << endl; cerr << " -d, --debug 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; @@ -330,6 +333,11 @@ int main(int argc, char **argv) hqpitch = false; } + if (precisiongiven) { + cerr << "NOTE: The -L/--loose and -P/--precise options are both ignored -- precise" << endl; + cerr << " became the default in v1.6 and loose was removed in v3.0" << endl; + } + switch (crispness) { case -1: crispness = 5; break; case 0: detector = CompoundDetector; transients = NoTransients; lamination = false; longwin = true; shortwin = false; break; @@ -493,7 +501,6 @@ int main(int argc, char **argv) RubberBandStretcher::Options options = 0; if (realtime) options |= RubberBandStretcher::OptionProcessRealTime; - if (precise) options |= RubberBandStretcher::OptionStretchPrecise; if (!lamination) options |= RubberBandStretcher::OptionPhaseIndependent; if (longwin) options |= RubberBandStretcher::OptionWindowLong; if (shortwin) options |= RubberBandStretcher::OptionWindowShort; diff --git a/meson.build b/meson.build index 3f9a9ec..679b897 100644 --- a/meson.build +++ b/meson.build @@ -38,10 +38,8 @@ library_sources = [ 'src/base/Profiler.cpp', 'src/dsp/AudioCurveCalculator.cpp', 'src/audiocurves/CompoundAudioCurve.cpp', - 'src/audiocurves/SpectralDifferenceAudioCurve.cpp', 'src/audiocurves/HighFrequencyAudioCurve.cpp', 'src/audiocurves/SilentAudioCurve.cpp', - 'src/audiocurves/ConstantAudioCurve.cpp', 'src/audiocurves/PercussiveAudioCurve.cpp', 'src/dsp/Resampler.cpp', 'src/dsp/FFT.cpp', diff --git a/rubberband/RubberBandStretcher.h b/rubberband/RubberBandStretcher.h index 6e963b1..b216048 100644 --- a/rubberband/RubberBandStretcher.h +++ b/rubberband/RubberBandStretcher.h @@ -109,27 +109,6 @@ public: * non-real-time operation on seekable files: Offline; real-time * or streaming operation: RealTime. * - * 2. Flags prefixed \c OptionStretch control the profile used for - * variable timestretching. Rubber Band always adjusts the - * stretch profile to minimise stretching of busy broadband - * transient sounds, but the degree to which it does so is - * adjustable. These options may not be changed after - * construction. - * - * \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 * frequency phase-reset mechanism that may be used at transient * 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 * but a loss of stereo space and width. Any channels beyond * the first two are processed individually. + * + * Finally, flags prefixed \c OptionStretch are obsolete flags + * provided for backward compatibility only. They are ignored by + * the stretcher. */ enum Option { @@ -300,8 +283,8 @@ public: OptionProcessOffline = 0x00000000, OptionProcessRealTime = 0x00000001, - OptionStretchElastic = 0x00000000, - OptionStretchPrecise = 0x00000010, + OptionStretchElastic = 0x00000000, // obsolete + OptionStretchPrecise = 0x00000010, // obsolete OptionTransientsCrisp = 0x00000000, OptionTransientsMixed = 0x00000100, diff --git a/rubberband/rubberband-c.h b/rubberband/rubberband-c.h index 6c3a4e9..5172c26 100644 --- a/rubberband/rubberband-c.h +++ b/rubberband/rubberband-c.h @@ -57,8 +57,8 @@ enum RubberBandOption { RubberBandOptionProcessOffline = 0x00000000, RubberBandOptionProcessRealTime = 0x00000001, - RubberBandOptionStretchElastic = 0x00000000, - RubberBandOptionStretchPrecise = 0x00000010, + RubberBandOptionStretchElastic = 0x00000000, // obsolete + RubberBandOptionStretchPrecise = 0x00000010, // obsolete RubberBandOptionTransientsCrisp = 0x00000000, RubberBandOptionTransientsMixed = 0x00000100, diff --git a/src/StretchCalculator.cpp b/src/StretchCalculator.cpp index 2e04de0..da228a3 100644 --- a/src/StretchCalculator.cpp +++ b/src/StretchCalculator.cpp @@ -74,11 +74,8 @@ StretchCalculator::setKeyFrameMap(const std::map &mapping) std::vector StretchCalculator::calculate(double ratio, size_t inputDuration, - const std::vector &phaseResetDf, - const std::vector &stretchDf) + const std::vector &phaseResetDf) { - assert(phaseResetDf.size() == stretchDf.size()); - m_peaks = findPeaks(phaseResetDf); size_t totalCount = phaseResetDf.size(); @@ -107,16 +104,6 @@ StretchCalculator::calculate(double ratio, size_t inputDuration, 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 increments; for (size_t i = 0; i <= peaks.size(); ++i) { @@ -141,47 +128,61 @@ StretchCalculator::calculate(double ratio, size_t inputDuration, regionEndChunk = peaks[i].chunk; regionEnd = targets[i]; } - + if (regionStartChunk > totalCount) regionStartChunk = totalCount; if (regionStart > outputDuration) regionStart = outputDuration; if (regionEndChunk > totalCount) regionEndChunk = totalCount; if (regionEnd > outputDuration) regionEnd = outputDuration; - + + if (regionEndChunk < regionStartChunk) regionEndChunk = regionStartChunk; + if (regionEnd < regionStart) regionEnd = regionStart; + size_t regionDuration = regionEnd - regionStart; - regionTotalChunks += regionDuration; - std::vector dfRegion; + size_t nchunks = regionEndChunk - regionStartChunk; - for (size_t j = regionStartChunk; j != regionEndChunk; ++j) { - dfRegion.push_back(stretchDf[j]); + if (nchunks == 0) { + //!!! + break; } - if (m_debugLevel > 1) { - std::cerr << "distributeRegion from " << regionStartChunk << " to " << regionEndChunk << " (samples " << regionStart << " to " << regionEnd << ")" << std::endl; - } - - dfRegion = smoothDF(dfRegion); - - std::vector regionIncrements = distributeRegion - (dfRegion, regionDuration, ratio, phaseReset); - + double per = double(regionDuration) / double(nchunks); + double acc = 0.0; + size_t nremaining = nchunks; size_t totalForRegion = 0; - for (size_t j = 0; j < regionIncrements.size(); ++j) { - - int incr = regionIncrements[j]; - - if (j == 0 && phaseReset) increments.push_back(-incr); - else increments.push_back(incr); - - if (incr > 0) totalForRegion += incr; - else totalForRegion += -incr; - + if (phaseReset) { + size_t incr; + if (nchunks > 1) { + incr = m_increment; + if (incr > regionDuration) { + incr = regionDuration; + } + } else { + incr = regionDuration; + } + increments.push_back(- int64_t(incr)); + per = double(regionDuration - incr) / double(nchunks - 1); + acc += incr; + totalForRegion += incr; totalInput += m_increment; + nremaining = nremaining - 1; } - if (totalForRegion != regionDuration) { - std::cerr << "*** ERROR: distributeRegion returned wrong duration " << totalForRegion << ", expected " << regionDuration << std::endl; + if (nremaining > 0) { + for (size_t j = 0; j+1 < nremaining; ++j) { + acc += per; + size_t incr = size_t(round(acc - totalForRegion)); + increments.push_back(incr); + totalForRegion += incr; + totalInput += m_increment; + } + if (regionDuration > totalForRegion) { + size_t final = regionDuration - totalForRegion; + increments.push_back(final); + totalForRegion += final; + totalInput += m_increment; + } } totalOutput += totalForRegion; @@ -189,7 +190,6 @@ StretchCalculator::calculate(double ratio, size_t inputDuration, 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 << "(region total = " << regionTotalChunks << ")" << std::endl; } return increments; @@ -861,285 +861,5 @@ StretchCalculator::smoothDF(const std::vector &df) return smoothedDF; } -std::vector -StretchCalculator::distributeRegion(const std::vector &dfIn, - size_t duration, float ratio, bool phaseReset) -{ - std::vector df(dfIn); - std::vector 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 &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; - } - } -} - } diff --git a/src/StretchCalculator.h b/src/StretchCalculator.h index 416b0da..13334e1 100644 --- a/src/StretchCalculator.h +++ b/src/StretchCalculator.h @@ -51,13 +51,10 @@ public: /** * Calculate phase increments for a region of audio, given the * overall target stretch ratio, input duration in audio samples, - * and the audio curves to use for identifying phase lock points - * (lockAudioCurve) and for allocating stretches to relatively - * less prominent points (stretchAudioCurve). + * and the audio curves to use for identifying phase lock points. */ std::vector calculate(double ratio, size_t inputDuration, - const std::vector &lockAudioCurve, - const std::vector &stretchAudioCurve); + const std::vector &lockAudioCurve); /** * Calculate the phase increment for a single audio block, given @@ -96,16 +93,6 @@ protected: void mapPeaks(std::vector &peaks, std::vector &targets, size_t outputDuration, size_t totalCount); - std::vector distributeRegion(const std::vector ®ionCurve, - size_t outputDuration, float ratio, - bool phaseReset); - - void calculateDisplacements(const std::vector &df, - float &maxDf, - double &totalDisplacement, - double &maxDisplacement, - float adj) const; - size_t m_sampleRate; size_t m_increment; float m_prevDf; diff --git a/src/StretcherImpl.cpp b/src/StretcherImpl.cpp index cb9d2f0..cfc16a8 100644 --- a/src/StretcherImpl.cpp +++ b/src/StretcherImpl.cpp @@ -25,9 +25,7 @@ #include "audiocurves/PercussiveAudioCurve.h" #include "audiocurves/HighFrequencyAudioCurve.h" -#include "audiocurves/SpectralDifferenceAudioCurve.h" #include "audiocurves/SilentAudioCurve.h" -#include "audiocurves/ConstantAudioCurve.h" #include "audiocurves/CompoundAudioCurve.h" #include "dsp/Resampler.h" @@ -105,7 +103,6 @@ RubberBandStretcher::Impl::Impl(size_t sampleRate, m_lastProcessPhaseResetDf(16), m_emergencyScavenger(10, 4), m_phaseResetAudioCurve(0), - m_stretchAudioCurve(0), m_silentAudioCurve(0), m_stretchCalculator(0), m_freq0(600), @@ -150,12 +147,7 @@ RubberBandStretcher::Impl::Impl(size_t sampleRate, } if (m_options & OptionProcessRealTime) { - m_realtime = true; - - if (!(m_options & OptionStretchPrecise)) { - m_options |= OptionStretchPrecise; - } } #ifndef NO_THREADING @@ -203,7 +195,6 @@ RubberBandStretcher::Impl::~Impl() } delete m_phaseResetAudioCurve; - delete m_stretchAudioCurve; delete m_silentAudioCurve; delete m_stretchCalculator; delete m_studyFFT; @@ -249,7 +240,6 @@ RubberBandStretcher::Impl::reset() m_mode = JustCreated; if (m_phaseResetAudioCurve) m_phaseResetAudioCurve->reset(); - if (m_stretchAudioCurve) m_stretchAudioCurve->reset(); if (m_silentAudioCurve) m_silentAudioCurve->reset(); m_inputDuration = 0; m_silentHistory = 0; @@ -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; m_phaseResetAudioCurve = new CompoundAudioCurve (CompoundAudioCurve::Parameters(m_sampleRate, m_fftSize)); @@ -714,17 +700,6 @@ RubberBandStretcher::Impl::configure() m_silentAudioCurve = new SilentAudioCurve (SilentAudioCurve::Parameters(m_sampleRate, m_fftSize)); - if (!m_realtime) { - delete m_stretchAudioCurve; - if (!(m_options & OptionStretchPrecise)) { - m_stretchAudioCurve = new SpectralDifferenceAudioCurve - (SpectralDifferenceAudioCurve::Parameters(m_sampleRate, m_fftSize)); - } else { - m_stretchAudioCurve = new ConstantAudioCurve - (ConstantAudioCurve::Parameters(m_sampleRate, m_fftSize)); - } - } - delete m_stretchCalculator; m_stretchCalculator = new StretchCalculator (m_sampleRate, m_increment, @@ -765,7 +740,6 @@ RubberBandStretcher::Impl::reconfigure() // the df vectors calculateStretch(); m_phaseResetDf.clear(); - m_stretchDf.clear(); m_silence.clear(); m_inputDuration = 0; } @@ -854,9 +828,6 @@ RubberBandStretcher::Impl::reconfigure() if (m_fftSize != prevFftSize) { m_phaseResetAudioCurve->setFftSize(m_fftSize); m_silentAudioCurve->setFftSize(m_fftSize); - if (m_stretchAudioCurve) { - m_stretchAudioCurve->setFftSize(m_fftSize); - } somethingChanged = true; } @@ -1069,9 +1040,6 @@ RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool // cout << m_phaseResetDf.size() << " [" << final << "] -> " << df << " \t: "; - df = m_stretchAudioCurve->processFloat(cd.fltbuf, m_increment); - m_stretchDf.push_back(df); - df = m_silentAudioCurve->processFloat(cd.fltbuf, m_increment); bool silent = (df > 0.f); if (silent && m_debugLevel > 1) { @@ -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 increments = m_stretchCalculator->calculate (getEffectiveRatio(), inputDuration, - m_phaseResetDf, - m_stretchDf); + m_phaseResetDf); int history = 0; for (size_t i = 0; i < increments.size(); ++i) { diff --git a/src/StretcherImpl.h b/src/StretcherImpl.h index ceb5f12..b75fc9e 100644 --- a/src/StretcherImpl.h +++ b/src/StretcherImpl.h @@ -220,19 +220,19 @@ protected: mutable Mutex m_threadSetMutex; typedef std::set ThreadSet; ThreadSet m_threadSet; - -#if defined HAVE_IPP && !defined USE_SPEEX + +#if defined(HAVE_IPP) && !defined(NO_THREADING) && !defined(USE_BQRESAMPLER) && !defined(USE_SPEEX) && !defined(HAVE_LIBSAMPLERATE) // Exasperatingly, the IPP polyphase resampler does not appear to - // be thread-safe as advertised -- a good reason to prefer the - // Speex alternative + // be thread-safe as advertised -- a good reason to prefer any of + // the alternatives +#define STRETCHER_IMPL_RESAMPLER_MUTEX_REQUIRED 1 Mutex m_resamplerMutex; #endif -#endif - +#endif // ! NO_THREADING + size_t m_inputDuration; CompoundAudioCurve::Type m_detectorType; std::vector m_phaseResetDf; - std::vector m_stretchDf; std::vector m_silence; int m_silentHistory; @@ -246,7 +246,6 @@ protected: Scavenger > m_emergencyScavenger; CompoundAudioCurve *m_phaseResetAudioCurve; - AudioCurveCalculator *m_stretchAudioCurve; AudioCurveCalculator *m_silentAudioCurve; StretchCalculator *m_stretchCalculator; diff --git a/src/StretcherProcess.cpp b/src/StretcherProcess.cpp index edc18c9..78365b3 100644 --- a/src/StretcherProcess.cpp +++ b/src/StretcherProcess.cpp @@ -22,11 +22,6 @@ */ #include "StretcherImpl.h" - -#include "audiocurves/PercussiveAudioCurve.h" -#include "audiocurves/HighFrequencyAudioCurve.h" -#include "audiocurves/ConstantAudioCurve.h" - #include "StretchCalculator.h" #include "StretcherChannelData.h" @@ -213,12 +208,10 @@ RubberBandStretcher::Impl::consumeChannel(size_t c, cd.setResampleBufSize(reqSize); } -#ifndef NO_THREADING -#if defined HAVE_IPP && !defined USE_SPEEX +#if defined(STRETCHER_IMPL_RESAMPLER_MUTEX_REQUIRED) if (m_threaded) { m_resamplerMutex.lock(); } -#endif #endif if (useMidSide) { @@ -235,12 +228,10 @@ RubberBandStretcher::Impl::consumeChannel(size_t c, 1.0 / m_pitchScale, final); -#ifndef NO_THREADING -#if defined HAVE_IPP && !defined USE_SPEEX +#if defined(STRETCHER_IMPL_RESAMPLER_MUTEX_REQUIRED) if (m_threaded) { m_resamplerMutex.unlock(); } -#endif #endif } @@ -1102,12 +1093,11 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo cd.setResampleBufSize(reqSize); } -#ifndef NO_THREADING -#if defined HAVE_IPP && !defined USE_SPEEX + +#if defined(STRETCHER_IMPL_RESAMPLER_MUTEX_REQUIRED) if (m_threaded) { m_resamplerMutex.lock(); } -#endif #endif size_t outframes = cd.resampler->resample(&cd.resamplebuf, @@ -1117,12 +1107,10 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo 1.0 / m_pitchScale, last); -#ifndef NO_THREADING -#if defined HAVE_IPP && !defined USE_SPEEX +#if defined(STRETCHER_IMPL_RESAMPLER_MUTEX_REQUIRED) if (m_threaded) { m_resamplerMutex.unlock(); } -#endif #endif writeOutput(*cd.outbuf, cd.resamplebuf, diff --git a/src/audiocurves/ConstantAudioCurve.cpp b/src/audiocurves/ConstantAudioCurve.cpp deleted file mode 100644 index 0c2e08a..0000000 --- a/src/audiocurves/ConstantAudioCurve.cpp +++ /dev/null @@ -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; -} - -} - diff --git a/src/audiocurves/ConstantAudioCurve.h b/src/audiocurves/ConstantAudioCurve.h deleted file mode 100644 index b1a8e50..0000000 --- a/src/audiocurves/ConstantAudioCurve.h +++ /dev/null @@ -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 diff --git a/src/audiocurves/SpectralDifferenceAudioCurve.cpp b/src/audiocurves/SpectralDifferenceAudioCurve.cpp deleted file mode 100644 index ee3b85b..0000000 --- a/src/audiocurves/SpectralDifferenceAudioCurve.cpp +++ /dev/null @@ -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(m_lastPerceivedBin + 1); - m_tmpbuf = allocate(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(m_lastPerceivedBin + 1); - m_tmpbuf = allocate(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; -} - -} - diff --git a/src/audiocurves/SpectralDifferenceAudioCurve.h b/src/audiocurves/SpectralDifferenceAudioCurve.h deleted file mode 100644 index c78383d..0000000 --- a/src/audiocurves/SpectralDifferenceAudioCurve.h +++ /dev/null @@ -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