1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-31 16:09:28 +02:00

Don't pass whole TimeTrack to Ruler or Mixer...

... they need only the information in a (Bounded)Envelope.
This commit is contained in:
Paul Licameli 2019-06-06 09:21:01 -04:00
parent 5ae606cf53
commit 46bf5a82fc
17 changed files with 142 additions and 123 deletions

View File

@ -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

View File

@ -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);

View File

@ -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,

View File

@ -31,6 +31,7 @@
#include <wx/timer.h>
#include <wx/intl.h>
#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; i<mNumInputTracks; i++) {
double factor = (mRate / mInputTrack[i].GetTrack()->GetRate());
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,

View File

@ -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<WaveTrackCache> mInputTrack;
bool mbVariableRates;
const TimeTrack *mTimeTrack;
const BoundedEnvelope *mEnvelope;
ArrayOf<sampleCount> mSamplePos;
bool mApplyTrackGains;
Doubles mEnvValues;

View File

@ -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;
}

View File

@ -58,11 +58,12 @@ TimeTrack::TimeTrack(const std::shared_ptr<DirManager> &projDirManager, const Zo
{
mHeight = 100;
mEnvelope = std::make_unique<BoundedEnvelope>(true, TIMETRACK_MIN, TIMETRACK_MAX, 1.0);
SetRangeLower( 0.9 );
SetRangeUpper( 1.1 );
mDisplayLog = false;
mEnvelope = std::make_unique<BoundedEnvelope>(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<BoundedEnvelope>( *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(),

View File

@ -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;

View File

@ -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<Mixer> 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<Mixer>(inputTracks,
// Throw, to stop exporting, if read fails:
true,
Mixer::WarpOptions(timeTrack),
Mixer::WarpOptions(envelope),
startTime, stopTime,
numOutChannels, outBufferSize, outInterleaved,
outRate, outFormat,

View File

@ -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;

View File

@ -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

View File

@ -28,7 +28,6 @@ class wxStatusBar;
class AButton;
class AudacityProject;
class TrackList;
class TimeTrack;
struct AudioIOStartStreamOptions;
class SelectedRegion;

View File

@ -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<BoundedEnvelope>(
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

View File

@ -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<TimeTrack> mTimeTrack;
std::shared_ptr<BoundedEnvelope> mEnvelope;
public:

View File

@ -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;

View File

@ -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

View File

@ -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);