diff --git a/rubberband/RubberBandStretcher.h b/rubberband/RubberBandStretcher.h index 6820516..8ddc867 100644 --- a/rubberband/RubberBandStretcher.h +++ b/rubberband/RubberBandStretcher.h @@ -182,44 +182,52 @@ public: * \li \c OptionPitchHighQuality - Use the highest quality * method for pitch shifting. This method has a CPU cost * approximately proportional to the required frequency shift. + + * \li \c OptionPitchHighConsistency - Use the method that gives + * greatest consistency when used to create small variations in + * pitch around the 1.0-ratio level. Unlike the previous two + * options, this avoids discontinuities when moving across the + * 1.0 pitch scale in real-time; it also consumes more CPU than + * the others in the case where the pitch scale is exactly 1.0. */ enum Option { - OptionProcessOffline = 0x00000000, - OptionProcessRealTime = 0x00000001, + OptionProcessOffline = 0x00000000, + OptionProcessRealTime = 0x00000001, - OptionStretchElastic = 0x00000000, - OptionStretchPrecise = 0x00000010, + OptionStretchElastic = 0x00000000, + OptionStretchPrecise = 0x00000010, - OptionTransientsCrisp = 0x00000000, - OptionTransientsMixed = 0x00000100, - OptionTransientsSmooth = 0x00000200, + OptionTransientsCrisp = 0x00000000, + OptionTransientsMixed = 0x00000100, + OptionTransientsSmooth = 0x00000200, - OptionPhaseAdaptive = 0x00000000, - OptionPhasePeakLocked = 0x00001000, - OptionPhaseIndependent = 0x00002000, + OptionPhaseAdaptive = 0x00000000, + OptionPhasePeakLocked = 0x00001000, + OptionPhaseIndependent = 0x00002000, - OptionThreadingAuto = 0x00000000, - OptionThreadingNever = 0x00010000, - OptionThreadingAlways = 0x00020000, + OptionThreadingAuto = 0x00000000, + OptionThreadingNever = 0x00010000, + OptionThreadingAlways = 0x00020000, - OptionWindowStandard = 0x00000000, - OptionWindowShort = 0x00100000, - OptionWindowLong = 0x00200000, + OptionWindowStandard = 0x00000000, + OptionWindowShort = 0x00100000, + OptionWindowLong = 0x00200000, - OptionFormantShifted = 0x00000000, - OptionFormantPreserved = 0x01000000, + OptionFormantShifted = 0x00000000, + OptionFormantPreserved = 0x01000000, - OptionPitchHighSpeed = 0x00000000, - OptionPitchHighQuality = 0x02000000 + OptionPitchHighSpeed = 0x00000000, + OptionPitchHighQuality = 0x02000000, + OptionPitchHighConsistency = 0x04000000 }; typedef int Options; enum PresetOption { - DefaultOptions = 0x00000000, - PercussiveOptions = 0x00102000 + DefaultOptions = 0x00000000, + PercussiveOptions = 0x00102000 }; /** diff --git a/rubberband/rubberband-c.h b/rubberband/rubberband-c.h index bcf13f0..8fe92bb 100644 --- a/rubberband/rubberband-c.h +++ b/rubberband/rubberband-c.h @@ -34,33 +34,34 @@ extern "C" { enum RubberBandOption { - RubberBandOptionProcessOffline = 0x00000000, - RubberBandOptionProcessRealTime = 0x00000001, + RubberBandOptionProcessOffline = 0x00000000, + RubberBandOptionProcessRealTime = 0x00000001, - RubberBandOptionStretchElastic = 0x00000000, - RubberBandOptionStretchPrecise = 0x00000010, + RubberBandOptionStretchElastic = 0x00000000, + RubberBandOptionStretchPrecise = 0x00000010, - RubberBandOptionTransientsCrisp = 0x00000000, - RubberBandOptionTransientsMixed = 0x00000100, - RubberBandOptionTransientsSmooth = 0x00000200, + RubberBandOptionTransientsCrisp = 0x00000000, + RubberBandOptionTransientsMixed = 0x00000100, + RubberBandOptionTransientsSmooth = 0x00000200, - RubberBandOptionPhaseAdaptive = 0x00000000, - RubberBandOptionPhasePeakLocked = 0x00001000, - RubberBandOptionPhaseIndependent = 0x00002000, + RubberBandOptionPhaseAdaptive = 0x00000000, + RubberBandOptionPhasePeakLocked = 0x00001000, + RubberBandOptionPhaseIndependent = 0x00002000, - RubberBandOptionThreadingAuto = 0x00000000, - RubberBandOptionThreadingNever = 0x00010000, - RubberBandOptionThreadingAlways = 0x00020000, + RubberBandOptionThreadingAuto = 0x00000000, + RubberBandOptionThreadingNever = 0x00010000, + RubberBandOptionThreadingAlways = 0x00020000, - RubberBandOptionWindowStandard = 0x00000000, - RubberBandOptionWindowShort = 0x00100000, - RubberBandOptionWindowLong = 0x00200000, + RubberBandOptionWindowStandard = 0x00000000, + RubberBandOptionWindowShort = 0x00100000, + RubberBandOptionWindowLong = 0x00200000, - RubberBandOptionFormantShifted = 0x00000000, - RubberBandOptionFormantPreserved = 0x01000000, + RubberBandOptionFormantShifted = 0x00000000, + RubberBandOptionFormantPreserved = 0x01000000, - RubberBandOptionPitchHighQuality = 0x00000000, - RubberBandOptionPitchHighSpeed = 0x02000000 + RubberBandOptionPitchHighQuality = 0x00000000, + RubberBandOptionPitchHighSpeed = 0x02000000, + RubberBandOptionPitchHighConsistency = 0x04000000 }; typedef int RubberBandOptions; diff --git a/src/StretcherImpl.cpp b/src/StretcherImpl.cpp index 04820bf..47b0d90 100644 --- a/src/StretcherImpl.cpp +++ b/src/StretcherImpl.cpp @@ -524,7 +524,9 @@ RubberBandStretcher::Impl::configure() m_studyFFT->initFloat(); } - if (m_pitchScale != 1.0 || m_realtime) { + if (m_pitchScale != 1.0 || + (m_options & OptionPitchHighConsistency) || + m_realtime) { for (size_t c = 0; c < m_channels; ++c) { @@ -708,7 +710,9 @@ RubberBandStretcher::Impl::setPitchOption(Options options) Options prior = m_options; - int mask = (OptionPitchHighQuality | OptionPitchHighSpeed); + int mask = (OptionPitchHighQuality | + OptionPitchHighSpeed | + OptionPitchHighConsistency); m_options &= ~mask; options &= mask; m_options |= options; @@ -989,8 +993,6 @@ RubberBandStretcher::Impl::process(const float *const *input, size_t samples, bo while (!allConsumed) { -// cerr << "process looping" << endl; - //#ifndef NO_THREADING // if (m_threaded) { // pthread_mutex_lock(&m_inputProcessedMutex); @@ -1052,6 +1054,9 @@ RubberBandStretcher::Impl::process(const float *const *input, size_t samples, bo } */ } + + if (!allConsumed) cerr << "process looping" << endl; + } // cerr << "process returning" << endl; diff --git a/src/StretcherProcess.cpp b/src/StretcherProcess.cpp index de1a51d..26c3773 100644 --- a/src/StretcherProcess.cpp +++ b/src/StretcherProcess.cpp @@ -110,6 +110,8 @@ RubberBandStretcher::Impl::resampleBeforeStretching() const if (m_options & OptionPitchHighQuality) { return (m_pitchScale < 1.0); // better sound + } else if (m_options & OptionPitchHighConsistency) { + return false; } else { return (m_pitchScale > 1.0); // better performance } @@ -145,6 +147,8 @@ RubberBandStretcher::Impl::consumeChannel(size_t c, const float *input, } +// std::cerr << "resampling on INPUT" << std::endl; + toWrite = cd.resampler->resample(&input, &cd.resamplebuf, samples, @@ -1009,7 +1013,9 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo bool resampledAlready = resampleBeforeStretching(); - if (!resampledAlready && m_pitchScale != 1.0 && cd.resampler) { + if (!resampledAlready && + (m_pitchScale != 1.0 || m_options & OptionPitchHighConsistency) && + cd.resampler) { size_t reqSize = int(ceil(si / m_pitchScale)); if (reqSize > cd.resamplebufSize) { @@ -1024,6 +1030,8 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo } +// std::cerr << "resampling on OUTPUT" << std::endl; + size_t outframes = cd.resampler->resample(&cd.accumulator, &cd.resamplebuf, si,