1 #include "sbsms.h"
2 #include "real.h"
3 #include <math.h>
4 #include <algorithm>
5 using namespace std;
6 
7 namespace _sbsms_ {
8 
9 class SlideImp {
10 public:
~SlideImp()11   virtual ~SlideImp() {}
12   virtual float getTotalStretch()=0;
13   virtual float getStretchedTime(float t)=0;
14   virtual float getInverseStretchedTime(float t)=0;
15   virtual float getRate(float t)=0;
16   virtual float getStretch(float t)=0;
17   virtual float getMeanStretch(float t0, float t1)=0;
18   virtual float getRate()=0;
19   virtual float getStretch()=0;
20   virtual void step()=0;
21 };
22 
23 class IdentitySlide : public SlideImp {
24 public:
IdentitySlide()25   IdentitySlide() {
26   }
getTotalStretch()27   float getTotalStretch() {
28     return 1.0f;
29   }
getStretchedTime(float t)30   float getStretchedTime(float t) {
31     return t;
32   }
getInverseStretchedTime(float t)33   float getInverseStretchedTime(float t) {
34     return t;
35   }
getRate(float t)36   float getRate(float t) {
37     return 1.0f;
38   }
getStretch(float t)39   float getStretch(float t) {
40     return 1.0f;
41   }
getMeanStretch(float t0,float t1)42   float getMeanStretch(float t0, float t1) {
43     return 1.0f;
44   }
getRate()45   float getRate() {
46     return 1.0f;
47   }
getStretch()48   float getStretch() {
49     return 1.0f;
50   }
step()51   void step() {
52   }
53 };
54 
55 class ConstantSlide : public SlideImp {
56 public:
ConstantSlide(float rate)57   ConstantSlide(float rate) {
58     this->rate = rate;
59   }
getTotalStretch()60   float getTotalStretch() {
61     return 1.0f / rate;
62   }
getStretchedTime(float t)63   float getStretchedTime(float t) {
64     return t / rate;
65   }
getInverseStretchedTime(float t)66   float getInverseStretchedTime(float t) {
67     return rate * t;
68   }
getRate(float t)69   float getRate(float t) {
70     return rate;
71   }
getStretch(float t)72   float getStretch(float t) {
73     return 1.0f / rate;
74   }
getMeanStretch(float t0,float t1)75   float getMeanStretch(float t0, float t1) {
76     return 1.0f / rate;
77   }
getRate()78   float getRate() {
79     return rate;
80   }
getStretch()81   float getStretch() {
82     return 1.0f / rate;
83   }
step()84   void step() {
85   }
86 protected:
87   float rate;
88 };
89 
90 class LinearInputRateSlide : public SlideImp {
91 public:
LinearInputRateSlide(float rate0,float rate1,const SampleCountType & n)92   LinearInputRateSlide(float rate0, float rate1, const SampleCountType &n) {
93     this->rate0 = rate0;
94     this->rate1 = rate1;
95     if(n) {
96       val = rate0;
97       inc = (rate1 - rate0) / (double)n;
98     }
99   }
getTotalStretch()100   float getTotalStretch() {
101     return log(rate1 / rate0) / (rate1 - rate0);
102   }
getStretchedTime(float t)103   float getStretchedTime(float t) {
104     float ratet = getRate(t);
105     return log(ratet / rate0) / (rate1 - rate0);
106   }
getInverseStretchedTime(float t)107   float getInverseStretchedTime(float t) {
108     return (exp((rate1-rate0)*t)-1.0f)*rate0/(rate1-rate0);
109   }
getRate(float t)110   float getRate(float t) {
111     return rate0 + (rate1 - rate0) * t;
112   }
getStretch(float t)113   float getStretch(float t) {
114     return 1.0f / getRate(t);
115   }
getMeanStretch(float t0,float t1)116   float getMeanStretch(float t0, float t1) {
117     return log(getRate(t1)/getRate(t0))/((rate1-rate0)*(t1-t0));
118   }
getRate()119   float getRate() {
120     return (float)val;
121   }
getStretch()122   float getStretch() {
123     return (float)(1.0 / val);
124   }
step()125   void step() {
126     val += inc;
127   }
128 protected:
129   float rate0, rate1;
130   double val, inc;
131 };
132 
133 class LinearOutputRateSlide : public SlideImp {
134 public:
LinearOutputRateSlide(float rate0,float rate1,const SampleCountType & n)135   LinearOutputRateSlide(float rate0, float rate1, const SampleCountType &n) {
136     this->rate0 = rate0;
137     this->rate1 = rate1;
138     if(n) {
139       val = 0.0;
140       inc = 1.0 / (double)n;
141     }
142   }
getTotalStretch()143   float getTotalStretch() {
144     return 2.0f / (rate0 + rate1);
145   }
getStretchedTime(float t)146   float getStretchedTime(float t) {
147     return (sqrt(rate0 * rate0 + (rate1 * rate1 - rate0 * rate0) * t) - rate0) * 2.0f / (rate1 * rate1 - rate0 * rate0);
148   }
getInverseStretchedTime(float t)149   float getInverseStretchedTime(float t) {
150     float r12 = rate1 * rate1 - rate0 * rate0;
151     float s = 0.5f * r12 * t + rate0;
152     return (s * s - rate0 * rate0) / r12;
153   }
getRate(float t)154   float getRate(float t) {
155     return sqrt(rate0 * rate0 + (rate1 * rate1 - rate0 * rate0) * t);
156   }
getStretch(float t)157   float getStretch(float t) {
158     return 1.0f / getRate(t);
159   }
getMeanStretch(float t0,float t1)160   float getMeanStretch(float t0, float t1) {
161     float r02 = rate0 * rate0;
162     float r102 = rate1 * rate1 - r02;
163     return 2.0f * (sqrt(r02 + r102*t1) - sqrt(r02 + r102 * t0)) / (r102 * (t1 - t0));
164   }
getRate()165   float getRate() {
166     return getRate((float)val);
167   }
getStretch()168   float getStretch() {
169     return getStretch((float)val);
170   }
step()171   void step() {
172     val += inc;
173   }
174 protected:
175   float rate0, rate1;
176   double val, inc;
177 };
178 
179 class LinearInputStretchSlide : public SlideImp {
180 public:
LinearInputStretchSlide(float rate0,float rate1,const SampleCountType & n)181   LinearInputStretchSlide(float rate0, float rate1, const SampleCountType &n) {
182     this->rate0 = rate0;
183     this->rate1 = rate1;
184     if(n) {
185       val = 1.0 / rate0;
186       inc = (1.0 / rate1 - 1.0 / rate0) / (double)n;
187     }
188   }
getTotalStretch()189   float getTotalStretch() {
190     return 0.5f / rate0 + 0.5f / rate1;
191   }
getStretchedTime(float t)192   float getStretchedTime(float t) {
193     return t / rate0 * (1.0f + 0.5f * t * (rate0 / rate1 - 1.0f));
194   }
getInverseStretchedTime(float t)195   float getInverseStretchedTime(float t) {
196     float s = 1.0f / rate1 - 1.0f / rate0;
197     return (-1.0f / rate0 + sqrt(1/(rate0*rate0)-2.0f*t*s)) / s;
198   }
getRate(float t)199   float getRate(float t) {
200     return 1.0f / getStretch(t);
201   }
getStretch(float t)202   float getStretch(float t) {
203     return (1.0f / rate0 + (1.0f / rate1 - 1.0f / rate0) * t);
204   }
getMeanStretch(float t0,float t1)205   float getMeanStretch(float t0, float t1) {
206     return ((t1 + t0) * (rate0 - rate1)  - 2.0f * rate1) / (2.0f * rate0 * rate1);
207   }
getRate()208   float getRate() {
209     return (float)(1.0 / val);
210   }
getStretch()211   float getStretch() {
212     return (float)val;
213   }
step()214   void step() {
215     val += inc;
216   }
217 protected:
218   float rate0, rate1;
219   double val, inc;
220 };
221 
222 class LinearOutputStretchSlide : public SlideImp {
223 public:
LinearOutputStretchSlide(float rate0,float rate1,const SampleCountType & n)224   LinearOutputStretchSlide(float rate0, float rate1, const SampleCountType &n) {
225     this->rate0 = rate0;
226     this->rate1 = rate1;
227     c0 = rate0 / rate1;
228     c1 = 1.0f / (rate0 * log(c0));
229     if(n) {
230       val = 0.0;
231       inc = 1.0 / (double)n;
232     }
233   }
getTotalStretch()234   float getTotalStretch() {
235     return c1 * (c0 - 1.0f);
236   }
getStretchedTime(float t)237   float getStretchedTime(float t) {
238     return c1 * (pow(c0, t) - 1.0f);
239   }
getInverseStretchedTime(float t)240   float getInverseStretchedTime(float t) {
241     return log(t/c1 + 1.0f) * c1 * rate0;
242   }
getRate(float t)243   float getRate(float t) {
244     return rate0 * pow(c0, -t);
245   }
getStretch(float t)246   float getStretch(float t) {
247     return pow(c0, t) / rate0;
248   }
getMeanStretch(float t0,float t1)249   float getMeanStretch(float t0, float t1) {
250     return (pow(c0,t1) - pow(c0,t0)) / (c1 * (t1 - t0));
251   }
getRate()252   float getRate() {
253     return getRate((float)val);
254   }
getStretch()255   float getStretch() {
256     return getStretch((float)val);
257   }
step()258   void step() {
259     val += inc;
260   }
261 protected:
262   float rate0, rate1;
263   double val, inc;
264   float c0, c1;
265 };
266 
267 class GeometricInputSlide : public SlideImp {
268 public:
GeometricInputSlide(float rate0,float rate1,const SampleCountType & n)269   GeometricInputSlide(float rate0, float rate1, const SampleCountType &n) {
270     this->rate0 = rate0;
271     this->rate1 = rate1;
272     this->c0 = rate0 / rate1;
273     this->log01 = log(c0);
274     if(n) {
275       val = rate0;
276       inc = pow((double)rate1 / rate0, 1.0 / (double)n);
277     }
278   }
getTotalStretch()279   float getTotalStretch() {
280     return (rate0 - rate1) / (log01 * (rate0 * rate1));
281   }
getStretchedTime(float t)282   float getStretchedTime(float t) {
283     return (float)(pow(rate0 / rate1, t) - 1.0) / (rate0 * log01);
284   }
getInverseStretchedTime(float t)285   float getInverseStretchedTime(float t) {
286     return log(t * rate0 * log01 + 1.0f) / log01;
287   }
getRate(float t)288   float getRate(float t) {
289     return rate0 * pow(rate1 / rate0, t);
290   }
getStretch(float t)291   float getStretch(float t) {
292     return 1.0f / getRate(t);
293   }
getMeanStretch(float t0,float t1)294   float getMeanStretch(float t0, float t1) {
295     return (pow(c0,t1) - pow(c0,t0)) / (rate0 * log01 * (t1 - t0));
296   }
getRate()297   float getRate() {
298     return (float)val;
299   }
getStretch()300   float getStretch() {
301     return (float)(1.0 / val);
302   }
step()303   void step() {
304     val *= inc;
305   }
306 protected:
307   float rate0, rate1, c0, log01;
308   double val, inc;
309 };
310 
311 class GeometricOutputSlide : public SlideImp {
312 public:
GeometricOutputSlide(float rate0,float rate1,const SampleCountType & n)313   GeometricOutputSlide(float rate0, float rate1, const SampleCountType &n) {
314     this->rate0 = rate0;
315     this->rate1 = rate1;
316     log10 = log(rate1 / rate0);
317     r10 = rate1 - rate0;
318     totalStretch = getTotalStretch();
319     if(n) {
320       val = 0.0;
321       inc = 1.0 / (double)n;
322     }
323   }
getTotalStretch()324   float getTotalStretch() {
325     return log(rate1 / rate0) / (rate1 - rate0);
326   }
getStretchedTime(float t)327   float getStretchedTime(float t) {
328     return log(r10 / rate0 * t + 1.0f) / r10;
329   }
getInverseStretchedTime(float t)330   float getInverseStretchedTime(float t) {
331     return rate0 / r10 * (exp(t * r10) - 1.0f);
332   }
getRate(float t)333   float getRate(float t) {
334     float t1 = getStretchedTime(t) / totalStretch;
335     return rate0 * pow(rate1 / rate0, t1);
336   }
getStretch(float t)337   float getStretch(float t) {
338     return 1.0f / getRate(t);
339   }
getMeanStretch(float t0,float t1)340   float getMeanStretch(float t0, float t1) {
341     return log((rate0 + r10 * t1)/(rate0 + r10 * t0)) /(r10 * (t1 - t0));
342   }
getRate()343   float getRate() {
344     return getRate((float)val);
345   }
getStretch()346   float getStretch() {
347     return getStretch((float)val);
348   }
step()349   void step() {
350     val += inc;
351   }
352 protected:
353   float rate0, rate1;
354   float log10, r10, totalStretch;
355   double val, inc;
356 };
357 
358 
Slide(SlideType slideType,float rate0,float rate1,const SampleCountType & n)359 Slide :: Slide(SlideType slideType, float rate0, float rate1, const SampleCountType &n)
360 {
361   if(slideType == SlideIdentity) {
362     imp = new IdentitySlide();
363   } else if(slideType == SlideConstant || rate0 == rate1) {
364     imp = new ConstantSlide(rate0);
365   } else if(slideType == SlideLinearInputRate) {
366     imp = new LinearInputRateSlide(rate0,rate1,n);
367   } else if(slideType == SlideLinearOutputRate) {
368     imp = new LinearOutputRateSlide(rate0,rate1,n);
369   } else if(slideType == SlideLinearInputStretch) {
370     imp = new LinearInputStretchSlide(rate0,rate1,n);
371   } else if(slideType == SlideLinearOutputStretch) {
372     imp = new LinearOutputStretchSlide(rate0,rate1,n);
373   } else if(slideType == SlideGeometricInput) {
374     imp = new GeometricInputSlide(rate0,rate1,n);
375   } else if(slideType == SlideGeometricOutput) {
376     imp = new GeometricOutputSlide(rate0,rate1,n);
377   }
378 }
379 
~Slide()380 Slide :: ~Slide()
381 {
382   delete imp;
383 }
384 
getTotalStretch()385 float Slide :: getTotalStretch()
386 {
387   return imp->getTotalStretch();
388 }
389 
getRate(float t)390 float Slide :: getRate(float t)
391 {
392   if(t > 1.0f) t = 1.0f;
393   return imp->getRate(t);
394 }
395 
getStretch(float t)396 float Slide :: getStretch(float t)
397 {
398   if(t > 1.0f) t = 1.0f;
399   return imp->getStretch(t);
400 }
401 
getStretchedTime(float t)402 float Slide :: getStretchedTime(float t)
403 {
404   if(t > 1.0f) t = 1.0f;
405   return imp->getStretchedTime(t);
406 }
407 
getMeanStretch(float t0,float t1)408 float Slide :: getMeanStretch(float t0, float t1) {
409   if(t0 < 0.0f) t0 = 0.0f;
410   return imp->getMeanStretch(t0,t1);
411 }
412 
getInverseStretchedTime(float t)413 float Slide :: getInverseStretchedTime(float t)
414 {
415   return imp->getInverseStretchedTime(t);
416 }
417 
getRate()418 float Slide :: getRate()
419 {
420   return imp->getRate();
421 }
422 
getStretch()423 float Slide :: getStretch()
424 {
425   return imp->getStretch();
426 }
427 
step()428 void Slide :: step()
429 {
430   imp->step();
431 }
432 
433 class SBSMSInterfaceSlidingImp  {
434 public:
435   friend class SBSMSInterfaceSliding;
436   SBSMSInterfaceSlidingImp(Slide *rateSlide,
437                            Slide *pitchSlide,
438                            bool bPitchReferenceInput,
439                            const SampleCountType &samplesToInput,
440                            long preSamples,
441                            SBSMSQuality *quality);
~SBSMSInterfaceSlidingImp()442   ~SBSMSInterfaceSlidingImp() {}
443   inline float getStretch(float t);
444   inline float getMeanStretch(float t0, float t1);
445   inline float getPitch(float t);
446   inline long getPresamples();
447   SampleCountType getSamplesToInput();
448   SampleCountType getSamplesToOutput();
449 protected:
450   Slide *stretchSlide;
451   Slide *pitchSlide;
452   bool bPitchReferenceInput;
453   float totalStretch;
454   float stretchScale;
455   long preSamples;
456   SampleCountType samplesToInput;
457   SampleCountType samplesToOutput;
458 };
459 
SBSMSInterfaceSlidingImp(Slide * stretchSlide,Slide * pitchSlide,bool bPitchReferenceInput,const SampleCountType & samplesToInput,long preSamples,SBSMSQuality * quality)460 SBSMSInterfaceSlidingImp :: SBSMSInterfaceSlidingImp(Slide *stretchSlide,
461                                                      Slide *pitchSlide,
462                                                      bool bPitchReferenceInput,
463                                                      const SampleCountType &samplesToInput,
464                                                      long preSamples,
465                                                      SBSMSQuality *quality)
466 {
467   this->stretchSlide = stretchSlide;
468   this->pitchSlide = pitchSlide;
469   this->bPitchReferenceInput = bPitchReferenceInput;
470   this->samplesToInput = samplesToInput;
471   this->preSamples = preSamples;
472   this->totalStretch = stretchSlide->getTotalStretch();
473   this->samplesToOutput = (SampleCountType)((float)samplesToInput * totalStretch);
474   stretchScale = 1.0f;
475 
476   if(quality) {
477     SampleCountType samplesIn = 0;
478     SampleCountType samplesOut = 0;
479     float outFrameSizefloat = 0.0f;
480     float stretch = 1.0f;
481     int inFrameSize = quality->getFrameSize();
482     while(samplesIn < samplesToInput) {
483       float t = (float)samplesIn / (float)samplesToInput;
484       float t1 =(float)(samplesIn + inFrameSize) / (float)samplesToInput;
485       stretch = stretchSlide->getMeanStretch(t,t1);
486       outFrameSizefloat += stretch * inFrameSize;
487       int outFrameSize = (int) outFrameSizefloat;
488       outFrameSizefloat -= (float) outFrameSize;
489       samplesIn += inFrameSize;
490       samplesOut += outFrameSize;
491     }
492     SampleCountType samplesOutputed = samplesOut - lrintf(stretch * (samplesIn - samplesToInput));
493     stretchScale = (float)samplesToOutput / (float)samplesOutputed;
494   }
495 }
496 
getStretch(float t)497 float SBSMSInterfaceSliding :: getStretch(float t) { return imp->getStretch(t); }
getStretch(float t)498 float SBSMSInterfaceSlidingImp :: getStretch(float t)
499 {
500   return stretchScale * stretchSlide->getStretch(t);
501 }
502 
getMeanStretch(float t0,float t1)503 float SBSMSInterfaceSliding :: getMeanStretch(float t0, float t1) { return imp->getMeanStretch(t0, t1); }
getMeanStretch(float t0,float t1)504 float SBSMSInterfaceSlidingImp :: getMeanStretch(float t0, float t1)
505 {
506   return stretchSlide->getMeanStretch(t0, t1);
507 }
508 
getPitch(float t)509 float SBSMSInterfaceSliding :: getPitch(float t) { return imp->getPitch(t); }
getPitch(float t)510 float SBSMSInterfaceSlidingImp :: getPitch(float t)
511 {
512   if(bPitchReferenceInput) return pitchSlide->getRate(t);
513   else return pitchSlide->getRate(min(1.0f,stretchSlide->getStretchedTime(t) / totalStretch));
514 }
515 
getPresamples()516 long SBSMSInterfaceSliding :: getPresamples() { return imp->getPresamples(); }
getPresamples()517 long SBSMSInterfaceSlidingImp :: getPresamples()
518 {
519   return preSamples;
520 }
521 
getSamplesToInput()522 SampleCountType SBSMSInterfaceSliding :: getSamplesToInput() { return imp->getSamplesToInput(); }
getSamplesToInput()523 SampleCountType SBSMSInterfaceSlidingImp :: getSamplesToInput()
524 {
525   return samplesToInput;
526 }
527 
getSamplesToOutput()528 SampleCountType SBSMSInterfaceSliding :: getSamplesToOutput() { return imp->getSamplesToOutput(); }
getSamplesToOutput()529 SampleCountType SBSMSInterfaceSlidingImp :: getSamplesToOutput()
530 {
531   return samplesToOutput;
532 }
533 
SBSMSInterfaceSliding(Slide * stretchSlide,Slide * pitchSlide,bool bPitchReferenceInput,const SampleCountType & samplesToInput,long preSamples,SBSMSQuality * quality)534 SBSMSInterfaceSliding :: SBSMSInterfaceSliding(Slide *stretchSlide,
535                                                Slide *pitchSlide,
536                                                bool bPitchReferenceInput,
537                                                const SampleCountType &samplesToInput,
538                                                long preSamples,
539                                                SBSMSQuality *quality)
540 {
541   imp = new SBSMSInterfaceSlidingImp(stretchSlide, pitchSlide, bPitchReferenceInput,
542                                      samplesToInput, preSamples, quality);
543 }
544 
~SBSMSInterfaceSliding()545 SBSMSInterfaceSliding :: ~SBSMSInterfaceSliding()
546 {
547   delete imp;
548 }
549 
550 }
551