diff --git a/src/effects/Paulstretch.cpp b/src/effects/Paulstretch.cpp index cfe542b44..df6abae81 100644 --- a/src/effects/Paulstretch.cpp +++ b/src/effects/Paulstretch.cpp @@ -41,35 +41,42 @@ Param( Time, float, XO("Time Resolution"), 0.25f, 0.00099f, FLT_MAX, 1 class PaulStretch { public: - PaulStretch(float rap_,int in_bufsize_,float samplerate_); + PaulStretch(float rap_, size_t in_bufsize_, float samplerate_); //in_bufsize is also a half of a FFT buffer (in samples) virtual ~PaulStretch(); void process(float *smps,int nsmps); - int in_bufsize; - int poolsize;//how many samples are inside the input_pool size (need to know how many samples to fill when seeking) - - int out_bufsize; - float *out_buf; - - int get_nsamples();//how many samples are required to be added in the pool next time - int get_nsamples_for_fill();//how many samples are required to be added for a complete buffer refill (at start of the song or after seek) - - void set_rap(float newrap);//set the current stretch value - -protected: - void process_spectrum(float *WXUNUSED(freq)) {}; - float samplerate; + size_t get_nsamples();//how many samples are required to be added in the pool next time + size_t get_nsamples_for_fill();//how many samples are required to be added for a complete buffer refill (at start of the song or after seek) private: - float *in_pool;//de marimea in_bufsize - float rap; - float *old_out_smp_buf; + void process_spectrum(float *WXUNUSED(freq)) {}; - float *fft_smps,*fft_c,*fft_s,*fft_freq,*fft_tmp; + const float samplerate; + const float rap; + const size_t in_bufsize; + +public: + const size_t out_bufsize; + float *const out_buf; + +private: + float *const old_out_smp_buf; + +public: + const size_t poolsize;//how many samples are inside the input_pool size (need to know how many samples to fill when seeking) + +private: + float *const in_pool;//de marimea in_bufsize double remained_samples;//how many fraction of samples has remained (0..1) + + float *const fft_smps; + float *const fft_c; + float *const fft_s; + float *const fft_freq; + float *const fft_tmp; }; // @@ -138,7 +145,7 @@ double EffectPaulstretch::CalcPreviewInputLength(double previewLength) { // FIXME: Preview is currently at the project rate, but should really be // at the track rate (bugs 1284 and 852). - int minDuration = GetBufferSize(mProjectRate) * 2 + 1; + auto minDuration = GetBufferSize(mProjectRate) * 2 + 1; // Preview playback may need to be trimmed but this is the smallest selection that we can use. double minLength = std::max(minDuration / mProjectRate, previewLength / mAmount); @@ -264,7 +271,7 @@ bool EffectPaulstretch::ProcessOne(WaveTrack *track,double t0,double t1,int coun return false; } - if (len < minDuration){ //error because the selection is too short + if (len < minDuration) { //error because the selection is too short float maxTimeRes = log(len) / log(2.0); maxTimeRes = pow(2.0, floor(maxTimeRes) + 0.5); @@ -306,8 +313,9 @@ bool EffectPaulstretch::ProcessOne(WaveTrack *track,double t0,double t1,int coun } - double adjust_amount=(double)len/((double)len-((double)stretch_buf_size*2.0)); - amount=1.0+(amount-1.0)*adjust_amount; + double adjust_amount = (double)len / + ((double)len - ((double)stretch_buf_size * 2.0)); + amount = 1.0 + (amount - 1.0) * adjust_amount; auto outputTrack = mFactory->NewWaveTrack(track->GetSampleFormat(),track->GetRate()); @@ -315,51 +323,54 @@ bool EffectPaulstretch::ProcessOne(WaveTrack *track,double t0,double t1,int coun // This encloses all the allocations of buffers, including those in // the constructor of the PaulStretch object - PaulStretch stretch(amount,stretch_buf_size,track->GetRate()); + PaulStretch stretch(amount, stretch_buf_size, track->GetRate()); auto nget = stretch.get_nsamples_for_fill(); - int bufsize=stretch.poolsize; - float *buffer0=new float[bufsize]; - float *bufferptr0=buffer0; - bool first_time=true; + auto bufsize = stretch.poolsize; + float *buffer0 = new float[bufsize]; + float *bufferptr0 = buffer0; + bool first_time = true; - int fade_len=100; - if (fade_len>(bufsize/2-1)) fade_len=bufsize/2-1; - float *fade_track_smps=new float[fade_len]; - decltype(len) s=0; - bool cancelled=false; + const auto fade_len = std::min(100, bufsize / 2 - 1); + float *fade_track_smps = new float[fade_len]; + decltype(len) s = 0; + bool cancelled = false; - while (sGet((samplePtr)bufferptr0,floatSample,start+s,nget); - stretch.process(buffer0,nget); + while (s < len) { + track->Get((samplePtr)bufferptr0, floatSample, start + s, nget); + stretch.process(buffer0, nget); if (first_time) { - stretch.process(buffer0,0); + stretch.process(buffer0, 0); }; - s+=nget; + s += nget; - if (first_time){//blend the the start of the selection - track->Get((samplePtr)fade_track_smps,floatSample,start,fade_len); - first_time=false; - for (int i=0;iGet((samplePtr)fade_track_smps, floatSample, start, fade_len); + first_time = false; + for (int i = 0; i < fade_len; i++){ + float fi = (float)i / (float)fade_len; + stretch.out_buf[i] = + stretch.out_buf[i] * fi + (1.0 - fi) * fade_track_smps[i]; }; }; - if (s>=len){//blend the end of the selection + if (s >= len) {//blend the end of the selection track->Get((samplePtr)fade_track_smps,floatSample,end-fade_len,fade_len); - for (int i=0;iAppend((samplePtr)stretch.out_buf,floatSample,stretch.out_bufsize); + outputTrack->Append((samplePtr)stretch.out_buf, floatSample, + stretch.out_bufsize); - nget=stretch.get_nsamples(); + nget = stretch.get_nsamples(); if (TrackProgress(count, (s / (double) len))) { cancelled=true; break; @@ -388,34 +399,22 @@ bool EffectPaulstretch::ProcessOne(WaveTrack *track,double t0,double t1,int coun /*************************************************************/ -PaulStretch::PaulStretch(float rap_,int in_bufsize_,float samplerate_) +PaulStretch::PaulStretch(float rap_, size_t in_bufsize_, float samplerate_) + : samplerate { samplerate } + , rap { std::max(1.0f, rap_) } + , in_bufsize { in_bufsize_ } + , out_bufsize { std::max(size_t{ 8 }, in_bufsize) } + , out_buf { new float[out_bufsize] } + , old_out_smp_buf { new float[out_bufsize * 2] { 0.0f } } + , poolsize { in_bufsize_ * 2 } + , in_pool { new float[poolsize] { 0.0f } } + , remained_samples { 0.0 } + , fft_smps { new float[poolsize] { 0.0f } } + , fft_s { new float[poolsize] { 0.0f } } + , fft_c { new float[poolsize] { 0.0f } } + , fft_freq { new float[poolsize] { 0.0f } } + , fft_tmp { new float[poolsize] } { - samplerate=samplerate_; - rap=rap_; - in_bufsize=in_bufsize_; - if (rap<1.0) rap=1.0; - out_bufsize=in_bufsize; - if (out_bufsize<8) out_bufsize=8; - - out_buf=new float[out_bufsize]; - old_out_smp_buf=new float[out_bufsize*2];for (int i=0;i=1.0) rap=newrap; - else rap=1.0; -} - void PaulStretch::process(float *smps,int nsmps) { //add NEW samples to the pool - if ((smps!=NULL)&&(nsmps!=0)){ - if (nsmps>poolsize){ - nsmps=poolsize; + if ((smps != NULL) && (nsmps != 0)) { + if (nsmps > poolsize) { + nsmps = poolsize; } - int nleft=poolsize-nsmps; + int nleft = poolsize - nsmps; //move left the samples from the pool to make room for NEW samples - for (int i=0;imax) max=a; - float b=fabs(fft_smps[i]); - if (b>max2) max2=b; + float max = 0.0, max2 = 0.0; + for (size_t i = 0; i < poolsize; i++) { + max = std::max(max, fabsf(fft_tmp[i])); + max2 = std::max(max2, fabsf(fft_smps[i])); } //make the output buffer - float tmp=1.0/(float) out_bufsize*M_PI; - float hinv_sqrt2=0.853553390593f;//(1.0+1.0/sqrt(2))*0.5; + float tmp = 1.0 / (float) out_bufsize * M_PI; + float hinv_sqrt2 = 0.853553390593f;//(1.0+1.0/sqrt(2))*0.5; - float ampfactor=1.0; - if (rap<1.0) ampfactor=rap*0.707; - else ampfactor=(out_bufsize/(float)poolsize)*4.0; + float ampfactor = 1.0; + if (rap < 1.0) + ampfactor = rap * 0.707; + else + ampfactor = (out_bufsize / (float)poolsize) * 4.0; - for (int i=0;i=1.0){ - ri+=(int)floor(remained_samples); - remained_samples=remained_samples-floor(remained_samples); + remained_samples += rf; + if (remained_samples >= 1.0){ + ri += (size_t)floor(remained_samples); + remained_samples = remained_samples - floor(remained_samples); } - if (ri>poolsize){ - ri=poolsize; + if (ri > poolsize) { + ri = poolsize; } return ri; } -int PaulStretch::get_nsamples_for_fill() +size_t PaulStretch::get_nsamples_for_fill() { return poolsize; }