Started to rewrite the Reverb's Bandwidth effect (based on a better idea)

(cherry picked from commit 6512c3d04d6843cbb86a35cced936a02cc19439e)
This commit is contained in:
Paul
2009-09-29 23:08:30 +03:00
committed by Tobias Doerffel
parent bbe967e3a0
commit e39d7b429c
2 changed files with 229 additions and 0 deletions

View File

@@ -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;
};
*/

View File

@@ -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