mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-02 00:29:41 +02:00
Merge: Scroll-seek improvements
This commit is contained in:
commit
eca5c25ec0
@ -403,7 +403,7 @@ struct AudioIO::ScrubQueue
|
||||
}
|
||||
~ScrubQueue() {}
|
||||
|
||||
bool Producer(double startTime, double end, double maxSpeed, bool bySpeed, bool maySkip)
|
||||
bool Producer(double end, double maxSpeed, bool bySpeed, bool maySkip)
|
||||
{
|
||||
// Main thread indicates a scrubbing interval
|
||||
|
||||
@ -415,9 +415,8 @@ struct AudioIO::ScrubQueue
|
||||
{
|
||||
Entry &previous = mEntries[(mLeadingIdx + Size - 1) % Size];
|
||||
|
||||
if (startTime < 0.0)
|
||||
// Use the previous end as new start.
|
||||
startTime = previous.mS1 / mRate;
|
||||
// Use the previous end as new start.
|
||||
const double startTime = previous.mS1 / mRate;
|
||||
// Might reject the request because of zero duration,
|
||||
// or a too-short "stutter"
|
||||
const bool success =
|
||||
@ -518,7 +517,7 @@ private:
|
||||
bool maxed = false;
|
||||
|
||||
// May change the requested speed (or reject)
|
||||
if (speed > maxSpeed)
|
||||
if (!adjustStart && speed > maxSpeed)
|
||||
{
|
||||
// Reduce speed to the maximum selected in the user interface.
|
||||
speed = maxSpeed;
|
||||
@ -579,10 +578,10 @@ private:
|
||||
{
|
||||
// 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)
|
||||
if (duration < minStutter)
|
||||
return false;
|
||||
|
||||
const long diff = lrint(speed * duration);
|
||||
// Limit diff because this is seeking.
|
||||
const long diff = lrint(std::min(1.0, speed) * duration);
|
||||
if (s0 < s1)
|
||||
s0 = s1 - diff;
|
||||
else
|
||||
@ -2413,7 +2412,7 @@ bool AudioIO::IsPaused()
|
||||
bool AudioIO::EnqueueScrubByPosition(double endTime, double maxSpeed, bool maySkip)
|
||||
{
|
||||
if (mScrubQueue)
|
||||
return mScrubQueue->Producer(-1.0, endTime, maxSpeed, false, maySkip);
|
||||
return mScrubQueue->Producer(endTime, maxSpeed, false, maySkip);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
@ -2421,7 +2420,7 @@ bool AudioIO::EnqueueScrubByPosition(double endTime, double maxSpeed, bool maySk
|
||||
bool AudioIO::EnqueueScrubBySignedSpeed(double speed, double maxSpeed, bool maySkip)
|
||||
{
|
||||
if (mScrubQueue)
|
||||
return mScrubQueue->Producer(-1.0, speed, maxSpeed, true, maySkip);
|
||||
return mScrubQueue->Producer(speed, maxSpeed, true, maySkip);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
@ -1049,7 +1049,7 @@ void TrackPanel::OnTimer()
|
||||
{
|
||||
wxMouseState state(::wxGetMouseState());
|
||||
wxCoord position = state.GetX();
|
||||
const bool seek = mScrubSeekPress || state.LeftIsDown();
|
||||
const bool seek = mScrubSeekPress || PollIsSeeking();
|
||||
ScreenToClient(&position, NULL);
|
||||
if (ContinueScrubbing(position, mScrubHasFocus, seek))
|
||||
mScrubSeekPress = false;
|
||||
@ -2322,9 +2322,46 @@ double TrackPanel::FindScrubSpeed(double timeAtMouse) const
|
||||
result *= -1.0;
|
||||
return result;
|
||||
}
|
||||
|
||||
double TrackPanel::FindSeekSpeed(double timeAtMouse) const
|
||||
{
|
||||
// Map a time (which was mapped from a mouse position)
|
||||
// to a signed skip speed: a multiplier of the stutter duration,
|
||||
// by which to advance the play position.
|
||||
// (The stutter will play at unit speed.)
|
||||
|
||||
// Times near the midline of the screen map to skip-less play,
|
||||
// and the extremes to a value proportional to maximum scrub speed.
|
||||
|
||||
// If the maximum scrubbing speed defaults to 1.0 when you begin to scroll-scrub,
|
||||
// the extreme skipping for scroll-seek needs to be larger to be useful.
|
||||
static const double ARBITRARY_MULTIPLIER = 10.0;
|
||||
const double extreme = std::max(1.0, mMaxScrubSpeed * ARBITRARY_MULTIPLIER);
|
||||
|
||||
// Width of visible track area, in time terms:
|
||||
const double screen = mViewInfo->screen;
|
||||
const double halfScreen = screen / 2.0;
|
||||
const double origin = mViewInfo->h + halfScreen;
|
||||
|
||||
// The snapping zone is this fraction of screen, on each side of the
|
||||
// center line:
|
||||
const double snap = 0.05;
|
||||
const double fraction =
|
||||
std::max(snap, std::min(1.0, fabs(timeAtMouse - origin) / halfScreen));
|
||||
|
||||
double result = 1.0 + ((fraction - snap) / (1.0 - snap)) * (extreme - 1.0);
|
||||
if (timeAtMouse < origin)
|
||||
result *= -1.0;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
|
||||
bool TrackPanel::PollIsSeeking()
|
||||
{
|
||||
return ::wxGetMouseState().LeftIsDown();
|
||||
}
|
||||
|
||||
bool TrackPanel::IsScrubbing()
|
||||
{
|
||||
if (mScrubToken <= 0)
|
||||
@ -2427,27 +2464,27 @@ bool TrackPanel::MaybeStartScrubbing(wxMouseEvent &event)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TrackPanel::ContinueScrubbing(wxCoord position, bool hasFocus, bool maySkip)
|
||||
bool TrackPanel::ContinueScrubbing(wxCoord position, bool hasFocus, bool seek)
|
||||
{
|
||||
// When we don't have focus, enqueue silent scrubs until we regain focus.
|
||||
if (!hasFocus)
|
||||
return gAudioIO->EnqueueScrubBySignedSpeed(0, mMaxScrubSpeed, maySkip);
|
||||
return gAudioIO->EnqueueScrubBySignedSpeed(0, mMaxScrubSpeed, false);
|
||||
|
||||
const double newEnd = PositionToTime(position, GetLeftOffset());
|
||||
const double time = PositionToTime(position, GetLeftOffset());
|
||||
|
||||
if (maySkip)
|
||||
if (seek)
|
||||
// Cause OnTimer() to suppress the speed display
|
||||
mScrubSpeedDisplayCountdown = 1;
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
if (mSmoothScrollingScrub && !maySkip) {
|
||||
const double speed = FindScrubSpeed(newEnd);
|
||||
return gAudioIO->EnqueueScrubBySignedSpeed(speed, mMaxScrubSpeed, maySkip);
|
||||
if (mSmoothScrollingScrub) {
|
||||
const double speed = seek ? FindSeekSpeed(time) : FindScrubSpeed(time);
|
||||
return gAudioIO->EnqueueScrubBySignedSpeed(speed, mMaxScrubSpeed, seek);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return gAudioIO->EnqueueScrubByPosition
|
||||
(newEnd, maySkip ? 1.0 : mMaxScrubSpeed, maySkip);
|
||||
(time, seek ? 1.0 : mMaxScrubSpeed, seek);
|
||||
}
|
||||
|
||||
bool TrackPanel::StopScrubbing()
|
||||
@ -7348,19 +7385,20 @@ void TrackPanel::DrawEverythingElse(wxDC * dc,
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
|
||||
void TrackPanel::DrawScrubSpeed(wxDC &dc)
|
||||
{
|
||||
// Halt scrubbing and associated display when some other program
|
||||
// has focus
|
||||
if (!mScrubHasFocus)
|
||||
return;
|
||||
|
||||
// Don't draw it during stutter play with shift down
|
||||
if (!::wxGetMouseState().LeftDown() && (
|
||||
|
||||
mScrubSpeedDisplayCountdown > 0
|
||||
|
||||
|
||||
const bool seeking = PollIsSeeking();
|
||||
if (// Draw for (non-scroll) scrub, sometimes, but never for seek
|
||||
(!seeking && mScrubSpeedDisplayCountdown > 0)
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
|| mSmoothScrollingScrub
|
||||
// Draw always for scroll-scrub and for scroll-seek
|
||||
|| mSmoothScrollingScrub
|
||||
#endif
|
||||
|
||||
)) {
|
||||
) {
|
||||
int panelWidth, panelHeight;
|
||||
GetSize(&panelWidth, &panelHeight);
|
||||
|
||||
@ -7373,16 +7411,23 @@ void TrackPanel::DrawScrubSpeed(wxDC &dc)
|
||||
const double speed =
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
mSmoothScrollingScrub
|
||||
? FindScrubSpeed(PositionToTime(xx, GetLeftOffset()))
|
||||
? seeking
|
||||
? FindSeekSpeed(PositionToTime(xx, GetLeftOffset()))
|
||||
: FindScrubSpeed(PositionToTime(xx, GetLeftOffset()))
|
||||
:
|
||||
#endif
|
||||
mMaxScrubSpeed;
|
||||
mMaxScrubSpeed;
|
||||
|
||||
const wxChar *format =
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
mSmoothScrollingScrub ? wxT("%+.2f")
|
||||
mSmoothScrollingScrub
|
||||
? seeking
|
||||
? wxT("%+.2fX")
|
||||
: wxT("%+.2f")
|
||||
:
|
||||
#endif
|
||||
wxT("%.2f");
|
||||
wxT("%.2f");
|
||||
|
||||
wxString text(wxString::Format(format, speed));
|
||||
|
||||
static const wxFont labelFont(24, wxSWISS, wxNORMAL, wxNORMAL);
|
||||
|
@ -302,9 +302,11 @@ class AUDACITY_DLL_API TrackPanel:public wxPanel {
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
double FindScrubSpeed(double timeAtMouse) const;
|
||||
double FindSeekSpeed(double timeAtMouse) const;
|
||||
#endif
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_BASIC
|
||||
static bool PollIsSeeking();
|
||||
bool IsScrubbing();
|
||||
void MarkScrubStart(
|
||||
wxCoord xx
|
||||
@ -313,7 +315,7 @@ class AUDACITY_DLL_API TrackPanel:public wxPanel {
|
||||
#endif
|
||||
);
|
||||
bool MaybeStartScrubbing(wxMouseEvent &event);
|
||||
bool ContinueScrubbing(wxCoord position, bool hasFocus, bool maySkip);
|
||||
bool ContinueScrubbing(wxCoord position, bool hasFocus, bool seek);
|
||||
bool StopScrubbing();
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user