commit 6512c3d04d6843cbb86a35cced936a02cc19439e
parent aa79e53f0be4308b3cf693c029023bebaaa369ca
Author: Paul <nop@nop-desktop.(none)>
Date: Tue, 29 Sep 2009 23:08:06 +0300
Started to rewrite the Reverb's Bandwidth effect (based on a better idea)
Diffstat:
A | src/DSP/Unison.cpp | | | 166 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/DSP/Unison.h | | | 63 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 files changed, 229 insertions(+), 0 deletions(-)
diff --git a/src/DSP/Unison.cpp b/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 <math.h>
+#include <stdio.h>
+#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<unison_size;i++){
+ REALTYPE period=pow(2.0,RND*2.0-1.0)/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);
+ };
+
+#warning compute unison_amplitude_samples in functie de centi
+ unison_amplitude_samples=20.0;
+
+ if (unison_amplitude_samples>=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<bufsize;i++){
+ if ((update_period_sample_k++)>=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<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
+ int posi;
+ REALTYPE posf;
+ 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];
+ };
+ 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<unison_size;k++){
+ REALTYPE pos=uv[k].position;
+ REALTYPE step=uv[k].step;
+ pos+=step;
+ if (pos<=-1.0) {
+ pos=-1.0;
+ step=-step;
+ };
+ if (pos>=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<bufsize;i++) printf("%.3g ",out[i]);printf("\n");
+
+ return 1;
+};
+*/
diff --git a/src/DSP/Unison.h b/src/DSP/Unison.h
@@ -0,0 +1,63 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ Unison.h - 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
+*/
+
+#ifndef UNISON_H
+#define UNISON_H
+#include "../globals.h"
+
+
+class Unison{
+ public:
+ Unison(int update_period_samples_,REALTYPE max_delay_sec_);
+ ~Unison();
+
+ void set_size(int new_size);
+ void set_base_frequency(REALTYPE freq);
+
+ void process(int bufsize,REALTYPE *inbuf,REALTYPE *outbuf=NULL);
+
+ private:
+ void update_parameters();
+ void update_unison_data();
+
+ int unison_size;
+ REALTYPE base_freq;
+ 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 lin_fpos,lin_ffreq;
+ UnisonVoice(){
+ position=RND*1.8-0.9;
+ realpos1=0.0;
+ realpos2=0.0;
+ step=0.0;
+ };
+ }*uv;
+ int update_period_samples,update_period_sample_k;
+ int max_delay,delay_k;
+ bool first_time;
+ REALTYPE *delay_buffer;
+ REALTYPE unison_amplitude_samples;
+};
+#endif
+