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