From 46bf5a82fcb20a5ade26c456fec8519172b7bc1d Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Thu, 6 Jun 2019 09:21:01 -0400 Subject: [PATCH] Don't pass whole TimeTrack to Ruler or Mixer... ... they need only the information in a (Bounded)Envelope. --- src/AdornedRulerPanel.cpp | 2 +- src/AudioIO.cpp | 57 ++++++++++++++++++++------- src/AudioIO.h | 8 ++-- src/Mix.cpp | 44 +++++++++++++++------ src/Mix.h | 10 ++--- src/ProjectAudioManager.cpp | 7 +++- src/TimeTrack.cpp | 27 ++++--------- src/TimeTrack.h | 32 --------------- src/export/Export.cpp | 4 +- src/export/Export.h | 1 - src/toolbars/ControlToolBar.cpp | 8 +--- src/toolbars/ControlToolBar.h | 1 - src/toolbars/TranscriptionToolBar.cpp | 22 ++++++----- src/toolbars/TranscriptionToolBar.h | 4 +- src/tracks/ui/Scrubbing.cpp | 4 +- src/widgets/Ruler.cpp | 28 +++++++++---- src/widgets/Ruler.h | 6 +-- 17 files changed, 142 insertions(+), 123 deletions(-) diff --git a/src/AdornedRulerPanel.cpp b/src/AdornedRulerPanel.cpp index 657e9f2e3..88bbd0899 100644 --- a/src/AdornedRulerPanel.cpp +++ b/src/AdornedRulerPanel.cpp @@ -1626,7 +1626,7 @@ void AdornedRulerPanel::StartQPPlay(bool looped, bool cutPreview) if (!cutPreview) options.pStartTime = &oldStart; else - options.timeTrack = NULL; + options.envelope = nullptr; auto mode = cutPreview ? PlayMode::cutPreviewPlay diff --git a/src/AudioIO.cpp b/src/AudioIO.cpp index 640a46770..3522903bf 100644 --- a/src/AudioIO.cpp +++ b/src/AudioIO.cpp @@ -409,7 +409,7 @@ callbacks for these events. \class AudioIOStartStreamOptions \brief struct holding stream options, including a pointer to the -TimeTrack and AudioIOListener and whether the playback is looped. +time warp info and AudioIOListener and whether the playback is looped. *//*******************************************************************/ @@ -458,7 +458,7 @@ TimeTrack and AudioIOListener and whether the playback is looped. #include "Prefs.h" #include "Project.h" #include "ProjectWindow.h" -#include "TimeTrack.h" +#include "Envelope.h" #include "WaveTrack.h" #include "AutoRecovery.h" @@ -2143,7 +2143,7 @@ bool AudioIO::AllocateBuffers( ScrubbingOptions::MaxAllowedScrubSpeed()) : #endif - Mixer::WarpOptions(mPlaybackSchedule.mTimeTrack); + Mixer::WarpOptions(mPlaybackSchedule.mEnvelope); mPlaybackQueueMinimum = mPlaybackSamplesToCopy; if (scrubbing) @@ -2806,9 +2806,9 @@ void AudioIO::PlaybackSchedule::Init( // the existing audio. (Unless we figured out the inverse warp of the // captured samples in real time.) // So just quietly ignore the time track. - mTimeTrack = nullptr; + mEnvelope = nullptr; else - mTimeTrack = options.timeTrack; + mEnvelope = options.envelope; mT0 = t0; if (pRecordingSchedule) @@ -2838,7 +2838,7 @@ void AudioIO::PlaybackSchedule::Init( const auto &scrubOptions = *options.pScrubbingOptions; if (pRecordingSchedule || Looping() || - mTimeTrack != NULL || + mEnvelope || scrubOptions.maxSpeed < ScrubbingOptions::MinAllowedScrubSpeed()) { wxASSERT(false); scrubbing = false; @@ -4173,7 +4173,7 @@ static Alg_update gAllNotesOff; // special event for loop ending double AudioIO::UncorrectedMidiEventTime() { double time; - if (mPlaybackSchedule.mTimeTrack) + if (mPlaybackSchedule.mEnvelope) time = mPlaybackSchedule.RealDuration(mNextEventTime - MidiLoopOffset()) + mPlaybackSchedule.mT0 + (mMidiLoopPasses * @@ -5633,6 +5633,35 @@ bool AudioIO::PlaybackSchedule::Overruns( double trackTime ) const return (ReversedTime() ? trackTime <= mT1 : trackTime >= mT1); } +namespace +{ +/** @brief Compute the duration (in seconds at playback) of the specified region of the track. + * + * Takes a region of the time track (specified by the unwarped time points in the project), and + * calculates how long it will actually take to play this region back, taking the time track's + * warping effects into account. + * @param t0 unwarped time to start calculation from + * @param t1 unwarped time to stop calculation at + * @return the warped duration in seconds + */ +double ComputeWarpedLength(const Envelope &env, double t0, double t1) +{ + return env.IntegralOfInverse(t0, t1); +} + +/** @brief Compute how much unwarped time must have elapsed if length seconds of warped time has + * elapsed + * + * @param t0 The unwarped time (seconds from project start) at which to start + * @param length How many seconds of warped time went past. + * @return The end point (in seconds from project start) as unwarped time + */ +double SolveWarpedLength(const Envelope &env, double t0, double length) +{ + return env.SolveIntegralOfInverse(t0, length); +} +} + double AudioIO::PlaybackSchedule::AdvancedTrackTime( double time, double realElapsed, double speed ) const { @@ -5643,7 +5672,7 @@ double AudioIO::PlaybackSchedule::AdvancedTrackTime( if ( fabs(mT0 - mT1) < 1e-9 ) return mT0; - if (mTimeTrack) { + if (mEnvelope) { wxASSERT( speed == 1.0 ); double total=0.0; @@ -5654,7 +5683,7 @@ double AudioIO::PlaybackSchedule::AdvancedTrackTime( // Avoid SolveWarpedLength time = mT1; else - time = mTimeTrack->SolveWarpedLength(time, realElapsed); + time = SolveWarpedLength(*mEnvelope, time, realElapsed); if (!Looping() || !Overruns( time )) break; @@ -5666,7 +5695,7 @@ double AudioIO::PlaybackSchedule::AdvancedTrackTime( // Avoid integrating again delta = total; else { - delta = mTimeTrack->ComputeWarpedLength(oldTime, mT1); + delta = ComputeWarpedLength(*mEnvelope, oldTime, mT1); if (oldTime == mT0) foundTotal = true, total = delta; } @@ -5762,8 +5791,8 @@ double AudioIO::TimeQueue::Consumer( size_t nSamples, double rate ) double AudioIO::PlaybackSchedule::TrackDuration(double realElapsed) const { - if (mTimeTrack) - return mTimeTrack->SolveWarpedLength(mT0, realElapsed); + if (mEnvelope) + return SolveWarpedLength(*mEnvelope, mT0, realElapsed); else return realElapsed; } @@ -5771,8 +5800,8 @@ double AudioIO::PlaybackSchedule::TrackDuration(double realElapsed) const double AudioIO::PlaybackSchedule::RealDuration(double trackTime1) const { double duration; - if (mTimeTrack) - duration = mTimeTrack->ComputeWarpedLength(mT0, trackTime1); + if (mEnvelope) + duration = ComputeWarpedLength(*mEnvelope, mT0, trackTime1); else duration = trackTime1 - mT0; return fabs(duration); diff --git a/src/AudioIO.h b/src/AudioIO.h index 69b887aa7..93af97fc4 100644 --- a/src/AudioIO.h +++ b/src/AudioIO.h @@ -57,7 +57,7 @@ class AudioIO; class RingBuffer; class Mixer; class Resample; -class TimeTrack; +class BoundedEnvelope; class AudioThread; class MeterPanel; class SelectedRegion; @@ -118,7 +118,7 @@ struct AudioIOStartStreamOptions explicit AudioIOStartStreamOptions(AudacityProject *pProject_, double rate_) : pProject{ pProject_ } - , timeTrack(NULL) + , envelope(nullptr) , listener(NULL) , rate(rate_) , playLooped(false) @@ -130,7 +130,7 @@ struct AudioIOStartStreamOptions AudacityProject *pProject{}; MeterPanel *captureMeter{}, *playbackMeter{}; - TimeTrack *timeTrack; + BoundedEnvelope *envelope; // for time warping AudioIOListener* listener; double rate; bool playLooped; @@ -668,7 +668,7 @@ protected: // with ComputeWarpedLength, it is now possible the calculate the warped length with 100% accuracy // (ignoring accumulated rounding errors during playback) which fixes the 'missing sound at the end' bug - const TimeTrack *mTimeTrack; + const BoundedEnvelope *mEnvelope; volatile enum { PLAY_STRAIGHT, diff --git a/src/Mix.cpp b/src/Mix.cpp index c1ce42b2f..5fcd72a97 100644 --- a/src/Mix.cpp +++ b/src/Mix.cpp @@ -31,6 +31,7 @@ #include #include +#include "Envelope.h" #include "WaveTrack.h" #include "Prefs.h" #include "Resample.h" @@ -143,10 +144,11 @@ void MixAndRender(TrackList *tracks, TrackFactory *trackFactory, endTime = mixEndTime; } + auto timeTrack = tracks->GetTimeTrack(); Mixer mixer(waveArray, // Throw to abort mix-and-render if read fails: true, - Mixer::WarpOptions(tracks->GetTimeTrack()), + Mixer::WarpOptions(timeTrack ? timeTrack->GetEnvelope() : nullptr), startTime, endTime, mono ? 1 : 2, maxBlockLen, false, rate, format); @@ -204,7 +206,7 @@ void MixAndRender(TrackList *tracks, TrackFactory *trackFactory, } Mixer::WarpOptions::WarpOptions(double min, double max) - : timeTrack(0), minSpeed(min), maxSpeed(max) + : minSpeed(min), maxSpeed(max) { if (minSpeed < 0) { @@ -253,7 +255,7 @@ Mixer::Mixer(const WaveTrackConstArray &inputTracks, mInputTrack[i].SetTrack(inputTracks[i]); mSamplePos[i] = inputTracks[i]->TimeToLongSamples(startTime); } - mTimeTrack = warpOptions.timeTrack; + mEnvelope = warpOptions.envelope; mT0 = startTime; mT1 = stopTime; mTime = startTime; @@ -301,11 +303,11 @@ Mixer::Mixer(const WaveTrackConstArray &inputTracks, mMaxFactor.resize(mNumInputTracks); for (size_t i = 0; iGetRate()); - if (mTimeTrack) { + if (mEnvelope) { // variable rate resampling mbVariableRates = true; - mMinFactor[i] = factor / mTimeTrack->GetRangeUpper(); - mMaxFactor[i] = factor / mTimeTrack->GetRangeLower(); + mMinFactor[i] = factor / mEnvelope->GetRangeUpper(); + mMaxFactor[i] = factor / mEnvelope->GetRangeLower(); } else if (warpOptions.minSpeed > 0.0 && warpOptions.maxSpeed > 0.0) { // variable rate resampling @@ -380,6 +382,26 @@ void MixBuffers(unsigned numChannels, int *channelFlags, float *gains, } } +namespace { + //Note: The meaning of this function has changed (December 2012) + //Previously this function did something that was close to the opposite (but not entirely accurate). + /** @brief Compute the integral warp factor between two non-warped time points + * + * Calculate the relative length increase of the chosen segment from the original sound. + * So if this time track has a low value (i.e. makes the sound slower), the NEW warped + * sound will be *longer* than the original sound, so the return value of this function + * is larger. + * @param t0 The starting time to calculate from + * @param t1 The ending time to calculate to + * @return The relative length increase of the chosen segment from the original sound. + */ +double ComputeWarpFactor(const Envelope &env, double t0, double t1) +{ + return env.AverageOfInverse(t0, t1); +} + +} + size_t Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache, sampleCount *pos, float *queue, int *queueStart, int *queueLen, @@ -474,7 +496,7 @@ size_t Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache, } double factor = initialWarp; - if (mTimeTrack) + if (mEnvelope) { //TODO-MB: The end time is wrong when the resampler doesn't use all input samples, // as a result of this the warp factor may be slightly wrong, so AudioIO will stop too soon @@ -482,11 +504,11 @@ size_t Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache, // without changing the way the resampler works, because the number of input samples that will be used // is unpredictable. Maybe it can be compensated later though. if (backwards) - factor *= mTimeTrack->ComputeWarpFactor - (t - (double)thisProcessLen / trackRate + tstep, t + tstep); + factor *= ComputeWarpFactor( *mEnvelope, + t - (double)thisProcessLen / trackRate + tstep, t + tstep); else - factor *= mTimeTrack->ComputeWarpFactor - (t, t + (double)thisProcessLen / trackRate); + factor *= ComputeWarpFactor( *mEnvelope, + t, t + (double)thisProcessLen / trackRate); } auto results = pResample->Process(factor, diff --git a/src/Mix.h b/src/Mix.h index 6afe5869b..39a66bb76 100644 --- a/src/Mix.h +++ b/src/Mix.h @@ -25,7 +25,7 @@ class Resample; class DirManager; -class TimeTrack; +class BoundedEnvelope; class TrackFactory; class TrackList; class WaveTrack; @@ -83,15 +83,15 @@ class AUDACITY_DLL_API Mixer { class WarpOptions { public: - explicit WarpOptions(const TimeTrack *t) - : timeTrack(t), minSpeed(0.0), maxSpeed(0.0) + explicit WarpOptions(const BoundedEnvelope *e) + : envelope(e), minSpeed(0.0), maxSpeed(0.0) {} WarpOptions(double min, double max); private: friend class Mixer; - const TimeTrack *timeTrack; + const BoundedEnvelope *envelope = nullptr; double minSpeed, maxSpeed; }; @@ -164,7 +164,7 @@ class AUDACITY_DLL_API Mixer { size_t mNumInputTracks; ArrayOf mInputTrack; bool mbVariableRates; - const TimeTrack *mTimeTrack; + const BoundedEnvelope *mEnvelope; ArrayOf mSamplePos; bool mApplyTrackGains; Doubles mEnvValues; diff --git a/src/ProjectAudioManager.cpp b/src/ProjectAudioManager.cpp index a86489843..9f6e42c39 100644 --- a/src/ProjectAudioManager.cpp +++ b/src/ProjectAudioManager.cpp @@ -24,6 +24,7 @@ Paul Licameli split from ProjectManager.cpp #include "ProjectHistory.h" #include "ProjectSettings.h" #include "ProjectWindow.h" +#include "TimeTrack.h" #include "toolbars/ControlToolBar.h" #include "widgets/ErrorDialog.h" #include "widgets/Warning.h" @@ -174,7 +175,8 @@ DefaultPlayOptions( AudacityProject &project ) ProjectSettings::Get( project ).GetRate() }; options.captureMeter = projectAudioIO.GetCaptureMeter(); options.playbackMeter = projectAudioIO.GetPlaybackMeter(); - options.timeTrack = TrackList::Get( project ).GetTimeTrack(); + auto timeTrack = TrackList::Get( project ).GetTimeTrack(); + options.envelope = timeTrack ? timeTrack->GetEnvelope() : nullptr; options.listener = &ProjectAudioManager::Get( project ); return options; } @@ -191,7 +193,8 @@ DefaultSpeedPlayOptions( AudacityProject &project ) AudioIOStartStreamOptions options{ &project, PlayAtSpeedRate }; options.captureMeter = projectAudioIO.GetCaptureMeter(); options.playbackMeter = projectAudioIO.GetPlaybackMeter(); - options.timeTrack = TrackList::Get( project ).GetTimeTrack(); + auto timeTrack = TrackList::Get( project ).GetTimeTrack(); + options.envelope = timeTrack ? timeTrack->GetEnvelope() : nullptr; options.listener = &ProjectAudioManager::Get( project ); return options; } diff --git a/src/TimeTrack.cpp b/src/TimeTrack.cpp index 34e72e388..255a08f1c 100644 --- a/src/TimeTrack.cpp +++ b/src/TimeTrack.cpp @@ -58,11 +58,12 @@ TimeTrack::TimeTrack(const std::shared_ptr &projDirManager, const Zo { mHeight = 100; + mEnvelope = std::make_unique(true, TIMETRACK_MIN, TIMETRACK_MAX, 1.0); + SetRangeLower( 0.9 ); SetRangeUpper( 1.1 ); mDisplayLog = false; - mEnvelope = std::make_unique(true, TIMETRACK_MIN, TIMETRACK_MAX, 1.0); mEnvelope->SetTrackLen(DBL_MAX); mEnvelope->SetOffset(0); @@ -88,6 +89,10 @@ TimeTrack::TimeTrack(const TimeTrack &orig, double *pT0, double *pT1) } else mEnvelope = std::make_unique( *orig.mEnvelope ); + + SetRangeLower(orig.GetRangeLower()); + SetRangeUpper(orig.GetRangeUpper()); + mEnvelope->SetTrackLen( len ); mEnvelope->SetOffset(0); @@ -104,8 +109,6 @@ void TimeTrack::Init(const TimeTrack &orig) Track::Init(orig); SetDefaultName(orig.GetDefaultName()); SetName(orig.GetName()); - SetRangeLower(orig.GetRangeLower()); - SetRangeUpper(orig.GetRangeUpper()); SetDisplayLog(orig.GetDisplayLog()); } @@ -188,22 +191,6 @@ void TimeTrack::SetInterpolateLog(bool interpolateLog) { mEnvelope->SetExponential(interpolateLog); } -//Compute the (average) warp factor between two non-warped time points -double TimeTrack::ComputeWarpFactor(double t0, double t1) const -{ - return GetEnvelope()->AverageOfInverse(t0, t1); -} - -double TimeTrack::ComputeWarpedLength(double t0, double t1) const -{ - return GetEnvelope()->IntegralOfInverse(t0, t1); -} - -double TimeTrack::SolveWarpedLength(double t0, double length) const -{ - return GetEnvelope()->SolveIntegralOfInverse(t0, length); -} - bool TimeTrack::HandleXMLTag(const wxChar *tag, const wxChar **attrs) { if (!wxStrcmp(tag, wxT("timetrack"))) { @@ -335,7 +322,7 @@ void TimeTrack::Draw // than the current value. mRuler->SetFlip(GetHeight() > 75 ? true : true); // MB: so why don't we just call Invalidate()? :) mRuler->SetTickColour( theTheme.Colour( clrTrackPanelText )); - mRuler->Draw(dc, this); + mRuler->Draw(dc, GetEnvelope()); Doubles envValues{ size_t(mid.width) }; EnvelopeEditor::GetValues( *GetEnvelope(), diff --git a/src/TimeTrack.h b/src/TimeTrack.h index 726e1a4d7..85d40cccb 100644 --- a/src/TimeTrack.h +++ b/src/TimeTrack.h @@ -83,38 +83,6 @@ class TimeTrack final : public Track { BoundedEnvelope *GetEnvelope() { return mEnvelope.get(); } const BoundedEnvelope *GetEnvelope() const { return mEnvelope.get(); } - //Note: The meaning of this function has changed (December 2012) - //Previously this function did something that was close to the opposite (but not entirely accurate). - /** @brief Compute the integral warp factor between two non-warped time points - * - * Calculate the relative length increase of the chosen segment from the original sound. - * So if this time track has a low value (i.e. makes the sound slower), the NEW warped - * sound will be *longer* than the original sound, so the return value of this function - * is larger. - * @param t0 The starting time to calculate from - * @param t1 The ending time to calculate to - * @return The relative length increase of the chosen segment from the original sound. - */ - double ComputeWarpFactor(double t0, double t1) const; - /** @brief Compute the duration (in seconds at playback) of the specified region of the track. - * - * Takes a region of the time track (specified by the unwarped time points in the project), and - * calculates how long it will actually take to play this region back, taking the time track's - * warping effects into account. - * @param t0 unwarped time to start calculation from - * @param t1 unwarped time to stop calculation at - * @return the warped duration in seconds - */ - double ComputeWarpedLength(double t0, double t1) const; - /** @brief Compute how much unwarped time must have elapsed if length seconds of warped time has - * elapsed - * - * @param t0 The unwarped time (seconds from project start) at which to start - * @param length How many seconds of warped time went past. - * @return The end point (in seconds from project start) as unwarped time - */ - double SolveWarpedLength(double t0, double length) const; - // Get/Set the speed-warping range, as percentage of original speed (e.g. 90%-110%) double GetRangeLower() const; diff --git a/src/export/Export.cpp b/src/export/Export.cpp index 6dfa8c991..da42dd0e7 100644 --- a/src/export/Export.cpp +++ b/src/export/Export.cpp @@ -68,6 +68,7 @@ #include "../ProjectSettings.h" #include "../ProjectWindow.h" #include "../ShuttleGui.h" +#include "../TimeTrack.h" #include "../WaveTrack.h" #include "../widgets/AudacityMessageBox.h" #include "../widgets/Warning.h" @@ -250,11 +251,12 @@ std::unique_ptr ExportPlugin::CreateMixer(const TrackList &tracks, const WaveTrackConstArray inputTracks = tracks.GetWaveTrackConstArray(selectionOnly, false); const TimeTrack *timeTrack = tracks.GetTimeTrack(); + auto envelope = timeTrack ? timeTrack->GetEnvelope() : nullptr; // MB: the stop time should not be warped, this was a bug. return std::make_unique(inputTracks, // Throw, to stop exporting, if read fails: true, - Mixer::WarpOptions(timeTrack), + Mixer::WarpOptions(envelope), startTime, stopTime, numOutChannels, outBufferSize, outInterleaved, outRate, outFormat, diff --git a/src/export/Export.h b/src/export/Export.h index 6f5b5e30c..6660652c0 100644 --- a/src/export/Export.h +++ b/src/export/Export.h @@ -29,7 +29,6 @@ class Tags; class TrackList; class MixerSpec; class ProgressDialog; -class TimeTrack; class Mixer; using WaveTrackConstArray = std::vector < std::shared_ptr < const WaveTrack > >; enum class ProgressResult : unsigned; diff --git a/src/toolbars/ControlToolBar.cpp b/src/toolbars/ControlToolBar.cpp index 93aa061c9..7e1842956 100644 --- a/src/toolbars/ControlToolBar.cpp +++ b/src/toolbars/ControlToolBar.cpp @@ -713,12 +713,6 @@ int ControlToolBar::PlayPlayRegion(const SelectedRegion &selectedRegion, return -1; } else { - // Lifted the following into AudacityProject::GetDefaultPlayOptions() - /* - if (!timetrack) { - timetrack = t->GetTimeTrack(); - } - */ token = gAudioIO->StartStream( GetAllPlaybackTracks( tracks, false, useMidi ), t0, t1, options); @@ -775,7 +769,7 @@ void ControlToolBar::PlayCurrentRegion(bool looped /* = false */, auto options = DefaultPlayOptions( *p ); options.playLooped = looped; if (cutpreview) - options.timeTrack = NULL; + options.envelope = nullptr; auto mode = cutpreview ? PlayMode::cutPreviewPlay : options.playLooped ? PlayMode::loopedPlay diff --git a/src/toolbars/ControlToolBar.h b/src/toolbars/ControlToolBar.h index 84c6d6358..8ff74e7ae 100644 --- a/src/toolbars/ControlToolBar.h +++ b/src/toolbars/ControlToolBar.h @@ -28,7 +28,6 @@ class wxStatusBar; class AButton; class AudacityProject; class TrackList; -class TimeTrack; struct AudioIOStartStreamOptions; class SelectedRegion; diff --git a/src/toolbars/TranscriptionToolBar.cpp b/src/toolbars/TranscriptionToolBar.cpp index dabaa9d36..ca3fcea8c 100644 --- a/src/toolbars/TranscriptionToolBar.cpp +++ b/src/toolbars/TranscriptionToolBar.cpp @@ -40,7 +40,7 @@ #include "../KeyboardCapture.h" #include "../Project.h" #include "../ProjectAudioManager.h" -#include "../TimeTrack.h" +#include "../Envelope.h" #include "../ViewInfo.h" #include "../WaveTrack.h" #include "../widgets/AButton.h" @@ -443,6 +443,11 @@ void TranscriptionToolBar::GetSamples( *slen = ss1 - ss0; } +// PRL: duplicating constants from TimeTrack.cpp +//TODO-MB: are these sensible values? +#define TIMETRACK_MIN 0.01 +#define TIMETRACK_MAX 10.0 + // Come here from button clicks, or commands void TranscriptionToolBar::PlayAtSpeed(bool looped, bool cutPreview) { @@ -464,17 +469,16 @@ void TranscriptionToolBar::PlayAtSpeed(bool looped, bool cutPreview) bFixedSpeedPlay = bFixedSpeedPlay || looped || cutPreview; if (bFixedSpeedPlay) { - // Create a TimeTrack if we haven't done so already - if (!mTimeTrack) { - mTimeTrack = TrackFactory::Get( *p ).NewTimeTrack(); - if (!mTimeTrack) { - return; - } + // Create a BoundedEnvelope if we haven't done so already + if (!mEnvelope) { + mEnvelope = + std::make_unique( + true, TIMETRACK_MIN, TIMETRACK_MAX, 1.0); } // Set the speed range //mTimeTrack->SetRangeUpper((double)mPlaySpeed / 100.0); //mTimeTrack->SetRangeLower((double)mPlaySpeed / 100.0); - mTimeTrack->GetEnvelope()->Flatten((double)mPlaySpeed / 100.0); + mEnvelope->Flatten((double)mPlaySpeed / 100.0); } // Pop up the button @@ -498,7 +502,7 @@ void TranscriptionToolBar::PlayAtSpeed(bool looped, bool cutPreview) auto options = DefaultPlayOptions( *p ); options.playLooped = looped; // No need to set cutPreview options. - options.timeTrack = mTimeTrack.get(); + options.envelope = mEnvelope.get(); auto mode = cutPreview ? PlayMode::cutPreviewPlay : options.playLooped ? PlayMode::loopedPlay diff --git a/src/toolbars/TranscriptionToolBar.h b/src/toolbars/TranscriptionToolBar.h index 5852c4828..3d9f687ae 100644 --- a/src/toolbars/TranscriptionToolBar.h +++ b/src/toolbars/TranscriptionToolBar.h @@ -29,7 +29,7 @@ class wxKeyEvent; class AButton; class ASlider; class AudacityProject; -class TimeTrack; +class BoundedEnvelope; class WaveTrack; #ifdef EXPERIMENTAL_VOICE_DETECTION @@ -152,7 +152,7 @@ class TranscriptionToolBar final : public ToolBar { int mBackgroundWidth; int mBackgroundHeight; - std::shared_ptr mTimeTrack; + std::shared_ptr mEnvelope; public: diff --git a/src/tracks/ui/Scrubbing.cpp b/src/tracks/ui/Scrubbing.cpp index fcf00657e..6eb617120 100644 --- a/src/tracks/ui/Scrubbing.cpp +++ b/src/tracks/ui/Scrubbing.cpp @@ -387,7 +387,7 @@ bool Scrubber::MaybeStartScrubbing(wxCoord xx) auto options = DefaultPlayOptions( *mProject ); options.pScrubbingOptions = &mOptions; - options.timeTrack = NULL; + options.envelope = nullptr; mOptions.delay = (ScrubPollInterval_ms / 1000.0); mOptions.isPlayingAtSpeed = false; mOptions.minSpeed = 0.0; @@ -487,7 +487,7 @@ bool Scrubber::StartSpeedPlay(double speed, double time0, double time1) auto options = DefaultSpeedPlayOptions( *mProject ); options.pScrubbingOptions = &mOptions; - options.timeTrack = NULL; + options.envelope = nullptr; mOptions.delay = (ScrubPollInterval_ms / 1000.0); mOptions.minSpeed = speed -0.01; mOptions.maxSpeed = speed +0.01; diff --git a/src/widgets/Ruler.cpp b/src/widgets/Ruler.cpp index 96229302c..f8847e0d2 100644 --- a/src/widgets/Ruler.cpp +++ b/src/widgets/Ruler.cpp @@ -64,8 +64,8 @@ array of Ruler::Label. #include "../AColor.h" #include "../AllThemeResources.h" +#include "../Envelope.h" #include "../NumberScale.h" -#include "../TimeTrack.h" #include "../ViewInfo.h" using std::min; @@ -954,7 +954,19 @@ void Ruler::Update() Update(NULL); } -void Ruler::Update(const TimeTrack* timetrack)// Envelope *speedEnv, long minSpeed, long maxSpeed ) +namespace { +double ComputeWarpedLength(const Envelope &env, double t0, double t1) +{ + return env.IntegralOfInverse(t0, t1); +} + +double SolveWarpedLength(const Envelope &env, double t0, double length) +{ + return env.SolveIntegralOfInverse(t0, length); +} +} + +void Ruler::Update(const Envelope* envelope)// Envelope *speedEnv, long minSpeed, long maxSpeed ) { const ZoomInfo *zoomInfo = NULL; if (!mLog && mOrientation == wxHORIZONTAL) @@ -1115,8 +1127,8 @@ void Ruler::Update(const TimeTrack* timetrack)// Envelope *speedEnv, long minSpe } else d = mMin - UPP / 2; - if (timetrack) - warpedD = timetrack->ComputeWarpedLength(0.0, d); + if (envelope) + warpedD = ComputeWarpedLength(*envelope, 0.0, d); else warpedD = d; // using ints doesn't work, as @@ -1133,8 +1145,8 @@ void Ruler::Update(const TimeTrack* timetrack)// Envelope *speedEnv, long minSpe } else nextD = d + UPP; - if (timetrack) - warpedD += timetrack->ComputeWarpedLength(d, nextD); + if (envelope) + warpedD += ComputeWarpedLength(*envelope, d, nextD); else warpedD = nextD; d = nextD; @@ -1290,14 +1302,14 @@ void Ruler::Draw(wxDC& dc) Draw( dc, NULL); } -void Ruler::Draw(wxDC& dc, const TimeTrack* timetrack) +void Ruler::Draw(wxDC& dc, const Envelope* envelope) { mDC = &dc; if( mLength <=0 ) return; if (!mValid) - Update(timetrack); + Update(envelope); mDC->SetTextForeground( mTickColour ); #ifdef EXPERIMENTAL_THEMING diff --git a/src/widgets/Ruler.h b/src/widgets/Ruler.h index 301c98349..847e5f4ef 100644 --- a/src/widgets/Ruler.h +++ b/src/widgets/Ruler.h @@ -21,7 +21,7 @@ class wxDC; class wxFont; class NumberScale; -class TimeTrack; +class Envelope; class ZoomInfo; class AUDACITY_DLL_API Ruler { @@ -136,7 +136,7 @@ class AUDACITY_DLL_API Ruler { // Note that it will not erase for you... void Draw(wxDC& dc); - void Draw(wxDC& dc, const TimeTrack* timetrack); + void Draw(wxDC& dc, const Envelope* envelope); // If length <> 0, draws lines perpendiculars to ruler corresponding // to selected ticks (major, minor, or both), in an adjacent window. // You may need to use the offsets if you are using part of the dc for rulers, borders etc. @@ -151,7 +151,7 @@ class AUDACITY_DLL_API Ruler { private: void Update(); - void Update(const TimeTrack* timetrack); + void Update(const Envelope* envelope); void FindTickSizes(); void FindLinearTickSizes(double UPP); wxString LabelString(double d, bool major);