1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-01 16:19:43 +02:00

Keyboard scrubbing and Play-at-speed: remove initial silence

Currently AudioIoCallback::ScrubState::Get(), inserts a period of silence the first time it's called because at this time Scrubber::ContinueScrubbingPoll() has not been called, and so message.end has not been set to an appropriate value.
In the case of keyboard scrubbing and play-at-speed, the initial speed is already known, so message.end can be set to this value, removing the need for an initial silence.
The start of keyboard scrubbing and play-at-speed are now faster (the latter very much faster).
This commit is contained in:
David Bailes 2020-02-11 09:54:45 +00:00
parent 55e44cdc83
commit e0302257c5
3 changed files with 27 additions and 16 deletions

View File

@ -543,7 +543,7 @@ struct AudioIoCallback::ScrubState
: mRate(rate)
, mStartTime( t0 )
{
const double t1 = options.bySpeed ? 1.0 : t0;
const double t1 = options.bySpeed ? options.initSpeed : t0;
Update( t1, options );
}
@ -558,25 +558,33 @@ struct AudioIoCallback::ScrubState
{
// Called by the thread that calls AudioIO::FillBuffers
startSample = endSample = duration = -1LL;
sampleCount s0Init;
Message message( mMessage.Read() );
if ( !mStarted ) {
// Make some initial silence
const sampleCount s0 { llrint( mRate *
s0Init = llrint( mRate *
std::max( message.options.minTime,
std::min( message.options.maxTime, mStartTime ) ) ) };
mData.mS0 = mData.mS1 = s0;
mData.mGoal = -1;
mData.mDuration = duration = inDuration;
mData.mSilence = 0;
mStarted = true;
std::min( message.options.maxTime, mStartTime ) ) );
// Make some initial silence. This is not needed in the case of
// keyboard scrubbing or play-at-speed, because the initial speed
// is known when this function is called the first time.
if ( !(message.options.isKeyboardScrubbing ||
message.options.isPlayingAtSpeed) ) {
mData.mS0 = mData.mS1 = s0Init;
mData.mGoal = -1;
mData.mDuration = duration = inDuration;
mData.mSilence = 0;
}
}
else {
if (mStarted || message.options.isKeyboardScrubbing ||
message.options.isPlayingAtSpeed) {
Data newData;
inDuration += mAccumulatedSeekDuration;
// Use the previous end as NEW start.
const auto s0 = mData.mS1;
// If already started, use the previous end as NEW start.
const auto s0 = mStarted ? mData.mS1 : s0Init;
const sampleCount s1 ( message.options.bySpeed
? s0.as_double() +
lrint(inDuration.as_double() * message.end) // end is a speed
@ -593,6 +601,8 @@ struct AudioIoCallback::ScrubState
mData = newData;
};
mStarted = true;
Data &entry = mData;
if ( mStopped.load( std::memory_order_relaxed ) ) {
// We got the shut-down signal, or we discarded all the work.

View File

@ -53,7 +53,8 @@ struct ScrubbingOptions {
double delay {};
// Limiting values for the speed of a scrub interval:
// Initial and limiting values for the speed of a scrub interval:
double initSpeed { 1.0 };
double minSpeed { 0.0 };
double maxSpeed { 1.0 };

View File

@ -527,6 +527,7 @@ bool Scrubber::StartSpeedPlay(double speed, double time0, double time1)
options.pScrubbingOptions = &mOptions;
options.envelope = nullptr;
mOptions.delay = (ScrubPollInterval_ms / 1000.0);
mOptions.initSpeed = speed;
mOptions.minSpeed = speed -0.01;
mOptions.maxSpeed = speed +0.01;
@ -602,12 +603,11 @@ bool Scrubber::StartKeyboardScrubbing(double time0, bool backwards)
options.envelope = nullptr;
// delay and minStutterTime are used in AudioIO::AllocateBuffers() for setting the
// values of mPlaybackQueueMinimum and mPlaybackSamplesToCopy respectively. minStutterTime
// is set lower here than in mouse scrubbing to ensure that there is not a long
// delay before the start of the playback of the audio.
// values of mPlaybackQueueMinimum and mPlaybackSamplesToCopy respectively.
mOptions.delay = (ScrubPollInterval_ms / 1000.0);
mOptions.minStutterTime = mOptions.delay;
mOptions.initSpeed = GetKeyboardScrubbingSpeed();
mOptions.minSpeed = ScrubbingOptions::MinAllowedScrubSpeed();
mOptions.maxSpeed = ScrubbingOptions::MaxAllowedScrubSpeed();
mOptions.minTime = 0;