1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-02 00:29:41 +02:00

Bugs 925, 926, 928 fixed again, better, for double click and shift too

This commit is contained in:
Paul Licameli 2015-05-24 17:31:00 -04:00
parent 5c62b80bc4
commit 3c88f8ce4d
3 changed files with 67 additions and 22 deletions

View File

@ -370,10 +370,13 @@ So a small, fixed queue size should be adequate.
struct AudioIO::ScrubQueue
{
ScrubQueue(double t0, double t1, wxLongLong startClockMillis,
double minTime, double maxTime,
double rate, double maxSpeed, double minStutter)
: mTrailingIdx(0)
, mMiddleIdx(1)
, mLeadingIdx(2)
, mMinSample(minTime * rate)
, mMaxSample(maxTime * rate)
, mRate(rate)
, mMinStutter(lrint(std::max(0.0, minStutter) * mRate))
, mLastScrubTimeMillis(startClockMillis)
@ -505,7 +508,8 @@ private:
{}
bool Init(long s0, long s1, long duration, Entry *previous,
double maxSpeed, long minStutter, bool adjustStart)
double maxSpeed, long minStutter, long minSample, long maxSample,
bool adjustStart)
{
if (duration <= 0)
return false;
@ -539,39 +543,76 @@ private:
maxed = true;
}
if (maxed)
{
// When playback follows a fast mouse movement by "stuttering"
// at maximum playback, don't make stutters too short to be useful.
if (adjustStart && duration < minStutter)
return false;
}
else if (speed < GetMinScrubSpeed())
if (speed < GetMinScrubSpeed())
// Mixers were set up to go only so slowly, not slower.
// This will put a request for some silence in the work queue.
speed = 0.0;
// No more rejections.
// Before we change s1:
mGoal = maxed ? s1 : -1;
// May change s1 or s0 to match speed change:
long diff = lrint(speed * duration);
if (adjustStart)
{
if (s0 < s1)
s0 = s1 - diff;
else
s0 = s1 + diff;
bool silent = false;
// Adjust s1 first, and duration, if s1 is out of bounds.
// (Assume s0 is in bounds, because it is the last scrub's s1 which was checked.)
if (s1 != s0)
{
const long newS1 = std::max(minSample, std::min(maxSample, s1));
if (s1 != newS1)
{
long newDuration = long(duration * double(newS1 - s0) / (s1 - s0));
s1 = newS1;
if (newDuration == 0)
// Enqueue a silent scrub with s0 == s1
silent = true;
else
// Shorten
duration = newDuration;
}
}
if (!silent)
{
// When playback follows a fast mouse movement by "stuttering"
// at maximum playback, don't make stutters too short to be useful.
if (maxed && duration < minStutter)
return false;
const long diff = lrint(speed * duration);
if (s0 < s1)
s0 = s1 - diff;
else
s0 = s1 + diff;
}
}
else
{
// adjust end
const long diff = lrint(speed * duration);
if (s0 < s1)
s1 = s0 + diff;
else
s1 = s0 - diff;
// Adjust s1 again, and duration, if s1 is out of bounds. (Assume s0 is in bounds.)
if (s1 != s0)
{
const long newS1 = std::max(minSample, std::min(maxSample, s1));
if (s1 != newS1)
{
long newDuration = long(duration * double(newS1 - s0) / (s1 - s0));
s1 = newS1;
if (newDuration == 0)
// Enqueue a silent scrub with s0 == s1
;
else
// Shorten
duration = newDuration;
}
}
}
mS0 = s0;
@ -614,7 +655,8 @@ private:
? s0 + lrint(duration * end) // end is a speed
: lrint(end * mRate); // end is a time
const bool success =
entry.Init(s0, s1, duration, previous, maxSpeed, mMinStutter, maySkip);
entry.Init(s0, s1, duration, previous, maxSpeed, mMinStutter,
mMinSample, mMaxSample, maySkip);
if (success)
mLastScrubTimeMillis = clockTime;
return success;
@ -625,6 +667,7 @@ private:
unsigned mTrailingIdx;
unsigned mMiddleIdx;
unsigned mLeadingIdx;
const long mMinSample, mMaxSample;
const double mRate;
const long mMinStutter;
wxLongLong mLastScrubTimeMillis;
@ -1787,6 +1830,7 @@ int AudioIO::StartStream(WaveTrackArray playbackTracks,
{
mScrubQueue =
new ScrubQueue(mT0, mT1, options.scrubStartClockTimeMillis,
0.0, options.maxScrubTime,
sampleRate, maxScrubSpeed, minScrubStutter);
mScrubDuration = 0;
mSilentScrub = false;

View File

@ -90,6 +90,7 @@ struct AudioIOStartStreamOptions
, maxScrubSpeed(1.0)
, minScrubStutter(0.0)
, scrubStartClockTimeMillis(-1)
, maxScrubTime(0.0)
#endif
{}
@ -117,6 +118,9 @@ struct AudioIOStartStreamOptions
// Scrubbing needs the time of start of the mouse movement that began
// the scrub:
wxLongLong scrubStartClockTimeMillis;
// usually from TrackList::GetEndTime()
double maxScrubTime;
#endif
};

View File

@ -2381,6 +2381,7 @@ bool TrackPanel::MaybeStartScrubbing(wxMouseEvent &event)
// but it may be varied during the scrub.
mMaxScrubSpeed = options.maxScrubSpeed =
p->GetTranscriptionToolBar()->GetPlaySpeed();
options.maxScrubTime = mTracks->GetEndTime();
const bool cutPreview = false;
const bool backwards = time1 < time0;
#ifdef EXPERIMENTAL_SCRUBBING_SCROLL_WHEEL
@ -2412,11 +2413,7 @@ bool TrackPanel::MaybeStartScrubbing(wxMouseEvent &event)
bool TrackPanel::ContinueScrubbing(wxCoord position, bool maySkip)
{
wxCoord leadPosition = position;
double newEnd =
std::max(0.0,
std::min(PositionToTime(leadPosition, GetLeftOffset()),
mTracks->GetEndTime()
));
double newEnd = PositionToTime(leadPosition, GetLeftOffset());
if (maySkip)
// Cause OnTimer() to suppress the speed display