mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-16 08:09:32 +02:00
Timetrack fixes and refactoring.
Possibly fixes: Bug 206 - Time Tracks: Ruler warp goes in wrong direction Bug 205 - Time Tracks that slow down the audio result in truncated exports
This commit is contained in:
parent
2fd5555378
commit
a9a0d51454
@ -1124,14 +1124,9 @@ int AudioIO::StartStream(WaveTrackArray playbackTracks,
|
||||
mCutPreviewGapLen = cutPreviewGapLen;
|
||||
|
||||
double factor = 1.0;
|
||||
if (mTimeTrack) {
|
||||
factor = mTimeTrack->GetEnvelope()->Average(mT0, mT1);
|
||||
factor = (mTimeTrack->GetRangeLower() *
|
||||
(1 - factor) +
|
||||
factor *
|
||||
mTimeTrack->GetRangeUpper()) /
|
||||
100.0;
|
||||
}
|
||||
if (mTimeTrack)
|
||||
factor = mTimeTrack->ComputeWarpFactor(mT0, mT1);
|
||||
|
||||
mWarpedT1 = factor >= 1 ? mT1 : mT0 + ((mT1 - mT0) / factor);
|
||||
|
||||
//
|
||||
|
@ -109,6 +109,19 @@ double TimeTrack::warp( double t )
|
||||
return result;
|
||||
}
|
||||
|
||||
//Compute the integral warp factor between two non-warped time points
|
||||
double TimeTrack::ComputeWarpFactor(double t0, double t1)
|
||||
{
|
||||
double factor;
|
||||
factor = GetEnvelope()->Average(t0, t1);
|
||||
factor = (GetRangeLower() *
|
||||
(1 - factor) +
|
||||
factor *
|
||||
GetRangeUpper()) /
|
||||
100.0;
|
||||
return factor;
|
||||
}
|
||||
|
||||
bool TimeTrack::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
|
||||
{
|
||||
if (!wxStrcmp(tag, wxT("timetrack"))) {
|
||||
@ -208,7 +221,7 @@ void TimeTrack::Draw(wxDC & dc, const wxRect & r, double h, double pps)
|
||||
// LL: It's because the ruler only Invalidate()s when the new value is different
|
||||
// than the current value.
|
||||
mRuler->SetFlip(GetHeight() > 75 ? true : true);
|
||||
mRuler->Draw(dc, GetEnvelope(), GetRangeLower(), GetRangeUpper());
|
||||
mRuler->Draw(dc, this);
|
||||
|
||||
int *heights = new int[mid.width];
|
||||
double *envValues = new double[mid.width];
|
||||
|
@ -57,6 +57,9 @@ class TimeTrack: public Track {
|
||||
// Access the track's speed envelope
|
||||
|
||||
Envelope *GetEnvelope() { return mEnvelope; }
|
||||
|
||||
//Compute the integral warp factor between two non-warped time points
|
||||
double ComputeWarpFactor(double t0, double t1);
|
||||
|
||||
// Get/Set the speed-warping range, as percentage of original speed (e.g. 90%-110%)
|
||||
|
||||
|
@ -72,6 +72,7 @@
|
||||
#include "../WaveTrack.h"
|
||||
#include "../widgets/Warning.h"
|
||||
#include "../AColor.h"
|
||||
#include "../TimeTrack.h"
|
||||
|
||||
// Callback to display format options
|
||||
static void ExportCallback(void *cbdata, int index)
|
||||
@ -264,6 +265,28 @@ int ExportPlugin::DoExport(AudacityProject *project,
|
||||
return false;
|
||||
}
|
||||
|
||||
//Create a mixer by computing the time warp factor
|
||||
Mixer* ExportPlugin::CreateMixer(int numInputTracks, WaveTrack **inputTracks,
|
||||
TimeTrack *timeTrack,
|
||||
double startTime, double stopTime,
|
||||
int numOutChannels, int outBufferSize, bool outInterleaved,
|
||||
double outRate, sampleFormat outFormat,
|
||||
bool highQuality, MixerSpec *mixerSpec)
|
||||
{
|
||||
double warpedStopTime;
|
||||
double warpFactor = 1.0;
|
||||
if(timeTrack)
|
||||
warpFactor = timeTrack->ComputeWarpFactor(startTime, stopTime);
|
||||
|
||||
warpedStopTime = warpFactor >= 1.0 ? stopTime : (startTime + ((stopTime - startTime) / warpFactor));
|
||||
printf("warpfactor %f, stoptime %f, warpstoptime %f\n",warpFactor, stopTime, warpedStopTime);
|
||||
return new Mixer(numInputTracks, inputTracks,
|
||||
timeTrack,
|
||||
startTime, warpedStopTime,
|
||||
numOutChannels, outBufferSize, outInterleaved,
|
||||
outRate, outFormat,
|
||||
highQuality, mixerSpec);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
// Export
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <wx/filename.h>
|
||||
#include <wx/panel.h>
|
||||
#include "../Tags.h"
|
||||
#include "../SampleFormat.h"
|
||||
|
||||
class wxMemoryDC;
|
||||
class wxStaticText;
|
||||
@ -25,6 +26,8 @@ class WaveTrack;
|
||||
class TrackList;
|
||||
class MixerSpec;
|
||||
class FileDialog;
|
||||
class TimeTrack;
|
||||
class Mixer;
|
||||
|
||||
class FormatInfo
|
||||
{
|
||||
@ -114,8 +117,15 @@ public:
|
||||
MixerSpec *mixerSpec,
|
||||
int subformat);
|
||||
|
||||
private:
|
||||
protected:
|
||||
Mixer* CreateMixer(int numInputTracks, WaveTrack **inputTracks,
|
||||
TimeTrack *timeTrack,
|
||||
double startTime, double stopTime,
|
||||
int numOutChannels, int outBufferSize, bool outInterleaved,
|
||||
double outRate, sampleFormat outFormat,
|
||||
bool highQuality = true, MixerSpec *mixerSpec = NULL);
|
||||
|
||||
private:
|
||||
FormatInfoArray mFormatInfos;
|
||||
};
|
||||
|
||||
|
@ -338,7 +338,7 @@ int ExportCL::Export(AudacityProject *project,
|
||||
WaveTrack **waveTracks;
|
||||
TrackList *tracks = project->GetTracks();
|
||||
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
||||
Mixer *mixer = new Mixer(numWaveTracks,
|
||||
Mixer *mixer = CreateMixer(numWaveTracks,
|
||||
waveTracks,
|
||||
tracks->GetTimeTrack(),
|
||||
t0,
|
||||
|
@ -729,7 +729,7 @@ int ExportFFmpeg::Export(AudacityProject *project,
|
||||
int numWaveTracks;
|
||||
WaveTrack **waveTracks;
|
||||
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
||||
Mixer *mixer = new Mixer(numWaveTracks, waveTracks,
|
||||
Mixer *mixer = CreateMixer(numWaveTracks, waveTracks,
|
||||
tracks->GetTimeTrack(),
|
||||
t0, t1,
|
||||
channels, pcmBufferSize, true,
|
||||
|
@ -306,7 +306,7 @@ int ExportFLAC::Export(AudacityProject *project,
|
||||
int numWaveTracks;
|
||||
WaveTrack **waveTracks;
|
||||
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
||||
Mixer *mixer = new Mixer(numWaveTracks, waveTracks,
|
||||
Mixer *mixer = CreateMixer(numWaveTracks, waveTracks,
|
||||
tracks->GetTimeTrack(),
|
||||
t0, t1,
|
||||
numChannels, SAMPLES_PER_RUN, false,
|
||||
|
@ -261,7 +261,7 @@ int ExportMP2::Export(AudacityProject *project,
|
||||
int numWaveTracks;
|
||||
WaveTrack **waveTracks;
|
||||
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
||||
Mixer *mixer = new Mixer(numWaveTracks, waveTracks,
|
||||
Mixer *mixer = CreateMixer(numWaveTracks, waveTracks,
|
||||
tracks->GetTimeTrack(),
|
||||
t0, t1,
|
||||
stereo? 2: 1, pcmBufferSize, true,
|
||||
|
@ -1639,7 +1639,7 @@ int ExportMP3::Export(AudacityProject *project,
|
||||
int numWaveTracks;
|
||||
WaveTrack **waveTracks;
|
||||
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
||||
Mixer *mixer = new Mixer(numWaveTracks, waveTracks,
|
||||
Mixer *mixer = CreateMixer(numWaveTracks, waveTracks,
|
||||
tracks->GetTimeTrack(),
|
||||
t0, t1,
|
||||
channels, inSamples, true,
|
||||
|
@ -244,7 +244,7 @@ int ExportOGG::Export(AudacityProject *project,
|
||||
int numWaveTracks;
|
||||
WaveTrack **waveTracks;
|
||||
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
||||
Mixer *mixer = new Mixer(numWaveTracks, waveTracks,
|
||||
Mixer *mixer = CreateMixer(numWaveTracks, waveTracks,
|
||||
tracks->GetTimeTrack(),
|
||||
t0, t1,
|
||||
numChannels, SAMPLES_PER_RUN, false,
|
||||
|
@ -517,7 +517,7 @@ int ExportPCM::Export(AudacityProject *project,
|
||||
int numWaveTracks;
|
||||
WaveTrack **waveTracks;
|
||||
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
||||
Mixer *mixer = new Mixer(numWaveTracks, waveTracks,
|
||||
Mixer *mixer = CreateMixer(numWaveTracks, waveTracks,
|
||||
tracks->GetTimeTrack(),
|
||||
t0, t1,
|
||||
info.channels, maxBlockLen, true,
|
||||
|
@ -69,6 +69,7 @@ array of Ruler::Label.
|
||||
#include "../Theme.h"
|
||||
#include "../AllThemeResources.h"
|
||||
#include "../Experimental.h"
|
||||
#include "../TimeTrack.h"
|
||||
|
||||
#define max(a,b) ( (a<b)?b:a )
|
||||
|
||||
@ -905,10 +906,10 @@ void Ruler::TickCustom(int labelIdx, bool major, bool minor)
|
||||
|
||||
void Ruler::Update()
|
||||
{
|
||||
Update(NULL, 0, 0);
|
||||
Update(NULL);
|
||||
}
|
||||
|
||||
void Ruler::Update( Envelope *speedEnv, long minSpeed, long maxSpeed )
|
||||
void Ruler::Update(TimeTrack* timetrack)// Envelope *speedEnv, long minSpeed, long maxSpeed )
|
||||
{
|
||||
// This gets called when something has been changed
|
||||
// (i.e. we've been invalidated). Recompute all
|
||||
@ -1050,19 +1051,14 @@ void Ruler::Update( Envelope *speedEnv, long minSpeed, long maxSpeed )
|
||||
i = -1;
|
||||
while(i <= mLength) {
|
||||
double warpfactor;
|
||||
if( d>0 && speedEnv != NULL ) {
|
||||
warpfactor = speedEnv->Average( lastD, d );
|
||||
// Now we re-scale so that 0.5 is normal speed and
|
||||
// 0 and 1.0 are min% and max% of normal speed
|
||||
warpfactor = (maxSpeed * (1 - warpfactor) +
|
||||
warpfactor * minSpeed) / 100.0;
|
||||
}
|
||||
if( d>0 && timetrack != NULL )
|
||||
warpfactor = timetrack->ComputeWarpFactor( lastD, d );
|
||||
else
|
||||
warpfactor = 1.0;
|
||||
|
||||
i++;
|
||||
lastD = d;
|
||||
d += UPP*warpfactor;
|
||||
d += UPP/warpfactor;
|
||||
|
||||
if ((int)floor(sg * d / mMajor) > majorInt) {
|
||||
majorInt = (int)floor(sg * d / mMajor);
|
||||
@ -1077,19 +1073,14 @@ void Ruler::Update( Envelope *speedEnv, long minSpeed, long maxSpeed )
|
||||
i = -1;
|
||||
while(i <= mLength) {
|
||||
double warpfactor;
|
||||
if( d>0 && speedEnv != NULL ) {
|
||||
warpfactor = speedEnv->Average( lastD, d );
|
||||
// Now we re-scale so that 0.5 is normal speed and
|
||||
// 0 and 1.0 are min% and max% of normal speed
|
||||
warpfactor = (maxSpeed * (1 - warpfactor) +
|
||||
warpfactor * minSpeed) / 100.0;
|
||||
}
|
||||
if( d>0 && timetrack != NULL )
|
||||
warpfactor = timetrack->ComputeWarpFactor( lastD, d );
|
||||
else
|
||||
warpfactor = 1.0;
|
||||
|
||||
i++;
|
||||
lastD = d;
|
||||
d += UPP*warpfactor;
|
||||
d += UPP/warpfactor;
|
||||
|
||||
if ((int)floor(sg * d / mMinor) > minorInt) {
|
||||
minorInt = (int)floor(sg * d / mMinor);
|
||||
@ -1217,17 +1208,17 @@ void Ruler::Update( Envelope *speedEnv, long minSpeed, long maxSpeed )
|
||||
|
||||
void Ruler::Draw(wxDC& dc)
|
||||
{
|
||||
Draw( dc, NULL, 0, 0);
|
||||
Draw( dc, NULL);
|
||||
}
|
||||
|
||||
void Ruler::Draw(wxDC& dc, Envelope *speedEnv, long minSpeed, long maxSpeed)
|
||||
void Ruler::Draw(wxDC& dc, TimeTrack* timetrack)
|
||||
{
|
||||
mDC = &dc;
|
||||
if( mLength <=0 )
|
||||
return;
|
||||
|
||||
if (!mValid)
|
||||
Update( speedEnv, minSpeed, maxSpeed );
|
||||
Update(timetrack);
|
||||
|
||||
#ifdef EXPERIMENTAL_THEMING
|
||||
mDC->SetPen(mPen);
|
||||
@ -1462,7 +1453,7 @@ void Ruler::GetMaxSize(wxCoord *width, wxCoord *height)
|
||||
wxBitmap tmpBM(1, 1);
|
||||
tmpDC.SelectObject(tmpBM);
|
||||
mDC = &tmpDC;
|
||||
Update( NULL, 0, 0 );
|
||||
Update( NULL);
|
||||
}
|
||||
|
||||
if (width)
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
struct ViewInfo;
|
||||
class AudacityProject;
|
||||
class TimeTrack;
|
||||
|
||||
class AUDACITY_DLL_API Ruler {
|
||||
public:
|
||||
@ -115,7 +116,7 @@ class AUDACITY_DLL_API Ruler {
|
||||
|
||||
// Note that it will not erase for you...
|
||||
void Draw(wxDC& dc);
|
||||
void Draw(wxDC& dc, Envelope *speedEnv, long minSpeed, long maxSpeed);
|
||||
void Draw(wxDC& dc, TimeTrack* timetrack);
|
||||
// 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.
|
||||
@ -128,7 +129,7 @@ class AUDACITY_DLL_API Ruler {
|
||||
private:
|
||||
void Invalidate();
|
||||
void Update();
|
||||
void Update(Envelope *speedEnv, long minSpeed, long maxSpeed);
|
||||
void Update(TimeTrack* timetrack);
|
||||
void FindTickSizes();
|
||||
void FindLinearTickSizes(double UPP);
|
||||
wxString LabelString(double d, bool major);
|
||||
|
Loading…
x
Reference in New Issue
Block a user