mirror of
https://github.com/cookiengineer/audacity
synced 2025-10-16 07:31:16 +02:00
Major update to TimeScale effect, incorporating libsbsms-2.0.0, fixes to bug 172, changes to ui
This commit is contained in:
@@ -6,7 +6,7 @@ SBSMSEffect.cpp
|
||||
|
||||
Clayton Otey
|
||||
|
||||
This abstract class contains all of the common code for an
|
||||
This class contains all of the common code for an
|
||||
effect that uses SBSMS to do its processing (TimeScale)
|
||||
|
||||
**********************************************************************/
|
||||
@@ -22,79 +22,90 @@ effect that uses SBSMS to do its processing (TimeScale)
|
||||
#include "../Project.h"
|
||||
#include "TimeWarper.h"
|
||||
|
||||
class resampleBuf
|
||||
enum {
|
||||
SBSMSOutBlockSize = 512
|
||||
};
|
||||
|
||||
class ResampleBuf
|
||||
{
|
||||
public:
|
||||
resampleBuf()
|
||||
ResampleBuf()
|
||||
{
|
||||
processed = 0;
|
||||
buf = NULL;
|
||||
leftBuffer = NULL;
|
||||
rightBuffer = NULL;
|
||||
quality = NULL;
|
||||
iface = NULL;
|
||||
sbsms = NULL;
|
||||
|
||||
sbsmser = NULL;
|
||||
outBuf = NULL;
|
||||
outputLeftBuffer = NULL;
|
||||
outputRightBuffer = NULL;
|
||||
resampler = NULL;
|
||||
SBSMSBuf = NULL;
|
||||
outputLeftTrack = NULL;
|
||||
outputRightTrack = NULL;
|
||||
resampler = NULL;
|
||||
}
|
||||
|
||||
~resampleBuf()
|
||||
~ResampleBuf()
|
||||
{
|
||||
if(buf) free(buf);
|
||||
if(leftBuffer) free(leftBuffer);
|
||||
if(rightBuffer) free(rightBuffer);
|
||||
if(sbsmser) sbsms_destroy(sbsmser);
|
||||
if(outBuf) free(outBuf);
|
||||
if(outputLeftBuffer) free(outputLeftBuffer);
|
||||
if(outputRightBuffer) free(outputRightBuffer);
|
||||
if(SBSMSBuf) free(SBSMSBuf);
|
||||
if(outputLeftTrack) delete outputLeftTrack;
|
||||
if(outputRightTrack) delete outputRightTrack;
|
||||
if(quality) delete quality;
|
||||
if(sbsms) delete sbsms;
|
||||
if(iface) delete iface;
|
||||
if(resampler) delete resampler;
|
||||
}
|
||||
|
||||
bool bPitch;
|
||||
audio *buf;
|
||||
double ratio;
|
||||
sampleCount block;
|
||||
sampleCount processed;
|
||||
sampleCount blockSize;
|
||||
sampleCount SBSMSBlockSize;
|
||||
sampleCount offset;
|
||||
sampleCount end;
|
||||
float *leftBuffer;
|
||||
float *rightBuffer;
|
||||
WaveTrack *leftTrack;
|
||||
WaveTrack *rightTrack;
|
||||
SBSMS *sbsms;
|
||||
SBSMSInterface *iface;
|
||||
audio *SBSMSBuf;
|
||||
|
||||
// Not required by callbacks, but makes for easier cleanup
|
||||
sbsms *sbsmser;
|
||||
audio *outBuf;
|
||||
float *outputLeftBuffer;
|
||||
float *outputRightBuffer;
|
||||
Resampler *resampler;
|
||||
SBSMSQuality *quality;
|
||||
WaveTrack *outputLeftTrack;
|
||||
WaveTrack *outputRightTrack;
|
||||
};
|
||||
|
||||
class SBSMSEffectInterface : public SBSMSInterfaceSliding {
|
||||
public:
|
||||
SBSMSEffectInterface(Resampler *resampler,
|
||||
Slide *rateSlide, Slide *pitchSlide,
|
||||
bool bReferenceInput,
|
||||
long samples, long preSamples,
|
||||
SBSMSQuality *quality)
|
||||
: SBSMSInterfaceSliding(rateSlide,pitchSlide,bReferenceInput,samples,preSamples,quality)
|
||||
{
|
||||
this->resampler = resampler;
|
||||
}
|
||||
virtual ~SBSMSEffectInterface() {}
|
||||
|
||||
long samples(audio *buf, long n) {
|
||||
return resampler->read(buf, n);
|
||||
}
|
||||
|
||||
protected:
|
||||
Resampler *resampler;
|
||||
};
|
||||
|
||||
long samplesCB(audio *chdata, long numFrames, void *userData)
|
||||
{
|
||||
sbsmsInfo *si = (sbsmsInfo*) userData;
|
||||
long n_read = si->rs->read(chdata, numFrames);
|
||||
return n_read;
|
||||
}
|
||||
|
||||
void EffectSBSMS :: setParameters(double rateStart, double rateEnd, double pitchStart, double pitchEnd, bool bPreAnalyze)
|
||||
long resampleCB(void *cb_data, SBSMSFrame *data)
|
||||
{
|
||||
this->rateStart = rateStart;
|
||||
this->rateEnd = rateEnd;
|
||||
this->pitchStart = pitchStart;
|
||||
this->pitchEnd = pitchEnd;
|
||||
this->bPreAnalyze = bPreAnalyze;
|
||||
}
|
||||
|
||||
bool EffectSBSMS :: bInit = FALSE;
|
||||
|
||||
long resampleCB(void *cb_data, sbsms_resample_frame *data)
|
||||
{
|
||||
resampleBuf *r = (resampleBuf*) cb_data;
|
||||
ResampleBuf *r = (ResampleBuf*) cb_data;
|
||||
|
||||
long blockSize = r->leftTrack->GetBestBlockSize(r->offset);
|
||||
|
||||
@@ -112,29 +123,75 @@ long resampleCB(void *cb_data, sbsms_resample_frame *data)
|
||||
r->buf[i][1] = r->rightBuffer[i];
|
||||
}
|
||||
|
||||
r->offset += blockSize;
|
||||
data->in = r->buf;
|
||||
data->buf = r->buf;
|
||||
data->size = blockSize;
|
||||
data->ratio0 = r->ratio;
|
||||
data->ratio1 = r->ratio;
|
||||
|
||||
if(r->bPitch) {
|
||||
float t0 = (float)(r->processed) / r->iface->getSamplesToInput();
|
||||
float t1 = (float)(r->processed + blockSize) / r->iface->getSamplesToInput();
|
||||
data->ratio0 = r->iface->getStretch(t0);
|
||||
data->ratio1 = r->iface->getStretch(t1);
|
||||
} else {
|
||||
data->ratio0 = r->ratio;
|
||||
data->ratio1 = r->ratio;
|
||||
}
|
||||
r->processed += blockSize;
|
||||
r->offset += blockSize;
|
||||
return blockSize;
|
||||
}
|
||||
|
||||
long postResampleCB(void *cb_data, SBSMSFrame *data)
|
||||
{
|
||||
ResampleBuf *r = (ResampleBuf*) cb_data;
|
||||
long sampleCount = r->sbsms->read(r->iface, r->SBSMSBuf, r->SBSMSBlockSize);
|
||||
data->buf = r->SBSMSBuf;
|
||||
data->size = sampleCount;
|
||||
data->ratio0 = 1.0 / r->ratio;
|
||||
data->ratio1 = 1.0 / r->ratio;
|
||||
return sampleCount;
|
||||
}
|
||||
|
||||
void EffectSBSMS :: setParameters(double rateStart, double rateEnd, double pitchStart, double pitchEnd,
|
||||
SlideType rateSlideType, SlideType pitchSlideType,
|
||||
bool bLinkRatePitch, bool bRateReferenceInput, bool bPitchReferenceInput)
|
||||
{
|
||||
this->rateStart = rateStart;
|
||||
this->rateEnd = rateEnd;
|
||||
this->pitchStart = pitchStart;
|
||||
this->pitchEnd = pitchEnd;
|
||||
this->bLinkRatePitch = bLinkRatePitch;
|
||||
this->rateSlideType = rateSlideType;
|
||||
this->pitchSlideType = pitchSlideType;
|
||||
this->bRateReferenceInput = bRateReferenceInput;
|
||||
this->bPitchReferenceInput = bPitchReferenceInput;
|
||||
}
|
||||
|
||||
TimeWarper *createTimeWarper(double t0, double t1, double duration,
|
||||
double rateStart, double rateEnd, SlideType rateSlideType)
|
||||
{
|
||||
TimeWarper *warper = NULL;
|
||||
if (rateStart == rateEnd || rateSlideType == SlideConstant) {
|
||||
warper = new LinearTimeWarper(t0, t0, t1, t0+duration);
|
||||
} else if(rateSlideType == SlideLinearInputRate) {
|
||||
warper = new LinearInputRateTimeWarper(t0, t1, rateStart, rateEnd);
|
||||
} else if(rateSlideType == SlideLinearOutputRate) {
|
||||
warper = new LinearOutputRateTimeWarper(t0, t1, rateStart, rateEnd);
|
||||
} else if(rateSlideType == SlideLinearInputStretch) {
|
||||
warper = new LinearInputStretchTimeWarper(t0, t1, rateStart, rateEnd);
|
||||
} else if(rateSlideType == SlideLinearOutputStretch) {
|
||||
warper = new LinearOutputStretchTimeWarper(t0, t1, rateStart, rateEnd);
|
||||
} else if(rateSlideType == SlideGeometricInput) {
|
||||
warper = new GeometricInputTimeWarper(t0, t1, rateStart, rateEnd);
|
||||
} else if(rateSlideType == SlideGeometricOutput) {
|
||||
warper = new GeometricOutputTimeWarper(t0, t1, rateStart, rateEnd);
|
||||
}
|
||||
return warper;
|
||||
}
|
||||
|
||||
// Labels inside the affected region are moved to match the audio; labels after
|
||||
// it are shifted along appropriately.
|
||||
bool EffectSBSMS::ProcessLabelTrack(Track *t)
|
||||
{
|
||||
TimeWarper *warper = NULL;
|
||||
if (rateStart == rateEnd)
|
||||
{
|
||||
warper = new LinearTimeWarper(mT0, mT0,
|
||||
mT1, mT0+(mT1-mT0)*mTotalStretch);
|
||||
} else
|
||||
{
|
||||
warper = new LogarithmicTimeWarper(mT0, mT1,
|
||||
rateStart, rateEnd);
|
||||
}
|
||||
TimeWarper *warper = createTimeWarper(mT0,mT1,(mT1-mT0)*mTotalStretch,rateStart,rateEnd,rateSlideType);
|
||||
SetTimeWarper(new RegionTimeWarper(mT0, mT1, warper));
|
||||
LabelTrack *lt = (LabelTrack*)t;
|
||||
if (lt == NULL) return false;
|
||||
@@ -144,16 +201,10 @@ bool EffectSBSMS::ProcessLabelTrack(Track *t)
|
||||
|
||||
bool EffectSBSMS::Process()
|
||||
{
|
||||
if(!bInit) {
|
||||
sbsms_init(8192);
|
||||
bInit = TRUE;
|
||||
}
|
||||
|
||||
bool bGoodResult = true;
|
||||
|
||||
//Iterate over each track
|
||||
// Track::All is needed because this effect needs to introduce
|
||||
// silence in the group tracks to keep sync-lock.
|
||||
//Track::All is needed because this effect needs to introduce silence in the group tracks to keep sync
|
||||
this->CopyInputTracks(Track::All); // Set up mOutputTracks.
|
||||
TrackListIterator iter(mOutputTracks);
|
||||
Track* t;
|
||||
@@ -161,13 +212,11 @@ bool EffectSBSMS::Process()
|
||||
|
||||
double maxDuration = 0.0;
|
||||
|
||||
if(rateStart == rateEnd)
|
||||
mTotalStretch = 1.0/rateStart;
|
||||
else
|
||||
mTotalStretch = 1.0/(rateEnd-rateStart)*log(rateEnd/rateStart);
|
||||
|
||||
// Must sync if selection length will change
|
||||
bool mustSync = (mTotalStretch != 1.0);
|
||||
bool mustSync = (rateStart != rateEnd);
|
||||
Slide rateSlide(rateSlideType,rateStart,rateEnd);
|
||||
Slide pitchSlide(pitchSlideType,pitchStart,pitchEnd);
|
||||
mTotalStretch = rateSlide.getTotalStretch();
|
||||
|
||||
t = iter.First();
|
||||
while (t != NULL) {
|
||||
@@ -218,131 +267,116 @@ bool EffectSBSMS::Process()
|
||||
|
||||
mCurTrackNum++; // Increment for rightTrack, too.
|
||||
}
|
||||
|
||||
sampleCount trackStart = leftTrack->TimeToLongSamples(leftTrack->GetStartTime());
|
||||
sampleCount trackEnd = leftTrack->TimeToLongSamples(leftTrack->GetEndTime());
|
||||
|
||||
// SBSMS has a fixed sample rate - we just convert to its sample rate and then convert back
|
||||
float srIn = leftTrack->GetRate();
|
||||
// mchinen: srSBMS doesn't do the right thing when it was set to fixed 44100. This seems to fix it.
|
||||
float srSBSMS = leftTrack->GetRate();
|
||||
|
||||
float srTrack = leftTrack->GetRate();
|
||||
float srProcess = bLinkRatePitch?srTrack:44100.0;
|
||||
|
||||
// the resampler needs a callback to supply its samples
|
||||
resampleBuf rb;
|
||||
ResampleBuf rb;
|
||||
sampleCount maxBlockSize = leftTrack->GetMaxBlockSize();
|
||||
rb.block = maxBlockSize;
|
||||
rb.buf = (audio*)calloc(rb.block,sizeof(audio));
|
||||
rb.blockSize = maxBlockSize;
|
||||
rb.buf = (audio*)calloc(rb.blockSize,sizeof(audio));
|
||||
rb.leftTrack = leftTrack;
|
||||
rb.rightTrack = rightTrack?rightTrack:leftTrack;
|
||||
rb.leftBuffer = (float*)calloc(maxBlockSize,sizeof(float));
|
||||
rb.rightBuffer = (float*)calloc(maxBlockSize,sizeof(float));
|
||||
rb.offset = start;
|
||||
rb.end = trackEnd;
|
||||
rb.ratio = srSBSMS/srIn;
|
||||
rb.resampler = new Resampler(resampleCB, &rb);
|
||||
|
||||
// Samples in selection
|
||||
sampleCount samplesIn = end-start;
|
||||
|
||||
// Samples for SBSMS to process after resampling
|
||||
sampleCount samplesToProcess = (sampleCount) ((real)samplesIn*(srSBSMS/srIn));
|
||||
sampleCount samplesToProcess = (sampleCount) ((float)samplesIn*(srProcess/srTrack));
|
||||
|
||||
SlideType outSlideType;
|
||||
SBSMSResampleCB outResampleCB;
|
||||
|
||||
sampleCount processPresamples = 0;
|
||||
sampleCount trackPresamples = 0;
|
||||
|
||||
if(bLinkRatePitch) {
|
||||
rb.bPitch = true;
|
||||
outSlideType = rateSlideType;
|
||||
outResampleCB = resampleCB;
|
||||
rb.offset = start;
|
||||
rb.end = end;
|
||||
rb.iface = new SBSMSInterfaceSliding(&rateSlide,&pitchSlide,
|
||||
bPitchReferenceInput,
|
||||
samplesToProcess,0,
|
||||
NULL);
|
||||
} else {
|
||||
rb.bPitch = false;
|
||||
outSlideType = (srProcess==srTrack?SlideIdentity:SlideConstant);
|
||||
outResampleCB = postResampleCB;
|
||||
rb.ratio = srProcess/srTrack;
|
||||
rb.quality = new SBSMSQuality(&SBSMSQualityStandard);
|
||||
rb.resampler = new Resampler(resampleCB, &rb, srProcess==srTrack?SlideIdentity:SlideConstant);
|
||||
rb.sbsms = new SBSMS(rightTrack?2:1,rb.quality,true);
|
||||
rb.SBSMSBlockSize = rb.sbsms->getInputFrameSize();
|
||||
rb.SBSMSBuf = (audio*)calloc(rb.SBSMSBlockSize,sizeof(audio));
|
||||
|
||||
processPresamples = wxMin(rb.quality->getMaxPresamples(),
|
||||
(long)((float)(start-trackStart)*(srProcess/srTrack)));
|
||||
trackPresamples = wxMin(start-trackStart,
|
||||
(long)((float)(processPresamples)*(srTrack/srProcess)));
|
||||
rb.offset = start - trackPresamples;
|
||||
rb.end = trackEnd;
|
||||
rb.iface = new SBSMSEffectInterface(rb.resampler,
|
||||
&rateSlide,&pitchSlide,
|
||||
bPitchReferenceInput,
|
||||
samplesToProcess,processPresamples,
|
||||
rb.quality);
|
||||
}
|
||||
|
||||
Resampler resampler(outResampleCB,&rb,outSlideType);
|
||||
|
||||
audio outBuf[SBSMSOutBlockSize];
|
||||
float outBufLeft[2*SBSMSOutBlockSize];
|
||||
float outBufRight[2*SBSMSOutBlockSize];
|
||||
|
||||
// Samples in output after SBSMS
|
||||
sampleCount samplesToOutput = rb.iface->getSamplesToOutput();
|
||||
|
||||
// Samples in output after resampling back
|
||||
sampleCount samplesToGenerate = (sampleCount) ((real)samplesToProcess * mTotalStretch);
|
||||
sampleCount samplesOut = (sampleCount) ((real)samplesIn * mTotalStretch);
|
||||
sampleCount samplesOut = (sampleCount) ((float)samplesToOutput * (srTrack/srProcess));
|
||||
|
||||
// Duration in track time
|
||||
double duration = (mCurT1-mCurT0) * mTotalStretch;
|
||||
|
||||
if(duration > maxDuration)
|
||||
maxDuration = duration;
|
||||
|
||||
TimeWarper *warper = NULL;
|
||||
if (rateStart == rateEnd)
|
||||
{
|
||||
warper = new LinearTimeWarper(mCurT0, mCurT0,
|
||||
mCurT1, mCurT0+maxDuration);
|
||||
} else
|
||||
{
|
||||
warper = new LogarithmicTimeWarper(mCurT0, mCurT1,
|
||||
rateStart, rateEnd);
|
||||
}
|
||||
TimeWarper *warper = createTimeWarper(mCurT0,mCurT1,maxDuration,rateStart,rateEnd,rateSlideType);
|
||||
SetTimeWarper(warper);
|
||||
|
||||
sbsmsInfo si;
|
||||
si.rs = rb.resampler;
|
||||
si.samplesToProcess = samplesToProcess;
|
||||
si.samplesToGenerate = samplesToGenerate;
|
||||
si.rate0 = rateStart;
|
||||
si.rate1 = rateEnd;
|
||||
si.pitch0 = pitchStart;
|
||||
si.pitch1 = pitchEnd;
|
||||
|
||||
sbsms_quality quality = sbsms_quality_fast;
|
||||
rb.sbsmser = sbsms_create(&samplesCB,&rateCBLinear,&pitchCBLinear,rightTrack?2:1,&quality,bPreAnalyze,true);
|
||||
|
||||
|
||||
rb.outputLeftTrack = mFactory->NewWaveTrack(leftTrack->GetSampleFormat(),
|
||||
leftTrack->GetRate());
|
||||
if(rightTrack)
|
||||
rb.outputRightTrack = mFactory->NewWaveTrack(rightTrack->GetSampleFormat(),
|
||||
rightTrack->GetRate());
|
||||
|
||||
|
||||
sampleCount blockSize = quality.maxoutframesize;
|
||||
rb.outBuf = (audio*)calloc(blockSize,sizeof(audio));
|
||||
rb.outputLeftBuffer = (float*)calloc(blockSize*2,sizeof(float));
|
||||
if(rightTrack)
|
||||
rb.outputRightBuffer = (float*)calloc(blockSize*2,sizeof(float));
|
||||
|
||||
long pos = 0;
|
||||
long outputCount = -1;
|
||||
|
||||
// pre analysis
|
||||
real fracPre = 0.0f;
|
||||
if(bPreAnalyze) {
|
||||
fracPre = 0.05f;
|
||||
resampleBuf rbPre;
|
||||
rbPre.block = maxBlockSize;
|
||||
rbPre.buf = (audio*)calloc(rb.block,sizeof(audio));
|
||||
rbPre.leftTrack = leftTrack;
|
||||
rbPre.rightTrack = rightTrack?rightTrack:leftTrack;
|
||||
rbPre.leftBuffer = (float*)calloc(maxBlockSize,sizeof(float));
|
||||
rbPre.rightBuffer = (float*)calloc(maxBlockSize,sizeof(float));
|
||||
rbPre.offset = start;
|
||||
rbPre.end = end;
|
||||
rbPre.ratio = srSBSMS/srIn;
|
||||
rbPre.resampler = new Resampler(resampleCB, &rbPre);
|
||||
si.rs = rbPre.resampler;
|
||||
|
||||
long pos = 0;
|
||||
long lastPos = 0;
|
||||
long ret = 0;
|
||||
while(lastPos<samplesToProcess) {
|
||||
ret = sbsms_pre_analyze(&samplesCB,&si,rb.sbsmser);
|
||||
lastPos = pos;
|
||||
pos += ret;
|
||||
real completion = (real)lastPos/(real)samplesToProcess;
|
||||
if (TrackProgress(0,fracPre*completion))
|
||||
return false;
|
||||
}
|
||||
sbsms_pre_analyze_complete(rb.sbsmser);
|
||||
sbsms_reset(rb.sbsmser);
|
||||
si.rs = rb.resampler;
|
||||
}
|
||||
|
||||
|
||||
// process
|
||||
while(pos<samplesOut && outputCount) {
|
||||
outputCount = sbsms_read_frame(rb.outBuf, &si, rb.sbsmser, NULL, NULL);
|
||||
if(pos+outputCount>samplesOut) {
|
||||
outputCount = samplesOut - pos;
|
||||
long frames;
|
||||
if(pos+SBSMSOutBlockSize>samplesOut) {
|
||||
frames = samplesOut - pos;
|
||||
} else {
|
||||
frames = SBSMSOutBlockSize;
|
||||
}
|
||||
|
||||
outputCount = resampler.read(outBuf,frames);
|
||||
for(int i = 0; i < outputCount; i++) {
|
||||
rb.outputLeftBuffer[i] = rb.outBuf[i][0];
|
||||
outBufLeft[i] = outBuf[i][0];
|
||||
if(rightTrack)
|
||||
rb.outputRightBuffer[i] = rb.outBuf[i][1];
|
||||
outBufRight[i] = outBuf[i][1];
|
||||
}
|
||||
pos += outputCount;
|
||||
rb.outputLeftTrack->Append((samplePtr)rb.outputLeftBuffer, floatSample, outputCount);
|
||||
rb.outputLeftTrack->Append((samplePtr)outBufLeft, floatSample, outputCount);
|
||||
if(rightTrack)
|
||||
rb.outputRightTrack->Append((samplePtr)rb.outputRightBuffer, floatSample, outputCount);
|
||||
rb.outputRightTrack->Append((samplePtr)outBufRight, floatSample, outputCount);
|
||||
|
||||
double frac = (double)pos/(double)samplesOut;
|
||||
int nWhichTrack = mCurTrackNum;
|
||||
@@ -356,7 +390,7 @@ bool EffectSBSMS::Process()
|
||||
frac *= 2.0; // Show twice as far for each track, because we're doing 2 at once.
|
||||
}
|
||||
}
|
||||
if (TrackProgress(nWhichTrack, fracPre + (1.0-fracPre)*frac))
|
||||
if (TrackProgress(nWhichTrack, frac))
|
||||
return false;
|
||||
}
|
||||
rb.outputLeftTrack->Flush();
|
||||
|
@@ -21,22 +21,23 @@
|
||||
#include "sbsms.h"
|
||||
using namespace _sbsms_;
|
||||
|
||||
class WaveTrack;
|
||||
|
||||
class EffectSBSMS : public Effect {
|
||||
public:
|
||||
static bool bInit;
|
||||
virtual bool Process();
|
||||
void setParameters(double rateStart, double rateEnd, double pitchStart, double pitchEnd, bool bPreAnalyze);
|
||||
void setParameters(double rateStart, double rateEnd, double pitchStart, double pitchEnd,
|
||||
SlideType rateSlideType, SlideType pitchSlideType,
|
||||
bool bLinkRatePitch, bool bRateReferenceInput, bool bPitchReferenceInput);
|
||||
|
||||
private:
|
||||
bool ProcessLabelTrack(Track *track);
|
||||
double rateStart, rateEnd, pitchStart, pitchEnd;
|
||||
bool bPreAnalyze;
|
||||
bool bLinkRatePitch, bRateReferenceInput, bPitchReferenceInput;
|
||||
SlideType rateSlideType;
|
||||
SlideType pitchSlideType;
|
||||
int mCurTrackNum;
|
||||
double mCurT0;
|
||||
double mCurT1;
|
||||
real mTotalStretch;
|
||||
float mTotalStretch;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -27,6 +27,8 @@
|
||||
#include "../ShuttleGui.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
@@ -38,7 +40,7 @@
|
||||
// EffectTimeScale
|
||||
//
|
||||
|
||||
EffectTimeScale::EffectTimeScale()
|
||||
EffectTimeScale::EffectTimeScale()
|
||||
{
|
||||
m_RatePercentChangeStart = 0;
|
||||
m_RatePercentChangeEnd = 0;
|
||||
@@ -46,7 +48,13 @@ EffectTimeScale::EffectTimeScale()
|
||||
m_PitchHalfStepsEnd = 0;
|
||||
m_PitchPercentChangeStart = 0;
|
||||
m_PitchPercentChangeEnd = 0;
|
||||
m_PreAnalyze = false;
|
||||
m_RateSlideType = 0;
|
||||
m_PitchSlideType = 0;
|
||||
m_RateSlideReference = 0;
|
||||
m_PitchSlideReference = 0;
|
||||
m_RateLinkInitialFinal = false;
|
||||
m_PitchLinkInitialFinal = false;
|
||||
m_LinkRatePitch = false;
|
||||
}
|
||||
|
||||
wxString EffectTimeScale::GetEffectDescription() {
|
||||
@@ -68,7 +76,13 @@ bool EffectTimeScale::PromptUser()
|
||||
dlog.m_PitchHalfStepsEnd = m_PitchHalfStepsEnd;
|
||||
dlog.m_PitchPercentChangeStart = m_PitchPercentChangeStart;
|
||||
dlog.m_PitchPercentChangeEnd = m_PitchPercentChangeEnd;
|
||||
dlog.m_PreAnalyze = m_PreAnalyze;
|
||||
dlog.m_LinkRatePitch = m_LinkRatePitch;
|
||||
dlog.m_RateSlideType = m_RateSlideType;
|
||||
dlog.m_PitchSlideType = m_PitchSlideType;
|
||||
dlog.m_RateSlideReference = m_RateSlideReference;
|
||||
dlog.m_PitchSlideReference = m_PitchSlideReference;
|
||||
dlog.m_RateLinkInitialFinal = m_RateLinkInitialFinal;
|
||||
dlog.m_PitchLinkInitialFinal = m_PitchLinkInitialFinal;
|
||||
|
||||
// Don't need to call TransferDataToWindow, although other
|
||||
// Audacity dialogs (from which I derived this one) do it, because
|
||||
@@ -86,7 +100,13 @@ bool EffectTimeScale::PromptUser()
|
||||
m_PitchHalfStepsEnd = dlog.m_PitchHalfStepsEnd;
|
||||
m_PitchPercentChangeStart = dlog.m_PitchPercentChangeStart;
|
||||
m_PitchPercentChangeEnd = dlog.m_PitchPercentChangeEnd;
|
||||
m_PreAnalyze = dlog.m_PreAnalyze;
|
||||
m_LinkRatePitch = dlog.m_LinkRatePitch;
|
||||
m_RateSlideType = dlog.m_RateSlideType;
|
||||
m_PitchSlideType = dlog.m_PitchSlideType;
|
||||
m_RateSlideReference = dlog.m_RateSlideReference;
|
||||
m_PitchSlideReference = dlog.m_PitchSlideReference;
|
||||
m_RateLinkInitialFinal = dlog.m_RateLinkInitialFinal;
|
||||
m_PitchLinkInitialFinal = dlog.m_PitchLinkInitialFinal;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -99,14 +119,15 @@ bool EffectTimeScale::TransferParameters( Shuttle & shuttle )
|
||||
shuttle.TransferDouble(wxT("PitchHalfStepsEnd"),m_PitchHalfStepsEnd,0.0);
|
||||
shuttle.TransferDouble(wxT("PitchPercentChangeStart"),m_PitchPercentChangeStart,0.0);
|
||||
shuttle.TransferDouble(wxT("PitchPercentChangeEnd"),m_PitchPercentChangeEnd,0.0);
|
||||
shuttle.TransferBool(wxT("PreAnalyze"),m_PreAnalyze,false);
|
||||
return true;
|
||||
}
|
||||
shuttle.TransferBool(wxT("LinkRatePitch"),m_LinkRatePitch,false);
|
||||
shuttle.TransferInt(wxT("RateSlideType"),m_RateSlideType,0);
|
||||
shuttle.TransferInt(wxT("PitchSlideType"),m_PitchSlideType,0);
|
||||
shuttle.TransferInt(wxT("RateSlideReference"),m_RateSlideReference,0);
|
||||
shuttle.TransferInt(wxT("PitchSlideReference"),m_PitchSlideReference,0);
|
||||
shuttle.TransferBool(wxT("RateLinkInitialFinal"),m_RateLinkInitialFinal,false);
|
||||
shuttle.TransferBool(wxT("PitchLinkInitialFinal"),m_PitchLinkInitialFinal,false);
|
||||
|
||||
inline double InvertedPercentChangeToRatio(double percentChange)
|
||||
{
|
||||
//mchinen hack: invert the ratio so it works with the sbsms bug which requires the reciprocal number.
|
||||
return 1.0/(1.0 + percentChange / 100.0);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline double PercentChangeToRatio(double percentChange)
|
||||
@@ -121,19 +142,50 @@ inline double HalfStepsToPercentChange(double halfSteps)
|
||||
|
||||
inline double PercentChangeToHalfSteps(double percentChange)
|
||||
{
|
||||
// mchinen: hack: take the negative of this so the correct value is displayed
|
||||
// (see the InvertedPercentChangeToRatio hack for why this is needed)
|
||||
return 17.312340490667560888319096172023 * log(PercentChangeToRatio(percentChange));
|
||||
}
|
||||
|
||||
bool EffectTimeScale::Process()
|
||||
{
|
||||
// The pitch part of sbsms is backwards, so use an inverted function
|
||||
double pitchStart = InvertedPercentChangeToRatio(m_PitchPercentChangeStart);
|
||||
double pitchEnd = InvertedPercentChangeToRatio(m_PitchPercentChangeEnd);
|
||||
double pitchStart = PercentChangeToRatio(m_PitchPercentChangeStart);
|
||||
double pitchEnd = PercentChangeToRatio(m_PitchPercentChangeEnd);
|
||||
double rateStart = PercentChangeToRatio(m_RatePercentChangeStart);
|
||||
double rateEnd = PercentChangeToRatio(m_RatePercentChangeEnd);
|
||||
this->EffectSBSMS::setParameters(rateStart,rateEnd,pitchStart,pitchEnd,m_PreAnalyze);
|
||||
SlideType rateSlideType;
|
||||
SlideType pitchSlideType;
|
||||
if(rateStart == rateEnd || m_RateLinkInitialFinal) {
|
||||
rateSlideType = SlideConstant;
|
||||
} else if(m_RateSlideType == 0) {
|
||||
if(m_RateSlideReference == 1) {
|
||||
rateSlideType = SlideLinearInputRate;
|
||||
} else {
|
||||
rateSlideType = SlideLinearOutputRate;
|
||||
}
|
||||
} else if(m_RateSlideType == 1) {
|
||||
if(m_RateSlideReference == 1) {
|
||||
rateSlideType = SlideLinearInputStretch;
|
||||
} else {
|
||||
rateSlideType = SlideLinearOutputStretch;
|
||||
}
|
||||
} else if(m_RateSlideType == 2) {
|
||||
if(m_RateSlideReference == 1) {
|
||||
rateSlideType = SlideGeometricInput;
|
||||
} else {
|
||||
rateSlideType = SlideGeometricOutput;
|
||||
}
|
||||
}
|
||||
if(pitchStart == pitchEnd || m_PitchLinkInitialFinal) {
|
||||
pitchSlideType = SlideConstant;
|
||||
} else if(m_PitchSlideType == 0) {
|
||||
pitchSlideType = SlideLinearInputRate;
|
||||
} else if(m_PitchSlideType == 1) {
|
||||
pitchSlideType = SlideLinearInputStretch;
|
||||
} else if(m_PitchSlideType == 2) {
|
||||
pitchSlideType = SlideGeometricInput;
|
||||
}
|
||||
bool rateReferenceInput = (m_RateSlideReference == 1);
|
||||
bool pitchReferenceInput = (m_PitchSlideReference == 1);
|
||||
this->EffectSBSMS::setParameters(rateStart,rateEnd,pitchStart,pitchEnd,rateSlideType,pitchSlideType,m_LinkRatePitch,rateReferenceInput,pitchReferenceInput);
|
||||
return this->EffectSBSMS::Process();
|
||||
}
|
||||
|
||||
@@ -141,16 +193,15 @@ bool EffectTimeScale::Process()
|
||||
// TimeScaleDialog
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#define RATE_PERCENTCHANGE_MAX_SLIDER 150
|
||||
#define RATE_PERCENTCHANGE_MIN_SLIDER -75
|
||||
#define RATE_PERCENTCHANGE_MAX_TEXT 500
|
||||
#define RATE_PERCENTCHANGE_MAX_SLIDER 150
|
||||
#define RATE_PERCENTCHANGE_MIN_TEXT -90
|
||||
#define RATE_PERCENTCHANGE_MAX_TEXT 500
|
||||
#define RATE_PERCENTCHANGE_DEFAULT 0
|
||||
#define PITCH_HALFSTEPS_MIN_TEXT -12
|
||||
#define PITCH_HALFSTEPS_MAX_TEXT 12
|
||||
#define PITCH_PERCENTCHANGE_MIN_TEXT -50
|
||||
#define PITCH_PERCENTCHANGE_MAX_TEXT 100
|
||||
|
||||
#define PITCH_HALFSTEPS_MIN_TEXT -24
|
||||
#define PITCH_HALFSTEPS_MAX_TEXT 24
|
||||
#define PITCH_PERCENTCHANGE_MIN_TEXT -75
|
||||
#define PITCH_PERCENTCHANGE_MAX_TEXT 300
|
||||
|
||||
#define ID_TEXT_RATE_PERCENTCHANGE_START 10001
|
||||
#define ID_TEXT_RATE_PERCENTCHANGE_END 10002
|
||||
@@ -160,7 +211,13 @@ bool EffectTimeScale::Process()
|
||||
#define ID_TEXT_PITCH_PERCENTCHANGE_END 10006
|
||||
#define ID_SLIDER_RATE_PERCENTCHANGE_START 10007
|
||||
#define ID_SLIDER_RATE_PERCENTCHANGE_END 10008
|
||||
#define ID_CHECKBOX_PREANALYZE 10009
|
||||
#define ID_CHECKBOX_LINKRATEPITCH 10010
|
||||
#define ID_CHOICE_RATE_SLIDETYPE 10011
|
||||
#define ID_CHOICE_PITCH_SLIDETYPE 10012
|
||||
#define ID_CHOICE_RATE_SLIDEREFERENCE 10013
|
||||
#define ID_CHOICE_PITCH_SLIDEREFERENCE 10014
|
||||
#define ID_CHECKBOX_RATE_LINKINITIALFINAL 10015
|
||||
#define ID_CHECKBOX_PITCH_LINKINITIALFINAL 10016
|
||||
|
||||
// event table for TimeScaleDialog
|
||||
|
||||
@@ -173,13 +230,31 @@ BEGIN_EVENT_TABLE(TimeScaleDialog, EffectDialog)
|
||||
EVT_TEXT(ID_TEXT_PITCH_PERCENTCHANGE_END, TimeScaleDialog::OnText_PitchPercentChangeEnd)
|
||||
EVT_SLIDER(ID_SLIDER_RATE_PERCENTCHANGE_START, TimeScaleDialog::OnSlider_RatePercentChangeStart)
|
||||
EVT_SLIDER(ID_SLIDER_RATE_PERCENTCHANGE_END, TimeScaleDialog::OnSlider_RatePercentChangeEnd)
|
||||
EVT_CHECKBOX(ID_CHECKBOX_PREANALYZE, TimeScaleDialog::OnCheckBox_PreAnalyze)
|
||||
EVT_CHECKBOX(ID_CHECKBOX_LINKRATEPITCH, TimeScaleDialog::OnCheckBox_LinkRatePitch)
|
||||
EVT_CHOICE(ID_CHOICE_RATE_SLIDETYPE, TimeScaleDialog::OnChoice_RateSlideType)
|
||||
EVT_CHOICE(ID_CHOICE_PITCH_SLIDETYPE, TimeScaleDialog::OnChoice_PitchSlideType)
|
||||
EVT_CHOICE(ID_CHOICE_RATE_SLIDEREFERENCE, TimeScaleDialog::OnChoice_RateSlideReference)
|
||||
EVT_CHOICE(ID_CHOICE_PITCH_SLIDEREFERENCE, TimeScaleDialog::OnChoice_PitchSlideReference)
|
||||
EVT_CHECKBOX(ID_CHECKBOX_RATE_LINKINITIALFINAL, TimeScaleDialog::OnCheckBox_RateLinkInitialFinal)
|
||||
EVT_CHECKBOX(ID_CHECKBOX_PITCH_LINKINITIALFINAL, TimeScaleDialog::OnCheckBox_PitchLinkInitialFinal)
|
||||
EVT_BUTTON(ID_EFFECT_PREVIEW, TimeScaleDialog::OnPreview)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
TimeScaleDialog::TimeScaleDialog(EffectTimeScale *effect, wxWindow *parent)
|
||||
: EffectDialog(parent, _("Time Scale"), INSERT_EFFECT),
|
||||
: EffectDialog(parent, _("Time Scale"), PROCESS_EFFECT),
|
||||
mEffect(effect)
|
||||
{
|
||||
rateSlideTypes.Add(_("Linear Rate"));
|
||||
rateSlideTypes.Add(_("Linear Stretch"));
|
||||
rateSlideTypes.Add(_("Geometric"));
|
||||
pitchSlideTypes.Add(_("Linear Rate"));
|
||||
pitchSlideTypes.Add(_("Linear Stretch"));
|
||||
pitchSlideTypes.Add(_("Geometric"));
|
||||
rateSlideReferences.Add(_("Output"));
|
||||
rateSlideReferences.Add(_("Input"));
|
||||
pitchSlideReferences.Add(_("Output"));
|
||||
pitchSlideReferences.Add(_("Input"));
|
||||
|
||||
m_bLoopDetect = false;
|
||||
|
||||
// NULL out these control members because there are some cases where the
|
||||
@@ -194,7 +269,13 @@ TimeScaleDialog::TimeScaleDialog(EffectTimeScale *effect, wxWindow *parent)
|
||||
m_pTextCtrl_PitchPercentChangeEnd = NULL;
|
||||
m_pTextCtrl_PitchHalfStepsStart = NULL;
|
||||
m_pTextCtrl_PitchHalfStepsEnd = NULL;
|
||||
m_pCheckBox_PreAnalyze = NULL;
|
||||
m_pCheckBox_LinkRatePitch = NULL;
|
||||
m_pChoice_RateSlideType = NULL;
|
||||
m_pChoice_PitchSlideType = NULL;
|
||||
m_pChoice_RateSlideReference = NULL;
|
||||
m_pChoice_PitchSlideReference = NULL;
|
||||
m_pCheckBox_RateLinkInitialFinal = NULL;
|
||||
m_pCheckBox_PitchLinkInitialFinal = NULL;
|
||||
|
||||
// effect parameters
|
||||
m_RatePercentChangeStart = 0;
|
||||
@@ -203,17 +284,27 @@ TimeScaleDialog::TimeScaleDialog(EffectTimeScale *effect, wxWindow *parent)
|
||||
m_PitchPercentChangeEnd = 0;
|
||||
m_PitchHalfStepsStart = 0;
|
||||
m_PitchHalfStepsEnd = 0;
|
||||
m_PreAnalyze = false;
|
||||
m_LinkRatePitch = false;
|
||||
m_RateSlideType = 0;
|
||||
m_PitchSlideType = 0;
|
||||
m_RateSlideReference = 0;
|
||||
m_PitchSlideReference = 0;
|
||||
m_RateLinkInitialFinal = false;
|
||||
m_PitchLinkInitialFinal = false;
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
void TimeScaleDialog::OnPreview(wxCommandEvent & event)
|
||||
{
|
||||
mEffect->Preview();
|
||||
}
|
||||
|
||||
void TimeScaleDialog::PopulateOrExchange(ShuttleGui & S)
|
||||
{
|
||||
|
||||
wxTextValidator nullvld(wxFILTER_INCLUDE_CHAR_LIST);
|
||||
wxTextValidator numvld(wxFILTER_NUMERIC);
|
||||
|
||||
|
||||
S.SetBorder(10);
|
||||
S.StartHorizontalLay(wxCENTER, false);
|
||||
{
|
||||
@@ -223,94 +314,130 @@ void TimeScaleDialog::PopulateOrExchange(ShuttleGui & S)
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
S.SetBorder(5);
|
||||
|
||||
S.StartMultiColumn(2, 0);
|
||||
// Rate Start
|
||||
S.StartStatic(_("Initial Tempo Change (%)"));
|
||||
|
||||
S.StartStatic(_("Tempo Change"));
|
||||
{
|
||||
S.StartMultiColumn(1, wxCENTER);
|
||||
S.StartHorizontalLay(wxEXPAND);
|
||||
{
|
||||
m_pTextCtrl_RatePercentChangeStart = S.Id(ID_TEXT_RATE_PERCENTCHANGE_START)
|
||||
.AddTextBox(wxT(""), wxT(""), 12);
|
||||
m_pTextCtrl_RatePercentChangeStart->SetValidator(numvld);
|
||||
S.StartVerticalLay(wxCENTER);
|
||||
{
|
||||
S.StartHorizontalLay(wxCENTER,0);
|
||||
{
|
||||
m_pTextCtrl_RatePercentChangeStart = S.Id(ID_TEXT_RATE_PERCENTCHANGE_START)
|
||||
.AddTextBox(_("Initial (%)"), wxT(""), 12);
|
||||
m_pTextCtrl_RatePercentChangeStart->SetValidator(numvld);
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
|
||||
S.StartHorizontalLay(wxEXPAND,0);
|
||||
{
|
||||
S.SetStyle(wxSL_HORIZONTAL);
|
||||
m_pSlider_RatePercentChangeStart = S.Id(ID_SLIDER_RATE_PERCENTCHANGE_START)
|
||||
.AddSlider(wxT(""), (int)RATE_PERCENTCHANGE_DEFAULT, (int)RATE_PERCENTCHANGE_MAX_SLIDER, (int)RATE_PERCENTCHANGE_MIN_SLIDER);
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
}
|
||||
S.EndVerticalLay();
|
||||
|
||||
S.StartVerticalLay(wxCENTER);
|
||||
{
|
||||
S.StartHorizontalLay(wxCENTER,0);
|
||||
{
|
||||
m_pTextCtrl_RatePercentChangeEnd = S.Id(ID_TEXT_RATE_PERCENTCHANGE_END)
|
||||
.AddTextBox(_("Final (%)"), wxT(""), 12);
|
||||
m_pTextCtrl_RatePercentChangeEnd->SetValidator(numvld);
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
|
||||
S.StartHorizontalLay(wxEXPAND,0);
|
||||
{
|
||||
S.SetStyle(wxSL_HORIZONTAL);
|
||||
m_pSlider_RatePercentChangeEnd = S.Id(ID_SLIDER_RATE_PERCENTCHANGE_END)
|
||||
.AddSlider(wxT(""), (int)RATE_PERCENTCHANGE_DEFAULT, (int)RATE_PERCENTCHANGE_MAX_SLIDER, (int)RATE_PERCENTCHANGE_MIN_SLIDER);
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
}
|
||||
S.EndVerticalLay();
|
||||
}
|
||||
S.EndMultiColumn();
|
||||
S.StartHorizontalLay(wxEXPAND,0);
|
||||
S.EndHorizontalLay();
|
||||
|
||||
S.StartHorizontalLay(0,0);
|
||||
{
|
||||
S.SetStyle(wxSL_HORIZONTAL);
|
||||
m_pSlider_RatePercentChangeStart = S.Id(ID_SLIDER_RATE_PERCENTCHANGE_START)
|
||||
.AddSlider(wxT(""), (int)RATE_PERCENTCHANGE_DEFAULT, (int)RATE_PERCENTCHANGE_MAX_SLIDER, (int)RATE_PERCENTCHANGE_MIN_SLIDER);
|
||||
m_pChoice_RateSlideType = S.Id(ID_CHOICE_RATE_SLIDETYPE)
|
||||
.AddChoice(_("Slide Type"),_("Linear Rate"),&rateSlideTypes);
|
||||
m_pChoice_RateSlideType->SetSelection(0);
|
||||
m_pChoice_RateSlideType->SetSizeHints(-1,-1);
|
||||
m_pChoice_RateSlideReference = S.Id(ID_CHOICE_RATE_SLIDEREFERENCE)
|
||||
.AddChoice(_("Reference"),_("Output"),&rateSlideReferences);
|
||||
m_pChoice_RateSlideReference->SetSelection(0);
|
||||
m_pChoice_RateSlideReference->SetSizeHints(-1,-1);
|
||||
m_pCheckBox_RateLinkInitialFinal = S.Id(ID_CHECKBOX_RATE_LINKINITIALFINAL)
|
||||
.AddCheckBox(_("Link Initial/Final"), wxT("false"));
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
}
|
||||
S.EndStatic();
|
||||
|
||||
S.StartStatic(_("Final Tempo Change (%)"));
|
||||
// Pitch Change
|
||||
S.StartStatic(_("Pitch Shift"));
|
||||
{
|
||||
S.StartMultiColumn(1, wxCENTER);
|
||||
S.StartMultiColumn(2, wxCENTER);
|
||||
{
|
||||
m_pTextCtrl_RatePercentChangeEnd = S.Id(ID_TEXT_RATE_PERCENTCHANGE_END)
|
||||
.AddTextBox(wxT(""), wxT(""), 12);
|
||||
m_pTextCtrl_RatePercentChangeEnd->SetValidator(numvld);
|
||||
S.StartMultiColumn(2, wxCENTER);
|
||||
{
|
||||
m_pTextCtrl_PitchHalfStepsStart = S.Id(ID_TEXT_PITCH_HALFSTEPS_START)
|
||||
.AddTextBox(_("Initial (semitones) [-24 to 24]:"), wxT(""), 12);
|
||||
m_pTextCtrl_PitchHalfStepsStart->SetValidator(numvld);
|
||||
m_pTextCtrl_PitchPercentChangeStart = S.Id(ID_TEXT_PITCH_PERCENTCHANGE_START)
|
||||
.AddTextBox(_("Initial (%) [-75 to 300]:"), wxT(""), 12);
|
||||
m_pTextCtrl_PitchPercentChangeStart->SetValidator(numvld);
|
||||
}
|
||||
S.EndMultiColumn();
|
||||
|
||||
S.StartMultiColumn(2, wxCENTER);
|
||||
{
|
||||
m_pTextCtrl_PitchHalfStepsEnd = S.Id(ID_TEXT_PITCH_HALFSTEPS_END)
|
||||
.AddTextBox(_("Final (semitones) [-24 to 24]:"), wxT(""), 12);
|
||||
m_pTextCtrl_PitchHalfStepsEnd->SetValidator(numvld);
|
||||
|
||||
m_pTextCtrl_PitchPercentChangeEnd = S.Id(ID_TEXT_PITCH_PERCENTCHANGE_END)
|
||||
.AddTextBox(_("Final (%) [-75 to 300]:"), wxT(""), 12);
|
||||
m_pTextCtrl_PitchPercentChangeEnd->SetValidator(numvld);
|
||||
}
|
||||
S.EndMultiColumn();
|
||||
}
|
||||
S.EndMultiColumn();
|
||||
S.StartHorizontalLay(wxEXPAND,0);
|
||||
{
|
||||
S.SetStyle(wxSL_HORIZONTAL);
|
||||
m_pSlider_RatePercentChangeEnd = S.Id(ID_SLIDER_RATE_PERCENTCHANGE_END)
|
||||
.AddSlider(wxT(""), (int)RATE_PERCENTCHANGE_DEFAULT, (int)RATE_PERCENTCHANGE_MAX_SLIDER, (int)RATE_PERCENTCHANGE_MIN_SLIDER);
|
||||
|
||||
S.StartHorizontalLay(0,0);
|
||||
{
|
||||
m_pChoice_PitchSlideType = S.Id(ID_CHOICE_PITCH_SLIDETYPE)
|
||||
.AddChoice(_("Slide Type"),_("Linear"),&pitchSlideTypes);
|
||||
m_pChoice_PitchSlideType->SetSelection(0);
|
||||
m_pChoice_PitchSlideType->SetSizeHints(-1,-1);
|
||||
m_pChoice_PitchSlideReference = S.Id(ID_CHOICE_PITCH_SLIDEREFERENCE)
|
||||
.AddChoice(_("Reference"),_("Output"),&pitchSlideReferences);
|
||||
m_pChoice_PitchSlideReference->SetSelection(0);
|
||||
m_pChoice_PitchSlideReference->SetSizeHints(-1,-1);
|
||||
m_pCheckBox_PitchLinkInitialFinal = S.Id(ID_CHECKBOX_PITCH_LINKINITIALFINAL)
|
||||
.AddCheckBox(_("Link Initial/Final"), wxT("false"));
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
}
|
||||
S.EndStatic();
|
||||
|
||||
// Pitch Start
|
||||
S.StartStatic(_("Initial Pitch Shift"));
|
||||
{
|
||||
S.StartMultiColumn(2, wxCENTER);
|
||||
{
|
||||
m_pTextCtrl_PitchHalfStepsStart = S.Id(ID_TEXT_PITCH_HALFSTEPS_START)
|
||||
.AddTextBox(_("(semitones) [-12 to 12]:"), wxT(""), 12);
|
||||
m_pTextCtrl_PitchHalfStepsStart->SetValidator(numvld);
|
||||
|
||||
m_pTextCtrl_PitchPercentChangeStart = S.Id(ID_TEXT_PITCH_PERCENTCHANGE_START)
|
||||
.AddTextBox(_("(%) [-50 to 100]:"), wxT(""), 12);
|
||||
m_pTextCtrl_PitchPercentChangeStart->SetValidator(numvld);
|
||||
}
|
||||
S.EndMultiColumn();
|
||||
}
|
||||
S.EndStatic();
|
||||
|
||||
// Pitch End
|
||||
S.StartStatic(_("Final Pitch Shift"));
|
||||
{
|
||||
S.StartMultiColumn(2, wxCENTER);
|
||||
{
|
||||
m_pTextCtrl_PitchHalfStepsEnd = S.Id(ID_TEXT_PITCH_HALFSTEPS_END)
|
||||
.AddTextBox(_("(semitones) [-12 to 12]:"), wxT(""), 12);
|
||||
m_pTextCtrl_PitchHalfStepsEnd->SetValidator(numvld);
|
||||
|
||||
m_pTextCtrl_PitchPercentChangeEnd = S.Id(ID_TEXT_PITCH_PERCENTCHANGE_END)
|
||||
.AddTextBox(_("(%) [-50 to 100]:"), wxT(""), 12);
|
||||
m_pTextCtrl_PitchPercentChangeEnd->SetValidator(numvld);
|
||||
}
|
||||
S.EndMultiColumn();
|
||||
}
|
||||
S.EndStatic();
|
||||
S.EndMultiColumn();
|
||||
|
||||
S.StartStatic(_("Options"));
|
||||
{
|
||||
S.StartHorizontalLay(wxEXPAND);
|
||||
{
|
||||
S.SetStyle(wxSL_HORIZONTAL);
|
||||
m_pCheckBox_PreAnalyze = S.Id(ID_CHECKBOX_PREANALYZE)
|
||||
.AddCheckBox(wxT("Dynamic Transient Sharpening"), wxT("Dynamic Transient Sharpening"));
|
||||
m_pCheckBox_LinkRatePitch = S.Id(ID_CHECKBOX_LINKRATEPITCH)
|
||||
.AddCheckBox(_("Link Rate/Pitch (Resample)"), wxT("false"));
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
}
|
||||
S.EndStatic();
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -326,7 +453,13 @@ bool TimeScaleDialog::TransferDataToWindow()
|
||||
this->Update_Text_PitchHalfStepsEnd();
|
||||
this->Update_Text_PitchPercentChangeStart();
|
||||
this->Update_Text_PitchPercentChangeEnd();
|
||||
this->Update_CheckBox_PreAnalyze();
|
||||
this->Update_CheckBox_LinkRatePitch();
|
||||
this->Update_Choice_RateSlideType();
|
||||
this->Update_Choice_PitchSlideType();
|
||||
this->Update_Choice_RateSlideReference();
|
||||
this->Update_Choice_PitchSlideReference();
|
||||
this->Update_CheckBox_RateLinkInitialFinal();
|
||||
this->Update_CheckBox_PitchLinkInitialFinal();
|
||||
|
||||
m_bLoopDetect = false;
|
||||
|
||||
@@ -379,8 +512,32 @@ bool TimeScaleDialog::TransferDataFromWindow()
|
||||
m_PitchPercentChangeEnd = newValue;
|
||||
}
|
||||
|
||||
if(m_pCheckBox_PreAnalyze) {
|
||||
m_PreAnalyze = m_pCheckBox_PreAnalyze->GetValue();
|
||||
if(m_pCheckBox_LinkRatePitch) {
|
||||
m_LinkRatePitch = m_pCheckBox_LinkRatePitch->GetValue();
|
||||
}
|
||||
|
||||
if(m_pChoice_RateSlideType) {
|
||||
m_RateSlideType = m_pChoice_RateSlideType->GetSelection();
|
||||
}
|
||||
|
||||
if(m_pChoice_PitchSlideType) {
|
||||
m_PitchSlideType = m_pChoice_PitchSlideType->GetSelection();
|
||||
}
|
||||
|
||||
if(m_pChoice_RateSlideReference) {
|
||||
m_RateSlideReference = m_pChoice_RateSlideReference->GetSelection();
|
||||
}
|
||||
|
||||
if(m_pChoice_PitchSlideReference) {
|
||||
m_PitchSlideReference = m_pChoice_PitchSlideReference->GetSelection();
|
||||
}
|
||||
|
||||
if(m_pCheckBox_RateLinkInitialFinal) {
|
||||
m_RateLinkInitialFinal = m_pCheckBox_RateLinkInitialFinal->GetValue();
|
||||
}
|
||||
|
||||
if(m_pCheckBox_PitchLinkInitialFinal) {
|
||||
m_PitchLinkInitialFinal = m_pCheckBox_PitchLinkInitialFinal->GetValue();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -395,17 +552,18 @@ bool TimeScaleDialog::CheckParameters()
|
||||
(m_RatePercentChangeEnd >= RATE_PERCENTCHANGE_MIN_TEXT &&
|
||||
m_RatePercentChangeEnd <= RATE_PERCENTCHANGE_MAX_TEXT)
|
||||
&&
|
||||
(m_PitchHalfStepsStart >= PITCH_HALFSTEPS_MIN_TEXT &&
|
||||
m_PitchHalfStepsStart <= PITCH_HALFSTEPS_MAX_TEXT)
|
||||
&&
|
||||
(m_PitchHalfStepsEnd >= PITCH_HALFSTEPS_MIN_TEXT &&
|
||||
m_PitchHalfStepsEnd <= PITCH_HALFSTEPS_MAX_TEXT)
|
||||
&&
|
||||
(m_PitchPercentChangeStart >= PITCH_PERCENTCHANGE_MIN_TEXT &&
|
||||
m_PitchPercentChangeStart <= PITCH_PERCENTCHANGE_MAX_TEXT)
|
||||
&&
|
||||
(m_PitchPercentChangeEnd >= PITCH_PERCENTCHANGE_MIN_TEXT &&
|
||||
m_PitchPercentChangeEnd <= PITCH_PERCENTCHANGE_MAX_TEXT);
|
||||
(m_LinkRatePitch ||
|
||||
((m_PitchHalfStepsStart >= PITCH_HALFSTEPS_MIN_TEXT &&
|
||||
m_PitchHalfStepsStart <= PITCH_HALFSTEPS_MAX_TEXT)
|
||||
&&
|
||||
(m_PitchHalfStepsEnd >= PITCH_HALFSTEPS_MIN_TEXT &&
|
||||
m_PitchHalfStepsEnd <= PITCH_HALFSTEPS_MAX_TEXT)
|
||||
&&
|
||||
(m_PitchPercentChangeStart >= PITCH_PERCENTCHANGE_MIN_TEXT &&
|
||||
m_PitchPercentChangeStart <= PITCH_PERCENTCHANGE_MAX_TEXT)
|
||||
&&
|
||||
(m_PitchPercentChangeEnd >= PITCH_PERCENTCHANGE_MIN_TEXT &&
|
||||
m_PitchPercentChangeEnd <= PITCH_PERCENTCHANGE_MAX_TEXT)));
|
||||
}
|
||||
|
||||
// handler implementations for TimeScaleDialog
|
||||
@@ -423,6 +581,23 @@ void TimeScaleDialog::OnText_RatePercentChangeStart(wxCommandEvent & event)
|
||||
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Slider_RatePercentChangeStart();
|
||||
if(m_LinkRatePitch) {
|
||||
m_PitchPercentChangeStart = m_RatePercentChangeStart;
|
||||
m_PitchHalfStepsStart = PercentChangeToHalfSteps(m_PitchPercentChangeStart);
|
||||
this->Update_Text_PitchPercentChangeStart();
|
||||
this->Update_Text_PitchHalfStepsStart();
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_PitchPercentChangeEnd = m_RatePercentChangeStart;
|
||||
m_PitchHalfStepsEnd = m_PitchHalfStepsStart;
|
||||
this->Update_Text_PitchPercentChangeEnd();
|
||||
this->Update_Text_PitchHalfStepsEnd();
|
||||
}
|
||||
}
|
||||
if(m_RateLinkInitialFinal) {
|
||||
m_RatePercentChangeEnd = m_RatePercentChangeStart;
|
||||
this->Update_Text_RatePercentChangeEnd();
|
||||
this->Update_Slider_RatePercentChangeEnd();
|
||||
}
|
||||
m_bLoopDetect = false;
|
||||
|
||||
FindWindow(wxID_OK)->Enable(CheckParameters());
|
||||
@@ -442,6 +617,23 @@ void TimeScaleDialog::OnText_RatePercentChangeEnd(wxCommandEvent & event)
|
||||
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Slider_RatePercentChangeEnd();
|
||||
if(m_LinkRatePitch) {
|
||||
m_PitchPercentChangeEnd = m_RatePercentChangeEnd;
|
||||
m_PitchHalfStepsEnd = PercentChangeToHalfSteps(m_PitchPercentChangeEnd);
|
||||
this->Update_Text_PitchPercentChangeEnd();
|
||||
this->Update_Text_PitchHalfStepsEnd();
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_PitchPercentChangeStart = m_RatePercentChangeEnd;
|
||||
m_PitchHalfStepsStart = m_PitchHalfStepsEnd;
|
||||
this->Update_Text_PitchPercentChangeStart();
|
||||
this->Update_Text_PitchHalfStepsStart();
|
||||
}
|
||||
}
|
||||
if(m_RateLinkInitialFinal) {
|
||||
m_RatePercentChangeStart = m_RatePercentChangeEnd;
|
||||
this->Update_Text_RatePercentChangeStart();
|
||||
this->Update_Slider_RatePercentChangeStart();
|
||||
}
|
||||
m_bLoopDetect = false;
|
||||
|
||||
FindWindow(wxID_OK)->Enable(CheckParameters());
|
||||
@@ -458,7 +650,26 @@ void TimeScaleDialog::OnSlider_RatePercentChangeStart(wxCommandEvent & event)
|
||||
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Text_RatePercentChangeStart();
|
||||
if(m_LinkRatePitch) {
|
||||
m_PitchPercentChangeStart = m_RatePercentChangeStart;
|
||||
m_PitchHalfStepsStart = PercentChangeToHalfSteps(m_PitchPercentChangeStart);
|
||||
this->Update_Text_PitchPercentChangeStart();
|
||||
this->Update_Text_PitchHalfStepsStart();
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_PitchPercentChangeEnd = m_RatePercentChangeStart;
|
||||
m_PitchHalfStepsEnd = m_PitchHalfStepsStart;
|
||||
this->Update_Text_PitchPercentChangeEnd();
|
||||
this->Update_Text_PitchHalfStepsEnd();
|
||||
}
|
||||
}
|
||||
if(m_RateLinkInitialFinal) {
|
||||
m_RatePercentChangeEnd = m_RatePercentChangeStart;
|
||||
this->Update_Text_RatePercentChangeEnd();
|
||||
this->Update_Slider_RatePercentChangeEnd();
|
||||
}
|
||||
m_bLoopDetect = false;
|
||||
|
||||
FindWindow(wxID_OK)->Enable(CheckParameters());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -472,7 +683,26 @@ void TimeScaleDialog::OnSlider_RatePercentChangeEnd(wxCommandEvent & event)
|
||||
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Text_RatePercentChangeEnd();
|
||||
if(m_LinkRatePitch) {
|
||||
m_PitchPercentChangeEnd = m_RatePercentChangeEnd;
|
||||
m_PitchHalfStepsEnd = PercentChangeToHalfSteps(m_PitchPercentChangeEnd);
|
||||
this->Update_Text_PitchPercentChangeEnd();
|
||||
this->Update_Text_PitchHalfStepsEnd();
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_PitchPercentChangeStart = m_RatePercentChangeEnd;
|
||||
m_PitchHalfStepsStart = m_PitchHalfStepsEnd;
|
||||
this->Update_Text_PitchPercentChangeStart();
|
||||
this->Update_Text_PitchHalfStepsStart();
|
||||
}
|
||||
}
|
||||
if(m_RateLinkInitialFinal) {
|
||||
m_RatePercentChangeStart = m_RatePercentChangeEnd;
|
||||
this->Update_Text_RatePercentChangeStart();
|
||||
this->Update_Slider_RatePercentChangeStart();
|
||||
}
|
||||
m_bLoopDetect = false;
|
||||
|
||||
FindWindow(wxID_OK)->Enable(CheckParameters());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,6 +720,22 @@ void TimeScaleDialog::OnText_PitchHalfStepsStart(wxCommandEvent & event)
|
||||
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Text_PitchPercentChangeStart();
|
||||
if(m_LinkRatePitch) {
|
||||
m_RatePercentChangeStart = m_PitchPercentChangeStart;
|
||||
this->Update_Text_RatePercentChangeStart();
|
||||
this->Update_Slider_RatePercentChangeStart();
|
||||
if(m_RateLinkInitialFinal) {
|
||||
m_RatePercentChangeEnd = m_PitchPercentChangeStart;
|
||||
this->Update_Text_RatePercentChangeEnd();
|
||||
this->Update_Slider_RatePercentChangeEnd();
|
||||
}
|
||||
}
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_PitchPercentChangeEnd = m_PitchPercentChangeStart;
|
||||
m_PitchHalfStepsEnd = m_PitchHalfStepsStart;
|
||||
this->Update_Text_PitchPercentChangeEnd();
|
||||
this->Update_Text_PitchHalfStepsEnd();
|
||||
}
|
||||
m_bLoopDetect = false;
|
||||
|
||||
FindWindow(wxID_OK)->Enable(CheckParameters());
|
||||
@@ -510,6 +756,22 @@ void TimeScaleDialog::OnText_PitchHalfStepsEnd(wxCommandEvent & event)
|
||||
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Text_PitchPercentChangeEnd();
|
||||
if(m_LinkRatePitch) {
|
||||
m_RatePercentChangeEnd = m_PitchPercentChangeEnd;
|
||||
this->Update_Text_RatePercentChangeEnd();
|
||||
this->Update_Slider_RatePercentChangeEnd();
|
||||
if(m_RateLinkInitialFinal) {
|
||||
m_RatePercentChangeStart = m_PitchPercentChangeEnd;
|
||||
this->Update_Text_RatePercentChangeStart();
|
||||
this->Update_Slider_RatePercentChangeStart();
|
||||
}
|
||||
}
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_PitchPercentChangeStart = m_PitchPercentChangeEnd;
|
||||
m_PitchHalfStepsStart = m_PitchHalfStepsEnd;
|
||||
this->Update_Text_PitchPercentChangeStart();
|
||||
this->Update_Text_PitchHalfStepsStart();
|
||||
}
|
||||
m_bLoopDetect = false;
|
||||
|
||||
FindWindow(wxID_OK)->Enable(CheckParameters());
|
||||
@@ -527,11 +789,27 @@ void TimeScaleDialog::OnText_PitchPercentChangeStart(wxCommandEvent & event)
|
||||
str.ToDouble(&newValue);
|
||||
m_PitchPercentChangeStart = newValue;
|
||||
m_PitchHalfStepsStart = PercentChangeToHalfSteps(newValue);
|
||||
|
||||
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Text_PitchHalfStepsStart();
|
||||
if(m_LinkRatePitch) {
|
||||
m_RatePercentChangeStart = m_PitchPercentChangeStart;
|
||||
this->Update_Text_RatePercentChangeStart();
|
||||
this->Update_Slider_RatePercentChangeStart();
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_RatePercentChangeEnd = m_PitchPercentChangeStart;
|
||||
this->Update_Text_RatePercentChangeEnd();
|
||||
this->Update_Slider_RatePercentChangeEnd();
|
||||
}
|
||||
}
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_PitchPercentChangeEnd = m_PitchPercentChangeStart;
|
||||
m_PitchHalfStepsEnd = m_PitchHalfStepsStart;
|
||||
this->Update_Text_PitchPercentChangeEnd();
|
||||
this->Update_Text_PitchHalfStepsEnd();
|
||||
}
|
||||
m_bLoopDetect = false;
|
||||
|
||||
|
||||
FindWindow(wxID_OK)->Enable(CheckParameters());
|
||||
}
|
||||
}
|
||||
@@ -550,16 +828,156 @@ void TimeScaleDialog::OnText_PitchPercentChangeEnd(wxCommandEvent & event)
|
||||
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Text_PitchHalfStepsEnd();
|
||||
if(m_LinkRatePitch) {
|
||||
m_RatePercentChangeEnd = m_PitchPercentChangeEnd;
|
||||
this->Update_Text_RatePercentChangeEnd();
|
||||
this->Update_Slider_RatePercentChangeEnd();
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_RatePercentChangeStart = m_PitchPercentChangeEnd;
|
||||
this->Update_Text_RatePercentChangeStart();
|
||||
this->Update_Slider_RatePercentChangeStart();
|
||||
}
|
||||
}
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_PitchPercentChangeStart = m_PitchPercentChangeEnd;
|
||||
m_PitchHalfStepsStart = m_PitchHalfStepsEnd;
|
||||
this->Update_Text_PitchPercentChangeStart();
|
||||
this->Update_Text_PitchHalfStepsStart();
|
||||
}
|
||||
m_bLoopDetect = false;
|
||||
|
||||
FindWindow(wxID_OK)->Enable(CheckParameters());
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::OnCheckBox_PreAnalyze(wxCommandEvent & event)
|
||||
void TimeScaleDialog::OnCheckBox_LinkRatePitch(wxCommandEvent & event)
|
||||
{
|
||||
if (m_pCheckBox_PreAnalyze) {
|
||||
m_PreAnalyze = m_pCheckBox_PreAnalyze->GetValue();
|
||||
if (m_bLoopDetect)
|
||||
return;
|
||||
|
||||
if (m_pCheckBox_LinkRatePitch) {
|
||||
m_LinkRatePitch = m_pCheckBox_LinkRatePitch->GetValue();
|
||||
|
||||
if(m_LinkRatePitch) {
|
||||
m_bLoopDetect = true;
|
||||
m_RatePercentChangeStart = m_PitchPercentChangeStart;
|
||||
m_RatePercentChangeEnd = m_PitchPercentChangeEnd;
|
||||
m_RateSlideType = m_PitchSlideType;
|
||||
m_RateSlideReference = m_PitchSlideReference;
|
||||
m_RateLinkInitialFinal = m_PitchLinkInitialFinal;
|
||||
this->Update_Text_RatePercentChangeStart();
|
||||
this->Update_Text_RatePercentChangeEnd();
|
||||
this->Update_Slider_RatePercentChangeStart();
|
||||
this->Update_Slider_RatePercentChangeEnd();
|
||||
this->Update_Choice_RateSlideType();
|
||||
this->Update_Choice_RateSlideReference();
|
||||
this->Update_CheckBox_RateLinkInitialFinal();
|
||||
m_bLoopDetect = false;
|
||||
} else {
|
||||
}
|
||||
|
||||
FindWindow(wxID_OK)->Enable(CheckParameters());
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::OnCheckBox_RateLinkInitialFinal(wxCommandEvent & event)
|
||||
{
|
||||
if (m_bLoopDetect)
|
||||
return;
|
||||
|
||||
if (m_pCheckBox_RateLinkInitialFinal) {
|
||||
m_RateLinkInitialFinal = m_pCheckBox_RateLinkInitialFinal->GetValue();
|
||||
|
||||
if(m_RateLinkInitialFinal) {
|
||||
m_bLoopDetect = true;
|
||||
m_RatePercentChangeEnd = m_RatePercentChangeStart;
|
||||
this->Update_Text_RatePercentChangeEnd();
|
||||
this->Update_Slider_RatePercentChangeEnd();
|
||||
m_bLoopDetect = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::OnCheckBox_PitchLinkInitialFinal(wxCommandEvent & event)
|
||||
{
|
||||
if (m_bLoopDetect)
|
||||
return;
|
||||
|
||||
if (m_pCheckBox_PitchLinkInitialFinal) {
|
||||
m_PitchLinkInitialFinal = m_pCheckBox_PitchLinkInitialFinal->GetValue();
|
||||
|
||||
if(m_PitchLinkInitialFinal) {
|
||||
m_bLoopDetect = true;
|
||||
m_PitchPercentChangeEnd = m_PitchPercentChangeStart;
|
||||
m_PitchHalfStepsEnd = m_PitchHalfStepsStart;
|
||||
this->Update_Text_PitchPercentChangeEnd();
|
||||
this->Update_Text_PitchHalfStepsEnd();
|
||||
m_bLoopDetect = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::OnChoice_RateSlideType(wxCommandEvent & event)
|
||||
{
|
||||
if (m_bLoopDetect)
|
||||
return;
|
||||
|
||||
if (m_pChoice_RateSlideType) {
|
||||
m_RateSlideType = m_pChoice_RateSlideType->GetSelection();
|
||||
if(m_LinkRatePitch) {
|
||||
m_PitchSlideType = m_RateSlideType;
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Choice_PitchSlideType();
|
||||
m_bLoopDetect = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::OnChoice_PitchSlideType(wxCommandEvent & event)
|
||||
{
|
||||
if (m_bLoopDetect)
|
||||
return;
|
||||
|
||||
if (m_pChoice_PitchSlideType) {
|
||||
m_PitchSlideType = m_pChoice_PitchSlideType->GetSelection();
|
||||
if(m_LinkRatePitch) {
|
||||
m_RateSlideType = m_PitchSlideType;
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Choice_RateSlideType();
|
||||
m_bLoopDetect = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::OnChoice_RateSlideReference(wxCommandEvent & event)
|
||||
{
|
||||
if (m_bLoopDetect)
|
||||
return;
|
||||
|
||||
if (m_pChoice_RateSlideReference) {
|
||||
m_RateSlideReference = m_pChoice_RateSlideReference->GetSelection();
|
||||
if(m_LinkRatePitch) {
|
||||
m_PitchSlideReference = m_RateSlideReference;
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Choice_PitchSlideReference();
|
||||
m_bLoopDetect = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::OnChoice_PitchSlideReference(wxCommandEvent & event)
|
||||
{
|
||||
if (m_bLoopDetect)
|
||||
return;
|
||||
|
||||
if (m_pChoice_PitchSlideReference) {
|
||||
m_PitchSlideReference = m_pChoice_PitchSlideReference->GetSelection();
|
||||
if(m_LinkRatePitch) {
|
||||
m_RateSlideReference = m_PitchSlideReference;
|
||||
m_bLoopDetect = true;
|
||||
this->Update_Choice_RateSlideReference();
|
||||
m_bLoopDetect = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -631,10 +1049,52 @@ void TimeScaleDialog::Update_Text_PitchPercentChangeEnd()
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::Update_CheckBox_PreAnalyze()
|
||||
void TimeScaleDialog::Update_CheckBox_LinkRatePitch()
|
||||
{
|
||||
if (m_pCheckBox_PreAnalyze) {
|
||||
m_pCheckBox_PreAnalyze->SetValue(m_PreAnalyze);
|
||||
if (m_pCheckBox_LinkRatePitch) {
|
||||
m_pCheckBox_LinkRatePitch->SetValue(m_LinkRatePitch);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::Update_CheckBox_RateLinkInitialFinal()
|
||||
{
|
||||
if (m_pCheckBox_RateLinkInitialFinal) {
|
||||
m_pCheckBox_RateLinkInitialFinal->SetValue(m_RateLinkInitialFinal);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::Update_CheckBox_PitchLinkInitialFinal()
|
||||
{
|
||||
if (m_pCheckBox_PitchLinkInitialFinal) {
|
||||
m_pCheckBox_PitchLinkInitialFinal->SetValue(m_PitchLinkInitialFinal);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::Update_Choice_RateSlideType()
|
||||
{
|
||||
if (m_pChoice_RateSlideType) {
|
||||
m_pChoice_RateSlideType->SetSelection(m_RateSlideType);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::Update_Choice_PitchSlideType()
|
||||
{
|
||||
if (m_pChoice_PitchSlideType) {
|
||||
m_pChoice_PitchSlideType->SetSelection(m_PitchSlideType);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::Update_Choice_RateSlideReference()
|
||||
{
|
||||
if (m_pChoice_RateSlideReference) {
|
||||
m_pChoice_RateSlideReference->SetSelection(m_RateSlideReference);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeScaleDialog::Update_Choice_PitchSlideReference()
|
||||
{
|
||||
if (m_pChoice_PitchSlideReference) {
|
||||
m_pChoice_PitchSlideReference->SetSelection(m_PitchSlideReference);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -20,9 +20,13 @@
|
||||
#include <wx/intl.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/slider.h>
|
||||
#include <wx/choice.h>
|
||||
|
||||
class wxString;
|
||||
class wxArrayString;
|
||||
class wxTextCtrl;
|
||||
class wxCheckBox;
|
||||
class wxChoice;
|
||||
|
||||
class EffectTimeScale : public EffectSBSMS {
|
||||
|
||||
@@ -63,7 +67,13 @@ class EffectTimeScale : public EffectSBSMS {
|
||||
double m_PitchHalfStepsEnd;
|
||||
double m_PitchPercentChangeStart;
|
||||
double m_PitchPercentChangeEnd;
|
||||
bool m_PreAnalyze;
|
||||
int m_RateSlideType;
|
||||
int m_PitchSlideType;
|
||||
int m_RateSlideReference;
|
||||
int m_PitchSlideReference;
|
||||
bool m_LinkRatePitch;
|
||||
bool m_RateLinkInitialFinal;
|
||||
bool m_PitchLinkInitialFinal;
|
||||
|
||||
friend class TimeScaleDialog;
|
||||
};
|
||||
@@ -74,61 +84,92 @@ class EffectTimeScale : public EffectSBSMS {
|
||||
|
||||
class TimeScaleDialog:public EffectDialog {
|
||||
public:
|
||||
TimeScaleDialog(EffectTimeScale * effect,
|
||||
wxWindow * parent);
|
||||
|
||||
void PopulateOrExchange(ShuttleGui & S);
|
||||
bool TransferDataToWindow();
|
||||
bool TransferDataFromWindow();
|
||||
|
||||
TimeScaleDialog(EffectTimeScale * effect,
|
||||
wxWindow * parent);
|
||||
|
||||
void PopulateOrExchange(ShuttleGui & S);
|
||||
bool TransferDataToWindow();
|
||||
bool TransferDataFromWindow();
|
||||
|
||||
private:
|
||||
// handlers
|
||||
void OnText_RatePercentChangeStart(wxCommandEvent & event);
|
||||
void OnText_RatePercentChangeEnd(wxCommandEvent & event);
|
||||
void OnText_PitchPercentChangeStart(wxCommandEvent & event);
|
||||
void OnText_PitchPercentChangeEnd(wxCommandEvent & event);
|
||||
void OnText_PitchHalfStepsStart(wxCommandEvent & event);
|
||||
void OnText_PitchHalfStepsEnd(wxCommandEvent & event);
|
||||
void OnSlider_RatePercentChangeStart(wxCommandEvent & event);
|
||||
void OnSlider_RatePercentChangeEnd(wxCommandEvent & event);
|
||||
void OnCheckBox_PreAnalyze(wxCommandEvent & event);
|
||||
|
||||
// helper fns
|
||||
bool CheckParameters();
|
||||
void Update_Text_RatePercentChangeStart();
|
||||
void Update_Text_RatePercentChangeEnd();
|
||||
void Update_Text_PitchPercentChangeStart();
|
||||
void Update_Text_PitchPercentChangeEnd();
|
||||
void Update_Text_PitchHalfStepsStart();
|
||||
void Update_Text_PitchHalfStepsEnd();
|
||||
void Update_Slider_RatePercentChangeStart();
|
||||
void Update_Slider_RatePercentChangeEnd();
|
||||
void Update_CheckBox_PreAnalyze();
|
||||
|
||||
// handlers
|
||||
void OnText_RatePercentChangeStart(wxCommandEvent & event);
|
||||
void OnText_RatePercentChangeEnd(wxCommandEvent & event);
|
||||
void OnText_PitchPercentChangeStart(wxCommandEvent & event);
|
||||
void OnText_PitchPercentChangeEnd(wxCommandEvent & event);
|
||||
void OnText_PitchHalfStepsStart(wxCommandEvent & event);
|
||||
void OnText_PitchHalfStepsEnd(wxCommandEvent & event);
|
||||
void OnSlider_RatePercentChangeStart(wxCommandEvent & event);
|
||||
void OnSlider_RatePercentChangeEnd(wxCommandEvent & event);
|
||||
void OnCheckBox_LinkRatePitch(wxCommandEvent & event);
|
||||
void OnChoice_RateSlideType(wxCommandEvent & event);
|
||||
void OnChoice_PitchSlideType(wxCommandEvent & event);
|
||||
void OnChoice_RateSlideReference(wxCommandEvent & event);
|
||||
void OnChoice_PitchSlideReference(wxCommandEvent & event);
|
||||
void OnCheckBox_RateLinkInitialFinal(wxCommandEvent & event);
|
||||
void OnCheckBox_PitchLinkInitialFinal(wxCommandEvent & event);
|
||||
void OnPreview(wxCommandEvent & event);
|
||||
|
||||
// helper fns
|
||||
bool CheckParameters();
|
||||
void Update_Text_RatePercentChangeStart();
|
||||
void Update_Text_RatePercentChangeEnd();
|
||||
void Update_Text_PitchPercentChangeStart();
|
||||
void Update_Text_PitchPercentChangeEnd();
|
||||
void Update_Text_PitchHalfStepsStart();
|
||||
void Update_Text_PitchHalfStepsEnd();
|
||||
void Update_Slider_RatePercentChangeStart();
|
||||
void Update_Slider_RatePercentChangeEnd();
|
||||
void Update_CheckBox_LinkRatePitch();
|
||||
void Update_Choice_RateSlideType();
|
||||
void Update_Choice_PitchSlideType();
|
||||
void Update_Choice_RateSlideReference();
|
||||
void Update_Choice_PitchSlideReference();
|
||||
void Update_CheckBox_RateLinkInitialFinal();
|
||||
void Update_CheckBox_PitchLinkInitialFinal();
|
||||
|
||||
private:
|
||||
EffectTimeScale *mEffect;
|
||||
bool m_bLoopDetect;
|
||||
|
||||
// controls
|
||||
wxTextCtrl *m_pTextCtrl_RatePercentChangeStart;
|
||||
wxTextCtrl *m_pTextCtrl_RatePercentChangeEnd;
|
||||
wxSlider *m_pSlider_RatePercentChangeStart;
|
||||
wxSlider *m_pSlider_RatePercentChangeEnd;
|
||||
wxTextCtrl *m_pTextCtrl_PitchHalfStepsStart;
|
||||
wxTextCtrl *m_pTextCtrl_PitchHalfStepsEnd;
|
||||
wxTextCtrl *m_pTextCtrl_PitchPercentChangeStart;
|
||||
wxTextCtrl *m_pTextCtrl_PitchPercentChangeEnd;
|
||||
wxCheckBox *m_pCheckBox_PreAnalyze;
|
||||
|
||||
public:
|
||||
EffectTimeScale *mEffect;
|
||||
bool m_bLoopDetect;
|
||||
|
||||
wxArrayString rateSlideTypes;
|
||||
wxArrayString pitchSlideTypes;
|
||||
wxArrayString rateSlideReferences;
|
||||
wxArrayString pitchSlideReferences;
|
||||
|
||||
// controls
|
||||
wxTextCtrl *m_pTextCtrl_RatePercentChangeStart;
|
||||
wxTextCtrl *m_pTextCtrl_RatePercentChangeEnd;
|
||||
wxSlider *m_pSlider_RatePercentChangeStart;
|
||||
wxSlider *m_pSlider_RatePercentChangeEnd;
|
||||
wxTextCtrl *m_pTextCtrl_PitchHalfStepsStart;
|
||||
wxTextCtrl *m_pTextCtrl_PitchHalfStepsEnd;
|
||||
wxTextCtrl *m_pTextCtrl_PitchPercentChangeStart;
|
||||
wxTextCtrl *m_pTextCtrl_PitchPercentChangeEnd;
|
||||
wxCheckBox *m_pCheckBox_LinkRatePitch;
|
||||
wxChoice *m_pChoice_RateSlideType;
|
||||
wxChoice *m_pChoice_PitchSlideType;
|
||||
wxChoice *m_pChoice_RateSlideReference;
|
||||
wxChoice *m_pChoice_PitchSlideReference;
|
||||
wxCheckBox *m_pCheckBox_RateLinkInitialFinal;
|
||||
wxCheckBox *m_pCheckBox_PitchLinkInitialFinal;
|
||||
|
||||
double m_RatePercentChangeStart;
|
||||
double m_RatePercentChangeEnd;
|
||||
double m_PitchHalfStepsStart;
|
||||
double m_PitchHalfStepsEnd;
|
||||
double m_PitchPercentChangeStart;
|
||||
double m_PitchPercentChangeEnd;
|
||||
bool m_PreAnalyze;
|
||||
bool m_LinkRatePitch;
|
||||
int m_RateSlideType;
|
||||
int m_PitchSlideType;
|
||||
int m_RateSlideReference;
|
||||
int m_PitchSlideReference;
|
||||
bool m_RateLinkInitialFinal;
|
||||
bool m_PitchLinkInitialFinal;
|
||||
|
||||
friend class EffectTimeScale;
|
||||
|
||||
private:
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
@@ -10,7 +10,8 @@
|
||||
|
||||
\file TimeWarper.cpp
|
||||
\brief Contains definitions for IdentityTimeWarper, ShiftTimeWarper,
|
||||
LinearTimeWarper, LogarithmicTimeWarper classes
|
||||
LinearTimeWarper, LogarithmicTimeWarper, QuadraticTimeWarper,
|
||||
Geometric TimeWarper classes
|
||||
|
||||
*//*******************************************************************/
|
||||
|
||||
@@ -33,14 +34,14 @@ double LinearTimeWarper::Warp(double originalTime) const
|
||||
return originalTime*mScale + mShift;
|
||||
}
|
||||
|
||||
double LogarithmicTimeWarper::Warp(double originalTime) const
|
||||
double LinearInputRateTimeWarper::Warp(double originalTime) const
|
||||
{
|
||||
double rate = mRateWarper.Warp(originalTime);
|
||||
return mTStart + mScale*log(rate/mRStart);
|
||||
}
|
||||
|
||||
LogarithmicTimeWarper::LogarithmicTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd)
|
||||
LinearInputRateTimeWarper::LinearInputRateTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd)
|
||||
: mRateWarper(tStart, rStart, tEnd, rEnd), mRStart(rStart),
|
||||
mTStart(tStart), mScale((tEnd-tStart)/(rEnd-rStart))
|
||||
{
|
||||
@@ -48,6 +49,91 @@ LogarithmicTimeWarper::LogarithmicTimeWarper(double tStart, double tEnd,
|
||||
wxASSERT(tStart < tEnd);
|
||||
}
|
||||
|
||||
double LinearOutputRateTimeWarper::Warp(double originalTime) const
|
||||
{
|
||||
double scaledTime = mTimeWarper.Warp(originalTime);
|
||||
return mTStart + mScale*(sqrt(mC1 + scaledTime * mC2) - mRStart);
|
||||
}
|
||||
|
||||
LinearOutputRateTimeWarper::LinearOutputRateTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd)
|
||||
: mTimeWarper(tStart, 0.0, tEnd, 1.0),
|
||||
mRStart(rStart), mTStart(tStart),
|
||||
mScale(2.0*(tEnd-tStart)/(rEnd*rEnd-rStart*rStart)),
|
||||
mC1(rStart*rStart), mC2(rEnd*rEnd-rStart*rStart)
|
||||
{
|
||||
wxASSERT(rStart != rEnd);
|
||||
wxASSERT(rStart > 0.0);
|
||||
wxASSERT(rEnd > 0.0);
|
||||
wxASSERT(tStart < tEnd);
|
||||
}
|
||||
|
||||
double LinearInputStretchTimeWarper::Warp(double originalTime) const
|
||||
{
|
||||
double scaledTime = mTimeWarper.Warp(originalTime);
|
||||
return mTStart + mC1 * scaledTime * (1.0 + mC2 * scaledTime);
|
||||
}
|
||||
|
||||
LinearInputStretchTimeWarper::LinearInputStretchTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd)
|
||||
: mTimeWarper(tStart, 0.0, tEnd, 1.0), mTStart(tStart),
|
||||
mC1((tEnd-tStart)/rStart), mC2(0.5*(rStart/rEnd - 1.0))
|
||||
{
|
||||
wxASSERT(rStart > 0.0);
|
||||
wxASSERT(rEnd > 0.0);
|
||||
wxASSERT(tStart < tEnd);
|
||||
}
|
||||
|
||||
double LinearOutputStretchTimeWarper::Warp(double originalTime) const
|
||||
{
|
||||
double scaledTime = mTimeWarper.Warp(originalTime);
|
||||
return mTStart + mC1 * (pow(mC2, scaledTime) - 1.0);
|
||||
}
|
||||
|
||||
LinearOutputStretchTimeWarper::LinearOutputStretchTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd)
|
||||
: mTimeWarper(tStart, 0.0, tEnd, 1.0), mTStart(tStart),
|
||||
mC1((tEnd-tStart)/(rStart*log(rStart/rEnd))), mC2(rStart/rEnd)
|
||||
{
|
||||
wxASSERT(rStart != rEnd);
|
||||
wxASSERT(rStart > 0.0);
|
||||
wxASSERT(rEnd > 0.0);
|
||||
wxASSERT(tStart < tEnd);
|
||||
}
|
||||
|
||||
double GeometricInputTimeWarper::Warp(double originalTime) const
|
||||
{
|
||||
double scaledTime = mTimeWarper.Warp(originalTime);
|
||||
return mTStart + mScale*(pow(mRatio,scaledTime) - 1.0);
|
||||
}
|
||||
|
||||
GeometricInputTimeWarper::GeometricInputTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd)
|
||||
: mTimeWarper(tStart, 0.0, tEnd, 1.0), mTStart(tStart),
|
||||
mScale((tEnd-tStart)/(log(rStart/rEnd)*rStart)), mRatio(rStart/rEnd)
|
||||
{
|
||||
wxASSERT(rStart != rEnd);
|
||||
wxASSERT(rStart > 0.0);
|
||||
wxASSERT(rEnd > 0.0);
|
||||
wxASSERT(tStart < tEnd);
|
||||
}
|
||||
|
||||
double GeometricOutputTimeWarper::Warp(double originalTime) const
|
||||
{
|
||||
double scaledTime = mTimeWarper.Warp(originalTime);
|
||||
return mTStart + mScale*log(mC0 * scaledTime + 1.0);
|
||||
}
|
||||
|
||||
GeometricOutputTimeWarper::GeometricOutputTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd)
|
||||
: mTimeWarper(tStart, 0.0, tEnd, 1.0), mTStart(tStart),
|
||||
mScale((tEnd-tStart)/(rEnd-rStart)), mC0((rEnd-rStart)/rStart)
|
||||
{
|
||||
wxASSERT(rStart > 0.0);
|
||||
wxASSERT(rEnd > 0.0);
|
||||
wxASSERT(tStart < tEnd);
|
||||
}
|
||||
|
||||
StepTimeWarper::StepTimeWarper(double tStep, double offset)
|
||||
: mTStep(tStep), mOffset(offset)
|
||||
{ }
|
||||
|
@@ -10,7 +10,9 @@
|
||||
|
||||
\file TimeWarper.h
|
||||
\brief Contains declarations for TimeWarper, IdentityTimeWarper,
|
||||
ShiftTimeWarper, LinearTimeWarper, LogarithmicTimeWarper classes
|
||||
ShiftTimeWarper, LinearTimeWarper, LinearInputRateSlideTimeWarper,
|
||||
LinearOutputRateSlideTimeWarper, LinearInputInverseRateTimeWarper,
|
||||
GeometricInputRateTimeWarper, GeometricOutputRateTimeWarper classes
|
||||
|
||||
\class TimeWarper
|
||||
\brief Transforms one point in time to another point. For example, a time
|
||||
@@ -26,8 +28,20 @@ split points in the input.
|
||||
\class LinearTimeWarper
|
||||
\brief Linear scaling, initialised by giving two points on the line
|
||||
|
||||
\class LogarithmicTimeWarper
|
||||
\brief TimeScale - rate varies linearly, so time changes logarithmically.
|
||||
\class LinearInputRateTimeWarper
|
||||
\brief TimeScale - rate varies linearly with input
|
||||
|
||||
\class LinearOutputRateTimeWarper
|
||||
\brief TimeScale - rate varies linearly with output
|
||||
|
||||
\class LinearInputInverseRateTimeWarper
|
||||
\brief TimeScale - inverse rate varies linearly with input
|
||||
|
||||
\class GeometricInputRateTimeWarper
|
||||
\brief TimeScale - rate varies geometrically with input
|
||||
|
||||
\class GeometricOutputRateTimeWarper
|
||||
\brief TimeScale - rate varies geometrically with output
|
||||
|
||||
\class StepTimeWarper
|
||||
\brief Like identity but with a jump
|
||||
@@ -82,7 +96,7 @@ public:
|
||||
virtual double Warp(double originalTime) const;
|
||||
};
|
||||
|
||||
class LogarithmicTimeWarper : public TimeWarper
|
||||
class LinearInputRateTimeWarper : public TimeWarper
|
||||
{
|
||||
private:
|
||||
LinearTimeWarper mRateWarper;
|
||||
@@ -90,8 +104,75 @@ private:
|
||||
double mTStart;
|
||||
double mScale;
|
||||
public:
|
||||
LogarithmicTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd);
|
||||
LinearInputRateTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd);
|
||||
virtual double Warp(double originalTime) const;
|
||||
};
|
||||
|
||||
class LinearOutputRateTimeWarper : public TimeWarper
|
||||
{
|
||||
private:
|
||||
LinearTimeWarper mTimeWarper;
|
||||
double mRStart;
|
||||
double mTStart;
|
||||
double mScale;
|
||||
double mC1;
|
||||
double mC2;
|
||||
public:
|
||||
LinearOutputRateTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd);
|
||||
virtual double Warp(double originalTime) const;
|
||||
};
|
||||
|
||||
class LinearInputStretchTimeWarper : public TimeWarper
|
||||
{
|
||||
private:
|
||||
LinearTimeWarper mTimeWarper;
|
||||
double mTStart;
|
||||
double mC1;
|
||||
double mC2;
|
||||
public:
|
||||
LinearInputStretchTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd);
|
||||
virtual double Warp(double originalTime) const;
|
||||
};
|
||||
|
||||
class LinearOutputStretchTimeWarper : public TimeWarper
|
||||
{
|
||||
private:
|
||||
LinearTimeWarper mTimeWarper;
|
||||
double mTStart;
|
||||
double mC1;
|
||||
double mC2;
|
||||
public:
|
||||
LinearOutputStretchTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd);
|
||||
virtual double Warp(double originalTime) const;
|
||||
};
|
||||
|
||||
class GeometricInputTimeWarper : public TimeWarper
|
||||
{
|
||||
private:
|
||||
LinearTimeWarper mTimeWarper;
|
||||
double mTStart;
|
||||
double mScale;
|
||||
double mRatio;
|
||||
public:
|
||||
GeometricInputTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd);
|
||||
virtual double Warp(double originalTime) const;
|
||||
};
|
||||
|
||||
class GeometricOutputTimeWarper : public TimeWarper
|
||||
{
|
||||
private:
|
||||
LinearTimeWarper mTimeWarper;
|
||||
double mTStart;
|
||||
double mScale;
|
||||
double mC0;
|
||||
public:
|
||||
GeometricOutputTimeWarper(double tStart, double tEnd,
|
||||
double rStart, double rEnd);
|
||||
virtual double Warp(double originalTime) const;
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user