Fix for bug 955 from Clayton Otey
This commit is contained in:
parent
f7fba31319
commit
954bb0fd1c
|
@ -51,6 +51,7 @@ class SBSMSInterface {
|
|||
virtual ~SBSMSInterface() {}
|
||||
virtual long samples(audio *buf, long n) { return 0; }
|
||||
virtual float getStretch(float t)=0;
|
||||
virtual float getMeanStretch(float t0, float t1)=0;
|
||||
virtual float getPitch(float t)=0;
|
||||
virtual long getPresamples()=0;
|
||||
virtual SampleCountType getSamplesToInput()=0;
|
||||
|
@ -127,8 +128,10 @@ class Slide {
|
|||
~Slide();
|
||||
float getTotalStretch();
|
||||
float getStretchedTime(float t);
|
||||
float getInverseStretchedTime(float t);
|
||||
float getRate(float t);
|
||||
float getStretch(float t);
|
||||
float getMeanStretch(float t0, float t1);
|
||||
float getRate();
|
||||
float getStretch();
|
||||
void step();
|
||||
|
@ -148,6 +151,7 @@ public:
|
|||
SBSMSQuality *quality);
|
||||
virtual ~SBSMSInterfaceSliding();
|
||||
virtual float getStretch(float t);
|
||||
virtual float getMeanStretch(float t0, float t1);
|
||||
virtual float getPitch(float t);
|
||||
virtual long getPresamples();
|
||||
virtual SampleCountType getSamplesToInput();
|
||||
|
|
|
@ -663,7 +663,8 @@ long SBSMSImp :: write(SBSMSInterface *iface)
|
|||
long nWrite = 0;
|
||||
|
||||
float t = getInputTime(iface);
|
||||
float stretch = iface->getStretch(t);
|
||||
float t1 = (float)(nSamplesInputed + quality->getFrameSize()) / (float)iface->getSamplesToInput();
|
||||
float stretch = iface->getMeanStretch(t,t1);
|
||||
float pitch = iface->getPitch(t);
|
||||
|
||||
long nPresamples = iface->getPresamples();
|
||||
|
|
|
@ -11,8 +11,10 @@ public:
|
|||
virtual ~SlideImp() {}
|
||||
virtual float getTotalStretch()=0;
|
||||
virtual float getStretchedTime(float t)=0;
|
||||
virtual float getInverseStretchedTime(float t)=0;
|
||||
virtual float getRate(float t)=0;
|
||||
virtual float getStretch(float t)=0;
|
||||
virtual float getMeanStretch(float t0, float t1)=0;
|
||||
virtual float getRate()=0;
|
||||
virtual float getStretch()=0;
|
||||
virtual void step()=0;
|
||||
|
@ -28,12 +30,18 @@ public:
|
|||
float getStretchedTime(float t) {
|
||||
return t;
|
||||
}
|
||||
float getInverseStretchedTime(float t) {
|
||||
return t;
|
||||
}
|
||||
float getRate(float t) {
|
||||
return 1.0f;
|
||||
}
|
||||
float getStretch(float t) {
|
||||
return 1.0f;
|
||||
}
|
||||
float getMeanStretch(float t0, float t1) {
|
||||
return 1.0f;
|
||||
}
|
||||
float getRate() {
|
||||
return 1.0f;
|
||||
}
|
||||
|
@ -55,12 +63,18 @@ public:
|
|||
float getStretchedTime(float t) {
|
||||
return t / rate;
|
||||
}
|
||||
float getInverseStretchedTime(float t) {
|
||||
return rate * t;
|
||||
}
|
||||
float getRate(float t) {
|
||||
return rate;
|
||||
}
|
||||
float getStretch(float t) {
|
||||
return 1.0f / rate;
|
||||
}
|
||||
float getMeanStretch(float t0, float t1) {
|
||||
return 1.0f / rate;
|
||||
}
|
||||
float getRate() {
|
||||
return rate;
|
||||
}
|
||||
|
@ -90,12 +104,18 @@ public:
|
|||
float ratet = getRate(t);
|
||||
return log(ratet / rate0) / (rate1 - rate0);
|
||||
}
|
||||
float getInverseStretchedTime(float t) {
|
||||
return (exp((rate1-rate0)*t)-1.0f)*rate0/(rate1-rate0);
|
||||
}
|
||||
float getRate(float t) {
|
||||
return rate0 + (rate1 - rate0) * t;
|
||||
}
|
||||
float getStretch(float t) {
|
||||
return 1.0f / getRate(t);
|
||||
}
|
||||
float getMeanStretch(float t0, float t1) {
|
||||
return log(getRate(t1)/getRate(t0))/((rate1-rate0)*(t1-t0));
|
||||
}
|
||||
float getRate() {
|
||||
return (float)val;
|
||||
}
|
||||
|
@ -126,12 +146,22 @@ public:
|
|||
float getStretchedTime(float t) {
|
||||
return (sqrt(rate0 * rate0 + (rate1 * rate1 - rate0 * rate0) * t) - rate0) * 2.0f / (rate1 * rate1 - rate0 * rate0);
|
||||
}
|
||||
float getInverseStretchedTime(float t) {
|
||||
float r12 = rate1 * rate1 - rate0 * rate0;
|
||||
float s = 0.5f * r12 * t + rate0;
|
||||
return (s * s - rate0 * rate0) / r12;
|
||||
}
|
||||
float getRate(float t) {
|
||||
return rate0 + (sqrt(rate0 * rate0 + (rate1 * rate1 - rate0 * rate0) * t) - rate0);
|
||||
return sqrt(rate0 * rate0 + (rate1 * rate1 - rate0 * rate0) * t);
|
||||
}
|
||||
float getStretch(float t) {
|
||||
return 1.0f / getRate(t);
|
||||
}
|
||||
float getMeanStretch(float t0, float t1) {
|
||||
float r02 = rate0 * rate0;
|
||||
float r102 = rate1 * rate1 - r02;
|
||||
return 2.0f * (sqrt(r02 + r102*t1) - sqrt(r02 + r102 * t0)) / (r102 * (t1 - t0));
|
||||
}
|
||||
float getRate() {
|
||||
return getRate((float)val);
|
||||
}
|
||||
|
@ -162,12 +192,19 @@ public:
|
|||
float getStretchedTime(float t) {
|
||||
return t / rate0 * (1.0f + 0.5f * t * (rate0 / rate1 - 1.0f));
|
||||
}
|
||||
float getInverseStretchedTime(float t) {
|
||||
float s = 1.0f / rate1 - 1.0f / rate0;
|
||||
return (-1.0f / rate0 + sqrt(1/(rate0*rate0)-2.0f*t*s)) / s;
|
||||
}
|
||||
float getRate(float t) {
|
||||
return 1.0f / getStretch(t);
|
||||
}
|
||||
float getStretch(float t) {
|
||||
return (1.0f / rate0 + (1.0f / rate1 - 1.0f / rate0) * t);
|
||||
}
|
||||
float getMeanStretch(float t0, float t1) {
|
||||
return ((t1 + t0) * (rate0 - rate1) - 2.0f * rate1) / (2.0f * rate0 * rate1);
|
||||
}
|
||||
float getRate() {
|
||||
return (float)(1.0 / val);
|
||||
}
|
||||
|
@ -200,12 +237,18 @@ public:
|
|||
float getStretchedTime(float t) {
|
||||
return c1 * (pow(c0, t) - 1.0f);
|
||||
}
|
||||
float getInverseStretchedTime(float t) {
|
||||
return log(t/c1 + 1.0f) * c1 * rate0;
|
||||
}
|
||||
float getRate(float t) {
|
||||
return rate0 * pow(c0, -t);
|
||||
}
|
||||
float getStretch(float t) {
|
||||
return pow(c0, t) / rate0;
|
||||
}
|
||||
float getMeanStretch(float t0, float t1) {
|
||||
return (pow(c0,t1) - pow(c0,t0)) / (c1 * (t1 - t0));
|
||||
}
|
||||
float getRate() {
|
||||
return getRate((float)val);
|
||||
}
|
||||
|
@ -226,16 +269,21 @@ public:
|
|||
GeometricInputSlide(float rate0, float rate1, const SampleCountType &n) {
|
||||
this->rate0 = rate0;
|
||||
this->rate1 = rate1;
|
||||
this->c0 = rate0 / rate1;
|
||||
this->log01 = log(c0);
|
||||
if(n) {
|
||||
val = rate0;
|
||||
inc = pow((double)rate1 / rate0, 1.0 / (double)n);
|
||||
}
|
||||
}
|
||||
float getTotalStretch() {
|
||||
return (rate1 - rate0) / (log(rate1 / rate0) * (rate0 * rate1));
|
||||
return (rate0 - rate1) / (log01 * (rate0 * rate1));
|
||||
}
|
||||
float getStretchedTime(float t) {
|
||||
return (float)(pow(rate0 / rate1, t) - 1.0) / (rate0 * log(rate0 / rate1));
|
||||
return (float)(pow(rate0 / rate1, t) - 1.0) / (rate0 * log01);
|
||||
}
|
||||
float getInverseStretchedTime(float t) {
|
||||
return log(t * rate0 * log01 + 1.0f) / log01;
|
||||
}
|
||||
float getRate(float t) {
|
||||
return rate0 * pow(rate1 / rate0, t);
|
||||
|
@ -243,6 +291,9 @@ public:
|
|||
float getStretch(float t) {
|
||||
return 1.0f / getRate(t);
|
||||
}
|
||||
float getMeanStretch(float t0, float t1) {
|
||||
return (pow(c0,t1) - pow(c0,t0)) / (rate0 * log01 * (t1 - t0));
|
||||
}
|
||||
float getRate() {
|
||||
return (float)val;
|
||||
}
|
||||
|
@ -253,7 +304,7 @@ public:
|
|||
val *= inc;
|
||||
}
|
||||
protected:
|
||||
float rate0, rate1;
|
||||
float rate0, rate1, c0, log01;
|
||||
double val, inc;
|
||||
};
|
||||
|
||||
|
@ -276,6 +327,9 @@ public:
|
|||
float getStretchedTime(float t) {
|
||||
return log(r10 / rate0 * t + 1.0f) / r10;
|
||||
}
|
||||
float getInverseStretchedTime(float t) {
|
||||
return rate0 / r10 * (exp(t * r10) - 1.0f);
|
||||
}
|
||||
float getRate(float t) {
|
||||
float t1 = getStretchedTime(t) / totalStretch;
|
||||
return rate0 * pow(rate1 / rate0, t1);
|
||||
|
@ -283,6 +337,9 @@ public:
|
|||
float getStretch(float t) {
|
||||
return 1.0f / getRate(t);
|
||||
}
|
||||
float getMeanStretch(float t0, float t1) {
|
||||
return log((rate0 + r10 * t1)/(rate0 + r10 * t0)) /(r10 * (t1 - t0));
|
||||
}
|
||||
float getRate() {
|
||||
return getRate((float)val);
|
||||
}
|
||||
|
@ -347,6 +404,16 @@ float Slide :: getStretchedTime(float t)
|
|||
if(t > 1.0f) t = 1.0f;
|
||||
return imp->getStretchedTime(t);
|
||||
}
|
||||
|
||||
float Slide :: getMeanStretch(float t0, float t1) {
|
||||
if(t0 < 0.0f) t0 = 0.0f;
|
||||
return imp->getMeanStretch(t0,t1);
|
||||
}
|
||||
|
||||
float Slide :: getInverseStretchedTime(float t)
|
||||
{
|
||||
return imp->getInverseStretchedTime(t);
|
||||
}
|
||||
|
||||
float Slide :: getRate()
|
||||
{
|
||||
|
@ -374,6 +441,7 @@ public:
|
|||
SBSMSQuality *quality);
|
||||
~SBSMSInterfaceSlidingImp() {}
|
||||
inline float getStretch(float t);
|
||||
inline float getMeanStretch(float t0, float t1);
|
||||
inline float getPitch(float t);
|
||||
inline long getPresamples();
|
||||
SampleCountType getSamplesToInput();
|
||||
|
@ -388,8 +456,7 @@ protected:
|
|||
SampleCountType samplesToInput;
|
||||
SampleCountType samplesToOutput;
|
||||
};
|
||||
|
||||
|
||||
|
||||
SBSMSInterfaceSlidingImp :: SBSMSInterfaceSlidingImp(Slide *stretchSlide,
|
||||
Slide *pitchSlide,
|
||||
bool bPitchReferenceInput,
|
||||
|
@ -414,7 +481,8 @@ SBSMSInterfaceSlidingImp :: SBSMSInterfaceSlidingImp(Slide *stretchSlide,
|
|||
int inFrameSize = quality->getFrameSize();
|
||||
while(samplesIn < samplesToInput) {
|
||||
float t = (float)samplesIn / (float)samplesToInput;
|
||||
stretch = stretchSlide->getStretch(t);
|
||||
float t1 =(float)(samplesIn + inFrameSize) / (float)samplesToInput;
|
||||
stretch = stretchSlide->getMeanStretch(t,t1);
|
||||
outFrameSizefloat += stretch * inFrameSize;
|
||||
int outFrameSize = (int) outFrameSizefloat;
|
||||
outFrameSizefloat -= (float) outFrameSize;
|
||||
|
@ -432,6 +500,12 @@ float SBSMSInterfaceSlidingImp :: getStretch(float t)
|
|||
return stretchScale * stretchSlide->getStretch(t);
|
||||
}
|
||||
|
||||
float SBSMSInterfaceSliding :: getMeanStretch(float t0, float t1) { return imp->getMeanStretch(t0, t1); }
|
||||
float SBSMSInterfaceSlidingImp :: getMeanStretch(float t0, float t1)
|
||||
{
|
||||
return stretchSlide->getMeanStretch(t0, t1);
|
||||
}
|
||||
|
||||
float SBSMSInterfaceSliding :: getPitch(float t) { return imp->getPitch(t); }
|
||||
float SBSMSInterfaceSlidingImp :: getPitch(float t)
|
||||
{
|
||||
|
|
|
@ -12,7 +12,7 @@ AC_DEFUN([AUDACITY_CHECKLIB_LIBSBSMS], [
|
|||
|
||||
dnl see if sbsms is installed on the system
|
||||
|
||||
PKG_CHECK_MODULES(SBSMS, sbsms >= 1.6.0,
|
||||
PKG_CHECK_MODULES(SBSMS, sbsms >= 2.2.0,
|
||||
LIBSBSMS_SYSTEM_AVAILABLE="yes",
|
||||
LIBSBSMS_SYSTEM_AVAILABLE="no")
|
||||
|
||||
|
|
|
@ -200,6 +200,18 @@ bool EffectSBSMS::ProcessLabelTrack(Track *t)
|
|||
return true;
|
||||
}
|
||||
|
||||
double EffectSBSMS::getInvertedStretchedTime(double rateStart, double rateEnd, SlideType slideType, double outputTime)
|
||||
{
|
||||
Slide slide(slideType,rateStart,rateEnd,0);
|
||||
return slide.getInverseStretchedTime(outputTime);
|
||||
}
|
||||
|
||||
double EffectSBSMS::getRate(double rateStart, double rateEnd, SlideType slideType, double t)
|
||||
{
|
||||
Slide slide(slideType,rateStart,rateEnd,0);
|
||||
return slide.getRate(t);
|
||||
}
|
||||
|
||||
bool EffectSBSMS::Process()
|
||||
{
|
||||
bool bGoodResult = true;
|
||||
|
@ -307,6 +319,8 @@ bool EffectSBSMS::Process()
|
|||
bPitchReferenceInput,
|
||||
samplesToProcess,0,
|
||||
NULL);
|
||||
|
||||
|
||||
} else {
|
||||
rb.bPitch = false;
|
||||
outSlideType = (srProcess==srTrack?SlideIdentity:SlideConstant);
|
||||
|
@ -330,7 +344,7 @@ bool EffectSBSMS::Process()
|
|||
samplesToProcess,processPresamples,
|
||||
rb.quality);
|
||||
}
|
||||
|
||||
|
||||
Resampler resampler(outResampleCB,&rb,outSlideType);
|
||||
|
||||
audio outBuf[SBSMSOutBlockSize];
|
||||
|
|
|
@ -28,7 +28,8 @@ public:
|
|||
void setParameters(double rateStart, double rateEnd, double pitchStart, double pitchEnd,
|
||||
SlideType rateSlideType, SlideType pitchSlideType,
|
||||
bool bLinkRatePitch, bool bRateReferenceInput, bool bPitchReferenceInput);
|
||||
|
||||
static double getInvertedStretchedTime(double rateStart, double rateEnd, SlideType slideType, double outputTime);
|
||||
static double getRate(double rateStart, double rateEnd, SlideType slideType, double t);
|
||||
private:
|
||||
bool ProcessLabelTrack(Track *track);
|
||||
double rateStart, rateEnd, pitchStart, pitchEnd;
|
||||
|
|
|
@ -72,6 +72,11 @@ EffectTimeScale::EffectTimeScale()
|
|||
m_PitchPercentChangeStart = DEF_PitchPercentStart;
|
||||
m_PitchPercentChangeEnd = DEF_PitchPercentEnd;
|
||||
|
||||
slideTypeRate = SlideLinearOutputRate;
|
||||
slideTypePitch = SlideLinearOutputRate;
|
||||
bPreview = false;
|
||||
previewSelectedDuration = 0.0;
|
||||
|
||||
SetLinearEffectFlag(true);
|
||||
}
|
||||
|
||||
|
@ -143,13 +148,42 @@ bool EffectTimeScale::Init()
|
|||
return true;
|
||||
}
|
||||
|
||||
double EffectTimeScale::CalcPreviewInputLength(double previewLength)
|
||||
{
|
||||
double inputLength = Effect::GetDuration();
|
||||
if(inputLength == 0.0) {
|
||||
return 0.0;
|
||||
} else {
|
||||
double rateStart = PercentChangeToRatio(m_RatePercentChangeStart);
|
||||
double rateEnd = PercentChangeToRatio(m_RatePercentChangeEnd);
|
||||
double tOut = previewLength/inputLength;
|
||||
double t = EffectSBSMS::getInvertedStretchedTime(rateStart,rateEnd,slideTypeRate,tOut);
|
||||
return t * inputLength;
|
||||
}
|
||||
}
|
||||
|
||||
void EffectTimeScale::Preview(bool dryOnly)
|
||||
{
|
||||
previewSelectedDuration = Effect::GetDuration();
|
||||
bPreview = true;
|
||||
Effect::Preview(dryOnly);
|
||||
bPreview = false;
|
||||
}
|
||||
|
||||
bool EffectTimeScale::Process()
|
||||
{
|
||||
double pitchStart = PercentChangeToRatio(m_PitchPercentChangeStart);
|
||||
double pitchEnd = PercentChangeToRatio(m_PitchPercentChangeEnd);
|
||||
double rateStart = PercentChangeToRatio(m_RatePercentChangeStart);
|
||||
double rateEnd = PercentChangeToRatio(m_RatePercentChangeEnd);
|
||||
EffectSBSMS::setParameters(rateStart,rateEnd,pitchStart,pitchEnd,SlideLinearOutputRate,SlideLinearOutputRate,false,false,false);
|
||||
|
||||
if(bPreview) {
|
||||
double t = (mT1-mT0) / previewSelectedDuration;
|
||||
rateEnd = EffectSBSMS::getRate(rateStart,rateEnd,slideTypeRate,t);
|
||||
pitchEnd = EffectSBSMS::getRate(pitchStart,pitchEnd,slideTypePitch,t);
|
||||
}
|
||||
|
||||
EffectSBSMS::setParameters(rateStart,rateEnd,pitchStart,pitchEnd,slideTypeRate,slideTypePitch,false,false,false);
|
||||
return EffectSBSMS::Process();
|
||||
}
|
||||
|
||||
|
|
|
@ -50,10 +50,12 @@ public:
|
|||
// Effect implementation
|
||||
|
||||
virtual bool Init();
|
||||
virtual void Preview(bool dryOnly);
|
||||
virtual bool Process();
|
||||
virtual void PopulateOrExchange(ShuttleGui & S);
|
||||
virtual bool TransferDataToWindow();
|
||||
virtual bool TransferDataFromWindow();
|
||||
virtual double CalcPreviewInputLength(double previewLength);
|
||||
|
||||
private:
|
||||
// EffectTimeScale implementation
|
||||
|
@ -82,6 +84,10 @@ private:
|
|||
void Update_Slider_RatePercentChangeEnd();
|
||||
|
||||
private:
|
||||
bool bPreview;
|
||||
double previewSelectedDuration;
|
||||
SlideType slideTypeRate;
|
||||
SlideType slideTypePitch;
|
||||
double m_RatePercentChangeStart;
|
||||
double m_RatePercentChangeEnd;
|
||||
double m_PitchHalfStepsStart;
|
||||
|
|
Loading…
Reference in New Issue