1
0
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:
clayton.otey
2011-07-02 18:35:18 +00:00
parent 9869ea4afd
commit a17e741abc
45 changed files with 12912 additions and 6785 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -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)
{ }

View File

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