diff --git a/src/AudioIO.cpp b/src/AudioIO.cpp index 6c64ed1ad..e67ad1a06 100644 --- a/src/AudioIO.cpp +++ b/src/AudioIO.cpp @@ -623,6 +623,9 @@ private: double speed = static_cast(std::abs(s1 - s0)) / duration; bool adjustedSpeed = false; + auto minSpeed = std::min(options.minSpeed, options.maxSpeed); + wxASSERT(minSpeed == options.minSpeed); + // May change the requested speed and duration if (!adjustStart && speed > options.maxSpeed) { @@ -641,15 +644,20 @@ private: // continue at no less than maximum. (Without this // the final catch-up can make a slow scrub interval // that drops the pitch and sounds wrong.) - // Trim the duration. - duration = std::max(0L, lrint(speed * duration / options.maxSpeed)); - speed = options.maxSpeed; + minSpeed = options.maxSpeed; mGoal = s1; adjustedSpeed = true; } else mGoal = -1; + if (speed < minSpeed) { + // Trim the duration. + duration = std::max(0L, lrint(speed * duration / minSpeed)); + speed = minSpeed; + adjustedSpeed = true; + } + if (speed < ScrubbingOptions::MinAllowedScrubSpeed()) { // Mixers were set up to go only so slowly, not slower. // This will put a request for some silence in the work queue. diff --git a/src/tracks/ui/Scrubbing.cpp b/src/tracks/ui/Scrubbing.cpp index 6e34d7f69..4351e4aee 100644 --- a/src/tracks/ui/Scrubbing.cpp +++ b/src/tracks/ui/Scrubbing.cpp @@ -341,6 +341,7 @@ bool Scrubber::MaybeStartScrubbing(wxCoord xx) options.pScrubbingOptions = &mOptions; options.timeTrack = NULL; mOptions.delay = (ScrubPollInterval_ms * 0.9 / 1000.0); + mOptions.minSpeed = 0.0; #ifdef USE_TRANSCRIPTION_TOOLBAR if (!mAlwaysSeeking) { // Take the starting speed limit from the transcription toolbar, @@ -414,6 +415,7 @@ void Scrubber::ContinueScrubbingPoll() bool result = false; if (mPaused) { // When paused, enqueue silent scrubs. + mOptions.minSpeed = 0.0; mOptions.maxSpeed = mMaxSpeed; mOptions.adjustStart = false; mOptions.enqueueBySpeed = true; @@ -428,6 +430,7 @@ void Scrubber::ContinueScrubbingPoll() const auto lastTime = gAudioIO->GetLastTimeInScrubQueue(); const auto delta = mLastScrubPosition - position.x; const double time = viewInfo.OffsetTimeByPixels(lastTime, delta); + mOptions.minSpeed = 0.0; mOptions.maxSpeed = mMaxSpeed; mOptions.adjustStart = true; mOptions.enqueueBySpeed = false; @@ -437,6 +440,7 @@ void Scrubber::ContinueScrubbingPoll() else { const double time = viewInfo.PositionToTime(position.x, trackPanel->GetLeftOffset()); mOptions.adjustStart = seek; + mOptions.minSpeed = (mDragging || !seek) ? 0.0 : 1.0; mOptions.maxSpeed = (mDragging || !seek) ? mMaxSpeed : 1.0; if (mSmoothScrollingScrub) { diff --git a/src/tracks/ui/Scrubbing.h b/src/tracks/ui/Scrubbing.h index 76a7a0b20..6b0d84f4c 100644 --- a/src/tracks/ui/Scrubbing.h +++ b/src/tracks/ui/Scrubbing.h @@ -40,7 +40,8 @@ struct ScrubbingOptions { double delay {}; - // A limiting value for the speed of a scrub interval: + // Limiting values for the speed of a scrub interval: + double minSpeed { 0.0 }; double maxSpeed { 1.0 };