zynaddsubfx

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

commit cefe2b53d04b1d5de3b51e0f977abcd5d8528619
parent 6512c3d04d6843cbb86a35cced936a02cc19439e
Author: Paul <nop@nop-desktop.(none)>
Date:   Tue, 29 Sep 2009 23:27:37 +0300

Bandwidth effect on Reverb

Diffstat:
MChangeLog | 4++++
Msrc/DSP/Makefile | 2+-
Msrc/DSP/Unison.cpp | 27+++++----------------------
Msrc/DSP/Unison.h | 5++++-
Msrc/Effects/Reverb.cpp | 128+++++++------------------------------------------------------------------------
Msrc/Effects/Reverb.h | 121++-----------------------------------------------------------------------------
Msrc/globals.h | 1+
7 files changed, 29 insertions(+), 259 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -934,3 +934,6 @@ 25 Sep 2009 (Mark McCurry) - Allowed for XMLwrapper to retrieve strings stored in mxml TEXT fields +29 Sep 2009 (Paul Nasca) + - Remove the old (FFT based) Bandwidth effect to Reverb and started rewrite it (based on multivoice chorus/unison effect) + +\ No newline at end of file diff --git a/src/DSP/Makefile b/src/DSP/Makefile @@ -1,6 +1,6 @@ include ../Makefile.inc -objects=FFTwrapper.o AnalogFilter.o FormantFilter.o SVFilter.o Filter.o +objects=FFTwrapper.o AnalogFilter.o FormantFilter.o SVFilter.o Filter.o Unison.o all: $(objects) diff --git a/src/DSP/Unison.cpp b/src/DSP/Unison.cpp @@ -73,7 +73,7 @@ void Unison::update_parameters(){ }; #warning compute unison_amplitude_samples in functie de centi - unison_amplitude_samples=20.0; + unison_amplitude_samples=200.0; if (unison_amplitude_samples>=max_delay-1) unison_amplitude_samples=max_delay-2; @@ -96,7 +96,7 @@ void Unison::process(int bufsize,REALTYPE *inbuf,REALTYPE *outbuf){ xpos+=xpos_step; REALTYPE in=inbuf[i],out=0.0; - + REALTYPE sign=1.0; for (int k=0;k<unison_size;k++){ REALTYPE vpos=uv[k].realpos1*(1.0-xpos)+uv[k].realpos2*xpos;//optimize REALTYPE pos=delay_k+max_delay-vpos-1.0;//optimize @@ -105,7 +105,8 @@ void Unison::process(int bufsize,REALTYPE *inbuf,REALTYPE *outbuf){ F2I(pos,posi);//optimize! if (posi>=max_delay) posi-=max_delay; posf=pos-floor(pos); - out+=(1.0-posf)*delay_buffer[posi]+posf*delay_buffer[posi+1]; + out+=((1.0-posf)*delay_buffer[posi]+posf*delay_buffer[posi+1])*sign; + sign=-sign; }; outbuf[i]=out*volume; // printf("%d %g\n",i,outbuf[i]); @@ -129,8 +130,7 @@ void Unison::update_unison_data(){ pos=1.0; step=-step; }; - //REALTYPE vibratto_val=pos-0.35*pos*pos*pos;//make the vibratto lfo smoother - REALTYPE vibratto_val=(pos+1); + REALTYPE vibratto_val=pos-0.35*pos*pos*pos;//make the vibratto lfo smoother REALTYPE newval=1.0+0.5*(vibratto_val+1.0)*unison_amplitude_samples; if (first_time){ @@ -146,21 +146,4 @@ void Unison::update_unison_data(){ if (first_time) first_time=false; }; -/* -int main(){ - srand(time(NULL)); - Unison unison(10,0.2); - //unison.set_base_frequency(1.0); - - int bufsize=100; - REALTYPE in[bufsize],out[bufsize]; - ZERO_REALTYPE (in,bufsize); - ZERO_REALTYPE (out,bufsize); - in[20]=1; - for (int i=0;i<100000;i++) unison.process(bufsize,in,out); - for (int i=0;i<bufsize;i++) printf("%.3g ",out[i]);printf("\n"); - - return 1; -}; -*/ diff --git a/src/DSP/Unison.h b/src/DSP/Unison.h @@ -21,6 +21,7 @@ #ifndef UNISON_H #define UNISON_H +#include <stdlib.h> #include "../globals.h" @@ -31,6 +32,8 @@ class Unison{ void set_size(int new_size); void set_base_frequency(REALTYPE freq); + void set_bandwidth(REALTYPE bandwidth_cents){ + }; void process(int bufsize,REALTYPE *inbuf,REALTYPE *outbuf=NULL); @@ -44,7 +47,7 @@ class Unison{ REALTYPE step,position;//base LFO REALTYPE realpos1,realpos2; //the position regarding samples int lin_ipos,lin_ifreq; -#error sa calculez frecventa si pozitia a.i. la inceput sa fie realpos1 si la final sa fie realpos2 +//#error sa calculez frecventa si pozitia a.i. la inceput sa fie realpos1 si la final sa fie realpos2 REALTYPE lin_fpos,lin_ffreq; UnisonVoice(){ position=RND*1.8-0.9; diff --git a/src/Effects/Reverb.cpp b/src/Effects/Reverb.cpp @@ -25,114 +25,6 @@ /**\todo: EarlyReflections,Prdelay,Perbalance */ -ReverbBandwidth::ReverbBandwidth (int small_buffer_size_,int n_small_buffers_per_half_big_buffer_): - OverlapAdd (small_buffer_size_,n_small_buffers_per_half_big_buffer_){ - bandwidth=0.1; - fft=new FFTwrapper(big_buffer_size); - newFFTFREQS(&freqs,half_big_buffer_size); - srcfreq=new REALTYPE[half_big_buffer_size]; - destfreq=new REALTYPE[half_big_buffer_size]; - tmpfreq=new REALTYPE[half_big_buffer_size]; - window=new REALTYPE[big_buffer_size]; - ZERO(srcfreq,half_big_buffer_size); - ZERO(destfreq,half_big_buffer_size); - ZERO(tmpfreq,half_big_buffer_size); - - for (int i=0;i<big_buffer_size;i++) window[i]=0.5*(1.0-cos(2*M_PI*i/(big_buffer_size-1.0))); -}; - -ReverbBandwidth::~ReverbBandwidth(){ - delete fft; - deleteFFTFREQS(&freqs); - delete []srcfreq; - delete []destfreq; - delete []tmpfreq; - delete []window; -}; - -void ReverbBandwidth::do_process_big_buffer(){ - - for (int i=0;i<big_buffer_size;i++) big_buffer[i]*=window[i]; - - fft->smps2freqs(big_buffer,freqs); - for (int i=0;i<half_big_buffer_size;i++){ - srcfreq[i]=sqrt(freqs.c[i]*freqs.c[i]+freqs.s[i]*freqs.s[i])/half_big_buffer_size; - }; - - - //spread - do_spread(half_big_buffer_size,srcfreq,destfreq,bandwidth); - - unsigned int rand_seed=rand(); - REALTYPE inv_2p15_2pi=1.0/16384.0*M_PI; - freqs.c[0]=freqs.s[0]=0.0; - for (int i=1;i<half_big_buffer_size;i++) { - rand_seed=(rand_seed*1103515245+12345); - unsigned int rand=(rand_seed>>16)&0x7fff; - REALTYPE phase=rand*inv_2p15_2pi; - freqs.c[i]=destfreq[i]*cos(phase); - freqs.s[i]=destfreq[i]*sin(phase); - }; - - - fft->freqs2smps(freqs,big_buffer); - for (int i=0;i<big_buffer_size;i++) big_buffer[i]*=window[i]; -}; - -void ReverbBandwidth::do_spread(int nfreq,REALTYPE *freq1,REALTYPE *freq2,REALTYPE bandwidth){ - //convert to log spectrum - REALTYPE minfreq=20.0; - REALTYPE maxfreq=0.5*SAMPLE_RATE; - - REALTYPE log_minfreq=log(minfreq); - REALTYPE log_maxfreq=log(maxfreq); - - for (int i=0;i<nfreq;i++){ - REALTYPE freqx=i/(REALTYPE) nfreq; - REALTYPE x=exp(log_minfreq+freqx*(log_maxfreq-log_minfreq))/maxfreq*nfreq; - REALTYPE y=0.0; - int x0=(int)floor(x); if (x0>=nfreq) x0=nfreq-1; - int x1=x0+1; if (x1>=nfreq) x1=nfreq-1; - REALTYPE xp=x-x0; - if (x<nfreq){ - y=freq1[x0]*(1.0-xp)+freq1[x1]*xp; - }; - tmpfreq[i]=y; - }; - - //increase the bandwidth of each harmonic (by smoothing the log spectrum) - int n=2; - REALTYPE a=1.0-pow(2.0,-bandwidth*bandwidth*10.0); - a=pow(a,8192.0/nfreq*n); - - for (int k=0;k<n;k++){ - tmpfreq[0]=0.0; - for (int i=1;i<nfreq;i++){ - tmpfreq[i]=tmpfreq[i-1]*a+tmpfreq[i]*(1.0-a); - }; - tmpfreq[nfreq-1]=0.0; - for (int i=nfreq-2;i>0;i--){ - tmpfreq[i]=tmpfreq[i+1]*a+tmpfreq[i]*(1.0-a); - }; - }; - - freq2[0]=0; - REALTYPE log_maxfreq_d_minfreq=log(maxfreq/minfreq); - for (int i=1;i<nfreq;i++){ - REALTYPE freqx=i/(REALTYPE) nfreq; - REALTYPE x=log((freqx*maxfreq)/minfreq)/log_maxfreq_d_minfreq*nfreq; - REALTYPE y=0.0; - if ((x>0.0)&&(x<nfreq)){ - int x0=(int)floor(x); if (x0>=nfreq) x0=nfreq-1; - int x1=x0+1; if (x1>=nfreq) x1=nfreq-1; - REALTYPE xp=x-x0; - y=tmpfreq[x0]*(1.0-xp)+tmpfreq[x1]*xp; - }; - freq2[i]=y; - }; -}; - - Reverb::Reverb(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) :Effect(insertion_,efxoutl_,efxoutr_,NULL,0) { @@ -269,6 +161,7 @@ void Reverb::out(REALTYPE *smps_l, REALTYPE *smps_r) for (i=0;i<SOUND_BUFFER_SIZE;i++) { inputbuf[i]=(smps_l[i]+smps_r[i])/2.0; }; + if (idelay!=NULL) { for (i=0;i<SOUND_BUFFER_SIZE;i++) { //Initial delay r @@ -276,11 +169,13 @@ void Reverb::out(REALTYPE *smps_l, REALTYPE *smps_r) inputbuf[i]=idelay[idelayk]; idelay[idelayk]=tmp; idelayk++; - if (idelayk>=idelaylen) idelayk=0; + if (idelayk>=idelaylen) { + idelayk=0; + }; }; - }; + }; - if (bandwidth) bandwidth->process(inputbuf); + if (bandwidth) bandwidth->process(SOUND_BUFFER_SIZE,inputbuf); if (lpf!=NULL) lpf->filterout(inputbuf); if (hpf!=NULL) hpf->filterout(inputbuf); @@ -458,11 +353,10 @@ void Reverb::settype(unsigned char Ptype) if (bandwidth) delete bandwidth; bandwidth=NULL; if (Ptype==2){//bandwidth - -#warning sa calculez numarul optim de buffere - bandwidth=new ReverbBandwidth(SOUND_BUFFER_SIZE,32); - - + bandwidth=new Unison(SOUND_BUFFER_SIZE/4+1,0.5); + bandwidth->set_size(50); + bandwidth->set_base_frequency(1.0); +#warning sa schimb size-ul }; }; @@ -479,7 +373,7 @@ void Reverb::setroomsize(const unsigned char &Proomsize) void Reverb::setbandwidth(const unsigned char &Pbandwidth){ this->Pbandwidth=Pbandwidth; - if (bandwidth) bandwidth->set_bandwidth(Pbandwidth/127.0); + if (bandwidth) bandwidth->set_bandwidth(Pbandwidth/127.0*200.0); }; void Reverb::setpreset(unsigned char npreset) diff --git a/src/Effects/Reverb.h b/src/Effects/Reverb.h @@ -27,6 +27,7 @@ #include "../globals.h" #include "../DSP/AnalogFilter.h" #include "../DSP/FFTwrapper.h" +#include "../DSP/Unison.h" #include "Effect.h" #define REV_COMBS 8 @@ -34,122 +35,6 @@ /**Creates Reverberation Effects*/ -class OverlapAdd{//50% overlap - public: - OverlapAdd(int small_buffer_size_,int n_small_buffers_per_half_big_buffer_){ - small_buffer_size=small_buffer_size_; - n_small_buffers_per_half_big_buffer=n_small_buffers_per_half_big_buffer_; - half_big_buffer_size=small_buffer_size*n_small_buffers_per_half_big_buffer; - big_buffer_size=half_big_buffer_size*2; - - new_half_big_buffer_input=new REALTYPE[half_big_buffer_size]; - old_half_big_buffer_input=new REALTYPE[half_big_buffer_size]; - new_half_big_buffer_processed=new REALTYPE[half_big_buffer_size]; - half_big_buffer_output=new REALTYPE[half_big_buffer_size]; - big_buffer=new REALTYPE[big_buffer_size]; - for (int i=0;i<half_big_buffer_size;i++){ - new_half_big_buffer_input[i]=0.0; - old_half_big_buffer_input[i]=0.0; - new_half_big_buffer_processed[i]=0.0; - half_big_buffer_output[i]=0.0; - }; - for (int i=0;i<big_buffer_size;i++){ - big_buffer[i]=0.0; - }; - small_buffer_k=0; - }; - virtual ~OverlapAdd(){ - delete []new_half_big_buffer_input; - delete []old_half_big_buffer_input; - delete []new_half_big_buffer_processed; - delete []half_big_buffer_output; - delete []big_buffer; - }; - - - void process(REALTYPE *small_buffer){ - - int input_start_pos=small_buffer_size*small_buffer_k; - - for (int i=0;i<small_buffer_size;i++){ - new_half_big_buffer_input[input_start_pos+i]=small_buffer[i]; - }; - small_buffer_k++; - if (small_buffer_k>=n_small_buffers_per_half_big_buffer){ - small_buffer_k=0; - process_big_buffer(); - }; - - int output_start_pos=small_buffer_size*small_buffer_k; //check if this is correct - - for (int i=0;i<small_buffer_size;i++){ - small_buffer[i]=half_big_buffer_output[output_start_pos+i]; - }; - - - }; - protected: - int half_big_buffer_size; - int big_buffer_size; - REALTYPE *big_buffer; - - virtual void do_process_big_buffer(){//the resulting buffer must be windowed - for (int i=0;i<big_buffer_size;i++){ - big_buffer[i]*=(1.0-cos(i*M_PI*2.0/big_buffer_size))*0.5; -// big_buffer[i]*=0.5; - }; -// printf("BIG_BUFFER:\n"); for (int i=0;i<big_buffer_size;i++) printf(" %g ",big_buffer[i]); printf("\n\n"); - }; - private: - void process_big_buffer(){ - for (int i=0;i<half_big_buffer_size;i++){ - big_buffer[i]=old_half_big_buffer_input[i]; - big_buffer[i+half_big_buffer_size]=new_half_big_buffer_input[i]; - }; - - do_process_big_buffer();//process input buffer and get windowed buffer - - for (int i=0;i<half_big_buffer_size;i++){ - old_half_big_buffer_input[i]=new_half_big_buffer_input[i]; - }; - -// printf("OUT1:\n"); for (int i=0;i<half_big_buffer_size;i++) printf(" %g,%g ",big_buffer[i],new_half_big_buffer_processed[i]); printf("\n\n"); - for (int i=0;i<half_big_buffer_size;i++){ - half_big_buffer_output[i]=big_buffer[i]+new_half_big_buffer_processed[i]; - new_half_big_buffer_processed[i]=big_buffer[i+half_big_buffer_size]; - }; - - }; - - int small_buffer_size; - int n_small_buffers_per_half_big_buffer; - int small_buffer_k; - - REALTYPE *old_half_big_buffer_input,*new_half_big_buffer_input; - REALTYPE *new_half_big_buffer_processed; - - REALTYPE *half_big_buffer_output; -}; - -class ReverbBandwidth: public OverlapAdd{ - public: - ReverbBandwidth (int small_buffer_size_,int n_small_buffers_per_half_big_buffer_); - ~ReverbBandwidth(); - void do_spread(int nfreq,REALTYPE *freq1,REALTYPE *freq2, REALTYPE bandwidth); - void set_bandwidth(REALTYPE par){ - if (par<0.0) par=0.0; - if (par>1.0) par=1.0; - bandwidth=par; - }; - private: - void do_process_big_buffer(); - FFTwrapper *fft; - FFTFREQS freqs; - REALTYPE *srcfreq,*destfreq,*tmpfreq; - REALTYPE *window; - REALTYPE bandwidth; -}; - class Reverb:public Effect { public: @@ -218,14 +103,14 @@ private: void setbandwidth(const unsigned char &Pbandwidth); REALTYPE pan,erbalance; - //Parametrii 2 + //Parameters int lohidamptype;/**<0=disable,1=highdamp(lowpass),2=lowdamp(highpass)*/ int idelaylen,rdelaylen; int idelayk; REALTYPE lohifb,idelayfb,roomsize,rs;//rs is used to "normalise" the volume according to the roomsize int comblen[REV_COMBS*2]; int aplen[REV_APS*2]; - ReverbBandwidth *bandwidth; + Unison *bandwidth; //Internal Variables diff --git a/src/globals.h b/src/globals.h @@ -184,6 +184,7 @@ extern int OSCIL_SIZE; #define RND (rand()/(RAND_MAX+1.0)) #define ZERO(data,size) {char *data_=(char *) data;for (int i=0;i<size;i++) data_[i]=0;}; +#define ZERO_REALTYPE(data,size) {REALTYPE *data_=(REALTYPE *) data;for (int i=0;i<size;i++) data_[i]=0.0;}; enum ONOFFTYPE {OFF=0,ON=1};