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:
parent
55e44cdc83
commit
e0302257c5
@ -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.
|
||||
|
@ -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 };
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user