mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-28 22:28:44 +02:00
Bugs 925, 926, 928 fixed again, better, for double click and shift too
This commit is contained in:
parent
5c62b80bc4
commit
3c88f8ce4d
@ -370,10 +370,13 @@ So a small, fixed queue size should be adequate.
|
|||||||
struct AudioIO::ScrubQueue
|
struct AudioIO::ScrubQueue
|
||||||
{
|
{
|
||||||
ScrubQueue(double t0, double t1, wxLongLong startClockMillis,
|
ScrubQueue(double t0, double t1, wxLongLong startClockMillis,
|
||||||
|
double minTime, double maxTime,
|
||||||
double rate, double maxSpeed, double minStutter)
|
double rate, double maxSpeed, double minStutter)
|
||||||
: mTrailingIdx(0)
|
: mTrailingIdx(0)
|
||||||
, mMiddleIdx(1)
|
, mMiddleIdx(1)
|
||||||
, mLeadingIdx(2)
|
, mLeadingIdx(2)
|
||||||
|
, mMinSample(minTime * rate)
|
||||||
|
, mMaxSample(maxTime * rate)
|
||||||
, mRate(rate)
|
, mRate(rate)
|
||||||
, mMinStutter(lrint(std::max(0.0, minStutter) * mRate))
|
, mMinStutter(lrint(std::max(0.0, minStutter) * mRate))
|
||||||
, mLastScrubTimeMillis(startClockMillis)
|
, mLastScrubTimeMillis(startClockMillis)
|
||||||
@ -505,7 +508,8 @@ private:
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
bool Init(long s0, long s1, long duration, Entry *previous,
|
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)
|
if (duration <= 0)
|
||||||
return false;
|
return false;
|
||||||
@ -539,39 +543,76 @@ private:
|
|||||||
maxed = true;
|
maxed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxed)
|
if (speed < GetMinScrubSpeed())
|
||||||
{
|
|
||||||
// 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())
|
|
||||||
// Mixers were set up to go only so slowly, not slower.
|
// Mixers were set up to go only so slowly, not slower.
|
||||||
// This will put a request for some silence in the work queue.
|
// This will put a request for some silence in the work queue.
|
||||||
speed = 0.0;
|
speed = 0.0;
|
||||||
|
|
||||||
// No more rejections.
|
|
||||||
|
|
||||||
// Before we change s1:
|
// Before we change s1:
|
||||||
mGoal = maxed ? s1 : -1;
|
mGoal = maxed ? s1 : -1;
|
||||||
|
|
||||||
// May change s1 or s0 to match speed change:
|
// May change s1 or s0 to match speed change:
|
||||||
long diff = lrint(speed * duration);
|
|
||||||
if (adjustStart)
|
if (adjustStart)
|
||||||
{
|
{
|
||||||
|
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)
|
if (s0 < s1)
|
||||||
s0 = s1 - diff;
|
s0 = s1 - diff;
|
||||||
else
|
else
|
||||||
s0 = s1 + diff;
|
s0 = s1 + diff;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// adjust end
|
// adjust end
|
||||||
|
const long diff = lrint(speed * duration);
|
||||||
if (s0 < s1)
|
if (s0 < s1)
|
||||||
s1 = s0 + diff;
|
s1 = s0 + diff;
|
||||||
else
|
else
|
||||||
s1 = s0 - diff;
|
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;
|
mS0 = s0;
|
||||||
@ -614,7 +655,8 @@ private:
|
|||||||
? s0 + lrint(duration * end) // end is a speed
|
? s0 + lrint(duration * end) // end is a speed
|
||||||
: lrint(end * mRate); // end is a time
|
: lrint(end * mRate); // end is a time
|
||||||
const bool success =
|
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)
|
if (success)
|
||||||
mLastScrubTimeMillis = clockTime;
|
mLastScrubTimeMillis = clockTime;
|
||||||
return success;
|
return success;
|
||||||
@ -625,6 +667,7 @@ private:
|
|||||||
unsigned mTrailingIdx;
|
unsigned mTrailingIdx;
|
||||||
unsigned mMiddleIdx;
|
unsigned mMiddleIdx;
|
||||||
unsigned mLeadingIdx;
|
unsigned mLeadingIdx;
|
||||||
|
const long mMinSample, mMaxSample;
|
||||||
const double mRate;
|
const double mRate;
|
||||||
const long mMinStutter;
|
const long mMinStutter;
|
||||||
wxLongLong mLastScrubTimeMillis;
|
wxLongLong mLastScrubTimeMillis;
|
||||||
@ -1787,6 +1830,7 @@ int AudioIO::StartStream(WaveTrackArray playbackTracks,
|
|||||||
{
|
{
|
||||||
mScrubQueue =
|
mScrubQueue =
|
||||||
new ScrubQueue(mT0, mT1, options.scrubStartClockTimeMillis,
|
new ScrubQueue(mT0, mT1, options.scrubStartClockTimeMillis,
|
||||||
|
0.0, options.maxScrubTime,
|
||||||
sampleRate, maxScrubSpeed, minScrubStutter);
|
sampleRate, maxScrubSpeed, minScrubStutter);
|
||||||
mScrubDuration = 0;
|
mScrubDuration = 0;
|
||||||
mSilentScrub = false;
|
mSilentScrub = false;
|
||||||
|
@ -90,6 +90,7 @@ struct AudioIOStartStreamOptions
|
|||||||
, maxScrubSpeed(1.0)
|
, maxScrubSpeed(1.0)
|
||||||
, minScrubStutter(0.0)
|
, minScrubStutter(0.0)
|
||||||
, scrubStartClockTimeMillis(-1)
|
, scrubStartClockTimeMillis(-1)
|
||||||
|
, maxScrubTime(0.0)
|
||||||
#endif
|
#endif
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -117,6 +118,9 @@ struct AudioIOStartStreamOptions
|
|||||||
// Scrubbing needs the time of start of the mouse movement that began
|
// Scrubbing needs the time of start of the mouse movement that began
|
||||||
// the scrub:
|
// the scrub:
|
||||||
wxLongLong scrubStartClockTimeMillis;
|
wxLongLong scrubStartClockTimeMillis;
|
||||||
|
|
||||||
|
// usually from TrackList::GetEndTime()
|
||||||
|
double maxScrubTime;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2381,6 +2381,7 @@ bool TrackPanel::MaybeStartScrubbing(wxMouseEvent &event)
|
|||||||
// but it may be varied during the scrub.
|
// but it may be varied during the scrub.
|
||||||
mMaxScrubSpeed = options.maxScrubSpeed =
|
mMaxScrubSpeed = options.maxScrubSpeed =
|
||||||
p->GetTranscriptionToolBar()->GetPlaySpeed();
|
p->GetTranscriptionToolBar()->GetPlaySpeed();
|
||||||
|
options.maxScrubTime = mTracks->GetEndTime();
|
||||||
const bool cutPreview = false;
|
const bool cutPreview = false;
|
||||||
const bool backwards = time1 < time0;
|
const bool backwards = time1 < time0;
|
||||||
#ifdef EXPERIMENTAL_SCRUBBING_SCROLL_WHEEL
|
#ifdef EXPERIMENTAL_SCRUBBING_SCROLL_WHEEL
|
||||||
@ -2412,11 +2413,7 @@ bool TrackPanel::MaybeStartScrubbing(wxMouseEvent &event)
|
|||||||
bool TrackPanel::ContinueScrubbing(wxCoord position, bool maySkip)
|
bool TrackPanel::ContinueScrubbing(wxCoord position, bool maySkip)
|
||||||
{
|
{
|
||||||
wxCoord leadPosition = position;
|
wxCoord leadPosition = position;
|
||||||
double newEnd =
|
double newEnd = PositionToTime(leadPosition, GetLeftOffset());
|
||||||
std::max(0.0,
|
|
||||||
std::min(PositionToTime(leadPosition, GetLeftOffset()),
|
|
||||||
mTracks->GetEndTime()
|
|
||||||
));
|
|
||||||
|
|
||||||
if (maySkip)
|
if (maySkip)
|
||||||
// Cause OnTimer() to suppress the speed display
|
// Cause OnTimer() to suppress the speed display
|
||||||
|
Loading…
x
Reference in New Issue
Block a user