mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-16 16:10:06 +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;
|
mCutPreviewGapLen = cutPreviewGapLen;
|
||||||
|
|
||||||
double factor = 1.0;
|
double factor = 1.0;
|
||||||
if (mTimeTrack) {
|
if (mTimeTrack)
|
||||||
factor = mTimeTrack->GetEnvelope()->Average(mT0, mT1);
|
factor = mTimeTrack->ComputeWarpFactor(mT0, mT1);
|
||||||
factor = (mTimeTrack->GetRangeLower() *
|
|
||||||
(1 - factor) +
|
|
||||||
factor *
|
|
||||||
mTimeTrack->GetRangeUpper()) /
|
|
||||||
100.0;
|
|
||||||
}
|
|
||||||
mWarpedT1 = factor >= 1 ? mT1 : mT0 + ((mT1 - mT0) / factor);
|
mWarpedT1 = factor >= 1 ? mT1 : mT0 + ((mT1 - mT0) / factor);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -109,6 +109,19 @@ double TimeTrack::warp( double t )
|
|||||||
return result;
|
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)
|
bool TimeTrack::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
|
||||||
{
|
{
|
||||||
if (!wxStrcmp(tag, wxT("timetrack"))) {
|
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
|
// LL: It's because the ruler only Invalidate()s when the new value is different
|
||||||
// than the current value.
|
// than the current value.
|
||||||
mRuler->SetFlip(GetHeight() > 75 ? true : true);
|
mRuler->SetFlip(GetHeight() > 75 ? true : true);
|
||||||
mRuler->Draw(dc, GetEnvelope(), GetRangeLower(), GetRangeUpper());
|
mRuler->Draw(dc, this);
|
||||||
|
|
||||||
int *heights = new int[mid.width];
|
int *heights = new int[mid.width];
|
||||||
double *envValues = new double[mid.width];
|
double *envValues = new double[mid.width];
|
||||||
|
@ -57,6 +57,9 @@ class TimeTrack: public Track {
|
|||||||
// Access the track's speed envelope
|
// Access the track's speed envelope
|
||||||
|
|
||||||
Envelope *GetEnvelope() { return mEnvelope; }
|
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%)
|
// Get/Set the speed-warping range, as percentage of original speed (e.g. 90%-110%)
|
||||||
|
|
||||||
|
@ -72,6 +72,7 @@
|
|||||||
#include "../WaveTrack.h"
|
#include "../WaveTrack.h"
|
||||||
#include "../widgets/Warning.h"
|
#include "../widgets/Warning.h"
|
||||||
#include "../AColor.h"
|
#include "../AColor.h"
|
||||||
|
#include "../TimeTrack.h"
|
||||||
|
|
||||||
// Callback to display format options
|
// Callback to display format options
|
||||||
static void ExportCallback(void *cbdata, int index)
|
static void ExportCallback(void *cbdata, int index)
|
||||||
@ -264,6 +265,28 @@ int ExportPlugin::DoExport(AudacityProject *project,
|
|||||||
return false;
|
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
|
// Export
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <wx/filename.h>
|
#include <wx/filename.h>
|
||||||
#include <wx/panel.h>
|
#include <wx/panel.h>
|
||||||
#include "../Tags.h"
|
#include "../Tags.h"
|
||||||
|
#include "../SampleFormat.h"
|
||||||
|
|
||||||
class wxMemoryDC;
|
class wxMemoryDC;
|
||||||
class wxStaticText;
|
class wxStaticText;
|
||||||
@ -25,6 +26,8 @@ class WaveTrack;
|
|||||||
class TrackList;
|
class TrackList;
|
||||||
class MixerSpec;
|
class MixerSpec;
|
||||||
class FileDialog;
|
class FileDialog;
|
||||||
|
class TimeTrack;
|
||||||
|
class Mixer;
|
||||||
|
|
||||||
class FormatInfo
|
class FormatInfo
|
||||||
{
|
{
|
||||||
@ -114,8 +117,15 @@ public:
|
|||||||
MixerSpec *mixerSpec,
|
MixerSpec *mixerSpec,
|
||||||
int subformat);
|
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;
|
FormatInfoArray mFormatInfos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -338,7 +338,7 @@ int ExportCL::Export(AudacityProject *project,
|
|||||||
WaveTrack **waveTracks;
|
WaveTrack **waveTracks;
|
||||||
TrackList *tracks = project->GetTracks();
|
TrackList *tracks = project->GetTracks();
|
||||||
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
||||||
Mixer *mixer = new Mixer(numWaveTracks,
|
Mixer *mixer = CreateMixer(numWaveTracks,
|
||||||
waveTracks,
|
waveTracks,
|
||||||
tracks->GetTimeTrack(),
|
tracks->GetTimeTrack(),
|
||||||
t0,
|
t0,
|
||||||
|
@ -729,7 +729,7 @@ int ExportFFmpeg::Export(AudacityProject *project,
|
|||||||
int numWaveTracks;
|
int numWaveTracks;
|
||||||
WaveTrack **waveTracks;
|
WaveTrack **waveTracks;
|
||||||
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
||||||
Mixer *mixer = new Mixer(numWaveTracks, waveTracks,
|
Mixer *mixer = CreateMixer(numWaveTracks, waveTracks,
|
||||||
tracks->GetTimeTrack(),
|
tracks->GetTimeTrack(),
|
||||||
t0, t1,
|
t0, t1,
|
||||||
channels, pcmBufferSize, true,
|
channels, pcmBufferSize, true,
|
||||||
|
@ -306,7 +306,7 @@ int ExportFLAC::Export(AudacityProject *project,
|
|||||||
int numWaveTracks;
|
int numWaveTracks;
|
||||||
WaveTrack **waveTracks;
|
WaveTrack **waveTracks;
|
||||||
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
||||||
Mixer *mixer = new Mixer(numWaveTracks, waveTracks,
|
Mixer *mixer = CreateMixer(numWaveTracks, waveTracks,
|
||||||
tracks->GetTimeTrack(),
|
tracks->GetTimeTrack(),
|
||||||
t0, t1,
|
t0, t1,
|
||||||
numChannels, SAMPLES_PER_RUN, false,
|
numChannels, SAMPLES_PER_RUN, false,
|
||||||
|
@ -261,7 +261,7 @@ int ExportMP2::Export(AudacityProject *project,
|
|||||||
int numWaveTracks;
|
int numWaveTracks;
|
||||||
WaveTrack **waveTracks;
|
WaveTrack **waveTracks;
|
||||||
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
||||||
Mixer *mixer = new Mixer(numWaveTracks, waveTracks,
|
Mixer *mixer = CreateMixer(numWaveTracks, waveTracks,
|
||||||
tracks->GetTimeTrack(),
|
tracks->GetTimeTrack(),
|
||||||
t0, t1,
|
t0, t1,
|
||||||
stereo? 2: 1, pcmBufferSize, true,
|
stereo? 2: 1, pcmBufferSize, true,
|
||||||
|
@ -1639,7 +1639,7 @@ int ExportMP3::Export(AudacityProject *project,
|
|||||||
int numWaveTracks;
|
int numWaveTracks;
|
||||||
WaveTrack **waveTracks;
|
WaveTrack **waveTracks;
|
||||||
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
||||||
Mixer *mixer = new Mixer(numWaveTracks, waveTracks,
|
Mixer *mixer = CreateMixer(numWaveTracks, waveTracks,
|
||||||
tracks->GetTimeTrack(),
|
tracks->GetTimeTrack(),
|
||||||
t0, t1,
|
t0, t1,
|
||||||
channels, inSamples, true,
|
channels, inSamples, true,
|
||||||
|
@ -244,7 +244,7 @@ int ExportOGG::Export(AudacityProject *project,
|
|||||||
int numWaveTracks;
|
int numWaveTracks;
|
||||||
WaveTrack **waveTracks;
|
WaveTrack **waveTracks;
|
||||||
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
||||||
Mixer *mixer = new Mixer(numWaveTracks, waveTracks,
|
Mixer *mixer = CreateMixer(numWaveTracks, waveTracks,
|
||||||
tracks->GetTimeTrack(),
|
tracks->GetTimeTrack(),
|
||||||
t0, t1,
|
t0, t1,
|
||||||
numChannels, SAMPLES_PER_RUN, false,
|
numChannels, SAMPLES_PER_RUN, false,
|
||||||
|
@ -517,7 +517,7 @@ int ExportPCM::Export(AudacityProject *project,
|
|||||||
int numWaveTracks;
|
int numWaveTracks;
|
||||||
WaveTrack **waveTracks;
|
WaveTrack **waveTracks;
|
||||||
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
|
||||||
Mixer *mixer = new Mixer(numWaveTracks, waveTracks,
|
Mixer *mixer = CreateMixer(numWaveTracks, waveTracks,
|
||||||
tracks->GetTimeTrack(),
|
tracks->GetTimeTrack(),
|
||||||
t0, t1,
|
t0, t1,
|
||||||
info.channels, maxBlockLen, true,
|
info.channels, maxBlockLen, true,
|
||||||
|
@ -69,6 +69,7 @@ array of Ruler::Label.
|
|||||||
#include "../Theme.h"
|
#include "../Theme.h"
|
||||||
#include "../AllThemeResources.h"
|
#include "../AllThemeResources.h"
|
||||||
#include "../Experimental.h"
|
#include "../Experimental.h"
|
||||||
|
#include "../TimeTrack.h"
|
||||||
|
|
||||||
#define max(a,b) ( (a<b)?b:a )
|
#define max(a,b) ( (a<b)?b:a )
|
||||||
|
|
||||||
@ -905,10 +906,10 @@ void Ruler::TickCustom(int labelIdx, bool major, bool minor)
|
|||||||
|
|
||||||
void Ruler::Update()
|
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
|
// This gets called when something has been changed
|
||||||
// (i.e. we've been invalidated). Recompute all
|
// (i.e. we've been invalidated). Recompute all
|
||||||
@ -1050,19 +1051,14 @@ void Ruler::Update( Envelope *speedEnv, long minSpeed, long maxSpeed )
|
|||||||
i = -1;
|
i = -1;
|
||||||
while(i <= mLength) {
|
while(i <= mLength) {
|
||||||
double warpfactor;
|
double warpfactor;
|
||||||
if( d>0 && speedEnv != NULL ) {
|
if( d>0 && timetrack != NULL )
|
||||||
warpfactor = speedEnv->Average( lastD, d );
|
warpfactor = timetrack->ComputeWarpFactor( 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;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
warpfactor = 1.0;
|
warpfactor = 1.0;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
lastD = d;
|
lastD = d;
|
||||||
d += UPP*warpfactor;
|
d += UPP/warpfactor;
|
||||||
|
|
||||||
if ((int)floor(sg * d / mMajor) > majorInt) {
|
if ((int)floor(sg * d / mMajor) > majorInt) {
|
||||||
majorInt = (int)floor(sg * d / mMajor);
|
majorInt = (int)floor(sg * d / mMajor);
|
||||||
@ -1077,19 +1073,14 @@ void Ruler::Update( Envelope *speedEnv, long minSpeed, long maxSpeed )
|
|||||||
i = -1;
|
i = -1;
|
||||||
while(i <= mLength) {
|
while(i <= mLength) {
|
||||||
double warpfactor;
|
double warpfactor;
|
||||||
if( d>0 && speedEnv != NULL ) {
|
if( d>0 && timetrack != NULL )
|
||||||
warpfactor = speedEnv->Average( lastD, d );
|
warpfactor = timetrack->ComputeWarpFactor( 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;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
warpfactor = 1.0;
|
warpfactor = 1.0;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
lastD = d;
|
lastD = d;
|
||||||
d += UPP*warpfactor;
|
d += UPP/warpfactor;
|
||||||
|
|
||||||
if ((int)floor(sg * d / mMinor) > minorInt) {
|
if ((int)floor(sg * d / mMinor) > minorInt) {
|
||||||
minorInt = (int)floor(sg * d / mMinor);
|
minorInt = (int)floor(sg * d / mMinor);
|
||||||
@ -1217,17 +1208,17 @@ void Ruler::Update( Envelope *speedEnv, long minSpeed, long maxSpeed )
|
|||||||
|
|
||||||
void Ruler::Draw(wxDC& dc)
|
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;
|
mDC = &dc;
|
||||||
if( mLength <=0 )
|
if( mLength <=0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!mValid)
|
if (!mValid)
|
||||||
Update( speedEnv, minSpeed, maxSpeed );
|
Update(timetrack);
|
||||||
|
|
||||||
#ifdef EXPERIMENTAL_THEMING
|
#ifdef EXPERIMENTAL_THEMING
|
||||||
mDC->SetPen(mPen);
|
mDC->SetPen(mPen);
|
||||||
@ -1462,7 +1453,7 @@ void Ruler::GetMaxSize(wxCoord *width, wxCoord *height)
|
|||||||
wxBitmap tmpBM(1, 1);
|
wxBitmap tmpBM(1, 1);
|
||||||
tmpDC.SelectObject(tmpBM);
|
tmpDC.SelectObject(tmpBM);
|
||||||
mDC = &tmpDC;
|
mDC = &tmpDC;
|
||||||
Update( NULL, 0, 0 );
|
Update( NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (width)
|
if (width)
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
struct ViewInfo;
|
struct ViewInfo;
|
||||||
class AudacityProject;
|
class AudacityProject;
|
||||||
|
class TimeTrack;
|
||||||
|
|
||||||
class AUDACITY_DLL_API Ruler {
|
class AUDACITY_DLL_API Ruler {
|
||||||
public:
|
public:
|
||||||
@ -115,7 +116,7 @@ class AUDACITY_DLL_API Ruler {
|
|||||||
|
|
||||||
// Note that it will not erase for you...
|
// Note that it will not erase for you...
|
||||||
void Draw(wxDC& dc);
|
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
|
// If length <> 0, draws lines perpendiculars to ruler corresponding
|
||||||
// to selected ticks (major, minor, or both), in an adjacent window.
|
// 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.
|
// 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:
|
private:
|
||||||
void Invalidate();
|
void Invalidate();
|
||||||
void Update();
|
void Update();
|
||||||
void Update(Envelope *speedEnv, long minSpeed, long maxSpeed);
|
void Update(TimeTrack* timetrack);
|
||||||
void FindTickSizes();
|
void FindTickSizes();
|
||||||
void FindLinearTickSizes(double UPP);
|
void FindLinearTickSizes(double UPP);
|
||||||
wxString LabelString(double d, bool major);
|
wxString LabelString(double d, bool major);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user