zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit dea5fe9666952d3596ef242df0231fbc7a1280b2
parent 824a93aef8992b0cbfb7c689a3a9a3b32000541b
Author: fundamental <mark.d.mccurry@gmail.com>
Date:   Wed, 23 Dec 2009 11:12:09 -0500

Echo: Resizing delaySample rather than clearing

- Right now there are some crackles, so this will be reworked

Diffstat:
Msrc/Effects/Echo.cpp | 107++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Msrc/Effects/Echo.h | 19+++++++++----------
Msrc/Samples/Sample.cpp | 28++++++++++++++++++++++++++++
Msrc/Samples/Sample.h | 3+++
4 files changed, 105 insertions(+), 52 deletions(-)

diff --git a/src/Effects/Echo.cpp b/src/Effects/Echo.cpp @@ -24,14 +24,22 @@ #include <iostream> #include "Echo.h" +using namespace std; + Echo::Echo(const int &insertion_, REALTYPE *const efxoutl_, REALTYPE *const efxoutr_) :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), Pvolume(50), Ppanning(64), //Pdelay(60), Plrdelay(100), Plrcross(100), Pfb(40), Phidamp(60), - lrdelay(0), delaySample(1), old(0.0) + dl(0), dr(0), lrdelay(0), delaySample(1), old(0.0), + itr(0), + maxDelay(SAMPLE_RATE * (1.5 + (pow(2.0, 9) - 1.0) /1000.0) + 1) { + pthread_mutex_init(&mutex, NULL); + delaySample.l() = Sample(maxDelay, 0.0); + delaySample.r() = Sample(maxDelay, 0.0); + initdelays(); setpreset(Ppreset); } @@ -53,44 +61,63 @@ void Echo::cleanup() */ void Echo::initdelays() { - /**\todo make this adjust insted of destroy old delays*/ - kl = 0; - kr = 0; - dl = (int)(1 + delay.getiVal() * SAMPLE_RATE - lrdelay); - if(dl < 1) - dl = 1; - dr = (int)(1 + delay.getiVal() * SAMPLE_RATE + lrdelay); - if(dr < 1) - dr = 1; - - delaySample.l() = Sample(dl); - delaySample.r() = Sample(dr); + pthread_mutex_lock(&mutex); + int ndl = (int)(delay.getiVal() * SAMPLE_RATE - lrdelay); + if(ndl < 0) + ndl = dl = 0; + + int ndr = (int)(delay.getiVal() * SAMPLE_RATE + lrdelay); + if(ndr < 0) + ndr = dr = 0; + + if(ndl != dl) { //lets rewite history + Sample rewrite(ndl); + int j = 0; + //this is where real iterators would be useful + for(int i=(itr>dl?itr-dl:itr+maxDelay-dl); i%maxDelay!=itr; ++i) + rewrite[j++] = delaySample.l()[i]; + rewrite.resize(ndl); + j = 0; + for(int i=(itr>ndl?itr-ndl:itr+maxDelay-ndl); i%maxDelay!=itr; ++i) + delaySample.l()[i] = rewrite[j++]; + } - old = Stereo<REALTYPE>(0.0); -} + if(ndr != dr) { //lets rewite history + Sample rewrite(ndr); + int j = 0; + //this is where real iterators would be useful + for(int i=(itr>dr?itr-dr:itr+maxDelay-dr); i%maxDelay!=itr; ++i) + rewrite[j++] = delaySample.r()[i]; + rewrite.resize(ndr); + j = 0; + for(int i=(itr>ndr?itr-ndr:itr+maxDelay-ndr); i%maxDelay!=itr; ++i) + delaySample.r()[i] = rewrite[j++]; + } + dl = ndl; + dr = ndr; + + + //cout << "dl: " << dl << endl; + //cout << "dr: " << dr << endl; + //cout << "max: " << maxDelay << endl; + pthread_mutex_unlock(&mutex); -/* - * Effect output - */ -void Echo::out(REALTYPE *const smpsl, REALTYPE *const smpsr) -{ - Stereo<Sample> input(Sample(SOUND_BUFFER_SIZE, smpsl), Sample( - SOUND_BUFFER_SIZE, - smpsr)); - out(input); } void Echo::out(const Stereo<Sample> &input) { - REALTYPE l, r, ldl, rdl; /**\todo move l+r->? ldl+rdl->?*/ - - for(int i = 0; i < input.l().size(); i++) { - ldl = delaySample.l()[kl]; - rdl = delaySample.r()[kr]; - l = ldl * (1.0 - lrcross) + rdl * lrcross; - r = rdl * (1.0 - lrcross) + ldl * lrcross; - ldl = l; - rdl = r; + REALTYPE ldl, rdl; + + pthread_mutex_lock(&mutex); + for(int i = 0; i < input.l().size(); ++i) { + //get past samples (maxDelay is used due to implementaiton of Sample) + dl; + "foo"; + itr; + ldl = delaySample.l()[itr-dl+maxDelay]; + rdl = delaySample.r()[itr-dr+maxDelay]; + ldl = ldl * (1.0 - lrcross) + rdl * lrcross; + rdl = rdl * (1.0 - lrcross) + ldl * lrcross; efxoutl[i] = ldl * 2.0; efxoutr[i] = rdl * 2.0; @@ -100,16 +127,12 @@ void Echo::out(const Stereo<Sample> &input) rdl = input.r()[i] * (1.0 - panning) - rdl * fb; //LowPass Filter - delaySample.l()[kl] = ldl = ldl * hidamp + old.l() * (1.0 - hidamp); - delaySample.r()[kr] = rdl = rdl * hidamp + old.r() * (1.0 - hidamp); - old.l() = ldl; - old.r() = rdl; - - if(++kl >= dl) - kl = 0; - if(++kr >= dr) - kr = 0; + old.l() = delaySample.l()[itr] = ldl * hidamp + old.l() * (1.0 - hidamp); + old.r() = delaySample.r()[itr] = rdl * hidamp + old.r() * (1.0 - hidamp); + ++itr; } + itr %= maxDelay; + pthread_mutex_unlock(&mutex); } diff --git a/src/Effects/Echo.h b/src/Effects/Echo.h @@ -28,6 +28,7 @@ #include "../Samples/Sample.h" #include "../Misc/Stereo.h" #include "../Controls/DelayCtl.h" +#include <pthread.h> /**Echo Effect*/ class Echo:public Effect @@ -51,14 +52,6 @@ class Echo:public Effect */ ~Echo(); - /** - * Outputs the echo to efxoutl and efxoutr - * @param smpsl Sample from Left channel - * @param smpsr Sample from Right channel - * \todo try to figure out if smpsl should be const *const - * or not (It should be) - */ - void out(REALTYPE *const smpsl, REALTYPE *const smpr); void out(const Stereo<Sample> &input); /** @@ -126,13 +119,19 @@ class Echo:public Effect //Real Parameters REALTYPE panning, lrcross, fb, hidamp; //needs better names - int dl, dr, lrdelay; //needs better names + //Left/Right delay lengths + int dl, dr, lrdelay; + +// int ndl, ndr; //used for shifting delay amounts void initdelays(); Stereo<Sample> delaySample; Stereo<REALTYPE> old; - int kl, kr; + int itr; + //int kl, kr; + int maxDelay; + mutable pthread_mutex_t mutex; }; #endif diff --git a/src/Samples/Sample.cpp b/src/Samples/Sample.cpp @@ -125,6 +125,8 @@ float linearEstimate(float ya, float yb, float xt, float xa = 0.0, float xb =1.0 void Sample::resample(const unsigned int rate, const unsigned int nrate) { + //does not call resize, as I have a feeling that that could lose precision + //(have not tested, so feel free to prove me wrong) if(rate == nrate) return; //no resampling here else {//resampling occurs here @@ -149,6 +151,32 @@ void Sample::resample(const unsigned int rate, const unsigned int nrate) } } +void Sample::resize(unsigned int nsize) +{ + if(bufferSize == nsize) + return; + else {//resampling occurs here + int itr = 0; + float ratio = (nsize * 1.0) / (bufferSize * 1.0); + + int nBufferSize = nsize; + float *nBuffer = new float[nBufferSize]; + + //addition is done to avoid 0 edge case + for(int i = 0; i < nBufferSize; ++i) + nBuffer[i] = linearEstimate(buffer[(int)floor(i/ratio)], + buffer[(int)ceil((i+1)/ratio)], + i, + floor(i/ratio), + ceil((i+1)/ratio)); + + //put the new data in + delete buffer; + buffer = nBuffer; + bufferSize = nBufferSize; + } +} + void Sample::append(const Sample &smp) { int nbufferSize = bufferSize + smp.bufferSize; diff --git a/src/Samples/Sample.h b/src/Samples/Sample.h @@ -60,6 +60,9 @@ class Sample /**Change the sampling rate of the Sample*/ void resample(const unsigned int rate, const unsigned int nrate); + /**Change the size of the sample*/ + void resize(unsigned int nsize); + /**Appends another Sample to this Sample*/ void append(const Sample &smp);