diff --git a/plugins/zynaddsubfx/src/DSP/Unison.cpp b/plugins/zynaddsubfx/src/DSP/Unison.cpp new file mode 100644 index 000000000..2a273671c --- /dev/null +++ b/plugins/zynaddsubfx/src/DSP/Unison.cpp @@ -0,0 +1,166 @@ +/* + ZynAddSubFX - a software synthesizer + + Unison.cpp - Unison effect (multivoice chorus) + Copyright (C) 2002-2009 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include "Unison.h" + +Unison::Unison(int update_period_samples_,REALTYPE max_delay_sec_){ + update_period_samples=update_period_samples_; + max_delay=(int)(max_delay_sec_*(REALTYPE)SAMPLE_RATE+1); + if (max_delay<10) max_delay=10; + delay_buffer=new REALTYPE[max_delay]; + delay_k=0; + base_freq=1.0; + + ZERO_REALTYPE(delay_buffer,max_delay); + + uv=NULL; + update_period_sample_k=0; + first_time=0; + + set_size(1); + +}; + +Unison::~Unison(){ + delete []delay_buffer; + if (uv) delete []uv; +}; + +void Unison::set_size(int new_size){ + if (new_size<1) new_size=1; + unison_size=new_size; + if (uv) delete []uv; + uv=new UnisonVoice[unison_size]; + first_time=true; + update_parameters(); +}; + +void Unison::set_base_frequency(REALTYPE freq){ + base_freq=freq; + 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); + for (int i=0;i=max_delay-1) unison_amplitude_samples=max_delay-2; + + update_unison_data(); +}; + +void Unison::process(int bufsize,REALTYPE *inbuf,REALTYPE *outbuf){ + if (!uv) return; + if (!outbuf) outbuf=inbuf; + + REALTYPE volume=1.0/sqrt(unison_size); + REALTYPE xpos_step=1.0/(REALTYPE) update_period_samples; + REALTYPE xpos=(REALTYPE) update_period_sample_k*xpos_step; + for (int i=0;i=update_period_samples) { + update_unison_data(); + update_period_sample_k=0; + xpos=0.0; + }; + xpos+=xpos_step; + REALTYPE in=inbuf[i],out=0.0; + + + for (int k=0;k=max_delay) posi-=max_delay; + posf=pos-floor(pos); + out+=(1.0-posf)*delay_buffer[posi]+posf*delay_buffer[posi+1]; + }; + outbuf[i]=out*volume; +// printf("%d %g\n",i,outbuf[i]); + delay_buffer[delay_k]=in; + if ((++delay_k)>=max_delay) delay_k=0; + }; +}; + +void Unison::update_unison_data(){ + if (!uv) return; + + for (int k=0;k=1.0){ + 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 newval=1.0+0.5*(vibratto_val+1.0)*unison_amplitude_samples; + + if (first_time){ + uv[k].realpos1=uv[k].realpos2=newval; + }else{ + uv[k].realpos1=uv[k].realpos2; + uv[k].realpos2=newval; + }; + + uv[k].position=pos; + uv[k].step=step; + }; + 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