zynaddsubfx

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

commit 35418bd30b28a1eb5bd842f277a4cc0bfeeb44d5
parent cefe2b53d04b1d5de3b51e0f977abcd5d8528619
Author: Paul <nop@nop-desktop.(none)>
Date:   Thu,  1 Oct 2009 23:51:23 +0300

Unison improvements

Diffstat:
MChangeLog | 9+++++++--
Msrc/DSP/Unison.cpp | 31++++++++++++++++++++++++-------
Msrc/DSP/Unison.h | 10++++++----
Msrc/Effects/Reverb.cpp | 31++++++++++++++++---------------
Msrc/Synth/ADnote.cpp | 2+-
5 files changed, 54 insertions(+), 29 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -936,4 +936,10 @@ 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 + +01 Oct 2009 (Paul Nasca) + - Corrected the ADsynth unison LFO rounding function + - Made Unison based on Bandwidth (in cents) parameter + + + diff --git a/src/DSP/Unison.cpp b/src/DSP/Unison.cpp @@ -30,6 +30,7 @@ Unison::Unison(int update_period_samples_,REALTYPE max_delay_sec_){ delay_buffer=new REALTYPE[max_delay]; delay_k=0; base_freq=1.0; + unison_bandwidth_cents=10.0; ZERO_REALTYPE(delay_buffer,max_delay); @@ -60,21 +61,35 @@ void Unison::set_base_frequency(REALTYPE freq){ update_parameters(); }; +void Unison::set_bandwidth(REALTYPE bandwidth){ + if (bandwidth<0) bandwidth=0.0; + if (bandwidth>1200.0) bandwidth=1200.0; + + printf("bandwidth %g\n",bandwidth); +#warning: todo: if bandwidth is too small the audio will be self canceled (because of the sign change of the outputs) + unison_bandwidth_cents=bandwidth; + update_parameters(); +}; + void Unison::update_parameters(){ if (!uv) return; REALTYPE increments_per_second=SAMPLE_RATE/(REALTYPE) update_period_samples; - printf("#%g, %g\n",increments_per_second,base_freq); +// printf("#%g, %g\n",increments_per_second,base_freq); for (int i=0;i<unison_size;i++){ - REALTYPE period=pow(2.0,RND*2.0-1.0)/base_freq; + REALTYPE base=pow(UNISON_FREQ_SPAN,RND*2.0-1.0); + uv[i].relative_amplitude=base; + REALTYPE period=base/base_freq; REALTYPE m=4.0/(period*increments_per_second); if (RND<0.5) m=-m; uv[i].step=m; - printf("%g %g\n",period,m); +// printf("%g %g\n",uv[i].relative_amplitude,period); }; -#warning compute unison_amplitude_samples in functie de centi - unison_amplitude_samples=200.0; + REALTYPE max_speed=pow(2.0,unison_bandwidth_cents/1200.0); + unison_amplitude_samples=0.125*(max_speed-1.0)*SAMPLE_RATE/base_freq; +printf("unison_amplitude_samples %g\n",unison_amplitude_samples); +#warning todo: test if unison_amplitude_samples is to big and reallocate bigger memory if (unison_amplitude_samples>=max_delay-1) unison_amplitude_samples=max_delay-2; update_unison_data(); @@ -130,8 +145,10 @@ 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 newval=1.0+0.5*(vibratto_val+1.0)*unison_amplitude_samples; + REALTYPE vibratto_val=(pos-0.333333333*pos*pos*pos)*1.5;//make the vibratto lfo smoother +#warning I will use relative amplitude, so the delay might be bigger than the whole buffer +#warning I have to enlarge (reallocate) the buffer to make place for the whole delay + REALTYPE newval=1.0+0.5*(vibratto_val+1.0)*unison_amplitude_samples*uv[k].relative_amplitude; if (first_time){ uv[k].realpos1=uv[k].realpos2=newval; diff --git a/src/DSP/Unison.h b/src/DSP/Unison.h @@ -24,6 +24,8 @@ #include <stdlib.h> #include "../globals.h" +#define UNISON_FREQ_SPAN 2.0 +//how much the unison frequencies varies (always >= 1.0) class Unison{ public: @@ -32,8 +34,7 @@ class Unison{ void set_size(int new_size); void set_base_frequency(REALTYPE freq); - void set_bandwidth(REALTYPE bandwidth_cents){ - }; + void set_bandwidth(REALTYPE bandwidth_cents); void process(int bufsize,REALTYPE *inbuf,REALTYPE *outbuf=NULL); @@ -46,14 +47,14 @@ class Unison{ struct UnisonVoice{ 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 + REALTYPE relative_amplitude; REALTYPE lin_fpos,lin_ffreq; UnisonVoice(){ position=RND*1.8-0.9; realpos1=0.0; realpos2=0.0; step=0.0; + relative_amplitude=1.0; }; }*uv; int update_period_samples,update_period_sample_k; @@ -61,6 +62,7 @@ class Unison{ bool first_time; REALTYPE *delay_buffer; REALTYPE unison_amplitude_samples; + REALTYPE unison_bandwidth_cents; }; #endif diff --git a/src/Effects/Reverb.cpp b/src/Effects/Reverb.cpp @@ -353,7 +353,7 @@ void Reverb::settype(unsigned char Ptype) if (bandwidth) delete bandwidth; bandwidth=NULL; if (Ptype==2){//bandwidth - bandwidth=new Unison(SOUND_BUFFER_SIZE/4+1,0.5); + bandwidth=new Unison(SOUND_BUFFER_SIZE/4+1,2.0); bandwidth->set_size(50); bandwidth->set_base_frequency(1.0); #warning sa schimb size-ul @@ -373,7 +373,8 @@ 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*200.0); + REALTYPE v=Pbandwidth/127.0; + if (bandwidth) bandwidth->set_bandwidth(pow(v,2.0)*200.0); }; void Reverb::setpreset(unsigned char npreset) @@ -382,31 +383,31 @@ void Reverb::setpreset(unsigned char npreset) const int NUM_PRESETS=13; unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ //Cathedral1 - {80,64,63,24,0,0,0,85,5,83,1,64,0}, + {80,64,63,24,0,0,0,85,5,83,1,64,20}, //Cathedral2 - {80,64,69,35,0,0,0,127,0,71,0,64,0}, + {80,64,69,35,0,0,0,127,0,71,0,64,20}, //Cathedral3 - {80,64,69,24,0,0,0,127,75,78,1,85,0}, + {80,64,69,24,0,0,0,127,75,78,1,85,20}, //Hall1 - {90,64,51,10,0,0,0,127,21,78,1,64,0}, + {90,64,51,10,0,0,0,127,21,78,1,64,20}, //Hall2 - {90,64,53,20,0,0,0,127,75,71,1,64,0}, + {90,64,53,20,0,0,0,127,75,71,1,64,20}, //Room1 - {100,64,33,0,0,0,0,127,0,106,0,30,0}, + {100,64,33,0,0,0,0,127,0,106,0,30,20}, //Room2 - {100,64,21,26,0,0,0,62,0,77,1,45,0}, + {100,64,21,26,0,0,0,62,0,77,1,45,20}, //Basement - {110,64,14,0,0,0,0,127,5,71,0,25,0}, + {110,64,14,0,0,0,0,127,5,71,0,25,20}, //Tunnel - {85,80,84,20,42,0,0,51,0,78,1,105,0}, + {85,80,84,20,42,0,0,51,0,78,1,105,20}, //Echoed1 - {95,64,26,60,71,0,0,114,0,64,1,64,0}, + {95,64,26,60,71,0,0,114,0,64,1,64,20}, //Echoed2 - {90,64,40,88,71,0,0,114,0,88,1,64,0}, + {90,64,40,88,71,0,0,114,0,88,1,64,20}, //VeryLong1 - {90,64,93,15,0,0,0,114,0,77,0,95,0}, + {90,64,93,15,0,0,0,114,0,77,0,95,20}, //VeryLong2 - {90,64,111,30,0,0,0,114,90,74,1,80,0} + {90,64,111,30,0,0,0,114,90,74,1,80,20} }; if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; diff --git a/src/Synth/ADnote.cpp b/src/Synth/ADnote.cpp @@ -787,7 +787,7 @@ void ADnote::compute_unison_freq_rap(int nvoice){ pos=1.0; step=-step; }; - REALTYPE vibratto_val=pos-0.3*pos*pos*pos;//make the vibratto lfo smoother + REALTYPE vibratto_val=(pos-0.333333333*pos*pos*pos)*1.5;//make the vibratto lfo smoother unison_freq_rap[nvoice][k]=1.0+((unison_base_freq_rap[nvoice][k]-1.0)+vibratto_val*unison_vibratto[nvoice].amplitude)*relbw; unison_vibratto[nvoice].position[k]=pos;