zynaddsubfx

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

commit 6c127c360a86633fdc5d8b4ea340bb1157112cb0
parent 7f1a38a479c98ad795d1fe489db0a756ec72cdef
Author: Harald Hvaal <[email protected]>
Date:   Tue, 23 Jun 2009 22:25:12 +0900

Ran astyle on the whole codebase, with the following command:
find -name \*.C -or -name \*.cpp -or -name \*.h | xargs astyle --style=kr -l

Diffstat:
Msrc/Controls/Control.C | 8++++----
Msrc/Controls/Control.h | 56++++++++++++++++++++++++++++----------------------------
Msrc/Controls/DelayCtl.C | 6+++---
Msrc/Controls/DelayCtl.h | 24++++++++++++------------
Msrc/DSP/AnalogFilter.C | 511+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/DSP/AnalogFilter.h | 25+++++++++++++------------
Msrc/DSP/FFTwrapper.C | 34+++++++++++++++++++---------------
Msrc/DSP/FFTwrapper.h | 39++++++++++++++++++++-------------------
Msrc/DSP/Filter.C | 54++++++++++++++++++++++++++++++++----------------------
Msrc/DSP/Filter.h | 13+++++++------
Msrc/DSP/Filter_.h | 15++++++++-------
Msrc/DSP/FormantFilter.C | 137+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/DSP/FormantFilter.h | 25+++++++++++++------------
Msrc/DSP/SVFilter.C | 122+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Msrc/DSP/SVFilter.h | 23++++++++++++-----------
Msrc/Effects/Alienwah.C | 230++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/Effects/Alienwah.h | 93++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Effects/Chorus.C | 332++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/Effects/Chorus.h | 155++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Effects/Distorsion.C | 473++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/Effects/Distorsion.h | 71++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/Effects/DynamicFilter.C | 400+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/Effects/DynamicFilter.h | 73+++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/Effects/EQ.C | 201++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/Effects/EQ.h | 51++++++++++++++++++++++++++-------------------------
Msrc/Effects/Echo.C | 156++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Msrc/Effects/Echo.h | 203++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Effects/Effect.C | 10+++++-----
Msrc/Effects/Effect.h | 121++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Effects/EffectLFO.C | 60++++++++++++++++++++++++++++++++++--------------------------
Msrc/Effects/EffectLFO.h | 13+++++++------
Msrc/Effects/EffectMgr.C | 289++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/Effects/EffectMgr.h | 105++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Effects/Phaser.C | 262++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/Effects/Phaser.h | 83++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Effects/Reverb.C | 401+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/Effects/Reverb.h | 31++++++++++++++++---------------
Msrc/Input/ALSAMidiIn.C | 90+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/Input/ALSAMidiIn.h | 33+++++++++++++++++----------------
Msrc/Input/MidiIn.C | 115+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Msrc/Input/MidiIn.h | 31++++++++++++++++---------------
Msrc/Input/NULLMidiIn.C | 13++++++++-----
Msrc/Input/NULLMidiIn.h | 33+++++++++++++++++----------------
Msrc/Input/OSSMidiIn.C | 35++++++++++++++++++++---------------
Msrc/Input/OSSMidiIn.h | 35++++++++++++++++++-----------------
Msrc/Input/WINMidiIn.C | 86+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/Input/WINMidiIn.h | 4++--
Msrc/Misc/Bank.C | 530+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/Misc/Bank.h | 135++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Misc/Config.C | 320+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/Misc/Config.h | 79++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Misc/Control.h | 122++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/Misc/Dump.C | 78+++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/Misc/Dump.h | 65+++++++++++++++++++++++++++++++++--------------------------------
Msrc/Misc/LASHClient.C | 121+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/Misc/LASHClient.h | 57+++++++++++++++++++++++++++++----------------------------
Msrc/Misc/Master.C | 865+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/Misc/Master.h | 247++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Misc/Microtonal.C | 520++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/Misc/Microtonal.h | 173++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Misc/Part.C | 1458+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/Misc/Part.h | 279++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Misc/Stereo.C | 8++++----
Msrc/Misc/Stereo.h | 63++++++++++++++++++++++++++++++++++++++++-----------------------
Msrc/Misc/Util.C | 66++++++++++++++++++++++++++++++++++++++----------------------------
Msrc/Misc/Util.h | 4++--
Msrc/Misc/XMLwrapper.C | 392+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/Misc/XMLwrapper.h | 279++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Output/DSSIaudiooutput.C | 249+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/Output/DSSIaudiooutput.h | 10+++++-----
Msrc/Output/JACK_RTaudiooutput.C | 156++++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/Output/JACKaudiooutput.C | 172+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/Output/JACKaudiooutput.h | 4++--
Msrc/Output/OSSaudiooutput.C | 41+++++++++++++++++++++++------------------
Msrc/Output/OSSaudiooutput.h | 37+++++++++++++++++++------------------
Msrc/Output/PAaudiooutput.C | 27+++++++++++++++------------
Msrc/Output/PAaudiooutput.h | 4++--
Msrc/Output/Recorder.C | 47++++++++++++++++++++++++++++-------------------
Msrc/Output/Recorder.h | 51++++++++++++++++++++++++++-------------------------
Msrc/Output/VSTaudiooutput.C | 40+++++++++++++++++++++++-----------------
Msrc/Output/VSTaudiooutput.h | 47++++++++++++++++++++++++-----------------------
Msrc/Output/WAVaudiooutput.C | 28+++++++++++++++++-----------
Msrc/Output/WAVaudiooutput.h | 35++++++++++++++++++-----------------
Msrc/Params/ADnoteParameters.C | 773++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Params/ADnoteParameters.h | 489++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Params/Controller.C | 178++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/Params/Controller.h | 223++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Params/EnvelopeParams.C | 196++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Msrc/Params/EnvelopeParams.h | 99++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Params/FilterParams.C | 322++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/Params/FilterParams.h | 139++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Params/LFOParams.C | 38+++++++++++++++++++++++---------------
Msrc/Params/LFOParams.h | 65+++++++++++++++++++++++++++++++++--------------------------------
Msrc/Params/PADnoteParameters.C | 888+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/Params/PADnoteParameters.h | 259++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Params/Presets.C | 101+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/Params/Presets.h | 55++++++++++++++++++++++++++++---------------------------
Msrc/Params/PresetsStore.C | 164++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/Params/PresetsStore.h | 67++++++++++++++++++++++++++++++++++---------------------------------
Msrc/Params/SUBnoteParameters.C | 257++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Params/SUBnoteParameters.h | 143++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Samples/AuSample.C | 8++++----
Msrc/Samples/AuSample.h | 12++++++------
Msrc/Samples/FqSample.C | 8++++----
Msrc/Samples/FqSample.h | 16++++++++--------
Msrc/Samples/Sample.C | 40++++++++++++++++++----------------------
Msrc/Samples/Sample.h | 63++++++++++++++++++++++++++++++++++++---------------------------
Msrc/Seq/MIDIEvents.C | 39+++++++++++++++++++++++----------------
Msrc/Seq/MIDIEvents.h | 41+++++++++++++++++++++--------------------
Msrc/Seq/MIDIFile.C | 303++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/Seq/MIDIFile.h | 123++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Seq/Sequencer.C | 117+++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/Seq/Sequencer.h | 117++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Synth/ADnote.C | 1698+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/Synth/ADnote.h | 317++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Synth/Envelope.C | 141+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/Synth/Envelope.h | 13+++++++------
Msrc/Synth/LFO.C | 138+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/Synth/LFO.h | 17+++++++++--------
Msrc/Synth/OscilGen.C | 1404+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/Synth/OscilGen.h | 287++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Synth/PADnote.C | 647++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Synth/PADnote.h | 183++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Synth/Resonance.C | 162+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Msrc/Synth/Resonance.h | 49+++++++++++++++++++++++++------------------------
Msrc/Synth/SUBnote.C | 743+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/Synth/SUBnote.h | 163++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Tests/EchoTest.h | 173+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/Tests/SampleTest.h | 91+++++++++++++++++++++++++++++++++++++------------------------------------------
Msrc/globals.h | 33+++++++++++++++++----------------
Msrc/main.C | 685+++++++++++++++++++++++++++++++++++++++++--------------------------------------
131 files changed, 12910 insertions(+), 11566 deletions(-)

diff --git a/src/Controls/Control.C b/src/Controls/Control.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Control.C - Control base class Copyright (C) 2009-2009 Mark McCurry Author: Mark McCurry 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 + 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, @@ -22,7 +22,7 @@ #include "Control.h" Control::Control(char ndefaultval) - :defaultval(ndefaultval),lockqueue(-1),locked(false) + :defaultval(ndefaultval),lockqueue(-1),locked(false) {} void Control::lock() @@ -33,7 +33,7 @@ void Control::lock() void Control::ulock() { - if(locked&&lockqueue>=0) + if (locked&&lockqueue>=0) setmVal(lockqueue); locked=false; } diff --git a/src/Controls/Control.h b/src/Controls/Control.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Control.h - Control base class Copyright (C) 2009-2009 Mark McCurry Author: Mark McCurry 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 + 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, @@ -25,33 +25,33 @@ /**A control for a parameter within the program*/ class Control { - public: - Control(char ndefaultval);/**\todo create proper initialization list*/ - ~Control(){}; - /**Return the string, which represents the internal value - * @return a string representation of the current value*/ - virtual std::string getString()const=0; - /**Set the Control to the given value - * @param nval A number 0-127*/ - virtual void setmVal(char nval)=0; - /**Return the midi value (aka the char) - * @return the current value*/ - virtual char getmVal()const=0; - /** Will lock the Control until it is ulocked - * - * Locking a Control will Stop it from having - * its internal data altered*/ - void lock(); - /** Will unlock the Control - * - * This will also update the Control - * if something attempted to update it while it was locked*/ - void ulock(); - private: - char defaultval;/**<Default value of the Control*/ - char lockqueue; /**<The value is that is stored, while the Control is locked +public: + Control(char ndefaultval);/**\todo create proper initialization list*/ + ~Control() {}; + /**Return the string, which represents the internal value + * @return a string representation of the current value*/ + virtual std::string getString()const=0; + /**Set the Control to the given value + * @param nval A number 0-127*/ + virtual void setmVal(char nval)=0; + /**Return the midi value (aka the char) + * @return the current value*/ + virtual char getmVal()const=0; + /** Will lock the Control until it is ulocked + * + * Locking a Control will Stop it from having + * its internal data altered*/ + void lock(); + /** Will unlock the Control + * + * This will also update the Control + * if something attempted to update it while it was locked*/ + void ulock(); +private: + char defaultval;/**<Default value of the Control*/ + char lockqueue; /**<The value is that is stored, while the Control is locked * and something attempts to update it*/ - bool locked;//upgrade this to a integer lock level if problems occur + bool locked;//upgrade this to a integer lock level if problems occur }; #endif diff --git a/src/Controls/DelayCtl.C b/src/Controls/DelayCtl.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + DelayCtl.C - Control For Delays Copyright (C) 2009-2009 Mark McCurry Author: Mark McCurry 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 + 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, @@ -23,7 +23,7 @@ #include <sstream> DelayCtl::DelayCtl() - :Control(64),value(64/127.0*1.5){} /**\todo finishme*/ + :Control(64),value(64/127.0*1.5) {} /**\todo finishme*/ std::string DelayCtl::getString() const { diff --git a/src/Controls/DelayCtl.h b/src/Controls/DelayCtl.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + DelayCtl.h - Control For Delays Copyright (C) 2009-2009 Mark McCurry Author: Mark McCurry 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 + 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, @@ -24,19 +24,19 @@ #ifndef DELAYCTL_H #define DELAYCTL_H /**A Control for Delays - * + * * Will vary from 0 seconds to 1.5 seconds*/ class DelayCtl:public Control { - public: - DelayCtl(); - ~DelayCtl(){}; - std::string getString() const; - void setmVal(char nval); - char getmVal() const; - float getiVal() const; - private: - float value; +public: + DelayCtl(); + ~DelayCtl() {}; + std::string getString() const; + void setmVal(char nval); + char getmVal() const; + float getiVal() const; +private: + float value; }; #endif diff --git a/src/DSP/AnalogFilter.C b/src/DSP/AnalogFilter.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + AnalogFilter.C - Several analog filters (lowpass, highpass...) Copyright (C) 2002-2005 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 + 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, @@ -24,11 +24,14 @@ #include <stdio.h> #include "AnalogFilter.h" -AnalogFilter::AnalogFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages){ +AnalogFilter::AnalogFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages) +{ stages=Fstages; - for (int i=0;i<3;i++){ - oldc[i]=0.0;oldd[i]=0.0; - c[i]=0.0;d[i]=0.0; + for (int i=0;i<3;i++) { + oldc[i]=0.0; + oldd[i]=0.0; + c[i]=0.0; + d[i]=0.0; }; type=Ftype; freq=Ffreq; @@ -37,27 +40,33 @@ AnalogFilter::AnalogFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsig if (stages>=MAX_FILTER_STAGES) stages=MAX_FILTER_STAGES; cleanup(); firsttime=0; - abovenq=0;oldabovenq=0; + abovenq=0; + oldabovenq=0; setfreq_and_q(Ffreq,Fq); firsttime=1; d[0]=0;//this is not used outgain=1.0; }; -AnalogFilter::~AnalogFilter(){ +AnalogFilter::~AnalogFilter() +{ }; -void AnalogFilter::cleanup(){ - for (int i=0;i<MAX_FILTER_STAGES+1;i++){ - x[i].c1=0.0;x[i].c2=0.0; - y[i].c1=0.0;y[i].c2=0.0; - oldx[i]=x[i]; - oldy[i]=y[i]; +void AnalogFilter::cleanup() +{ + for (int i=0;i<MAX_FILTER_STAGES+1;i++) { + x[i].c1=0.0; + x[i].c2=0.0; + y[i].c1=0.0; + y[i].c2=0.0; + oldx[i]=x[i]; + oldy[i]=y[i]; }; needsinterpolation=0; }; -void AnalogFilter::computefiltercoefs(){ +void AnalogFilter::computefiltercoefs() +{ REALTYPE tmp; REALTYPE omega,sn,cs,alpha,beta; int zerocoefs=0;//this is used if the freq is too high @@ -65,199 +74,230 @@ void AnalogFilter::computefiltercoefs(){ //do not allow frequencies bigger than samplerate/2 REALTYPE freq=this->freq; if (freq>(SAMPLE_RATE/2-500.0)) { - freq=SAMPLE_RATE/2-500.0; - zerocoefs=1; + freq=SAMPLE_RATE/2-500.0; + zerocoefs=1; }; if (freq<0.1) freq=0.1; //do not allow bogus Q if (q<0.0) q=0.0; REALTYPE tmpq,tmpgain; if (stages==0) { - tmpq=q; - tmpgain=gain; + tmpq=q; + tmpgain=gain; } else { tmpq=(q>1.0 ? pow(q,1.0/(stages+1)) : q); - tmpgain=pow(gain,1.0/(stages+1)); + tmpgain=pow(gain,1.0/(stages+1)); }; - - //most of theese are implementations of + + //most of theese are implementations of //the "Cookbook formulae for audio EQ" by Robert Bristow-Johnson //The original location of the Cookbook is: //http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt - switch(type){ - case 0://LPF 1 pole - if (zerocoefs==0) tmp=exp(-2.0*PI*freq/SAMPLE_RATE); - else tmp=0.0; - c[0]=1.0-tmp;c[1]=0.0;c[2]=0.0; - d[1]=tmp;d[2]=0.0; - order=1; - break; - case 1://HPF 1 pole - if (zerocoefs==0) tmp=exp(-2.0*PI*freq/SAMPLE_RATE); - else tmp=0.0; - c[0]=(1.0+tmp)/2.0;c[1]=-(1.0+tmp)/2.0;c[2]=0.0; - d[1]=tmp;d[2]=0.0; - order=1; - break; - case 2://LPF 2 poles - if (zerocoefs==0){ - omega=2*PI*freq/SAMPLE_RATE; - sn=sin(omega); - cs=cos(omega); - alpha=sn/(2*tmpq); - tmp=1+alpha; - c[0]=(1.0-cs)/2.0/tmp; - c[1]=(1.0-cs)/tmp; - c[2]=(1.0-cs)/2.0/tmp; - d[1]=-2*cs/tmp*(-1); - d[2]=(1-alpha)/tmp*(-1); - } else { - c[0]=1.0;c[1]=0.0;c[2]=0.0; - d[1]=0.0;d[2]=0.0; - }; - order=2; - break; - case 3://HPF 2 poles - if (zerocoefs==0){ - omega=2*PI*freq/SAMPLE_RATE; - sn=sin(omega); - cs=cos(omega); - alpha=sn/(2*tmpq); - tmp=1+alpha; - c[0]=(1.0+cs)/2.0/tmp; - c[1]=-(1.0+cs)/tmp; - c[2]=(1.0+cs)/2.0/tmp; - d[1]=-2*cs/tmp*(-1); - d[2]=(1-alpha)/tmp*(-1); - } else { - c[0]=0.0;c[1]=0.0;c[2]=0.0; - d[1]=0.0;d[2]=0.0; - }; - order=2; - break; - case 4://BPF 2 poles - if (zerocoefs==0){ - omega=2*PI*freq/SAMPLE_RATE; - sn=sin(omega); - cs=cos(omega); - alpha=sn/(2*tmpq); - tmp=1+alpha; - c[0]=alpha/tmp*sqrt(tmpq+1); - c[1]=0; - c[2]=-alpha/tmp*sqrt(tmpq+1); - d[1]=-2*cs/tmp*(-1); - d[2]=(1-alpha)/tmp*(-1); - } else { - c[0]=0.0;c[1]=0.0;c[2]=0.0; - d[1]=0.0;d[2]=0.0; - }; - order=2; - break; - case 5://NOTCH 2 poles - if (zerocoefs==0){ - omega=2*PI*freq/SAMPLE_RATE; - sn=sin(omega); - cs=cos(omega); - alpha=sn/(2*sqrt(tmpq)); - tmp=1+alpha; - c[0]=1/tmp; - c[1]=-2*cs/tmp; - c[2]=1/tmp; - d[1]=-2*cs/tmp*(-1); - d[2]=(1-alpha)/tmp*(-1); - } else { - c[0]=1.0;c[1]=0.0;c[2]=0.0; - d[1]=0.0;d[2]=0.0; - }; - order=2; - break; - case 6://PEAK (2 poles) - if (zerocoefs==0){ - omega=2*PI*freq/SAMPLE_RATE; - sn=sin(omega); - cs=cos(omega); - tmpq*=3.0; - alpha=sn/(2*tmpq); - tmp=1+alpha/tmpgain; - c[0]=(1.0+alpha*tmpgain)/tmp; - c[1]=(-2.0*cs)/tmp; - c[2]=(1.0-alpha*tmpgain)/tmp; - d[1]=-2*cs/tmp*(-1); - d[2]=(1-alpha/tmpgain)/tmp*(-1); - } else { - c[0]=1.0;c[1]=0.0;c[2]=0.0; - d[1]=0.0;d[2]=0.0; - }; - order=2; - break; - case 7://Low Shelf - 2 poles - if (zerocoefs==0){ - omega=2*PI*freq/SAMPLE_RATE; - sn=sin(omega); - cs=cos(omega); - tmpq=sqrt(tmpq); - alpha=sn/(2*tmpq); - beta=sqrt(tmpgain)/tmpq; - tmp=(tmpgain+1.0)+(tmpgain-1.0)*cs+beta*sn; - - c[0]=tmpgain*((tmpgain+1.0)-(tmpgain-1.0)*cs+beta*sn)/tmp; - c[1]=2.0*tmpgain*((tmpgain-1.0)-(tmpgain+1.0)*cs)/tmp; - c[2]=tmpgain*((tmpgain+1.0)-(tmpgain-1.0)*cs-beta*sn)/tmp; - d[1]=-2.0*((tmpgain-1.0)+(tmpgain+1.0)*cs)/tmp*(-1); - d[2]=((tmpgain+1.0)+(tmpgain-1.0)*cs-beta*sn)/tmp*(-1); - } else { - c[0]=tmpgain;c[1]=0.0;c[2]=0.0; - d[1]=0.0;d[2]=0.0; - }; - order=2; - break; - case 8://High Shelf - 2 poles - if (zerocoefs==0){ - omega=2*PI*freq/SAMPLE_RATE; - sn=sin(omega); - cs=cos(omega); - tmpq=sqrt(tmpq); - alpha=sn/(2*tmpq); - beta=sqrt(tmpgain)/tmpq; - tmp=(tmpgain+1.0)-(tmpgain-1.0)*cs+beta*sn; - - c[0]=tmpgain*((tmpgain+1.0)+(tmpgain-1.0)*cs+beta*sn)/tmp; - c[1]=-2.0*tmpgain*((tmpgain-1.0)+(tmpgain+1.0)*cs)/tmp; - c[2]=tmpgain*((tmpgain+1.0)+(tmpgain-1.0)*cs-beta*sn)/tmp; - d[1]=2.0*((tmpgain-1.0)-(tmpgain+1.0)*cs)/tmp*(-1); - d[2]=((tmpgain+1.0)-(tmpgain-1.0)*cs-beta*sn)/tmp*(-1); - } else { - c[0]=1.0;c[1]=0.0;c[2]=0.0; - d[1]=0.0;d[2]=0.0; - }; - order=2; - break; - default://wrong type - type=0; - computefiltercoefs(); - break; + switch (type) { + case 0://LPF 1 pole + if (zerocoefs==0) tmp=exp(-2.0*PI*freq/SAMPLE_RATE); + else tmp=0.0; + c[0]=1.0-tmp; + c[1]=0.0; + c[2]=0.0; + d[1]=tmp; + d[2]=0.0; + order=1; + break; + case 1://HPF 1 pole + if (zerocoefs==0) tmp=exp(-2.0*PI*freq/SAMPLE_RATE); + else tmp=0.0; + c[0]=(1.0+tmp)/2.0; + c[1]=-(1.0+tmp)/2.0; + c[2]=0.0; + d[1]=tmp; + d[2]=0.0; + order=1; + break; + case 2://LPF 2 poles + if (zerocoefs==0) { + omega=2*PI*freq/SAMPLE_RATE; + sn=sin(omega); + cs=cos(omega); + alpha=sn/(2*tmpq); + tmp=1+alpha; + c[0]=(1.0-cs)/2.0/tmp; + c[1]=(1.0-cs)/tmp; + c[2]=(1.0-cs)/2.0/tmp; + d[1]=-2*cs/tmp*(-1); + d[2]=(1-alpha)/tmp*(-1); + } else { + c[0]=1.0; + c[1]=0.0; + c[2]=0.0; + d[1]=0.0; + d[2]=0.0; + }; + order=2; + break; + case 3://HPF 2 poles + if (zerocoefs==0) { + omega=2*PI*freq/SAMPLE_RATE; + sn=sin(omega); + cs=cos(omega); + alpha=sn/(2*tmpq); + tmp=1+alpha; + c[0]=(1.0+cs)/2.0/tmp; + c[1]=-(1.0+cs)/tmp; + c[2]=(1.0+cs)/2.0/tmp; + d[1]=-2*cs/tmp*(-1); + d[2]=(1-alpha)/tmp*(-1); + } else { + c[0]=0.0; + c[1]=0.0; + c[2]=0.0; + d[1]=0.0; + d[2]=0.0; + }; + order=2; + break; + case 4://BPF 2 poles + if (zerocoefs==0) { + omega=2*PI*freq/SAMPLE_RATE; + sn=sin(omega); + cs=cos(omega); + alpha=sn/(2*tmpq); + tmp=1+alpha; + c[0]=alpha/tmp*sqrt(tmpq+1); + c[1]=0; + c[2]=-alpha/tmp*sqrt(tmpq+1); + d[1]=-2*cs/tmp*(-1); + d[2]=(1-alpha)/tmp*(-1); + } else { + c[0]=0.0; + c[1]=0.0; + c[2]=0.0; + d[1]=0.0; + d[2]=0.0; + }; + order=2; + break; + case 5://NOTCH 2 poles + if (zerocoefs==0) { + omega=2*PI*freq/SAMPLE_RATE; + sn=sin(omega); + cs=cos(omega); + alpha=sn/(2*sqrt(tmpq)); + tmp=1+alpha; + c[0]=1/tmp; + c[1]=-2*cs/tmp; + c[2]=1/tmp; + d[1]=-2*cs/tmp*(-1); + d[2]=(1-alpha)/tmp*(-1); + } else { + c[0]=1.0; + c[1]=0.0; + c[2]=0.0; + d[1]=0.0; + d[2]=0.0; + }; + order=2; + break; + case 6://PEAK (2 poles) + if (zerocoefs==0) { + omega=2*PI*freq/SAMPLE_RATE; + sn=sin(omega); + cs=cos(omega); + tmpq*=3.0; + alpha=sn/(2*tmpq); + tmp=1+alpha/tmpgain; + c[0]=(1.0+alpha*tmpgain)/tmp; + c[1]=(-2.0*cs)/tmp; + c[2]=(1.0-alpha*tmpgain)/tmp; + d[1]=-2*cs/tmp*(-1); + d[2]=(1-alpha/tmpgain)/tmp*(-1); + } else { + c[0]=1.0; + c[1]=0.0; + c[2]=0.0; + d[1]=0.0; + d[2]=0.0; + }; + order=2; + break; + case 7://Low Shelf - 2 poles + if (zerocoefs==0) { + omega=2*PI*freq/SAMPLE_RATE; + sn=sin(omega); + cs=cos(omega); + tmpq=sqrt(tmpq); + alpha=sn/(2*tmpq); + beta=sqrt(tmpgain)/tmpq; + tmp=(tmpgain+1.0)+(tmpgain-1.0)*cs+beta*sn; + + c[0]=tmpgain*((tmpgain+1.0)-(tmpgain-1.0)*cs+beta*sn)/tmp; + c[1]=2.0*tmpgain*((tmpgain-1.0)-(tmpgain+1.0)*cs)/tmp; + c[2]=tmpgain*((tmpgain+1.0)-(tmpgain-1.0)*cs-beta*sn)/tmp; + d[1]=-2.0*((tmpgain-1.0)+(tmpgain+1.0)*cs)/tmp*(-1); + d[2]=((tmpgain+1.0)+(tmpgain-1.0)*cs-beta*sn)/tmp*(-1); + } else { + c[0]=tmpgain; + c[1]=0.0; + c[2]=0.0; + d[1]=0.0; + d[2]=0.0; + }; + order=2; + break; + case 8://High Shelf - 2 poles + if (zerocoefs==0) { + omega=2*PI*freq/SAMPLE_RATE; + sn=sin(omega); + cs=cos(omega); + tmpq=sqrt(tmpq); + alpha=sn/(2*tmpq); + beta=sqrt(tmpgain)/tmpq; + tmp=(tmpgain+1.0)-(tmpgain-1.0)*cs+beta*sn; + + c[0]=tmpgain*((tmpgain+1.0)+(tmpgain-1.0)*cs+beta*sn)/tmp; + c[1]=-2.0*tmpgain*((tmpgain-1.0)+(tmpgain+1.0)*cs)/tmp; + c[2]=tmpgain*((tmpgain+1.0)+(tmpgain-1.0)*cs-beta*sn)/tmp; + d[1]=2.0*((tmpgain-1.0)-(tmpgain+1.0)*cs)/tmp*(-1); + d[2]=((tmpgain+1.0)-(tmpgain-1.0)*cs-beta*sn)/tmp*(-1); + } else { + c[0]=1.0; + c[1]=0.0; + c[2]=0.0; + d[1]=0.0; + d[2]=0.0; + }; + order=2; + break; + default://wrong type + type=0; + computefiltercoefs(); + break; }; }; -void AnalogFilter::setfreq(REALTYPE frequency){ +void AnalogFilter::setfreq(REALTYPE frequency) +{ if (frequency<0.1) frequency=0.1; - REALTYPE rap=freq/frequency;if (rap<1.0) rap=1.0/rap; - - oldabovenq=abovenq;abovenq=frequency>(SAMPLE_RATE/2-500.0); - + REALTYPE rap=freq/frequency; + if (rap<1.0) rap=1.0/rap; + + oldabovenq=abovenq; + abovenq=frequency>(SAMPLE_RATE/2-500.0); + int nyquistthresh=(abovenq^oldabovenq); - if ((rap>3.0)||(nyquistthresh!=0)){//if the frequency is changed fast, it needs interpolation (now, filter and coeficients backup) - for (int i=0;i<3;i++){ - oldc[i]=c[i];oldd[i]=d[i]; - }; - for (int i=0;i<MAX_FILTER_STAGES+1;i++){ - oldx[i]=x[i]; - oldy[i]=y[i]; - }; - if (firsttime==0) needsinterpolation=1; + if ((rap>3.0)||(nyquistthresh!=0)) {//if the frequency is changed fast, it needs interpolation (now, filter and coeficients backup) + for (int i=0;i<3;i++) { + oldc[i]=c[i]; + oldd[i]=d[i]; + }; + for (int i=0;i<MAX_FILTER_STAGES+1;i++) { + oldx[i]=x[i]; + oldy[i]=y[i]; + }; + if (firsttime==0) needsinterpolation=1; }; freq=frequency; computefiltercoefs(); @@ -265,92 +305,101 @@ void AnalogFilter::setfreq(REALTYPE frequency){ }; -void AnalogFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_){ +void AnalogFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_) +{ q=q_; setfreq(frequency); }; -void AnalogFilter::setq(REALTYPE q_){ +void AnalogFilter::setq(REALTYPE q_) +{ q=q_; computefiltercoefs(); }; -void AnalogFilter::settype(int type_){ +void AnalogFilter::settype(int type_) +{ type=type_; computefiltercoefs(); }; -void AnalogFilter::setgain(REALTYPE dBgain){ +void AnalogFilter::setgain(REALTYPE dBgain) +{ gain=dB2rap(dBgain); computefiltercoefs(); }; -void AnalogFilter::setstages(int stages_){ +void AnalogFilter::setstages(int stages_) +{ if (stages_>=MAX_FILTER_STAGES) stages_=MAX_FILTER_STAGES-1; stages=stages_; cleanup(); computefiltercoefs(); }; -void AnalogFilter::singlefilterout(REALTYPE *smp,fstage &x,fstage &y,REALTYPE *c,REALTYPE *d){ +void AnalogFilter::singlefilterout(REALTYPE *smp,fstage &x,fstage &y,REALTYPE *c,REALTYPE *d) +{ int i; REALTYPE y0; if (order==1) {//First order filter - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - y0=smp[i]*c[0]+x.c1*c[1]+y.c1*d[1]; - y.c1=y0; - x.c1=smp[i]; - //output - smp[i]=y0; - }; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + y0=smp[i]*c[0]+x.c1*c[1]+y.c1*d[1]; + y.c1=y0; + x.c1=smp[i]; + //output + smp[i]=y0; + }; }; if (order==2) {//Second order filter - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - y0=smp[i]*c[0]+x.c1*c[1]+x.c2*c[2]+y.c1*d[1]+y.c2*d[2]; - y.c2=y.c1; - y.c1=y0; - x.c2=x.c1; - x.c1=smp[i]; - //output - smp[i]=y0; - }; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + y0=smp[i]*c[0]+x.c1*c[1]+x.c2*c[2]+y.c1*d[1]+y.c2*d[2]; + y.c2=y.c1; + y.c1=y0; + x.c2=x.c1; + x.c1=smp[i]; + //output + smp[i]=y0; + }; }; }; -void AnalogFilter::filterout(REALTYPE *smp){ +void AnalogFilter::filterout(REALTYPE *smp) +{ REALTYPE *ismp=NULL;//used if it needs interpolation int i; - if (needsinterpolation!=0){ - ismp=new REALTYPE[SOUND_BUFFER_SIZE]; - for (i=0;i<SOUND_BUFFER_SIZE;i++) ismp[i]=smp[i]; - for (i=0;i<stages+1;i++) singlefilterout(ismp,oldx[i],oldy[i],oldc,oldd); + if (needsinterpolation!=0) { + ismp=new REALTYPE[SOUND_BUFFER_SIZE]; + for (i=0;i<SOUND_BUFFER_SIZE;i++) ismp[i]=smp[i]; + for (i=0;i<stages+1;i++) singlefilterout(ismp,oldx[i],oldy[i],oldc,oldd); }; - + for (i=0;i<stages+1;i++) singlefilterout(smp,x[i],y[i],c,d); - if (needsinterpolation!=0){ - for (i=0;i<SOUND_BUFFER_SIZE;i++) { - REALTYPE x=i/(REALTYPE) SOUND_BUFFER_SIZE; - smp[i]=ismp[i]*(1.0-x)+smp[i]*x; - }; - delete [] ismp; - needsinterpolation=0; + if (needsinterpolation!=0) { + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + REALTYPE x=i/(REALTYPE) SOUND_BUFFER_SIZE; + smp[i]=ismp[i]*(1.0-x)+smp[i]*x; + }; + delete [] ismp; + needsinterpolation=0; }; for (i=0;i<SOUND_BUFFER_SIZE;i++) smp[i]*=outgain; }; -REALTYPE AnalogFilter::H(REALTYPE freq){ +REALTYPE AnalogFilter::H(REALTYPE freq) +{ REALTYPE fr=freq/SAMPLE_RATE*PI*2.0; REALTYPE x=c[0],y=0.0; - for (int n=1;n<3;n++){ - x+=cos(n*fr)*c[n]; - y-=sin(n*fr)*c[n]; + for (int n=1;n<3;n++) { + x+=cos(n*fr)*c[n]; + y-=sin(n*fr)*c[n]; }; REALTYPE h=x*x+y*y; - x=1.0;y=0.0; - for (int n=1;n<3;n++){ - x-=cos(n*fr)*d[n]; - y+=sin(n*fr)*d[n]; + x=1.0; + y=0.0; + for (int n=1;n<3;n++) { + x-=cos(n*fr)*d[n]; + y+=sin(n*fr)*d[n]; }; h=h/(x*x+y*y); return(pow(h,(stages+1.0)/2.0)); diff --git a/src/DSP/AnalogFilter.h b/src/DSP/AnalogFilter.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Analog Filter.h - Several analog filters (lowpass, highpass...) Copyright (C) 2002-2005 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 + 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, @@ -27,10 +27,11 @@ #include "Filter_.h" /**Implementation of Several analog filters (lowpass, highpass...)*/ -class AnalogFilter:public Filter_{ - public: +class AnalogFilter:public Filter_ +{ +public: AnalogFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages); - ~AnalogFilter(); + ~AnalogFilter(); void filterout(REALTYPE *smp); void setfreq(REALTYPE frequency); void setfreq_and_q(REALTYPE frequency,REALTYPE q_); @@ -40,14 +41,14 @@ class AnalogFilter:public Filter_{ void setgain(REALTYPE dBgain); void setstages(int stages_); void cleanup(); - + REALTYPE H(REALTYPE freq);//Obtains the response for a given frequency - - private: - struct fstage{ - REALTYPE c1,c2; + +private: + struct fstage { + REALTYPE c1,c2; } x[MAX_FILTER_STAGES+1],y[MAX_FILTER_STAGES+1], - oldx[MAX_FILTER_STAGES+1],oldy[MAX_FILTER_STAGES+1]; + oldx[MAX_FILTER_STAGES+1],oldy[MAX_FILTER_STAGES+1]; void singlefilterout(REALTYPE *smp,fstage &x,fstage &y,REALTYPE *c,REALTYPE *d); void computefiltercoefs(); @@ -56,7 +57,7 @@ class AnalogFilter:public Filter_{ REALTYPE freq;//Frequency given in Hz REALTYPE q; //Q factor (resonance or Q factor) REALTYPE gain;//the gain of the filter (if are shelf/peak) filters - + int order;//the order of the filter (number of poles) REALTYPE c[3],d[3];//coefficients diff --git a/src/DSP/FFTwrapper.C b/src/DSP/FFTwrapper.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + FFTwrapper.c - A wrapper for Fast Fourier Transforms Copyright (C) 2002-2005 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 + 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, @@ -23,7 +23,8 @@ #include <math.h> #include "FFTwrapper.h" -FFTwrapper::FFTwrapper(int fftsize_){ +FFTwrapper::FFTwrapper(int fftsize_) +{ fftsize=fftsize_; tmpfftdata1=new fftw_real[fftsize]; tmpfftdata2=new fftw_real[fftsize]; @@ -36,11 +37,12 @@ FFTwrapper::FFTwrapper(int fftsize_){ #endif }; -FFTwrapper::~FFTwrapper(){ +FFTwrapper::~FFTwrapper() +{ #ifdef FFTW_VERSION_2 rfftw_destroy_plan(planfftw); rfftw_destroy_plan(planfftw_inv); -#else +#else fftw_destroy_plan(planfftw); fftw_destroy_plan(planfftw_inv); #endif @@ -52,20 +54,21 @@ FFTwrapper::~FFTwrapper(){ /* * do the Fast Fourier Transform */ -void FFTwrapper::smps2freqs(REALTYPE *smps,FFTFREQS freqs){ +void FFTwrapper::smps2freqs(REALTYPE *smps,FFTFREQS freqs) +{ #ifdef FFTW_VERSION_2 for (int i=0;i<fftsize;i++) tmpfftdata1[i]=smps[i]; rfftw_one(planfftw,tmpfftdata1,tmpfftdata2); for (int i=0;i<fftsize/2;i++) { - freqs.c[i]=tmpfftdata2[i]; - if (i!=0) freqs.s[i]=tmpfftdata2[fftsize-i]; + freqs.c[i]=tmpfftdata2[i]; + if (i!=0) freqs.s[i]=tmpfftdata2[fftsize-i]; }; #else for (int i=0;i<fftsize;i++) tmpfftdata1[i]=smps[i]; fftw_execute(planfftw); for (int i=0;i<fftsize/2;i++) { - freqs.c[i]=tmpfftdata1[i]; - if (i!=0) freqs.s[i]=tmpfftdata1[fftsize-i]; + freqs.c[i]=tmpfftdata1[i]; + if (i!=0) freqs.s[i]=tmpfftdata1[fftsize-i]; }; #endif tmpfftdata2[fftsize/2]=0.0; @@ -74,19 +77,20 @@ void FFTwrapper::smps2freqs(REALTYPE *smps,FFTFREQS freqs){ /* * do the Inverse Fast Fourier Transform */ -void FFTwrapper::freqs2smps(FFTFREQS freqs,REALTYPE *smps){ +void FFTwrapper::freqs2smps(FFTFREQS freqs,REALTYPE *smps) +{ tmpfftdata2[fftsize/2]=0.0; #ifdef FFTW_VERSION_2 for (int i=0;i<fftsize/2;i++) { - tmpfftdata1[i]=freqs.c[i]; - if (i!=0) tmpfftdata1[fftsize-i]=freqs.s[i]; + tmpfftdata1[i]=freqs.c[i]; + if (i!=0) tmpfftdata1[fftsize-i]=freqs.s[i]; }; rfftw_one(planfftw_inv,tmpfftdata1,tmpfftdata2); for (int i=0;i<fftsize;i++) smps[i]=tmpfftdata2[i]; #else for (int i=0;i<fftsize/2;i++) { - tmpfftdata2[i]=freqs.c[i]; - if (i!=0) tmpfftdata2[fftsize-i]=freqs.s[i]; + tmpfftdata2[i]=freqs.c[i]; + if (i!=0) tmpfftdata2[fftsize-i]=freqs.s[i]; }; fftw_execute(planfftw_inv); for (int i=0;i<fftsize;i++) smps[i]=tmpfftdata2[i]; diff --git a/src/DSP/FFTwrapper.h b/src/DSP/FFTwrapper.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + FFTwrapper.h - A wrapper for Fast Fourier Transforms Copyright (C) 2002-2005 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 + 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, @@ -31,7 +31,7 @@ /* If you got error messages about rfftw.h, replace the next include line with "#include <srfftw.h>" or with "#include <drfftw.h> (if one doesn't work try the other). It may be necessary to replace -the <fftw.h> with <dfftw.h> or <sfftw.h>. If the neither one doesn't work, +the <fftw.h> with <dfftw.h> or <sfftw.h>. If the neither one doesn't work, please install latest version of fftw(recomanded from the sources) from www.fftw.org. If you'll install fftw3 you need to change the Makefile.inc Hope all goes right." */ @@ -45,22 +45,23 @@ Hope all goes right." */ #endif /**A wrapper for the FFTW library (Fast Fourier Transforms)*/ -class FFTwrapper{ - public: - /**Constructor - * @param fftsize The size of samples to be fed to fftw*/ - FFTwrapper(int fftsize_); - /**Destructor*/ - ~FFTwrapper(); - /**Convert Samples to Frequencies using Fourier Transform - * @param smps Pointer to Samples to be converted; has length fftsize_ - * @param freqs Structure FFTFREQS which stores the frequencies*/ - void smps2freqs(REALTYPE *smps,FFTFREQS freqs); - void freqs2smps(FFTFREQS freqs,REALTYPE *smps); - private: - int fftsize; - fftw_real *tmpfftdata1,*tmpfftdata2; - rfftw_plan planfftw,planfftw_inv; +class FFTwrapper +{ +public: + /**Constructor + * @param fftsize The size of samples to be fed to fftw*/ + FFTwrapper(int fftsize_); + /**Destructor*/ + ~FFTwrapper(); + /**Convert Samples to Frequencies using Fourier Transform + * @param smps Pointer to Samples to be converted; has length fftsize_ + * @param freqs Structure FFTFREQS which stores the frequencies*/ + void smps2freqs(REALTYPE *smps,FFTFREQS freqs); + void freqs2smps(FFTFREQS freqs,REALTYPE *smps); +private: + int fftsize; + fftw_real *tmpfftdata1,*tmpfftdata2; + rfftw_plan planfftw,planfftw_inv; }; #endif diff --git a/src/DSP/Filter.C b/src/DSP/Filter.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Filter.C - Filters, uses analog,formant,etc. filters Copyright (C) 2002-2005 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 + 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, @@ -25,48 +25,58 @@ #include "Filter.h" -Filter::Filter(FilterParams *pars){ +Filter::Filter(FilterParams *pars) +{ unsigned char Ftype=pars->Ptype; unsigned char Fstages=pars->Pstages; - + category=pars->Pcategory; - + switch (category) { - case 1:filter=new FormantFilter(pars); - break; - case 2:filter=new SVFilter(Ftype,1000.0,pars->getq(),Fstages); - filter->outgain=dB2rap(pars->getgain()); - if (filter->outgain>1.0) filter->outgain=sqrt(filter->outgain); - break; - default:filter=new AnalogFilter(Ftype,1000.0,pars->getq(),Fstages); - if ((Ftype>=6)&&(Ftype<=8)) filter->setgain(pars->getgain()); - else filter->outgain=dB2rap(pars->getgain()); - break; + case 1: + filter=new FormantFilter(pars); + break; + case 2: + filter=new SVFilter(Ftype,1000.0,pars->getq(),Fstages); + filter->outgain=dB2rap(pars->getgain()); + if (filter->outgain>1.0) filter->outgain=sqrt(filter->outgain); + break; + default: + filter=new AnalogFilter(Ftype,1000.0,pars->getq(),Fstages); + if ((Ftype>=6)&&(Ftype<=8)) filter->setgain(pars->getgain()); + else filter->outgain=dB2rap(pars->getgain()); + break; }; }; -Filter::~Filter(){ +Filter::~Filter() +{ delete (filter); }; -void Filter::filterout(REALTYPE *smp){ +void Filter::filterout(REALTYPE *smp) +{ filter->filterout(smp); }; -void Filter::setfreq(REALTYPE frequency){ +void Filter::setfreq(REALTYPE frequency) +{ filter->setfreq(frequency); }; -void Filter::setfreq_and_q(REALTYPE frequency,REALTYPE q_){ +void Filter::setfreq_and_q(REALTYPE frequency,REALTYPE q_) +{ filter->setfreq_and_q(frequency,q_); }; -void Filter::setq(REALTYPE q_){ +void Filter::setq(REALTYPE q_) +{ filter->setq(q_); }; -REALTYPE Filter::getrealfreq(REALTYPE freqpitch){ +REALTYPE Filter::getrealfreq(REALTYPE freqpitch) +{ if ((category==0)||(category==2)) return(pow(2.0,freqpitch+9.96578428));//log2(1000)=9.95748 - else return(freqpitch); + else return(freqpitch); }; diff --git a/src/DSP/Filter.h b/src/DSP/Filter.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Filter.h - Filters, uses analog,formant,etc. filters Copyright (C) 2002-2005 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 + 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, @@ -31,17 +31,18 @@ #include "SVFilter.h" #include "../Params/FilterParams.h" -class Filter{ - public: +class Filter +{ +public: Filter(FilterParams *pars); - ~Filter(); + ~Filter(); void filterout(REALTYPE *smp); void setfreq(REALTYPE frequency); void setfreq_and_q(REALTYPE frequency,REALTYPE q_); void setq(REALTYPE q_); REALTYPE getrealfreq(REALTYPE freqpitch); - private: +private: Filter_ *filter; unsigned char category; }; diff --git a/src/DSP/Filter_.h b/src/DSP/Filter_.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Filter_.h - This class is inherited by filter classes Copyright (C) 2002-2005 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 + 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, @@ -25,16 +25,17 @@ #include "../globals.h" -class Filter_{ - public: - virtual ~Filter_(){}; +class Filter_ +{ +public: + virtual ~Filter_() {}; virtual void filterout(REALTYPE *smp)=0; virtual void setfreq(REALTYPE frequency)=0; virtual void setfreq_and_q(REALTYPE frequency,REALTYPE q_)=0; virtual void setq(REALTYPE q_)=0; - virtual void setgain(REALTYPE dBgain){}; + virtual void setgain(REALTYPE dBgain) {}; REALTYPE outgain; - private: +private: }; diff --git a/src/DSP/FormantFilter.C b/src/DSP/FormantFilter.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + FormantFilter.C - formant filters Copyright (C) 2002-2005 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 + 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, @@ -24,31 +24,33 @@ #include <stdio.h> #include "FormantFilter.h" -FormantFilter::FormantFilter(FilterParams *pars){ +FormantFilter::FormantFilter(FilterParams *pars) +{ numformants=pars->Pnumformants; for (int i=0;i<numformants;i++) formant[i]=new AnalogFilter(4/*BPF*/,1000.0,10.0,pars->Pstages); cleanup(); inbuffer=new REALTYPE [SOUND_BUFFER_SIZE]; tmpbuf=new REALTYPE [SOUND_BUFFER_SIZE]; - for (int j=0;j<FF_MAX_VOWELS;j++) - for (int i=0;i<numformants;i++){ - formantpar[j][i].freq=pars->getformantfreq(pars->Pvowels[j].formants[i].freq); - formantpar[j][i].amp=pars->getformantamp(pars->Pvowels[j].formants[i].amp); - formantpar[j][i].q=pars->getformantq(pars->Pvowels[j].formants[i].q); - }; + for (int j=0;j<FF_MAX_VOWELS;j++) + for (int i=0;i<numformants;i++) { + formantpar[j][i].freq=pars->getformantfreq(pars->Pvowels[j].formants[i].freq); + formantpar[j][i].amp=pars->getformantamp(pars->Pvowels[j].formants[i].amp); + formantpar[j][i].q=pars->getformantq(pars->Pvowels[j].formants[i].q); + }; for (int i=0;i<FF_MAX_FORMANTS;i++) oldformantamp[i]=1.0; - for (int i=0;i<numformants;i++){ - currentformants[i].freq=1000.0; - currentformants[i].amp=1.0; - currentformants[i].q=2.0; + for (int i=0;i<numformants;i++) { + currentformants[i].freq=1000.0; + currentformants[i].amp=1.0; + currentformants[i].q=2.0; }; formantslowness=pow(1.0-(pars->Pformantslowness/128.0),3.0); - sequencesize=pars->Psequencesize;if (sequencesize==0) sequencesize=1; + sequencesize=pars->Psequencesize; + if (sequencesize==0) sequencesize=1; for (int k=0;k<sequencesize;k++) sequence[k].nvowel=pars->Psequence[k].nvowel; - + vowelclearness=pow(10.0,(pars->Pvowelclearness-32.0)/48.0); sequencestretch=pow(0.1,(pars->Psequencestretch-32.0)/48.0); @@ -57,11 +59,13 @@ FormantFilter::FormantFilter(FilterParams *pars){ outgain=dB2rap(pars->getgain()); oldinput=-1.0; - Qfactor=1.0;oldQfactor=Qfactor; + Qfactor=1.0; + oldQfactor=Qfactor; firsttime=1; }; -FormantFilter::~FormantFilter(){ +FormantFilter::~FormantFilter() +{ for (int i=0;i<numformants;i++) delete(formant[i]); delete[] inbuffer; delete[] tmpbuf; @@ -70,94 +74,103 @@ FormantFilter::~FormantFilter(){ -void FormantFilter::cleanup(){ +void FormantFilter::cleanup() +{ for (int i=0;i<numformants;i++) formant[i]->cleanup(); }; -void FormantFilter::setpos(REALTYPE input){ +void FormantFilter::setpos(REALTYPE input) +{ int p1,p2; - + if (firsttime!=0) slowinput=input; - else slowinput=slowinput*(1.0-formantslowness)+input*formantslowness; + else slowinput=slowinput*(1.0-formantslowness)+input*formantslowness; if ((fabs(oldinput-input)<0.001)&&(fabs(slowinput-input)<0.001)&& - (fabs(Qfactor-oldQfactor)<0.001)) { + (fabs(Qfactor-oldQfactor)<0.001)) { // oldinput=input; daca setez asta, o sa faca probleme la schimbari foarte lente - firsttime=0; - return; + firsttime=0; + return; } else oldinput=input; - REALTYPE pos=fmod(input*sequencestretch,1.0);if (pos<0.0) pos+=1.0; - + REALTYPE pos=fmod(input*sequencestretch,1.0); + if (pos<0.0) pos+=1.0; + F2I(pos*sequencesize,p2); - p1=p2-1;if (p1<0) p1+=sequencesize; + p1=p2-1; + if (p1<0) p1+=sequencesize; - pos=fmod(pos*sequencesize,1.0); - if (pos<0.0) pos=0.0; else if (pos>1.0) pos=1.0; + pos=fmod(pos*sequencesize,1.0); + if (pos<0.0) pos=0.0; + else if (pos>1.0) pos=1.0; pos=(atan((pos*2.0-1.0)*vowelclearness)/atan(vowelclearness)+1.0)*0.5; p1=sequence[p1].nvowel; p2=sequence[p2].nvowel; - + if (firsttime!=0) { - for (int i=0;i<numformants;i++){ - currentformants[i].freq=formantpar[p1][i].freq*(1.0-pos)+formantpar[p2][i].freq*pos; - currentformants[i].amp=formantpar[p1][i].amp*(1.0-pos)+formantpar[p2][i].amp*pos; - currentformants[i].q=formantpar[p1][i].q*(1.0-pos)+formantpar[p2][i].q*pos; - formant[i]->setfreq_and_q(currentformants[i].freq,currentformants[i].q*Qfactor); - oldformantamp[i]=currentformants[i].amp; - }; - firsttime=0; + for (int i=0;i<numformants;i++) { + currentformants[i].freq=formantpar[p1][i].freq*(1.0-pos)+formantpar[p2][i].freq*pos; + currentformants[i].amp=formantpar[p1][i].amp*(1.0-pos)+formantpar[p2][i].amp*pos; + currentformants[i].q=formantpar[p1][i].q*(1.0-pos)+formantpar[p2][i].q*pos; + formant[i]->setfreq_and_q(currentformants[i].freq,currentformants[i].q*Qfactor); + oldformantamp[i]=currentformants[i].amp; + }; + firsttime=0; } else { - for (int i=0;i<numformants;i++){ - currentformants[i].freq=currentformants[i].freq*(1.0-formantslowness) - +(formantpar[p1][i].freq*(1.0-pos)+formantpar[p2][i].freq*pos)*formantslowness; + for (int i=0;i<numformants;i++) { + currentformants[i].freq=currentformants[i].freq*(1.0-formantslowness) + +(formantpar[p1][i].freq*(1.0-pos)+formantpar[p2][i].freq*pos)*formantslowness; - currentformants[i].amp=currentformants[i].amp*(1.0-formantslowness) - +(formantpar[p1][i].amp*(1.0-pos)+formantpar[p2][i].amp*pos)*formantslowness; + currentformants[i].amp=currentformants[i].amp*(1.0-formantslowness) + +(formantpar[p1][i].amp*(1.0-pos)+formantpar[p2][i].amp*pos)*formantslowness; - currentformants[i].q=currentformants[i].q*(1.0-formantslowness) - +(formantpar[p1][i].q*(1.0-pos)+formantpar[p2][i].q*pos)*formantslowness; + currentformants[i].q=currentformants[i].q*(1.0-formantslowness) + +(formantpar[p1][i].q*(1.0-pos)+formantpar[p2][i].q*pos)*formantslowness; - formant[i]->setfreq_and_q(currentformants[i].freq,currentformants[i].q*Qfactor); - }; + formant[i]->setfreq_and_q(currentformants[i].freq,currentformants[i].q*Qfactor); + }; }; - + oldQfactor=Qfactor; }; -void FormantFilter::setfreq(REALTYPE frequency){ +void FormantFilter::setfreq(REALTYPE frequency) +{ setpos(frequency); }; -void FormantFilter::setq(REALTYPE q_){ +void FormantFilter::setq(REALTYPE q_) +{ Qfactor=q_; for (int i=0;i<numformants;i++) formant[i]->setq(Qfactor*currentformants[i].q); }; -void FormantFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_){ - Qfactor=q_; +void FormantFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_) +{ + Qfactor=q_; setpos(frequency); }; -void FormantFilter::filterout(REALTYPE *smp){ +void FormantFilter::filterout(REALTYPE *smp) +{ int i,j; for (i=0;i<SOUND_BUFFER_SIZE;i++) { - inbuffer[i]=smp[i]; - smp[i]=0.0; + inbuffer[i]=smp[i]; + smp[i]=0.0; }; - + for (j=0;j<numformants;j++) { for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpbuf[i]=inbuffer[i]*outgain; - formant[j]->filterout(tmpbuf); + formant[j]->filterout(tmpbuf); - if (ABOVE_AMPLITUDE_THRESHOLD(oldformantamp[j],currentformants[j].amp)) - for (i=0;i<SOUND_BUFFER_SIZE;i++) smp[i]+=tmpbuf[i]* - INTERPOLATE_AMPLITUDE(oldformantamp[j],currentformants[j].amp,i,SOUND_BUFFER_SIZE); - else for (i=0;i<SOUND_BUFFER_SIZE;i++) smp[i]+=tmpbuf[i]*currentformants[j].amp; - oldformantamp[j]=currentformants[j].amp; + if (ABOVE_AMPLITUDE_THRESHOLD(oldformantamp[j],currentformants[j].amp)) + for (i=0;i<SOUND_BUFFER_SIZE;i++) smp[i]+=tmpbuf[i]* + INTERPOLATE_AMPLITUDE(oldformantamp[j],currentformants[j].amp,i,SOUND_BUFFER_SIZE); + else for (i=0;i<SOUND_BUFFER_SIZE;i++) smp[i]+=tmpbuf[i]*currentformants[j].amp; + oldformantamp[j]=currentformants[j].amp; }; }; diff --git a/src/DSP/FormantFilter.h b/src/DSP/FormantFilter.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + FormantFilter.h - formant filter Copyright (C) 2002-2005 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 + 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, @@ -29,37 +29,38 @@ #include "../Params/FilterParams.h" -class FormantFilter:public Filter_{ - public: +class FormantFilter:public Filter_ +{ +public: FormantFilter(FilterParams *pars); - ~FormantFilter(); + ~FormantFilter(); void filterout(REALTYPE *smp); void setfreq(REALTYPE frequency); void setfreq_and_q(REALTYPE frequency,REALTYPE q_); void setq(REALTYPE q_); void cleanup(); - private: +private: AnalogFilter *formant[FF_MAX_FORMANTS]; REALTYPE *inbuffer,*tmpbuf; struct { - REALTYPE freq,amp,q;//frequency,amplitude,Q + REALTYPE freq,amp,q;//frequency,amplitude,Q } formantpar[FF_MAX_VOWELS][FF_MAX_FORMANTS],currentformants[FF_MAX_FORMANTS]; struct { - unsigned char nvowel; + unsigned char nvowel; } sequence [FF_MAX_SEQUENCE]; - + REALTYPE oldformantamp[FF_MAX_FORMANTS]; - + int sequencesize,numformants,firsttime; REALTYPE oldinput,slowinput; REALTYPE Qfactor,formantslowness,oldQfactor; REALTYPE vowelclearness,sequencestretch; - + void setpos(REALTYPE input); - + }; diff --git a/src/DSP/SVFilter.C b/src/DSP/SVFilter.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + SVFilter.C - Several state-variable filters Copyright (C) 2002-2005 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 + 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, @@ -24,7 +24,8 @@ #include <stdio.h> #include "SVFilter.h" -SVFilter::SVFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages){ +SVFilter::SVFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages) +{ stages=Fstages; type=Ftype; freq=Ffreq; @@ -38,19 +39,24 @@ SVFilter::SVFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char setfreq_and_q(Ffreq,Fq); }; -SVFilter::~SVFilter(){ +SVFilter::~SVFilter() +{ }; -void SVFilter::cleanup(){ - for (int i=0;i<MAX_FILTER_STAGES+1;i++){ - st[i].low=0.0;st[i].high=0.0; - st[i].band=0.0;st[i].notch=0.0; +void SVFilter::cleanup() +{ + for (int i=0;i<MAX_FILTER_STAGES+1;i++) { + st[i].low=0.0; + st[i].high=0.0; + st[i].band=0.0; + st[i].notch=0.0; }; oldabovenq=0; abovenq=0; }; -void SVFilter::computefiltercoefs(){ +void SVFilter::computefiltercoefs() +{ par.f=freq / SAMPLE_RATE*4.0; if (par.f>0.99999) par.f=0.99999; par.q=1.0-atan(sqrt(q))*2.0/PI; @@ -59,18 +65,21 @@ void SVFilter::computefiltercoefs(){ }; -void SVFilter::setfreq(REALTYPE frequency){ +void SVFilter::setfreq(REALTYPE frequency) +{ if (frequency<0.1) frequency=0.1; - REALTYPE rap=freq/frequency;if (rap<1.0) rap=1.0/rap; - - oldabovenq=abovenq;abovenq=frequency>(SAMPLE_RATE/2-500.0); - + REALTYPE rap=freq/frequency; + if (rap<1.0) rap=1.0/rap; + + oldabovenq=abovenq; + abovenq=frequency>(SAMPLE_RATE/2-500.0); + int nyquistthresh=(abovenq^oldabovenq); - if ((rap>3.0)||(nyquistthresh!=0)){//if the frequency is changed fast, it needs interpolation (now, filter and coeficients backup) - if (firsttime==0) needsinterpolation=1; - ipar=par; + if ((rap>3.0)||(nyquistthresh!=0)) {//if the frequency is changed fast, it needs interpolation (now, filter and coeficients backup) + if (firsttime==0) needsinterpolation=1; + ipar=par; }; freq=frequency; computefiltercoefs(); @@ -78,72 +87,87 @@ void SVFilter::setfreq(REALTYPE frequency){ }; -void SVFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_){ +void SVFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_) +{ q=q_; setfreq(frequency); }; -void SVFilter::setq(REALTYPE q_){ +void SVFilter::setq(REALTYPE q_) +{ q=q_; computefiltercoefs(); }; -void SVFilter::settype(int type_){ +void SVFilter::settype(int type_) +{ type=type_; computefiltercoefs(); }; -void SVFilter::setgain(REALTYPE dBgain){ +void SVFilter::setgain(REALTYPE dBgain) +{ gain=dB2rap(dBgain); computefiltercoefs(); }; -void SVFilter::setstages(int stages_){ +void SVFilter::setstages(int stages_) +{ if (stages_>=MAX_FILTER_STAGES) stages_=MAX_FILTER_STAGES-1; stages=stages_; cleanup(); computefiltercoefs(); }; -void SVFilter::singlefilterout(REALTYPE *smp,fstage &x,parameters &par){ +void SVFilter::singlefilterout(REALTYPE *smp,fstage &x,parameters &par) +{ int i; REALTYPE *out=NULL; - switch(type){ - case 0: out=&x.low;break; - case 1: out=&x.high;break; - case 2: out=&x.band;break; - case 3: out=&x.notch;break; + switch (type) { + case 0: + out=&x.low; + break; + case 1: + out=&x.high; + break; + case 2: + out=&x.band; + break; + case 3: + out=&x.notch; + break; }; - - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - x.low = x.low + par.f * x.band; - x.high = par.q_sqrt * smp[i] - x.low - par.q*x.band; - x.band = par.f * x.high + x.band; - x.notch = x.high + x.low; - - smp[i]= *out; + + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + x.low = x.low + par.f * x.band; + x.high = par.q_sqrt * smp[i] - x.low - par.q*x.band; + x.band = par.f * x.high + x.band; + x.notch = x.high + x.low; + + smp[i]= *out; }; }; -void SVFilter::filterout(REALTYPE *smp){ +void SVFilter::filterout(REALTYPE *smp) +{ int i; REALTYPE *ismp=NULL; - - if (needsinterpolation!=0){ - ismp=new REALTYPE[SOUND_BUFFER_SIZE]; - for (i=0;i<SOUND_BUFFER_SIZE;i++) ismp[i]=smp[i]; - for (i=0;i<stages+1;i++) singlefilterout(ismp,st[i],ipar); + + if (needsinterpolation!=0) { + ismp=new REALTYPE[SOUND_BUFFER_SIZE]; + for (i=0;i<SOUND_BUFFER_SIZE;i++) ismp[i]=smp[i]; + for (i=0;i<stages+1;i++) singlefilterout(ismp,st[i],ipar); }; for (i=0;i<stages+1;i++) singlefilterout(smp,st[i],par); - if (needsinterpolation!=0){ - for (i=0;i<SOUND_BUFFER_SIZE;i++) { - REALTYPE x=i/(REALTYPE) SOUND_BUFFER_SIZE; - smp[i]=ismp[i]*(1.0-x)+smp[i]*x; - }; - delete [] ismp; - needsinterpolation=0; + if (needsinterpolation!=0) { + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + REALTYPE x=i/(REALTYPE) SOUND_BUFFER_SIZE; + smp[i]=ismp[i]*(1.0-x)+smp[i]*x; + }; + delete [] ismp; + needsinterpolation=0; }; for (i=0;i<SOUND_BUFFER_SIZE;i++) smp[i]*=outgain; diff --git a/src/DSP/SVFilter.h b/src/DSP/SVFilter.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + SV Filter.h - Several state-variable filters Copyright (C) 2002-2005 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 + 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, @@ -25,10 +25,11 @@ #include "../globals.h" #include "Filter_.h" -class SVFilter:public Filter_{ - public: +class SVFilter:public Filter_ +{ +public: SVFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages); - ~SVFilter(); + ~SVFilter(); void filterout(REALTYPE *smp); void setfreq(REALTYPE frequency); void setfreq_and_q(REALTYPE frequency,REALTYPE q_); @@ -39,13 +40,13 @@ class SVFilter:public Filter_{ void setstages(int stages_); void cleanup(); - private: - struct fstage{ - REALTYPE low,high,band,notch; +private: + struct fstage { + REALTYPE low,high,band,notch; } st[MAX_FILTER_STAGES+1]; - struct parameters{ - REALTYPE f,q,q_sqrt; + struct parameters { + REALTYPE f,q,q_sqrt; }par,ipar; @@ -56,7 +57,7 @@ class SVFilter:public Filter_{ REALTYPE freq;//Frequency given in Hz REALTYPE q; //Q factor (resonance or Q factor) REALTYPE gain;//the gain of the filter (if are shelf/peak) filters - + int abovenq;//this is 1 if the frequency is above the nyquist int oldabovenq; int needsinterpolation,firsttime; diff --git a/src/Effects/Alienwah.C b/src/Effects/Alienwah.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Alienwah.C - "AlienWah" effect Copyright (C) 2002-2005 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 + 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, @@ -24,7 +24,7 @@ #include "Alienwah.h" Alienwah::Alienwah(const int &insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_) - :Effect(insertion_,efxoutl_,efxoutr_,NULL,0),oldl(NULL),oldr(NULL) + :Effect(insertion_,efxoutl_,efxoutr_,NULL,0),oldl(NULL),oldr(NULL) { setpreset(Ppreset); cleanup(); @@ -32,7 +32,8 @@ Alienwah::Alienwah(const int &insertion_,REALTYPE *const efxoutl_,REALTYPE *cons oldclfor=complex<REALTYPE>(fb,0.0); }; -Alienwah::~Alienwah(){ +Alienwah::~Alienwah() +{ if (oldl!=NULL) delete [] oldl; if (oldr!=NULL) delete [] oldr ; }; @@ -41,7 +42,8 @@ Alienwah::~Alienwah(){ /* * Apply the effect */ -void Alienwah::out(REALTYPE *smpsl,REALTYPE *smpsr){ +void Alienwah::out(REALTYPE *smpsl,REALTYPE *smpsr) +{ REALTYPE lfol,lfor; //Left/Right LFOs complex<REALTYPE> clfol,clfor,out,tmp; /**\todo Rework, as optimization can be used when the new complex type is @@ -49,36 +51,37 @@ void Alienwah::out(REALTYPE *smpsl,REALTYPE *smpsr){ * Before all calculations needed to be done with individual REALTYPE, * but now they can be done together*/ lfo.effectlfoout(&lfol,&lfor); - lfol*=depth*PI*2.0;lfor*=depth*PI*2.0; + lfol*=depth*PI*2.0; + lfor*=depth*PI*2.0; clfol=complex<REALTYPE>(cos(lfol+phase)*fb,sin(lfol+phase)*fb); //rework clfor=complex<REALTYPE>(cos(lfor+phase)*fb,sin(lfor+phase)*fb); //rework - for (int i=0;i<SOUND_BUFFER_SIZE;i++){ - REALTYPE x=((REALTYPE) i)/SOUND_BUFFER_SIZE; - REALTYPE x1=1.0-x; - //left + for (int i=0;i<SOUND_BUFFER_SIZE;i++) { + REALTYPE x=((REALTYPE) i)/SOUND_BUFFER_SIZE; + REALTYPE x1=1.0-x; + //left tmp=clfol*x+oldclfol*x1; out=tmp*oldl[oldk]; out.real()+=(1-fabs(fb))*smpsr[i]*(1.0-panning); - + oldl[oldk]=out; - REALTYPE l=out.real()*10.0*(fb+0.1); - - //right + REALTYPE l=out.real()*10.0*(fb+0.1); + + //right tmp=clfor*x+oldclfor*x1; - + out=tmp*oldr[oldk]; out.real()+=(1-fabs(fb))*smpsr[i]*(1.0-panning); - + oldr[oldk]=out; - REALTYPE r=out.real()*10.0*(fb+0.1); + REALTYPE r=out.real()*10.0*(fb+0.1); - if (++oldk>=Pdelay) oldk=0; - //LRcross - efxoutl[i]=l*(1.0-lrcross)+r*lrcross; - efxoutr[i]=r*(1.0-lrcross)+l*lrcross; + if (++oldk>=Pdelay) oldk=0; + //LRcross + efxoutl[i]=l*(1.0-lrcross)+r*lrcross; + efxoutr[i]=r*(1.0-lrcross)+l*lrcross; }; oldclfol=clfol; @@ -89,10 +92,11 @@ void Alienwah::out(REALTYPE *smpsl,REALTYPE *smpsr){ /* * Cleanup the effect */ -void Alienwah::cleanup(){ +void Alienwah::cleanup() +{ for (int i=0;i<Pdelay;i++) { - oldl[i]=complex<REALTYPE>(0.0,0.0); - oldr[i]=complex<REALTYPE>(0.0,0.0); + oldl[i]=complex<REALTYPE>(0.0,0.0); + oldr[i]=complex<REALTYPE>(0.0,0.0); }; oldk=0; }; @@ -102,12 +106,14 @@ void Alienwah::cleanup(){ * Parameter control */ -void Alienwah::setdepth(const unsigned char &Pdepth){ +void Alienwah::setdepth(const unsigned char &Pdepth) +{ this->Pdepth=Pdepth; depth=(Pdepth/127.0); }; -void Alienwah::setfb(const unsigned char &Pfb){ +void Alienwah::setfb(const unsigned char &Pfb) +{ this->Pfb=Pfb; fb=fabs((Pfb-64.0)/64.1); fb=sqrt(fb); @@ -115,29 +121,34 @@ void Alienwah::setfb(const unsigned char &Pfb){ if (Pfb<64) fb=-fb; }; -void Alienwah::setvolume(const unsigned char &Pvolume){ +void Alienwah::setvolume(const unsigned char &Pvolume) +{ this->Pvolume=Pvolume; outvolume=Pvolume/127.0; if (insertion==0) volume=1.0; - else volume=outvolume; + else volume=outvolume; }; -void Alienwah::setpanning(const unsigned char &Ppanning){ +void Alienwah::setpanning(const unsigned char &Ppanning) +{ this->Ppanning=Ppanning; panning=Ppanning/127.0; }; -void Alienwah::setlrcross(const unsigned char &Plrcross){ +void Alienwah::setlrcross(const unsigned char &Plrcross) +{ this->Plrcross=Plrcross; lrcross=Plrcross/127.0; }; -void Alienwah::setphase(const unsigned char &Pphase){ +void Alienwah::setphase(const unsigned char &Pphase) +{ this->Pphase=Pphase; phase=(Pphase-64.0)/64.0*PI; }; -void Alienwah::setdelay(const unsigned char &Pdelay){ +void Alienwah::setdelay(const unsigned char &Pdelay) +{ if (oldl!=NULL) delete [] oldl; if (oldr!=NULL) delete [] oldr; if (Pdelay>=MAX_ALIENWAH_DELAY) this->Pdelay=MAX_ALIENWAH_DELAY; @@ -147,19 +158,21 @@ void Alienwah::setdelay(const unsigned char &Pdelay){ cleanup(); }; -void Alienwah::setpreset(unsigned char npreset){ +void Alienwah::setpreset(unsigned char npreset) +{ const int PRESET_SIZE=11; const int NUM_PRESETS=4; unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ - //AlienWah1 - {127,64,70,0,0,62,60,105,25,0,64}, - //AlienWah2 - {127,64,73,106,0,101,60,105,17,0,64}, - //AlienWah3 - {127,64,63,0,1,100,112,105,31,0,42}, - //AlienWah4 - {93,64,25,0,1,66,101,11,47,0,86}}; - + //AlienWah1 + {127,64,70,0,0,62,60,105,25,0,64}, + //AlienWah2 + {127,64,73,106,0,101,60,105,17,0,64}, + //AlienWah3 + {127,64,63,0,1,100,112,105,31,0,42}, + //AlienWah4 + {93,64,25,0,1,66,101,11,47,0,86} + }; + if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]); if (insertion==0) changepar(0,presets[npreset][0]/2);//lower the volume if this is system effect @@ -167,63 +180,88 @@ void Alienwah::setpreset(unsigned char npreset){ }; -void Alienwah::changepar(const int &npar,const unsigned char &value){ - switch(npar){ - case 0: setvolume(value); - break; - case 1: setpanning(value); - break; - case 2: lfo.Pfreq=value; - lfo.updateparams(); - break; - case 3: lfo.Prandomness=value; - lfo.updateparams(); - break; - case 4: lfo.PLFOtype=value; - lfo.updateparams(); - break; - case 5: lfo.Pstereo=value; - lfo.updateparams(); - break; - case 6: setdepth(value); - break; - case 7: setfb(value); - break; - case 8: setdelay(value); - break; - case 9: setlrcross(value); - break; - case 10:setphase(value); - break; +void Alienwah::changepar(const int &npar,const unsigned char &value) +{ + switch (npar) { + case 0: + setvolume(value); + break; + case 1: + setpanning(value); + break; + case 2: + lfo.Pfreq=value; + lfo.updateparams(); + break; + case 3: + lfo.Prandomness=value; + lfo.updateparams(); + break; + case 4: + lfo.PLFOtype=value; + lfo.updateparams(); + break; + case 5: + lfo.Pstereo=value; + lfo.updateparams(); + break; + case 6: + setdepth(value); + break; + case 7: + setfb(value); + break; + case 8: + setdelay(value); + break; + case 9: + setlrcross(value); + break; + case 10: + setphase(value); + break; }; }; -unsigned char Alienwah::getpar(const int &npar)const{ - switch (npar){ - case 0: return(Pvolume); - break; - case 1: return(Ppanning); - break; - case 2: return(lfo.Pfreq); - break; - case 3: return(lfo.Prandomness); - break; - case 4: return(lfo.PLFOtype); - break; - case 5: return(lfo.Pstereo); - break; - case 6: return(Pdepth); - break; - case 7: return(Pfb); - break; - case 8: return(Pdelay); - break; - case 9: return(Plrcross); - break; - case 10:return(Pphase); - break; - default:return (0); +unsigned char Alienwah::getpar(const int &npar)const +{ + switch (npar) { + case 0: + return(Pvolume); + break; + case 1: + return(Ppanning); + break; + case 2: + return(lfo.Pfreq); + break; + case 3: + return(lfo.Prandomness); + break; + case 4: + return(lfo.PLFOtype); + break; + case 5: + return(lfo.Pstereo); + break; + case 6: + return(Pdepth); + break; + case 7: + return(Pfb); + break; + case 8: + return(Pdelay); + break; + case 9: + return(Plrcross); + break; + case 10: + return(Pphase); + break; + default: + return (0); }; - + }; diff --git a/src/Effects/Alienwah.h b/src/Effects/Alienwah.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Alienwah.h - "AlienWah" effect Copyright (C) 2002-2005 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 + 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, @@ -32,50 +32,51 @@ using namespace std; #define MAX_ALIENWAH_DELAY 100 /**"AlienWah" Effect*/ -class Alienwah:public Effect { - public: - /** - * Constructor - * @param insetion_ 1 for insertion Effect, 0 for others - * @param efxoutl_ Pointer to Alienwah's left channel output buffer - * @param efxoutr_ Pointer to Alienwah's left channel output buffer - * @return Initialized Alienwah - */ - Alienwah(const int &insetion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_); - ~Alienwah(); - void out(REALTYPE *const smpsl,REALTYPE *const smpsr); - - void setpreset(unsigned char npreset); - void changepar(const int &npar,const unsigned char &value); - unsigned char getpar(const int &npar)const; - void cleanup(); - - private: - //Alienwah Parameters - EffectLFO lfo;//lfo-ul Alienwah - unsigned char Pvolume; - unsigned char Ppanning; - unsigned char Pdepth;//the depth of the Alienwah - unsigned char Pfb;//feedback - unsigned char Plrcross;//feedback - unsigned char Pdelay; - unsigned char Pphase; - - - //Control Parameters - void setvolume(const unsigned char &Pvolume); - void setpanning(const unsigned char &Ppanning); - void setdepth(const unsigned char &Pdepth); - void setfb(const unsigned char &Pfb); - void setlrcross(const unsigned char &Plrcross); - void setdelay(const unsigned char &Pdelay); - void setphase(const unsigned char &Pphase); - - //Internal Values - REALTYPE panning,fb,depth,lrcross,phase; - complex<REALTYPE> *oldl,*oldr; - complex<REALTYPE> oldclfol,oldclfor; - int oldk; +class Alienwah:public Effect +{ +public: + /** + * Constructor + * @param insetion_ 1 for insertion Effect, 0 for others + * @param efxoutl_ Pointer to Alienwah's left channel output buffer + * @param efxoutr_ Pointer to Alienwah's left channel output buffer + * @return Initialized Alienwah + */ + Alienwah(const int &insetion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_); + ~Alienwah(); + void out(REALTYPE *const smpsl,REALTYPE *const smpsr); + + void setpreset(unsigned char npreset); + void changepar(const int &npar,const unsigned char &value); + unsigned char getpar(const int &npar)const; + void cleanup(); + +private: + //Alienwah Parameters + EffectLFO lfo;//lfo-ul Alienwah + unsigned char Pvolume; + unsigned char Ppanning; + unsigned char Pdepth;//the depth of the Alienwah + unsigned char Pfb;//feedback + unsigned char Plrcross;//feedback + unsigned char Pdelay; + unsigned char Pphase; + + + //Control Parameters + void setvolume(const unsigned char &Pvolume); + void setpanning(const unsigned char &Ppanning); + void setdepth(const unsigned char &Pdepth); + void setfb(const unsigned char &Pfb); + void setlrcross(const unsigned char &Plrcross); + void setdelay(const unsigned char &Pdelay); + void setphase(const unsigned char &Pphase); + + //Internal Values + REALTYPE panning,fb,depth,lrcross,phase; + complex<REALTYPE> *oldl,*oldr; + complex<REALTYPE> oldclfol,oldclfor; + int oldk; }; #endif diff --git a/src/Effects/Chorus.C b/src/Effects/Chorus.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Chorus.C - Chorus and Flange effects Copyright (C) 2002-2005 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 + 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, @@ -27,11 +27,12 @@ using namespace std; Chorus::Chorus(const int &insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_) - :Effect(insertion_,efxoutl_,efxoutr_,NULL,0), - maxdelay((int)(MAX_CHORUS_DELAY/1000.0*SAMPLE_RATE)), - delaySample(maxdelay) + :Effect(insertion_,efxoutl_,efxoutr_,NULL,0), + maxdelay((int)(MAX_CHORUS_DELAY/1000.0*SAMPLE_RATE)), + delaySample(maxdelay) { - dlk=0;drk=0; + dlk=0; + drk=0; //maxdelay=(int)(MAX_CHORUS_DELAY/1000.0*SAMPLE_RATE); //delayl=new REALTYPE[maxdelay]; //delayr=new REALTYPE[maxdelay]; @@ -44,22 +45,23 @@ Chorus::Chorus(const int &insertion_,REALTYPE *const efxoutl_,REALTYPE *const ef cleanup(); }; -Chorus::~Chorus(){}; +Chorus::~Chorus() {}; /* * get the delay value in samples; xlfo is the current lfo value */ -REALTYPE Chorus::getdelay(REALTYPE xlfo){ +REALTYPE Chorus::getdelay(REALTYPE xlfo) +{ REALTYPE result; - if (Pflangemode==0){ - result=(delay+xlfo*depth)*SAMPLE_RATE; + if (Pflangemode==0) { + result=(delay+xlfo*depth)*SAMPLE_RATE; } else result=0; - + //check if it is too big delay(caused bu errornous setdelay() and setdepth() /**\todo fix setdelay() and setdepth(), so this error cannot occur*/ if ((result+0.5)>=maxdelay) { - cerr << "WARNING: Chorus.C::getdelay(..) too big delay (see setdelay and setdepth funcs.)\n"; - result=maxdelay-1.0; + cerr << "WARNING: Chorus.C::getdelay(..) too big delay (see setdelay and setdepth funcs.)\n"; + result=maxdelay-1.0; }; return(result); }; @@ -67,140 +69,151 @@ REALTYPE Chorus::getdelay(REALTYPE xlfo){ /* * Apply the effect */ -void Chorus::out(REALTYPE *smpsl,REALTYPE *smpsr){ - const Stereo<AuSample> input(AuSample(smpsl,SOUND_BUFFER_SIZE),AuSample(smpsr,SOUND_BUFFER_SIZE)); +void Chorus::out(REALTYPE *smpsl,REALTYPE *smpsr) +{ + const Stereo<AuSample> input(AuSample(smpsl,SOUND_BUFFER_SIZE),AuSample(smpsr,SOUND_BUFFER_SIZE)); const REALTYPE one=1.0; - dl1=dl2;dr1=dr2; + dl1=dl2; + dr1=dr2; lfo.effectlfoout(&lfol,&lfor); - + dl2=getdelay(lfol); dr2=getdelay(lfor); - for (int i=0;i<input.l().size();i++){ - REALTYPE inl=input.l()[i]; - REALTYPE inr=input.r()[i]; - //LRcross - Stereo<REALTYPE> tmpc(inl,inr); - //REALTYPE r=inr; - inl=tmpc.l()*(1.0-lrcross)+tmpc.r()*lrcross; - inr=tmpc.r()*(1.0-lrcross)+tmpc.l()*lrcross; - - //Left channel - - //compute the delay in samples using linear interpolation between the lfo delays - mdel=(dl1*(SOUND_BUFFER_SIZE-i)+dl2*i)/SOUND_BUFFER_SIZE; - if (++dlk>=maxdelay) dlk=0; - REALTYPE tmp=dlk-mdel+maxdelay*2.0;//where should I get the sample from - - F2I(tmp,dlhi); - dlhi%=maxdelay; - - dlhi2=(dlhi-1+maxdelay)%maxdelay; - dllo=1.0-fmod(tmp,one); + for (int i=0;i<input.l().size();i++) { + REALTYPE inl=input.l()[i]; + REALTYPE inr=input.r()[i]; + //LRcross + Stereo<REALTYPE> tmpc(inl,inr); + //REALTYPE r=inr; + inl=tmpc.l()*(1.0-lrcross)+tmpc.r()*lrcross; + inr=tmpc.r()*(1.0-lrcross)+tmpc.l()*lrcross; + + //Left channel + + //compute the delay in samples using linear interpolation between the lfo delays + mdel=(dl1*(SOUND_BUFFER_SIZE-i)+dl2*i)/SOUND_BUFFER_SIZE; + if (++dlk>=maxdelay) dlk=0; + REALTYPE tmp=dlk-mdel+maxdelay*2.0;//where should I get the sample from + + F2I(tmp,dlhi); + dlhi%=maxdelay; + + dlhi2=(dlhi-1+maxdelay)%maxdelay; + dllo=1.0-fmod(tmp,one); efxoutl[i]=delaySample.l()[dlhi2]*dllo+delaySample.l()[dlhi]*(1.0-dllo); - delaySample.l()[dlk]=inl+efxoutl[i]*fb; + delaySample.l()[dlk]=inl+efxoutl[i]*fb; - //Right channel + //Right channel - //compute the delay in samples using linear interpolation between the lfo delays - mdel=(dr1*(SOUND_BUFFER_SIZE-i)+dr2*i)/SOUND_BUFFER_SIZE; - if (++drk>=maxdelay) drk=0; - tmp=drk*1.0-mdel+maxdelay*2.0;//where should I get the sample from + //compute the delay in samples using linear interpolation between the lfo delays + mdel=(dr1*(SOUND_BUFFER_SIZE-i)+dr2*i)/SOUND_BUFFER_SIZE; + if (++drk>=maxdelay) drk=0; + tmp=drk*1.0-mdel+maxdelay*2.0;//where should I get the sample from - F2I(tmp,dlhi); - dlhi%=maxdelay; - - dlhi2=(dlhi-1+maxdelay)%maxdelay; - dllo=1.0-fmod(tmp,one); + F2I(tmp,dlhi); + dlhi%=maxdelay; + + dlhi2=(dlhi-1+maxdelay)%maxdelay; + dllo=1.0-fmod(tmp,one); efxoutr[i]=delaySample.r()[dlhi2]*dllo+delaySample.r()[dlhi]*(1.0-dllo); - delaySample.r()[dlk]=inr+efxoutr[i]*fb; + delaySample.r()[dlk]=inr+efxoutr[i]*fb; }; if (Poutsub!=0) - for (int i=0;i<input.l().size();i++){ - efxoutl[i] *= -1.0; + for (int i=0;i<input.l().size();i++) { + efxoutl[i] *= -1.0; efxoutr[i] *= -1.0; - }; + }; - for (int i=0;i<input.l().size();i++){ - efxoutl[i]*=panning; - efxoutr[i]*=(1.0-panning); + for (int i=0;i<input.l().size();i++) { + efxoutl[i]*=panning; + efxoutr[i]*=(1.0-panning); }; }; /* * Cleanup the effect */ -void Chorus::cleanup(){ +void Chorus::cleanup() +{ delaySample.l().clear(); delaySample.r().clear(); //for (int i=0;i<maxdelay;i++){ // delayl[i]=0.0; // delayr[i]=0.0; //}; - + }; /* * Parameter control */ -void Chorus::setdepth(const unsigned char &Pdepth){ +void Chorus::setdepth(const unsigned char &Pdepth) +{ this->Pdepth=Pdepth; depth=(pow(8.0,(Pdepth/127.0)*2.0)-1.0)/1000.0;//seconds }; -void Chorus::setdelay(const unsigned char &Pdelay){ +void Chorus::setdelay(const unsigned char &Pdelay) +{ this->Pdelay=Pdelay; delay=(pow(10.0,(Pdelay/127.0)*2.0)-1.0)/1000.0;//seconds }; -void Chorus::setfb(const unsigned char &Pfb){ +void Chorus::setfb(const unsigned char &Pfb) +{ this->Pfb=Pfb; fb=(Pfb-64.0)/64.1; }; -void Chorus::setvolume(const unsigned char &Pvolume){ +void Chorus::setvolume(const unsigned char &Pvolume) +{ this->Pvolume=Pvolume; outvolume=Pvolume/127.0; if (insertion==0) volume=1.0; - else volume=outvolume; + else volume=outvolume; }; -void Chorus::setpanning(const unsigned char &Ppanning){ +void Chorus::setpanning(const unsigned char &Ppanning) +{ this->Ppanning=Ppanning; panning=Ppanning/127.0; }; -void Chorus::setlrcross(const unsigned char &Plrcross){ +void Chorus::setlrcross(const unsigned char &Plrcross) +{ this->Plrcross=Plrcross; lrcross=Plrcross/127.0; }; -void Chorus::setpreset(unsigned char npreset){ +void Chorus::setpreset(unsigned char npreset) +{ const int PRESET_SIZE=12; const int NUM_PRESETS=10; unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ - //Chorus1 - {64,64,50,0,0,90,40,85,64,119,0,0}, - //Chorus2 - {64,64,45,0,0,98,56,90,64,19,0,0}, - //Chorus3 - {64,64,29,0,1,42,97,95,90,127,0,0}, - //Celeste1 - {64,64,26,0,0,42,115,18,90,127,0,0}, - //Celeste2 - {64,64,29,117,0,50,115,9,31,127,0,1}, - //Flange1 - {64,64,57,0,0,60,23,3,62,0,0,0}, - //Flange2 - {64,64,33,34,1,40,35,3,109,0,0,0}, - //Flange3 - {64,64,53,34,1,94,35,3,54,0,0,1}, - //Flange4 - {64,64,40,0,1,62,12,19,97,0,0,0}, - //Flange5 - {64,64,55,105,0,24,39,19,17,0,0,1}}; + //Chorus1 + {64,64,50,0,0,90,40,85,64,119,0,0}, + //Chorus2 + {64,64,45,0,0,98,56,90,64,19,0,0}, + //Chorus3 + {64,64,29,0,1,42,97,95,90,127,0,0}, + //Celeste1 + {64,64,26,0,0,42,115,18,90,127,0,0}, + //Celeste2 + {64,64,29,117,0,50,115,9,31,127,0,1}, + //Flange1 + {64,64,57,0,0,60,23,3,62,0,0,0}, + //Flange2 + {64,64,33,34,1,40,35,3,109,0,0,0}, + //Flange3 + {64,64,53,34,1,94,35,3,54,0,0,1}, + //Flange4 + {64,64,40,0,1,62,12,19,97,0,0,0}, + //Flange5 + {64,64,55,105,0,24,39,19,17,0,0,1} + }; if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]); @@ -208,69 +221,96 @@ void Chorus::setpreset(unsigned char npreset){ }; -void Chorus::changepar(const int &npar,const unsigned char &value){ - switch(npar){ - case 0: setvolume(value); - break; - case 1: setpanning(value); - break; - case 2: lfo.Pfreq=value; - lfo.updateparams(); - break; - case 3: lfo.Prandomness=value; - lfo.updateparams(); - break; - case 4: lfo.PLFOtype=value; - lfo.updateparams(); - break; - case 5: lfo.Pstereo=value; - lfo.updateparams(); - break; - case 6: setdepth(value); - break; - case 7: setdelay(value); - break; - case 8: setfb(value); - break; - case 9: setlrcross(value); - break; - case 10:if (value>1) Pflangemode=1; - else Pflangemode=value; - break; - case 11:if (value>1) Poutsub=1; - else Poutsub=value; - break; +void Chorus::changepar(const int &npar,const unsigned char &value) +{ + switch (npar) { + case 0: + setvolume(value); + break; + case 1: + setpanning(value); + break; + case 2: + lfo.Pfreq=value; + lfo.updateparams(); + break; + case 3: + lfo.Prandomness=value; + lfo.updateparams(); + break; + case 4: + lfo.PLFOtype=value; + lfo.updateparams(); + break; + case 5: + lfo.Pstereo=value; + lfo.updateparams(); + break; + case 6: + setdepth(value); + break; + case 7: + setdelay(value); + break; + case 8: + setfb(value); + break; + case 9: + setlrcross(value); + break; + case 10: + if (value>1) Pflangemode=1; + else Pflangemode=value; + break; + case 11: + if (value>1) Poutsub=1; + else Poutsub=value; + break; }; }; -unsigned char Chorus::getpar(const int &npar)const{ - switch (npar){ - case 0: return(Pvolume); - break; - case 1: return(Ppanning); - break; - case 2: return(lfo.Pfreq); - break; - case 3: return(lfo.Prandomness); - break; - case 4: return(lfo.PLFOtype); - break; - case 5: return(lfo.Pstereo); - break; - case 6: return(Pdepth); - break; - case 7: return(Pdelay); - break; - case 8: return(Pfb); - break; - case 9: return(Plrcross); - break; - case 10:return(Pflangemode); - break; - case 11:return(Poutsub); - break; - default:return (0); +unsigned char Chorus::getpar(const int &npar)const +{ + switch (npar) { + case 0: + return(Pvolume); + break; + case 1: + return(Ppanning); + break; + case 2: + return(lfo.Pfreq); + break; + case 3: + return(lfo.Prandomness); + break; + case 4: + return(lfo.PLFOtype); + break; + case 5: + return(lfo.Pstereo); + break; + case 6: + return(Pdepth); + break; + case 7: + return(Pdelay); + break; + case 8: + return(Pfb); + break; + case 9: + return(Plrcross); + break; + case 10: + return(Pflangemode); + break; + case 11: + return(Poutsub); + break; + default: + return (0); }; - + }; diff --git a/src/Effects/Chorus.h b/src/Effects/Chorus.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Chorus.h - Chorus and Flange effects Copyright (C) 2002-2005 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 + 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, @@ -31,83 +31,84 @@ #define MAX_CHORUS_DELAY 250.0 //ms /**Chorus and Flange effects*/ -class Chorus:public Effect { - public: - Chorus(const int &insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); - /**Destructor*/ - ~Chorus(); - void out(REALTYPE *smpsl,REALTYPE *smpsr); - void setpreset(unsigned char npreset); - /** - * Sets the value of the chosen variable - * - * The possible parameters are: - * -# Volume - * -# Panning - * -# LFO Frequency - * -# LFO Randomness - * -# LFO Type - * -# LFO stereo - * -# Depth - * -# Delay - * -# Feedback - * -# Flange Mode - * -# Subtractive - * @param npar number of chosen parameter - * @param value the new value - */ - void changepar(const int &npar,const unsigned char &value); - /** - * Gets the value of the chosen variable - * - * The possible parameters are: - * -# Volume - * -# Panning - * -# LFO Frequency - * -# LFO Randomness - * -# LFO Type - * -# LFO stereo - * -# Depth - * -# Delay - * -# Feedback - * -# Flange Mode - * -# Subtractive - * @param npar number of chosen parameter - * @return the value of the parameter - */ - unsigned char getpar(const int &npar)const; - void cleanup(); - - private: - //Chorus Parameters - EffectLFO lfo;//lfo-ul chorus - unsigned char Pvolume; - unsigned char Ppanning; - unsigned char Pdepth;//the depth of the Chorus(ms) - unsigned char Pdelay;//the delay (ms) - unsigned char Pfb;//feedback - unsigned char Plrcross;//feedback - unsigned char Pflangemode;//how the LFO is scaled, to result chorus or flange - unsigned char Poutsub;//if I wish to substract the output instead of the adding it +class Chorus:public Effect +{ +public: + Chorus(const int &insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); + /**Destructor*/ + ~Chorus(); + void out(REALTYPE *smpsl,REALTYPE *smpsr); + void setpreset(unsigned char npreset); + /** + * Sets the value of the chosen variable + * + * The possible parameters are: + * -# Volume + * -# Panning + * -# LFO Frequency + * -# LFO Randomness + * -# LFO Type + * -# LFO stereo + * -# Depth + * -# Delay + * -# Feedback + * -# Flange Mode + * -# Subtractive + * @param npar number of chosen parameter + * @param value the new value + */ + void changepar(const int &npar,const unsigned char &value); + /** + * Gets the value of the chosen variable + * + * The possible parameters are: + * -# Volume + * -# Panning + * -# LFO Frequency + * -# LFO Randomness + * -# LFO Type + * -# LFO stereo + * -# Depth + * -# Delay + * -# Feedback + * -# Flange Mode + * -# Subtractive + * @param npar number of chosen parameter + * @return the value of the parameter + */ + unsigned char getpar(const int &npar)const; + void cleanup(); + +private: + //Chorus Parameters + EffectLFO lfo;//lfo-ul chorus + unsigned char Pvolume; + unsigned char Ppanning; + unsigned char Pdepth;//the depth of the Chorus(ms) + unsigned char Pdelay;//the delay (ms) + unsigned char Pfb;//feedback + unsigned char Plrcross;//feedback + unsigned char Pflangemode;//how the LFO is scaled, to result chorus or flange + unsigned char Poutsub;//if I wish to substract the output instead of the adding it + - - //Parameter Controls - void setvolume(const unsigned char &Pvolume); - void setpanning(const unsigned char &Ppanning); - void setdepth(const unsigned char &Pdepth); - void setdelay(const unsigned char &Pdelay); - void setfb(const unsigned char &Pfb); - void setlrcross(const unsigned char &Plrcross); + //Parameter Controls + void setvolume(const unsigned char &Pvolume); + void setpanning(const unsigned char &Ppanning); + void setdepth(const unsigned char &Pdepth); + void setdelay(const unsigned char &Pdelay); + void setfb(const unsigned char &Pfb); + void setlrcross(const unsigned char &Plrcross); - //Internal Values - REALTYPE depth,delay,fb,lrcross,panning; - REALTYPE dl1,dl2,dr1,dr2,lfol,lfor; - int maxdelay; - Stereo<AuSample> delaySample; - //REALTYPE *delayl,*delayr; - int dlk,drk,dlhi,dlhi2; - REALTYPE getdelay(REALTYPE xlfo); - REALTYPE dllo,mdel; + //Internal Values + REALTYPE depth,delay,fb,lrcross,panning; + REALTYPE dl1,dl2,dr1,dr2,lfol,lfor; + int maxdelay; + Stereo<AuSample> delaySample; + //REALTYPE *delayl,*delayr; + int dlk,drk,dlhi,dlhi2; + REALTYPE getdelay(REALTYPE xlfo); + REALTYPE dllo,mdel; }; #endif diff --git a/src/Effects/Distorsion.C b/src/Effects/Distorsion.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Distorsion.C - Distorsion effect Copyright (C) 2002-2005 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 + 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, @@ -28,132 +28,147 @@ * Waveshape (this is called by OscilGen::waveshape and Distorsion::process) */ -void waveshapesmps(int n,REALTYPE *smps,unsigned char type,unsigned char drive){ +void waveshapesmps(int n,REALTYPE *smps,unsigned char type,unsigned char drive) +{ int i; REALTYPE ws=drive/127.0; REALTYPE tmpv; - switch(type){ - case 1: ws=pow(10,ws*ws*3.0)-1.0+0.001;//Arctangent - for (i=0;i<n;i++) - smps[i]=atan(smps[i]*ws)/atan(ws); - break; - case 2: ws=ws*ws*32.0+0.0001;//Asymmetric - if (ws<1.0) tmpv=sin(ws)+0.1; - else tmpv=1.1; - for (i=0;i<n;i++) { - smps[i]=sin(smps[i]*(0.1+ws-ws*smps[i]))/tmpv; - }; - break; - case 3: ws=ws*ws*ws*20.0+0.0001;//Pow - for (i=0;i<n;i++) { - smps[i]*=ws; - if (fabs(smps[i])<1.0) { - smps[i]=(smps[i]-pow(smps[i],3.0))*3.0; - if (ws<1.0) smps[i]/=ws; - } else smps[i]=0.0; - }; - break; - case 4: ws=ws*ws*ws*32.0+0.0001;//Sine - if (ws<1.57) tmpv=sin(ws); - else tmpv=1.0; - for (i=0;i<n;i++) smps[i]=sin(smps[i]*ws)/tmpv; - break; - case 5: ws=ws*ws+0.000001;//Quantisize - for (i=0;i<n;i++) - smps[i]=floor(smps[i]/ws+0.5)*ws; - break; - case 6: ws=ws*ws*ws*32+0.0001;//Zigzag - if (ws<1.0) tmpv=sin(ws); - else tmpv=1.0; - for (i=0;i<n;i++) - smps[i]=asin(sin(smps[i]*ws))/tmpv; - break; - case 7: ws=pow(2.0,-ws*ws*8.0); //Limiter - for (i=0;i<n;i++) { - REALTYPE tmp=smps[i]; - if (fabs(tmp)>ws) { - if (tmp>=0.0) smps[i]=1.0; - else smps[i]=-1.0; - } else smps[i]/=ws; - }; - break; - case 8: ws=pow(2.0,-ws*ws*8.0); //Upper Limiter - for (i=0;i<n;i++) { - REALTYPE tmp=smps[i]; - if (tmp>ws) smps[i]=ws; - smps[i]*=2.0; - }; - break; - case 9: ws=pow(2.0,-ws*ws*8.0); //Lower Limiter - for (i=0;i<n;i++) { - REALTYPE tmp=smps[i]; - if (tmp<-ws) smps[i]=-ws; - smps[i]*=2.0; - }; - break; - case 10:ws=(pow(2.0,ws*6.0)-1.0)/pow(2.0,6.0); //Inverse Limiter - for (i=0;i<n;i++) { - REALTYPE tmp=smps[i]; - if (fabs(tmp)>ws) { - if (tmp>=0.0) smps[i]=tmp-ws; - else smps[i]=tmp+ws; - } else smps[i]=0; - }; - break; - case 11:ws=pow(5,ws*ws*1.0)-1.0;//Clip - for (i=0;i<n;i++) - smps[i]=smps[i]*(ws+0.5)*0.9999-floor(0.5+smps[i]*(ws+0.5)*0.9999); - break; - case 12:ws=ws*ws*ws*30+0.001;//Asym2 - if (ws<0.3) tmpv=ws; - else tmpv=1.0; - for (i=0;i<n;i++) { - REALTYPE tmp=smps[i]*ws; - if ((tmp>-2.0) && (tmp<1.0)) smps[i]=tmp*(1.0-tmp)*(tmp+2.0)/tmpv; - else smps[i]=0.0; - }; - break; - case 13:ws=ws*ws*ws*32.0+0.0001;//Pow2 - if (ws<1.0) tmpv=ws*(1+ws)/2.0; - else tmpv=1.0; - for (i=0;i<n;i++) { - REALTYPE tmp=smps[i]*ws; - if ((tmp>-1.0)&&(tmp<1.618034)) smps[i]=tmp*(1.0-tmp)/tmpv; - else if (tmp>0.0) smps[i]=-1.0; - else smps[i]=-2.0; - }; - break; - case 14:ws=pow(ws,5.0)*80.0+0.0001;//sigmoid - if (ws>10.0) tmpv=0.5; - else tmpv=0.5-1.0/(exp(ws)+1.0); - for (i=0;i<n;i++) { - REALTYPE tmp=smps[i]*ws; - if (tmp<-10.0) tmp=-10.0; - else if (tmp>10.0) tmp=10.0; - tmp=0.5-1.0/(exp(tmp)+1.0); - smps[i]=tmp/tmpv; - }; - break; - /**\todo update to Distorsion::changepar (Ptype max) if there is added more waveshapings functions*/ + switch (type) { + case 1: + ws=pow(10,ws*ws*3.0)-1.0+0.001;//Arctangent + for (i=0;i<n;i++) + smps[i]=atan(smps[i]*ws)/atan(ws); + break; + case 2: + ws=ws*ws*32.0+0.0001;//Asymmetric + if (ws<1.0) tmpv=sin(ws)+0.1; + else tmpv=1.1; + for (i=0;i<n;i++) { + smps[i]=sin(smps[i]*(0.1+ws-ws*smps[i]))/tmpv; + }; + break; + case 3: + ws=ws*ws*ws*20.0+0.0001;//Pow + for (i=0;i<n;i++) { + smps[i]*=ws; + if (fabs(smps[i])<1.0) { + smps[i]=(smps[i]-pow(smps[i],3.0))*3.0; + if (ws<1.0) smps[i]/=ws; + } else smps[i]=0.0; + }; + break; + case 4: + ws=ws*ws*ws*32.0+0.0001;//Sine + if (ws<1.57) tmpv=sin(ws); + else tmpv=1.0; + for (i=0;i<n;i++) smps[i]=sin(smps[i]*ws)/tmpv; + break; + case 5: + ws=ws*ws+0.000001;//Quantisize + for (i=0;i<n;i++) + smps[i]=floor(smps[i]/ws+0.5)*ws; + break; + case 6: + ws=ws*ws*ws*32+0.0001;//Zigzag + if (ws<1.0) tmpv=sin(ws); + else tmpv=1.0; + for (i=0;i<n;i++) + smps[i]=asin(sin(smps[i]*ws))/tmpv; + break; + case 7: + ws=pow(2.0,-ws*ws*8.0); //Limiter + for (i=0;i<n;i++) { + REALTYPE tmp=smps[i]; + if (fabs(tmp)>ws) { + if (tmp>=0.0) smps[i]=1.0; + else smps[i]=-1.0; + } else smps[i]/=ws; + }; + break; + case 8: + ws=pow(2.0,-ws*ws*8.0); //Upper Limiter + for (i=0;i<n;i++) { + REALTYPE tmp=smps[i]; + if (tmp>ws) smps[i]=ws; + smps[i]*=2.0; + }; + break; + case 9: + ws=pow(2.0,-ws*ws*8.0); //Lower Limiter + for (i=0;i<n;i++) { + REALTYPE tmp=smps[i]; + if (tmp<-ws) smps[i]=-ws; + smps[i]*=2.0; + }; + break; + case 10: + ws=(pow(2.0,ws*6.0)-1.0)/pow(2.0,6.0); //Inverse Limiter + for (i=0;i<n;i++) { + REALTYPE tmp=smps[i]; + if (fabs(tmp)>ws) { + if (tmp>=0.0) smps[i]=tmp-ws; + else smps[i]=tmp+ws; + } else smps[i]=0; + }; + break; + case 11: + ws=pow(5,ws*ws*1.0)-1.0;//Clip + for (i=0;i<n;i++) + smps[i]=smps[i]*(ws+0.5)*0.9999-floor(0.5+smps[i]*(ws+0.5)*0.9999); + break; + case 12: + ws=ws*ws*ws*30+0.001;//Asym2 + if (ws<0.3) tmpv=ws; + else tmpv=1.0; + for (i=0;i<n;i++) { + REALTYPE tmp=smps[i]*ws; + if ((tmp>-2.0) && (tmp<1.0)) smps[i]=tmp*(1.0-tmp)*(tmp+2.0)/tmpv; + else smps[i]=0.0; + }; + break; + case 13: + ws=ws*ws*ws*32.0+0.0001;//Pow2 + if (ws<1.0) tmpv=ws*(1+ws)/2.0; + else tmpv=1.0; + for (i=0;i<n;i++) { + REALTYPE tmp=smps[i]*ws; + if ((tmp>-1.0)&&(tmp<1.618034)) smps[i]=tmp*(1.0-tmp)/tmpv; + else if (tmp>0.0) smps[i]=-1.0; + else smps[i]=-2.0; + }; + break; + case 14: + ws=pow(ws,5.0)*80.0+0.0001;//sigmoid + if (ws>10.0) tmpv=0.5; + else tmpv=0.5-1.0/(exp(ws)+1.0); + for (i=0;i<n;i++) { + REALTYPE tmp=smps[i]*ws; + if (tmp<-10.0) tmp=-10.0; + else if (tmp>10.0) tmp=10.0; + tmp=0.5-1.0/(exp(tmp)+1.0); + smps[i]=tmp/tmpv; + }; + break; + /**\todo update to Distorsion::changepar (Ptype max) if there is added more waveshapings functions*/ }; }; Distorsion::Distorsion(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) - :Effect(insertion_,efxoutl_,efxoutr_,NULL,0) + :Effect(insertion_,efxoutl_,efxoutr_,NULL,0) { lpfl=new AnalogFilter(2,22000,1,0); lpfr=new AnalogFilter(2,22000,1,0); hpfl=new AnalogFilter(3,20,1,0); hpfr=new AnalogFilter(3,20,1,0); - + //default values Pvolume=50; - Plrcross=40; + Plrcross=40; Pdrive=90; Plevel=64; Ptype=0; @@ -163,22 +178,24 @@ Distorsion::Distorsion(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxout Pstereo=0; Pprefiltering=0; - setpreset(Ppreset); + setpreset(Ppreset); cleanup(); }; -Distorsion::~Distorsion(){ +Distorsion::~Distorsion() +{ delete lpfl; delete lpfr; delete hpfl; delete hpfr; - + }; /* * Cleanup the effect */ -void Distorsion::cleanup(){ +void Distorsion::cleanup() +{ lpfl->cleanup(); hpfl->cleanup(); lpfr->cleanup(); @@ -190,11 +207,12 @@ void Distorsion::cleanup(){ * Apply the filters */ -void Distorsion::applyfilters(REALTYPE *efxoutl,REALTYPE *efxoutr){ +void Distorsion::applyfilters(REALTYPE *efxoutl,REALTYPE *efxoutr) +{ lpfl->filterout(efxoutl); hpfl->filterout(efxoutl); - if (Pstereo!=0){//stereo - lpfr->filterout(efxoutr); + if (Pstereo!=0) {//stereo + lpfr->filterout(efxoutr); hpfr->filterout(efxoutr); }; @@ -204,24 +222,25 @@ void Distorsion::applyfilters(REALTYPE *efxoutl,REALTYPE *efxoutr){ /* * Effect output */ -void Distorsion::out(REALTYPE *smpsl,REALTYPE *smpsr){ +void Distorsion::out(REALTYPE *smpsl,REALTYPE *smpsr) +{ int i; REALTYPE l,r,lout,rout; REALTYPE inputvol=pow(5.0,(Pdrive-32.0)/127.0); if (Pnegate!=0) inputvol*=-1.0; - - if (Pstereo!=0){//Stereo - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - efxoutl[i]=smpsl[i]*inputvol*panning; - efxoutr[i]=smpsr[i]*inputvol*(1.0-panning); - }; + + if (Pstereo!=0) {//Stereo + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + efxoutl[i]=smpsl[i]*inputvol*panning; + efxoutr[i]=smpsr[i]*inputvol*(1.0-panning); + }; } else { - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - efxoutl[i]=( smpsl[i]*panning + smpsr[i]*(1.0-panning) ) * inputvol; - }; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + efxoutl[i]=( smpsl[i]*panning + smpsr[i]*(1.0-panning) ) * inputvol; + }; }; - + if (Pprefiltering!=0) applyfilters(efxoutl,efxoutr); //no optimised, yet (no look table) @@ -229,60 +248,66 @@ void Distorsion::out(REALTYPE *smpsl,REALTYPE *smpsr){ if (Pstereo!=0) waveshapesmps(SOUND_BUFFER_SIZE,efxoutr,Ptype+1,Pdrive); if (Pprefiltering==0) applyfilters(efxoutl,efxoutr); - + if (Pstereo==0) for (i=0;i<SOUND_BUFFER_SIZE;i++) efxoutr[i]=efxoutl[i]; - + REALTYPE level=dB2rap(60.0*Plevel/127.0-40.0); - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - lout=efxoutl[i]; - rout=efxoutr[i]; - l=lout*(1.0-lrcross)+rout*lrcross; - r=rout*(1.0-lrcross)+lout*lrcross; - lout=l;rout=r; - - efxoutl[i]=lout*2.0*level; - efxoutr[i]=rout*2.0*level; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + lout=efxoutl[i]; + rout=efxoutr[i]; + l=lout*(1.0-lrcross)+rout*lrcross; + r=rout*(1.0-lrcross)+lout*lrcross; + lout=l; + rout=r; + + efxoutl[i]=lout*2.0*level; + efxoutr[i]=rout*2.0*level; }; - + }; /* * Parameter control */ -void Distorsion::setvolume(const unsigned char &Pvolume){ +void Distorsion::setvolume(const unsigned char &Pvolume) +{ this->Pvolume=Pvolume; if (insertion==0) { - outvolume=pow(0.01,(1.0-Pvolume/127.0))*4.0; - volume=1.0; + outvolume=pow(0.01,(1.0-Pvolume/127.0))*4.0; + volume=1.0; } else { - volume=outvolume=Pvolume/127.0; + volume=outvolume=Pvolume/127.0; }; if (Pvolume==0) cleanup(); }; -void Distorsion::setpanning(const unsigned char &Ppanning){ +void Distorsion::setpanning(const unsigned char &Ppanning) +{ this->Ppanning=Ppanning; panning=(Ppanning+0.5)/127.0; }; -void Distorsion::setlrcross(const unsigned char &Plrcross){ +void Distorsion::setlrcross(const unsigned char &Plrcross) +{ this->Plrcross=Plrcross; lrcross=Plrcross/127.0*1.0; }; -void Distorsion::setlpf(const unsigned char &Plpf){ +void Distorsion::setlpf(const unsigned char &Plpf) +{ this->Plpf=Plpf; REALTYPE fr=exp(pow(Plpf/127.0,0.5)*log(25000.0))+40; lpfl->setfreq(fr); lpfr->setfreq(fr); }; -void Distorsion::sethpf(const unsigned char &Phpf){ +void Distorsion::sethpf(const unsigned char &Phpf) +{ this->Phpf=Phpf; REALTYPE fr=exp(pow(Phpf/127.0,0.5)*log(25000.0))+20.0; hpfl->setfreq(fr); @@ -290,22 +315,24 @@ void Distorsion::sethpf(const unsigned char &Phpf){ }; -void Distorsion::setpreset(unsigned char npreset){ +void Distorsion::setpreset(unsigned char npreset) +{ const int PRESET_SIZE=11; const int NUM_PRESETS=6; unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ - //Overdrive 1 - {127,64,35,56,70,0,0,96,0,0,0}, - //Overdrive 2 - {127,64,35,29,75,1,0,127,0,0,0}, - //A. Exciter 1 - {64,64,35,75,80,5,0,127,105,1,0}, - //A. Exciter 2 - {64,64,35,85,62,1,0,127,118,1,0}, - //Guitar Amp - {127,64,35,63,75,2,0,55,0,0,0}, - //Quantisize - {127,64,35,88,75,4,0,127,0,1,0}}; + //Overdrive 1 + {127,64,35,56,70,0,0,96,0,0,0}, + //Overdrive 2 + {127,64,35,29,75,1,0,127,0,0,0}, + //A. Exciter 1 + {64,64,35,75,80,5,0,127,105,1,0}, + //A. Exciter 2 + {64,64,35,85,62,1,0,127,118,1,0}, + //Guitar Amp + {127,64,35,63,75,2,0,55,0,0,0}, + //Quantisize + {127,64,35,88,75,4,0,127,0,1,0} + }; if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; @@ -316,60 +343,84 @@ void Distorsion::setpreset(unsigned char npreset){ }; -void Distorsion::changepar(const int &npar,const unsigned char &value){ - switch (npar){ - case 0: setvolume(value); - break; - case 1: setpanning(value); - break; - case 2: setlrcross(value); - break; - case 3: Pdrive=value; - break; - case 4: Plevel=value; - break; - case 5: if (value>13) Ptype=13;//this must be increased if more distorsion types are added - else Ptype=value; - break; - case 6: if (value>1) Pnegate=1; - else Pnegate=value; - break; - case 7: setlpf(value); - break; - case 8: sethpf(value); - break; - case 9: if (value>1) Pstereo=1; - else Pstereo=value; - break; - case 10:Pprefiltering=value; - break; +void Distorsion::changepar(const int &npar,const unsigned char &value) +{ + switch (npar) { + case 0: + setvolume(value); + break; + case 1: + setpanning(value); + break; + case 2: + setlrcross(value); + break; + case 3: + Pdrive=value; + break; + case 4: + Plevel=value; + break; + case 5: + if (value>13) Ptype=13;//this must be increased if more distorsion types are added + else Ptype=value; + break; + case 6: + if (value>1) Pnegate=1; + else Pnegate=value; + break; + case 7: + setlpf(value); + break; + case 8: + sethpf(value); + break; + case 9: + if (value>1) Pstereo=1; + else Pstereo=value; + break; + case 10: + Pprefiltering=value; + break; }; }; -unsigned char Distorsion::getpar(const int &npar)const{ - switch (npar){ - case 0: return(Pvolume); - break; - case 1: return(Ppanning); - break; - case 2: return(Plrcross); - break; - case 3: return(Pdrive); - break; - case 4: return(Plevel); - break; - case 5: return(Ptype); - break; - case 6: return(Pnegate); - break; - case 7: return(Plpf); - break; - case 8: return(Phpf); - break; - case 9: return(Pstereo); - break; - case 10:return(Pprefiltering); - break; +unsigned char Distorsion::getpar(const int &npar)const +{ + switch (npar) { + case 0: + return(Pvolume); + break; + case 1: + return(Ppanning); + break; + case 2: + return(Plrcross); + break; + case 3: + return(Pdrive); + break; + case 4: + return(Plevel); + break; + case 5: + return(Ptype); + break; + case 6: + return(Pnegate); + break; + case 7: + return(Plpf); + break; + case 8: + return(Phpf); + break; + case 9: + return(Pstereo); + break; + case 10: + return(Pprefiltering); + break; }; return(0);//in case of bogus parameter number }; diff --git a/src/Effects/Distorsion.h b/src/Effects/Distorsion.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Distorsion.h - Distorsion Effect Copyright (C) 2002-2005 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 + 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, @@ -30,40 +30,41 @@ //Waveshaping(called by Distorsion effect and waveshape from OscilGen) void waveshapesmps(int n,REALTYPE *smps,unsigned char type,unsigned char drive); /**Distortion Effect*/ -class Distorsion:public Effect{ - public: - Distorsion(const int &insertion,REALTYPE *efxoutl_,REALTYPE *efxoutr_); - ~Distorsion(); - void out(REALTYPE *smpsl,REALTYPE *smpr); - void setpreset(unsigned char npreset); - void changepar(const int &npar,const unsigned char &value); - unsigned char getpar(const int &npar)const; - void cleanup(); - void applyfilters(REALTYPE *efxoutl,REALTYPE *efxoutr); +class Distorsion:public Effect +{ +public: + Distorsion(const int &insertion,REALTYPE *efxoutl_,REALTYPE *efxoutr_); + ~Distorsion(); + void out(REALTYPE *smpsl,REALTYPE *smpr); + void setpreset(unsigned char npreset); + void changepar(const int &npar,const unsigned char &value); + unsigned char getpar(const int &npar)const; + void cleanup(); + void applyfilters(REALTYPE *efxoutl,REALTYPE *efxoutr); + +private: + //Parametrii + unsigned char Pvolume; //Volumul or E/R + unsigned char Ppanning;//Panning + unsigned char Plrcross;// L/R Mixing + unsigned char Pdrive; //the input amplification + unsigned char Plevel; //the output amplification + unsigned char Ptype; //Distorsion type + unsigned char Pnegate; //if the input is negated + unsigned char Plpf; //lowpass filter + unsigned char Phpf; //highpass filter + unsigned char Pstereo; //0=mono,1=stereo + unsigned char Pprefiltering;//if you want to do the filtering before the distorsion + + void setvolume(const unsigned char &Pvolume); + void setpanning(const unsigned char &Ppanning); + void setlrcross(const unsigned char &Plrcross); + void setlpf(const unsigned char &Plpf); + void sethpf(const unsigned char &Phpf); - private: - //Parametrii - unsigned char Pvolume; //Volumul or E/R - unsigned char Ppanning;//Panning - unsigned char Plrcross;// L/R Mixing - unsigned char Pdrive; //the input amplification - unsigned char Plevel; //the output amplification - unsigned char Ptype; //Distorsion type - unsigned char Pnegate; //if the input is negated - unsigned char Plpf; //lowpass filter - unsigned char Phpf; //highpass filter - unsigned char Pstereo; //0=mono,1=stereo - unsigned char Pprefiltering;//if you want to do the filtering before the distorsion - - void setvolume(const unsigned char &Pvolume); - void setpanning(const unsigned char &Ppanning); - void setlrcross(const unsigned char &Plrcross); - void setlpf(const unsigned char &Plpf); - void sethpf(const unsigned char &Phpf); - - //Real Parameters - REALTYPE panning,lrcross; - AnalogFilter *lpfl,*lpfr,*hpfl,*hpfr; + //Real Parameters + REALTYPE panning,lrcross; + AnalogFilter *lpfl,*lpfr,*hpfl,*hpfr; }; diff --git a/src/Effects/DynamicFilter.C b/src/Effects/DynamicFilter.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + DynamicFilter.C - "WahWah" effect and others Copyright (C) 2002-2005 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 + 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, @@ -24,16 +24,17 @@ #include "DynamicFilter.h" DynamicFilter::DynamicFilter(int insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) - :Effect(insertion_,efxoutl_,efxoutr_,new FilterParams(0,64,64),0), - Pvolume(110),Ppanning(64),Pdepth(0),Pampsns(90), - Pampsnsinv(0),Pampsmooth(60), - filterl(NULL),filterr(NULL) + :Effect(insertion_,efxoutl_,efxoutr_,new FilterParams(0,64,64),0), + Pvolume(110),Ppanning(64),Pdepth(0),Pampsns(90), + Pampsnsinv(0),Pampsmooth(60), + filterl(NULL),filterr(NULL) { setpreset(Ppreset); cleanup(); }; -DynamicFilter::~DynamicFilter(){ +DynamicFilter::~DynamicFilter() +{ delete filterpars; delete filterl; delete filterr; @@ -43,27 +44,29 @@ DynamicFilter::~DynamicFilter(){ /* * Apply the effect */ -void DynamicFilter::out(REALTYPE *smpsl,REALTYPE *smpsr){ +void DynamicFilter::out(REALTYPE *smpsl,REALTYPE *smpsr) +{ int i; - if (filterpars->changed){ - filterpars->changed=false; - cleanup(); + if (filterpars->changed) { + filterpars->changed=false; + cleanup(); }; - + REALTYPE lfol,lfor; lfo.effectlfoout(&lfol,&lfor); - lfol*=depth*5.0;lfor*=depth*5.0; + lfol*=depth*5.0; + lfor*=depth*5.0; REALTYPE freq=filterpars->getfreq(); REALTYPE q=filterpars->getq(); - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - efxoutl[i]=smpsl[i]; - efxoutr[i]=smpsr[i]; - - REALTYPE x=(fabs(smpsl[i])+fabs(smpsr[i]))*0.5; - ms1=ms1*(1.0-ampsmooth)+x*ampsmooth+1e-10; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + efxoutl[i]=smpsl[i]; + efxoutr[i]=smpsr[i]; + + REALTYPE x=(fabs(smpsl[i])+fabs(smpsr[i]))*0.5; + ms1=ms1*(1.0-ampsmooth)+x*ampsmooth+1e-10; }; - + REALTYPE ampsmooth2=pow(ampsmooth,0.2)*0.3; ms2=ms2*(1.0-ampsmooth2)+ms1*ampsmooth2; @@ -73,18 +76,18 @@ void DynamicFilter::out(REALTYPE *smpsl,REALTYPE *smpsr){ REALTYPE frl=filterl->getrealfreq(freq+lfol+rms); REALTYPE frr=filterr->getrealfreq(freq+lfor+rms); - + filterl->setfreq_and_q(frl,q); filterr->setfreq_and_q(frr,q); - - + + filterl->filterout(efxoutl); filterr->filterout(efxoutr); - //panning - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - efxoutl[i]*=panning; - efxoutr[i]*=(1.0-panning); + //panning + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + efxoutl[i]*=panning; + efxoutr[i]*=(1.0-panning); }; }; @@ -92,7 +95,8 @@ void DynamicFilter::out(REALTYPE *smpsl,REALTYPE *smpsr){ /* * Cleanup the effect */ -void DynamicFilter::cleanup(){ +void DynamicFilter::cleanup() +{ reinitfilter(); ms1=0.0; ms2=0.0; @@ -105,206 +109,236 @@ void DynamicFilter::cleanup(){ * Parameter control */ -void DynamicFilter::setdepth(const unsigned char &Pdepth){ +void DynamicFilter::setdepth(const unsigned char &Pdepth) +{ this->Pdepth=Pdepth; depth=pow((Pdepth/127.0),2.0); }; -void DynamicFilter::setvolume(const unsigned char &Pvolume){ +void DynamicFilter::setvolume(const unsigned char &Pvolume) +{ this->Pvolume=Pvolume; outvolume=Pvolume/127.0; if (insertion==0) volume=1.0; - else volume=outvolume; + else volume=outvolume; }; -void DynamicFilter::setpanning(const unsigned char &Ppanning){ +void DynamicFilter::setpanning(const unsigned char &Ppanning) +{ this->Ppanning=Ppanning; panning=Ppanning/127.0; }; -void DynamicFilter::setampsns(const unsigned char &Pampsns){ +void DynamicFilter::setampsns(const unsigned char &Pampsns) +{ ampsns=pow(Pampsns/127.0,2.5)*10.0; - if (Pampsnsinv!=0) ampsns=-ampsns; + if (Pampsnsinv!=0) ampsns=-ampsns; ampsmooth=exp(-Pampsmooth/127.0*10.0)*0.99; this->Pampsns=Pampsns; }; -void DynamicFilter::reinitfilter(){ +void DynamicFilter::reinitfilter() +{ if (filterl!=NULL) delete(filterl); if (filterr!=NULL) delete(filterr); filterl=new Filter(filterpars); filterr=new Filter(filterpars); }; -void DynamicFilter::setpreset(unsigned char npreset){ +void DynamicFilter::setpreset(unsigned char npreset) +{ const int PRESET_SIZE=10; const int NUM_PRESETS=5; unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ - //WahWah - {110,64,80,0,0,64,0,90,0,60}, - //AutoWah - {110,64,70,0,0,80,70,0,0,60}, - //Sweep - {100,64,30,0,0,50,80,0,0,60}, - //VocalMorph1 - {110,64,80,0,0,64,0,64,0,60}, - //VocalMorph1 - {127,64,50,0,0,96,64,0,0,60}}; - + //WahWah + {110,64,80,0,0,64,0,90,0,60}, + //AutoWah + {110,64,70,0,0,80,70,0,0,60}, + //Sweep + {100,64,30,0,0,50,80,0,0,60}, + //VocalMorph1 + {110,64,80,0,0,64,0,64,0,60}, + //VocalMorph1 + {127,64,50,0,0,96,64,0,0,60} + }; + if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]); - + filterpars->defaults(); - switch(npreset){ - case 0: - filterpars->Pcategory=0; - filterpars->Ptype=2; - filterpars->Pfreq=45; - filterpars->Pq=64; - filterpars->Pstages=1; - filterpars->Pgain=64; - break; - case 1: - filterpars->Pcategory=2; - filterpars->Ptype=0; - filterpars->Pfreq=72; - filterpars->Pq=64; - filterpars->Pstages=0; - filterpars->Pgain=64; - break; - case 2: - filterpars->Pcategory=0; - filterpars->Ptype=4; - filterpars->Pfreq=64; - filterpars->Pq=64; - filterpars->Pstages=2; - filterpars->Pgain=64; - break; - case 3: - filterpars->Pcategory=1; - filterpars->Ptype=0; - filterpars->Pfreq=50; - filterpars->Pq=70; - filterpars->Pstages=1; - filterpars->Pgain=64; - - filterpars->Psequencesize=2; - // "I" - filterpars->Pvowels[0].formants[0].freq=34; - filterpars->Pvowels[0].formants[0].amp=127; - filterpars->Pvowels[0].formants[0].q=64; - filterpars->Pvowels[0].formants[1].freq=99; - filterpars->Pvowels[0].formants[1].amp=122; - filterpars->Pvowels[0].formants[1].q=64; - filterpars->Pvowels[0].formants[2].freq=108; - filterpars->Pvowels[0].formants[2].amp=112; - filterpars->Pvowels[0].formants[2].q=64; - // "A" - filterpars->Pvowels[1].formants[0].freq=61; - filterpars->Pvowels[1].formants[0].amp=127; - filterpars->Pvowels[1].formants[0].q=64; - filterpars->Pvowels[1].formants[1].freq=71; - filterpars->Pvowels[1].formants[1].amp=121; - filterpars->Pvowels[1].formants[1].q=64; - filterpars->Pvowels[1].formants[2].freq=99; - filterpars->Pvowels[1].formants[2].amp=117; - filterpars->Pvowels[1].formants[2].q=64; - break; - case 4: - filterpars->Pcategory=1; - filterpars->Ptype=0; - filterpars->Pfreq=64; - filterpars->Pq=70; - filterpars->Pstages=1; - filterpars->Pgain=64; - - filterpars->Psequencesize=2; - filterpars->Pnumformants=2; - filterpars->Pvowelclearness=0; - - filterpars->Pvowels[0].formants[0].freq=70; - filterpars->Pvowels[0].formants[0].amp=127; - filterpars->Pvowels[0].formants[0].q=64; - filterpars->Pvowels[0].formants[1].freq=80; - filterpars->Pvowels[0].formants[1].amp=122; - filterpars->Pvowels[0].formants[1].q=64; - - filterpars->Pvowels[1].formants[0].freq=20; - filterpars->Pvowels[1].formants[0].amp=127; - filterpars->Pvowels[1].formants[0].q=64; - filterpars->Pvowels[1].formants[1].freq=100; - filterpars->Pvowels[1].formants[1].amp=121; - filterpars->Pvowels[1].formants[1].q=64; - break; + switch (npreset) { + case 0: + filterpars->Pcategory=0; + filterpars->Ptype=2; + filterpars->Pfreq=45; + filterpars->Pq=64; + filterpars->Pstages=1; + filterpars->Pgain=64; + break; + case 1: + filterpars->Pcategory=2; + filterpars->Ptype=0; + filterpars->Pfreq=72; + filterpars->Pq=64; + filterpars->Pstages=0; + filterpars->Pgain=64; + break; + case 2: + filterpars->Pcategory=0; + filterpars->Ptype=4; + filterpars->Pfreq=64; + filterpars->Pq=64; + filterpars->Pstages=2; + filterpars->Pgain=64; + break; + case 3: + filterpars->Pcategory=1; + filterpars->Ptype=0; + filterpars->Pfreq=50; + filterpars->Pq=70; + filterpars->Pstages=1; + filterpars->Pgain=64; + + filterpars->Psequencesize=2; + // "I" + filterpars->Pvowels[0].formants[0].freq=34; + filterpars->Pvowels[0].formants[0].amp=127; + filterpars->Pvowels[0].formants[0].q=64; + filterpars->Pvowels[0].formants[1].freq=99; + filterpars->Pvowels[0].formants[1].amp=122; + filterpars->Pvowels[0].formants[1].q=64; + filterpars->Pvowels[0].formants[2].freq=108; + filterpars->Pvowels[0].formants[2].amp=112; + filterpars->Pvowels[0].formants[2].q=64; + // "A" + filterpars->Pvowels[1].formants[0].freq=61; + filterpars->Pvowels[1].formants[0].amp=127; + filterpars->Pvowels[1].formants[0].q=64; + filterpars->Pvowels[1].formants[1].freq=71; + filterpars->Pvowels[1].formants[1].amp=121; + filterpars->Pvowels[1].formants[1].q=64; + filterpars->Pvowels[1].formants[2].freq=99; + filterpars->Pvowels[1].formants[2].amp=117; + filterpars->Pvowels[1].formants[2].q=64; + break; + case 4: + filterpars->Pcategory=1; + filterpars->Ptype=0; + filterpars->Pfreq=64; + filterpars->Pq=70; + filterpars->Pstages=1; + filterpars->Pgain=64; + + filterpars->Psequencesize=2; + filterpars->Pnumformants=2; + filterpars->Pvowelclearness=0; + + filterpars->Pvowels[0].formants[0].freq=70; + filterpars->Pvowels[0].formants[0].amp=127; + filterpars->Pvowels[0].formants[0].q=64; + filterpars->Pvowels[0].formants[1].freq=80; + filterpars->Pvowels[0].formants[1].amp=122; + filterpars->Pvowels[0].formants[1].q=64; + + filterpars->Pvowels[1].formants[0].freq=20; + filterpars->Pvowels[1].formants[0].amp=127; + filterpars->Pvowels[1].formants[0].q=64; + filterpars->Pvowels[1].formants[1].freq=100; + filterpars->Pvowels[1].formants[1].amp=121; + filterpars->Pvowels[1].formants[1].q=64; + break; }; - + // for (int i=0;i<5;i++){ // printf("freq=%d amp=%d q=%d\n",filterpars->Pvowels[0].formants[i].freq,filterpars->Pvowels[0].formants[i].amp,filterpars->Pvowels[0].formants[i].q); // }; if (insertion==0) changepar(0,presets[npreset][0]/2);//lower the volume if this is system effect Ppreset=npreset; - + reinitfilter(); }; -void DynamicFilter::changepar(const int &npar,const unsigned char &value){ - switch(npar){ - case 0: setvolume(value); - break; - case 1: setpanning(value); - break; - case 2: lfo.Pfreq=value; - lfo.updateparams(); - break; - case 3: lfo.Prandomness=value; - lfo.updateparams(); - break; - case 4: lfo.PLFOtype=value; - lfo.updateparams(); - break; - case 5: lfo.Pstereo=value; - lfo.updateparams(); - break; - case 6: setdepth(value); - break; - case 7: setampsns(value); - break; - case 8: Pampsnsinv=value; - setampsns(Pampsns); - break; - case 9: Pampsmooth=value; - setampsns(Pampsns); - break; +void DynamicFilter::changepar(const int &npar,const unsigned char &value) +{ + switch (npar) { + case 0: + setvolume(value); + break; + case 1: + setpanning(value); + break; + case 2: + lfo.Pfreq=value; + lfo.updateparams(); + break; + case 3: + lfo.Prandomness=value; + lfo.updateparams(); + break; + case 4: + lfo.PLFOtype=value; + lfo.updateparams(); + break; + case 5: + lfo.Pstereo=value; + lfo.updateparams(); + break; + case 6: + setdepth(value); + break; + case 7: + setampsns(value); + break; + case 8: + Pampsnsinv=value; + setampsns(Pampsns); + break; + case 9: + Pampsmooth=value; + setampsns(Pampsns); + break; }; }; -unsigned char DynamicFilter::getpar(const int &npar)const{ - switch (npar){ - case 0: return(Pvolume); - break; - case 1: return(Ppanning); - break; - case 2: return(lfo.Pfreq); - break; - case 3: return(lfo.Prandomness); - break; - case 4: return(lfo.PLFOtype); - break; - case 5: return(lfo.Pstereo); - break; - case 6: return(Pdepth); - break; - case 7: return(Pampsns); - break; - case 8: return(Pampsnsinv); - break; - case 9: return(Pampsmooth); - break; - default:return (0); +unsigned char DynamicFilter::getpar(const int &npar)const +{ + switch (npar) { + case 0: + return(Pvolume); + break; + case 1: + return(Ppanning); + break; + case 2: + return(lfo.Pfreq); + break; + case 3: + return(lfo.Prandomness); + break; + case 4: + return(lfo.PLFOtype); + break; + case 5: + return(lfo.Pstereo); + break; + case 6: + return(Pdepth); + break; + case 7: + return(Pampsns); + break; + case 8: + return(Pampsnsinv); + break; + case 9: + return(Pampsmooth); + break; + default: + return (0); }; - + }; diff --git a/src/Effects/DynamicFilter.h b/src/Effects/DynamicFilter.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + DynamicFilter.h - "WahWah" effect and others Copyright (C) 2002-2005 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 + 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, @@ -28,43 +28,44 @@ #include "../DSP/Filter.h" /**DynamicFilter Effect*/ -class DynamicFilter:public Effect { - public: - DynamicFilter(int insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); - ~DynamicFilter(); - void out(REALTYPE *smpsl,REALTYPE *smpsr); +class DynamicFilter:public Effect +{ +public: + DynamicFilter(int insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); + ~DynamicFilter(); + void out(REALTYPE *smpsl,REALTYPE *smpsr); - void setpreset(unsigned char npreset); - void changepar(const int &npar,const unsigned char &value); - unsigned char getpar(const int &npar)const; - void cleanup(); + void setpreset(unsigned char npreset); + void changepar(const int &npar,const unsigned char &value); + unsigned char getpar(const int &npar)const; + void cleanup(); // void setdryonly(); - - private: - //Parametrii DynamicFilter - EffectLFO lfo;//lfo-ul DynamicFilter - unsigned char Pvolume; - unsigned char Ppanning; - unsigned char Pdepth;/**<the depth of the lfo of the DynamicFilter*/ - unsigned char Pampsns;/**<how the filter varies according to the input amplitude*/ - unsigned char Pampsnsinv;//if the filter freq is lowered if the input amplitude rises - unsigned char Pampsmooth;//how smooth the input amplitude changes the filter - - //Parameter Control - void setvolume(const unsigned char &Pvolume); - void setpanning(const unsigned char &Ppanning); - void setdepth(const unsigned char &Pdepth); - void setampsns(const unsigned char &Pampsns); - - void reinitfilter(); - - //Internal Values - REALTYPE panning,depth,ampsns,ampsmooth; - - Filter *filterl,*filterr; - - REALTYPE ms1,ms2,ms3,ms4;//mean squares + +private: + //Parametrii DynamicFilter + EffectLFO lfo;//lfo-ul DynamicFilter + unsigned char Pvolume; + unsigned char Ppanning; + unsigned char Pdepth;/**<the depth of the lfo of the DynamicFilter*/ + unsigned char Pampsns;/**<how the filter varies according to the input amplitude*/ + unsigned char Pampsnsinv;//if the filter freq is lowered if the input amplitude rises + unsigned char Pampsmooth;//how smooth the input amplitude changes the filter + + //Parameter Control + void setvolume(const unsigned char &Pvolume); + void setpanning(const unsigned char &Ppanning); + void setdepth(const unsigned char &Pdepth); + void setampsns(const unsigned char &Pampsns); + + void reinitfilter(); + + //Internal Values + REALTYPE panning,depth,ampsns,ampsmooth; + + Filter *filterl,*filterr; + + REALTYPE ms1,ms2,ms3,ms4;//mean squares }; #endif diff --git a/src/Effects/EQ.C b/src/Effects/EQ.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + EQ.C - EQ effect Copyright (C) 2002-2005 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 + 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, @@ -24,35 +24,37 @@ #include "EQ.h" EQ::EQ(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) - :Effect(insertion_,efxoutl_,efxoutr_,NULL,0) + :Effect(insertion_,efxoutl_,efxoutr_,NULL,0) { - - for (int i=0;i<MAX_EQ_BANDS;i++){ - filter[i].Ptype=0; - filter[i].Pfreq=64; - filter[i].Pgain=64; - filter[i].Pq=64; - filter[i].Pstages=0; - filter[i].l=new AnalogFilter(6,1000.0,1.0,0); - filter[i].r=new AnalogFilter(6,1000.0,1.0,0); + + for (int i=0;i<MAX_EQ_BANDS;i++) { + filter[i].Ptype=0; + filter[i].Pfreq=64; + filter[i].Pgain=64; + filter[i].Pq=64; + filter[i].Pstages=0; + filter[i].l=new AnalogFilter(6,1000.0,1.0,0); + filter[i].r=new AnalogFilter(6,1000.0,1.0,0); }; //default values Pvolume=50; - - setpreset(Ppreset); + + setpreset(Ppreset); cleanup(); }; -EQ::~EQ(){ +EQ::~EQ() +{ }; /* * Cleanup the effect */ -void EQ::cleanup(){ - for (int i=0;i<MAX_EQ_BANDS;i++){ - filter[i].l->cleanup(); - filter[i].r->cleanup(); +void EQ::cleanup() +{ + for (int i=0;i<MAX_EQ_BANDS;i++) { + filter[i].l->cleanup(); + filter[i].r->cleanup(); }; }; @@ -61,17 +63,18 @@ void EQ::cleanup(){ /* * Effect output */ -void EQ::out(REALTYPE *smpsl,REALTYPE *smpsr){ +void EQ::out(REALTYPE *smpsl,REALTYPE *smpsr) +{ int i; - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - efxoutl[i]=smpsl[i]*volume; - efxoutr[i]=smpsr[i]*volume; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + efxoutl[i]=smpsl[i]*volume; + efxoutr[i]=smpsr[i]*volume; }; - - for (i=0;i<MAX_EQ_BANDS;i++){ - if (filter[i].Ptype==0) continue; - filter[i].l->filterout(efxoutl); - filter[i].r->filterout(efxoutr); + + for (i=0;i<MAX_EQ_BANDS;i++) { + if (filter[i].Ptype==0) continue; + filter[i].l->filterout(efxoutl); + filter[i].r->filterout(efxoutr); }; }; @@ -79,27 +82,30 @@ void EQ::out(REALTYPE *smpsl,REALTYPE *smpsr){ /* * Parameter control */ -void EQ::setvolume(const unsigned char &Pvolume){ +void EQ::setvolume(const unsigned char &Pvolume) +{ this->Pvolume=Pvolume; outvolume=pow(0.005,(1.0-Pvolume/127.0))*10.0; if (insertion==0) { - volume=1.0; + volume=1.0; } else { - volume=outvolume; + volume=outvolume; }; }; -void EQ::setpreset(unsigned char npreset){ +void EQ::setpreset(unsigned char npreset) +{ const int PRESET_SIZE=1; const int NUM_PRESETS=2; unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ - //EQ 1 - {67}, - //EQ 2 - {67}}; + //EQ 1 + {67}, + //EQ 2 + {67} + }; if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]); @@ -107,71 +113,85 @@ void EQ::setpreset(unsigned char npreset){ }; -void EQ::changepar(const int &npar,const unsigned char &value){ - switch (npar){ - case 0: setvolume(value); - break; +void EQ::changepar(const int &npar,const unsigned char &value) +{ + switch (npar) { + case 0: + setvolume(value); + break; }; if (npar<10) return; - + int nb=(npar-10)/5;//number of the band (filter) if (nb>=MAX_EQ_BANDS) return; int bp=npar%5;//band paramenter - + REALTYPE tmp; - switch(bp){ - case 0: filter[nb].Ptype=value; - if (value>9) filter[nb].Ptype=0;//has to be changed if more filters will be added - if (filter[nb].Ptype!=0){ - filter[nb].l->settype(value-1); - filter[nb].r->settype(value-1); - }; - break; - case 1: filter[nb].Pfreq=value; - tmp=600.0*pow(30.0,(value-64.0)/64.0); - filter[nb].l->setfreq(tmp); - filter[nb].r->setfreq(tmp); - break; - case 2: filter[nb].Pgain=value; - tmp=30.0*(value-64.0)/64.0; - filter[nb].l->setgain(tmp); - filter[nb].r->setgain(tmp); - break; - case 3: filter[nb].Pq=value; - tmp=pow(30.0,(value-64.0)/64.0); - filter[nb].l->setq(tmp); - filter[nb].r->setq(tmp); - break; - case 4: filter[nb].Pstages=value; - if (value>=MAX_FILTER_STAGES) filter[nb].Pstages=MAX_FILTER_STAGES-1; - filter[nb].l->setstages(value); - filter[nb].r->setstages(value); - break; + switch (bp) { + case 0: + filter[nb].Ptype=value; + if (value>9) filter[nb].Ptype=0;//has to be changed if more filters will be added + if (filter[nb].Ptype!=0) { + filter[nb].l->settype(value-1); + filter[nb].r->settype(value-1); + }; + break; + case 1: + filter[nb].Pfreq=value; + tmp=600.0*pow(30.0,(value-64.0)/64.0); + filter[nb].l->setfreq(tmp); + filter[nb].r->setfreq(tmp); + break; + case 2: + filter[nb].Pgain=value; + tmp=30.0*(value-64.0)/64.0; + filter[nb].l->setgain(tmp); + filter[nb].r->setgain(tmp); + break; + case 3: + filter[nb].Pq=value; + tmp=pow(30.0,(value-64.0)/64.0); + filter[nb].l->setq(tmp); + filter[nb].r->setq(tmp); + break; + case 4: + filter[nb].Pstages=value; + if (value>=MAX_FILTER_STAGES) filter[nb].Pstages=MAX_FILTER_STAGES-1; + filter[nb].l->setstages(value); + filter[nb].r->setstages(value); + break; }; }; -unsigned char EQ::getpar(const int &npar)const{ - switch (npar){ - case 0: return(Pvolume); - break; +unsigned char EQ::getpar(const int &npar)const +{ + switch (npar) { + case 0: + return(Pvolume); + break; }; if (npar<10) return(0); - + int nb=(npar-10)/5;//number of the band (filter) if (nb>=MAX_EQ_BANDS) return(0); int bp=npar%5;//band paramenter - switch(bp){ - case 0: return(filter[nb].Ptype); - break; - case 1: return(filter[nb].Pfreq); - break; - case 2: return(filter[nb].Pgain); - break; - case 3: return(filter[nb].Pq); - break; - case 4: return(filter[nb].Pstages); - break; + switch (bp) { + case 0: + return(filter[nb].Ptype); + break; + case 1: + return(filter[nb].Pfreq); + break; + case 2: + return(filter[nb].Pgain); + break; + case 3: + return(filter[nb].Pq); + break; + case 4: + return(filter[nb].Pstages); + break; }; return(0);//in case of bogus parameter number @@ -180,12 +200,13 @@ unsigned char EQ::getpar(const int &npar)const{ -REALTYPE EQ::getfreqresponse(REALTYPE freq){ +REALTYPE EQ::getfreqresponse(REALTYPE freq) +{ REALTYPE resp=1.0; - for (int i=0;i<MAX_EQ_BANDS;i++){ - if (filter[i].Ptype==0) continue; - resp*=filter[i].l->H(freq); + for (int i=0;i<MAX_EQ_BANDS;i++) { + if (filter[i].Ptype==0) continue; + resp*=filter[i].l->H(freq); }; return(rap2dB(resp*outvolume)); }; diff --git a/src/Effects/EQ.h b/src/Effects/EQ.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + EQ.h - EQ Effect Copyright (C) 2002-2005 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 + 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, @@ -28,29 +28,30 @@ #include "Effect.h" /**EQ Effect*/ -class EQ:public Effect{ - public: - EQ(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); - ~EQ(); - void out(REALTYPE *smpsl,REALTYPE *smpr); - void setpreset(unsigned char npreset); - void changepar(const int &npar,const unsigned char &value); - unsigned char getpar(const int &npar)const; - void cleanup(); - REALTYPE getfreqresponse(REALTYPE freq); - private: - //Parameters - unsigned char Pvolume;/**<Volume*/ - - void setvolume(const unsigned char &Pvolume); - - struct { - //parameters - unsigned char Ptype,Pfreq,Pgain,Pq,Pstages; - //internal values - AnalogFilter *l,*r; - }filter[MAX_EQ_BANDS]; - +class EQ:public Effect +{ +public: + EQ(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); + ~EQ(); + void out(REALTYPE *smpsl,REALTYPE *smpr); + void setpreset(unsigned char npreset); + void changepar(const int &npar,const unsigned char &value); + unsigned char getpar(const int &npar)const; + void cleanup(); + REALTYPE getfreqresponse(REALTYPE freq); +private: + //Parameters + unsigned char Pvolume;/**<Volume*/ + + void setvolume(const unsigned char &Pvolume); + + struct { + //parameters + unsigned char Ptype,Pfreq,Pgain,Pq,Pstages; + //internal values + AnalogFilter *l,*r; + }filter[MAX_EQ_BANDS]; + }; diff --git a/src/Effects/Echo.C b/src/Effects/Echo.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Echo.C - Echo effect Copyright (C) 2002-2005 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 + 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, @@ -25,21 +25,22 @@ #include "Echo.h" Echo::Echo(const int & insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_) - : Effect(insertion_,efxoutl_,efxoutr_,NULL,0), - Pvolume(50),Ppanning(64),//Pdelay(60), - Plrdelay(100),Plrcross(100),Pfb(40),Phidamp(60), - lrdelay(0),delaySample(1),old(0.0) + : Effect(insertion_,efxoutl_,efxoutr_,NULL,0), + Pvolume(50),Ppanning(64),//Pdelay(60), + Plrdelay(100),Plrcross(100),Pfb(40),Phidamp(60), + lrdelay(0),delaySample(1),old(0.0) { - setpreset(Ppreset); + setpreset(Ppreset); cleanup(); } -Echo::~Echo(){} +Echo::~Echo() {} /* * Cleanup the effect */ -void Echo::cleanup(){ +void Echo::cleanup() +{ delaySample.left().clear(); delaySample.right().clear(); old=Stereo<REALTYPE>(0.0); @@ -49,12 +50,16 @@ void Echo::cleanup(){ /* * Initialize the delays */ -void Echo::initdelays(){ - /**\todo make this adjust insted of destroy old delays*/ - kl=0;kr=0; - dl=(int)(1+delay.getiVal()*SAMPLE_RATE-lrdelay);if (dl<1) dl=1; - dr=(int)(1+delay.getiVal()*SAMPLE_RATE+lrdelay);if (dr<1) dr=1; - +void Echo::initdelays() +{ + /**\todo make this adjust insted of destroy old delays*/ + kl=0; + kr=0; + dl=(int)(1+delay.getiVal()*SAMPLE_RATE-lrdelay); + if (dl<1) dl=1; + dr=(int)(1+delay.getiVal()*SAMPLE_RATE+lrdelay); + if (dr<1) dr=1; + delaySample.left()=AuSample(dl); delaySample.right()=AuSample(dr); @@ -64,18 +69,20 @@ void Echo::initdelays(){ /* * Effect output */ -void Echo::out(REALTYPE *const smpsl,REALTYPE *const smpsr){ +void Echo::out(REALTYPE *const smpsl,REALTYPE *const smpsr) +{ //void Echo::out(const Stereo<AuSample> & input){ //ideal REALTYPE l,r,ldl,rdl;/**\todo move l+r->? ldl+rdl->?*/ Stereo<AuSample> input(AuSample(smpsl,SOUND_BUFFER_SIZE),AuSample(smpsr,SOUND_BUFFER_SIZE)); - for (int i=0;i<input.left().size();i++){ + for (int i=0;i<input.left().size();i++) { ldl=delaySample.left()[kl]; rdl=delaySample.right()[kr]; l=ldl*(1.0-lrcross)+rdl*lrcross; r=rdl*(1.0-lrcross)+ldl*lrcross; - ldl=l;rdl=r; - + ldl=l; + rdl=r; + efxoutl[i]=ldl*2.0; efxoutr[i]=rdl*2.0; @@ -92,14 +99,15 @@ void Echo::out(REALTYPE *const smpsl,REALTYPE *const smpsr){ if (++kl>=dl) kl=0; if (++kr>=dr) kr=0; }; - + } /* * Parameter control */ -void Echo::setvolume(const unsigned char & Pvolume){ +void Echo::setvolume(const unsigned char & Pvolume) +{ this->Pvolume=Pvolume; if (insertion==0) { @@ -112,43 +120,50 @@ void Echo::setvolume(const unsigned char & Pvolume){ } -void Echo::setpanning(const unsigned char & Ppanning){ +void Echo::setpanning(const unsigned char & Ppanning) +{ this->Ppanning=Ppanning; panning=(Ppanning+0.5)/127.0; } -void Echo::setdelay(const unsigned char & Pdelay){ +void Echo::setdelay(const unsigned char & Pdelay) +{ delay.setmVal(Pdelay); //this->Pdelay=Pdelay; //delay=1+(int)(Pdelay/127.0*SAMPLE_RATE*1.5);//0 .. 1.5 sec initdelays(); } -void Echo::setlrdelay(const unsigned char & Plrdelay){ +void Echo::setlrdelay(const unsigned char & Plrdelay) +{ REALTYPE tmp; - this->Plrdelay=Plrdelay; + this->Plrdelay=Plrdelay; tmp=(pow(2,fabs(Plrdelay-64.0)/64.0*9)-1.0)/1000.0*SAMPLE_RATE; if (Plrdelay<64.0) tmp=-tmp; lrdelay=(int) tmp; initdelays(); } -void Echo::setlrcross(const unsigned char & Plrcross){ +void Echo::setlrcross(const unsigned char & Plrcross) +{ this->Plrcross=Plrcross; lrcross=Plrcross/127.0*1.0; } -void Echo::setfb(const unsigned char & Pfb){ +void Echo::setfb(const unsigned char & Pfb) +{ this->Pfb=Pfb; fb=Pfb/128.0; } -void Echo::sethidamp(const unsigned char & Phidamp){ +void Echo::sethidamp(const unsigned char & Phidamp) +{ this->Phidamp=Phidamp; hidamp=1.0-Phidamp/127.0; } -void Echo::setpreset(unsigned char npreset){ +void Echo::setpreset(unsigned char npreset) +{ /**\todo see if the preset array can be replaced with a struct or a class*/ const int PRESET_SIZE=7; const int NUM_PRESETS=9; @@ -170,7 +185,8 @@ void Echo::setpreset(unsigned char npreset){ //Panning Echo 3 {81,60,26,100,127,67,36}, //Feedback Echo - {62,64,28,64,100,90,55}}; + {62,64,28,64,100,90,55} + }; if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; @@ -180,41 +196,57 @@ void Echo::setpreset(unsigned char npreset){ } -void Echo::changepar(const int & npar,const unsigned char & value){ - switch (npar){ - case 0: setvolume(value); - break; - case 1: setpanning(value); - break; - case 2: setdelay(value); - break; - case 3: setlrdelay(value); - break; - case 4: setlrcross(value); - break; - case 5: setfb(value); - break; - case 6: sethidamp(value); - break; +void Echo::changepar(const int & npar,const unsigned char & value) +{ + switch (npar) { + case 0: + setvolume(value); + break; + case 1: + setpanning(value); + break; + case 2: + setdelay(value); + break; + case 3: + setlrdelay(value); + break; + case 4: + setlrcross(value); + break; + case 5: + setfb(value); + break; + case 6: + sethidamp(value); + break; }; } -unsigned char Echo::getpar(const int & npar)const{ - switch (npar){ - case 0: return(Pvolume); - break; - case 1: return(Ppanning); - break; - case 2: return(delay.getmVal()); - break; - case 3: return(Plrdelay); - break; - case 4: return(Plrcross); - break; - case 5: return(Pfb); - break; - case 6: return(Phidamp); - break; +unsigned char Echo::getpar(const int & npar)const +{ + switch (npar) { + case 0: + return(Pvolume); + break; + case 1: + return(Ppanning); + break; + case 2: + return(delay.getmVal()); + break; + case 3: + return(Plrdelay); + break; + case 4: + return(Plrcross); + break; + case 5: + return(Pfb); + break; + case 6: + return(Phidamp); + break; }; return(0);// in case of bogus parameter number } diff --git a/src/Effects/Echo.h b/src/Effects/Echo.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Echo.h - Echo Effect Copyright (C) 2002-2005 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 + 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, @@ -30,105 +30,106 @@ #include "../Controls/DelayCtl.h" /**Echo Effect*/ -class Echo:public Effect{ - public: - - /** - * The Constructor For Echo - * @param insertion_ integer to determine if Echo is an insertion effect - * or not - * @param efxoutl_ Effect out Left Channel - * @param efxoutr_ Effect out Right Channel - * @return An initialized Echo Object - */ - Echo(const int & insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_); - - /** - * The destructor - */ - ~Echo(); - - /** - * Outputs the echo to efxoutl and efxoutr - * @param smpsl Sample from Left channel - * @param smpsr Sample from Right channel - * \todo try to figure out if smpsl should be const *const - * or not (It should be) - */ - void out(REALTYPE *const smpsl,REALTYPE *const smpr); - - /** - * Sets the state of Echo to the specified preset - * @param npreset number of chosen preset - */ - void setpreset(unsigned char npreset); - - /** - * Sets the value of the chosen variable - * - * The possible parameters are: - * -# Volume - * -# Panning - * -# Delay - * -# L/R Delay - * -# L/R Crossover - * -# Feedback - * -# Dampening - * @param npar number of chosen parameter - * @param value the new value - */ - void changepar(const int & npar,const unsigned char & value); - - /** - * Gets the specified parameter - * - * The possible parameters are - * -# Volume - * -# Panning - * -# Delay - * -# L/R Delay - * -# L/R Crossover - * -# Feedback - * -# Dampening - * @param npar number of chosen parameter - * @return value of parameter - */ - unsigned char getpar(const int & npar)const; - - int getnumparams(); - - /**Zeros out the state of the Echo*/ - void cleanup(); - - /**\todo This function needs to be implemented or the prototype should be removed*/ - void setdryonly(); - private: - //Parameters - char Pvolume;/**<#1 Volume or Dry/Wetness*/ - char Ppanning;/**<#2 Panning*/ - DelayCtl delay;/**<#3 Delay of the Echo*/ - char Plrdelay;/**<#4 L/R delay difference*/ - char Plrcross;/**<#5 L/R Mixing*/ - char Pfb;/**<#6Feedback*/ - char Phidamp;/**<#7Dampening of the Echo*/ - - void setvolume(const unsigned char & Pvolume); - void setpanning(const unsigned char & Ppanning); - void setdelay(const unsigned char & Pdelay); - void setlrdelay(const unsigned char & Plrdelay); - void setlrcross(const unsigned char & Plrcross); - void setfb(const unsigned char & Pfb); - void sethidamp(const unsigned char & Phidamp); - - //Real Parameters - REALTYPE panning,lrcross,fb,hidamp; //needs better names - int dl,dr,lrdelay; //needs better names - - void initdelays(); - Stereo<AuSample> delaySample; - Stereo<REALTYPE> old; - - int kl,kr; +class Echo:public Effect +{ +public: + + /** + * The Constructor For Echo + * @param insertion_ integer to determine if Echo is an insertion effect + * or not + * @param efxoutl_ Effect out Left Channel + * @param efxoutr_ Effect out Right Channel + * @return An initialized Echo Object + */ + Echo(const int & insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_); + + /** + * The destructor + */ + ~Echo(); + + /** + * Outputs the echo to efxoutl and efxoutr + * @param smpsl Sample from Left channel + * @param smpsr Sample from Right channel + * \todo try to figure out if smpsl should be const *const + * or not (It should be) + */ + void out(REALTYPE *const smpsl,REALTYPE *const smpr); + + /** + * Sets the state of Echo to the specified preset + * @param npreset number of chosen preset + */ + void setpreset(unsigned char npreset); + + /** + * Sets the value of the chosen variable + * + * The possible parameters are: + * -# Volume + * -# Panning + * -# Delay + * -# L/R Delay + * -# L/R Crossover + * -# Feedback + * -# Dampening + * @param npar number of chosen parameter + * @param value the new value + */ + void changepar(const int & npar,const unsigned char & value); + + /** + * Gets the specified parameter + * + * The possible parameters are + * -# Volume + * -# Panning + * -# Delay + * -# L/R Delay + * -# L/R Crossover + * -# Feedback + * -# Dampening + * @param npar number of chosen parameter + * @return value of parameter + */ + unsigned char getpar(const int & npar)const; + + int getnumparams(); + + /**Zeros out the state of the Echo*/ + void cleanup(); + + /**\todo This function needs to be implemented or the prototype should be removed*/ + void setdryonly(); +private: + //Parameters + char Pvolume;/**<#1 Volume or Dry/Wetness*/ + char Ppanning;/**<#2 Panning*/ + DelayCtl delay;/**<#3 Delay of the Echo*/ + char Plrdelay;/**<#4 L/R delay difference*/ + char Plrcross;/**<#5 L/R Mixing*/ + char Pfb;/**<#6Feedback*/ + char Phidamp;/**<#7Dampening of the Echo*/ + + void setvolume(const unsigned char & Pvolume); + void setpanning(const unsigned char & Ppanning); + void setdelay(const unsigned char & Pdelay); + void setlrdelay(const unsigned char & Plrdelay); + void setlrcross(const unsigned char & Plrcross); + void setfb(const unsigned char & Pfb); + void sethidamp(const unsigned char & Phidamp); + + //Real Parameters + REALTYPE panning,lrcross,fb,hidamp; //needs better names + int dl,dr,lrdelay; //needs better names + + void initdelays(); + Stereo<AuSample> delaySample; + Stereo<REALTYPE> old; + + int kl,kr; }; #endif diff --git a/src/Effects/Effect.C b/src/Effects/Effect.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Effect.C - this class is inherited by the all effects(Reverb, Echo, ..) Copyright (C) 2002-2005 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 + 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, @@ -22,9 +22,9 @@ #include "Effect.h" - + Effect::Effect(bool insertion_,REALTYPE *const efxoutl_, REALTYPE *const efxoutr_,FilterParams *filterpars_, const unsigned char & Ppreset_) - :Ppreset(Ppreset_),efxoutl(efxoutl_),efxoutr(efxoutr_), - filterpars(filterpars_),insertion(insertion_){} + :Ppreset(Ppreset_),efxoutl(efxoutl_),efxoutr(efxoutr_), + filterpars(filterpars_),insertion(insertion_) {} diff --git a/src/Effects/Effect.h b/src/Effects/Effect.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Effect.h - this class is inherited by the all effects(Reverb, Echo, ..) Copyright (C) 2002-2005 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 + 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, @@ -29,70 +29,73 @@ /**this class is inherited by the all effects(Reverb, Echo, ..)*/ -class Effect{ - public: - /** - * Effect Constructor - * @param insertion_ 1 when it is an insertion Effect and 0 when it - * is not an insertion Effect - * @param efxoutl_ Effect output buffer Left channel - * @param efxoutr_ Effect output buffer Right channel - * @param filterpars_ pointer to FilterParams array - * @param Ppreset_ chosen preset - * @return Initialized Effect object*/ - Effect(bool insertion_,REALTYPE *const efxoutl_, - REALTYPE *const efxoutr_,FilterParams *filterpars_, - const unsigned char & Ppreset_); - /**Deconstructor - * - * Deconstructs the Effect and releases any resouces that it has - * allocated for itself*/ - virtual ~Effect(){}; - /** - * Choose a preset - * @param npreset number of chosen preset*/ - virtual void setpreset(unsigned char npreset)=0; - /**Change parameter npar to value - * @param npar chosen parameter - * @param value chosen new value*/ - virtual void changepar(const int &npar,const unsigned char &value)=0; - /**Get the value of parameter npar - * @param npar chosen parameter - * @return the value of the parameter in an unsigned char or 0 if it - * does not exist*/ - virtual unsigned char getpar(const int &npar)const=0; - /**Output result of effect based on the given buffers - * - * This method should result in the effect generating its results - * and placing them into the efxoutl and efxoutr buffers. - * Every Effect should overide this method. - * - * @param smpsl Input buffer for the Left channel - * @param smpsr Input buffer for the Right channel - */ - virtual void out(REALTYPE *const smpsl,REALTYPE *const smpsr)=0; - /**Reset the state of the effect*/ - virtual void cleanup(){}; - /**This is only used for EQ (for user interface)*/ - virtual REALTYPE getfreqresponse(REALTYPE freq){return (0);}; - - unsigned char Ppreset;/**<Currently used preset*/ - REALTYPE *const efxoutl;/**<Effect out Left Channel*/ - REALTYPE *const efxoutr;/**<Effect out Right Channel*/ - /**\todo make efxoutl and efxoutr private and replace them with a StereoSample*/ - - REALTYPE outvolume;/**<This is the volume of effect and is public because +class Effect +{ +public: + /** + * Effect Constructor + * @param insertion_ 1 when it is an insertion Effect and 0 when it + * is not an insertion Effect + * @param efxoutl_ Effect output buffer Left channel + * @param efxoutr_ Effect output buffer Right channel + * @param filterpars_ pointer to FilterParams array + * @param Ppreset_ chosen preset + * @return Initialized Effect object*/ + Effect(bool insertion_,REALTYPE *const efxoutl_, + REALTYPE *const efxoutr_,FilterParams *filterpars_, + const unsigned char & Ppreset_); + /**Deconstructor + * + * Deconstructs the Effect and releases any resouces that it has + * allocated for itself*/ + virtual ~Effect() {}; + /** + * Choose a preset + * @param npreset number of chosen preset*/ + virtual void setpreset(unsigned char npreset)=0; + /**Change parameter npar to value + * @param npar chosen parameter + * @param value chosen new value*/ + virtual void changepar(const int &npar,const unsigned char &value)=0; + /**Get the value of parameter npar + * @param npar chosen parameter + * @return the value of the parameter in an unsigned char or 0 if it + * does not exist*/ + virtual unsigned char getpar(const int &npar)const=0; + /**Output result of effect based on the given buffers + * + * This method should result in the effect generating its results + * and placing them into the efxoutl and efxoutr buffers. + * Every Effect should overide this method. + * + * @param smpsl Input buffer for the Left channel + * @param smpsr Input buffer for the Right channel + */ + virtual void out(REALTYPE *const smpsl,REALTYPE *const smpsr)=0; + /**Reset the state of the effect*/ + virtual void cleanup() {}; + /**This is only used for EQ (for user interface)*/ + virtual REALTYPE getfreqresponse(REALTYPE freq) { + return (0); + }; + + unsigned char Ppreset;/**<Currently used preset*/ + REALTYPE *const efxoutl;/**<Effect out Left Channel*/ + REALTYPE *const efxoutr;/**<Effect out Right Channel*/ + /**\todo make efxoutl and efxoutr private and replace them with a StereoSample*/ + + REALTYPE outvolume;/**<This is the volume of effect and is public because * it is needed in system effects. * The out volume of such effects are always 1.0, so * this setting tells me how is the volume to the * Master Output only.*/ - REALTYPE volume; + REALTYPE volume; - FilterParams *filterpars;/**<Parameters for filters used by Effect*/ - protected: + FilterParams *filterpars;/**<Parameters for filters used by Effect*/ +protected: - const bool insertion;/**<If Effect is an insertion effect, insertion=1 + const bool insertion;/**<If Effect is an insertion effect, insertion=1 *otherwise, it should be insertion=0*/ }; diff --git a/src/Effects/EffectLFO.C b/src/Effects/EffectLFO.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + EffectLFO.C - Stereo LFO used by some effects Copyright (C) 2002-2005 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 + 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, @@ -26,13 +26,15 @@ #include "EffectLFO.h" -EffectLFO::EffectLFO(){ - xl=0.0;xr=0.0; +EffectLFO::EffectLFO() +{ + xl=0.0; + xr=0.0; Pfreq=40; Prandomness=0; PLFOtype=0; Pstereo=96; - + updateparams(); ampl1=(1-lfornd)+lfornd*RND; @@ -41,20 +43,23 @@ EffectLFO::EffectLFO(){ ampr2=(1-lfornd)+lfornd*RND; }; -EffectLFO::~EffectLFO(){ +EffectLFO::~EffectLFO() +{ }; /* * Update the changed parameters */ -void EffectLFO::updateparams(){ +void EffectLFO::updateparams() +{ REALTYPE lfofreq=(pow(2,Pfreq/127.0*10.0)-1.0)*0.03; incx=fabs(lfofreq)*(REALTYPE)SOUND_BUFFER_SIZE/(REALTYPE)SAMPLE_RATE; if (incx>0.49999999) incx=0.499999999; //Limit the Frequency lfornd=Prandomness/127.0; - if (lfornd<0.0) lfornd=0.0; else if (lfornd>1.0) lfornd=1.0; + if (lfornd<0.0) lfornd=0.0; + else if (lfornd>1.0) lfornd=1.0; if (PLFOtype>1) PLFOtype=1;//this has to be updated if more lfo's are added lfotype=PLFOtype; @@ -66,16 +71,18 @@ void EffectLFO::updateparams(){ /* * Compute the shape of the LFO */ -REALTYPE EffectLFO::getlfoshape(REALTYPE x){ +REALTYPE EffectLFO::getlfoshape(REALTYPE x) +{ REALTYPE out; - switch (lfotype){ - case 1: //EffectLFO_TRIANGLE - if ((x>0.0)&&(x<0.25)) out=4.0*x; - else if ((x>0.25)&&(x<0.75)) out=2-4*x; - else out=4.0*x-4.0; - break; - /**\todo more to be added here; also ::updateparams() need to be updated (to allow more lfotypes)*/ - default:out=cos(x*2*PI);//EffectLFO_SINE + switch (lfotype) { + case 1: //EffectLFO_TRIANGLE + if ((x>0.0)&&(x<0.25)) out=4.0*x; + else if ((x>0.25)&&(x<0.75)) out=2-4*x; + else out=4.0*x-4.0; + break; + /**\todo more to be added here; also ::updateparams() need to be updated (to allow more lfotypes)*/ + default: + out=cos(x*2*PI);//EffectLFO_SINE }; return(out); }; @@ -83,16 +90,17 @@ REALTYPE EffectLFO::getlfoshape(REALTYPE x){ /* * LFO output */ -void EffectLFO::effectlfoout(REALTYPE *outl,REALTYPE *outr){ - REALTYPE out; - +void EffectLFO::effectlfoout(REALTYPE *outl,REALTYPE *outr) +{ + REALTYPE out; + out=getlfoshape(xl); if ((lfotype==0)||(lfotype==1)) out*=(ampl1+xl*(ampl2-ampl1)); xl+=incx; if (xl>1.0) { - xl-=1.0; - ampl1=ampl2; - ampl2=(1.0-lfornd)+lfornd*RND; + xl-=1.0; + ampl1=ampl2; + ampl2=(1.0-lfornd)+lfornd*RND; }; *outl=(out+1.0)*0.5; @@ -100,9 +108,9 @@ void EffectLFO::effectlfoout(REALTYPE *outl,REALTYPE *outr){ if ((lfotype==0)||(lfotype==1)) out*=(ampr1+xr*(ampr2-ampr1)); xr+=incx; if (xr>1.0) { - xr-=1.0; - ampr1=ampr2; - ampr2=(1.0-lfornd)+lfornd*RND; + xr-=1.0; + ampr1=ampr2; + ampr2=(1.0-lfornd)+lfornd*RND; }; *outr=(out+1.0)*0.5; }; diff --git a/src/Effects/EffectLFO.h b/src/Effects/EffectLFO.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + EffectLFO.h - Stereo LFO used by some effects Copyright (C) 2002-2005 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 + 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, @@ -26,8 +26,9 @@ #include "../globals.h" /**LFO for some of the Effect objects * \todo see if this should inherit LFO*/ -class EffectLFO{ - public: +class EffectLFO +{ +public: EffectLFO(); ~EffectLFO(); void effectlfoout(REALTYPE *outl,REALTYPE *outr); @@ -36,9 +37,9 @@ class EffectLFO{ unsigned char Prandomness; unsigned char PLFOtype; unsigned char Pstereo;//"64"=0 - private: +private: REALTYPE getlfoshape(REALTYPE x); - + REALTYPE xl,xr; REALTYPE incx; REALTYPE ampl1,ampl2,ampr1,ampr2;//necessary for "randomness" diff --git a/src/Effects/EffectMgr.C b/src/Effects/EffectMgr.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + EffectMgr.C - Effect manager, an interface betwen the program and effects Copyright (C) 2002-2005 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 + 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, @@ -23,10 +23,10 @@ #include "EffectMgr.h" EffectMgr::EffectMgr(int insertion_,pthread_mutex_t *mutex_) - :insertion(insertion_), - efxoutl(new REALTYPE[SOUND_BUFFER_SIZE]), - efxoutr(new REALTYPE[SOUND_BUFFER_SIZE]), - filterpars(NULL),nefx(0),efx(NULL),mutex(mutex_),dryonly(false) + :insertion(insertion_), + efxoutl(new REALTYPE[SOUND_BUFFER_SIZE]), + efxoutr(new REALTYPE[SOUND_BUFFER_SIZE]), + filterpars(NULL),nefx(0),efx(NULL),mutex(mutex_),dryonly(false) { setpresettype("Peffect"); /**\todo Figure out what this is doing * , as it might be another leaky abstraction.*/ @@ -36,9 +36,9 @@ EffectMgr::EffectMgr(int insertion_,pthread_mutex_t *mutex_) // mutex=mutex_; // efxoutl=new REALTYPE[SOUND_BUFFER_SIZE]; // efxoutr=new REALTYPE[SOUND_BUFFER_SIZE]; - for (int i=0;i<SOUND_BUFFER_SIZE;i++){ - efxoutl[i]=0.0; - efxoutr[i]=0.0; + for (int i=0;i<SOUND_BUFFER_SIZE;i++) { + efxoutl[i]=0.0; + efxoutr[i]=0.0; }; // filterpars=NULL; // dryonly=false; @@ -46,13 +46,15 @@ EffectMgr::EffectMgr(int insertion_,pthread_mutex_t *mutex_) } -EffectMgr::~EffectMgr(){ +EffectMgr::~EffectMgr() +{ if (efx!=NULL) delete efx; delete []efxoutl; delete []efxoutr; } -void EffectMgr::defaults(){ +void EffectMgr::defaults() +{ changeeffect(0); setdryonly(false); } @@ -60,43 +62,64 @@ void EffectMgr::defaults(){ /* * Change the effect */ -void EffectMgr::changeeffect(int nefx_){ +void EffectMgr::changeeffect(int nefx_) +{ cleanup(); if (nefx==nefx_) return; nefx=nefx_; - for (int i=0;i<SOUND_BUFFER_SIZE;i++){ - efxoutl[i]=0.0; - efxoutr[i]=0.0; + for (int i=0;i<SOUND_BUFFER_SIZE;i++) { + efxoutl[i]=0.0; + efxoutr[i]=0.0; }; if (efx!=NULL) delete efx; - switch (nefx){ /**\todo replace leaky abstraction*/ - case 1:efx=new Reverb(insertion,efxoutl,efxoutr);break; - case 2:efx=new Echo(insertion,efxoutl,efxoutr);break; - case 3:efx=new Chorus(insertion,efxoutl,efxoutr);break; - case 4:efx=new Phaser(insertion,efxoutl,efxoutr);break; - case 5:efx=new Alienwah(insertion,efxoutl,efxoutr);break; - case 6:efx=new Distorsion(insertion,efxoutl,efxoutr);break; - case 7:efx=new EQ(insertion,efxoutl,efxoutr);break; - case 8:efx=new DynamicFilter(insertion,efxoutl,efxoutr);break; - //put more effect here - default:efx=NULL;break;//no effect (thru) + switch (nefx) { /**\todo replace leaky abstraction*/ + case 1: + efx=new Reverb(insertion,efxoutl,efxoutr); + break; + case 2: + efx=new Echo(insertion,efxoutl,efxoutr); + break; + case 3: + efx=new Chorus(insertion,efxoutl,efxoutr); + break; + case 4: + efx=new Phaser(insertion,efxoutl,efxoutr); + break; + case 5: + efx=new Alienwah(insertion,efxoutl,efxoutr); + break; + case 6: + efx=new Distorsion(insertion,efxoutl,efxoutr); + break; + case 7: + efx=new EQ(insertion,efxoutl,efxoutr); + break; + case 8: + efx=new DynamicFilter(insertion,efxoutl,efxoutr); + break; + //put more effect here + default: + efx=NULL; + break;//no effect (thru) }; - + if (efx!=NULL) filterpars=efx->filterpars; } /* * Obtain the effect number */ -int EffectMgr::geteffect(){ +int EffectMgr::geteffect() +{ return (nefx); } /* * Cleanup the current effect */ -void EffectMgr::cleanup(){ +void EffectMgr::cleanup() +{ if (efx!=NULL) efx->cleanup(); } @@ -104,23 +127,26 @@ void EffectMgr::cleanup(){ /* * Get the preset of the current effect */ - -unsigned char EffectMgr::getpreset(){ + +unsigned char EffectMgr::getpreset() +{ if (efx!=NULL) return(efx->Ppreset); - else return(0); + else return(0); } /* * Change the preset of the current effect */ -void EffectMgr::changepreset_nolock(unsigned char npreset){ +void EffectMgr::changepreset_nolock(unsigned char npreset) +{ if (efx!=NULL) efx->setpreset(npreset); } /* * Change the preset of the current effect(with thread locking) */ -void EffectMgr::changepreset(unsigned char npreset){ +void EffectMgr::changepreset(unsigned char npreset) +{ pthread_mutex_lock(mutex); changepreset_nolock(npreset); pthread_mutex_unlock(mutex); @@ -128,9 +154,10 @@ void EffectMgr::changepreset(unsigned char npreset){ /* - * Change a parameter of the current effect + * Change a parameter of the current effect */ -void EffectMgr::seteffectpar_nolock(int npar,unsigned char value){ +void EffectMgr::seteffectpar_nolock(int npar,unsigned char value) +{ if (efx==NULL) return; efx->changepar(npar,value); } @@ -138,7 +165,8 @@ void EffectMgr::seteffectpar_nolock(int npar,unsigned char value){ /* * Change a parameter of the current effect (with thread locking) */ -void EffectMgr::seteffectpar(int npar,unsigned char value){ +void EffectMgr::seteffectpar(int npar,unsigned char value) +{ pthread_mutex_lock(mutex); seteffectpar_nolock(npar,value); pthread_mutex_unlock(mutex); @@ -147,7 +175,8 @@ void EffectMgr::seteffectpar(int npar,unsigned char value){ /* * Get a parameter of the current effect */ -unsigned char EffectMgr::geteffectpar(int npar){ +unsigned char EffectMgr::geteffectpar(int npar) +{ if (efx==NULL) return(0); return(efx->getpar(npar)); } @@ -156,139 +185,147 @@ unsigned char EffectMgr::geteffectpar(int npar){ /* * Apply the effect */ -void EffectMgr::out(REALTYPE *smpsl,REALTYPE *smpsr){ +void EffectMgr::out(REALTYPE *smpsl,REALTYPE *smpsr) +{ int i; - if (efx==NULL){ - if (insertion==0) - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - smpsl[i]=0.0;smpsr[i]=0.0; - efxoutl[i]=0.0;efxoutr[i]=0.0; - }; - return; + if (efx==NULL) { + if (insertion==0) + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + smpsl[i]=0.0; + smpsr[i]=0.0; + efxoutl[i]=0.0; + efxoutr[i]=0.0; + }; + return; }; - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - smpsl[i]+=denormalkillbuf[i]; - smpsr[i]+=denormalkillbuf[i]; - efxoutl[i]=0.0; - efxoutr[i]=0.0; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + smpsl[i]+=denormalkillbuf[i]; + smpsr[i]+=denormalkillbuf[i]; + efxoutl[i]=0.0; + efxoutr[i]=0.0; }; efx->out(smpsl,smpsr); - + REALTYPE volume=efx->volume; - - if (nefx==7){//this is need only for the EQ effect - /**\todo figure out why*/ - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - smpsl[i]=efxoutl[i]; - smpsr[i]=efxoutr[i]; - }; - return; + + if (nefx==7) {//this is need only for the EQ effect + /**\todo figure out why*/ + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + smpsl[i]=efxoutl[i]; + smpsr[i]=efxoutr[i]; + }; + return; }; - + //Insertion effect if (insertion!=0) { REALTYPE v1,v2; - if (volume<0.5) { - v1=1.0; - v2=volume*2.0; - } else { - v1=(1.0-volume)*2.0; - v2=1.0; - }; - if ((nefx==1)||(nefx==2)) v2*=v2;//for Reverb and Echo, the wet function is not liniar - - if (dryonly){//this is used for instrument effect only - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - smpsl[i]*=v1; - smpsr[i]*=v1; - efxoutl[i]*=v2; - efxoutr[i]*=v2; - }; - }else{//normal instrument/insertion effect - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - smpsl[i]=smpsl[i]*v1+efxoutl[i]*v2; - smpsr[i]=smpsr[i]*v1+efxoutr[i]*v2; - }; - }; + if (volume<0.5) { + v1=1.0; + v2=volume*2.0; + } else { + v1=(1.0-volume)*2.0; + v2=1.0; + }; + if ((nefx==1)||(nefx==2)) v2*=v2;//for Reverb and Echo, the wet function is not liniar + + if (dryonly) {//this is used for instrument effect only + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + smpsl[i]*=v1; + smpsr[i]*=v1; + efxoutl[i]*=v2; + efxoutr[i]*=v2; + }; + } else {//normal instrument/insertion effect + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + smpsl[i]=smpsl[i]*v1+efxoutl[i]*v2; + smpsr[i]=smpsr[i]*v1+efxoutr[i]*v2; + }; + }; } else {//System effect - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - efxoutl[i]*=2.0*volume; - efxoutr[i]*=2.0*volume; - smpsl[i]=efxoutl[i]; - smpsr[i]=efxoutr[i]; - }; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + efxoutl[i]*=2.0*volume; + efxoutr[i]*=2.0*volume; + smpsl[i]=efxoutl[i]; + smpsr[i]=efxoutr[i]; + }; }; - + } /* * Get the effect volume for the system effect */ -REALTYPE EffectMgr::sysefxgetvolume(){ +REALTYPE EffectMgr::sysefxgetvolume() +{ if (efx==NULL) return (1.0); - else return(efx->outvolume); + else return(efx->outvolume); } /* * Get the EQ response */ -REALTYPE EffectMgr::getEQfreqresponse(REALTYPE freq){ +REALTYPE EffectMgr::getEQfreqresponse(REALTYPE freq) +{ if (nefx==7) return(efx->getfreqresponse(freq)); - else return(0.0); + else return(0.0); } -void EffectMgr::setdryonly(bool value){ +void EffectMgr::setdryonly(bool value) +{ dryonly=value; } -void EffectMgr::add2XML(XMLwrapper *xml){ +void EffectMgr::add2XML(XMLwrapper *xml) +{ xml->addpar("type",geteffect()); if ((efx==NULL)||(geteffect()==0)) return; xml->addpar("preset",efx->Ppreset); xml->beginbranch("EFFECT_PARAMETERS"); - for (int n=0;n<128;n++){ /**\todo evaluate who should oversee saving + for (int n=0;n<128;n++) { /**\todo evaluate who should oversee saving * and loading of parameters*/ - int par=geteffectpar(n); - if (par==0) continue; - xml->beginbranch("par_no",n); - xml->addpar("par",par); - xml->endbranch(); - }; - if (filterpars!=NULL){ - xml->beginbranch("FILTER"); - filterpars->add2XML(xml); - xml->endbranch(); - }; + int par=geteffectpar(n); + if (par==0) continue; + xml->beginbranch("par_no",n); + xml->addpar("par",par); + xml->endbranch(); + }; + if (filterpars!=NULL) { + xml->beginbranch("FILTER"); + filterpars->add2XML(xml); + xml->endbranch(); + }; xml->endbranch(); } -void EffectMgr::getfromXML(XMLwrapper *xml){ +void EffectMgr::getfromXML(XMLwrapper *xml) +{ changeeffect(xml->getpar127("type",geteffect())); if ((efx==NULL)||(geteffect()==0)) return; - + efx->Ppreset=xml->getpar127("preset",efx->Ppreset); - if (xml->enterbranch("EFFECT_PARAMETERS")){ - for (int n=0;n<128;n++){ - seteffectpar_nolock(n,0);//erase effect parameter - if (xml->enterbranch("par_no",n)==0) continue; - - int par=geteffectpar(n); - seteffectpar_nolock(n,xml->getpar127("par",par)); - xml->exitbranch(); - }; - if (filterpars!=NULL){ - if (xml->enterbranch("FILTER")){ - filterpars->getfromXML(xml); - xml->exitbranch(); - }; - }; - xml->exitbranch(); + if (xml->enterbranch("EFFECT_PARAMETERS")) { + for (int n=0;n<128;n++) { + seteffectpar_nolock(n,0);//erase effect parameter + if (xml->enterbranch("par_no",n)==0) continue; + + int par=geteffectpar(n); + seteffectpar_nolock(n,xml->getpar127("par",par)); + xml->exitbranch(); + }; + if (filterpars!=NULL) { + if (xml->enterbranch("FILTER")) { + filterpars->getfromXML(xml); + xml->exitbranch(); + }; + }; + xml->exitbranch(); }; cleanup(); } diff --git a/src/Effects/EffectMgr.h b/src/Effects/EffectMgr.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + EffectMgr.h - Effect manager, an interface betwen the program and effects Copyright (C) 2002-2005 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 + 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, @@ -39,63 +39,64 @@ /**Effect manager, an interface betwen the program and effects*/ -class EffectMgr:public Presets{ - public: - EffectMgr(int insertion_,pthread_mutex_t *mutex_); - ~EffectMgr(); +class EffectMgr:public Presets +{ +public: + EffectMgr(int insertion_,pthread_mutex_t *mutex_); + ~EffectMgr(); + + void add2XML(XMLwrapper *xml); + void defaults(); + void getfromXML(XMLwrapper *xml); - void add2XML(XMLwrapper *xml); - void defaults(); - void getfromXML(XMLwrapper *xml); + void out(REALTYPE *smpsl,REALTYPE *smpsr); - void out(REALTYPE *smpsl,REALTYPE *smpsr); + void setdryonly(bool value); - void setdryonly(bool value); - - /**get the output(to speakers) volume of the systemeffect*/ - REALTYPE sysefxgetvolume(); + /**get the output(to speakers) volume of the systemeffect*/ + REALTYPE sysefxgetvolume(); - void cleanup();/**<cleanup the effect*/ + void cleanup();/**<cleanup the effect*/ - /**change effect to the given int + /**change effect to the given int * @param nefx_ the number of the effect*/ - void changeeffect(int nefx_); - /**Get the number of the effect - * @return the number*/ - int geteffect(); - /** - * Change the preset to the given one - * @param npreset number of the chosen preset - */ - void changepreset(unsigned char npreset); - /** - * Change the preset to the given one without locking the thread - * @param npreset number of the chosen preset - */ - void changepreset_nolock(unsigned char npreset); - /** - * Get the current preset - * @return the current preset*/ - unsigned char getpreset(); - /**sets the effect par*/ - void seteffectpar(int npar,unsigned char value); - /**<sets the effect par without thread lock*/ - void seteffectpar_nolock(int npar,unsigned char value); - unsigned char geteffectpar(int npar); - const bool insertion;/**<1 if the effect is connected as insertion effect*/ - REALTYPE *efxoutl,*efxoutr; - - /**used by UI + void changeeffect(int nefx_); + /**Get the number of the effect + * @return the number*/ + int geteffect(); + /** + * Change the preset to the given one + * @param npreset number of the chosen preset + */ + void changepreset(unsigned char npreset); + /** + * Change the preset to the given one without locking the thread + * @param npreset number of the chosen preset + */ + void changepreset_nolock(unsigned char npreset); + /** + * Get the current preset + * @return the current preset*/ + unsigned char getpreset(); + /**sets the effect par*/ + void seteffectpar(int npar,unsigned char value); + /**<sets the effect par without thread lock*/ + void seteffectpar_nolock(int npar,unsigned char value); + unsigned char geteffectpar(int npar); + const bool insertion;/**<1 if the effect is connected as insertion effect*/ + REALTYPE *efxoutl,*efxoutr; + + /**used by UI * \todo needs to be decoupled*/ - REALTYPE getEQfreqresponse(REALTYPE freq); - - FilterParams *filterpars; - - private: - int nefx; - Effect *efx; - pthread_mutex_t *mutex; - bool dryonly; + REALTYPE getEQfreqresponse(REALTYPE freq); + + FilterParams *filterpars; + +private: + int nefx; + Effect *efx; + pthread_mutex_t *mutex; + bool dryonly; }; #endif diff --git a/src/Effects/Phaser.C b/src/Effects/Phaser.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Phaser.C - Phaser effect Copyright (C) 2002-2005 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 + 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, @@ -25,13 +25,14 @@ #define PHASER_LFO_SHAPE 2 Phaser::Phaser(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) - :Effect(insertion_,efxoutl_,efxoutr_,NULL,0),old(1),oldgain(0.0) + :Effect(insertion_,efxoutl_,efxoutr_,NULL,0),old(1),oldgain(0.0) { setpreset(Ppreset); cleanup(); }; -Phaser::~Phaser(){ +Phaser::~Phaser() +{ //if (oldl!=NULL) delete [] oldl; //if (oldr!=NULL) delete [] oldr; }; @@ -40,7 +41,8 @@ Phaser::~Phaser(){ /* * Effect output */ -void Phaser::out(REALTYPE *smpsl,REALTYPE *smpsr){ +void Phaser::out(REALTYPE *smpsl,REALTYPE *smpsr) +{ int i,j; REALTYPE lfol,lfor,lgain,rgain,tmp; @@ -53,58 +55,62 @@ void Phaser::out(REALTYPE *smpsl,REALTYPE *smpsr){ lgain=1.0-phase*(1.0-depth)-(1.0-phase)*lgain*depth; rgain=1.0-phase*(1.0-depth)-(1.0-phase)*rgain*depth; - - if (lgain>1.0) lgain=1.0;else if (lgain<0.0) lgain=0.0; - if (rgain>1.0) rgain=1.0;else if (rgain<0.0) rgain=0.0; - - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - REALTYPE x=(REALTYPE) i /SOUND_BUFFER_SIZE; - REALTYPE x1=1.0-x; - REALTYPE gl=lgain*x+oldgain.left()*x1; - REALTYPE gr=rgain*x+oldgain.right()*x1; - REALTYPE inl=smpsl[i]*panning+fbl; - REALTYPE inr=smpsr[i]*(1.0-panning)+fbr; - - //Left channel - for (j=0;j<Pstages*2;j++){//Phasing routine - tmp=old.left()[j]; - old.left()[j]=gl*tmp+inl; - inl=tmp-gl*old.left()[j]; - }; - //Right channel - for (j=0;j<Pstages*2;j++){//Phasing routine - tmp=old.right()[j]; - old.right()[j]=gr*tmp+inr; - inr=tmp-gr*old.right()[j]; - }; - //Left/Right crossing - REALTYPE l=inl; - REALTYPE r=inr; - inl=l*(1.0-lrcross)+r*lrcross; - inr=r*(1.0-lrcross)+l*lrcross; - - fbl=inl*fb; - fbr=inr*fb; - efxoutl[i]=inl; - efxoutr[i]=inr; + + if (lgain>1.0) lgain=1.0; + else if (lgain<0.0) lgain=0.0; + if (rgain>1.0) rgain=1.0; + else if (rgain<0.0) rgain=0.0; + + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + REALTYPE x=(REALTYPE) i /SOUND_BUFFER_SIZE; + REALTYPE x1=1.0-x; + REALTYPE gl=lgain*x+oldgain.left()*x1; + REALTYPE gr=rgain*x+oldgain.right()*x1; + REALTYPE inl=smpsl[i]*panning+fbl; + REALTYPE inr=smpsr[i]*(1.0-panning)+fbr; + + //Left channel + for (j=0;j<Pstages*2;j++) {//Phasing routine + tmp=old.left()[j]; + old.left()[j]=gl*tmp+inl; + inl=tmp-gl*old.left()[j]; + }; + //Right channel + for (j=0;j<Pstages*2;j++) {//Phasing routine + tmp=old.right()[j]; + old.right()[j]=gr*tmp+inr; + inr=tmp-gr*old.right()[j]; + }; + //Left/Right crossing + REALTYPE l=inl; + REALTYPE r=inr; + inl=l*(1.0-lrcross)+r*lrcross; + inr=r*(1.0-lrcross)+l*lrcross; + + fbl=inl*fb; + fbr=inr*fb; + efxoutl[i]=inl; + efxoutr[i]=inr; }; oldgain=Stereo<REALTYPE>(lgain,rgain); if (Poutsub!=0) - for (i=0;i<SOUND_BUFFER_SIZE;i++){ + for (i=0;i<SOUND_BUFFER_SIZE;i++) { efxoutl[i]*= -1.0; efxoutr[i]*= -1.0; - }; + }; }; /* * Cleanup the effect */ -void Phaser::cleanup(){ - fbl=0.0;fbr=0.0; +void Phaser::cleanup() +{ + fbl=0.0; + fbr=0.0; //oldlgain=0.0; //oldrgain=0.0; oldgain=Stereo<REALTYPE>(0.0); @@ -119,35 +125,41 @@ void Phaser::cleanup(){ /* * Parameter control */ -void Phaser::setdepth(const unsigned char &Pdepth){ +void Phaser::setdepth(const unsigned char &Pdepth) +{ this->Pdepth=Pdepth; depth=(Pdepth/127.0); }; -void Phaser::setfb(const unsigned char &Pfb){ +void Phaser::setfb(const unsigned char &Pfb) +{ this->Pfb=Pfb; fb=(Pfb-64.0)/64.1; }; -void Phaser::setvolume(const unsigned char &Pvolume){ +void Phaser::setvolume(const unsigned char &Pvolume) +{ this->Pvolume=Pvolume; outvolume=Pvolume/127.0; if (insertion==0) volume=1.0; else volume=outvolume; }; -void Phaser::setpanning(const unsigned char &Ppanning){ +void Phaser::setpanning(const unsigned char &Ppanning) +{ this->Ppanning=Ppanning; panning=Ppanning/127.0; }; -void Phaser::setlrcross(const unsigned char &Plrcross){ +void Phaser::setlrcross(const unsigned char &Plrcross) +{ this->Plrcross=Plrcross; lrcross=Plrcross/127.0; }; -void Phaser::setstages(const unsigned char &Pstages){ +void Phaser::setstages(const unsigned char &Pstages) +{ //if (oldl!=NULL) delete [] oldl; //if (oldr!=NULL) delete [] oldr; if (Pstages>=MAX_PHASER_STAGES) this->Pstages=MAX_PHASER_STAGES-1; @@ -158,96 +170,126 @@ void Phaser::setstages(const unsigned char &Pstages){ cleanup(); }; -void Phaser::setphase(const unsigned char &Pphase){ +void Phaser::setphase(const unsigned char &Pphase) +{ this->Pphase=Pphase; phase=(Pphase/127.0); }; -void Phaser::setpreset(unsigned char npreset){ +void Phaser::setpreset(unsigned char npreset) +{ const int PRESET_SIZE=12; const int NUM_PRESETS=6; unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ - //Phaser1 - {64,64,36,0,0,64,110,64,1,0,0,20}, - //Phaser2 - {64,64,35,0,0,88,40,64,3,0,0,20}, - //Phaser3 - {64,64,31,0,0,66,68,107,2,0,0,20}, - //Phaser4 - {39,64,22,0,0,66,67,10,5,0,1,20}, - //Phaser5 - {64,64,20,0,1,110,67,78,10,0,0,20}, - //Phaser6 - {64,64,53,100,0,58,37,78,3,0,0,20}}; + //Phaser1 + {64,64,36,0,0,64,110,64,1,0,0,20}, + //Phaser2 + {64,64,35,0,0,88,40,64,3,0,0,20}, + //Phaser3 + {64,64,31,0,0,66,68,107,2,0,0,20}, + //Phaser4 + {39,64,22,0,0,66,67,10,5,0,1,20}, + //Phaser5 + {64,64,20,0,1,110,67,78,10,0,0,20}, + //Phaser6 + {64,64,53,100,0,58,37,78,3,0,0,20} + }; if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]); Ppreset=npreset; }; -void Phaser::changepar(const int &npar,const unsigned char &value){ - switch(npar){ - case 0: setvolume(value); - break; - case 1: setpanning(value); - break; - case 2: lfo.Pfreq=value; - lfo.updateparams(); - break; - case 3: lfo.Prandomness=value; - lfo.updateparams(); - break; - case 4: lfo.PLFOtype=value; - lfo.updateparams(); - break; - case 5: lfo.Pstereo=value; - lfo.updateparams(); - break; - case 6: setdepth(value); - break; - case 7: setfb(value); - break; - case 8: setstages(value); - break; - case 9: setlrcross(value); - break; - case 10:if (value>1) Poutsub=1; - else Poutsub=value; - break; - case 11:setphase(value); - break; +void Phaser::changepar(const int &npar,const unsigned char &value) +{ + switch (npar) { + case 0: + setvolume(value); + break; + case 1: + setpanning(value); + break; + case 2: + lfo.Pfreq=value; + lfo.updateparams(); + break; + case 3: + lfo.Prandomness=value; + lfo.updateparams(); + break; + case 4: + lfo.PLFOtype=value; + lfo.updateparams(); + break; + case 5: + lfo.Pstereo=value; + lfo.updateparams(); + break; + case 6: + setdepth(value); + break; + case 7: + setfb(value); + break; + case 8: + setstages(value); + break; + case 9: + setlrcross(value); + break; + case 10: + if (value>1) Poutsub=1; + else Poutsub=value; + break; + case 11: + setphase(value); + break; }; }; -unsigned char Phaser::getpar(const int &npar)const{ - switch (npar){ - case 0: return(Pvolume); +unsigned char Phaser::getpar(const int &npar)const +{ + switch (npar) { + case 0: + return(Pvolume); break; - case 1: return(Ppanning); + case 1: + return(Ppanning); break; - case 2: return(lfo.Pfreq); + case 2: + return(lfo.Pfreq); break; - case 3: return(lfo.Prandomness); + case 3: + return(lfo.Prandomness); break; - case 4: return(lfo.PLFOtype); + case 4: + return(lfo.PLFOtype); break; - case 5: return(lfo.Pstereo); + case 5: + return(lfo.Pstereo); break; - case 6: return(Pdepth); + case 6: + return(Pdepth); break; - case 7: return(Pfb); + case 7: + return(Pfb); break; - case 8: return(Pstages); + case 8: + return(Pstages); break; - case 9: return(Plrcross); + case 9: + return(Plrcross); break; - case 10:return(Poutsub); + case 10: + return(Poutsub); break; - case 11:return(Pphase); + case 11: + return(Pphase); break; - default:return (0); + default: + return (0); }; - + }; diff --git a/src/Effects/Phaser.h b/src/Effects/Phaser.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Phaser.h - Phaser effect Copyright (C) 2002-2005 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 + 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, @@ -30,45 +30,46 @@ #define MAX_PHASER_STAGES 12 /**Phaser Effect*/ -class Phaser:public Effect { - public: - Phaser(const int &insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); - ~Phaser(); - void out(REALTYPE *smpsl,REALTYPE *smpsr); - void setpreset(unsigned char npreset); - void changepar(const int &npar,const unsigned char &value); - unsigned char getpar(const int &npar)const; - void cleanup(); - void setdryonly(); - - private: - //Parametrii Phaser - EffectLFO lfo;/**<lfo-ul Phaser*/ - unsigned char Pvolume; - unsigned char Ppanning; - unsigned char Pdepth;/**<the depth of the Phaser*/ - unsigned char Pfb;/**<feedback*/ - unsigned char Plrcross;/**<feedback*/ - unsigned char Pstages; - unsigned char Poutsub;/**<if I wish to substract the output instead of the adding it*/ - unsigned char Pphase; - - //Control Parametrii - void setvolume(const unsigned char &Pvolume); - void setpanning(const unsigned char &Ppanning); - void setdepth(const unsigned char &Pdepth); - void setfb(const unsigned char &Pfb); - void setlrcross(const unsigned char &Plrcross); - void setstages(const unsigned char &Pstages); - void setphase(const unsigned char &Pphase); - - //Internal Values - //int insertion; //inherited from Effect - REALTYPE panning,fb,depth,lrcross,fbl,fbr,phase; - //REALTYPE *oldl,*oldr; - Stereo<AuSample> old; - //REALTYPE oldlgain,oldrgain; - Stereo<REALTYPE> oldgain; +class Phaser:public Effect +{ +public: + Phaser(const int &insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); + ~Phaser(); + void out(REALTYPE *smpsl,REALTYPE *smpsr); + void setpreset(unsigned char npreset); + void changepar(const int &npar,const unsigned char &value); + unsigned char getpar(const int &npar)const; + void cleanup(); + void setdryonly(); + +private: + //Parametrii Phaser + EffectLFO lfo;/**<lfo-ul Phaser*/ + unsigned char Pvolume; + unsigned char Ppanning; + unsigned char Pdepth;/**<the depth of the Phaser*/ + unsigned char Pfb;/**<feedback*/ + unsigned char Plrcross;/**<feedback*/ + unsigned char Pstages; + unsigned char Poutsub;/**<if I wish to substract the output instead of the adding it*/ + unsigned char Pphase; + + //Control Parametrii + void setvolume(const unsigned char &Pvolume); + void setpanning(const unsigned char &Ppanning); + void setdepth(const unsigned char &Pdepth); + void setfb(const unsigned char &Pfb); + void setlrcross(const unsigned char &Plrcross); + void setstages(const unsigned char &Pstages); + void setphase(const unsigned char &Pphase); + + //Internal Values + //int insertion; //inherited from Effect + REALTYPE panning,fb,depth,lrcross,fbl,fbr,phase; + //REALTYPE *oldl,*oldr; + Stereo<AuSample> old; + //REALTYPE oldlgain,oldrgain; + Stereo<REALTYPE> oldgain; }; #endif diff --git a/src/Effects/Reverb.C b/src/Effects/Reverb.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Reverb.C - Reverberation effect Copyright (C) 2002-2005 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 + 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, @@ -26,39 +26,42 @@ /**\todo: EarlyReflections,Prdelay,Perbalance */ Reverb::Reverb(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) - :Effect(insertion_,efxoutl_,efxoutr_,NULL,0) + :Effect(insertion_,efxoutl_,efxoutr_,NULL,0) { inputbuf=new REALTYPE[SOUND_BUFFER_SIZE]; //defaults - Pvolume=48; - Ppan=64; + Pvolume=48; + Ppan=64; Ptime=64; - Pidelay=40; - Pidelayfb=0; - Prdelay=0; + Pidelay=40; + Pidelayfb=0; + Prdelay=0; Plpf=127; - Phpf=0; - Perbalance=64; + Phpf=0; + Perbalance=64; Plohidamp=80; Ptype=1; - Proomsize=64;roomsize=1.0;rs=1.0; + Proomsize=64; + roomsize=1.0; + rs=1.0; for (int i=0;i<REV_COMBS*2;i++) { - comblen[i]=800+(int)(RND*1400); - combk[i]=0; - lpcomb[i]=0; - combfb[i]=-0.97; - comb[i]=NULL; - }; + comblen[i]=800+(int)(RND*1400); + combk[i]=0; + lpcomb[i]=0; + combfb[i]=-0.97; + comb[i]=NULL; + }; for (int i=0;i<REV_APS*2;i++) { - aplen[i]=500+(int)(RND*500); - apk[i]=0; - ap[i]=NULL; + aplen[i]=500+(int)(RND*500); + apk[i]=0; + ap[i]=NULL; }; - - lpf=NULL;hpf=NULL;//no filter + + lpf=NULL; + hpf=NULL;//no filter idelay=NULL; setpreset(Ppreset); @@ -66,7 +69,8 @@ Reverb::Reverb(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) }; -Reverb::~Reverb(){ +Reverb::~Reverb() +{ int i; if (idelay!=NULL) delete []idelay; if (hpf!=NULL) delete hpf; @@ -81,14 +85,15 @@ Reverb::~Reverb(){ /* * Cleanup the effect */ -void Reverb::cleanup(){ +void Reverb::cleanup() +{ int i,j; - for (i=0;i<REV_COMBS*2;i++){ + for (i=0;i<REV_COMBS*2;i++) { lpcomb[i]=0.0; for (j=0;j<comblen[i];j++) comb[i][j]=0.0; }; - for (i=0;i<REV_APS*2;i++) + for (i=0;i<REV_APS*2;i++) for (j=0;j<aplen[i];j++) ap[i][j]=0.0; if (idelay!=NULL) for (i=0;i<idelaylen;i++) idelay[i]=0.0; @@ -101,61 +106,64 @@ void Reverb::cleanup(){ /* * Process one channel; 0=left,1=right */ -void Reverb::processmono(int ch,REALTYPE *output){ +void Reverb::processmono(int ch,REALTYPE *output) +{ int i,j; REALTYPE fbout,tmp; /**\todo: implement the high part from lohidamp*/ - - for (j=REV_COMBS*ch;j<REV_COMBS*(ch+1);j++){ - int ck=combk[j]; - int comblength=comblen[j]; - REALTYPE lpcombj=lpcomb[j]; + for (j=REV_COMBS*ch;j<REV_COMBS*(ch+1);j++) { + + int ck=combk[j]; + int comblength=comblen[j]; + REALTYPE lpcombj=lpcomb[j]; - for (i=0;i<SOUND_BUFFER_SIZE;i++){ + for (i=0;i<SOUND_BUFFER_SIZE;i++) { fbout=comb[j][ck]*combfb[j]; fbout=fbout*(1.0-lohifb)+lpcombj*lohifb; - lpcombj=fbout; + lpcombj=fbout; - comb[j][ck]=inputbuf[i]+fbout; - output[i]+=fbout; + comb[j][ck]=inputbuf[i]+fbout; + output[i]+=fbout; - if ((++ck)>=comblength) ck=0; - }; + if ((++ck)>=comblength) ck=0; + }; - combk[j]=ck; - lpcomb[j]=lpcombj; + combk[j]=ck; + lpcomb[j]=lpcombj; }; - for (j=REV_APS*ch;j<REV_APS*(1+ch);j++){ - int ak=apk[j]; - int aplength=aplen[j]; - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - tmp=ap[j][ak]; - ap[j][ak]=0.7*tmp+output[i]; - output[i]=tmp-0.7*ap[j][ak]; - if ((++ak)>=aplength) ak=0; - }; - apk[j]=ak; + for (j=REV_APS*ch;j<REV_APS*(1+ch);j++) { + int ak=apk[j]; + int aplength=aplen[j]; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + tmp=ap[j][ak]; + ap[j][ak]=0.7*tmp+output[i]; + output[i]=tmp-0.7*ap[j][ak]; + if ((++ak)>=aplength) ak=0; + }; + apk[j]=ak; }; }; /* * Effect output */ -void Reverb::out(REALTYPE *smps_l, REALTYPE *smps_r){ +void Reverb::out(REALTYPE *smps_l, REALTYPE *smps_r) +{ int i; if ((Pvolume==0)&&(insertion!=0)) return; - + for (i=0;i<SOUND_BUFFER_SIZE;i++) { - inputbuf[i]=(smps_l[i]+smps_r[i])/2.0; - //Initial delay r - if (idelay!=NULL){ + inputbuf[i]=(smps_l[i]+smps_r[i])/2.0; + //Initial delay r + if (idelay!=NULL) { REALTYPE tmp=inputbuf[i]+idelay[idelayk]*idelayfb; inputbuf[i]=idelay[idelayk]; - idelay[idelayk]=tmp; - idelayk++;if (idelayk>=idelaylen) idelayk=0; - }; + idelay[idelayk]=tmp; + idelayk++; + if (idelayk>=idelaylen) idelayk=0; + }; }; if (lpf!=NULL) lpf->filterout(inputbuf); @@ -163,15 +171,16 @@ void Reverb::out(REALTYPE *smps_l, REALTYPE *smps_r){ processmono(0,efxoutl);//left processmono(1,efxoutr);//right - + REALTYPE lvol=rs/REV_COMBS*pan; REALTYPE rvol=rs/REV_COMBS*(1.0-pan); - if (insertion!=0){ - lvol*=2;rvol*=2; + if (insertion!=0) { + lvol*=2; + rvol*=2; }; - for (int i=0;i<SOUND_BUFFER_SIZE;i++){ - efxoutl[i]*=lvol; - efxoutr[i]*=rvol; + for (int i=0;i<SOUND_BUFFER_SIZE;i++) { + efxoutl[i]*=lvol; + efxoutr[i]*=rvol; }; }; @@ -179,188 +188,198 @@ void Reverb::out(REALTYPE *smps_l, REALTYPE *smps_r){ /* * Parameter control */ -void Reverb::setvolume(const unsigned char &Pvolume){ +void Reverb::setvolume(const unsigned char &Pvolume) +{ this->Pvolume=Pvolume; if (insertion==0) { - outvolume=pow(0.01,(1.0-Pvolume/127.0))*4.0; - volume=1.0; + outvolume=pow(0.01,(1.0-Pvolume/127.0))*4.0; + volume=1.0; } else { - volume=outvolume=Pvolume/127.0; - if (Pvolume==0) cleanup(); + volume=outvolume=Pvolume/127.0; + if (Pvolume==0) cleanup(); }; }; -void Reverb::setpan(const unsigned char &Ppan){ +void Reverb::setpan(const unsigned char &Ppan) +{ this->Ppan=Ppan; pan=(REALTYPE)Ppan/127.0; }; -void Reverb::settime(const unsigned char &Ptime){ +void Reverb::settime(const unsigned char &Ptime) +{ int i; REALTYPE t; this->Ptime=Ptime; t=pow(60.0,(REALTYPE)Ptime/127.0)-0.97; - for (i=0;i<REV_COMBS*2;i++){ - combfb[i]=-exp((REALTYPE)comblen[i]/(REALTYPE)SAMPLE_RATE*log(0.001)/t); - //the feedback is negative because it removes the DC + for (i=0;i<REV_COMBS*2;i++) { + combfb[i]=-exp((REALTYPE)comblen[i]/(REALTYPE)SAMPLE_RATE*log(0.001)/t); + //the feedback is negative because it removes the DC }; }; -void Reverb::setlohidamp(unsigned char Plohidamp){ - REALTYPE x; - +void Reverb::setlohidamp(unsigned char Plohidamp) +{ + REALTYPE x; + if (Plohidamp<64) Plohidamp=64;//remove this when the high part from lohidamp will be added - + this->Plohidamp=Plohidamp; if (Plohidamp==64) { - lohidamptype=0; - lohifb=0.0; + lohidamptype=0; + lohifb=0.0; } else { if (Plohidamp<64) lohidamptype=1; - if (Plohidamp>64) lohidamptype=2; + if (Plohidamp>64) lohidamptype=2; x=fabs((REALTYPE)(Plohidamp-64)/64.1); lohifb=x*x; }; }; -void Reverb::setidelay(const unsigned char &Pidelay){ +void Reverb::setidelay(const unsigned char &Pidelay) +{ REALTYPE delay; this->Pidelay=Pidelay; delay=pow(50*Pidelay/127.0,2)-1.0; - + if (idelay!=NULL) delete []idelay; idelay=NULL; - + idelaylen=(int) (SAMPLE_RATE*delay/1000); if (idelaylen>1) { - idelayk=0; - idelay=new REALTYPE[idelaylen]; + idelayk=0; + idelay=new REALTYPE[idelaylen]; for (int i=0;i<idelaylen;i++) idelay[i]=0.0; }; }; -void Reverb::setidelayfb(const unsigned char &Pidelayfb){ +void Reverb::setidelayfb(const unsigned char &Pidelayfb) +{ this->Pidelayfb=Pidelayfb; idelayfb=Pidelayfb/128.0; }; -void Reverb::sethpf(const unsigned char &Phpf){ +void Reverb::sethpf(const unsigned char &Phpf) +{ this->Phpf=Phpf; if (Phpf==0) {//No HighPass if (hpf!=NULL) delete hpf; hpf=NULL; - } - else{ + } else { REALTYPE fr=exp(pow(Phpf/127.0,0.5)*log(10000.0))+20.0; - if (hpf==NULL) hpf=new AnalogFilter(3,fr,1,0); - else hpf->setfreq(fr); + if (hpf==NULL) hpf=new AnalogFilter(3,fr,1,0); + else hpf->setfreq(fr); }; }; -void Reverb::setlpf(const unsigned char &Plpf){ +void Reverb::setlpf(const unsigned char &Plpf) +{ this->Plpf=Plpf; if (Plpf==127) {//No LowPass if (lpf!=NULL) delete lpf; lpf=NULL; - } - else{ + } else { REALTYPE fr=exp(pow(Plpf/127.0,0.5)*log(25000.0))+40; - if (lpf==NULL) lpf=new AnalogFilter(2,fr,1,0); - else lpf->setfreq(fr); + if (lpf==NULL) lpf=new AnalogFilter(2,fr,1,0); + else lpf->setfreq(fr); }; }; -void Reverb::settype(unsigned char Ptype){ +void Reverb::settype(unsigned char Ptype) +{ const int NUM_TYPES=2; int combtunings[NUM_TYPES][REV_COMBS]={ - //this is unused (for random) - {0,0,0,0,0,0,0,0}, - //Freeverb by Jezar at Dreampoint - {1116,1188,1277,1356,1422,1491,1557,1617} + //this is unused (for random) + {0,0,0,0,0,0,0,0}, + //Freeverb by Jezar at Dreampoint + {1116,1188,1277,1356,1422,1491,1557,1617} }; int aptunings[NUM_TYPES][REV_APS]={ - //this is unused (for random) - {0,0,0,0}, - //Freeverb by Jezar at Dreampoint - {225,341,441,556} + //this is unused (for random) + {0,0,0,0}, + //Freeverb by Jezar at Dreampoint + {225,341,441,556} }; if (Ptype>=NUM_TYPES) Ptype=NUM_TYPES-1; this->Ptype=Ptype; - + REALTYPE tmp; for (int i=0;i<REV_COMBS*2;i++) { - if (Ptype==0) tmp=800.0+(int)(RND*1400.0); + if (Ptype==0) tmp=800.0+(int)(RND*1400.0); else tmp=combtunings[Ptype][i%REV_COMBS]; - tmp*=roomsize; - if (i>REV_COMBS) tmp+=23.0; - tmp*=SAMPLE_RATE/44100.0;//adjust the combs according to the samplerate - if (tmp<10) tmp=10; - - comblen[i]=(int) tmp; - combk[i]=0; - lpcomb[i]=0; - if (comb[i]!=NULL) delete []comb[i]; - comb[i]=new REALTYPE[comblen[i]]; - }; + tmp*=roomsize; + if (i>REV_COMBS) tmp+=23.0; + tmp*=SAMPLE_RATE/44100.0;//adjust the combs according to the samplerate + if (tmp<10) tmp=10; + + comblen[i]=(int) tmp; + combk[i]=0; + lpcomb[i]=0; + if (comb[i]!=NULL) delete []comb[i]; + comb[i]=new REALTYPE[comblen[i]]; + }; for (int i=0;i<REV_APS*2;i++) { - if (Ptype==0) tmp=500+(int)(RND*500); + if (Ptype==0) tmp=500+(int)(RND*500); else tmp=aptunings[Ptype][i%REV_APS]; - tmp*=roomsize; - if (i>REV_APS) tmp+=23.0; - tmp*=SAMPLE_RATE/44100.0;//adjust the combs according to the samplerate - if (tmp<10) tmp=10; - aplen[i]=(int) tmp; - apk[i]=0; - if (ap[i]!=NULL) delete []ap[i]; - ap[i]=new REALTYPE[aplen[i]]; + tmp*=roomsize; + if (i>REV_APS) tmp+=23.0; + tmp*=SAMPLE_RATE/44100.0;//adjust the combs according to the samplerate + if (tmp<10) tmp=10; + aplen[i]=(int) tmp; + apk[i]=0; + if (ap[i]!=NULL) delete []ap[i]; + ap[i]=new REALTYPE[aplen[i]]; }; settime(Ptime); cleanup(); }; -void Reverb::setroomsize(const unsigned char &Proomsize){ +void Reverb::setroomsize(const unsigned char &Proomsize) +{ this->Proomsize=Proomsize; if (Proomsize==0) this->Proomsize=64;//this is because the older versions consider roomsize=0 roomsize=(this->Proomsize-64.0)/64.0; if (roomsize>0.0) roomsize*=2.0; roomsize=pow(10.0,roomsize); rs=sqrt(roomsize); - settype(Ptype); + settype(Ptype); }; -void Reverb::setpreset(unsigned char npreset){ +void Reverb::setpreset(unsigned char npreset) +{ const int PRESET_SIZE=12; 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}, + //Cathedral1 + {80,64,63,24,0,0,0,85,5,83,1,64}, //Cathedral2 - {80,64,69,35,0,0,0,127,0,71,0,64}, - //Cathedral3 - {80,64,69,24,0,0,0,127,75,78,1,85}, - //Hall1 - {90,64,51,10,0,0,0,127,21,78,1,64}, - //Hall2 - {90,64,53,20,0,0,0,127,75,71,1,64}, - //Room1 - {100,64,33,0,0,0,0,127,0,106,0,30}, - //Room2 - {100,64,21,26,0,0,0,62,0,77,1,45}, - //Basement - {110,64,14,0,0,0,0,127,5,71,0,25}, - //Tunnel - {85,80,84,20,42,0,0,51,0,78,1,105}, - //Echoed1 - {95,64,26,60,71,0,0,114,0,64,1,64}, - //Echoed2 - {90,64,40,88,71,0,0,114,0,88,1,64}, - //VeryLong1 - {90,64,93,15,0,0,0,114,0,77,0,95}, - //VeryLong2 - {90,64,111,30,0,0,0,114,90,74,1,80}}; + {80,64,69,35,0,0,0,127,0,71,0,64}, + //Cathedral3 + {80,64,69,24,0,0,0,127,75,78,1,85}, + //Hall1 + {90,64,51,10,0,0,0,127,21,78,1,64}, + //Hall2 + {90,64,53,20,0,0,0,127,75,71,1,64}, + //Room1 + {100,64,33,0,0,0,0,127,0,106,0,30}, + //Room2 + {100,64,21,26,0,0,0,62,0,77,1,45}, + //Basement + {110,64,14,0,0,0,0,127,5,71,0,25}, + //Tunnel + {85,80,84,20,42,0,0,51,0,78,1,105}, + //Echoed1 + {95,64,26,60,71,0,0,114,0,64,1,64}, + //Echoed2 + {90,64,40,88,71,0,0,114,0,88,1,64}, + //VeryLong1 + {90,64,93,15,0,0,0,114,0,77,0,95}, + //VeryLong2 + {90,64,111,30,0,0,0,114,90,74,1,80} + }; if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]); @@ -369,60 +388,82 @@ void Reverb::setpreset(unsigned char npreset){ }; -void Reverb::changepar(const int &npar,const unsigned char &value){ - switch (npar){ - case 0: setvolume(value); +void Reverb::changepar(const int &npar,const unsigned char &value) +{ + switch (npar) { + case 0: + setvolume(value); break; - case 1: setpan(value); + case 1: + setpan(value); break; - case 2: settime(value); + case 2: + settime(value); break; - case 3: setidelay(value); + case 3: + setidelay(value); break; - case 4: setidelayfb(value); + case 4: + setidelayfb(value); break; // case 5: setrdelay(value); // break; // case 6: seterbalance(value); // break; - case 7: setlpf(value); + case 7: + setlpf(value); break; - case 8: sethpf(value); + case 8: + sethpf(value); break; - case 9: setlohidamp(value); + case 9: + setlohidamp(value); break; - case 10:settype(value); + case 10: + settype(value); break; - case 11:setroomsize(value); + case 11: + setroomsize(value); break; }; }; -unsigned char Reverb::getpar(const int &npar)const{ - switch (npar){ - case 0: return(Pvolume); +unsigned char Reverb::getpar(const int &npar)const +{ + switch (npar) { + case 0: + return(Pvolume); break; - case 1: return(Ppan); + case 1: + return(Ppan); break; - case 2: return(Ptime); + case 2: + return(Ptime); break; - case 3: return(Pidelay); + case 3: + return(Pidelay); break; - case 4: return(Pidelayfb); + case 4: + return(Pidelayfb); break; // case 5: return(Prdelay); // break; // case 6: return(Perbalance); // break; - case 7: return(Plpf); + case 7: + return(Plpf); break; - case 8: return(Phpf); + case 8: + return(Phpf); break; - case 9: return(Plohidamp); + case 9: + return(Plohidamp); break; - case 10:return(Ptype); + case 10: + return(Ptype); break; - case 11:return(Proomsize); + case 11: + return(Proomsize); break; }; return(0);//in case of bogus "parameter" diff --git a/src/Effects/Reverb.h b/src/Effects/Reverb.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Reverb.h - Reverberation effect Copyright (C) 2002-2005 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 + 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, @@ -32,18 +32,19 @@ #define REV_APS 4 /**Creates Reverberation Effects*/ -class Reverb:public Effect { - public: +class Reverb:public Effect +{ +public: Reverb(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); ~Reverb(); void out(REALTYPE *smps_l,REALTYPE *smps_r); void cleanup(); - void setpreset(unsigned char npreset); + void setpreset(unsigned char npreset); void changepar(const int &npar,const unsigned char &value); unsigned char getpar(const int &npar)const; - private: +private: //Parametrii /**Amount of the reverb*/ unsigned char Pvolume; @@ -93,32 +94,32 @@ class Reverb:public Effect { void setlpf(const unsigned char &Plpf); void settype( unsigned char Ptype); void setroomsize(const unsigned char &Proomsize); - + REALTYPE pan,erbalance; - //Parametrii 2 + //Parametrii 2 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 comblen[REV_COMBS*2]; int aplen[REV_APS*2]; - + //Internal Variables - + REALTYPE *comb[REV_COMBS*2]; - + int combk[REV_COMBS*2]; REALTYPE combfb[REV_COMBS*2];/**<feedback-ul fiecarui filtru "comb"*/ REALTYPE lpcomb[REV_COMBS*2];/**<pentru Filtrul LowPass*/ REALTYPE *ap[REV_APS*2]; - + int apk[REV_APS*2]; - + REALTYPE *idelay; AnalogFilter *lpf,*hpf;//filters REALTYPE *inputbuf; - + void processmono(int ch,REALTYPE *output); }; diff --git a/src/Input/ALSAMidiIn.C b/src/Input/ALSAMidiIn.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + ALSAMidiIn.C - Midi input for ALSA (this creates an ALSA virtual port) Copyright (C) 2002-2005 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 + 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, @@ -22,25 +22,27 @@ #include "ALSAMidiIn.h" -ALSAMidiIn::ALSAMidiIn(){ +ALSAMidiIn::ALSAMidiIn() +{ int alsaport; inputok=false; midi_handle=NULL; - + if (snd_seq_open(&midi_handle,"default",SND_SEQ_OPEN_INPUT,0)!=0) return; - + snd_seq_set_client_name(midi_handle,"ZynAddSubFX");//thanks to Frank Neumann alsaport = snd_seq_create_simple_port(midi_handle,"ZynAddSubFX" - ,SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE - ,SND_SEQ_PORT_TYPE_SYNTH); + ,SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE + ,SND_SEQ_PORT_TYPE_SYNTH); if (alsaport<0) return; inputok=true; }; -ALSAMidiIn::~ALSAMidiIn(){ +ALSAMidiIn::~ALSAMidiIn() +{ if (midi_handle) snd_seq_close(midi_handle); }; @@ -48,51 +50,53 @@ ALSAMidiIn::~ALSAMidiIn(){ /* * Get the midi command,channel and parameters */ -void ALSAMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams){ +void ALSAMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams) +{ snd_seq_event_t *midievent=NULL; cmdtype=MidiNull; - if (inputok==false){ - /* The input is broken. We need to block for a while anyway so other - non-RT threads get a chance to run. */ - sleep(1); - return; + if (inputok==false) { + /* The input is broken. We need to block for a while anyway so other + non-RT threads get a chance to run. */ + sleep(1); + return; }; - + snd_seq_event_input(midi_handle,&midievent); - + if (midievent==NULL) return; - switch (midievent->type){ - case SND_SEQ_EVENT_NOTEON: - cmdtype=MidiNoteON; - cmdchan=midievent->data.note.channel; - cmdparams[0]=midievent->data.note.note; - cmdparams[1]=midievent->data.note.velocity; - break; - case SND_SEQ_EVENT_NOTEOFF: - cmdtype=MidiNoteOFF; - cmdchan=midievent->data.note.channel; - cmdparams[0]=midievent->data.note.note; - break; - case SND_SEQ_EVENT_PITCHBEND: - cmdtype=MidiController; - cmdchan=midievent->data.control.channel; - cmdparams[0]=C_pitchwheel;//Pitch Bend - cmdparams[1]=midievent->data.control.value; - break; - case SND_SEQ_EVENT_CONTROLLER: - cmdtype=MidiController; - cmdchan=midievent->data.control.channel; - cmdparams[0]=getcontroller(midievent->data.control.param); - cmdparams[1]=midievent->data.control.value; - //fprintf(stderr,"t=%d val=%d\n",midievent->data.control.param,midievent->data.control.value); - break; - + switch (midievent->type) { + case SND_SEQ_EVENT_NOTEON: + cmdtype=MidiNoteON; + cmdchan=midievent->data.note.channel; + cmdparams[0]=midievent->data.note.note; + cmdparams[1]=midievent->data.note.velocity; + break; + case SND_SEQ_EVENT_NOTEOFF: + cmdtype=MidiNoteOFF; + cmdchan=midievent->data.note.channel; + cmdparams[0]=midievent->data.note.note; + break; + case SND_SEQ_EVENT_PITCHBEND: + cmdtype=MidiController; + cmdchan=midievent->data.control.channel; + cmdparams[0]=C_pitchwheel;//Pitch Bend + cmdparams[1]=midievent->data.control.value; + break; + case SND_SEQ_EVENT_CONTROLLER: + cmdtype=MidiController; + cmdchan=midievent->data.control.channel; + cmdparams[0]=getcontroller(midievent->data.control.param); + cmdparams[1]=midievent->data.control.value; + //fprintf(stderr,"t=%d val=%d\n",midievent->data.control.param,midievent->data.control.value); + break; + }; }; -int ALSAMidiIn::getalsaid() { +int ALSAMidiIn::getalsaid() +{ if (midi_handle) { snd_seq_client_info_t* seq_info; snd_seq_client_info_malloc(&seq_info); diff --git a/src/Input/ALSAMidiIn.h b/src/Input/ALSAMidiIn.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + ALSAMidiIn.h - Midi input for ALSA (this creates an ALSA virtual port) Copyright (C) 2002-2005 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 + 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, @@ -28,20 +28,21 @@ /**Midi input for ALSA (this creates an ALSA virtual port)*/ -class ALSAMidiIn:public MidiIn{ - public: - /**Constructor*/ - ALSAMidiIn(); - /**Destructor*/ - ~ALSAMidiIn(); - - void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams); - /**Get the ALSA id - * @return ALSA id*/ - int getalsaid(); - - private: - snd_seq_t *midi_handle; +class ALSAMidiIn:public MidiIn +{ +public: + /**Constructor*/ + ALSAMidiIn(); + /**Destructor*/ + ~ALSAMidiIn(); + + void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams); + /**Get the ALSA id + * @return ALSA id*/ + int getalsaid(); + +private: + snd_seq_t *midi_handle; }; #endif diff --git a/src/Input/MidiIn.C b/src/Input/MidiIn.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + MidiIn.C - This class is inherited by all the Midi input classes Copyright (C) 2002-2005 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 + 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, @@ -23,52 +23,73 @@ #include "../globals.h" #include "MidiIn.h" -int MidiIn::getcontroller(unsigned char b){ +int MidiIn::getcontroller(unsigned char b) +{ /**\todo there might be a better way to do this*/ int ctl=C_NULL; - switch (b){ - case 1:ctl=C_modwheel;//Modulation Wheel - break; - case 7:ctl=C_volume;//Volume - break; - case 10:ctl=C_panning;//Panning - break; - case 11:ctl=C_expression;//Expression - break; - case 64:ctl=C_sustain;//Sustain pedal - break; - case 65:ctl=C_portamento;//Portamento - break; - case 71:ctl=C_filterq;//Filter Q (Sound Timbre) - break; - case 74:ctl=C_filtercutoff;//Filter Cutoff (Brightness) - break; - case 75:ctl=C_bandwidth;//BandWidth - break; - case 76:ctl=C_fmamp;//FM amplitude - break; - case 77:ctl=C_resonance_center;//Resonance Center Frequency - break; - case 78:ctl=C_resonance_bandwidth;//Resonance Bandwith - break; - case 120:ctl=C_allsoundsoff;//All Sounds OFF - break; - case 121:ctl=C_resetallcontrollers;//Reset All Controllers - break; - case 123:ctl=C_allnotesoff;//All Notes OFF - break; - //RPN and NRPN - case 0x06:ctl=C_dataentryhi;//Data Entry (Coarse) - break; - case 0x26:ctl=C_dataentrylo;//Data Entry (Fine) - break; - case 99:ctl=C_nrpnhi;//NRPN (Coarse) - break; - case 98:ctl=C_nrpnlo;//NRPN (Fine) - break; - default:ctl=C_NULL;//unknown controller - //fprintf(stderr,"Controller=%d , par=%d\n",midievent->data.control.param,cmdparams[1]); - break; - }; + switch (b) { + case 1: + ctl=C_modwheel;//Modulation Wheel + break; + case 7: + ctl=C_volume;//Volume + break; + case 10: + ctl=C_panning;//Panning + break; + case 11: + ctl=C_expression;//Expression + break; + case 64: + ctl=C_sustain;//Sustain pedal + break; + case 65: + ctl=C_portamento;//Portamento + break; + case 71: + ctl=C_filterq;//Filter Q (Sound Timbre) + break; + case 74: + ctl=C_filtercutoff;//Filter Cutoff (Brightness) + break; + case 75: + ctl=C_bandwidth;//BandWidth + break; + case 76: + ctl=C_fmamp;//FM amplitude + break; + case 77: + ctl=C_resonance_center;//Resonance Center Frequency + break; + case 78: + ctl=C_resonance_bandwidth;//Resonance Bandwith + break; + case 120: + ctl=C_allsoundsoff;//All Sounds OFF + break; + case 121: + ctl=C_resetallcontrollers;//Reset All Controllers + break; + case 123: + ctl=C_allnotesoff;//All Notes OFF + break; + //RPN and NRPN + case 0x06: + ctl=C_dataentryhi;//Data Entry (Coarse) + break; + case 0x26: + ctl=C_dataentrylo;//Data Entry (Fine) + break; + case 99: + ctl=C_nrpnhi;//NRPN (Coarse) + break; + case 98: + ctl=C_nrpnlo;//NRPN (Fine) + break; + default: + ctl=C_NULL;//unknown controller + //fprintf(stderr,"Controller=%d , par=%d\n",midievent->data.control.param,cmdparams[1]); + break; + }; return(ctl); }; diff --git a/src/Input/MidiIn.h b/src/Input/MidiIn.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + MidiIn.h - This class is inherited by all the Midi input classes Copyright (C) 2002-2005 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 + 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, @@ -25,22 +25,23 @@ #include "../globals.h" -enum MidiCmdType{MidiNull,MidiNoteOFF,MidiNoteON,MidiController}; +enum MidiCmdType {MidiNull,MidiNoteOFF,MidiNoteON,MidiController}; #define MP_MAX_BYTES 4000 //in case of loooong SYS_EXes /**This class is inherited by all the Midi input classes*/ -class MidiIn{ - public: - /**Get the command,channel and parameters of the MIDI - * - * \todo make pure virtual - * @param cmdtype the referece to the variable that will store the type - * @param cmdchan the channel for the event - * @param parameters for the event*/ - virtual void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams)=0; - int getcontroller(unsigned char b); - protected: - bool inputok;/**<1 if I can read midi bytes from input ports*/ +class MidiIn +{ +public: + /**Get the command,channel and parameters of the MIDI + * + * \todo make pure virtual + * @param cmdtype the referece to the variable that will store the type + * @param cmdchan the channel for the event + * @param parameters for the event*/ + virtual void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams)=0; + int getcontroller(unsigned char b); +protected: + bool inputok;/**<1 if I can read midi bytes from input ports*/ }; #endif diff --git a/src/Input/NULLMidiIn.C b/src/Input/NULLMidiIn.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + NULLMidiIn.C - a dummy Midi port Copyright (C) 2002-2005 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 + 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, @@ -22,17 +22,20 @@ #include "NULLMidiIn.h" -NULLMidiIn::NULLMidiIn(){ +NULLMidiIn::NULLMidiIn() +{ }; -NULLMidiIn::~NULLMidiIn(){ +NULLMidiIn::~NULLMidiIn() +{ }; /* * Get the midi command,channel and parameters * It returns MidiNull because it is a dummy driver */ -void NULLMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,unsigned char *cmdparams){ +void NULLMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,unsigned char *cmdparams) +{ cmdtype=MidiNull; }; diff --git a/src/Input/NULLMidiIn.h b/src/Input/NULLMidiIn.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + NULLMidiIn.h - a dummy Midi port Copyright (C) 2002-2005 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 + 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, @@ -27,20 +27,21 @@ /**a dummy Midi port*/ -class NULLMidiIn:public MidiIn{ - public: - /**Dummy Constructor - * \todo see if the default constructor would work here*/ - NULLMidiIn(); - /**Dummy Destructor - * \todo see if the default destructor would work here*/ - ~NULLMidiIn(); - /**Get the midi command,channel and parameters - * It returns MidiNull because it is a dummy driver - */ - void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,unsigned char *cmdparams); - - private: +class NULLMidiIn:public MidiIn +{ +public: + /**Dummy Constructor + * \todo see if the default constructor would work here*/ + NULLMidiIn(); + /**Dummy Destructor + * \todo see if the default destructor would work here*/ + ~NULLMidiIn(); + /**Get the midi command,channel and parameters + * It returns MidiNull because it is a dummy driver + */ + void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,unsigned char *cmdparams); + +private: }; #endif diff --git a/src/Input/OSSMidiIn.C b/src/Input/OSSMidiIn.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + OSSMidiIn.C - Midi input for Open Sound System Copyright (C) 2002-2005 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 + 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, @@ -31,31 +31,35 @@ #include "OSSMidiIn.h" #include "../Misc/Util.h" -OSSMidiIn::OSSMidiIn(){ +OSSMidiIn::OSSMidiIn() +{ inputok=false; midi_handle=open(config.cfg.LinuxOSSSeqInDev,O_RDONLY,0); if (midi_handle!=-1) inputok=true; - + lastmidicmd=0; cmdtype=0; cmdchan=0; }; -OSSMidiIn::~OSSMidiIn(){ +OSSMidiIn::~OSSMidiIn() +{ close(midi_handle); }; -unsigned char OSSMidiIn::readbyte(){ +unsigned char OSSMidiIn::readbyte() +{ unsigned char tmp[4]; read(midi_handle,&tmp[0],1); - while (tmp[0]!=SEQ_MIDIPUTC){ + while (tmp[0]!=SEQ_MIDIPUTC) { read(midi_handle,&tmp[0],4); } return(tmp[1]); }; -unsigned char OSSMidiIn::getmidibyte(){ +unsigned char OSSMidiIn::getmidibyte() +{ unsigned char b; do { b=readbyte(); @@ -66,14 +70,15 @@ unsigned char OSSMidiIn::getmidibyte(){ /* * Get the midi command,channel and parameters */ -void OSSMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams){ +void OSSMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams) +{ unsigned char tmp,i; if (inputok==false) { cmdtype=MidiNull; return; } i=0; - if (lastmidicmd==0){//asteapta prima data pana cand vine prima comanda midi + if (lastmidicmd==0) {//asteapta prima data pana cand vine prima comanda midi while (tmp<0x80) tmp=getmidibyte(); lastmidicmd=tmp; } @@ -85,26 +90,26 @@ void OSSMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdp tmp=getmidibyte(); } - if ((lastmidicmd>=0x80)&&(lastmidicmd<=0x8f)){//Note OFF + if ((lastmidicmd>=0x80)&&(lastmidicmd<=0x8f)) {//Note OFF cmdtype=MidiNoteOFF; cmdchan=lastmidicmd%16; cmdparams[0]=tmp;//note number } - if ((lastmidicmd>=0x90)&&(lastmidicmd<=0x9f)){//Note ON + if ((lastmidicmd>=0x90)&&(lastmidicmd<=0x9f)) {//Note ON cmdtype=MidiNoteON; cmdchan=lastmidicmd%16; - cmdparams[0]=tmp;//note number + cmdparams[0]=tmp;//note number cmdparams[1]=getmidibyte();//velocity if (cmdparams[1]==0) cmdtype=MidiNoteOFF;//if velocity==0 then is note off } - if ((lastmidicmd>=0xB0)&&(lastmidicmd<=0xBF)){//Controllers + if ((lastmidicmd>=0xB0)&&(lastmidicmd<=0xBF)) {//Controllers cmdtype=MidiController; cmdchan=lastmidicmd%16; cmdparams[0]=getcontroller(tmp); cmdparams[1]=getmidibyte(); } - if ((lastmidicmd>=0xE0)&&(lastmidicmd<=0xEF)){//Pitch Wheel + if ((lastmidicmd>=0xE0)&&(lastmidicmd<=0xEF)) {//Pitch Wheel cmdtype=MidiController; cmdchan=lastmidicmd%16; cmdparams[0]=C_pitchwheel; diff --git a/src/Input/OSSMidiIn.h b/src/Input/OSSMidiIn.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + OSSMidiIn.h - Midi input for Open Sound System Copyright (C) 2002-2005 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 + 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, @@ -25,21 +25,22 @@ #include "MidiIn.h" -class OSSMidiIn:public MidiIn{ - public: - OSSMidiIn(); - ~OSSMidiIn(); - unsigned char getmidibyte(); - unsigned char readbyte(); - - //Midi parser - void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams); - unsigned char cmdtype;//the Message Type (noteon,noteof,sysex..) - unsigned char cmdchan;//the channel number - - private: - int midi_handle; - unsigned char lastmidicmd;//last byte (>=80) received from the Midi +class OSSMidiIn:public MidiIn +{ +public: + OSSMidiIn(); + ~OSSMidiIn(); + unsigned char getmidibyte(); + unsigned char readbyte(); + + //Midi parser + void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams); + unsigned char cmdtype;//the Message Type (noteon,noteof,sysex..) + unsigned char cmdchan;//the channel number + +private: + int midi_handle; + unsigned char lastmidicmd;//last byte (>=80) received from the Midi }; diff --git a/src/Input/WINMidiIn.C b/src/Input/WINMidiIn.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + WINMidiIn.C - Midi input for Windows Copyright (C) 2002-2005 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 + 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, @@ -35,49 +35,53 @@ HMIDIIN winmidiinhandle; MidiIn midictl;//used to convert the controllers to ZynAddSubFX controllers void CALLBACK WinMidiInProc(HMIDIIN hMidiIn,UINT wMsg,DWORD dwInstance, - DWORD dwParam1,DWORD dwParam2){ - int midicommand=MidiNull; - if (wMsg==MIM_DATA){ - int cmd,par1,par2; - cmd=dwParam1&0xff; - if (cmd==0xfe) return; - par1=(dwParam1>>8)&0xff; - par2=dwParam1>>16; - //printf("%x %x %x\n",cmd,par1,par2);fflush(stdout); - int cmdchan=cmd&0x0f; - int cmdtype=(cmd>>4)&0x0f; + DWORD dwParam1,DWORD dwParam2) +{ + int midicommand=MidiNull; + if (wMsg==MIM_DATA) { + int cmd,par1,par2; + cmd=dwParam1&0xff; + if (cmd==0xfe) return; + par1=(dwParam1>>8)&0xff; + par2=dwParam1>>16; + //printf("%x %x %x\n",cmd,par1,par2);fflush(stdout); + int cmdchan=cmd&0x0f; + int cmdtype=(cmd>>4)&0x0f; - int tmp=0; - pthread_mutex_lock(&winmaster->mutex); - switch(cmdtype){ - case(0x8)://noteon - winmaster->NoteOff(cmdchan,par1); - break; - case(0x9)://noteoff - winmaster->NoteOn(cmdchan,par1,par2&0xff); - break; - case(0xb)://controller - winmaster->SetController(cmdchan,midictl.getcontroller(par1),par2&0xff); - break; - case(0xe)://pitch wheel - tmp=(par1+par2*(long int) 128)-8192; - winmaster->SetController(cmdchan,C_pitchwheel,tmp); - break; - default:break; - }; - pthread_mutex_unlock(&winmaster->mutex); + int tmp=0; + pthread_mutex_lock(&winmaster->mutex); + switch (cmdtype) { + case(0x8)://noteon + winmaster->NoteOff(cmdchan,par1); + break; + case(0x9)://noteoff + winmaster->NoteOn(cmdchan,par1,par2&0xff); + break; + case(0xb)://controller + winmaster->SetController(cmdchan,midictl.getcontroller(par1),par2&0xff); + break; + case(0xe)://pitch wheel + tmp=(par1+par2*(long int) 128)-8192; + winmaster->SetController(cmdchan,C_pitchwheel,tmp); + break; + default: + break; + }; + pthread_mutex_unlock(&winmaster->mutex); - }; + }; }; -void InitWinMidi(Master *master_){ - winmaster=master_; - - long int result=midiInOpen(&winmidiinhandle,config.cfg.WindowsMidiInId,(DWORD)WinMidiInProc,0,CALLBACK_FUNCTION); - result=midiInStart(winmidiinhandle); +void InitWinMidi(Master *master_) +{ + winmaster=master_; + + long int result=midiInOpen(&winmidiinhandle,config.cfg.WindowsMidiInId,(DWORD)WinMidiInProc,0,CALLBACK_FUNCTION); + result=midiInStart(winmidiinhandle); }; -void StopWinMidi(){ - midiInStop(winmidiinhandle); - midiInClose(winmidiinhandle); +void StopWinMidi() +{ + midiInStop(winmidiinhandle); + midiInClose(winmidiinhandle); }; diff --git a/src/Input/WINMidiIn.h b/src/Input/WINMidiIn.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + WINMidiIn.h - Midi input for Windows Copyright (C) 2002-2005 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 + 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, diff --git a/src/Misc/Bank.C b/src/Misc/Bank.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - - Bank.h - Instrument Bank + + Bank.h - Instrument Bank Copyright (C) 2002-2005 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 + 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, @@ -39,37 +39,39 @@ //if this file exists into a directory, this make the directory to be considered as a bank, even if it not contains a instrument file #define FORCE_BANK_DIR_FILE ".bankdir" -Bank::Bank(){ +Bank::Bank() +{ ZERO(defaultinsname,PART_MAX_NAME_LEN); snprintf(defaultinsname,PART_MAX_NAME_LEN,"%s"," "); - - for (int i=0;i<BANK_SIZE;i++){ - ins[i].used=false; - ins[i].filename=NULL; - ins[i].info.PADsynth_used=false; + + for (int i=0;i<BANK_SIZE;i++) { + ins[i].used=false; + ins[i].filename=NULL; + ins[i].info.PADsynth_used=false; }; dirname=NULL; clearbank(); - for (int i=0;i<MAX_NUM_BANKS;i++){ - banks[i].dir=NULL; - banks[i].name=NULL; + for (int i=0;i<MAX_NUM_BANKS;i++) { + banks[i].dir=NULL; + banks[i].name=NULL; }; - + bankfiletitle=dirname; loadbank(config.cfg.currentBankDir); }; -Bank::~Bank(){ - for (int i=0;i<MAX_NUM_BANKS;i++){ - if (banks[i].dir!=NULL) delete []banks[i].dir; - if (banks[i].name!=NULL) delete []banks[i].name; +Bank::~Bank() +{ + for (int i=0;i<MAX_NUM_BANKS;i++) { + if (banks[i].dir!=NULL) delete []banks[i].dir; + if (banks[i].name!=NULL) delete []banks[i].name; }; clearbank(); @@ -78,7 +80,8 @@ Bank::~Bank(){ /* * Get the name of an instrument from the bank */ -char *Bank::getname (unsigned int ninstrument){ +char *Bank::getname (unsigned int ninstrument) +{ if (emptyslot(ninstrument)) return (defaultinsname); return (ins[ninstrument].name); }; @@ -86,7 +89,8 @@ char *Bank::getname (unsigned int ninstrument){ /* * Get the numbered name of an instrument from the bank */ -char *Bank::getnamenumbered (unsigned int ninstrument){ +char *Bank::getnamenumbered (unsigned int ninstrument) +{ if (emptyslot(ninstrument)) return (defaultinsname); snprintf(tmpinsname[ninstrument],PART_MAX_NAME_LEN+15,"%d. %s",ninstrument+1,getname(ninstrument)); return(tmpinsname[ninstrument]); @@ -95,28 +99,29 @@ char *Bank::getnamenumbered (unsigned int ninstrument){ /* * Changes the name of an instrument (and the filename) */ -void Bank::setname(unsigned int ninstrument,const char *newname,int newslot){ +void Bank::setname(unsigned int ninstrument,const char *newname,int newslot) +{ if (emptyslot(ninstrument)) return; - + char newfilename[1000+1],tmpfilename[100+1]; - + ZERO(newfilename,1001); ZERO(tmpfilename,101); if (newslot>=0) snprintf(tmpfilename,100,"%4d-%s",newslot+1,newname); - else snprintf(tmpfilename,100,"%4d-%s",ninstrument+1,newname); - + else snprintf(tmpfilename,100,"%4d-%s",ninstrument+1,newname); + //add the zeroes at the start of filename for (int i=0;i<4;i++) if (tmpfilename[i]==' ') tmpfilename[i]='0'; //make the filenames legal for (int i=0;i<(int) strlen(tmpfilename);i++) { - char c=tmpfilename[i]; - if ((c>='0')&&(c<='9')) continue; - if ((c>='A')&&(c<='Z')) continue; - if ((c>='a')&&(c<='z')) continue; - if ((c=='-')||(c==' ')) continue; - - tmpfilename[i]='_'; + char c=tmpfilename[i]; + if ((c>='0')&&(c<='9')) continue; + if ((c>='A')&&(c<='Z')) continue; + if ((c>='a')&&(c<='z')) continue; + if ((c=='-')||(c==' ')) continue; + + tmpfilename[i]='_'; }; snprintf(newfilename,1000,"%s/%s.xiz",dirname,tmpfilename); @@ -128,39 +133,42 @@ void Bank::setname(unsigned int ninstrument,const char *newname,int newslot){ ins[ninstrument].filename=new char[strlen(newfilename)+5]; snprintf(ins[ninstrument].filename,strlen(newfilename)+1,"%s",newfilename); snprintf(ins[ninstrument].name,PART_MAX_NAME_LEN,"%s",&tmpfilename[5]); - + }; /* * Check if there is no instrument on a slot from the bank */ -int Bank::emptyslot(unsigned int ninstrument){ +int Bank::emptyslot(unsigned int ninstrument) +{ if (ninstrument>=BANK_SIZE) return (1); if (ins[ninstrument].filename==NULL) return(1); if (ins[ninstrument].used) return (0); - else return(1); + else return(1); }; /* * Removes the instrument from the bank */ -void Bank::clearslot(unsigned int ninstrument){ +void Bank::clearslot(unsigned int ninstrument) +{ if (emptyslot(ninstrument)) return; - + // printf("remove %s \n",ins[ninstrument].filename);//////////////////////// - - + + remove(ins[ninstrument].filename); deletefrombank(ninstrument); }; /* - * Save the instrument to a slot + * Save the instrument to a slot */ -void Bank::savetoslot(unsigned int ninstrument,Part *part){ +void Bank::savetoslot(unsigned int ninstrument,Part *part) +{ clearslot(ninstrument); - + const int maxfilename=200; char tmpfilename[maxfilename+20]; ZERO(tmpfilename,maxfilename+20); @@ -169,16 +177,16 @@ void Bank::savetoslot(unsigned int ninstrument,Part *part){ //add the zeroes at the start of filename for (int i=0;i<4;i++) if (tmpfilename[i]==' ') tmpfilename[i]='0'; - + //make the filenames legal for (int i=0;i<(int)strlen(tmpfilename);i++) { - char c=tmpfilename[i]; - if ((c>='0')&&(c<='9')) continue; - if ((c>='A')&&(c<='Z')) continue; - if ((c>='a')&&(c<='z')) continue; - if ((c=='-')||(c==' ')) continue; - - tmpfilename[i]='_'; + char c=tmpfilename[i]; + if ((c>='0')&&(c<='9')) continue; + if ((c>='A')&&(c<='Z')) continue; + if ((c>='a')&&(c<='z')) continue; + if ((c=='-')||(c==' ')) continue; + + tmpfilename[i]='_'; }; strncat(tmpfilename,".xiz",maxfilename+10); @@ -192,29 +200,31 @@ void Bank::savetoslot(unsigned int ninstrument,Part *part){ remove(filename); part->saveXML(filename); addtobank(ninstrument,tmpfilename,(char *) part->Pname); - + delete[]filename; }; /* * Loads the instrument from the bank */ -void Bank::loadfromslot(unsigned int ninstrument,Part *part){ +void Bank::loadfromslot(unsigned int ninstrument,Part *part) +{ if (emptyslot(ninstrument)) return; - + part->defaultsinstrument(); // printf("load: %s\n",ins[ninstrument].filename); - + part->loadXMLinstrument(ins[ninstrument].filename); - + }; /* * Makes current a bank directory */ -int Bank::loadbank(const char *bankdirname){ +int Bank::loadbank(const char *bankdirname) +{ DIR *dir=opendir(bankdirname); clearbank(); @@ -223,59 +233,59 @@ int Bank::loadbank(const char *bankdirname){ if (dirname!=NULL) delete[]dirname; dirname=new char[strlen(bankdirname)+1]; snprintf(dirname,strlen(bankdirname)+1,"%s",bankdirname); - + bankfiletitle=dirname; - // printf("loadbank %s/\n",bankdirname); + // printf("loadbank %s/\n",bankdirname); struct dirent *fn; - - while ((fn=readdir(dir))){ - const char *filename= fn->d_name; - - //sa verific daca e si extensia dorita - if (strstr(filename,INSTRUMENT_EXTENSION)==NULL) continue; - - //verify if the name is like this NNNN-name (where N is a digit) - int no=0; - unsigned int startname=0; - - for (unsigned int i=0;i<4;i++) { - if (strlen(filename)<=i) break; - - if ((filename[i]>='0')&&(filename[i]<='9')) { - no=no*10+(filename[i]-'0'); - startname++; - }; - }; - - - if ((startname+1)<strlen(filename)) startname++;//to take out the "-" - - char name[PART_MAX_NAME_LEN+1]; - ZERO(name,PART_MAX_NAME_LEN+1); - snprintf(name,PART_MAX_NAME_LEN,"%s",filename); - - //remove the file extension - for (int i=strlen(name)-1;i>=2;i--){ - if (name[i]=='.') { - name[i]='\0'; - break; - }; - }; - - if (no!=0){//the instrument position in the bank is found - addtobank(no-1,filename,&name[startname]); - } else { - addtobank(-1,filename,name); - }; - + + while ((fn=readdir(dir))) { + const char *filename= fn->d_name; + + //sa verific daca e si extensia dorita + if (strstr(filename,INSTRUMENT_EXTENSION)==NULL) continue; + + //verify if the name is like this NNNN-name (where N is a digit) + int no=0; + unsigned int startname=0; + + for (unsigned int i=0;i<4;i++) { + if (strlen(filename)<=i) break; + + if ((filename[i]>='0')&&(filename[i]<='9')) { + no=no*10+(filename[i]-'0'); + startname++; + }; + }; + + + if ((startname+1)<strlen(filename)) startname++;//to take out the "-" + + char name[PART_MAX_NAME_LEN+1]; + ZERO(name,PART_MAX_NAME_LEN+1); + snprintf(name,PART_MAX_NAME_LEN,"%s",filename); + + //remove the file extension + for (int i=strlen(name)-1;i>=2;i--) { + if (name[i]=='.') { + name[i]='\0'; + break; + }; + }; + + if (no!=0) {//the instrument position in the bank is found + addtobank(no-1,filename,&name[startname]); + } else { + addtobank(-1,filename,name); + }; + }; - - + + closedir(dir); if (dirname!=NULL) { - sprintf(config.cfg.currentBankDir,"%s",dirname); + sprintf(config.cfg.currentBankDir,"%s",dirname); }; return(0); @@ -284,14 +294,15 @@ int Bank::loadbank(const char *bankdirname){ /* * Makes a new bank, put it on a file and makes it current bank */ -int Bank::newbank(const char *newbankdirname){ +int Bank::newbank(const char *newbankdirname) +{ int result; char tmpfilename[MAX_STRING_SIZE]; char bankdir[MAX_STRING_SIZE]; snprintf(bankdir,MAX_STRING_SIZE,"%s",config.cfg.bankRootDirList[0]); - if (((bankdir[strlen(bankdir)-1])!='/')&&((bankdir[strlen(bankdir)-1])!='\\')){ - strncat(bankdir,"/",MAX_STRING_SIZE); + if (((bankdir[strlen(bankdir)-1])!='/')&&((bankdir[strlen(bankdir)-1])!='\\')) { + strncat(bankdir,"/",MAX_STRING_SIZE); }; strncat(bankdir,newbankdirname,MAX_STRING_SIZE); #ifdef OS_WINDOWS @@ -305,57 +316,62 @@ int Bank::newbank(const char *newbankdirname){ // printf("%s\n",tmpfilename); FILE *tmpfile=fopen(tmpfilename,"w+"); fclose(tmpfile); - + return(loadbank(bankdir)); }; /* * Check if the bank is locked (i.e. the file opened was readonly) */ -int Bank::locked(){ +int Bank::locked() +{ return(dirname==NULL); }; /* * Swaps a slot with another */ -void Bank::swapslot(unsigned int n1, unsigned int n2){ +void Bank::swapslot(unsigned int n1, unsigned int n2) +{ if ((n1==n2)||(locked())) return; if (emptyslot(n1)&&(emptyslot(n2))) return; - if (emptyslot(n1)){//change n1 to n2 in order to make - int tmp=n2;n2=n1;n1=tmp; + if (emptyslot(n1)) {//change n1 to n2 in order to make + int tmp=n2; + n2=n1; + n1=tmp; }; - - if (emptyslot(n2)){//this is just a movement from slot1 to slot2 - setname(n1,getname(n1),n2); - ins[n2]=ins[n1]; - ins[n1].used=false; - ins[n1].name[0]='\0'; - ins[n1].filename=NULL; - ins[n1].info.PADsynth_used=0; + + if (emptyslot(n2)) {//this is just a movement from slot1 to slot2 + setname(n1,getname(n1),n2); + ins[n2]=ins[n1]; + ins[n1].used=false; + ins[n1].name[0]='\0'; + ins[n1].filename=NULL; + ins[n1].info.PADsynth_used=0; } else {//if both slots are used - if (strcmp(ins[n1].name,ins[n2].name)==0){//change the name of the second instrument if the name are equal - strncat(ins[n2].name,"2",PART_MAX_NAME_LEN); - }; - setname(n1,getname(n1),n2); - setname(n2,getname(n2),n1); - ins_t tmp; - tmp.used=true; - strcpy(tmp.name,ins[n2].name); - char *tmpfilename=ins[n2].filename; - bool padsynth_used=ins[n2].info.PADsynth_used; - - ins[n2]=ins[n1]; - strcpy(ins[n1].name,tmp.name); - ins[n1].filename=tmpfilename; - ins[n1].info.PADsynth_used=padsynth_used; + if (strcmp(ins[n1].name,ins[n2].name)==0) {//change the name of the second instrument if the name are equal + strncat(ins[n2].name,"2",PART_MAX_NAME_LEN); + }; + setname(n1,getname(n1),n2); + setname(n2,getname(n2),n1); + ins_t tmp; + tmp.used=true; + strcpy(tmp.name,ins[n2].name); + char *tmpfilename=ins[n2].filename; + bool padsynth_used=ins[n2].info.PADsynth_used; + + ins[n2]=ins[n1]; + strcpy(ins[n1].name,tmp.name); + ins[n1].filename=tmpfilename; + ins[n1].info.PADsynth_used=padsynth_used; }; - + }; //a helper function that compares 2 banks[] arrays -int Bank_compar(const void *a,const void *b){ +int Bank_compar(const void *a,const void *b) +{ struct Bank::bankstruct *bank1= (Bank::bankstruct *)a; struct Bank::bankstruct *bank2= (Bank::bankstruct *)b; if (((bank1->name)==NULL)||((bank2->name)==NULL)) return(0); @@ -369,156 +385,160 @@ int Bank_compar(const void *a,const void *b){ * Re-scan for directories containing instrument banks */ -void Bank::rescanforbanks(){ - for (int i=0;i<MAX_NUM_BANKS;i++){ - if (banks[i].dir!=NULL) delete []banks[i].dir; - if (banks[i].name!=NULL) delete []banks[i].name; - banks[i].dir=NULL; - banks[i].name=NULL; +void Bank::rescanforbanks() +{ + for (int i=0;i<MAX_NUM_BANKS;i++) { + if (banks[i].dir!=NULL) delete []banks[i].dir; + if (banks[i].name!=NULL) delete []banks[i].name; + banks[i].dir=NULL; + banks[i].name=NULL; }; for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) if (config.cfg.bankRootDirList[i]!=NULL) scanrootdir(config.cfg.bankRootDirList[i]); //sort the banks - for (int j=0;j<MAX_NUM_BANKS-1;j++){ - for (int i=j+1;i<MAX_NUM_BANKS;i++){ - if (Bank_compar(&banks[i],&banks[j])) { - char *tmpname=banks[i].name; - char *tmpdir=banks[i].dir; - - banks[i].name=banks[j].name; - banks[i].dir=banks[j].dir; - - banks[j].name=tmpname; - banks[j].dir=tmpdir; - - }; - }; + for (int j=0;j<MAX_NUM_BANKS-1;j++) { + for (int i=j+1;i<MAX_NUM_BANKS;i++) { + if (Bank_compar(&banks[i],&banks[j])) { + char *tmpname=banks[i].name; + char *tmpdir=banks[i].dir; + + banks[i].name=banks[j].name; + banks[i].dir=banks[j].dir; + + banks[j].name=tmpname; + banks[j].dir=tmpdir; + + }; + }; }; - + //remove duplicate bank names int dupl=0; - for (int j=0;j<MAX_NUM_BANKS-1;j++){ - for (int i=j+1;i<MAX_NUM_BANKS;i++){ - if ((banks[i].name==NULL)||(banks[j].name==NULL)) continue; - if (strcmp(banks[i].name,banks[j].name)==0) {//add a [1] to the first bankname and [n] to others - char *tmpname=banks[i].name; - banks[i].name=new char[strlen(tmpname)+100]; - sprintf(banks[i].name,"%s[%d]",tmpname,dupl+2); - delete[]tmpname; - - if (dupl==0){ - char *tmpname=banks[j].name; - banks[j].name=new char[strlen(tmpname)+100]; - sprintf(banks[j].name,"%s[1]",tmpname); - delete[]tmpname; - }; - - dupl++; - } else dupl=0; - }; + for (int j=0;j<MAX_NUM_BANKS-1;j++) { + for (int i=j+1;i<MAX_NUM_BANKS;i++) { + if ((banks[i].name==NULL)||(banks[j].name==NULL)) continue; + if (strcmp(banks[i].name,banks[j].name)==0) {//add a [1] to the first bankname and [n] to others + char *tmpname=banks[i].name; + banks[i].name=new char[strlen(tmpname)+100]; + sprintf(banks[i].name,"%s[%d]",tmpname,dupl+2); + delete[]tmpname; + + if (dupl==0) { + char *tmpname=banks[j].name; + banks[j].name=new char[strlen(tmpname)+100]; + sprintf(banks[j].name,"%s[1]",tmpname); + delete[]tmpname; + }; + + dupl++; + } else dupl=0; + }; }; - -}; + +}; // private stuff -void Bank::scanrootdir(char *rootdir){ +void Bank::scanrootdir(char *rootdir) +{ // printf("Scanning root dir:%s\n",rootdir); DIR *dir=opendir(rootdir); if (dir==NULL) return; const int maxdirsize=1000; struct { - char dir[maxdirsize]; - char name[maxdirsize]; + char dir[maxdirsize]; + char name[maxdirsize]; }bank; const char *separator="/"; if (strlen(rootdir)) { - char tmp=rootdir[strlen(rootdir)-1]; - if ((tmp=='/') || (tmp=='\\')) separator=""; + char tmp=rootdir[strlen(rootdir)-1]; + if ((tmp=='/') || (tmp=='\\')) separator=""; }; - + struct dirent *fn; - while ((fn=readdir(dir))){ - const char *dirname=fn->d_name; - if (dirname[0]=='.') continue; - - snprintf(bank.dir,maxdirsize,"%s%s%s/",rootdir,separator,dirname); - snprintf(bank.name,maxdirsize,"%s",dirname); - //find out if the directory contains at least 1 instrument - bool isbank=false; - - DIR *d=opendir(bank.dir); - if (d==NULL) continue; - - struct dirent *fname; - - while((fname=readdir(d))){ - if ((strstr(fname->d_name,INSTRUMENT_EXTENSION)!=NULL)|| - (strstr(fname->d_name,FORCE_BANK_DIR_FILE)!=NULL)){ - isbank=true; - break;//aici as putea pune in loc de break un update la un counter care imi arata nr. de instrumente din bank - }; - }; - - closedir(d); - - if (isbank) { - int pos=-1; - for (int i=1;i<MAX_NUM_BANKS;i++){ //banks[0] e liber intotdeauna - if (banks[i].name==NULL) { - pos=i; - break; - }; - }; - - if (pos>=0) { - banks[pos].name=new char[maxdirsize]; - banks[pos].dir=new char[maxdirsize]; - snprintf(banks[pos].name,maxdirsize,"%s",bank.name); - snprintf(banks[pos].dir,maxdirsize,"%s",bank.dir); - }; - - }; - + while ((fn=readdir(dir))) { + const char *dirname=fn->d_name; + if (dirname[0]=='.') continue; + + snprintf(bank.dir,maxdirsize,"%s%s%s/",rootdir,separator,dirname); + snprintf(bank.name,maxdirsize,"%s",dirname); + //find out if the directory contains at least 1 instrument + bool isbank=false; + + DIR *d=opendir(bank.dir); + if (d==NULL) continue; + + struct dirent *fname; + + while ((fname=readdir(d))) { + if ((strstr(fname->d_name,INSTRUMENT_EXTENSION)!=NULL)|| + (strstr(fname->d_name,FORCE_BANK_DIR_FILE)!=NULL)) { + isbank=true; + break;//aici as putea pune in loc de break un update la un counter care imi arata nr. de instrumente din bank + }; + }; + + closedir(d); + + if (isbank) { + int pos=-1; + for (int i=1;i<MAX_NUM_BANKS;i++) { //banks[0] e liber intotdeauna + if (banks[i].name==NULL) { + pos=i; + break; + }; + }; + + if (pos>=0) { + banks[pos].name=new char[maxdirsize]; + banks[pos].dir=new char[maxdirsize]; + snprintf(banks[pos].name,maxdirsize,"%s",bank.name); + snprintf(banks[pos].dir,maxdirsize,"%s",bank.dir); + }; + + }; + }; closedir(dir); - + }; -void Bank::clearbank(){ +void Bank::clearbank() +{ for (int i=0;i<BANK_SIZE;i++) deletefrombank(i); if (dirname!=NULL) delete[]dirname; bankfiletitle=NULL; dirname=NULL; }; -int Bank::addtobank(int pos, const char *filename, const char* name){ - if ((pos>=0)&&(pos<BANK_SIZE)){ - if (ins[pos].used) pos=-1;//force it to find a new free position +int Bank::addtobank(int pos, const char *filename, const char* name) +{ + if ((pos>=0)&&(pos<BANK_SIZE)) { + if (ins[pos].used) pos=-1;//force it to find a new free position } else if (pos>=BANK_SIZE) pos=-1; - - + + if (pos<0) {//find a free position - for (int i=BANK_SIZE-1;i>=0;i--) - if (!ins[i].used) { - pos=i; - break; - }; - + for (int i=BANK_SIZE-1;i>=0;i--) + if (!ins[i].used) { + pos=i; + break; + }; + }; - + if (pos<0) return (-1);//the bank is full - // printf("%s %d\n",filename,pos); + // printf("%s %d\n",filename,pos); deletefrombank(pos); - + ins[pos].used=true; snprintf(ins[pos].name,PART_MAX_NAME_LEN,"%s",name); @@ -530,33 +550,35 @@ int Bank::addtobank(int pos, const char *filename, const char* name){ snprintf(ins[pos].filename,len+1,"%s/%s",dirname,filename); //see if PADsynth is used - if (config.cfg.CheckPADsynth){ - XMLwrapper *xml=new XMLwrapper(); - xml->checkfileinformation(ins[pos].filename); - - ins[pos].info.PADsynth_used=xml->information.PADsynth_used; - delete xml; + if (config.cfg.CheckPADsynth) { + XMLwrapper *xml=new XMLwrapper(); + xml->checkfileinformation(ins[pos].filename); + + ins[pos].info.PADsynth_used=xml->information.PADsynth_used; + delete xml; } else ins[pos].info.PADsynth_used=false; - + return(0); }; -bool Bank::isPADsynth_used(unsigned int ninstrument){ +bool Bank::isPADsynth_used(unsigned int ninstrument) +{ if (config.cfg.CheckPADsynth==0) return(0); - else return(ins[ninstrument].info.PADsynth_used); + else return(ins[ninstrument].info.PADsynth_used); }; -void Bank::deletefrombank(int pos){ +void Bank::deletefrombank(int pos) +{ if ((pos<0)||(pos>=BANK_SIZE)) return; ins[pos].used=false; ZERO(ins[pos].name,PART_MAX_NAME_LEN+1); if (ins[pos].filename!=NULL) { - delete []ins[pos].filename; - ins[pos].filename=NULL; + delete []ins[pos].filename; + ins[pos].filename=NULL; }; - + ZERO(tmpinsname[pos],PART_MAX_NAME_LEN+20); - + }; diff --git a/src/Misc/Bank.h b/src/Misc/Bank.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Bank.C - Instrument Bank Copyright (C) 2002-2005 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 + 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, @@ -36,71 +36,72 @@ /**The instrument Bank * \todo add in strings to replace char* */ -class Bank{ - public: - /**Constructor*/ - Bank(); - ~Bank(); - char *getname(unsigned int ninstrument); - char *getnamenumbered(unsigned int ninstrument); - void setname(unsigned int ninstrument,const char *newname,int newslot);//if newslot==-1 then this is ignored, else it will be put on that slot - bool isPADsynth_used(unsigned int ninstrument); - - /**returns 0 if the slot is not empty or 1 if the slot is empty - * \todo start using bool before facepalm*/ - int emptyslot(unsigned int ninstrument); - - /**Empties out the selected slot*/ - void clearslot(unsigned int ninstrument); - /**Saves the given Part to slot*/ - void savetoslot(unsigned int ninstrument,Part *part); - /**Loads the given slot into a Part*/ - void loadfromslot(unsigned int ninstrument,Part *part); - - /**Swaps Slots*/ - void swapslot(unsigned int n1,unsigned int n2); - - int loadbank(const char *bankdirname); - int newbank(const char *newbankdirname); - - char *bankfiletitle; //this is shown on the UI of the bank (the title of the window) - int locked(); - - void rescanforbanks(); - - struct bankstruct{ - char *dir; - char *name; - }; - - bankstruct banks[MAX_NUM_BANKS]; - - private: - - //it adds a filename to the bank - //if pos is -1 it try to find a position - //returns -1 if the bank is full, or 0 if the instrument was added - int addtobank(int pos,const char* filename,const char* name); - - void deletefrombank(int pos); - - void clearbank(); - - char defaultinsname[PART_MAX_NAME_LEN]; - char tmpinsname[BANK_SIZE][PART_MAX_NAME_LEN+20];//this keeps the numbered names - - struct ins_t{ - bool used; - char name[PART_MAX_NAME_LEN+1]; - char *filename; - struct{ - bool PADsynth_used; - } info; - }ins[BANK_SIZE]; - - char *dirname; - - void scanrootdir(char *rootdir);//scans a root dir for banks +class Bank +{ +public: + /**Constructor*/ + Bank(); + ~Bank(); + char *getname(unsigned int ninstrument); + char *getnamenumbered(unsigned int ninstrument); + void setname(unsigned int ninstrument,const char *newname,int newslot);//if newslot==-1 then this is ignored, else it will be put on that slot + bool isPADsynth_used(unsigned int ninstrument); + + /**returns 0 if the slot is not empty or 1 if the slot is empty + * \todo start using bool before facepalm*/ + int emptyslot(unsigned int ninstrument); + + /**Empties out the selected slot*/ + void clearslot(unsigned int ninstrument); + /**Saves the given Part to slot*/ + void savetoslot(unsigned int ninstrument,Part *part); + /**Loads the given slot into a Part*/ + void loadfromslot(unsigned int ninstrument,Part *part); + + /**Swaps Slots*/ + void swapslot(unsigned int n1,unsigned int n2); + + int loadbank(const char *bankdirname); + int newbank(const char *newbankdirname); + + char *bankfiletitle; //this is shown on the UI of the bank (the title of the window) + int locked(); + + void rescanforbanks(); + + struct bankstruct { + char *dir; + char *name; + }; + + bankstruct banks[MAX_NUM_BANKS]; + +private: + + //it adds a filename to the bank + //if pos is -1 it try to find a position + //returns -1 if the bank is full, or 0 if the instrument was added + int addtobank(int pos,const char* filename,const char* name); + + void deletefrombank(int pos); + + void clearbank(); + + char defaultinsname[PART_MAX_NAME_LEN]; + char tmpinsname[BANK_SIZE][PART_MAX_NAME_LEN+20];//this keeps the numbered names + + struct ins_t { + bool used; + char name[PART_MAX_NAME_LEN+1]; + char *filename; + struct { + bool PADsynth_used; + } info; + }ins[BANK_SIZE]; + + char *dirname; + + void scanrootdir(char *rootdir);//scans a root dir for banks }; #endif diff --git a/src/Misc/Config.C b/src/Misc/Config.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Config.C - Configuration file functions Copyright (C) 2003-2005 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 + 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, @@ -32,16 +32,18 @@ #include "Config.h" #include "XMLwrapper.h" -Config::Config(){ +Config::Config() +{ }; -void Config::init(){ +void Config::init() +{ maxstringsize=MAX_STRING_SIZE;//for ui //defaults cfg.SampleRate=44100; cfg.SoundBufferSize=256; cfg.OscilSize=1024; cfg.SwapStereo=0; - + cfg.LinuxOSSWaveOutDev=new char[MAX_STRING_SIZE]; snprintf(cfg.LinuxOSSWaveOutDev,MAX_STRING_SIZE,"/dev/dsp"); cfg.LinuxOSSSeqInDev=new char[MAX_STRING_SIZE]; @@ -52,7 +54,7 @@ void Config::init(){ cfg.WindowsWaveOutId=0; cfg.WindowsMidiInId=0; - + cfg.BankUIAutoClose=0; cfg.DumpNotesToFile=0; cfg.DumpAppend=1; @@ -64,7 +66,8 @@ void Config::init(){ cfg.UserInterfaceMode=0; cfg.VirKeybLayout=1; - winwavemax=1;winmidimax=1; + winwavemax=1; + winmidimax=1; //try to find out how many input midi devices are there #ifdef WINMIDIIN winmidimax=midiInGetNumDevs(); @@ -72,107 +75,108 @@ void Config::init(){ #endif winmididevices=new winmidionedevice[winmidimax]; for (int i=0;i<winmidimax;i++) { - winmididevices[i].name=new char[MAX_STRING_SIZE]; - for (int j=0;j<MAX_STRING_SIZE;j++) winmididevices[i].name[j]='\0'; + winmididevices[i].name=new char[MAX_STRING_SIZE]; + for (int j=0;j<MAX_STRING_SIZE;j++) winmididevices[i].name[j]='\0'; }; //get the midi input devices name #ifdef WINMIDIIN MIDIINCAPS midiincaps; - for (int i=0;i<winmidimax;i++){ - if (! midiInGetDevCaps(i,&midiincaps,sizeof(MIDIINCAPS))) - snprintf(winmididevices[i].name,MAX_STRING_SIZE,"%s",midiincaps.szPname); + for (int i=0;i<winmidimax;i++) { + if (! midiInGetDevCaps(i,&midiincaps,sizeof(MIDIINCAPS))) + snprintf(winmididevices[i].name,MAX_STRING_SIZE,"%s",midiincaps.szPname); }; #endif for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) cfg.bankRootDirList[i]=NULL; cfg.currentBankDir=new char[MAX_STRING_SIZE]; sprintf(cfg.currentBankDir,"./testbnk"); - + for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) cfg.presetsDirList[i]=NULL; - + char filename[MAX_STRING_SIZE]; getConfigFileName(filename,MAX_STRING_SIZE); readConfig(filename); - if (cfg.bankRootDirList[0]==NULL){ + if (cfg.bankRootDirList[0]==NULL) { #if defined(OS_LINUX) - //banks + //banks cfg.bankRootDirList[0]=new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[0],"~/banks"); + sprintf(cfg.bankRootDirList[0],"~/banks"); - cfg.bankRootDirList[1]=new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[1],"./"); + cfg.bankRootDirList[1]=new char[MAX_STRING_SIZE]; + sprintf(cfg.bankRootDirList[1],"./"); cfg.bankRootDirList[2]=new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[2],"/usr/share/zynaddsubfx/banks"); + sprintf(cfg.bankRootDirList[2],"/usr/share/zynaddsubfx/banks"); + + cfg.bankRootDirList[3]=new char[MAX_STRING_SIZE]; + sprintf(cfg.bankRootDirList[3],"/usr/local/share/zynaddsubfx/banks"); - cfg.bankRootDirList[3]=new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[3],"/usr/local/share/zynaddsubfx/banks"); + cfg.bankRootDirList[4]=new char[MAX_STRING_SIZE]; + sprintf(cfg.bankRootDirList[4],"../banks"); - cfg.bankRootDirList[4]=new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[4],"../banks"); + cfg.bankRootDirList[5]=new char[MAX_STRING_SIZE]; + sprintf(cfg.bankRootDirList[5],"banks"); - cfg.bankRootDirList[5]=new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[5],"banks"); - #else - //banks - cfg.bankRootDirList[0]=new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[0],"./"); + //banks + cfg.bankRootDirList[0]=new char[MAX_STRING_SIZE]; + sprintf(cfg.bankRootDirList[0],"./"); #ifdef VSTAUDIOOUT - cfg.bankRootDirList[1]=new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[1],"c:/Program Files/ZynAddSubFX/banks"); + cfg.bankRootDirList[1]=new char[MAX_STRING_SIZE]; + sprintf(cfg.bankRootDirList[1],"c:/Program Files/ZynAddSubFX/banks"); #else - cfg.bankRootDirList[1]=new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[1],"../banks"); + cfg.bankRootDirList[1]=new char[MAX_STRING_SIZE]; + sprintf(cfg.bankRootDirList[1],"../banks"); #endif - cfg.bankRootDirList[2]=new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[2],"banks"); - + cfg.bankRootDirList[2]=new char[MAX_STRING_SIZE]; + sprintf(cfg.bankRootDirList[2],"banks"); + #endif }; - if (cfg.presetsDirList[0]==NULL){ + if (cfg.presetsDirList[0]==NULL) { #if defined(OS_LINUX) - //presets - cfg.presetsDirList[0]=new char[MAX_STRING_SIZE]; - sprintf(cfg.presetsDirList[0],"./"); + //presets + cfg.presetsDirList[0]=new char[MAX_STRING_SIZE]; + sprintf(cfg.presetsDirList[0],"./"); + + cfg.presetsDirList[1]=new char[MAX_STRING_SIZE]; + sprintf(cfg.presetsDirList[1],"../presets"); - cfg.presetsDirList[1]=new char[MAX_STRING_SIZE]; - sprintf(cfg.presetsDirList[1],"../presets"); + cfg.presetsDirList[2]=new char[MAX_STRING_SIZE]; + sprintf(cfg.presetsDirList[2],"presets"); - cfg.presetsDirList[2]=new char[MAX_STRING_SIZE]; - sprintf(cfg.presetsDirList[2],"presets"); - cfg.presetsDirList[3]=new char[MAX_STRING_SIZE]; - sprintf(cfg.presetsDirList[3],"/usr/share/zynaddsubfx/presets"); + sprintf(cfg.presetsDirList[3],"/usr/share/zynaddsubfx/presets"); + + cfg.presetsDirList[4]=new char[MAX_STRING_SIZE]; + sprintf(cfg.presetsDirList[4],"/usr/local/share/zynaddsubfx/presets"); - cfg.presetsDirList[4]=new char[MAX_STRING_SIZE]; - sprintf(cfg.presetsDirList[4],"/usr/local/share/zynaddsubfx/presets"); - #else - //presets - cfg.presetsDirList[0]=new char[MAX_STRING_SIZE]; - sprintf(cfg.presetsDirList[0],"./"); + //presets + cfg.presetsDirList[0]=new char[MAX_STRING_SIZE]; + sprintf(cfg.presetsDirList[0],"./"); #ifdef VSTAUDIOOUT - cfg.presetsDirList[1]=new char[MAX_STRING_SIZE]; - sprintf(cfg.presetsDirList[1],"c:/Program Files/ZynAddSubFX/presets"); + cfg.presetsDirList[1]=new char[MAX_STRING_SIZE]; + sprintf(cfg.presetsDirList[1],"c:/Program Files/ZynAddSubFX/presets"); #else - cfg.presetsDirList[1]=new char[MAX_STRING_SIZE]; - sprintf(cfg.presetsDirList[1],"../presets"); + cfg.presetsDirList[1]=new char[MAX_STRING_SIZE]; + sprintf(cfg.presetsDirList[1],"../presets"); #endif - cfg.presetsDirList[2]=new char[MAX_STRING_SIZE]; - sprintf(cfg.presetsDirList[2],"presets"); + cfg.presetsDirList[2]=new char[MAX_STRING_SIZE]; + sprintf(cfg.presetsDirList[2],"presets"); #endif }; }; -Config::~Config(){ +Config::~Config() +{ delete [] cfg.LinuxOSSWaveOutDev; delete [] cfg.LinuxOSSSeqInDev; @@ -183,78 +187,82 @@ Config::~Config(){ }; -void Config::save(){ +void Config::save() +{ char filename[MAX_STRING_SIZE]; getConfigFileName(filename,MAX_STRING_SIZE); saveConfig(filename); }; -void Config::clearbankrootdirlist(){ +void Config::clearbankrootdirlist() +{ for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) { - if (cfg.bankRootDirList[i]==NULL) delete(cfg.bankRootDirList[i]); - cfg.bankRootDirList[i]=NULL; + if (cfg.bankRootDirList[i]==NULL) delete(cfg.bankRootDirList[i]); + cfg.bankRootDirList[i]=NULL; }; }; -void Config::clearpresetsdirlist(){ +void Config::clearpresetsdirlist() +{ for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) { - if (cfg.presetsDirList[i]==NULL) delete(cfg.presetsDirList[i]); - cfg.presetsDirList[i]=NULL; + if (cfg.presetsDirList[i]==NULL) delete(cfg.presetsDirList[i]); + cfg.presetsDirList[i]=NULL; }; }; -void Config::readConfig(const char *filename){ +void Config::readConfig(const char *filename) +{ XMLwrapper *xmlcfg=new XMLwrapper(); if (xmlcfg->loadXMLfile(filename)<0) return; - if (xmlcfg->enterbranch("CONFIGURATION")){ - cfg.SampleRate=xmlcfg->getpar("sample_rate",cfg.SampleRate,4000,1024000); - cfg.SoundBufferSize=xmlcfg->getpar("sound_buffer_size",cfg.SoundBufferSize,16,8192); - cfg.OscilSize=xmlcfg->getpar("oscil_size",cfg.OscilSize,MAX_AD_HARMONICS*2,131072); - cfg.SwapStereo=xmlcfg->getpar("swap_stereo",cfg.SwapStereo,0,1); - cfg.BankUIAutoClose=xmlcfg->getpar("bank_window_auto_close",cfg.BankUIAutoClose,0,1); - - cfg.DumpNotesToFile=xmlcfg->getpar("dump_notes_to_file",cfg.DumpNotesToFile,0,1); - cfg.DumpAppend=xmlcfg->getpar("dump_append",cfg.DumpAppend,0,1); - xmlcfg->getparstr("dump_file",cfg.DumpFile,MAX_STRING_SIZE); - - cfg.GzipCompression=xmlcfg->getpar("gzip_compression",cfg.GzipCompression,0,9); - - xmlcfg->getparstr("bank_current",cfg.currentBankDir,MAX_STRING_SIZE); - cfg.Interpolation=xmlcfg->getpar("interpolation",cfg.Interpolation,0,1); - - cfg.CheckPADsynth=xmlcfg->getpar("check_pad_synth",cfg.CheckPADsynth,0,1); - - - cfg.UserInterfaceMode=xmlcfg->getpar("user_interface_mode",cfg.UserInterfaceMode,0,2); - cfg.VirKeybLayout=xmlcfg->getpar("virtual_keyboard_layout",cfg.VirKeybLayout,0,10); - - //get bankroot dirs - for (int i=0;i<MAX_BANK_ROOT_DIRS;i++){ - if (xmlcfg->enterbranch("BANKROOT",i)){ - cfg.bankRootDirList[i]=new char[MAX_STRING_SIZE]; - xmlcfg->getparstr("bank_root",cfg.bankRootDirList[i],MAX_STRING_SIZE); - xmlcfg->exitbranch(); - }; - }; - - //get preset root dirs - for (int i=0;i<MAX_BANK_ROOT_DIRS;i++){ - if (xmlcfg->enterbranch("PRESETSROOT",i)){ - cfg.presetsDirList[i]=new char[MAX_STRING_SIZE]; - xmlcfg->getparstr("presets_root",cfg.presetsDirList[i],MAX_STRING_SIZE); - xmlcfg->exitbranch(); - }; - }; - - //linux stuff - xmlcfg->getparstr("linux_oss_wave_out_dev",cfg.LinuxOSSWaveOutDev,MAX_STRING_SIZE); - xmlcfg->getparstr("linux_oss_seq_in_dev",cfg.LinuxOSSSeqInDev,MAX_STRING_SIZE); - - //windows stuff - cfg.WindowsWaveOutId=xmlcfg->getpar("windows_wave_out_id",cfg.WindowsWaveOutId,0,winwavemax); - cfg.WindowsMidiInId=xmlcfg->getpar("windows_midi_in_id",cfg.WindowsMidiInId,0,winmidimax); - - xmlcfg->exitbranch(); + if (xmlcfg->enterbranch("CONFIGURATION")) { + cfg.SampleRate=xmlcfg->getpar("sample_rate",cfg.SampleRate,4000,1024000); + cfg.SoundBufferSize=xmlcfg->getpar("sound_buffer_size",cfg.SoundBufferSize,16,8192); + cfg.OscilSize=xmlcfg->getpar("oscil_size",cfg.OscilSize,MAX_AD_HARMONICS*2,131072); + cfg.SwapStereo=xmlcfg->getpar("swap_stereo",cfg.SwapStereo,0,1); + cfg.BankUIAutoClose=xmlcfg->getpar("bank_window_auto_close",cfg.BankUIAutoClose,0,1); + + cfg.DumpNotesToFile=xmlcfg->getpar("dump_notes_to_file",cfg.DumpNotesToFile,0,1); + cfg.DumpAppend=xmlcfg->getpar("dump_append",cfg.DumpAppend,0,1); + xmlcfg->getparstr("dump_file",cfg.DumpFile,MAX_STRING_SIZE); + + cfg.GzipCompression=xmlcfg->getpar("gzip_compression",cfg.GzipCompression,0,9); + + xmlcfg->getparstr("bank_current",cfg.currentBankDir,MAX_STRING_SIZE); + cfg.Interpolation=xmlcfg->getpar("interpolation",cfg.Interpolation,0,1); + + cfg.CheckPADsynth=xmlcfg->getpar("check_pad_synth",cfg.CheckPADsynth,0,1); + + + cfg.UserInterfaceMode=xmlcfg->getpar("user_interface_mode",cfg.UserInterfaceMode,0,2); + cfg.VirKeybLayout=xmlcfg->getpar("virtual_keyboard_layout",cfg.VirKeybLayout,0,10); + + //get bankroot dirs + for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) { + if (xmlcfg->enterbranch("BANKROOT",i)) { + cfg.bankRootDirList[i]=new char[MAX_STRING_SIZE]; + xmlcfg->getparstr("bank_root",cfg.bankRootDirList[i],MAX_STRING_SIZE); + xmlcfg->exitbranch(); + }; + }; + + //get preset root dirs + for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) { + if (xmlcfg->enterbranch("PRESETSROOT",i)) { + cfg.presetsDirList[i]=new char[MAX_STRING_SIZE]; + xmlcfg->getparstr("presets_root",cfg.presetsDirList[i],MAX_STRING_SIZE); + xmlcfg->exitbranch(); + }; + }; + + //linux stuff + xmlcfg->getparstr("linux_oss_wave_out_dev",cfg.LinuxOSSWaveOutDev,MAX_STRING_SIZE); + xmlcfg->getparstr("linux_oss_seq_in_dev",cfg.LinuxOSSSeqInDev,MAX_STRING_SIZE); + + //windows stuff + cfg.WindowsWaveOutId=xmlcfg->getpar("windows_wave_out_id",cfg.WindowsWaveOutId,0,winwavemax); + cfg.WindowsMidiInId=xmlcfg->getpar("windows_midi_in_id",cfg.WindowsMidiInId,0,winmidimax); + + xmlcfg->exitbranch(); }; delete(xmlcfg); @@ -262,64 +270,66 @@ void Config::readConfig(const char *filename){ }; -void Config::saveConfig(const char *filename){ +void Config::saveConfig(const char *filename) +{ XMLwrapper *xmlcfg=new XMLwrapper(); - - xmlcfg->beginbranch("CONFIGURATION"); - - xmlcfg->addpar("sample_rate",cfg.SampleRate); - xmlcfg->addpar("sound_buffer_size",cfg.SoundBufferSize); - xmlcfg->addpar("oscil_size",cfg.OscilSize); - xmlcfg->addpar("swap_stereo",cfg.SwapStereo); - xmlcfg->addpar("bank_window_auto_close",cfg.BankUIAutoClose); - xmlcfg->addpar("dump_notes_to_file",cfg.DumpNotesToFile); - xmlcfg->addpar("dump_append",cfg.DumpAppend); - xmlcfg->addparstr("dump_file",cfg.DumpFile); + xmlcfg->beginbranch("CONFIGURATION"); + + xmlcfg->addpar("sample_rate",cfg.SampleRate); + xmlcfg->addpar("sound_buffer_size",cfg.SoundBufferSize); + xmlcfg->addpar("oscil_size",cfg.OscilSize); + xmlcfg->addpar("swap_stereo",cfg.SwapStereo); + xmlcfg->addpar("bank_window_auto_close",cfg.BankUIAutoClose); - xmlcfg->addpar("gzip_compression",cfg.GzipCompression); + xmlcfg->addpar("dump_notes_to_file",cfg.DumpNotesToFile); + xmlcfg->addpar("dump_append",cfg.DumpAppend); + xmlcfg->addparstr("dump_file",cfg.DumpFile); - xmlcfg->addpar("check_pad_synth",cfg.CheckPADsynth); + xmlcfg->addpar("gzip_compression",cfg.GzipCompression); - xmlcfg->addparstr("bank_current",cfg.currentBankDir); + xmlcfg->addpar("check_pad_synth",cfg.CheckPADsynth); - xmlcfg->addpar("user_interface_mode",cfg.UserInterfaceMode); - xmlcfg->addpar("virtual_keyboard_layout",cfg.VirKeybLayout); + xmlcfg->addparstr("bank_current",cfg.currentBankDir); + xmlcfg->addpar("user_interface_mode",cfg.UserInterfaceMode); + xmlcfg->addpar("virtual_keyboard_layout",cfg.VirKeybLayout); - for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) if (cfg.bankRootDirList[i]!=NULL) { - xmlcfg->beginbranch("BANKROOT",i); - xmlcfg->addparstr("bank_root",cfg.bankRootDirList[i]); - xmlcfg->endbranch(); - }; - for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) if (cfg.presetsDirList[i]!=NULL) { - xmlcfg->beginbranch("PRESETSROOT",i); - xmlcfg->addparstr("presets_root",cfg.presetsDirList[i]); - xmlcfg->endbranch(); - }; + for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) if (cfg.bankRootDirList[i]!=NULL) { + xmlcfg->beginbranch("BANKROOT",i); + xmlcfg->addparstr("bank_root",cfg.bankRootDirList[i]); + xmlcfg->endbranch(); + }; - xmlcfg->addpar("interpolation",cfg.Interpolation); + for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) if (cfg.presetsDirList[i]!=NULL) { + xmlcfg->beginbranch("PRESETSROOT",i); + xmlcfg->addparstr("presets_root",cfg.presetsDirList[i]); + xmlcfg->endbranch(); + }; - //linux stuff - xmlcfg->addparstr("linux_oss_wave_out_dev",cfg.LinuxOSSWaveOutDev); - xmlcfg->addparstr("linux_oss_seq_in_dev",cfg.LinuxOSSSeqInDev); - - //windows stuff - xmlcfg->addpar("windows_wave_out_id",cfg.WindowsWaveOutId); - xmlcfg->addpar("windows_midi_in_id",cfg.WindowsMidiInId); + xmlcfg->addpar("interpolation",cfg.Interpolation); + + //linux stuff + xmlcfg->addparstr("linux_oss_wave_out_dev",cfg.LinuxOSSWaveOutDev); + xmlcfg->addparstr("linux_oss_seq_in_dev",cfg.LinuxOSSSeqInDev); + + //windows stuff + xmlcfg->addpar("windows_wave_out_id",cfg.WindowsWaveOutId); + xmlcfg->addpar("windows_midi_in_id",cfg.WindowsMidiInId); xmlcfg->endbranch(); - + int tmp=cfg.GzipCompression; cfg.GzipCompression=0; xmlcfg->saveXMLfile(filename); cfg.GzipCompression=tmp; - + delete(xmlcfg); }; -void Config::getConfigFileName(char *name, int namesize){ +void Config::getConfigFileName(char *name, int namesize) +{ name[0]=0; #ifdef OS_LINUX snprintf(name,namesize,"%s%s",getenv("HOME"),"/.zynaddsubfxXML.cfg"); diff --git a/src/Misc/Config.h b/src/Misc/Config.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Config.h - Configuration file functions Copyright (C) 2003-2005 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 + 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, @@ -27,44 +27,45 @@ #define MAX_BANK_ROOT_DIRS 100 /**Configuration file functions*/ -class Config{ - public: - /** Constructor*/ - Config(); - /** Destructor*/ - ~Config(); - struct { - char *LinuxOSSWaveOutDev,*LinuxOSSSeqInDev; - int SampleRate,SoundBufferSize,OscilSize,SwapStereo; - int WindowsWaveOutId,WindowsMidiInId; - int BankUIAutoClose; - int DumpNotesToFile,DumpAppend; - int GzipCompression; - int Interpolation; - char *DumpFile; - char *bankRootDirList[MAX_BANK_ROOT_DIRS],*currentBankDir; - char *presetsDirList[MAX_BANK_ROOT_DIRS]; - int CheckPADsynth; - int UserInterfaceMode; - int VirKeybLayout; - } cfg; - int winwavemax,winmidimax;//number of wave/midi devices on Windows - int maxstringsize; - - struct winmidionedevice{ - char *name; - }; - winmidionedevice *winmididevices; +class Config +{ +public: + /** Constructor*/ + Config(); + /** Destructor*/ + ~Config(); + struct { + char *LinuxOSSWaveOutDev,*LinuxOSSSeqInDev; + int SampleRate,SoundBufferSize,OscilSize,SwapStereo; + int WindowsWaveOutId,WindowsMidiInId; + int BankUIAutoClose; + int DumpNotesToFile,DumpAppend; + int GzipCompression; + int Interpolation; + char *DumpFile; + char *bankRootDirList[MAX_BANK_ROOT_DIRS],*currentBankDir; + char *presetsDirList[MAX_BANK_ROOT_DIRS]; + int CheckPADsynth; + int UserInterfaceMode; + int VirKeybLayout; + } cfg; + int winwavemax,winmidimax;//number of wave/midi devices on Windows + int maxstringsize; + + struct winmidionedevice { + char *name; + }; + winmidionedevice *winmididevices; + + void clearbankrootdirlist(); + void clearpresetsdirlist(); + void init(); + void save(); - void clearbankrootdirlist(); - void clearpresetsdirlist(); - void init(); - void save(); - - private: - void readConfig(const char *filename); - void saveConfig(const char *filename); - void getConfigFileName(char *name,int namesize); +private: + void readConfig(const char *filename); + void saveConfig(const char *filename); + void getConfigFileName(char *name,int namesize); }; #endif diff --git a/src/Misc/Control.h b/src/Misc/Control.h @@ -1,13 +1,13 @@ /* ZynAddSubFX - a software synthesizer - + Control.h - Defines a variable that can be controled from a frontend Copyright (C) 2009 Harald Hvaal Author: Harald Hvaal 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 + 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, @@ -27,74 +27,74 @@ class Control { - public: - /** - * The parent is the logical owner of this control. Parent should only - * be null for the root node. - * The id is a string uniquely identifying this control within the - * context of the parent control. No spaces or dots are allowed in this - * id. - * Children id's are denoted by <parent-id>.<children-id>, so that one - * can refer to any control in the hierarchy by separating them with - * dots. Example: Main.AddSynth.FrequencyLFO.Amplitude - */ - Control(Control *parent, string id); - - /** - * Will recursively get the XML representation for all the subcontrols. - * Used for saving to file and copy-pasting settings - */ - string getXMLRepresentation(); - - /** - * Set the value of this (and possibly subcomponents as well) based on - * a xml description. - */ - void restoreFromXML(string xml); - - /** - * Register a controluser. This will cause this user to be notified - * whenever the contents of the control changes. - */ - void registerControlUser(ControlUser *user); - - /** - * This should return a string representation of the controls internal - * value - */ - virtual string getStringRepresentation() = 0; +public: + /** + * The parent is the logical owner of this control. Parent should only + * be null for the root node. + * The id is a string uniquely identifying this control within the + * context of the parent control. No spaces or dots are allowed in this + * id. + * Children id's are denoted by <parent-id>.<children-id>, so that one + * can refer to any control in the hierarchy by separating them with + * dots. Example: Main.AddSynth.FrequencyLFO.Amplitude + */ + Control(Control *parent, string id); + + /** + * Will recursively get the XML representation for all the subcontrols. + * Used for saving to file and copy-pasting settings + */ + string getXMLRepresentation(); + + /** + * Set the value of this (and possibly subcomponents as well) based on + * a xml description. + */ + void restoreFromXML(string xml); + + /** + * Register a controluser. This will cause this user to be notified + * whenever the contents of the control changes. + */ + void registerControlUser(ControlUser *user); + + /** + * This should return a string representation of the controls internal + * value + */ + virtual string getStringRepresentation() = 0; }; class FloatControl : public Control { - public: - /** - * Set the value of this control. If the ControlUser variable is set, - * then this user will not be updated with the new value. This is to - * avoid setting a value being set back to the source that set it - * (which would be redundant, or possibly causing infinite setValue - * loops). - * NOTE: this function is thread-safe (using a mutex internally) - */ - void setValue(float value, ControlUser *user = NULL); - - /** - * Reimplemented from Control - */ - virtual string getStringRepresentation(); - - float value(); +public: + /** + * Set the value of this control. If the ControlUser variable is set, + * then this user will not be updated with the new value. This is to + * avoid setting a value being set back to the source that set it + * (which would be redundant, or possibly causing infinite setValue + * loops). + * NOTE: this function is thread-safe (using a mutex internally) + */ + void setValue(float value, ControlUser *user = NULL); + + /** + * Reimplemented from Control + */ + virtual string getStringRepresentation(); + + float value(); }; class ControlUser { - public: - /** - * Pure virtual method, to notify the controluser that the value has - * been changed internally, and needs to be read again. - */ - virtual void controlUpdated(Control *control) = 0; +public: + /** + * Pure virtual method, to notify the controluser that the value has + * been changed internally, and needs to be read again. + */ + virtual void controlUpdated(Control *control) = 0; }; #endif /* _CONTROL_H_ */ diff --git a/src/Misc/Dump.C b/src/Misc/Dump.C @@ -1,13 +1,13 @@ /* ZynAddSubFX - a software synthesizer - + Dump.C - It dumps the notes to a text file Copyright (C) 2002-2005 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 + 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, @@ -26,72 +26,80 @@ Dump dump; -Dump::Dump(){ +Dump::Dump() +{ file=NULL; tick=0; k=0; keyspressed=0; }; -Dump::~Dump(){ +Dump::~Dump() +{ if (file!=NULL) { - double duration=(double)tick*(double) SOUND_BUFFER_SIZE/(double) SAMPLE_RATE; - fprintf(file,"\n# statistics: duration = %d seconds; keyspressed = %d\n\n\n\n",(int) duration,keyspressed); - fclose(file); + double duration=(double)tick*(double) SOUND_BUFFER_SIZE/(double) SAMPLE_RATE; + fprintf(file,"\n# statistics: duration = %d seconds; keyspressed = %d\n\n\n\n",(int) duration,keyspressed); + fclose(file); }; }; -void Dump::startnow(){ +void Dump::startnow() +{ if (file!=NULL) return;//the file is already open - if (config.cfg.DumpNotesToFile!=0){ - if (config.cfg.DumpAppend!=0) file=fopen(config.cfg.DumpFile,"a"); - else file=fopen(config.cfg.DumpFile,"w"); - if (file==NULL) return; - if (config.cfg.DumpAppend!=0) fprintf(file,"%s","#************************************\n"); - - time_t tm=time(NULL); - - fprintf(file,"#date/time = %s\n",ctime(&tm)); - fprintf(file,"#1 tick = %g milliseconds\n",SOUND_BUFFER_SIZE*1000.0/SAMPLE_RATE); - fprintf(file,"SAMPLERATE = %d\n",SAMPLE_RATE); - fprintf(file,"TICKSIZE = %d #samples\n",SOUND_BUFFER_SIZE); - fprintf(file,"\n\nSTART\n"); + if (config.cfg.DumpNotesToFile!=0) { + if (config.cfg.DumpAppend!=0) file=fopen(config.cfg.DumpFile,"a"); + else file=fopen(config.cfg.DumpFile,"w"); + if (file==NULL) return; + if (config.cfg.DumpAppend!=0) fprintf(file,"%s","#************************************\n"); + + time_t tm=time(NULL); + + fprintf(file,"#date/time = %s\n",ctime(&tm)); + fprintf(file,"#1 tick = %g milliseconds\n",SOUND_BUFFER_SIZE*1000.0/SAMPLE_RATE); + fprintf(file,"SAMPLERATE = %d\n",SAMPLE_RATE); + fprintf(file,"TICKSIZE = %d #samples\n",SOUND_BUFFER_SIZE); + fprintf(file,"\n\nSTART\n"); }; }; -void Dump::inctick(){ +void Dump::inctick() +{ tick++; }; -void Dump::dumpnote(char chan,char note, char vel){ +void Dump::dumpnote(char chan,char note, char vel) +{ if (file==NULL) return; if (note==0) return; if (vel==0) fprintf(file,"n %d -> %d %d \n",tick,chan,note);//note off - else fprintf(file,"N %d -> %d %d %d \n",tick,chan,note,vel);//note on - + else fprintf(file,"N %d -> %d %d %d \n",tick,chan,note,vel);//note on + if (vel!=0) keyspressed++; #ifndef JACKAUDIOOUT if (k++>25) { - fflush(file); - k=0; + fflush(file); + k=0; }; #endif }; -void Dump::dumpcontroller(char chan,unsigned int type,int par){ +void Dump::dumpcontroller(char chan,unsigned int type,int par) +{ if (file==NULL) return; - switch(type){ - case C_pitchwheel:fprintf(file,"P %d -> %d %d\n",tick,chan,par); - break; - default:fprintf(file,"C %d -> %d %d %d\n",tick,chan,type,par); - break; + switch (type) { + case C_pitchwheel: + fprintf(file,"P %d -> %d %d\n",tick,chan,par); + break; + default: + fprintf(file,"C %d -> %d %d %d\n",tick,chan,type,par); + break; }; #ifndef JACKAUDIOOUT if (k++>25) { - fflush(file); - k=0; + fflush(file); + k=0; }; #endif }; diff --git a/src/Misc/Dump.h b/src/Misc/Dump.h @@ -1,13 +1,13 @@ /* ZynAddSubFX - a software synthesizer - + Dump.h - It dumps the notes to a text file Copyright (C) 2002-2005 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 + 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, @@ -28,35 +28,36 @@ * \todo see if this object should have knowledge about the file * that it will write to * \todo upgrade from stdio to iostream*/ -class Dump{ - public: - /**Constructor*/ - Dump(); - /**Destructor - * Closes the dumpfile*/ - ~Dump(); - /**Open dumpfile and prepare it for dumps - * \todo see if this fits better in the constructor*/ - void startnow(); - /**Tick the timestamp*/ - void inctick(); - /**Dump Note to dumpfile - * @param chan The channel of the note - * @param note The note - * @param vel The velocity of the note*/ - void dumpnote(char chan,char note, char vel); - /** Dump the Controller - * @param chan The channel of the Controller - * @param type The type - * @param par The value of the controller - * \todo figure out what type is exactly meaning*/ - void dumpcontroller(char chan,unsigned int type,int par); - - private: - FILE *file; - int tick; - int k;//This appears to be a constant used to flush the file - //periodically when JACK is used - int keyspressed; +class Dump +{ +public: + /**Constructor*/ + Dump(); + /**Destructor + * Closes the dumpfile*/ + ~Dump(); + /**Open dumpfile and prepare it for dumps + * \todo see if this fits better in the constructor*/ + void startnow(); + /**Tick the timestamp*/ + void inctick(); + /**Dump Note to dumpfile + * @param chan The channel of the note + * @param note The note + * @param vel The velocity of the note*/ + void dumpnote(char chan,char note, char vel); + /** Dump the Controller + * @param chan The channel of the Controller + * @param type The type + * @param par The value of the controller + * \todo figure out what type is exactly meaning*/ + void dumpcontroller(char chan,unsigned int type,int par); + +private: + FILE *file; + int tick; + int k;//This appears to be a constant used to flush the file + //periodically when JACK is used + int keyspressed; }; #endif diff --git a/src/Misc/LASHClient.C b/src/Misc/LASHClient.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + LASHClient.C - LASH support Copyright (C) 2006-2009 Lars Luthman Author: Lars Luthman 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 + 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, @@ -26,74 +26,79 @@ #include "LASHClient.h" -LASHClient::LASHClient(int* argc, char*** argv) { - client = lash_init(lash_extract_args(argc, argv), "ZynAddSubFX", - LASH_Config_File, LASH_PROTOCOL(2, 0)); +LASHClient::LASHClient(int* argc, char*** argv) +{ + client = lash_init(lash_extract_args(argc, argv), "ZynAddSubFX", + LASH_Config_File, LASH_PROTOCOL(2, 0)); } -void LASHClient::setalsaid(int id) { - if (lash_enabled(client)) { - if (id != -1) - lash_alsa_client_id(client, id); - } +void LASHClient::setalsaid(int id) +{ + if (lash_enabled(client)) { + if (id != -1) + lash_alsa_client_id(client, id); + } } -void LASHClient::setjackname(const char* name) { - if (lash_enabled(client)) { - if (name != NULL){ - lash_jack_client_name(client, name); +void LASHClient::setjackname(const char* name) +{ + if (lash_enabled(client)) { + if (name != NULL) { + lash_jack_client_name(client, name); - lash_event_t *event = lash_event_new_with_type(LASH_Client_Name); - lash_event_set_string(event, name); - lash_send_event(client, event); - } - } + lash_event_t *event = lash_event_new_with_type(LASH_Client_Name); + lash_event_set_string(event, name); + lash_send_event(client, event); + } + } } -LASHClient::Event LASHClient::checkevents(std::string& filename) { - - if (!lash_enabled(client)) - return NoEvent; - - Event received = NoEvent; - lash_event_t* event; - while (event = lash_get_event(client)) { - - // save - if (lash_event_get_type(event) == LASH_Save_File) { - std::cerr<<"LASH event: LASH_Save_File"<<std::endl; - filename = std::string(lash_event_get_string(event)) + "/master.xmz"; - received = Save; - break; - } - - // restore - else if (lash_event_get_type(event) == LASH_Restore_File) { - std::cerr<<"LASH event: LASH_Restore_File"<<std::endl; - filename = std::string(lash_event_get_string(event)) + "/master.xmz"; - received = Restore; - break; - } - - // quit - else if (lash_event_get_type(event) == LASH_Quit) { - std::cerr<<"LASH event: LASH_Quit"<<std::endl; - received = Quit; - break; +LASHClient::Event LASHClient::checkevents(std::string& filename) +{ + + if (!lash_enabled(client)) + return NoEvent; + + Event received = NoEvent; + lash_event_t* event; + while (event = lash_get_event(client)) { + + // save + if (lash_event_get_type(event) == LASH_Save_File) { + std::cerr<<"LASH event: LASH_Save_File"<<std::endl; + filename = std::string(lash_event_get_string(event)) + "/master.xmz"; + received = Save; + break; + } + + // restore + else if (lash_event_get_type(event) == LASH_Restore_File) { + std::cerr<<"LASH event: LASH_Restore_File"<<std::endl; + filename = std::string(lash_event_get_string(event)) + "/master.xmz"; + received = Restore; + break; + } + + // quit + else if (lash_event_get_type(event) == LASH_Quit) { + std::cerr<<"LASH event: LASH_Quit"<<std::endl; + received = Quit; + break; + } + + lash_event_destroy(event); } - - lash_event_destroy(event); - } - return received; + return received; } -void LASHClient::confirmevent(Event event) { - if (event == Save) - lash_send_event(client, lash_event_new_with_type(LASH_Save_File)); - else if (event == Restore) - lash_send_event(client, lash_event_new_with_type(LASH_Restore_File)); +void LASHClient::confirmevent(Event event) +{ + if (event == Save) + lash_send_event(client, lash_event_new_with_type(LASH_Save_File)); + else if (event == Restore) + lash_send_event(client, lash_event_new_with_type(LASH_Restore_File)); } diff --git a/src/Misc/LASHClient.h b/src/Misc/LASHClient.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + LASHClient.h - LASH support Copyright (C) 2006-2009 Lars Luthman Author: Lars Luthman 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 + 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, @@ -31,33 +31,34 @@ * the LASH daemon. * \todo fix indentation nonconformism * \todo see why there is no destructor*/ -class LASHClient { - public: - /**Enum to represent the LASH events that are currently handled*/ - enum Event { - Save, - Restore, - Quit, - NoEvent - }; +class LASHClient +{ +public: + /**Enum to represent the LASH events that are currently handled*/ + enum Event { + Save, + Restore, + Quit, + NoEvent + }; + + /** Constructor + * @param argc number of arguments + * @param argv the text arguments*/ + LASHClient(int* argc, char*** argv); + + /**set the ALSA id + * @param id new ALSA id*/ + void setalsaid(int id); + /**Set the JACK name + * @param name the new name*/ + void setjackname(const char* name); + Event checkevents(std::string& filename); + void confirmevent(Event event); + +private: - /** Constructor - * @param argc number of arguments - * @param argv the text arguments*/ - LASHClient(int* argc, char*** argv); - - /**set the ALSA id - * @param id new ALSA id*/ - void setalsaid(int id); - /**Set the JACK name - * @param name the new name*/ - void setjackname(const char* name); - Event checkevents(std::string& filename); - void confirmevent(Event event); - - private: - - lash_client_t* client; + lash_client_t* client; }; diff --git a/src/Misc/Master.C b/src/Misc/Master.C @@ -1,13 +1,13 @@ /* ZynAddSubFX - a software synthesizer - + Master.C - It sends Midi Messages to Parts, receives samples from parts, process them with system/insertion effects and mix them Copyright (C) 2002-2005 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 + 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, @@ -29,9 +29,10 @@ #include <unistd.h> -Master::Master(){ +Master::Master() +{ swaplr=0; - + pthread_mutex_init(&mutex,NULL); fft=new FFTwrapper(OSCIL_SIZE); @@ -39,77 +40,80 @@ Master::Master(){ tmpmixr=new REALTYPE[SOUND_BUFFER_SIZE]; audiooutl=new REALTYPE[SOUND_BUFFER_SIZE]; audiooutr=new REALTYPE[SOUND_BUFFER_SIZE]; - + ksoundbuffersample=-1;//this is only time when this is -1; this means that the GetAudioOutSamples was never called ksoundbuffersamplelow=0.0; - oldsamplel=0.0;oldsampler=0.0; + oldsamplel=0.0; + oldsampler=0.0; shutup=0; for (int npart=0;npart<NUM_MIDI_PARTS;npart++) { - vuoutpeakpart[npart]=1e-9; - fakepeakpart[npart]=0; + vuoutpeakpart[npart]=1e-9; + fakepeakpart[npart]=0; }; - + for (int i=0;i<SOUND_BUFFER_SIZE;i++) { - audiooutl[i]=0.0; - audiooutr[i]=0.0; + audiooutl[i]=0.0; + audiooutr[i]=0.0; }; for (int npart=0;npart<NUM_MIDI_PARTS;npart++) - part[npart]=new Part(&microtonal,fft,&mutex); - + part[npart]=new Part(&microtonal,fft,&mutex); - //Insertion Effects init + + //Insertion Effects init for (int nefx=0;nefx<NUM_INS_EFX;nefx++) - insefx[nefx]=new EffectMgr(1,&mutex); + insefx[nefx]=new EffectMgr(1,&mutex); - //System Effects init + //System Effects init for (int nefx=0;nefx<NUM_SYS_EFX;nefx++) { - sysefx[nefx]=new EffectMgr(0,&mutex); + sysefx[nefx]=new EffectMgr(0,&mutex); }; - + defaults(); }; -void Master::defaults(){ - volume=1.0; - setPvolume(80); - setPkeyshift(64); - - for (int npart=0;npart<NUM_MIDI_PARTS;npart++){ - part[npart]->defaults(); - part[npart]->Prcvchn=npart%NUM_MIDI_CHANNELS; - }; - - partonoff(0,1);//enable the first part - - for (int nefx=0;nefx<NUM_INS_EFX;nefx++) { - insefx[nefx]->defaults(); - Pinsparts[nefx]=-1; - }; - - //System Effects init - for (int nefx=0;nefx<NUM_SYS_EFX;nefx++) { - sysefx[nefx]->defaults(); - for (int npart=0;npart<NUM_MIDI_PARTS;npart++){ - //if (nefx==0) setPsysefxvol(npart,nefx,64); - //else - setPsysefxvol(npart,nefx,0); - }; - for (int nefxto=0;nefxto<NUM_SYS_EFX;nefxto++) - setPsysefxsend(nefx,nefxto,0); - }; +void Master::defaults() +{ + volume=1.0; + setPvolume(80); + setPkeyshift(64); + + for (int npart=0;npart<NUM_MIDI_PARTS;npart++) { + part[npart]->defaults(); + part[npart]->Prcvchn=npart%NUM_MIDI_CHANNELS; + }; + + partonoff(0,1);//enable the first part + + for (int nefx=0;nefx<NUM_INS_EFX;nefx++) { + insefx[nefx]->defaults(); + Pinsparts[nefx]=-1; + }; + + //System Effects init + for (int nefx=0;nefx<NUM_SYS_EFX;nefx++) { + sysefx[nefx]->defaults(); + for (int npart=0;npart<NUM_MIDI_PARTS;npart++) { + //if (nefx==0) setPsysefxvol(npart,nefx,64); + //else + setPsysefxvol(npart,nefx,0); + }; + for (int nefxto=0;nefxto<NUM_SYS_EFX;nefxto++) + setPsysefxsend(nefx,nefxto,0); + }; // sysefx[0]->changeeffect(1); - microtonal.defaults(); - ShutUp(); + microtonal.defaults(); + ShutUp(); }; /* * Note On Messages (velocity=0 for NoteOff) */ -void Master::NoteOn(unsigned char chan,unsigned char note,unsigned char velocity){ +void Master::NoteOn(unsigned char chan,unsigned char note,unsigned char velocity) +{ dump.dumpnote(chan,note,velocity); noteon(chan,note,velocity); @@ -118,82 +122,87 @@ void Master::NoteOn(unsigned char chan,unsigned char note,unsigned char velocity /* * Internal Note On (velocity=0 for NoteOff) */ -void Master::noteon(unsigned char chan,unsigned char note,unsigned char velocity){ +void Master::noteon(unsigned char chan,unsigned char note,unsigned char velocity) +{ int npart; - if (velocity!=0){ - for (npart=0;npart<NUM_MIDI_PARTS;npart++){ - if (chan==part[npart]->Prcvchn){ - fakepeakpart[npart]=velocity*2; - if (part[npart]->Penabled!=0) part[npart]->NoteOn(note,velocity,keyshift); - }; - }; - }else{ - this->NoteOff(chan,note); - }; - HDDRecorder.triggernow(); + if (velocity!=0) { + for (npart=0;npart<NUM_MIDI_PARTS;npart++) { + if (chan==part[npart]->Prcvchn) { + fakepeakpart[npart]=velocity*2; + if (part[npart]->Penabled!=0) part[npart]->NoteOn(note,velocity,keyshift); + }; + }; + } else { + this->NoteOff(chan,note); + }; + HDDRecorder.triggernow(); }; /* * Note Off Messages */ -void Master::NoteOff(unsigned char chan,unsigned char note){ +void Master::NoteOff(unsigned char chan,unsigned char note) +{ dump.dumpnote(chan,note,0); - + noteoff(chan,note); }; /* * Internal Note Off */ -void Master::noteoff(unsigned char chan,unsigned char note){ +void Master::noteoff(unsigned char chan,unsigned char note) +{ int npart; - for (npart=0;npart<NUM_MIDI_PARTS;npart++){ - if ((chan==part[npart]->Prcvchn) && (part[npart]->Penabled!=0)) - part[npart]->NoteOff(note); + for (npart=0;npart<NUM_MIDI_PARTS;npart++) { + if ((chan==part[npart]->Prcvchn) && (part[npart]->Penabled!=0)) + part[npart]->NoteOff(note); }; }; /* - * Controllers + * Controllers */ -void Master::SetController(unsigned char chan,unsigned int type,int par){ +void Master::SetController(unsigned char chan,unsigned int type,int par) +{ dump.dumpcontroller(chan,type,par); - + setcontroller(chan,type,par); }; /* - * Internal Controllers + * Internal Controllers */ -void Master::setcontroller(unsigned char chan,unsigned int type,int par){ +void Master::setcontroller(unsigned char chan,unsigned int type,int par) +{ if ((type==C_dataentryhi)||(type==C_dataentrylo)|| - (type==C_nrpnhi)||(type==C_nrpnlo)){//Process RPN and NRPN by the Master (ignore the chan) - ctl.setparameternumber(type,par); - - int parhi=-1,parlo=-1,valhi=-1,vallo=-1; - if (ctl.getnrpn(&parhi,&parlo,&valhi,&vallo)==0){//this is NRPN - //fprintf(stderr,"rcv. NRPN: %d %d %d %d\n",parhi,parlo,valhi,vallo); - switch (parhi){ - case 0x04://System Effects - if (parlo<NUM_SYS_EFX) { - sysefx[parlo]->seteffectpar_nolock(valhi,vallo); - }; - break; - case 0x08://Insertion Effects - if (parlo<NUM_INS_EFX) { - insefx[parlo]->seteffectpar_nolock(valhi,vallo); - }; - break; - - }; - }; + (type==C_nrpnhi)||(type==C_nrpnlo)) {//Process RPN and NRPN by the Master (ignore the chan) + ctl.setparameternumber(type,par); + + int parhi=-1,parlo=-1,valhi=-1,vallo=-1; + if (ctl.getnrpn(&parhi,&parlo,&valhi,&vallo)==0) {//this is NRPN + //fprintf(stderr,"rcv. NRPN: %d %d %d %d\n",parhi,parlo,valhi,vallo); + switch (parhi) { + case 0x04://System Effects + if (parlo<NUM_SYS_EFX) { + sysefx[parlo]->seteffectpar_nolock(valhi,vallo); + }; + break; + case 0x08://Insertion Effects + if (parlo<NUM_INS_EFX) { + insefx[parlo]->seteffectpar_nolock(valhi,vallo); + }; + break; + + }; + }; } else {//other controllers - for (int npart=0;npart<NUM_MIDI_PARTS;npart++){//Send the controller to all part assigned to the channel - if ((chan==part[npart]->Prcvchn) && (part[npart]->Penabled!=0)) - part[npart]->SetController(type,par); - }; - - if(type==C_allsoundsoff) { //cleanup insertion/system FX + for (int npart=0;npart<NUM_MIDI_PARTS;npart++) {//Send the controller to all part assigned to the channel + if ((chan==part[npart]->Prcvchn) && (part[npart]->Penabled!=0)) + part[npart]->SetController(type,par); + }; + + if (type==C_allsoundsoff) { //cleanup insertion/system FX for (int nefx=0;nefx<NUM_SYS_EFX;++nefx) { sysefx[nefx]->cleanup(); } @@ -208,171 +217,173 @@ void Master::setcontroller(unsigned char chan,unsigned int type,int par){ /* * Enable/Disable a part */ -void Master::partonoff(int npart,int what){ +void Master::partonoff(int npart,int what) +{ if (npart>=NUM_MIDI_PARTS) return; - if (what==0){//disable part - fakepeakpart[npart]=0; - part[npart]->Penabled=0; - part[npart]->cleanup(); - for (int nefx=0;nefx<NUM_INS_EFX;nefx++){ - if (Pinsparts[nefx]==npart) { - insefx[nefx]->cleanup(); - }; - }; + if (what==0) {//disable part + fakepeakpart[npart]=0; + part[npart]->Penabled=0; + part[npart]->cleanup(); + for (int nefx=0;nefx<NUM_INS_EFX;nefx++) { + if (Pinsparts[nefx]==npart) { + insefx[nefx]->cleanup(); + }; + }; } else {//enabled - part[npart]->Penabled=1; - fakepeakpart[npart]=0; + part[npart]->Penabled=1; + fakepeakpart[npart]=0; }; }; /* * Master audio out (the final sound) */ -void Master::AudioOut(REALTYPE *outl,REALTYPE *outr){ +void Master::AudioOut(REALTYPE *outl,REALTYPE *outr) +{ int i,npart,nefx; -/* //test!!!!!!!!!!!!! se poate bloca aici (mutex) - if (seq.play){ - int type,par1,par2,again,midichan; - int ntrack=1; -// do{ - again=seq.getevent(ntrack,&midichan,&type,&par1,&par2); - if (type>0) { -// printf("aaa\n"); - - if (type==1){//note_on or note_off - if (par2!=0) NoteOn(midichan,par1,par2); - else NoteOff(midichan,par1); - }; - }; -// } while (again); - }; -*/ + /* //test!!!!!!!!!!!!! se poate bloca aici (mutex) + if (seq.play){ + int type,par1,par2,again,midichan; + int ntrack=1; + // do{ + again=seq.getevent(ntrack,&midichan,&type,&par1,&par2); + if (type>0) { + // printf("aaa\n"); + + if (type==1){//note_on or note_off + if (par2!=0) NoteOn(midichan,par1,par2); + else NoteOff(midichan,par1); + }; + }; + // } while (again); + }; + */ // printf("zzzz\n"); //Swaps the Left channel with Right Channel (if it is asked for) - if (swaplr!=0){ + if (swaplr!=0) { REALTYPE *tmp=outl; - outl=outr; - outr=tmp; + outl=outr; + outr=tmp; }; - - //clean up the output samples + + //clean up the output samples for (i=0;i<SOUND_BUFFER_SIZE;i++) { - outl[i]=0.0; - outr[i]=0.0; + outl[i]=0.0; + outr[i]=0.0; }; //Compute part samples and store them part[npart]->partoutl,partoutr for (npart=0;npart<NUM_MIDI_PARTS;npart++) - if (part[npart]->Penabled!=0) part[npart]->ComputePartSmps(); - - //Insertion effects - for (nefx=0;nefx<NUM_INS_EFX;nefx++){ - if (Pinsparts[nefx]>=0) { - int efxpart=Pinsparts[nefx]; - if (part[efxpart]->Penabled!=0) - insefx[nefx]->out(part[efxpart]->partoutl,part[efxpart]->partoutr); - }; - }; - - + if (part[npart]->Penabled!=0) part[npart]->ComputePartSmps(); + + //Insertion effects + for (nefx=0;nefx<NUM_INS_EFX;nefx++) { + if (Pinsparts[nefx]>=0) { + int efxpart=Pinsparts[nefx]; + if (part[efxpart]->Penabled!=0) + insefx[nefx]->out(part[efxpart]->partoutl,part[efxpart]->partoutr); + }; + }; + + //Apply the part volumes and pannings (after insertion effects) - for (npart=0;npart<NUM_MIDI_PARTS;npart++){ - if (part[npart]->Penabled==0) continue; - - REALTYPE newvol_l=part[npart]->volume; - REALTYPE newvol_r=part[npart]->volume; - REALTYPE oldvol_l=part[npart]->oldvolumel; - REALTYPE oldvol_r=part[npart]->oldvolumer; - REALTYPE pan=part[npart]->panning; - if (pan<0.5) newvol_l*=pan*2.0; - else newvol_r*=(1.0-pan)*2.0; - - if (ABOVE_AMPLITUDE_THRESHOLD(oldvol_l,newvol_l)|| - ABOVE_AMPLITUDE_THRESHOLD(oldvol_r,newvol_r)){//the volume or the panning has changed and needs interpolation - - for (i=0;i<SOUND_BUFFER_SIZE;i++) { - REALTYPE vol_l=INTERPOLATE_AMPLITUDE(oldvol_l,newvol_l,i,SOUND_BUFFER_SIZE); - REALTYPE vol_r=INTERPOLATE_AMPLITUDE(oldvol_r,newvol_r,i,SOUND_BUFFER_SIZE); - part[npart]->partoutl[i]*=vol_l; - part[npart]->partoutr[i]*=vol_r; - }; - part[npart]->oldvolumel=newvol_l; - part[npart]->oldvolumer=newvol_r; - - } else { - for (i=0;i<SOUND_BUFFER_SIZE;i++) {//the volume did not changed - part[npart]->partoutl[i]*=newvol_l; - part[npart]->partoutr[i]*=newvol_r; - }; - }; + for (npart=0;npart<NUM_MIDI_PARTS;npart++) { + if (part[npart]->Penabled==0) continue; + + REALTYPE newvol_l=part[npart]->volume; + REALTYPE newvol_r=part[npart]->volume; + REALTYPE oldvol_l=part[npart]->oldvolumel; + REALTYPE oldvol_r=part[npart]->oldvolumer; + REALTYPE pan=part[npart]->panning; + if (pan<0.5) newvol_l*=pan*2.0; + else newvol_r*=(1.0-pan)*2.0; + + if (ABOVE_AMPLITUDE_THRESHOLD(oldvol_l,newvol_l)|| + ABOVE_AMPLITUDE_THRESHOLD(oldvol_r,newvol_r)) {//the volume or the panning has changed and needs interpolation + + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + REALTYPE vol_l=INTERPOLATE_AMPLITUDE(oldvol_l,newvol_l,i,SOUND_BUFFER_SIZE); + REALTYPE vol_r=INTERPOLATE_AMPLITUDE(oldvol_r,newvol_r,i,SOUND_BUFFER_SIZE); + part[npart]->partoutl[i]*=vol_l; + part[npart]->partoutr[i]*=vol_r; + }; + part[npart]->oldvolumel=newvol_l; + part[npart]->oldvolumer=newvol_r; + + } else { + for (i=0;i<SOUND_BUFFER_SIZE;i++) {//the volume did not changed + part[npart]->partoutl[i]*=newvol_l; + part[npart]->partoutr[i]*=newvol_r; + }; + }; }; //System effects - for (nefx=0;nefx<NUM_SYS_EFX;nefx++){ - if (sysefx[nefx]->geteffect()==0) continue;//the effect is disabled - - //Clean up the samples used by the system effects - for (i=0;i<SOUND_BUFFER_SIZE;i++) { - tmpmixl[i]=0.0; - tmpmixr[i]=0.0; - }; - - //Mix the channels according to the part settings about System Effect - for (npart=0;npart<NUM_MIDI_PARTS;npart++){ - //skip if the part has no output to effect - if (Psysefxvol[nefx][npart]==0) continue; - - //skip if the part is disabled - if (part[npart]->Penabled==0) continue; - - //the output volume of each part to system effect - REALTYPE vol=sysefxvol[nefx][npart]; - for (i=0;i<SOUND_BUFFER_SIZE;i++) { - tmpmixl[i]+=part[npart]->partoutl[i]*vol; - tmpmixr[i]+=part[npart]->partoutr[i]*vol; - }; - }; - - // system effect send to next ones - for (int nefxfrom=0;nefxfrom<nefx;nefxfrom++){ - if (Psysefxsend[nefxfrom][nefx]!=0){ - REALTYPE v=sysefxsend[nefxfrom][nefx]; - for (i=0;i<SOUND_BUFFER_SIZE;i++) { - tmpmixl[i]+=sysefx[nefxfrom]->efxoutl[i]*v; - tmpmixr[i]+=sysefx[nefxfrom]->efxoutr[i]*v; - }; - }; - }; - - sysefx[nefx]->out(tmpmixl,tmpmixr); - - //Add the System Effect to sound output - REALTYPE outvol=sysefx[nefx]->sysefxgetvolume(); - for (i=0;i<SOUND_BUFFER_SIZE;i++) { - outl[i]+=tmpmixl[i]*outvol; - outr[i]+=tmpmixr[i]*outvol; - }; + for (nefx=0;nefx<NUM_SYS_EFX;nefx++) { + if (sysefx[nefx]->geteffect()==0) continue;//the effect is disabled + + //Clean up the samples used by the system effects + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + tmpmixl[i]=0.0; + tmpmixr[i]=0.0; + }; + + //Mix the channels according to the part settings about System Effect + for (npart=0;npart<NUM_MIDI_PARTS;npart++) { + //skip if the part has no output to effect + if (Psysefxvol[nefx][npart]==0) continue; + + //skip if the part is disabled + if (part[npart]->Penabled==0) continue; + + //the output volume of each part to system effect + REALTYPE vol=sysefxvol[nefx][npart]; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + tmpmixl[i]+=part[npart]->partoutl[i]*vol; + tmpmixr[i]+=part[npart]->partoutr[i]*vol; + }; + }; + + // system effect send to next ones + for (int nefxfrom=0;nefxfrom<nefx;nefxfrom++) { + if (Psysefxsend[nefxfrom][nefx]!=0) { + REALTYPE v=sysefxsend[nefxfrom][nefx]; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + tmpmixl[i]+=sysefx[nefxfrom]->efxoutl[i]*v; + tmpmixr[i]+=sysefx[nefxfrom]->efxoutr[i]*v; + }; + }; + }; + + sysefx[nefx]->out(tmpmixl,tmpmixr); + + //Add the System Effect to sound output + REALTYPE outvol=sysefx[nefx]->sysefxgetvolume(); + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + outl[i]+=tmpmixl[i]*outvol; + outr[i]+=tmpmixr[i]*outvol; + }; }; //Mix all parts - for (npart=0;npart<NUM_MIDI_PARTS;npart++){ - for (i=0;i<SOUND_BUFFER_SIZE;i++) {//the volume did not changed - outl[i]+=part[npart]->partoutl[i]; - outr[i]+=part[npart]->partoutr[i]; - }; + for (npart=0;npart<NUM_MIDI_PARTS;npart++) { + for (i=0;i<SOUND_BUFFER_SIZE;i++) {//the volume did not changed + outl[i]+=part[npart]->partoutl[i]; + outr[i]+=part[npart]->partoutr[i]; + }; }; - + //Insertion effects for Master Out - for (nefx=0;nefx<NUM_INS_EFX;nefx++){ - if (Pinsparts[nefx] == -2) - insefx[nefx]->out(outl,outr); + for (nefx=0;nefx<NUM_INS_EFX;nefx++) { + if (Pinsparts[nefx] == -2) + insefx[nefx]->out(outl,outr); }; //Master Volume @@ -382,7 +393,8 @@ void Master::AudioOut(REALTYPE *outl,REALTYPE *outr){ }; //Peak computation (for vumeters) - vuoutpeakl=1e-12;vuoutpeakr=1e-12; + vuoutpeakl=1e-12; + vuoutpeakr=1e-12; for (i=0;i<SOUND_BUFFER_SIZE;i++) { if (fabs(outl[i])>vuoutpeakl) vuoutpeakl=fabs(outl[i]); if (fabs(outr[i])>vuoutpeakr) vuoutpeakr=fabs(outr[i]); @@ -392,39 +404,40 @@ void Master::AudioOut(REALTYPE *outl,REALTYPE *outr){ if (vumaxoutpeakr<vuoutpeakr) vumaxoutpeakr=vuoutpeakr; //RMS Peak computation (for vumeters) - vurmspeakl=1e-12;vurmspeakr=1e-12; + vurmspeakl=1e-12; + vurmspeakr=1e-12; for (i=0;i<SOUND_BUFFER_SIZE;i++) { vurmspeakl+=outl[i]*outl[i]; vurmspeakr+=outr[i]*outr[i]; }; vurmspeakl=sqrt(vurmspeakl/SOUND_BUFFER_SIZE); vurmspeakr=sqrt(vurmspeakr/SOUND_BUFFER_SIZE); - + //Part Peak computation (for Part vumeters or fake part vumeters) - for (npart=0;npart<NUM_MIDI_PARTS;npart++){ - vuoutpeakpart[npart]=1.0e-12; - if (part[npart]->Penabled!=0) { - REALTYPE *outl=part[npart]->partoutl, - *outr=part[npart]->partoutr; - for (i=0;i<SOUND_BUFFER_SIZE;i++) { - REALTYPE tmp=fabs(outl[i]+outr[i]); - if (tmp>vuoutpeakpart[npart]) vuoutpeakpart[npart]=tmp; - }; - vuoutpeakpart[npart]*=volume; - } else { - if (fakepeakpart[npart]>1) fakepeakpart[npart]--; - }; + for (npart=0;npart<NUM_MIDI_PARTS;npart++) { + vuoutpeakpart[npart]=1.0e-12; + if (part[npart]->Penabled!=0) { + REALTYPE *outl=part[npart]->partoutl, + *outr=part[npart]->partoutr; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + REALTYPE tmp=fabs(outl[i]+outr[i]); + if (tmp>vuoutpeakpart[npart]) vuoutpeakpart[npart]=tmp; + }; + vuoutpeakpart[npart]*=volume; + } else { + if (fakepeakpart[npart]>1) fakepeakpart[npart]--; + }; }; //Shutup if it is asked (with fade-out) - if (shutup!=0){ - for (i=0;i<SOUND_BUFFER_SIZE;i++) { - REALTYPE tmp=(SOUND_BUFFER_SIZE-i)/(REALTYPE) SOUND_BUFFER_SIZE; - outl[i]*=tmp; - outr[i]*=tmp; - }; - ShutUp(); + if (shutup!=0) { + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + REALTYPE tmp=(SOUND_BUFFER_SIZE-i)/(REALTYPE) SOUND_BUFFER_SIZE; + outl[i]*=tmp; + outr[i]*=tmp; + }; + ShutUp(); }; //update the LFO's time @@ -434,67 +447,69 @@ void Master::AudioOut(REALTYPE *outl,REALTYPE *outr){ dump.inctick(); }; -void Master::GetAudioOutSamples(int nsamples,int samplerate,REALTYPE *outl,REALTYPE *outr){ - if (ksoundbuffersample==-1){//first time - AudioOut(&audiooutl[0],&audiooutr[0]); - ksoundbuffersample=0; +void Master::GetAudioOutSamples(int nsamples,int samplerate,REALTYPE *outl,REALTYPE *outr) +{ + if (ksoundbuffersample==-1) {//first time + AudioOut(&audiooutl[0],&audiooutr[0]); + ksoundbuffersample=0; }; - if (samplerate==SAMPLE_RATE){//no resample - int ksample=0; - while (ksample<nsamples){ - outl[ksample]=audiooutl[ksoundbuffersample]; - outr[ksample]=audiooutr[ksoundbuffersample]; + if (samplerate==SAMPLE_RATE) {//no resample + int ksample=0; + while (ksample<nsamples) { + outl[ksample]=audiooutl[ksoundbuffersample]; + outr[ksample]=audiooutr[ksoundbuffersample]; - ksample++; - ksoundbuffersample++; - if (ksoundbuffersample>=SOUND_BUFFER_SIZE){ - AudioOut(&audiooutl[0],&audiooutr[0]); - ksoundbuffersample=0; - }; - }; + ksample++; + ksoundbuffersample++; + if (ksoundbuffersample>=SOUND_BUFFER_SIZE) { + AudioOut(&audiooutl[0],&audiooutr[0]); + ksoundbuffersample=0; + }; + }; } else {//Resample - int ksample=0; - REALTYPE srinc=SAMPLE_RATE/(REALTYPE)samplerate; - - while (ksample<nsamples){ - if (ksoundbuffersample!=0){ - outl[ksample]=audiooutl[ksoundbuffersample]*ksoundbuffersamplelow - +audiooutl[ksoundbuffersample-1]*(1.0-ksoundbuffersamplelow); - outr[ksample]=audiooutr[ksoundbuffersample]*ksoundbuffersamplelow - +audiooutr[ksoundbuffersample-1]*(1.0-ksoundbuffersamplelow); - } else { - outl[ksample]=audiooutl[ksoundbuffersample]*ksoundbuffersamplelow - +oldsamplel*(1.0-ksoundbuffersamplelow); - outr[ksample]=audiooutr[ksoundbuffersample]*ksoundbuffersamplelow - +oldsampler*(1.0-ksoundbuffersamplelow); - }; - - ksample++; - - ksoundbuffersamplelow+=srinc; - if (ksoundbuffersamplelow>=1.0){ - ksoundbuffersample+=(int) floor(ksoundbuffersamplelow); - ksoundbuffersamplelow=ksoundbuffersamplelow-floor(ksoundbuffersamplelow); - }; - - if (ksoundbuffersample>=SOUND_BUFFER_SIZE){ - oldsamplel=audiooutl[SOUND_BUFFER_SIZE-1]; - oldsampler=audiooutr[SOUND_BUFFER_SIZE-1]; - AudioOut(&audiooutl[0],&audiooutr[0]); - ksoundbuffersample=0; - }; - }; + int ksample=0; + REALTYPE srinc=SAMPLE_RATE/(REALTYPE)samplerate; + + while (ksample<nsamples) { + if (ksoundbuffersample!=0) { + outl[ksample]=audiooutl[ksoundbuffersample]*ksoundbuffersamplelow + +audiooutl[ksoundbuffersample-1]*(1.0-ksoundbuffersamplelow); + outr[ksample]=audiooutr[ksoundbuffersample]*ksoundbuffersamplelow + +audiooutr[ksoundbuffersample-1]*(1.0-ksoundbuffersamplelow); + } else { + outl[ksample]=audiooutl[ksoundbuffersample]*ksoundbuffersamplelow + +oldsamplel*(1.0-ksoundbuffersamplelow); + outr[ksample]=audiooutr[ksoundbuffersample]*ksoundbuffersamplelow + +oldsampler*(1.0-ksoundbuffersamplelow); + }; + + ksample++; + + ksoundbuffersamplelow+=srinc; + if (ksoundbuffersamplelow>=1.0) { + ksoundbuffersample+=(int) floor(ksoundbuffersamplelow); + ksoundbuffersamplelow=ksoundbuffersamplelow-floor(ksoundbuffersamplelow); + }; + + if (ksoundbuffersample>=SOUND_BUFFER_SIZE) { + oldsamplel=audiooutl[SOUND_BUFFER_SIZE-1]; + oldsampler=audiooutr[SOUND_BUFFER_SIZE-1]; + AudioOut(&audiooutl[0],&audiooutr[0]); + ksoundbuffersample=0; + }; + }; }; }; -Master::~Master(){ +Master::~Master() +{ for (int npart=0;npart<NUM_MIDI_PARTS;npart++) delete part[npart]; for (int nefx=0;nefx<NUM_INS_EFX;nefx++) delete insefx[nefx]; for (int nefx=0;nefx<NUM_SYS_EFX;nefx++) delete sysefx[nefx]; - + delete [] audiooutl; delete [] audiooutr; delete [] tmpmixl; @@ -508,23 +523,27 @@ Master::~Master(){ /* * Parameter control */ -void Master::setPvolume(char Pvolume_){ +void Master::setPvolume(char Pvolume_) +{ Pvolume=Pvolume_; volume=dB2rap((Pvolume-96.0)/96.0*40.0); }; -void Master::setPkeyshift(char Pkeyshift_){ +void Master::setPkeyshift(char Pkeyshift_) +{ Pkeyshift=Pkeyshift_; keyshift=(int)Pkeyshift-64; }; -void Master::setPsysefxvol(int Ppart,int Pefx,char Pvol){ +void Master::setPsysefxvol(int Ppart,int Pefx,char Pvol) +{ Psysefxvol[Pefx][Ppart]=Pvol; sysefxvol[Pefx][Ppart]=pow(0.1,(1.0-Pvol/96.0)*2.0); }; -void Master::setPsysefxsend(int Pefxfrom,int Pefxto,char Pvol){ +void Master::setPsysefxsend(int Pefxfrom,int Pefxto,char Pvol) +{ Psysefxsend[Pefxfrom][Pefxto]=Pvol; sysefxsend[Pefxfrom][Pefxto]=pow(0.1,(1.0-Pvol/96.0)*2.0); }; @@ -533,10 +552,11 @@ void Master::setPsysefxsend(int Pefxfrom,int Pefxto,char Pvol){ /* * Panic! (Clean up all parts and effects) */ -void Master::ShutUp(){ +void Master::ShutUp() +{ for (int npart=0;npart<NUM_MIDI_PARTS;npart++) { - part[npart]->cleanup(); - fakepeakpart[npart]=0; + part[npart]->cleanup(); + fakepeakpart[npart]=0; }; for (int nefx=0;nefx<NUM_INS_EFX;nefx++) insefx[nefx]->cleanup(); for (int nefx=0;nefx<NUM_SYS_EFX;nefx++) sysefx[nefx]->cleanup(); @@ -548,75 +568,82 @@ void Master::ShutUp(){ /* * Reset peaks and clear the "cliped" flag (for VU-meter) */ -void Master::vuresetpeaks(){ - vuoutpeakl=1e-9;vuoutpeakr=1e-9;vumaxoutpeakl=1e-9;vumaxoutpeakr=1e-9; +void Master::vuresetpeaks() +{ + vuoutpeakl=1e-9; + vuoutpeakr=1e-9; + vumaxoutpeakl=1e-9; + vumaxoutpeakr=1e-9; vuclipped=0; }; -void Master::applyparameters(){ - for (int npart=0;npart<NUM_MIDI_PARTS;npart++){ - part[npart]->applyparameters(); +void Master::applyparameters() +{ + for (int npart=0;npart<NUM_MIDI_PARTS;npart++) { + part[npart]->applyparameters(); }; }; -void Master::add2XML(XMLwrapper *xml){ +void Master::add2XML(XMLwrapper *xml) +{ xml->addpar("volume",Pvolume); xml->addpar("key_shift",Pkeyshift); xml->addparbool("nrpn_receive",ctl.NRPN.receive); xml->beginbranch("MICROTONAL"); - microtonal.add2XML(xml); + microtonal.add2XML(xml); xml->endbranch(); - for (int npart=0;npart<NUM_MIDI_PARTS;npart++){ - xml->beginbranch("PART",npart); - part[npart]->add2XML(xml); - xml->endbranch(); + for (int npart=0;npart<NUM_MIDI_PARTS;npart++) { + xml->beginbranch("PART",npart); + part[npart]->add2XML(xml); + xml->endbranch(); }; - + xml->beginbranch("SYSTEM_EFFECTS"); - for (int nefx=0;nefx<NUM_SYS_EFX;nefx++){ - xml->beginbranch("SYSTEM_EFFECT",nefx); - xml->beginbranch("EFFECT"); - sysefx[nefx]->add2XML(xml); - xml->endbranch(); - - for (int pefx=0;pefx<NUM_MIDI_PARTS;pefx++){ - xml->beginbranch("VOLUME",pefx); - xml->addpar("vol",Psysefxvol[nefx][pefx]); - xml->endbranch(); - }; - - for (int tonefx=nefx+1;tonefx<NUM_SYS_EFX;tonefx++){ - xml->beginbranch("SENDTO",tonefx); - xml->addpar("send_vol",Psysefxsend[nefx][tonefx]); - xml->endbranch(); - }; - - - xml->endbranch(); - }; + for (int nefx=0;nefx<NUM_SYS_EFX;nefx++) { + xml->beginbranch("SYSTEM_EFFECT",nefx); + xml->beginbranch("EFFECT"); + sysefx[nefx]->add2XML(xml); + xml->endbranch(); + + for (int pefx=0;pefx<NUM_MIDI_PARTS;pefx++) { + xml->beginbranch("VOLUME",pefx); + xml->addpar("vol",Psysefxvol[nefx][pefx]); + xml->endbranch(); + }; + + for (int tonefx=nefx+1;tonefx<NUM_SYS_EFX;tonefx++) { + xml->beginbranch("SENDTO",tonefx); + xml->addpar("send_vol",Psysefxsend[nefx][tonefx]); + xml->endbranch(); + }; + + + xml->endbranch(); + }; xml->endbranch(); xml->beginbranch("INSERTION_EFFECTS"); - for (int nefx=0;nefx<NUM_INS_EFX;nefx++){ - xml->beginbranch("INSERTION_EFFECT",nefx); - xml->addpar("part",Pinsparts[nefx]); - - xml->beginbranch("EFFECT"); - insefx[nefx]->add2XML(xml); - xml->endbranch(); - xml->endbranch(); - }; - + for (int nefx=0;nefx<NUM_INS_EFX;nefx++) { + xml->beginbranch("INSERTION_EFFECT",nefx); + xml->addpar("part",Pinsparts[nefx]); + + xml->beginbranch("EFFECT"); + insefx[nefx]->add2XML(xml); + xml->endbranch(); + xml->endbranch(); + }; + xml->endbranch(); - + }; -int Master::getalldata(char **data){ +int Master::getalldata(char **data) +{ XMLwrapper *xml=new XMLwrapper(); xml->beginbranch("MASTER"); @@ -632,25 +659,27 @@ int Master::getalldata(char **data){ return(strlen(*data)+1); }; -void Master::putalldata(char *data,int size){ +void Master::putalldata(char *data,int size) +{ XMLwrapper *xml=new XMLwrapper(); if (!xml->putXMLdata(data)) { - delete(xml); - return; + delete(xml); + return; }; - + if (xml->enterbranch("MASTER")==0) return; pthread_mutex_lock(&mutex); - getfromXML(xml); + getfromXML(xml); pthread_mutex_unlock(&mutex); xml->exitbranch(); - + delete(xml); }; -int Master::saveXML(const char *filename){ +int Master::saveXML(const char *filename) +{ XMLwrapper *xml=new XMLwrapper(); xml->beginbranch("MASTER"); @@ -664,82 +693,84 @@ int Master::saveXML(const char *filename){ -int Master::loadXML(const char *filename){ +int Master::loadXML(const char *filename) +{ XMLwrapper *xml=new XMLwrapper(); if (xml->loadXMLfile(filename)<0) { - delete(xml); - return(-1); + delete(xml); + return(-1); }; - + if (xml->enterbranch("MASTER")==0) return(-10); - getfromXML(xml); + getfromXML(xml); xml->exitbranch(); - + delete(xml); return(0); }; -void Master::getfromXML(XMLwrapper *xml){ +void Master::getfromXML(XMLwrapper *xml) +{ setPvolume(xml->getpar127("volume",Pvolume)); setPkeyshift(xml->getpar127("key_shift",Pkeyshift)); ctl.NRPN.receive=xml->getparbool("nrpn_receive",ctl.NRPN.receive); - - + + part[0]->Penabled=0; - for (int npart=0;npart<NUM_MIDI_PARTS;npart++){ - if (xml->enterbranch("PART",npart)==0) continue; - part[npart]->getfromXML(xml); - xml->exitbranch(); + for (int npart=0;npart<NUM_MIDI_PARTS;npart++) { + if (xml->enterbranch("PART",npart)==0) continue; + part[npart]->getfromXML(xml); + xml->exitbranch(); }; - if (xml->enterbranch("MICROTONAL")){ + if (xml->enterbranch("MICROTONAL")) { microtonal.getfromXML(xml); xml->exitbranch(); }; - + sysefx[0]->changeeffect(0); - if (xml->enterbranch("SYSTEM_EFFECTS")){ - for (int nefx=0;nefx<NUM_SYS_EFX;nefx++){ - if (xml->enterbranch("SYSTEM_EFFECT",nefx)==0) continue; - if (xml->enterbranch("EFFECT")){ - sysefx[nefx]->getfromXML(xml); - xml->exitbranch(); - }; - - for (int partefx=0;partefx<NUM_MIDI_PARTS;partefx++){ - if (xml->enterbranch("VOLUME",partefx)==0) continue; - setPsysefxvol(partefx,nefx,xml->getpar127("vol",Psysefxvol[partefx][nefx])); - xml->exitbranch(); - }; - - for (int tonefx=nefx+1;tonefx<NUM_SYS_EFX;tonefx++){ - if (xml->enterbranch("SENDTO",tonefx)==0) continue; - setPsysefxsend(nefx,tonefx,xml->getpar127("send_vol",Psysefxsend[nefx][tonefx])); - xml->exitbranch(); - }; - xml->exitbranch(); - }; - xml->exitbranch(); - }; - - - if (xml->enterbranch("INSERTION_EFFECTS")){ - for (int nefx=0;nefx<NUM_INS_EFX;nefx++){ - - if (xml->enterbranch("INSERTION_EFFECT",nefx)==0) continue; - Pinsparts[nefx]=xml->getpar("part",Pinsparts[nefx],-2,NUM_MIDI_PARTS); - if (xml->enterbranch("EFFECT")){ - insefx[nefx]->getfromXML(xml); - xml->exitbranch(); - }; - xml->exitbranch(); - - }; - - xml->exitbranch(); - }; - - + if (xml->enterbranch("SYSTEM_EFFECTS")) { + for (int nefx=0;nefx<NUM_SYS_EFX;nefx++) { + if (xml->enterbranch("SYSTEM_EFFECT",nefx)==0) continue; + if (xml->enterbranch("EFFECT")) { + sysefx[nefx]->getfromXML(xml); + xml->exitbranch(); + }; + + for (int partefx=0;partefx<NUM_MIDI_PARTS;partefx++) { + if (xml->enterbranch("VOLUME",partefx)==0) continue; + setPsysefxvol(partefx,nefx,xml->getpar127("vol",Psysefxvol[partefx][nefx])); + xml->exitbranch(); + }; + + for (int tonefx=nefx+1;tonefx<NUM_SYS_EFX;tonefx++) { + if (xml->enterbranch("SENDTO",tonefx)==0) continue; + setPsysefxsend(nefx,tonefx,xml->getpar127("send_vol",Psysefxsend[nefx][tonefx])); + xml->exitbranch(); + }; + xml->exitbranch(); + }; + xml->exitbranch(); + }; + + + if (xml->enterbranch("INSERTION_EFFECTS")) { + for (int nefx=0;nefx<NUM_INS_EFX;nefx++) { + + if (xml->enterbranch("INSERTION_EFFECT",nefx)==0) continue; + Pinsparts[nefx]=xml->getpar("part",Pinsparts[nefx],-2,NUM_MIDI_PARTS); + if (xml->enterbranch("EFFECT")) { + insefx[nefx]->getfromXML(xml); + xml->exitbranch(); + }; + xml->exitbranch(); + + }; + + xml->exitbranch(); + }; + + }; diff --git a/src/Misc/Master.h b/src/Misc/Master.h @@ -1,13 +1,13 @@ /* ZynAddSubFX - a software synthesizer - + Master.h - It sends Midi Messages to Parts, receives samples from parts, process them with system/insertion effects and mix them Copyright (C) 2002-2005 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 + 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, @@ -38,129 +38,130 @@ extern Dump dump; /** It sends Midi Messages to Parts, receives samples from parts, * process them with system/insertion effects and mix them */ -class Master{ - public: - /** Constructor*/ - Master(); - /** Destructor*/ - ~Master(); - - /**Saves all settings to a XML file - * @return 0 for ok or <0 if there is an error*/ - int saveXML(const char *filename); - - /**This adds the parameters to the XML data*/ - void add2XML(XMLwrapper *xml); - - void defaults(); - - - /**loads all settings from a XML file - * @return 0 for ok or -1 if there is an error*/ - int loadXML(const char *filename); - void applyparameters(); - - void getfromXML(XMLwrapper *xml); - - /**get all data to a newly allocated array (used for VST) - * @return the datasize*/ - int getalldata(char **data); - /**put all data from the *data array to zynaddsubfx parameters (used for VST)*/ - void putalldata(char *data,int size); - - - - //Midi IN - void NoteOn(unsigned char chan,unsigned char note,unsigned char velocity); - void NoteOff(unsigned char chan,unsigned char note); - void SetController(unsigned char chan,unsigned int type,int par); - //void NRPN... - - - void ShutUp(); - int shutup; - - /**Audio Output*/ - void AudioOut(REALTYPE *outl,REALTYPE *outr); - /**Audio Output (for callback mode). This allows the program to be controled by an external program*/ - void GetAudioOutSamples(int nsamples,int samplerate,REALTYPE *outl,REALTYPE *outr); - - - void partonoff(int npart,int what); - - /**parts \todo see if this can be made to be dynamic*/ - Part *part[NUM_MIDI_PARTS]; - - //parameters - unsigned char Pvolume; - unsigned char Pkeyshift; - unsigned char Psysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS]; - unsigned char Psysefxsend[NUM_SYS_EFX][NUM_SYS_EFX]; - - //parameters control - void setPvolume(char Pvolume_); - void setPkeyshift(char Pkeyshift_); - void setPsysefxvol(int Ppart,int Pefx,char Pvol); - void setPsysefxsend(int Pefxfrom,int Pefxto,char Pvol); - - //effects - EffectMgr *sysefx[NUM_SYS_EFX];//system - EffectMgr *insefx[NUM_INS_EFX];//insertion +class Master +{ +public: + /** Constructor*/ + Master(); + /** Destructor*/ + ~Master(); + + /**Saves all settings to a XML file + * @return 0 for ok or <0 if there is an error*/ + int saveXML(const char *filename); + + /**This adds the parameters to the XML data*/ + void add2XML(XMLwrapper *xml); + + void defaults(); + + + /**loads all settings from a XML file + * @return 0 for ok or -1 if there is an error*/ + int loadXML(const char *filename); + void applyparameters(); + + void getfromXML(XMLwrapper *xml); + + /**get all data to a newly allocated array (used for VST) + * @return the datasize*/ + int getalldata(char **data); + /**put all data from the *data array to zynaddsubfx parameters (used for VST)*/ + void putalldata(char *data,int size); + + + + //Midi IN + void NoteOn(unsigned char chan,unsigned char note,unsigned char velocity); + void NoteOff(unsigned char chan,unsigned char note); + void SetController(unsigned char chan,unsigned int type,int par); + //void NRPN... + + + void ShutUp(); + int shutup; + + /**Audio Output*/ + void AudioOut(REALTYPE *outl,REALTYPE *outr); + /**Audio Output (for callback mode). This allows the program to be controled by an external program*/ + void GetAudioOutSamples(int nsamples,int samplerate,REALTYPE *outl,REALTYPE *outr); + + + void partonoff(int npart,int what); + + /**parts \todo see if this can be made to be dynamic*/ + Part *part[NUM_MIDI_PARTS]; + + //parameters + unsigned char Pvolume; + unsigned char Pkeyshift; + unsigned char Psysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS]; + unsigned char Psysefxsend[NUM_SYS_EFX][NUM_SYS_EFX]; + + //parameters control + void setPvolume(char Pvolume_); + void setPkeyshift(char Pkeyshift_); + void setPsysefxvol(int Ppart,int Pefx,char Pvol); + void setPsysefxsend(int Pefxfrom,int Pefxto,char Pvol); + + //effects + EffectMgr *sysefx[NUM_SYS_EFX];//system + EffectMgr *insefx[NUM_INS_EFX];//insertion // void swapcopyeffects(int what,int type,int neff1,int neff2); - //HDD recorder - Recorder HDDRecorder; - - //part that's apply the insertion effect; -1 to disable - short int Pinsparts[NUM_INS_EFX]; - - //peaks for VU-meter - void vuresetpeaks(); - REALTYPE vuoutpeakl,vuoutpeakr,vumaxoutpeakl,vumaxoutpeakr,vurmspeakl,vurmspeakr; - int vuclipped; - - //peaks for part VU-meters - REALTYPE vuoutpeakpart[NUM_MIDI_PARTS]; - unsigned char fakepeakpart[NUM_MIDI_PARTS];//this is used to compute the "peak" when the part is disabled - - Controller ctl; - int swaplr;//1 if L and R are swapped - - //Sequencer - Sequencer seq; - - //other objects - Microtonal microtonal; - Bank bank; - - FFTwrapper *fft; - pthread_mutex_t mutex; - - private: - REALTYPE volume; - REALTYPE sysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS]; - REALTYPE sysefxsend[NUM_SYS_EFX][NUM_SYS_EFX]; - - //Temporary mixing samples for part samples which is sent to system effect - REALTYPE *tmpmixl; - REALTYPE *tmpmixr; - - - int keyshift; - - //Audio Output samples (if it used GetAudioOutSamples - eg. for Jack output; elsewhere is unused) - REALTYPE *audiooutl; - REALTYPE *audiooutr; - - int ksoundbuffersample;//this is used to know if there is need to call AudioOut by GetAudioOutSamples method - REALTYPE ksoundbuffersamplelow;//this is used for resampling (eg. if Jack samplerate!= SAMPLE_RATE) - REALTYPE oldsamplel,oldsampler;//this is used for resampling - - //These are called by the NoteOn, NoteOff,SetController (which are from external sources like MIDI, Virtual Keyboard) - //and are called by internal parts of the program (like sequencer) - void noteon(unsigned char chan,unsigned char note,unsigned char velocity); - void noteoff(unsigned char chan,unsigned char note); - void setcontroller(unsigned char chan,unsigned int type,int par); + //HDD recorder + Recorder HDDRecorder; + + //part that's apply the insertion effect; -1 to disable + short int Pinsparts[NUM_INS_EFX]; + + //peaks for VU-meter + void vuresetpeaks(); + REALTYPE vuoutpeakl,vuoutpeakr,vumaxoutpeakl,vumaxoutpeakr,vurmspeakl,vurmspeakr; + int vuclipped; + + //peaks for part VU-meters + REALTYPE vuoutpeakpart[NUM_MIDI_PARTS]; + unsigned char fakepeakpart[NUM_MIDI_PARTS];//this is used to compute the "peak" when the part is disabled + + Controller ctl; + int swaplr;//1 if L and R are swapped + + //Sequencer + Sequencer seq; + + //other objects + Microtonal microtonal; + Bank bank; + + FFTwrapper *fft; + pthread_mutex_t mutex; + +private: + REALTYPE volume; + REALTYPE sysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS]; + REALTYPE sysefxsend[NUM_SYS_EFX][NUM_SYS_EFX]; + + //Temporary mixing samples for part samples which is sent to system effect + REALTYPE *tmpmixl; + REALTYPE *tmpmixr; + + + int keyshift; + + //Audio Output samples (if it used GetAudioOutSamples - eg. for Jack output; elsewhere is unused) + REALTYPE *audiooutl; + REALTYPE *audiooutr; + + int ksoundbuffersample;//this is used to know if there is need to call AudioOut by GetAudioOutSamples method + REALTYPE ksoundbuffersamplelow;//this is used for resampling (eg. if Jack samplerate!= SAMPLE_RATE) + REALTYPE oldsamplel,oldsampler;//this is used for resampling + + //These are called by the NoteOn, NoteOff,SetController (which are from external sources like MIDI, Virtual Keyboard) + //and are called by internal parts of the program (like sequencer) + void noteon(unsigned char chan,unsigned char note,unsigned char velocity); + void noteoff(unsigned char chan,unsigned char note); + void setcontroller(unsigned char chan,unsigned int type,int par); }; diff --git a/src/Misc/Microtonal.C b/src/Misc/Microtonal.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Microtonal.C - Tuning settings and microtonal capabilities Copyright (C) 2002-2005 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 + 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, @@ -26,13 +26,15 @@ #define MAX_LINE_SIZE 80 -Microtonal::Microtonal(){ +Microtonal::Microtonal() +{ Pname=new unsigned char[MICROTONAL_MAX_NAME_LEN]; Pcomment=new unsigned char[MICROTONAL_MAX_NAME_LEN]; defaults(); }; -void Microtonal::defaults(){ +void Microtonal::defaults() +{ Pinvertupdown=0; Pinvertupdowncenter=60; octavesize=12; @@ -40,30 +42,35 @@ void Microtonal::defaults(){ PAnote=69; PAfreq=440.0; Pscaleshift=64; - - Pfirstkey=0;Plastkey=127; - Pmiddlenote=60;Pmapsize=12; + + Pfirstkey=0; + Plastkey=127; + Pmiddlenote=60; + Pmapsize=12; Pmappingenabled=0; - + for (int i=0;i<128;i++) Pmapping[i]=i; - - for (int i=0;i<MAX_OCTAVE_SIZE;i++){ - octave[i].tuning=tmpoctave[i].tuning=pow(2,(i%octavesize+1)/12.0); - octave[i].type=tmpoctave[i].type=1; - octave[i].x1=tmpoctave[i].x1=(i%octavesize+1)*100; - octave[i].x2=tmpoctave[i].x2=0; + + for (int i=0;i<MAX_OCTAVE_SIZE;i++) { + octave[i].tuning=tmpoctave[i].tuning=pow(2,(i%octavesize+1)/12.0); + octave[i].type=tmpoctave[i].type=1; + octave[i].x1=tmpoctave[i].x1=(i%octavesize+1)*100; + octave[i].x2=tmpoctave[i].x2=0; }; - octave[11].type=2;octave[11].x1=2;octave[11].x2=1; - for (int i=0;i<MICROTONAL_MAX_NAME_LEN;i++){ - Pname[i]='\0'; - Pcomment[i]='\0'; + octave[11].type=2; + octave[11].x1=2; + octave[11].x2=1; + for (int i=0;i<MICROTONAL_MAX_NAME_LEN;i++) { + Pname[i]='\0'; + Pcomment[i]='\0'; }; snprintf((char *) Pname,MICROTONAL_MAX_NAME_LEN,"12tET"); - snprintf((char *) Pcomment,MICROTONAL_MAX_NAME_LEN,"Equal Temperament 12 notes per octave"); + snprintf((char *) Pcomment,MICROTONAL_MAX_NAME_LEN,"Equal Temperament 12 notes per octave"); Pglobalfinedetune=64; }; -Microtonal::~Microtonal(){ +Microtonal::~Microtonal() +{ delete [] Pname; delete [] Pcomment; }; @@ -71,86 +78,91 @@ Microtonal::~Microtonal(){ /* * Get the size of the octave */ -unsigned char Microtonal::getoctavesize(){ +unsigned char Microtonal::getoctavesize() +{ if (Penabled!=0) return(octavesize); - else return(12); + else return(12); }; /* * Get the frequency according the note number */ -REALTYPE Microtonal::getnotefreq(int note,int keyshift){ +REALTYPE Microtonal::getnotefreq(int note,int keyshift) +{ // in this function will appears many times things like this: - // var=(a+b*100)%b + // var=(a+b*100)%b // I had written this way because if I use var=a%b gives unwanted results when a<0 // This is the same with divisions. - + if ((Pinvertupdown!=0)&&((Pmappingenabled==0)||(Penabled==0))) note=(int) Pinvertupdowncenter*2-note; //compute global fine detune REALTYPE globalfinedetunerap=pow(2.0,(Pglobalfinedetune-64.0)/1200.0);//-64.0 .. 63.0 cents - + if (Penabled==0) return(pow(2.0,(note-PAnote+keyshift)/12.0)*PAfreq*globalfinedetunerap);//12tET - + int scaleshift=((int)Pscaleshift-64+(int) octavesize*100)%octavesize; //compute the keyshift REALTYPE rap_keyshift=1.0; - if (keyshift!=0){ - int kskey=(keyshift+(int)octavesize*100)%octavesize; - int ksoct=(keyshift+(int)octavesize*100)/octavesize-100; - rap_keyshift=(kskey==0) ? (1.0):(octave[kskey-1].tuning); - rap_keyshift*=pow(octave[octavesize-1].tuning,ksoct); + if (keyshift!=0) { + int kskey=(keyshift+(int)octavesize*100)%octavesize; + int ksoct=(keyshift+(int)octavesize*100)/octavesize-100; + rap_keyshift=(kskey==0) ? (1.0):(octave[kskey-1].tuning); + rap_keyshift*=pow(octave[octavesize-1].tuning,ksoct); }; //if the mapping is enabled - if (Pmappingenabled!=0){ - if ((note<Pfirstkey)||(note>Plastkey)) return (-1.0); - //Compute how many mapped keys are from middle note to reference note - //and find out the proportion between the freq. of middle note and "A" note - int tmp=PAnote-Pmiddlenote,minus=0; - if (tmp<0) { tmp=-tmp; minus=1; }; - int deltanote=0; - for (int i=0;i<tmp;i++) if (Pmapping[i%Pmapsize]>=0) deltanote++; - REALTYPE rap_anote_middlenote=(deltanote==0) ? (1.0) : (octave[(deltanote-1)%octavesize].tuning); - if (deltanote!=0) rap_anote_middlenote*=pow(octave[octavesize-1].tuning,(deltanote-1)/octavesize); - if (minus!=0) rap_anote_middlenote=1.0/rap_anote_middlenote; - - //Convert from note (midi) to degree (note from the tunning) - int degoct=(note-(int)Pmiddlenote+(int) Pmapsize*200)/(int)Pmapsize-200; - int degkey=(note-Pmiddlenote+(int)Pmapsize*100)%Pmapsize; - degkey=Pmapping[degkey]; - if (degkey<0) return(-1.0);//this key is not mapped - - //invert the keyboard upside-down if it is asked for - //TODO: do the right way by using Pinvertupdowncenter - if (Pinvertupdown!=0){ - degkey=octavesize-degkey-1; - degoct=-degoct; - }; - //compute the frequency of the note - degkey=degkey+scaleshift; - degoct+=degkey/octavesize; - degkey%=octavesize; - - REALTYPE freq=(degkey==0) ? (1.0):octave[degkey-1].tuning; - freq*=pow(octave[octavesize-1].tuning,degoct); - freq*=PAfreq/rap_anote_middlenote; - freq*=globalfinedetunerap; - if (scaleshift!=0) freq/=octave[scaleshift-1].tuning; - return(freq*rap_keyshift); + if (Pmappingenabled!=0) { + if ((note<Pfirstkey)||(note>Plastkey)) return (-1.0); + //Compute how many mapped keys are from middle note to reference note + //and find out the proportion between the freq. of middle note and "A" note + int tmp=PAnote-Pmiddlenote,minus=0; + if (tmp<0) { + tmp=-tmp; + minus=1; + }; + int deltanote=0; + for (int i=0;i<tmp;i++) if (Pmapping[i%Pmapsize]>=0) deltanote++; + REALTYPE rap_anote_middlenote=(deltanote==0) ? (1.0) : (octave[(deltanote-1)%octavesize].tuning); + if (deltanote!=0) rap_anote_middlenote*=pow(octave[octavesize-1].tuning,(deltanote-1)/octavesize); + if (minus!=0) rap_anote_middlenote=1.0/rap_anote_middlenote; + + //Convert from note (midi) to degree (note from the tunning) + int degoct=(note-(int)Pmiddlenote+(int) Pmapsize*200)/(int)Pmapsize-200; + int degkey=(note-Pmiddlenote+(int)Pmapsize*100)%Pmapsize; + degkey=Pmapping[degkey]; + if (degkey<0) return(-1.0);//this key is not mapped + + //invert the keyboard upside-down if it is asked for + //TODO: do the right way by using Pinvertupdowncenter + if (Pinvertupdown!=0) { + degkey=octavesize-degkey-1; + degoct=-degoct; + }; + //compute the frequency of the note + degkey=degkey+scaleshift; + degoct+=degkey/octavesize; + degkey%=octavesize; + + REALTYPE freq=(degkey==0) ? (1.0):octave[degkey-1].tuning; + freq*=pow(octave[octavesize-1].tuning,degoct); + freq*=PAfreq/rap_anote_middlenote; + freq*=globalfinedetunerap; + if (scaleshift!=0) freq/=octave[scaleshift-1].tuning; + return(freq*rap_keyshift); } else {//if the mapping is disabled - int nt=note-PAnote+scaleshift; - int ntkey=(nt+(int)octavesize*100)%octavesize; - int ntoct=(nt-ntkey)/octavesize; - - REALTYPE oct=octave[octavesize-1].tuning; - REALTYPE freq=octave[(ntkey+octavesize-1)%octavesize].tuning*pow(oct,ntoct)*PAfreq; - if (ntkey==0) freq/=oct; + int nt=note-PAnote+scaleshift; + int ntkey=(nt+(int)octavesize*100)%octavesize; + int ntoct=(nt-ntkey)/octavesize; + + REALTYPE oct=octave[octavesize-1].tuning; + REALTYPE freq=octave[(ntkey+octavesize-1)%octavesize].tuning*pow(oct,ntoct)*PAfreq; + if (ntkey==0) freq/=oct; if (scaleshift!=0) freq/=octave[scaleshift-1].tuning; // fprintf(stderr,"note=%d freq=%.3f cents=%d\n",note,freq,(int)floor(log(freq/PAfreq)/log(2.0)*1200.0+0.5)); - freq*=globalfinedetunerap; - return(freq*rap_keyshift); + freq*=globalfinedetunerap; + return(freq*rap_keyshift); }; }; @@ -158,82 +170,86 @@ REALTYPE Microtonal::getnotefreq(int note,int keyshift){ /* * Convert a line to tunings; returns -1 if it ok */ -int Microtonal::linetotunings(unsigned int nline,const char *line){ +int Microtonal::linetotunings(unsigned int nline,const char *line) +{ int x1=-1,x2=-1,type=-1; REALTYPE x=-1.0,tmp,tuning=1.0; - if (strstr(line,"/")==NULL){ - if (strstr(line,".")==NULL){// M case (M=M/1) - sscanf(line,"%d",&x1); - x2=1; - type=2;//division - } else {// float number case - sscanf(line,"%f",&x); - if (x<0.000001) return(1); - type=1;//float type(cents) - }; + if (strstr(line,"/")==NULL) { + if (strstr(line,".")==NULL) {// M case (M=M/1) + sscanf(line,"%d",&x1); + x2=1; + type=2;//division + } else {// float number case + sscanf(line,"%f",&x); + if (x<0.000001) return(1); + type=1;//float type(cents) + }; } else {// M/N case - sscanf(line,"%d/%d",&x1,&x2); - if ((x1<0)||(x2<0)) return(1); - if (x2==0) x2=1; - type=2;//division + sscanf(line,"%d/%d",&x1,&x2); + if ((x1<0)||(x2<0)) return(1); + if (x2==0) x2=1; + type=2;//division }; - + if (x1<=0) x1=1;//not allow zero frequency sounds (consider 0 as 1) - + //convert to float if the number are too big - if ((type==2)&&((x1>(128*128*128-1))||(x2>(128*128*128-1)))){ - type=1; - x=((REALTYPE) x1)/x2; + if ((type==2)&&((x1>(128*128*128-1))||(x2>(128*128*128-1)))) { + type=1; + x=((REALTYPE) x1)/x2; }; - switch (type){ - case 1: x1=(int) floor(x); - tmp=fmod(x,1.0); - x2=(int) (floor (tmp*1e6)); - tuning=pow(2.0,x/1200.0); - break; - case 2: x=((REALTYPE)x1)/x2; - tuning=x; - break; + switch (type) { + case 1: + x1=(int) floor(x); + tmp=fmod(x,1.0); + x2=(int) (floor (tmp*1e6)); + tuning=pow(2.0,x/1200.0); + break; + case 2: + x=((REALTYPE)x1)/x2; + tuning=x; + break; }; - + tmpoctave[nline].tuning=tuning; tmpoctave[nline].type=type; tmpoctave[nline].x1=x1; tmpoctave[nline].x2=x2; - + return(-1);//ok }; /* * Convert the text to tunnings */ -int Microtonal::texttotunings(const char *text){ +int Microtonal::texttotunings(const char *text) +{ unsigned int i,k=0,nl=0; char *lin; lin=new char[MAX_LINE_SIZE+1]; - while (k<strlen(text)){ - for (i=0;i<MAX_LINE_SIZE;i++){ - lin[i]=text[k++]; - if (lin[i]<0x20) break; - }; - lin[i]='\0'; - if (strlen(lin)==0) continue; - int err=linetotunings(nl,lin); - if (err!=-1) { - delete [] lin; - return(nl);//Parse error - }; - nl++; + while (k<strlen(text)) { + for (i=0;i<MAX_LINE_SIZE;i++) { + lin[i]=text[k++]; + if (lin[i]<0x20) break; + }; + lin[i]='\0'; + if (strlen(lin)==0) continue; + int err=linetotunings(nl,lin); + if (err!=-1) { + delete [] lin; + return(nl);//Parse error + }; + nl++; }; delete [] lin; if (nl>MAX_OCTAVE_SIZE) nl=MAX_OCTAVE_SIZE; if (nl==0) return(-2);//the input is empty octavesize=nl; - for (i=0;i<octavesize;i++){ - octave[i].tuning=tmpoctave[i].tuning; - octave[i].type=tmpoctave[i].type; - octave[i].x1=tmpoctave[i].x1; - octave[i].x2=tmpoctave[i].x2; + for (i=0;i<octavesize;i++) { + octave[i].tuning=tmpoctave[i].tuning; + octave[i].type=tmpoctave[i].type; + octave[i].x1=tmpoctave[i].x1; + octave[i].x2=tmpoctave[i].x2; }; return(-1);//ok }; @@ -241,29 +257,30 @@ int Microtonal::texttotunings(const char *text){ /* * Convert the text to mapping */ -void Microtonal::texttomapping(const char *text){ +void Microtonal::texttomapping(const char *text) +{ unsigned int i,k=0; char *lin; lin=new char[MAX_LINE_SIZE+1]; for (i=0;i<128;i++) Pmapping[i]=-1; int tx=0; - while (k<strlen(text)){ - for (i=0;i<MAX_LINE_SIZE;i++){ - lin[i]=text[k++]; - if (lin[i]<0x20) break; - }; - lin[i]='\0'; - if (strlen(lin)==0) continue; - - int tmp=0; - if (sscanf(lin,"%d",&tmp)==0) tmp=-1; - if (tmp<-1) tmp=-1; - Pmapping[tx]=tmp; - - if ((tx++)>127) break; + while (k<strlen(text)) { + for (i=0;i<MAX_LINE_SIZE;i++) { + lin[i]=text[k++]; + if (lin[i]<0x20) break; + }; + lin[i]='\0'; + if (strlen(lin)==0) continue; + + int tmp=0; + if (sscanf(lin,"%d",&tmp)==0) tmp=-1; + if (tmp<-1) tmp=-1; + Pmapping[tx]=tmp; + + if ((tx++)>127) break; }; delete [] lin; - + if (tx==0) tx=1; Pmapsize=tx; }; @@ -271,26 +288,29 @@ void Microtonal::texttomapping(const char *text){ /* * Convert tunning to text line */ -void Microtonal::tuningtoline(int n,char *line,int maxn){ +void Microtonal::tuningtoline(int n,char *line,int maxn) +{ if ((n>octavesize) || (n>MAX_OCTAVE_SIZE)) { - line[0]='\0'; - return; + line[0]='\0'; + return; }; if (octave[n].type==1) snprintf(line,maxn,"%d.%d",octave[n].x1,octave[n].x2); if (octave[n].type==2) snprintf(line,maxn,"%d/%d",octave[n].x1,octave[n].x2); }; - -int Microtonal::loadline(FILE *file,char *line){ + +int Microtonal::loadline(FILE *file,char *line) +{ do { - if (fgets(line,500,file)==0) return(1); + if (fgets(line,500,file)==0) return(1); } while (line[0]=='!'); return(0); }; /* * Loads the tunnings from a scl file */ -int Microtonal::loadscl(const char *filename){ +int Microtonal::loadscl(const char *filename) +{ FILE *file=fopen(filename, "r"); char tmp[500]; fseek(file,0,SEEK_SET); @@ -305,18 +325,18 @@ int Microtonal::loadscl(const char *filename){ sscanf(&tmp[0],"%d",&nnotes); if (nnotes>MAX_OCTAVE_SIZE) return (2); //load the tunnings - for (int nline=0;nline<nnotes;nline++){ - if (loadline(file,&tmp[0])!=0) return(2); - linetotunings(nline,&tmp[0]); + for (int nline=0;nline<nnotes;nline++) { + if (loadline(file,&tmp[0])!=0) return(2); + linetotunings(nline,&tmp[0]); }; fclose(file); octavesize=nnotes; - for (int i=0;i<octavesize;i++){ - octave[i].tuning=tmpoctave[i].tuning; - octave[i].type=tmpoctave[i].type; - octave[i].x1=tmpoctave[i].x1; - octave[i].x2=tmpoctave[i].x2; + for (int i=0;i<octavesize;i++) { + octave[i].tuning=tmpoctave[i].tuning; + octave[i].type=tmpoctave[i].type; + octave[i].x1=tmpoctave[i].x1; + octave[i].x2=tmpoctave[i].x2; }; return(0); @@ -325,7 +345,8 @@ int Microtonal::loadscl(const char *filename){ /* * Loads the mapping from a kbm file */ -int Microtonal::loadkbm(const char *filename){ +int Microtonal::loadkbm(const char *filename) +{ FILE *file=fopen(filename, "r"); int x; char tmp[500]; @@ -334,27 +355,32 @@ int Microtonal::loadkbm(const char *filename){ //loads the mapsize if (loadline(file,&tmp[0])!=0) return(2); if (sscanf(&tmp[0],"%d",&x)==0) return(2); - if (x<1) x=0;if (x>127) x=127;//just in case... + if (x<1) x=0; + if (x>127) x=127;//just in case... Pmapsize=x; //loads first MIDI note to retune if (loadline(file,&tmp[0])!=0) return(2); if (sscanf(&tmp[0],"%d",&x)==0) return(2); - if (x<1) x=0;if (x>127) x=127;//just in case... + if (x<1) x=0; + if (x>127) x=127;//just in case... Pfirstkey=x; //loads last MIDI note to retune if (loadline(file,&tmp[0])!=0) return(2); if (sscanf(&tmp[0],"%d",&x)==0) return(2); - if (x<1) x=0;if (x>127) x=127;//just in case... + if (x<1) x=0; + if (x>127) x=127;//just in case... Plastkey=x; //loads last the middle note where scale fro scale degree=0 if (loadline(file,&tmp[0])!=0) return(2); if (sscanf(&tmp[0],"%d",&x)==0) return(2); - if (x<1) x=0;if (x>127) x=127;//just in case... + if (x<1) x=0; + if (x>127) x=127;//just in case... Pmiddlenote=x; //loads the reference note if (loadline(file,&tmp[0])!=0) return(2); if (sscanf(&tmp[0],"%d",&x)==0) return(2); - if (x<1) x=0;if (x>127) x=127;//just in case... + if (x<1) x=0; + if (x>127) x=127;//just in case... PAnote=x; //loads the reference freq. if (loadline(file,&tmp[0])!=0) return(2); @@ -366,17 +392,17 @@ int Microtonal::loadkbm(const char *filename){ if (loadline(file,&tmp[0])!=0) return(2); //load the mappings - if (Pmapsize!=0){ - for (int nline=0;nline<Pmapsize;nline++){ - if (loadline(file,&tmp[0])!=0) return(2); - if (sscanf(&tmp[0],"%d",&x)==0) x=-1; - Pmapping[nline]=x; - }; - Pmappingenabled=1; + if (Pmapsize!=0) { + for (int nline=0;nline<Pmapsize;nline++) { + if (loadline(file,&tmp[0])!=0) return(2); + if (sscanf(&tmp[0],"%d",&x)==0) x=-1; + Pmapping[nline]=x; + }; + Pmappingenabled=1; } else { - Pmappingenabled=0; - Pmapping[0]=0; - Pmapsize=1; + Pmappingenabled=0; + Pmapping[0]=0; + Pmapsize=1; }; fclose(file); @@ -385,7 +411,8 @@ int Microtonal::loadkbm(const char *filename){ -void Microtonal::add2XML(XMLwrapper *xml){ +void Microtonal::add2XML(XMLwrapper *xml) +{ xml->addparstr("name",(char *) Pname); xml->addparstr("comment",(char *) Pcomment); @@ -401,39 +428,40 @@ void Microtonal::add2XML(XMLwrapper *xml){ if ((Penabled==0)&&(xml->minimal)) return; xml->beginbranch("SCALE"); - xml->addpar("scale_shift",Pscaleshift); - xml->addpar("first_key",Pfirstkey); - xml->addpar("last_key",Plastkey); - xml->addpar("middle_note",Pmiddlenote); - - xml->beginbranch("OCTAVE"); - xml->addpar("octave_size",octavesize); - for (int i=0;i<octavesize;i++){ - xml->beginbranch("DEGREE",i); - if (octave[i].type==1){ - xml->addparreal("cents",octave[i].tuning); - }; - if (octave[i].type==2){ - xml->addpar("numerator",octave[i].x1); - xml->addpar("denominator",octave[i].x2); - }; - xml->endbranch(); - }; - xml->endbranch(); - - xml->beginbranch("KEYBOARD_MAPPING"); - xml->addpar("map_size",Pmapsize); - xml->addpar("mapping_enabled",Pmappingenabled); - for (int i=0;i<Pmapsize;i++){ - xml->beginbranch("KEYMAP",i); - xml->addpar("degree",Pmapping[i]); - xml->endbranch(); - }; - xml->endbranch(); + xml->addpar("scale_shift",Pscaleshift); + xml->addpar("first_key",Pfirstkey); + xml->addpar("last_key",Plastkey); + xml->addpar("middle_note",Pmiddlenote); + + xml->beginbranch("OCTAVE"); + xml->addpar("octave_size",octavesize); + for (int i=0;i<octavesize;i++) { + xml->beginbranch("DEGREE",i); + if (octave[i].type==1) { + xml->addparreal("cents",octave[i].tuning); + }; + if (octave[i].type==2) { + xml->addpar("numerator",octave[i].x1); + xml->addpar("denominator",octave[i].x2); + }; + xml->endbranch(); + }; + xml->endbranch(); + + xml->beginbranch("KEYBOARD_MAPPING"); + xml->addpar("map_size",Pmapsize); + xml->addpar("mapping_enabled",Pmappingenabled); + for (int i=0;i<Pmapsize;i++) { + xml->beginbranch("KEYMAP",i); + xml->addpar("degree",Pmapping[i]); + xml->endbranch(); + }; + xml->endbranch(); xml->endbranch(); }; -void Microtonal::getfromXML(XMLwrapper *xml){ +void Microtonal::getfromXML(XMLwrapper *xml) +{ xml->getparstr("name",(char *) Pname,MICROTONAL_MAX_NAME_LEN); xml->getparstr("comment",(char *) Pcomment,MICROTONAL_MAX_NAME_LEN); @@ -446,45 +474,46 @@ void Microtonal::getfromXML(XMLwrapper *xml){ PAnote=xml->getpar127("a_note",PAnote); PAfreq=xml->getparreal("a_freq",PAfreq,1.0,10000.0); - if (xml->enterbranch("SCALE")){ - Pscaleshift=xml->getpar127("scale_shift",Pscaleshift); - Pfirstkey=xml->getpar127("first_key",Pfirstkey); - Plastkey=xml->getpar127("last_key",Plastkey); - Pmiddlenote=xml->getpar127("middle_note",Pmiddlenote); - - if (xml->enterbranch("OCTAVE")){ - octavesize=xml->getpar127("octave_size",octavesize); - for (int i=0;i<octavesize;i++){ - if (xml->enterbranch("DEGREE",i)==0) continue; - octave[i].x2=0; - octave[i].tuning=xml->getparreal("cents",octave[i].tuning); - octave[i].x1=xml->getpar127("numerator",octave[i].x1); - octave[i].x2=xml->getpar127("denominator",octave[i].x2); - - if (octave[i].x2!=0) octave[i].type=2; - else octave[i].type=1; - - xml->exitbranch(); - }; - xml->exitbranch(); - }; - - if (xml->enterbranch("KEYBOARD_MAPPING")){ - Pmapsize=xml->getpar127("map_size",Pmapsize); - Pmappingenabled=xml->getpar127("mapping_enabled",Pmappingenabled); - for (int i=0;i<Pmapsize;i++){ - if (xml->enterbranch("KEYMAP",i)==0) continue; - Pmapping[i]=xml->getpar127("degree",Pmapping[i]); - xml->exitbranch(); - }; - xml->exitbranch(); - }; - xml->exitbranch(); + if (xml->enterbranch("SCALE")) { + Pscaleshift=xml->getpar127("scale_shift",Pscaleshift); + Pfirstkey=xml->getpar127("first_key",Pfirstkey); + Plastkey=xml->getpar127("last_key",Plastkey); + Pmiddlenote=xml->getpar127("middle_note",Pmiddlenote); + + if (xml->enterbranch("OCTAVE")) { + octavesize=xml->getpar127("octave_size",octavesize); + for (int i=0;i<octavesize;i++) { + if (xml->enterbranch("DEGREE",i)==0) continue; + octave[i].x2=0; + octave[i].tuning=xml->getparreal("cents",octave[i].tuning); + octave[i].x1=xml->getpar127("numerator",octave[i].x1); + octave[i].x2=xml->getpar127("denominator",octave[i].x2); + + if (octave[i].x2!=0) octave[i].type=2; + else octave[i].type=1; + + xml->exitbranch(); + }; + xml->exitbranch(); + }; + + if (xml->enterbranch("KEYBOARD_MAPPING")) { + Pmapsize=xml->getpar127("map_size",Pmapsize); + Pmappingenabled=xml->getpar127("mapping_enabled",Pmappingenabled); + for (int i=0;i<Pmapsize;i++) { + if (xml->enterbranch("KEYMAP",i)==0) continue; + Pmapping[i]=xml->getpar127("degree",Pmapping[i]); + xml->exitbranch(); + }; + xml->exitbranch(); + }; + xml->exitbranch(); }; }; -int Microtonal::saveXML(char *filename){ +int Microtonal::saveXML(char *filename) +{ XMLwrapper *xml=new XMLwrapper(); xml->beginbranch("MICROTONAL"); @@ -496,17 +525,18 @@ int Microtonal::saveXML(char *filename){ return(result); }; -int Microtonal::loadXML(char *filename){ +int Microtonal::loadXML(char *filename) +{ XMLwrapper *xml=new XMLwrapper(); if (xml->loadXMLfile(filename)<0) { - delete(xml); - return(-1); + delete(xml); + return(-1); }; - + if (xml->enterbranch("MICROTONAL")==0) return(-10); - getfromXML(xml); + getfromXML(xml); xml->exitbranch(); - + delete(xml); return(0); }; diff --git a/src/Misc/Microtonal.h b/src/Misc/Microtonal.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Microtonal.h - Tuning settings and microtonal capabilities Copyright (C) 2002-2005 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 + 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, @@ -33,89 +33,90 @@ /**Tuning settings and microtonal capabilities*/ -class Microtonal{ - public: - /**Constructor*/ - Microtonal(); - /**Destructor*/ - ~Microtonal(); - void defaults(); - /**Calculates the frequency for a given note - */ - REALTYPE getnotefreq(int note,int keyshift); - - - //Parameters - /**if the keys are inversed (the pitch is lower to keys from the right direction) \todo figure out why this is not a bool*/ - unsigned char Pinvertupdown; - - /**the central key of the inversion*/ - unsigned char Pinvertupdowncenter; - - /**0 for 12 key temperate scale, 1 for microtonal - * \todo find one good reason why this is not a bool*/ - unsigned char Penabled; - - /**the note of "A" key*/ - unsigned char PAnote; - - /**the frequency of the "A" note*/ - REALTYPE PAfreq; - - /**if the scale is "tuned" to a note, you can tune to other note*/ - unsigned char Pscaleshift; - - //first and last key (to retune) - unsigned char Pfirstkey; - unsigned char Plastkey; - - //The middle note where scale degree 0 is mapped to - unsigned char Pmiddlenote; - - //Map size - unsigned char Pmapsize; - - //Mapping ON/OFF - unsigned char Pmappingenabled; - //Mapping (keys) - short int Pmapping[128]; - - unsigned char Pglobalfinedetune; - - // Functions - /** Return the current octave size - * \todo why is this not an int?*/ - unsigned char getoctavesize(); - void tuningtoline(int n,char *line,int maxn); - int loadscl(const char *filename);//load the tunnings from a .scl file - int loadkbm(const char *filename);//load the mapping from .kbm file - int texttotunings(const char *text); - void texttomapping(const char *text); - unsigned char *Pname; - unsigned char *Pcomment; - - void add2XML(XMLwrapper *xml); - void getfromXML(XMLwrapper *xml); - int saveXML(char *filename); - int loadXML(char *filename); - - private: - int linetotunings(unsigned int nline,const char *line); - int loadline(FILE *file,char *line);//loads a line from the text file, while ignoring the lines beggining with "!" - unsigned char octavesize; - struct { - unsigned char type;//1 for cents or 2 for division - - // the real tuning (eg. +1.05946 for one halftone) - // or 2.0 for one octave - REALTYPE tuning; - - //the real tunning is x1/x2 - unsigned int x1,x2; - - } octave[MAX_OCTAVE_SIZE],tmpoctave[MAX_OCTAVE_SIZE]; - -}; - +class Microtonal +{ +public: + /**Constructor*/ + Microtonal(); + /**Destructor*/ + ~Microtonal(); + void defaults(); + /**Calculates the frequency for a given note + */ + REALTYPE getnotefreq(int note,int keyshift); + + + //Parameters + /**if the keys are inversed (the pitch is lower to keys from the right direction) \todo figure out why this is not a bool*/ + unsigned char Pinvertupdown; + + /**the central key of the inversion*/ + unsigned char Pinvertupdowncenter; + + /**0 for 12 key temperate scale, 1 for microtonal + * \todo find one good reason why this is not a bool*/ + unsigned char Penabled; + + /**the note of "A" key*/ + unsigned char PAnote; + + /**the frequency of the "A" note*/ + REALTYPE PAfreq; + + /**if the scale is "tuned" to a note, you can tune to other note*/ + unsigned char Pscaleshift; + + //first and last key (to retune) + unsigned char Pfirstkey; + unsigned char Plastkey; + + //The middle note where scale degree 0 is mapped to + unsigned char Pmiddlenote; + + //Map size + unsigned char Pmapsize; + + //Mapping ON/OFF + unsigned char Pmappingenabled; + //Mapping (keys) + short int Pmapping[128]; + + unsigned char Pglobalfinedetune; + + // Functions + /** Return the current octave size + * \todo why is this not an int?*/ + unsigned char getoctavesize(); + void tuningtoline(int n,char *line,int maxn); + int loadscl(const char *filename);//load the tunnings from a .scl file + int loadkbm(const char *filename);//load the mapping from .kbm file + int texttotunings(const char *text); + void texttomapping(const char *text); + unsigned char *Pname; + unsigned char *Pcomment; + + void add2XML(XMLwrapper *xml); + void getfromXML(XMLwrapper *xml); + int saveXML(char *filename); + int loadXML(char *filename); + +private: + int linetotunings(unsigned int nline,const char *line); + int loadline(FILE *file,char *line);//loads a line from the text file, while ignoring the lines beggining with "!" + unsigned char octavesize; + struct { + unsigned char type;//1 for cents or 2 for division + + // the real tuning (eg. +1.05946 for one halftone) + // or 2.0 for one octave + REALTYPE tuning; + + //the real tunning is x1/x2 + unsigned int x1,x2; + + } octave[MAX_OCTAVE_SIZE],tmpoctave[MAX_OCTAVE_SIZE]; + +}; + #endif diff --git a/src/Misc/Part.C b/src/Misc/Part.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Part.C - Part implementation Copyright (C) 2002-2005 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 + 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, @@ -26,18 +26,21 @@ #include <stdio.h> #include <string.h> -Part::Part(Microtonal *microtonal_,FFTwrapper *fft_, pthread_mutex_t *mutex_){ - microtonal=microtonal_; +Part::Part(Microtonal *microtonal_,FFTwrapper *fft_, pthread_mutex_t *mutex_) +{ + microtonal=microtonal_; fft=fft_; mutex=mutex_; partoutl=new REALTYPE [SOUND_BUFFER_SIZE]; partoutr=new REALTYPE [SOUND_BUFFER_SIZE]; tmpoutl=new REALTYPE [SOUND_BUFFER_SIZE]; tmpoutr=new REALTYPE [SOUND_BUFFER_SIZE]; - - for (int n=0;n<NUM_KIT_ITEMS;n++){ - kit[n].Pname=new unsigned char [PART_MAX_NAME_LEN]; - kit[n].adpars=NULL;kit[n].subpars=NULL;kit[n].padpars=NULL; + + for (int n=0;n<NUM_KIT_ITEMS;n++) { + kit[n].Pname=new unsigned char [PART_MAX_NAME_LEN]; + kit[n].adpars=NULL; + kit[n].subpars=NULL; + kit[n].padpars=NULL; }; kit[0].adpars=new ADnoteParameters(fft); @@ -47,44 +50,45 @@ Part::Part(Microtonal *microtonal_,FFTwrapper *fft_, pthread_mutex_t *mutex_){ // SUBPartParameters=kit[0].subpars; //Part's Insertion Effects init - for (int nefx=0;nefx<NUM_PART_EFX;nefx++) - partefx[nefx]=new EffectMgr(1,mutex); + for (int nefx=0;nefx<NUM_PART_EFX;nefx++) + partefx[nefx]=new EffectMgr(1,mutex); for (int n=0;n<NUM_PART_EFX+1;n++) { - partfxinputl[n]=new REALTYPE [SOUND_BUFFER_SIZE]; - partfxinputr[n]=new REALTYPE [SOUND_BUFFER_SIZE]; - Pefxbypass[n]=false; + partfxinputl[n]=new REALTYPE [SOUND_BUFFER_SIZE]; + partfxinputr[n]=new REALTYPE [SOUND_BUFFER_SIZE]; + Pefxbypass[n]=false; }; killallnotes=0; oldfreq=-1.0; int i,j; - for (i=0;i<POLIPHONY;i++){ - partnote[i].status=KEY_OFF; - partnote[i].note=-1; - partnote[i].itemsplaying=0; - for (j=0;j<NUM_KIT_ITEMS;j++){ - partnote[i].kititem[j].adnote=NULL; - partnote[i].kititem[j].subnote=NULL; - partnote[i].kititem[j].padnote=NULL; - }; - partnote[i].time=0; + for (i=0;i<POLIPHONY;i++) { + partnote[i].status=KEY_OFF; + partnote[i].note=-1; + partnote[i].itemsplaying=0; + for (j=0;j<NUM_KIT_ITEMS;j++) { + partnote[i].kititem[j].adnote=NULL; + partnote[i].kititem[j].subnote=NULL; + partnote[i].kititem[j].padnote=NULL; + }; + partnote[i].time=0; }; - cleanup(); + cleanup(); Pname=new unsigned char [PART_MAX_NAME_LEN]; - + oldvolumel=oldvolumer=0.5; lastnote=-1; lastpos=0; // lastpos will store previously used NoteOn(...)'s pos. lastlegatomodevalid=false; // To store previous legatomodevalid value. - - + + defaults(); }; -void Part::defaults(){ +void Part::defaults() +{ Penabled=0; Pminkey=0; Pmaxkey=127; @@ -102,7 +106,8 @@ void Part::defaults(){ ctl.defaults(); }; -void Part::defaultsinstrument(){ +void Part::defaultsinstrument() +{ ZERO(Pname,PART_MAX_NAME_LEN); info.Ptype=0; @@ -112,23 +117,27 @@ void Part::defaultsinstrument(){ Pkitmode=0; Pdrummode=0; - for (int n=0;n<NUM_KIT_ITEMS;n++){ - kit[n].Penabled=0;kit[n].Pmuted=0; - kit[n].Pminkey=0;kit[n].Pmaxkey=127; - kit[n].Padenabled=0;kit[n].Psubenabled=0;kit[n].Ppadenabled=0; - ZERO(kit[n].Pname,PART_MAX_NAME_LEN); - kit[n].Psendtoparteffect=0; - if (n!=0) setkititemstatus(n,0); + for (int n=0;n<NUM_KIT_ITEMS;n++) { + kit[n].Penabled=0; + kit[n].Pmuted=0; + kit[n].Pminkey=0; + kit[n].Pmaxkey=127; + kit[n].Padenabled=0; + kit[n].Psubenabled=0; + kit[n].Ppadenabled=0; + ZERO(kit[n].Pname,PART_MAX_NAME_LEN); + kit[n].Psendtoparteffect=0; + if (n!=0) setkititemstatus(n,0); }; kit[0].Penabled=1; kit[0].Padenabled=1; kit[0].adpars->defaults(); kit[0].subpars->defaults(); kit[0].padpars->defaults(); - + for (int nefx=0;nefx<NUM_PART_EFX;nefx++) { - partefx[nefx]->defaults(); - Pefxroute[nefx]=0;//route to next effect + partefx[nefx]->defaults(); + Pefxroute[nefx]=0;//route to next effect }; }; @@ -138,32 +147,36 @@ void Part::defaultsinstrument(){ /* * Cleanup the part */ -void Part::cleanup(){ +void Part::cleanup() +{ for (int k=0;k<POLIPHONY;k++) KillNotePos(k); - for (int i=0;i<SOUND_BUFFER_SIZE;i++){ - partoutl[i]=denormalkillbuf[i]; - partoutr[i]=denormalkillbuf[i]; - tmpoutl[i]=0.0; - tmpoutr[i]=0.0; + for (int i=0;i<SOUND_BUFFER_SIZE;i++) { + partoutl[i]=denormalkillbuf[i]; + partoutr[i]=denormalkillbuf[i]; + tmpoutl[i]=0.0; + tmpoutr[i]=0.0; }; ctl.resetall(); for (int nefx=0;nefx<NUM_PART_EFX;nefx++) partefx[nefx]->cleanup(); for (int n=0;n<NUM_PART_EFX+1;n++) { - for (int i=0;i<SOUND_BUFFER_SIZE;i++){ - partfxinputl[n][i]=denormalkillbuf[i]; - partfxinputr[n][i]=denormalkillbuf[i]; - }; + for (int i=0;i<SOUND_BUFFER_SIZE;i++) { + partfxinputl[n][i]=denormalkillbuf[i]; + partfxinputr[n][i]=denormalkillbuf[i]; + }; }; }; -Part::~Part(){ +Part::~Part() +{ cleanup(); - for (int n=0;n<NUM_KIT_ITEMS;n++){ - if (kit[n].adpars!=NULL) delete (kit[n].adpars); - if (kit[n].subpars!=NULL) delete (kit[n].subpars); - if (kit[n].padpars!=NULL) delete (kit[n].padpars); - kit[n].adpars=NULL;kit[n].subpars=NULL;kit[n].padpars=NULL; - delete [] kit[n].Pname; + for (int n=0;n<NUM_KIT_ITEMS;n++) { + if (kit[n].adpars!=NULL) delete (kit[n].adpars); + if (kit[n].subpars!=NULL) delete (kit[n].subpars); + if (kit[n].padpars!=NULL) delete (kit[n].padpars); + kit[n].adpars=NULL; + kit[n].subpars=NULL; + kit[n].padpars=NULL; + delete [] kit[n].Pname; }; delete [] Pname; @@ -171,18 +184,19 @@ Part::~Part(){ delete [] partoutr; delete [] tmpoutl; delete [] tmpoutr; - for (int nefx=0;nefx<NUM_PART_EFX;nefx++) - delete (partefx[nefx]); + for (int nefx=0;nefx<NUM_PART_EFX;nefx++) + delete (partefx[nefx]); for (int n=0;n<NUM_PART_EFX+1;n++) { - delete [] partfxinputl[n]; - delete [] partfxinputr[n]; + delete [] partfxinputl[n]; + delete [] partfxinputr[n]; } }; /* * Note On Messages */ -void Part::NoteOn(unsigned char note,unsigned char velocity,int masterkeyshift){ +void Part::NoteOn(unsigned char note,unsigned char velocity,int masterkeyshift) +{ int i,pos; // Legato and MonoMem used vars: @@ -197,255 +211,256 @@ void Part::NoteOn(unsigned char note,unsigned char velocity,int masterkeyshift){ if ((note<Pminkey)||(note>Pmaxkey)) return; // MonoMem stuff: - if (Ppolymode==0){ // If Poly is off - monomemnotes.push_back(note); // Add note to the list. - monomem[note].velocity=velocity; // Store this note's velocity. - monomem[note].mkeyshift=masterkeyshift; /* Store masterkeyshift too, + if (Ppolymode==0) { // If Poly is off + monomemnotes.push_back(note); // Add note to the list. + monomem[note].velocity=velocity; // Store this note's velocity. + monomem[note].mkeyshift=masterkeyshift; /* Store masterkeyshift too, I'm not sure why though... */ - if ((partnote[lastpos].status!=KEY_PLAYING) - && (partnote[lastpos].status!=KEY_RELASED_AND_SUSTAINED)){ - ismonofirstnote=true; // No other keys are held or sustained. - } + if ((partnote[lastpos].status!=KEY_PLAYING) + && (partnote[lastpos].status!=KEY_RELASED_AND_SUSTAINED)) { + ismonofirstnote=true; // No other keys are held or sustained. + } } else { - // Poly mode is On so just make sure the list is empty. - if (not monomemnotes.empty()) monomemnotes.clear(); + // Poly mode is On so just make sure the list is empty. + if (not monomemnotes.empty()) monomemnotes.clear(); } lastnote=note; pos=-1; - for (i=0;i<POLIPHONY;i++){ - if (partnote[i].status==KEY_OFF){ - pos=i; - break; - }; + for (i=0;i<POLIPHONY;i++) { + if (partnote[i].status==KEY_OFF) { + pos=i; + break; + }; }; - if ((Plegatomode!=0) && (Pdrummode==0)){ - if (Ppolymode!=0){ - fprintf(stderr, "ZynAddSubFX WARNING: Poly and Legato modes are both On, that should not happen ! ... Disabling Legato mode ! - (Part.C::NoteOn(..))\n"); - Plegatomode=0; - } else { - // Legato mode is on and applicable. - legatomodevalid=true; - if ((not ismonofirstnote)&&(lastlegatomodevalid)){ - // At least one other key is held or sustained, and the - // previous note was played while in valid legato mode. - doinglegato=true; // So we'll do a legato note. - pos=lastpos; // A legato note uses same pos as previous.. - posb=lastposb; // .. same goes for posb. - } else { - // Legato mode is valid, but this is only a first note. - for (i=0;i<POLIPHONY;i++) - if ((partnote[i].status==KEY_PLAYING) || - (partnote[i].status==KEY_RELASED_AND_SUSTAINED)) - RelaseNotePos(i); - - // Set posb - posb=(pos+1)%POLIPHONY;//We really want it (if the following fails) - for (i=0;i<POLIPHONY;i++){ - if ((partnote[i].status==KEY_OFF) && (pos!=i)){ - posb=i; - break; - } - } - } - lastposb=posb;// Keep a trace of used posb - } + if ((Plegatomode!=0) && (Pdrummode==0)) { + if (Ppolymode!=0) { + fprintf(stderr, "ZynAddSubFX WARNING: Poly and Legato modes are both On, that should not happen ! ... Disabling Legato mode ! - (Part.C::NoteOn(..))\n"); + Plegatomode=0; + } else { + // Legato mode is on and applicable. + legatomodevalid=true; + if ((not ismonofirstnote)&&(lastlegatomodevalid)) { + // At least one other key is held or sustained, and the + // previous note was played while in valid legato mode. + doinglegato=true; // So we'll do a legato note. + pos=lastpos; // A legato note uses same pos as previous.. + posb=lastposb; // .. same goes for posb. + } else { + // Legato mode is valid, but this is only a first note. + for (i=0;i<POLIPHONY;i++) + if ((partnote[i].status==KEY_PLAYING) || + (partnote[i].status==KEY_RELASED_AND_SUSTAINED)) + RelaseNotePos(i); + + // Set posb + posb=(pos+1)%POLIPHONY;//We really want it (if the following fails) + for (i=0;i<POLIPHONY;i++) { + if ((partnote[i].status==KEY_OFF) && (pos!=i)) { + posb=i; + break; + } + } + } + lastposb=posb;// Keep a trace of used posb + } } else { // Legato mode is either off or non-applicable. - if (Ppolymode==0){//if the mode is 'mono' turn off all other notes - for (i=0;i<POLIPHONY;i++) - if (partnote[i].status==KEY_PLAYING) RelaseNotePos(i); - RelaseSustainedKeys(); - } + if (Ppolymode==0) {//if the mode is 'mono' turn off all other notes + for (i=0;i<POLIPHONY;i++) + if (partnote[i].status==KEY_PLAYING) RelaseNotePos(i); + RelaseSustainedKeys(); + } } lastlegatomodevalid=legatomodevalid; - if (pos==-1){ + if (pos==-1) { //test - fprintf(stderr,"%s","NOTES TOO MANY (> POLIPHONY) - (Part.C::NoteOn(..))\n"); + fprintf(stderr,"%s","NOTES TOO MANY (> POLIPHONY) - (Part.C::NoteOn(..))\n"); } else { - //start the note - partnote[pos].status=KEY_PLAYING; - partnote[pos].note=note; - if (legatomodevalid){ - partnote[posb].status=KEY_PLAYING; - partnote[posb].note=note; - } - - //this computes the velocity sensing of the part - REALTYPE vel=VelF(velocity/127.0,Pvelsns); - - //compute the velocity offset - vel+=(Pveloffs-64.0)/64.0; - if (vel<0.0) vel=0.0; else if (vel>1.0) vel=1.0; - - //compute the keyshift - int partkeyshift=(int)Pkeyshift-64; - int keyshift=masterkeyshift+partkeyshift; - - //initialise note frequency - REALTYPE notebasefreq; - if (Pdrummode==0){ - notebasefreq=microtonal->getnotefreq(note,keyshift); - if (notebasefreq<0.0) return;//the key is no mapped - } else { - notebasefreq=440.0*pow(2.0,(note-69.0)/12.0); - }; - - //Portamento - if (oldfreq<1.0) oldfreq=notebasefreq;//this is only the first note is played - - // For Mono/Legato: Force Portamento Off on first - // notes. That means it is required that the previous note is - // still held down or sustained for the Portamento to activate - // (that's like Legato). - int portamento=0; - if ((Ppolymode!=0) || (not ismonofirstnote)){ - // I added a third argument to the - // ctl.initportamento(...) function to be able - // to tell it if we're doing a legato note. - portamento=ctl.initportamento(oldfreq,notebasefreq,doinglegato); - } - - if (portamento!=0) ctl.portamento.noteusing=pos; - oldfreq=notebasefreq; - - lastpos=pos; // Keep a trace of used pos. - - if (doinglegato){ - // Do Legato note - if (Pkitmode==0){ // "normal mode" legato note - if ((kit[0].Padenabled!=0) - && (partnote[pos].kititem[0].adnote!=NULL) - && (partnote[posb].kititem[0].adnote!=NULL)){ - partnote[pos].kititem[0].adnote->ADlegatonote(notebasefreq, vel, portamento, note, true);//'true' is to tell it it's being called from here. - partnote[posb].kititem[0].adnote->ADlegatonote(notebasefreq, vel, portamento, note, true); - } - - if ((kit[0].Psubenabled!=0) - && (partnote[pos].kititem[0].subnote!=NULL) - && (partnote[posb].kititem[0].subnote!=NULL)){ - partnote[pos].kititem[0].subnote->SUBlegatonote(notebasefreq, vel, portamento, note, true); - partnote[posb].kititem[0].subnote->SUBlegatonote(notebasefreq, vel, portamento, note, true); - } - - if ((kit[0].Ppadenabled!=0) - && (partnote[pos].kititem[0].padnote!=NULL) - && (partnote[posb].kititem[0].padnote!=NULL)){ - partnote[pos].kititem[0].padnote->PADlegatonote(notebasefreq, vel, portamento, note, true); - partnote[posb].kititem[0].padnote->PADlegatonote(notebasefreq, vel, portamento, note, true); - } - - } else { // "kit mode" legato note - int ci=0; - for (int item=0;item<NUM_KIT_ITEMS;item++){ - if (kit[item].Pmuted!=0) continue; - if ((note<kit[item].Pminkey)||(note>kit[item].Pmaxkey)) continue; - - if ((lastnotecopy<kit[item].Pminkey) - ||(lastnotecopy>kit[item].Pmaxkey)) - continue; // We will not perform legato across 2 key regions. - - partnote[pos].kititem[ci].sendtoparteffect=( kit[item].Psendtoparteffect<NUM_PART_EFX ? kit[item].Psendtoparteffect: NUM_PART_EFX);//if this parameter is 127 for "unprocessed" - partnote[posb].kititem[ci].sendtoparteffect=( kit[item].Psendtoparteffect<NUM_PART_EFX ? kit[item].Psendtoparteffect: NUM_PART_EFX); - - if ((kit[item].Padenabled!=0) && (kit[item].adpars!=NULL) - && (partnote[pos].kititem[ci].adnote!=NULL) - && (partnote[posb].kititem[ci].adnote!=NULL)){ - partnote[pos].kititem[ci].adnote->ADlegatonote(notebasefreq,vel,portamento,note,true); - partnote[posb].kititem[ci].adnote->ADlegatonote(notebasefreq,vel,portamento,note,true); - } - if ((kit[item].Psubenabled!=0) && (kit[item].subpars!=NULL) - && (partnote[pos].kititem[ci].subnote!=NULL) - && (partnote[posb].kititem[ci].subnote!=NULL)){ - partnote[pos].kititem[ci].subnote->SUBlegatonote(notebasefreq,vel,portamento,note,true); - partnote[posb].kititem[ci].subnote->SUBlegatonote(notebasefreq,vel,portamento,note,true); - } - if ((kit[item].Ppadenabled!=0) && (kit[item].padpars!=NULL) - && (partnote[pos].kititem[ci].padnote!=NULL) - && (partnote[posb].kititem[ci].padnote!=NULL)){ - partnote[pos].kititem[ci].padnote->PADlegatonote(notebasefreq,vel,portamento,note,true); - partnote[posb].kititem[ci].padnote->PADlegatonote(notebasefreq,vel,portamento,note,true); - } - - if ((kit[item].adpars!=NULL)||(kit[item].subpars!=NULL)||(kit[item].padpars!=NULL)) { - ci++; - if ( ((kit[item].Padenabled!=0)||(kit[item].Psubenabled!=0)||(kit[item].Ppadenabled!=0)) && (Pkitmode==2) ) break; - } - } - if (ci==0){ - // No legato were performed at all, so pretend nothing happened: - monomemnotes.pop_back(); // Remove last note from the list. - lastnote=lastnotecopy; // Set lastnote back to previous value. - } - } - return; // Ok, Legato note done, return. - } - - partnote[pos].itemsplaying=0; - if (legatomodevalid) partnote[posb].itemsplaying=0; - - if (Pkitmode==0){//init the notes for the "normal mode" - partnote[pos].kititem[0].sendtoparteffect=0; - if (kit[0].Padenabled!=0) partnote[pos].kititem[0].adnote=new ADnote(kit[0].adpars,&ctl,notebasefreq,vel,portamento,note,false); - if (kit[0].Psubenabled!=0) partnote[pos].kititem[0].subnote=new SUBnote(kit[0].subpars,&ctl,notebasefreq,vel,portamento,note,false); - if (kit[0].Ppadenabled!=0) partnote[pos].kititem[0].padnote=new PADnote(kit[0].padpars,&ctl,notebasefreq,vel,portamento,note,false); - if ((kit[0].Padenabled!=0)||(kit[0].Psubenabled!=0)||(kit[0].Ppadenabled!=0)) partnote[pos].itemsplaying++; - - // Spawn another note (but silent) if legatomodevalid==true - if (legatomodevalid){ - partnote[posb].kititem[0].sendtoparteffect=0; - if (kit[0].Padenabled!=0) partnote[posb].kititem[0].adnote=new ADnote(kit[0].adpars,&ctl,notebasefreq,vel,portamento,note,true);//true for silent. - if (kit[0].Psubenabled!=0) partnote[posb].kititem[0].subnote=new SUBnote(kit[0].subpars,&ctl,notebasefreq,vel,portamento,note,true); - if (kit[0].Ppadenabled!=0) partnote[posb].kititem[0].padnote=new PADnote(kit[0].padpars,&ctl,notebasefreq,vel,portamento,note,true); - if ((kit[0].Padenabled!=0)||(kit[0].Psubenabled!=0)||(kit[0].Ppadenabled!=0)) partnote[posb].itemsplaying++; - } - - } else {//init the notes for the "kit mode" - for (int item=0;item<NUM_KIT_ITEMS;item++){ - if (kit[item].Pmuted!=0) continue; - if ((note<kit[item].Pminkey)||(note>kit[item].Pmaxkey)) continue; - - int ci=partnote[pos].itemsplaying;//ci=current item - - partnote[pos].kititem[ci].sendtoparteffect=( kit[item].Psendtoparteffect<NUM_PART_EFX ? - kit[item].Psendtoparteffect: NUM_PART_EFX);//if this parameter is 127 for "unprocessed" - - if ((kit[item].adpars!=NULL)&&(kit[item].Padenabled)!=0) - partnote[pos].kititem[ci].adnote=new ADnote(kit[item].adpars,&ctl,notebasefreq,vel,portamento,note,false); - - if ((kit[item].subpars!=NULL)&&(kit[item].Psubenabled)!=0) - partnote[pos].kititem[ci].subnote=new SUBnote(kit[item].subpars,&ctl,notebasefreq,vel,portamento,note,false); - - if ((kit[item].padpars!=NULL)&&(kit[item].Ppadenabled)!=0) - partnote[pos].kititem[ci].padnote=new PADnote(kit[item].padpars,&ctl,notebasefreq,vel,portamento,note,false); - - // Spawn another note (but silent) if legatomodevalid==true - if (legatomodevalid){ - partnote[posb].kititem[ci].sendtoparteffect=( kit[item].Psendtoparteffect<NUM_PART_EFX ? kit[item].Psendtoparteffect: NUM_PART_EFX);//if this parameter is 127 for "unprocessed" - - if ((kit[item].adpars!=NULL)&&(kit[item].Padenabled)!=0) - partnote[posb].kititem[ci].adnote=new ADnote(kit[item].adpars,&ctl,notebasefreq,vel,portamento,note,true);//true for silent. - if ((kit[item].subpars!=NULL)&&(kit[item].Psubenabled)!=0) - partnote[posb].kititem[ci].subnote=new SUBnote(kit[item].subpars,&ctl,notebasefreq,vel,portamento,note,true); - if ((kit[item].padpars!=NULL)&&(kit[item].Ppadenabled)!=0) - partnote[posb].kititem[ci].padnote=new PADnote(kit[item].padpars,&ctl,notebasefreq,vel,portamento,note,true); - - if ((kit[item].adpars!=NULL)|| (kit[item].subpars!=NULL)) - partnote[posb].itemsplaying++; - } - - if ((kit[item].adpars!=NULL)|| (kit[item].subpars!=NULL)) { - partnote[pos].itemsplaying++; - if ( ((kit[item].Padenabled!=0)||(kit[item].Psubenabled!=0)||(kit[item].Ppadenabled!=0)) - && (Pkitmode==2) ) break; - }; - }; - }; + //start the note + partnote[pos].status=KEY_PLAYING; + partnote[pos].note=note; + if (legatomodevalid) { + partnote[posb].status=KEY_PLAYING; + partnote[posb].note=note; + } + + //this computes the velocity sensing of the part + REALTYPE vel=VelF(velocity/127.0,Pvelsns); + + //compute the velocity offset + vel+=(Pveloffs-64.0)/64.0; + if (vel<0.0) vel=0.0; + else if (vel>1.0) vel=1.0; + + //compute the keyshift + int partkeyshift=(int)Pkeyshift-64; + int keyshift=masterkeyshift+partkeyshift; + + //initialise note frequency + REALTYPE notebasefreq; + if (Pdrummode==0) { + notebasefreq=microtonal->getnotefreq(note,keyshift); + if (notebasefreq<0.0) return;//the key is no mapped + } else { + notebasefreq=440.0*pow(2.0,(note-69.0)/12.0); + }; + + //Portamento + if (oldfreq<1.0) oldfreq=notebasefreq;//this is only the first note is played + + // For Mono/Legato: Force Portamento Off on first + // notes. That means it is required that the previous note is + // still held down or sustained for the Portamento to activate + // (that's like Legato). + int portamento=0; + if ((Ppolymode!=0) || (not ismonofirstnote)) { + // I added a third argument to the + // ctl.initportamento(...) function to be able + // to tell it if we're doing a legato note. + portamento=ctl.initportamento(oldfreq,notebasefreq,doinglegato); + } + + if (portamento!=0) ctl.portamento.noteusing=pos; + oldfreq=notebasefreq; + + lastpos=pos; // Keep a trace of used pos. + + if (doinglegato) { + // Do Legato note + if (Pkitmode==0) { // "normal mode" legato note + if ((kit[0].Padenabled!=0) + && (partnote[pos].kititem[0].adnote!=NULL) + && (partnote[posb].kititem[0].adnote!=NULL)) { + partnote[pos].kititem[0].adnote->ADlegatonote(notebasefreq, vel, portamento, note, true);//'true' is to tell it it's being called from here. + partnote[posb].kititem[0].adnote->ADlegatonote(notebasefreq, vel, portamento, note, true); + } + + if ((kit[0].Psubenabled!=0) + && (partnote[pos].kititem[0].subnote!=NULL) + && (partnote[posb].kititem[0].subnote!=NULL)) { + partnote[pos].kititem[0].subnote->SUBlegatonote(notebasefreq, vel, portamento, note, true); + partnote[posb].kititem[0].subnote->SUBlegatonote(notebasefreq, vel, portamento, note, true); + } + + if ((kit[0].Ppadenabled!=0) + && (partnote[pos].kititem[0].padnote!=NULL) + && (partnote[posb].kititem[0].padnote!=NULL)) { + partnote[pos].kititem[0].padnote->PADlegatonote(notebasefreq, vel, portamento, note, true); + partnote[posb].kititem[0].padnote->PADlegatonote(notebasefreq, vel, portamento, note, true); + } + + } else { // "kit mode" legato note + int ci=0; + for (int item=0;item<NUM_KIT_ITEMS;item++) { + if (kit[item].Pmuted!=0) continue; + if ((note<kit[item].Pminkey)||(note>kit[item].Pmaxkey)) continue; + + if ((lastnotecopy<kit[item].Pminkey) + ||(lastnotecopy>kit[item].Pmaxkey)) + continue; // We will not perform legato across 2 key regions. + + partnote[pos].kititem[ci].sendtoparteffect=( kit[item].Psendtoparteffect<NUM_PART_EFX ? kit[item].Psendtoparteffect: NUM_PART_EFX);//if this parameter is 127 for "unprocessed" + partnote[posb].kititem[ci].sendtoparteffect=( kit[item].Psendtoparteffect<NUM_PART_EFX ? kit[item].Psendtoparteffect: NUM_PART_EFX); + + if ((kit[item].Padenabled!=0) && (kit[item].adpars!=NULL) + && (partnote[pos].kititem[ci].adnote!=NULL) + && (partnote[posb].kititem[ci].adnote!=NULL)) { + partnote[pos].kititem[ci].adnote->ADlegatonote(notebasefreq,vel,portamento,note,true); + partnote[posb].kititem[ci].adnote->ADlegatonote(notebasefreq,vel,portamento,note,true); + } + if ((kit[item].Psubenabled!=0) && (kit[item].subpars!=NULL) + && (partnote[pos].kititem[ci].subnote!=NULL) + && (partnote[posb].kititem[ci].subnote!=NULL)) { + partnote[pos].kititem[ci].subnote->SUBlegatonote(notebasefreq,vel,portamento,note,true); + partnote[posb].kititem[ci].subnote->SUBlegatonote(notebasefreq,vel,portamento,note,true); + } + if ((kit[item].Ppadenabled!=0) && (kit[item].padpars!=NULL) + && (partnote[pos].kititem[ci].padnote!=NULL) + && (partnote[posb].kititem[ci].padnote!=NULL)) { + partnote[pos].kititem[ci].padnote->PADlegatonote(notebasefreq,vel,portamento,note,true); + partnote[posb].kititem[ci].padnote->PADlegatonote(notebasefreq,vel,portamento,note,true); + } + + if ((kit[item].adpars!=NULL)||(kit[item].subpars!=NULL)||(kit[item].padpars!=NULL)) { + ci++; + if ( ((kit[item].Padenabled!=0)||(kit[item].Psubenabled!=0)||(kit[item].Ppadenabled!=0)) && (Pkitmode==2) ) break; + } + } + if (ci==0) { + // No legato were performed at all, so pretend nothing happened: + monomemnotes.pop_back(); // Remove last note from the list. + lastnote=lastnotecopy; // Set lastnote back to previous value. + } + } + return; // Ok, Legato note done, return. + } + + partnote[pos].itemsplaying=0; + if (legatomodevalid) partnote[posb].itemsplaying=0; + + if (Pkitmode==0) {//init the notes for the "normal mode" + partnote[pos].kititem[0].sendtoparteffect=0; + if (kit[0].Padenabled!=0) partnote[pos].kititem[0].adnote=new ADnote(kit[0].adpars,&ctl,notebasefreq,vel,portamento,note,false); + if (kit[0].Psubenabled!=0) partnote[pos].kititem[0].subnote=new SUBnote(kit[0].subpars,&ctl,notebasefreq,vel,portamento,note,false); + if (kit[0].Ppadenabled!=0) partnote[pos].kititem[0].padnote=new PADnote(kit[0].padpars,&ctl,notebasefreq,vel,portamento,note,false); + if ((kit[0].Padenabled!=0)||(kit[0].Psubenabled!=0)||(kit[0].Ppadenabled!=0)) partnote[pos].itemsplaying++; + + // Spawn another note (but silent) if legatomodevalid==true + if (legatomodevalid) { + partnote[posb].kititem[0].sendtoparteffect=0; + if (kit[0].Padenabled!=0) partnote[posb].kititem[0].adnote=new ADnote(kit[0].adpars,&ctl,notebasefreq,vel,portamento,note,true);//true for silent. + if (kit[0].Psubenabled!=0) partnote[posb].kititem[0].subnote=new SUBnote(kit[0].subpars,&ctl,notebasefreq,vel,portamento,note,true); + if (kit[0].Ppadenabled!=0) partnote[posb].kititem[0].padnote=new PADnote(kit[0].padpars,&ctl,notebasefreq,vel,portamento,note,true); + if ((kit[0].Padenabled!=0)||(kit[0].Psubenabled!=0)||(kit[0].Ppadenabled!=0)) partnote[posb].itemsplaying++; + } + + } else {//init the notes for the "kit mode" + for (int item=0;item<NUM_KIT_ITEMS;item++) { + if (kit[item].Pmuted!=0) continue; + if ((note<kit[item].Pminkey)||(note>kit[item].Pmaxkey)) continue; + + int ci=partnote[pos].itemsplaying;//ci=current item + + partnote[pos].kititem[ci].sendtoparteffect=( kit[item].Psendtoparteffect<NUM_PART_EFX ? + kit[item].Psendtoparteffect: NUM_PART_EFX);//if this parameter is 127 for "unprocessed" + + if ((kit[item].adpars!=NULL)&&(kit[item].Padenabled)!=0) + partnote[pos].kititem[ci].adnote=new ADnote(kit[item].adpars,&ctl,notebasefreq,vel,portamento,note,false); + + if ((kit[item].subpars!=NULL)&&(kit[item].Psubenabled)!=0) + partnote[pos].kititem[ci].subnote=new SUBnote(kit[item].subpars,&ctl,notebasefreq,vel,portamento,note,false); + + if ((kit[item].padpars!=NULL)&&(kit[item].Ppadenabled)!=0) + partnote[pos].kititem[ci].padnote=new PADnote(kit[item].padpars,&ctl,notebasefreq,vel,portamento,note,false); + + // Spawn another note (but silent) if legatomodevalid==true + if (legatomodevalid) { + partnote[posb].kititem[ci].sendtoparteffect=( kit[item].Psendtoparteffect<NUM_PART_EFX ? kit[item].Psendtoparteffect: NUM_PART_EFX);//if this parameter is 127 for "unprocessed" + + if ((kit[item].adpars!=NULL)&&(kit[item].Padenabled)!=0) + partnote[posb].kititem[ci].adnote=new ADnote(kit[item].adpars,&ctl,notebasefreq,vel,portamento,note,true);//true for silent. + if ((kit[item].subpars!=NULL)&&(kit[item].Psubenabled)!=0) + partnote[posb].kititem[ci].subnote=new SUBnote(kit[item].subpars,&ctl,notebasefreq,vel,portamento,note,true); + if ((kit[item].padpars!=NULL)&&(kit[item].Ppadenabled)!=0) + partnote[posb].kititem[ci].padnote=new PADnote(kit[item].padpars,&ctl,notebasefreq,vel,portamento,note,true); + + if ((kit[item].adpars!=NULL)|| (kit[item].subpars!=NULL)) + partnote[posb].itemsplaying++; + } + + if ((kit[item].adpars!=NULL)|| (kit[item].subpars!=NULL)) { + partnote[pos].itemsplaying++; + if ( ((kit[item].Padenabled!=0)||(kit[item].Psubenabled!=0)||(kit[item].Ppadenabled!=0)) + && (Pkitmode==2) ) break; + }; + }; + }; }; - + //this only relase the keys if there is maximum number of keys allowed setkeylimit(Pkeylimit); }; @@ -453,185 +468,205 @@ void Part::NoteOn(unsigned char note,unsigned char velocity,int masterkeyshift){ /* * Note Off Messages */ -void Part::NoteOff(unsigned char note){//relase the key - int i; +void Part::NoteOff(unsigned char note) //relase the key +{ + int i; // This note is released, so we remove it from the list. if (not monomemnotes.empty()) monomemnotes.remove(note); - for (i=POLIPHONY-1;i>=0;i--){ //first note in, is first out if there are same note multiple times - if ((partnote[i].status==KEY_PLAYING)&&(partnote[i].note==note)) { - if (ctl.sustain.sustain==0){ //the sustain pedal is not pushed - if ((Ppolymode==0) && (not monomemnotes.empty())){ - MonoMemRenote(); // To play most recent still held note. - } else { - RelaseNotePos(i); - /// break; - } - } else {//the sustain pedal is pushed - partnote[i].status=KEY_RELASED_AND_SUSTAINED; - } - } + for (i=POLIPHONY-1;i>=0;i--) { //first note in, is first out if there are same note multiple times + if ((partnote[i].status==KEY_PLAYING)&&(partnote[i].note==note)) { + if (ctl.sustain.sustain==0) { //the sustain pedal is not pushed + if ((Ppolymode==0) && (not monomemnotes.empty())) { + MonoMemRenote(); // To play most recent still held note. + } else { + RelaseNotePos(i); + /// break; + } + } else {//the sustain pedal is pushed + partnote[i].status=KEY_RELASED_AND_SUSTAINED; + } + } } }; /* * Controllers */ -void Part::SetController(unsigned int type,int par){ - switch (type){ - case C_pitchwheel:ctl.setpitchwheel(par); - break; - case C_expression:ctl.setexpression(par); - setPvolume(Pvolume);//update the volume - break; - case C_portamento:ctl.setportamento(par); - break; - case C_panning:ctl.setpanning(par); - setPpanning(Ppanning);//update the panning - break; - case C_filtercutoff:ctl.setfiltercutoff(par); - break; - case C_filterq:ctl.setfilterq(par); - break; - case C_bandwidth:ctl.setbandwidth(par); - break; - case C_modwheel:ctl.setmodwheel(par); - break; - case C_fmamp:ctl.setfmamp(par); - break; - case C_volume:ctl.setvolume(par); - if (ctl.volume.receive!=0) volume=ctl.volume.volume; - else setPvolume(Pvolume); - break; - case C_sustain:ctl.setsustain(par); - if (ctl.sustain.sustain==0) RelaseSustainedKeys(); - break; - case C_allsoundsoff:AllNotesOff();//Panic - break; - case C_resetallcontrollers: - ctl.resetall(); - RelaseSustainedKeys(); - if (ctl.volume.receive!=0) volume=ctl.volume.volume; - else setPvolume(Pvolume); - setPvolume(Pvolume);//update the volume - setPpanning(Ppanning);//update the panning - - for (int item=0;item<NUM_KIT_ITEMS;item++){ - if (kit[item].adpars==NULL) continue; - kit[item].adpars->GlobalPar.Reson-> - sendcontroller(C_resonance_center,1.0); - - kit[item].adpars->GlobalPar.Reson-> - sendcontroller(C_resonance_bandwidth,1.0); - }; - //more update to add here if I add controllers - break; - case C_allnotesoff:RelaseAllKeys(); - break; - case C_resonance_center: - ctl.setresonancecenter(par); - for (int item=0;item<NUM_KIT_ITEMS;item++){ - if (kit[item].adpars==NULL) continue; - kit[item].adpars->GlobalPar.Reson-> - sendcontroller(C_resonance_center,ctl.resonancecenter.relcenter); - }; - break; - case C_resonance_bandwidth: - ctl.setresonancebw(par); - kit[0].adpars->GlobalPar.Reson-> - sendcontroller(C_resonance_bandwidth,ctl.resonancebandwidth.relbw); - break; +void Part::SetController(unsigned int type,int par) +{ + switch (type) { + case C_pitchwheel: + ctl.setpitchwheel(par); + break; + case C_expression: + ctl.setexpression(par); + setPvolume(Pvolume);//update the volume + break; + case C_portamento: + ctl.setportamento(par); + break; + case C_panning: + ctl.setpanning(par); + setPpanning(Ppanning);//update the panning + break; + case C_filtercutoff: + ctl.setfiltercutoff(par); + break; + case C_filterq: + ctl.setfilterq(par); + break; + case C_bandwidth: + ctl.setbandwidth(par); + break; + case C_modwheel: + ctl.setmodwheel(par); + break; + case C_fmamp: + ctl.setfmamp(par); + break; + case C_volume: + ctl.setvolume(par); + if (ctl.volume.receive!=0) volume=ctl.volume.volume; + else setPvolume(Pvolume); + break; + case C_sustain: + ctl.setsustain(par); + if (ctl.sustain.sustain==0) RelaseSustainedKeys(); + break; + case C_allsoundsoff: + AllNotesOff();//Panic + break; + case C_resetallcontrollers: + ctl.resetall(); + RelaseSustainedKeys(); + if (ctl.volume.receive!=0) volume=ctl.volume.volume; + else setPvolume(Pvolume); + setPvolume(Pvolume);//update the volume + setPpanning(Ppanning);//update the panning + + for (int item=0;item<NUM_KIT_ITEMS;item++) { + if (kit[item].adpars==NULL) continue; + kit[item].adpars->GlobalPar.Reson-> + sendcontroller(C_resonance_center,1.0); + + kit[item].adpars->GlobalPar.Reson-> + sendcontroller(C_resonance_bandwidth,1.0); + }; + //more update to add here if I add controllers + break; + case C_allnotesoff: + RelaseAllKeys(); + break; + case C_resonance_center: + ctl.setresonancecenter(par); + for (int item=0;item<NUM_KIT_ITEMS;item++) { + if (kit[item].adpars==NULL) continue; + kit[item].adpars->GlobalPar.Reson-> + sendcontroller(C_resonance_center,ctl.resonancecenter.relcenter); + }; + break; + case C_resonance_bandwidth: + ctl.setresonancebw(par); + kit[0].adpars->GlobalPar.Reson-> + sendcontroller(C_resonance_bandwidth,ctl.resonancebandwidth.relbw); + break; }; }; /* * Relase the sustained keys */ -void Part::RelaseSustainedKeys(){ +void Part::RelaseSustainedKeys() +{ // Let's call MonoMemRenote() on some conditions: if ((Ppolymode==0) && (not monomemnotes.empty())) - if (monomemnotes.back()!=lastnote) // Sustain controller manipulation would cause repeated same note respawn without this check. - MonoMemRenote(); // To play most recent still held note. + if (monomemnotes.back()!=lastnote) // Sustain controller manipulation would cause repeated same note respawn without this check. + MonoMemRenote(); // To play most recent still held note. for (int i=0;i<POLIPHONY;i++) - if (partnote[i].status==KEY_RELASED_AND_SUSTAINED) RelaseNotePos(i); + if (partnote[i].status==KEY_RELASED_AND_SUSTAINED) RelaseNotePos(i); }; /* * Relase all keys */ -void Part::RelaseAllKeys(){ - for (int i=0;i<POLIPHONY;i++){ - if ((partnote[i].status!=KEY_RELASED)&& - (partnote[i].status!=KEY_OFF)) //thanks to Frank Neumann - RelaseNotePos(i); +void Part::RelaseAllKeys() +{ + for (int i=0;i<POLIPHONY;i++) { + if ((partnote[i].status!=KEY_RELASED)&& + (partnote[i].status!=KEY_OFF)) //thanks to Frank Neumann + RelaseNotePos(i); }; }; // Call NoteOn(...) with the most recent still held key as new note // (Made for Mono/Legato). -void Part::MonoMemRenote(){ - unsigned char mmrtempnote=monomemnotes.back(); // Last list element. - monomemnotes.pop_back();// We remove it, will be added again in NoteOn(...). - if (Pnoteon==0){ - RelaseNotePos(lastpos); - } else { - NoteOn(mmrtempnote, monomem[mmrtempnote].velocity, - monomem[mmrtempnote].mkeyshift); - } +void Part::MonoMemRenote() +{ + unsigned char mmrtempnote=monomemnotes.back(); // Last list element. + monomemnotes.pop_back();// We remove it, will be added again in NoteOn(...). + if (Pnoteon==0) { + RelaseNotePos(lastpos); + } else { + NoteOn(mmrtempnote, monomem[mmrtempnote].velocity, + monomem[mmrtempnote].mkeyshift); + } } /* * Release note at position */ -void Part::RelaseNotePos(int pos){ +void Part::RelaseNotePos(int pos) +{ - for (int j=0;j<NUM_KIT_ITEMS;j++){ + for (int j=0;j<NUM_KIT_ITEMS;j++) { - if (partnote[pos].kititem[j].adnote!=NULL) - if (partnote[pos].kititem[j].adnote) - partnote[pos].kititem[j].adnote->relasekey(); + if (partnote[pos].kititem[j].adnote!=NULL) + if (partnote[pos].kititem[j].adnote) + partnote[pos].kititem[j].adnote->relasekey(); - if (partnote[pos].kititem[j].subnote!=NULL) - if (partnote[pos].kititem[j].subnote!=NULL) - partnote[pos].kititem[j].subnote->relasekey(); + if (partnote[pos].kititem[j].subnote!=NULL) + if (partnote[pos].kititem[j].subnote!=NULL) + partnote[pos].kititem[j].subnote->relasekey(); - if (partnote[pos].kititem[j].padnote!=NULL) - if (partnote[pos].kititem[j].padnote) - partnote[pos].kititem[j].padnote->relasekey(); + if (partnote[pos].kititem[j].padnote!=NULL) + if (partnote[pos].kititem[j].padnote) + partnote[pos].kititem[j].padnote->relasekey(); }; partnote[pos].status=KEY_RELASED; -}; - - +}; + + /* * Kill note at position */ -void Part::KillNotePos(int pos){ +void Part::KillNotePos(int pos) +{ partnote[pos].status=KEY_OFF; partnote[pos].note=-1; partnote[pos].time=0; partnote[pos].itemsplaying=0; - for (int j=0;j<NUM_KIT_ITEMS;j++){ - if (partnote[pos].kititem[j].adnote!=NULL) { - delete(partnote[pos].kititem[j].adnote); - partnote[pos].kititem[j].adnote=NULL; - }; - if (partnote[pos].kititem[j].subnote!=NULL) { - delete(partnote[pos].kititem[j].subnote); - partnote[pos].kititem[j].subnote=NULL; - }; - if (partnote[pos].kititem[j].padnote!=NULL) { - delete(partnote[pos].kititem[j].padnote); - partnote[pos].kititem[j].padnote=NULL; - }; + for (int j=0;j<NUM_KIT_ITEMS;j++) { + if (partnote[pos].kititem[j].adnote!=NULL) { + delete(partnote[pos].kititem[j].adnote); + partnote[pos].kititem[j].adnote=NULL; + }; + if (partnote[pos].kititem[j].subnote!=NULL) { + delete(partnote[pos].kititem[j].subnote); + partnote[pos].kititem[j].subnote=NULL; + }; + if (partnote[pos].kititem[j].padnote!=NULL) { + delete(partnote[pos].kititem[j].padnote); + partnote[pos].kititem[j].padnote=NULL; + }; }; if (pos==ctl.portamento.noteusing) { - ctl.portamento.noteusing=-1; - ctl.portamento.used=0; + ctl.portamento.noteusing=-1; + ctl.portamento.used=0; }; }; @@ -639,29 +674,30 @@ void Part::KillNotePos(int pos){ /* * Set Part's key limit */ -void Part::setkeylimit(unsigned char Pkeylimit){ +void Part::setkeylimit(unsigned char Pkeylimit) +{ this->Pkeylimit=Pkeylimit; int keylimit=Pkeylimit; if (keylimit==0) keylimit=POLIPHONY-5; //release old keys if the number of notes>keylimit - if (Ppolymode!=0){ - int notecount=0; - for (int i=0;i<POLIPHONY;i++){ - if ((partnote[i].status==KEY_PLAYING)||(partnote[i].status==KEY_RELASED_AND_SUSTAINED)) - notecount++; - }; - int oldestnotepos=-1,maxtime=0; - if (notecount>keylimit){//find out the oldest note - for (int i=0;i<POLIPHONY;i++){ - if ( ((partnote[i].status==KEY_PLAYING)||(partnote[i].status==KEY_RELASED_AND_SUSTAINED)) - && (partnote[i].time>maxtime)){ - maxtime=partnote[i].time; - oldestnotepos=i; - }; - }; - }; - if (oldestnotepos!=-1) RelaseNotePos(oldestnotepos); + if (Ppolymode!=0) { + int notecount=0; + for (int i=0;i<POLIPHONY;i++) { + if ((partnote[i].status==KEY_PLAYING)||(partnote[i].status==KEY_RELASED_AND_SUSTAINED)) + notecount++; + }; + int oldestnotepos=-1,maxtime=0; + if (notecount>keylimit) {//find out the oldest note + for (int i=0;i<POLIPHONY;i++) { + if ( ((partnote[i].status==KEY_PLAYING)||(partnote[i].status==KEY_RELASED_AND_SUSTAINED)) + && (partnote[i].time>maxtime)) { + maxtime=partnote[i].time; + oldestnotepos=i; + }; + }; + }; + if (oldestnotepos!=-1) RelaseNotePos(oldestnotepos); }; }; @@ -669,124 +705,135 @@ void Part::setkeylimit(unsigned char Pkeylimit){ /* * Prepare all notes to be turned off */ -void Part::AllNotesOff(){ - killallnotes=1; +void Part::AllNotesOff() +{ + killallnotes=1; }; /* * Compute Part samples and store them in the partoutl[] and partoutr[] */ -void Part::ComputePartSmps(){ +void Part::ComputePartSmps() +{ int i,k; int noteplay;//0 if there is nothing activated - for (int nefx=0;nefx<NUM_PART_EFX+1;nefx++){ - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - partfxinputl[nefx][i]=0.0; - partfxinputr[nefx][i]=0.0; - }; + for (int nefx=0;nefx<NUM_PART_EFX+1;nefx++) { + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + partfxinputl[nefx][i]=0.0; + partfxinputr[nefx][i]=0.0; + }; }; - - for (k=0;k<POLIPHONY;k++){ - if (partnote[k].status==KEY_OFF) continue; - noteplay=0; - partnote[k].time++; - //get the sampledata of the note and kill it if it's finished - - for (int item=0;item<partnote[k].itemsplaying;item++){ - - int sendcurrenttofx=partnote[k].kititem[item].sendtoparteffect; - - ADnote *adnote=partnote[k].kititem[item].adnote; - SUBnote *subnote=partnote[k].kititem[item].subnote; - PADnote *padnote=partnote[k].kititem[item].padnote; - //get from the ADnote + + for (k=0;k<POLIPHONY;k++) { + if (partnote[k].status==KEY_OFF) continue; + noteplay=0; + partnote[k].time++; + //get the sampledata of the note and kill it if it's finished + + for (int item=0;item<partnote[k].itemsplaying;item++) { + + int sendcurrenttofx=partnote[k].kititem[item].sendtoparteffect; + + ADnote *adnote=partnote[k].kititem[item].adnote; + SUBnote *subnote=partnote[k].kititem[item].subnote; + PADnote *padnote=partnote[k].kititem[item].padnote; + //get from the ADnote if (adnote!=NULL) { - noteplay++; - if (adnote->ready!=0) adnote->noteout(&tmpoutl[0],&tmpoutr[0]); - else for (i=0;i<SOUND_BUFFER_SIZE;i++){tmpoutl[i]=0.0;tmpoutr[i]=0.0;}; - if (adnote->finished()!=0){ - delete (adnote); - partnote[k].kititem[item].adnote=NULL; - }; - for (i=0;i<SOUND_BUFFER_SIZE;i++){//add the ADnote to part(mix) - partfxinputl[sendcurrenttofx][i]+=tmpoutl[i]; - partfxinputr[sendcurrenttofx][i]+=tmpoutr[i]; - }; - }; - //get from the SUBnote - if (subnote!=NULL) { - noteplay++; - if (subnote->ready!=0) subnote->noteout(&tmpoutl[0],&tmpoutr[0]); - else for (i=0;i<SOUND_BUFFER_SIZE;i++){tmpoutl[i]=0.0;tmpoutr[i]=0.0;}; - - for (i=0;i<SOUND_BUFFER_SIZE;i++){//add the SUBnote to part(mix) - partfxinputl[sendcurrenttofx][i]+=tmpoutl[i]; - partfxinputr[sendcurrenttofx][i]+=tmpoutr[i]; - }; - if (subnote->finished()!=0){ - delete (subnote); - partnote[k].kititem[item].subnote=NULL; - }; - }; - //get from the PADnote + noteplay++; + if (adnote->ready!=0) adnote->noteout(&tmpoutl[0],&tmpoutr[0]); + else for (i=0;i<SOUND_BUFFER_SIZE;i++) { + tmpoutl[i]=0.0; + tmpoutr[i]=0.0; + }; + if (adnote->finished()!=0) { + delete (adnote); + partnote[k].kititem[item].adnote=NULL; + }; + for (i=0;i<SOUND_BUFFER_SIZE;i++) {//add the ADnote to part(mix) + partfxinputl[sendcurrenttofx][i]+=tmpoutl[i]; + partfxinputr[sendcurrenttofx][i]+=tmpoutr[i]; + }; + }; + //get from the SUBnote + if (subnote!=NULL) { + noteplay++; + if (subnote->ready!=0) subnote->noteout(&tmpoutl[0],&tmpoutr[0]); + else for (i=0;i<SOUND_BUFFER_SIZE;i++) { + tmpoutl[i]=0.0; + tmpoutr[i]=0.0; + }; + + for (i=0;i<SOUND_BUFFER_SIZE;i++) {//add the SUBnote to part(mix) + partfxinputl[sendcurrenttofx][i]+=tmpoutl[i]; + partfxinputr[sendcurrenttofx][i]+=tmpoutr[i]; + }; + if (subnote->finished()!=0) { + delete (subnote); + partnote[k].kititem[item].subnote=NULL; + }; + }; + //get from the PADnote if (padnote!=NULL) { - noteplay++; - if (padnote->ready!=0) padnote->noteout(&tmpoutl[0],&tmpoutr[0]); - else for (i=0;i<SOUND_BUFFER_SIZE;i++){tmpoutl[i]=0.0;tmpoutr[i]=0.0;}; - if (padnote->finished()!=0){ - delete (padnote); - partnote[k].kititem[item].padnote=NULL; - }; - for (i=0;i<SOUND_BUFFER_SIZE;i++){//add the PADnote to part(mix) - partfxinputl[sendcurrenttofx][i]+=tmpoutl[i]; - partfxinputr[sendcurrenttofx][i]+=tmpoutr[i]; - }; - }; - - }; - //Kill note if there is no synth on that note - if (noteplay==0) KillNotePos(k); + noteplay++; + if (padnote->ready!=0) padnote->noteout(&tmpoutl[0],&tmpoutr[0]); + else for (i=0;i<SOUND_BUFFER_SIZE;i++) { + tmpoutl[i]=0.0; + tmpoutr[i]=0.0; + }; + if (padnote->finished()!=0) { + delete (padnote); + partnote[k].kititem[item].padnote=NULL; + }; + for (i=0;i<SOUND_BUFFER_SIZE;i++) {//add the PADnote to part(mix) + partfxinputl[sendcurrenttofx][i]+=tmpoutl[i]; + partfxinputr[sendcurrenttofx][i]+=tmpoutr[i]; + }; + }; + + }; + //Kill note if there is no synth on that note + if (noteplay==0) KillNotePos(k); }; //Apply part's effects and mix them for (int nefx=0;nefx<NUM_PART_EFX;nefx++) { - if (!Pefxbypass[nefx]) { - partefx[nefx]->out(partfxinputl[nefx],partfxinputr[nefx]); - if (Pefxroute[nefx]==2){ - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - partfxinputl[nefx+1][i]+=partefx[nefx]->efxoutl[i]; - partfxinputr[nefx+1][i]+=partefx[nefx]->efxoutr[i]; - }; - }; - }; - int routeto=((Pefxroute[nefx]==0) ? nefx+1 : NUM_PART_EFX); - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - partfxinputl[routeto][i]+=partfxinputl[nefx][i]; - partfxinputr[routeto][i]+=partfxinputr[nefx][i]; - }; - + if (!Pefxbypass[nefx]) { + partefx[nefx]->out(partfxinputl[nefx],partfxinputr[nefx]); + if (Pefxroute[nefx]==2) { + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + partfxinputl[nefx+1][i]+=partefx[nefx]->efxoutl[i]; + partfxinputr[nefx+1][i]+=partefx[nefx]->efxoutr[i]; + }; + }; + }; + int routeto=((Pefxroute[nefx]==0) ? nefx+1 : NUM_PART_EFX); + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + partfxinputl[routeto][i]+=partfxinputl[nefx][i]; + partfxinputr[routeto][i]+=partfxinputr[nefx][i]; + }; + }; - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - partoutl[i]=partfxinputl[NUM_PART_EFX][i]; - partoutr[i]=partfxinputr[NUM_PART_EFX][i]; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + partoutl[i]=partfxinputl[NUM_PART_EFX][i]; + partoutr[i]=partfxinputr[NUM_PART_EFX][i]; }; //Kill All Notes if killallnotes!=0 if (killallnotes!=0) { - for (i=0;i<SOUND_BUFFER_SIZE;i++) { - REALTYPE tmp=(SOUND_BUFFER_SIZE-i)/(REALTYPE) SOUND_BUFFER_SIZE; - partoutl[i]*=tmp; - partoutr[i]*=tmp; - tmpoutl[i]=0.0; - tmpoutr[i]=0.0; - }; - for (int k=0;k<POLIPHONY;k++) KillNotePos(k); - killallnotes=0; - for (int nefx=0;nefx<NUM_PART_EFX;nefx++) { - partefx[nefx]->cleanup(); - }; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + REALTYPE tmp=(SOUND_BUFFER_SIZE-i)/(REALTYPE) SOUND_BUFFER_SIZE; + partoutl[i]*=tmp; + partoutr[i]*=tmp; + tmpoutl[i]=0.0; + tmpoutr[i]=0.0; + }; + for (int k=0;k<POLIPHONY;k++) KillNotePos(k); + killallnotes=0; + for (int nefx=0;nefx<NUM_PART_EFX;nefx++) { + partefx[nefx]->cleanup(); + }; }; ctl.updateportamento(); }; @@ -794,114 +841,122 @@ void Part::ComputePartSmps(){ /* * Parameter control */ -void Part::setPvolume(char Pvolume_){ +void Part::setPvolume(char Pvolume_) +{ Pvolume=Pvolume_; volume=dB2rap((Pvolume-96.0)/96.0*40.0)*ctl.expression.relvolume; }; -void Part::setPpanning(char Ppanning_){ +void Part::setPpanning(char Ppanning_) +{ Ppanning=Ppanning_; panning=Ppanning/127.0+ctl.panning.pan; - if (panning<0.0) panning=0.0;else if (panning>1.0) panning=1.0; + if (panning<0.0) panning=0.0; + else if (panning>1.0) panning=1.0; }; /* * Enable or disable a kit item */ -void Part::setkititemstatus(int kititem,int Penabled_){ +void Part::setkititemstatus(int kititem,int Penabled_) +{ if ((kititem==0)&&(kititem>=NUM_KIT_ITEMS)) return;//nonexistent kit item and the first kit item is always enabled kit[kititem].Penabled=Penabled_; - + bool resetallnotes=false; - if (Penabled_==0){ - if (kit[kititem].adpars!=NULL) delete (kit[kititem].adpars); - if (kit[kititem].subpars!=NULL) delete (kit[kititem].subpars); - if (kit[kititem].padpars!=NULL) { - delete (kit[kititem].padpars); - resetallnotes=true; - }; - kit[kititem].adpars=NULL;kit[kititem].subpars=NULL;kit[kititem].padpars=NULL; - kit[kititem].Pname[0]='\0'; + if (Penabled_==0) { + if (kit[kititem].adpars!=NULL) delete (kit[kititem].adpars); + if (kit[kititem].subpars!=NULL) delete (kit[kititem].subpars); + if (kit[kititem].padpars!=NULL) { + delete (kit[kititem].padpars); + resetallnotes=true; + }; + kit[kititem].adpars=NULL; + kit[kititem].subpars=NULL; + kit[kititem].padpars=NULL; + kit[kititem].Pname[0]='\0'; } else { - if (kit[kititem].adpars==NULL) kit[kititem].adpars=new ADnoteParameters(fft); - if (kit[kititem].subpars==NULL) kit[kititem].subpars=new SUBnoteParameters(); - if (kit[kititem].padpars==NULL) kit[kititem].padpars=new PADnoteParameters(fft,mutex); + if (kit[kititem].adpars==NULL) kit[kititem].adpars=new ADnoteParameters(fft); + if (kit[kititem].subpars==NULL) kit[kititem].subpars=new SUBnoteParameters(); + if (kit[kititem].padpars==NULL) kit[kititem].padpars=new PADnoteParameters(fft,mutex); }; - + if (resetallnotes) for (int k=0;k<POLIPHONY;k++) KillNotePos(k); }; -void Part::add2XMLinstrument(XMLwrapper *xml){ +void Part::add2XMLinstrument(XMLwrapper *xml) +{ xml->beginbranch("INFO"); - xml->addparstr("name",(char *)Pname); - xml->addparstr("author",(char *)info.Pauthor); - xml->addparstr("comments",(char *)info.Pcomments); - xml->addpar("type",info.Ptype); + xml->addparstr("name",(char *)Pname); + xml->addparstr("author",(char *)info.Pauthor); + xml->addparstr("comments",(char *)info.Pcomments); + xml->addpar("type",info.Ptype); xml->endbranch(); - - + + xml->beginbranch("INSTRUMENT_KIT"); - xml->addpar("kit_mode",Pkitmode); - xml->addparbool("drum_mode",Pdrummode); - - for (int i=0;i<NUM_KIT_ITEMS;i++){ - xml->beginbranch("INSTRUMENT_KIT_ITEM",i); - xml->addparbool("enabled",kit[i].Penabled); - if (kit[i].Penabled!=0) { - xml->addparstr("name",(char *)kit[i].Pname); - - xml->addparbool("muted",kit[i].Pmuted); - xml->addpar("min_key",kit[i].Pminkey); - xml->addpar("max_key",kit[i].Pmaxkey); - - xml->addpar("send_to_instrument_effect",kit[i].Psendtoparteffect); - - xml->addparbool("add_enabled",kit[i].Padenabled); - if ((kit[i].Padenabled!=0)&&(kit[i].adpars!=NULL)){ - xml->beginbranch("ADD_SYNTH_PARAMETERS"); - kit[i].adpars->add2XML(xml); - xml->endbranch(); - }; - - xml->addparbool("sub_enabled",kit[i].Psubenabled); - if ((kit[i].Psubenabled!=0)&&(kit[i].subpars!=NULL)){ - xml->beginbranch("SUB_SYNTH_PARAMETERS"); - kit[i].subpars->add2XML(xml); - xml->endbranch(); - }; - - xml->addparbool("pad_enabled",kit[i].Ppadenabled); - if ((kit[i].Ppadenabled!=0)&&(kit[i].padpars!=NULL)){ - xml->beginbranch("PAD_SYNTH_PARAMETERS"); - kit[i].padpars->add2XML(xml); - xml->endbranch(); - }; - - }; - xml->endbranch(); - }; + xml->addpar("kit_mode",Pkitmode); + xml->addparbool("drum_mode",Pdrummode); + + for (int i=0;i<NUM_KIT_ITEMS;i++) { + xml->beginbranch("INSTRUMENT_KIT_ITEM",i); + xml->addparbool("enabled",kit[i].Penabled); + if (kit[i].Penabled!=0) { + xml->addparstr("name",(char *)kit[i].Pname); + + xml->addparbool("muted",kit[i].Pmuted); + xml->addpar("min_key",kit[i].Pminkey); + xml->addpar("max_key",kit[i].Pmaxkey); + + xml->addpar("send_to_instrument_effect",kit[i].Psendtoparteffect); + + xml->addparbool("add_enabled",kit[i].Padenabled); + if ((kit[i].Padenabled!=0)&&(kit[i].adpars!=NULL)) { + xml->beginbranch("ADD_SYNTH_PARAMETERS"); + kit[i].adpars->add2XML(xml); + xml->endbranch(); + }; + + xml->addparbool("sub_enabled",kit[i].Psubenabled); + if ((kit[i].Psubenabled!=0)&&(kit[i].subpars!=NULL)) { + xml->beginbranch("SUB_SYNTH_PARAMETERS"); + kit[i].subpars->add2XML(xml); + xml->endbranch(); + }; + + xml->addparbool("pad_enabled",kit[i].Ppadenabled); + if ((kit[i].Ppadenabled!=0)&&(kit[i].padpars!=NULL)) { + xml->beginbranch("PAD_SYNTH_PARAMETERS"); + kit[i].padpars->add2XML(xml); + xml->endbranch(); + }; + + }; + xml->endbranch(); + }; xml->endbranch(); - - xml->beginbranch("INSTRUMENT_EFFECTS"); - for (int nefx=0;nefx<NUM_PART_EFX;nefx++){ - xml->beginbranch("INSTRUMENT_EFFECT",nefx); - xml->beginbranch("EFFECT"); - partefx[nefx]->add2XML(xml); - xml->endbranch(); - - xml->addpar("route",Pefxroute[nefx]); - partefx[nefx]->setdryonly(Pefxroute[nefx]==2); - xml->addparbool("bypass",Pefxbypass[nefx]); - xml->endbranch(); + + xml->beginbranch("INSTRUMENT_EFFECTS"); + for (int nefx=0;nefx<NUM_PART_EFX;nefx++) { + xml->beginbranch("INSTRUMENT_EFFECT",nefx); + xml->beginbranch("EFFECT"); + partefx[nefx]->add2XML(xml); + xml->endbranch(); + + xml->addpar("route",Pefxroute[nefx]); + partefx[nefx]->setdryonly(Pefxroute[nefx]==2); + xml->addparbool("bypass",Pefxbypass[nefx]); + xml->endbranch(); }; xml->endbranch(); }; -void Part::add2XML(XMLwrapper *xml){ +void Part::add2XML(XMLwrapper *xml) +{ //parameters xml->addparbool("enabled",Penabled); if ((Penabled==0)&&(xml->minimal)) return; @@ -923,15 +978,16 @@ void Part::add2XML(XMLwrapper *xml){ xml->addpar("key_limit",Pkeylimit); xml->beginbranch("INSTRUMENT"); - add2XMLinstrument(xml); + add2XMLinstrument(xml); xml->endbranch(); - + xml->beginbranch("CONTROLLER"); - ctl.add2XML(xml); + ctl.add2XML(xml); xml->endbranch(); }; -int Part::saveXML(char *filename){ +int Part::saveXML(char *filename) +{ XMLwrapper *xml; xml=new XMLwrapper(); @@ -944,103 +1000,107 @@ int Part::saveXML(char *filename){ return(result); }; -int Part::loadXMLinstrument(const char *filename){ +int Part::loadXMLinstrument(const char *filename) +{ XMLwrapper *xml=new XMLwrapper(); if (xml->loadXMLfile(filename)<0) { - delete(xml); - return(-1); + delete(xml); + return(-1); }; - + if (xml->enterbranch("INSTRUMENT")==0) return(-10); - getfromXMLinstrument(xml); + getfromXMLinstrument(xml); xml->exitbranch(); - + delete(xml); return(0); }; -void Part::applyparameters(){ - for (int n=0;n<NUM_KIT_ITEMS;n++){ - if ((kit[n].padpars!=NULL)&&(kit[n].Ppadenabled!=0)) kit[n].padpars->applyparameters(true); +void Part::applyparameters() +{ + for (int n=0;n<NUM_KIT_ITEMS;n++) { + if ((kit[n].padpars!=NULL)&&(kit[n].Ppadenabled!=0)) kit[n].padpars->applyparameters(true); }; }; -void Part::getfromXMLinstrument(XMLwrapper *xml){ - if (xml->enterbranch("INFO")){ - xml->getparstr("name",(char *)Pname,PART_MAX_NAME_LEN); - xml->getparstr("author",(char *)info.Pauthor,MAX_INFO_TEXT_SIZE); - xml->getparstr("comments",(char *)info.Pcomments,MAX_INFO_TEXT_SIZE); - info.Ptype=xml->getpar("type",info.Ptype,0,16); - - xml->exitbranch(); +void Part::getfromXMLinstrument(XMLwrapper *xml) +{ + if (xml->enterbranch("INFO")) { + xml->getparstr("name",(char *)Pname,PART_MAX_NAME_LEN); + xml->getparstr("author",(char *)info.Pauthor,MAX_INFO_TEXT_SIZE); + xml->getparstr("comments",(char *)info.Pcomments,MAX_INFO_TEXT_SIZE); + info.Ptype=xml->getpar("type",info.Ptype,0,16); + + xml->exitbranch(); }; - if (xml->enterbranch("INSTRUMENT_KIT")){ - Pkitmode=xml->getpar127("kit_mode",Pkitmode); - Pdrummode=xml->getparbool("drum_mode",Pdrummode); - - setkititemstatus(0,0); - for (int i=0;i<NUM_KIT_ITEMS;i++){ - if (xml->enterbranch("INSTRUMENT_KIT_ITEM",i)==0) continue; - setkititemstatus(i,xml->getparbool("enabled",kit[i].Penabled)); - if (kit[i].Penabled==0) { - xml->exitbranch(); - continue; - }; - - xml->getparstr("name",(char *)kit[i].Pname,PART_MAX_NAME_LEN); - - kit[i].Pmuted=xml->getparbool("muted",kit[i].Pmuted); - kit[i].Pminkey=xml->getpar127("min_key",kit[i].Pminkey); - kit[i].Pmaxkey=xml->getpar127("max_key",kit[i].Pmaxkey); - - kit[i].Psendtoparteffect=xml->getpar127("send_to_instrument_effect",kit[i].Psendtoparteffect); - - kit[i].Padenabled=xml->getparbool("add_enabled",kit[i].Padenabled); - if (xml->enterbranch("ADD_SYNTH_PARAMETERS")){ - kit[i].adpars->getfromXML(xml); - xml->exitbranch(); - }; - - kit[i].Psubenabled=xml->getparbool("sub_enabled",kit[i].Psubenabled); - if (xml->enterbranch("SUB_SYNTH_PARAMETERS")){ - kit[i].subpars->getfromXML(xml); - xml->exitbranch(); - }; - - kit[i].Ppadenabled=xml->getparbool("pad_enabled",kit[i].Ppadenabled); - if (xml->enterbranch("PAD_SYNTH_PARAMETERS")){ - kit[i].padpars->getfromXML(xml); - xml->exitbranch(); - }; - - xml->exitbranch(); - }; - - xml->exitbranch(); + if (xml->enterbranch("INSTRUMENT_KIT")) { + Pkitmode=xml->getpar127("kit_mode",Pkitmode); + Pdrummode=xml->getparbool("drum_mode",Pdrummode); + + setkititemstatus(0,0); + for (int i=0;i<NUM_KIT_ITEMS;i++) { + if (xml->enterbranch("INSTRUMENT_KIT_ITEM",i)==0) continue; + setkititemstatus(i,xml->getparbool("enabled",kit[i].Penabled)); + if (kit[i].Penabled==0) { + xml->exitbranch(); + continue; + }; + + xml->getparstr("name",(char *)kit[i].Pname,PART_MAX_NAME_LEN); + + kit[i].Pmuted=xml->getparbool("muted",kit[i].Pmuted); + kit[i].Pminkey=xml->getpar127("min_key",kit[i].Pminkey); + kit[i].Pmaxkey=xml->getpar127("max_key",kit[i].Pmaxkey); + + kit[i].Psendtoparteffect=xml->getpar127("send_to_instrument_effect",kit[i].Psendtoparteffect); + + kit[i].Padenabled=xml->getparbool("add_enabled",kit[i].Padenabled); + if (xml->enterbranch("ADD_SYNTH_PARAMETERS")) { + kit[i].adpars->getfromXML(xml); + xml->exitbranch(); + }; + + kit[i].Psubenabled=xml->getparbool("sub_enabled",kit[i].Psubenabled); + if (xml->enterbranch("SUB_SYNTH_PARAMETERS")) { + kit[i].subpars->getfromXML(xml); + xml->exitbranch(); + }; + + kit[i].Ppadenabled=xml->getparbool("pad_enabled",kit[i].Ppadenabled); + if (xml->enterbranch("PAD_SYNTH_PARAMETERS")) { + kit[i].padpars->getfromXML(xml); + xml->exitbranch(); + }; + + xml->exitbranch(); + }; + + xml->exitbranch(); }; - - if (xml->enterbranch("INSTRUMENT_EFFECTS")){ - for (int nefx=0;nefx<NUM_PART_EFX;nefx++){ - if (xml->enterbranch("INSTRUMENT_EFFECT",nefx)==0) continue; - if (xml->enterbranch("EFFECT")){ - partefx[nefx]->getfromXML(xml); - xml->exitbranch(); - }; - - Pefxroute[nefx]=xml->getpar("route",Pefxroute[nefx],0,NUM_PART_EFX); - partefx[nefx]->setdryonly(Pefxroute[nefx]==2); - Pefxbypass[nefx]=xml->getparbool("bypass",Pefxbypass[nefx]); - xml->exitbranch(); - }; - xml->exitbranch(); - }; + + if (xml->enterbranch("INSTRUMENT_EFFECTS")) { + for (int nefx=0;nefx<NUM_PART_EFX;nefx++) { + if (xml->enterbranch("INSTRUMENT_EFFECT",nefx)==0) continue; + if (xml->enterbranch("EFFECT")) { + partefx[nefx]->getfromXML(xml); + xml->exitbranch(); + }; + + Pefxroute[nefx]=xml->getpar("route",Pefxroute[nefx],0,NUM_PART_EFX); + partefx[nefx]->setdryonly(Pefxroute[nefx]==2); + Pefxbypass[nefx]=xml->getparbool("bypass",Pefxbypass[nefx]); + xml->exitbranch(); + }; + xml->exitbranch(); + }; }; -void Part::getfromXML(XMLwrapper *xml){ +void Part::getfromXML(XMLwrapper *xml) +{ Penabled=xml->getparbool("enabled",Penabled); setPvolume(xml->getpar127("volume",Pvolume)); @@ -1061,14 +1121,14 @@ void Part::getfromXML(XMLwrapper *xml){ Pkeylimit=xml->getpar127("key_limit",Pkeylimit); - if (xml->enterbranch("INSTRUMENT")){ - getfromXMLinstrument(xml); + if (xml->enterbranch("INSTRUMENT")) { + getfromXMLinstrument(xml); xml->exitbranch(); }; - - if (xml->enterbranch("CONTROLLER")){ - ctl.getfromXML(xml); - xml->exitbranch(); + + if (xml->enterbranch("CONTROLLER")) { + ctl.getfromXML(xml); + xml->exitbranch(); }; }; diff --git a/src/Misc/Part.h b/src/Misc/Part.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Part.h - Part implementation Copyright (C) 2002-2005 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 + 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, @@ -41,145 +41,146 @@ #include <list> // For the monomemnotes list. /** Part implementation*/ -class Part{ - - public: - /**Constructor - * @param microtonal_ Pointer to the microtonal object - * @param fft_ Pointer to the FFTwrapper - * @param mutex_ Pointer to the master pthread_mutex_t*/ - Part(Microtonal *microtonal_,FFTwrapper *fft_,pthread_mutex_t *mutex_); - /**Destructor*/ - ~Part(); - - // Midi commands implemented - void NoteOn(unsigned char note,unsigned char velocity,int masterkeyshift); - void NoteOff(unsigned char note); - void AllNotesOff();//panic - void SetController(unsigned int type,int par); - void RelaseSustainedKeys();//this is called when the sustain pedal is relased - void RelaseAllKeys();//this is called on AllNotesOff controller - - /* The synthesizer part output */ - void ComputePartSmps();//Part output - - //instrumentonly: 0 - save all, 1 - save only instrumnet, 2 - save only instrument without the name(used in bank) - - - //saves the instrument settings to a XML file - //returns 0 for ok or <0 if there is an error - int saveXML(char *filename); - int loadXMLinstrument(const char *filename); - - void add2XML(XMLwrapper *xml); - void add2XMLinstrument(XMLwrapper *xml); - - void defaults(); - void defaultsinstrument(); - - void applyparameters(); - - void getfromXML(XMLwrapper *xml); - void getfromXMLinstrument(XMLwrapper *xml); - - void cleanup(); +class Part +{ + +public: + /**Constructor + * @param microtonal_ Pointer to the microtonal object + * @param fft_ Pointer to the FFTwrapper + * @param mutex_ Pointer to the master pthread_mutex_t*/ + Part(Microtonal *microtonal_,FFTwrapper *fft_,pthread_mutex_t *mutex_); + /**Destructor*/ + ~Part(); + + // Midi commands implemented + void NoteOn(unsigned char note,unsigned char velocity,int masterkeyshift); + void NoteOff(unsigned char note); + void AllNotesOff();//panic + void SetController(unsigned int type,int par); + void RelaseSustainedKeys();//this is called when the sustain pedal is relased + void RelaseAllKeys();//this is called on AllNotesOff controller + + /* The synthesizer part output */ + void ComputePartSmps();//Part output + + //instrumentonly: 0 - save all, 1 - save only instrumnet, 2 - save only instrument without the name(used in bank) + + + //saves the instrument settings to a XML file + //returns 0 for ok or <0 if there is an error + int saveXML(char *filename); + int loadXMLinstrument(const char *filename); + + void add2XML(XMLwrapper *xml); + void add2XMLinstrument(XMLwrapper *xml); + + void defaults(); + void defaultsinstrument(); + + void applyparameters(); + + void getfromXML(XMLwrapper *xml); + void getfromXMLinstrument(XMLwrapper *xml); + + void cleanup(); // ADnoteParameters *ADPartParameters; // SUBnoteParameters *SUBPartParameters; - //the part's kit - struct { + //the part's kit + struct { unsigned char Penabled,Pmuted,Pminkey,Pmaxkey; - unsigned char *Pname; - unsigned char Padenabled,Psubenabled,Ppadenabled; - unsigned char Psendtoparteffect; + unsigned char *Pname; + unsigned char Padenabled,Psubenabled,Ppadenabled; + unsigned char Psendtoparteffect; ADnoteParameters *adpars; SUBnoteParameters *subpars; PADnoteParameters *padpars; - } kit[NUM_KIT_ITEMS]; - - - //Part parameters - void setkeylimit(unsigned char Pkeylimit); - void setkititemstatus(int kititem,int Penabled_); - - unsigned char Penabled;/**<if the part is enabled*/ - unsigned char Pvolume;/**<part volume*/ - unsigned char Pminkey;/**<the minimum key that the part receives noteon messages*/ - unsigned char Pmaxkey;//the maximum key that the part receives noteon messages - void setPvolume(char Pvolume); - unsigned char Pkeyshift;//Part keyshift - unsigned char Prcvchn;//from what midi channel it receive commnads - unsigned char Ppanning;//part panning - void setPpanning(char Ppanning); - unsigned char Pvelsns;//velocity sensing (amplitude velocity scale) - unsigned char Pveloffs;//velocity offset - unsigned char Pnoteon;//if the part receives NoteOn messages - unsigned char Pkitmode;//if the kitmode is enabled - unsigned char Pdrummode;//if all keys are mapped and the system is 12tET (used for drums) - - unsigned char Ppolymode;//Part mode - 0=monophonic , 1=polyphonic - unsigned char Plegatomode;// 0=normal, 1=legato - unsigned char Pkeylimit;//how many keys are alowed to be played same time (0=off), the older will be relased - - unsigned char *Pname; //name of the instrument - struct{//instrument additional information - unsigned char Ptype; - unsigned char Pauthor[MAX_INFO_TEXT_SIZE+1]; - unsigned char Pcomments[MAX_INFO_TEXT_SIZE+1]; - } info; - - - REALTYPE *partoutl;//Left channel output of the part - REALTYPE *partoutr;//Right channel output of the part - - REALTYPE *partfxinputl[NUM_PART_EFX+1],*partfxinputr[NUM_PART_EFX+1];//Left and right signal that pass thru part effects; partfxinput l/r [NUM_PART_EFX] is for "no effect" buffer - - enum NoteStatus{KEY_OFF,KEY_PLAYING,KEY_RELASED_AND_SUSTAINED,KEY_RELASED}; - - REALTYPE volume,oldvolumel,oldvolumer;//this is applied by Master - REALTYPE panning;//this is applied by Master, too - - Controller ctl;//Part controllers - - EffectMgr *partefx[NUM_PART_EFX];//insertion part effects (they are part of the instrument) - unsigned char Pefxroute[NUM_PART_EFX];//how the effect's output is routed(to next effect/to out) - bool Pefxbypass[NUM_PART_EFX];//if the effects are bypassed - - - pthread_mutex_t *mutex; - - int lastnote; - - private: - void KillNotePos(int pos); - void RelaseNotePos(int pos); - void MonoMemRenote(); // MonoMem stuff. - - int killallnotes;//is set to 1 if I want to kill all notes - - struct PartNotes{ + } kit[NUM_KIT_ITEMS]; + + + //Part parameters + void setkeylimit(unsigned char Pkeylimit); + void setkititemstatus(int kititem,int Penabled_); + + unsigned char Penabled;/**<if the part is enabled*/ + unsigned char Pvolume;/**<part volume*/ + unsigned char Pminkey;/**<the minimum key that the part receives noteon messages*/ + unsigned char Pmaxkey;//the maximum key that the part receives noteon messages + void setPvolume(char Pvolume); + unsigned char Pkeyshift;//Part keyshift + unsigned char Prcvchn;//from what midi channel it receive commnads + unsigned char Ppanning;//part panning + void setPpanning(char Ppanning); + unsigned char Pvelsns;//velocity sensing (amplitude velocity scale) + unsigned char Pveloffs;//velocity offset + unsigned char Pnoteon;//if the part receives NoteOn messages + unsigned char Pkitmode;//if the kitmode is enabled + unsigned char Pdrummode;//if all keys are mapped and the system is 12tET (used for drums) + + unsigned char Ppolymode;//Part mode - 0=monophonic , 1=polyphonic + unsigned char Plegatomode;// 0=normal, 1=legato + unsigned char Pkeylimit;//how many keys are alowed to be played same time (0=off), the older will be relased + + unsigned char *Pname; //name of the instrument + struct {//instrument additional information + unsigned char Ptype; + unsigned char Pauthor[MAX_INFO_TEXT_SIZE+1]; + unsigned char Pcomments[MAX_INFO_TEXT_SIZE+1]; + } info; + + + REALTYPE *partoutl;//Left channel output of the part + REALTYPE *partoutr;//Right channel output of the part + + REALTYPE *partfxinputl[NUM_PART_EFX+1],*partfxinputr[NUM_PART_EFX+1];//Left and right signal that pass thru part effects; partfxinput l/r [NUM_PART_EFX] is for "no effect" buffer + + enum NoteStatus {KEY_OFF,KEY_PLAYING,KEY_RELASED_AND_SUSTAINED,KEY_RELASED}; + + REALTYPE volume,oldvolumel,oldvolumer;//this is applied by Master + REALTYPE panning;//this is applied by Master, too + + Controller ctl;//Part controllers + + EffectMgr *partefx[NUM_PART_EFX];//insertion part effects (they are part of the instrument) + unsigned char Pefxroute[NUM_PART_EFX];//how the effect's output is routed(to next effect/to out) + bool Pefxbypass[NUM_PART_EFX];//if the effects are bypassed + + + pthread_mutex_t *mutex; + + int lastnote; + +private: + void KillNotePos(int pos); + void RelaseNotePos(int pos); + void MonoMemRenote(); // MonoMem stuff. + + int killallnotes;//is set to 1 if I want to kill all notes + + struct PartNotes { NoteStatus status; int note;//if there is no note playing, the "note"=-1 - int itemsplaying; - struct { - ADnote *adnote; - SUBnote *subnote; - PADnote *padnote; - int sendtoparteffect; - } kititem[NUM_KIT_ITEMS]; - int time; - }; - - int lastpos, lastposb; // To keep track of previously used pos and posb. - bool lastlegatomodevalid; // To keep track of previous legatomodevalid. - - // MonoMem stuff - std::list<unsigned char> monomemnotes; // A list to remember held notes. - struct { - unsigned char velocity; - int mkeyshift;// I'm not sure masterkeyshift should be remembered. - } monomem[256]; /* 256 is to cover all possible note values. + int itemsplaying; + struct { + ADnote *adnote; + SUBnote *subnote; + PADnote *padnote; + int sendtoparteffect; + } kititem[NUM_KIT_ITEMS]; + int time; + }; + + int lastpos, lastposb; // To keep track of previously used pos and posb. + bool lastlegatomodevalid; // To keep track of previous legatomodevalid. + + // MonoMem stuff + std::list<unsigned char> monomemnotes; // A list to remember held notes. + struct { + unsigned char velocity; + int mkeyshift;// I'm not sure masterkeyshift should be remembered. + } monomem[256]; /* 256 is to cover all possible note values. monomem[] is used in conjunction with the list to store the velocity and masterkeyshift values of a given note (the list only store note values). @@ -187,14 +188,14 @@ class Part{ velocity value of the note 'note'. */ - PartNotes partnote[POLIPHONY]; - - REALTYPE *tmpoutl;//used to get the note - REALTYPE *tmpoutr; - - REALTYPE oldfreq;//this is used for portamento - Microtonal *microtonal; - FFTwrapper *fft; + PartNotes partnote[POLIPHONY]; + + REALTYPE *tmpoutl;//used to get the note + REALTYPE *tmpoutr; + + REALTYPE oldfreq;//this is used for portamento + Microtonal *microtonal; + FFTwrapper *fft; }; #endif diff --git a/src/Misc/Stereo.C b/src/Misc/Stereo.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Stereo.C - Object for storing a pair of objects Copyright (C) 2009-2009 Mark McCurry Author: Mark McCurry 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 + 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, @@ -21,12 +21,12 @@ template <class T> Stereo<T>::Stereo(const T &left, const T &right) - :leftChannel(left),rightChannel(right) + :leftChannel(left),rightChannel(right) {} template <class T> Stereo<T>::Stereo(const T &val) - :leftChannel(val),rightChannel(val) + :leftChannel(val),rightChannel(val) {} template <class T> diff --git a/src/Misc/Stereo.h b/src/Misc/Stereo.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Stereo.h - Object for storing a pair of objects Copyright (C) 2009-2009 Mark McCurry Author: Mark McCurry 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 + 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, @@ -22,27 +22,44 @@ #define STEREO_H template <class T> -class Stereo{ - public: - Stereo(const T &left,const T &right); - - /**Initializes Stereo with left and right set to val - * @param val the value for both channels*/ - Stereo(const T &val); - ~Stereo(){}; - - void operator=(const Stereo<T> &smp); - T &left(){return leftChannel;}; - T &right(){return rightChannel;}; - T &l(){return leftChannel;}; - T &r(){return rightChannel;}; - const T &left()const{return leftChannel;}; - const T &right()const{return rightChannel;}; - const T &l()const{return leftChannel;}; - const T &r()const{return rightChannel;}; - private: - T leftChannel; - T rightChannel; +class Stereo +{ +public: + Stereo(const T &left,const T &right); + + /**Initializes Stereo with left and right set to val + * @param val the value for both channels*/ + Stereo(const T &val); + ~Stereo() {}; + + void operator=(const Stereo<T> &smp); + T &left() { + return leftChannel; + }; + T &right() { + return rightChannel; + }; + T &l() { + return leftChannel; + }; + T &r() { + return rightChannel; + }; + const T &left()const { + return leftChannel; + }; + const T &right()const { + return rightChannel; + }; + const T &l()const { + return leftChannel; + }; + const T &r()const { + return rightChannel; + }; +private: + T leftChannel; + T rightChannel; }; #include "Stereo.C" diff --git a/src/Misc/Util.C b/src/Misc/Util.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Util.C - Miscellaneous functions Copyright (C) 2002-2005 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 + 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, @@ -42,17 +42,19 @@ REALTYPE *denormalkillbuf; /* * Transform the velocity according the scaling parameter (velocity sensing) */ -REALTYPE VelF(REALTYPE velocity,unsigned char scaling){ +REALTYPE VelF(REALTYPE velocity,unsigned char scaling) +{ REALTYPE x; x=pow(VELOCITY_MAX_SCALE,(64.0-scaling)/64.0); if ((scaling==127)||(velocity>0.99)) return(1.0); - else return(pow(velocity,x)); + else return(pow(velocity,x)); }; /* - * Get the detune in cents + * Get the detune in cents */ -REALTYPE getdetune(unsigned char type,unsigned short int coarsedetune,unsigned short int finedetune){ +REALTYPE getdetune(unsigned char type,unsigned short int coarsedetune,unsigned short int finedetune) +{ REALTYPE det=0.0,octdet=0.0,cdet=0.0,findet=0.0; //Get Octave int octave=coarsedetune/1024; @@ -62,49 +64,57 @@ REALTYPE getdetune(unsigned char type,unsigned short int coarsedetune,unsigned s //Coarse and fine detune int cdetune=coarsedetune%1024; if (cdetune>512) cdetune-=1024; - + int fdetune=finedetune-8192; - switch (type){ + switch (type) { // case 1: is used for the default (see below) - case 2: cdet=fabs(cdetune*10.0); - findet=fabs(fdetune/8192.0)*10.0; - break; - case 3: cdet=fabs(cdetune*100); - findet=pow(10,fabs(fdetune/8192.0)*3.0)/10.0-0.1; - break; - case 4: cdet=fabs(cdetune*701.95500087);//perfect fifth - findet=(pow(2,fabs(fdetune/8192.0)*12.0)-1.0)/4095*1200; - break; - //case ...: need to update N_DETUNE_TYPES, if you'll add more - default:cdet=fabs(cdetune*50.0); - findet=fabs(fdetune/8192.0)*35.0;//almost like "Paul's Sound Designer 2" - break; + case 2: + cdet=fabs(cdetune*10.0); + findet=fabs(fdetune/8192.0)*10.0; + break; + case 3: + cdet=fabs(cdetune*100); + findet=pow(10,fabs(fdetune/8192.0)*3.0)/10.0-0.1; + break; + case 4: + cdet=fabs(cdetune*701.95500087);//perfect fifth + findet=(pow(2,fabs(fdetune/8192.0)*12.0)-1.0)/4095*1200; + break; + //case ...: need to update N_DETUNE_TYPES, if you'll add more + default: + cdet=fabs(cdetune*50.0); + findet=fabs(fdetune/8192.0)*35.0;//almost like "Paul's Sound Designer 2" + break; }; if (finedetune<8192) findet=-findet; if (cdetune<0) cdet=-cdet; - + det=octdet+cdet+findet; return(det); }; -bool fileexists(const char *filename){ +bool fileexists(const char *filename) +{ struct stat tmp; int result=stat(filename,&tmp); if (result>=0) return(true); - + return(false); }; -void newFFTFREQS(FFTFREQS *f,int size){ +void newFFTFREQS(FFTFREQS *f,int size) +{ f->c=new REALTYPE[size]; f->s=new REALTYPE[size]; - for (int i=0;i<size;i++){ - f->c[i]=0.0;f->s[i]=0.0; + for (int i=0;i<size;i++) { + f->c[i]=0.0; + f->s[i]=0.0; }; }; -void deleteFFTFREQS(FFTFREQS *f){ +void deleteFFTFREQS(FFTFREQS *f) +{ delete[] f->c; delete[] f->s; f->c=f->s=NULL; diff --git a/src/Misc/Util.h b/src/Misc/Util.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Util.h - Miscellaneous functions Copyright (C) 2002-2005 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 + 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, diff --git a/src/Misc/XMLwrapper.C b/src/Misc/XMLwrapper.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + XMLwrapper.C - XML wrapper Copyright (C) 2003-2005 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 + 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, @@ -33,40 +33,42 @@ using namespace std; int xml_k=0; char tabs[STACKSIZE+2]; -const char *XMLwrapper_whitespace_callback(mxml_node_t *node,int where){ +const char *XMLwrapper_whitespace_callback(mxml_node_t *node,int where) +{ const char *name=node->value.element.name; if ((where==MXML_WS_BEFORE_OPEN)&&(!strcmp(name,"?xml"))) return(NULL); if ((where==MXML_WS_BEFORE_CLOSE)&&(!strcmp(name,"string"))) return(NULL); if ((where==MXML_WS_BEFORE_OPEN)||(where==MXML_WS_BEFORE_CLOSE)) { -/* const char *tmp=node->value.element.name; - if (tmp!=NULL) { - if ((strstr(tmp,"par")!=tmp)&&(strstr(tmp,"string")!=tmp)) { - printf("%s ",tmp); - if (where==MXML_WS_BEFORE_OPEN) xml_k++; - if (where==MXML_WS_BEFORE_CLOSE) xml_k--; - if (xml_k>=STACKSIZE) xml_k=STACKSIZE-1; - if (xml_k<0) xml_k=0; - printf("%d\n",xml_k); - printf("\n"); - }; - - }; - int i=0; - for (i=1;i<xml_k;i++) tabs[i]='\t'; - tabs[0]='\n';tabs[i+1]='\0'; - if (where==MXML_WS_BEFORE_OPEN) return(tabs); - else return("\n"); -*/ - return("\n"); + /* const char *tmp=node->value.element.name; + if (tmp!=NULL) { + if ((strstr(tmp,"par")!=tmp)&&(strstr(tmp,"string")!=tmp)) { + printf("%s ",tmp); + if (where==MXML_WS_BEFORE_OPEN) xml_k++; + if (where==MXML_WS_BEFORE_CLOSE) xml_k--; + if (xml_k>=STACKSIZE) xml_k=STACKSIZE-1; + if (xml_k<0) xml_k=0; + printf("%d\n",xml_k); + printf("\n"); + }; + + }; + int i=0; + for (i=1;i<xml_k;i++) tabs[i]='\t'; + tabs[0]='\n';tabs[i+1]='\0'; + if (where==MXML_WS_BEFORE_OPEN) return(tabs); + else return("\n"); + */ + return("\n"); }; - + return(0); }; -XMLwrapper::XMLwrapper(){ +XMLwrapper::XMLwrapper() +{ ZERO(&parentstack,(int)sizeof(parentstack)); ZERO(&values,(int)sizeof(values)); @@ -74,50 +76,53 @@ XMLwrapper::XMLwrapper(){ stackpos=0; information.PADsynth_used=false; - + tree=mxmlNewElement(MXML_NO_PARENT,"?xml version=\"1.0\" encoding=\"UTF-8\"?"); -/* for mxml 2.1 (and older) - tree=mxmlNewElement(MXML_NO_PARENT,"?xml"); - mxmlElementSetAttr(tree,"version","1.0"); - mxmlElementSetAttr(tree,"encoding","UTF-8"); -*/ - + /* for mxml 2.1 (and older) + tree=mxmlNewElement(MXML_NO_PARENT,"?xml"); + mxmlElementSetAttr(tree,"version","1.0"); + mxmlElementSetAttr(tree,"encoding","UTF-8"); + */ + mxml_node_t *doctype=mxmlNewElement(tree,"!DOCTYPE"); mxmlElementSetAttr(doctype,"ZynAddSubFX-data",NULL); node=root=mxmlNewElement(tree,"ZynAddSubFX-data"); - + mxmlElementSetAttr(root,"version-major","1"); mxmlElementSetAttr(root,"version-minor","1"); mxmlElementSetAttr(root,"ZynAddSubFX-author","Nasca Octavian Paul"); //make the empty branch that will contain the information parameters info=addparams0("INFORMATION"); - + //save zynaddsubfx specifications beginbranch("BASE_PARAMETERS"); - addpar("max_midi_parts",NUM_MIDI_PARTS); - addpar("max_kit_items_per_instrument",NUM_KIT_ITEMS); + addpar("max_midi_parts",NUM_MIDI_PARTS); + addpar("max_kit_items_per_instrument",NUM_KIT_ITEMS); - addpar("max_system_effects",NUM_SYS_EFX); - addpar("max_insertion_effects",NUM_INS_EFX); - addpar("max_instrument_effects",NUM_PART_EFX); + addpar("max_system_effects",NUM_SYS_EFX); + addpar("max_insertion_effects",NUM_INS_EFX); + addpar("max_instrument_effects",NUM_PART_EFX); - addpar("max_addsynth_voices",NUM_VOICES); + addpar("max_addsynth_voices",NUM_VOICES); endbranch(); }; -XMLwrapper::~XMLwrapper(){ +XMLwrapper::~XMLwrapper() +{ if (tree!=NULL) mxmlDelete(tree); }; -bool XMLwrapper::checkfileinformation(const char *filename){ +bool XMLwrapper::checkfileinformation(const char *filename) +{ stackpos=0; ZERO(&parentstack,(int)sizeof(parentstack)); information.PADsynth_used=false; - if (tree!=NULL) mxmlDelete(tree);tree=NULL; + if (tree!=NULL) mxmlDelete(tree); + tree=NULL; char *xmldata=doloadfile(filename); if (xmldata==NULL) return(-1);//the file could not be loaded or uncompressed @@ -126,31 +131,31 @@ bool XMLwrapper::checkfileinformation(const char *filename){ char *end=strstr(xmldata,"</INFORMATION>"); if ((start==NULL)||(end==NULL)||(start>end)) { - delete []xmldata; - return(false); + delete []xmldata; + return(false); }; end+=strlen("</INFORMATION>"); - end[0]='\0'; - + end[0]='\0'; + tree=mxmlNewElement(MXML_NO_PARENT,"?xml"); node=root=mxmlLoadString(tree,xmldata,MXML_OPAQUE_CALLBACK); if (root==NULL) { - delete []xmldata; - mxmlDelete(tree); - node=root=tree=NULL; - return(false); + delete []xmldata; + mxmlDelete(tree); + node=root=tree=NULL; + return(false); }; root=mxmlFindElement(tree,tree,"INFORMATION",NULL,NULL,MXML_DESCEND); push(root); - if (root==NULL){ - delete []xmldata; - mxmlDelete(tree); - node=root=tree=NULL; - return(false); + if (root==NULL) { + delete []xmldata; + mxmlDelete(tree); + node=root=tree=NULL; + return(false); }; - + information.PADsynth_used=getparbool("PADsynth_used",false); exitbranch(); @@ -164,27 +169,29 @@ bool XMLwrapper::checkfileinformation(const char *filename){ /* SAVE XML members */ -int XMLwrapper::saveXMLfile(const string &filename){ +int XMLwrapper::saveXMLfile(const string &filename) +{ char *xmldata=getXMLdata(); if (xmldata==NULL) return(-2); int compression=config.cfg.GzipCompression; int result=dosavefile(filename.c_str(),compression,xmldata); - - free(xmldata); + + free(xmldata); return(result); }; -char *XMLwrapper::getXMLdata(){ +char *XMLwrapper::getXMLdata() +{ xml_k=0; ZERO(tabs,STACKSIZE+2); - + mxml_node_t *oldnode=node; - + node=info; //Info storing addparbool("PADsynth_used",information.PADsynth_used); - + node=oldnode; char *xmldata=mxmlSaveAllocString(tree,XMLwrapper_whitespace_callback); @@ -192,62 +199,70 @@ char *XMLwrapper::getXMLdata(){ }; -int XMLwrapper::dosavefile(const char *filename,int compression,const char *xmldata){ - if (compression==0){ - FILE *file; - file=fopen(filename,"w"); - if (file==NULL) return(-1); - fputs(xmldata,file); - fclose(file); +int XMLwrapper::dosavefile(const char *filename,int compression,const char *xmldata) +{ + if (compression==0) { + FILE *file; + file=fopen(filename,"w"); + if (file==NULL) return(-1); + fputs(xmldata,file); + fclose(file); } else { - if (compression>9) compression=9; - if (compression<1) compression=1; - char options[10]; - snprintf(options,10,"wb%d",compression); - - gzFile gzfile; - gzfile=gzopen(filename,options); - if (gzfile==NULL) return(-1); - gzputs(gzfile,xmldata); - gzclose(gzfile); + if (compression>9) compression=9; + if (compression<1) compression=1; + char options[10]; + snprintf(options,10,"wb%d",compression); + + gzFile gzfile; + gzfile=gzopen(filename,options); + if (gzfile==NULL) return(-1); + gzputs(gzfile,xmldata); + gzclose(gzfile); }; - + return(0); }; -void XMLwrapper::addpar(const string &name,int val){ +void XMLwrapper::addpar(const string &name,int val) +{ addparams2("par","name",name.c_str(),"value",int2str(val)); }; -void XMLwrapper::addparreal(const string &name,REALTYPE val){ +void XMLwrapper::addparreal(const string &name,REALTYPE val) +{ addparams2("par_real","name",name.c_str(),"value",real2str(val)); }; -void XMLwrapper::addparbool(const string &name,int val){ +void XMLwrapper::addparbool(const string &name,int val) +{ if (val!=0) addparams2("par_bool","name",name.c_str(),"value","yes"); else addparams2("par_bool","name",name.c_str(),"value","no"); }; -void XMLwrapper::addparstr(const string &name,const string &val){ +void XMLwrapper::addparstr(const string &name,const string &val) +{ mxml_node_t *element=mxmlNewElement(node,"string"); mxmlElementSetAttr(element,"name",name.c_str()); mxmlNewText(element,0,val.c_str()); }; -void XMLwrapper::beginbranch(const string &name){ +void XMLwrapper::beginbranch(const string &name) +{ push(node); node=addparams0(name.c_str()); }; -void XMLwrapper::beginbranch(const string &name,int id){ +void XMLwrapper::beginbranch(const string &name,int id) +{ push(node); node=addparams1(name.c_str(),"id",int2str(id)); }; -void XMLwrapper::endbranch(){ +void XMLwrapper::endbranch() +{ node=pop(); }; @@ -255,7 +270,8 @@ void XMLwrapper::endbranch(){ /* LOAD XML members */ -int XMLwrapper::loadXMLfile(const string &filename){ +int XMLwrapper::loadXMLfile(const string &filename) +{ if (tree!=NULL) mxmlDelete(tree); tree=NULL; @@ -264,16 +280,16 @@ int XMLwrapper::loadXMLfile(const string &filename){ stackpos=0; - const char *xmldata=doloadfile(filename.c_str()); + const char *xmldata=doloadfile(filename.c_str()); if (xmldata==NULL) return(-1);//the file could not be loaded or uncompressed - + root=tree=mxmlLoadString(NULL,xmldata,MXML_OPAQUE_CALLBACK); delete []xmldata; if (tree==NULL) return(-2);//this is not XML - - + + node=root=mxmlFindElement(tree,tree,"ZynAddSubFX-data",NULL,NULL,MXML_DESCEND); if (root==NULL) return(-3);//the XML doesnt embbed zynaddsubfx data push(root); @@ -285,51 +301,53 @@ int XMLwrapper::loadXMLfile(const string &filename){ }; -char *XMLwrapper::doloadfile(const string &filename){ +char *XMLwrapper::doloadfile(const string &filename) +{ char *xmldata=NULL; int filesize=-1; - + //try get filesize as gzip data (first) gzFile gzfile=gzopen(filename.c_str(),"rb"); - if (gzfile!=NULL){//this is a gzip file - // first check it's size - while(!gzeof(gzfile)) { - gzseek (gzfile,1024*1024,SEEK_CUR); - if (gztell(gzfile)>10000000) { - gzclose(gzfile); - goto notgzip;//the file is too big - }; - }; - filesize=gztell(gzfile); - - //rewind the file and load the data - xmldata=new char[filesize+1]; - ZERO(xmldata,filesize+1); - - gzrewind(gzfile); - gzread(gzfile,xmldata,filesize); - - gzclose(gzfile); - return (xmldata); + if (gzfile!=NULL) {//this is a gzip file + // first check it's size + while (!gzeof(gzfile)) { + gzseek (gzfile,1024*1024,SEEK_CUR); + if (gztell(gzfile)>10000000) { + gzclose(gzfile); + goto notgzip;//the file is too big + }; + }; + filesize=gztell(gzfile); + + //rewind the file and load the data + xmldata=new char[filesize+1]; + ZERO(xmldata,filesize+1); + + gzrewind(gzfile); + gzread(gzfile,xmldata,filesize); + + gzclose(gzfile); + return (xmldata); } else {//this is not a gzip file - notgzip: - FILE *file=fopen(filename.c_str(),"rb"); - if (file==NULL) return(NULL); - fseek(file,0,SEEK_END); - filesize=ftell(file); - - xmldata=new char [filesize+1]; - ZERO(xmldata,filesize+1); - - rewind(file); - fread(xmldata,filesize,1,file); - - fclose(file); - return(xmldata); - }; -}; - -bool XMLwrapper::putXMLdata(const char *xmldata){ +notgzip: + FILE *file=fopen(filename.c_str(),"rb"); + if (file==NULL) return(NULL); + fseek(file,0,SEEK_END); + filesize=ftell(file); + + xmldata=new char [filesize+1]; + ZERO(xmldata,filesize+1); + + rewind(file); + fread(xmldata,filesize,1,file); + + fclose(file); + return(xmldata); + }; +}; + +bool XMLwrapper::putXMLdata(const char *xmldata) +{ if (tree!=NULL) mxmlDelete(tree); tree=NULL; @@ -339,11 +357,11 @@ bool XMLwrapper::putXMLdata(const char *xmldata){ stackpos=0; if (xmldata==NULL) return (false); - + root=tree=mxmlLoadString(NULL,xmldata,MXML_OPAQUE_CALLBACK); if (tree==NULL) return(false); - + node=root=mxmlFindElement(tree,tree,"ZynAddSubFX-data",NULL,NULL,MXML_DESCEND); if (root==NULL) return (false);; push(root); @@ -353,7 +371,8 @@ bool XMLwrapper::putXMLdata(const char *xmldata){ -int XMLwrapper::enterbranch(const string &name){ +int XMLwrapper::enterbranch(const string &name) +{ node=mxmlFindElement(peek(),peek(),name.c_str(),NULL,NULL,MXML_DESCEND_FIRST); if (node==NULL) return(0); @@ -361,7 +380,8 @@ int XMLwrapper::enterbranch(const string &name){ return(1); }; -int XMLwrapper::enterbranch(const string &name,int id){ +int XMLwrapper::enterbranch(const string &name,int id) +{ snprintf(tmpstr,TMPSTR_SIZE,"%d",id); node=mxmlFindElement(peek(),peek(),name.c_str(),"id",tmpstr,MXML_DESCEND_FIRST); if (node==NULL) return(0); @@ -371,118 +391,133 @@ int XMLwrapper::enterbranch(const string &name,int id){ }; -void XMLwrapper::exitbranch(){ +void XMLwrapper::exitbranch() +{ pop(); }; -int XMLwrapper::getbranchid(int min, int max){ +int XMLwrapper::getbranchid(int min, int max) +{ int id=str2int(mxmlElementGetAttr(node,"id")); if ((min==0)&&(max==0)) return(id); - + if (id<min) id=min; - else if (id>max) id=max; + else if (id>max) id=max; return(id); }; -int XMLwrapper::getpar(const string &name,int defaultpar,int min,int max){ +int XMLwrapper::getpar(const string &name,int defaultpar,int min,int max) +{ node=mxmlFindElement(peek(),peek(),"par","name",name.c_str(),MXML_DESCEND_FIRST); if (node==NULL) return(defaultpar); const char *strval=mxmlElementGetAttr(node,"value"); if (strval==NULL) return(defaultpar); - + int val=str2int(strval); if (val<min) val=min; - else if (val>max) val=max; - + else if (val>max) val=max; + return(val); }; -int XMLwrapper::getpar127(const string &name,int defaultpar){ +int XMLwrapper::getpar127(const string &name,int defaultpar) +{ return(getpar(name,defaultpar,0,127)); }; -int XMLwrapper::getparbool(const string &name,int defaultpar){ +int XMLwrapper::getparbool(const string &name,int defaultpar) +{ node=mxmlFindElement(peek(),peek(),"par_bool","name",name.c_str(),MXML_DESCEND_FIRST); if (node==NULL) return(defaultpar); const char *strval=mxmlElementGetAttr(node,"value"); if (strval==NULL) return(defaultpar); - + if ((strval[0]=='Y')||(strval[0]=='y')) return(1); - else return(0); + else return(0); }; -void XMLwrapper::getparstr(const string &name,char *par,int maxstrlen){ +void XMLwrapper::getparstr(const string &name,char *par,int maxstrlen) +{ ZERO(par,maxstrlen); node=mxmlFindElement(peek(),peek(),"string","name",name.c_str(),MXML_DESCEND_FIRST); - + if (node==NULL) return; if (node->child==NULL) return; if (node->child->type!=MXML_OPAQUE) return; - + snprintf(par,maxstrlen,"%s",node->child->value.element.name); - + }; -REALTYPE XMLwrapper::getparreal(const char *name,REALTYPE defaultpar){ +REALTYPE XMLwrapper::getparreal(const char *name,REALTYPE defaultpar) +{ node=mxmlFindElement(peek(),peek(),"par_real","name",name,MXML_DESCEND_FIRST); if (node==NULL) return(defaultpar); const char *strval=mxmlElementGetAttr(node,"value"); if (strval==NULL) return(defaultpar); - + return(str2real(strval)); }; -REALTYPE XMLwrapper::getparreal(const char *name,REALTYPE defaultpar,REALTYPE min,REALTYPE max){ +REALTYPE XMLwrapper::getparreal(const char *name,REALTYPE defaultpar,REALTYPE min,REALTYPE max) +{ REALTYPE result=getparreal(name,defaultpar); - + if (result<min) result=min; - else if (result>max) result=max; + else if (result>max) result=max; return(result); }; /** Private members **/ -char *XMLwrapper::int2str(int x){ +char *XMLwrapper::int2str(int x) +{ snprintf(tmpstr,TMPSTR_SIZE,"%d",x); return(tmpstr); }; -char *XMLwrapper::real2str(REALTYPE x){ +char *XMLwrapper::real2str(REALTYPE x) +{ snprintf(tmpstr,TMPSTR_SIZE,"%g",x); return(tmpstr); }; -int XMLwrapper::str2int(const char *str){ +int XMLwrapper::str2int(const char *str) +{ if (str==NULL) return(0); int result=strtol(str,NULL,10); return(result); }; -REALTYPE XMLwrapper::str2real(const char *str){ +REALTYPE XMLwrapper::str2real(const char *str) +{ if (str==NULL) return(0.0); REALTYPE result=strtod(str,NULL); return(result); }; -mxml_node_t *XMLwrapper::addparams0(const char *name){ +mxml_node_t *XMLwrapper::addparams0(const char *name) +{ mxml_node_t *element=mxmlNewElement(node,name); return(element); }; -mxml_node_t *XMLwrapper::addparams1(const char *name,const char *par1,const char *val1){ +mxml_node_t *XMLwrapper::addparams1(const char *name,const char *par1,const char *val1) +{ mxml_node_t *element=mxmlNewElement(node,name); mxmlElementSetAttr(element,par1,val1); return(element); }; -mxml_node_t *XMLwrapper::addparams2(const char *name,const char *par1,const char *val1,const char *par2, const char *val2){ +mxml_node_t *XMLwrapper::addparams2(const char *name,const char *par1,const char *val1,const char *par2, const char *val2) +{ mxml_node_t *element=mxmlNewElement(node,name); mxmlElementSetAttr(element,par1,val1); mxmlElementSetAttr(element,par2,val2); @@ -492,21 +527,23 @@ mxml_node_t *XMLwrapper::addparams2(const char *name,const char *par1,const char -void XMLwrapper::push(mxml_node_t *node){ +void XMLwrapper::push(mxml_node_t *node) +{ if (stackpos>=STACKSIZE-1) { - printf("BUG!: XMLwrapper::push() - full parentstack\n"); - return; + printf("BUG!: XMLwrapper::push() - full parentstack\n"); + return; }; stackpos++; parentstack[stackpos]=node; - + // printf("push %d - %s\n",stackpos,node->value.element.name); - + }; -mxml_node_t *XMLwrapper::pop(){ +mxml_node_t *XMLwrapper::pop() +{ if (stackpos<=0) { - printf("BUG!: XMLwrapper::pop() - empty parentstack\n"); - return (root); + printf("BUG!: XMLwrapper::pop() - empty parentstack\n"); + return (root); }; mxml_node_t *node=parentstack[stackpos]; parentstack[stackpos]=NULL; @@ -517,10 +554,11 @@ mxml_node_t *XMLwrapper::pop(){ return(node); }; -mxml_node_t *XMLwrapper::peek(){ +mxml_node_t *XMLwrapper::peek() +{ if (stackpos<=0) { - printf("BUG!: XMLwrapper::peek() - empty parentstack\n"); - return (root); + printf("BUG!: XMLwrapper::peek() - empty parentstack\n"); + return (root); }; return(parentstack[stackpos]); }; diff --git a/src/Misc/XMLwrapper.h b/src/Misc/XMLwrapper.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + XML.h - XML wrapper Copyright (C) 2003-2005 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 + 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, @@ -34,143 +34,144 @@ //the maxim tree depth #define STACKSIZE 100 -class XMLwrapper{ - public: - XMLwrapper(); - ~XMLwrapper(); - - /********************************/ - /* SAVE to XML */ - /********************************/ - - //returns 0 if ok or -1 if the file cannot be saved - int saveXMLfile(const std::string &filename); - - //returns the new allocated string that contains the XML data (used for clipboard) - //the string is NULL terminated - char *getXMLdata(); - - //add simple parameter (name and value) - void addpar(const std::string &name,int val); - void addparreal(const std::string &name,REALTYPE val); - - //add boolean parameter (name and boolean value) - //if the value is 0 => "yes", else "no" - void addparbool(const std::string &name,int val); - - //add string parameter (name and string) - void addparstr(const std::string &name,const std::string &val); - - //add a branch - void beginbranch(const std::string &name); - void beginbranch(const std::string &name, int id); - - //this must be called after each branch (nodes that contains child nodes) - void endbranch(); - - /********************************/ - /* LOAD from XML */ - /********************************/ - - //returns 0 if ok or -1 if the file cannot be loaded - int loadXMLfile(const std::string &filename); - - //used by the clipboard - bool putXMLdata(const char *xmldata); - - //enter into the branch - //returns 1 if is ok, or 0 otherwise - int enterbranch(const std::string &name); - - - //enter into the branch with id - //returns 1 if is ok, or 0 otherwise - int enterbranch(const std::string &name, int id); - - //exits from a branch - void exitbranch(); - - //get the the branch_id and limits it between the min and max - //if min==max==0, it will not limit it - //if there isn't any id, will return min - //this must be called only imediately after enterbranch() - int getbranchid(int min, int max); - - //it returns the parameter and limits it between min and max - //if min==max==0, it will not limit it - //if no parameter will be here, the defaultpar will be returned - int getpar(const std::string &name,int defaultpar,int min,int max); - - //the same as getpar, but the limits are 0 and 127 - int getpar127(const std::string &name,int defaultpar); - - int getparbool(const std::string &name,int defaultpar); - - void getparstr(const std::string &name,char *par,int maxstrlen); - REALTYPE getparreal(const char *name,REALTYPE defaultpar); - REALTYPE getparreal(const char *name,REALTYPE defaultpar,REALTYPE min,REALTYPE max); - - bool minimal;//false if all parameters will be stored (used only for clipboard) - - struct { - bool PADsynth_used; - }information; - - //opens a file and parse only the "information" data on it - //returns "true" if all went ok or "false" on errors - bool checkfileinformation(const char *filename); - - private: - - int dosavefile(const char *filename,int compression,const char *xmldata); - char *doloadfile(const std::string &filename); - - - mxml_node_t *tree;//all xml data - mxml_node_t *root;//xml data used by zynaddsubfx - mxml_node_t *node;//current node - mxml_node_t *info;//this node is used to store the information about the data - - //adds params like this: - // <name> - //returns the node - mxml_node_t *addparams0(const char *name); - - //adds params like this: - // <name par1="val1"> - //returns the node - mxml_node_t *addparams1(const char *name,const char *par1,const char *val1); - - //adds params like this: - // <name par1="val1" par2="val2"> - //returns the node - mxml_node_t *addparams2(const char *name,const char *par1,const char *val1,const char *par2, const char *val2); - - char *int2str(int x); - char *real2str(REALTYPE x); - - int str2int(const char *str); - REALTYPE str2real(const char *str); - - char tmpstr[TMPSTR_SIZE]; - - - //this is used to store the parents - mxml_node_t *parentstack[STACKSIZE]; - int stackpos; - - - void push(mxml_node_t *node); - mxml_node_t *pop(); - mxml_node_t *peek(); - - //theese are used to store the values - struct{ - struct { - int major,minor; - }xml_version; - }values; - +class XMLwrapper +{ +public: + XMLwrapper(); + ~XMLwrapper(); + + /********************************/ + /* SAVE to XML */ + /********************************/ + + //returns 0 if ok or -1 if the file cannot be saved + int saveXMLfile(const std::string &filename); + + //returns the new allocated string that contains the XML data (used for clipboard) + //the string is NULL terminated + char *getXMLdata(); + + //add simple parameter (name and value) + void addpar(const std::string &name,int val); + void addparreal(const std::string &name,REALTYPE val); + + //add boolean parameter (name and boolean value) + //if the value is 0 => "yes", else "no" + void addparbool(const std::string &name,int val); + + //add string parameter (name and string) + void addparstr(const std::string &name,const std::string &val); + + //add a branch + void beginbranch(const std::string &name); + void beginbranch(const std::string &name, int id); + + //this must be called after each branch (nodes that contains child nodes) + void endbranch(); + + /********************************/ + /* LOAD from XML */ + /********************************/ + + //returns 0 if ok or -1 if the file cannot be loaded + int loadXMLfile(const std::string &filename); + + //used by the clipboard + bool putXMLdata(const char *xmldata); + + //enter into the branch + //returns 1 if is ok, or 0 otherwise + int enterbranch(const std::string &name); + + + //enter into the branch with id + //returns 1 if is ok, or 0 otherwise + int enterbranch(const std::string &name, int id); + + //exits from a branch + void exitbranch(); + + //get the the branch_id and limits it between the min and max + //if min==max==0, it will not limit it + //if there isn't any id, will return min + //this must be called only imediately after enterbranch() + int getbranchid(int min, int max); + + //it returns the parameter and limits it between min and max + //if min==max==0, it will not limit it + //if no parameter will be here, the defaultpar will be returned + int getpar(const std::string &name,int defaultpar,int min,int max); + + //the same as getpar, but the limits are 0 and 127 + int getpar127(const std::string &name,int defaultpar); + + int getparbool(const std::string &name,int defaultpar); + + void getparstr(const std::string &name,char *par,int maxstrlen); + REALTYPE getparreal(const char *name,REALTYPE defaultpar); + REALTYPE getparreal(const char *name,REALTYPE defaultpar,REALTYPE min,REALTYPE max); + + bool minimal;//false if all parameters will be stored (used only for clipboard) + + struct { + bool PADsynth_used; + }information; + + //opens a file and parse only the "information" data on it + //returns "true" if all went ok or "false" on errors + bool checkfileinformation(const char *filename); + +private: + + int dosavefile(const char *filename,int compression,const char *xmldata); + char *doloadfile(const std::string &filename); + + + mxml_node_t *tree;//all xml data + mxml_node_t *root;//xml data used by zynaddsubfx + mxml_node_t *node;//current node + mxml_node_t *info;//this node is used to store the information about the data + + //adds params like this: + // <name> + //returns the node + mxml_node_t *addparams0(const char *name); + + //adds params like this: + // <name par1="val1"> + //returns the node + mxml_node_t *addparams1(const char *name,const char *par1,const char *val1); + + //adds params like this: + // <name par1="val1" par2="val2"> + //returns the node + mxml_node_t *addparams2(const char *name,const char *par1,const char *val1,const char *par2, const char *val2); + + char *int2str(int x); + char *real2str(REALTYPE x); + + int str2int(const char *str); + REALTYPE str2real(const char *str); + + char tmpstr[TMPSTR_SIZE]; + + + //this is used to store the parents + mxml_node_t *parentstack[STACKSIZE]; + int stackpos; + + + void push(mxml_node_t *node); + mxml_node_t *pop(); + mxml_node_t *peek(); + + //theese are used to store the values + struct { + struct { + int major,minor; + }xml_version; + }values; + }; #endif diff --git a/src/Output/DSSIaudiooutput.C b/src/Output/DSSIaudiooutput.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + DSSIaudiooutput.C - Audio functions for DSSI Copyright (C) 2002 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 + 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, @@ -20,7 +20,7 @@ */ -//this file contains code used from trivial_synth.c from +//this file contains code used from trivial_synth.c from //the DSSI (published by Steve Harris under public domain) as a template //the code is incomplete #include <string.h> @@ -37,54 +37,58 @@ typedef struct { } TS; -static void cleanupTS(LADSPA_Handle instance){ +static void cleanupTS(LADSPA_Handle instance) +{ free(instance); } static void connectPortTS(LADSPA_Handle instance, unsigned long port, - LADSPA_Data * data){ + LADSPA_Data * data) +{ TS *plugin; plugin = (TS *) instance; switch (port) { case 0: - plugin->outl = data; - break; + plugin->outl = data; + break; case 1: - plugin->outr = data; - break; + plugin->outr = data; + break; } } -const LADSPA_Descriptor *ladspa_descriptor(unsigned long index){ +const LADSPA_Descriptor *ladspa_descriptor(unsigned long index) +{ switch (index) { case 0: - return tsLDescriptor; + return tsLDescriptor; default: - return NULL; + return NULL; } } -const DSSI_Descriptor *dssi_descriptor(unsigned long index){ +const DSSI_Descriptor *dssi_descriptor(unsigned long index) +{ // FILE *a=fopen("/tmp/zzzzz11z","w"); // fprintf(a,"aaaaaaaaaaa TEST\n"); // fclose(a); switch (index) { case 0: - return tsDDescriptor; + return tsDDescriptor; default: - return NULL; + return NULL; } } static LADSPA_Handle instantiateTS(const LADSPA_Descriptor * descriptor, - unsigned long s_rate) + unsigned long s_rate) { TS *plugin_data = (TS *) malloc(sizeof(TS)); -/* for (i=0; i<MIDI_NOTES; i++) { - plugin_data->omega[i] = M_PI * 2.0 / (double)s_rate * - pow(2.0, (i-69.0) / 12.0); - } -*/ + /* for (i=0; i<MIDI_NOTES; i++) { + plugin_data->omega[i] = M_PI * 2.0 / (double)s_rate * + pow(2.0, (i-69.0) / 12.0); + } + */ return (LADSPA_Handle) plugin_data; } @@ -99,7 +103,8 @@ static void activateTS(LADSPA_Handle instance) static void runTS(LADSPA_Handle instance, unsigned long sample_count, - snd_seq_event_t *events, unsigned long event_count){ + snd_seq_event_t *events, unsigned long event_count) +{ TS *plugin_data = (TS *) instance; // LADSPA_Data *const output = plugin_data->output; // LADSPA_Data freq = *(plugin_data->freq); @@ -109,67 +114,70 @@ static void runTS(LADSPA_Handle instance, unsigned long sample_count, unsigned long event_pos; unsigned long note; -/* if (freq < 1.0) { - freq = 440.0f; - } - if (vol < 0.000001) { - vol = 1.0f; - } - - if (event_count > 0) { - printf("trivial_synth: have %ld events\n", event_count); - } - - for (pos = 0, event_pos = 0; pos < sample_count; pos++) { - - while (event_pos < event_count - && pos == events[event_pos].time.tick) { - - printf("trivial_synth: event type %d\n", events[event_pos].type); - - if (events[event_pos].type == SND_SEQ_EVENT_NOTEON) { - data[events[event_pos].data.note.note].amp = - events[event_pos].data.note.velocity / 512.0f; - data[events[event_pos].data.note.note]. - active = events[event_pos].data.note.velocity > 0; - data[events[event_pos].data.note.note]. - phase = 0.0; - } else if (events[event_pos].type == SND_SEQ_EVENT_NOTEOFF) { - data[events[event_pos].data.note.note]. - active = 0; - } - event_pos++; - } - - output[pos] = 0.0f; - for (note = 0; note < MIDI_NOTES; note++) { - if (data[note].active) { - output[pos] += sin(data[note].phase) * data[note].amp * vol; - data[note].phase += plugin_data->omega[note] * freq; - if (data[note].phase > M_PI * 2.0) { - data[note].phase -= M_PI * 2.0; - } - } - } - } - */ + /* if (freq < 1.0) { + freq = 440.0f; + } + if (vol < 0.000001) { + vol = 1.0f; + } + + if (event_count > 0) { + printf("trivial_synth: have %ld events\n", event_count); + } + + for (pos = 0, event_pos = 0; pos < sample_count; pos++) { + + while (event_pos < event_count + && pos == events[event_pos].time.tick) { + + printf("trivial_synth: event type %d\n", events[event_pos].type); + + if (events[event_pos].type == SND_SEQ_EVENT_NOTEON) { + data[events[event_pos].data.note.note].amp = + events[event_pos].data.note.velocity / 512.0f; + data[events[event_pos].data.note.note]. + active = events[event_pos].data.note.velocity > 0; + data[events[event_pos].data.note.note]. + phase = 0.0; + } else if (events[event_pos].type == SND_SEQ_EVENT_NOTEOFF) { + data[events[event_pos].data.note.note]. + active = 0; + } + event_pos++; + } + + output[pos] = 0.0f; + for (note = 0; note < MIDI_NOTES; note++) { + if (data[note].active) { + output[pos] += sin(data[note].phase) * data[note].amp * vol; + data[note].phase += plugin_data->omega[note] * freq; + if (data[note].phase > M_PI * 2.0) { + data[note].phase -= M_PI * 2.0; + } + } + } + } + */ } static void runTSWrapper(LADSPA_Handle instance, - unsigned long sample_count){ + unsigned long sample_count) +{ runTS(instance, sample_count, NULL, 0); } -int getControllerTS(LADSPA_Handle instance, unsigned long port){ +int getControllerTS(LADSPA_Handle instance, unsigned long port) +{ return -1; } -void _init(){ +void _init() +{ char **port_names; LADSPA_PortDescriptor *port_descriptors; LADSPA_PortRangeHint *port_range_hints; - + FILE *a=fopen("/tmp/zzzzzz","w"); fprintf(a,"aaaaaaaaaaa TEST\n"); fclose(a); @@ -177,63 +185,64 @@ void _init(){ tsLDescriptor = (LADSPA_Descriptor *) malloc(sizeof(LADSPA_Descriptor)); if (tsLDescriptor) { - tsLDescriptor->UniqueID = 100; - tsLDescriptor->Label = "ZASF"; - tsLDescriptor->Properties = 0; - tsLDescriptor->Name = "ZynAddSubFX"; - tsLDescriptor->Maker = "Nasca Octavian Paul <[email protected]>"; - tsLDescriptor->Copyright = "GNU General Public License v.2"; - tsLDescriptor->PortCount = 2; - - port_descriptors = (LADSPA_PortDescriptor *) - calloc(tsLDescriptor->PortCount, sizeof - (LADSPA_PortDescriptor)); - tsLDescriptor->PortDescriptors = - (const LADSPA_PortDescriptor *) port_descriptors; - - port_range_hints = (LADSPA_PortRangeHint *) - calloc(tsLDescriptor->PortCount, sizeof - (LADSPA_PortRangeHint)); - tsLDescriptor->PortRangeHints = - (const LADSPA_PortRangeHint *) port_range_hints; - - port_names = (char **) calloc(tsLDescriptor->PortCount, sizeof(char *)); - tsLDescriptor->PortNames = (const char **) port_names; - - port_descriptors[0] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; - port_names[0] = "Output L"; - port_range_hints[0].HintDescriptor = 0; - port_descriptors[1] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; - port_names[1] = "Output R"; - port_range_hints[1].HintDescriptor = 0; - - tsLDescriptor->activate = activateTS; - tsLDescriptor->cleanup = cleanupTS; - tsLDescriptor->connect_port = connectPortTS; - tsLDescriptor->deactivate = NULL; - tsLDescriptor->instantiate = instantiateTS; - tsLDescriptor->run = runTSWrapper; - tsLDescriptor->run_adding = NULL; - tsLDescriptor->set_run_adding_gain = NULL; + tsLDescriptor->UniqueID = 100; + tsLDescriptor->Label = "ZASF"; + tsLDescriptor->Properties = 0; + tsLDescriptor->Name = "ZynAddSubFX"; + tsLDescriptor->Maker = "Nasca Octavian Paul <[email protected]>"; + tsLDescriptor->Copyright = "GNU General Public License v.2"; + tsLDescriptor->PortCount = 2; + + port_descriptors = (LADSPA_PortDescriptor *) + calloc(tsLDescriptor->PortCount, sizeof + (LADSPA_PortDescriptor)); + tsLDescriptor->PortDescriptors = + (const LADSPA_PortDescriptor *) port_descriptors; + + port_range_hints = (LADSPA_PortRangeHint *) + calloc(tsLDescriptor->PortCount, sizeof + (LADSPA_PortRangeHint)); + tsLDescriptor->PortRangeHints = + (const LADSPA_PortRangeHint *) port_range_hints; + + port_names = (char **) calloc(tsLDescriptor->PortCount, sizeof(char *)); + tsLDescriptor->PortNames = (const char **) port_names; + + port_descriptors[0] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; + port_names[0] = "Output L"; + port_range_hints[0].HintDescriptor = 0; + port_descriptors[1] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; + port_names[1] = "Output R"; + port_range_hints[1].HintDescriptor = 0; + + tsLDescriptor->activate = activateTS; + tsLDescriptor->cleanup = cleanupTS; + tsLDescriptor->connect_port = connectPortTS; + tsLDescriptor->deactivate = NULL; + tsLDescriptor->instantiate = instantiateTS; + tsLDescriptor->run = runTSWrapper; + tsLDescriptor->run_adding = NULL; + tsLDescriptor->set_run_adding_gain = NULL; } tsDDescriptor = (DSSI_Descriptor *) malloc(sizeof(DSSI_Descriptor)); if (tsDDescriptor) { - tsDDescriptor->DSSI_API_Version = 1; - tsDDescriptor->LADSPA_Plugin = tsLDescriptor; - tsDDescriptor->configure = NULL; - tsDDescriptor->get_program = NULL; - tsDDescriptor->get_midi_controller_for_port = getControllerTS; - tsDDescriptor->select_program = NULL; - tsDDescriptor->run_synth = runTS; - tsDDescriptor->run_synth_adding = NULL; - tsDDescriptor->run_multiple_synths = NULL; - tsDDescriptor->run_multiple_synths_adding = NULL; + tsDDescriptor->DSSI_API_Version = 1; + tsDDescriptor->LADSPA_Plugin = tsLDescriptor; + tsDDescriptor->configure = NULL; + tsDDescriptor->get_program = NULL; + tsDDescriptor->get_midi_controller_for_port = getControllerTS; + tsDDescriptor->select_program = NULL; + tsDDescriptor->run_synth = runTS; + tsDDescriptor->run_synth_adding = NULL; + tsDDescriptor->run_multiple_synths = NULL; + tsDDescriptor->run_multiple_synths_adding = NULL; } - + }; -void _fini(){ +void _fini() +{ }; diff --git a/src/Output/DSSIaudiooutput.h b/src/Output/DSSIaudiooutput.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + VSTaudiooutput.h - Audio output for VST Copyright (C) 2002 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 + 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, @@ -36,7 +36,7 @@ class VSTSynth:public AudioEffectX{ public: VSTSynth (audioMasterCallback audioMaster); ~VSTSynth(); - + virtual void process (float **inputs, float **outputs, long sampleframes); virtual void processReplacing (float **inputs, float **outputs, long sampleframes); virtual long processEvents(VstEvents *events);//this is used for Midi input @@ -44,9 +44,9 @@ class VSTSynth:public AudioEffectX{ virtual bool getVendorString(char *txt); virtual bool getProductString(char *txt); virtual void resume(); - + virtual long getChunk(void** data,bool isPreset=false); - virtual void setChunk(void *data,long size,bool isPreset=false); + virtual void setChunk(void *data,long size,bool isPreset=false); MasterUI *ui; int Pexitprogram; diff --git a/src/Output/JACK_RTaudiooutput.C b/src/Output/JACK_RTaudiooutput.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + JACKaudiooutput.C - Audio output for JACK Copyright (C) 2002 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 + 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, @@ -26,7 +26,8 @@ #include <unistd.h> -extern "C" { +extern "C" +{ #include <jack/ringbuffer.h> }; #include "JACKaudiooutput.h" @@ -50,89 +51,92 @@ pthread_mutex_t zyn_thread_lock=PTHREAD_MUTEX_INITIALIZER; pthread_t bthr; -bool JACKaudiooutputinit(Master *master_){ +bool JACKaudiooutputinit(Master *master_) +{ jackmaster=master_; jackclient=0; char tmpstr[100]; jackoutl=new REALTYPE [SOUND_BUFFER_SIZE]; jackoutr=new REALTYPE [SOUND_BUFFER_SIZE]; - + int rbbufsize=SOUND_BUFFER_SIZE*sizeof (REALTYPE)*2*2; printf("%d\n",rbbufsize); rb=jack_ringbuffer_create(rbbufsize); for (int i=0;i<rbbufsize;i++) rb->buf[i]=0.0; - for (int i=0;i<15;i++){ - if (i!=0) snprintf(tmpstr,100,"ZynAddSubFX_%d",i); - else snprintf(tmpstr,100,"ZynAddSubFX"); - jackclient=jack_client_new(tmpstr); - if (jackclient!=0) break; + for (int i=0;i<15;i++) { + if (i!=0) snprintf(tmpstr,100,"ZynAddSubFX_%d",i); + else snprintf(tmpstr,100,"ZynAddSubFX"); + jackclient=jack_client_new(tmpstr); + if (jackclient!=0) break; }; if (jackclient==0) { - fprintf(stderr,"\nERROR: Cannot make a jack client (possible reasons: JACK server is not running or jackd is launched by root and zynaddsubfx by another user.).\n\n\n"); - return(false); + fprintf(stderr,"\nERROR: Cannot make a jack client (possible reasons: JACK server is not running or jackd is launched by root and zynaddsubfx by another user.).\n\n\n"); + return(false); }; fprintf(stderr,"Internal SampleRate = %d\nJack Output SampleRate= %d\n",SAMPLE_RATE,jack_get_sample_rate(jackclient)); - if ((unsigned int)jack_get_sample_rate(jackclient)!=(unsigned int) SAMPLE_RATE) - fprintf(stderr,"It is recomanded that the both samplerates to be equal.\n"); - - jack_set_process_callback(jackclient,jackprocess,0); - jack_set_sample_rate_callback(jackclient,jacksrate,0); - jack_on_shutdown(jackclient,jackshutdown,0); - + if ((unsigned int)jack_get_sample_rate(jackclient)!=(unsigned int) SAMPLE_RATE) + fprintf(stderr,"It is recomanded that the both samplerates to be equal.\n"); + + jack_set_process_callback(jackclient,jackprocess,0); + jack_set_sample_rate_callback(jackclient,jacksrate,0); + jack_on_shutdown(jackclient,jackshutdown,0); + outport_left=jack_port_register(jackclient,"out_1", - JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0); + JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0); outport_right=jack_port_register(jackclient,"out_2", - JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0); + JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0); - if (jack_activate(jackclient)){ - fprintf(stderr,"Cannot activate jack client\n"); - return(false); + if (jack_activate(jackclient)) { + fprintf(stderr,"Cannot activate jack client\n"); + return(false); }; pthread_create(&bthr,NULL,thread_blocked,NULL); - + /* jack_connect(jackclient,jack_port_name(outport_left),"alsa_pcm:out_1"); jack_connect(jackclient,jack_port_name(outport_right),"alsa_pcm:out_2"); */ - - return(true); + + return(true); }; -void *thread_blocked(void *arg){ +void *thread_blocked(void *arg) +{ int datasize=SOUND_BUFFER_SIZE*sizeof (REALTYPE); //try to get realtime sched_param sc; sc.sched_priority=50; int err=sched_setscheduler(0,SCHED_FIFO,&sc); - + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); pthread_mutex_lock(&zyn_thread_lock); - while (jackfinish==0){ - while (jack_ringbuffer_write_space(rb)>=datasize){ - pthread_mutex_lock(&jackmaster->mutex); - jackmaster->GetAudioOutSamples(SOUND_BUFFER_SIZE,jack_get_sample_rate(jackclient),jackoutl,jackoutr); - pthread_mutex_unlock(&jackmaster->mutex); - - jack_ringbuffer_write(rb, (char *) jackoutl,datasize); - jack_ringbuffer_write(rb, (char *) jackoutr,datasize); - }; - pthread_cond_wait(&more_data,&zyn_thread_lock); + while (jackfinish==0) { + while (jack_ringbuffer_write_space(rb)>=datasize) { + pthread_mutex_lock(&jackmaster->mutex); + jackmaster->GetAudioOutSamples(SOUND_BUFFER_SIZE,jack_get_sample_rate(jackclient),jackoutl,jackoutr); + pthread_mutex_unlock(&jackmaster->mutex); + + jack_ringbuffer_write(rb, (char *) jackoutl,datasize); + jack_ringbuffer_write(rb, (char *) jackoutr,datasize); + }; + pthread_cond_wait(&more_data,&zyn_thread_lock); }; pthread_mutex_unlock(&zyn_thread_lock); - + return(0); }; -int jackprocess(jack_nframes_t nframes,void *arg){ +int jackprocess(jack_nframes_t nframes,void *arg) +{ jack_default_audio_sample_t *outl=(jack_default_audio_sample_t *) jack_port_get_buffer (outport_left, nframes); jack_default_audio_sample_t *outr=(jack_default_audio_sample_t *) jack_port_get_buffer (outport_right, nframes); @@ -141,42 +145,44 @@ int jackprocess(jack_nframes_t nframes,void *arg){ int data_read=0; - if (jack_ringbuffer_read_space(rb)>=(2*incoming_datasize)){ - if (datasize>incoming_datasize){ - data_read=0; - while (data_read < datasize){ - jack_ringbuffer_read(rb, (char *) outl+data_read,datasize); - jack_ringbuffer_read(rb, (char *) outr+data_read,datasize); - data_read+=incoming_datasize; - }; - } else if (datasize==incoming_datasize){ - jack_ringbuffer_read(rb, (char *) outl,datasize); - jack_ringbuffer_read(rb, (char *) outr,datasize); - } else { - }; - } else {//the ringbuffer is empty or there are too small amount of samples in it - for (int i=0;i<nframes;i++){ - outl[i]=0.0;outr[i]=0.0; - }; - }; -/* if (jack_ringbuffer_read_space(rb)>=datasize){ - jack_ringbuffer_read(rb, (char *) outl,datasize); - jack_ringbuffer_read(rb, (char *) outr,datasize); + if (jack_ringbuffer_read_space(rb)>=(2*incoming_datasize)) { + if (datasize>incoming_datasize) { + data_read=0; + while (data_read < datasize) { + jack_ringbuffer_read(rb, (char *) outl+data_read,datasize); + jack_ringbuffer_read(rb, (char *) outr+data_read,datasize); + data_read+=incoming_datasize; + }; + } else if (datasize==incoming_datasize) { + jack_ringbuffer_read(rb, (char *) outl,datasize); + jack_ringbuffer_read(rb, (char *) outr,datasize); + } else { + }; } else {//the ringbuffer is empty or there are too small amount of samples in it - for (int i=0;i<nframes;i++){ - outl[i]=0.0;outr[i]=0.0; - }; + for (int i=0;i<nframes;i++) { + outl[i]=0.0; + outr[i]=0.0; + }; }; -*/ - if (pthread_mutex_trylock(&zyn_thread_lock)==0){ - pthread_cond_signal(&more_data); - pthread_mutex_unlock(&zyn_thread_lock); + /* if (jack_ringbuffer_read_space(rb)>=datasize){ + jack_ringbuffer_read(rb, (char *) outl,datasize); + jack_ringbuffer_read(rb, (char *) outr,datasize); + } else {//the ringbuffer is empty or there are too small amount of samples in it + for (int i=0;i<nframes;i++){ + outl[i]=0.0;outr[i]=0.0; + }; + }; + */ + if (pthread_mutex_trylock(&zyn_thread_lock)==0) { + pthread_cond_signal(&more_data); + pthread_mutex_unlock(&zyn_thread_lock); }; - + return(0); }; -void JACKfinish(){ +void JACKfinish() +{ jackfinish=1; jack_ringbuffer_free(rb); jack_client_close(jackclient); @@ -186,12 +192,14 @@ void JACKfinish(){ delete(jackoutr); }; -int jacksrate(jack_nframes_t nframes,void *arg){ - +int jacksrate(jack_nframes_t nframes,void *arg) +{ + return(0); }; -void jackshutdown(void *arg){ +void jackshutdown(void *arg) +{ }; diff --git a/src/Output/JACKaudiooutput.C b/src/Output/JACKaudiooutput.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + JACKaudiooutput.C - Audio output for JACK Copyright (C) 2002 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 + 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, @@ -33,125 +33,131 @@ int jackprocess(jack_nframes_t nframes,void *arg); int jacksrate(jack_nframes_t nframes,void *arg); void jackshutdown(void *arg); -bool JACKaudiooutputinit(Master *master_){ +bool JACKaudiooutputinit(Master *master_) +{ jackmaster=master_; jackclient=0; - for (int i=0;i<15;i++){ - if (i!=0) snprintf(jackname,100,"ZynAddSubFX_%d",i); - else snprintf(jackname,100,"ZynAddSubFX"); - jackclient=jack_client_new(jackname); - if (jackclient!=0) break; + for (int i=0;i<15;i++) { + if (i!=0) snprintf(jackname,100,"ZynAddSubFX_%d",i); + else snprintf(jackname,100,"ZynAddSubFX"); + jackclient=jack_client_new(jackname); + if (jackclient!=0) break; }; if (jackclient==0) { - fprintf(stderr,"\nERROR: Cannot make a jack client (possible reasons: JACK server is not running or jackd is launched by root and zynaddsubfx by another user.).\n"); - return(false); + fprintf(stderr,"\nERROR: Cannot make a jack client (possible reasons: JACK server is not running or jackd is launched by root and zynaddsubfx by another user.).\n"); + return(false); }; fprintf(stderr,"Internal SampleRate = %d\nJack Output SampleRate= %d\n",SAMPLE_RATE,jack_get_sample_rate(jackclient)); - if ((unsigned int)jack_get_sample_rate(jackclient)!=(unsigned int) SAMPLE_RATE) - fprintf(stderr,"It is recomanded that the both samplerates to be equal.\n"); - - jack_set_process_callback(jackclient,jackprocess,0); - jack_set_sample_rate_callback(jackclient,jacksrate,0); - jack_on_shutdown(jackclient,jackshutdown,0); - + if ((unsigned int)jack_get_sample_rate(jackclient)!=(unsigned int) SAMPLE_RATE) + fprintf(stderr,"It is recomanded that the both samplerates to be equal.\n"); + + jack_set_process_callback(jackclient,jackprocess,0); + jack_set_sample_rate_callback(jackclient,jacksrate,0); + jack_on_shutdown(jackclient,jackshutdown,0); + outport_left=jack_port_register(jackclient,"out_1", - JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0); + JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0); outport_right=jack_port_register(jackclient,"out_2", - JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0); + JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0); midi_inport=jack_port_register(jackclient,"midi_input", - JACK_DEFAULT_MIDI_TYPE,JackPortIsInput|JackPortIsTerminal,0); + JACK_DEFAULT_MIDI_TYPE,JackPortIsInput|JackPortIsTerminal,0); - if (jack_activate(jackclient)){ - fprintf(stderr,"Cannot activate jack client\n"); - return(false); + if (jack_activate(jackclient)) { + fprintf(stderr,"Cannot activate jack client\n"); + return(false); }; - + /* jack_connect(jackclient,jack_port_name(outport_left),"alsa_pcm:out_1"); jack_connect(jackclient,jack_port_name(outport_right),"alsa_pcm:out_2"); */ - return(true); + return(true); }; -int jackprocess(jack_nframes_t nframes,void *arg){ +int jackprocess(jack_nframes_t nframes,void *arg) +{ jack_default_audio_sample_t *outl=(jack_default_audio_sample_t *) jack_port_get_buffer (outport_left, nframes); jack_default_audio_sample_t *outr=(jack_default_audio_sample_t *) jack_port_get_buffer (outport_right, nframes); if (!pthread_mutex_trylock(&jackmaster->mutex)) { - JACKhandlemidi(nframes); - jackmaster->GetAudioOutSamples(nframes,jack_get_sample_rate(jackclient),outl,outr); - pthread_mutex_unlock(&jackmaster->mutex); - } - else { - memset(outl, 0, sizeof(jack_default_audio_sample_t) * nframes); - memset(outr, 0, sizeof(jack_default_audio_sample_t) * nframes); + JACKhandlemidi(nframes); + jackmaster->GetAudioOutSamples(nframes,jack_get_sample_rate(jackclient),outl,outr); + pthread_mutex_unlock(&jackmaster->mutex); + } else { + memset(outl, 0, sizeof(jack_default_audio_sample_t) * nframes); + memset(outr, 0, sizeof(jack_default_audio_sample_t) * nframes); } - + return(0); }; -void JACKfinish(){ +void JACKfinish() +{ jack_client_close(jackclient); }; -int jacksrate(jack_nframes_t nframes,void *arg){ - +int jacksrate(jack_nframes_t nframes,void *arg) +{ + return(0); }; -void jackshutdown(void *arg){ +void jackshutdown(void *arg) +{ }; -void JACKhandlemidi(unsigned long frames) { - - // We must have the master mutex before we run this function - - // XXX This is really nasty, not only do we lose the sample accuracy of - // JACK MIDI, but any accuracy at all below the buffer size - - void* midi_buf = jack_port_get_buffer(midi_inport, frames); - jack_midi_event_t jack_midi_event; - jack_nframes_t event_index = 0; - unsigned char* midi_data; - unsigned char type, chan; - - while (jack_midi_event_get(&jack_midi_event,midi_buf, event_index++) == 0) { - midi_data = jack_midi_event.buffer; - type = midi_data[0] & 0xF0; - chan = midi_data[0] & 0x0F; - - switch (type) { - - case 0x80: /* note-off */ - jackmaster->NoteOff(chan, midi_data[1]); - break; - - case 0x90: /* note-on */ - jackmaster->NoteOn(chan, midi_data[1], midi_data[2]); - break; - - case 0xB0: /* controller */ - jackmaster->SetController(chan, midi_data[1], midi_data[2]); - break; - - case 0xE0: /* pitch bend */ - jackmaster->SetController(chan, C_pitchwheel, - ((midi_data[2] << 7) | midi_data[1])); - break; - - /* XXX TODO: handle MSB/LSB controllers and RPNs and NRPNs */ - } - } - +void JACKhandlemidi(unsigned long frames) +{ + + // We must have the master mutex before we run this function + + // XXX This is really nasty, not only do we lose the sample accuracy of + // JACK MIDI, but any accuracy at all below the buffer size + + void* midi_buf = jack_port_get_buffer(midi_inport, frames); + jack_midi_event_t jack_midi_event; + jack_nframes_t event_index = 0; + unsigned char* midi_data; + unsigned char type, chan; + + while (jack_midi_event_get(&jack_midi_event,midi_buf, event_index++) == 0) { + midi_data = jack_midi_event.buffer; + type = midi_data[0] & 0xF0; + chan = midi_data[0] & 0x0F; + + switch (type) { + + case 0x80: /* note-off */ + jackmaster->NoteOff(chan, midi_data[1]); + break; + + case 0x90: /* note-on */ + jackmaster->NoteOn(chan, midi_data[1], midi_data[2]); + break; + + case 0xB0: /* controller */ + jackmaster->SetController(chan, midi_data[1], midi_data[2]); + break; + + case 0xE0: /* pitch bend */ + jackmaster->SetController(chan, C_pitchwheel, + ((midi_data[2] << 7) | midi_data[1])); + break; + + /* XXX TODO: handle MSB/LSB controllers and RPNs and NRPNs */ + } + } + } -const char* JACKgetname() { - if (jackclient != NULL) - return jackname; - return NULL; +const char* JACKgetname() +{ + if (jackclient != NULL) + return jackname; + return NULL; } diff --git a/src/Output/JACKaudiooutput.h b/src/Output/JACKaudiooutput.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + JACKaudiooutput.h - Audio output for JACK Copyright (C) 2002 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 + 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, diff --git a/src/Output/OSSaudiooutput.C b/src/Output/OSSaudiooutput.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + OSSaudiooutput.C - Audio output for Open Sound System Copyright (C) 2002-2005 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 + 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, @@ -34,22 +34,23 @@ #include "../globals.h" using namespace std; -OSSaudiooutput::OSSaudiooutput(){ +OSSaudiooutput::OSSaudiooutput() +{ int i; int snd_bitsize=16; snd_fragment=0x00080009;//fragment size (?) snd_stereo=1;//stereo snd_format=AFMT_S16_LE; snd_samplerate=SAMPLE_RATE; - + smps=new short int[SOUND_BUFFER_SIZE*2]; for (i=0;i<SOUND_BUFFER_SIZE*2;i++) smps[i]=0; - + snd_handle=open(config.cfg.LinuxOSSWaveOutDev,O_WRONLY,0); if (snd_handle == -1) { cerr << "ERROR - I can't open the "; cerr << config.cfg.LinuxOSSWaveOutDev << '.'<< endl; - return; + return; }; ioctl(snd_handle,SNDCTL_DSP_RESET,NULL); @@ -58,7 +59,7 @@ OSSaudiooutput::OSSaudiooutput(){ ioctl(snd_handle,SNDCTL_DSP_SPEED,&snd_samplerate); ioctl(snd_handle,SNDCTL_DSP_SAMPLESIZE,&snd_bitsize); ioctl(snd_handle,SNDCTL_DSP_SETFRAGMENT,&snd_fragment); - + }; @@ -66,25 +67,29 @@ OSSaudiooutput::OSSaudiooutput(){ * Output the samples to the soundcard * The samples are bigger than -1.0 and smaller 1.0 */ -void OSSaudiooutput::OSSout(REALTYPE *smp_left,REALTYPE *smp_right){ +void OSSaudiooutput::OSSout(REALTYPE *smp_left,REALTYPE *smp_right) +{ int i; REALTYPE l,r; if (snd_handle<0) return; - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - l=smp_left[i]; - r=smp_right[i]; - - if (l<-1.0) l=-1.0; else if (l>1.0) l=1.0; - if (r<-1.0) r=-1.0; else if (r>1.0) r=1.0; - - smps[i*2]=(short int) (l*32767.0); - smps[i*2+1]=(short int) (r*32767.0); + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + l=smp_left[i]; + r=smp_right[i]; + + if (l<-1.0) l=-1.0; + else if (l>1.0) l=1.0; + if (r<-1.0) r=-1.0; + else if (r>1.0) r=1.0; + + smps[i*2]=(short int) (l*32767.0); + smps[i*2+1]=(short int) (r*32767.0); }; write(snd_handle,smps,SOUND_BUFFER_SIZE*4);// *2 because is 16 bit, again * 2 because is stereo }; -OSSaudiooutput::~OSSaudiooutput(){ +OSSaudiooutput::~OSSaudiooutput() +{ close(snd_handle); delete [] smps; }; diff --git a/src/Output/OSSaudiooutput.h b/src/Output/OSSaudiooutput.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + OSSaudiooutput.h - Audio output for Open Sound System Copyright (C) 2002-2005 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 + 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, @@ -25,22 +25,23 @@ #include "../globals.h" -class OSSaudiooutput{ - public: - OSSaudiooutput(); - ~OSSaudiooutput(); - - //the out is [-1.0 .. 1.0] - /* smp_left[] and smp_right[] has the size of SOUND_BUFFER_SIZE */ - void OSSout(REALTYPE *smp_left,REALTYPE *smp_right); - private: - int snd_handle; - int snd_fragment; - int snd_stereo; - int snd_format; - int snd_samplerate; - - short int *smps;//Samples to be sent to soundcard +class OSSaudiooutput +{ +public: + OSSaudiooutput(); + ~OSSaudiooutput(); + + //the out is [-1.0 .. 1.0] + /* smp_left[] and smp_right[] has the size of SOUND_BUFFER_SIZE */ + void OSSout(REALTYPE *smp_left,REALTYPE *smp_right); +private: + int snd_handle; + int snd_fragment; + int snd_stereo; + int snd_format; + int snd_samplerate; + + short int *smps;//Samples to be sent to soundcard }; #endif diff --git a/src/Output/PAaudiooutput.C b/src/Output/PAaudiooutput.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + PAaudiooutput.C - Audio output for PortAudio Copyright (C) 2002 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 + 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, @@ -27,30 +27,32 @@ PaStream *stream; REALTYPE *outl,*outr; int PAprocess(void *inputBuffer,void *outputBuffer, - unsigned long framesPerBuffer, - PaTimestamp outTime,void *userData){ + unsigned long framesPerBuffer, + PaTimestamp outTime,void *userData) +{ if (framesPerBuffer!=SOUND_BUFFER_SIZE) { - fprintf(stderr,"Bug: PAudioOutput::PAprocess SOUND_BUFFER_SIZE!=framesPerBuffer"); + fprintf(stderr,"Bug: PAudioOutput::PAprocess SOUND_BUFFER_SIZE!=framesPerBuffer"); fprintf(stderr,"%d %d\n",framesPerBuffer,SOUND_BUFFER_SIZE); }; pthread_mutex_lock(&PAmaster->mutex); - PAmaster->GetAudioOutSamples(SOUND_BUFFER_SIZE,SAMPLE_RATE,outl,outr); + PAmaster->GetAudioOutSamples(SOUND_BUFFER_SIZE,SAMPLE_RATE,outl,outr); pthread_mutex_unlock(&PAmaster->mutex); float *out=(float *)outputBuffer; - for (int i=0;i<framesPerBuffer;i++){ - if (i>=SOUND_BUFFER_SIZE) break;//this should never happens, except only when framesPerBuffer!>SOUND_BUFFER_SIZE - out[i*2]=outl[i]; - out[i*2+1]=outr[i]; + for (int i=0;i<framesPerBuffer;i++) { + if (i>=SOUND_BUFFER_SIZE) break;//this should never happens, except only when framesPerBuffer!>SOUND_BUFFER_SIZE + out[i*2]=outl[i]; + out[i*2+1]=outr[i]; }; return(0); }; -void PAaudiooutputinit(Master *master_){ +void PAaudiooutputinit(Master *master_) +{ PAmaster=master_; outl=new REALTYPE [SOUND_BUFFER_SIZE]; outr=new REALTYPE [SOUND_BUFFER_SIZE]; @@ -59,7 +61,8 @@ void PAaudiooutputinit(Master *master_){ Pa_StartStream(stream); }; -void PAfinish(){ +void PAfinish() +{ Pa_StopStream(stream); delete (outl); delete (outr); diff --git a/src/Output/PAaudiooutput.h b/src/Output/PAaudiooutput.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + PAaudiooutput.h - Audio output for PortAudio Copyright (C) 2002 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 + 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, diff --git a/src/Output/Recorder.C b/src/Output/Recorder.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Recorder.C - Records sound to a file Copyright (C) 2002-2005 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 + 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, @@ -23,60 +23,68 @@ #include <sys/stat.h> #include "Recorder.h" -Recorder::Recorder(){ +Recorder::Recorder() +{ recordbuf_16bit=new short int [SOUND_BUFFER_SIZE*2]; status=0; notetrigger=0; - for (int i=0;i<SOUND_BUFFER_SIZE*2;i++){ + for (int i=0;i<SOUND_BUFFER_SIZE*2;i++) { recordbuf_16bit[i]=0; } }; -Recorder::~Recorder(){ +Recorder::~Recorder() +{ if (recording()==1) stop(); delete [] recordbuf_16bit; }; -int Recorder::preparefile(std::string filename_,int overwrite){ - if (!overwrite){ +int Recorder::preparefile(std::string filename_,int overwrite) +{ + if (!overwrite) { struct stat fileinfo; int statr; statr = stat(filename_.c_str(),&fileinfo); - if(statr == 0) {//file exists + if (statr == 0) {//file exists return 1; } } - + if (!wav.newfile(filename_, SAMPLE_RATE,2)) return 2; - + status=1;//ready - + return(0); }; -void Recorder::start(){ +void Recorder::start() +{ notetrigger=0; status=2;//recording }; -void Recorder::stop(){ - wav.close(); +void Recorder::stop() +{ + wav.close(); status=0; }; -void Recorder::pause(){ +void Recorder::pause() +{ status=0; }; -int Recorder::recording(){ +int Recorder::recording() +{ if ((status==2)&&(notetrigger!=0)) return(1); else return(0); }; -void Recorder::recordbuffer(REALTYPE *outl,REALTYPE *outr){ +void Recorder::recordbuffer(REALTYPE *outl,REALTYPE *outr) +{ int tmp; if (status!=2) return; - for (int i=0;i<SOUND_BUFFER_SIZE;i++){ + for (int i=0;i<SOUND_BUFFER_SIZE;i++) { tmp=(int)(outl[i]*32767.0); if (tmp<-32768) tmp=-32768; if (tmp>32767) tmp=32767; @@ -90,6 +98,7 @@ void Recorder::recordbuffer(REALTYPE *outl,REALTYPE *outr){ wav.write_stereo_samples(SOUND_BUFFER_SIZE,recordbuf_16bit); }; -void Recorder::triggernow(){ +void Recorder::triggernow() +{ if (status==2) notetrigger=1; }; diff --git a/src/Output/Recorder.h b/src/Output/Recorder.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Recorder.h - Records sound to a file Copyright (C) 2002-2005 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 + 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, @@ -27,29 +27,30 @@ #include "WAVaudiooutput.h" /**Records sound to a file*/ -class Recorder{ - public: - - Recorder(); - ~Recorder(); - int preparefile(std::string filename_,int overwrite);//returns 1 if the file exists - void start(); - void stop(); - void pause(); - int recording(); - void triggernow(); - void recordbuffer(REALTYPE *outl,REALTYPE *outr); - - /** Status: - * 0 - not ready(no file selected), - * 1 - ready - * 2 - recording */ - int status; - - private: - WAVaudiooutput wav; - short int *recordbuf_16bit; - int notetrigger; +class Recorder +{ +public: + + Recorder(); + ~Recorder(); + int preparefile(std::string filename_,int overwrite);//returns 1 if the file exists + void start(); + void stop(); + void pause(); + int recording(); + void triggernow(); + void recordbuffer(REALTYPE *outl,REALTYPE *outr); + + /** Status: + * 0 - not ready(no file selected), + * 1 - ready + * 2 - recording */ + int status; + +private: + WAVaudiooutput wav; + short int *recordbuf_16bit; + int notetrigger; }; #endif diff --git a/src/Output/VSTaudiooutput.C b/src/Output/VSTaudiooutput.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + VSTaudiooutput.C - Audio output for VST Copyright (C) 2002 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 + 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, @@ -24,36 +24,42 @@ //the constructor and the destructor are defined in main.C -void VSTSynth::process (float **inputs, float **outputs, long sampleframes){ +void VSTSynth::process (float **inputs, float **outputs, long sampleframes) +{ float *outl=outputs[0]; float *outr=outputs[1]; pthread_mutex_lock(&vmaster->mutex); - vmaster->GetAudioOutSamples(sampleframes,(int) getSampleRate(),outl,outr); + vmaster->GetAudioOutSamples(sampleframes,(int) getSampleRate(),outl,outr); pthread_mutex_unlock(&vmaster->mutex); }; -void VSTSynth::processReplacing (float **inputs, float **outputs, long sampleframes){ +void VSTSynth::processReplacing (float **inputs, float **outputs, long sampleframes) +{ process(inputs,outputs,sampleframes); }; -long int VSTSynth::canDo(char *txt){ - if (strcmp(txt,"receiveVstEvents")==0) return (1); - if (strcmp(txt,"receiveVstMidiEvent")==0) return (1); - return(-1); +long int VSTSynth::canDo(char *txt) +{ + if (strcmp(txt,"receiveVstEvents")==0) return (1); + if (strcmp(txt,"receiveVstMidiEvent")==0) return (1); + return(-1); }; -bool VSTSynth::getVendorString(char *txt){ - strcpy(txt,"Nasca O. Paul"); - return(true); +bool VSTSynth::getVendorString(char *txt) +{ + strcpy(txt,"Nasca O. Paul"); + return(true); }; -bool VSTSynth::getProductString(char *txt){ - strcpy(txt,"ZynAddSubFX"); - return(true); +bool VSTSynth::getProductString(char *txt) +{ + strcpy(txt,"ZynAddSubFX"); + return(true); }; -void VSTSynth::resume(){ - wantEvents(); +void VSTSynth::resume() +{ + wantEvents(); }; diff --git a/src/Output/VSTaudiooutput.h b/src/Output/VSTaudiooutput.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + VSTaudiooutput.h - Audio output for VST Copyright (C) 2002 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 + 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, @@ -30,27 +30,28 @@ #include "../../../vstsdk2/source/common/audioeffectx.h" -class VSTSynth:public AudioEffectX{ - public: - VSTSynth (audioMasterCallback audioMaster); - ~VSTSynth(); - - virtual void process (float **inputs, float **outputs, long sampleframes); - virtual void processReplacing (float **inputs, float **outputs, long sampleframes); - virtual long processEvents(VstEvents *events);//this is used for Midi input - virtual long int canDo(char *txt); - virtual bool getVendorString(char *txt); - virtual bool getProductString(char *txt); - virtual void resume(); - - virtual long getChunk(void** data,bool isPreset=false); - virtual long setChunk(void *data,long size,bool isPreset=false); - - MasterUI *ui; - int Pexitprogram; - - Master *vmaster; - pthread_t thr; +class VSTSynth:public AudioEffectX +{ +public: + VSTSynth (audioMasterCallback audioMaster); + ~VSTSynth(); + + virtual void process (float **inputs, float **outputs, long sampleframes); + virtual void processReplacing (float **inputs, float **outputs, long sampleframes); + virtual long processEvents(VstEvents *events);//this is used for Midi input + virtual long int canDo(char *txt); + virtual bool getVendorString(char *txt); + virtual bool getProductString(char *txt); + virtual void resume(); + + virtual long getChunk(void** data,bool isPreset=false); + virtual long setChunk(void *data,long size,bool isPreset=false); + + MasterUI *ui; + int Pexitprogram; + + Master *vmaster; + pthread_t thr; }; #endif diff --git a/src/Output/WAVaudiooutput.C b/src/Output/WAVaudiooutput.C @@ -3,7 +3,7 @@ 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 + 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, @@ -21,18 +21,21 @@ #include "WAVaudiooutput.h" using namespace std; -WAVaudiooutput::WAVaudiooutput(){ +WAVaudiooutput::WAVaudiooutput() +{ file=NULL; sampleswritten=0; samplerate=44100; }; -WAVaudiooutput::~WAVaudiooutput(){ +WAVaudiooutput::~WAVaudiooutput() +{ close(); }; -bool WAVaudiooutput::newfile(string filename,int samplerate,int channels){ - /**\todo Move this into the Constructor*/ +bool WAVaudiooutput::newfile(string filename,int samplerate,int channels) +{ + /**\todo Move this into the Constructor*/ close();//inchide un posibil fisier existent file=fopen(filename.c_str(),"w"); if (!file) return false; @@ -44,14 +47,15 @@ bool WAVaudiooutput::newfile(string filename,int samplerate,int channels){ return(true); }; -void WAVaudiooutput::close(){ - if (file){ +void WAVaudiooutput::close() +{ + if (file) { unsigned int chunksize; rewind(file); fwrite("RIFF",4,1,file); chunksize=sampleswritten*4+36; - fwrite(&chunksize,4,1,file); + fwrite(&chunksize,4,1,file); fwrite("WAVEfmt ",8,1,file); chunksize=16; @@ -68,7 +72,7 @@ void WAVaudiooutput::close(){ fwrite(&blockalign,2,1,file); unsigned short int bitspersample=16; fwrite(&bitspersample,2,1,file); - + fwrite("data",4,1,file); chunksize=sampleswritten*blockalign; fwrite(&chunksize,4,1,file); @@ -78,13 +82,15 @@ void WAVaudiooutput::close(){ } }; -void WAVaudiooutput::write_stereo_samples(int nsmps,short int *smps){ +void WAVaudiooutput::write_stereo_samples(int nsmps,short int *smps) +{ if (!file) return; fwrite(smps,nsmps,4,file); sampleswritten+=nsmps; }; -void WAVaudiooutput::write_mono_samples(int nsmps,short int *smps){ +void WAVaudiooutput::write_mono_samples(int nsmps,short int *smps) +{ if (!file) return; fwrite(smps,nsmps,2,file); sampleswritten+=nsmps; diff --git a/src/Output/WAVaudiooutput.h b/src/Output/WAVaudiooutput.h @@ -4,7 +4,7 @@ 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 + 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, @@ -21,21 +21,22 @@ #define WAVOUTPUT_H #include <string> -class WAVaudiooutput{ - public: - WAVaudiooutput(); - ~WAVaudiooutput(); - - bool newfile(std::string filename,int samplerate,int channels); - void close(); - - void write_mono_samples(int nsmps, short int *smps); - void write_stereo_samples(int nsmps, short int *smps); - - private: - int sampleswritten; - int samplerate; - int channels; - FILE *file; +class WAVaudiooutput +{ +public: + WAVaudiooutput(); + ~WAVaudiooutput(); + + bool newfile(std::string filename,int samplerate,int channels); + void close(); + + void write_mono_samples(int nsmps, short int *smps); + void write_stereo_samples(int nsmps, short int *smps); + +private: + int sampleswritten; + int samplerate; + int channels; + FILE *file; }; #endif diff --git a/src/Params/ADnoteParameters.C b/src/Params/ADnoteParameters.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + ADnoteParameters.C - Parameters for ADnote (ADsynth) Copyright (C) 2002-2005 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 + 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, @@ -26,14 +26,15 @@ #include "ADnoteParameters.h" -ADnoteParameters::ADnoteParameters(FFTwrapper *fft_):Presets(){ +ADnoteParameters::ADnoteParameters(FFTwrapper *fft_):Presets() +{ setpresettype("Padsyth"); fft=fft_; GlobalPar.FreqEnvelope=new EnvelopeParams(0,0); GlobalPar.FreqEnvelope->ASRinit(64,50,64,60); GlobalPar.FreqLfo=new LFOParams(70,0,64,0,0,0,0,0); - + GlobalPar.AmpEnvelope=new EnvelopeParams(64,1); GlobalPar.AmpEnvelope->ADSRinit_dB(0,40,127,25); GlobalPar.AmpLfo=new LFOParams(80,0,64,0,0,0,0,1); @@ -45,11 +46,12 @@ ADnoteParameters::ADnoteParameters(FFTwrapper *fft_):Presets(){ GlobalPar.Reson=new Resonance(); for (int nvoice=0;nvoice<NUM_VOICES;nvoice++) EnableVoice(nvoice); - + defaults(); }; -void ADnoteParameters::defaults(){ +void ADnoteParameters::defaults() +{ //Default Parameters /* Frequency Global Parameters */ GlobalPar.PStereo=1;//stereo @@ -59,7 +61,7 @@ void ADnoteParameters::defaults(){ GlobalPar.FreqEnvelope->defaults(); GlobalPar.FreqLfo->defaults(); GlobalPar.PBandwidth=64; - + /* Amplitude Global Parameters */ GlobalPar.PVolume=90; GlobalPar.PPanning=64;//center @@ -71,7 +73,7 @@ void ADnoteParameters::defaults(){ GlobalPar.PPunchStretch=64; GlobalPar.PPunchVelocitySensing=72; GlobalPar.Hrandgrouping=0; - + /* Filter Global Parameters*/ GlobalPar.PFilterVelocityScale=64; GlobalPar.PFilterVelocityScaleFunction=64; @@ -81,8 +83,8 @@ void ADnoteParameters::defaults(){ GlobalPar.Reson->defaults(); - for (int nvoice=0;nvoice<NUM_VOICES;nvoice++){ - defaults(nvoice); + for (int nvoice=0;nvoice<NUM_VOICES;nvoice++) { + defaults(nvoice); }; VoicePar[0].Enabled=1; }; @@ -90,62 +92,63 @@ void ADnoteParameters::defaults(){ /* * Defaults a voice */ -void ADnoteParameters::defaults(int n){ - int nvoice=n; - VoicePar[nvoice].Enabled=0; - VoicePar[nvoice].Type=0; - VoicePar[nvoice].Pfixedfreq=0; - VoicePar[nvoice].PfixedfreqET=0; - VoicePar[nvoice].Presonance=1; - VoicePar[nvoice].Pfilterbypass=0; - VoicePar[nvoice].Pextoscil=-1; - VoicePar[nvoice].PextFMoscil=-1; - VoicePar[nvoice].Poscilphase=64; - VoicePar[nvoice].PFMoscilphase=64; - VoicePar[nvoice].PDelay=0; - VoicePar[nvoice].PVolume=100; - VoicePar[nvoice].PVolumeminus=0; - VoicePar[nvoice].PPanning=64;//center - VoicePar[nvoice].PDetune=8192;//8192=0 - VoicePar[nvoice].PCoarseDetune=0; - VoicePar[nvoice].PDetuneType=0; - VoicePar[nvoice].PFreqLfoEnabled=0; - VoicePar[nvoice].PFreqEnvelopeEnabled=0; - VoicePar[nvoice].PAmpEnvelopeEnabled=0; - VoicePar[nvoice].PAmpLfoEnabled=0; - VoicePar[nvoice].PAmpVelocityScaleFunction=127; - VoicePar[nvoice].PFilterEnabled=0; - VoicePar[nvoice].PFilterEnvelopeEnabled=0; - VoicePar[nvoice].PFilterLfoEnabled=0; - VoicePar[nvoice].PFMEnabled=0; - - //I use the internal oscillator (-1) - VoicePar[nvoice].PFMVoice=-1; - - VoicePar[nvoice].PFMVolume=90; - VoicePar[nvoice].PFMVolumeDamp=64; - VoicePar[nvoice].PFMDetune=8192; - VoicePar[nvoice].PFMCoarseDetune=0; - VoicePar[nvoice].PFMDetuneType=0; - VoicePar[nvoice].PFMFreqEnvelopeEnabled=0; - VoicePar[nvoice].PFMAmpEnvelopeEnabled=0; - VoicePar[nvoice].PFMVelocityScaleFunction=64; - - VoicePar[nvoice].OscilSmp->defaults(); - VoicePar[nvoice].FMSmp->defaults(); - - VoicePar[nvoice].AmpEnvelope->defaults(); - VoicePar[nvoice].AmpLfo->defaults(); - - VoicePar[nvoice].FreqEnvelope->defaults(); - VoicePar[nvoice].FreqLfo->defaults(); - - VoicePar[nvoice].VoiceFilter->defaults(); - VoicePar[nvoice].FilterEnvelope->defaults(); - VoicePar[nvoice].FilterLfo->defaults(); - - VoicePar[nvoice].FMFreqEnvelope->defaults(); - VoicePar[nvoice].FMAmpEnvelope->defaults(); +void ADnoteParameters::defaults(int n) +{ + int nvoice=n; + VoicePar[nvoice].Enabled=0; + VoicePar[nvoice].Type=0; + VoicePar[nvoice].Pfixedfreq=0; + VoicePar[nvoice].PfixedfreqET=0; + VoicePar[nvoice].Presonance=1; + VoicePar[nvoice].Pfilterbypass=0; + VoicePar[nvoice].Pextoscil=-1; + VoicePar[nvoice].PextFMoscil=-1; + VoicePar[nvoice].Poscilphase=64; + VoicePar[nvoice].PFMoscilphase=64; + VoicePar[nvoice].PDelay=0; + VoicePar[nvoice].PVolume=100; + VoicePar[nvoice].PVolumeminus=0; + VoicePar[nvoice].PPanning=64;//center + VoicePar[nvoice].PDetune=8192;//8192=0 + VoicePar[nvoice].PCoarseDetune=0; + VoicePar[nvoice].PDetuneType=0; + VoicePar[nvoice].PFreqLfoEnabled=0; + VoicePar[nvoice].PFreqEnvelopeEnabled=0; + VoicePar[nvoice].PAmpEnvelopeEnabled=0; + VoicePar[nvoice].PAmpLfoEnabled=0; + VoicePar[nvoice].PAmpVelocityScaleFunction=127; + VoicePar[nvoice].PFilterEnabled=0; + VoicePar[nvoice].PFilterEnvelopeEnabled=0; + VoicePar[nvoice].PFilterLfoEnabled=0; + VoicePar[nvoice].PFMEnabled=0; + + //I use the internal oscillator (-1) + VoicePar[nvoice].PFMVoice=-1; + + VoicePar[nvoice].PFMVolume=90; + VoicePar[nvoice].PFMVolumeDamp=64; + VoicePar[nvoice].PFMDetune=8192; + VoicePar[nvoice].PFMCoarseDetune=0; + VoicePar[nvoice].PFMDetuneType=0; + VoicePar[nvoice].PFMFreqEnvelopeEnabled=0; + VoicePar[nvoice].PFMAmpEnvelopeEnabled=0; + VoicePar[nvoice].PFMVelocityScaleFunction=64; + + VoicePar[nvoice].OscilSmp->defaults(); + VoicePar[nvoice].FMSmp->defaults(); + + VoicePar[nvoice].AmpEnvelope->defaults(); + VoicePar[nvoice].AmpLfo->defaults(); + + VoicePar[nvoice].FreqEnvelope->defaults(); + VoicePar[nvoice].FreqLfo->defaults(); + + VoicePar[nvoice].VoiceFilter->defaults(); + VoicePar[nvoice].FilterEnvelope->defaults(); + VoicePar[nvoice].FilterLfo->defaults(); + + VoicePar[nvoice].FMFreqEnvelope->defaults(); + VoicePar[nvoice].FMAmpEnvelope->defaults(); }; @@ -153,12 +156,13 @@ void ADnoteParameters::defaults(int n){ /* * Init the voice parameters */ -void ADnoteParameters::EnableVoice(int nvoice){ +void ADnoteParameters::EnableVoice(int nvoice) +{ VoicePar[nvoice].OscilSmp=new OscilGen(fft,GlobalPar.Reson); VoicePar[nvoice].FMSmp=new OscilGen(fft,NULL); VoicePar[nvoice].AmpEnvelope=new EnvelopeParams(64,1); - VoicePar[nvoice].AmpEnvelope->ADSRinit_dB(0,100,127,100); + VoicePar[nvoice].AmpEnvelope->ADSRinit_dB(0,100,127,100); VoicePar[nvoice].AmpLfo=new LFOParams(90,32,64,0,0,30,0,1); VoicePar[nvoice].FreqEnvelope=new EnvelopeParams(0,0); @@ -179,10 +183,11 @@ void ADnoteParameters::EnableVoice(int nvoice){ /* * Get the Multiplier of the fine detunes of the voices */ -REALTYPE ADnoteParameters::getBandwidthDetuneMultiplier(){ +REALTYPE ADnoteParameters::getBandwidthDetuneMultiplier() +{ REALTYPE bw=(GlobalPar.PBandwidth-64.0)/64.0; bw=pow(2.0,bw*pow(fabs(bw),0.2)*5.0); - + return(bw); }; @@ -190,7 +195,8 @@ REALTYPE ADnoteParameters::getBandwidthDetuneMultiplier(){ /* * Kill the voice */ -void ADnoteParameters::KillVoice(int nvoice){ +void ADnoteParameters::KillVoice(int nvoice) +{ delete (VoicePar[nvoice].OscilSmp); delete (VoicePar[nvoice].FMSmp); @@ -208,7 +214,8 @@ void ADnoteParameters::KillVoice(int nvoice){ delete (VoicePar[nvoice].FMAmpEnvelope); }; -ADnoteParameters::~ADnoteParameters(){ +ADnoteParameters::~ADnoteParameters() +{ delete(GlobalPar.FreqEnvelope); delete(GlobalPar.FreqLfo); delete(GlobalPar.AmpEnvelope); @@ -218,7 +225,7 @@ ADnoteParameters::~ADnoteParameters(){ delete(GlobalPar.FilterLfo); delete(GlobalPar.Reson); - for (int nvoice=0;nvoice<NUM_VOICES;nvoice++){ + for (int nvoice=0;nvoice<NUM_VOICES;nvoice++) { KillVoice(nvoice); }; }; @@ -226,24 +233,25 @@ ADnoteParameters::~ADnoteParameters(){ -void ADnoteParameters::add2XMLsection(XMLwrapper *xml,int n){ +void ADnoteParameters::add2XMLsection(XMLwrapper *xml,int n) +{ int nvoice=n; if (nvoice>=NUM_VOICES) return; - + int oscilused=0,fmoscilused=0;//if the oscil or fmoscil are used by another voice - for (int i=0;i<NUM_VOICES;i++){ - if (VoicePar[i].Pextoscil==nvoice) oscilused=1; - if (VoicePar[i].PextFMoscil==nvoice) fmoscilused=1; + for (int i=0;i<NUM_VOICES;i++) { + if (VoicePar[i].Pextoscil==nvoice) oscilused=1; + if (VoicePar[i].PextFMoscil==nvoice) fmoscilused=1; }; - + xml->addparbool("enabled",VoicePar[nvoice].Enabled); if (((VoicePar[nvoice].Enabled==0)&&(oscilused==0)&&(fmoscilused==0))&&(xml->minimal)) return; xml->addpar("type",VoicePar[nvoice].Type); xml->addpar("delay",VoicePar[nvoice].PDelay); xml->addparbool("resonance",VoicePar[nvoice].Presonance); - + xml->addpar("ext_oscil",VoicePar[nvoice].Pextoscil); xml->addpar("ext_fm_oscil",VoicePar[nvoice].PextFMoscil); @@ -256,259 +264,262 @@ void ADnoteParameters::add2XMLsection(XMLwrapper *xml,int n){ xml->addpar("fm_enabled",VoicePar[nvoice].PFMEnabled); xml->beginbranch("OSCIL"); - VoicePar[nvoice].OscilSmp->add2XML(xml); + VoicePar[nvoice].OscilSmp->add2XML(xml); xml->endbranch(); xml->beginbranch("AMPLITUDE_PARAMETERS"); - xml->addpar("panning",VoicePar[nvoice].PPanning); - xml->addpar("volume",VoicePar[nvoice].PVolume); - xml->addparbool("volume_minus",VoicePar[nvoice].PVolumeminus); - xml->addpar("velocity_sensing",VoicePar[nvoice].PAmpVelocityScaleFunction); - - xml->addparbool("amp_envelope_enabled",VoicePar[nvoice].PAmpEnvelopeEnabled); - if ((VoicePar[nvoice].PAmpEnvelopeEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("AMPLITUDE_ENVELOPE"); - VoicePar[nvoice].AmpEnvelope->add2XML(xml); - xml->endbranch(); - }; - xml->addparbool("amp_lfo_enabled",VoicePar[nvoice].PAmpLfoEnabled); - if ((VoicePar[nvoice].PAmpLfoEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("AMPLITUDE_LFO"); - VoicePar[nvoice].AmpLfo->add2XML(xml); - xml->endbranch(); - }; + xml->addpar("panning",VoicePar[nvoice].PPanning); + xml->addpar("volume",VoicePar[nvoice].PVolume); + xml->addparbool("volume_minus",VoicePar[nvoice].PVolumeminus); + xml->addpar("velocity_sensing",VoicePar[nvoice].PAmpVelocityScaleFunction); + + xml->addparbool("amp_envelope_enabled",VoicePar[nvoice].PAmpEnvelopeEnabled); + if ((VoicePar[nvoice].PAmpEnvelopeEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("AMPLITUDE_ENVELOPE"); + VoicePar[nvoice].AmpEnvelope->add2XML(xml); + xml->endbranch(); + }; + xml->addparbool("amp_lfo_enabled",VoicePar[nvoice].PAmpLfoEnabled); + if ((VoicePar[nvoice].PAmpLfoEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("AMPLITUDE_LFO"); + VoicePar[nvoice].AmpLfo->add2XML(xml); + xml->endbranch(); + }; xml->endbranch(); xml->beginbranch("FREQUENCY_PARAMETERS"); - xml->addparbool("fixed_freq",VoicePar[nvoice].Pfixedfreq); - xml->addpar("fixed_freq_et",VoicePar[nvoice].PfixedfreqET); - xml->addpar("detune",VoicePar[nvoice].PDetune); - xml->addpar("coarse_detune",VoicePar[nvoice].PCoarseDetune); - xml->addpar("detune_type",VoicePar[nvoice].PDetuneType); - - xml->addparbool("freq_envelope_enabled",VoicePar[nvoice].PFreqEnvelopeEnabled); - if ((VoicePar[nvoice].PFreqEnvelopeEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("FREQUENCY_ENVELOPE"); - VoicePar[nvoice].FreqEnvelope->add2XML(xml); - xml->endbranch(); - }; - xml->addparbool("freq_lfo_enabled",VoicePar[nvoice].PFreqLfoEnabled); - if ((VoicePar[nvoice].PFreqLfoEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("FREQUENCY_LFO"); - VoicePar[nvoice].FreqLfo->add2XML(xml); - xml->endbranch(); - }; + xml->addparbool("fixed_freq",VoicePar[nvoice].Pfixedfreq); + xml->addpar("fixed_freq_et",VoicePar[nvoice].PfixedfreqET); + xml->addpar("detune",VoicePar[nvoice].PDetune); + xml->addpar("coarse_detune",VoicePar[nvoice].PCoarseDetune); + xml->addpar("detune_type",VoicePar[nvoice].PDetuneType); + + xml->addparbool("freq_envelope_enabled",VoicePar[nvoice].PFreqEnvelopeEnabled); + if ((VoicePar[nvoice].PFreqEnvelopeEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("FREQUENCY_ENVELOPE"); + VoicePar[nvoice].FreqEnvelope->add2XML(xml); + xml->endbranch(); + }; + xml->addparbool("freq_lfo_enabled",VoicePar[nvoice].PFreqLfoEnabled); + if ((VoicePar[nvoice].PFreqLfoEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("FREQUENCY_LFO"); + VoicePar[nvoice].FreqLfo->add2XML(xml); + xml->endbranch(); + }; xml->endbranch(); - if ((VoicePar[nvoice].PFilterEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("FILTER_PARAMETERS"); - xml->beginbranch("FILTER"); - VoicePar[nvoice].VoiceFilter->add2XML(xml); - xml->endbranch(); - - xml->addparbool("filter_envelope_enabled",VoicePar[nvoice].PFilterEnvelopeEnabled); - if ((VoicePar[nvoice].PFilterEnvelopeEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("FILTER_ENVELOPE"); - VoicePar[nvoice].FilterEnvelope->add2XML(xml); - xml->endbranch(); - }; - - xml->addparbool("filter_lfo_enabled",VoicePar[nvoice].PFilterLfoEnabled); - if ((VoicePar[nvoice].PFilterLfoEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("FILTER_LFO"); - VoicePar[nvoice].FilterLfo->add2XML(xml); - xml->endbranch(); - }; - xml->endbranch(); + if ((VoicePar[nvoice].PFilterEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("FILTER_PARAMETERS"); + xml->beginbranch("FILTER"); + VoicePar[nvoice].VoiceFilter->add2XML(xml); + xml->endbranch(); + + xml->addparbool("filter_envelope_enabled",VoicePar[nvoice].PFilterEnvelopeEnabled); + if ((VoicePar[nvoice].PFilterEnvelopeEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("FILTER_ENVELOPE"); + VoicePar[nvoice].FilterEnvelope->add2XML(xml); + xml->endbranch(); + }; + + xml->addparbool("filter_lfo_enabled",VoicePar[nvoice].PFilterLfoEnabled); + if ((VoicePar[nvoice].PFilterLfoEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("FILTER_LFO"); + VoicePar[nvoice].FilterLfo->add2XML(xml); + xml->endbranch(); + }; + xml->endbranch(); }; - if ((VoicePar[nvoice].PFMEnabled!=0)||(fmoscilused!=0)||(!xml->minimal)){ - xml->beginbranch("FM_PARAMETERS"); - xml->addpar("input_voice",VoicePar[nvoice].PFMVoice); - - xml->addpar("volume",VoicePar[nvoice].PFMVolume); - xml->addpar("volume_damp",VoicePar[nvoice].PFMVolumeDamp); - xml->addpar("velocity_sensing",VoicePar[nvoice].PFMVelocityScaleFunction); - - xml->addparbool("amp_envelope_enabled",VoicePar[nvoice].PFMAmpEnvelopeEnabled); - if ((VoicePar[nvoice].PFMAmpEnvelopeEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("AMPLITUDE_ENVELOPE"); - VoicePar[nvoice].FMAmpEnvelope->add2XML(xml); - xml->endbranch(); - }; - xml->beginbranch("MODULATOR"); - xml->addpar("detune",VoicePar[nvoice].PFMDetune); - xml->addpar("coarse_detune",VoicePar[nvoice].PFMCoarseDetune); - xml->addpar("detune_type",VoicePar[nvoice].PFMDetuneType); - - xml->addparbool("freq_envelope_enabled",VoicePar[nvoice].PFMFreqEnvelopeEnabled); - if ((VoicePar[nvoice].PFMFreqEnvelopeEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("FREQUENCY_ENVELOPE"); - VoicePar[nvoice].FMFreqEnvelope->add2XML(xml); - xml->endbranch(); - }; - - xml->beginbranch("OSCIL"); - VoicePar[nvoice].FMSmp->add2XML(xml); - xml->endbranch(); - - xml->endbranch(); - xml->endbranch(); + if ((VoicePar[nvoice].PFMEnabled!=0)||(fmoscilused!=0)||(!xml->minimal)) { + xml->beginbranch("FM_PARAMETERS"); + xml->addpar("input_voice",VoicePar[nvoice].PFMVoice); + + xml->addpar("volume",VoicePar[nvoice].PFMVolume); + xml->addpar("volume_damp",VoicePar[nvoice].PFMVolumeDamp); + xml->addpar("velocity_sensing",VoicePar[nvoice].PFMVelocityScaleFunction); + + xml->addparbool("amp_envelope_enabled",VoicePar[nvoice].PFMAmpEnvelopeEnabled); + if ((VoicePar[nvoice].PFMAmpEnvelopeEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("AMPLITUDE_ENVELOPE"); + VoicePar[nvoice].FMAmpEnvelope->add2XML(xml); + xml->endbranch(); + }; + xml->beginbranch("MODULATOR"); + xml->addpar("detune",VoicePar[nvoice].PFMDetune); + xml->addpar("coarse_detune",VoicePar[nvoice].PFMCoarseDetune); + xml->addpar("detune_type",VoicePar[nvoice].PFMDetuneType); + + xml->addparbool("freq_envelope_enabled",VoicePar[nvoice].PFMFreqEnvelopeEnabled); + if ((VoicePar[nvoice].PFMFreqEnvelopeEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("FREQUENCY_ENVELOPE"); + VoicePar[nvoice].FMFreqEnvelope->add2XML(xml); + xml->endbranch(); + }; + + xml->beginbranch("OSCIL"); + VoicePar[nvoice].FMSmp->add2XML(xml); + xml->endbranch(); + + xml->endbranch(); + xml->endbranch(); }; }; -void ADnoteParameters::add2XML(XMLwrapper *xml){ +void ADnoteParameters::add2XML(XMLwrapper *xml) +{ xml->addparbool("stereo",GlobalPar.PStereo); xml->beginbranch("AMPLITUDE_PARAMETERS"); - xml->addpar("volume",GlobalPar.PVolume); - xml->addpar("panning",GlobalPar.PPanning); - xml->addpar("velocity_sensing",GlobalPar.PAmpVelocityScaleFunction); - xml->addpar("punch_strength",GlobalPar.PPunchStrength); - xml->addpar("punch_time",GlobalPar.PPunchTime); - xml->addpar("punch_stretch",GlobalPar.PPunchStretch); - xml->addpar("punch_velocity_sensing",GlobalPar.PPunchVelocitySensing); - xml->addpar("harmonic_randomness_grouping",GlobalPar.Hrandgrouping); - - xml->beginbranch("AMPLITUDE_ENVELOPE"); - GlobalPar.AmpEnvelope->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("AMPLITUDE_LFO"); - GlobalPar.AmpLfo->add2XML(xml); - xml->endbranch(); + xml->addpar("volume",GlobalPar.PVolume); + xml->addpar("panning",GlobalPar.PPanning); + xml->addpar("velocity_sensing",GlobalPar.PAmpVelocityScaleFunction); + xml->addpar("punch_strength",GlobalPar.PPunchStrength); + xml->addpar("punch_time",GlobalPar.PPunchTime); + xml->addpar("punch_stretch",GlobalPar.PPunchStretch); + xml->addpar("punch_velocity_sensing",GlobalPar.PPunchVelocitySensing); + xml->addpar("harmonic_randomness_grouping",GlobalPar.Hrandgrouping); + + xml->beginbranch("AMPLITUDE_ENVELOPE"); + GlobalPar.AmpEnvelope->add2XML(xml); + xml->endbranch(); + + xml->beginbranch("AMPLITUDE_LFO"); + GlobalPar.AmpLfo->add2XML(xml); + xml->endbranch(); xml->endbranch(); xml->beginbranch("FREQUENCY_PARAMETERS"); - xml->addpar("detune",GlobalPar.PDetune); - - xml->addpar("coarse_detune",GlobalPar.PCoarseDetune); - xml->addpar("detune_type",GlobalPar.PDetuneType); - - xml->addpar("bandwidth",GlobalPar.PBandwidth); - - xml->beginbranch("FREQUENCY_ENVELOPE"); - GlobalPar.FreqEnvelope->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("FREQUENCY_LFO"); - GlobalPar.FreqLfo->add2XML(xml); - xml->endbranch(); + xml->addpar("detune",GlobalPar.PDetune); + + xml->addpar("coarse_detune",GlobalPar.PCoarseDetune); + xml->addpar("detune_type",GlobalPar.PDetuneType); + + xml->addpar("bandwidth",GlobalPar.PBandwidth); + + xml->beginbranch("FREQUENCY_ENVELOPE"); + GlobalPar.FreqEnvelope->add2XML(xml); xml->endbranch(); - - + + xml->beginbranch("FREQUENCY_LFO"); + GlobalPar.FreqLfo->add2XML(xml); + xml->endbranch(); + xml->endbranch(); + + xml->beginbranch("FILTER_PARAMETERS"); - xml->addpar("velocity_sensing_amplitude",GlobalPar.PFilterVelocityScale); - xml->addpar("velocity_sensing",GlobalPar.PFilterVelocityScaleFunction); - - xml->beginbranch("FILTER"); - GlobalPar.GlobalFilter->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("FILTER_ENVELOPE"); - GlobalPar.FilterEnvelope->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("FILTER_LFO"); - GlobalPar.FilterLfo->add2XML(xml); - xml->endbranch(); + xml->addpar("velocity_sensing_amplitude",GlobalPar.PFilterVelocityScale); + xml->addpar("velocity_sensing",GlobalPar.PFilterVelocityScaleFunction); + + xml->beginbranch("FILTER"); + GlobalPar.GlobalFilter->add2XML(xml); xml->endbranch(); - + + xml->beginbranch("FILTER_ENVELOPE"); + GlobalPar.FilterEnvelope->add2XML(xml); + xml->endbranch(); + + xml->beginbranch("FILTER_LFO"); + GlobalPar.FilterLfo->add2XML(xml); + xml->endbranch(); + xml->endbranch(); + xml->beginbranch("RESONANCE"); - GlobalPar.Reson->add2XML(xml); + GlobalPar.Reson->add2XML(xml); xml->endbranch(); - for (int nvoice=0;nvoice<NUM_VOICES;nvoice++){ - xml->beginbranch("VOICE",nvoice); - add2XMLsection(xml,nvoice); - xml->endbranch(); + for (int nvoice=0;nvoice<NUM_VOICES;nvoice++) { + xml->beginbranch("VOICE",nvoice); + add2XMLsection(xml,nvoice); + xml->endbranch(); }; }; -void ADnoteParameters::getfromXML(XMLwrapper *xml){ +void ADnoteParameters::getfromXML(XMLwrapper *xml) +{ GlobalPar.PStereo=xml->getparbool("stereo",GlobalPar.PStereo); - - if (xml->enterbranch("AMPLITUDE_PARAMETERS")){ - GlobalPar.PVolume=xml->getpar127("volume",GlobalPar.PVolume); - GlobalPar.PPanning=xml->getpar127("panning",GlobalPar.PPanning); - GlobalPar.PAmpVelocityScaleFunction=xml->getpar127("velocity_sensing",GlobalPar.PAmpVelocityScaleFunction); - - GlobalPar.PPunchStrength=xml->getpar127("punch_strength",GlobalPar.PPunchStrength); - GlobalPar.PPunchTime=xml->getpar127("punch_time",GlobalPar.PPunchTime); - GlobalPar.PPunchStretch=xml->getpar127("punch_stretch",GlobalPar.PPunchStretch); - GlobalPar.PPunchVelocitySensing=xml->getpar127("punch_velocity_sensing",GlobalPar.PPunchVelocitySensing); - GlobalPar.Hrandgrouping=xml->getpar127("harmonic_randomness_grouping",GlobalPar.Hrandgrouping); - - if (xml->enterbranch("AMPLITUDE_ENVELOPE")){ - GlobalPar.AmpEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - - if (xml->enterbranch("AMPLITUDE_LFO")){ - GlobalPar.AmpLfo->getfromXML(xml); - xml->exitbranch(); - }; - - xml->exitbranch(); + + if (xml->enterbranch("AMPLITUDE_PARAMETERS")) { + GlobalPar.PVolume=xml->getpar127("volume",GlobalPar.PVolume); + GlobalPar.PPanning=xml->getpar127("panning",GlobalPar.PPanning); + GlobalPar.PAmpVelocityScaleFunction=xml->getpar127("velocity_sensing",GlobalPar.PAmpVelocityScaleFunction); + + GlobalPar.PPunchStrength=xml->getpar127("punch_strength",GlobalPar.PPunchStrength); + GlobalPar.PPunchTime=xml->getpar127("punch_time",GlobalPar.PPunchTime); + GlobalPar.PPunchStretch=xml->getpar127("punch_stretch",GlobalPar.PPunchStretch); + GlobalPar.PPunchVelocitySensing=xml->getpar127("punch_velocity_sensing",GlobalPar.PPunchVelocitySensing); + GlobalPar.Hrandgrouping=xml->getpar127("harmonic_randomness_grouping",GlobalPar.Hrandgrouping); + + if (xml->enterbranch("AMPLITUDE_ENVELOPE")) { + GlobalPar.AmpEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + + if (xml->enterbranch("AMPLITUDE_LFO")) { + GlobalPar.AmpLfo->getfromXML(xml); + xml->exitbranch(); + }; + + xml->exitbranch(); }; - if (xml->enterbranch("FREQUENCY_PARAMETERS")){ - GlobalPar.PDetune=xml->getpar("detune",GlobalPar.PDetune,0,16383); - GlobalPar.PCoarseDetune=xml->getpar("coarse_detune",GlobalPar.PCoarseDetune,0,16383); + if (xml->enterbranch("FREQUENCY_PARAMETERS")) { + GlobalPar.PDetune=xml->getpar("detune",GlobalPar.PDetune,0,16383); + GlobalPar.PCoarseDetune=xml->getpar("coarse_detune",GlobalPar.PCoarseDetune,0,16383); GlobalPar.PDetuneType=xml->getpar127("detune_type",GlobalPar.PDetuneType); GlobalPar.PBandwidth=xml->getpar127("bandwidth",GlobalPar.PBandwidth); - - xml->enterbranch("FREQUENCY_ENVELOPE"); - GlobalPar.FreqEnvelope->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("FREQUENCY_LFO"); - GlobalPar.FreqLfo->getfromXML(xml); - xml->exitbranch(); - - xml->exitbranch(); + + xml->enterbranch("FREQUENCY_ENVELOPE"); + GlobalPar.FreqEnvelope->getfromXML(xml); + xml->exitbranch(); + + xml->enterbranch("FREQUENCY_LFO"); + GlobalPar.FreqLfo->getfromXML(xml); + xml->exitbranch(); + + xml->exitbranch(); }; - - - if (xml->enterbranch("FILTER_PARAMETERS")){ - GlobalPar.PFilterVelocityScale=xml->getpar127("velocity_sensing_amplitude",GlobalPar.PFilterVelocityScale); - GlobalPar.PFilterVelocityScaleFunction=xml->getpar127("velocity_sensing",GlobalPar.PFilterVelocityScaleFunction); - - xml->enterbranch("FILTER"); - GlobalPar.GlobalFilter->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("FILTER_ENVELOPE"); - GlobalPar.FilterEnvelope->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("FILTER_LFO"); - GlobalPar.FilterLfo->getfromXML(xml); - xml->exitbranch(); - xml->exitbranch(); + + + if (xml->enterbranch("FILTER_PARAMETERS")) { + GlobalPar.PFilterVelocityScale=xml->getpar127("velocity_sensing_amplitude",GlobalPar.PFilterVelocityScale); + GlobalPar.PFilterVelocityScaleFunction=xml->getpar127("velocity_sensing",GlobalPar.PFilterVelocityScaleFunction); + + xml->enterbranch("FILTER"); + GlobalPar.GlobalFilter->getfromXML(xml); + xml->exitbranch(); + + xml->enterbranch("FILTER_ENVELOPE"); + GlobalPar.FilterEnvelope->getfromXML(xml); + xml->exitbranch(); + + xml->enterbranch("FILTER_LFO"); + GlobalPar.FilterLfo->getfromXML(xml); + xml->exitbranch(); + xml->exitbranch(); }; - if (xml->enterbranch("RESONANCE")){ - GlobalPar.Reson->getfromXML(xml); - xml->exitbranch(); + if (xml->enterbranch("RESONANCE")) { + GlobalPar.Reson->getfromXML(xml); + xml->exitbranch(); }; - for (int nvoice=0;nvoice<NUM_VOICES;nvoice++){ - VoicePar[nvoice].Enabled=0; - if (xml->enterbranch("VOICE",nvoice)==0) continue; - getfromXMLsection(xml,nvoice); - xml->exitbranch(); + for (int nvoice=0;nvoice<NUM_VOICES;nvoice++) { + VoicePar[nvoice].Enabled=0; + if (xml->enterbranch("VOICE",nvoice)==0) continue; + getfromXMLsection(xml,nvoice); + xml->exitbranch(); }; - - + + }; -void ADnoteParameters::getfromXMLsection(XMLwrapper *xml,int n){ +void ADnoteParameters::getfromXMLsection(XMLwrapper *xml,int n) +{ int nvoice=n; if (nvoice>=NUM_VOICES) return; @@ -517,7 +528,7 @@ void ADnoteParameters::getfromXMLsection(XMLwrapper *xml,int n){ VoicePar[nvoice].Type=xml->getpar127("type",VoicePar[nvoice].Type); VoicePar[nvoice].PDelay=xml->getpar127("delay",VoicePar[nvoice].PDelay); VoicePar[nvoice].Presonance=xml->getparbool("resonance",VoicePar[nvoice].Presonance); - + VoicePar[nvoice].Pextoscil=xml->getpar("ext_oscil",-1,-1,nvoice-1); VoicePar[nvoice].PextFMoscil=xml->getpar("ext_fm_oscil",-1,-1,nvoice-1); @@ -529,108 +540,108 @@ void ADnoteParameters::getfromXMLsection(XMLwrapper *xml,int n){ VoicePar[nvoice].PFMEnabled=xml->getpar127("fm_enabled",VoicePar[nvoice].PFMEnabled); - if (xml->enterbranch("OSCIL")){ - VoicePar[nvoice].OscilSmp->getfromXML(xml); - xml->exitbranch(); + if (xml->enterbranch("OSCIL")) { + VoicePar[nvoice].OscilSmp->getfromXML(xml); + xml->exitbranch(); }; - if (xml->enterbranch("AMPLITUDE_PARAMETERS")){ - VoicePar[nvoice].PPanning=xml->getpar127("panning",VoicePar[nvoice].PPanning); - VoicePar[nvoice].PVolume=xml->getpar127("volume",VoicePar[nvoice].PVolume); - VoicePar[nvoice].PVolumeminus=xml->getparbool("volume_minus",VoicePar[nvoice].PVolumeminus); - VoicePar[nvoice].PAmpVelocityScaleFunction=xml->getpar127("velocity_sensing",VoicePar[nvoice].PAmpVelocityScaleFunction); - - VoicePar[nvoice].PAmpEnvelopeEnabled=xml->getparbool("amp_envelope_enabled",VoicePar[nvoice].PAmpEnvelopeEnabled); - if (xml->enterbranch("AMPLITUDE_ENVELOPE")){ - VoicePar[nvoice].AmpEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - - VoicePar[nvoice].PAmpLfoEnabled=xml->getparbool("amp_lfo_enabled",VoicePar[nvoice].PAmpLfoEnabled); - if (xml->enterbranch("AMPLITUDE_LFO")){ - VoicePar[nvoice].AmpLfo->getfromXML(xml); - xml->exitbranch(); - }; - xml->exitbranch(); + if (xml->enterbranch("AMPLITUDE_PARAMETERS")) { + VoicePar[nvoice].PPanning=xml->getpar127("panning",VoicePar[nvoice].PPanning); + VoicePar[nvoice].PVolume=xml->getpar127("volume",VoicePar[nvoice].PVolume); + VoicePar[nvoice].PVolumeminus=xml->getparbool("volume_minus",VoicePar[nvoice].PVolumeminus); + VoicePar[nvoice].PAmpVelocityScaleFunction=xml->getpar127("velocity_sensing",VoicePar[nvoice].PAmpVelocityScaleFunction); + + VoicePar[nvoice].PAmpEnvelopeEnabled=xml->getparbool("amp_envelope_enabled",VoicePar[nvoice].PAmpEnvelopeEnabled); + if (xml->enterbranch("AMPLITUDE_ENVELOPE")) { + VoicePar[nvoice].AmpEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + + VoicePar[nvoice].PAmpLfoEnabled=xml->getparbool("amp_lfo_enabled",VoicePar[nvoice].PAmpLfoEnabled); + if (xml->enterbranch("AMPLITUDE_LFO")) { + VoicePar[nvoice].AmpLfo->getfromXML(xml); + xml->exitbranch(); + }; + xml->exitbranch(); }; - if (xml->enterbranch("FREQUENCY_PARAMETERS")){ - VoicePar[nvoice].Pfixedfreq=xml->getparbool("fixed_freq",VoicePar[nvoice].Pfixedfreq); - VoicePar[nvoice].PfixedfreqET=xml->getpar127("fixed_freq_et",VoicePar[nvoice].PfixedfreqET); - - - VoicePar[nvoice].PDetune=xml->getpar("detune",VoicePar[nvoice].PDetune,0,16383); - - VoicePar[nvoice].PCoarseDetune=xml->getpar("coarse_detune",VoicePar[nvoice].PCoarseDetune,0,16383); - VoicePar[nvoice].PDetuneType=xml->getpar127("detune_type",VoicePar[nvoice].PDetuneType); - - VoicePar[nvoice].PFreqEnvelopeEnabled=xml->getparbool("freq_envelope_enabled",VoicePar[nvoice].PFreqEnvelopeEnabled); - if (xml->enterbranch("FREQUENCY_ENVELOPE")){ - VoicePar[nvoice].FreqEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - - VoicePar[nvoice].PFreqLfoEnabled=xml->getparbool("freq_lfo_enabled",VoicePar[nvoice].PFreqLfoEnabled); - if (xml->enterbranch("FREQUENCY_LFO")){ - VoicePar[nvoice].FreqLfo->getfromXML(xml); - xml->exitbranch(); - }; - xml->exitbranch(); + if (xml->enterbranch("FREQUENCY_PARAMETERS")) { + VoicePar[nvoice].Pfixedfreq=xml->getparbool("fixed_freq",VoicePar[nvoice].Pfixedfreq); + VoicePar[nvoice].PfixedfreqET=xml->getpar127("fixed_freq_et",VoicePar[nvoice].PfixedfreqET); + + + VoicePar[nvoice].PDetune=xml->getpar("detune",VoicePar[nvoice].PDetune,0,16383); + + VoicePar[nvoice].PCoarseDetune=xml->getpar("coarse_detune",VoicePar[nvoice].PCoarseDetune,0,16383); + VoicePar[nvoice].PDetuneType=xml->getpar127("detune_type",VoicePar[nvoice].PDetuneType); + + VoicePar[nvoice].PFreqEnvelopeEnabled=xml->getparbool("freq_envelope_enabled",VoicePar[nvoice].PFreqEnvelopeEnabled); + if (xml->enterbranch("FREQUENCY_ENVELOPE")) { + VoicePar[nvoice].FreqEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + + VoicePar[nvoice].PFreqLfoEnabled=xml->getparbool("freq_lfo_enabled",VoicePar[nvoice].PFreqLfoEnabled); + if (xml->enterbranch("FREQUENCY_LFO")) { + VoicePar[nvoice].FreqLfo->getfromXML(xml); + xml->exitbranch(); + }; + xml->exitbranch(); }; - if (xml->enterbranch("FILTER_PARAMETERS")){ - if (xml->enterbranch("FILTER")){ - VoicePar[nvoice].VoiceFilter->getfromXML(xml); - xml->exitbranch(); - }; - - VoicePar[nvoice].PFilterEnvelopeEnabled=xml->getparbool("filter_envelope_enabled",VoicePar[nvoice].PFilterEnvelopeEnabled); - if (xml->enterbranch("FILTER_ENVELOPE")){ - VoicePar[nvoice].FilterEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - - VoicePar[nvoice].PFilterLfoEnabled=xml->getparbool("filter_lfo_enabled",VoicePar[nvoice].PFilterLfoEnabled); - if (xml->enterbranch("FILTER_LFO")){ - VoicePar[nvoice].FilterLfo->getfromXML(xml); - xml->exitbranch(); - }; - xml->exitbranch(); + if (xml->enterbranch("FILTER_PARAMETERS")) { + if (xml->enterbranch("FILTER")) { + VoicePar[nvoice].VoiceFilter->getfromXML(xml); + xml->exitbranch(); + }; + + VoicePar[nvoice].PFilterEnvelopeEnabled=xml->getparbool("filter_envelope_enabled",VoicePar[nvoice].PFilterEnvelopeEnabled); + if (xml->enterbranch("FILTER_ENVELOPE")) { + VoicePar[nvoice].FilterEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + + VoicePar[nvoice].PFilterLfoEnabled=xml->getparbool("filter_lfo_enabled",VoicePar[nvoice].PFilterLfoEnabled); + if (xml->enterbranch("FILTER_LFO")) { + VoicePar[nvoice].FilterLfo->getfromXML(xml); + xml->exitbranch(); + }; + xml->exitbranch(); }; - if (xml->enterbranch("FM_PARAMETERS")){ - VoicePar[nvoice].PFMVoice=xml->getpar("input_voice",VoicePar[nvoice].PFMVoice,-1,nvoice-1); - - VoicePar[nvoice].PFMVolume=xml->getpar127("volume",VoicePar[nvoice].PFMVolume); - VoicePar[nvoice].PFMVolumeDamp=xml->getpar127("volume_damp",VoicePar[nvoice].PFMVolumeDamp); - VoicePar[nvoice].PFMVelocityScaleFunction=xml->getpar127("velocity_sensing",VoicePar[nvoice].PFMVelocityScaleFunction); - - VoicePar[nvoice].PFMAmpEnvelopeEnabled=xml->getparbool("amp_envelope_enabled",VoicePar[nvoice].PFMAmpEnvelopeEnabled); - if (xml->enterbranch("AMPLITUDE_ENVELOPE")){ - VoicePar[nvoice].FMAmpEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - - if (xml->enterbranch("MODULATOR")){ - VoicePar[nvoice].PFMDetune=xml->getpar("detune",VoicePar[nvoice].PFMDetune,0,16383); - VoicePar[nvoice].PFMCoarseDetune=xml->getpar("coarse_detune",VoicePar[nvoice].PFMCoarseDetune,0,16383); - VoicePar[nvoice].PFMDetuneType=xml->getpar127("detune_type",VoicePar[nvoice].PFMDetuneType); - - VoicePar[nvoice].PFMFreqEnvelopeEnabled=xml->getparbool("freq_envelope_enabled",VoicePar[nvoice].PFMFreqEnvelopeEnabled); - if (xml->enterbranch("FREQUENCY_ENVELOPE")){ - VoicePar[nvoice].FMFreqEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - - if (xml->enterbranch("OSCIL")){ - VoicePar[nvoice].FMSmp->getfromXML(xml); - xml->exitbranch(); - }; - - xml->exitbranch(); - }; - xml->exitbranch(); + if (xml->enterbranch("FM_PARAMETERS")) { + VoicePar[nvoice].PFMVoice=xml->getpar("input_voice",VoicePar[nvoice].PFMVoice,-1,nvoice-1); + + VoicePar[nvoice].PFMVolume=xml->getpar127("volume",VoicePar[nvoice].PFMVolume); + VoicePar[nvoice].PFMVolumeDamp=xml->getpar127("volume_damp",VoicePar[nvoice].PFMVolumeDamp); + VoicePar[nvoice].PFMVelocityScaleFunction=xml->getpar127("velocity_sensing",VoicePar[nvoice].PFMVelocityScaleFunction); + + VoicePar[nvoice].PFMAmpEnvelopeEnabled=xml->getparbool("amp_envelope_enabled",VoicePar[nvoice].PFMAmpEnvelopeEnabled); + if (xml->enterbranch("AMPLITUDE_ENVELOPE")) { + VoicePar[nvoice].FMAmpEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + + if (xml->enterbranch("MODULATOR")) { + VoicePar[nvoice].PFMDetune=xml->getpar("detune",VoicePar[nvoice].PFMDetune,0,16383); + VoicePar[nvoice].PFMCoarseDetune=xml->getpar("coarse_detune",VoicePar[nvoice].PFMCoarseDetune,0,16383); + VoicePar[nvoice].PFMDetuneType=xml->getpar127("detune_type",VoicePar[nvoice].PFMDetuneType); + + VoicePar[nvoice].PFMFreqEnvelopeEnabled=xml->getparbool("freq_envelope_enabled",VoicePar[nvoice].PFMFreqEnvelopeEnabled); + if (xml->enterbranch("FREQUENCY_ENVELOPE")) { + VoicePar[nvoice].FMFreqEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + + if (xml->enterbranch("OSCIL")) { + VoicePar[nvoice].FMSmp->getfromXML(xml); + xml->exitbranch(); + }; + + xml->exitbranch(); + }; + xml->exitbranch(); }; }; diff --git a/src/Params/ADnoteParameters.h b/src/Params/ADnoteParameters.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + ADnoteParameters.h - Parameters for ADnote (ADsynth) Copyright (C) 2002-2005 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 + 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, @@ -35,248 +35,249 @@ #include "../DSP/FFTwrapper.h" #include "Presets.h" - enum FMTYPE{NONE,MORPH,RING_MOD,PHASE_MOD,FREQ_MOD,PITCH_MOD}; - - /*****************************************************************/ - /* GLOBAL PARAMETERS */ - /*****************************************************************/ - - struct ADnoteGlobalParam{ - - /* The instrument type - MONO/STEREO - If the mode is MONO, the panning of voices are not used - Stereo=1, Mono=0. */ - - unsigned char PStereo; - - - /****************************************** - * FREQUENCY GLOBAL PARAMETERS * - ******************************************/ - unsigned short int PDetune;//fine detune - unsigned short int PCoarseDetune;//coarse detune+octave - unsigned char PDetuneType;//detune type - - unsigned char PBandwidth;//how much the relative fine detunes of the voices are changed - - EnvelopeParams *FreqEnvelope; //Frequency Envelope - - LFOParams *FreqLfo;//Frequency LFO - - /******************************************** - * AMPLITUDE GLOBAL PARAMETERS * - ********************************************/ - - /* Panning - 0 - random - 1 - left - 64 - center - 127 - right */ - unsigned char PPanning; - - unsigned char PVolume; - - unsigned char PAmpVelocityScaleFunction; - - EnvelopeParams *AmpEnvelope; - - LFOParams *AmpLfo; - - unsigned char PPunchStrength,PPunchTime,PPunchStretch,PPunchVelocitySensing; - - /****************************************** - * FILTER GLOBAL PARAMETERS * - ******************************************/ - FilterParams *GlobalFilter; - - // filter velocity sensing - unsigned char PFilterVelocityScale; - - // filter velocity sensing - unsigned char PFilterVelocityScaleFunction; - - EnvelopeParams *FilterEnvelope; - - LFOParams *FilterLfo; - - // RESONANCE - Resonance *Reson; - - //how the randomness is applied to the harmonics on more voices using the same oscillator - unsigned char Hrandgrouping; - }; - - - - /***********************************************************/ - /* VOICE PARAMETERS */ - /***********************************************************/ - struct ADnoteVoiceParam{ - - /** If the voice is enabled */ - unsigned char Enabled; - - /** Type of the voice (0=Sound,1=Noise)*/ - unsigned char Type; - - /** Voice Delay */ - unsigned char PDelay; - - /** If the resonance is enabled for this voice */ - unsigned char Presonance; - - // What external oscil should I use, -1 for internal OscilSmp&FMSmp - short int Pextoscil,PextFMoscil; - // it is not allowed that the externoscil,externFMoscil => current voice - - // oscillator phases - unsigned char Poscilphase,PFMoscilphase; - - // filter bypass - unsigned char Pfilterbypass; - - /** Voice oscillator */ - OscilGen *OscilSmp; - - /********************************** - * FREQUENCY PARAMETERS * - **********************************/ - - /** If the base frequency is fixed to 440 Hz*/ - unsigned char Pfixedfreq; - - /* Equal temperate (this is used only if the Pfixedfreq is enabled) - If this parameter is 0, the frequency is fixed (to 440 Hz); - if this parameter is 64, 1 MIDI halftone -> 1 frequency halftone */ - unsigned char PfixedfreqET; - - /** Fine detune */ - unsigned short int PDetune; - - /** Coarse detune + octave */ - unsigned short int PCoarseDetune; - - /** Detune type */ - unsigned char PDetuneType; - - /* Frequency Envelope */ - unsigned char PFreqEnvelopeEnabled; - EnvelopeParams *FreqEnvelope; - - /* Frequency LFO */ - unsigned char PFreqLfoEnabled; - LFOParams *FreqLfo; - - - /*************************** - * AMPLITUDE PARAMETERS * - ***************************/ - - /* Panning 0 - random - 1 - left - 64 - center - 127 - right - The Panning is ignored if the instrument is mono */ - unsigned char PPanning; - - /* Voice Volume */ - unsigned char PVolume; - - /* If the Volume negative */ - unsigned char PVolumeminus; - - /* Velocity sensing */ - unsigned char PAmpVelocityScaleFunction; - - /* Amplitude Envelope */ - unsigned char PAmpEnvelopeEnabled; - EnvelopeParams *AmpEnvelope; - - /* Amplitude LFO */ - unsigned char PAmpLfoEnabled; - LFOParams *AmpLfo; - - - - /************************* - * FILTER PARAMETERS * - *************************/ - - /* Voice Filter */ - unsigned char PFilterEnabled; - FilterParams *VoiceFilter; - - /* Filter Envelope */ - unsigned char PFilterEnvelopeEnabled; - EnvelopeParams *FilterEnvelope; - - /* LFO Envelope */ - unsigned char PFilterLfoEnabled; - LFOParams *FilterLfo; - - /**************************** - * MODULLATOR PARAMETERS * - ****************************/ - - /* Modullator Parameters (0=off,1=Morph,2=RM,3=PM,4=FM.. */ - unsigned char PFMEnabled; - - /* Voice that I use as modullator instead of FMSmp. - It is -1 if I use FMSmp(default). - It maynot be equal or bigger than current voice */ - short int PFMVoice; - - /* Modullator oscillator */ - OscilGen *FMSmp; - - /* Modullator Volume */ - unsigned char PFMVolume; - - /* Modullator damping at higher frequencies */ - unsigned char PFMVolumeDamp; - - /* Modullator Velocity Sensing */ - unsigned char PFMVelocityScaleFunction; - - /* Fine Detune of the Modullator*/ - unsigned short int PFMDetune; - - /* Coarse Detune of the Modullator */ - unsigned short int PFMCoarseDetune; - - /* The detune type */ - unsigned char PFMDetuneType; - - /* Frequency Envelope of the Modullator */ - unsigned char PFMFreqEnvelopeEnabled; - EnvelopeParams *FMFreqEnvelope; - - /* Frequency Envelope of the Modullator */ - unsigned char PFMAmpEnvelopeEnabled; - EnvelopeParams *FMAmpEnvelope; - }; - -class ADnoteParameters:public Presets{ - public: - ADnoteParameters(FFTwrapper *fft_); - ~ADnoteParameters(); - - ADnoteGlobalParam GlobalPar; - ADnoteVoiceParam VoicePar[NUM_VOICES]; - - void defaults(); - void add2XML(XMLwrapper *xml); - void getfromXML(XMLwrapper *xml); - - REALTYPE getBandwidthDetuneMultiplier(); - private: - void defaults(int n);//n is the nvoice - - void EnableVoice(int nvoice); - void KillVoice(int nvoice); - FFTwrapper *fft; - - void add2XMLsection(XMLwrapper *xml,int n); - void getfromXMLsection(XMLwrapper *xml,int n); +enum FMTYPE {NONE,MORPH,RING_MOD,PHASE_MOD,FREQ_MOD,PITCH_MOD}; + +/*****************************************************************/ +/* GLOBAL PARAMETERS */ +/*****************************************************************/ + +struct ADnoteGlobalParam { + + /* The instrument type - MONO/STEREO + If the mode is MONO, the panning of voices are not used + Stereo=1, Mono=0. */ + + unsigned char PStereo; + + + /****************************************** + * FREQUENCY GLOBAL PARAMETERS * + ******************************************/ + unsigned short int PDetune;//fine detune + unsigned short int PCoarseDetune;//coarse detune+octave + unsigned char PDetuneType;//detune type + + unsigned char PBandwidth;//how much the relative fine detunes of the voices are changed + + EnvelopeParams *FreqEnvelope; //Frequency Envelope + + LFOParams *FreqLfo;//Frequency LFO + + /******************************************** + * AMPLITUDE GLOBAL PARAMETERS * + ********************************************/ + + /* Panning - 0 - random + 1 - left + 64 - center + 127 - right */ + unsigned char PPanning; + + unsigned char PVolume; + + unsigned char PAmpVelocityScaleFunction; + + EnvelopeParams *AmpEnvelope; + + LFOParams *AmpLfo; + + unsigned char PPunchStrength,PPunchTime,PPunchStretch,PPunchVelocitySensing; + + /****************************************** + * FILTER GLOBAL PARAMETERS * + ******************************************/ + FilterParams *GlobalFilter; + + // filter velocity sensing + unsigned char PFilterVelocityScale; + + // filter velocity sensing + unsigned char PFilterVelocityScaleFunction; + + EnvelopeParams *FilterEnvelope; + + LFOParams *FilterLfo; + + // RESONANCE + Resonance *Reson; + + //how the randomness is applied to the harmonics on more voices using the same oscillator + unsigned char Hrandgrouping; +}; + + + +/***********************************************************/ +/* VOICE PARAMETERS */ +/***********************************************************/ +struct ADnoteVoiceParam { + + /** If the voice is enabled */ + unsigned char Enabled; + + /** Type of the voice (0=Sound,1=Noise)*/ + unsigned char Type; + + /** Voice Delay */ + unsigned char PDelay; + + /** If the resonance is enabled for this voice */ + unsigned char Presonance; + + // What external oscil should I use, -1 for internal OscilSmp&FMSmp + short int Pextoscil,PextFMoscil; + // it is not allowed that the externoscil,externFMoscil => current voice + + // oscillator phases + unsigned char Poscilphase,PFMoscilphase; + + // filter bypass + unsigned char Pfilterbypass; + + /** Voice oscillator */ + OscilGen *OscilSmp; + + /********************************** + * FREQUENCY PARAMETERS * + **********************************/ + + /** If the base frequency is fixed to 440 Hz*/ + unsigned char Pfixedfreq; + + /* Equal temperate (this is used only if the Pfixedfreq is enabled) + If this parameter is 0, the frequency is fixed (to 440 Hz); + if this parameter is 64, 1 MIDI halftone -> 1 frequency halftone */ + unsigned char PfixedfreqET; + + /** Fine detune */ + unsigned short int PDetune; + + /** Coarse detune + octave */ + unsigned short int PCoarseDetune; + + /** Detune type */ + unsigned char PDetuneType; + + /* Frequency Envelope */ + unsigned char PFreqEnvelopeEnabled; + EnvelopeParams *FreqEnvelope; + + /* Frequency LFO */ + unsigned char PFreqLfoEnabled; + LFOParams *FreqLfo; + + + /*************************** + * AMPLITUDE PARAMETERS * + ***************************/ + + /* Panning 0 - random + 1 - left + 64 - center + 127 - right + The Panning is ignored if the instrument is mono */ + unsigned char PPanning; + + /* Voice Volume */ + unsigned char PVolume; + + /* If the Volume negative */ + unsigned char PVolumeminus; + + /* Velocity sensing */ + unsigned char PAmpVelocityScaleFunction; + + /* Amplitude Envelope */ + unsigned char PAmpEnvelopeEnabled; + EnvelopeParams *AmpEnvelope; + + /* Amplitude LFO */ + unsigned char PAmpLfoEnabled; + LFOParams *AmpLfo; + + + + /************************* + * FILTER PARAMETERS * + *************************/ + + /* Voice Filter */ + unsigned char PFilterEnabled; + FilterParams *VoiceFilter; + + /* Filter Envelope */ + unsigned char PFilterEnvelopeEnabled; + EnvelopeParams *FilterEnvelope; + + /* LFO Envelope */ + unsigned char PFilterLfoEnabled; + LFOParams *FilterLfo; + + /**************************** + * MODULLATOR PARAMETERS * + ****************************/ + + /* Modullator Parameters (0=off,1=Morph,2=RM,3=PM,4=FM.. */ + unsigned char PFMEnabled; + + /* Voice that I use as modullator instead of FMSmp. + It is -1 if I use FMSmp(default). + It maynot be equal or bigger than current voice */ + short int PFMVoice; + + /* Modullator oscillator */ + OscilGen *FMSmp; + + /* Modullator Volume */ + unsigned char PFMVolume; + + /* Modullator damping at higher frequencies */ + unsigned char PFMVolumeDamp; + + /* Modullator Velocity Sensing */ + unsigned char PFMVelocityScaleFunction; + + /* Fine Detune of the Modullator*/ + unsigned short int PFMDetune; + + /* Coarse Detune of the Modullator */ + unsigned short int PFMCoarseDetune; + + /* The detune type */ + unsigned char PFMDetuneType; + + /* Frequency Envelope of the Modullator */ + unsigned char PFMFreqEnvelopeEnabled; + EnvelopeParams *FMFreqEnvelope; + + /* Frequency Envelope of the Modullator */ + unsigned char PFMAmpEnvelopeEnabled; + EnvelopeParams *FMAmpEnvelope; +}; + +class ADnoteParameters:public Presets +{ +public: + ADnoteParameters(FFTwrapper *fft_); + ~ADnoteParameters(); + + ADnoteGlobalParam GlobalPar; + ADnoteVoiceParam VoicePar[NUM_VOICES]; + + void defaults(); + void add2XML(XMLwrapper *xml); + void getfromXML(XMLwrapper *xml); + + REALTYPE getBandwidthDetuneMultiplier(); +private: + void defaults(int n);//n is the nvoice + + void EnableVoice(int nvoice); + void KillVoice(int nvoice); + FFTwrapper *fft; + + void add2XMLsection(XMLwrapper *xml,int n); + void getfromXMLsection(XMLwrapper *xml,int n); }; #endif diff --git a/src/Params/Controller.C b/src/Params/Controller.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Controller.C - (Midi) Controllers implementation Copyright (C) 2002-2005 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 + 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, @@ -24,15 +24,18 @@ #include <math.h> #include <stdio.h> -Controller::Controller(){ +Controller::Controller() +{ defaults(); resetall(); }; -Controller::~Controller(){ +Controller::~Controller() +{ }; -void Controller::defaults(){ +void Controller::defaults() +{ setpitchwheelbendrange(200);//2 halftones expression.receive=1; panning.depth=64; @@ -63,7 +66,8 @@ void Controller::defaults(){ }; -void Controller::resetall(){ +void Controller::resetall() +{ setpitchwheel(0);//center setexpression(127); setpanning(64); @@ -76,7 +80,7 @@ void Controller::resetall(){ setsustain(0); setresonancecenter(64); setresonancebw(64); - + //reset the NRPN NRPN.parhi=-1; NRPN.parlo=-1; @@ -84,7 +88,8 @@ void Controller::resetall(){ NRPN.vallo=-1; }; -void Controller::setpitchwheel(int value){ +void Controller::setpitchwheel(int value) +{ pitchwheel.data=value; REALTYPE cents=value/8192.0; cents*=pitchwheel.bendrange; @@ -92,106 +97,118 @@ void Controller::setpitchwheel(int value){ //fprintf(stderr,"%ld %ld -> %.3f\n",pitchwheel.bendrange,pitchwheel.data,pitchwheel.relfreq);fflush(stderr); }; -void Controller::setpitchwheelbendrange(unsigned short int value){ +void Controller::setpitchwheelbendrange(unsigned short int value) +{ pitchwheel.bendrange=value; }; -void Controller::setexpression(int value){ +void Controller::setexpression(int value) +{ expression.data=value; if (expression.receive!=0) expression.relvolume=value/127.0; - else expression.relvolume=1.0; + else expression.relvolume=1.0; }; -void Controller::setpanning(int value){ +void Controller::setpanning(int value) +{ panning.data=value; panning.pan=(value/128.0-0.5)*(panning.depth/64.0); }; -void Controller::setfiltercutoff(int value){ +void Controller::setfiltercutoff(int value) +{ filtercutoff.data=value; filtercutoff.relfreq=(value-64.0)*filtercutoff.depth/4096.0*3.321928;//3.3219..=ln2(10) }; -void Controller::setfilterq(int value){ +void Controller::setfilterq(int value) +{ filterq.data=value; filterq.relq=pow(30.0,(value-64.0)/64.0*(filterq.depth/64.0)); }; -void Controller::setbandwidth(int value){ +void Controller::setbandwidth(int value) +{ bandwidth.data=value; if (bandwidth.exponential==0) { - REALTYPE tmp=pow(25.0,pow(bandwidth.depth/127.0,1.5))-1.0; - if ((value<64)&&(bandwidth.depth>=64)) tmp=1.0; - bandwidth.relbw=(value/64.0-1.0)*tmp+1.0; - if (bandwidth.relbw<0.01) bandwidth.relbw=0.01; + REALTYPE tmp=pow(25.0,pow(bandwidth.depth/127.0,1.5))-1.0; + if ((value<64)&&(bandwidth.depth>=64)) tmp=1.0; + bandwidth.relbw=(value/64.0-1.0)*tmp+1.0; + if (bandwidth.relbw<0.01) bandwidth.relbw=0.01; } else { - bandwidth.relbw=pow(25.0,(value-64.0)/64.0*(bandwidth.depth/64.0)); + bandwidth.relbw=pow(25.0,(value-64.0)/64.0*(bandwidth.depth/64.0)); }; }; -void Controller::setmodwheel(int value){ +void Controller::setmodwheel(int value) +{ modwheel.data=value; if (modwheel.exponential==0) { - REALTYPE tmp=pow(25.0,pow(modwheel.depth/127.0,1.5)*2.0)/25.0; - if ((value<64)&&(modwheel.depth>=64)) tmp=1.0; - modwheel.relmod=(value/64.0-1.0)*tmp+1.0; - if (modwheel.relmod<0.0) modwheel.relmod=0.0; - } else modwheel.relmod=pow(25.0,(value-64.0)/64.0*(modwheel.depth/80.0)); + REALTYPE tmp=pow(25.0,pow(modwheel.depth/127.0,1.5)*2.0)/25.0; + if ((value<64)&&(modwheel.depth>=64)) tmp=1.0; + modwheel.relmod=(value/64.0-1.0)*tmp+1.0; + if (modwheel.relmod<0.0) modwheel.relmod=0.0; + } else modwheel.relmod=pow(25.0,(value-64.0)/64.0*(modwheel.depth/80.0)); }; -void Controller::setfmamp(int value){ +void Controller::setfmamp(int value) +{ fmamp.data=value; fmamp.relamp=value/127.0; if (fmamp.receive!=0) fmamp.relamp=value/127.0; - else fmamp.relamp=1.0; + else fmamp.relamp=1.0; }; -void Controller::setvolume(int value){ +void Controller::setvolume(int value) +{ volume.data=value; if (volume.receive!=0) volume.volume=pow(0.1,(127-value)/127.0*2.0); - else volume.volume=1.0; + else volume.volume=1.0; }; -void Controller::setsustain(int value){ +void Controller::setsustain(int value) +{ sustain.data=value; if (sustain.receive!=0) sustain.sustain=((value<64) ? 0 : 1 ); - else sustain.sustain=0; + else sustain.sustain=0; }; -void Controller::setportamento(int value){ +void Controller::setportamento(int value) +{ portamento.data=value; if (portamento.receive!=0) portamento.portamento=((value<64) ? 0 : 1 ); }; // I added a third argument to pass legato status, // when legatoflag is true it means "there's a legato in progress". -int Controller::initportamento(REALTYPE oldfreq,REALTYPE newfreq,bool legatoflag){ +int Controller::initportamento(REALTYPE oldfreq,REALTYPE newfreq,bool legatoflag) +{ portamento.x=0.0; - if (legatoflag){ // Legato in progress - if (portamento.portamento==0) return(0); + if (legatoflag) { // Legato in progress + if (portamento.portamento==0) return(0); } else { // No legato, do the original if...return - if ((portamento.used!=0) || (portamento.portamento==0)) return(0); + if ((portamento.used!=0) || (portamento.portamento==0)) return(0); }; REALTYPE portamentotime=pow(100.0,portamento.time/127.0)/50.0;//portamento time in seconds - if ((portamento.updowntimestretch>=64)&&(newfreq<oldfreq)){ - if (portamento.updowntimestretch==127) return(0); - portamentotime*=pow(0.1,(portamento.updowntimestretch-64)/63.0); - } - if ((portamento.updowntimestretch<64)&&(newfreq>oldfreq)){ - if (portamento.updowntimestretch==0) return(0); - portamentotime*=pow(0.1,(64.0-portamento.updowntimestretch)/64.0); + if ((portamento.updowntimestretch>=64)&&(newfreq<oldfreq)) { + if (portamento.updowntimestretch==127) return(0); + portamentotime*=pow(0.1,(portamento.updowntimestretch-64)/63.0); + } + if ((portamento.updowntimestretch<64)&&(newfreq>oldfreq)) { + if (portamento.updowntimestretch==0) return(0); + portamentotime*=pow(0.1,(64.0-portamento.updowntimestretch)/64.0); }; - + portamento.dx=SOUND_BUFFER_SIZE/(portamentotime*SAMPLE_RATE); portamento.origfreqrap=oldfreq/newfreq; - - REALTYPE tmprap=( (portamento.origfreqrap>1.0) ? - (portamento.origfreqrap) : - (1.0/portamento.origfreqrap) ); - + + REALTYPE tmprap=( (portamento.origfreqrap>1.0) ? + (portamento.origfreqrap) : + (1.0/portamento.origfreqrap) ); + REALTYPE thresholdrap=pow(2.0,portamento.pitchthresh/12.0); if ((portamento.pitchthreshtype==0) && (tmprap-0.00001>thresholdrap) ) return(0); if ((portamento.pitchthreshtype==1) && (tmprap+0.00001<thresholdrap) ) return(0); @@ -201,34 +218,38 @@ int Controller::initportamento(REALTYPE oldfreq,REALTYPE newfreq,bool legatoflag return (1); }; -void Controller::updateportamento(){ +void Controller::updateportamento() +{ if (portamento.used==0) return; - + portamento.x+=portamento.dx; if (portamento.x>1.0) { - portamento.x=1.0; - portamento.used=0; + portamento.x=1.0; + portamento.used=0; }; portamento.freqrap=(1.0-portamento.x)*portamento.origfreqrap+portamento.x; }; -void Controller::setresonancecenter(int value){ +void Controller::setresonancecenter(int value) +{ resonancecenter.data=value; resonancecenter.relcenter=pow(3.0,(value-64.0)/64.0*(resonancecenter.depth/64.0)); }; -void Controller::setresonancebw(int value){ +void Controller::setresonancebw(int value) +{ resonancebandwidth.data=value; resonancebandwidth.relbw=pow(1.5,(value-64.0)/64.0*(resonancebandwidth.depth/127.0)); }; //Returns 0 if there is NRPN or 1 if there is not -int Controller::getnrpn(int *parhi, int *parlo, int *valhi, int *vallo){ +int Controller::getnrpn(int *parhi, int *parlo, int *valhi, int *vallo) +{ if (NRPN.receive==0) return(1); - if ((NRPN.parhi<0)||(NRPN.parlo<0)||(NRPN.valhi<0)||(NRPN.vallo<0)) - return(1); - + if ((NRPN.parhi<0)||(NRPN.parlo<0)||(NRPN.valhi<0)||(NRPN.vallo<0)) + return(1); + *parhi=NRPN.parhi; *parlo=NRPN.parlo; *valhi=NRPN.valhi; @@ -237,24 +258,32 @@ int Controller::getnrpn(int *parhi, int *parlo, int *valhi, int *vallo){ }; -void Controller::setparameternumber(unsigned int type,int value){ - switch(type){ - case C_nrpnhi:NRPN.parhi=value; - NRPN.valhi=-1;NRPN.vallo=-1;//clear the values - break; - case C_nrpnlo:NRPN.parlo=value; - NRPN.valhi=-1;NRPN.vallo=-1;//clear the values - break; - case C_dataentryhi:if ((NRPN.parhi>=0)&&(NRPN.parlo>=0)) NRPN.valhi=value; - break; - case C_dataentrylo:if ((NRPN.parhi>=0)&&(NRPN.parlo>=0)) NRPN.vallo=value; - break; +void Controller::setparameternumber(unsigned int type,int value) +{ + switch (type) { + case C_nrpnhi: + NRPN.parhi=value; + NRPN.valhi=-1; + NRPN.vallo=-1;//clear the values + break; + case C_nrpnlo: + NRPN.parlo=value; + NRPN.valhi=-1; + NRPN.vallo=-1;//clear the values + break; + case C_dataentryhi: + if ((NRPN.parhi>=0)&&(NRPN.parlo>=0)) NRPN.valhi=value; + break; + case C_dataentrylo: + if ((NRPN.parhi>=0)&&(NRPN.parlo>=0)) NRPN.vallo=value; + break; }; }; -void Controller::add2XML(XMLwrapper *xml){ +void Controller::add2XML(XMLwrapper *xml) +{ xml->addpar("pitchwheel_bendrange",pitchwheel.bendrange); xml->addparbool("expression_receive",expression.receive); @@ -279,7 +308,8 @@ void Controller::add2XML(XMLwrapper *xml){ xml->addpar("resonance_bandwidth_depth",resonancebandwidth.depth); }; -void Controller::getfromXML(XMLwrapper *xml){ +void Controller::getfromXML(XMLwrapper *xml) +{ pitchwheel.bendrange=xml->getpar("pitchwheel_bendrange",pitchwheel.bendrange,-6400,6400); expression.receive=xml->getparbool("expression_receive",expression.receive); diff --git a/src/Params/Controller.h b/src/Params/Controller.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Controller.h - (Midi) Controllers implementation Copyright (C) 2002-2005 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 + 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, @@ -28,152 +28,153 @@ #include "../Misc/XMLwrapper.h" /**(Midi) Controllers implementation*/ -class Controller{ - public: - Controller(); - ~Controller(); - void resetall(); +class Controller +{ +public: + Controller(); + ~Controller(); + void resetall(); - void add2XML(XMLwrapper *xml); - void defaults(); - void getfromXML(XMLwrapper *xml); + void add2XML(XMLwrapper *xml); + void defaults(); + void getfromXML(XMLwrapper *xml); //Controllers functions - void setpitchwheel(int value); - void setpitchwheelbendrange(unsigned short int value); - void setexpression(int value); - void setpanning(int value); - void setfiltercutoff(int value); - void setfilterq(int value); - void setbandwidth(int value); - void setmodwheel(int value); - void setfmamp(int value); - void setvolume(int value); - void setsustain(int value); - void setportamento(int value); - void setresonancecenter(int value); - void setresonancebw(int value); - - - void setparameternumber(unsigned int type,int value);//used for RPN and NRPN's - int getnrpn(int *parhi, int *parlo, int *valhi, int *vallo); - - int initportamento(REALTYPE oldfreq,REALTYPE newfreq,bool legatoflag);//returns 1 if the portamento's conditions are true, else return 0 - void updateportamento(); //update portamento values - - // Controllers values + void setpitchwheel(int value); + void setpitchwheelbendrange(unsigned short int value); + void setexpression(int value); + void setpanning(int value); + void setfiltercutoff(int value); + void setfilterq(int value); + void setbandwidth(int value); + void setmodwheel(int value); + void setfmamp(int value); + void setvolume(int value); + void setsustain(int value); + void setportamento(int value); + void setresonancecenter(int value); + void setresonancebw(int value); + + + void setparameternumber(unsigned int type,int value);//used for RPN and NRPN's + int getnrpn(int *parhi, int *parlo, int *valhi, int *vallo); + + int initportamento(REALTYPE oldfreq,REALTYPE newfreq,bool legatoflag);//returns 1 if the portamento's conditions are true, else return 0 + void updateportamento(); //update portamento values + + // Controllers values struct {//Pitch Wheel - int data; - short int bendrange;//bendrange is in cents - REALTYPE relfreq;//the relative frequency (default is 1.0) + int data; + short int bendrange;//bendrange is in cents + REALTYPE relfreq;//the relative frequency (default is 1.0) } pitchwheel; - - struct{//Expression - int data; - REALTYPE relvolume; - unsigned char receive; + + struct {//Expression + int data; + REALTYPE relvolume; + unsigned char receive; } expression; - struct{//Panning - int data; - REALTYPE pan; - unsigned char depth; + struct {//Panning + int data; + REALTYPE pan; + unsigned char depth; } panning; - - struct{//Filter cutoff - int data; - REALTYPE relfreq; - unsigned char depth; + + struct {//Filter cutoff + int data; + REALTYPE relfreq; + unsigned char depth; } filtercutoff; - struct{//Filter Q - int data; - REALTYPE relq; - unsigned char depth; + struct {//Filter Q + int data; + REALTYPE relq; + unsigned char depth; } filterq; - struct{//Bandwidth - int data; - REALTYPE relbw; - unsigned char depth; - unsigned char exponential; + struct {//Bandwidth + int data; + REALTYPE relbw; + unsigned char depth; + unsigned char exponential; } bandwidth; struct {//Modulation Wheel - int data; - REALTYPE relmod; - unsigned char depth; - unsigned char exponential; + int data; + REALTYPE relmod; + unsigned char depth; + unsigned char exponential; } modwheel; - struct{//FM amplitude - int data; - REALTYPE relamp; - unsigned char receive; + struct {//FM amplitude + int data; + REALTYPE relamp; + unsigned char receive; } fmamp; - struct{//Volume - int data; - REALTYPE volume; - unsigned char receive; + struct {//Volume + int data; + REALTYPE volume; + unsigned char receive; } volume; - struct{//Sustain - int data,sustain; - unsigned char receive; + struct {//Sustain + int data,sustain; + unsigned char receive; } sustain; - struct{/**<Portamento*/ - //parameters - int data; - unsigned char portamento; - - unsigned char receive,time; - /**pitchthresh is the threshold of enabling protamento \todo see if this should be an int*/ - unsigned char pitchthresh; - /**pitchthreshtype -> enable the portamento only below(0)/above(1) the threshold*/ - unsigned char pitchthreshtype; + struct {/**<Portamento*/ + //parameters + int data; + unsigned char portamento; + + unsigned char receive,time; + /**pitchthresh is the threshold of enabling protamento \todo see if this should be an int*/ + unsigned char pitchthresh; + /**pitchthreshtype -> enable the portamento only below(0)/above(1) the threshold*/ + unsigned char pitchthreshtype; /**this value represent how the portamento time is reduced * 0 - for down portamento, 1..63 - the up portamento's time is smaller than the down portamento - * 64 - the portamento time is always the same - * 64-126 - the down portamento's time is smaller than the up portamento - * 127 - for upper portamento + * 64 - the portamento time is always the same + * 64-126 - the down portamento's time is smaller than the up portamento + * 127 - for upper portamento * 'up portanemto' means when the frequency is rising (eg: the portamento is from 200Hz to 300 Hz) * 'down portanemto' means when the frequency is lowering (eg: the portamento is from 300Hz to 200 Hz) */ - unsigned char updowntimestretch; - - REALTYPE freqrap;/**<this value is used to compute the actual portamento*/ - int noteusing;/**this is used by the Part for knowing which note uses the portamento*/ - int used;/**<if a the portamento is used by a note \todo see if this can be a bool*/ - //internal data - REALTYPE x,dx;//x is from 0.0 (start portamento) to 1.0 (finished portamento), dx is x increment - REALTYPE origfreqrap;// this is used for computing oldfreq value from x + unsigned char updowntimestretch; + + REALTYPE freqrap;/**<this value is used to compute the actual portamento*/ + int noteusing;/**this is used by the Part for knowing which note uses the portamento*/ + int used;/**<if a the portamento is used by a note \todo see if this can be a bool*/ + //internal data + REALTYPE x,dx;//x is from 0.0 (start portamento) to 1.0 (finished portamento), dx is x increment + REALTYPE origfreqrap;// this is used for computing oldfreq value from x } portamento; - - struct{//Resonance Center Frequency - int data; - REALTYPE relcenter; - unsigned char depth; + + struct {//Resonance Center Frequency + int data; + REALTYPE relcenter; + unsigned char depth; } resonancecenter; - struct{//Resonance Bandwidth - int data; - REALTYPE relbw; - unsigned char depth; + struct {//Resonance Bandwidth + int data; + REALTYPE relbw; + unsigned char depth; } resonancebandwidth; - + /** RPN and NPRPN */ - struct{//nrpn - int parhi,parlo; - int valhi,vallo; - unsigned char receive;//this is saved to disk by Master + struct {//nrpn + int parhi,parlo; + int valhi,vallo; + unsigned char receive;//this is saved to disk by Master } NRPN; - - private: + +private: }; #endif diff --git a/src/Params/EnvelopeParams.C b/src/Params/EnvelopeParams.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + EnvelopeParams.C - Parameters for Envelope Copyright (C) 2002-2005 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 + 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, @@ -26,31 +26,40 @@ #include <stdlib.h> #include "EnvelopeParams.h" -EnvelopeParams::EnvelopeParams(unsigned char Penvstretch_,unsigned char Pforcedrelease_):Presets(){ +EnvelopeParams::EnvelopeParams(unsigned char Penvstretch_,unsigned char Pforcedrelease_):Presets() +{ int i; - - PA_dt=10;PD_dt=10;PR_dt=10;PA_val=64;PD_val=64;PS_val=64;PR_val=64; - - for (i=0;i<MAX_ENVELOPE_POINTS;i++){ - Penvdt[i]=32; - Penvval[i]=64; + + PA_dt=10; + PD_dt=10; + PR_dt=10; + PA_val=64; + PD_val=64; + PS_val=64; + PR_val=64; + + for (i=0;i<MAX_ENVELOPE_POINTS;i++) { + Penvdt[i]=32; + Penvval[i]=64; }; Penvdt[0]=0;//no used Penvsustain=1; Penvpoints=1; Envmode=1; Penvstretch=Penvstretch_; - Pforcedrelease=Pforcedrelease_; + Pforcedrelease=Pforcedrelease_; Pfreemode=1; Plinearenvelope=0; - + store2defaults(); }; -EnvelopeParams::~EnvelopeParams(){ +EnvelopeParams::~EnvelopeParams() +{ }; -REALTYPE EnvelopeParams::getdt(char i){ +REALTYPE EnvelopeParams::getdt(char i) +{ REALTYPE result=(pow(2.0,Penvdt[(int)i]/127.0*12.0)-1.0)*10.0;//miliseconds return(result); }; @@ -59,49 +68,71 @@ REALTYPE EnvelopeParams::getdt(char i){ /* * ADSR/ASR... initialisations */ -void EnvelopeParams::ADSRinit(char A_dt,char D_dt,char S_val,char R_dt){ +void EnvelopeParams::ADSRinit(char A_dt,char D_dt,char S_val,char R_dt) +{ setpresettype("Penvamplitude"); Envmode=1; - PA_dt=A_dt;PD_dt=D_dt;PS_val=S_val;PR_dt=R_dt; + PA_dt=A_dt; + PD_dt=D_dt; + PS_val=S_val; + PR_dt=R_dt; Pfreemode=0; converttofree(); store2defaults(); }; -void EnvelopeParams::ADSRinit_dB(char A_dt,char D_dt,char S_val,char R_dt){ +void EnvelopeParams::ADSRinit_dB(char A_dt,char D_dt,char S_val,char R_dt) +{ setpresettype("Penvamplitude"); Envmode=2; - PA_dt=A_dt;PD_dt=D_dt;PS_val=S_val;PR_dt=R_dt; + PA_dt=A_dt; + PD_dt=D_dt; + PS_val=S_val; + PR_dt=R_dt; Pfreemode=0; converttofree(); store2defaults(); }; -void EnvelopeParams::ASRinit(char A_val,char A_dt,char R_val,char R_dt){ +void EnvelopeParams::ASRinit(char A_val,char A_dt,char R_val,char R_dt) +{ setpresettype("Penvfrequency"); Envmode=3; - PA_val=A_val;PA_dt=A_dt;PR_val=R_val;PR_dt=R_dt; + PA_val=A_val; + PA_dt=A_dt; + PR_val=R_val; + PR_dt=R_dt; Pfreemode=0; converttofree(); store2defaults(); }; -void EnvelopeParams::ADSRinit_filter(char A_val,char A_dt,char D_val,char D_dt,char R_dt,char R_val){ +void EnvelopeParams::ADSRinit_filter(char A_val,char A_dt,char D_val,char D_dt,char R_dt,char R_val) +{ setpresettype("Penvfilter"); Envmode=4; - PA_val=A_val;PA_dt=A_dt;PD_val=D_val;PD_dt=D_dt;PR_dt=R_dt;PR_val=R_val; + PA_val=A_val; + PA_dt=A_dt; + PD_val=D_val; + PD_dt=D_dt; + PR_dt=R_dt; + PR_val=R_val; Pfreemode=0; converttofree(); store2defaults(); }; -void EnvelopeParams::ASRinit_bw(char A_val,char A_dt,char R_val,char R_dt){ +void EnvelopeParams::ASRinit_bw(char A_val,char A_dt,char R_val,char R_dt) +{ setpresettype("Penvbandwidth"); Envmode=5; - PA_val=A_val;PA_dt=A_dt;PR_val=R_val;PR_dt=R_dt; + PA_val=A_val; + PA_dt=A_dt; + PR_val=R_val; + PR_dt=R_dt; Pfreemode=0; converttofree(); store2defaults(); @@ -110,39 +141,69 @@ void EnvelopeParams::ASRinit_bw(char A_val,char A_dt,char R_val,char R_dt){ /* * Convert the Envelope to freemode */ -void EnvelopeParams::converttofree(){ - switch (Envmode){ - case 1: Penvpoints=4;Penvsustain=2; - Penvval[0]=0;Penvdt[1]=PA_dt;Penvval[1]=127; - Penvdt[2]=PD_dt;Penvval[2]=PS_val; - Penvdt[3]=PR_dt;Penvval[3]=0; - break; - case 2: Penvpoints=4;Penvsustain=2; - Penvval[0]=0;Penvdt[1]=PA_dt; - Penvval[1]=127;Penvdt[2]=PD_dt; - Penvval[2]=PS_val;Penvdt[3]=PR_dt;Penvval[3]=0; - break; - case 3: Penvpoints=3;Penvsustain=1; - Penvval[0]=PA_val;Penvdt[1]=PA_dt; - Penvval[1]=64;Penvdt[2]=PR_dt;Penvval[2]=PR_val; - break; - case 4: Penvpoints=4;Penvsustain=2; - Penvval[0]=PA_val;Penvdt[1]=PA_dt; - Penvval[1]=PD_val;Penvdt[2]=PD_dt;Penvval[2]=64; - Penvdt[3]=PR_dt;Penvval[3]=PR_val; - break; - case 5: Penvpoints=3;Penvsustain=1; - Penvval[0]=PA_val;Penvdt[1]=PA_dt; - Penvval[1]=64;Penvdt[2]=PR_dt;Penvval[2]=PR_val; - break; +void EnvelopeParams::converttofree() +{ + switch (Envmode) { + case 1: + Penvpoints=4; + Penvsustain=2; + Penvval[0]=0; + Penvdt[1]=PA_dt; + Penvval[1]=127; + Penvdt[2]=PD_dt; + Penvval[2]=PS_val; + Penvdt[3]=PR_dt; + Penvval[3]=0; + break; + case 2: + Penvpoints=4; + Penvsustain=2; + Penvval[0]=0; + Penvdt[1]=PA_dt; + Penvval[1]=127; + Penvdt[2]=PD_dt; + Penvval[2]=PS_val; + Penvdt[3]=PR_dt; + Penvval[3]=0; + break; + case 3: + Penvpoints=3; + Penvsustain=1; + Penvval[0]=PA_val; + Penvdt[1]=PA_dt; + Penvval[1]=64; + Penvdt[2]=PR_dt; + Penvval[2]=PR_val; + break; + case 4: + Penvpoints=4; + Penvsustain=2; + Penvval[0]=PA_val; + Penvdt[1]=PA_dt; + Penvval[1]=PD_val; + Penvdt[2]=PD_dt; + Penvval[2]=64; + Penvdt[3]=PR_dt; + Penvval[3]=PR_val; + break; + case 5: + Penvpoints=3; + Penvsustain=1; + Penvval[0]=PA_val; + Penvdt[1]=PA_dt; + Penvval[1]=64; + Penvdt[2]=PR_dt; + Penvval[2]=PR_val; + break; }; }; -void EnvelopeParams::add2XML(XMLwrapper *xml){ - xml->addparbool("free_mode",Pfreemode); +void EnvelopeParams::add2XML(XMLwrapper *xml) +{ + xml->addparbool("free_mode",Pfreemode); xml->addpar("env_points",Penvpoints); xml->addpar("env_sustain",Penvsustain); xml->addpar("env_stretch",Penvstretch); @@ -156,20 +217,21 @@ void EnvelopeParams::add2XML(XMLwrapper *xml){ xml->addpar("S_val",PS_val); xml->addpar("R_val",PR_val); - if ((Pfreemode!=0)||(!xml->minimal)){ - for (int i=0;i<Penvpoints;i++){ - xml->beginbranch("POINT",i); - if (i!=0) xml->addpar("dt",Penvdt[i]); - xml->addpar("val",Penvval[i]); - xml->endbranch(); - }; + if ((Pfreemode!=0)||(!xml->minimal)) { + for (int i=0;i<Penvpoints;i++) { + xml->beginbranch("POINT",i); + if (i!=0) xml->addpar("dt",Penvdt[i]); + xml->addpar("val",Penvval[i]); + xml->endbranch(); + }; }; }; -void EnvelopeParams::getfromXML(XMLwrapper *xml){ - Pfreemode=xml->getparbool("free_mode",Pfreemode); +void EnvelopeParams::getfromXML(XMLwrapper *xml) +{ + Pfreemode=xml->getparbool("free_mode",Pfreemode); Penvpoints=xml->getpar127("env_points",Penvpoints); Penvsustain=xml->getpar127("env_sustain",Penvsustain); Penvstretch=xml->getpar127("env_stretch",Penvstretch); @@ -184,18 +246,19 @@ void EnvelopeParams::getfromXML(XMLwrapper *xml){ PS_val=xml->getpar127("S_val",PS_val); PR_val=xml->getpar127("R_val",PR_val); - for (int i=0;i<Penvpoints;i++){ + for (int i=0;i<Penvpoints;i++) { if (xml->enterbranch("POINT",i)==0) continue; - if (i!=0) Penvdt[i]=xml->getpar127("dt",Penvdt[i]); - Penvval[i]=xml->getpar127("val",Penvval[i]); - xml->exitbranch(); + if (i!=0) Penvdt[i]=xml->getpar127("dt",Penvdt[i]); + Penvval[i]=xml->getpar127("val",Penvval[i]); + xml->exitbranch(); }; - + if (!Pfreemode) converttofree(); }; -void EnvelopeParams::defaults(){ +void EnvelopeParams::defaults() +{ Penvstretch=Denvstretch; Pforcedrelease=Dforcedrelease; Plinearenvelope=Dlinearenvelope; @@ -210,7 +273,8 @@ void EnvelopeParams::defaults(){ converttofree(); }; -void EnvelopeParams::store2defaults(){ +void EnvelopeParams::store2defaults() +{ Denvstretch=Penvstretch; Dforcedrelease=Pforcedrelease; Dlinearenvelope=Plinearenvelope; diff --git a/src/Params/EnvelopeParams.h b/src/Params/EnvelopeParams.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + EnvelopeParams.h - Parameters for Envelope Copyright (C) 2002-2005 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 + 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, @@ -30,53 +30,54 @@ #define MAX_ENVELOPE_POINTS 40 #define MIN_ENVELOPE_DB -40 -class EnvelopeParams:public Presets{ - public: - EnvelopeParams(unsigned char Penvstretch_,unsigned char Pforcedrelease_); - ~EnvelopeParams(); - void ADSRinit(char A_dt,char D_dt,char S_val,char R_dt); - void ADSRinit_dB(char A_dt,char D_dt,char S_val,char R_dt); - void ASRinit(char A_val,char A_dt,char R_val,char R_dt); - void ADSRinit_filter(char A_val,char A_dt,char D_val,char D_dt,char R_dt,char R_val); - void ASRinit_bw(char A_val,char A_dt,char R_val,char R_dt); - void converttofree(); - - void add2XML(XMLwrapper *xml); - void defaults(); - void getfromXML(XMLwrapper *xml); - - REALTYPE getdt(char i); - - /* MIDI Parameters */ - unsigned char Pfreemode;//1 daca este in modul free sau 0 daca este in mod ADSR,ASR,... - unsigned char Penvpoints; - unsigned char Penvsustain;//127 pentru dezactivat - unsigned char Penvdt[MAX_ENVELOPE_POINTS]; - unsigned char Penvval[MAX_ENVELOPE_POINTS]; - unsigned char Penvstretch;//64=normal stretch (piano-like), 0=no stretch - unsigned char Pforcedrelease;//0 - OFF, 1 - ON - unsigned char Plinearenvelope;//if the amplitude envelope is linear - - unsigned char PA_dt,PD_dt,PR_dt, - PA_val,PD_val,PS_val,PR_val; - - - - int Envmode;// 1 for ADSR parameters (linear amplitude) - // 2 for ADSR_dB parameters (dB amplitude) - // 3 for ASR parameters (frequency LFO) - // 4 for ADSR_filter parameters (filter parameters) - // 5 for ASR_bw parameters (bandwidth parameters) - - private: - void store2defaults(); - - /* Default parameters */ - unsigned char Denvstretch; - unsigned char Dforcedrelease; - unsigned char Dlinearenvelope; - unsigned char DA_dt,DD_dt,DR_dt, - DA_val,DD_val,DS_val,DR_val; +class EnvelopeParams:public Presets +{ +public: + EnvelopeParams(unsigned char Penvstretch_,unsigned char Pforcedrelease_); + ~EnvelopeParams(); + void ADSRinit(char A_dt,char D_dt,char S_val,char R_dt); + void ADSRinit_dB(char A_dt,char D_dt,char S_val,char R_dt); + void ASRinit(char A_val,char A_dt,char R_val,char R_dt); + void ADSRinit_filter(char A_val,char A_dt,char D_val,char D_dt,char R_dt,char R_val); + void ASRinit_bw(char A_val,char A_dt,char R_val,char R_dt); + void converttofree(); + + void add2XML(XMLwrapper *xml); + void defaults(); + void getfromXML(XMLwrapper *xml); + + REALTYPE getdt(char i); + + /* MIDI Parameters */ + unsigned char Pfreemode;//1 daca este in modul free sau 0 daca este in mod ADSR,ASR,... + unsigned char Penvpoints; + unsigned char Penvsustain;//127 pentru dezactivat + unsigned char Penvdt[MAX_ENVELOPE_POINTS]; + unsigned char Penvval[MAX_ENVELOPE_POINTS]; + unsigned char Penvstretch;//64=normal stretch (piano-like), 0=no stretch + unsigned char Pforcedrelease;//0 - OFF, 1 - ON + unsigned char Plinearenvelope;//if the amplitude envelope is linear + + unsigned char PA_dt,PD_dt,PR_dt, + PA_val,PD_val,PS_val,PR_val; + + + + int Envmode;// 1 for ADSR parameters (linear amplitude) + // 2 for ADSR_dB parameters (dB amplitude) + // 3 for ASR parameters (frequency LFO) + // 4 for ADSR_filter parameters (filter parameters) + // 5 for ASR_bw parameters (bandwidth parameters) + +private: + void store2defaults(); + + /* Default parameters */ + unsigned char Denvstretch; + unsigned char Dforcedrelease; + unsigned char Dlinearenvelope; + unsigned char DA_dt,DD_dt,DR_dt, + DA_val,DD_val,DS_val,DR_val; }; diff --git a/src/Params/FilterParams.C b/src/Params/FilterParams.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + FilterParams.C - Parameters for filter Copyright (C) 2002-2005 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 + 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, @@ -25,21 +25,24 @@ #include <stdlib.h> #include "FilterParams.h" -FilterParams::FilterParams(unsigned char Ptype_,unsigned char Pfreq_,unsigned char Pq_):Presets(){ +FilterParams::FilterParams(unsigned char Ptype_,unsigned char Pfreq_,unsigned char Pq_):Presets() +{ setpresettype("Pfilter"); Dtype=Ptype_; Dfreq=Pfreq_; Dq=Pq_; changed=false; - defaults(); + defaults(); }; -FilterParams::~FilterParams(){ +FilterParams::~FilterParams() +{ }; -void FilterParams::defaults(){ +void FilterParams::defaults() +{ Ptype=Dtype; Pfreq=Dfreq; Pq=Dq; @@ -48,13 +51,13 @@ void FilterParams::defaults(){ Pfreqtrack=64; Pgain=64; Pcategory=0; - + Pnumformants=3; Pformantslowness=64; - for (int j=0;j<FF_MAX_VOWELS;j++){ - defaults(j); + for (int j=0;j<FF_MAX_VOWELS;j++) { + defaults(j); }; - + Psequencesize=3; for (int i=0;i<FF_MAX_SEQUENCE;i++) Psequence[i].nvowel=i%FF_MAX_VOWELS; @@ -65,25 +68,27 @@ void FilterParams::defaults(){ Pvowelclearness=64; }; -void FilterParams::defaults(int n){ +void FilterParams::defaults(int n) +{ int j=n; - for (int i=0;i<FF_MAX_FORMANTS;i++){ - Pvowels[j].formants[i].freq=(int)(RND*127.0);//some random freqs - Pvowels[j].formants[i].q=64; - Pvowels[j].formants[i].amp=127; - }; + for (int i=0;i<FF_MAX_FORMANTS;i++) { + Pvowels[j].formants[i].freq=(int)(RND*127.0);//some random freqs + Pvowels[j].formants[i].q=64; + Pvowels[j].formants[i].amp=127; + }; }; /* * Get the parameters from other FilterParams */ - -void FilterParams::getfromFilterParams(FilterParams *pars){ + +void FilterParams::getfromFilterParams(FilterParams *pars) +{ defaults(); - + if (pars==NULL) return; - + Ptype=pars->Ptype; Pfreq=pars->Pfreq; Pq=pars->Pq; @@ -92,17 +97,17 @@ void FilterParams::getfromFilterParams(FilterParams *pars){ Pfreqtrack=pars->Pfreqtrack; Pgain=pars->Pgain; Pcategory=pars->Pcategory; - + Pnumformants=pars->Pnumformants; Pformantslowness=pars->Pformantslowness; - for (int j=0;j<FF_MAX_VOWELS;j++){ - for (int i=0;i<FF_MAX_FORMANTS;i++){ - Pvowels[j].formants[i].freq=pars->Pvowels[j].formants[i].freq; - Pvowels[j].formants[i].q=pars->Pvowels[j].formants[i].q; - Pvowels[j].formants[i].amp=pars->Pvowels[j].formants[i].amp; - }; + for (int j=0;j<FF_MAX_VOWELS;j++) { + for (int i=0;i<FF_MAX_FORMANTS;i++) { + Pvowels[j].formants[i].freq=pars->Pvowels[j].formants[i].freq; + Pvowels[j].formants[i].q=pars->Pvowels[j].formants[i].q; + Pvowels[j].formants[i].amp=pars->Pvowels[j].formants[i].amp; + }; }; - + Psequencesize=pars->Psequencesize; for (int i=0;i<FF_MAX_SEQUENCE;i++) Psequence[i].nvowel=pars->Psequence[i].nvowel; @@ -117,39 +122,46 @@ void FilterParams::getfromFilterParams(FilterParams *pars){ /* * Parameter control */ -REALTYPE FilterParams::getfreq(){ +REALTYPE FilterParams::getfreq() +{ return((Pfreq/64.0-1.0)*5.0); }; -REALTYPE FilterParams::getq(){ +REALTYPE FilterParams::getq() +{ return(exp(pow((REALTYPE) Pq/127.0,2)*log(1000.0))-0.9); }; -REALTYPE FilterParams::getfreqtracking(REALTYPE notefreq){ +REALTYPE FilterParams::getfreqtracking(REALTYPE notefreq) +{ return(log(notefreq/440.0)*(Pfreqtrack-64.0)/(64.0*LOG_2)); }; -REALTYPE FilterParams::getgain(){ +REALTYPE FilterParams::getgain() +{ return((Pgain/64.0-1.0)*30.0);//-30..30dB }; /* * Get the center frequency of the formant's graph */ -REALTYPE FilterParams::getcenterfreq(){ +REALTYPE FilterParams::getcenterfreq() +{ return(10000.0*pow(10,-(1.0-Pcenterfreq/127.0)*2.0)); }; /* * Get the number of octave that the formant functions applies to */ -REALTYPE FilterParams::getoctavesfreq(){ +REALTYPE FilterParams::getoctavesfreq() +{ return(0.25+10.0*Poctavesfreq/127.0); }; /* * Get the frequency from x, where x is [0..1] */ -REALTYPE FilterParams::getfreqx(REALTYPE x){ +REALTYPE FilterParams::getfreqx(REALTYPE x) +{ if (x>1.0) x=1.0; REALTYPE octf=pow(2.0,getoctavesfreq()); return(getcenterfreq()/sqrt(octf)*pow(octf,x)); @@ -158,7 +170,8 @@ REALTYPE FilterParams::getfreqx(REALTYPE x){ /* * Get the x coordinate from frequency (used by the UI) */ -REALTYPE FilterParams::getfreqpos(REALTYPE freq){ +REALTYPE FilterParams::getfreqpos(REALTYPE freq) +{ return((log(freq)-log(getfreqx(0.0)))/log(2.0)/getoctavesfreq()); }; @@ -166,7 +179,8 @@ REALTYPE FilterParams::getfreqpos(REALTYPE freq){ /* * Get the freq. response of the formant filter */ -void FilterParams::formantfilterH(int nvowel,int nfreqs,REALTYPE *freqs){ +void FilterParams::formantfilterH(int nvowel,int nfreqs,REALTYPE *freqs) +{ REALTYPE c[3],d[3]; REALTYPE filter_freq,filter_q,filter_amp; REALTYPE omega,sn,cs,alpha; @@ -174,55 +188,56 @@ void FilterParams::formantfilterH(int nvowel,int nfreqs,REALTYPE *freqs){ for (int i=0;i<nfreqs;i++) freqs[i]=0.0; //for each formant... - for (int nformant=0;nformant<Pnumformants;nformant++){ - //compute formant parameters(frequency,amplitude,etc.) - filter_freq=getformantfreq(Pvowels[nvowel].formants[nformant].freq); - filter_q=getformantq(Pvowels[nvowel].formants[nformant].q)*getq(); - if (Pstages>0) filter_q=(filter_q>1.0 ? pow(filter_q,1.0/(Pstages+1)) : filter_q); - - filter_amp=getformantamp(Pvowels[nvowel].formants[nformant].amp); - - - if (filter_freq<=(SAMPLE_RATE/2-100.0)){ - omega=2*PI*filter_freq/SAMPLE_RATE; - sn=sin(omega); - cs=cos(omega); - alpha=sn/(2*filter_q); - REALTYPE tmp=1+alpha; - c[0]=alpha/tmp*sqrt(filter_q+1); - c[1]=0; - c[2]=-alpha/tmp*sqrt(filter_q+1); - d[1]=-2*cs/tmp*(-1); - d[2]=(1-alpha)/tmp*(-1); - } else continue; - - - for (int i=0;i<nfreqs;i++) { - REALTYPE freq=getfreqx(i/(REALTYPE) nfreqs); - if (freq>SAMPLE_RATE/2) { - for (int tmp=i;tmp<nfreqs;tmp++) freqs[tmp]=0.0; - break; - }; - REALTYPE fr=freq/SAMPLE_RATE*PI*2.0; - REALTYPE x=c[0],y=0.0; - for (int n=1;n<3;n++){ - x+=cos(n*fr)*c[n]; - y-=sin(n*fr)*c[n]; - }; - REALTYPE h=x*x+y*y; - x=1.0;y=0.0; - for (int n=1;n<3;n++){ - x-=cos(n*fr)*d[n]; - y+=sin(n*fr)*d[n]; - }; - h=h/(x*x+y*y); - - freqs[i]+=pow(h,(Pstages+1.0)/2.0)*filter_amp; - }; + for (int nformant=0;nformant<Pnumformants;nformant++) { + //compute formant parameters(frequency,amplitude,etc.) + filter_freq=getformantfreq(Pvowels[nvowel].formants[nformant].freq); + filter_q=getformantq(Pvowels[nvowel].formants[nformant].q)*getq(); + if (Pstages>0) filter_q=(filter_q>1.0 ? pow(filter_q,1.0/(Pstages+1)) : filter_q); + + filter_amp=getformantamp(Pvowels[nvowel].formants[nformant].amp); + + + if (filter_freq<=(SAMPLE_RATE/2-100.0)) { + omega=2*PI*filter_freq/SAMPLE_RATE; + sn=sin(omega); + cs=cos(omega); + alpha=sn/(2*filter_q); + REALTYPE tmp=1+alpha; + c[0]=alpha/tmp*sqrt(filter_q+1); + c[1]=0; + c[2]=-alpha/tmp*sqrt(filter_q+1); + d[1]=-2*cs/tmp*(-1); + d[2]=(1-alpha)/tmp*(-1); + } else continue; + + + for (int i=0;i<nfreqs;i++) { + REALTYPE freq=getfreqx(i/(REALTYPE) nfreqs); + if (freq>SAMPLE_RATE/2) { + for (int tmp=i;tmp<nfreqs;tmp++) freqs[tmp]=0.0; + break; + }; + REALTYPE fr=freq/SAMPLE_RATE*PI*2.0; + REALTYPE x=c[0],y=0.0; + for (int n=1;n<3;n++) { + x+=cos(n*fr)*c[n]; + y-=sin(n*fr)*c[n]; + }; + REALTYPE h=x*x+y*y; + x=1.0; + y=0.0; + for (int n=1;n<3;n++) { + x-=cos(n*fr)*d[n]; + y+=sin(n*fr)*d[n]; + }; + h=h/(x*x+y*y); + + freqs[i]+=pow(h,(Pstages+1.0)/2.0)*filter_amp; + }; }; for (int i=0;i<nfreqs;i++) { - if (freqs[i]>0.000000001) freqs[i]=rap2dB(freqs[i])+getgain(); - else freqs[i]=-90.0; + if (freqs[i]>0.000000001) freqs[i]=rap2dB(freqs[i])+getgain(); + else freqs[i]=-90.0; }; }; @@ -230,17 +245,20 @@ void FilterParams::formantfilterH(int nvowel,int nfreqs,REALTYPE *freqs){ /* * Transforms a parameter to the real value */ -REALTYPE FilterParams::getformantfreq(unsigned char freq){ +REALTYPE FilterParams::getformantfreq(unsigned char freq) +{ REALTYPE result=getfreqx(freq/127.0); return(result); }; -REALTYPE FilterParams::getformantamp(unsigned char amp){ +REALTYPE FilterParams::getformantamp(unsigned char amp) +{ REALTYPE result=pow(0.1,(1.0-amp/127.0)*4.0); return(result); }; -REALTYPE FilterParams::getformantq(unsigned char q){ +REALTYPE FilterParams::getformantq(unsigned char q) +{ //temp REALTYPE result=pow(25.0,(q-32.0)/64.0); return(result); @@ -248,18 +266,20 @@ REALTYPE FilterParams::getformantq(unsigned char q){ -void FilterParams::add2XMLsection(XMLwrapper *xml,int n){ - int nvowel=n; - for (int nformant=0;nformant<FF_MAX_FORMANTS;nformant++){ - xml->beginbranch("FORMANT",nformant); - xml->addpar("freq",Pvowels[nvowel].formants[nformant].freq); - xml->addpar("amp",Pvowels[nvowel].formants[nformant].amp); - xml->addpar("q",Pvowels[nvowel].formants[nformant].q); - xml->endbranch(); - }; +void FilterParams::add2XMLsection(XMLwrapper *xml,int n) +{ + int nvowel=n; + for (int nformant=0;nformant<FF_MAX_FORMANTS;nformant++) { + xml->beginbranch("FORMANT",nformant); + xml->addpar("freq",Pvowels[nvowel].formants[nformant].freq); + xml->addpar("amp",Pvowels[nvowel].formants[nformant].amp); + xml->addpar("q",Pvowels[nvowel].formants[nformant].q); + xml->endbranch(); + }; }; -void FilterParams::add2XML(XMLwrapper *xml){ +void FilterParams::add2XML(XMLwrapper *xml) +{ //filter parameters xml->addpar("category",Pcategory); xml->addpar("type",Ptype); @@ -270,43 +290,45 @@ void FilterParams::add2XML(XMLwrapper *xml){ xml->addpar("gain",Pgain); //formant filter parameters - if ((Pcategory==1)||(!xml->minimal)){ - xml->beginbranch("FORMANT_FILTER"); - xml->addpar("num_formants",Pnumformants); - xml->addpar("formant_slowness",Pformantslowness); - xml->addpar("vowel_clearness",Pvowelclearness); - xml->addpar("center_freq",Pcenterfreq); - xml->addpar("octaves_freq",Poctavesfreq); - for (int nvowel=0;nvowel<FF_MAX_VOWELS;nvowel++){ - xml->beginbranch("VOWEL",nvowel); - add2XMLsection(xml,nvowel); - xml->endbranch(); - }; - xml->addpar("sequence_size",Psequencesize); - xml->addpar("sequence_stretch",Psequencestretch); - xml->addparbool("sequence_reversed",Psequencereversed); - for (int nseq=0;nseq<FF_MAX_SEQUENCE;nseq++){ - xml->beginbranch("SEQUENCE_POS",nseq); - xml->addpar("vowel_id",Psequence[nseq].nvowel); - xml->endbranch(); - }; - xml->endbranch(); + if ((Pcategory==1)||(!xml->minimal)) { + xml->beginbranch("FORMANT_FILTER"); + xml->addpar("num_formants",Pnumformants); + xml->addpar("formant_slowness",Pformantslowness); + xml->addpar("vowel_clearness",Pvowelclearness); + xml->addpar("center_freq",Pcenterfreq); + xml->addpar("octaves_freq",Poctavesfreq); + for (int nvowel=0;nvowel<FF_MAX_VOWELS;nvowel++) { + xml->beginbranch("VOWEL",nvowel); + add2XMLsection(xml,nvowel); + xml->endbranch(); + }; + xml->addpar("sequence_size",Psequencesize); + xml->addpar("sequence_stretch",Psequencestretch); + xml->addparbool("sequence_reversed",Psequencereversed); + for (int nseq=0;nseq<FF_MAX_SEQUENCE;nseq++) { + xml->beginbranch("SEQUENCE_POS",nseq); + xml->addpar("vowel_id",Psequence[nseq].nvowel); + xml->endbranch(); + }; + xml->endbranch(); }; }; -void FilterParams::getfromXMLsection(XMLwrapper *xml,int n){ - int nvowel=n; - for (int nformant=0;nformant<FF_MAX_FORMANTS;nformant++){ - if (xml->enterbranch("FORMANT",nformant)==0) continue; - Pvowels[nvowel].formants[nformant].freq=xml->getpar127("freq",Pvowels[nvowel].formants[nformant].freq); - Pvowels[nvowel].formants[nformant].amp=xml->getpar127("amp",Pvowels[nvowel].formants[nformant].amp); - Pvowels[nvowel].formants[nformant].q=xml->getpar127("q",Pvowels[nvowel].formants[nformant].q); - xml->exitbranch(); - }; +void FilterParams::getfromXMLsection(XMLwrapper *xml,int n) +{ + int nvowel=n; + for (int nformant=0;nformant<FF_MAX_FORMANTS;nformant++) { + if (xml->enterbranch("FORMANT",nformant)==0) continue; + Pvowels[nvowel].formants[nformant].freq=xml->getpar127("freq",Pvowels[nvowel].formants[nformant].freq); + Pvowels[nvowel].formants[nformant].amp=xml->getpar127("amp",Pvowels[nvowel].formants[nformant].amp); + Pvowels[nvowel].formants[nformant].q=xml->getpar127("q",Pvowels[nvowel].formants[nformant].q); + xml->exitbranch(); + }; }; -void FilterParams::getfromXML(XMLwrapper *xml){ +void FilterParams::getfromXML(XMLwrapper *xml) +{ //filter parameters Pcategory=xml->getpar127("category",Pcategory); Ptype=xml->getpar127("type",Ptype); @@ -317,28 +339,28 @@ void FilterParams::getfromXML(XMLwrapper *xml){ Pgain=xml->getpar127("gain",Pgain); //formant filter parameters - if(xml->enterbranch("FORMANT_FILTER")){ - Pnumformants=xml->getpar127("num_formants",Pnumformants); - Pformantslowness=xml->getpar127("formant_slowness",Pformantslowness); - Pvowelclearness=xml->getpar127("vowel_clearness",Pvowelclearness); - Pcenterfreq=xml->getpar127("center_freq",Pcenterfreq); - Poctavesfreq=xml->getpar127("octaves_freq",Poctavesfreq); - - for (int nvowel=0;nvowel<FF_MAX_VOWELS;nvowel++){ - if (xml->enterbranch("VOWEL",nvowel)==0) continue; - getfromXMLsection(xml,nvowel); - xml->exitbranch(); - }; - Psequencesize=xml->getpar127("sequence_size",Psequencesize); - Psequencestretch=xml->getpar127("sequence_stretch",Psequencestretch); - Psequencereversed=xml->getparbool("sequence_reversed",Psequencereversed); - for (int nseq=0;nseq<FF_MAX_SEQUENCE;nseq++){ - if (xml->enterbranch("SEQUENCE_POS",nseq)==0) continue; - Psequence[nseq].nvowel=xml->getpar("vowel_id",Psequence[nseq].nvowel,0,FF_MAX_VOWELS-1); - xml->exitbranch(); - }; - xml->exitbranch(); + if (xml->enterbranch("FORMANT_FILTER")) { + Pnumformants=xml->getpar127("num_formants",Pnumformants); + Pformantslowness=xml->getpar127("formant_slowness",Pformantslowness); + Pvowelclearness=xml->getpar127("vowel_clearness",Pvowelclearness); + Pcenterfreq=xml->getpar127("center_freq",Pcenterfreq); + Poctavesfreq=xml->getpar127("octaves_freq",Poctavesfreq); + + for (int nvowel=0;nvowel<FF_MAX_VOWELS;nvowel++) { + if (xml->enterbranch("VOWEL",nvowel)==0) continue; + getfromXMLsection(xml,nvowel); + xml->exitbranch(); + }; + Psequencesize=xml->getpar127("sequence_size",Psequencesize); + Psequencestretch=xml->getpar127("sequence_stretch",Psequencestretch); + Psequencereversed=xml->getparbool("sequence_reversed",Psequencereversed); + for (int nseq=0;nseq<FF_MAX_SEQUENCE;nseq++) { + if (xml->enterbranch("SEQUENCE_POS",nseq)==0) continue; + Psequence[nseq].nvowel=xml->getpar("vowel_id",Psequence[nseq].nvowel,0,FF_MAX_VOWELS-1); + xml->exitbranch(); + }; + xml->exitbranch(); }; - + }; diff --git a/src/Params/FilterParams.h b/src/Params/FilterParams.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + FilterParams.h - Parameters for filter Copyright (C) 2002-2005 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 + 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, @@ -27,73 +27,74 @@ #include "../Misc/XMLwrapper.h" #include "Presets.h" -class FilterParams:public Presets{ - public: - FilterParams(unsigned char Ptype_,unsigned char Pfreq,unsigned char Pq_); - ~FilterParams(); - - void add2XML(XMLwrapper *xml); - void add2XMLsection(XMLwrapper *xml,int n); - void defaults(); - void getfromXML(XMLwrapper *xml); - void getfromXMLsection(XMLwrapper *xml,int n); - - - void getfromFilterParams(FilterParams *pars); - - REALTYPE getfreq(); - REALTYPE getq(); - REALTYPE getfreqtracking(REALTYPE notefreq); - REALTYPE getgain(); - - unsigned char Pcategory;//Filter category (Analog/Formant/StVar) - unsigned char Ptype;// Filter type (for analog lpf,hpf,bpf..) - unsigned char Pfreq;// Frequency (64-central frequency) - unsigned char Pq; // Q parameters (resonance or bandwidth) - unsigned char Pstages; //filter stages+1 - unsigned char Pfreqtrack;//how the filter frequency is changing according the note frequency - unsigned char Pgain;//filter's output gain - - //Formant filter parameters - unsigned char Pnumformants;//how many formants are used - unsigned char Pformantslowness;//how slow varies the formants - unsigned char Pvowelclearness;//how vowels are kept clean (how much try to avoid "mixed" vowels) - unsigned char Pcenterfreq,Poctavesfreq;//the center frequency of the res. func., and the number of octaves - - struct { - struct { - unsigned char freq,amp,q;//frequency,amplitude,Q - }formants[FF_MAX_FORMANTS]; - }Pvowels[FF_MAX_VOWELS]; - - - unsigned char Psequencesize;//how many vowels are in the sequence - unsigned char Psequencestretch;//how the sequence is stretched (how the input from filter envelopes/LFOs/etc. is "stretched") - unsigned char Psequencereversed;//if the input from filter envelopes/LFOs/etc. is reversed(negated) - struct { - unsigned char nvowel;//the vowel from the position - } Psequence[FF_MAX_SEQUENCE]; - - REALTYPE getcenterfreq(); - REALTYPE getoctavesfreq(); - REALTYPE getfreqpos(REALTYPE freq); - REALTYPE getfreqx(REALTYPE x); - - void formantfilterH(int nvowel,int nfreqs,REALTYPE *freqs);//used by UI - - REALTYPE getformantfreq(unsigned char freq); - REALTYPE getformantamp(unsigned char amp); - REALTYPE getformantq(unsigned char q); - - bool changed; - - private: - void defaults(int n); - - //stored default parameters - unsigned char Dtype; - unsigned char Dfreq; - unsigned char Dq; +class FilterParams:public Presets +{ +public: + FilterParams(unsigned char Ptype_,unsigned char Pfreq,unsigned char Pq_); + ~FilterParams(); + + void add2XML(XMLwrapper *xml); + void add2XMLsection(XMLwrapper *xml,int n); + void defaults(); + void getfromXML(XMLwrapper *xml); + void getfromXMLsection(XMLwrapper *xml,int n); + + + void getfromFilterParams(FilterParams *pars); + + REALTYPE getfreq(); + REALTYPE getq(); + REALTYPE getfreqtracking(REALTYPE notefreq); + REALTYPE getgain(); + + unsigned char Pcategory;//Filter category (Analog/Formant/StVar) + unsigned char Ptype;// Filter type (for analog lpf,hpf,bpf..) + unsigned char Pfreq;// Frequency (64-central frequency) + unsigned char Pq; // Q parameters (resonance or bandwidth) + unsigned char Pstages; //filter stages+1 + unsigned char Pfreqtrack;//how the filter frequency is changing according the note frequency + unsigned char Pgain;//filter's output gain + + //Formant filter parameters + unsigned char Pnumformants;//how many formants are used + unsigned char Pformantslowness;//how slow varies the formants + unsigned char Pvowelclearness;//how vowels are kept clean (how much try to avoid "mixed" vowels) + unsigned char Pcenterfreq,Poctavesfreq;//the center frequency of the res. func., and the number of octaves + + struct { + struct { + unsigned char freq,amp,q;//frequency,amplitude,Q + }formants[FF_MAX_FORMANTS]; + }Pvowels[FF_MAX_VOWELS]; + + + unsigned char Psequencesize;//how many vowels are in the sequence + unsigned char Psequencestretch;//how the sequence is stretched (how the input from filter envelopes/LFOs/etc. is "stretched") + unsigned char Psequencereversed;//if the input from filter envelopes/LFOs/etc. is reversed(negated) + struct { + unsigned char nvowel;//the vowel from the position + } Psequence[FF_MAX_SEQUENCE]; + + REALTYPE getcenterfreq(); + REALTYPE getoctavesfreq(); + REALTYPE getfreqpos(REALTYPE freq); + REALTYPE getfreqx(REALTYPE x); + + void formantfilterH(int nvowel,int nfreqs,REALTYPE *freqs);//used by UI + + REALTYPE getformantfreq(unsigned char freq); + REALTYPE getformantamp(unsigned char amp); + REALTYPE getformantq(unsigned char q); + + bool changed; + +private: + void defaults(int n); + + //stored default parameters + unsigned char Dtype; + unsigned char Dfreq; + unsigned char Dq; }; #endif diff --git a/src/Params/LFOParams.C b/src/Params/LFOParams.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + LFOParams.C - Parameters for LFO Copyright (C) 2002-2005 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 + 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, @@ -27,14 +27,18 @@ int LFOParams::time; -LFOParams::LFOParams(char Pfreq_,char Pintensity_,char Pstartphase_, char PLFOtype_,char Prandomness_, char Pdelay_,char Pcontinous_,char fel_):Presets(){ - switch(fel_) { - case 0:setpresettype("Plfofrequency"); - break; - case 1:setpresettype("Plfoamplitude"); - break; - case 2:setpresettype("Plfofilter"); - break; +LFOParams::LFOParams(char Pfreq_,char Pintensity_,char Pstartphase_, char PLFOtype_,char Prandomness_, char Pdelay_,char Pcontinous_,char fel_):Presets() +{ + switch (fel_) { + case 0: + setpresettype("Plfofrequency"); + break; + case 1: + setpresettype("Plfoamplitude"); + break; + case 2: + setpresettype("Plfofilter"); + break; }; Dfreq=Pfreq_; Dintensity=Pintensity_; @@ -45,14 +49,16 @@ LFOParams::LFOParams(char Pfreq_,char Pintensity_,char Pstartphase_, char PLFOty Dcontinous=Pcontinous_; fel=fel_; time=0; - + defaults(); }; -LFOParams::~LFOParams(){ +LFOParams::~LFOParams() +{ }; -void LFOParams::defaults(){ +void LFOParams::defaults() +{ Pfreq=Dfreq/127.0; Pintensity=Dintensity; Pstartphase=Dstartphase; @@ -65,7 +71,8 @@ void LFOParams::defaults(){ }; -void LFOParams::add2XML(XMLwrapper *xml){ +void LFOParams::add2XML(XMLwrapper *xml) +{ xml->addparreal("freq",Pfreq); xml->addpar("intensity",Pintensity); xml->addpar("start_phase",Pstartphase); @@ -77,7 +84,8 @@ void LFOParams::add2XML(XMLwrapper *xml){ xml->addparbool("continous",Pcontinous); }; -void LFOParams::getfromXML(XMLwrapper *xml){ +void LFOParams::getfromXML(XMLwrapper *xml) +{ Pfreq=xml->getparreal("freq",Pfreq,0.0,1.0); Pintensity=xml->getpar127("intensity",Pintensity); Pstartphase=xml->getpar127("start_phase",Pstartphase); diff --git a/src/Params/LFOParams.h b/src/Params/LFOParams.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + LFOParams.h - Parameters for LFO Copyright (C) 2002-2005 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 + 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, @@ -26,38 +26,39 @@ #include "../Misc/XMLwrapper.h" #include "Presets.h" -class LFOParams:public Presets{ - public: - LFOParams(char Pfreq_,char Pintensity_,char Pstartphase_, char PLFOtype_,char Prandomness_, char Pdelay_,char Pcontinous,char fel_); - ~LFOParams(); - - void add2XML(XMLwrapper *xml); - void defaults(); - /**Loads the LFO from the xml*/ - void getfromXML(XMLwrapper *xml); - +class LFOParams:public Presets +{ +public: + LFOParams(char Pfreq_,char Pintensity_,char Pstartphase_, char PLFOtype_,char Prandomness_, char Pdelay_,char Pcontinous,char fel_); + ~LFOParams(); + + void add2XML(XMLwrapper *xml); + void defaults(); + /**Loads the LFO from the xml*/ + void getfromXML(XMLwrapper *xml); + /* MIDI Parameters*/ - REALTYPE Pfreq; /**<frequency*/ - unsigned char Pintensity; /**<intensity*/ - unsigned char Pstartphase;/**<start phase (0=random)*/ - unsigned char PLFOtype; /**<LFO type (sin,triangle,square,ramp,...)*/ - unsigned char Prandomness;/**<randomness (0=off)*/ - unsigned char Pfreqrand; /**<frequency randomness (0=off)*/ - unsigned char Pdelay; /**<delay (0=off)*/ - unsigned char Pcontinous; /**<1 if LFO is continous*/ - unsigned char Pstretch; /**<how the LFO is "stretched" according the note frequency (64=no stretch)*/ + REALTYPE Pfreq; /**<frequency*/ + unsigned char Pintensity; /**<intensity*/ + unsigned char Pstartphase;/**<start phase (0=random)*/ + unsigned char PLFOtype; /**<LFO type (sin,triangle,square,ramp,...)*/ + unsigned char Prandomness;/**<randomness (0=off)*/ + unsigned char Pfreqrand; /**<frequency randomness (0=off)*/ + unsigned char Pdelay; /**<delay (0=off)*/ + unsigned char Pcontinous; /**<1 if LFO is continous*/ + unsigned char Pstretch; /**<how the LFO is "stretched" according the note frequency (64=no stretch)*/ - int fel;//what kind is the LFO (0 - frequency, 1 - amplitude, 2 - filter) - static int time;//is used by Pcontinous parameter - private: - /* Default parameters */ - unsigned char Dfreq; - unsigned char Dintensity; - unsigned char Dstartphase; - unsigned char DLFOtype; - unsigned char Drandomness; - unsigned char Ddelay; - unsigned char Dcontinous; + int fel;//what kind is the LFO (0 - frequency, 1 - amplitude, 2 - filter) + static int time;//is used by Pcontinous parameter +private: + /* Default parameters */ + unsigned char Dfreq; + unsigned char Dintensity; + unsigned char Dstartphase; + unsigned char DLFOtype; + unsigned char Drandomness; + unsigned char Ddelay; + unsigned char Dcontinous; }; diff --git a/src/Params/PADnoteParameters.C b/src/Params/PADnoteParameters.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - - PADnoteParameters.C - Parameters for PADnote (PADsynth) + + PADnoteParameters.C - Parameters for PADnote (PADsynth) Copyright (C) 2002-2005 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 + 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, @@ -24,12 +24,13 @@ #include "../Output/WAVaudiooutput.h" using namespace std; -PADnoteParameters::PADnoteParameters(FFTwrapper *fft_,pthread_mutex_t *mutex_):Presets(){ +PADnoteParameters::PADnoteParameters(FFTwrapper *fft_,pthread_mutex_t *mutex_):Presets() +{ setpresettype("Ppadsyth"); fft=fft_; mutex=mutex_; - + resonance=new Resonance(); oscilgen=new OscilGen(fft_,resonance); oscilgen->ADvsPAD=true; @@ -37,7 +38,7 @@ PADnoteParameters::PADnoteParameters(FFTwrapper *fft_,pthread_mutex_t *mutex_):P FreqEnvelope=new EnvelopeParams(0,0); FreqEnvelope->ASRinit(64,50,64,60); FreqLfo=new LFOParams(70,0,64,0,0,0,0,0); - + AmpEnvelope=new EnvelopeParams(64,1); AmpEnvelope->ADSRinit_dB(0,40,127,25); AmpLfo=new LFOParams(80,0,64,0,0,0,0,1); @@ -46,14 +47,15 @@ PADnoteParameters::PADnoteParameters(FFTwrapper *fft_,pthread_mutex_t *mutex_):P FilterEnvelope=new EnvelopeParams(0,1); FilterEnvelope->ADSRinit_filter(64,40,64,70,60,64); FilterLfo=new LFOParams(80,0,64,0,0,0,0,2); - + for (int i=0;i<PAD_MAX_SAMPLES;i++) sample[i].smp=NULL; newsample.smp=NULL; - + defaults(); }; -PADnoteParameters::~PADnoteParameters(){ +PADnoteParameters::~PADnoteParameters() +{ deletesamples(); delete(oscilgen); delete(resonance); @@ -65,10 +67,11 @@ PADnoteParameters::~PADnoteParameters(){ delete(GlobalFilter); delete(FilterEnvelope); delete(FilterLfo); - + }; -void PADnoteParameters::defaults(){ +void PADnoteParameters::defaults() +{ Pmode=0; Php.base.type=0; Php.base.par1=80; @@ -85,7 +88,7 @@ void PADnoteParameters::defaults(){ setPbandwidth(500); Pbwscale=0; - + resonance->defaults(); oscilgen->defaults(); @@ -93,7 +96,7 @@ void PADnoteParameters::defaults(){ Phrpos.par1=64; Phrpos.par2=64; Phrpos.par3=0; - + Pquality.samplesize=3; Pquality.basenote=4; Pquality.oct=3; @@ -108,7 +111,7 @@ void PADnoteParameters::defaults(){ PDetuneType=1; FreqEnvelope->defaults(); FreqLfo->defaults(); - + /* Amplitude Global Parameters */ PVolume=90; PPanning=64;//center @@ -119,7 +122,7 @@ void PADnoteParameters::defaults(){ PPunchTime=60; PPunchStretch=64; PPunchVelocitySensing=72; - + /* Filter Global Parameters*/ PFilterVelocityScale=64; PFilterVelocityScaleFunction=64; @@ -130,24 +133,27 @@ void PADnoteParameters::defaults(){ deletesamples(); }; -void PADnoteParameters::deletesample(int n){ +void PADnoteParameters::deletesample(int n) +{ if ((n<0)||(n>=PAD_MAX_SAMPLES)) return; - if (sample[n].smp!=NULL){ - delete[]sample[n].smp; - sample[n].smp=NULL; + if (sample[n].smp!=NULL) { + delete[]sample[n].smp; + sample[n].smp=NULL; }; sample[n].size=0; sample[n].basefreq=440.0; }; -void PADnoteParameters::deletesamples(){ +void PADnoteParameters::deletesamples() +{ for (int i=0;i<PAD_MAX_SAMPLES;i++) deletesample(i); }; /* * Get the harmonic profile (i.e. the frequency distributio of a single harmonic) */ -REALTYPE PADnoteParameters::getprofile(REALTYPE *smp,int size){ +REALTYPE PADnoteParameters::getprofile(REALTYPE *smp,int size) +{ for (int i=0;i<size;i++) smp[i]=0.0; const int supersample=16; REALTYPE basepar=pow(2.0,(1.0-Php.base.par1/127.0)*12.0); @@ -159,104 +165,118 @@ REALTYPE PADnoteParameters::getprofile(REALTYPE *smp,int size){ REALTYPE amppar2=(1.0-Php.amp.par2/127.0)*0.998+0.001; REALTYPE width=pow(150.0/(Php.width+22.0),2.0); - for (int i=0;i<size*supersample;i++){ - bool makezero=false; - REALTYPE x=i*1.0/(size*(REALTYPE) supersample); - - REALTYPE origx=x; - - //do the sizing (width) - x=(x-0.5)*width+0.5; - if (x<0.0) { - x=0.0; - makezero=true; - } else { - if (x>1.0) { - x=1.0; - makezero=true; - }; - }; - - //compute the full profile or one half - switch(Php.onehalf){ - case 1:x=x*0.5+0.5; - break; - case 2:x=x*0.5; - break; - }; - - REALTYPE x_before_freq_mult=x; - - //do the frequency multiplier - x*=freqmult; - - //do the modulation of the profile - x+=sin(x_before_freq_mult*3.1415926*modfreq)*modpar1; - x=fmod(x+1000.0,1.0)*2.0-1.0; - - - //this is the base function of the profile - REALTYPE f; - switch (Php.base.type){ - case 1:f=exp(-(x*x)*basepar);if (f<0.4) f=0.0; else f=1.0; - break; - case 2:f=exp(-(fabs(x))*sqrt(basepar)); - break; - default:f=exp(-(x*x)*basepar); - break; - }; - if (makezero) f=0.0; - - REALTYPE amp=1.0; - origx=origx*2.0-1.0; - - //compute the amplitude multiplier - switch(Php.amp.type){ - case 1:amp=exp(-(origx*origx)*10.0*amppar1); - break; - case 2:amp=0.5*(1.0+cos(3.1415926*origx*sqrt(amppar1*4.0+1.0))); - break; - case 3:amp=1.0/(pow(origx*(amppar1*2.0+0.8),14.0)+1.0); - break; - }; - - //apply the amplitude multiplier - REALTYPE finalsmp=f; - if (Php.amp.type!=0){ - switch(Php.amp.mode){ - case 0:finalsmp=amp*(1.0-amppar2)+finalsmp*amppar2; - break; - case 1:finalsmp*=amp*(1.0-amppar2)+amppar2; - break; - case 2:finalsmp=finalsmp/(amp+pow(amppar2,4.0)*20.0+0.0001); - break; - case 3:finalsmp=amp/(finalsmp+pow(amppar2,4.0)*20.0+0.0001); - break; - }; - }; - - smp[i/supersample]+=finalsmp/supersample; - }; + for (int i=0;i<size*supersample;i++) { + bool makezero=false; + REALTYPE x=i*1.0/(size*(REALTYPE) supersample); + + REALTYPE origx=x; + + //do the sizing (width) + x=(x-0.5)*width+0.5; + if (x<0.0) { + x=0.0; + makezero=true; + } else { + if (x>1.0) { + x=1.0; + makezero=true; + }; + }; + + //compute the full profile or one half + switch (Php.onehalf) { + case 1: + x=x*0.5+0.5; + break; + case 2: + x=x*0.5; + break; + }; + + REALTYPE x_before_freq_mult=x; + + //do the frequency multiplier + x*=freqmult; + + //do the modulation of the profile + x+=sin(x_before_freq_mult*3.1415926*modfreq)*modpar1; + x=fmod(x+1000.0,1.0)*2.0-1.0; + + + //this is the base function of the profile + REALTYPE f; + switch (Php.base.type) { + case 1: + f=exp(-(x*x)*basepar); + if (f<0.4) f=0.0; + else f=1.0; + break; + case 2: + f=exp(-(fabs(x))*sqrt(basepar)); + break; + default: + f=exp(-(x*x)*basepar); + break; + }; + if (makezero) f=0.0; + + REALTYPE amp=1.0; + origx=origx*2.0-1.0; + + //compute the amplitude multiplier + switch (Php.amp.type) { + case 1: + amp=exp(-(origx*origx)*10.0*amppar1); + break; + case 2: + amp=0.5*(1.0+cos(3.1415926*origx*sqrt(amppar1*4.0+1.0))); + break; + case 3: + amp=1.0/(pow(origx*(amppar1*2.0+0.8),14.0)+1.0); + break; + }; + + //apply the amplitude multiplier + REALTYPE finalsmp=f; + if (Php.amp.type!=0) { + switch (Php.amp.mode) { + case 0: + finalsmp=amp*(1.0-amppar2)+finalsmp*amppar2; + break; + case 1: + finalsmp*=amp*(1.0-amppar2)+amppar2; + break; + case 2: + finalsmp=finalsmp/(amp+pow(amppar2,4.0)*20.0+0.0001); + break; + case 3: + finalsmp=amp/(finalsmp+pow(amppar2,4.0)*20.0+0.0001); + break; + }; + }; + + smp[i/supersample]+=finalsmp/supersample; + }; //normalize the profile (make the max. to be equal to 1.0) REALTYPE max=0.0; for (int i=0;i<size;i++) { - if (smp[i]<0.0) smp[i]=0.0; - if (smp[i]>max) max=smp[i]; + if (smp[i]<0.0) smp[i]=0.0; + if (smp[i]>max) max=smp[i]; }; if (max<0.00001) max=1.0; for (int i=0;i<size;i++) smp[i]/=max; - + if (!Php.autoscale) return(0.5); //compute the estimated perceived bandwidth REALTYPE sum=0.0; int i; for (i=0;i<size/2-2;i++) { - sum+=smp[i]*smp[i]+smp[size-i-1]*smp[size-i-1]; - if (sum>=4.0) break; + sum+=smp[i]*smp[i]+smp[size-i-1]*smp[size-i-1]; + if (sum>=4.0) break; }; - + REALTYPE result=1.0-2.0*i/(REALTYPE) size; return(result); }; @@ -265,7 +285,8 @@ REALTYPE PADnoteParameters::getprofile(REALTYPE *smp,int size){ * Compute the real bandwidth in cents and returns it * Also, sets the bandwidth parameter */ -REALTYPE PADnoteParameters::setPbandwidth(int Pbandwidth){ +REALTYPE PADnoteParameters::setPbandwidth(int Pbandwidth) +{ this->Pbandwidth=Pbandwidth; REALTYPE result=pow(Pbandwidth/1000.0,1.1); result=pow(10.0,result*4.0)*0.25; @@ -275,46 +296,47 @@ REALTYPE PADnoteParameters::setPbandwidth(int Pbandwidth){ /* * Get the harmonic(overtone) position */ -REALTYPE PADnoteParameters::getNhr(int n){ +REALTYPE PADnoteParameters::getNhr(int n) +{ REALTYPE result=1.0; REALTYPE par1=pow(10.0,-(1.0-Phrpos.par1/255.0)*3.0); REALTYPE par2=Phrpos.par2/255.0; - + REALTYPE n0=n-1.0; REALTYPE tmp=0.0; int thresh=0; - switch(Phrpos.type){ - case 1: - thresh=(int)(par2*par2*100.0)+1; - if (n<thresh) result=n; - else result=1.0+n0+(n0-thresh+1.0)*par1*8.0; - break; - case 2: - thresh=(int)(par2*par2*100.0)+1; - if (n<thresh) result=n; - else result=1.0+n0-(n0-thresh+1.0)*par1*0.90; - break; - case 3: - tmp=par1*100.0+1.0; - result=pow(n0/tmp,1.0-par2*0.8)*tmp+1.0; - break; - case 4: - result=n0*(1.0-par1)+pow(n0*0.1,par2*3.0+1.0)*par1*10.0+1.0; - break; - case 5: - result=n0+sin(n0*par2*par2*PI*0.999)*sqrt(par1)*2.0+1.0; - break; - case 6: - tmp=pow(par2*2.0,2.0)+0.1; - result=n0*pow(1.0+par1*pow(n0*0.8,tmp),tmp)+1.0; - break; - default: - result=n; - break; + switch (Phrpos.type) { + case 1: + thresh=(int)(par2*par2*100.0)+1; + if (n<thresh) result=n; + else result=1.0+n0+(n0-thresh+1.0)*par1*8.0; + break; + case 2: + thresh=(int)(par2*par2*100.0)+1; + if (n<thresh) result=n; + else result=1.0+n0-(n0-thresh+1.0)*par1*0.90; + break; + case 3: + tmp=par1*100.0+1.0; + result=pow(n0/tmp,1.0-par2*0.8)*tmp+1.0; + break; + case 4: + result=n0*(1.0-par1)+pow(n0*0.1,par2*3.0+1.0)*par1*10.0+1.0; + break; + case 5: + result=n0+sin(n0*par2*par2*PI*0.999)*sqrt(par1)*2.0+1.0; + break; + case 6: + tmp=pow(par2*2.0,2.0)+0.1; + result=n0*pow(1.0+par1*pow(n0*0.8,tmp),tmp)+1.0; + break; + default: + result=n; + break; }; REALTYPE par3=Phrpos.par3/255.0; - + REALTYPE iresult=floor(result+0.5); REALTYPE dresult=result-iresult; @@ -326,9 +348,10 @@ REALTYPE PADnoteParameters::getNhr(int n){ /* * Generates the long spectrum for Bandwidth mode (only amplitudes are generated; phases will be random) */ -void PADnoteParameters::generatespectrum_bandwidthMode(REALTYPE *spectrum, int size,REALTYPE basefreq,REALTYPE *profile,int profilesize,REALTYPE bwadjust){ +void PADnoteParameters::generatespectrum_bandwidthMode(REALTYPE *spectrum, int size,REALTYPE basefreq,REALTYPE *profile,int profilesize,REALTYPE bwadjust) +{ for (int i=0;i<size;i++) spectrum[i]=0.0; - + REALTYPE harmonics[OSCIL_SIZE/2]; for (int i=0;i<OSCIL_SIZE/2;i++) harmonics[i]=0.0; //get the harmonic structure from the oscillator (I am using the frequency amplitudes, only) @@ -339,66 +362,83 @@ void PADnoteParameters::generatespectrum_bandwidthMode(REALTYPE *spectrum, int s for (int i=0;i<OSCIL_SIZE/2;i++) if (harmonics[i]>max) max=harmonics[i]; if (max<0.000001) max=1; for (int i=0;i<OSCIL_SIZE/2;i++) harmonics[i]/=max; - - for (int nh=1;nh<OSCIL_SIZE/2;nh++){//for each harmonic - REALTYPE realfreq=getNhr(nh)*basefreq; - if (realfreq>SAMPLE_RATE*0.49999) break; - if (realfreq<20.0) break; - if (harmonics[nh-1]<1e-4) continue; - - //compute the bandwidth of each harmonic - REALTYPE bandwidthcents=setPbandwidth(Pbandwidth); - REALTYPE bw=(pow(2.0,bandwidthcents/1200.0)-1.0)*basefreq/bwadjust; - REALTYPE power=1.0; - switch (Pbwscale){ - case 0: power=1.0;break; - case 1: power=0.0;break; - case 2: power=0.25;break; - case 3: power=0.5;break; - case 4: power=0.75;break; - case 5: power=1.5;break; - case 6: power=2.0;break; - case 7: power=-0.5;break; - }; - bw=bw*pow(realfreq/basefreq,power); + + for (int nh=1;nh<OSCIL_SIZE/2;nh++) {//for each harmonic + REALTYPE realfreq=getNhr(nh)*basefreq; + if (realfreq>SAMPLE_RATE*0.49999) break; + if (realfreq<20.0) break; + if (harmonics[nh-1]<1e-4) continue; + + //compute the bandwidth of each harmonic + REALTYPE bandwidthcents=setPbandwidth(Pbandwidth); + REALTYPE bw=(pow(2.0,bandwidthcents/1200.0)-1.0)*basefreq/bwadjust; + REALTYPE power=1.0; + switch (Pbwscale) { + case 0: + power=1.0; + break; + case 1: + power=0.0; + break; + case 2: + power=0.25; + break; + case 3: + power=0.5; + break; + case 4: + power=0.75; + break; + case 5: + power=1.5; + break; + case 6: + power=2.0; + break; + case 7: + power=-0.5; + break; + }; + bw=bw*pow(realfreq/basefreq,power); int ibw=(int)((bw/(SAMPLE_RATE*0.5)*size))+1; - REALTYPE amp=harmonics[nh-1]; - if (resonance->Penabled) amp*=resonance->getfreqresponse(realfreq); - - if (ibw>profilesize){//if the bandwidth is larger than the profilesize - REALTYPE rap=sqrt((REALTYPE)profilesize/(REALTYPE)ibw); - int cfreq=(int) (realfreq/(SAMPLE_RATE*0.5)*size)-ibw/2; - for (int i=0;i<ibw;i++){ - int src=(int)(i*rap*rap); - int spfreq=i+cfreq; - if (spfreq<0) continue; - if (spfreq>=size) break; - spectrum[spfreq]+=amp*profile[src]*rap; - }; - }else{//if the bandwidth is smaller than the profilesize - REALTYPE rap=sqrt((REALTYPE)ibw/(REALTYPE)profilesize); - REALTYPE ibasefreq=realfreq/(SAMPLE_RATE*0.5)*size; - for (int i=0;i<profilesize;i++){ - REALTYPE idfreq=i/(REALTYPE)profilesize-0.5; - idfreq*=ibw; - int spfreq=(int) (idfreq+ibasefreq); - REALTYPE fspfreq=fmod(idfreq+ibasefreq,1.0); - if (spfreq<=0) continue; - if (spfreq>=size-1) break; - spectrum[spfreq]+=amp*profile[i]*rap*(1.0-fspfreq); - spectrum[spfreq+1]+=amp*profile[i]*rap*fspfreq; - }; - }; + REALTYPE amp=harmonics[nh-1]; + if (resonance->Penabled) amp*=resonance->getfreqresponse(realfreq); + + if (ibw>profilesize) {//if the bandwidth is larger than the profilesize + REALTYPE rap=sqrt((REALTYPE)profilesize/(REALTYPE)ibw); + int cfreq=(int) (realfreq/(SAMPLE_RATE*0.5)*size)-ibw/2; + for (int i=0;i<ibw;i++) { + int src=(int)(i*rap*rap); + int spfreq=i+cfreq; + if (spfreq<0) continue; + if (spfreq>=size) break; + spectrum[spfreq]+=amp*profile[src]*rap; + }; + } else {//if the bandwidth is smaller than the profilesize + REALTYPE rap=sqrt((REALTYPE)ibw/(REALTYPE)profilesize); + REALTYPE ibasefreq=realfreq/(SAMPLE_RATE*0.5)*size; + for (int i=0;i<profilesize;i++) { + REALTYPE idfreq=i/(REALTYPE)profilesize-0.5; + idfreq*=ibw; + int spfreq=(int) (idfreq+ibasefreq); + REALTYPE fspfreq=fmod(idfreq+ibasefreq,1.0); + if (spfreq<=0) continue; + if (spfreq>=size-1) break; + spectrum[spfreq]+=amp*profile[i]*rap*(1.0-fspfreq); + spectrum[spfreq+1]+=amp*profile[i]*rap*fspfreq; + }; + }; }; }; /* * Generates the long spectrum for non-Bandwidth modes (only amplitudes are generated; phases will be random) */ -void PADnoteParameters::generatespectrum_otherModes(REALTYPE *spectrum, int size,REALTYPE basefreq,REALTYPE *profile,int profilesize,REALTYPE bwadjust){ +void PADnoteParameters::generatespectrum_otherModes(REALTYPE *spectrum, int size,REALTYPE basefreq,REALTYPE *profile,int profilesize,REALTYPE bwadjust) +{ for (int i=0;i<size;i++) spectrum[i]=0.0; - + REALTYPE harmonics[OSCIL_SIZE/2]; for (int i=0;i<OSCIL_SIZE/2;i++) harmonics[i]=0.0; //get the harmonic structure from the oscillator (I am using the frequency amplitudes, only) @@ -410,46 +450,47 @@ void PADnoteParameters::generatespectrum_otherModes(REALTYPE *spectrum, int size if (max<0.000001) max=1; for (int i=0;i<OSCIL_SIZE/2;i++) harmonics[i]/=max; - for (int nh=1;nh<OSCIL_SIZE/2;nh++){//for each harmonic - REALTYPE realfreq=getNhr(nh)*basefreq; - - ///sa fac aici interpolarea si sa am grija daca frecv descresc - - if (realfreq>SAMPLE_RATE*0.49999) break; - if (realfreq<20.0) break; + for (int nh=1;nh<OSCIL_SIZE/2;nh++) {//for each harmonic + REALTYPE realfreq=getNhr(nh)*basefreq; + + ///sa fac aici interpolarea si sa am grija daca frecv descresc + + if (realfreq>SAMPLE_RATE*0.49999) break; + if (realfreq<20.0) break; // if (harmonics[nh-1]<1e-4) continue; - REALTYPE amp=harmonics[nh-1]; - if (resonance->Penabled) amp*=resonance->getfreqresponse(realfreq); - int cfreq=(int) (realfreq/(SAMPLE_RATE*0.5)*size); + REALTYPE amp=harmonics[nh-1]; + if (resonance->Penabled) amp*=resonance->getfreqresponse(realfreq); + int cfreq=(int) (realfreq/(SAMPLE_RATE*0.5)*size); - spectrum[cfreq]=amp+1e-9; + spectrum[cfreq]=amp+1e-9; }; - - if (Pmode!=1){ + + if (Pmode!=1) { int old=0; - for (int k=1;k<size;k++){ - if ( (spectrum[k]>1e-10) || (k==(size-1)) ){ - int delta=k-old; - REALTYPE val1=spectrum[old]; - REALTYPE val2=spectrum[k]; - REALTYPE idelta=1.0/delta; - for (int i=0;i<delta;i++){ - REALTYPE x=idelta*i; - spectrum[old+i]=val1*(1.0-x)+val2*x; - }; - old=k; - }; - }; + for (int k=1;k<size;k++) { + if ( (spectrum[k]>1e-10) || (k==(size-1)) ) { + int delta=k-old; + REALTYPE val1=spectrum[old]; + REALTYPE val2=spectrum[k]; + REALTYPE idelta=1.0/delta; + for (int i=0;i<delta;i++) { + REALTYPE x=idelta*i; + spectrum[old+i]=val1*(1.0-x)+val2*x; + }; + old=k; + }; + }; }; - + }; /* * Applies the parameters (i.e. computes all the samples, based on parameters); */ -void PADnoteParameters::applyparameters(bool lockmutex){ +void PADnoteParameters::applyparameters(bool lockmutex) +{ const int samplesize=(((int) 1)<<(Pquality.samplesize+14)); int spectrumsize=samplesize/2; REALTYPE spectrum[spectrumsize]; @@ -467,97 +508,99 @@ void PADnoteParameters::applyparameters(bool lockmutex){ if (Pquality.smpoct==5) smpoct=6; if (Pquality.smpoct==6) smpoct=12; if (smpoct!=0) samplemax*=smpoct; - else samplemax=samplemax/2+1; + else samplemax=samplemax/2+1; if (samplemax==0) samplemax=1; - + //prepare a BIG FFT stuff FFTwrapper *fft=new FFTwrapper(samplesize); FFTFREQS fftfreqs; newFFTFREQS(&fftfreqs,samplesize/2); - + REALTYPE adj[samplemax];//this is used to compute frequency relation to the base frequency for (int nsample=0;nsample<samplemax;nsample++) adj[nsample]=(Pquality.oct+1.0)*(REALTYPE)nsample/samplemax; - for (int nsample=0;nsample<samplemax;nsample++){ - REALTYPE tmp=adj[nsample]-adj[samplemax-1]*0.5; - REALTYPE basefreqadjust=pow(2.0,tmp); + for (int nsample=0;nsample<samplemax;nsample++) { + REALTYPE tmp=adj[nsample]-adj[samplemax-1]*0.5; + REALTYPE basefreqadjust=pow(2.0,tmp); if (Pmode==0) generatespectrum_bandwidthMode(spectrum,spectrumsize,basefreq*basefreqadjust,profile,profilesize,bwadjust); - else generatespectrum_otherModes(spectrum,spectrumsize,basefreq*basefreqadjust,profile,profilesize,bwadjust); + else generatespectrum_otherModes(spectrum,spectrumsize,basefreq*basefreqadjust,profile,profilesize,bwadjust); - const int extra_samples=5;//the last samples contains the first samples (used for linear/cubic interpolation) + const int extra_samples=5;//the last samples contains the first samples (used for linear/cubic interpolation) newsample.smp=new REALTYPE[samplesize+extra_samples]; - - newsample.smp[0]=0.0; - for (int i=1;i<spectrumsize;i++){//randomize the phases - REALTYPE phase=RND*6.29; - fftfreqs.c[i]=spectrum[i]*cos(phase); - fftfreqs.s[i]=spectrum[i]*sin(phase); - }; - fft->freqs2smps(fftfreqs,newsample.smp);//that's all; here is the only ifft for the whole sample; no windows are used ;-) - + + newsample.smp[0]=0.0; + for (int i=1;i<spectrumsize;i++) {//randomize the phases + REALTYPE phase=RND*6.29; + fftfreqs.c[i]=spectrum[i]*cos(phase); + fftfreqs.s[i]=spectrum[i]*sin(phase); + }; + fft->freqs2smps(fftfreqs,newsample.smp);//that's all; here is the only ifft for the whole sample; no windows are used ;-) + //normalize(rms) - REALTYPE rms=0.0; + REALTYPE rms=0.0; for (int i=0;i<samplesize;i++) rms+=newsample.smp[i]*newsample.smp[i]; - rms=sqrt(rms); + rms=sqrt(rms); if (rms<0.000001) rms=1.0; - rms*=sqrt(262144.0/samplesize); + rms*=sqrt(262144.0/samplesize); for (int i=0;i<samplesize;i++) newsample.smp[i]*=1.0/rms*50.0; - - //prepare extra samples used by the linear or cubic interpolation + + //prepare extra samples used by the linear or cubic interpolation for (int i=0;i<extra_samples;i++) newsample.smp[i+samplesize]=newsample.smp[i]; - //replace the current sample with the new computed sample - if (lockmutex){ - pthread_mutex_lock(mutex); - deletesample(nsample); - sample[nsample].smp=newsample.smp; - sample[nsample].size=samplesize; - sample[nsample].basefreq=basefreq*basefreqadjust; - pthread_mutex_unlock(mutex); - } else { - deletesample(nsample); - sample[nsample].smp=newsample.smp; - sample[nsample].size=samplesize; - sample[nsample].basefreq=basefreq*basefreqadjust; - }; - newsample.smp=NULL; + //replace the current sample with the new computed sample + if (lockmutex) { + pthread_mutex_lock(mutex); + deletesample(nsample); + sample[nsample].smp=newsample.smp; + sample[nsample].size=samplesize; + sample[nsample].basefreq=basefreq*basefreqadjust; + pthread_mutex_unlock(mutex); + } else { + deletesample(nsample); + sample[nsample].smp=newsample.smp; + sample[nsample].size=samplesize; + sample[nsample].basefreq=basefreq*basefreqadjust; + }; + newsample.smp=NULL; }; delete(fft); deleteFFTFREQS(&fftfreqs); - + //delete the additional samples that might exists and are not useful - if (lockmutex){ + if (lockmutex) { pthread_mutex_lock(mutex); - for (int i=samplemax;i<PAD_MAX_SAMPLES;i++) deletesample(i); + for (int i=samplemax;i<PAD_MAX_SAMPLES;i++) deletesample(i); pthread_mutex_unlock(mutex); } else { - for (int i=samplemax;i<PAD_MAX_SAMPLES;i++) deletesample(i); + for (int i=samplemax;i<PAD_MAX_SAMPLES;i++) deletesample(i); }; }; -void PADnoteParameters::export2wav(string basefilename){ - applyparameters(true); - basefilename+="_PADsynth_"; - for (int k=0;k<PAD_MAX_SAMPLES;k++){ - if (sample[k].smp==NULL) continue; - char tmpstr[20]; - snprintf(tmpstr,20,"_%02d",k+1); - string filename=basefilename+string(tmpstr)+".wav"; - WAVaudiooutput wav; - if (wav.newfile(filename,SAMPLE_RATE,1)) { - int nsmps=sample[k].size; - short int *smps=new short int[nsmps]; - for (int i=0;i<nsmps;i++) smps[i]=(short int)(sample[k].smp[i]*32767.0); - wav.write_mono_samples(nsmps, smps); - wav.close(); - }; - }; +void PADnoteParameters::export2wav(string basefilename) +{ + applyparameters(true); + basefilename+="_PADsynth_"; + for (int k=0;k<PAD_MAX_SAMPLES;k++) { + if (sample[k].smp==NULL) continue; + char tmpstr[20]; + snprintf(tmpstr,20,"_%02d",k+1); + string filename=basefilename+string(tmpstr)+".wav"; + WAVaudiooutput wav; + if (wav.newfile(filename,SAMPLE_RATE,1)) { + int nsmps=sample[k].size; + short int *smps=new short int[nsmps]; + for (int i=0;i<nsmps;i++) smps[i]=(short int)(sample[k].smp[i]*32767.0); + wav.write_mono_samples(nsmps, smps); + wav.close(); + }; + }; }; -void PADnoteParameters::add2XML(XMLwrapper *xml){ +void PADnoteParameters::add2XML(XMLwrapper *xml) +{ xml->information.PADsynth_used=true; xml->addparbool("stereo",PStereo); @@ -566,196 +609,197 @@ void PADnoteParameters::add2XML(XMLwrapper *xml){ xml->addpar("bandwidth_scale",Pbwscale); xml->beginbranch("HARMONIC_PROFILE"); - xml->addpar("base_type",Php.base.type); - xml->addpar("base_par1",Php.base.par1); - xml->addpar("frequency_multiplier",Php.freqmult); - xml->addpar("modulator_par1",Php.modulator.par1); - xml->addpar("modulator_frequency",Php.modulator.freq); - xml->addpar("width",Php.width); - xml->addpar("amplitude_multiplier_type",Php.amp.type); - xml->addpar("amplitude_multiplier_mode",Php.amp.mode); - xml->addpar("amplitude_multiplier_par1",Php.amp.par1); - xml->addpar("amplitude_multiplier_par2",Php.amp.par2); - xml->addparbool("autoscale",Php.autoscale); - xml->addpar("one_half",Php.onehalf); + xml->addpar("base_type",Php.base.type); + xml->addpar("base_par1",Php.base.par1); + xml->addpar("frequency_multiplier",Php.freqmult); + xml->addpar("modulator_par1",Php.modulator.par1); + xml->addpar("modulator_frequency",Php.modulator.freq); + xml->addpar("width",Php.width); + xml->addpar("amplitude_multiplier_type",Php.amp.type); + xml->addpar("amplitude_multiplier_mode",Php.amp.mode); + xml->addpar("amplitude_multiplier_par1",Php.amp.par1); + xml->addpar("amplitude_multiplier_par2",Php.amp.par2); + xml->addparbool("autoscale",Php.autoscale); + xml->addpar("one_half",Php.onehalf); xml->endbranch(); xml->beginbranch("OSCIL"); - oscilgen->add2XML(xml); + oscilgen->add2XML(xml); xml->endbranch(); xml->beginbranch("RESONANCE"); - resonance->add2XML(xml); + resonance->add2XML(xml); xml->endbranch(); xml->beginbranch("HARMONIC_POSITION"); - xml->addpar("type",Phrpos.type); - xml->addpar("parameter1",Phrpos.par1); - xml->addpar("parameter2",Phrpos.par2); - xml->addpar("parameter3",Phrpos.par3); + xml->addpar("type",Phrpos.type); + xml->addpar("parameter1",Phrpos.par1); + xml->addpar("parameter2",Phrpos.par2); + xml->addpar("parameter3",Phrpos.par3); xml->endbranch(); xml->beginbranch("SAMPLE_QUALITY"); - xml->addpar("samplesize",Pquality.samplesize); - xml->addpar("basenote",Pquality.basenote); - xml->addpar("octaves",Pquality.oct); - xml->addpar("samples_per_octave",Pquality.smpoct); + xml->addpar("samplesize",Pquality.samplesize); + xml->addpar("basenote",Pquality.basenote); + xml->addpar("octaves",Pquality.oct); + xml->addpar("samples_per_octave",Pquality.smpoct); xml->endbranch(); xml->beginbranch("AMPLITUDE_PARAMETERS"); - xml->addpar("volume",PVolume); - xml->addpar("panning",PPanning); - xml->addpar("velocity_sensing",PAmpVelocityScaleFunction); - xml->addpar("punch_strength",PPunchStrength); - xml->addpar("punch_time",PPunchTime); - xml->addpar("punch_stretch",PPunchStretch); - xml->addpar("punch_velocity_sensing",PPunchVelocitySensing); - - xml->beginbranch("AMPLITUDE_ENVELOPE"); - AmpEnvelope->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("AMPLITUDE_LFO"); - AmpLfo->add2XML(xml); - xml->endbranch(); + xml->addpar("volume",PVolume); + xml->addpar("panning",PPanning); + xml->addpar("velocity_sensing",PAmpVelocityScaleFunction); + xml->addpar("punch_strength",PPunchStrength); + xml->addpar("punch_time",PPunchTime); + xml->addpar("punch_stretch",PPunchStretch); + xml->addpar("punch_velocity_sensing",PPunchVelocitySensing); + + xml->beginbranch("AMPLITUDE_ENVELOPE"); + AmpEnvelope->add2XML(xml); + xml->endbranch(); + xml->beginbranch("AMPLITUDE_LFO"); + AmpLfo->add2XML(xml); xml->endbranch(); - + + xml->endbranch(); + xml->beginbranch("FREQUENCY_PARAMETERS"); - xml->addpar("fixed_freq",Pfixedfreq); - xml->addpar("fixed_freq_et",PfixedfreqET); - xml->addpar("detune",PDetune); - xml->addpar("coarse_detune",PCoarseDetune); - xml->addpar("detune_type",PDetuneType); - - xml->beginbranch("FREQUENCY_ENVELOPE"); - FreqEnvelope->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("FREQUENCY_LFO"); - FreqLfo->add2XML(xml); - xml->endbranch(); + xml->addpar("fixed_freq",Pfixedfreq); + xml->addpar("fixed_freq_et",PfixedfreqET); + xml->addpar("detune",PDetune); + xml->addpar("coarse_detune",PCoarseDetune); + xml->addpar("detune_type",PDetuneType); + + xml->beginbranch("FREQUENCY_ENVELOPE"); + FreqEnvelope->add2XML(xml); + xml->endbranch(); + + xml->beginbranch("FREQUENCY_LFO"); + FreqLfo->add2XML(xml); + xml->endbranch(); xml->endbranch(); - + xml->beginbranch("FILTER_PARAMETERS"); - xml->addpar("velocity_sensing_amplitude",PFilterVelocityScale); - xml->addpar("velocity_sensing",PFilterVelocityScaleFunction); - - xml->beginbranch("FILTER"); - GlobalFilter->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("FILTER_ENVELOPE"); - FilterEnvelope->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("FILTER_LFO"); - FilterLfo->add2XML(xml); - xml->endbranch(); - xml->endbranch(); + xml->addpar("velocity_sensing_amplitude",PFilterVelocityScale); + xml->addpar("velocity_sensing",PFilterVelocityScaleFunction); + + xml->beginbranch("FILTER"); + GlobalFilter->add2XML(xml); + xml->endbranch(); + + xml->beginbranch("FILTER_ENVELOPE"); + FilterEnvelope->add2XML(xml); + xml->endbranch(); + + xml->beginbranch("FILTER_LFO"); + FilterLfo->add2XML(xml); + xml->endbranch(); + xml->endbranch(); }; -void PADnoteParameters::getfromXML(XMLwrapper *xml){ +void PADnoteParameters::getfromXML(XMLwrapper *xml) +{ PStereo=xml->getparbool("stereo",PStereo); Pmode=xml->getpar127("mode",0); Pbandwidth=xml->getpar("bandwidth",Pbandwidth,0,1000); Pbwscale=xml->getpar127("bandwidth_scale",Pbwscale); - if (xml->enterbranch("HARMONIC_PROFILE")){ - Php.base.type=xml->getpar127("base_type",Php.base.type); - Php.base.par1=xml->getpar127("base_par1",Php.base.par1); - Php.freqmult=xml->getpar127("frequency_multiplier",Php.freqmult); - Php.modulator.par1=xml->getpar127("modulator_par1",Php.modulator.par1); - Php.modulator.freq=xml->getpar127("modulator_frequency",Php.modulator.freq); - Php.width=xml->getpar127("width",Php.width); - Php.amp.type=xml->getpar127("amplitude_multiplier_type",Php.amp.type); - Php.amp.mode=xml->getpar127("amplitude_multiplier_mode",Php.amp.mode); - Php.amp.par1=xml->getpar127("amplitude_multiplier_par1",Php.amp.par1); - Php.amp.par2=xml->getpar127("amplitude_multiplier_par2",Php.amp.par2); - Php.autoscale=xml->getparbool("autoscale",Php.autoscale); - Php.onehalf=xml->getpar127("one_half",Php.onehalf); - xml->exitbranch(); + if (xml->enterbranch("HARMONIC_PROFILE")) { + Php.base.type=xml->getpar127("base_type",Php.base.type); + Php.base.par1=xml->getpar127("base_par1",Php.base.par1); + Php.freqmult=xml->getpar127("frequency_multiplier",Php.freqmult); + Php.modulator.par1=xml->getpar127("modulator_par1",Php.modulator.par1); + Php.modulator.freq=xml->getpar127("modulator_frequency",Php.modulator.freq); + Php.width=xml->getpar127("width",Php.width); + Php.amp.type=xml->getpar127("amplitude_multiplier_type",Php.amp.type); + Php.amp.mode=xml->getpar127("amplitude_multiplier_mode",Php.amp.mode); + Php.amp.par1=xml->getpar127("amplitude_multiplier_par1",Php.amp.par1); + Php.amp.par2=xml->getpar127("amplitude_multiplier_par2",Php.amp.par2); + Php.autoscale=xml->getparbool("autoscale",Php.autoscale); + Php.onehalf=xml->getpar127("one_half",Php.onehalf); + xml->exitbranch(); }; - if (xml->enterbranch("OSCIL")){ + if (xml->enterbranch("OSCIL")) { oscilgen->getfromXML(xml); - xml->exitbranch(); + xml->exitbranch(); }; - if (xml->enterbranch("RESONANCE")){ + if (xml->enterbranch("RESONANCE")) { resonance->getfromXML(xml); - xml->exitbranch(); + xml->exitbranch(); }; - if (xml->enterbranch("HARMONIC_POSITION")){ - Phrpos.type=xml->getpar127("type",Phrpos.type); - Phrpos.par1=xml->getpar("parameter1",Phrpos.par1,0,255); - Phrpos.par2=xml->getpar("parameter2",Phrpos.par2,0,255); - Phrpos.par3=xml->getpar("parameter3",Phrpos.par3,0,255); - xml->exitbranch(); + if (xml->enterbranch("HARMONIC_POSITION")) { + Phrpos.type=xml->getpar127("type",Phrpos.type); + Phrpos.par1=xml->getpar("parameter1",Phrpos.par1,0,255); + Phrpos.par2=xml->getpar("parameter2",Phrpos.par2,0,255); + Phrpos.par3=xml->getpar("parameter3",Phrpos.par3,0,255); + xml->exitbranch(); }; - if (xml->enterbranch("SAMPLE_QUALITY")){ - Pquality.samplesize=xml->getpar127("samplesize",Pquality.samplesize); - Pquality.basenote=xml->getpar127("basenote",Pquality.basenote); - Pquality.oct=xml->getpar127("octaves",Pquality.oct); - Pquality.smpoct=xml->getpar127("samples_per_octave",Pquality.smpoct); - xml->exitbranch(); + if (xml->enterbranch("SAMPLE_QUALITY")) { + Pquality.samplesize=xml->getpar127("samplesize",Pquality.samplesize); + Pquality.basenote=xml->getpar127("basenote",Pquality.basenote); + Pquality.oct=xml->getpar127("octaves",Pquality.oct); + Pquality.smpoct=xml->getpar127("samples_per_octave",Pquality.smpoct); + xml->exitbranch(); }; - if (xml->enterbranch("AMPLITUDE_PARAMETERS")){ - PVolume=xml->getpar127("volume",PVolume); - PPanning=xml->getpar127("panning",PPanning); - PAmpVelocityScaleFunction=xml->getpar127("velocity_sensing",PAmpVelocityScaleFunction); - PPunchStrength=xml->getpar127("punch_strength",PPunchStrength); - PPunchTime=xml->getpar127("punch_time",PPunchTime); - PPunchStretch=xml->getpar127("punch_stretch",PPunchStretch); - PPunchVelocitySensing=xml->getpar127("punch_velocity_sensing",PPunchVelocitySensing); - - xml->enterbranch("AMPLITUDE_ENVELOPE"); - AmpEnvelope->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("AMPLITUDE_LFO"); - AmpLfo->getfromXML(xml); - xml->exitbranch(); - - xml->exitbranch(); + if (xml->enterbranch("AMPLITUDE_PARAMETERS")) { + PVolume=xml->getpar127("volume",PVolume); + PPanning=xml->getpar127("panning",PPanning); + PAmpVelocityScaleFunction=xml->getpar127("velocity_sensing",PAmpVelocityScaleFunction); + PPunchStrength=xml->getpar127("punch_strength",PPunchStrength); + PPunchTime=xml->getpar127("punch_time",PPunchTime); + PPunchStretch=xml->getpar127("punch_stretch",PPunchStretch); + PPunchVelocitySensing=xml->getpar127("punch_velocity_sensing",PPunchVelocitySensing); + + xml->enterbranch("AMPLITUDE_ENVELOPE"); + AmpEnvelope->getfromXML(xml); + xml->exitbranch(); + + xml->enterbranch("AMPLITUDE_LFO"); + AmpLfo->getfromXML(xml); + xml->exitbranch(); + + xml->exitbranch(); }; - - if (xml->enterbranch("FREQUENCY_PARAMETERS")){ - Pfixedfreq=xml->getpar127("fixed_freq",Pfixedfreq); + + if (xml->enterbranch("FREQUENCY_PARAMETERS")) { + Pfixedfreq=xml->getpar127("fixed_freq",Pfixedfreq); PfixedfreqET=xml->getpar127("fixed_freq_et",PfixedfreqET); PDetune=xml->getpar("detune",PDetune,0,16383); PCoarseDetune=xml->getpar("coarse_detune",PCoarseDetune,0,16383); PDetuneType=xml->getpar127("detune_type",PDetuneType); - - xml->enterbranch("FREQUENCY_ENVELOPE"); - FreqEnvelope->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("FREQUENCY_LFO"); - FreqLfo->getfromXML(xml); - xml->exitbranch(); - xml->exitbranch(); + + xml->enterbranch("FREQUENCY_ENVELOPE"); + FreqEnvelope->getfromXML(xml); + xml->exitbranch(); + + xml->enterbranch("FREQUENCY_LFO"); + FreqLfo->getfromXML(xml); + xml->exitbranch(); + xml->exitbranch(); }; - - if (xml->enterbranch("FILTER_PARAMETERS")){ - PFilterVelocityScale=xml->getpar127("velocity_sensing_amplitude",PFilterVelocityScale); - PFilterVelocityScaleFunction=xml->getpar127("velocity_sensing",PFilterVelocityScaleFunction); - - xml->enterbranch("FILTER"); - GlobalFilter->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("FILTER_ENVELOPE"); - FilterEnvelope->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("FILTER_LFO"); - FilterLfo->getfromXML(xml); - xml->exitbranch(); - xml->exitbranch(); + + if (xml->enterbranch("FILTER_PARAMETERS")) { + PFilterVelocityScale=xml->getpar127("velocity_sensing_amplitude",PFilterVelocityScale); + PFilterVelocityScaleFunction=xml->getpar127("velocity_sensing",PFilterVelocityScaleFunction); + + xml->enterbranch("FILTER"); + GlobalFilter->getfromXML(xml); + xml->exitbranch(); + + xml->enterbranch("FILTER_ENVELOPE"); + FilterEnvelope->getfromXML(xml); + xml->exitbranch(); + + xml->enterbranch("FILTER_LFO"); + FilterLfo->getfromXML(xml); + xml->exitbranch(); + xml->exitbranch(); }; }; diff --git a/src/Params/PADnoteParameters.h b/src/Params/PADnoteParameters.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - - PADnoteParameters.h - Parameters for PADnote (PADsynth) + + PADnoteParameters.h - Parameters for PADnote (PADsynth) Copyright (C) 2002-2005 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 + 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, @@ -36,132 +36,133 @@ #include "Presets.h" #include <string> -class PADnoteParameters:public Presets{ - public: - PADnoteParameters(FFTwrapper *fft_,pthread_mutex_t *mutex_); - ~PADnoteParameters(); - - void defaults(); - void add2XML(XMLwrapper *xml); - void getfromXML(XMLwrapper *xml); - - //returns a value between 0.0-1.0 that represents the estimation perceived bandwidth - REALTYPE getprofile(REALTYPE *smp,int size); - - //parameters - - //the mode: 0 - bandwidth, 1 - discrete (bandwidth=0), 2 - continous - //the harmonic profile is used only on mode 0 - unsigned char Pmode; - - //Harmonic profile (the frequency distribution of a single harmonic) - struct { - struct{//base function - unsigned char type; - unsigned char par1; - }base; - unsigned char freqmult;//frequency multiplier of the distribution - struct{//the modulator of the distribution - unsigned char par1; - unsigned char freq; - }modulator; - - unsigned char width;//the width of the resulting function after the modulation - struct{//the amplitude multiplier of the harmonic profile - unsigned char mode; - unsigned char type; - unsigned char par1; - unsigned char par2; - }amp; - bool autoscale;//if the scale of the harmonic profile is computed automaticaly - unsigned char onehalf;//what part of the base function is used to make the distribution - }Php; - - - unsigned int Pbandwidth;//the values are from 0 to 1000 - unsigned char Pbwscale;//how the bandwidth is increased according to the harmonic's frequency - - struct{//where are positioned the harmonics (on integer multimplier or different places) - unsigned char type; - unsigned char par1,par2,par3;//0..255 - }Phrpos; - - struct {//quality of the samples (how many samples, the length of them,etc.) - unsigned char samplesize; - unsigned char basenote,oct,smpoct; - } Pquality; - - //frequency parameters - //If the base frequency is fixed to 440 Hz - unsigned char Pfixedfreq; - - /* Equal temperate (this is used only if the Pfixedfreq is enabled) - If this parameter is 0, the frequency is fixed (to 440 Hz); - if this parameter is 64, 1 MIDI halftone -> 1 frequency halftone */ - unsigned char PfixedfreqET; - unsigned short int PDetune;//fine detune - unsigned short int PCoarseDetune;//coarse detune+octave - unsigned char PDetuneType;//detune type - - EnvelopeParams *FreqEnvelope; //Frequency Envelope - LFOParams *FreqLfo;//Frequency LFO - - //Amplitude parameters - unsigned char PStereo; - /* Panning - 0 - random - 1 - left - 64 - center - 127 - right */ - unsigned char PPanning; - - unsigned char PVolume; - - unsigned char PAmpVelocityScaleFunction; - - EnvelopeParams *AmpEnvelope; - - LFOParams *AmpLfo; - - unsigned char PPunchStrength,PPunchTime,PPunchStretch,PPunchVelocitySensing; - - //Filter Parameters - FilterParams *GlobalFilter; - - // filter velocity sensing - unsigned char PFilterVelocityScale; - - // filter velocity sensing - unsigned char PFilterVelocityScaleFunction; - - EnvelopeParams *FilterEnvelope; - LFOParams *FilterLfo; - - - - - REALTYPE setPbandwidth(int Pbandwidth);//returns the BandWidth in cents - REALTYPE getNhr(int n);//gets the n-th overtone position relatively to N harmonic - - void applyparameters(bool lockmutex); - void export2wav(std::string basefilename); - - OscilGen *oscilgen; - Resonance *resonance; - - struct{ - int size; - REALTYPE basefreq; - REALTYPE *smp; - }sample[PAD_MAX_SAMPLES],newsample; - - private: - void generatespectrum_bandwidthMode(REALTYPE *spectrum, int size,REALTYPE basefreq,REALTYPE *profile,int profilesize,REALTYPE bwadjust); - void generatespectrum_otherModes(REALTYPE *spectrum, int size,REALTYPE basefreq,REALTYPE *profile,int profilesize,REALTYPE bwadjust); - void deletesamples(); - void deletesample(int n); - - FFTwrapper *fft; - pthread_mutex_t *mutex; +class PADnoteParameters:public Presets +{ +public: + PADnoteParameters(FFTwrapper *fft_,pthread_mutex_t *mutex_); + ~PADnoteParameters(); + + void defaults(); + void add2XML(XMLwrapper *xml); + void getfromXML(XMLwrapper *xml); + + //returns a value between 0.0-1.0 that represents the estimation perceived bandwidth + REALTYPE getprofile(REALTYPE *smp,int size); + + //parameters + + //the mode: 0 - bandwidth, 1 - discrete (bandwidth=0), 2 - continous + //the harmonic profile is used only on mode 0 + unsigned char Pmode; + + //Harmonic profile (the frequency distribution of a single harmonic) + struct { + struct {//base function + unsigned char type; + unsigned char par1; + }base; + unsigned char freqmult;//frequency multiplier of the distribution + struct {//the modulator of the distribution + unsigned char par1; + unsigned char freq; + }modulator; + + unsigned char width;//the width of the resulting function after the modulation + struct {//the amplitude multiplier of the harmonic profile + unsigned char mode; + unsigned char type; + unsigned char par1; + unsigned char par2; + }amp; + bool autoscale;//if the scale of the harmonic profile is computed automaticaly + unsigned char onehalf;//what part of the base function is used to make the distribution + }Php; + + + unsigned int Pbandwidth;//the values are from 0 to 1000 + unsigned char Pbwscale;//how the bandwidth is increased according to the harmonic's frequency + + struct {//where are positioned the harmonics (on integer multimplier or different places) + unsigned char type; + unsigned char par1,par2,par3;//0..255 + }Phrpos; + + struct {//quality of the samples (how many samples, the length of them,etc.) + unsigned char samplesize; + unsigned char basenote,oct,smpoct; + } Pquality; + + //frequency parameters + //If the base frequency is fixed to 440 Hz + unsigned char Pfixedfreq; + + /* Equal temperate (this is used only if the Pfixedfreq is enabled) + If this parameter is 0, the frequency is fixed (to 440 Hz); + if this parameter is 64, 1 MIDI halftone -> 1 frequency halftone */ + unsigned char PfixedfreqET; + unsigned short int PDetune;//fine detune + unsigned short int PCoarseDetune;//coarse detune+octave + unsigned char PDetuneType;//detune type + + EnvelopeParams *FreqEnvelope; //Frequency Envelope + LFOParams *FreqLfo;//Frequency LFO + + //Amplitude parameters + unsigned char PStereo; + /* Panning - 0 - random + 1 - left + 64 - center + 127 - right */ + unsigned char PPanning; + + unsigned char PVolume; + + unsigned char PAmpVelocityScaleFunction; + + EnvelopeParams *AmpEnvelope; + + LFOParams *AmpLfo; + + unsigned char PPunchStrength,PPunchTime,PPunchStretch,PPunchVelocitySensing; + + //Filter Parameters + FilterParams *GlobalFilter; + + // filter velocity sensing + unsigned char PFilterVelocityScale; + + // filter velocity sensing + unsigned char PFilterVelocityScaleFunction; + + EnvelopeParams *FilterEnvelope; + LFOParams *FilterLfo; + + + + + REALTYPE setPbandwidth(int Pbandwidth);//returns the BandWidth in cents + REALTYPE getNhr(int n);//gets the n-th overtone position relatively to N harmonic + + void applyparameters(bool lockmutex); + void export2wav(std::string basefilename); + + OscilGen *oscilgen; + Resonance *resonance; + + struct { + int size; + REALTYPE basefreq; + REALTYPE *smp; + }sample[PAD_MAX_SAMPLES],newsample; + +private: + void generatespectrum_bandwidthMode(REALTYPE *spectrum, int size,REALTYPE basefreq,REALTYPE *profile,int profilesize,REALTYPE bwadjust); + void generatespectrum_otherModes(REALTYPE *spectrum, int size,REALTYPE basefreq,REALTYPE *profile,int profilesize,REALTYPE bwadjust); + void deletesamples(); + void deletesample(int n); + + FFTwrapper *fft; + pthread_mutex_t *mutex; }; diff --git a/src/Params/Presets.C b/src/Params/Presets.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Presets.C - Presets and Clipboard management Copyright (C) 2002-2005 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 + 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, @@ -24,89 +24,95 @@ #include <string.h> -Presets::Presets(){ +Presets::Presets() +{ type[0]=0; nelement=-1; }; -Presets::~Presets(){ +Presets::~Presets() +{ }; -void Presets::setpresettype(const char *type){ +void Presets::setpresettype(const char *type) +{ strcpy(this->type,type); }; -void Presets::copy(const char *name){ +void Presets::copy(const char *name) +{ XMLwrapper *xml=new XMLwrapper(); - + //used only for the clipboard if (name==NULL) xml->minimal=false; - + char type[MAX_PRESETTYPE_SIZE]; strcpy(type,this->type); if (nelement!=-1) strcat(type,"n"); if (name==NULL) { - if (strstr(type,"Plfo")!=NULL) strcpy(type,"Plfo"); + if (strstr(type,"Plfo")!=NULL) strcpy(type,"Plfo"); }; xml->beginbranch(type); if (nelement==-1) add2XML(xml); - else add2XMLsection(xml,nelement); + else add2XMLsection(xml,nelement); xml->endbranch(); if (name==NULL) presetsstore.copyclipboard(xml,type); - else presetsstore.copypreset(xml,type,name); - + else presetsstore.copypreset(xml,type,name); + delete(xml); nelement=-1; }; -void Presets::paste(int npreset){ +void Presets::paste(int npreset) +{ char type[MAX_PRESETTYPE_SIZE]; strcpy(type,this->type); if (nelement!=-1) strcat(type,"n"); - if (npreset==0){ - if (strstr(type,"Plfo")!=NULL) strcpy(type,"Plfo"); + if (npreset==0) { + if (strstr(type,"Plfo")!=NULL) strcpy(type,"Plfo"); }; XMLwrapper *xml=new XMLwrapper(); - if (npreset==0){ - if (!checkclipboardtype()) { - nelement=-1; - delete(xml); - return; - }; - if (!presetsstore.pasteclipboard(xml)) { - delete(xml); - nelement=-1; - return; - }; + if (npreset==0) { + if (!checkclipboardtype()) { + nelement=-1; + delete(xml); + return; + }; + if (!presetsstore.pasteclipboard(xml)) { + delete(xml); + nelement=-1; + return; + }; } else { - if (!presetsstore.pastepreset(xml,npreset)) { - delete(xml); - nelement=-1; - return; - }; + if (!presetsstore.pastepreset(xml,npreset)) { + delete(xml); + nelement=-1; + return; + }; }; - + if (xml->enterbranch(type)==0) { - nelement=-1; - return; + nelement=-1; + return; + }; + if (nelement==-1) { + defaults(); + getfromXML(xml); + } else { + defaults(nelement); + getfromXMLsection(xml,nelement); }; - if (nelement==-1) { - defaults(); - getfromXML(xml); - } else { - defaults(nelement); - getfromXMLsection(xml,nelement); - }; xml->exitbranch(); - + delete(xml); nelement=-1; }; -bool Presets::checkclipboardtype(){ +bool Presets::checkclipboardtype() +{ char type[MAX_PRESETTYPE_SIZE]; strcpy(type,this->type); if (nelement!=-1) strcat(type,"n"); @@ -114,16 +120,19 @@ bool Presets::checkclipboardtype(){ return(presetsstore.checkclipboardtype(type)); }; -void Presets::setelement(int n){ +void Presets::setelement(int n) +{ nelement=n; }; -void Presets::rescanforpresets(){ +void Presets::rescanforpresets() +{ presetsstore.rescanforpresets(type); }; -void Presets::deletepreset(int npreset){ +void Presets::deletepreset(int npreset) +{ presetsstore.deletepreset(npreset); }; diff --git a/src/Params/Presets.h b/src/Params/Presets.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Presets.h - Presets and Clipboard management Copyright (C) 2002-2005 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 + 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, @@ -28,31 +28,32 @@ #include "PresetsStore.h" /**Presets and Clipboard management*/ -class Presets{ - public: - Presets(); - virtual ~Presets(); - - void copy(const char *name);/**<if name==NULL, the clipboard is used*/ - void paste(int npreset);//npreset==0 for clipboard - bool checkclipboardtype(); - void deletepreset(int npreset); - - char type[MAX_PRESETTYPE_SIZE]; - void setelement(int n); - - void rescanforpresets(); - - protected: - void setpresettype(const char *type); - private: - virtual void add2XML(XMLwrapper *xml)=0; - virtual void getfromXML(XMLwrapper *xml)=0; - virtual void defaults()=0; - virtual void add2XMLsection(XMLwrapper *xml,int n){}; - virtual void getfromXMLsection(XMLwrapper *xml,int n){}; - virtual void defaults(int n){}; - int nelement; +class Presets +{ +public: + Presets(); + virtual ~Presets(); + + void copy(const char *name);/**<if name==NULL, the clipboard is used*/ + void paste(int npreset);//npreset==0 for clipboard + bool checkclipboardtype(); + void deletepreset(int npreset); + + char type[MAX_PRESETTYPE_SIZE]; + void setelement(int n); + + void rescanforpresets(); + +protected: + void setpresettype(const char *type); +private: + virtual void add2XML(XMLwrapper *xml)=0; + virtual void getfromXML(XMLwrapper *xml)=0; + virtual void defaults()=0; + virtual void add2XMLsection(XMLwrapper *xml,int n) {}; + virtual void getfromXMLsection(XMLwrapper *xml,int n) {}; + virtual void defaults(int n) {}; + int nelement; }; #endif diff --git a/src/Params/PresetsStore.C b/src/Params/PresetsStore.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + PresetsStore.C - Presets and Clipboard store Copyright (C) 2002-2005 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 + 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, @@ -29,130 +29,140 @@ PresetsStore presetsstore; -PresetsStore::PresetsStore(){ +PresetsStore::PresetsStore() +{ clipboard.data=NULL; clipboard.type[0]=0; - - for (int i=0;i<MAX_PRESETS;i++){ - presets[i].file=NULL; - presets[i].name=NULL; + + for (int i=0;i<MAX_PRESETS;i++) { + presets[i].file=NULL; + presets[i].name=NULL; }; - + }; -PresetsStore::~PresetsStore(){ +PresetsStore::~PresetsStore() +{ if (clipboard.data!=NULL) free (clipboard.data); clearpresets(); }; //Clipboard management -void PresetsStore::copyclipboard(XMLwrapper *xml,char *type){ +void PresetsStore::copyclipboard(XMLwrapper *xml,char *type) +{ strcpy(clipboard.type,type); if (clipboard.data!=NULL) free (clipboard.data); clipboard.data=xml->getXMLdata(); }; -bool PresetsStore::pasteclipboard(XMLwrapper *xml){ +bool PresetsStore::pasteclipboard(XMLwrapper *xml) +{ if (clipboard.data!=NULL) xml->putXMLdata(clipboard.data); - else return(false); - return(true); + else return(false); + return(true); }; -bool PresetsStore::checkclipboardtype(char *type){ +bool PresetsStore::checkclipboardtype(char *type) +{ //makes LFO's compatible if ((strstr(type,"Plfo")!=NULL)&&(strstr(clipboard.type,"Plfo")!=NULL)) return(true); return(strcmp(type,clipboard.type)==0); }; //Presets management -void PresetsStore::clearpresets(){ - for (int i=0;i<MAX_PRESETS;i++){ - if (presets[i].file!=NULL) { - delete(presets[i].file); - presets[i].file=NULL; - }; - if (presets[i].name!=NULL) { - delete(presets[i].name); - presets[i].name=NULL; - }; +void PresetsStore::clearpresets() +{ + for (int i=0;i<MAX_PRESETS;i++) { + if (presets[i].file!=NULL) { + delete(presets[i].file); + presets[i].file=NULL; + }; + if (presets[i].name!=NULL) { + delete(presets[i].name); + presets[i].name=NULL; + }; }; - + }; //a helper function that compares 2 presets[] -int Presets_compar(const void *a,const void *b){ +int Presets_compar(const void *a,const void *b) +{ struct PresetsStore::presetstruct *p1= (PresetsStore::presetstruct *)a; struct PresetsStore::presetstruct *p2= (PresetsStore::presetstruct *)b; if (((p1->name)==NULL)||((p2->name)==NULL)) return(0); - + return(strcasecmp(p1->name,p2->name)<0); }; -void PresetsStore::rescanforpresets(char *type){ +void PresetsStore::rescanforpresets(char *type) +{ clearpresets(); int presetk=0; char ftype[MAX_STRING_SIZE]; snprintf(ftype,MAX_STRING_SIZE,".%s.xpz",type); - - for (int i=0;i<MAX_BANK_ROOT_DIRS;i++){ - if (config.cfg.presetsDirList[i]==NULL) continue; - char *dirname=config.cfg.presetsDirList[i]; - DIR *dir=opendir(dirname); - if (dir==NULL) continue; - struct dirent *fn; - while((fn=readdir(dir))){ - const char *filename=fn->d_name; - if (strstr(filename,ftype)==NULL) continue; - - - presets[presetk].file=new char [MAX_STRING_SIZE]; - presets[presetk].name=new char [MAX_STRING_SIZE]; - char tmpc=dirname[strlen(dirname)-1]; - const char *tmps; - if ((tmpc=='/')||(tmpc=='\\')) tmps=""; - else tmps="/"; - snprintf(presets[presetk].file,MAX_STRING_SIZE,"%s%s%s",dirname,tmps,filename); - snprintf(presets[presetk].name,MAX_STRING_SIZE,"%s",filename); - - char *tmp=strstr(presets[presetk].name,ftype); - if (tmp!=NULL) tmp[0]='\0'; - presetk++; if (presetk>=MAX_PRESETS) return; - }; - - closedir(dir); + + for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) { + if (config.cfg.presetsDirList[i]==NULL) continue; + char *dirname=config.cfg.presetsDirList[i]; + DIR *dir=opendir(dirname); + if (dir==NULL) continue; + struct dirent *fn; + while ((fn=readdir(dir))) { + const char *filename=fn->d_name; + if (strstr(filename,ftype)==NULL) continue; + + + presets[presetk].file=new char [MAX_STRING_SIZE]; + presets[presetk].name=new char [MAX_STRING_SIZE]; + char tmpc=dirname[strlen(dirname)-1]; + const char *tmps; + if ((tmpc=='/')||(tmpc=='\\')) tmps=""; + else tmps="/"; + snprintf(presets[presetk].file,MAX_STRING_SIZE,"%s%s%s",dirname,tmps,filename); + snprintf(presets[presetk].name,MAX_STRING_SIZE,"%s",filename); + + char *tmp=strstr(presets[presetk].name,ftype); + if (tmp!=NULL) tmp[0]='\0'; + presetk++; + if (presetk>=MAX_PRESETS) return; + }; + + closedir(dir); }; //sort the presets - for (int j=0;j<MAX_PRESETS-1;j++){ - for (int i=j+1;i<MAX_PRESETS;i++){ - if (Presets_compar(&presets[i],&presets[j])) { - presetstruct tmp=presets[i]; - presets[i]=presets[j]; - presets[j]=tmp; - }; - }; + for (int j=0;j<MAX_PRESETS-1;j++) { + for (int i=j+1;i<MAX_PRESETS;i++) { + if (Presets_compar(&presets[i],&presets[j])) { + presetstruct tmp=presets[i]; + presets[i]=presets[j]; + presets[j]=tmp; + }; + }; }; }; -void PresetsStore::copypreset(XMLwrapper *xml,char *type, const char *name){ +void PresetsStore::copypreset(XMLwrapper *xml,char *type, const char *name) +{ char filename[MAX_STRING_SIZE],tmpfilename[MAX_STRING_SIZE]; - + if (config.cfg.presetsDirList[0]==NULL) return; - + snprintf(tmpfilename,MAX_STRING_SIZE,"%s",name); //make the filenames legal for (int i=0;i<(int) strlen(tmpfilename);i++) { - char c=tmpfilename[i]; - if ((c>='0')&&(c<='9')) continue; - if ((c>='A')&&(c<='Z')) continue; - if ((c>='a')&&(c<='z')) continue; - if ((c=='-')||(c==' ')) continue; - tmpfilename[i]='_'; + char c=tmpfilename[i]; + if ((c>='0')&&(c<='9')) continue; + if ((c>='A')&&(c<='Z')) continue; + if ((c>='a')&&(c<='z')) continue; + if ((c=='-')||(c==' ')) continue; + tmpfilename[i]='_'; }; - + const char *dirname=config.cfg.presetsDirList[0]; char tmpc=dirname[strlen(dirname)-1]; const char *tmps; @@ -160,11 +170,12 @@ void PresetsStore::copypreset(XMLwrapper *xml,char *type, const char *name){ else tmps="/"; snprintf(filename,MAX_STRING_SIZE,"%s%s%s.%s.xpz",dirname,tmps,name,type); - + xml->saveXMLfile(filename); }; -bool PresetsStore::pastepreset(XMLwrapper *xml, int npreset){ +bool PresetsStore::pastepreset(XMLwrapper *xml, int npreset) +{ npreset--; if (npreset>=MAX_PRESETS) return(false); char *filename=presets[npreset].file; @@ -173,7 +184,8 @@ bool PresetsStore::pastepreset(XMLwrapper *xml, int npreset){ return(result); }; -void PresetsStore::deletepreset(int npreset){ +void PresetsStore::deletepreset(int npreset) +{ npreset--; if (npreset>=MAX_PRESETS) return; char *filename=presets[npreset].file; diff --git a/src/Params/PresetsStore.h b/src/Params/PresetsStore.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + PresetsStore.C - Presets and Clipboard store Copyright (C) 2002-2005 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 + 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, @@ -26,37 +26,38 @@ #define MAX_PRESETTYPE_SIZE 30 #define MAX_PRESETS 1000 -class PresetsStore{ - public: - PresetsStore(); - ~PresetsStore(); - - //Clipboard stuff - void copyclipboard(XMLwrapper *xml,char *type); - bool pasteclipboard(XMLwrapper *xml); - bool checkclipboardtype(char *type); - - //presets stuff - void copypreset(XMLwrapper *xml,char *type, const char *name); - bool pastepreset(XMLwrapper *xml, int npreset); - void deletepreset(int npreset); - - struct presetstruct{ - char *file; - char *name; - }; - presetstruct presets[MAX_PRESETS]; - - void rescanforpresets(char *type); - - private: - struct { - char *data; - char type[MAX_PRESETTYPE_SIZE]; - } clipboard; - - void clearpresets(); - +class PresetsStore +{ +public: + PresetsStore(); + ~PresetsStore(); + + //Clipboard stuff + void copyclipboard(XMLwrapper *xml,char *type); + bool pasteclipboard(XMLwrapper *xml); + bool checkclipboardtype(char *type); + + //presets stuff + void copypreset(XMLwrapper *xml,char *type, const char *name); + bool pastepreset(XMLwrapper *xml, int npreset); + void deletepreset(int npreset); + + struct presetstruct { + char *file; + char *name; + }; + presetstruct presets[MAX_PRESETS]; + + void rescanforpresets(char *type); + +private: + struct { + char *data; + char type[MAX_PRESETTYPE_SIZE]; + } clipboard; + + void clearpresets(); + }; extern PresetsStore presetsstore; diff --git a/src/Params/SUBnoteParameters.C b/src/Params/SUBnoteParameters.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - - SUBnoteParameters.C - Parameters for SUBnote (SUBsynth) + + SUBnoteParameters.C - Parameters for SUBnote (SUBsynth) Copyright (C) 2002-2005 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 + 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, @@ -24,7 +24,8 @@ #include "SUBnoteParameters.h" #include <stdio.h> -SUBnoteParameters::SUBnoteParameters():Presets(){ +SUBnoteParameters::SUBnoteParameters():Presets() +{ setpresettype("Psubsyth"); AmpEnvelope=new EnvelopeParams(64,1); AmpEnvelope->ADSRinit_dB(0,40,127,25); @@ -36,16 +37,17 @@ SUBnoteParameters::SUBnoteParameters():Presets(){ GlobalFilter=new FilterParams(2,80,40); GlobalFilterEnvelope=new EnvelopeParams(0,1); GlobalFilterEnvelope->ADSRinit_filter(64,40,64,70,60,64); - + defaults(); }; -void SUBnoteParameters::defaults(){ - PVolume=96; +void SUBnoteParameters::defaults() +{ + PVolume=96; PPanning=64; PAmpVelocityScaleFunction=90; - + Pfixedfreq=0; PfixedfreqET=0; Pnumstages=2; @@ -60,10 +62,10 @@ void SUBnoteParameters::defaults(){ PDetuneType=1; PFreqEnvelopeEnabled=0; PBandWidthEnvelopeEnabled=0; - - for (int n=0;n<MAX_SUB_HARMONICS;n++){ - Phmag[n]=0; - Phrelbw[n]=64; + + for (int n=0;n<MAX_SUB_HARMONICS;n++) { + Phmag[n]=0; + Phrelbw[n]=64; }; Phmag[0]=127; @@ -81,7 +83,8 @@ void SUBnoteParameters::defaults(){ -SUBnoteParameters::~SUBnoteParameters(){ +SUBnoteParameters::~SUBnoteParameters() +{ delete (AmpEnvelope); delete (FreqEnvelope); delete (BandWidthEnvelope); @@ -92,144 +95,146 @@ SUBnoteParameters::~SUBnoteParameters(){ -void SUBnoteParameters::add2XML(XMLwrapper *xml){ +void SUBnoteParameters::add2XML(XMLwrapper *xml) +{ xml->addpar("num_stages",Pnumstages); xml->addpar("harmonic_mag_type",Phmagtype); xml->addpar("start",Pstart); - + xml->beginbranch("HARMONICS"); - for (int i=0;i<MAX_SUB_HARMONICS;i++){ - if ((Phmag[i]==0)&&(xml->minimal)) continue; - xml->beginbranch("HARMONIC",i); - xml->addpar("mag",Phmag[i]); - xml->addpar("relbw",Phrelbw[i]); - xml->endbranch(); - }; + for (int i=0;i<MAX_SUB_HARMONICS;i++) { + if ((Phmag[i]==0)&&(xml->minimal)) continue; + xml->beginbranch("HARMONIC",i); + xml->addpar("mag",Phmag[i]); + xml->addpar("relbw",Phrelbw[i]); + xml->endbranch(); + }; xml->endbranch(); xml->beginbranch("AMPLITUDE_PARAMETERS"); - xml->addparbool("stereo",Pstereo); - xml->addpar("volume",PVolume); - xml->addpar("panning",PPanning); - xml->addpar("velocity_sensing",PAmpVelocityScaleFunction); - xml->beginbranch("AMPLITUDE_ENVELOPE"); - AmpEnvelope->add2XML(xml); - xml->endbranch(); + xml->addparbool("stereo",Pstereo); + xml->addpar("volume",PVolume); + xml->addpar("panning",PPanning); + xml->addpar("velocity_sensing",PAmpVelocityScaleFunction); + xml->beginbranch("AMPLITUDE_ENVELOPE"); + AmpEnvelope->add2XML(xml); + xml->endbranch(); xml->endbranch(); xml->beginbranch("FREQUENCY_PARAMETERS"); - xml->addparbool("fixed_freq",Pfixedfreq); - xml->addpar("fixed_freq_et",PfixedfreqET); - - xml->addpar("detune",PDetune); - xml->addpar("coarse_detune",PCoarseDetune); - xml->addpar("detune_type",PDetuneType); - - xml->addpar("bandwidth",Pbandwidth); - xml->addpar("bandwidth_scale",Pbwscale); - - xml->addparbool("freq_envelope_enabled",PFreqEnvelopeEnabled); - if ((PFreqEnvelopeEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("FREQUENCY_ENVELOPE"); - FreqEnvelope->add2XML(xml); - xml->endbranch(); - }; - - xml->addparbool("band_width_envelope_enabled",PBandWidthEnvelopeEnabled); - if ((PBandWidthEnvelopeEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("BANDWIDTH_ENVELOPE"); - BandWidthEnvelope->add2XML(xml); - xml->endbranch(); - }; + xml->addparbool("fixed_freq",Pfixedfreq); + xml->addpar("fixed_freq_et",PfixedfreqET); + + xml->addpar("detune",PDetune); + xml->addpar("coarse_detune",PCoarseDetune); + xml->addpar("detune_type",PDetuneType); + + xml->addpar("bandwidth",Pbandwidth); + xml->addpar("bandwidth_scale",Pbwscale); + + xml->addparbool("freq_envelope_enabled",PFreqEnvelopeEnabled); + if ((PFreqEnvelopeEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("FREQUENCY_ENVELOPE"); + FreqEnvelope->add2XML(xml); + xml->endbranch(); + }; + + xml->addparbool("band_width_envelope_enabled",PBandWidthEnvelopeEnabled); + if ((PBandWidthEnvelopeEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("BANDWIDTH_ENVELOPE"); + BandWidthEnvelope->add2XML(xml); + xml->endbranch(); + }; xml->endbranch(); xml->beginbranch("FILTER_PARAMETERS"); - xml->addparbool("enabled",PGlobalFilterEnabled); - if ((PGlobalFilterEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("FILTER"); - GlobalFilter->add2XML(xml); - xml->endbranch(); - - xml->addpar("filter_velocity_sensing",PGlobalFilterVelocityScaleFunction); - xml->addpar("filter_velocity_sensing_amplitude",PGlobalFilterVelocityScale); - - xml->beginbranch("FILTER_ENVELOPE"); - GlobalFilterEnvelope->add2XML(xml); - xml->endbranch(); - }; + xml->addparbool("enabled",PGlobalFilterEnabled); + if ((PGlobalFilterEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("FILTER"); + GlobalFilter->add2XML(xml); + xml->endbranch(); + + xml->addpar("filter_velocity_sensing",PGlobalFilterVelocityScaleFunction); + xml->addpar("filter_velocity_sensing_amplitude",PGlobalFilterVelocityScale); + + xml->beginbranch("FILTER_ENVELOPE"); + GlobalFilterEnvelope->add2XML(xml); + xml->endbranch(); + }; xml->endbranch(); }; -void SUBnoteParameters::getfromXML(XMLwrapper *xml){ +void SUBnoteParameters::getfromXML(XMLwrapper *xml) +{ Pnumstages=xml->getpar127("num_stages",Pnumstages); Phmagtype=xml->getpar127("harmonic_mag_type",Phmagtype); Pstart=xml->getpar127("start",Pstart); - - if (xml->enterbranch("HARMONICS")){ - Phmag[0]=0; - for (int i=0;i<MAX_SUB_HARMONICS;i++){ - if (xml->enterbranch("HARMONIC",i)==0) continue; - Phmag[i]=xml->getpar127("mag",Phmag[i]); - Phrelbw[i]=xml->getpar127("relbw",Phrelbw[i]); - xml->exitbranch(); - }; - xml->exitbranch(); + + if (xml->enterbranch("HARMONICS")) { + Phmag[0]=0; + for (int i=0;i<MAX_SUB_HARMONICS;i++) { + if (xml->enterbranch("HARMONIC",i)==0) continue; + Phmag[i]=xml->getpar127("mag",Phmag[i]); + Phrelbw[i]=xml->getpar127("relbw",Phrelbw[i]); + xml->exitbranch(); + }; + xml->exitbranch(); }; - if (xml->enterbranch("AMPLITUDE_PARAMETERS")){ - Pstereo=xml->getparbool("stereo",Pstereo); - PVolume=xml->getpar127("volume",PVolume); - PPanning=xml->getpar127("panning",PPanning); - PAmpVelocityScaleFunction=xml->getpar127("velocity_sensing",PAmpVelocityScaleFunction); - if (xml->enterbranch("AMPLITUDE_ENVELOPE")){ - AmpEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - xml->exitbranch(); + if (xml->enterbranch("AMPLITUDE_PARAMETERS")) { + Pstereo=xml->getparbool("stereo",Pstereo); + PVolume=xml->getpar127("volume",PVolume); + PPanning=xml->getpar127("panning",PPanning); + PAmpVelocityScaleFunction=xml->getpar127("velocity_sensing",PAmpVelocityScaleFunction); + if (xml->enterbranch("AMPLITUDE_ENVELOPE")) { + AmpEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + xml->exitbranch(); }; - if (xml->enterbranch("FREQUENCY_PARAMETERS")){ - Pfixedfreq=xml->getparbool("fixed_freq",Pfixedfreq); - PfixedfreqET=xml->getpar127("fixed_freq_et",PfixedfreqET); - - PDetune=xml->getpar("detune",PDetune,0,16383); - PCoarseDetune=xml->getpar("coarse_detune",PCoarseDetune,0,16383); - PDetuneType=xml->getpar127("detune_type",PDetuneType); - - Pbandwidth=xml->getpar127("bandwidth",Pbandwidth); - Pbwscale=xml->getpar127("bandwidth_scale",Pbwscale); - - PFreqEnvelopeEnabled=xml->getparbool("freq_envelope_enabled",PFreqEnvelopeEnabled); - if (xml->enterbranch("FREQUENCY_ENVELOPE")){ - FreqEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - - PBandWidthEnvelopeEnabled=xml->getparbool("band_width_envelope_enabled",PBandWidthEnvelopeEnabled); - if (xml->enterbranch("BANDWIDTH_ENVELOPE")){ - BandWidthEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - + if (xml->enterbranch("FREQUENCY_PARAMETERS")) { + Pfixedfreq=xml->getparbool("fixed_freq",Pfixedfreq); + PfixedfreqET=xml->getpar127("fixed_freq_et",PfixedfreqET); + + PDetune=xml->getpar("detune",PDetune,0,16383); + PCoarseDetune=xml->getpar("coarse_detune",PCoarseDetune,0,16383); + PDetuneType=xml->getpar127("detune_type",PDetuneType); + + Pbandwidth=xml->getpar127("bandwidth",Pbandwidth); + Pbwscale=xml->getpar127("bandwidth_scale",Pbwscale); + + PFreqEnvelopeEnabled=xml->getparbool("freq_envelope_enabled",PFreqEnvelopeEnabled); + if (xml->enterbranch("FREQUENCY_ENVELOPE")) { + FreqEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + + PBandWidthEnvelopeEnabled=xml->getparbool("band_width_envelope_enabled",PBandWidthEnvelopeEnabled); + if (xml->enterbranch("BANDWIDTH_ENVELOPE")) { + BandWidthEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + xml->exitbranch(); }; - - if (xml->enterbranch("FILTER_PARAMETERS")){ - PGlobalFilterEnabled=xml->getparbool("enabled",PGlobalFilterEnabled); - if (xml->enterbranch("FILTER")){ - GlobalFilter->getfromXML(xml); - xml->exitbranch(); - }; - - PGlobalFilterVelocityScaleFunction=xml->getpar127("filter_velocity_sensing",PGlobalFilterVelocityScaleFunction); - PGlobalFilterVelocityScale=xml->getpar127("filter_velocity_sensing_amplitude",PGlobalFilterVelocityScale); - - if (xml->enterbranch("FILTER_ENVELOPE")){ - GlobalFilterEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - - xml->exitbranch(); + + if (xml->enterbranch("FILTER_PARAMETERS")) { + PGlobalFilterEnabled=xml->getparbool("enabled",PGlobalFilterEnabled); + if (xml->enterbranch("FILTER")) { + GlobalFilter->getfromXML(xml); + xml->exitbranch(); + }; + + PGlobalFilterVelocityScaleFunction=xml->getpar127("filter_velocity_sensing",PGlobalFilterVelocityScaleFunction); + PGlobalFilterVelocityScale=xml->getpar127("filter_velocity_sensing_amplitude",PGlobalFilterVelocityScale); + + if (xml->enterbranch("FILTER_ENVELOPE")) { + GlobalFilterEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + + xml->exitbranch(); }; }; diff --git a/src/Params/SUBnoteParameters.h b/src/Params/SUBnoteParameters.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - - SUBnoteParameters.h - Parameters for SUBnote (SUBsynth) + + SUBnoteParameters.h - Parameters for SUBnote (SUBsynth) Copyright (C) 2002-2005 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 + 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, @@ -29,74 +29,75 @@ #include "FilterParams.h" #include "Presets.h" -class SUBnoteParameters:public Presets{ - public: - SUBnoteParameters(); - ~SUBnoteParameters(); - - void add2XML(XMLwrapper *xml); - void defaults(); - void getfromXML(XMLwrapper *xml); - - //Parameters - //AMPLITUDE PARAMETRERS - unsigned char Pstereo;//0 for mono,1 for stereo - unsigned char PVolume; - unsigned char PPanning; - unsigned char PAmpVelocityScaleFunction; - EnvelopeParams *AmpEnvelope; - - //Frequency Parameters - unsigned short int PDetune; - unsigned short int PCoarseDetune; - unsigned char PDetuneType; - unsigned char PFreqEnvelopeEnabled; - EnvelopeParams *FreqEnvelope; - unsigned char PBandWidthEnvelopeEnabled; - EnvelopeParams *BandWidthEnvelope; - - //Filter Parameters (Global) - unsigned char PGlobalFilterEnabled; - FilterParams *GlobalFilter; - unsigned char PGlobalFilterVelocityScale; - unsigned char PGlobalFilterVelocityScaleFunction; - EnvelopeParams *GlobalFilterEnvelope; - - - //Other Parameters - - //If the base frequency is fixed to 440 Hz - unsigned char Pfixedfreq; - - /* Equal temperate (this is used only if the Pfixedfreq is enabled) - If this parameter is 0, the frequency is fixed (to 440 Hz); - if this parameter is 64, 1 MIDI halftone -> 1 frequency halftone */ - unsigned char PfixedfreqET; - - - //how many times the filters are applied - unsigned char Pnumstages; - - //bandwidth - unsigned char Pbandwidth; - - //How the magnitudes are computed (0=linear,1=-60dB,2=-60dB) - unsigned char Phmagtype; - - //Magnitudes - unsigned char Phmag[MAX_SUB_HARMONICS]; - - //Relative BandWidth ("64"=1.0) - unsigned char Phrelbw[MAX_SUB_HARMONICS]; - - //how much the bandwidth is increased according to lower/higher frequency; 64-default - unsigned char Pbwscale; - - //how the harmonics start("0"=0,"1"=random,"2"=1) - unsigned char Pstart; - - - private: +class SUBnoteParameters:public Presets +{ +public: + SUBnoteParameters(); + ~SUBnoteParameters(); + + void add2XML(XMLwrapper *xml); + void defaults(); + void getfromXML(XMLwrapper *xml); + + //Parameters + //AMPLITUDE PARAMETRERS + unsigned char Pstereo;//0 for mono,1 for stereo + unsigned char PVolume; + unsigned char PPanning; + unsigned char PAmpVelocityScaleFunction; + EnvelopeParams *AmpEnvelope; + + //Frequency Parameters + unsigned short int PDetune; + unsigned short int PCoarseDetune; + unsigned char PDetuneType; + unsigned char PFreqEnvelopeEnabled; + EnvelopeParams *FreqEnvelope; + unsigned char PBandWidthEnvelopeEnabled; + EnvelopeParams *BandWidthEnvelope; + + //Filter Parameters (Global) + unsigned char PGlobalFilterEnabled; + FilterParams *GlobalFilter; + unsigned char PGlobalFilterVelocityScale; + unsigned char PGlobalFilterVelocityScaleFunction; + EnvelopeParams *GlobalFilterEnvelope; + + + //Other Parameters + + //If the base frequency is fixed to 440 Hz + unsigned char Pfixedfreq; + + /* Equal temperate (this is used only if the Pfixedfreq is enabled) + If this parameter is 0, the frequency is fixed (to 440 Hz); + if this parameter is 64, 1 MIDI halftone -> 1 frequency halftone */ + unsigned char PfixedfreqET; + + + //how many times the filters are applied + unsigned char Pnumstages; + + //bandwidth + unsigned char Pbandwidth; + + //How the magnitudes are computed (0=linear,1=-60dB,2=-60dB) + unsigned char Phmagtype; + + //Magnitudes + unsigned char Phmag[MAX_SUB_HARMONICS]; + + //Relative BandWidth ("64"=1.0) + unsigned char Phrelbw[MAX_SUB_HARMONICS]; + + //how much the bandwidth is increased according to lower/higher frequency; 64-default + unsigned char Pbwscale; + + //how the harmonics start("0"=0,"1"=random,"2"=1) + unsigned char Pstart; + + +private: }; #endif diff --git a/src/Samples/AuSample.C b/src/Samples/AuSample.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + AuSample.h - Object for storing information on audio samples (for one channel) Copyright (C) 2009-2009 Mark McCurry Author: Mark McCurry 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 + 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, @@ -21,8 +21,8 @@ #include "AuSample.h" AuSample::AuSample(const int &length) - : Sample(length){} + : Sample(length) {} AuSample::AuSample(float *input,const int &length) - : Sample(input,length){} + : Sample(input,length) {} diff --git a/src/Samples/AuSample.h b/src/Samples/AuSample.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + AuSample.h - Object for storing information on audio samples (for one channel) Copyright (C) 2009-2009 Mark McCurry Author: Mark McCurry 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 + 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, @@ -26,10 +26,10 @@ class AuSample : public Sample { - public: - AuSample(const int &length); - AuSample(float *input,const int &length); - FqSample getFqSample();/**\todo implement this*/ +public: + AuSample(const int &length); + AuSample(float *input,const int &length); + FqSample getFqSample();/**\todo implement this*/ }; #endif diff --git a/src/Samples/FqSample.C b/src/Samples/FqSample.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + FqSample.C - Object for storing information on samples Copyright (C) 2009-2009 Mark McCurry Author: Mark McCurry 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 + 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, @@ -21,11 +21,11 @@ #include "FqSample.h" FqSample::FqSample(const int &length) - :Sample(length) + :Sample(length) {} FqSample::FqSample(float *input,const int &length) - : Sample(input,length) + : Sample(input,length) {} FqSample::~FqSample() diff --git a/src/Samples/FqSample.h b/src/Samples/FqSample.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + FqSample.h - Object for storing information on samples Copyright (C) 2009-2009 Mark McCurry Author: Mark McCurry 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 + 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, @@ -26,12 +26,12 @@ class FqSample : public Sample { - public: - FqSample(const int &length); - FqSample(float *input,const int &length); - ~FqSample(); - //FqSample &operator=(const FqSample &smp); - //float *dontuse(){return buffer;}; +public: + FqSample(const int &length); + FqSample(float *input,const int &length); + ~FqSample(); + //FqSample &operator=(const FqSample &smp); + //float *dontuse(){return buffer;}; }; #endif diff --git a/src/Samples/Sample.C b/src/Samples/Sample.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Sample.C - Object for storing information on samples Copyright (C) 2009-2009 Mark McCurry Author: Mark McCurry 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 + 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, @@ -21,31 +21,30 @@ #include "Sample.h" Sample::Sample(const Sample &smp) - : bufferSize(smp.bufferSize) + : bufferSize(smp.bufferSize) { buffer=new float[bufferSize]; - for(int i=0;i<bufferSize;++i) + for (int i=0;i<bufferSize;++i) *(i+buffer)=*(i+smp.buffer); } - + Sample::Sample(const int &length) - : bufferSize(length) + : bufferSize(length) { - if(length<1) - bufferSize=1; + if (length<1) + bufferSize=1; buffer=new float[bufferSize]; clear(); } Sample::Sample(float *input,const int &length) - : bufferSize(length) + : bufferSize(length) { - if(length>0){ + if (length>0) { buffer=new float[length]; - for(int i=0;i<length;++i) + for (int i=0;i<length;++i) *(buffer+i)=*(input+i); - } - else{ + } else { buffer=new float[1]; bufferSize=1; *buffer=0; @@ -54,29 +53,26 @@ Sample::Sample(float *input,const int &length) Sample::~Sample() { - delete[] buffer; + delete[] buffer; } void Sample::clear() { - for(int i=0;i<bufferSize;++i) + for (int i=0;i<bufferSize;++i) *(i+buffer)=0; } void Sample::operator=(const Sample &smp) { /**\todo rewrite to be less repetitive*/ - if(bufferSize==smp.bufferSize) - { - for(int i=0;i<bufferSize;++i) + if (bufferSize==smp.bufferSize) { + for (int i=0;i<bufferSize;++i) *(i+buffer)=*(i+smp.buffer); - } - else - { + } else { delete[] buffer; buffer=new float[smp.bufferSize]; bufferSize=smp.bufferSize; - for(int i=0;i<bufferSize;++i) + for (int i=0;i<bufferSize;++i) *(i+buffer)=*(i+smp.buffer); } } diff --git a/src/Samples/Sample.h b/src/Samples/Sample.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Sample.h - Object for storing information on samples Copyright (C) 2009-2009 Mark McCurry Author: Mark McCurry 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 + 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, @@ -24,31 +24,40 @@ /** * Base Class for Samples */ -class Sample{ - public: - Sample(const Sample &smp); - Sample(const int &length); - Sample(float *input,const int &length); - ~Sample(); - /**Fills the buffer with zeros*/ - void clear(); - /**States the size of the buffer - * @return the size of the buffer*/ - int size() const {return bufferSize;}; - /**Provides the indexing operator for non const Samples*/ - float &operator[](int index){return *(buffer+index%bufferSize);}; - /**Provides the indexing operator for const Samples*/ - const float &operator[](int index)const{return *(buffer+index%bufferSize);}; - /**Provides the assignment operator*/ - void operator=(const Sample &smp); - /**Provides direct access to the buffer to allow for transition - * - * This method should be removed to ensure encapsulation once - * it is integrated into the code*/ - float *dontuse(){return buffer;}; - private: - int bufferSize; - float *buffer; +class Sample +{ +public: + Sample(const Sample &smp); + Sample(const int &length); + Sample(float *input,const int &length); + ~Sample(); + /**Fills the buffer with zeros*/ + void clear(); + /**States the size of the buffer + * @return the size of the buffer*/ + int size() const { + return bufferSize; + }; + /**Provides the indexing operator for non const Samples*/ + float &operator[](int index) { + return *(buffer+index%bufferSize); + }; + /**Provides the indexing operator for const Samples*/ + const float &operator[](int index)const { + return *(buffer+index%bufferSize); + }; + /**Provides the assignment operator*/ + void operator=(const Sample &smp); + /**Provides direct access to the buffer to allow for transition + * + * This method should be removed to ensure encapsulation once + * it is integrated into the code*/ + float *dontuse() { + return buffer; + }; +private: + int bufferSize; + float *buffer; }; diff --git a/src/Seq/MIDIEvents.C b/src/Seq/MIDIEvents.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + MIDIEvents.C - It stores the midi events from midi file or sequencer Copyright (C) 2003-2005 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 + 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, @@ -24,30 +24,34 @@ #include <stdlib.h> #include <stdio.h> -MIDIEvents::MIDIEvents(){ +MIDIEvents::MIDIEvents() +{ }; -MIDIEvents::~MIDIEvents(){ +MIDIEvents::~MIDIEvents() +{ }; /************** Track stuff ***************/ -void MIDIEvents::writeevent(list *l,event *ev){ +void MIDIEvents::writeevent(list *l,event *ev) +{ listpos *tmp=new listpos; tmp->next=NULL; tmp->ev=*ev; if (l->current!=NULL) l->current->next=tmp; - else l->first=tmp; + else l->first=tmp; l->current=tmp; // printf("Wx%x ",(int) l->current); // printf("-> %d \n",l->current->ev.deltatime); l->size++; }; -void MIDIEvents::readevent(list *l,event *ev){ +void MIDIEvents::readevent(list *l,event *ev) +{ if (l->current==NULL) { - ev->type=-1; - return; + ev->type=-1; + return; }; *ev=l->current->ev; l->current=l->current->next; @@ -63,22 +67,25 @@ void MIDIEvents::readevent(list *l,event *ev){ }; -void MIDIEvents::rewindlist(list *l){ +void MIDIEvents::rewindlist(list *l) +{ l->current=l->first; }; -void MIDIEvents::deletelist(list *l){ +void MIDIEvents::deletelist(list *l) +{ l->current=l->first; if (l->current==NULL) return; - while (l->current->next!=NULL){ - listpos *tmp=l->current; - l->current=l->current->next; - delete(tmp); + while (l->current->next!=NULL) { + listpos *tmp=l->current; + l->current=l->current->next; + delete(tmp); }; deletelistreference(l); }; -void MIDIEvents::deletelistreference(list *l){ +void MIDIEvents::deletelistreference(list *l) +{ l->current=l->first=NULL; l->size=0; l->length=0.0; diff --git a/src/Seq/MIDIEvents.h b/src/Seq/MIDIEvents.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + MIDIEvents.h - It stores the midi events from midi file or sequencer Copyright (C) 2003-2005 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 + 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, @@ -28,37 +28,38 @@ /**storage the midi events from midi file or sequencer * \todo this looks quite like a remake of a linked list * if it is, then it should be rewritten to use <list>*/ -class MIDIEvents{ +class MIDIEvents +{ friend class MIDIFile; - public: - MIDIEvents(); - ~MIDIEvents(); +public: + MIDIEvents(); + ~MIDIEvents(); - protected: +protected: /* Events */ - struct event{ + struct event { int deltatime; - int channel;//on what midi channel is - int type,par1,par2;//type=1 for note, type=2 for controller, type=255 for time messages + int channel;//on what midi channel is + int type,par1,par2;//type=1 for note, type=2 for controller, type=255 for time messages } tmpevent; - struct listpos{ - event ev; + struct listpos { + event ev; struct listpos *next; }; - struct list{ - listpos *first,*current; - int size;//how many events are - double length;//in seconds + struct list { + listpos *first,*current; + int size;//how many events are + double length;//in seconds }; struct { - list track;//the stored track - list record;//the track being "recorded" from midi + list track;//the stored track + list record;//the track being "recorded" from midi } miditrack[NUM_MIDI_TRACKS]; - + void writeevent(list *l,event *ev); void readevent(list *l,event *ev); - + void rewindlist(list *l); void deletelist(list *l); void deletelistreference(list *l); diff --git a/src/Seq/MIDIFile.C b/src/Seq/MIDIFile.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + MIDIFile.C - MIDI file loader Copyright (C) 2003-2005 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 + 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, @@ -25,7 +25,8 @@ #include "MIDIFile.h" -MIDIFile::MIDIFile(){ +MIDIFile::MIDIFile() +{ midifile=NULL; midifilesize=0; midifilek=0; @@ -33,31 +34,33 @@ MIDIFile::MIDIFile(){ me=NULL; }; -MIDIFile::~MIDIFile(){ +MIDIFile::~MIDIFile() +{ clearmidifile(); }; -int MIDIFile::loadfile(const char *filename){ +int MIDIFile::loadfile(const char *filename) +{ clearmidifile(); - + FILE *file=fopen(filename,"r"); if (file==NULL) return(-1); - + char header[4]; ZERO(header,4); fread(header,4,1,file); //test to see if this a midi file - if ((header[0]!='M')||(header[1]!='T')||(header[2]!='h')||(header[3]!='d')){ - fclose(file); - return(-1); + if ((header[0]!='M')||(header[1]!='T')||(header[2]!='h')||(header[3]!='d')) { + fclose(file); + return(-1); }; - + //get the filesize fseek(file,0,SEEK_END); midifilesize=ftell(file); rewind(file); - + midifile=new unsigned char[midifilesize]; ZERO(midifile,midifilesize); fread(midifile,midifilesize,1,file); @@ -65,12 +68,13 @@ int MIDIFile::loadfile(const char *filename){ // for (int i=0;i<midifilesize;i++) printf("%2x ",midifile[i]); // printf("\n"); - - + + return(0); }; -int MIDIFile::parsemidifile(MIDIEvents *me_){ +int MIDIFile::parsemidifile(MIDIEvents *me_) +{ this->me=me_; //read the header @@ -88,19 +92,19 @@ int MIDIFile::parsemidifile(MIDIEvents *me_){ int division=getint16(); printf("division %d\n",division); - if (division>=0){//delta time units in each a quater note + if (division>=0) {//delta time units in each a quater note // tick=???; } else {//SMPTE (frames/second and ticks/frame) - printf("ERROR:in MIDIFile.C::parsemidifile() - SMPTE not implemented yet."); - }; - + printf("ERROR:in MIDIFile.C::parsemidifile() - SMPTE not implemented yet."); + }; + if (ntracks>=NUM_MIDI_TRACKS) ntracks=NUM_MIDI_TRACKS-1; - - for (int n=0;n<ntracks;n++){ - if (parsetrack(n)<0) { - clearmidifile(); - return(-1); - }; + + for (int n=0;n<ntracks;n++) { + if (parsetrack(n)<0) { + clearmidifile(); + return(-1); + }; }; printf("\n\nCURRENT File position is = 0x%x\n",midifilek); @@ -114,7 +118,8 @@ int MIDIFile::parsemidifile(MIDIEvents *me_){ //private members -int MIDIFile::parsetrack(int ntrack){ +int MIDIFile::parsetrack(int ntrack) +{ printf("\n--==*Reading track %d **==--\n",ntrack); int chunk=getint32();//MTrk @@ -127,82 +132,82 @@ int MIDIFile::parsetrack(int ntrack){ unsigned char lastmsg=0; unsigned int dt=0; - - while(!midieof){ - unsigned int msgdeltatime=getvarint32(); - + + while (!midieof) { + unsigned int msgdeltatime=getvarint32(); + /// printf("MSGDELTATIME = %d\n",msgdeltatime); - + // dt+=msgdeltatime; - int msg=peekbyte(); + int msg=peekbyte(); /// printf("raw msg=0x%x ",msg); - if (msg<0x80) { - msg=lastmsg; - } else { - lastmsg=msg; - getbyte(); - }; + if (msg<0x80) { + msg=lastmsg; + } else { + lastmsg=msg; + getbyte(); + }; /// printf("msg=0x%x\n",msg); // dt+=msgdeltatime; - add_dt(ntrack, msgdeltatime); - - unsigned int mtype,mlength; - - switch(msg){ - case 0x80 ... 0x8f://note on off - parsenoteoff(ntrack,msg & 0x0f,dt); - dt=0; - break; - case 0x90 ... 0x9f://note on (or note off) - parsenoteon(ntrack,msg & 0x0f,dt); - dt=0; - break; - case 0xa0 ... 0xaf://aftertouch - ignored - skipnbytes(2); - break; - case 0xb0 ... 0xbf://control change - parsecontrolchange(ntrack,msg & 0x0f,dt); - dt=0; - break; - case 0xc0 ... 0xcf://program change - ignored - skipnbytes(1); - break; - case 0xd0 ... 0xdf://channel pressure - ignored - skipnbytes(1); - break; - case 0xe0 ... 0xef://channel mode messages - skipnbytes(2); - break; - case 0xf0://sysex - ignored - while (getbyte()!=0xf7){ - if (midieof) break; - }; - break; - case 0xf7://sysex (another type) - ignored - skipnbytes(getvarint32()); - break; - - case 0xff://meta-event - mtype=getbyte(); - mlength=getbyte(); - parsemetaevent(mtype,mlength); - break; - - default: - getbyte(); - printf("UNKNOWN message! 0x%x\n",msg); - return(-1); - break; - }; - - - - if (midieof) return(-1); - - if ((midifilek-oldmidifilek)==size) break; - else if((midifilek-oldmidifilek)>size) return(-1); + add_dt(ntrack, msgdeltatime); + + unsigned int mtype,mlength; + + switch (msg) { + case 0x80 ... 0x8f://note on off + parsenoteoff(ntrack,msg & 0x0f,dt); + dt=0; + break; + case 0x90 ... 0x9f://note on (or note off) + parsenoteon(ntrack,msg & 0x0f,dt); + dt=0; + break; + case 0xa0 ... 0xaf://aftertouch - ignored + skipnbytes(2); + break; + case 0xb0 ... 0xbf://control change + parsecontrolchange(ntrack,msg & 0x0f,dt); + dt=0; + break; + case 0xc0 ... 0xcf://program change - ignored + skipnbytes(1); + break; + case 0xd0 ... 0xdf://channel pressure - ignored + skipnbytes(1); + break; + case 0xe0 ... 0xef://channel mode messages + skipnbytes(2); + break; + case 0xf0://sysex - ignored + while (getbyte()!=0xf7) { + if (midieof) break; + }; + break; + case 0xf7://sysex (another type) - ignored + skipnbytes(getvarint32()); + break; + + case 0xff://meta-event + mtype=getbyte(); + mlength=getbyte(); + parsemetaevent(mtype,mlength); + break; + + default: + getbyte(); + printf("UNKNOWN message! 0x%x\n",msg); + return(-1); + break; + }; + + + + if (midieof) return(-1); + + if ((midifilek-oldmidifilek)==size) break; + else if ((midifilek-oldmidifilek)>size) return(-1); // if (size!=6) return(-1);//header is always 6 bytes long }; @@ -212,40 +217,42 @@ int MIDIFile::parsetrack(int ntrack){ }; -void MIDIFile::parsenoteoff(char ntrack,char chan,unsigned int dt){ +void MIDIFile::parsenoteoff(char ntrack,char chan,unsigned int dt) +{ unsigned char note; note=getbyte(); - + unsigned char noteoff_velocity=getbyte();//unused by zynaddsubfx noteoff_velocity=0; if (chan>=NUM_MIDI_CHANNELS) return; - + me->tmpevent.deltatime=convertdt(dt); me->tmpevent.type=1; me->tmpevent.par1=note; me->tmpevent.par2=0; me->tmpevent.channel=chan; - + printf("Note off:%d \n",note); - - ///test + + ///test // ntrack=0; - + me->writeevent(&me->miditrack[(int)ntrack].record,&me->tmpevent); - + }; -void MIDIFile::parsenoteon(char ntrack,char chan,unsigned int dt){ +void MIDIFile::parsenoteon(char ntrack,char chan,unsigned int dt) +{ unsigned char note,vel; note=getbyte(); vel=getbyte(); - + // printf("ntrack=%d\n",ntrack); printf("[dt %d ] Note on:%d %d\n",dt,note,vel); - + if (chan>=NUM_MIDI_CHANNELS) return; - + me->tmpevent.deltatime=convertdt(dt); me->tmpevent.type=1; me->tmpevent.par1=note; @@ -253,52 +260,56 @@ void MIDIFile::parsenoteon(char ntrack,char chan,unsigned int dt){ me->tmpevent.channel=chan; me->writeevent(&me->miditrack[(int)ntrack].record,&me->tmpevent); - - + + }; -void MIDIFile::parsecontrolchange(char ntrack,char chan,unsigned int dt){ +void MIDIFile::parsecontrolchange(char ntrack,char chan,unsigned int dt) +{ unsigned char control,value; control=getbyte(); value=getbyte(); - + if (chan>=NUM_MIDI_CHANNELS) return; - + printf("[dt %d] Control change:%d %d\n",dt,control,value); - + me->tmpevent.deltatime=convertdt(dt); me->tmpevent.type=2; me->tmpevent.par1=control;//???????????? ma uit la Sequencer::recordnote() din varianele vechi de zyn me->tmpevent.par2=value; me->tmpevent.channel=chan; me->writeevent(&me->miditrack[(int)ntrack].record,&me->tmpevent); - + }; -void MIDIFile::parsepitchwheel(char ntrack,char chan, unsigned int dt){ +void MIDIFile::parsepitchwheel(char ntrack,char chan, unsigned int dt) +{ unsigned char valhi,vallo; vallo=getbyte(); valhi=getbyte(); - + if (chan>=NUM_MIDI_CHANNELS) return; - + int value=(int)valhi*128+vallo; - + printf("[dt %d] Pitch wheel:%d\n",dt,value); - + }; -void MIDIFile::parsemetaevent(unsigned char mtype,unsigned char mlength){ +void MIDIFile::parsemetaevent(unsigned char mtype,unsigned char mlength) +{ int oldmidifilek=midifilek; printf("meta-event type=0x%x length=%d\n",mtype,mlength); - + midifilek=oldmidifilek+mlength; - + }; -void MIDIFile::add_dt(char ntrack, unsigned int dt){ +void MIDIFile::add_dt(char ntrack, unsigned int dt) +{ me->tmpevent.deltatime=convertdt(dt); me->tmpevent.type=255; me->tmpevent.par1=0; @@ -308,7 +319,8 @@ void MIDIFile::add_dt(char ntrack, unsigned int dt){ }; -unsigned int MIDIFile::convertdt(unsigned int dt){ +unsigned int MIDIFile::convertdt(unsigned int dt) +{ double result=dt; printf("DT=%d\n",dt); @@ -316,7 +328,8 @@ unsigned int MIDIFile::convertdt(unsigned int dt){ }; -void MIDIFile::clearmidifile(){ +void MIDIFile::clearmidifile() +{ if (midifile!=NULL) delete(midifile); midifile=NULL; midifilesize=0; @@ -325,43 +338,48 @@ void MIDIFile::clearmidifile(){ data.tick=0.05; }; -unsigned char MIDIFile::getbyte(){ +unsigned char MIDIFile::getbyte() +{ if (midifilek>=midifilesize) { - midieof=true; - return(0); + midieof=true; + return(0); }; /// printf("(%d) ",midifile[midifilek]); return(midifile[midifilek++]); }; -unsigned char MIDIFile::peekbyte(){ +unsigned char MIDIFile::peekbyte() +{ if (midifilek>=midifilesize) { - midieof=true; - return(0); + midieof=true; + return(0); }; return(midifile[midifilek]); }; -unsigned int MIDIFile::getint32(){ +unsigned int MIDIFile::getint32() +{ unsigned int result=0; for (int i=0;i<4;i++) { - result=result*256+getbyte(); + result=result*256+getbyte(); }; if (midieof) result=0; return(result); }; -unsigned short int MIDIFile::getint16(){ +unsigned short int MIDIFile::getint16() +{ unsigned short int result=0; for (int i=0;i<2;i++) { - result=result*256+getbyte(); + result=result*256+getbyte(); }; if (midieof) result=0; return(result); }; -unsigned int MIDIFile::getvarint32(){ +unsigned int MIDIFile::getvarint32() +{ unsigned long result=0; unsigned char b; @@ -370,20 +388,21 @@ unsigned int MIDIFile::getvarint32(){ if ((result = getbyte()) & 0x80) { result &= 0x7f; do { - b=getbyte(); + b=getbyte(); result = (result << 7) + (b & 0x7f); - }while (b & 0x80); + } while (b & 0x80); } /// printf("[end - result= %d]\n",result); return result; }; -void MIDIFile::skipnbytes(int n){ +void MIDIFile::skipnbytes(int n) +{ midifilek+=n; - if (midifilek>=midifilesize){ - midifilek=midifilesize-1; - midieof=true; + if (midifilek>=midifilesize) { + midifilek=midifilesize-1; + midieof=true; }; }; diff --git a/src/Seq/MIDIFile.h b/src/Seq/MIDIFile.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + MIDIFile.h - MIDI file loader Copyright (C) 2003-2005 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 + 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, @@ -27,67 +27,68 @@ #include "MIDIEvents.h" /**MIDI file loader*/ -class MIDIFile{ - public: - MIDIFile(); - ~MIDIFile(); - - /**Loads the given file +class MIDIFile +{ +public: + MIDIFile(); + ~MIDIFile(); + + /**Loads the given file * @param filename The name of the file to load * @return -1 if there is an error, otherwise 0*/ - int loadfile(const char *filename); - - //returns -1 if there is an error, otherwise 0 - int parsemidifile(MIDIEvents *me_); - - private: - MIDIEvents *me; - - unsigned char *midifile; - int midifilesize,midifilek; - bool midieof; - - //returns -1 if there is an error, otherwise 0 - int parsetrack(int ntrack); - - void parsenoteoff(char ntrack,char chan,unsigned int dt); - void parsenoteon(char ntrack,char chan,unsigned int dt); - void parsecontrolchange(char ntrack,char chan,unsigned int dt); - void parsepitchwheel(char ntrack,char chan, unsigned int dt); - void parsemetaevent(unsigned char mtype,unsigned char mlength); - - void add_dt(char ntrack, unsigned int dt); - - void clearmidifile(); - - //convert the delta-time to internal format - unsigned int convertdt(unsigned int dt); - - /* Low Level MIDIfile functions */ - - //get a byte from the midifile - unsigned char getbyte(); - - //peek the current byte from the midifile - unsigned char peekbyte(); - - //get a set of 4 bytes from the midifile - unsigned int getint32(); - - //get a word of 2 bytes from the midifile - unsigned short int getint16(); - - //read a variable length quantity - unsigned int getvarint32(); - - //skip some bytes - void skipnbytes(int n); - - struct { - double tick;//how many seconds one tick has - - }data; - + int loadfile(const char *filename); + + //returns -1 if there is an error, otherwise 0 + int parsemidifile(MIDIEvents *me_); + +private: + MIDIEvents *me; + + unsigned char *midifile; + int midifilesize,midifilek; + bool midieof; + + //returns -1 if there is an error, otherwise 0 + int parsetrack(int ntrack); + + void parsenoteoff(char ntrack,char chan,unsigned int dt); + void parsenoteon(char ntrack,char chan,unsigned int dt); + void parsecontrolchange(char ntrack,char chan,unsigned int dt); + void parsepitchwheel(char ntrack,char chan, unsigned int dt); + void parsemetaevent(unsigned char mtype,unsigned char mlength); + + void add_dt(char ntrack, unsigned int dt); + + void clearmidifile(); + + //convert the delta-time to internal format + unsigned int convertdt(unsigned int dt); + + /* Low Level MIDIfile functions */ + + //get a byte from the midifile + unsigned char getbyte(); + + //peek the current byte from the midifile + unsigned char peekbyte(); + + //get a set of 4 bytes from the midifile + unsigned int getint32(); + + //get a word of 2 bytes from the midifile + unsigned short int getint16(); + + //read a variable length quantity + unsigned int getvarint32(); + + //skip some bytes + void skipnbytes(int n); + + struct { + double tick;//how many seconds one tick has + + }data; + }; #endif diff --git a/src/Seq/Sequencer.C b/src/Seq/Sequencer.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Sequencer.C - The Sequencer Copyright (C) 2003-2005 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 + 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, @@ -31,70 +31,76 @@ -Sequencer::Sequencer(){ +Sequencer::Sequencer() +{ play=0; - for (int i=0;i<NUM_MIDI_TRACKS;i++){ - miditrack[i].track.first=NULL; - miditrack[i].track.current=NULL; - miditrack[i].track.size=0; - miditrack[i].track.length=0.0; - miditrack[i].record.first=NULL; - miditrack[i].record.current=NULL; - miditrack[i].record.size=0; - miditrack[i].record.length=0.0; - - nextevent[i].time=0.0; - resettime(&playtime[i]); + for (int i=0;i<NUM_MIDI_TRACKS;i++) { + miditrack[i].track.first=NULL; + miditrack[i].track.current=NULL; + miditrack[i].track.size=0; + miditrack[i].track.length=0.0; + miditrack[i].record.first=NULL; + miditrack[i].record.current=NULL; + miditrack[i].record.size=0; + miditrack[i].record.length=0.0; + + nextevent[i].time=0.0; + resettime(&playtime[i]); }; - + setplayspeed(0); }; -Sequencer::~Sequencer(){ - for (int i=0;i<NUM_MIDI_TRACKS;i++){ - deletelist(&miditrack[i].track); - deletelist(&miditrack[i].record); +Sequencer::~Sequencer() +{ + for (int i=0;i<NUM_MIDI_TRACKS;i++) { + deletelist(&miditrack[i].track); + deletelist(&miditrack[i].record); }; }; -int Sequencer::importmidifile(const char *filename){ +int Sequencer::importmidifile(const char *filename) +{ if (midifile.loadfile(filename)<0) return(-1); - for (int i=0;i<NUM_MIDI_TRACKS;i++){ - deletelist(&miditrack[i].record); + for (int i=0;i<NUM_MIDI_TRACKS;i++) { + deletelist(&miditrack[i].record); }; if (midifile.parsemidifile(this)<0) return(-1); - + //copy the "record" track to the main track - for (int i=0;i<NUM_MIDI_TRACKS;i++){ - deletelist(&miditrack[i].track); - miditrack[i].track=miditrack[i].record; - deletelistreference(&miditrack[i].record); + for (int i=0;i<NUM_MIDI_TRACKS;i++) { + deletelist(&miditrack[i].track); + miditrack[i].track=miditrack[i].record; + deletelistreference(&miditrack[i].record); }; return(0); }; -void Sequencer::startplay(){ +void Sequencer::startplay() +{ if (play!=0) return; for (int i=0;i<NUM_MIDI_TRACKS;i++) resettime(&playtime[i]); - - for (int i=0;i<NUM_MIDI_TRACKS;i++){ - rewindlist(&miditrack[i].track); + + for (int i=0;i<NUM_MIDI_TRACKS;i++) { + rewindlist(&miditrack[i].track); }; play=1; - + }; -void Sequencer::stopplay(){ +void Sequencer::stopplay() +{ if (play==0) return; play=0; }; // ************ Player stuff *************** -int Sequencer::getevent(char ntrack,int *midich, int *type,int *par1, int *par2){ +int Sequencer::getevent(char ntrack,int *midich, int *type,int *par1, int *par2) +{ *type=0; if (play==0) return(-1); @@ -106,9 +112,9 @@ int Sequencer::getevent(char ntrack,int *midich, int *type,int *par1, int *par2) // printf("%g %g\n",nextevent[ntrack].time,playtime[ntrack].abs); if (nextevent[(int)ntrack].time<playtime[(int)ntrack].abs) readevent(&miditrack[(int)ntrack].track,&nextevent[(int)ntrack].ev); - else return(-1); + else return(-1); if (nextevent[(int)ntrack].ev.type==-1) return(-1); -// printf("********************************\n"); +// printf("********************************\n"); //sa pun aici o protectie. a.i. daca distanta dintre timpul curent si eveliment e prea mare (>1sec) sa elimin nota @@ -119,7 +125,7 @@ int Sequencer::getevent(char ntrack,int *midich, int *type,int *par1, int *par2) *par2=nextevent[(int)ntrack].ev.par2; *midich=nextevent[(int)ntrack].ev.channel; - + double dt=nextevent[(int)ntrack].ev.deltatime*0.0001*realplayspeed; printf("zzzzzzzzzzzzzz[%d] %d\n",ntrack,nextevent[(int)ntrack].ev.deltatime); nextevent[(int)ntrack].time+=dt; @@ -130,36 +136,39 @@ int Sequencer::getevent(char ntrack,int *midich, int *type,int *par1, int *par2) /************** Timer stuff ***************/ -void Sequencer::resettime(timestruct *t){ +void Sequencer::resettime(timestruct *t) +{ t->abs=0.0; t->rel=0.0; - + timeval tval; - + t->last=0.0; - #ifndef OS_WINDOWS - if (gettimeofday(&tval,NULL)==0) - t->last=tval.tv_sec+tval.tv_usec*0.000001; - #endif - +#ifndef OS_WINDOWS + if (gettimeofday(&tval,NULL)==0) + t->last=tval.tv_sec+tval.tv_usec*0.000001; +#endif + }; -void Sequencer::updatecounter(timestruct *t){ +void Sequencer::updatecounter(timestruct *t) +{ timeval tval; double current=0.0; - #ifndef OS_WINDOWS - if (gettimeofday(&tval,NULL)==0) - current=tval.tv_sec+tval.tv_usec*0.000001; - #endif - +#ifndef OS_WINDOWS + if (gettimeofday(&tval,NULL)==0) + current=tval.tv_sec+tval.tv_usec*0.000001; +#endif + t->rel=current - t->last; t->abs+=t->rel; t->last=current; - + // printf("%f %f %f\n",t->last,t->abs,t->rel); }; -void Sequencer::setplayspeed(int speed){ +void Sequencer::setplayspeed(int speed) +{ playspeed=speed; realplayspeed=pow(10.0,speed/128.0); }; diff --git a/src/Seq/Sequencer.h b/src/Seq/Sequencer.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Sequencer.h - The Sequencer Copyright (C) 2003-2005 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 + 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, @@ -28,62 +28,63 @@ /**The Sequencer * \todo restructure some of this code*/ -class Sequencer:public MIDIEvents{ - public: - /**Constructor*/ - Sequencer(); - /**Destructor*/ - ~Sequencer(); - - //these functions are called by the master and are ignored if the recorder/player are stopped - void recordnote(char chan, char note, char vel); - void recordcontroller(char chan,unsigned int type,int par); - - /**Gets an event \todo better description - * - * this is only for player - * @return 1 if this must be called at least once more - * 0 if there are no more notes for the current time - * -1 if there are no notes*/ - int getevent(char ntrack, int *midich,int *type,int *par1, int *par2); - - /**Imports a given midifile - * @return 0 if ok or -1 if there is a error loading file*/ - int importmidifile(const char *filename); - - void startplay(); - void stopplay(); - - - int play; - int playspeed;//viteza de rulare (0.1x-10x), 0=1.0x, 128=10x - void setplayspeed(int speed); - - private: - - MIDIFile midifile; - - /* Timer */ - struct timestruct{ - double abs;//the time from the begining of the track - double rel;//the time difference between the last and the current event - double last;//the time of the last event (absolute, since 1 Jan 1970) - //these must be double, because the float's precision is too low - //and all these represent the time in seconds - } playtime[NUM_MIDI_TRACKS]; - - void resettime(timestruct *t); - void updatecounter(timestruct *t);//this updates the timer values - - /* Player only*/ - - struct { - event ev; - double time; - } nextevent[NUM_MIDI_TRACKS]; - - double realplayspeed; - +class Sequencer:public MIDIEvents +{ +public: + /**Constructor*/ + Sequencer(); + /**Destructor*/ + ~Sequencer(); + + //these functions are called by the master and are ignored if the recorder/player are stopped + void recordnote(char chan, char note, char vel); + void recordcontroller(char chan,unsigned int type,int par); + + /**Gets an event \todo better description + * + * this is only for player + * @return 1 if this must be called at least once more + * 0 if there are no more notes for the current time + * -1 if there are no notes*/ + int getevent(char ntrack, int *midich,int *type,int *par1, int *par2); + + /**Imports a given midifile + * @return 0 if ok or -1 if there is a error loading file*/ + int importmidifile(const char *filename); + + void startplay(); + void stopplay(); + + + int play; + int playspeed;//viteza de rulare (0.1x-10x), 0=1.0x, 128=10x + void setplayspeed(int speed); + +private: + + MIDIFile midifile; + + /* Timer */ + struct timestruct { + double abs;//the time from the begining of the track + double rel;//the time difference between the last and the current event + double last;//the time of the last event (absolute, since 1 Jan 1970) + //these must be double, because the float's precision is too low + //and all these represent the time in seconds + } playtime[NUM_MIDI_TRACKS]; + + void resettime(timestruct *t); + void updatecounter(timestruct *t);//this updates the timer values + + /* Player only*/ + + struct { + event ev; + double time; + } nextevent[NUM_MIDI_TRACKS]; + + double realplayspeed; + }; #endif diff --git a/src/Synth/ADnote.C b/src/Synth/ADnote.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + ADnote.C - The "additive" synthesizer Copyright (C) 2002-2005 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 + 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, @@ -29,7 +29,8 @@ #include "ADnote.h" -ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote_,bool besilent){ +ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote_,bool besilent) +{ ready=0; tmpwave=new REALTYPE [SOUND_BUFFER_SIZE]; @@ -55,136 +56,152 @@ ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE ve NoteEnabled=ON; basefreq=freq; if (velocity>1.0) velocity=1.0; - this->velocity=velocity; + this->velocity=velocity; time=0.0; stereo=pars->GlobalPar.PStereo; NoteGlobalPar.Detune=getdetune(pars->GlobalPar.PDetuneType - ,pars->GlobalPar.PCoarseDetune,pars->GlobalPar.PDetune); + ,pars->GlobalPar.PCoarseDetune,pars->GlobalPar.PDetune); bandwidthDetuneMultiplier=pars->getBandwidthDetuneMultiplier(); - + if (pars->GlobalPar.PPanning==0) NoteGlobalPar.Panning=RND; - else NoteGlobalPar.Panning=pars->GlobalPar.PPanning/128.0; - + else NoteGlobalPar.Panning=pars->GlobalPar.PPanning/128.0; + NoteGlobalPar.FilterCenterPitch=pars->GlobalPar.GlobalFilter->getfreq()+//center freq - pars->GlobalPar.PFilterVelocityScale/127.0*6.0* //velocity sensing - (VelF(velocity,pars->GlobalPar.PFilterVelocityScaleFunction)-1); + pars->GlobalPar.PFilterVelocityScale/127.0*6.0* //velocity sensing + (VelF(velocity,pars->GlobalPar.PFilterVelocityScaleFunction)-1); if (pars->GlobalPar.PPunchStrength!=0) { NoteGlobalPar.Punch.Enabled=1; - NoteGlobalPar.Punch.t=1.0;//start from 1.0 and to 0.0 - NoteGlobalPar.Punch.initialvalue=( (pow(10,1.5*pars->GlobalPar.PPunchStrength/127.0)-1.0) - *VelF(velocity,pars->GlobalPar.PPunchVelocitySensing) ); - REALTYPE time=pow(10,3.0*pars->GlobalPar.PPunchTime/127.0)/10000.0;//0.1 .. 100 ms - REALTYPE stretch=pow(440.0/freq,pars->GlobalPar.PPunchStretch/64.0); - NoteGlobalPar.Punch.dt=1.0/(time*SAMPLE_RATE*stretch); + NoteGlobalPar.Punch.t=1.0;//start from 1.0 and to 0.0 + NoteGlobalPar.Punch.initialvalue=( (pow(10,1.5*pars->GlobalPar.PPunchStrength/127.0)-1.0) + *VelF(velocity,pars->GlobalPar.PPunchVelocitySensing) ); + REALTYPE time=pow(10,3.0*pars->GlobalPar.PPunchTime/127.0)/10000.0;//0.1 .. 100 ms + REALTYPE stretch=pow(440.0/freq,pars->GlobalPar.PPunchStretch/64.0); + NoteGlobalPar.Punch.dt=1.0/(time*SAMPLE_RATE*stretch); } else NoteGlobalPar.Punch.Enabled=0; - for (int nvoice=0;nvoice<NUM_VOICES;nvoice++){ - pars->VoicePar[nvoice].OscilSmp->newrandseed(rand()); - NoteVoicePar[nvoice].OscilSmp=NULL; - NoteVoicePar[nvoice].FMSmp=NULL; - NoteVoicePar[nvoice].VoiceOut=NULL; - - NoteVoicePar[nvoice].FMVoice=-1; - - if (pars->VoicePar[nvoice].Enabled==0) { - NoteVoicePar[nvoice].Enabled=OFF; - continue; //the voice is disabled - }; + for (int nvoice=0;nvoice<NUM_VOICES;nvoice++) { + pars->VoicePar[nvoice].OscilSmp->newrandseed(rand()); + NoteVoicePar[nvoice].OscilSmp=NULL; + NoteVoicePar[nvoice].FMSmp=NULL; + NoteVoicePar[nvoice].VoiceOut=NULL; - NoteVoicePar[nvoice].Enabled=ON; - NoteVoicePar[nvoice].fixedfreq=pars->VoicePar[nvoice].Pfixedfreq; - NoteVoicePar[nvoice].fixedfreqET=pars->VoicePar[nvoice].PfixedfreqET; - - //use the Globalpars.detunetype if the detunetype is 0 - if (pars->VoicePar[nvoice].PDetuneType!=0){ - NoteVoicePar[nvoice].Detune=getdetune(pars->VoicePar[nvoice].PDetuneType - ,pars->VoicePar[nvoice].PCoarseDetune,8192);//coarse detune - NoteVoicePar[nvoice].FineDetune=getdetune(pars->VoicePar[nvoice].PDetuneType - ,0,pars->VoicePar[nvoice].PDetune);//fine detune - } else { - NoteVoicePar[nvoice].Detune=getdetune(pars->GlobalPar.PDetuneType - ,pars->VoicePar[nvoice].PCoarseDetune,8192);//coarse detune - NoteVoicePar[nvoice].FineDetune=getdetune(pars->GlobalPar.PDetuneType - ,0,pars->VoicePar[nvoice].PDetune);//fine detune - }; - if (pars->VoicePar[nvoice].PFMDetuneType!=0){ - NoteVoicePar[nvoice].FMDetune=getdetune(pars->VoicePar[nvoice].PFMDetuneType - ,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune); - } else { - NoteVoicePar[nvoice].FMDetune=getdetune(pars->GlobalPar.PDetuneType - ,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune); - }; + NoteVoicePar[nvoice].FMVoice=-1; + + if (pars->VoicePar[nvoice].Enabled==0) { + NoteVoicePar[nvoice].Enabled=OFF; + continue; //the voice is disabled + }; + + NoteVoicePar[nvoice].Enabled=ON; + NoteVoicePar[nvoice].fixedfreq=pars->VoicePar[nvoice].Pfixedfreq; + NoteVoicePar[nvoice].fixedfreqET=pars->VoicePar[nvoice].PfixedfreqET; + + //use the Globalpars.detunetype if the detunetype is 0 + if (pars->VoicePar[nvoice].PDetuneType!=0) { + NoteVoicePar[nvoice].Detune=getdetune(pars->VoicePar[nvoice].PDetuneType + ,pars->VoicePar[nvoice].PCoarseDetune,8192);//coarse detune + NoteVoicePar[nvoice].FineDetune=getdetune(pars->VoicePar[nvoice].PDetuneType + ,0,pars->VoicePar[nvoice].PDetune);//fine detune + } else { + NoteVoicePar[nvoice].Detune=getdetune(pars->GlobalPar.PDetuneType + ,pars->VoicePar[nvoice].PCoarseDetune,8192);//coarse detune + NoteVoicePar[nvoice].FineDetune=getdetune(pars->GlobalPar.PDetuneType + ,0,pars->VoicePar[nvoice].PDetune);//fine detune + }; + if (pars->VoicePar[nvoice].PFMDetuneType!=0) { + NoteVoicePar[nvoice].FMDetune=getdetune(pars->VoicePar[nvoice].PFMDetuneType + ,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune); + } else { + NoteVoicePar[nvoice].FMDetune=getdetune(pars->GlobalPar.PDetuneType + ,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune); + }; - oscposhi[nvoice]=0;oscposlo[nvoice]=0.0; - oscposhiFM[nvoice]=0;oscposloFM[nvoice]=0.0; - - NoteVoicePar[nvoice].OscilSmp=new REALTYPE[OSCIL_SIZE+OSCIL_SMP_EXTRA_SAMPLES];//the extra points contains the first point - - //Get the voice's oscil or external's voice oscil - int vc=nvoice; - if (pars->VoicePar[nvoice].Pextoscil!=-1) vc=pars->VoicePar[nvoice].Pextoscil; - if (!pars->GlobalPar.Hrandgrouping) pars->VoicePar[vc].OscilSmp->newrandseed(rand()); - oscposhi[nvoice]=pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,getvoicebasefreq(nvoice), - pars->VoicePar[nvoice].Presonance); - - //I store the first elments to the last position for speedups - for (int i=0;i<OSCIL_SMP_EXTRA_SAMPLES;i++) NoteVoicePar[nvoice].OscilSmp[OSCIL_SIZE+i]=NoteVoicePar[nvoice].OscilSmp[i]; - - oscposhi[nvoice]+=(int)((pars->VoicePar[nvoice].Poscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4); - oscposhi[nvoice]%=OSCIL_SIZE; - - - NoteVoicePar[nvoice].FreqLfo=NULL; - NoteVoicePar[nvoice].FreqEnvelope=NULL; - - NoteVoicePar[nvoice].AmpLfo=NULL; - NoteVoicePar[nvoice].AmpEnvelope=NULL; - - NoteVoicePar[nvoice].VoiceFilter=NULL; - NoteVoicePar[nvoice].FilterEnvelope=NULL; - NoteVoicePar[nvoice].FilterLfo=NULL; - - NoteVoicePar[nvoice].FilterCenterPitch=pars->VoicePar[nvoice].VoiceFilter->getfreq(); + oscposhi[nvoice]=0; + oscposlo[nvoice]=0.0; + oscposhiFM[nvoice]=0; + oscposloFM[nvoice]=0.0; + + NoteVoicePar[nvoice].OscilSmp=new REALTYPE[OSCIL_SIZE+OSCIL_SMP_EXTRA_SAMPLES];//the extra points contains the first point + + //Get the voice's oscil or external's voice oscil + int vc=nvoice; + if (pars->VoicePar[nvoice].Pextoscil!=-1) vc=pars->VoicePar[nvoice].Pextoscil; + if (!pars->GlobalPar.Hrandgrouping) pars->VoicePar[vc].OscilSmp->newrandseed(rand()); + oscposhi[nvoice]=pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,getvoicebasefreq(nvoice), + pars->VoicePar[nvoice].Presonance); + + //I store the first elments to the last position for speedups + for (int i=0;i<OSCIL_SMP_EXTRA_SAMPLES;i++) NoteVoicePar[nvoice].OscilSmp[OSCIL_SIZE+i]=NoteVoicePar[nvoice].OscilSmp[i]; + + oscposhi[nvoice]+=(int)((pars->VoicePar[nvoice].Poscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4); + oscposhi[nvoice]%=OSCIL_SIZE; + + + NoteVoicePar[nvoice].FreqLfo=NULL; + NoteVoicePar[nvoice].FreqEnvelope=NULL; + + NoteVoicePar[nvoice].AmpLfo=NULL; + NoteVoicePar[nvoice].AmpEnvelope=NULL; + + NoteVoicePar[nvoice].VoiceFilter=NULL; + NoteVoicePar[nvoice].FilterEnvelope=NULL; + NoteVoicePar[nvoice].FilterLfo=NULL; + + NoteVoicePar[nvoice].FilterCenterPitch=pars->VoicePar[nvoice].VoiceFilter->getfreq(); NoteVoicePar[nvoice].filterbypass=pars->VoicePar[nvoice].Pfilterbypass; - - switch(pars->VoicePar[nvoice].PFMEnabled){ - case 1:NoteVoicePar[nvoice].FMEnabled=MORPH;break; - case 2:NoteVoicePar[nvoice].FMEnabled=RING_MOD;break; - case 3:NoteVoicePar[nvoice].FMEnabled=PHASE_MOD;break; - case 4:NoteVoicePar[nvoice].FMEnabled=FREQ_MOD;break; - case 5:NoteVoicePar[nvoice].FMEnabled=PITCH_MOD;break; - default:NoteVoicePar[nvoice].FMEnabled=NONE; - }; - NoteVoicePar[nvoice].FMVoice=pars->VoicePar[nvoice].PFMVoice; - NoteVoicePar[nvoice].FMFreqEnvelope=NULL; - NoteVoicePar[nvoice].FMAmpEnvelope=NULL; - - //Compute the Voice's modulator volume (incl. damping) - REALTYPE fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0-1.0); - switch (NoteVoicePar[nvoice].FMEnabled){ - case PHASE_MOD:fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0); - NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0; - break; - case FREQ_MOD:NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0; - break; - // case PITCH_MOD:NoteVoicePar[nvoice].FMVolume=(pars->VoicePar[nvoice].PFMVolume/127.0*8.0)*fmvoldamp;//??????????? - // break; - default:if (fmvoldamp>1.0) fmvoldamp=1.0; - NoteVoicePar[nvoice].FMVolume=pars->VoicePar[nvoice].PFMVolume/127.0*fmvoldamp; - }; + switch (pars->VoicePar[nvoice].PFMEnabled) { + case 1: + NoteVoicePar[nvoice].FMEnabled=MORPH; + break; + case 2: + NoteVoicePar[nvoice].FMEnabled=RING_MOD; + break; + case 3: + NoteVoicePar[nvoice].FMEnabled=PHASE_MOD; + break; + case 4: + NoteVoicePar[nvoice].FMEnabled=FREQ_MOD; + break; + case 5: + NoteVoicePar[nvoice].FMEnabled=PITCH_MOD; + break; + default: + NoteVoicePar[nvoice].FMEnabled=NONE; + }; + + NoteVoicePar[nvoice].FMVoice=pars->VoicePar[nvoice].PFMVoice; + NoteVoicePar[nvoice].FMFreqEnvelope=NULL; + NoteVoicePar[nvoice].FMAmpEnvelope=NULL; + + //Compute the Voice's modulator volume (incl. damping) + REALTYPE fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0-1.0); + switch (NoteVoicePar[nvoice].FMEnabled) { + case PHASE_MOD: + fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0); + NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0; + break; + case FREQ_MOD: + NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0; + break; + // case PITCH_MOD:NoteVoicePar[nvoice].FMVolume=(pars->VoicePar[nvoice].PFMVolume/127.0*8.0)*fmvoldamp;//??????????? + // break; + default: + if (fmvoldamp>1.0) fmvoldamp=1.0; + NoteVoicePar[nvoice].FMVolume=pars->VoicePar[nvoice].PFMVolume/127.0*fmvoldamp; + }; - //Voice's modulator velocity sensing - NoteVoicePar[nvoice].FMVolume*=VelF(velocity,partparams->VoicePar[nvoice].PFMVelocityScaleFunction); + //Voice's modulator velocity sensing + NoteVoicePar[nvoice].FMVolume*=VelF(velocity,partparams->VoicePar[nvoice].PFMVelocityScaleFunction); - FMoldsmp[nvoice]=0.0;//this is for FM (integration) + FMoldsmp[nvoice]=0.0;//this is for FM (integration) - firsttick[nvoice]=1; - NoteVoicePar[nvoice].DelayTicks=(int)((exp(pars->VoicePar[nvoice].PDelay/127.0*log(50.0))-1.0)/SOUND_BUFFER_SIZE/10.0*SAMPLE_RATE); - }; + firsttick[nvoice]=1; + NoteVoicePar[nvoice].DelayTicks=(int)((exp(pars->VoicePar[nvoice].PDelay/127.0*log(50.0))-1.0)/SOUND_BUFFER_SIZE/10.0*SAMPLE_RATE); + }; initparameters(); ready=1; @@ -195,29 +212,30 @@ ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE ve // initparameters() stuck together with some lines removed so that it // only alter the already playing note (to perform legato). It is // possible I left stuff that is not required for this. -void ADnote::ADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote_, bool externcall){ +void ADnote::ADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote_, bool externcall) +{ ADnoteParameters *pars=partparams; //Controller *ctl_=ctl; // Manage legato stuff if (externcall) Legato.msg=LM_Norm; - if (Legato.msg!=LM_CatchUp){ - Legato.lastfreq=Legato.param.freq; - Legato.param.freq=freq; - Legato.param.vel=velocity; - Legato.param.portamento=portamento_; - Legato.param.midinote=midinote_; - if (Legato.msg==LM_Norm){ - if (Legato.silent){ - Legato.fade.m=0.0; - Legato.msg=LM_FadeIn; - } else { - Legato.fade.m=1.0; - Legato.msg=LM_FadeOut; - return; - } - } - if (Legato.msg==LM_ToNorm) Legato.msg=LM_Norm; + if (Legato.msg!=LM_CatchUp) { + Legato.lastfreq=Legato.param.freq; + Legato.param.freq=freq; + Legato.param.vel=velocity; + Legato.param.portamento=portamento_; + Legato.param.midinote=midinote_; + if (Legato.msg==LM_Norm) { + if (Legato.silent) { + Legato.fade.m=0.0; + Legato.msg=LM_FadeIn; + } else { + Legato.fade.m=1.0; + Legato.msg=LM_FadeOut; + return; + } + } + if (Legato.msg==LM_ToNorm) Legato.msg=LM_Norm; } portamento=portamento_; @@ -225,10 +243,10 @@ void ADnote::ADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int basefreq=freq; if (velocity>1.0) velocity=1.0; - this->velocity=velocity; + this->velocity=velocity; NoteGlobalPar.Detune=getdetune(pars->GlobalPar.PDetuneType - ,pars->GlobalPar.PCoarseDetune,pars->GlobalPar.PDetune); + ,pars->GlobalPar.PCoarseDetune,pars->GlobalPar.PDetune); bandwidthDetuneMultiplier=pars->getBandwidthDetuneMultiplier(); if (pars->GlobalPar.PPanning==0) NoteGlobalPar.Panning=RND; @@ -236,85 +254,88 @@ void ADnote::ADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int NoteGlobalPar.FilterCenterPitch=pars->GlobalPar.GlobalFilter->getfreq()+//center freq - pars->GlobalPar.PFilterVelocityScale/127.0*6.0* //velocity sensing - (VelF(velocity,pars->GlobalPar.PFilterVelocityScaleFunction)-1); - - - for (int nvoice=0;nvoice<NUM_VOICES;nvoice++){ - if (NoteVoicePar[nvoice].Enabled==OFF) - continue; //(gf) Stay the same as first note in legato. - - NoteVoicePar[nvoice].fixedfreq=pars->VoicePar[nvoice].Pfixedfreq; - NoteVoicePar[nvoice].fixedfreqET=pars->VoicePar[nvoice].PfixedfreqET; - - //use the Globalpars.detunetype if the detunetype is 0 - if (pars->VoicePar[nvoice].PDetuneType!=0){ - NoteVoicePar[nvoice].Detune=getdetune(pars->VoicePar[nvoice].PDetuneType - ,pars->VoicePar[nvoice].PCoarseDetune,8192);//coarse detune - NoteVoicePar[nvoice].FineDetune=getdetune(pars->VoicePar[nvoice].PDetuneType - ,0,pars->VoicePar[nvoice].PDetune);//fine detune - } else { - NoteVoicePar[nvoice].Detune=getdetune(pars->GlobalPar.PDetuneType - ,pars->VoicePar[nvoice].PCoarseDetune,8192);//coarse detune - NoteVoicePar[nvoice].FineDetune=getdetune(pars->GlobalPar.PDetuneType - ,0,pars->VoicePar[nvoice].PDetune);//fine detune - }; - if (pars->VoicePar[nvoice].PFMDetuneType!=0){ - NoteVoicePar[nvoice].FMDetune=getdetune(pars->VoicePar[nvoice].PFMDetuneType - ,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune); - } else { - NoteVoicePar[nvoice].FMDetune=getdetune(pars->GlobalPar.PDetuneType - ,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune); - }; - - //Get the voice's oscil or external's voice oscil - int vc=nvoice; - if (pars->VoicePar[nvoice].Pextoscil!=-1) vc=pars->VoicePar[nvoice].Pextoscil; - if (!pars->GlobalPar.Hrandgrouping) pars->VoicePar[vc].OscilSmp->newrandseed(rand()); - - ///oscposhi[nvoice]=pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,getvoicebasefreq(nvoice),pars->VoicePar[nvoice].Presonance); - pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,getvoicebasefreq(nvoice),pars->VoicePar[nvoice].Presonance);//(gf)Modif of the above line. - - //I store the first elments to the last position for speedups - for (int i=0;i<OSCIL_SMP_EXTRA_SAMPLES;i++) NoteVoicePar[nvoice].OscilSmp[OSCIL_SIZE+i]=NoteVoicePar[nvoice].OscilSmp[i]; - - - NoteVoicePar[nvoice].FilterCenterPitch=pars->VoicePar[nvoice].VoiceFilter->getfreq(); - NoteVoicePar[nvoice].filterbypass=pars->VoicePar[nvoice].Pfilterbypass; - - - NoteVoicePar[nvoice].FMVoice=pars->VoicePar[nvoice].PFMVoice; - - //Compute the Voice's modulator volume (incl. damping) - REALTYPE fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0-1.0); - - switch (NoteVoicePar[nvoice].FMEnabled){ - case PHASE_MOD:fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0); - NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0; - break; - case FREQ_MOD:NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0; - break; - // case PITCH_MOD:NoteVoicePar[nvoice].FMVolume=(pars->VoicePar[nvoice].PFMVolume/127.0*8.0)*fmvoldamp;//??????????? - // break; - default:if (fmvoldamp>1.0) fmvoldamp=1.0; - NoteVoicePar[nvoice].FMVolume=pars->VoicePar[nvoice].PFMVolume/127.0*fmvoldamp; - }; - - //Voice's modulator velocity sensing - NoteVoicePar[nvoice].FMVolume*=VelF(velocity,partparams->VoicePar[nvoice].PFMVelocityScaleFunction); - - NoteVoicePar[nvoice].DelayTicks=(int)((exp(pars->VoicePar[nvoice].PDelay/127.0*log(50.0))-1.0)/SOUND_BUFFER_SIZE/10.0*SAMPLE_RATE); + pars->GlobalPar.PFilterVelocityScale/127.0*6.0* //velocity sensing + (VelF(velocity,pars->GlobalPar.PFilterVelocityScaleFunction)-1); + + + for (int nvoice=0;nvoice<NUM_VOICES;nvoice++) { + if (NoteVoicePar[nvoice].Enabled==OFF) + continue; //(gf) Stay the same as first note in legato. + + NoteVoicePar[nvoice].fixedfreq=pars->VoicePar[nvoice].Pfixedfreq; + NoteVoicePar[nvoice].fixedfreqET=pars->VoicePar[nvoice].PfixedfreqET; + + //use the Globalpars.detunetype if the detunetype is 0 + if (pars->VoicePar[nvoice].PDetuneType!=0) { + NoteVoicePar[nvoice].Detune=getdetune(pars->VoicePar[nvoice].PDetuneType + ,pars->VoicePar[nvoice].PCoarseDetune,8192);//coarse detune + NoteVoicePar[nvoice].FineDetune=getdetune(pars->VoicePar[nvoice].PDetuneType + ,0,pars->VoicePar[nvoice].PDetune);//fine detune + } else { + NoteVoicePar[nvoice].Detune=getdetune(pars->GlobalPar.PDetuneType + ,pars->VoicePar[nvoice].PCoarseDetune,8192);//coarse detune + NoteVoicePar[nvoice].FineDetune=getdetune(pars->GlobalPar.PDetuneType + ,0,pars->VoicePar[nvoice].PDetune);//fine detune + }; + if (pars->VoicePar[nvoice].PFMDetuneType!=0) { + NoteVoicePar[nvoice].FMDetune=getdetune(pars->VoicePar[nvoice].PFMDetuneType + ,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune); + } else { + NoteVoicePar[nvoice].FMDetune=getdetune(pars->GlobalPar.PDetuneType + ,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune); + }; + + //Get the voice's oscil or external's voice oscil + int vc=nvoice; + if (pars->VoicePar[nvoice].Pextoscil!=-1) vc=pars->VoicePar[nvoice].Pextoscil; + if (!pars->GlobalPar.Hrandgrouping) pars->VoicePar[vc].OscilSmp->newrandseed(rand()); + + ///oscposhi[nvoice]=pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,getvoicebasefreq(nvoice),pars->VoicePar[nvoice].Presonance); + pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,getvoicebasefreq(nvoice),pars->VoicePar[nvoice].Presonance);//(gf)Modif of the above line. + + //I store the first elments to the last position for speedups + for (int i=0;i<OSCIL_SMP_EXTRA_SAMPLES;i++) NoteVoicePar[nvoice].OscilSmp[OSCIL_SIZE+i]=NoteVoicePar[nvoice].OscilSmp[i]; + + + NoteVoicePar[nvoice].FilterCenterPitch=pars->VoicePar[nvoice].VoiceFilter->getfreq(); + NoteVoicePar[nvoice].filterbypass=pars->VoicePar[nvoice].Pfilterbypass; + + + NoteVoicePar[nvoice].FMVoice=pars->VoicePar[nvoice].PFMVoice; + + //Compute the Voice's modulator volume (incl. damping) + REALTYPE fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0-1.0); + + switch (NoteVoicePar[nvoice].FMEnabled) { + case PHASE_MOD: + fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0); + NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0; + break; + case FREQ_MOD: + NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0; + break; + // case PITCH_MOD:NoteVoicePar[nvoice].FMVolume=(pars->VoicePar[nvoice].PFMVolume/127.0*8.0)*fmvoldamp;//??????????? + // break; + default: + if (fmvoldamp>1.0) fmvoldamp=1.0; + NoteVoicePar[nvoice].FMVolume=pars->VoicePar[nvoice].PFMVolume/127.0*fmvoldamp; + }; + + //Voice's modulator velocity sensing + NoteVoicePar[nvoice].FMVolume*=VelF(velocity,partparams->VoicePar[nvoice].PFMVelocityScaleFunction); + + NoteVoicePar[nvoice].DelayTicks=(int)((exp(pars->VoicePar[nvoice].PDelay/127.0*log(50.0))-1.0)/SOUND_BUFFER_SIZE/10.0*SAMPLE_RATE); }; /// initparameters(); - /////////////// - // Altered content of initparameters(): + /////////////// + // Altered content of initparameters(): int nvoice,i,tmp[NUM_VOICES]; NoteGlobalPar.Volume=4.0*pow(0.1,3.0*(1.0-partparams->GlobalPar.PVolume/96.0))//-60 dB .. 0 dB - *VelF(velocity,partparams->GlobalPar.PAmpVelocityScaleFunction);//velocity sensing + *VelF(velocity,partparams->GlobalPar.PAmpVelocityScaleFunction);//velocity sensing globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout(); @@ -325,96 +346,97 @@ void ADnote::ADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int for (i=0;i<NUM_VOICES;i++) if (NoteVoicePar[i].FMVoice>=i) NoteVoicePar[i].FMVoice=-1; // Voice Parameter init - for (nvoice=0;nvoice<NUM_VOICES;nvoice++){ - if (NoteVoicePar[nvoice].Enabled==0) continue; + for (nvoice=0;nvoice<NUM_VOICES;nvoice++) { + if (NoteVoicePar[nvoice].Enabled==0) continue; - NoteVoicePar[nvoice].noisetype=partparams->VoicePar[nvoice].Type; - /* Voice Amplitude Parameters Init */ - NoteVoicePar[nvoice].Volume=pow(0.1,3.0*(1.0-partparams->VoicePar[nvoice].PVolume/127.0)) // -60 dB .. 0 dB - *VelF(velocity,partparams->VoicePar[nvoice].PAmpVelocityScaleFunction);//velocity + NoteVoicePar[nvoice].noisetype=partparams->VoicePar[nvoice].Type; + /* Voice Amplitude Parameters Init */ + NoteVoicePar[nvoice].Volume=pow(0.1,3.0*(1.0-partparams->VoicePar[nvoice].PVolume/127.0)) // -60 dB .. 0 dB + *VelF(velocity,partparams->VoicePar[nvoice].PAmpVelocityScaleFunction);//velocity - if (partparams->VoicePar[nvoice].PVolumeminus!=0) NoteVoicePar[nvoice].Volume=-NoteVoicePar[nvoice].Volume; + if (partparams->VoicePar[nvoice].PVolumeminus!=0) NoteVoicePar[nvoice].Volume=-NoteVoicePar[nvoice].Volume; - if (partparams->VoicePar[nvoice].PPanning==0) - NoteVoicePar[nvoice].Panning=RND;// random panning - else NoteVoicePar[nvoice].Panning=partparams->VoicePar[nvoice].PPanning/128.0; + if (partparams->VoicePar[nvoice].PPanning==0) + NoteVoicePar[nvoice].Panning=RND;// random panning + else NoteVoicePar[nvoice].Panning=partparams->VoicePar[nvoice].PPanning/128.0; - newamplitude[nvoice]=1.0; - if ((partparams->VoicePar[nvoice].PAmpEnvelopeEnabled!=0) - && (NoteVoicePar[nvoice].AmpEnvelope!=NULL)){ - newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); - }; + newamplitude[nvoice]=1.0; + if ((partparams->VoicePar[nvoice].PAmpEnvelopeEnabled!=0) + && (NoteVoicePar[nvoice].AmpEnvelope!=NULL)) { + newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); + }; - if ((partparams->VoicePar[nvoice].PAmpLfoEnabled!=0) - && (NoteVoicePar[nvoice].AmpLfo!=NULL)){ - newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpLfo->amplfoout(); - }; + if ((partparams->VoicePar[nvoice].PAmpLfoEnabled!=0) + && (NoteVoicePar[nvoice].AmpLfo!=NULL)) { + newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpLfo->amplfoout(); + }; - NoteVoicePar[nvoice].FilterFreqTracking=partparams->VoicePar[nvoice].VoiceFilter->getfreqtracking(basefreq); + NoteVoicePar[nvoice].FilterFreqTracking=partparams->VoicePar[nvoice].VoiceFilter->getfreqtracking(basefreq); - /* Voice Modulation Parameters Init */ - if ((NoteVoicePar[nvoice].FMEnabled!=NONE)&&(NoteVoicePar[nvoice].FMVoice<0)){ - partparams->VoicePar[nvoice].FMSmp->newrandseed(rand()); + /* Voice Modulation Parameters Init */ + if ((NoteVoicePar[nvoice].FMEnabled!=NONE)&&(NoteVoicePar[nvoice].FMVoice<0)) { + partparams->VoicePar[nvoice].FMSmp->newrandseed(rand()); - //Perform Anti-aliasing only on MORPH or RING MODULATION + //Perform Anti-aliasing only on MORPH or RING MODULATION - int vc=nvoice; - if (partparams->VoicePar[nvoice].PextFMoscil!=-1) vc=partparams->VoicePar[nvoice].PextFMoscil; + int vc=nvoice; + if (partparams->VoicePar[nvoice].PextFMoscil!=-1) vc=partparams->VoicePar[nvoice].PextFMoscil; - REALTYPE tmp=1.0; - if ((partparams->VoicePar[vc].FMSmp->Padaptiveharmonics!=0)|| - (NoteVoicePar[nvoice].FMEnabled==MORPH)|| - (NoteVoicePar[nvoice].FMEnabled==RING_MOD)){ - tmp=getFMvoicebasefreq(nvoice); - }; - if (!partparams->GlobalPar.Hrandgrouping) partparams->VoicePar[vc].FMSmp->newrandseed(rand()); + REALTYPE tmp=1.0; + if ((partparams->VoicePar[vc].FMSmp->Padaptiveharmonics!=0)|| + (NoteVoicePar[nvoice].FMEnabled==MORPH)|| + (NoteVoicePar[nvoice].FMEnabled==RING_MOD)) { + tmp=getFMvoicebasefreq(nvoice); + }; + if (!partparams->GlobalPar.Hrandgrouping) partparams->VoicePar[vc].FMSmp->newrandseed(rand()); - ///oscposhiFM[nvoice]=(oscposhi[nvoice]+partparams->VoicePar[vc].FMSmp->get(NoteVoicePar[nvoice].FMSmp,tmp)) % OSCIL_SIZE; - // / oscposhi[nvoice]+partparams->VoicePar[vc].FMSmp->get(NoteVoicePar[nvoice].FMSmp,tmp); //(gf) Modif of the above line. - for (int i=0;i<OSCIL_SMP_EXTRA_SAMPLES;i++) NoteVoicePar[nvoice].FMSmp[OSCIL_SIZE+i]=NoteVoicePar[nvoice].FMSmp[i]; - ///oscposhiFM[nvoice]+=(int)((partparams->VoicePar[nvoice].PFMoscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4); - ///oscposhiFM[nvoice]%=OSCIL_SIZE; - }; + ///oscposhiFM[nvoice]=(oscposhi[nvoice]+partparams->VoicePar[vc].FMSmp->get(NoteVoicePar[nvoice].FMSmp,tmp)) % OSCIL_SIZE; + // / oscposhi[nvoice]+partparams->VoicePar[vc].FMSmp->get(NoteVoicePar[nvoice].FMSmp,tmp); //(gf) Modif of the above line. + for (int i=0;i<OSCIL_SMP_EXTRA_SAMPLES;i++) NoteVoicePar[nvoice].FMSmp[OSCIL_SIZE+i]=NoteVoicePar[nvoice].FMSmp[i]; + ///oscposhiFM[nvoice]+=(int)((partparams->VoicePar[nvoice].PFMoscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4); + ///oscposhiFM[nvoice]%=OSCIL_SIZE; + }; - FMnewamplitude[nvoice]=NoteVoicePar[nvoice].FMVolume*ctl->fmamp.relamp; + FMnewamplitude[nvoice]=NoteVoicePar[nvoice].FMVolume*ctl->fmamp.relamp; - if ((partparams->VoicePar[nvoice].PFMAmpEnvelopeEnabled!=0) - && (NoteVoicePar[nvoice].FMAmpEnvelope!=NULL)){ - FMnewamplitude[nvoice]*=NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB(); - }; + if ((partparams->VoicePar[nvoice].PFMAmpEnvelopeEnabled!=0) + && (NoteVoicePar[nvoice].FMAmpEnvelope!=NULL)) { + FMnewamplitude[nvoice]*=NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB(); + }; }; - for (nvoice=0;nvoice<NUM_VOICES;nvoice++){ - for (i=nvoice+1;i<NUM_VOICES;i++) tmp[i]=0; - for (i=nvoice+1;i<NUM_VOICES;i++) - if ((NoteVoicePar[i].FMVoice==nvoice)&&(tmp[i]==0)){ - tmp[i]=1; - }; - /// if (NoteVoicePar[nvoice].VoiceOut!=NULL) for (i=0;i<SOUND_BUFFER_SIZE;i++) NoteVoicePar[nvoice].VoiceOut[i]=0.0; + for (nvoice=0;nvoice<NUM_VOICES;nvoice++) { + for (i=nvoice+1;i<NUM_VOICES;i++) tmp[i]=0; + for (i=nvoice+1;i<NUM_VOICES;i++) + if ((NoteVoicePar[i].FMVoice==nvoice)&&(tmp[i]==0)) { + tmp[i]=1; + }; + /// if (NoteVoicePar[nvoice].VoiceOut!=NULL) for (i=0;i<SOUND_BUFFER_SIZE;i++) NoteVoicePar[nvoice].VoiceOut[i]=0.0; }; /////////////// - // End of the ADlegatonote function. + // End of the ADlegatonote function. }; /* * Kill a voice of ADnote */ -void ADnote::KillVoice(int nvoice){ - +void ADnote::KillVoice(int nvoice) +{ + delete []NoteVoicePar[nvoice].OscilSmp; if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) delete(NoteVoicePar[nvoice].FreqEnvelope); NoteVoicePar[nvoice].FreqEnvelope=NULL; - + if (NoteVoicePar[nvoice].FreqLfo!=NULL) delete(NoteVoicePar[nvoice].FreqLfo); NoteVoicePar[nvoice].FreqLfo=NULL; if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) delete (NoteVoicePar[nvoice].AmpEnvelope); NoteVoicePar[nvoice].AmpEnvelope=NULL; - + if (NoteVoicePar[nvoice].AmpLfo!=NULL) delete (NoteVoicePar[nvoice].AmpLfo); NoteVoicePar[nvoice].AmpLfo=NULL; @@ -429,14 +451,14 @@ void ADnote::KillVoice(int nvoice){ if (NoteVoicePar[nvoice].FMFreqEnvelope!=NULL) delete (NoteVoicePar[nvoice].FMFreqEnvelope); NoteVoicePar[nvoice].FMFreqEnvelope=NULL; - + if (NoteVoicePar[nvoice].FMAmpEnvelope!=NULL) delete (NoteVoicePar[nvoice].FMAmpEnvelope); NoteVoicePar[nvoice].FMAmpEnvelope=NULL; - + if ((NoteVoicePar[nvoice].FMEnabled!=NONE)&&(NoteVoicePar[nvoice].FMVoice<0)) delete []NoteVoicePar[nvoice].FMSmp; - - if (NoteVoicePar[nvoice].VoiceOut!=NULL) - for (int i=0;i<SOUND_BUFFER_SIZE;i++) NoteVoicePar[nvoice].VoiceOut[i]=0.0;//do not delete, yet: perhaps is used by another voice + + if (NoteVoicePar[nvoice].VoiceOut!=NULL) + for (int i=0;i<SOUND_BUFFER_SIZE;i++) NoteVoicePar[nvoice].VoiceOut[i]=0.0;//do not delete, yet: perhaps is used by another voice NoteVoicePar[nvoice].Enabled=OFF; }; @@ -444,16 +466,17 @@ void ADnote::KillVoice(int nvoice){ /* * Kill the note */ -void ADnote::KillNote(){ +void ADnote::KillNote() +{ int nvoice; - for (nvoice=0;nvoice<NUM_VOICES;nvoice++){ - if (NoteVoicePar[nvoice].Enabled==ON) KillVoice(nvoice); + for (nvoice=0;nvoice<NUM_VOICES;nvoice++) { + if (NoteVoicePar[nvoice].Enabled==ON) KillVoice(nvoice); - //delete VoiceOut - if (NoteVoicePar[nvoice].VoiceOut!=NULL) delete(NoteVoicePar[nvoice].VoiceOut); - NoteVoicePar[nvoice].VoiceOut=NULL; + //delete VoiceOut + if (NoteVoicePar[nvoice].VoiceOut!=NULL) delete(NoteVoicePar[nvoice].VoiceOut); + NoteVoicePar[nvoice].VoiceOut=NULL; }; - + delete (NoteGlobalPar.FreqEnvelope); delete (NoteGlobalPar.FreqLfo); delete (NoteGlobalPar.AmpEnvelope); @@ -462,11 +485,12 @@ void ADnote::KillNote(){ if (stereo!=0) delete (NoteGlobalPar.GlobalFilterR); delete (NoteGlobalPar.FilterEnvelope); delete (NoteGlobalPar.FilterLfo); - + NoteEnabled=OFF; }; -ADnote::~ADnote(){ +ADnote::~ADnote() +{ if (NoteEnabled==ON) KillNote(); delete [] tmpwave; delete [] bypassl; @@ -477,122 +501,123 @@ ADnote::~ADnote(){ /* * Init the parameters */ -void ADnote::initparameters(){ +void ADnote::initparameters() +{ int nvoice,i,tmp[NUM_VOICES]; // Global Parameters NoteGlobalPar.FreqEnvelope=new Envelope(partparams->GlobalPar.FreqEnvelope,basefreq); NoteGlobalPar.FreqLfo=new LFO(partparams->GlobalPar.FreqLfo,basefreq); - + NoteGlobalPar.AmpEnvelope=new Envelope(partparams->GlobalPar.AmpEnvelope,basefreq); NoteGlobalPar.AmpLfo=new LFO(partparams->GlobalPar.AmpLfo,basefreq); NoteGlobalPar.Volume=4.0*pow(0.1,3.0*(1.0-partparams->GlobalPar.PVolume/96.0))//-60 dB .. 0 dB - *VelF(velocity,partparams->GlobalPar.PAmpVelocityScaleFunction);//velocity sensing + *VelF(velocity,partparams->GlobalPar.PAmpVelocityScaleFunction);//velocity sensing NoteGlobalPar.AmpEnvelope->envout_dB();//discard the first envelope output globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout(); NoteGlobalPar.GlobalFilterL=new Filter(partparams->GlobalPar.GlobalFilter); if (stereo!=0) NoteGlobalPar.GlobalFilterR=new Filter(partparams->GlobalPar.GlobalFilter); - + NoteGlobalPar.FilterEnvelope=new Envelope(partparams->GlobalPar.FilterEnvelope,basefreq); NoteGlobalPar.FilterLfo=new LFO(partparams->GlobalPar.FilterLfo,basefreq); NoteGlobalPar.FilterQ=partparams->GlobalPar.GlobalFilter->getq(); NoteGlobalPar.FilterFreqTracking=partparams->GlobalPar.GlobalFilter->getfreqtracking(basefreq); - + // Forbids the Modulation Voice to be greater or equal than voice for (i=0;i<NUM_VOICES;i++) if (NoteVoicePar[i].FMVoice>=i) NoteVoicePar[i].FMVoice=-1; // Voice Parameter init - for (nvoice=0;nvoice<NUM_VOICES;nvoice++){ + for (nvoice=0;nvoice<NUM_VOICES;nvoice++) { if (NoteVoicePar[nvoice].Enabled==0) continue; - NoteVoicePar[nvoice].noisetype=partparams->VoicePar[nvoice].Type; - /* Voice Amplitude Parameters Init */ - NoteVoicePar[nvoice].Volume=pow(0.1,3.0*(1.0-partparams->VoicePar[nvoice].PVolume/127.0)) // -60 dB .. 0 dB - *VelF(velocity,partparams->VoicePar[nvoice].PAmpVelocityScaleFunction);//velocity - - if (partparams->VoicePar[nvoice].PVolumeminus!=0) NoteVoicePar[nvoice].Volume=-NoteVoicePar[nvoice].Volume; - - if (partparams->VoicePar[nvoice].PPanning==0) - NoteVoicePar[nvoice].Panning=RND;// random panning - else NoteVoicePar[nvoice].Panning=partparams->VoicePar[nvoice].PPanning/128.0; - - newamplitude[nvoice]=1.0; - if (partparams->VoicePar[nvoice].PAmpEnvelopeEnabled!=0) { - NoteVoicePar[nvoice].AmpEnvelope=new Envelope(partparams->VoicePar[nvoice].AmpEnvelope,basefreq); - NoteVoicePar[nvoice].AmpEnvelope->envout_dB();//discard the first envelope sample - newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); - }; - - if (partparams->VoicePar[nvoice].PAmpLfoEnabled!=0){ - NoteVoicePar[nvoice].AmpLfo=new LFO(partparams->VoicePar[nvoice].AmpLfo,basefreq); - newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpLfo->amplfoout(); - }; + NoteVoicePar[nvoice].noisetype=partparams->VoicePar[nvoice].Type; + /* Voice Amplitude Parameters Init */ + NoteVoicePar[nvoice].Volume=pow(0.1,3.0*(1.0-partparams->VoicePar[nvoice].PVolume/127.0)) // -60 dB .. 0 dB + *VelF(velocity,partparams->VoicePar[nvoice].PAmpVelocityScaleFunction);//velocity - /* Voice Frequency Parameters Init */ - if (partparams->VoicePar[nvoice].PFreqEnvelopeEnabled!=0) - NoteVoicePar[nvoice].FreqEnvelope=new Envelope(partparams->VoicePar[nvoice].FreqEnvelope,basefreq); + if (partparams->VoicePar[nvoice].PVolumeminus!=0) NoteVoicePar[nvoice].Volume=-NoteVoicePar[nvoice].Volume; - if (partparams->VoicePar[nvoice].PFreqLfoEnabled!=0) NoteVoicePar[nvoice].FreqLfo=new LFO(partparams->VoicePar[nvoice].FreqLfo,basefreq); + if (partparams->VoicePar[nvoice].PPanning==0) + NoteVoicePar[nvoice].Panning=RND;// random panning + else NoteVoicePar[nvoice].Panning=partparams->VoicePar[nvoice].PPanning/128.0; - /* Voice Filter Parameters Init */ - if (partparams->VoicePar[nvoice].PFilterEnabled!=0){ - NoteVoicePar[nvoice].VoiceFilter=new Filter(partparams->VoicePar[nvoice].VoiceFilter); - }; + newamplitude[nvoice]=1.0; + if (partparams->VoicePar[nvoice].PAmpEnvelopeEnabled!=0) { + NoteVoicePar[nvoice].AmpEnvelope=new Envelope(partparams->VoicePar[nvoice].AmpEnvelope,basefreq); + NoteVoicePar[nvoice].AmpEnvelope->envout_dB();//discard the first envelope sample + newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); + }; - if (partparams->VoicePar[nvoice].PFilterEnvelopeEnabled!=0) - NoteVoicePar[nvoice].FilterEnvelope=new Envelope(partparams->VoicePar[nvoice].FilterEnvelope,basefreq); - - if (partparams->VoicePar[nvoice].PFilterLfoEnabled!=0) - NoteVoicePar[nvoice].FilterLfo=new LFO(partparams->VoicePar[nvoice].FilterLfo,basefreq); - - NoteVoicePar[nvoice].FilterFreqTracking=partparams->VoicePar[nvoice].VoiceFilter->getfreqtracking(basefreq); - - /* Voice Modulation Parameters Init */ - if ((NoteVoicePar[nvoice].FMEnabled!=NONE)&&(NoteVoicePar[nvoice].FMVoice<0)){ - partparams->VoicePar[nvoice].FMSmp->newrandseed(rand()); - NoteVoicePar[nvoice].FMSmp=new REALTYPE[OSCIL_SIZE+OSCIL_SMP_EXTRA_SAMPLES]; - - //Perform Anti-aliasing only on MORPH or RING MODULATION - - int vc=nvoice; - if (partparams->VoicePar[nvoice].PextFMoscil!=-1) vc=partparams->VoicePar[nvoice].PextFMoscil; - - REALTYPE tmp=1.0; - if ((partparams->VoicePar[vc].FMSmp->Padaptiveharmonics!=0)|| - (NoteVoicePar[nvoice].FMEnabled==MORPH)|| - (NoteVoicePar[nvoice].FMEnabled==RING_MOD)){ - tmp=getFMvoicebasefreq(nvoice); - }; - if (!partparams->GlobalPar.Hrandgrouping) partparams->VoicePar[vc].FMSmp->newrandseed(rand()); - - oscposhiFM[nvoice]=(oscposhi[nvoice]+partparams->VoicePar[vc].FMSmp->get(NoteVoicePar[nvoice].FMSmp,tmp)) % OSCIL_SIZE; - for (int i=0;i<OSCIL_SMP_EXTRA_SAMPLES;i++) NoteVoicePar[nvoice].FMSmp[OSCIL_SIZE+i]=NoteVoicePar[nvoice].FMSmp[i]; - oscposhiFM[nvoice]+=(int)((partparams->VoicePar[nvoice].PFMoscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4); - oscposhiFM[nvoice]%=OSCIL_SIZE; - }; + if (partparams->VoicePar[nvoice].PAmpLfoEnabled!=0) { + NoteVoicePar[nvoice].AmpLfo=new LFO(partparams->VoicePar[nvoice].AmpLfo,basefreq); + newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpLfo->amplfoout(); + }; - if (partparams->VoicePar[nvoice].PFMFreqEnvelopeEnabled!=0) - NoteVoicePar[nvoice].FMFreqEnvelope=new Envelope(partparams->VoicePar[nvoice].FMFreqEnvelope,basefreq); + /* Voice Frequency Parameters Init */ + if (partparams->VoicePar[nvoice].PFreqEnvelopeEnabled!=0) + NoteVoicePar[nvoice].FreqEnvelope=new Envelope(partparams->VoicePar[nvoice].FreqEnvelope,basefreq); - FMnewamplitude[nvoice]=NoteVoicePar[nvoice].FMVolume*ctl->fmamp.relamp; + if (partparams->VoicePar[nvoice].PFreqLfoEnabled!=0) NoteVoicePar[nvoice].FreqLfo=new LFO(partparams->VoicePar[nvoice].FreqLfo,basefreq); - if (partparams->VoicePar[nvoice].PFMAmpEnvelopeEnabled!=0){ - NoteVoicePar[nvoice].FMAmpEnvelope=new Envelope(partparams->VoicePar[nvoice].FMAmpEnvelope,basefreq); - FMnewamplitude[nvoice]*=NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB(); - }; + /* Voice Filter Parameters Init */ + if (partparams->VoicePar[nvoice].PFilterEnabled!=0) { + NoteVoicePar[nvoice].VoiceFilter=new Filter(partparams->VoicePar[nvoice].VoiceFilter); + }; + + if (partparams->VoicePar[nvoice].PFilterEnvelopeEnabled!=0) + NoteVoicePar[nvoice].FilterEnvelope=new Envelope(partparams->VoicePar[nvoice].FilterEnvelope,basefreq); + + if (partparams->VoicePar[nvoice].PFilterLfoEnabled!=0) + NoteVoicePar[nvoice].FilterLfo=new LFO(partparams->VoicePar[nvoice].FilterLfo,basefreq); + + NoteVoicePar[nvoice].FilterFreqTracking=partparams->VoicePar[nvoice].VoiceFilter->getfreqtracking(basefreq); + + /* Voice Modulation Parameters Init */ + if ((NoteVoicePar[nvoice].FMEnabled!=NONE)&&(NoteVoicePar[nvoice].FMVoice<0)) { + partparams->VoicePar[nvoice].FMSmp->newrandseed(rand()); + NoteVoicePar[nvoice].FMSmp=new REALTYPE[OSCIL_SIZE+OSCIL_SMP_EXTRA_SAMPLES]; + + //Perform Anti-aliasing only on MORPH or RING MODULATION + + int vc=nvoice; + if (partparams->VoicePar[nvoice].PextFMoscil!=-1) vc=partparams->VoicePar[nvoice].PextFMoscil; + + REALTYPE tmp=1.0; + if ((partparams->VoicePar[vc].FMSmp->Padaptiveharmonics!=0)|| + (NoteVoicePar[nvoice].FMEnabled==MORPH)|| + (NoteVoicePar[nvoice].FMEnabled==RING_MOD)) { + tmp=getFMvoicebasefreq(nvoice); + }; + if (!partparams->GlobalPar.Hrandgrouping) partparams->VoicePar[vc].FMSmp->newrandseed(rand()); + + oscposhiFM[nvoice]=(oscposhi[nvoice]+partparams->VoicePar[vc].FMSmp->get(NoteVoicePar[nvoice].FMSmp,tmp)) % OSCIL_SIZE; + for (int i=0;i<OSCIL_SMP_EXTRA_SAMPLES;i++) NoteVoicePar[nvoice].FMSmp[OSCIL_SIZE+i]=NoteVoicePar[nvoice].FMSmp[i]; + oscposhiFM[nvoice]+=(int)((partparams->VoicePar[nvoice].PFMoscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4); + oscposhiFM[nvoice]%=OSCIL_SIZE; + }; + + if (partparams->VoicePar[nvoice].PFMFreqEnvelopeEnabled!=0) + NoteVoicePar[nvoice].FMFreqEnvelope=new Envelope(partparams->VoicePar[nvoice].FMFreqEnvelope,basefreq); + + FMnewamplitude[nvoice]=NoteVoicePar[nvoice].FMVolume*ctl->fmamp.relamp; + + if (partparams->VoicePar[nvoice].PFMAmpEnvelopeEnabled!=0) { + NoteVoicePar[nvoice].FMAmpEnvelope=new Envelope(partparams->VoicePar[nvoice].FMAmpEnvelope,basefreq); + FMnewamplitude[nvoice]*=NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB(); + }; }; - for (nvoice=0;nvoice<NUM_VOICES;nvoice++){ - for (i=nvoice+1;i<NUM_VOICES;i++) tmp[i]=0; - for (i=nvoice+1;i<NUM_VOICES;i++) - if ((NoteVoicePar[i].FMVoice==nvoice)&&(tmp[i]==0)){ - NoteVoicePar[nvoice].VoiceOut=new REALTYPE[SOUND_BUFFER_SIZE]; - tmp[i]=1; - }; - if (NoteVoicePar[nvoice].VoiceOut!=NULL) for (i=0;i<SOUND_BUFFER_SIZE;i++) NoteVoicePar[nvoice].VoiceOut[i]=0.0; + for (nvoice=0;nvoice<NUM_VOICES;nvoice++) { + for (i=nvoice+1;i<NUM_VOICES;i++) tmp[i]=0; + for (i=nvoice+1;i<NUM_VOICES;i++) + if ((NoteVoicePar[i].FMVoice==nvoice)&&(tmp[i]==0)) { + NoteVoicePar[nvoice].VoiceOut=new REALTYPE[SOUND_BUFFER_SIZE]; + tmp[i]=1; + }; + if (NoteVoicePar[nvoice].VoiceOut!=NULL) for (i=0;i<SOUND_BUFFER_SIZE;i++) NoteVoicePar[nvoice].VoiceOut[i]=0.0; }; }; @@ -601,7 +626,8 @@ void ADnote::initparameters(){ /* * Computes the frequency of an oscillator */ -void ADnote::setfreq(int nvoice,REALTYPE freq){ +void ADnote::setfreq(int nvoice,REALTYPE freq) +{ REALTYPE speed; freq=fabs(freq); speed=freq*REALTYPE(OSCIL_SIZE)/(REALTYPE) SAMPLE_RATE; @@ -609,12 +635,13 @@ void ADnote::setfreq(int nvoice,REALTYPE freq){ F2I(speed,oscfreqhi[nvoice]); oscfreqlo[nvoice]=speed-floor(speed); -}; +}; /* * Computes the frequency of an modullator oscillator */ -void ADnote::setfreqFM(int nvoice,REALTYPE freq){ +void ADnote::setfreqFM(int nvoice,REALTYPE freq) +{ REALTYPE speed; freq=fabs(freq); speed=freq*REALTYPE(OSCIL_SIZE)/(REALTYPE) SAMPLE_RATE; @@ -627,28 +654,30 @@ void ADnote::setfreqFM(int nvoice,REALTYPE freq){ /* * Get Voice base frequency */ -REALTYPE ADnote::getvoicebasefreq(int nvoice){ +REALTYPE ADnote::getvoicebasefreq(int nvoice) +{ REALTYPE detune=NoteVoicePar[nvoice].Detune/100.0+ - NoteVoicePar[nvoice].FineDetune/100.0*ctl->bandwidth.relbw*bandwidthDetuneMultiplier+ - NoteGlobalPar.Detune/100.0; + NoteVoicePar[nvoice].FineDetune/100.0*ctl->bandwidth.relbw*bandwidthDetuneMultiplier+ + NoteGlobalPar.Detune/100.0; if (NoteVoicePar[nvoice].fixedfreq==0) return(this->basefreq*pow(2,detune/12.0)); - else {//the fixed freq is enabled - REALTYPE fixedfreq=440.0; - int fixedfreqET=NoteVoicePar[nvoice].fixedfreqET; - if (fixedfreqET!=0) {//if the frequency varies according the keyboard note - REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); - if (fixedfreqET<=64) fixedfreq*=pow(2.0,tmp); - else fixedfreq*=pow(3.0,tmp); - }; - return(fixedfreq*pow(2.0,detune/12.0)); - }; + else {//the fixed freq is enabled + REALTYPE fixedfreq=440.0; + int fixedfreqET=NoteVoicePar[nvoice].fixedfreqET; + if (fixedfreqET!=0) {//if the frequency varies according the keyboard note + REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); + if (fixedfreqET<=64) fixedfreq*=pow(2.0,tmp); + else fixedfreq*=pow(3.0,tmp); + }; + return(fixedfreq*pow(2.0,detune/12.0)); + }; }; /* * Get Voice's Modullator base frequency */ -REALTYPE ADnote::getFMvoicebasefreq(int nvoice){ +REALTYPE ADnote::getFMvoicebasefreq(int nvoice) +{ REALTYPE detune=NoteVoicePar[nvoice].FMDetune/100.0; return(getvoicebasefreq(nvoice)*pow(2,detune/12.0)); }; @@ -656,102 +685,103 @@ REALTYPE ADnote::getFMvoicebasefreq(int nvoice){ /* * Computes all the parameters for each tick */ -void ADnote::computecurrentparameters(){ +void ADnote::computecurrentparameters() +{ int nvoice; REALTYPE voicefreq,voicepitch,filterpitch,filterfreq,FMfreq,FMrelativepitch,globalpitch,globalfilterpitch; globalpitch=0.01*(NoteGlobalPar.FreqEnvelope->envout()+ - NoteGlobalPar.FreqLfo->lfoout()*ctl->modwheel.relmod); + NoteGlobalPar.FreqLfo->lfoout()*ctl->modwheel.relmod); globaloldamplitude=globalnewamplitude; globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout(); - + globalfilterpitch=NoteGlobalPar.FilterEnvelope->envout()+NoteGlobalPar.FilterLfo->lfoout() +NoteGlobalPar.FilterCenterPitch; - + REALTYPE tmpfilterfreq=globalfilterpitch+ctl->filtercutoff.relfreq - +NoteGlobalPar.FilterFreqTracking; - + +NoteGlobalPar.FilterFreqTracking; + tmpfilterfreq=NoteGlobalPar.GlobalFilterL->getrealfreq(tmpfilterfreq); - + REALTYPE globalfilterq=NoteGlobalPar.FilterQ*ctl->filterq.relq; NoteGlobalPar.GlobalFilterL->setfreq_and_q(tmpfilterfreq,globalfilterq); if (stereo!=0) NoteGlobalPar.GlobalFilterR->setfreq_and_q(tmpfilterfreq,globalfilterq); //compute the portamento, if it is used by this note - REALTYPE portamentofreqrap=1.0; - if (portamento!=0){//this voice use portamento - portamentofreqrap=ctl->portamento.freqrap; - if (ctl->portamento.used==0){//the portamento has finished - portamento=0;//this note is no longer "portamented" - }; + REALTYPE portamentofreqrap=1.0; + if (portamento!=0) {//this voice use portamento + portamentofreqrap=ctl->portamento.freqrap; + if (ctl->portamento.used==0) {//the portamento has finished + portamento=0;//this note is no longer "portamented" + }; }; - + //compute parameters for all voices - for (nvoice=0;nvoice<NUM_VOICES;nvoice++){ - if (NoteVoicePar[nvoice].Enabled!=ON) continue; - NoteVoicePar[nvoice].DelayTicks-=1; - if (NoteVoicePar[nvoice].DelayTicks>0) continue; - - /*******************/ - /* Voice Amplitude */ - /*******************/ + for (nvoice=0;nvoice<NUM_VOICES;nvoice++) { + if (NoteVoicePar[nvoice].Enabled!=ON) continue; + NoteVoicePar[nvoice].DelayTicks-=1; + if (NoteVoicePar[nvoice].DelayTicks>0) continue; + + /*******************/ + /* Voice Amplitude */ + /*******************/ oldamplitude[nvoice]=newamplitude[nvoice]; - newamplitude[nvoice]=1.0; - - if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) - newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); - - if (NoteVoicePar[nvoice].AmpLfo!=NULL) - newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpLfo->amplfoout(); - - /****************/ - /* Voice Filter */ - /****************/ - if (NoteVoicePar[nvoice].VoiceFilter!=NULL){ - filterpitch=NoteVoicePar[nvoice].FilterCenterPitch; - - if (NoteVoicePar[nvoice].FilterEnvelope!=NULL) - filterpitch+=NoteVoicePar[nvoice].FilterEnvelope->envout(); - - if (NoteVoicePar[nvoice].FilterLfo!=NULL) - filterpitch+=NoteVoicePar[nvoice].FilterLfo->lfoout(); - - filterfreq=filterpitch+NoteVoicePar[nvoice].FilterFreqTracking; - filterfreq=NoteVoicePar[nvoice].VoiceFilter->getrealfreq(filterfreq); - - NoteVoicePar[nvoice].VoiceFilter->setfreq(filterfreq); - }; + newamplitude[nvoice]=1.0; + + if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) + newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); + + if (NoteVoicePar[nvoice].AmpLfo!=NULL) + newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpLfo->amplfoout(); + + /****************/ + /* Voice Filter */ + /****************/ + if (NoteVoicePar[nvoice].VoiceFilter!=NULL) { + filterpitch=NoteVoicePar[nvoice].FilterCenterPitch; + + if (NoteVoicePar[nvoice].FilterEnvelope!=NULL) + filterpitch+=NoteVoicePar[nvoice].FilterEnvelope->envout(); + + if (NoteVoicePar[nvoice].FilterLfo!=NULL) + filterpitch+=NoteVoicePar[nvoice].FilterLfo->lfoout(); + + filterfreq=filterpitch+NoteVoicePar[nvoice].FilterFreqTracking; + filterfreq=NoteVoicePar[nvoice].VoiceFilter->getrealfreq(filterfreq); + + NoteVoicePar[nvoice].VoiceFilter->setfreq(filterfreq); + }; + + if (NoteVoicePar[nvoice].noisetype==0) {//compute only if the voice isn't noise + + /*******************/ + /* Voice Frequency */ + /*******************/ + voicepitch=0.0; + if (NoteVoicePar[nvoice].FreqLfo!=NULL) + voicepitch+=NoteVoicePar[nvoice].FreqLfo->lfoout()/100.0 + *ctl->bandwidth.relbw; + + if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) voicepitch+=NoteVoicePar[nvoice].FreqEnvelope->envout()/100.0; + voicefreq=getvoicebasefreq(nvoice)*pow(2,(voicepitch+globalpitch)/12.0);//Hz frequency + voicefreq*=ctl->pitchwheel.relfreq;//change the frequency by the controller + setfreq(nvoice,voicefreq*portamentofreqrap); + + /***************/ + /* Modulator */ + /***************/ + if (NoteVoicePar[nvoice].FMEnabled!=NONE) { + FMrelativepitch=NoteVoicePar[nvoice].FMDetune/100.0; + if (NoteVoicePar[nvoice].FMFreqEnvelope!=NULL) FMrelativepitch+=NoteVoicePar[nvoice].FMFreqEnvelope->envout()/100; + FMfreq=pow(2.0,FMrelativepitch/12.0)*voicefreq*portamentofreqrap; + setfreqFM(nvoice,FMfreq); + + FMoldamplitude[nvoice]=FMnewamplitude[nvoice]; + FMnewamplitude[nvoice]=NoteVoicePar[nvoice].FMVolume*ctl->fmamp.relamp; + if (NoteVoicePar[nvoice].FMAmpEnvelope!=NULL) + FMnewamplitude[nvoice]*=NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB(); + }; + }; - if (NoteVoicePar[nvoice].noisetype==0){//compute only if the voice isn't noise - - /*******************/ - /* Voice Frequency */ - /*******************/ - voicepitch=0.0; - if (NoteVoicePar[nvoice].FreqLfo!=NULL) - voicepitch+=NoteVoicePar[nvoice].FreqLfo->lfoout()/100.0 - *ctl->bandwidth.relbw; - - if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) voicepitch+=NoteVoicePar[nvoice].FreqEnvelope->envout()/100.0; - voicefreq=getvoicebasefreq(nvoice)*pow(2,(voicepitch+globalpitch)/12.0);//Hz frequency - voicefreq*=ctl->pitchwheel.relfreq;//change the frequency by the controller - setfreq(nvoice,voicefreq*portamentofreqrap); - - /***************/ - /* Modulator */ - /***************/ - if (NoteVoicePar[nvoice].FMEnabled!=NONE){ - FMrelativepitch=NoteVoicePar[nvoice].FMDetune/100.0; - if (NoteVoicePar[nvoice].FMFreqEnvelope!=NULL) FMrelativepitch+=NoteVoicePar[nvoice].FMFreqEnvelope->envout()/100; - FMfreq=pow(2.0,FMrelativepitch/12.0)*voicefreq*portamentofreqrap; - setfreqFM(nvoice,FMfreq); - - FMoldamplitude[nvoice]=FMnewamplitude[nvoice]; - FMnewamplitude[nvoice]=NoteVoicePar[nvoice].FMVolume*ctl->fmamp.relamp; - if (NoteVoicePar[nvoice].FMAmpEnvelope!=NULL) - FMnewamplitude[nvoice]*=NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB(); - }; - }; - }; time+=(REALTYPE)SOUND_BUFFER_SIZE/(REALTYPE)SAMPLE_RATE; }; @@ -760,41 +790,43 @@ void ADnote::computecurrentparameters(){ /* * Fadein in a way that removes clicks but keep sound "punchy" */ -inline void ADnote::fadein(REALTYPE *smps){ +inline void ADnote::fadein(REALTYPE *smps) +{ int zerocrossings=0; for (int i=1;i<SOUND_BUFFER_SIZE;i++) - if ((smps[i-1]<0.0) && (smps[i]>0.0)) zerocrossings++;//this is only the possitive crossings + if ((smps[i-1]<0.0) && (smps[i]>0.0)) zerocrossings++;//this is only the possitive crossings REALTYPE tmp=(SOUND_BUFFER_SIZE-1.0)/(zerocrossings+1)/3.0; if (tmp<8.0) tmp=8.0; int n; - F2I(tmp,n);//how many samples is the fade-in + F2I(tmp,n);//how many samples is the fade-in if (n>SOUND_BUFFER_SIZE) n=SOUND_BUFFER_SIZE; for (int i=0;i<n;i++) {//fade-in - REALTYPE tmp=0.5-cos((REALTYPE)i/(REALTYPE) n*PI)*0.5; - smps[i]*=tmp; - }; + REALTYPE tmp=0.5-cos((REALTYPE)i/(REALTYPE) n*PI)*0.5; + smps[i]*=tmp; + }; }; /* * Computes the Oscillator (Without Modulation) - LinearInterpolation */ -inline void ADnote::ComputeVoiceOscillator_LinearInterpolation(int nvoice){ +inline void ADnote::ComputeVoiceOscillator_LinearInterpolation(int nvoice) +{ int i,poshi; REALTYPE poslo; poshi=oscposhi[nvoice]; poslo=oscposlo[nvoice]; REALTYPE *smps=NoteVoicePar[nvoice].OscilSmp; - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - tmpwave[i]=smps[poshi]*(1.0-poslo)+smps[poshi+1]*poslo; - poslo+=oscfreqlo[nvoice]; - if (poslo>=1.0) { - poslo-=1.0; - poshi++; - }; - poshi+=oscfreqhi[nvoice]; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + tmpwave[i]=smps[poshi]*(1.0-poslo)+smps[poshi+1]*poslo; + poslo+=oscfreqlo[nvoice]; + if (poslo>=1.0) { + poslo-=1.0; + poshi++; + }; + poshi+=oscfreqhi[nvoice]; poshi&=OSCIL_SIZE-1; }; oscposhi[nvoice]=poshi; @@ -807,7 +839,7 @@ inline void ADnote::ComputeVoiceOscillator_LinearInterpolation(int nvoice){ * Computes the Oscillator (Without Modulation) - CubicInterpolation * The differences from the Linear are to little to deserve to be used. This is because I am using a large OSCIL_SIZE (>512) -inline void ADnote::ComputeVoiceOscillator_CubicInterpolation(int nvoice){ +inline void ADnote::ComputeVoiceOscillator_CubicInterpolation(int nvoice){ int i,poshi; REALTYPE poslo; @@ -828,10 +860,10 @@ inline void ADnote::ComputeVoiceOscillator_CubicInterpolation(int nvoice){ //tmpwave[i]=smps[poshi]*(1.0-poslo)+smps[poshi+1]*poslo; poslo+=oscfreqlo[nvoice]; if (poslo>=1.0) { - poslo-=1.0; + poslo-=1.0; poshi++; }; - poshi+=oscfreqhi[nvoice]; + poshi+=oscfreqhi[nvoice]; poshi&=OSCIL_SIZE-1; }; oscposhi[nvoice]=poshi; @@ -841,82 +873,84 @@ inline void ADnote::ComputeVoiceOscillator_CubicInterpolation(int nvoice){ /* * Computes the Oscillator (Morphing) */ -inline void ADnote::ComputeVoiceOscillatorMorph(int nvoice){ +inline void ADnote::ComputeVoiceOscillatorMorph(int nvoice) +{ int i; REALTYPE amp; - ComputeVoiceOscillator_LinearInterpolation(nvoice); + ComputeVoiceOscillator_LinearInterpolation(nvoice); if (FMnewamplitude[nvoice]>1.0) FMnewamplitude[nvoice]=1.0; if (FMoldamplitude[nvoice]>1.0) FMoldamplitude[nvoice]=1.0; - - if (NoteVoicePar[nvoice].FMVoice>=0){ - //if I use VoiceOut[] as modullator - int FMVoice=NoteVoicePar[nvoice].FMVoice; - for (i=0;i<SOUND_BUFFER_SIZE;i++) { - amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice] - ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE); - tmpwave[i]=tmpwave[i]*(1.0-amp)+amp*NoteVoicePar[FMVoice].VoiceOut[i]; - }; + + if (NoteVoicePar[nvoice].FMVoice>=0) { + //if I use VoiceOut[] as modullator + int FMVoice=NoteVoicePar[nvoice].FMVoice; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice] + ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE); + tmpwave[i]=tmpwave[i]*(1.0-amp)+amp*NoteVoicePar[FMVoice].VoiceOut[i]; + }; } else { - int poshiFM=oscposhiFM[nvoice]; - REALTYPE posloFM=oscposloFM[nvoice]; - - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice] - ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE); - tmpwave[i]=tmpwave[i]*(1.0-amp)+amp - *(NoteVoicePar[nvoice].FMSmp[poshiFM]*(1-posloFM) - +NoteVoicePar[nvoice].FMSmp[poshiFM+1]*posloFM); - posloFM+=oscfreqloFM[nvoice]; - if (posloFM>=1.0) { - posloFM-=1.0; - poshiFM++; - }; - poshiFM+=oscfreqhiFM[nvoice]; - poshiFM&=OSCIL_SIZE-1; - }; - oscposhiFM[nvoice]=poshiFM; - oscposloFM[nvoice]=posloFM; + int poshiFM=oscposhiFM[nvoice]; + REALTYPE posloFM=oscposloFM[nvoice]; + + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice] + ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE); + tmpwave[i]=tmpwave[i]*(1.0-amp)+amp + *(NoteVoicePar[nvoice].FMSmp[poshiFM]*(1-posloFM) + +NoteVoicePar[nvoice].FMSmp[poshiFM+1]*posloFM); + posloFM+=oscfreqloFM[nvoice]; + if (posloFM>=1.0) { + posloFM-=1.0; + poshiFM++; + }; + poshiFM+=oscfreqhiFM[nvoice]; + poshiFM&=OSCIL_SIZE-1; + }; + oscposhiFM[nvoice]=poshiFM; + oscposloFM[nvoice]=posloFM; }; }; /* * Computes the Oscillator (Ring Modulation) */ -inline void ADnote::ComputeVoiceOscillatorRingModulation(int nvoice){ +inline void ADnote::ComputeVoiceOscillatorRingModulation(int nvoice) +{ int i; REALTYPE amp; - ComputeVoiceOscillator_LinearInterpolation(nvoice); + ComputeVoiceOscillator_LinearInterpolation(nvoice); if (FMnewamplitude[nvoice]>1.0) FMnewamplitude[nvoice]=1.0; if (FMoldamplitude[nvoice]>1.0) FMoldamplitude[nvoice]=1.0; - if (NoteVoicePar[nvoice].FMVoice>=0){ - // if I use VoiceOut[] as modullator - for (i=0;i<SOUND_BUFFER_SIZE;i++) { - amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice] - ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE); - int FMVoice=NoteVoicePar[nvoice].FMVoice; - for (i=0;i<SOUND_BUFFER_SIZE;i++) - tmpwave[i]*=(1.0-amp)+amp*NoteVoicePar[FMVoice].VoiceOut[i]; - }; + if (NoteVoicePar[nvoice].FMVoice>=0) { + // if I use VoiceOut[] as modullator + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice] + ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE); + int FMVoice=NoteVoicePar[nvoice].FMVoice; + for (i=0;i<SOUND_BUFFER_SIZE;i++) + tmpwave[i]*=(1.0-amp)+amp*NoteVoicePar[FMVoice].VoiceOut[i]; + }; } else { - int poshiFM=oscposhiFM[nvoice]; - REALTYPE posloFM=oscposloFM[nvoice]; - - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice] - ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE); - tmpwave[i]*=( NoteVoicePar[nvoice].FMSmp[poshiFM]*(1.0-posloFM) - +NoteVoicePar[nvoice].FMSmp[poshiFM+1]*posloFM)*amp - +(1.0-amp); - posloFM+=oscfreqloFM[nvoice]; - if (posloFM>=1.0) { - posloFM-=1.0; - poshiFM++; - }; - poshiFM+=oscfreqhiFM[nvoice]; - poshiFM&=OSCIL_SIZE-1; - }; - oscposhiFM[nvoice]=poshiFM; - oscposloFM[nvoice]=posloFM; + int poshiFM=oscposhiFM[nvoice]; + REALTYPE posloFM=oscposloFM[nvoice]; + + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + amp=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice] + ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE); + tmpwave[i]*=( NoteVoicePar[nvoice].FMSmp[poshiFM]*(1.0-posloFM) + +NoteVoicePar[nvoice].FMSmp[poshiFM+1]*posloFM)*amp + +(1.0-amp); + posloFM+=oscfreqloFM[nvoice]; + if (posloFM>=1.0) { + posloFM-=1.0; + poshiFM++; + }; + poshiFM+=oscfreqhiFM[nvoice]; + poshiFM&=OSCIL_SIZE-1; + }; + oscposhiFM[nvoice]=poshiFM; + oscposloFM[nvoice]=posloFM; }; }; @@ -925,346 +959,362 @@ inline void ADnote::ComputeVoiceOscillatorRingModulation(int nvoice){ /* * Computes the Oscillator (Phase Modulation or Frequency Modulation) */ -inline void ADnote::ComputeVoiceOscillatorFrequencyModulation(int nvoice,int FMmode){ +inline void ADnote::ComputeVoiceOscillatorFrequencyModulation(int nvoice,int FMmode) +{ int carposhi; int i,FMmodfreqhi; REALTYPE FMmodfreqlo,carposlo; - - if (NoteVoicePar[nvoice].FMVoice>=0){ - //if I use VoiceOut[] as modulator - for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]=NoteVoicePar[NoteVoicePar[nvoice].FMVoice].VoiceOut[i]; + + if (NoteVoicePar[nvoice].FMVoice>=0) { + //if I use VoiceOut[] as modulator + for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]=NoteVoicePar[NoteVoicePar[nvoice].FMVoice].VoiceOut[i]; } else { - //Compute the modulator and store it in tmpwave[] - int poshiFM=oscposhiFM[nvoice]; - REALTYPE posloFM=oscposloFM[nvoice]; - - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - tmpwave[i]=(NoteVoicePar[nvoice].FMSmp[poshiFM]*(1.0-posloFM) - +NoteVoicePar[nvoice].FMSmp[poshiFM+1]*posloFM); - posloFM+=oscfreqloFM[nvoice]; - if (posloFM>=1.0) { - posloFM=fmod(posloFM,1.0); - poshiFM++; - }; - poshiFM+=oscfreqhiFM[nvoice]; - poshiFM&=OSCIL_SIZE-1; - }; - oscposhiFM[nvoice]=poshiFM; - oscposloFM[nvoice]=posloFM; + //Compute the modulator and store it in tmpwave[] + int poshiFM=oscposhiFM[nvoice]; + REALTYPE posloFM=oscposloFM[nvoice]; + + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + tmpwave[i]=(NoteVoicePar[nvoice].FMSmp[poshiFM]*(1.0-posloFM) + +NoteVoicePar[nvoice].FMSmp[poshiFM+1]*posloFM); + posloFM+=oscfreqloFM[nvoice]; + if (posloFM>=1.0) { + posloFM=fmod(posloFM,1.0); + poshiFM++; + }; + poshiFM+=oscfreqhiFM[nvoice]; + poshiFM&=OSCIL_SIZE-1; + }; + oscposhiFM[nvoice]=poshiFM; + oscposloFM[nvoice]=posloFM; }; // Amplitude interpolation - if (ABOVE_AMPLITUDE_THRESHOLD(FMoldamplitude[nvoice],FMnewamplitude[nvoice])){ - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - tmpwave[i]*=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice] - ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE); - }; - } else for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]*=FMnewamplitude[nvoice]; - - - //normalize makes all sample-rates, oscil_sizes toproduce same sound - if (FMmode!=0){//Frequency modulation - REALTYPE normalize=OSCIL_SIZE/262144.0*44100.0/(REALTYPE)SAMPLE_RATE; - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - FMoldsmp[nvoice]=fmod(FMoldsmp[nvoice]+tmpwave[i]*normalize,OSCIL_SIZE); - tmpwave[i]=FMoldsmp[nvoice]; - }; - } else {//Phase modulation - REALTYPE normalize=OSCIL_SIZE/262144.0; - for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]*=normalize; + if (ABOVE_AMPLITUDE_THRESHOLD(FMoldamplitude[nvoice],FMnewamplitude[nvoice])) { + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + tmpwave[i]*=INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice] + ,FMnewamplitude[nvoice],i,SOUND_BUFFER_SIZE); + }; + } else for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]*=FMnewamplitude[nvoice]; + + + //normalize makes all sample-rates, oscil_sizes toproduce same sound + if (FMmode!=0) {//Frequency modulation + REALTYPE normalize=OSCIL_SIZE/262144.0*44100.0/(REALTYPE)SAMPLE_RATE; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + FMoldsmp[nvoice]=fmod(FMoldsmp[nvoice]+tmpwave[i]*normalize,OSCIL_SIZE); + tmpwave[i]=FMoldsmp[nvoice]; + }; + } else {//Phase modulation + REALTYPE normalize=OSCIL_SIZE/262144.0; + for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]*=normalize; }; - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - F2I(tmpwave[i],FMmodfreqhi); - FMmodfreqlo=fmod(tmpwave[i]+0.0000000001,1.0); - if (FMmodfreqhi<0) FMmodfreqlo++; - - //carrier - carposhi=oscposhi[nvoice]+FMmodfreqhi; - carposlo=oscposlo[nvoice]+FMmodfreqlo; - - if (carposlo>=1.0) { - carposhi++; - carposlo=fmod(carposlo,1.0); - }; - carposhi&=(OSCIL_SIZE-1); - - tmpwave[i]=NoteVoicePar[nvoice].OscilSmp[carposhi]*(1.0-carposlo) - +NoteVoicePar[nvoice].OscilSmp[carposhi+1]*carposlo; - - oscposlo[nvoice]+=oscfreqlo[nvoice]; - if (oscposlo[nvoice]>=1.0) { - oscposlo[nvoice]=fmod(oscposlo[nvoice],1.0); - oscposhi[nvoice]++; - }; - - oscposhi[nvoice]+=oscfreqhi[nvoice]; - oscposhi[nvoice]&=OSCIL_SIZE-1; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + F2I(tmpwave[i],FMmodfreqhi); + FMmodfreqlo=fmod(tmpwave[i]+0.0000000001,1.0); + if (FMmodfreqhi<0) FMmodfreqlo++; + + //carrier + carposhi=oscposhi[nvoice]+FMmodfreqhi; + carposlo=oscposlo[nvoice]+FMmodfreqlo; + + if (carposlo>=1.0) { + carposhi++; + carposlo=fmod(carposlo,1.0); + }; + carposhi&=(OSCIL_SIZE-1); + + tmpwave[i]=NoteVoicePar[nvoice].OscilSmp[carposhi]*(1.0-carposlo) + +NoteVoicePar[nvoice].OscilSmp[carposhi+1]*carposlo; + + oscposlo[nvoice]+=oscfreqlo[nvoice]; + if (oscposlo[nvoice]>=1.0) { + oscposlo[nvoice]=fmod(oscposlo[nvoice],1.0); + oscposhi[nvoice]++; + }; + + oscposhi[nvoice]+=oscfreqhi[nvoice]; + oscposhi[nvoice]&=OSCIL_SIZE-1; }; }; /*Calculeaza Oscilatorul cu PITCH MODULATION*/ -inline void ADnote::ComputeVoiceOscillatorPitchModulation(int nvoice){ +inline void ADnote::ComputeVoiceOscillatorPitchModulation(int nvoice) +{ //TODO }; /* - * Computes the Noise + * Computes the Noise */ -inline void ADnote::ComputeVoiceNoise(int nvoice){ +inline void ADnote::ComputeVoiceNoise(int nvoice) +{ for (int i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]=RND*2.0-1.0; }; /* - * Compute the ADnote samples + * Compute the ADnote samples * Returns 0 if the note is finished */ -int ADnote::noteout(REALTYPE *outl,REALTYPE *outr){ - int i,nvoice; - - for (i=0;i<SOUND_BUFFER_SIZE;i++) { - outl[i]=denormalkillbuf[i]; - outr[i]=denormalkillbuf[i]; - }; - - if (NoteEnabled==OFF) return(0); - - for (i=0;i<SOUND_BUFFER_SIZE;i++) { - bypassl[i]=0.0; - bypassr[i]=0.0; - }; - - computecurrentparameters(); - - for (nvoice=0;nvoice<NUM_VOICES;nvoice++){ - if ((NoteVoicePar[nvoice].Enabled!=ON) || (NoteVoicePar[nvoice].DelayTicks>0)) continue; - if (NoteVoicePar[nvoice].noisetype==0){//voice mode=sound - switch (NoteVoicePar[nvoice].FMEnabled){ - case MORPH:ComputeVoiceOscillatorMorph(nvoice);break; - case RING_MOD:ComputeVoiceOscillatorRingModulation(nvoice);break; - case PHASE_MOD:ComputeVoiceOscillatorFrequencyModulation(nvoice,0);break; - case FREQ_MOD:ComputeVoiceOscillatorFrequencyModulation(nvoice,1);break; - //case PITCH_MOD:ComputeVoiceOscillatorPitchModulation(nvoice);break; - default:ComputeVoiceOscillator_LinearInterpolation(nvoice); - //if (config.cfg.Interpolation) ComputeVoiceOscillator_CubicInterpolation(nvoice); - - }; - } else ComputeVoiceNoise(nvoice); - // Voice Processing - - // Amplitude - if (ABOVE_AMPLITUDE_THRESHOLD(oldamplitude[nvoice],newamplitude[nvoice])){ - int rest=SOUND_BUFFER_SIZE; - //test if the amplitude if raising and the difference is high - if ((newamplitude[nvoice]>oldamplitude[nvoice])&&((newamplitude[nvoice]-oldamplitude[nvoice])>0.25)){ - rest=10; - if (rest>SOUND_BUFFER_SIZE) rest=SOUND_BUFFER_SIZE; - for (int i=0;i<SOUND_BUFFER_SIZE-rest;i++) tmpwave[i]*=oldamplitude[nvoice]; - }; - // Amplitude interpolation - for (i=0;i<rest;i++){ - tmpwave[i+(SOUND_BUFFER_SIZE-rest)]*=INTERPOLATE_AMPLITUDE(oldamplitude[nvoice] - ,newamplitude[nvoice],i,rest); - }; - } else for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]*=newamplitude[nvoice]; - - // Fade in - if (firsttick[nvoice]!=0){ - fadein(&tmpwave[0]); - firsttick[nvoice]=0; - }; - - - // Filter - if (NoteVoicePar[nvoice].VoiceFilter!=NULL) NoteVoicePar[nvoice].VoiceFilter->filterout(&tmpwave[0]); - - //check if the amplitude envelope is finished, if yes, the voice will be fadeout - if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) { - if (NoteVoicePar[nvoice].AmpEnvelope->finished()!=0) - for (i=0;i<SOUND_BUFFER_SIZE;i++) - tmpwave[i]*=1.0-(REALTYPE)i/(REALTYPE)SOUND_BUFFER_SIZE; - //the voice is killed later - }; - - - // Put the ADnote samples in VoiceOut (without appling Global volume, because I wish to use this voice as a modullator) - if (NoteVoicePar[nvoice].VoiceOut!=NULL) - for (i=0;i<SOUND_BUFFER_SIZE;i++) NoteVoicePar[nvoice].VoiceOut[i]=tmpwave[i]; - - - // Add the voice that do not bypass the filter to out - if (NoteVoicePar[nvoice].filterbypass==0){//no bypass - if (stereo==0) for (i=0;i<SOUND_BUFFER_SIZE;i++) outl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume;//mono - else for (i=0;i<SOUND_BUFFER_SIZE;i++) {//stereo - outl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*NoteVoicePar[nvoice].Panning*2.0; - outr[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*(1.0-NoteVoicePar[nvoice].Panning)*2.0; - }; - } else {//bypass the filter - if (stereo==0) for (i=0;i<SOUND_BUFFER_SIZE;i++) bypassl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume;//mono - else for (i=0;i<SOUND_BUFFER_SIZE;i++) {//stereo - bypassl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*NoteVoicePar[nvoice].Panning*2.0; - bypassr[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*(1.0-NoteVoicePar[nvoice].Panning)*2.0; - }; - }; - // chech if there is necesary to proces the voice longer (if the Amplitude envelope isn't finished) - if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) { - if (NoteVoicePar[nvoice].AmpEnvelope->finished()!=0) KillVoice(nvoice); - }; - }; - - - //Processing Global parameters - NoteGlobalPar.GlobalFilterL->filterout(&outl[0]); - - if (stereo==0) { - for (i=0;i<SOUND_BUFFER_SIZE;i++) {//set the right channel=left channel - outr[i]=outl[i]; - bypassr[i]=bypassl[i]; - } - } else NoteGlobalPar.GlobalFilterR->filterout(&outr[0]); - - for (i=0;i<SOUND_BUFFER_SIZE;i++) { - outl[i]+=bypassl[i]; - outr[i]+=bypassr[i]; - }; - - if (ABOVE_AMPLITUDE_THRESHOLD(globaloldamplitude,globalnewamplitude)){ - // Amplitude Interpolation - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - REALTYPE tmpvol=INTERPOLATE_AMPLITUDE(globaloldamplitude - ,globalnewamplitude,i,SOUND_BUFFER_SIZE); - outl[i]*=tmpvol*NoteGlobalPar.Panning; - outr[i]*=tmpvol*(1.0-NoteGlobalPar.Panning); +int ADnote::noteout(REALTYPE *outl,REALTYPE *outr) +{ + int i,nvoice; + + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + outl[i]=denormalkillbuf[i]; + outr[i]=denormalkillbuf[i]; + }; + + if (NoteEnabled==OFF) return(0); + + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + bypassl[i]=0.0; + bypassr[i]=0.0; + }; + + computecurrentparameters(); + + for (nvoice=0;nvoice<NUM_VOICES;nvoice++) { + if ((NoteVoicePar[nvoice].Enabled!=ON) || (NoteVoicePar[nvoice].DelayTicks>0)) continue; + if (NoteVoicePar[nvoice].noisetype==0) {//voice mode=sound + switch (NoteVoicePar[nvoice].FMEnabled) { + case MORPH: + ComputeVoiceOscillatorMorph(nvoice); + break; + case RING_MOD: + ComputeVoiceOscillatorRingModulation(nvoice); + break; + case PHASE_MOD: + ComputeVoiceOscillatorFrequencyModulation(nvoice,0); + break; + case FREQ_MOD: + ComputeVoiceOscillatorFrequencyModulation(nvoice,1); + break; + //case PITCH_MOD:ComputeVoiceOscillatorPitchModulation(nvoice);break; + default: + ComputeVoiceOscillator_LinearInterpolation(nvoice); + //if (config.cfg.Interpolation) ComputeVoiceOscillator_CubicInterpolation(nvoice); + + }; + } else ComputeVoiceNoise(nvoice); + // Voice Processing + + // Amplitude + if (ABOVE_AMPLITUDE_THRESHOLD(oldamplitude[nvoice],newamplitude[nvoice])) { + int rest=SOUND_BUFFER_SIZE; + //test if the amplitude if raising and the difference is high + if ((newamplitude[nvoice]>oldamplitude[nvoice])&&((newamplitude[nvoice]-oldamplitude[nvoice])>0.25)) { + rest=10; + if (rest>SOUND_BUFFER_SIZE) rest=SOUND_BUFFER_SIZE; + for (int i=0;i<SOUND_BUFFER_SIZE-rest;i++) tmpwave[i]*=oldamplitude[nvoice]; + }; + // Amplitude interpolation + for (i=0;i<rest;i++) { + tmpwave[i+(SOUND_BUFFER_SIZE-rest)]*=INTERPOLATE_AMPLITUDE(oldamplitude[nvoice] + ,newamplitude[nvoice],i,rest); + }; + } else for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpwave[i]*=newamplitude[nvoice]; + + // Fade in + if (firsttick[nvoice]!=0) { + fadein(&tmpwave[0]); + firsttick[nvoice]=0; }; - } else { - for (i=0;i<SOUND_BUFFER_SIZE;i++) { - outl[i]*=globalnewamplitude*NoteGlobalPar.Panning; - outr[i]*=globalnewamplitude*(1.0-NoteGlobalPar.Panning); - }; - }; - //Apply the punch - if (NoteGlobalPar.Punch.Enabled!=0){ - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - REALTYPE punchamp=NoteGlobalPar.Punch.initialvalue*NoteGlobalPar.Punch.t+1.0; - outl[i]*=punchamp; - outr[i]*=punchamp; - NoteGlobalPar.Punch.t-=NoteGlobalPar.Punch.dt; - if (NoteGlobalPar.Punch.t<0.0) { - NoteGlobalPar.Punch.Enabled=0; - break; - }; - }; - }; + // Filter + if (NoteVoicePar[nvoice].VoiceFilter!=NULL) NoteVoicePar[nvoice].VoiceFilter->filterout(&tmpwave[0]); - // Apply legato-specific sound signal modifications - if (Legato.silent){ // Silencer - if (Legato.msg!=LM_FadeIn){ - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - outl[i]=0.0; - outr[i]=0.0; - } - } - } - switch (Legato.msg){ - case LM_CatchUp : // Continue the catch-up... - if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; - for (i=0;i<SOUND_BUFFER_SIZE;i++){//Yea, could be done without the loop... - Legato.decounter--; - if (Legato.decounter<1){ - // Catching-up done, we can finally set - // the note to the actual parameters. - Legato.decounter=-10; - Legato.msg=LM_ToNorm; - ADlegatonote(Legato.param.freq, Legato.param.vel, Legato.param.portamento, Legato.param.midinote, false); - break; - } - } - break; - case LM_FadeIn : // Fade-in - if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; - Legato.silent=false; - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - Legato.decounter--; - if (Legato.decounter<1){ - Legato.decounter=-10; - Legato.msg=LM_Norm; - break; - } - Legato.fade.m+=Legato.fade.step; - outl[i]*=Legato.fade.m; - outr[i]*=Legato.fade.m; + //check if the amplitude envelope is finished, if yes, the voice will be fadeout + if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) { + if (NoteVoicePar[nvoice].AmpEnvelope->finished()!=0) + for (i=0;i<SOUND_BUFFER_SIZE;i++) + tmpwave[i]*=1.0-(REALTYPE)i/(REALTYPE)SOUND_BUFFER_SIZE; + //the voice is killed later + }; + + + // Put the ADnote samples in VoiceOut (without appling Global volume, because I wish to use this voice as a modullator) + if (NoteVoicePar[nvoice].VoiceOut!=NULL) + for (i=0;i<SOUND_BUFFER_SIZE;i++) NoteVoicePar[nvoice].VoiceOut[i]=tmpwave[i]; + + + // Add the voice that do not bypass the filter to out + if (NoteVoicePar[nvoice].filterbypass==0) {//no bypass + if (stereo==0) for (i=0;i<SOUND_BUFFER_SIZE;i++) outl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume;//mono + else for (i=0;i<SOUND_BUFFER_SIZE;i++) {//stereo + outl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*NoteVoicePar[nvoice].Panning*2.0; + outr[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*(1.0-NoteVoicePar[nvoice].Panning)*2.0; + }; + } else {//bypass the filter + if (stereo==0) for (i=0;i<SOUND_BUFFER_SIZE;i++) bypassl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume;//mono + else for (i=0;i<SOUND_BUFFER_SIZE;i++) {//stereo + bypassl[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*NoteVoicePar[nvoice].Panning*2.0; + bypassr[i]+=tmpwave[i]*NoteVoicePar[nvoice].Volume*(1.0-NoteVoicePar[nvoice].Panning)*2.0; + }; + }; + // chech if there is necesary to proces the voice longer (if the Amplitude envelope isn't finished) + if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) { + if (NoteVoicePar[nvoice].AmpEnvelope->finished()!=0) KillVoice(nvoice); + }; + }; + + + //Processing Global parameters + NoteGlobalPar.GlobalFilterL->filterout(&outl[0]); + + if (stereo==0) { + for (i=0;i<SOUND_BUFFER_SIZE;i++) {//set the right channel=left channel + outr[i]=outl[i]; + bypassr[i]=bypassl[i]; + } + } else NoteGlobalPar.GlobalFilterR->filterout(&outr[0]); + + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + outl[i]+=bypassl[i]; + outr[i]+=bypassr[i]; + }; + + if (ABOVE_AMPLITUDE_THRESHOLD(globaloldamplitude,globalnewamplitude)) { + // Amplitude Interpolation + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + REALTYPE tmpvol=INTERPOLATE_AMPLITUDE(globaloldamplitude + ,globalnewamplitude,i,SOUND_BUFFER_SIZE); + outl[i]*=tmpvol*NoteGlobalPar.Panning; + outr[i]*=tmpvol*(1.0-NoteGlobalPar.Panning); + }; + } else { + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + outl[i]*=globalnewamplitude*NoteGlobalPar.Panning; + outr[i]*=globalnewamplitude*(1.0-NoteGlobalPar.Panning); + }; + }; + +//Apply the punch + if (NoteGlobalPar.Punch.Enabled!=0) { + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + REALTYPE punchamp=NoteGlobalPar.Punch.initialvalue*NoteGlobalPar.Punch.t+1.0; + outl[i]*=punchamp; + outr[i]*=punchamp; + NoteGlobalPar.Punch.t-=NoteGlobalPar.Punch.dt; + if (NoteGlobalPar.Punch.t<0.0) { + NoteGlobalPar.Punch.Enabled=0; + break; + }; + }; + }; + + + // Apply legato-specific sound signal modifications + if (Legato.silent) { // Silencer + if (Legato.msg!=LM_FadeIn) { + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + outl[i]=0.0; + outr[i]=0.0; + } + } } - break; - case LM_FadeOut : // Fade-out, then set the catch-up - if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - Legato.decounter--; - if (Legato.decounter<1){ - for (int j=i;j<SOUND_BUFFER_SIZE;j++){ - outl[j]=0.0; - outr[j]=0.0; - } - Legato.decounter=-10; - Legato.silent=true; - // Fading-out done, now set the catch-up : - Legato.decounter=Legato.fade.length; - Legato.msg=LM_CatchUp; - REALTYPE catchupfreq=Legato.param.freq*(Legato.param.freq/Legato.lastfreq);//This freq should make this now silent note to catch-up (or should I say resync ?) with the heard note for the same length it stayed at the previous freq during the fadeout. - ADlegatonote(catchupfreq, Legato.param.vel, Legato.param.portamento, Legato.param.midinote, false); - break; - } - Legato.fade.m-=Legato.fade.step; - outl[i]*=Legato.fade.m; - outr[i]*=Legato.fade.m; + switch (Legato.msg) { + case LM_CatchUp : // Continue the catch-up... + if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; + for (i=0;i<SOUND_BUFFER_SIZE;i++) {//Yea, could be done without the loop... + Legato.decounter--; + if (Legato.decounter<1) { + // Catching-up done, we can finally set + // the note to the actual parameters. + Legato.decounter=-10; + Legato.msg=LM_ToNorm; + ADlegatonote(Legato.param.freq, Legato.param.vel, Legato.param.portamento, Legato.param.midinote, false); + break; + } + } + break; + case LM_FadeIn : // Fade-in + if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; + Legato.silent=false; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + Legato.decounter--; + if (Legato.decounter<1) { + Legato.decounter=-10; + Legato.msg=LM_Norm; + break; + } + Legato.fade.m+=Legato.fade.step; + outl[i]*=Legato.fade.m; + outr[i]*=Legato.fade.m; + } + break; + case LM_FadeOut : // Fade-out, then set the catch-up + if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + Legato.decounter--; + if (Legato.decounter<1) { + for (int j=i;j<SOUND_BUFFER_SIZE;j++) { + outl[j]=0.0; + outr[j]=0.0; + } + Legato.decounter=-10; + Legato.silent=true; + // Fading-out done, now set the catch-up : + Legato.decounter=Legato.fade.length; + Legato.msg=LM_CatchUp; + REALTYPE catchupfreq=Legato.param.freq*(Legato.param.freq/Legato.lastfreq);//This freq should make this now silent note to catch-up (or should I say resync ?) with the heard note for the same length it stayed at the previous freq during the fadeout. + ADlegatonote(catchupfreq, Legato.param.vel, Legato.param.portamento, Legato.param.midinote, false); + break; + } + Legato.fade.m-=Legato.fade.step; + outl[i]*=Legato.fade.m; + outr[i]*=Legato.fade.m; + } + break; + default : + break; } - break; - default : break; - } - - - // Check if the global amplitude is finished. - // If it does, disable the note - if (NoteGlobalPar.AmpEnvelope->finished()!=0) { - for (i=0;i<SOUND_BUFFER_SIZE;i++) {//fade-out - REALTYPE tmp=1.0-(REALTYPE)i/(REALTYPE)SOUND_BUFFER_SIZE; - outl[i]*=tmp; - outr[i]*=tmp; - }; - KillNote(); - }; - return(1); + + +// Check if the global amplitude is finished. +// If it does, disable the note + if (NoteGlobalPar.AmpEnvelope->finished()!=0) { + for (i=0;i<SOUND_BUFFER_SIZE;i++) {//fade-out + REALTYPE tmp=1.0-(REALTYPE)i/(REALTYPE)SOUND_BUFFER_SIZE; + outl[i]*=tmp; + outr[i]*=tmp; + }; + KillNote(); + }; + return(1); }; /* * Relase the key (NoteOff) */ -void ADnote::relasekey(){ -int nvoice; - for (nvoice=0;nvoice<NUM_VOICES;nvoice++){ - if (NoteVoicePar[nvoice].Enabled==0) continue; - if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) NoteVoicePar[nvoice].AmpEnvelope->relasekey(); - if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) NoteVoicePar[nvoice].FreqEnvelope->relasekey(); - if (NoteVoicePar[nvoice].FilterEnvelope!=NULL) NoteVoicePar[nvoice].FilterEnvelope->relasekey(); - if (NoteVoicePar[nvoice].FMFreqEnvelope!=NULL) NoteVoicePar[nvoice].FMFreqEnvelope->relasekey(); - if (NoteVoicePar[nvoice].FMAmpEnvelope!=NULL) NoteVoicePar[nvoice].FMAmpEnvelope->relasekey(); - }; - NoteGlobalPar.FreqEnvelope->relasekey(); - NoteGlobalPar.FilterEnvelope->relasekey(); - NoteGlobalPar.AmpEnvelope->relasekey(); +void ADnote::relasekey() +{ + int nvoice; + for (nvoice=0;nvoice<NUM_VOICES;nvoice++) { + if (NoteVoicePar[nvoice].Enabled==0) continue; + if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) NoteVoicePar[nvoice].AmpEnvelope->relasekey(); + if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) NoteVoicePar[nvoice].FreqEnvelope->relasekey(); + if (NoteVoicePar[nvoice].FilterEnvelope!=NULL) NoteVoicePar[nvoice].FilterEnvelope->relasekey(); + if (NoteVoicePar[nvoice].FMFreqEnvelope!=NULL) NoteVoicePar[nvoice].FMFreqEnvelope->relasekey(); + if (NoteVoicePar[nvoice].FMAmpEnvelope!=NULL) NoteVoicePar[nvoice].FMAmpEnvelope->relasekey(); + }; + NoteGlobalPar.FreqEnvelope->relasekey(); + NoteGlobalPar.FilterEnvelope->relasekey(); + NoteGlobalPar.AmpEnvelope->relasekey(); }; /* * Check if the note is finished */ -int ADnote::finished(){ +int ADnote::finished() +{ if (NoteEnabled==ON) return(0); - else return(1); + else return(1); }; diff --git a/src/Synth/ADnote.h b/src/Synth/ADnote.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + ADnote.h - The "additive" synthesizer Copyright (C) 2002-2005 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 + 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, @@ -38,14 +38,15 @@ #define OSCIL_SMP_EXTRA_SAMPLES 5 /**The "additive" synthesizer*/ -class ADnote{ //ADDitive note - public: +class ADnote //ADDitive note +{ +public: ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote_,bool besilent);//(gf)Added the besilent parameter to tell it to start silent (if true). ~ADnote(); void ADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote_, bool externcall); - int noteout(REALTYPE *outl,REALTYPE *outr); + int noteout(REALTYPE *outl,REALTYPE *outr); void relasekey(); int finished(); @@ -54,30 +55,30 @@ class ADnote{ //ADDitive note or other value if the parameters has been computed and if it is ready to output*/ char ready; - private: - - void setfreq(int nvoice,REALTYPE freq); - void setfreqFM(int nvoice,REALTYPE freq); - void computecurrentparameters(); - void initparameters(); - void KillVoice(int nvoice); - void KillNote(); - inline REALTYPE getvoicebasefreq(int nvoice); - inline REALTYPE getFMvoicebasefreq(int nvoice); - inline void ComputeVoiceOscillator_LinearInterpolation(int nvoice); - inline void ComputeVoiceOscillator_CubicInterpolation(int nvoice); - inline void ComputeVoiceOscillatorMorph(int nvoice); - inline void ComputeVoiceOscillatorRingModulation(int nvoice); - inline void ComputeVoiceOscillatorFrequencyModulation(int nvoice,int FMmode);//FMmode=0 for phase modulation, 1 for Frequency modulation - // inline void ComputeVoiceOscillatorFrequencyModulation(int nvoice); - inline void ComputeVoiceOscillatorPitchModulation(int nvoice); - - inline void ComputeVoiceNoise(int nvoice); - - inline void fadein(REALTYPE *smps); - - - //GLOBALS +private: + + void setfreq(int nvoice,REALTYPE freq); + void setfreqFM(int nvoice,REALTYPE freq); + void computecurrentparameters(); + void initparameters(); + void KillVoice(int nvoice); + void KillNote(); + inline REALTYPE getvoicebasefreq(int nvoice); + inline REALTYPE getFMvoicebasefreq(int nvoice); + inline void ComputeVoiceOscillator_LinearInterpolation(int nvoice); + inline void ComputeVoiceOscillator_CubicInterpolation(int nvoice); + inline void ComputeVoiceOscillatorMorph(int nvoice); + inline void ComputeVoiceOscillatorRingModulation(int nvoice); + inline void ComputeVoiceOscillatorFrequencyModulation(int nvoice,int FMmode);//FMmode=0 for phase modulation, 1 for Frequency modulation + // inline void ComputeVoiceOscillatorFrequencyModulation(int nvoice); + inline void ComputeVoiceOscillatorPitchModulation(int nvoice); + + inline void ComputeVoiceNoise(int nvoice); + + inline void fadein(REALTYPE *smps); + + + //GLOBALS ADnoteParameters *partparams; unsigned char stereo;//if the note is stereo (allows note Panning) int midinote; @@ -86,188 +87,188 @@ class ADnote{ //ADDitive note ONOFFTYPE NoteEnabled; Controller *ctl; - /*****************************************************************/ - /* GLOBAL PARAMETERS */ - /*****************************************************************/ - - struct ADnoteGlobal{ - /****************************************** - * FREQUENCY GLOBAL PARAMETERS * - ******************************************/ - REALTYPE Detune;//cents - - Envelope *FreqEnvelope; - LFO *FreqLfo; - - /******************************************** - * AMPLITUDE GLOBAL PARAMETERS * - ********************************************/ - REALTYPE Volume;// [ 0 .. 1 ] - - REALTYPE Panning;// [ 0 .. 1 ] - - Envelope *AmpEnvelope; - LFO *AmpLfo; - - struct { - int Enabled; - REALTYPE initialvalue,dt,t; - } Punch; - - /****************************************** - * FILTER GLOBAL PARAMETERS * - ******************************************/ - Filter *GlobalFilterL,*GlobalFilterR; - - REALTYPE FilterCenterPitch;//octaves - REALTYPE FilterQ; - REALTYPE FilterFreqTracking; - - Envelope *FilterEnvelope; - - LFO *FilterLfo; - } NoteGlobalPar; - - - - /***********************************************************/ - /* VOICE PARAMETERS */ - /***********************************************************/ - struct ADnoteVoice{ + /*****************************************************************/ + /* GLOBAL PARAMETERS */ + /*****************************************************************/ + + struct ADnoteGlobal { + /****************************************** + * FREQUENCY GLOBAL PARAMETERS * + ******************************************/ + REALTYPE Detune;//cents + + Envelope *FreqEnvelope; + LFO *FreqLfo; + + /******************************************** + * AMPLITUDE GLOBAL PARAMETERS * + ********************************************/ + REALTYPE Volume;// [ 0 .. 1 ] + + REALTYPE Panning;// [ 0 .. 1 ] + + Envelope *AmpEnvelope; + LFO *AmpLfo; + + struct { + int Enabled; + REALTYPE initialvalue,dt,t; + } Punch; + + /****************************************** + * FILTER GLOBAL PARAMETERS * + ******************************************/ + Filter *GlobalFilterL,*GlobalFilterR; + + REALTYPE FilterCenterPitch;//octaves + REALTYPE FilterQ; + REALTYPE FilterFreqTracking; + + Envelope *FilterEnvelope; + + LFO *FilterLfo; + } NoteGlobalPar; + + + + /***********************************************************/ + /* VOICE PARAMETERS */ + /***********************************************************/ + struct ADnoteVoice { /* If the voice is enabled */ - ONOFFTYPE Enabled; + ONOFFTYPE Enabled; + + /* Voice Type (sound/noise)*/ + int noisetype; - /* Voice Type (sound/noise)*/ - int noisetype; + /* Filter Bypass */ + int filterbypass; - /* Filter Bypass */ - int filterbypass; - - /* Delay (ticks) */ - int DelayTicks; - - /* Waveform of the Voice */ - REALTYPE *OscilSmp; + /* Delay (ticks) */ + int DelayTicks; + + /* Waveform of the Voice */ + REALTYPE *OscilSmp; /************************************ - * FREQUENCY PARAMETERS * - ************************************/ - int fixedfreq;//if the frequency is fixed to 440 Hz - int fixedfreqET;//if the "fixed" frequency varies according to the note (ET) + * FREQUENCY PARAMETERS * + ************************************/ + int fixedfreq;//if the frequency is fixed to 440 Hz + int fixedfreqET;//if the "fixed" frequency varies according to the note (ET) + + // cents = basefreq*VoiceDetune + REALTYPE Detune,FineDetune; + + Envelope *FreqEnvelope; + LFO *FreqLfo; + - // cents = basefreq*VoiceDetune - REALTYPE Detune,FineDetune; - - Envelope *FreqEnvelope; - LFO *FreqLfo; - + /*************************** + * AMPLITUDE PARAMETERS * + ***************************/ - /*************************** - * AMPLITUDE PARAMETERS * - ***************************/ + /* Panning 0.0=left, 0.5 - center, 1.0 = right */ + REALTYPE Panning; + REALTYPE Volume;// [-1.0 .. 1.0] - /* Panning 0.0=left, 0.5 - center, 1.0 = right */ - REALTYPE Panning; - REALTYPE Volume;// [-1.0 .. 1.0] + Envelope *AmpEnvelope; + LFO *AmpLfo; - Envelope *AmpEnvelope; - LFO *AmpLfo; + /************************* + * FILTER PARAMETERS * + *************************/ - /************************* - * FILTER PARAMETERS * - *************************/ - - Filter *VoiceFilter; - - REALTYPE FilterCenterPitch;/* Filter center Pitch*/ - REALTYPE FilterFreqTracking; + Filter *VoiceFilter; - Envelope *FilterEnvelope; - LFO *FilterLfo; + REALTYPE FilterCenterPitch;/* Filter center Pitch*/ + REALTYPE FilterFreqTracking; + Envelope *FilterEnvelope; + LFO *FilterLfo; - /**************************** - * MODULLATOR PARAMETERS * - ****************************/ - FMTYPE FMEnabled; + /**************************** + * MODULLATOR PARAMETERS * + ****************************/ - int FMVoice; + FMTYPE FMEnabled; - // Voice Output used by other voices if use this as modullator - REALTYPE *VoiceOut; + int FMVoice; - /* Wave of the Voice */ - REALTYPE *FMSmp; + // Voice Output used by other voices if use this as modullator + REALTYPE *VoiceOut; - REALTYPE FMVolume; - REALTYPE FMDetune; //in cents - - Envelope *FMFreqEnvelope; - Envelope *FMAmpEnvelope; - } NoteVoicePar[NUM_VOICES]; + /* Wave of the Voice */ + REALTYPE *FMSmp; + REALTYPE FMVolume; + REALTYPE FMDetune; //in cents - /********************************************************/ - /* INTERNAL VALUES OF THE NOTE AND OF THE VOICES */ - /********************************************************/ + Envelope *FMFreqEnvelope; + Envelope *FMAmpEnvelope; + } NoteVoicePar[NUM_VOICES]; + + + /********************************************************/ + /* INTERNAL VALUES OF THE NOTE AND OF THE VOICES */ + /********************************************************/ //time from the start of the note REALTYPE time; //fractional part (skip) - REALTYPE oscposlo[NUM_VOICES],oscfreqlo[NUM_VOICES]; + REALTYPE oscposlo[NUM_VOICES],oscfreqlo[NUM_VOICES]; //integer part (skip) int oscposhi[NUM_VOICES],oscfreqhi[NUM_VOICES]; //fractional part (skip) of the Modullator - REALTYPE oscposloFM[NUM_VOICES],oscfreqloFM[NUM_VOICES]; + REALTYPE oscposloFM[NUM_VOICES],oscfreqloFM[NUM_VOICES]; //integer part (skip) of the Modullator unsigned short int oscposhiFM[NUM_VOICES],oscfreqhiFM[NUM_VOICES]; //used to compute and interpolate the amplitudes of voices and modullators REALTYPE oldamplitude[NUM_VOICES], - newamplitude[NUM_VOICES], - FMoldamplitude[NUM_VOICES], - FMnewamplitude[NUM_VOICES]; + newamplitude[NUM_VOICES], + FMoldamplitude[NUM_VOICES], + FMnewamplitude[NUM_VOICES]; //used by Frequency Modulation (for integration) REALTYPE FMoldsmp[NUM_VOICES]; - + //temporary buffer REALTYPE *tmpwave; - + //Filter bypass samples REALTYPE *bypassl,*bypassr; - //interpolate the amplitudes + //interpolate the amplitudes REALTYPE globaloldamplitude,globalnewamplitude; - + //1 - if it is the fitst tick (used to fade in the sound) char firsttick[NUM_VOICES]; - - //1 if the note has portamento + + //1 if the note has portamento int portamento; - + //how the fine detunes are made bigger or smaller REALTYPE bandwidthDetuneMultiplier; // Legato vars struct { - bool silent; - REALTYPE lastfreq; - LegatoMsg msg; - int decounter; - struct { // Fade In/Out vars - int length; - REALTYPE m, step; - } fade; - struct { // Note parameters - REALTYPE freq, vel; - int portamento, midinote; - } param; + bool silent; + REALTYPE lastfreq; + LegatoMsg msg; + int decounter; + struct { // Fade In/Out vars + int length; + REALTYPE m, step; + } fade; + struct { // Note parameters + REALTYPE freq, vel; + int portamento, midinote; + } param; } Legato; }; diff --git a/src/Synth/Envelope.C b/src/Synth/Envelope.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Envelope.C - Envelope implementation Copyright (C) 2002-2005 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 + 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, @@ -23,7 +23,8 @@ #include <stdio.h> #include "Envelope.h" -Envelope::Envelope(EnvelopeParams *envpars,REALTYPE basefreq){ +Envelope::Envelope(EnvelopeParams *envpars,REALTYPE basefreq) +{ int i; envpoints=envpars->Penvpoints; if (envpoints>MAX_ENVELOPE_POINTS) envpoints=MAX_ENVELOPE_POINTS; @@ -33,7 +34,7 @@ Envelope::Envelope(EnvelopeParams *envpars,REALTYPE basefreq){ linearenvelope=envpars->Plinearenvelope; if (envpars->Pfreemode==0) envpars->converttofree(); - + REALTYPE bufferdt=SOUND_BUFFER_SIZE/(REALTYPE)SAMPLE_RATE; int mode=envpars->Envmode; @@ -44,22 +45,27 @@ Envelope::Envelope(EnvelopeParams *envpars,REALTYPE basefreq){ for (i=0;i<MAX_ENVELOPE_POINTS;i++) { REALTYPE tmp=envpars->getdt(i)/1000.0*envstretch; - if (tmp>bufferdt) envdt[i]=bufferdt/tmp; - else envdt[i]=2.0;//any value larger than 1 - - switch (mode){ - case 2:envval[i]=(1.0-envpars->Penvval[i]/127.0)*MIN_ENVELOPE_DB; - break; - case 3:envval[i]=(pow(2,6.0*fabs(envpars->Penvval[i]-64.0)/64.0)-1.0)*100.0; - if (envpars->Penvval[i]<64) envval[i]=-envval[i]; - break; - case 4:envval[i]=(envpars->Penvval[i]-64.0)/64.0*6.0;//6 octaves (filtru) - break; - case 5:envval[i]=(envpars->Penvval[i]-64.0)/64.0*10; - break; - default:envval[i]=envpars->Penvval[i]/127.0; - }; - + if (tmp>bufferdt) envdt[i]=bufferdt/tmp; + else envdt[i]=2.0;//any value larger than 1 + + switch (mode) { + case 2: + envval[i]=(1.0-envpars->Penvval[i]/127.0)*MIN_ENVELOPE_DB; + break; + case 3: + envval[i]=(pow(2,6.0*fabs(envpars->Penvval[i]-64.0)/64.0)-1.0)*100.0; + if (envpars->Penvval[i]<64) envval[i]=-envval[i]; + break; + case 4: + envval[i]=(envpars->Penvval[i]-64.0)/64.0*6.0;//6 octaves (filtru) + break; + case 5: + envval[i]=(envpars->Penvval[i]-64.0)/64.0*10; + break; + default: + envval[i]=envpars->Penvval[i]/127.0; + }; + }; envdt[0]=1.0; @@ -72,14 +78,16 @@ Envelope::Envelope(EnvelopeParams *envpars,REALTYPE basefreq){ envoutval=0.0; }; -Envelope::~Envelope(){ +Envelope::~Envelope() +{ }; /* * Relase the key (note envelope) */ -void Envelope::relasekey(){ +void Envelope::relasekey() +{ if (keyreleased==1) return; keyreleased=1; if (forcedrelase!=0) t=0.0; @@ -88,78 +96,81 @@ void Envelope::relasekey(){ /* * Envelope Output */ -REALTYPE Envelope::envout(){ +REALTYPE Envelope::envout() +{ REALTYPE out; if (envfinish!=0) {//if the envelope is finished - envoutval=envval[envpoints-1]; - return(envoutval); + envoutval=envval[envpoints-1]; + return(envoutval); }; if ((currentpoint==envsustain+1)&&(keyreleased==0)) {//if it is sustaining now - envoutval=envval[envsustain]; - return(envoutval); + envoutval=envval[envsustain]; + return(envoutval); }; - if ((keyreleased!=0) && (forcedrelase!=0)){//do the forced release - + if ((keyreleased!=0) && (forcedrelase!=0)) {//do the forced release + int tmp=(envsustain<0) ? (envpoints-1):(envsustain+1);//if there is no sustain point, use the last point for release - if (envdt[tmp]<0.00000001) out=envval[tmp]; - else out=envoutval+(envval[tmp]-envoutval)*t; - t+=envdt[tmp]*envstretch; - - if (t>=1.0) { - currentpoint=envsustain+2; - forcedrelase=0; - t=0.0; - inct=envdt[currentpoint]; - if ((currentpoint>=envpoints)||(envsustain<0)) envfinish=1; - }; - return(out); + if (envdt[tmp]<0.00000001) out=envval[tmp]; + else out=envoutval+(envval[tmp]-envoutval)*t; + t+=envdt[tmp]*envstretch; + + if (t>=1.0) { + currentpoint=envsustain+2; + forcedrelase=0; + t=0.0; + inct=envdt[currentpoint]; + if ((currentpoint>=envpoints)||(envsustain<0)) envfinish=1; + }; + return(out); }; if (inct>=1.0) out=envval[currentpoint]; - else out=envval[currentpoint-1]+(envval[currentpoint]-envval[currentpoint-1])*t; + else out=envval[currentpoint-1]+(envval[currentpoint]-envval[currentpoint-1])*t; t+=inct; - if (t>=1.0){ - if (currentpoint>=envpoints-1) envfinish=1; - else currentpoint++; - t=0.0; - inct=envdt[currentpoint]; + if (t>=1.0) { + if (currentpoint>=envpoints-1) envfinish=1; + else currentpoint++; + t=0.0; + inct=envdt[currentpoint]; }; - envoutval=out; + envoutval=out; return (out); }; /* * Envelope Output (dB) */ -REALTYPE Envelope::envout_dB(){ +REALTYPE Envelope::envout_dB() +{ REALTYPE out; if (linearenvelope!=0) return (envout()); - + if ((currentpoint==1)&&((keyreleased==0)||(forcedrelase==0))) {//first point is always lineary interpolated - REALTYPE v1=dB2rap(envval[0]); - REALTYPE v2=dB2rap(envval[1]); - out=v1+(v2-v1)*t; - - t+=inct; - if (t>=1.0) { - t=0.0; - inct=envdt[2]; - currentpoint++; - out=v2; - }; - - if (out>0.001) envoutval=rap2dB(out); - else envoutval=-40.0; + REALTYPE v1=dB2rap(envval[0]); + REALTYPE v2=dB2rap(envval[1]); + out=v1+(v2-v1)*t; + + t+=inct; + if (t>=1.0) { + t=0.0; + inct=envdt[2]; + currentpoint++; + out=v2; + }; + + if (out>0.001) envoutval=rap2dB(out); + else envoutval=-40.0; } else out=dB2rap(envout()); return(out); }; -int Envelope::finished(){ +int Envelope::finished() +{ return(envfinish); }; diff --git a/src/Synth/Envelope.h b/src/Synth/Envelope.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Envelope.h - Envelope implementation Copyright (C) 2002-2005 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 + 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, @@ -28,7 +28,8 @@ #include "../Params/EnvelopeParams.h" /**Implementation of a general Envelope*/ -class Envelope{ +class Envelope +{ public: /**Constructor*/ @@ -48,15 +49,15 @@ private: int envsustain;//"-1" means disabled REALTYPE envdt[MAX_ENVELOPE_POINTS];//millisecons REALTYPE envval[MAX_ENVELOPE_POINTS];// [0.0 .. 1.0] - REALTYPE envstretch; + REALTYPE envstretch; int linearenvelope; int currentpoint; //current envelope point (starts from 1) int forcedrelase; char keyreleased; //if the key was released /** \todo figure out WHY IS THIS A CHAR*/ - char envfinish; /** \todo figure out WHY IS THIS A CHAR*/ + char envfinish; /** \todo figure out WHY IS THIS A CHAR*/ REALTYPE t; // the time from the last point - REALTYPE inct;// the time increment + REALTYPE inct;// the time increment REALTYPE envoutval;//used to do the forced release }; diff --git a/src/Synth/LFO.C b/src/Synth/LFO.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + LFO.C - LFO implementation Copyright (C) 2002-2005 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 + 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, @@ -27,37 +27,44 @@ #include "LFO.h" -LFO::LFO(LFOParams *lfopars,REALTYPE basefreq){ +LFO::LFO(LFOParams *lfopars,REALTYPE basefreq) +{ if (lfopars->Pstretch==0) lfopars->Pstretch=1; REALTYPE lfostretch=pow(basefreq/440.0,(lfopars->Pstretch-64.0)/63.0);//max 2x/octave REALTYPE lfofreq=(pow(2,lfopars->Pfreq*10.0)-1.0)/12.0*lfostretch; incx=fabs(lfofreq)*(REALTYPE)SOUND_BUFFER_SIZE/(REALTYPE)SAMPLE_RATE; - if (lfopars->Pcontinous==0){ - if (lfopars->Pstartphase==0) x=RND; - else x=fmod((lfopars->Pstartphase-64.0)/127.0+1.0,1.0); + if (lfopars->Pcontinous==0) { + if (lfopars->Pstartphase==0) x=RND; + else x=fmod((lfopars->Pstartphase-64.0)/127.0+1.0,1.0); } else { - REALTYPE tmp=fmod(lfopars->time*incx,1.0); - x=fmod((lfopars->Pstartphase-64.0)/127.0+1.0+tmp,1.0); + REALTYPE tmp=fmod(lfopars->time*incx,1.0); + x=fmod((lfopars->Pstartphase-64.0)/127.0+1.0+tmp,1.0); }; //Limit the Frequency(or else...) if (incx>0.49999999) incx=0.499999999; - + lfornd=lfopars->Prandomness/127.0; - if (lfornd<0.0) lfornd=0.0; else if (lfornd>1.0) lfornd=1.0; + if (lfornd<0.0) lfornd=0.0; + else if (lfornd>1.0) lfornd=1.0; // lfofreqrnd=pow(lfopars->Pfreqrand/127.0,2.0)*2.0*4.0; lfofreqrnd=pow(lfopars->Pfreqrand/127.0,2.0)*4.0; - switch (lfopars->fel){ - case 1:lfointensity=lfopars->Pintensity/127.0;break; - case 2:lfointensity=lfopars->Pintensity/127.0*4.0;break;//in octave - default:lfointensity=pow(2,lfopars->Pintensity/127.0*11.0)-1.0;//in centi - x-=0.25;//chance the starting phase - break; + switch (lfopars->fel) { + case 1: + lfointensity=lfopars->Pintensity/127.0; + break; + case 2: + lfointensity=lfopars->Pintensity/127.0*4.0; + break;//in octave + default: + lfointensity=pow(2,lfopars->Pintensity/127.0*11.0)-1.0;//in centi + x-=0.25;//chance the starting phase + break; }; amp1=(1-lfornd)+lfornd*RND; @@ -70,57 +77,60 @@ LFO::LFO(LFOParams *lfopars,REALTYPE basefreq){ computenextincrnd();//twice because I want incrnd & nextincrnd to be random }; -LFO::~LFO(){ +LFO::~LFO() +{ }; /* * LFO out */ -REALTYPE LFO::lfoout(){ - REALTYPE out; - switch (lfotype){ - case 1: //LFO_TRIANGLE - if ((x>=0.0)&&(x<0.25)) out=4.0*x; - else if ((x>0.25)&&(x<0.75)) out=2-4*x; - else out=4.0*x-4.0; - break; - case 2: //LFO_SQUARE - if (x<0.5) out=-1; - else out=1; - break; - case 3: //LFO_RAMPUP - out=(x-0.5)*2.0; - break; - case 4: //LFO_RAMPDOWN - out=(0.5-x)*2.0; - break; - case 5: //LFO_EXP_DOWN 1 - out=pow(0.05,x)*2.0-1.0; - break; - case 6: //LFO_EXP_DOWN 2 - out=pow(0.001,x)*2.0-1.0; - break; - default:out=cos(x*2.0*PI);//LFO_SINE +REALTYPE LFO::lfoout() +{ + REALTYPE out; + switch (lfotype) { + case 1: //LFO_TRIANGLE + if ((x>=0.0)&&(x<0.25)) out=4.0*x; + else if ((x>0.25)&&(x<0.75)) out=2-4*x; + else out=4.0*x-4.0; + break; + case 2: //LFO_SQUARE + if (x<0.5) out=-1; + else out=1; + break; + case 3: //LFO_RAMPUP + out=(x-0.5)*2.0; + break; + case 4: //LFO_RAMPDOWN + out=(0.5-x)*2.0; + break; + case 5: //LFO_EXP_DOWN 1 + out=pow(0.05,x)*2.0-1.0; + break; + case 6: //LFO_EXP_DOWN 2 + out=pow(0.001,x)*2.0-1.0; + break; + default: + out=cos(x*2.0*PI);//LFO_SINE }; if ((lfotype==0)||(lfotype==1)) out*=lfointensity*(amp1+x*(amp2-amp1)); - else out*=lfointensity*amp2; + else out*=lfointensity*amp2; if (lfodelay<0.00001) { - if (freqrndenabled==0) x+=incx; - else { - float tmp=(incrnd*(1.0-x)+nextincrnd*x); - if (tmp>1.0) tmp=1.0; - else if (tmp<0.0) tmp=0.0; - x+=incx*tmp; - }; - if (x>=1) { - x=fmod(x,1.0); - amp1=amp2; - amp2=(1-lfornd)+lfornd*RND; - - computenextincrnd(); - }; + if (freqrndenabled==0) x+=incx; + else { + float tmp=(incrnd*(1.0-x)+nextincrnd*x); + if (tmp>1.0) tmp=1.0; + else if (tmp<0.0) tmp=0.0; + x+=incx*tmp; + }; + if (x>=1) { + x=fmod(x,1.0); + amp1=amp2; + amp2=(1-lfornd)+lfornd*RND; + + computenextincrnd(); + }; } else lfodelay-=(REALTYPE)SOUND_BUFFER_SIZE/(REALTYPE)SAMPLE_RATE; return(out); }; @@ -128,18 +138,20 @@ REALTYPE LFO::lfoout(){ /* * LFO out (for amplitude) */ -REALTYPE LFO::amplfoout(){ +REALTYPE LFO::amplfoout() +{ REALTYPE out; out=1.0-lfointensity+lfoout(); if (out<-1.0) out=-1.0; - else if (out>1.0) out=1.0; + else if (out>1.0) out=1.0; return(out); }; -void LFO::computenextincrnd(){ - if (freqrndenabled==0) return; - incrnd=nextincrnd; - nextincrnd=pow(0.5,lfofreqrnd)+RND*(pow(2.0,lfofreqrnd)-1.0); +void LFO::computenextincrnd() +{ + if (freqrndenabled==0) return; + incrnd=nextincrnd; + nextincrnd=pow(0.5,lfofreqrnd)+RND*(pow(2.0,lfofreqrnd)-1.0); }; diff --git a/src/Synth/LFO.h b/src/Synth/LFO.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + LFO.h - LFO implementation Copyright (C) 2002-2005 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 + 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, @@ -27,8 +27,9 @@ #include "../Params/LFOParams.h" /**Class for creating Low Frequency Ocillators*/ -class LFO{ - public: +class LFO +{ +public: /**Constructor * * @param lfopars pointer to a LFOParams object @@ -39,7 +40,7 @@ class LFO{ ~LFO(); REALTYPE lfoout(); REALTYPE amplfoout(); - private: +private: REALTYPE x; REALTYPE incx,incrnd,nextincrnd; REALTYPE amp1,amp2;// used for randomness @@ -49,10 +50,10 @@ class LFO{ /**\todo see if an enum would be better here*/ char lfotype; int freqrndenabled; - - + + void computenextincrnd(); - + }; #endif diff --git a/src/Synth/OscilGen.C b/src/Synth/OscilGen.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + OscilGen.C - Waveform generator for ADnote Copyright (C) 2002-2005 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 + 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, @@ -31,7 +31,8 @@ REALTYPE *OscilGen::tmpsmps;//this array stores some termporary data and it has FFTFREQS OscilGen::outoscilFFTfreqs; -OscilGen::OscilGen(FFTwrapper *fft_,Resonance *res_):Presets(){ +OscilGen::OscilGen(FFTwrapper *fft_,Resonance *res_):Presets() +{ setpresettype("Poscilgen"); fft=fft_; res=res_; @@ -44,28 +45,41 @@ OscilGen::OscilGen(FFTwrapper *fft_,Resonance *res_):Presets(){ defaults(); }; -OscilGen::~OscilGen(){ +OscilGen::~OscilGen() +{ deleteFFTFREQS(&basefuncFFTfreqs); deleteFFTFREQS(&oscilFFTfreqs); }; -void OscilGen::defaults(){ - - oldbasefunc=0;oldbasepar=64;oldhmagtype=0;oldwaveshapingfunction=0;oldwaveshaping=64; - oldbasefuncmodulation=0;oldharmonicshift=0;oldbasefuncmodulationpar1=0;oldbasefuncmodulationpar2=0;oldbasefuncmodulationpar3=0; - oldmodulation=0;oldmodulationpar1=0;oldmodulationpar2=0;oldmodulationpar3=0; - - for (int i=0;i<MAX_AD_HARMONICS;i++){ - hmag[i]=0.0; - hphase[i]=0.0; - Phmag[i]=64; - Phphase[i]=64; +void OscilGen::defaults() +{ + + oldbasefunc=0; + oldbasepar=64; + oldhmagtype=0; + oldwaveshapingfunction=0; + oldwaveshaping=64; + oldbasefuncmodulation=0; + oldharmonicshift=0; + oldbasefuncmodulationpar1=0; + oldbasefuncmodulationpar2=0; + oldbasefuncmodulationpar3=0; + oldmodulation=0; + oldmodulationpar1=0; + oldmodulationpar2=0; + oldmodulationpar3=0; + + for (int i=0;i<MAX_AD_HARMONICS;i++) { + hmag[i]=0.0; + hphase[i]=0.0; + Phmag[i]=64; + Phphase[i]=64; }; Phmag[0]=127; Phmagtype=0; if (ADvsPAD) Prand=127;//max phase randomness (usefull if the oscil will be imported to a ADsynth from a PADsynth - else Prand=64;//no randomness + else Prand=64;//no randomness Pcurrentbasefunc=0; Pbasefuncpar=64; @@ -91,7 +105,7 @@ void OscilGen::defaults(){ Pamprandpower=64; Pamprandtype=0; - + Pharmonicshift=0; Pharmonicshiftfirst=0; @@ -99,20 +113,22 @@ void OscilGen::defaults(){ Padaptiveharmonicspower=100; Padaptiveharmonicsbasefreq=128; Padaptiveharmonicspar=50; - + for (int i=0;i<OSCIL_SIZE/2;i++) { - oscilFFTfreqs.s[i]=0.0; - oscilFFTfreqs.c[i]=0.0; - basefuncFFTfreqs.s[i]=0.0; - basefuncFFTfreqs.c[i]=0.0; + oscilFFTfreqs.s[i]=0.0; + oscilFFTfreqs.c[i]=0.0; + basefuncFFTfreqs.s[i]=0.0; + basefuncFFTfreqs.c[i]=0.0; }; oscilprepared=0; - oldfilterpars=0;oldsapars=0; + oldfilterpars=0; + oldsapars=0; prepare(); }; -void OscilGen::convert2sine(int magtype){ - REALTYPE mag[MAX_AD_HARMONICS],phase[MAX_AD_HARMONICS]; +void OscilGen::convert2sine(int magtype) +{ + REALTYPE mag[MAX_AD_HARMONICS],phase[MAX_AD_HARMONICS]; REALTYPE oscil[OSCIL_SIZE]; FFTFREQS freqs; newFFTFREQS(&freqs,OSCIL_SIZE/2); @@ -123,115 +139,128 @@ void OscilGen::convert2sine(int magtype){ delete(fft); REALTYPE max=0.0; - + mag[0]=0; phase[0]=0; - for (int i=0;i<MAX_AD_HARMONICS;i++){ + for (int i=0;i<MAX_AD_HARMONICS;i++) { mag[i]=sqrt(pow(freqs.s[i+1],2)+pow(freqs.c[i+1],2.0)); - phase[i]=atan2(freqs.c[i+1],freqs.s[i+1]); - if (max<mag[i]) max=mag[i]; + phase[i]=atan2(freqs.c[i+1],freqs.s[i+1]); + if (max<mag[i]) max=mag[i]; }; if (max<0.00001) max=1.0; - + defaults(); - - for (int i=0;i<MAX_AD_HARMONICS-1;i++){ - REALTYPE newmag=mag[i]/max; - REALTYPE newphase=phase[i]; - - Phmag[i]=(int) ((newmag)*64.0)+64; - - Phphase[i]=64-(int) (64.0*newphase/PI); - if (Phphase[i]>127) Phphase[i]=127; - - if (Phmag[i]==64) Phphase[i]=64; + + for (int i=0;i<MAX_AD_HARMONICS-1;i++) { + REALTYPE newmag=mag[i]/max; + REALTYPE newphase=phase[i]; + + Phmag[i]=(int) ((newmag)*64.0)+64; + + Phphase[i]=64-(int) (64.0*newphase/PI); + if (Phphase[i]>127) Phphase[i]=127; + + if (Phmag[i]==64) Phphase[i]=64; }; deleteFFTFREQS(&freqs); prepare(); }; -/* - * Base Functions - START +/* + * Base Functions - START */ -REALTYPE OscilGen::basefunc_pulse(REALTYPE x,REALTYPE a){ +REALTYPE OscilGen::basefunc_pulse(REALTYPE x,REALTYPE a) +{ return((fmod(x,1.0)<a)?-1.0:1.0); }; -REALTYPE OscilGen::basefunc_saw(REALTYPE x,REALTYPE a){ +REALTYPE OscilGen::basefunc_saw(REALTYPE x,REALTYPE a) +{ if (a<0.00001) a=0.00001; - else if (a>0.99999) a=0.99999; + else if (a>0.99999) a=0.99999; x=fmod(x,1); if (x<a) return(x/a*2.0-1.0); - else return((1.0-x)/(1.0-a)*2.0-1.0); + else return((1.0-x)/(1.0-a)*2.0-1.0); }; -REALTYPE OscilGen::basefunc_triangle(REALTYPE x,REALTYPE a){ +REALTYPE OscilGen::basefunc_triangle(REALTYPE x,REALTYPE a) +{ x=fmod(x+0.25,1); a=1-a; if (a<0.00001) a=0.00001; if (x<0.5) x=x*4-1.0; - else x=(1.0-x)*4-1.0; + else x=(1.0-x)*4-1.0; x/=-a; if (x<-1.0) x=-1.0; if (x>1.0) x=1.0; return(x); }; -REALTYPE OscilGen::basefunc_power(REALTYPE x,REALTYPE a){ +REALTYPE OscilGen::basefunc_power(REALTYPE x,REALTYPE a) +{ x=fmod(x,1); if (a<0.00001) a=0.00001; - else if (a>0.99999) a=0.99999; + else if (a>0.99999) a=0.99999; return(pow(x,exp((a-0.5)*10.0))*2.0-1.0); }; -REALTYPE OscilGen::basefunc_gauss(REALTYPE x,REALTYPE a){ +REALTYPE OscilGen::basefunc_gauss(REALTYPE x,REALTYPE a) +{ x=fmod(x,1)*2.0-1.0; if (a<0.00001) a=0.00001; return(exp(-x*x*(exp(a*8)+5.0))*2.0-1.0); }; -REALTYPE OscilGen::basefunc_diode(REALTYPE x,REALTYPE a){ +REALTYPE OscilGen::basefunc_diode(REALTYPE x,REALTYPE a) +{ if (a<0.00001) a=0.00001; - else if (a>0.99999) a=0.99999; + else if (a>0.99999) a=0.99999; a=a*2.0-1.0; x=cos((x+0.5)*2.0*PI)-a; if (x<0.0) x=0.0; return(x/(1.0-a)*2-1.0); }; -REALTYPE OscilGen::basefunc_abssine(REALTYPE x,REALTYPE a){ +REALTYPE OscilGen::basefunc_abssine(REALTYPE x,REALTYPE a) +{ x=fmod(x,1); if (a<0.00001) a=0.00001; - else if (a>0.99999) a=0.99999; + else if (a>0.99999) a=0.99999; return(sin(pow(x,exp((a-0.5)*5.0))*PI)*2.0-1.0); }; -REALTYPE OscilGen::basefunc_pulsesine(REALTYPE x,REALTYPE a){ +REALTYPE OscilGen::basefunc_pulsesine(REALTYPE x,REALTYPE a) +{ if (a<0.00001) a=0.00001; x=(fmod(x,1)-0.5)*exp((a-0.5)*log(128)); if (x<-0.5) x=-0.5; - else if (x>0.5) x=0.5; + else if (x>0.5) x=0.5; x=sin(x*PI*2.0); return(x); }; -REALTYPE OscilGen::basefunc_stretchsine(REALTYPE x,REALTYPE a){ +REALTYPE OscilGen::basefunc_stretchsine(REALTYPE x,REALTYPE a) +{ x=fmod(x+0.5,1)*2.0-1.0; - a=(a-0.5)*4;if (a>0.0) a*=2; + a=(a-0.5)*4; + if (a>0.0) a*=2; a=pow(3.0,a); REALTYPE b=pow(fabs(x),a); if (x<0) b=-b; return(-sin(b*PI)); }; -REALTYPE OscilGen::basefunc_chirp(REALTYPE x,REALTYPE a){ +REALTYPE OscilGen::basefunc_chirp(REALTYPE x,REALTYPE a) +{ x=fmod(x,1.0)*2.0*PI; - a=(a-0.5)*4;if (a<0.0) a*=2.0; + a=(a-0.5)*4; + if (a<0.0) a*=2.0; a=pow(3.0,a); return(sin(x/2.0)*sin(a*x*x)); }; -REALTYPE OscilGen::basefunc_absstretchsine(REALTYPE x,REALTYPE a){ +REALTYPE OscilGen::basefunc_absstretchsine(REALTYPE x,REALTYPE a) +{ x=fmod(x+0.5,1)*2.0-1.0; a=(a-0.5)*9; a=pow(3.0,a); @@ -240,197 +269,235 @@ REALTYPE OscilGen::basefunc_absstretchsine(REALTYPE x,REALTYPE a){ return(-pow(sin(b*PI),2)); }; -REALTYPE OscilGen::basefunc_chebyshev(REALTYPE x,REALTYPE a){ +REALTYPE OscilGen::basefunc_chebyshev(REALTYPE x,REALTYPE a) +{ a=a*a*a*30.0+1.0; return(cos(acos(x*2.0-1.0)*a)); }; -REALTYPE OscilGen::basefunc_sqr(REALTYPE x,REALTYPE a){ +REALTYPE OscilGen::basefunc_sqr(REALTYPE x,REALTYPE a) +{ a=a*a*a*a*160.0+0.001; return(-atan(sin(x*2.0*PI)*a)); }; -/* +/* * Base Functions - END */ -/* +/* * Get the base function */ -void OscilGen::getbasefunction(REALTYPE *smps){ - int i; +void OscilGen::getbasefunction(REALTYPE *smps) +{ + int i; REALTYPE par=(Pbasefuncpar+0.5)/128.0; if (Pbasefuncpar==64) par=0.5; - + REALTYPE basefuncmodulationpar1=Pbasefuncmodulationpar1/127.0, - basefuncmodulationpar2=Pbasefuncmodulationpar2/127.0, - basefuncmodulationpar3=Pbasefuncmodulationpar3/127.0; - - switch(Pbasefuncmodulation){ - case 1:basefuncmodulationpar1=(pow(2,basefuncmodulationpar1*5.0)-1.0)/10.0; - basefuncmodulationpar3=floor((pow(2,basefuncmodulationpar3*5.0)-1.0)); - if (basefuncmodulationpar3<0.9999) basefuncmodulationpar3=-1.0; - break; - case 2:basefuncmodulationpar1=(pow(2,basefuncmodulationpar1*5.0)-1.0)/10.0; - basefuncmodulationpar3=1.0+floor((pow(2,basefuncmodulationpar3*5.0)-1.0)); - break; - case 3:basefuncmodulationpar1=(pow(2,basefuncmodulationpar1*7.0)-1.0)/10.0; - basefuncmodulationpar3=0.01+(pow(2,basefuncmodulationpar3*16.0)-1.0)/10.0; - break; - }; + basefuncmodulationpar2=Pbasefuncmodulationpar2/127.0, + basefuncmodulationpar3=Pbasefuncmodulationpar3/127.0; + + switch (Pbasefuncmodulation) { + case 1: + basefuncmodulationpar1=(pow(2,basefuncmodulationpar1*5.0)-1.0)/10.0; + basefuncmodulationpar3=floor((pow(2,basefuncmodulationpar3*5.0)-1.0)); + if (basefuncmodulationpar3<0.9999) basefuncmodulationpar3=-1.0; + break; + case 2: + basefuncmodulationpar1=(pow(2,basefuncmodulationpar1*5.0)-1.0)/10.0; + basefuncmodulationpar3=1.0+floor((pow(2,basefuncmodulationpar3*5.0)-1.0)); + break; + case 3: + basefuncmodulationpar1=(pow(2,basefuncmodulationpar1*7.0)-1.0)/10.0; + basefuncmodulationpar3=0.01+(pow(2,basefuncmodulationpar3*16.0)-1.0)/10.0; + break; + }; // printf("%.5f %.5f\n",basefuncmodulationpar1,basefuncmodulationpar3); for (i=0;i<OSCIL_SIZE;i++) { - REALTYPE t=i*1.0/OSCIL_SIZE; - - switch(Pbasefuncmodulation){ - case 1:t=t*basefuncmodulationpar3+sin((t+basefuncmodulationpar2)*2.0*PI)*basefuncmodulationpar1;//rev - break; - case 2:t=t+sin((t*basefuncmodulationpar3+basefuncmodulationpar2)*2.0*PI)*basefuncmodulationpar1;//sine - break; - case 3:t=t+pow((1.0-cos((t+basefuncmodulationpar2)*2.0*PI))*0.5,basefuncmodulationpar3)*basefuncmodulationpar1;//power - break; - }; - - t=t-floor(t); - - switch (Pcurrentbasefunc){ - case 1:smps[i]=basefunc_triangle(t,par); - break; - case 2:smps[i]=basefunc_pulse(t,par); - break; - case 3:smps[i]=basefunc_saw(t,par); - break; - case 4:smps[i]=basefunc_power(t,par); - break; - case 5:smps[i]=basefunc_gauss(t,par); - break; - case 6:smps[i]=basefunc_diode(t,par); - break; - case 7:smps[i]=basefunc_abssine(t,par); - break; - case 8:smps[i]=basefunc_pulsesine(t,par); - break; - case 9:smps[i]=basefunc_stretchsine(t,par); - break; - case 10:smps[i]=basefunc_chirp(t,par); - break; - case 11:smps[i]=basefunc_absstretchsine(t,par); - break; - case 12:smps[i]=basefunc_chebyshev(t,par); - break; - case 13:smps[i]=basefunc_sqr(t,par); - break; - default:smps[i]=-sin(2.0*PI*i/OSCIL_SIZE); - }; + REALTYPE t=i*1.0/OSCIL_SIZE; + + switch (Pbasefuncmodulation) { + case 1: + t=t*basefuncmodulationpar3+sin((t+basefuncmodulationpar2)*2.0*PI)*basefuncmodulationpar1;//rev + break; + case 2: + t=t+sin((t*basefuncmodulationpar3+basefuncmodulationpar2)*2.0*PI)*basefuncmodulationpar1;//sine + break; + case 3: + t=t+pow((1.0-cos((t+basefuncmodulationpar2)*2.0*PI))*0.5,basefuncmodulationpar3)*basefuncmodulationpar1;//power + break; + }; + + t=t-floor(t); + + switch (Pcurrentbasefunc) { + case 1: + smps[i]=basefunc_triangle(t,par); + break; + case 2: + smps[i]=basefunc_pulse(t,par); + break; + case 3: + smps[i]=basefunc_saw(t,par); + break; + case 4: + smps[i]=basefunc_power(t,par); + break; + case 5: + smps[i]=basefunc_gauss(t,par); + break; + case 6: + smps[i]=basefunc_diode(t,par); + break; + case 7: + smps[i]=basefunc_abssine(t,par); + break; + case 8: + smps[i]=basefunc_pulsesine(t,par); + break; + case 9: + smps[i]=basefunc_stretchsine(t,par); + break; + case 10: + smps[i]=basefunc_chirp(t,par); + break; + case 11: + smps[i]=basefunc_absstretchsine(t,par); + break; + case 12: + smps[i]=basefunc_chebyshev(t,par); + break; + case 13: + smps[i]=basefunc_sqr(t,par); + break; + default: + smps[i]=-sin(2.0*PI*i/OSCIL_SIZE); + }; }; }; -/* +/* * Filter the oscillator */ -void OscilGen::oscilfilter(){ +void OscilGen::oscilfilter() +{ if (Pfiltertype==0) return; REALTYPE par=1.0-Pfilterpar1/128.0; REALTYPE par2=Pfilterpar2/127.0; REALTYPE max=0.0,tmp=0.0,p2,x; - for (int i=1;i<OSCIL_SIZE/2;i++){ - REALTYPE gain=1.0; - switch(Pfiltertype){ - case 1: gain=pow(1.0-par*par*par*0.99,i);//lp - tmp=par2*par2*par2*par2*0.5+0.0001; - if (gain<tmp) gain=pow(gain,10.0)/pow(tmp,9.0); - break; - case 2: gain=1.0-pow(1.0-par*par,i+1);//hp1 - gain=pow(gain,par2*2.0+0.1); - break; - case 3: if (par<0.2) par=par*0.25+0.15; - gain=1.0-pow(1.0-par*par*0.999+0.001,i*0.05*i+1.0);//hp1b - tmp=pow(5.0,par2*2.0); - gain=pow(gain,tmp); - break; - case 4: gain=i+1-pow(2,(1.0-par)*7.5);//bp1 - gain=1.0/(1.0+gain*gain/(i+1.0)); - tmp=pow(5.0,par2*2.0); - gain=pow(gain,tmp); - if (gain<1e-5) gain=1e-5; - break; - case 5: gain=i+1-pow(2,(1.0-par)*7.5);//bs1 - gain=pow(atan(gain/(i/10.0+1))/1.57,6); - gain=pow(gain,par2*par2*3.9+0.1); - break; - case 6: tmp=pow(par2,0.33); - gain=(i+1>pow(2,(1.0-par)*10)?0.0:1.0)*par2+(1.0-par2);//lp2 - break; - case 7: tmp=pow(par2,0.33); - //tmp=1.0-(1.0-par2)*(1.0-par2); - gain=(i+1>pow(2,(1.0-par)*7)?1.0:0.0)*par2+(1.0-par2);//hp2 - if (Pfilterpar1==0) gain=1.0; - break; - case 8: tmp=pow(par2,0.33); - //tmp=1.0-(1.0-par2)*(1.0-par2); - gain=(fabs(pow(2,(1.0-par)*7)-i)>i/2+1?0.0:1.0)*par2+(1.0-par2);//bp2 - break; - case 9: tmp=pow(par2,0.33); - gain=(fabs(pow(2,(1.0-par)*7)-i)<i/2+1?0.0:1.0)*par2+(1.0-par2);//bs2 - break; - case 10:tmp=pow(5.0,par2*2.0-1.0); - tmp=pow(i/32.0,tmp)*32.0; - if (Pfilterpar2==64) tmp=i; - gain=cos(par*par*PI/2.0*tmp);//cos - gain*=gain; - break; - case 11:tmp=pow(5.0,par2*2.0-1.0); - tmp=pow(i/32.0,tmp)*32.0; - if (Pfilterpar2==64) tmp=i; - gain=sin(par*par*PI/2.0*tmp);//sin - gain*=gain; - break; - case 12:p2=1.0-par+0.2; - x=i/(64.0*p2*p2); - if (x<0.0) x=0.0; - else if (x>1.0) x=1.0; - tmp=pow(1.0-par2,2.0); - gain=cos(x*PI)*(1.0-tmp)+1.01+tmp;//low shelf - break; - case 13:tmp=(int) (pow(2.0,(1.0-par)*7.2)); - gain=1.0; - if (i==(int) (tmp)) gain=pow(2.0,par2*par2*8.0); - break; - }; - - - oscilFFTfreqs.s[i]*=gain; - oscilFFTfreqs.c[i]*=gain; - REALTYPE tmp=oscilFFTfreqs.s[i]*oscilFFTfreqs.s[i]+ - oscilFFTfreqs.c[i]*oscilFFTfreqs.c[i]; - if (max<tmp) max=tmp; + for (int i=1;i<OSCIL_SIZE/2;i++) { + REALTYPE gain=1.0; + switch (Pfiltertype) { + case 1: + gain=pow(1.0-par*par*par*0.99,i);//lp + tmp=par2*par2*par2*par2*0.5+0.0001; + if (gain<tmp) gain=pow(gain,10.0)/pow(tmp,9.0); + break; + case 2: + gain=1.0-pow(1.0-par*par,i+1);//hp1 + gain=pow(gain,par2*2.0+0.1); + break; + case 3: + if (par<0.2) par=par*0.25+0.15; + gain=1.0-pow(1.0-par*par*0.999+0.001,i*0.05*i+1.0);//hp1b + tmp=pow(5.0,par2*2.0); + gain=pow(gain,tmp); + break; + case 4: + gain=i+1-pow(2,(1.0-par)*7.5);//bp1 + gain=1.0/(1.0+gain*gain/(i+1.0)); + tmp=pow(5.0,par2*2.0); + gain=pow(gain,tmp); + if (gain<1e-5) gain=1e-5; + break; + case 5: + gain=i+1-pow(2,(1.0-par)*7.5);//bs1 + gain=pow(atan(gain/(i/10.0+1))/1.57,6); + gain=pow(gain,par2*par2*3.9+0.1); + break; + case 6: + tmp=pow(par2,0.33); + gain=(i+1>pow(2,(1.0-par)*10)?0.0:1.0)*par2+(1.0-par2);//lp2 + break; + case 7: + tmp=pow(par2,0.33); + //tmp=1.0-(1.0-par2)*(1.0-par2); + gain=(i+1>pow(2,(1.0-par)*7)?1.0:0.0)*par2+(1.0-par2);//hp2 + if (Pfilterpar1==0) gain=1.0; + break; + case 8: + tmp=pow(par2,0.33); + //tmp=1.0-(1.0-par2)*(1.0-par2); + gain=(fabs(pow(2,(1.0-par)*7)-i)>i/2+1?0.0:1.0)*par2+(1.0-par2);//bp2 + break; + case 9: + tmp=pow(par2,0.33); + gain=(fabs(pow(2,(1.0-par)*7)-i)<i/2+1?0.0:1.0)*par2+(1.0-par2);//bs2 + break; + case 10: + tmp=pow(5.0,par2*2.0-1.0); + tmp=pow(i/32.0,tmp)*32.0; + if (Pfilterpar2==64) tmp=i; + gain=cos(par*par*PI/2.0*tmp);//cos + gain*=gain; + break; + case 11: + tmp=pow(5.0,par2*2.0-1.0); + tmp=pow(i/32.0,tmp)*32.0; + if (Pfilterpar2==64) tmp=i; + gain=sin(par*par*PI/2.0*tmp);//sin + gain*=gain; + break; + case 12: + p2=1.0-par+0.2; + x=i/(64.0*p2*p2); + if (x<0.0) x=0.0; + else if (x>1.0) x=1.0; + tmp=pow(1.0-par2,2.0); + gain=cos(x*PI)*(1.0-tmp)+1.01+tmp;//low shelf + break; + case 13: + tmp=(int) (pow(2.0,(1.0-par)*7.2)); + gain=1.0; + if (i==(int) (tmp)) gain=pow(2.0,par2*par2*8.0); + break; + }; + + + oscilFFTfreqs.s[i]*=gain; + oscilFFTfreqs.c[i]*=gain; + REALTYPE tmp=oscilFFTfreqs.s[i]*oscilFFTfreqs.s[i]+ + oscilFFTfreqs.c[i]*oscilFFTfreqs.c[i]; + if (max<tmp) max=tmp; }; max=sqrt(max); if (max<1e-10) max=1.0; REALTYPE imax=1.0/max; for (int i=1;i<OSCIL_SIZE/2;i++) { - oscilFFTfreqs.s[i]*=imax; - oscilFFTfreqs.c[i]*=imax; + oscilFFTfreqs.s[i]*=imax; + oscilFFTfreqs.c[i]*=imax; }; }; - -/* + +/* * Change the base function */ -void OscilGen::changebasefunction(){ +void OscilGen::changebasefunction() +{ if (Pcurrentbasefunc!=0) { getbasefunction(tmpsmps); - fft->smps2freqs(tmpsmps,basefuncFFTfreqs); - basefuncFFTfreqs.c[0]=0.0; + fft->smps2freqs(tmpsmps,basefuncFFTfreqs); + basefuncFFTfreqs.c[0]=0.0; } else { - for (int i=0;i<OSCIL_SIZE/2;i++){ - basefuncFFTfreqs.s[i]=0.0; - basefuncFFTfreqs.c[i]=0.0; - }; - //in this case basefuncFFTfreqs_ are not used + for (int i=0;i<OSCIL_SIZE/2;i++) { + basefuncFFTfreqs.s[i]=0.0; + basefuncFFTfreqs.c[i]=0.0; + }; + //in this case basefuncFFTfreqs_ are not used } oscilprepared=0; oldbasefunc=Pcurrentbasefunc; @@ -441,10 +508,11 @@ void OscilGen::changebasefunction(){ oldbasefuncmodulationpar3=Pbasefuncmodulationpar3; }; -/* +/* * Waveshape */ -void OscilGen::waveshape(){ +void OscilGen::waveshape() +{ int i; oldwaveshapingfunction=Pwaveshapingfunction; @@ -454,30 +522,32 @@ void OscilGen::waveshape(){ oscilFFTfreqs.c[0]=0.0;//remove the DC //reduce the amplitude of the freqs near the nyquist for (i=1;i<OSCIL_SIZE/8;i++) { - REALTYPE tmp=i/(OSCIL_SIZE/8.0); - oscilFFTfreqs.s[OSCIL_SIZE/2-i]*=tmp; - oscilFFTfreqs.c[OSCIL_SIZE/2-i]*=tmp; + REALTYPE tmp=i/(OSCIL_SIZE/8.0); + oscilFFTfreqs.s[OSCIL_SIZE/2-i]*=tmp; + oscilFFTfreqs.c[OSCIL_SIZE/2-i]*=tmp; }; - fft->freqs2smps(oscilFFTfreqs,tmpsmps); + fft->freqs2smps(oscilFFTfreqs,tmpsmps); //Normalize REALTYPE max=0.0; - for (i=0;i<OSCIL_SIZE;i++) - if (max<fabs(tmpsmps[i])) max=fabs(tmpsmps[i]); + for (i=0;i<OSCIL_SIZE;i++) + if (max<fabs(tmpsmps[i])) max=fabs(tmpsmps[i]); if (max<0.00001) max=1.0; - max=1.0/max;for (i=0;i<OSCIL_SIZE;i++) tmpsmps[i]*=max; - + max=1.0/max; + for (i=0;i<OSCIL_SIZE;i++) tmpsmps[i]*=max; + //Do the waveshaping waveshapesmps(OSCIL_SIZE,tmpsmps,Pwaveshapingfunction,Pwaveshaping); - + fft->smps2freqs(tmpsmps,oscilFFTfreqs);//perform FFT }; -/* +/* * Do the Frequency Modulation of the Oscil */ -void OscilGen::modulation(){ +void OscilGen::modulation() +{ int i; oldmodulation=Pmodulation; @@ -488,28 +558,31 @@ void OscilGen::modulation(){ REALTYPE modulationpar1=Pmodulationpar1/127.0, - modulationpar2=0.5-Pmodulationpar2/127.0, - modulationpar3=Pmodulationpar3/127.0; - - switch(Pmodulation){ - case 1:modulationpar1=(pow(2,modulationpar1*7.0)-1.0)/100.0; - modulationpar3=floor((pow(2,modulationpar3*5.0)-1.0)); - if (modulationpar3<0.9999) modulationpar3=-1.0; - break; - case 2:modulationpar1=(pow(2,modulationpar1*7.0)-1.0)/100.0; - modulationpar3=1.0+floor((pow(2,modulationpar3*5.0)-1.0)); - break; - case 3:modulationpar1=(pow(2,modulationpar1*9.0)-1.0)/100.0; - modulationpar3=0.01+(pow(2,modulationpar3*16.0)-1.0)/10.0; - break; - }; + modulationpar2=0.5-Pmodulationpar2/127.0, + modulationpar3=Pmodulationpar3/127.0; + + switch (Pmodulation) { + case 1: + modulationpar1=(pow(2,modulationpar1*7.0)-1.0)/100.0; + modulationpar3=floor((pow(2,modulationpar3*5.0)-1.0)); + if (modulationpar3<0.9999) modulationpar3=-1.0; + break; + case 2: + modulationpar1=(pow(2,modulationpar1*7.0)-1.0)/100.0; + modulationpar3=1.0+floor((pow(2,modulationpar3*5.0)-1.0)); + break; + case 3: + modulationpar1=(pow(2,modulationpar1*9.0)-1.0)/100.0; + modulationpar3=0.01+(pow(2,modulationpar3*16.0)-1.0)/10.0; + break; + }; oscilFFTfreqs.c[0]=0.0;//remove the DC //reduce the amplitude of the freqs near the nyquist for (i=1;i<OSCIL_SIZE/8;i++) { - REALTYPE tmp=i/(OSCIL_SIZE/8.0); - oscilFFTfreqs.s[OSCIL_SIZE/2-i]*=tmp; - oscilFFTfreqs.c[OSCIL_SIZE/2-i]*=tmp; + REALTYPE tmp=i/(OSCIL_SIZE/8.0); + oscilFFTfreqs.s[OSCIL_SIZE/2-i]*=tmp; + oscilFFTfreqs.c[OSCIL_SIZE/2-i]*=tmp; }; fft->freqs2smps(oscilFFTfreqs,tmpsmps); int extra_points=2; @@ -519,28 +592,32 @@ void OscilGen::modulation(){ REALTYPE max=0.0; for (i=0;i<OSCIL_SIZE;i++) if (max<fabs(tmpsmps[i])) max=fabs(tmpsmps[i]); if (max<0.00001) max=1.0; - max=1.0/max;for (i=0;i<OSCIL_SIZE;i++) in[i]=tmpsmps[i]*max; + max=1.0/max; + for (i=0;i<OSCIL_SIZE;i++) in[i]=tmpsmps[i]*max; for (i=0;i<extra_points;i++) in[i+OSCIL_SIZE]=tmpsmps[i]*max; - + //Do the modulation for (i=0;i<OSCIL_SIZE;i++) { - REALTYPE t=i*1.0/OSCIL_SIZE; - - switch(Pmodulation){ - case 1:t=t*modulationpar3+sin((t+modulationpar2)*2.0*PI)*modulationpar1;//rev - break; - case 2:t=t+sin((t*modulationpar3+modulationpar2)*2.0*PI)*modulationpar1;//sine - break; - case 3:t=t+pow((1.0-cos((t+modulationpar2)*2.0*PI))*0.5,modulationpar3)*modulationpar1;//power - break; - }; - - t=(t-floor(t))*OSCIL_SIZE; - - int poshi=(int) t; - REALTYPE poslo=t-floor(t); - - tmpsmps[i]=in[poshi]*(1.0-poslo)+in[poshi+1]*poslo; + REALTYPE t=i*1.0/OSCIL_SIZE; + + switch (Pmodulation) { + case 1: + t=t*modulationpar3+sin((t+modulationpar2)*2.0*PI)*modulationpar1;//rev + break; + case 2: + t=t+sin((t*modulationpar3+modulationpar2)*2.0*PI)*modulationpar1;//sine + break; + case 3: + t=t+pow((1.0-cos((t+modulationpar2)*2.0*PI))*0.5,modulationpar3)*modulationpar1;//power + break; + }; + + t=(t-floor(t))*OSCIL_SIZE; + + int poshi=(int) t; + REALTYPE poslo=t-floor(t); + + tmpsmps[i]=in[poshi]*(1.0-poslo)+in[poshi+1]*poslo; }; delete [] in; @@ -549,267 +626,291 @@ void OscilGen::modulation(){ -/* +/* * Adjust the spectrum */ -void OscilGen::spectrumadjust(){ +void OscilGen::spectrumadjust() +{ if (Psatype==0) return; REALTYPE par=Psapar/127.0; - switch(Psatype){ - case 1: par=1.0-par*2.0; - if (par>=0.0) par=pow(5.0,par); - else par=pow(8.0,par); - break; - case 2: par=pow(10.0,(1.0-par)*3.0)*0.25; - break; - case 3: par=pow(10.0,(1.0-par)*3.0)*0.25; - break; + switch (Psatype) { + case 1: + par=1.0-par*2.0; + if (par>=0.0) par=pow(5.0,par); + else par=pow(8.0,par); + break; + case 2: + par=pow(10.0,(1.0-par)*3.0)*0.25; + break; + case 3: + par=pow(10.0,(1.0-par)*3.0)*0.25; + break; }; REALTYPE max=0.0; - for (int i=0;i<OSCIL_SIZE/2;i++){ - REALTYPE tmp=pow(oscilFFTfreqs.c[i],2)+pow(oscilFFTfreqs.s[i],2.0); - if (max<tmp) max=tmp; + for (int i=0;i<OSCIL_SIZE/2;i++) { + REALTYPE tmp=pow(oscilFFTfreqs.c[i],2)+pow(oscilFFTfreqs.s[i],2.0); + if (max<tmp) max=tmp; }; max=sqrt(max)/OSCIL_SIZE*2.0; if (max<1e-8) max=1.0; - - for (int i=0;i<OSCIL_SIZE/2;i++){ + + for (int i=0;i<OSCIL_SIZE/2;i++) { REALTYPE mag=sqrt(pow(oscilFFTfreqs.s[i],2)+pow(oscilFFTfreqs.c[i],2.0))/max; - REALTYPE phase=atan2(oscilFFTfreqs.s[i],oscilFFTfreqs.c[i]); - - switch (Psatype){ - case 1: mag=pow(mag,par); - break; - case 2: if (mag<par) mag=0.0; - break; - case 3: mag/=par; - if (mag>1.0) mag=1.0; - break; - }; - oscilFFTfreqs.c[i]=mag*cos(phase); - oscilFFTfreqs.s[i]=mag*sin(phase); + REALTYPE phase=atan2(oscilFFTfreqs.s[i],oscilFFTfreqs.c[i]); + + switch (Psatype) { + case 1: + mag=pow(mag,par); + break; + case 2: + if (mag<par) mag=0.0; + break; + case 3: + mag/=par; + if (mag>1.0) mag=1.0; + break; + }; + oscilFFTfreqs.c[i]=mag*cos(phase); + oscilFFTfreqs.s[i]=mag*sin(phase); }; - + }; -void OscilGen::shiftharmonics(){ +void OscilGen::shiftharmonics() +{ if (Pharmonicshift==0) return; - + REALTYPE hc,hs; int harmonicshift=-Pharmonicshift; - - if (harmonicshift>0){ - for (int i=OSCIL_SIZE/2-2;i>=0;i--){ - int oldh=i-harmonicshift; - if (oldh<0){ - hc=0.0; - hs=0.0; - } else { - hc=oscilFFTfreqs.c[oldh+1]; - hs=oscilFFTfreqs.s[oldh+1]; - }; - oscilFFTfreqs.c[i+1]=hc; - oscilFFTfreqs.s[i+1]=hs; - }; + + if (harmonicshift>0) { + for (int i=OSCIL_SIZE/2-2;i>=0;i--) { + int oldh=i-harmonicshift; + if (oldh<0) { + hc=0.0; + hs=0.0; + } else { + hc=oscilFFTfreqs.c[oldh+1]; + hs=oscilFFTfreqs.s[oldh+1]; + }; + oscilFFTfreqs.c[i+1]=hc; + oscilFFTfreqs.s[i+1]=hs; + }; } else { - for (int i=0;i<OSCIL_SIZE/2-1;i++){ - int oldh=i+abs(harmonicshift); - if (oldh>=(OSCIL_SIZE/2-1)){ - hc=0.0; - hs=0.0; - } else { - hc=oscilFFTfreqs.c[oldh+1]; - hs=oscilFFTfreqs.s[oldh+1]; - if (fabs(hc)<0.000001) hc=0.0; - if (fabs(hs)<0.000001) hs=0.0; - }; - - oscilFFTfreqs.c[i+1]=hc; - oscilFFTfreqs.s[i+1]=hs; - }; + for (int i=0;i<OSCIL_SIZE/2-1;i++) { + int oldh=i+abs(harmonicshift); + if (oldh>=(OSCIL_SIZE/2-1)) { + hc=0.0; + hs=0.0; + } else { + hc=oscilFFTfreqs.c[oldh+1]; + hs=oscilFFTfreqs.s[oldh+1]; + if (fabs(hc)<0.000001) hc=0.0; + if (fabs(hs)<0.000001) hs=0.0; + }; + + oscilFFTfreqs.c[i+1]=hc; + oscilFFTfreqs.s[i+1]=hs; + }; }; - + oscilFFTfreqs.c[0]=0.0; }; -/* +/* * Prepare the Oscillator */ -void OscilGen::prepare(){ - int i,j,k; - REALTYPE a,b,c,d,hmagnew; - - if ((oldbasepar!=Pbasefuncpar)||(oldbasefunc!=Pcurrentbasefunc)|| - (oldbasefuncmodulation!=Pbasefuncmodulation)|| - (oldbasefuncmodulationpar1!=Pbasefuncmodulationpar1)|| - (oldbasefuncmodulationpar2!=Pbasefuncmodulationpar2)|| - (oldbasefuncmodulationpar3!=Pbasefuncmodulationpar3)) - changebasefunction(); - - for (i=0;i<MAX_AD_HARMONICS;i++) hphase[i]=(Phphase[i]-64.0)/64.0*PI/(i+1); - - for (i=0;i<MAX_AD_HARMONICS;i++){ - hmagnew=1.0-fabs(Phmag[i]/64.0-1.0); - switch(Phmagtype){ - case 1:hmag[i]=exp(hmagnew*log(0.01)); break; - case 2:hmag[i]=exp(hmagnew*log(0.001));break; - case 3:hmag[i]=exp(hmagnew*log(0.0001));break; - case 4:hmag[i]=exp(hmagnew*log(0.00001));break; - default:hmag[i]=1.0-hmagnew; - break; - }; - - if (Phmag[i]<64) hmag[i]=-hmag[i]; - }; - - //remove the harmonics where Phmag[i]==64 - for (i=0;i<MAX_AD_HARMONICS;i++) if (Phmag[i]==64) hmag[i]=0.0; - - - for (i=0;i<OSCIL_SIZE/2;i++) { - oscilFFTfreqs.c[i]=0.0; - oscilFFTfreqs.s[i]=0.0; - }; - if (Pcurrentbasefunc==0) {//the sine case - for (i=0;i<MAX_AD_HARMONICS;i++){ - oscilFFTfreqs.c[i+1]=-hmag[i]*sin(hphase[i]*(i+1))/2.0; - oscilFFTfreqs.s[i+1]=hmag[i]*cos(hphase[i]*(i+1))/2.0; - }; - } else { - for (j=0;j<MAX_AD_HARMONICS;j++){ - if (Phmag[j]==64) continue; - for (i=1;i<OSCIL_SIZE/2;i++){ - k=i*(j+1);if (k>=OSCIL_SIZE/2) break; - a=basefuncFFTfreqs.c[i]; - b=basefuncFFTfreqs.s[i]; - c=hmag[j]*cos(hphase[j]*k); - d=hmag[j]*sin(hphase[j]*k); - oscilFFTfreqs.c[k]+=a*c-b*d; - oscilFFTfreqs.s[k]+=a*d+b*c; - }; - }; - - }; - - if (Pharmonicshiftfirst!=0) shiftharmonics(); - - - - if (Pfilterbeforews==0){ +void OscilGen::prepare() +{ + int i,j,k; + REALTYPE a,b,c,d,hmagnew; + + if ((oldbasepar!=Pbasefuncpar)||(oldbasefunc!=Pcurrentbasefunc)|| + (oldbasefuncmodulation!=Pbasefuncmodulation)|| + (oldbasefuncmodulationpar1!=Pbasefuncmodulationpar1)|| + (oldbasefuncmodulationpar2!=Pbasefuncmodulationpar2)|| + (oldbasefuncmodulationpar3!=Pbasefuncmodulationpar3)) + changebasefunction(); + + for (i=0;i<MAX_AD_HARMONICS;i++) hphase[i]=(Phphase[i]-64.0)/64.0*PI/(i+1); + + for (i=0;i<MAX_AD_HARMONICS;i++) { + hmagnew=1.0-fabs(Phmag[i]/64.0-1.0); + switch (Phmagtype) { + case 1: + hmag[i]=exp(hmagnew*log(0.01)); + break; + case 2: + hmag[i]=exp(hmagnew*log(0.001)); + break; + case 3: + hmag[i]=exp(hmagnew*log(0.0001)); + break; + case 4: + hmag[i]=exp(hmagnew*log(0.00001)); + break; + default: + hmag[i]=1.0-hmagnew; + break; + }; + + if (Phmag[i]<64) hmag[i]=-hmag[i]; + }; + + //remove the harmonics where Phmag[i]==64 + for (i=0;i<MAX_AD_HARMONICS;i++) if (Phmag[i]==64) hmag[i]=0.0; + + + for (i=0;i<OSCIL_SIZE/2;i++) { + oscilFFTfreqs.c[i]=0.0; + oscilFFTfreqs.s[i]=0.0; + }; + if (Pcurrentbasefunc==0) {//the sine case + for (i=0;i<MAX_AD_HARMONICS;i++) { + oscilFFTfreqs.c[i+1]=-hmag[i]*sin(hphase[i]*(i+1))/2.0; + oscilFFTfreqs.s[i+1]=hmag[i]*cos(hphase[i]*(i+1))/2.0; + }; + } else { + for (j=0;j<MAX_AD_HARMONICS;j++) { + if (Phmag[j]==64) continue; + for (i=1;i<OSCIL_SIZE/2;i++) { + k=i*(j+1); + if (k>=OSCIL_SIZE/2) break; + a=basefuncFFTfreqs.c[i]; + b=basefuncFFTfreqs.s[i]; + c=hmag[j]*cos(hphase[j]*k); + d=hmag[j]*sin(hphase[j]*k); + oscilFFTfreqs.c[k]+=a*c-b*d; + oscilFFTfreqs.s[k]+=a*d+b*c; + }; + }; + + }; + + if (Pharmonicshiftfirst!=0) shiftharmonics(); + + + + if (Pfilterbeforews==0) { waveshape(); - oscilfilter(); + oscilfilter(); } else { - oscilfilter(); + oscilfilter(); waveshape(); }; - modulation(); - spectrumadjust(); - if (Pharmonicshiftfirst==0) shiftharmonics(); + modulation(); + spectrumadjust(); + if (Pharmonicshiftfirst==0) shiftharmonics(); - oscilFFTfreqs.c[0]=0.0; + oscilFFTfreqs.c[0]=0.0; - oldhmagtype=Phmagtype; - oldharmonicshift=Pharmonicshift+Pharmonicshiftfirst*256; + oldhmagtype=Phmagtype; + oldharmonicshift=Pharmonicshift+Pharmonicshiftfirst*256; - oscilprepared=1; + oscilprepared=1; }; -void OscilGen::adaptiveharmonic(FFTFREQS f,REALTYPE freq){ - if ((Padaptiveharmonics==0)/*||(freq<1.0)*/) return; - if (freq<1.0) freq=440.0; - - FFTFREQS inf; - newFFTFREQS(&inf,OSCIL_SIZE/2); - for (int i=0;i<OSCIL_SIZE/2;i++) { - inf.s[i]=f.s[i]; - inf.c[i]=f.c[i]; - f.s[i]=0.0; - f.c[i]=0.0; - }; - inf.c[0]=0.0;inf.s[0]=0.0; - - REALTYPE hc=0.0,hs=0.0; - REALTYPE basefreq=30.0*pow(10.0,Padaptiveharmonicsbasefreq/128.0); - REALTYPE power=(Padaptiveharmonicspower+1.0)/101.0; - - REALTYPE rap=freq/basefreq; - - rap=pow(rap,power); - - bool down=false; - if (rap>1.0) { - rap=1.0/rap; - down=true; - }; - - for (int i=0;i<OSCIL_SIZE/2-2;i++){ - REALTYPE h=i*rap; - int high=(int)(i*rap); - REALTYPE low=fmod(h,1.0); - - if (high>=(OSCIL_SIZE/2-2)){ - break; - } else { - if (down){ - f.c[high]+=inf.c[i]*(1.0-low); - f.s[high]+=inf.s[i]*(1.0-low); - f.c[high+1]+=inf.c[i]*low; - f.s[high+1]+=inf.s[i]*low; - } else { - hc=inf.c[high]*(1.0-low)+inf.c[high+1]*low; - hs=inf.s[high]*(1.0-low)+inf.s[high+1]*low; - }; - if (fabs(hc)<0.000001) hc=0.0; - if (fabs(hs)<0.000001) hs=0.0; - }; - - if (!down){ - if (i==0) {//corect the aplitude of the first harmonic - hc*=rap; - hs*=rap; - }; - f.c[i]=hc; - f.s[i]=hs; - }; - }; - - f.c[1]+=f.c[0];f.s[1]+=f.s[0]; - f.c[0]=0.0;f.s[0]=0.0; - deleteFFTFREQS(&inf); +void OscilGen::adaptiveharmonic(FFTFREQS f,REALTYPE freq) +{ + if ((Padaptiveharmonics==0)/*||(freq<1.0)*/) return; + if (freq<1.0) freq=440.0; + + FFTFREQS inf; + newFFTFREQS(&inf,OSCIL_SIZE/2); + for (int i=0;i<OSCIL_SIZE/2;i++) { + inf.s[i]=f.s[i]; + inf.c[i]=f.c[i]; + f.s[i]=0.0; + f.c[i]=0.0; + }; + inf.c[0]=0.0; + inf.s[0]=0.0; + + REALTYPE hc=0.0,hs=0.0; + REALTYPE basefreq=30.0*pow(10.0,Padaptiveharmonicsbasefreq/128.0); + REALTYPE power=(Padaptiveharmonicspower+1.0)/101.0; + + REALTYPE rap=freq/basefreq; + + rap=pow(rap,power); + + bool down=false; + if (rap>1.0) { + rap=1.0/rap; + down=true; + }; + + for (int i=0;i<OSCIL_SIZE/2-2;i++) { + REALTYPE h=i*rap; + int high=(int)(i*rap); + REALTYPE low=fmod(h,1.0); + + if (high>=(OSCIL_SIZE/2-2)) { + break; + } else { + if (down) { + f.c[high]+=inf.c[i]*(1.0-low); + f.s[high]+=inf.s[i]*(1.0-low); + f.c[high+1]+=inf.c[i]*low; + f.s[high+1]+=inf.s[i]*low; + } else { + hc=inf.c[high]*(1.0-low)+inf.c[high+1]*low; + hs=inf.s[high]*(1.0-low)+inf.s[high+1]*low; + }; + if (fabs(hc)<0.000001) hc=0.0; + if (fabs(hs)<0.000001) hs=0.0; + }; + + if (!down) { + if (i==0) {//corect the aplitude of the first harmonic + hc*=rap; + hs*=rap; + }; + f.c[i]=hc; + f.s[i]=hs; + }; + }; + + f.c[1]+=f.c[0]; + f.s[1]+=f.s[0]; + f.c[0]=0.0; + f.s[0]=0.0; + deleteFFTFREQS(&inf); }; -void OscilGen::adaptiveharmonicpostprocess(REALTYPE *f,int size){ +void OscilGen::adaptiveharmonicpostprocess(REALTYPE *f,int size) +{ if (Padaptiveharmonics<=1) return; REALTYPE *inf=new REALTYPE[size]; REALTYPE par=Padaptiveharmonicspar*0.01; par=1.0-pow((1.0-par),1.5); - + for (int i=0;i<size;i++) { - inf[i]=f[i]*par; - f[i]=f[i]*(1.0-par); + inf[i]=f[i]*par; + f[i]=f[i]*(1.0-par); }; - - if (Padaptiveharmonics==2){//2n+1 + + if (Padaptiveharmonics==2) {//2n+1 for (int i=0;i<size;i++) if ((i%2)==0) f[i]+=inf[i];//i=0 pt prima armonica,etc. - } else{//celelalte moduri + } else {//celelalte moduri int nh=(Padaptiveharmonics-3)/2+2; int sub_vs_add=(Padaptiveharmonics-3)%2; - if (sub_vs_add==0){ - for (int i=0;i<size;i++) { - if (((i+1)%nh)==0){ - f[i]+=inf[i]; - }; - }; + if (sub_vs_add==0) { + for (int i=0;i<size;i++) { + if (((i+1)%nh)==0) { + f[i]+=inf[i]; + }; + }; } else { - for (int i=0;i<size/nh-1;i++) { - f[(i+1)*nh-1]+=inf[i]; - }; - }; + for (int i=0;i<size/nh-1;i++) { + f[(i+1)*nh-1]+=inf[i]; + }; + }; }; delete(inf); @@ -817,67 +918,70 @@ void OscilGen::adaptiveharmonicpostprocess(REALTYPE *f,int size){ -/* +/* * Get the oscillator function */ -short int OscilGen::get(REALTYPE *smps,REALTYPE freqHz){ +short int OscilGen::get(REALTYPE *smps,REALTYPE freqHz) +{ return(this->get(smps,freqHz,0)); }; -void OscilGen::newrandseed(unsigned int randseed){ +void OscilGen::newrandseed(unsigned int randseed) +{ this->randseed=randseed; }; -/* +/* * Get the oscillator function */ -short int OscilGen::get(REALTYPE *smps,REALTYPE freqHz,int resonance){ +short int OscilGen::get(REALTYPE *smps,REALTYPE freqHz,int resonance) +{ int i; int nyquist,outpos; - + if ((oldbasepar!=Pbasefuncpar)||(oldbasefunc!=Pcurrentbasefunc)||(oldhmagtype!=Phmagtype) - ||(oldwaveshaping!=Pwaveshaping)||(oldwaveshapingfunction!=Pwaveshapingfunction)) oscilprepared=0; - if (oldfilterpars!=Pfiltertype*256+Pfilterpar1+Pfilterpar2*65536+Pfilterbeforews*16777216){ - oscilprepared=0; - oldfilterpars=Pfiltertype*256+Pfilterpar1+Pfilterpar2*65536+Pfilterbeforews*16777216; + ||(oldwaveshaping!=Pwaveshaping)||(oldwaveshapingfunction!=Pwaveshapingfunction)) oscilprepared=0; + if (oldfilterpars!=Pfiltertype*256+Pfilterpar1+Pfilterpar2*65536+Pfilterbeforews*16777216) { + oscilprepared=0; + oldfilterpars=Pfiltertype*256+Pfilterpar1+Pfilterpar2*65536+Pfilterbeforews*16777216; }; - if (oldsapars!=Psatype*256+Psapar){ - oscilprepared=0; - oldsapars=Psatype*256+Psapar; + if (oldsapars!=Psatype*256+Psapar) { + oscilprepared=0; + oldsapars=Psatype*256+Psapar; }; if ((oldbasefuncmodulation!=Pbasefuncmodulation)|| - (oldbasefuncmodulationpar1!=Pbasefuncmodulationpar1)|| - (oldbasefuncmodulationpar2!=Pbasefuncmodulationpar2)|| - (oldbasefuncmodulationpar3!=Pbasefuncmodulationpar3)) - oscilprepared=0; + (oldbasefuncmodulationpar1!=Pbasefuncmodulationpar1)|| + (oldbasefuncmodulationpar2!=Pbasefuncmodulationpar2)|| + (oldbasefuncmodulationpar3!=Pbasefuncmodulationpar3)) + oscilprepared=0; if ((oldmodulation!=Pmodulation)|| - (oldmodulationpar1!=Pmodulationpar1)|| - (oldmodulationpar2!=Pmodulationpar2)|| - (oldmodulationpar3!=Pmodulationpar3)) - oscilprepared=0; + (oldmodulationpar1!=Pmodulationpar1)|| + (oldmodulationpar2!=Pmodulationpar2)|| + (oldmodulationpar3!=Pmodulationpar3)) + oscilprepared=0; if (oldharmonicshift!=Pharmonicshift+Pharmonicshiftfirst*256) oscilprepared=0; - + if (oscilprepared!=1) prepare(); outpos=(int)((RND*2.0-1.0)*(REALTYPE) OSCIL_SIZE*(Prand-64.0)/64.0); outpos=(outpos+2*OSCIL_SIZE) % OSCIL_SIZE; - for (i=0;i<OSCIL_SIZE/2;i++){ - outoscilFFTfreqs.c[i]=0.0; - outoscilFFTfreqs.s[i]=0.0; + for (i=0;i<OSCIL_SIZE/2;i++) { + outoscilFFTfreqs.c[i]=0.0; + outoscilFFTfreqs.s[i]=0.0; }; nyquist=(int)(0.5*SAMPLE_RATE/fabs(freqHz))+2; if (ADvsPAD) nyquist=(int)(OSCIL_SIZE/2); if (nyquist>OSCIL_SIZE/2) nyquist=OSCIL_SIZE/2; - - + + int realnyquist=nyquist; - + if (Padaptiveharmonics!=0) nyquist=OSCIL_SIZE/2; for (i=1;i<nyquist-1;i++) { outoscilFFTfreqs.c[i]=oscilFFTfreqs.c[i]; @@ -889,55 +993,57 @@ short int OscilGen::get(REALTYPE *smps,REALTYPE freqHz,int resonance){ adaptiveharmonicpostprocess(&outoscilFFTfreqs.s[1],OSCIL_SIZE/2-1); nyquist=realnyquist; - if (Padaptiveharmonics){//do the antialiasing in the case of adaptive harmonics + if (Padaptiveharmonics) {//do the antialiasing in the case of adaptive harmonics for (i=nyquist;i<OSCIL_SIZE/2;i++) { - outoscilFFTfreqs.s[i]=0; - outoscilFFTfreqs.c[i]=0; - }; + outoscilFFTfreqs.s[i]=0; + outoscilFFTfreqs.c[i]=0; + }; }; - // Randomness (each harmonic), the block type is computed + // Randomness (each harmonic), the block type is computed // in ADnote by setting start position according to this setting - if ((Prand>64)&&(freqHz>=0.0)&&(!ADvsPAD)){ + if ((Prand>64)&&(freqHz>=0.0)&&(!ADvsPAD)) { REALTYPE rnd,angle,a,b,c,d; rnd=PI*pow((Prand-64.0)/64.0,2.0); - for (i=1;i<nyquist-1;i++){//to Nyquist only for AntiAliasing - angle=rnd*i*RND; - a=outoscilFFTfreqs.c[i]; - b=outoscilFFTfreqs.s[i]; - c=cos(angle); - d=sin(angle); - outoscilFFTfreqs.c[i]=a*c-b*d; - outoscilFFTfreqs.s[i]=a*d+b*c; - }; + for (i=1;i<nyquist-1;i++) {//to Nyquist only for AntiAliasing + angle=rnd*i*RND; + a=outoscilFFTfreqs.c[i]; + b=outoscilFFTfreqs.s[i]; + c=cos(angle); + d=sin(angle); + outoscilFFTfreqs.c[i]=a*c-b*d; + outoscilFFTfreqs.s[i]=a*d+b*c; + }; }; //Harmonic Amplitude Randomness if ((freqHz>0.1)&&(!ADvsPAD)) { - unsigned int realrnd=rand(); - srand(randseed); - REALTYPE power=Pamprandpower/127.0; - REALTYPE normalize=1.0/(1.2-power); - switch (Pamprandtype){ - case 1: power=power*2.0-0.5; - power=pow(15.0,power); - for (i=1;i<nyquist-1;i++){ - REALTYPE amp=pow(RND,power)*normalize; - outoscilFFTfreqs.c[i]*=amp; - outoscilFFTfreqs.s[i]*=amp; - }; - break; - case 2: power=power*2.0-0.5; - power=pow(15.0,power)*2.0; - REALTYPE rndfreq=2*PI*RND; - for (i=1;i<nyquist-1;i++){ - REALTYPE amp=pow(fabs(sin(i*rndfreq)),power)*normalize; - outoscilFFTfreqs.c[i]*=amp; - outoscilFFTfreqs.s[i]*=amp; - }; - break; - }; - srand(realrnd+1); + unsigned int realrnd=rand(); + srand(randseed); + REALTYPE power=Pamprandpower/127.0; + REALTYPE normalize=1.0/(1.2-power); + switch (Pamprandtype) { + case 1: + power=power*2.0-0.5; + power=pow(15.0,power); + for (i=1;i<nyquist-1;i++) { + REALTYPE amp=pow(RND,power)*normalize; + outoscilFFTfreqs.c[i]*=amp; + outoscilFFTfreqs.s[i]*=amp; + }; + break; + case 2: + power=power*2.0-0.5; + power=pow(15.0,power)*2.0; + REALTYPE rndfreq=2*PI*RND; + for (i=1;i<nyquist-1;i++) { + REALTYPE amp=pow(fabs(sin(i*rndfreq)),power)*normalize; + outoscilFFTfreqs.c[i]*=amp; + outoscilFFTfreqs.s[i]*=amp; + }; + break; + }; + srand(realrnd+1); }; if ((freqHz>0.1)&&(resonance!=0)) res->applyres(nyquist-1,outoscilFFTfreqs,freqHz); @@ -946,85 +1052,89 @@ short int OscilGen::get(REALTYPE *smps,REALTYPE freqHz,int resonance){ REALTYPE sum=0; for (int j=1;j<OSCIL_SIZE/2;j++) { REALTYPE term=outoscilFFTfreqs.c[j]*outoscilFFTfreqs.c[j] - +outoscilFFTfreqs.s[j]*outoscilFFTfreqs.s[j]; + +outoscilFFTfreqs.s[j]*outoscilFFTfreqs.s[j]; sum+=term; }; - if (sum<0.000001) sum=1.0; + if (sum<0.000001) sum=1.0; sum=1.0/sqrt(sum); for (int j=1;j<OSCIL_SIZE/2;j++) { - outoscilFFTfreqs.c[j]*=sum; - outoscilFFTfreqs.s[j]*=sum; + outoscilFFTfreqs.c[j]*=sum; + outoscilFFTfreqs.s[j]*=sum; }; - - if ((ADvsPAD)&&(freqHz>0.1)){//in this case the smps will contain the freqs + + if ((ADvsPAD)&&(freqHz>0.1)) {//in this case the smps will contain the freqs for (i=1;i<OSCIL_SIZE/2;i++) smps[i-1]=sqrt(outoscilFFTfreqs.c[i]*outoscilFFTfreqs.c[i] - +outoscilFFTfreqs.s[i]*outoscilFFTfreqs.s[i]); + +outoscilFFTfreqs.s[i]*outoscilFFTfreqs.s[i]); } else { - fft->freqs2smps(outoscilFFTfreqs,smps); + fft->freqs2smps(outoscilFFTfreqs,smps); for (i=0;i<OSCIL_SIZE;i++) smps[i]*=0.25;//correct the amplitude }; if (Prand<64) return(outpos); - else return(0); + else return(0); }; -/* +/* * Get the spectrum of the oscillator for the UI */ -void OscilGen::getspectrum(int n, REALTYPE *spc,int what){ +void OscilGen::getspectrum(int n, REALTYPE *spc,int what) +{ if (n>OSCIL_SIZE/2) n=OSCIL_SIZE/2; - for (int i=1;i<n;i++){ - if (what==0){ - spc[i-1]=sqrt(oscilFFTfreqs.c[i]*oscilFFTfreqs.c[i] - +oscilFFTfreqs.s[i]*oscilFFTfreqs.s[i]); - } else { - if (Pcurrentbasefunc==0) spc[i-1]=((i==1)?(1.0):(0.0)); - else spc[i-1]=sqrt(basefuncFFTfreqs.c[i]*basefuncFFTfreqs.c[i]+ - basefuncFFTfreqs.s[i]*basefuncFFTfreqs.s[i]); - }; + for (int i=1;i<n;i++) { + if (what==0) { + spc[i-1]=sqrt(oscilFFTfreqs.c[i]*oscilFFTfreqs.c[i] + +oscilFFTfreqs.s[i]*oscilFFTfreqs.s[i]); + } else { + if (Pcurrentbasefunc==0) spc[i-1]=((i==1)?(1.0):(0.0)); + else spc[i-1]=sqrt(basefuncFFTfreqs.c[i]*basefuncFFTfreqs.c[i]+ + basefuncFFTfreqs.s[i]*basefuncFFTfreqs.s[i]); + }; }; - + if (what==0) { for (int i=0;i<n;i++) outoscilFFTfreqs.s[i]=outoscilFFTfreqs.c[i]=spc[i]; - for (int i=n;i<OSCIL_SIZE/2;i++) outoscilFFTfreqs.s[i]=outoscilFFTfreqs.c[i]=0.0; - adaptiveharmonic(outoscilFFTfreqs,0.0); - for (int i=0;i<n;i++) spc[i]=outoscilFFTfreqs.s[i]; - adaptiveharmonicpostprocess(spc,n-1); + for (int i=n;i<OSCIL_SIZE/2;i++) outoscilFFTfreqs.s[i]=outoscilFFTfreqs.c[i]=0.0; + adaptiveharmonic(outoscilFFTfreqs,0.0); + for (int i=0;i<n;i++) spc[i]=outoscilFFTfreqs.s[i]; + adaptiveharmonicpostprocess(spc,n-1); }; }; -/* +/* * Convert the oscillator as base function */ -void OscilGen::useasbase(){ - int i; +void OscilGen::useasbase() +{ + int i; - for (i=0;i<OSCIL_SIZE/2;i++) { - basefuncFFTfreqs.c[i]=oscilFFTfreqs.c[i]; - basefuncFFTfreqs.s[i]=oscilFFTfreqs.s[i]; - }; + for (i=0;i<OSCIL_SIZE/2;i++) { + basefuncFFTfreqs.c[i]=oscilFFTfreqs.c[i]; + basefuncFFTfreqs.s[i]=oscilFFTfreqs.s[i]; + }; - oldbasefunc=Pcurrentbasefunc=127; + oldbasefunc=Pcurrentbasefunc=127; - prepare(); + prepare(); }; -/* +/* * Get the base function for UI */ -void OscilGen::getcurrentbasefunction(REALTYPE *smps){ +void OscilGen::getcurrentbasefunction(REALTYPE *smps) +{ if (Pcurrentbasefunc!=0) { - fft->freqs2smps(basefuncFFTfreqs,smps); + fft->freqs2smps(basefuncFFTfreqs,smps); } else getbasefunction(smps);//the sine case }; -void OscilGen::add2XML(XMLwrapper *xml){ +void OscilGen::add2XML(XMLwrapper *xml) +{ xml->addpar("harmonic_mag_type",Phmagtype); xml->addpar("base_function",Pcurrentbasefunc); @@ -1062,41 +1172,42 @@ void OscilGen::add2XML(XMLwrapper *xml){ xml->addpar("adaptive_harmonics_power",Padaptiveharmonicspower); xml->beginbranch("HARMONICS"); - for (int n=0;n<MAX_AD_HARMONICS;n++){ - if ((Phmag[n]==64)&&(Phphase[n]==64)) continue; - xml->beginbranch("HARMONIC",n+1); - xml->addpar("mag",Phmag[n]); - xml->addpar("phase",Phphase[n]); - xml->endbranch(); - }; + for (int n=0;n<MAX_AD_HARMONICS;n++) { + if ((Phmag[n]==64)&&(Phphase[n]==64)) continue; + xml->beginbranch("HARMONIC",n+1); + xml->addpar("mag",Phmag[n]); + xml->addpar("phase",Phphase[n]); + xml->endbranch(); + }; xml->endbranch(); - - if (Pcurrentbasefunc==127){ - REALTYPE max=0.0; - - for (int i=0;i<OSCIL_SIZE/2;i++){ - if (max<fabs(basefuncFFTfreqs.c[i])) max=fabs(basefuncFFTfreqs.c[i]); - if (max<fabs(basefuncFFTfreqs.s[i])) max=fabs(basefuncFFTfreqs.s[i]); - }; - if (max<0.00000001) max=1.0; - - xml->beginbranch("BASE_FUNCTION"); - for (int i=1;i<OSCIL_SIZE/2;i++){ - REALTYPE xc=basefuncFFTfreqs.c[i]/max; - REALTYPE xs=basefuncFFTfreqs.s[i]/max; - if ((fabs(xs)>0.00001)&&(fabs(xs)>0.00001)){ - xml->beginbranch("BF_HARMONIC",i); - xml->addparreal("cos",xc); - xml->addparreal("sin",xs); - xml->endbranch(); - }; - }; - xml->endbranch(); + + if (Pcurrentbasefunc==127) { + REALTYPE max=0.0; + + for (int i=0;i<OSCIL_SIZE/2;i++) { + if (max<fabs(basefuncFFTfreqs.c[i])) max=fabs(basefuncFFTfreqs.c[i]); + if (max<fabs(basefuncFFTfreqs.s[i])) max=fabs(basefuncFFTfreqs.s[i]); + }; + if (max<0.00000001) max=1.0; + + xml->beginbranch("BASE_FUNCTION"); + for (int i=1;i<OSCIL_SIZE/2;i++) { + REALTYPE xc=basefuncFFTfreqs.c[i]/max; + REALTYPE xs=basefuncFFTfreqs.s[i]/max; + if ((fabs(xs)>0.00001)&&(fabs(xs)>0.00001)) { + xml->beginbranch("BF_HARMONIC",i); + xml->addparreal("cos",xc); + xml->addparreal("sin",xs); + xml->endbranch(); + }; + }; + xml->endbranch(); }; }; -void OscilGen::getfromXML(XMLwrapper *xml){ +void OscilGen::getfromXML(XMLwrapper *xml) +{ Phmagtype=xml->getpar127("harmonic_mag_type",Phmagtype); @@ -1136,45 +1247,46 @@ void OscilGen::getfromXML(XMLwrapper *xml){ Padaptiveharmonicspower=xml->getpar("adaptive_harmonics_power",Padaptiveharmonicspower,0,200); - if (xml->enterbranch("HARMONICS")){ - Phmag[0]=64;Phphase[0]=64; - for (int n=0;n<MAX_AD_HARMONICS;n++){ - if (xml->enterbranch("HARMONIC",n+1)==0) continue; - Phmag[n]=xml->getpar127("mag",64); - Phphase[n]=xml->getpar127("phase",64); - xml->exitbranch(); - }; - xml->exitbranch(); + if (xml->enterbranch("HARMONICS")) { + Phmag[0]=64; + Phphase[0]=64; + for (int n=0;n<MAX_AD_HARMONICS;n++) { + if (xml->enterbranch("HARMONIC",n+1)==0) continue; + Phmag[n]=xml->getpar127("mag",64); + Phphase[n]=xml->getpar127("phase",64); + xml->exitbranch(); + }; + xml->exitbranch(); }; - + if (Pcurrentbasefunc!=0) changebasefunction(); - - - if (xml->enterbranch("BASE_FUNCTION")){ - for (int i=1;i<OSCIL_SIZE/2;i++){ - if (xml->enterbranch("BF_HARMONIC",i)){ - basefuncFFTfreqs.c[i]=xml->getparreal("cos",0.0); - basefuncFFTfreqs.s[i]=xml->getparreal("sin",0.0); - xml->exitbranch(); - }; - - - }; - xml->exitbranch(); - - REALTYPE max=0.0; - - basefuncFFTfreqs.c[0]=0.0; - for (int i=0;i<OSCIL_SIZE/2;i++) { - if (max<fabs(basefuncFFTfreqs.c[i])) max=fabs(basefuncFFTfreqs.c[i]); - if (max<fabs(basefuncFFTfreqs.s[i])) max=fabs(basefuncFFTfreqs.s[i]); - }; - if (max<0.00000001) max=1.0; - - for (int i=0;i<OSCIL_SIZE/2;i++) { - if (basefuncFFTfreqs.c[i]) basefuncFFTfreqs.c[i]/=max; - if (basefuncFFTfreqs.s[i]) basefuncFFTfreqs.s[i]/=max; - }; + + + if (xml->enterbranch("BASE_FUNCTION")) { + for (int i=1;i<OSCIL_SIZE/2;i++) { + if (xml->enterbranch("BF_HARMONIC",i)) { + basefuncFFTfreqs.c[i]=xml->getparreal("cos",0.0); + basefuncFFTfreqs.s[i]=xml->getparreal("sin",0.0); + xml->exitbranch(); + }; + + + }; + xml->exitbranch(); + + REALTYPE max=0.0; + + basefuncFFTfreqs.c[0]=0.0; + for (int i=0;i<OSCIL_SIZE/2;i++) { + if (max<fabs(basefuncFFTfreqs.c[i])) max=fabs(basefuncFFTfreqs.c[i]); + if (max<fabs(basefuncFFTfreqs.s[i])) max=fabs(basefuncFFTfreqs.s[i]); + }; + if (max<0.00000001) max=1.0; + + for (int i=0;i<OSCIL_SIZE/2;i++) { + if (basefuncFFTfreqs.c[i]) basefuncFFTfreqs.c[i]/=max; + if (basefuncFFTfreqs.s[i]) basefuncFFTfreqs.s[i]/=max; + }; }; }; diff --git a/src/Synth/OscilGen.h b/src/Synth/OscilGen.h @@ -6,7 +6,7 @@ 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 + 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, @@ -26,151 +26,152 @@ #include "../globals.h" #include "../Misc/XMLwrapper.h" #include "Resonance.h" -#include "../DSP/FFTwrapper.h" +#include "../DSP/FFTwrapper.h" #include "../Params/Presets.h" -class OscilGen:public Presets{ - public: - OscilGen(FFTwrapper *fft_,Resonance *res_); - ~OscilGen(); - - /**computes the full spectrum of oscil from harmonics,phases and basefunc*/ - void prepare(); - - /**do the antialiasing(cut off higher freqs.),apply randomness and do a IFFT*/ - short get(REALTYPE *smps,REALTYPE freqHz);//returns where should I start getting samples, used in block type randomness - short get(REALTYPE *smps,REALTYPE freqHz,int resonance); - //if freqHz is smaller than 0, return the "un-randomized" sample for UI - - void getbasefunction(REALTYPE *smps); - - //called by UI - void getspectrum(int n,REALTYPE *spc,int what);//what=0 pt. oscil,1 pt. basefunc - void getcurrentbasefunction(REALTYPE *smps); - /**convert oscil to base function*/ - void useasbase(); - - void add2XML(XMLwrapper *xml); - void defaults(); - void getfromXML(XMLwrapper *xml); - - void convert2sine(int magtype); - - //Parameters - - /** - * The hmag and hphase starts counting from 0, so the first harmonic(1) has the index 0, - * 2-nd harmonic has index 1, ..the 128 harminic has index 127 - */ - unsigned char Phmag[MAX_AD_HARMONICS],Phphase[MAX_AD_HARMONICS];//the MIDI parameters for mag. and phases - - - /**The Type of magnitude: - * 0 - Linear - * 1 - dB scale (-40) - * 2 - dB scale (-60) - * 3 - dB scale (-80) - * 4 - dB scale (-100)*/ - unsigned char Phmagtype; - - unsigned char Pcurrentbasefunc;//The base function used - 0=sin, 1=... - unsigned char Pbasefuncpar;//the parameter of the base function - - unsigned char Pbasefuncmodulation;//what modulation is applied to the basefunc - unsigned char Pbasefuncmodulationpar1,Pbasefuncmodulationpar2,Pbasefuncmodulationpar3;//the parameter of the base function modulation - - /*the Randomness: - 64=no randomness - 63..0 - block type randomness - 0 is maximum - 65..127 - each harmonic randomness - 127 is maximum*/ - unsigned char Prand; - unsigned char Pwaveshaping,Pwaveshapingfunction; - unsigned char Pfiltertype,Pfilterpar1,Pfilterpar2; - unsigned char Pfilterbeforews; - unsigned char Psatype,Psapar;//spectrum adjust - - unsigned char Pamprandpower, Pamprandtype;//amplitude randomness - int Pharmonicshift;//how the harmonics are shifted - int Pharmonicshiftfirst;//if the harmonic shift is done before waveshaping and filter - - unsigned char Padaptiveharmonics;//the adaptive harmonics status (off=0,on=1,etc..) - unsigned char Padaptiveharmonicsbasefreq;//the base frequency of the adaptive harmonic (30..3000Hz) - unsigned char Padaptiveharmonicspower;//the strength of the effect (0=off,100=full) - unsigned char Padaptiveharmonicspar;//the parameters in 2,3,4.. modes of adaptive harmonics - - unsigned char Pmodulation;//what modulation is applied to the oscil - unsigned char Pmodulationpar1,Pmodulationpar2,Pmodulationpar3;//the parameter of the parameters - - - //makes a new random seed for Amplitude Randomness - //this should be called every note on event - void newrandseed(unsigned int randseed); - - bool ADvsPAD;//if it is used by ADsynth or by PADsynth - - static REALTYPE *tmpsmps;//this array stores some termporary data and it has SOUND_BUFFER_SIZE elements - static FFTFREQS outoscilFFTfreqs; - - private: - - REALTYPE hmag[MAX_AD_HARMONICS],hphase[MAX_AD_HARMONICS];//the magnituides and the phases of the sine/nonsine harmonics +class OscilGen:public Presets +{ +public: + OscilGen(FFTwrapper *fft_,Resonance *res_); + ~OscilGen(); + + /**computes the full spectrum of oscil from harmonics,phases and basefunc*/ + void prepare(); + + /**do the antialiasing(cut off higher freqs.),apply randomness and do a IFFT*/ + short get(REALTYPE *smps,REALTYPE freqHz);//returns where should I start getting samples, used in block type randomness + short get(REALTYPE *smps,REALTYPE freqHz,int resonance); + //if freqHz is smaller than 0, return the "un-randomized" sample for UI + + void getbasefunction(REALTYPE *smps); + + //called by UI + void getspectrum(int n,REALTYPE *spc,int what);//what=0 pt. oscil,1 pt. basefunc + void getcurrentbasefunction(REALTYPE *smps); + /**convert oscil to base function*/ + void useasbase(); + + void add2XML(XMLwrapper *xml); + void defaults(); + void getfromXML(XMLwrapper *xml); + + void convert2sine(int magtype); + + //Parameters + + /** + * The hmag and hphase starts counting from 0, so the first harmonic(1) has the index 0, + * 2-nd harmonic has index 1, ..the 128 harminic has index 127 + */ + unsigned char Phmag[MAX_AD_HARMONICS],Phphase[MAX_AD_HARMONICS];//the MIDI parameters for mag. and phases + + + /**The Type of magnitude: + * 0 - Linear + * 1 - dB scale (-40) + * 2 - dB scale (-60) + * 3 - dB scale (-80) + * 4 - dB scale (-100)*/ + unsigned char Phmagtype; + + unsigned char Pcurrentbasefunc;//The base function used - 0=sin, 1=... + unsigned char Pbasefuncpar;//the parameter of the base function + + unsigned char Pbasefuncmodulation;//what modulation is applied to the basefunc + unsigned char Pbasefuncmodulationpar1,Pbasefuncmodulationpar2,Pbasefuncmodulationpar3;//the parameter of the base function modulation + + /*the Randomness: + 64=no randomness + 63..0 - block type randomness - 0 is maximum + 65..127 - each harmonic randomness - 127 is maximum*/ + unsigned char Prand; + unsigned char Pwaveshaping,Pwaveshapingfunction; + unsigned char Pfiltertype,Pfilterpar1,Pfilterpar2; + unsigned char Pfilterbeforews; + unsigned char Psatype,Psapar;//spectrum adjust + + unsigned char Pamprandpower, Pamprandtype;//amplitude randomness + int Pharmonicshift;//how the harmonics are shifted + int Pharmonicshiftfirst;//if the harmonic shift is done before waveshaping and filter + + unsigned char Padaptiveharmonics;//the adaptive harmonics status (off=0,on=1,etc..) + unsigned char Padaptiveharmonicsbasefreq;//the base frequency of the adaptive harmonic (30..3000Hz) + unsigned char Padaptiveharmonicspower;//the strength of the effect (0=off,100=full) + unsigned char Padaptiveharmonicspar;//the parameters in 2,3,4.. modes of adaptive harmonics + + unsigned char Pmodulation;//what modulation is applied to the oscil + unsigned char Pmodulationpar1,Pmodulationpar2,Pmodulationpar3;//the parameter of the parameters + + + //makes a new random seed for Amplitude Randomness + //this should be called every note on event + void newrandseed(unsigned int randseed); + + bool ADvsPAD;//if it is used by ADsynth or by PADsynth + + static REALTYPE *tmpsmps;//this array stores some termporary data and it has SOUND_BUFFER_SIZE elements + static FFTFREQS outoscilFFTfreqs; + +private: + + REALTYPE hmag[MAX_AD_HARMONICS],hphase[MAX_AD_HARMONICS];//the magnituides and the phases of the sine/nonsine harmonics // private: - FFTwrapper *fft; - //computes the basefunction and make the FFT; newbasefunc<0 = same basefunc - void changebasefunction(); - //Waveshaping - void waveshape(); - - //Filter the oscillator accotding to Pfiltertype and Pfilterpar - void oscilfilter(); - - //Adjust the spectrum - void spectrumadjust(); - - //Shift the harmonics - void shiftharmonics(); - - //Do the oscil modulation stuff - void modulation(); - - //Do the adaptive harmonic stuff - void adaptiveharmonic(FFTFREQS f,REALTYPE freq); - - //Do the adaptive harmonic postprocessing (2n+1,2xS,2xA,etc..) - //this function is called even for the user interface - //this can be called for the sine and components, and for the spectrum - //(that's why the sine and cosine components should be processed with a separate call) - void adaptiveharmonicpostprocess(REALTYPE *f, int size); - - //Basic/base functions (Functiile De Baza) - REALTYPE basefunc_pulse(REALTYPE x,REALTYPE a); - REALTYPE basefunc_saw(REALTYPE x,REALTYPE a); - REALTYPE basefunc_triangle(REALTYPE x,REALTYPE a); - REALTYPE basefunc_power(REALTYPE x,REALTYPE a); - REALTYPE basefunc_gauss(REALTYPE x,REALTYPE a); - REALTYPE basefunc_diode(REALTYPE x,REALTYPE a); - REALTYPE basefunc_abssine(REALTYPE x,REALTYPE a); - REALTYPE basefunc_pulsesine(REALTYPE x,REALTYPE a); - REALTYPE basefunc_stretchsine(REALTYPE x,REALTYPE a); - REALTYPE basefunc_chirp(REALTYPE x,REALTYPE a); - REALTYPE basefunc_absstretchsine(REALTYPE x,REALTYPE a); - REALTYPE basefunc_chebyshev(REALTYPE x,REALTYPE a); - REALTYPE basefunc_sqr(REALTYPE x,REALTYPE a); - - //Internal Data - unsigned char oldbasefunc,oldbasepar,oldhmagtype,oldwaveshapingfunction,oldwaveshaping; - int oldfilterpars,oldsapars,oldbasefuncmodulation,oldbasefuncmodulationpar1,oldbasefuncmodulationpar2,oldbasefuncmodulationpar3,oldharmonicshift; - int oldmodulation,oldmodulationpar1,oldmodulationpar2,oldmodulationpar3; - - - FFTFREQS basefuncFFTfreqs;//Base Function Frequencies - FFTFREQS oscilFFTfreqs;//Oscillator Frequencies - this is different than the hamonics set-up by the user, it may contains time-domain data if the antialiasing is turned off - int oscilprepared;//1 if the oscil is prepared, 0 if it is not prepared and is need to call ::prepare() before ::get() - - Resonance *res; - - unsigned int randseed; - + FFTwrapper *fft; + //computes the basefunction and make the FFT; newbasefunc<0 = same basefunc + void changebasefunction(); + //Waveshaping + void waveshape(); + + //Filter the oscillator accotding to Pfiltertype and Pfilterpar + void oscilfilter(); + + //Adjust the spectrum + void spectrumadjust(); + + //Shift the harmonics + void shiftharmonics(); + + //Do the oscil modulation stuff + void modulation(); + + //Do the adaptive harmonic stuff + void adaptiveharmonic(FFTFREQS f,REALTYPE freq); + + //Do the adaptive harmonic postprocessing (2n+1,2xS,2xA,etc..) + //this function is called even for the user interface + //this can be called for the sine and components, and for the spectrum + //(that's why the sine and cosine components should be processed with a separate call) + void adaptiveharmonicpostprocess(REALTYPE *f, int size); + + //Basic/base functions (Functiile De Baza) + REALTYPE basefunc_pulse(REALTYPE x,REALTYPE a); + REALTYPE basefunc_saw(REALTYPE x,REALTYPE a); + REALTYPE basefunc_triangle(REALTYPE x,REALTYPE a); + REALTYPE basefunc_power(REALTYPE x,REALTYPE a); + REALTYPE basefunc_gauss(REALTYPE x,REALTYPE a); + REALTYPE basefunc_diode(REALTYPE x,REALTYPE a); + REALTYPE basefunc_abssine(REALTYPE x,REALTYPE a); + REALTYPE basefunc_pulsesine(REALTYPE x,REALTYPE a); + REALTYPE basefunc_stretchsine(REALTYPE x,REALTYPE a); + REALTYPE basefunc_chirp(REALTYPE x,REALTYPE a); + REALTYPE basefunc_absstretchsine(REALTYPE x,REALTYPE a); + REALTYPE basefunc_chebyshev(REALTYPE x,REALTYPE a); + REALTYPE basefunc_sqr(REALTYPE x,REALTYPE a); + + //Internal Data + unsigned char oldbasefunc,oldbasepar,oldhmagtype,oldwaveshapingfunction,oldwaveshaping; + int oldfilterpars,oldsapars,oldbasefuncmodulation,oldbasefuncmodulationpar1,oldbasefuncmodulationpar2,oldbasefuncmodulationpar3,oldharmonicshift; + int oldmodulation,oldmodulationpar1,oldmodulationpar2,oldmodulationpar3; + + + FFTFREQS basefuncFFTfreqs;//Base Function Frequencies + FFTFREQS oscilFFTfreqs;//Oscillator Frequencies - this is different than the hamonics set-up by the user, it may contains time-domain data if the antialiasing is turned off + int oscilprepared;//1 if the oscil is prepared, 0 if it is not prepared and is need to call ::prepare() before ::get() + + Resonance *res; + + unsigned int randseed; + }; diff --git a/src/Synth/PADnote.C b/src/Synth/PADnote.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + PADnote.C - The "pad" synthesizer Copyright (C) 2002-2005 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 + 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, @@ -22,7 +22,8 @@ #include "PADnote.h" #include "../Misc/Config.h" -PADnote::PADnote(PADnoteParameters *parameters, Controller *ctl_,REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool besilent){ +PADnote::PADnote(PADnoteParameters *parameters, Controller *ctl_,REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool besilent) +{ ready=0; // Initialise some legato-specific vars @@ -42,99 +43,99 @@ PADnote::PADnote(PADnoteParameters *parameters, Controller *ctl_,REALTYPE freq, ctl=ctl_; this->velocity=velocity; finished_=false; - + if (pars->Pfixedfreq==0) basefreq=freq; - else { - basefreq=440.0; - int fixedfreqET=pars->PfixedfreqET; - if (fixedfreqET!=0) {//if the frequency varies according the keyboard note - REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); - if (fixedfreqET<=64) basefreq*=pow(2.0,tmp); - else basefreq*=pow(3.0,tmp); - }; + else { + basefreq=440.0; + int fixedfreqET=pars->PfixedfreqET; + if (fixedfreqET!=0) {//if the frequency varies according the keyboard note + REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); + if (fixedfreqET<=64) basefreq*=pow(2.0,tmp); + else basefreq*=pow(3.0,tmp); + }; - }; + }; firsttime=true; released=false; realfreq=basefreq; NoteGlobalPar.Detune=getdetune(pars->PDetuneType - ,pars->PCoarseDetune,pars->PDetune); + ,pars->PCoarseDetune,pars->PDetune); //find out the closest note REALTYPE logfreq=log(basefreq*pow(2.0,NoteGlobalPar.Detune/1200.0)); REALTYPE mindist=fabs(logfreq-log(pars->sample[0].basefreq+0.0001)); nsample=0; - for (int i=1;i<PAD_MAX_SAMPLES;i++){ - if (pars->sample[i].smp==NULL) break; - REALTYPE dist=fabs(logfreq-log(pars->sample[i].basefreq+0.0001)); + for (int i=1;i<PAD_MAX_SAMPLES;i++) { + if (pars->sample[i].smp==NULL) break; + REALTYPE dist=fabs(logfreq-log(pars->sample[i].basefreq+0.0001)); // printf("(mindist=%g) %i %g %g\n",mindist,i,dist,pars->sample[i].basefreq); - - if (dist<mindist){ - nsample=i; - mindist=dist; - }; + + if (dist<mindist) { + nsample=i; + mindist=dist; + }; }; int size=pars->sample[nsample].size; if (size==0) size=1; - - + + poshi_l=(int)(RND*(size-1)); if (pars->PStereo!=0) poshi_r=(poshi_l+size/2)%size; - else poshi_r=poshi_l; + else poshi_r=poshi_l; poslo=0.0; - + tmpwave=new REALTYPE [SOUND_BUFFER_SIZE]; - + if (pars->PPanning==0) NoteGlobalPar.Panning=RND; - else NoteGlobalPar.Panning=pars->PPanning/128.0; + else NoteGlobalPar.Panning=pars->PPanning/128.0; NoteGlobalPar.FilterCenterPitch=pars->GlobalFilter->getfreq()+//center freq - pars->PFilterVelocityScale/127.0*6.0* //velocity sensing - (VelF(velocity,pars->PFilterVelocityScaleFunction)-1); + pars->PFilterVelocityScale/127.0*6.0* //velocity sensing + (VelF(velocity,pars->PFilterVelocityScaleFunction)-1); if (pars->PPunchStrength!=0) { NoteGlobalPar.Punch.Enabled=1; - NoteGlobalPar.Punch.t=1.0;//start from 1.0 and to 0.0 - NoteGlobalPar.Punch.initialvalue=( (pow(10,1.5*pars->PPunchStrength/127.0)-1.0) - *VelF(velocity,pars->PPunchVelocitySensing) ); - REALTYPE time=pow(10,3.0*pars->PPunchTime/127.0)/10000.0;//0.1 .. 100 ms - REALTYPE stretch=pow(440.0/freq,pars->PPunchStretch/64.0); - NoteGlobalPar.Punch.dt=1.0/(time*SAMPLE_RATE*stretch); + NoteGlobalPar.Punch.t=1.0;//start from 1.0 and to 0.0 + NoteGlobalPar.Punch.initialvalue=( (pow(10,1.5*pars->PPunchStrength/127.0)-1.0) + *VelF(velocity,pars->PPunchVelocitySensing) ); + REALTYPE time=pow(10,3.0*pars->PPunchTime/127.0)/10000.0;//0.1 .. 100 ms + REALTYPE stretch=pow(440.0/freq,pars->PPunchStretch/64.0); + NoteGlobalPar.Punch.dt=1.0/(time*SAMPLE_RATE*stretch); } else NoteGlobalPar.Punch.Enabled=0; NoteGlobalPar.FreqEnvelope=new Envelope(pars->FreqEnvelope,basefreq); NoteGlobalPar.FreqLfo=new LFO(pars->FreqLfo,basefreq); - + NoteGlobalPar.AmpEnvelope=new Envelope(pars->AmpEnvelope,basefreq); NoteGlobalPar.AmpLfo=new LFO(pars->AmpLfo,basefreq); NoteGlobalPar.Volume=4.0*pow(0.1,3.0*(1.0-pars->PVolume/96.0))//-60 dB .. 0 dB - *VelF(velocity,pars->PAmpVelocityScaleFunction);//velocity sensing + *VelF(velocity,pars->PAmpVelocityScaleFunction);//velocity sensing NoteGlobalPar.AmpEnvelope->envout_dB();//discard the first envelope output globaloldamplitude=globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout(); NoteGlobalPar.GlobalFilterL=new Filter(pars->GlobalFilter); NoteGlobalPar.GlobalFilterR=new Filter(pars->GlobalFilter); - + NoteGlobalPar.FilterEnvelope=new Envelope(pars->FilterEnvelope,basefreq); NoteGlobalPar.FilterLfo=new LFO(pars->FilterLfo,basefreq); NoteGlobalPar.FilterQ=pars->GlobalFilter->getq(); NoteGlobalPar.FilterFreqTracking=pars->GlobalFilter->getfreqtracking(basefreq); - + ready=1;///sa il pun pe asta doar cand e chiar gata - if (parameters->sample[nsample].smp==NULL){ - finished_=true; - return; + if (parameters->sample[nsample].smp==NULL) { + finished_=true; + return; }; }; @@ -143,97 +144,99 @@ PADnote::PADnote(PADnoteParameters *parameters, Controller *ctl_,REALTYPE freq, // with some lines removed so that it only alter the already playing // note (to perform legato). It is possible I left stuff that is not // required for this. -void PADnote::PADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool externcall){ - PADnoteParameters *parameters=pars; - //Controller *ctl_=ctl; - - // Manage legato stuff - if (externcall) Legato.msg=LM_Norm; - if (Legato.msg!=LM_CatchUp){ - Legato.lastfreq=Legato.param.freq; - Legato.param.freq=freq; - Legato.param.vel=velocity; - Legato.param.portamento=portamento_; - Legato.param.midinote=midinote; - if (Legato.msg==LM_Norm){ - if (Legato.silent){ - Legato.fade.m=0.0; - Legato.msg=LM_FadeIn; - } else { - Legato.fade.m=1.0; - Legato.msg=LM_FadeOut; - return; - } - } - if (Legato.msg==LM_ToNorm) Legato.msg=LM_Norm; - } - - portamento=portamento_; - this->velocity=velocity; - finished_=false; - - if (pars->Pfixedfreq==0) basefreq=freq; - else { - basefreq=440.0; - int fixedfreqET=pars->PfixedfreqET; - if (fixedfreqET!=0) {//if the frequency varies according the keyboard note - REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); - if (fixedfreqET<=64) basefreq*=pow(2.0,tmp); - else basefreq*=pow(3.0,tmp); - }; - }; - - released=false; - realfreq=basefreq; - - getdetune(pars->PDetuneType,pars->PCoarseDetune,pars->PDetune); - - - //find out the closest note - REALTYPE logfreq=log(basefreq*pow(2.0,NoteGlobalPar.Detune/1200.0)); - REALTYPE mindist=fabs(logfreq-log(pars->sample[0].basefreq+0.0001)); - nsample=0; - for (int i=1;i<PAD_MAX_SAMPLES;i++){ - if (pars->sample[i].smp==NULL) break; - REALTYPE dist=fabs(logfreq-log(pars->sample[i].basefreq+0.0001)); - - if (dist<mindist){ - nsample=i; - mindist=dist; - }; - }; - - int size=pars->sample[nsample].size; - if (size==0) size=1; - - if (pars->PPanning==0) NoteGlobalPar.Panning=RND; - else NoteGlobalPar.Panning=pars->PPanning/128.0; - - NoteGlobalPar.FilterCenterPitch=pars->GlobalFilter->getfreq()+//center freq - pars->PFilterVelocityScale/127.0*6.0* //velocity sensing - (VelF(velocity,pars->PFilterVelocityScaleFunction)-1); - - - NoteGlobalPar.Volume=4.0*pow(0.1,3.0*(1.0-pars->PVolume/96.0))//-60 dB .. 0 dB - *VelF(velocity,pars->PAmpVelocityScaleFunction);//velocity sensing - - NoteGlobalPar.AmpEnvelope->envout_dB();//discard the first envelope output - globaloldamplitude=globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout(); - - NoteGlobalPar.FilterQ=pars->GlobalFilter->getq(); - NoteGlobalPar.FilterFreqTracking=pars->GlobalFilter->getfreqtracking(basefreq); - - - if (parameters->sample[nsample].smp==NULL){ - finished_=true; - return; - }; - - // End of the PADlegatonote function. +void PADnote::PADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool externcall) +{ + PADnoteParameters *parameters=pars; + //Controller *ctl_=ctl; + + // Manage legato stuff + if (externcall) Legato.msg=LM_Norm; + if (Legato.msg!=LM_CatchUp) { + Legato.lastfreq=Legato.param.freq; + Legato.param.freq=freq; + Legato.param.vel=velocity; + Legato.param.portamento=portamento_; + Legato.param.midinote=midinote; + if (Legato.msg==LM_Norm) { + if (Legato.silent) { + Legato.fade.m=0.0; + Legato.msg=LM_FadeIn; + } else { + Legato.fade.m=1.0; + Legato.msg=LM_FadeOut; + return; + } + } + if (Legato.msg==LM_ToNorm) Legato.msg=LM_Norm; + } + + portamento=portamento_; + this->velocity=velocity; + finished_=false; + + if (pars->Pfixedfreq==0) basefreq=freq; + else { + basefreq=440.0; + int fixedfreqET=pars->PfixedfreqET; + if (fixedfreqET!=0) {//if the frequency varies according the keyboard note + REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); + if (fixedfreqET<=64) basefreq*=pow(2.0,tmp); + else basefreq*=pow(3.0,tmp); + }; + }; + + released=false; + realfreq=basefreq; + + getdetune(pars->PDetuneType,pars->PCoarseDetune,pars->PDetune); + + + //find out the closest note + REALTYPE logfreq=log(basefreq*pow(2.0,NoteGlobalPar.Detune/1200.0)); + REALTYPE mindist=fabs(logfreq-log(pars->sample[0].basefreq+0.0001)); + nsample=0; + for (int i=1;i<PAD_MAX_SAMPLES;i++) { + if (pars->sample[i].smp==NULL) break; + REALTYPE dist=fabs(logfreq-log(pars->sample[i].basefreq+0.0001)); + + if (dist<mindist) { + nsample=i; + mindist=dist; + }; + }; + + int size=pars->sample[nsample].size; + if (size==0) size=1; + + if (pars->PPanning==0) NoteGlobalPar.Panning=RND; + else NoteGlobalPar.Panning=pars->PPanning/128.0; + + NoteGlobalPar.FilterCenterPitch=pars->GlobalFilter->getfreq()+//center freq + pars->PFilterVelocityScale/127.0*6.0* //velocity sensing + (VelF(velocity,pars->PFilterVelocityScaleFunction)-1); + + + NoteGlobalPar.Volume=4.0*pow(0.1,3.0*(1.0-pars->PVolume/96.0))//-60 dB .. 0 dB + *VelF(velocity,pars->PAmpVelocityScaleFunction);//velocity sensing + + NoteGlobalPar.AmpEnvelope->envout_dB();//discard the first envelope output + globaloldamplitude=globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout(); + + NoteGlobalPar.FilterQ=pars->GlobalFilter->getq(); + NoteGlobalPar.FilterFreqTracking=pars->GlobalFilter->getfreqtracking(basefreq); + + + if (parameters->sample[nsample].smp==NULL) { + finished_=true; + return; + }; + + // End of the PADlegatonote function. }; -PADnote::~PADnote(){ +PADnote::~PADnote() +{ delete (NoteGlobalPar.FreqEnvelope); delete (NoteGlobalPar.FreqLfo); delete (NoteGlobalPar.AmpEnvelope); @@ -246,271 +249,279 @@ PADnote::~PADnote(){ }; -inline void PADnote::fadein(REALTYPE *smps){ +inline void PADnote::fadein(REALTYPE *smps) +{ int zerocrossings=0; for (int i=1;i<SOUND_BUFFER_SIZE;i++) - if ((smps[i-1]<0.0) && (smps[i]>0.0)) zerocrossings++;//this is only the possitive crossings + if ((smps[i-1]<0.0) && (smps[i]>0.0)) zerocrossings++;//this is only the possitive crossings REALTYPE tmp=(SOUND_BUFFER_SIZE-1.0)/(zerocrossings+1)/3.0; if (tmp<8.0) tmp=8.0; int n; - F2I(tmp,n);//how many samples is the fade-in + F2I(tmp,n);//how many samples is the fade-in if (n>SOUND_BUFFER_SIZE) n=SOUND_BUFFER_SIZE; for (int i=0;i<n;i++) {//fade-in - REALTYPE tmp=0.5-cos((REALTYPE)i/(REALTYPE) n*PI)*0.5; - smps[i]*=tmp; + REALTYPE tmp=0.5-cos((REALTYPE)i/(REALTYPE) n*PI)*0.5; + smps[i]*=tmp; }; }; -void PADnote::computecurrentparameters(){ +void PADnote::computecurrentparameters() +{ REALTYPE globalpitch,globalfilterpitch; globalpitch=0.01*(NoteGlobalPar.FreqEnvelope->envout()+ - NoteGlobalPar.FreqLfo->lfoout()*ctl->modwheel.relmod+NoteGlobalPar.Detune); + NoteGlobalPar.FreqLfo->lfoout()*ctl->modwheel.relmod+NoteGlobalPar.Detune); globaloldamplitude=globalnewamplitude; globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout(); - + globalfilterpitch=NoteGlobalPar.FilterEnvelope->envout()+NoteGlobalPar.FilterLfo->lfoout() +NoteGlobalPar.FilterCenterPitch; - + REALTYPE tmpfilterfreq=globalfilterpitch+ctl->filtercutoff.relfreq - +NoteGlobalPar.FilterFreqTracking; - + +NoteGlobalPar.FilterFreqTracking; + tmpfilterfreq=NoteGlobalPar.GlobalFilterL->getrealfreq(tmpfilterfreq); - + REALTYPE globalfilterq=NoteGlobalPar.FilterQ*ctl->filterq.relq; NoteGlobalPar.GlobalFilterL->setfreq_and_q(tmpfilterfreq,globalfilterq); NoteGlobalPar.GlobalFilterR->setfreq_and_q(tmpfilterfreq,globalfilterq); //compute the portamento, if it is used by this note - REALTYPE portamentofreqrap=1.0; - if (portamento!=0){//this voice use portamento - portamentofreqrap=ctl->portamento.freqrap; - if (ctl->portamento.used==0){//the portamento has finished - portamento=0;//this note is no longer "portamented" - }; + REALTYPE portamentofreqrap=1.0; + if (portamento!=0) {//this voice use portamento + portamentofreqrap=ctl->portamento.freqrap; + if (ctl->portamento.used==0) {//the portamento has finished + portamento=0;//this note is no longer "portamented" + }; }; realfreq=basefreq*portamentofreqrap*pow(2.0,globalpitch/12.0)*ctl->pitchwheel.relfreq; }; -int PADnote::Compute_Linear(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo){ +int PADnote::Compute_Linear(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo) +{ REALTYPE *smps=pars->sample[nsample].smp; - if (smps==NULL){ - finished_=true; - return(1); + if (smps==NULL) { + finished_=true; + return(1); }; int size=pars->sample[nsample].size; - for (int i=0;i<SOUND_BUFFER_SIZE;i++){ - poshi_l+=freqhi; - poshi_r+=freqhi; - poslo+=freqlo; - if (poslo>=1.0){ - poshi_l+=1; - poshi_r+=1; - poslo-=1.0; - }; - if (poshi_l>=size) poshi_l%=size; - if (poshi_r>=size) poshi_r%=size; - - outl[i]=smps[poshi_l]*(1.0-poslo)+smps[poshi_l+1]*poslo; - outr[i]=smps[poshi_r]*(1.0-poslo)+smps[poshi_r+1]*poslo; + for (int i=0;i<SOUND_BUFFER_SIZE;i++) { + poshi_l+=freqhi; + poshi_r+=freqhi; + poslo+=freqlo; + if (poslo>=1.0) { + poshi_l+=1; + poshi_r+=1; + poslo-=1.0; + }; + if (poshi_l>=size) poshi_l%=size; + if (poshi_r>=size) poshi_r%=size; + + outl[i]=smps[poshi_l]*(1.0-poslo)+smps[poshi_l+1]*poslo; + outr[i]=smps[poshi_r]*(1.0-poslo)+smps[poshi_r+1]*poslo; }; return(1); }; -int PADnote::Compute_Cubic(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo){ +int PADnote::Compute_Cubic(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo) +{ REALTYPE *smps=pars->sample[nsample].smp; - if (smps==NULL){ - finished_=true; - return(1); + if (smps==NULL) { + finished_=true; + return(1); }; int size=pars->sample[nsample].size; REALTYPE xm1,x0,x1,x2,a,b,c; - for (int i=0;i<SOUND_BUFFER_SIZE;i++){ - poshi_l+=freqhi; - poshi_r+=freqhi; - poslo+=freqlo; - if (poslo>=1.0){ - poshi_l+=1; - poshi_r+=1; - poslo-=1.0; - }; - if (poshi_l>=size) poshi_l%=size; - if (poshi_r>=size) poshi_r%=size; - - - //left - xm1=smps[poshi_l]; - x0=smps[poshi_l + 1]; - x1=smps[poshi_l + 2]; - x2=smps[poshi_l + 3]; - a = (3.0 * (x0-x1) - xm1 + x2)*0.5; - b = 2.0*x1 + xm1 - (5.0*x0 + x2)*0.5; - c = (x1 - xm1)*0.5; - outl[i] = (((a * poslo) + b) * poslo + c) * poslo + x0; - //right - xm1=smps[poshi_r]; - x0=smps[poshi_r + 1]; - x1=smps[poshi_r + 2]; - x2=smps[poshi_r + 3]; - a = (3.0 * (x0-x1) - xm1 + x2)*0.5; - b = 2.0*x1 + xm1 - (5.0*x0 + x2)*0.5; - c = (x1 - xm1)*0.5; - outr[i] = (((a * poslo) + b) * poslo + c) * poslo + x0; + for (int i=0;i<SOUND_BUFFER_SIZE;i++) { + poshi_l+=freqhi; + poshi_r+=freqhi; + poslo+=freqlo; + if (poslo>=1.0) { + poshi_l+=1; + poshi_r+=1; + poslo-=1.0; + }; + if (poshi_l>=size) poshi_l%=size; + if (poshi_r>=size) poshi_r%=size; + + + //left + xm1=smps[poshi_l]; + x0=smps[poshi_l + 1]; + x1=smps[poshi_l + 2]; + x2=smps[poshi_l + 3]; + a = (3.0 * (x0-x1) - xm1 + x2)*0.5; + b = 2.0*x1 + xm1 - (5.0*x0 + x2)*0.5; + c = (x1 - xm1)*0.5; + outl[i] = (((a * poslo) + b) * poslo + c) * poslo + x0; + //right + xm1=smps[poshi_r]; + x0=smps[poshi_r + 1]; + x1=smps[poshi_r + 2]; + x2=smps[poshi_r + 3]; + a = (3.0 * (x0-x1) - xm1 + x2)*0.5; + b = 2.0*x1 + xm1 - (5.0*x0 + x2)*0.5; + c = (x1 - xm1)*0.5; + outr[i] = (((a * poslo) + b) * poslo + c) * poslo + x0; }; return(1); }; -int PADnote::noteout(REALTYPE *outl,REALTYPE *outr){ +int PADnote::noteout(REALTYPE *outl,REALTYPE *outr) +{ computecurrentparameters(); REALTYPE *smps=pars->sample[nsample].smp; - if (smps==NULL){ - for (int i=0;i<SOUND_BUFFER_SIZE;i++){ - outl[i]=0.0; - outr[i]=0.0; - }; - return(1); + if (smps==NULL) { + for (int i=0;i<SOUND_BUFFER_SIZE;i++) { + outl[i]=0.0; + outr[i]=0.0; + }; + return(1); }; REALTYPE smpfreq=pars->sample[nsample].basefreq; - + REALTYPE freqrap=realfreq/smpfreq; int freqhi=(int) (floor(freqrap)); REALTYPE freqlo=freqrap-floor(freqrap); - + if (config.cfg.Interpolation) Compute_Cubic(outl,outr,freqhi,freqlo); - else Compute_Linear(outl,outr,freqhi,freqlo); - - - if (firsttime){ - fadein(outl); - fadein(outr); - firsttime=false; + else Compute_Linear(outl,outr,freqhi,freqlo); + + + if (firsttime) { + fadein(outl); + fadein(outr); + firsttime=false; }; - NoteGlobalPar.GlobalFilterL->filterout(outl); - NoteGlobalPar.GlobalFilterR->filterout(outr); - - //Apply the punch - if (NoteGlobalPar.Punch.Enabled!=0){ - for (int i=0;i<SOUND_BUFFER_SIZE;i++){ - REALTYPE punchamp=NoteGlobalPar.Punch.initialvalue*NoteGlobalPar.Punch.t+1.0; - outl[i]*=punchamp; - outr[i]*=punchamp; - NoteGlobalPar.Punch.t-=NoteGlobalPar.Punch.dt; - if (NoteGlobalPar.Punch.t<0.0) { - NoteGlobalPar.Punch.Enabled=0; - break; - }; - }; + NoteGlobalPar.GlobalFilterL->filterout(outl); + NoteGlobalPar.GlobalFilterR->filterout(outr); + + //Apply the punch + if (NoteGlobalPar.Punch.Enabled!=0) { + for (int i=0;i<SOUND_BUFFER_SIZE;i++) { + REALTYPE punchamp=NoteGlobalPar.Punch.initialvalue*NoteGlobalPar.Punch.t+1.0; + outl[i]*=punchamp; + outr[i]*=punchamp; + NoteGlobalPar.Punch.t-=NoteGlobalPar.Punch.dt; + if (NoteGlobalPar.Punch.t<0.0) { + NoteGlobalPar.Punch.Enabled=0; + break; + }; }; + }; - if (ABOVE_AMPLITUDE_THRESHOLD(globaloldamplitude,globalnewamplitude)){ - // Amplitude Interpolation - for (int i=0;i<SOUND_BUFFER_SIZE;i++){ - REALTYPE tmpvol=INTERPOLATE_AMPLITUDE(globaloldamplitude,globalnewamplitude,i,SOUND_BUFFER_SIZE); - outl[i]*=tmpvol*NoteGlobalPar.Panning; - outr[i]*=tmpvol*(1.0-NoteGlobalPar.Panning); - }; - } else { - for (int i=0;i<SOUND_BUFFER_SIZE;i++) { - outl[i]*=globalnewamplitude*NoteGlobalPar.Panning; - outr[i]*=globalnewamplitude*(1.0-NoteGlobalPar.Panning); - }; + if (ABOVE_AMPLITUDE_THRESHOLD(globaloldamplitude,globalnewamplitude)) { + // Amplitude Interpolation + for (int i=0;i<SOUND_BUFFER_SIZE;i++) { + REALTYPE tmpvol=INTERPOLATE_AMPLITUDE(globaloldamplitude,globalnewamplitude,i,SOUND_BUFFER_SIZE); + outl[i]*=tmpvol*NoteGlobalPar.Panning; + outr[i]*=tmpvol*(1.0-NoteGlobalPar.Panning); }; + } else { + for (int i=0;i<SOUND_BUFFER_SIZE;i++) { + outl[i]*=globalnewamplitude*NoteGlobalPar.Panning; + outr[i]*=globalnewamplitude*(1.0-NoteGlobalPar.Panning); + }; + }; // Apply legato-specific sound signal modifications - if (Legato.silent){ // Silencer - if (Legato.msg!=LM_FadeIn){ - for (int i=0;i<SOUND_BUFFER_SIZE;i++){ - outl[i]=0.0; - outr[i]=0.0; - } - } + if (Legato.silent) { // Silencer + if (Legato.msg!=LM_FadeIn) { + for (int i=0;i<SOUND_BUFFER_SIZE;i++) { + outl[i]=0.0; + outr[i]=0.0; + } + } } - switch (Legato.msg){ + switch (Legato.msg) { case LM_CatchUp : // Continue the catch-up... - if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; - for (int i=0;i<SOUND_BUFFER_SIZE;i++){//Yea, could be done without the loop... - Legato.decounter--; - if (Legato.decounter<1){ - // Catching-up done, we can finally set - // the note to the actual parameters. - Legato.decounter=-10; - Legato.msg=LM_ToNorm; - PADlegatonote(Legato.param.freq, Legato.param.vel, Legato.param.portamento, Legato.param.midinote, false); - break; - } - } - break; + if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; + for (int i=0;i<SOUND_BUFFER_SIZE;i++) {//Yea, could be done without the loop... + Legato.decounter--; + if (Legato.decounter<1) { + // Catching-up done, we can finally set + // the note to the actual parameters. + Legato.decounter=-10; + Legato.msg=LM_ToNorm; + PADlegatonote(Legato.param.freq, Legato.param.vel, Legato.param.portamento, Legato.param.midinote, false); + break; + } + } + break; case LM_FadeIn : // Fade-in - if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; - Legato.silent=false; - for (int i=0;i<SOUND_BUFFER_SIZE;i++){ - Legato.decounter--; - if (Legato.decounter<1){ - Legato.decounter=-10; - Legato.msg=LM_Norm; - break; - } - Legato.fade.m+=Legato.fade.step; - outl[i]*=Legato.fade.m; - outr[i]*=Legato.fade.m; - } - break; + if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; + Legato.silent=false; + for (int i=0;i<SOUND_BUFFER_SIZE;i++) { + Legato.decounter--; + if (Legato.decounter<1) { + Legato.decounter=-10; + Legato.msg=LM_Norm; + break; + } + Legato.fade.m+=Legato.fade.step; + outl[i]*=Legato.fade.m; + outr[i]*=Legato.fade.m; + } + break; case LM_FadeOut : // Fade-out, then set the catch-up - if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; - for (int i=0;i<SOUND_BUFFER_SIZE;i++){ - Legato.decounter--; - if (Legato.decounter<1){ - for (int j=i;j<SOUND_BUFFER_SIZE;j++){ - outl[j]=0.0; - outr[j]=0.0; - } - Legato.decounter=-10; - Legato.silent=true; - // Fading-out done, now set the catch-up : - Legato.decounter=Legato.fade.length; - Legato.msg=LM_CatchUp; - REALTYPE catchupfreq=Legato.param.freq*(Legato.param.freq/Legato.lastfreq);//This freq should make this now silent note to catch-up (or should I say resync ?) with the heard note for the same length it stayed at the previous freq during the fadeout. - PADlegatonote(catchupfreq, Legato.param.vel, Legato.param.portamento, Legato.param.midinote, false); - break; - } - Legato.fade.m-=Legato.fade.step; - outl[i]*=Legato.fade.m; - outr[i]*=Legato.fade.m; - } - break; - default : break; + if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; + for (int i=0;i<SOUND_BUFFER_SIZE;i++) { + Legato.decounter--; + if (Legato.decounter<1) { + for (int j=i;j<SOUND_BUFFER_SIZE;j++) { + outl[j]=0.0; + outr[j]=0.0; + } + Legato.decounter=-10; + Legato.silent=true; + // Fading-out done, now set the catch-up : + Legato.decounter=Legato.fade.length; + Legato.msg=LM_CatchUp; + REALTYPE catchupfreq=Legato.param.freq*(Legato.param.freq/Legato.lastfreq);//This freq should make this now silent note to catch-up (or should I say resync ?) with the heard note for the same length it stayed at the previous freq during the fadeout. + PADlegatonote(catchupfreq, Legato.param.vel, Legato.param.portamento, Legato.param.midinote, false); + break; + } + Legato.fade.m-=Legato.fade.step; + outl[i]*=Legato.fade.m; + outr[i]*=Legato.fade.m; + } + break; + default : + break; } - // Check if the global amplitude is finished. - // If it does, disable the note - if (NoteGlobalPar.AmpEnvelope->finished()!=0) { - for (int i=0;i<SOUND_BUFFER_SIZE;i++) {//fade-out - REALTYPE tmp=1.0-(REALTYPE)i/(REALTYPE)SOUND_BUFFER_SIZE; - outl[i]*=tmp; - outr[i]*=tmp; - }; - finished_=1; - }; + // Check if the global amplitude is finished. + // If it does, disable the note + if (NoteGlobalPar.AmpEnvelope->finished()!=0) { + for (int i=0;i<SOUND_BUFFER_SIZE;i++) {//fade-out + REALTYPE tmp=1.0-(REALTYPE)i/(REALTYPE)SOUND_BUFFER_SIZE; + outl[i]*=tmp; + outr[i]*=tmp; + }; + finished_=1; + }; return(1); }; -int PADnote::finished(){ +int PADnote::finished() +{ return(finished_); }; -void PADnote::relasekey(){ - NoteGlobalPar.FreqEnvelope->relasekey(); - NoteGlobalPar.FilterEnvelope->relasekey(); - NoteGlobalPar.AmpEnvelope->relasekey(); +void PADnote::relasekey() +{ + NoteGlobalPar.FreqEnvelope->relasekey(); + NoteGlobalPar.FilterEnvelope->relasekey(); + NoteGlobalPar.AmpEnvelope->relasekey(); }; diff --git a/src/Synth/PADnote.h b/src/Synth/PADnote.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + PADnote.h - The "pad" synthesizer Copyright (C) 2002-2005 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 + 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, @@ -30,95 +30,96 @@ #include "../Params/Controller.h" /**The "pad" synthesizer*/ -class PADnote{ - public: - PADnote(PADnoteParameters *parameters, Controller *ctl_,REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool besilent); - ~PADnote(); - - void PADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool externcall); - - int noteout(REALTYPE *outl,REALTYPE *outr); - int finished(); - void relasekey(); - - int ready; - - private: - void fadein(REALTYPE *smps); - void computecurrentparameters(); - bool finished_; - PADnoteParameters *pars; - - int poshi_l,poshi_r; - REALTYPE poslo; - - REALTYPE basefreq; - bool firsttime,released; - - int nsample,portamento; - - int Compute_Linear(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo); - int Compute_Cubic(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo); - - - struct{ - /****************************************** - * FREQUENCY GLOBAL PARAMETERS * - ******************************************/ - REALTYPE Detune;//cents - - Envelope *FreqEnvelope; - LFO *FreqLfo; - - /******************************************** - * AMPLITUDE GLOBAL PARAMETERS * - ********************************************/ - REALTYPE Volume;// [ 0 .. 1 ] - - REALTYPE Panning;// [ 0 .. 1 ] - - Envelope *AmpEnvelope; - LFO *AmpLfo; - - struct { - int Enabled; - REALTYPE initialvalue,dt,t; - } Punch; - - /****************************************** - * FILTER GLOBAL PARAMETERS * - ******************************************/ - Filter *GlobalFilterL,*GlobalFilterR; - - REALTYPE FilterCenterPitch;//octaves - REALTYPE FilterQ; - REALTYPE FilterFreqTracking; - - Envelope *FilterEnvelope; - - LFO *FilterLfo; - } NoteGlobalPar; - - - REALTYPE globaloldamplitude,globalnewamplitude,velocity,realfreq; - REALTYPE *tmpwave; - Controller *ctl; - - // Legato vars - struct { - bool silent; - REALTYPE lastfreq; - LegatoMsg msg; - int decounter; - struct { // Fade In/Out vars - int length; - REALTYPE m, step; - } fade; - struct { // Note parameters - REALTYPE freq, vel; - int portamento, midinote; - } param; - } Legato; +class PADnote +{ +public: + PADnote(PADnoteParameters *parameters, Controller *ctl_,REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool besilent); + ~PADnote(); + + void PADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool externcall); + + int noteout(REALTYPE *outl,REALTYPE *outr); + int finished(); + void relasekey(); + + int ready; + +private: + void fadein(REALTYPE *smps); + void computecurrentparameters(); + bool finished_; + PADnoteParameters *pars; + + int poshi_l,poshi_r; + REALTYPE poslo; + + REALTYPE basefreq; + bool firsttime,released; + + int nsample,portamento; + + int Compute_Linear(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo); + int Compute_Cubic(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo); + + + struct { + /****************************************** + * FREQUENCY GLOBAL PARAMETERS * + ******************************************/ + REALTYPE Detune;//cents + + Envelope *FreqEnvelope; + LFO *FreqLfo; + + /******************************************** + * AMPLITUDE GLOBAL PARAMETERS * + ********************************************/ + REALTYPE Volume;// [ 0 .. 1 ] + + REALTYPE Panning;// [ 0 .. 1 ] + + Envelope *AmpEnvelope; + LFO *AmpLfo; + + struct { + int Enabled; + REALTYPE initialvalue,dt,t; + } Punch; + + /****************************************** + * FILTER GLOBAL PARAMETERS * + ******************************************/ + Filter *GlobalFilterL,*GlobalFilterR; + + REALTYPE FilterCenterPitch;//octaves + REALTYPE FilterQ; + REALTYPE FilterFreqTracking; + + Envelope *FilterEnvelope; + + LFO *FilterLfo; + } NoteGlobalPar; + + + REALTYPE globaloldamplitude,globalnewamplitude,velocity,realfreq; + REALTYPE *tmpwave; + Controller *ctl; + + // Legato vars + struct { + bool silent; + REALTYPE lastfreq; + LegatoMsg msg; + int decounter; + struct { // Fade In/Out vars + int length; + REALTYPE m, step; + } fade; + struct { // Note parameters + REALTYPE freq, vel; + int portamento, midinote; + } param; + } Legato; }; diff --git a/src/Synth/Resonance.C b/src/Synth/Resonance.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Resonance.C - Resonance Copyright (C) 2002-2005 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 + 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, @@ -26,16 +26,19 @@ #include <stdio.h> -Resonance::Resonance():Presets(){ +Resonance::Resonance():Presets() +{ setpresettype("Presonance"); defaults(); }; -Resonance::~Resonance(){ +Resonance::~Resonance() +{ }; -void Resonance::defaults(){ +void Resonance::defaults() +{ Penabled=0; PmaxdB=20; Pcenterfreq=64;//1 kHz @@ -49,7 +52,8 @@ void Resonance::defaults(){ /* * Set a point of resonance function with a value */ -void Resonance::setpoint(int n,unsigned char p){ +void Resonance::setpoint(int n,unsigned char p) +{ if ((n<0)||(n>=N_RES_POINTS)) return; Prespoints[n]=p; }; @@ -57,51 +61,59 @@ void Resonance::setpoint(int n,unsigned char p){ /* * Apply the resonance to FFT data */ -void Resonance::applyres(int n,FFTFREQS fftdata,REALTYPE freq){ +void Resonance::applyres(int n,FFTFREQS fftdata,REALTYPE freq) +{ if (Penabled==0) return;//if the resonance is disabled REALTYPE sum=0.0, - l1=log(getfreqx(0.0)*ctlcenter), - l2=log(2.0)*getoctavesfreq()*ctlbw; + l1=log(getfreqx(0.0)*ctlcenter), + l2=log(2.0)*getoctavesfreq()*ctlbw; for (int i=0;i<N_RES_POINTS;i++) if (sum<Prespoints[i]) sum=Prespoints[i]; if (sum<1.0) sum=1.0; - for (int i=1;i<n;i++){ + for (int i=1;i<n;i++) { REALTYPE x=(log(freq*i)-l1)/l2;//compute where the n-th hamonics fits to the graph - if (x<0.0) x=0.0; - - x*=N_RES_POINTS; - REALTYPE dx=x-floor(x);x=floor(x); - int kx1=(int)x; if (kx1>=N_RES_POINTS) kx1=N_RES_POINTS-1; - int kx2=kx1+1;if (kx2>=N_RES_POINTS) kx2=N_RES_POINTS-1; - REALTYPE y=(Prespoints[kx1]*(1.0-dx)+Prespoints[kx2]*dx)/127.0-sum/127.0; - - y=pow(10.0,y*PmaxdB/20.0); - - if ((Pprotectthefundamental!=0)&&(i==1)) y=1.0; - + if (x<0.0) x=0.0; + + x*=N_RES_POINTS; + REALTYPE dx=x-floor(x); + x=floor(x); + int kx1=(int)x; + if (kx1>=N_RES_POINTS) kx1=N_RES_POINTS-1; + int kx2=kx1+1; + if (kx2>=N_RES_POINTS) kx2=N_RES_POINTS-1; + REALTYPE y=(Prespoints[kx1]*(1.0-dx)+Prespoints[kx2]*dx)/127.0-sum/127.0; + + y=pow(10.0,y*PmaxdB/20.0); + + if ((Pprotectthefundamental!=0)&&(i==1)) y=1.0; + fftdata.c[i]*=y; fftdata.s[i]*=y; - }; + }; }; /* * Gets the response at the frequency "freq" */ -REALTYPE Resonance::getfreqresponse(REALTYPE freq){ +REALTYPE Resonance::getfreqresponse(REALTYPE freq) +{ REALTYPE l1=log(getfreqx(0.0)*ctlcenter), - l2=log(2.0)*getoctavesfreq()*ctlbw,sum=0.0; - + l2=log(2.0)*getoctavesfreq()*ctlbw,sum=0.0; + for (int i=0;i<N_RES_POINTS;i++) if (sum<Prespoints[i]) sum=Prespoints[i]; if (sum<1.0) sum=1.0; REALTYPE x=(log(freq)-l1)/l2;//compute where the n-th hamonics fits to the graph if (x<0.0) x=0.0; x*=N_RES_POINTS; - REALTYPE dx=x-floor(x);x=floor(x); - int kx1=(int)x; if (kx1>=N_RES_POINTS) kx1=N_RES_POINTS-1; - int kx2=kx1+1;if (kx2>=N_RES_POINTS) kx2=N_RES_POINTS-1; + REALTYPE dx=x-floor(x); + x=floor(x); + int kx1=(int)x; + if (kx1>=N_RES_POINTS) kx1=N_RES_POINTS-1; + int kx2=kx1+1; + if (kx2>=N_RES_POINTS) kx2=N_RES_POINTS-1; REALTYPE result=(Prespoints[kx1]*(1.0-dx)+Prespoints[kx2]*dx)/127.0-sum/127.0; result=pow(10.0,result*PmaxdB/20.0); return(result); @@ -111,30 +123,32 @@ REALTYPE Resonance::getfreqresponse(REALTYPE freq){ /* * Smooth the resonance function */ -void Resonance::smooth(){ +void Resonance::smooth() +{ REALTYPE old=Prespoints[0]; - for (int i=0;i<N_RES_POINTS;i++){ + for (int i=0;i<N_RES_POINTS;i++) { old=old*0.4+Prespoints[i]*0.6; - Prespoints[i]=(int) old; + Prespoints[i]=(int) old; }; old=Prespoints[N_RES_POINTS-1]; - for (int i=N_RES_POINTS-1;i>0;i--){ + for (int i=N_RES_POINTS-1;i>0;i--) { old=old*0.4+Prespoints[i]*0.6; - Prespoints[i]=(int) old+1; - if (Prespoints[i]>127) Prespoints[i]=127; + Prespoints[i]=(int) old+1; + if (Prespoints[i]>127) Prespoints[i]=127; }; }; /* * Randomize the resonance function */ -void Resonance::randomize(int type){ +void Resonance::randomize(int type) +{ int r=(int)(RND*127.0); - for (int i=0;i<N_RES_POINTS;i++){ - Prespoints[i]=r; - if ((RND<0.1)&&(type==0)) r=(int)(RND*127.0); - if ((RND<0.3)&&(type==1)) r=(int)(RND*127.0); - if (type==2) r=(int)(RND*127.0); + for (int i=0;i<N_RES_POINTS;i++) { + Prespoints[i]=r; + if ((RND<0.1)&&(type==0)) r=(int)(RND*127.0); + if ((RND<0.3)&&(type==1)) r=(int)(RND*127.0); + if (type==2) r=(int)(RND*127.0); }; smooth(); }; @@ -142,26 +156,28 @@ void Resonance::randomize(int type){ /* * Interpolate the peaks */ -void Resonance::interpolatepeaks(int type){ +void Resonance::interpolatepeaks(int type) +{ int x1=0,y1=Prespoints[0]; - for (int i=1;i<N_RES_POINTS;i++){ - if ((Prespoints[i]!=64)||(i+1==N_RES_POINTS)){ - int y2=Prespoints[i]; - for (int k=0;k<i-x1;k++){ - float x=(float) k/(i-x1); - if (type==0) x=(1-cos(x*PI))*0.5; - Prespoints[x1+k]=(int)(y1*(1.0-x)+y2*x); - }; - x1=i; - y1=y2; - }; + for (int i=1;i<N_RES_POINTS;i++) { + if ((Prespoints[i]!=64)||(i+1==N_RES_POINTS)) { + int y2=Prespoints[i]; + for (int k=0;k<i-x1;k++) { + float x=(float) k/(i-x1); + if (type==0) x=(1-cos(x*PI))*0.5; + Prespoints[x1+k]=(int)(y1*(1.0-x)+y2*x); + }; + x1=i; + y1=y2; + }; }; }; /* * Get the frequency from x, where x is [0..1]; x is the x coordinate */ -REALTYPE Resonance::getfreqx(REALTYPE x){ +REALTYPE Resonance::getfreqx(REALTYPE x) +{ if (x>1.0) x=1.0; REALTYPE octf=pow(2.0,getoctavesfreq()); return(getcenterfreq()/sqrt(octf)*pow(octf,x)); @@ -170,35 +186,40 @@ REALTYPE Resonance::getfreqx(REALTYPE x){ /* * Get the x coordinate from frequency (used by the UI) */ -REALTYPE Resonance::getfreqpos(REALTYPE freq){ +REALTYPE Resonance::getfreqpos(REALTYPE freq) +{ return((log(freq)-log(getfreqx(0.0)))/log(2.0)/getoctavesfreq()); }; /* * Get the center frequency of the resonance graph */ -REALTYPE Resonance::getcenterfreq(){ +REALTYPE Resonance::getcenterfreq() +{ return(10000.0*pow(10,-(1.0-Pcenterfreq/127.0)*2.0)); }; /* * Get the number of octave that the resonance functions applies to */ -REALTYPE Resonance::getoctavesfreq(){ +REALTYPE Resonance::getoctavesfreq() +{ return(0.25+10.0*Poctavesfreq/127.0); }; -void Resonance::sendcontroller(MidiControllers ctl,REALTYPE par){ +void Resonance::sendcontroller(MidiControllers ctl,REALTYPE par) +{ if (ctl==C_resonance_center) ctlcenter=par; - else ctlbw=par; + else ctlbw=par; }; -void Resonance::add2XML(XMLwrapper *xml){ +void Resonance::add2XML(XMLwrapper *xml) +{ xml->addparbool("enabled",Penabled); - + if ((Penabled==0)&&(xml->minimal)) return; xml->addpar("max_db",PmaxdB); @@ -206,25 +227,26 @@ void Resonance::add2XML(XMLwrapper *xml){ xml->addpar("octaves_freq",Poctavesfreq); xml->addparbool("protect_fundamental_frequency",Pprotectthefundamental); xml->addpar("resonance_points",N_RES_POINTS); - for (int i=0;i<N_RES_POINTS;i++){ - xml->beginbranch("RESPOINT",i); - xml->addpar("val",Prespoints[i]); - xml->endbranch(); + for (int i=0;i<N_RES_POINTS;i++) { + xml->beginbranch("RESPOINT",i); + xml->addpar("val",Prespoints[i]); + xml->endbranch(); }; }; -void Resonance::getfromXML(XMLwrapper *xml){ +void Resonance::getfromXML(XMLwrapper *xml) +{ Penabled=xml->getparbool("enabled",Penabled); PmaxdB=xml->getpar127("max_db",PmaxdB); Pcenterfreq=xml->getpar127("center_freq",Pcenterfreq); Poctavesfreq=xml->getpar127("octaves_freq",Poctavesfreq); Pprotectthefundamental=xml->getparbool("protect_fundamental_frequency",Pprotectthefundamental); - for (int i=0;i<N_RES_POINTS;i++){ - if (xml->enterbranch("RESPOINT",i)==0) continue; - Prespoints[i]=xml->getpar127("val",Prespoints[i]); - xml->exitbranch(); + for (int i=0;i<N_RES_POINTS;i++) { + if (xml->enterbranch("RESPOINT",i)==0) continue; + Prespoints[i]=xml->getpar127("val",Prespoints[i]); + xml->exitbranch(); }; }; diff --git a/src/Synth/Resonance.h b/src/Synth/Resonance.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - - Resonance.h - Resonance + + Resonance.h - Resonance Copyright (C) 2002-2005 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 + 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, @@ -29,30 +29,31 @@ #define N_RES_POINTS 256 -class Resonance:public Presets{ - public: - Resonance(); - ~Resonance(); - void setpoint(int n,unsigned char p); - void applyres(int n,FFTFREQS fftdata,REALTYPE freq); - void smooth(); - void interpolatepeaks(int type); - void randomize(int type); +class Resonance:public Presets +{ +public: + Resonance(); + ~Resonance(); + void setpoint(int n,unsigned char p); + void applyres(int n,FFTFREQS fftdata,REALTYPE freq); + void smooth(); + void interpolatepeaks(int type); + void randomize(int type); - void add2XML(XMLwrapper *xml); - void defaults(); - void getfromXML(XMLwrapper *xml); + void add2XML(XMLwrapper *xml); + void defaults(); + void getfromXML(XMLwrapper *xml); - REALTYPE getfreqpos(REALTYPE freq); - REALTYPE getfreqx(REALTYPE x); - REALTYPE getfreqresponse(REALTYPE freq); - REALTYPE getcenterfreq(); - REALTYPE getoctavesfreq(); - void sendcontroller(MidiControllers ctl,REALTYPE par); + REALTYPE getfreqpos(REALTYPE freq); + REALTYPE getfreqx(REALTYPE x); + REALTYPE getfreqresponse(REALTYPE freq); + REALTYPE getcenterfreq(); + REALTYPE getoctavesfreq(); + void sendcontroller(MidiControllers ctl,REALTYPE par); //parameters - unsigned char Penabled; //if the ressonance is enabled + unsigned char Penabled; //if the ressonance is enabled unsigned char Prespoints[N_RES_POINTS]; //how many points define the resonance function unsigned char PmaxdB; //how many dB the signal may be amplified unsigned char Pcenterfreq,Poctavesfreq; //the center frequency of the res. func., and the number of octaves @@ -61,8 +62,8 @@ class Resonance:public Presets{ //controllers REALTYPE ctlcenter;//center frequency(relative) REALTYPE ctlbw;//bandwidth(relative) - - private: + +private: }; #endif diff --git a/src/Synth/SUBnote.C b/src/Synth/SUBnote.C @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + SUBnote.C - The "subtractive" synthesizer Copyright (C) 2002-2005 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 + 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, @@ -27,9 +27,10 @@ #include "SUBnote.h" #include "../Misc/Util.h" -SUBnote::SUBnote(SUBnoteParameters *parameters,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote,bool besilent){ +SUBnote::SUBnote(SUBnoteParameters *parameters,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote,bool besilent) +{ ready=0; - + tmpsmp=new REALTYPE[SOUND_BUFFER_SIZE]; tmprnd=new REALTYPE[SOUND_BUFFER_SIZE]; @@ -44,7 +45,7 @@ SUBnote::SUBnote(SUBnoteParameters *parameters,Controller *ctl_,REALTYPE freq,RE Legato.param.portamento=portamento_; Legato.param.midinote=midinote; Legato.silent=besilent; - + pars=parameters; ctl=ctl_; portamento=portamento_; @@ -52,7 +53,7 @@ SUBnote::SUBnote(SUBnoteParameters *parameters,Controller *ctl_,REALTYPE freq,RE volume=pow(0.1,3.0*(1.0-pars->PVolume/96.0));//-60 dB .. 0 dB volume*=VelF(velocity,pars->PAmpVelocityScaleFunction); if (pars->PPanning!=0) panning=pars->PPanning/127.0; - else panning=RND; + else panning=RND; numstages=pars->Pnumstages; stereo=pars->Pstereo; start=pars->Pstart; @@ -60,95 +61,105 @@ SUBnote::SUBnote(SUBnoteParameters *parameters,Controller *ctl_,REALTYPE freq,RE int pos[MAX_SUB_HARMONICS]; if (pars->Pfixedfreq==0) basefreq=freq; - else { - basefreq=440.0; - int fixedfreqET=pars->PfixedfreqET; - if (fixedfreqET!=0) {//if the frequency varies according the keyboard note - REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); - if (fixedfreqET<=64) basefreq*=pow(2.0,tmp); - else basefreq*=pow(3.0,tmp); - }; - - }; + else { + basefreq=440.0; + int fixedfreqET=pars->PfixedfreqET; + if (fixedfreqET!=0) {//if the frequency varies according the keyboard note + REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); + if (fixedfreqET<=64) basefreq*=pow(2.0,tmp); + else basefreq*=pow(3.0,tmp); + }; + + }; REALTYPE detune=getdetune(pars->PDetuneType,pars->PCoarseDetune,pars->PDetune); basefreq*=pow(2.0,detune/1200.0);//detune // basefreq*=ctl->pitchwheel.relfreq;//pitch wheel - - //global filter - GlobalFilterCenterPitch=pars->GlobalFilter->getfreq()+//center freq - (pars->PGlobalFilterVelocityScale/127.0*6.0)* //velocity sensing - (VelF(velocity,pars->PGlobalFilterVelocityScaleFunction)-1); - GlobalFilterL=NULL;GlobalFilterR=NULL; + //global filter + GlobalFilterCenterPitch=pars->GlobalFilter->getfreq()+//center freq + (pars->PGlobalFilterVelocityScale/127.0*6.0)* //velocity sensing + (VelF(velocity,pars->PGlobalFilterVelocityScaleFunction)-1); + + GlobalFilterL=NULL; + GlobalFilterR=NULL; GlobalFilterEnvelope=NULL; - //select only harmonics that desire to compute + //select only harmonics that desire to compute numharmonics=0; - for (int n=0;n<MAX_SUB_HARMONICS;n++){ - if (pars->Phmag[n]==0)continue; - if (n*basefreq>SAMPLE_RATE/2.0) break;//remove the freqs above the Nyquist freq - pos[numharmonics++]=n; + for (int n=0;n<MAX_SUB_HARMONICS;n++) { + if (pars->Phmag[n]==0)continue; + if (n*basefreq>SAMPLE_RATE/2.0) break;//remove the freqs above the Nyquist freq + pos[numharmonics++]=n; }; firstnumharmonics=numharmonics;//(gf)Useful in legato mode. - + if (numharmonics==0) { - NoteEnabled=OFF; - return; + NoteEnabled=OFF; + return; }; - - + + lfilter=new bpfilter[numstages*numharmonics]; if (stereo!=0) rfilter=new bpfilter[numstages*numharmonics]; - + //how much the amplitude is normalised (because the harmonics) REALTYPE reduceamp=0.0; - - for (int n=0;n<numharmonics;n++){ - REALTYPE freq=basefreq*(pos[n]+1); - - //the bandwidth is not absolute(Hz); it is relative to frequency - REALTYPE bw=pow(10,(pars->Pbandwidth-127.0)/127.0*4)*numstages; + for (int n=0;n<numharmonics;n++) { - //Bandwidth Scale - bw*=pow(1000/freq,(pars->Pbwscale-64.0)/64.0*3.0); + REALTYPE freq=basefreq*(pos[n]+1); - //Relative BandWidth - bw*=pow(100,(pars->Phrelbw[pos[n]]-64.0)/64.0); + //the bandwidth is not absolute(Hz); it is relative to frequency + REALTYPE bw=pow(10,(pars->Pbandwidth-127.0)/127.0*4)*numstages; - if (bw>25.0) bw=25.0; + //Bandwidth Scale + bw*=pow(1000/freq,(pars->Pbwscale-64.0)/64.0*3.0); - //try to keep same amplitude on all freqs and bw. (empirically) - REALTYPE gain=sqrt(1500.0/(bw*freq)); + //Relative BandWidth + bw*=pow(100,(pars->Phrelbw[pos[n]]-64.0)/64.0); + + if (bw>25.0) bw=25.0; + + //try to keep same amplitude on all freqs and bw. (empirically) + REALTYPE gain=sqrt(1500.0/(bw*freq)); REALTYPE hmagnew=1.0-pars->Phmag[pos[n]]/127.0; - REALTYPE hgain; - - switch(pars->Phmagtype){ - case 1:hgain=exp(hmagnew*log(0.01)); break; - case 2:hgain=exp(hmagnew*log(0.001));break; - case 3:hgain=exp(hmagnew*log(0.0001));break; - case 4:hgain=exp(hmagnew*log(0.00001));break; - default:hgain=1.0-hmagnew; - }; - gain*=hgain; + REALTYPE hgain; + + switch (pars->Phmagtype) { + case 1: + hgain=exp(hmagnew*log(0.01)); + break; + case 2: + hgain=exp(hmagnew*log(0.001)); + break; + case 3: + hgain=exp(hmagnew*log(0.0001)); + break; + case 4: + hgain=exp(hmagnew*log(0.00001)); + break; + default: + hgain=1.0-hmagnew; + }; + gain*=hgain; reduceamp+=hgain; - for (int nph=0;nph<numstages;nph++){ - REALTYPE amp=1.0; - if (nph==0) amp=gain; - initfilter(lfilter[nph+n*numstages],freq,bw,amp,hgain); - if (stereo!=0) initfilter(rfilter[nph+n*numstages],freq,bw,amp,hgain); - }; + for (int nph=0;nph<numstages;nph++) { + REALTYPE amp=1.0; + if (nph==0) amp=gain; + initfilter(lfilter[nph+n*numstages],freq,bw,amp,hgain); + if (stereo!=0) initfilter(rfilter[nph+n*numstages],freq,bw,amp,hgain); + }; }; - + if (reduceamp<0.001) reduceamp=1.0; volume/=reduceamp; - + oldpitchwheel=0; oldbandwidth=64; if (pars->Pfixedfreq==0) initparameters(basefreq); - else initparameters(basefreq/440.0*freq); + else initparameters(basefreq/440.0*freq); oldamplitude=newamplitude; ready=1; @@ -159,29 +170,30 @@ SUBnote::SUBnote(SUBnoteParameters *parameters,Controller *ctl_,REALTYPE freq,RE // initparameters(...) stuck together with some lines removed so that // it only alter the already playing note (to perform legato). It is // possible I left stuff that is not required for this. -void SUBnote::SUBlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool externcall){ +void SUBnote::SUBlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool externcall) +{ //SUBnoteParameters *parameters=pars; //Controller *ctl_=ctl; // Manage legato stuff if (externcall) Legato.msg=LM_Norm; - if (Legato.msg!=LM_CatchUp){ - Legato.lastfreq=Legato.param.freq; - Legato.param.freq=freq; - Legato.param.vel=velocity; - Legato.param.portamento=portamento_; - Legato.param.midinote=midinote; - if (Legato.msg==LM_Norm){ - if (Legato.silent){ - Legato.fade.m=0.0; - Legato.msg=LM_FadeIn; - } else { - Legato.fade.m=1.0; - Legato.msg=LM_FadeOut; - return; - } - } - if (Legato.msg==LM_ToNorm) Legato.msg=LM_Norm; + if (Legato.msg!=LM_CatchUp) { + Legato.lastfreq=Legato.param.freq; + Legato.param.freq=freq; + Legato.param.vel=velocity; + Legato.param.portamento=portamento_; + Legato.param.midinote=midinote; + if (Legato.msg==LM_Norm) { + if (Legato.silent) { + Legato.fade.m=0.0; + Legato.msg=LM_FadeIn; + } else { + Legato.fade.m=1.0; + Legato.msg=LM_FadeOut; + return; + } + } + if (Legato.msg==LM_ToNorm) Legato.msg=LM_Norm; } portamento=portamento_; @@ -197,78 +209,87 @@ void SUBnote::SUBlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, i if (pars->Pfixedfreq==0) basefreq=freq; else { - basefreq=440.0; - int fixedfreqET=pars->PfixedfreqET; - if (fixedfreqET!=0) {//if the frequency varies according the keyboard note - REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); - if (fixedfreqET<=64) basefreq*=pow(2.0,tmp); - else basefreq*=pow(3.0,tmp); - }; + basefreq=440.0; + int fixedfreqET=pars->PfixedfreqET; + if (fixedfreqET!=0) {//if the frequency varies according the keyboard note + REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); + if (fixedfreqET<=64) basefreq*=pow(2.0,tmp); + else basefreq*=pow(3.0,tmp); + }; }; REALTYPE detune=getdetune(pars->PDetuneType,pars->PCoarseDetune,pars->PDetune); basefreq*=pow(2.0,detune/1200.0);//detune //global filter GlobalFilterCenterPitch=pars->GlobalFilter->getfreq()+//center freq - (pars->PGlobalFilterVelocityScale/127.0*6.0)* //velocity sensing - (VelF(velocity,pars->PGlobalFilterVelocityScaleFunction)-1); + (pars->PGlobalFilterVelocityScale/127.0*6.0)* //velocity sensing + (VelF(velocity,pars->PGlobalFilterVelocityScaleFunction)-1); int legatonumharmonics=0; - for (int n=0;n<MAX_SUB_HARMONICS;n++){ - if (pars->Phmag[n]==0)continue; - if (n*basefreq>SAMPLE_RATE/2.0) break;//remove the freqs above the Nyquist freq - pos[legatonumharmonics++]=n; + for (int n=0;n<MAX_SUB_HARMONICS;n++) { + if (pars->Phmag[n]==0)continue; + if (n*basefreq>SAMPLE_RATE/2.0) break;//remove the freqs above the Nyquist freq + pos[legatonumharmonics++]=n; }; if (legatonumharmonics>firstnumharmonics) numharmonics=firstnumharmonics; else numharmonics=legatonumharmonics; if (numharmonics==0) { - NoteEnabled=OFF; - return; + NoteEnabled=OFF; + return; }; //how much the amplitude is normalised (because the harmonics) REALTYPE reduceamp=0.0; - for (int n=0;n<numharmonics;n++){ - - REALTYPE freq=basefreq*(pos[n]+1); + for (int n=0;n<numharmonics;n++) { - //the bandwidth is not absolute(Hz); it is relative to frequency - REALTYPE bw=pow(10,(pars->Pbandwidth-127.0)/127.0*4)*numstages; + REALTYPE freq=basefreq*(pos[n]+1); - //Bandwidth Scale - bw*=pow(1000/freq,(pars->Pbwscale-64.0)/64.0*3.0); + //the bandwidth is not absolute(Hz); it is relative to frequency + REALTYPE bw=pow(10,(pars->Pbandwidth-127.0)/127.0*4)*numstages; - //Relative BandWidth - bw*=pow(100,(pars->Phrelbw[pos[n]]-64.0)/64.0); + //Bandwidth Scale + bw*=pow(1000/freq,(pars->Pbwscale-64.0)/64.0*3.0); - if (bw>25.0) bw=25.0; + //Relative BandWidth + bw*=pow(100,(pars->Phrelbw[pos[n]]-64.0)/64.0); - //try to keep same amplitude on all freqs and bw. (empirically) - REALTYPE gain=sqrt(1500.0/(bw*freq)); + if (bw>25.0) bw=25.0; - REALTYPE hmagnew=1.0-pars->Phmag[pos[n]]/127.0; - REALTYPE hgain; + //try to keep same amplitude on all freqs and bw. (empirically) + REALTYPE gain=sqrt(1500.0/(bw*freq)); - switch(pars->Phmagtype){ - case 1:hgain=exp(hmagnew*log(0.01)); break; - case 2:hgain=exp(hmagnew*log(0.001));break; - case 3:hgain=exp(hmagnew*log(0.0001));break; - case 4:hgain=exp(hmagnew*log(0.00001));break; - default:hgain=1.0-hmagnew; - }; - gain*=hgain; - reduceamp+=hgain; + REALTYPE hmagnew=1.0-pars->Phmag[pos[n]]/127.0; + REALTYPE hgain; + + switch (pars->Phmagtype) { + case 1: + hgain=exp(hmagnew*log(0.01)); + break; + case 2: + hgain=exp(hmagnew*log(0.001)); + break; + case 3: + hgain=exp(hmagnew*log(0.0001)); + break; + case 4: + hgain=exp(hmagnew*log(0.00001)); + break; + default: + hgain=1.0-hmagnew; + }; + gain*=hgain; + reduceamp+=hgain; - for (int nph=0;nph<numstages;nph++){ - REALTYPE amp=1.0; - if (nph==0) amp=gain; - initfilter(lfilter[nph+n*numstages],freq,bw,amp,hgain); - if (stereo!=0) initfilter(rfilter[nph+n*numstages],freq,bw,amp,hgain); - }; + for (int nph=0;nph<numstages;nph++) { + REALTYPE amp=1.0; + if (nph==0) amp=gain; + initfilter(lfilter[nph+n*numstages],freq,bw,amp,hgain); + if (stereo!=0) initfilter(rfilter[nph+n*numstages],freq,bw,amp,hgain); + }; }; if (reduceamp<0.001) reduceamp=1.0; @@ -281,24 +302,25 @@ void SUBnote::SUBlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, i else freq*=basefreq/440.0; - /////////////// - // Altered initparameters(...) content: + /////////////// + // Altered initparameters(...) content: - if (pars->PGlobalFilterEnabled!=0){ - globalfiltercenterq=pars->GlobalFilter->getq(); - GlobalFilterFreqTracking=pars->GlobalFilter->getfreqtracking(basefreq); + if (pars->PGlobalFilterEnabled!=0) { + globalfiltercenterq=pars->GlobalFilter->getq(); + GlobalFilterFreqTracking=pars->GlobalFilter->getfreqtracking(basefreq); }; - // end of the altered initparameters function content. - /////////////// + // end of the altered initparameters function content. + /////////////// oldamplitude=newamplitude; - // End of the SUBlegatonote function. + // End of the SUBlegatonote function. }; -SUBnote::~SUBnote(){ +SUBnote::~SUBnote() +{ if (NoteEnabled!=OFF) KillNote(); delete [] tmpsmp; delete [] tmprnd; @@ -307,39 +329,42 @@ SUBnote::~SUBnote(){ /* * Kill the note */ -void SUBnote::KillNote(){ - if (NoteEnabled!=OFF){ - delete [] lfilter; - lfilter=NULL; - if (stereo!=0) delete [] rfilter; - rfilter=NULL; - delete(AmpEnvelope); - if (FreqEnvelope!=NULL) delete(FreqEnvelope); - if (BandWidthEnvelope!=NULL) delete(BandWidthEnvelope); - NoteEnabled=OFF; +void SUBnote::KillNote() +{ + if (NoteEnabled!=OFF) { + delete [] lfilter; + lfilter=NULL; + if (stereo!=0) delete [] rfilter; + rfilter=NULL; + delete(AmpEnvelope); + if (FreqEnvelope!=NULL) delete(FreqEnvelope); + if (BandWidthEnvelope!=NULL) delete(BandWidthEnvelope); + NoteEnabled=OFF; }; - + }; /* * Compute the filters coefficients */ -void SUBnote::computefiltercoefs(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE gain){ +void SUBnote::computefiltercoefs(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE gain) +{ if (freq>SAMPLE_RATE/2.0-200.0) { - freq=SAMPLE_RATE/2.0-200.0; + freq=SAMPLE_RATE/2.0-200.0; }; REALTYPE omega=2.0*PI*freq/SAMPLE_RATE; - REALTYPE sn=sin(omega);REALTYPE cs=cos(omega); + REALTYPE sn=sin(omega); + REALTYPE cs=cos(omega); REALTYPE alpha=sn*sinh(LOG_2/2.0*bw*omega/sn); if (alpha>1) alpha=1; if (alpha>bw) alpha=bw; - + filter.b0=alpha/(1.0+alpha)*filter.amp*gain; filter.b2=-alpha/(1.0+alpha)*filter.amp*gain; - filter.a1=-2.0*cs/(1.0+alpha); + filter.a1=-2.0*cs/(1.0+alpha); filter.a2=(1.0-alpha)/(1.0+alpha); }; @@ -348,29 +373,31 @@ void SUBnote::computefiltercoefs(bpfilter &filter,REALTYPE freq,REALTYPE bw,REAL /* * Initialise the filters */ -void SUBnote::initfilter(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE amp,REALTYPE mag){ - filter.xn1=0.0;filter.xn2=0.0; - +void SUBnote::initfilter(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE amp,REALTYPE mag) +{ + filter.xn1=0.0; + filter.xn2=0.0; + if (start==0) { - filter.yn1=0.0; - filter.yn2=0.0; + filter.yn1=0.0; + filter.yn2=0.0; } else { - REALTYPE a=0.1*mag;//empirically + REALTYPE a=0.1*mag;//empirically REALTYPE p=RND*2.0*PI; - if (start==1) a*=RND; - filter.yn1=a*cos(p); - filter.yn2=a*cos(p+freq*2.0*PI/SAMPLE_RATE); - - //correct the error of computation the start amplitude - //at very high frequencies - if (freq>SAMPLE_RATE*0.96) { - filter.yn1=0.0; - filter.yn2=0.0; - - }; + if (start==1) a*=RND; + filter.yn1=a*cos(p); + filter.yn2=a*cos(p+freq*2.0*PI/SAMPLE_RATE); + + //correct the error of computation the start amplitude + //at very high frequencies + if (freq>SAMPLE_RATE*0.96) { + filter.yn1=0.0; + filter.yn2=0.0; + + }; }; - filter.amp=amp; + filter.amp=amp; filter.freq=freq; filter.bw=bw; computefiltercoefs(filter,freq,bw,1.0); @@ -379,17 +406,18 @@ void SUBnote::initfilter(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE amp /* * Do the filtering */ -void SUBnote::filter(bpfilter &filter,REALTYPE *smps){ +void SUBnote::filter(bpfilter &filter,REALTYPE *smps) +{ int i; REALTYPE out; - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - out=smps[i] * filter.b0 + filter.b2 * filter.xn2 - -filter.a1 * filter.yn1 - filter.a2 * filter.yn2; - filter.xn2=filter.xn1; - filter.xn1=smps[i]; - filter.yn2=filter.yn1; - filter.yn1=out; - smps[i]=out; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + out=smps[i] * filter.b0 + filter.b2 * filter.xn2 + -filter.a1 * filter.yn1 - filter.a2 * filter.yn2; + filter.xn2=filter.xn1; + filter.xn1=smps[i]; + filter.yn2=filter.yn1; + filter.yn1=out; + smps[i]=out; }; }; @@ -397,18 +425,19 @@ void SUBnote::filter(bpfilter &filter,REALTYPE *smps){ /* * Init Parameters */ -void SUBnote::initparameters(REALTYPE freq){ +void SUBnote::initparameters(REALTYPE freq) +{ AmpEnvelope=new Envelope(pars->AmpEnvelope,freq); if (pars->PFreqEnvelopeEnabled!=0) FreqEnvelope=new Envelope(pars->FreqEnvelope,freq); - else FreqEnvelope=NULL; + else FreqEnvelope=NULL; if (pars->PBandWidthEnvelopeEnabled!=0) BandWidthEnvelope=new Envelope(pars->BandWidthEnvelope,freq); - else BandWidthEnvelope=NULL; - if (pars->PGlobalFilterEnabled!=0){ - globalfiltercenterq=pars->GlobalFilter->getq(); - GlobalFilterL=new Filter(pars->GlobalFilter); - if (stereo!=0) GlobalFilterR=new Filter(pars->GlobalFilter); - GlobalFilterEnvelope=new Envelope(pars->GlobalFilterEnvelope,freq); - GlobalFilterFreqTracking=pars->GlobalFilter->getfreqtracking(basefreq); + else BandWidthEnvelope=NULL; + if (pars->PGlobalFilterEnabled!=0) { + globalfiltercenterq=pars->GlobalFilter->getq(); + GlobalFilterL=new Filter(pars->GlobalFilter); + if (stereo!=0) GlobalFilterR=new Filter(pars->GlobalFilter); + GlobalFilterEnvelope=new Envelope(pars->GlobalFilterEnvelope,freq); + GlobalFilterFreqTracking=pars->GlobalFilter->getfreqtracking(basefreq); }; computecurrentparameters(); }; @@ -417,65 +446,68 @@ void SUBnote::initparameters(REALTYPE freq){ /* * Compute Parameters of SUBnote for each tick */ -void SUBnote::computecurrentparameters(){ +void SUBnote::computecurrentparameters() +{ if ((FreqEnvelope!=NULL)||(BandWidthEnvelope!=NULL)|| - (oldpitchwheel!=ctl->pitchwheel.data)|| - (oldbandwidth!=ctl->bandwidth.data)|| - (portamento!=0)){ - REALTYPE envfreq=1.0; - REALTYPE envbw=1.0; - REALTYPE gain=1.0; - - if (FreqEnvelope!=NULL) { - envfreq=FreqEnvelope->envout()/1200; - envfreq=pow(2.0,envfreq); - }; - envfreq*=ctl->pitchwheel.relfreq;//pitch wheel - if (portamento!=0) {//portamento is used - envfreq*=ctl->portamento.freqrap; - if (ctl->portamento.used==0){//the portamento has finished - portamento=0;//this note is no longer "portamented" - }; - }; - - if (BandWidthEnvelope!=NULL) { - envbw=BandWidthEnvelope->envout(); - envbw=pow(2,envbw); - }; - envbw*=ctl->bandwidth.relbw;//bandwidth controller - - REALTYPE tmpgain=1.0/sqrt(envbw*envfreq); - - for (int n=0;n<numharmonics;n++){ - for (int nph=0;nph<numstages;nph++) { - if (nph==0) gain=tmpgain;else gain=1.0; - computefiltercoefs( lfilter[nph+n*numstages], - lfilter[nph+n*numstages].freq*envfreq, - lfilter[nph+n*numstages].bw*envbw,gain); - }; - }; - if (stereo!=0) - for (int n=0;n<numharmonics;n++){ - for (int nph=0;nph<numstages;nph++) { - if (nph==0) gain=tmpgain;else gain=1.0; - computefiltercoefs( rfilter[nph+n*numstages], - rfilter[nph+n*numstages].freq*envfreq, - rfilter[nph+n*numstages].bw*envbw,gain); - }; - }; - oldbandwidth=ctl->bandwidth.data; - oldpitchwheel=ctl->pitchwheel.data; + (oldpitchwheel!=ctl->pitchwheel.data)|| + (oldbandwidth!=ctl->bandwidth.data)|| + (portamento!=0)) { + REALTYPE envfreq=1.0; + REALTYPE envbw=1.0; + REALTYPE gain=1.0; + + if (FreqEnvelope!=NULL) { + envfreq=FreqEnvelope->envout()/1200; + envfreq=pow(2.0,envfreq); + }; + envfreq*=ctl->pitchwheel.relfreq;//pitch wheel + if (portamento!=0) {//portamento is used + envfreq*=ctl->portamento.freqrap; + if (ctl->portamento.used==0) {//the portamento has finished + portamento=0;//this note is no longer "portamented" + }; + }; + + if (BandWidthEnvelope!=NULL) { + envbw=BandWidthEnvelope->envout(); + envbw=pow(2,envbw); + }; + envbw*=ctl->bandwidth.relbw;//bandwidth controller + + REALTYPE tmpgain=1.0/sqrt(envbw*envfreq); + + for (int n=0;n<numharmonics;n++) { + for (int nph=0;nph<numstages;nph++) { + if (nph==0) gain=tmpgain; + else gain=1.0; + computefiltercoefs( lfilter[nph+n*numstages], + lfilter[nph+n*numstages].freq*envfreq, + lfilter[nph+n*numstages].bw*envbw,gain); + }; + }; + if (stereo!=0) + for (int n=0;n<numharmonics;n++) { + for (int nph=0;nph<numstages;nph++) { + if (nph==0) gain=tmpgain; + else gain=1.0; + computefiltercoefs( rfilter[nph+n*numstages], + rfilter[nph+n*numstages].freq*envfreq, + rfilter[nph+n*numstages].bw*envbw,gain); + }; + }; + oldbandwidth=ctl->bandwidth.data; + oldpitchwheel=ctl->pitchwheel.data; }; newamplitude=volume*AmpEnvelope->envout_dB()*2.0; - + //Filter - if (GlobalFilterL!=NULL){ - REALTYPE globalfilterpitch=GlobalFilterCenterPitch+GlobalFilterEnvelope->envout(); - REALTYPE filterfreq=globalfilterpitch+ctl->filtercutoff.relfreq+GlobalFilterFreqTracking; - filterfreq=GlobalFilterL->getrealfreq(filterfreq); - - GlobalFilterL->setfreq_and_q(filterfreq,globalfiltercenterq*ctl->filterq.relq); - if (GlobalFilterR!=NULL) GlobalFilterR->setfreq_and_q(filterfreq,globalfiltercenterq*ctl->filterq.relq); + if (GlobalFilterL!=NULL) { + REALTYPE globalfilterpitch=GlobalFilterCenterPitch+GlobalFilterEnvelope->envout(); + REALTYPE filterfreq=globalfilterpitch+ctl->filtercutoff.relfreq+GlobalFilterFreqTracking; + filterfreq=GlobalFilterL->getrealfreq(filterfreq); + + GlobalFilterL->setfreq_and_q(filterfreq,globalfiltercenterq*ctl->filterq.relq); + if (GlobalFilterR!=NULL) GlobalFilterR->setfreq_and_q(filterfreq,globalfiltercenterq*ctl->filterq.relq); }; }; @@ -483,140 +515,143 @@ void SUBnote::computecurrentparameters(){ /* * Note Output */ -int SUBnote::noteout(REALTYPE *outl,REALTYPE *outr){ +int SUBnote::noteout(REALTYPE *outl,REALTYPE *outr) +{ int i; - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - outl[i]=denormalkillbuf[i]; - outr[i]=denormalkillbuf[i]; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + outl[i]=denormalkillbuf[i]; + outr[i]=denormalkillbuf[i]; }; - + if (NoteEnabled==OFF) return(0); //left channel for (i=0;i<SOUND_BUFFER_SIZE;i++) tmprnd[i]=RND*2.0-1.0; - for (int n=0;n<numharmonics;n++){ - for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpsmp[i]=tmprnd[i]; - for (int nph=0;nph<numstages;nph++) - filter(lfilter[nph+n*numstages],tmpsmp); - for (i=0;i<SOUND_BUFFER_SIZE;i++) outl[i]+=tmpsmp[i]; + for (int n=0;n<numharmonics;n++) { + for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpsmp[i]=tmprnd[i]; + for (int nph=0;nph<numstages;nph++) + filter(lfilter[nph+n*numstages],tmpsmp); + for (i=0;i<SOUND_BUFFER_SIZE;i++) outl[i]+=tmpsmp[i]; }; - if (GlobalFilterL!=NULL) GlobalFilterL->filterout(&outl[0]); - + if (GlobalFilterL!=NULL) GlobalFilterL->filterout(&outl[0]); + //right channel - if (stereo!=0){ - for (i=0;i<SOUND_BUFFER_SIZE;i++) tmprnd[i]=RND*2.0-1.0; - for (int n=0;n<numharmonics;n++){ - for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpsmp[i]=tmprnd[i]; - for (int nph=0;nph<numstages;nph++) - filter(rfilter[nph+n*numstages],tmpsmp); - for (i=0;i<SOUND_BUFFER_SIZE;i++) outr[i]+=tmpsmp[i]; - }; - if (GlobalFilterR!=NULL) GlobalFilterR->filterout(&outr[0]); + if (stereo!=0) { + for (i=0;i<SOUND_BUFFER_SIZE;i++) tmprnd[i]=RND*2.0-1.0; + for (int n=0;n<numharmonics;n++) { + for (i=0;i<SOUND_BUFFER_SIZE;i++) tmpsmp[i]=tmprnd[i]; + for (int nph=0;nph<numstages;nph++) + filter(rfilter[nph+n*numstages],tmpsmp); + for (i=0;i<SOUND_BUFFER_SIZE;i++) outr[i]+=tmpsmp[i]; + }; + if (GlobalFilterR!=NULL) GlobalFilterR->filterout(&outr[0]); } else for (i=0;i<SOUND_BUFFER_SIZE;i++) outr[i]=outl[i]; - - if (firsttick!=0){ - int n=10;if (n>SOUND_BUFFER_SIZE) n=SOUND_BUFFER_SIZE; - for (i=0;i<n;i++) { - REALTYPE ampfadein=0.5-0.5*cos((REALTYPE) i/(REALTYPE) n*PI); - outl[i]*=ampfadein; - outr[i]*=ampfadein; - }; - firsttick=0; + + if (firsttick!=0) { + int n=10; + if (n>SOUND_BUFFER_SIZE) n=SOUND_BUFFER_SIZE; + for (i=0;i<n;i++) { + REALTYPE ampfadein=0.5-0.5*cos((REALTYPE) i/(REALTYPE) n*PI); + outl[i]*=ampfadein; + outr[i]*=ampfadein; + }; + firsttick=0; }; - if (ABOVE_AMPLITUDE_THRESHOLD(oldamplitude,newamplitude)){ - // Amplitude interpolation - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - REALTYPE tmpvol=INTERPOLATE_AMPLITUDE(oldamplitude - ,newamplitude,i,SOUND_BUFFER_SIZE); - outl[i]*=tmpvol*panning; - outr[i]*=tmpvol*(1.0-panning); + if (ABOVE_AMPLITUDE_THRESHOLD(oldamplitude,newamplitude)) { + // Amplitude interpolation + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + REALTYPE tmpvol=INTERPOLATE_AMPLITUDE(oldamplitude + ,newamplitude,i,SOUND_BUFFER_SIZE); + outl[i]*=tmpvol*panning; + outr[i]*=tmpvol*(1.0-panning); }; } else { - for (i=0;i<SOUND_BUFFER_SIZE;i++) { - outl[i]*=newamplitude*panning; - outr[i]*=newamplitude*(1.0-panning); - }; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + outl[i]*=newamplitude*panning; + outr[i]*=newamplitude*(1.0-panning); + }; }; - oldamplitude=newamplitude; + oldamplitude=newamplitude; computecurrentparameters(); // Apply legato-specific sound signal modifications - if (Legato.silent){ // Silencer - if (Legato.msg!=LM_FadeIn){ - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - outl[i]=0.0; - outr[i]=0.0; - } - } + if (Legato.silent) { // Silencer + if (Legato.msg!=LM_FadeIn) { + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + outl[i]=0.0; + outr[i]=0.0; + } + } } - switch (Legato.msg){ + switch (Legato.msg) { case LM_CatchUp : // Continue the catch-up... - if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; - for (i=0;i<SOUND_BUFFER_SIZE;i++){//Yea, could be done without the loop... - Legato.decounter--; - if (Legato.decounter<1){ - // Catching-up done, we can finally set - // the note to the actual parameters. - Legato.decounter=-10; - Legato.msg=LM_ToNorm; - SUBlegatonote(Legato.param.freq, Legato.param.vel, Legato.param.portamento, Legato.param.midinote, false); - break; - } - } - break; + if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; + for (i=0;i<SOUND_BUFFER_SIZE;i++) {//Yea, could be done without the loop... + Legato.decounter--; + if (Legato.decounter<1) { + // Catching-up done, we can finally set + // the note to the actual parameters. + Legato.decounter=-10; + Legato.msg=LM_ToNorm; + SUBlegatonote(Legato.param.freq, Legato.param.vel, Legato.param.portamento, Legato.param.midinote, false); + break; + } + } + break; case LM_FadeIn : // Fade-in - if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; - Legato.silent=false; - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - Legato.decounter--; - if (Legato.decounter<1){ - Legato.decounter=-10; - Legato.msg=LM_Norm; - break; - } - Legato.fade.m+=Legato.fade.step; - outl[i]*=Legato.fade.m; - outr[i]*=Legato.fade.m; - } - break; + if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; + Legato.silent=false; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + Legato.decounter--; + if (Legato.decounter<1) { + Legato.decounter=-10; + Legato.msg=LM_Norm; + break; + } + Legato.fade.m+=Legato.fade.step; + outl[i]*=Legato.fade.m; + outr[i]*=Legato.fade.m; + } + break; case LM_FadeOut : // Fade-out, then set the catch-up - if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; - for (i=0;i<SOUND_BUFFER_SIZE;i++){ - Legato.decounter--; - if (Legato.decounter<1){ - for (int j=i;j<SOUND_BUFFER_SIZE;j++){ - outl[j]=0.0; - outr[j]=0.0; - } - Legato.decounter=-10; - Legato.silent=true; - // Fading-out done, now set the catch-up : - Legato.decounter=Legato.fade.length; - Legato.msg=LM_CatchUp; - REALTYPE catchupfreq=Legato.param.freq*(Legato.param.freq/Legato.lastfreq);//This freq should make this now silent note to catch-up (or should I say resync ?) with the heard note for the same length it stayed at the previous freq during the fadeout. - SUBlegatonote(catchupfreq, Legato.param.vel, Legato.param.portamento, Legato.param.midinote, false); - break; - } - Legato.fade.m-=Legato.fade.step; - outl[i]*=Legato.fade.m; - outr[i]*=Legato.fade.m; - } - break; - default : break; + if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; + for (i=0;i<SOUND_BUFFER_SIZE;i++) { + Legato.decounter--; + if (Legato.decounter<1) { + for (int j=i;j<SOUND_BUFFER_SIZE;j++) { + outl[j]=0.0; + outr[j]=0.0; + } + Legato.decounter=-10; + Legato.silent=true; + // Fading-out done, now set the catch-up : + Legato.decounter=Legato.fade.length; + Legato.msg=LM_CatchUp; + REALTYPE catchupfreq=Legato.param.freq*(Legato.param.freq/Legato.lastfreq);//This freq should make this now silent note to catch-up (or should I say resync ?) with the heard note for the same length it stayed at the previous freq during the fadeout. + SUBlegatonote(catchupfreq, Legato.param.vel, Legato.param.portamento, Legato.param.midinote, false); + break; + } + Legato.fade.m-=Legato.fade.step; + outl[i]*=Legato.fade.m; + outr[i]*=Legato.fade.m; + } + break; + default : + break; } // Check if the note needs to be computed more - if (AmpEnvelope->finished()!=0){ + if (AmpEnvelope->finished()!=0) { for (i=0;i<SOUND_BUFFER_SIZE;i++) {//fade-out - REALTYPE tmp=1.0-(REALTYPE)i/(REALTYPE)SOUND_BUFFER_SIZE; - outl[i]*=tmp; - outr[i]*=tmp; - }; - KillNote(); + REALTYPE tmp=1.0-(REALTYPE)i/(REALTYPE)SOUND_BUFFER_SIZE; + outl[i]*=tmp; + outr[i]*=tmp; + }; + KillNote(); }; return(1); }; @@ -624,7 +659,8 @@ int SUBnote::noteout(REALTYPE *outl,REALTYPE *outr){ /* * Relase Key (Note Off) */ -void SUBnote::relasekey(){ +void SUBnote::relasekey() +{ AmpEnvelope->relasekey(); if (FreqEnvelope!=NULL) FreqEnvelope->relasekey(); if (BandWidthEnvelope!=NULL) BandWidthEnvelope->relasekey(); @@ -634,8 +670,9 @@ void SUBnote::relasekey(){ /* * Check if the note is finished */ -int SUBnote::finished(){ - if (NoteEnabled==OFF) return(1); - else return(0); +int SUBnote::finished() +{ + if (NoteEnabled==OFF) return(1); + else return(0); }; diff --git a/src/Synth/SUBnote.h b/src/Synth/SUBnote.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + SUBnote.h - The subtractive synthesizer Copyright (C) 2002-2005 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 + 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, @@ -29,85 +29,86 @@ #include "Envelope.h" #include "../DSP/Filter.h" -class SUBnote{ - public: - SUBnote(SUBnoteParameters *parameters,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote,bool besilent); - ~SUBnote(); - - void SUBlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool externcall); - - int noteout(REALTYPE *outl,REALTYPE *outr);//note output,return 0 if the note is finished - void relasekey(); - int finished(); - - int ready; //if I can get the sampledata - - private: - - void computecurrentparameters(); - void initparameters(REALTYPE freq); - void KillNote(); - - SUBnoteParameters *pars; - - //parameters - int stereo; - int numstages;//number of stages of filters - int numharmonics;//number of harmonics (after the too higher hamonics are removed) - int firstnumharmonics;//To keep track of the first note's numharmonics value, useful in legato mode. - int start;//how the harmonics start - REALTYPE basefreq; - REALTYPE panning; - Envelope *AmpEnvelope; - Envelope *FreqEnvelope; - Envelope *BandWidthEnvelope; - - Filter *GlobalFilterL,*GlobalFilterR; - - Envelope *GlobalFilterEnvelope; - - //internal values - ONOFFTYPE NoteEnabled; - int firsttick,portamento; - REALTYPE volume,oldamplitude,newamplitude; - - REALTYPE GlobalFilterCenterPitch;//octaves - REALTYPE GlobalFilterFreqTracking; - - struct bpfilter{ - REALTYPE freq,bw,amp; //filter parameters - REALTYPE a1,a2,b0,b2;//filter coefs. b1=0 - REALTYPE xn1,xn2,yn1,yn2; //filter internal values - }; - - void initfilter(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE amp,REALTYPE mag); - void computefiltercoefs(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE gain); - void filter(bpfilter &filter,REALTYPE *smps); - - bpfilter *lfilter,*rfilter; - - REALTYPE *tmpsmp; - REALTYPE *tmprnd;//this is filled with random numbers - - Controller *ctl; - int oldpitchwheel,oldbandwidth; - REALTYPE globalfiltercenterq; - - // Legato vars - struct { - bool silent; - REALTYPE lastfreq; - LegatoMsg msg; - int decounter; - struct { // Fade In/Out vars - int length; - REALTYPE m, step; - } fade; - struct { // Note parameters - REALTYPE freq, vel; - int portamento, midinote; - } param; - } Legato; +class SUBnote +{ +public: + SUBnote(SUBnoteParameters *parameters,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote,bool besilent); + ~SUBnote(); + + void SUBlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool externcall); + + int noteout(REALTYPE *outl,REALTYPE *outr);//note output,return 0 if the note is finished + void relasekey(); + int finished(); + + int ready; //if I can get the sampledata + +private: + + void computecurrentparameters(); + void initparameters(REALTYPE freq); + void KillNote(); + + SUBnoteParameters *pars; + + //parameters + int stereo; + int numstages;//number of stages of filters + int numharmonics;//number of harmonics (after the too higher hamonics are removed) + int firstnumharmonics;//To keep track of the first note's numharmonics value, useful in legato mode. + int start;//how the harmonics start + REALTYPE basefreq; + REALTYPE panning; + Envelope *AmpEnvelope; + Envelope *FreqEnvelope; + Envelope *BandWidthEnvelope; + + Filter *GlobalFilterL,*GlobalFilterR; + + Envelope *GlobalFilterEnvelope; + + //internal values + ONOFFTYPE NoteEnabled; + int firsttick,portamento; + REALTYPE volume,oldamplitude,newamplitude; + + REALTYPE GlobalFilterCenterPitch;//octaves + REALTYPE GlobalFilterFreqTracking; + + struct bpfilter { + REALTYPE freq,bw,amp; //filter parameters + REALTYPE a1,a2,b0,b2;//filter coefs. b1=0 + REALTYPE xn1,xn2,yn1,yn2; //filter internal values + }; + + void initfilter(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE amp,REALTYPE mag); + void computefiltercoefs(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE gain); + void filter(bpfilter &filter,REALTYPE *smps); + + bpfilter *lfilter,*rfilter; + + REALTYPE *tmpsmp; + REALTYPE *tmprnd;//this is filled with random numbers + + Controller *ctl; + int oldpitchwheel,oldbandwidth; + REALTYPE globalfiltercenterq; + + // Legato vars + struct { + bool silent; + REALTYPE lastfreq; + LegatoMsg msg; + int decounter; + struct { // Fade In/Out vars + int length; + REALTYPE m, step; + } fade; + struct { // Note parameters + REALTYPE freq, vel; + int portamento, midinote; + } param; + } Legato; }; diff --git a/src/Tests/EchoTest.h b/src/Tests/EchoTest.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + EchoTest.h - CxxTest for Effect/Echo Copyright (C) 2009-2009 Mark McCurry Author: Mark McCurry 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 + 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, @@ -29,101 +29,98 @@ int SAMPLE_RATE=1024; class EchoTest : public CxxTest::TestSuite { - public: - void setUp() - { - outL=new float[SOUND_BUFFER_SIZE]; - for(int i=0;i<SOUND_BUFFER_SIZE;++i) - *(outL+i)=0; - outR=new float[SOUND_BUFFER_SIZE]; - for(int i=0;i<SOUND_BUFFER_SIZE;++i) - *(outR+i)=0; - inL=new float[SOUND_BUFFER_SIZE]; - for(int i=0;i<SOUND_BUFFER_SIZE;++i) - *(inL+i)=0; - inR=new float[SOUND_BUFFER_SIZE]; - for(int i=0;i<SOUND_BUFFER_SIZE;++i) - *(inR+i)=0; - testFX=new Echo(true,outL,outR); - } +public: + void setUp() { + outL=new float[SOUND_BUFFER_SIZE]; + for (int i=0;i<SOUND_BUFFER_SIZE;++i) + *(outL+i)=0; + outR=new float[SOUND_BUFFER_SIZE]; + for (int i=0;i<SOUND_BUFFER_SIZE;++i) + *(outR+i)=0; + inL=new float[SOUND_BUFFER_SIZE]; + for (int i=0;i<SOUND_BUFFER_SIZE;++i) + *(inL+i)=0; + inR=new float[SOUND_BUFFER_SIZE]; + for (int i=0;i<SOUND_BUFFER_SIZE;++i) + *(inR+i)=0; + testFX=new Echo(true,outL,outR); + } - void tearDown() - { - delete[] inL; - delete[] inR; - delete[] outL; - delete[] outR; - delete testFX; - } + void tearDown() { + delete[] inL; + delete[] inR; + delete[] outL; + delete[] outR; + delete testFX; + } - - void testInit() - { - //Make sure that the output will be zero at start - //(given a zero input) - testFX->out(inL,inR); - for(int i=0;i<SOUND_BUFFER_SIZE;++i) - TS_ASSERT_EQUALS(outL[i],0.0); - for(int i=0;i<SOUND_BUFFER_SIZE;++i) - TS_ASSERT_EQUALS(outR[i],0.0); - } - void testClear() - { - char DELAY=2; - testFX->changepar(DELAY,127); - for(int i=0;i<SOUND_BUFFER_SIZE;++i) - *(inL+i)=1.0; - for(int i=0;i<SOUND_BUFFER_SIZE;++i) - *(inR+i)=1.0; - for(int i=0;i<50;++i) - testFX->out(inL,inR); - for(int i=0;i<SOUND_BUFFER_SIZE;++i){ - TS_ASSERT_DIFFERS(outL[i],0.0); - TS_ASSERT_DIFFERS(outR[i],0.0)} - //After making sure the internal buffer has a nonzero value - //cleanup - //Then get the next output, which should be zereoed out if DELAY - //is large enough - testFX->cleanup(); + void testInit() { + //Make sure that the output will be zero at start + //(given a zero input) + testFX->out(inL,inR); + for (int i=0;i<SOUND_BUFFER_SIZE;++i) + TS_ASSERT_EQUALS(outL[i],0.0); + for (int i=0;i<SOUND_BUFFER_SIZE;++i) + TS_ASSERT_EQUALS(outR[i],0.0); + } + + void testClear() { + char DELAY=2; + testFX->changepar(DELAY,127); + for (int i=0;i<SOUND_BUFFER_SIZE;++i) + *(inL+i)=1.0; + for (int i=0;i<SOUND_BUFFER_SIZE;++i) + *(inR+i)=1.0; + for (int i=0;i<50;++i) testFX->out(inL,inR); - for(int i=0;i<SOUND_BUFFER_SIZE;++i){ - TS_ASSERT_DELTA(outL[i],0.0,0.0001); - TS_ASSERT_DELTA(outR[i],0.0,0.0001); - } + for (int i=0;i<SOUND_BUFFER_SIZE;++i) { + TS_ASSERT_DIFFERS(outL[i],0.0); + TS_ASSERT_DIFFERS(outR[i],0.0) + } + //After making sure the internal buffer has a nonzero value + //cleanup + //Then get the next output, which should be zereoed out if DELAY + //is large enough + testFX->cleanup(); + testFX->out(inL,inR); + for (int i=0;i<SOUND_BUFFER_SIZE;++i) { + TS_ASSERT_DELTA(outL[i],0.0,0.0001); + TS_ASSERT_DELTA(outR[i],0.0,0.0001); } - //Insures that the proper decay occurs with high feedback - void testDecaywFb() - { - for(int i=0;i<SOUND_BUFFER_SIZE;++i) - *(inL+i)=1.0; - for(int i=0;i<SOUND_BUFFER_SIZE;++i) - *(inR+i)=1.0; - char FEEDBACK=5; - testFX->changepar(FEEDBACK,127); - for(int i=0;i<4;++i) - testFX->out(inL,inR); - for(int i=0;i<SOUND_BUFFER_SIZE;++i){ - TS_ASSERT_DIFFERS(outL[i],0.0); - TS_ASSERT_DIFFERS(outR[i],0.0)} - float amp=abs(outL[0]+outR[0])/2; - //reset input to zero - for(int i=0;i<SOUND_BUFFER_SIZE;++i) - *(inL+i)=0.0; - for(int i=0;i<SOUND_BUFFER_SIZE;++i) - *(inR+i)=0.0; - //give the echo time to fade based upon zero input and high feedback - for(int i=0;i<50;++i) - testFX->out(inL,inR); - TS_ASSERT_LESS_THAN(abs(outL[0]+outR[0])/2, amp); + } + //Insures that the proper decay occurs with high feedback + void testDecaywFb() { + for (int i=0;i<SOUND_BUFFER_SIZE;++i) + *(inL+i)=1.0; + for (int i=0;i<SOUND_BUFFER_SIZE;++i) + *(inR+i)=1.0; + char FEEDBACK=5; + testFX->changepar(FEEDBACK,127); + for (int i=0;i<4;++i) + testFX->out(inL,inR); + for (int i=0;i<SOUND_BUFFER_SIZE;++i) { + TS_ASSERT_DIFFERS(outL[i],0.0); + TS_ASSERT_DIFFERS(outR[i],0.0) } + float amp=abs(outL[0]+outR[0])/2; + //reset input to zero + for (int i=0;i<SOUND_BUFFER_SIZE;++i) + *(inL+i)=0.0; + for (int i=0;i<SOUND_BUFFER_SIZE;++i) + *(inR+i)=0.0; + //give the echo time to fade based upon zero input and high feedback + for (int i=0;i<50;++i) + testFX->out(inL,inR); + TS_ASSERT_LESS_THAN(abs(outL[0]+outR[0])/2, amp); + } + - - private: - float *inL,*inR,*outR,*outL; - Echo *testFX; +private: + float *inL,*inR,*outR,*outL; + Echo *testFX; }; diff --git a/src/Tests/SampleTest.h b/src/Tests/SampleTest.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + SampleTest.h - CxxTest for Samples Copyright (C) 2009-2009 Mark McCurry Author: Mark McCurry 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 + 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, @@ -24,54 +24,49 @@ class SampleTest : public CxxTest::TestSuite { - public: - void testInit() - { - AuSample smp(10); - TS_ASSERT_EQUALS(smp.size(),10); - for(int i=0;i<20;++i) - TS_ASSERT_EQUALS(smp[i],0.0); - } +public: + void testInit() { + AuSample smp(10); + TS_ASSERT_EQUALS(smp.size(),10); + for (int i=0;i<20;++i) + TS_ASSERT_EQUALS(smp[i],0.0); + } - void testAssign() - { - AuSample smp(3); - smp[0]=0; - smp[1]=1; - smp[2]=2; - AuSample nsmp(40); - nsmp=smp; - TS_ASSERT_EQUALS(smp.size(),nsmp.size()); - for(int i=0;i<29;++i) - TS_ASSERT_EQUALS(smp[i],nsmp[i]); - } - void testBounds() - { - AuSample smp(0); - TS_ASSERT(smp.size()!=0); - } + void testAssign() { + AuSample smp(3); + smp[0]=0; + smp[1]=1; + smp[2]=2; + AuSample nsmp(40); + nsmp=smp; + TS_ASSERT_EQUALS(smp.size(),nsmp.size()); + for (int i=0;i<29;++i) + TS_ASSERT_EQUALS(smp[i],nsmp[i]); + } + void testBounds() { + AuSample smp(0); + TS_ASSERT(smp.size()!=0); + } - void testAllocDealloc() - { - float * fl=new float[50]; - for(int i=0;i<50;++i) - *(fl+i)=i; - AuSample smp(2); - smp = AuSample(fl, 50); - delete [] fl; - for(int i=0;i<50;++i) - TS_ASSERT_DELTA(smp[i],i,0.001); - smp = AuSample(3); - } + void testAllocDealloc() { + float * fl=new float[50]; + for (int i=0;i<50;++i) + *(fl+i)=i; + AuSample smp(2); + smp = AuSample(fl, 50); + delete [] fl; + for (int i=0;i<50;++i) + TS_ASSERT_DELTA(smp[i],i,0.001); + smp = AuSample(3); + } - void testClear() - { - AuSample smp(50); - for(int i=0;i<50;++i) - smp[i]=10; - smp.clear(); - for(int i=0;i<50;++i) - TS_ASSERT_EQUALS(smp[i],0); - } + void testClear() { + AuSample smp(50); + for (int i=0;i<50;++i) + smp[i]=10; + smp.clear(); + for (int i=0;i<50;++i) + TS_ASSERT_EQUALS(smp[i],0); + } }; diff --git a/src/globals.h b/src/globals.h @@ -1,13 +1,13 @@ /* ZynAddSubFX - a software synthesizer - globals.h - it contains program settings and the program capabilities + globals.h - it contains program settings and the program capabilities like number of parts, of effects Copyright (C) 2002-2005 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 + 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, @@ -28,7 +28,7 @@ //What float type I use for internal sampledata #define REALTYPE float -struct FFTFREQS{ +struct FFTFREQS { REALTYPE *s,*c;//sine and cosine components }; @@ -38,12 +38,12 @@ extern void deleteFFTFREQS(FFTFREQS *f); /**Sampling rate*/ extern int SAMPLE_RATE; -/** +/** * The size of a sound buffer (or the granularity) * All internal transfer of sound data use buffer of this size * All parameters are constant during this period of time, exception * some parameters(like amplitudes) which are linear interpolated. - * If you increase this you'll ecounter big latencies, but if you + * If you increase this you'll ecounter big latencies, but if you * decrease this the CPU requirements gets high. */ extern int SOUND_BUFFER_SIZE; @@ -107,7 +107,7 @@ extern int OSCIL_SIZE; #define NUM_INS_EFX 8 /* - * Number of part's insertion effects + * Number of part's insertion effects */ #define NUM_PART_EFX 3 @@ -142,7 +142,7 @@ extern int OSCIL_SIZE; #define MAX_FILTER_STAGES 5 /* - * Formant filter (FF) limits + * Formant filter (FF) limits */ #define FF_MAX_VOWELS 6 #define FF_MAX_FORMANTS 12 @@ -173,7 +173,7 @@ extern int OSCIL_SIZE; /* - * dB + * dB */ #define dB2rap(dB) ((exp((dB)*LOG_10/20.0))) #define rap2dB(rap) ((20*log(rap)/LOG_10)) @@ -185,16 +185,17 @@ extern int OSCIL_SIZE; #define ZERO(data,size) {char *data_=(char *) data;for (int i=0;i<size;i++) data_[i]=0;}; -enum ONOFFTYPE{OFF=0,ON=1}; +enum ONOFFTYPE {OFF=0,ON=1}; -enum MidiControllers{C_NULL=0,C_pitchwheel=1000,C_expression=11,C_panning=10, - C_filtercutoff=74,C_filterq=71,C_bandwidth=75,C_modwheel=1,C_fmamp=76, - C_volume=7,C_sustain=64,C_allnotesoff=123,C_allsoundsoff=120,C_resetallcontrollers=121, - C_portamento=65,C_resonance_center=77,C_resonance_bandwidth=78, +enum MidiControllers {C_NULL=0,C_pitchwheel=1000,C_expression=11,C_panning=10, + C_filtercutoff=74,C_filterq=71,C_bandwidth=75,C_modwheel=1,C_fmamp=76, + C_volume=7,C_sustain=64,C_allnotesoff=123,C_allsoundsoff=120,C_resetallcontrollers=121, + C_portamento=65,C_resonance_center=77,C_resonance_bandwidth=78, - C_dataentryhi=0x06,C_dataentrylo=0x26,C_nrpnhi=99,C_nrpnlo=98}; + C_dataentryhi=0x06,C_dataentrylo=0x26,C_nrpnhi=99,C_nrpnlo=98 + }; -enum LegatoMsg{LM_Norm, LM_FadeIn, LM_FadeOut, LM_CatchUp, LM_ToNorm}; +enum LegatoMsg {LM_Norm, LM_FadeIn, LM_FadeOut, LM_CatchUp, LM_ToNorm}; //is like i=(int)(floor(f)) #ifdef ASM_F2I_YES @@ -206,7 +207,7 @@ enum LegatoMsg{LM_Norm, LM_FadeIn, LM_FadeOut, LM_CatchUp, LM_ToNorm}; #ifndef O_BINARY -#define O_BINARY 0 +#define O_BINARY 0 #endif #endif diff --git a/src/main.C b/src/main.C @@ -6,7 +6,7 @@ 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 + 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, @@ -94,10 +94,11 @@ int Pexitprogram=0;//if the UI set this to 1, the program will exit /* * Try to get the realtime priority */ -void set_realtime(){ +void set_realtime() +{ #ifdef OS_LINUX sched_param sc; - + sc.sched_priority=50; //if you want get "sched_setscheduler undeclared" from compilation, you can safely remove the folowing line @@ -110,28 +111,29 @@ void set_realtime(){ * Midi input thread */ #if !(defined(WINMIDIIN)||defined(VSTMIDIIN)) -void *thread1(void *arg){ +void *thread1(void *arg) +{ MidiCmdType cmdtype=MidiNoteOFF; unsigned char cmdchan=0,note=0,vel=0; int cmdparams[MP_MAX_BYTES]; - for(int i=0;i<MP_MAX_BYTES;++i) + for (int i=0;i<MP_MAX_BYTES;++i) cmdparams[i]=0; set_realtime(); - while (Pexitprogram==0){ - Midi->getmidicmd(cmdtype,cmdchan,cmdparams); + while (Pexitprogram==0) { + Midi->getmidicmd(cmdtype,cmdchan,cmdparams); note=cmdparams[0]; - vel=cmdparams[1]; - - pthread_mutex_lock(&master->mutex); + vel=cmdparams[1]; - if ((cmdtype==MidiNoteON)&&(note!=0)) master->NoteOn(cmdchan,note,vel); - if ((cmdtype==MidiNoteOFF)&&(note!=0)) master->NoteOff(cmdchan,note); - if (cmdtype==MidiController) master->SetController(cmdchan,cmdparams[0],cmdparams[1]); + pthread_mutex_lock(&master->mutex); - pthread_mutex_unlock(&master->mutex); + if ((cmdtype==MidiNoteON)&&(note!=0)) master->NoteOn(cmdchan,note,vel); + if ((cmdtype==MidiNoteOFF)&&(note!=0)) master->NoteOff(cmdchan,note); + if (cmdtype==MidiController) master->SetController(cmdchan,cmdparams[0],cmdparams[1]); + + pthread_mutex_unlock(&master->mutex); }; - + return(0); }; #endif @@ -142,39 +144,40 @@ void *thread1(void *arg){ #if defined(OSSAUDIOOUT) //!(defined(JACKAUDIOOUT)||defined(JACK_RTAUDIOOUT)||defined(PAAUDIOOUT)||defined(VSTAUDIOOUT)) -void *thread2(void *arg){ +void *thread2(void *arg) +{ REALTYPE outputl[SOUND_BUFFER_SIZE]; REALTYPE outputr[SOUND_BUFFER_SIZE]; set_realtime(); - while (Pexitprogram==0){ - pthread_mutex_lock(&master->mutex); - master->AudioOut(outputl,outputr); - pthread_mutex_unlock(&master->mutex); + while (Pexitprogram==0) { + pthread_mutex_lock(&master->mutex); + master->AudioOut(outputl,outputr); + pthread_mutex_unlock(&master->mutex); #ifndef NONEAUDIOOUT - audioout->OSSout(outputl,outputr); -#endif - -/** / int i,x,x2; - REALTYPE xx,xx2; - - short int xsmps[SOUND_BUFFER_SIZE*2]; - for (i=0;i<SOUND_BUFFER_SIZE;i++){//output to stdout - xx=-outputl[i]*32767; - xx2=-outputr[i]*32767; - if (xx<-32768) xx=-32768; - if (xx>32767) xx=32767; - if (xx2<-32768) xx2=-32768; - if (xx2>32767) xx2=32767; - x=(short int) xx; - x2=(short int) xx2; - xsmps[i*2]=x;xsmps[i*2+1]=x2; - }; - write(1,&xsmps,SOUND_BUFFER_SIZE*2*2); - - / * */ - }; + audioout->OSSout(outputl,outputr); +#endif + + /** / int i,x,x2; + REALTYPE xx,xx2; + + short int xsmps[SOUND_BUFFER_SIZE*2]; + for (i=0;i<SOUND_BUFFER_SIZE;i++){//output to stdout + xx=-outputl[i]*32767; + xx2=-outputr[i]*32767; + if (xx<-32768) xx=-32768; + if (xx>32767) xx=32767; + if (xx2<-32768) xx2=-32768; + if (xx2>32767) xx2=32767; + x=(short int) xx; + x2=(short int) xx2; + xsmps[i*2]=x;xsmps[i*2+1]=x2; + }; + write(1,&xsmps,SOUND_BUFFER_SIZE*2*2); + + / * */ + }; return(0); }; #endif @@ -182,30 +185,31 @@ void *thread2(void *arg){ /* * User Interface thread */ - - -void *thread3(void *arg){ + + +void *thread3(void *arg) +{ #ifndef DISABLE_GUI ui->showUI(); while (Pexitprogram==0) { #ifdef USE_LASH - string filename; - switch (lash->checkevents(filename)) { - case LASHClient::Save: - ui->do_save_master(filename); - lash->confirmevent(LASHClient::Save); - break; - case LASHClient::Restore: - ui->do_load_master(filename); - lash->confirmevent(LASHClient::Restore); - break; - case LASHClient::Quit: - Pexitprogram = 1; - default: - break; - } -#endif - Fl::wait(); + string filename; + switch (lash->checkevents(filename)) { + case LASHClient::Save: + ui->do_save_master(filename); + lash->confirmevent(LASHClient::Save); + break; + case LASHClient::Restore: + ui->do_load_master(filename); + lash->confirmevent(LASHClient::Restore); + break; + case LASHClient::Quit: + Pexitprogram = 1; + default: + break; + } +#endif + Fl::wait(); } #endif return(0); @@ -214,40 +218,41 @@ void *thread3(void *arg){ /* * Sequencer thread (test) */ -void *thread4(void *arg){ - while (Pexitprogram==0){ - int type,par1,par2,again,midichan; - for (int ntrack=0;ntrack<NUM_MIDI_TRACKS;ntrack++){ - if (master->seq.play==0) break; - do{ - again=master->seq.getevent(ntrack,&midichan,&type,&par1,&par2); +void *thread4(void *arg) +{ + while (Pexitprogram==0) { + int type,par1,par2,again,midichan; + for (int ntrack=0;ntrack<NUM_MIDI_TRACKS;ntrack++) { + if (master->seq.play==0) break; + do { + again=master->seq.getevent(ntrack,&midichan,&type,&par1,&par2); // printf("ntrack=%d again=%d\n",ntrack,again); - if (type>0) { + if (type>0) { // printf("%d %d %d %d %d\n",type,midichan,chan,par1,par2); // if (cmdtype==MidiController) master->SetController(cmdchan,cmdparams[0],cmdparams[1]); - - - pthread_mutex_lock(&master->mutex); - if (type==1){//note_on or note_off - if (par2!=0) master->NoteOn(midichan,par1,par2); - else master->NoteOff(midichan,par1); - }; - pthread_mutex_unlock(&master->mutex); - }; - } while (again>0); - - }; + + + pthread_mutex_lock(&master->mutex); + if (type==1) {//note_on or note_off + if (par2!=0) master->NoteOn(midichan,par1,par2); + else master->NoteOff(midichan,par1); + }; + pthread_mutex_unlock(&master->mutex); + }; + } while (again>0); + + }; //if (!realtime player) atunci fac asta //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #ifdef OS_LINUX - usleep(1000); + usleep(1000); #elif OS_WINDOWS - Sleep(1); + Sleep(1); #endif }; - + return(0); }; @@ -256,7 +261,8 @@ void *thread4(void *arg){ */ -void initprogram(){ +void initprogram() +{ cerr.precision(1); cerr << std::fixed; #ifndef JACKAUDIOOUT @@ -272,27 +278,27 @@ void initprogram(){ srand(time(NULL)); denormalkillbuf=new REALTYPE [SOUND_BUFFER_SIZE]; for (int i=0;i<SOUND_BUFFER_SIZE;i++) denormalkillbuf[i]=(RND-0.5)*1e-16; - + OscilGen::tmpsmps=new REALTYPE[OSCIL_SIZE]; newFFTFREQS(&OscilGen::outoscilFFTfreqs,OSCIL_SIZE/2); - + master=new Master(); master->swaplr=swaplr; #if defined(JACKAUDIOOUT) if (usejackit) { - bool tmp=JACKaudiooutputinit(master); + bool tmp=JACKaudiooutputinit(master); #if defined(OSSAUDIOOUT) - if (!tmp) cout << "\nUsing OSS instead." << endl; + if (!tmp) cout << "\nUsing OSS instead." << endl; #else - if (!tmp) exit(1); + if (!tmp) exit(1); #endif - usejackit=tmp; + usejackit=tmp; }; #endif #if defined(OSSAUDIOOUT) if (!usejackit) audioout=new OSSaudiooutput(); - else audioout=NULL; + else audioout=NULL; #endif #ifdef JACK_RTAUDIOOUT @@ -300,7 +306,7 @@ void initprogram(){ #endif #ifdef PAAUDIOOUT PAaudiooutputinit(master); -#endif +#endif #ifdef ALSAMIDIIN Midi=new ALSAMidiIn(); @@ -319,7 +325,8 @@ void initprogram(){ /* * Program exit */ -void exitprogram(){ +void exitprogram() +{ pthread_mutex_lock(&master->mutex); #ifdef OSSAUDIOOUT delete(audioout); @@ -338,7 +345,7 @@ void exitprogram(){ delete(ui); #endif delete(Midi); - delete(master); + delete(master); #ifdef USE_LASH delete(lash); @@ -353,30 +360,32 @@ void exitprogram(){ #ifdef OS_WINDOWS #define ARGSIZE 100 - char winoptarguments[ARGSIZE]; - char getopt(int argc, char *argv[], const char *shortopts, int *index){ +char winoptarguments[ARGSIZE]; +char getopt(int argc, char *argv[], const char *shortopts, int *index) +{ winoptarguments[0]=0; char result=0; - + if (*index>=argc) return(-1); - - if (strlen(argv[*index])==2) - if (argv[*index][0]=='-') { - result=argv[*index][1]; - if (*index+1<argc) { - snprintf(winoptarguments,ARGSIZE,"%s",argv[*index+1]); - }; - }; + + if (strlen(argv[*index])==2) + if (argv[*index][0]=='-') { + result=argv[*index][1]; + if (*index+1<argc) { + snprintf(winoptarguments,ARGSIZE,"%s",argv[*index+1]); + }; + }; (*index)++; return(result); - }; - int opterr=0; +}; +int opterr=0; #undef ARGSIZE - + #endif #ifndef VSTAUDIOOUT -int main(int argc, char *argv[]){ +int main(int argc, char *argv[]) +{ #ifdef USE_LASH lash = new LASHClient(&argc, &argv); @@ -398,182 +407,194 @@ int main(int argc, char *argv[]){ if (argc==1) cerr << "Try 'zynaddsubfx -h' for command-line options.\n" << endl; #endif /* Get the settings from the Config*/ - SAMPLE_RATE=config.cfg.SampleRate; + SAMPLE_RATE=config.cfg.SampleRate; SOUND_BUFFER_SIZE=config.cfg.SoundBufferSize; OSCIL_SIZE=config.cfg.OscilSize; swaplr=config.cfg.SwapStereo; - + /* Parse command-line options */ #ifdef OS_LINUX struct option opts[]={ - {"load",2,NULL,'l'}, - {"load-instrument",2,NULL,'L'}, - {"sample-rate",2,NULL,'r'}, - {"buffer-size",2,NULL,'b'}, - {"oscil-size",2,NULL,'o'}, - {"dump",2,NULL,'D'}, - {"swap",2,NULL,'S'}, - {"no-gui",2,NULL,'U'}, - {"not-use-jack",2,NULL,'A'}, - {"dummy",2,NULL,'Y'}, - {"help",2,NULL,'h'}, - {0,0,0,0} + {"load",2,NULL,'l'}, + {"load-instrument",2,NULL,'L'}, + {"sample-rate",2,NULL,'r'}, + {"buffer-size",2,NULL,'b'}, + {"oscil-size",2,NULL,'o'}, + {"dump",2,NULL,'D'}, + {"swap",2,NULL,'S'}, + {"no-gui",2,NULL,'U'}, + {"not-use-jack",2,NULL,'A'}, + {"dummy",2,NULL,'Y'}, + {"help",2,NULL,'h'}, + {0,0,0,0} }; #endif opterr=0; int option_index=0,opt,exitwithhelp=0; - - char loadfile[1001];ZERO(loadfile,1001); - char loadinstrument[1001];ZERO(loadinstrument,1001); - - while (1){ + + char loadfile[1001]; + ZERO(loadfile,1001); + char loadinstrument[1001]; + ZERO(loadinstrument,1001); + + while (1) { /**\todo check this process for a small memory leak*/ #ifdef OS_LINUX - opt=getopt_long(argc,argv,"l:L:r:b:o:hSDUAY",opts,&option_index); - char *optarguments=optarg; + opt=getopt_long(argc,argv,"l:L:r:b:o:hSDUAY",opts,&option_index); + char *optarguments=optarg; #else - opt=getopt(argc,argv,"l:L:r:b:o:hSDUAY",&option_index); - char *optarguments=&winoptarguments[0]; -#endif - - if (opt==-1) break; - - int tmp; - switch(opt){ - case 'h':exitwithhelp=1; - break; - case 'Y':/* this command a dummy command (has NO effect) - and is used because I need for NSIS installer - (NSIS sometimes forces a command line for a - program, even if I don't need that; eg. when + opt=getopt(argc,argv,"l:L:r:b:o:hSDUAY",&option_index); + char *optarguments=&winoptarguments[0]; +#endif + + if (opt==-1) break; + + int tmp; + switch (opt) { + case 'h': + exitwithhelp=1; + break; + case 'Y':/* this command a dummy command (has NO effect) + and is used because I need for NSIS installer + (NSIS sometimes forces a command line for a + program, even if I don't need that; eg. when I want to add a icon to a shortcut. */ - break; - case 'U':noui=1; - break; - case 'A': + break; + case 'U': + noui=1; + break; + case 'A': #ifdef JACKAUDIOOUT #ifdef OSSAUDIOOUT - usejackit=false; -#endif -#endif - break; - case 'l':tmp=0; - if (optarguments!=NULL) { - snprintf(loadfile,1000,"%s",optarguments); - }; - break; - case 'L':tmp=0; - if (optarguments!=NULL) { - snprintf(loadinstrument,1000,"%s",optarguments); - }; - break; - case 'r':tmp=0; - if (optarguments!=NULL) tmp=atoi(optarguments); - if (tmp>=4000) { - SAMPLE_RATE=tmp; - } else { - cerr << "ERROR:Incorrect sample rate: " << optarguments << endl; - exit(1); - }; - break; - case 'b':tmp=0; - if (optarguments!=NULL) tmp=atoi(optarguments); - if (tmp>=2) { - SOUND_BUFFER_SIZE=tmp; - } else { - cerr << "ERROR:Incorrect buffer size: " << optarguments << endl; - exit(1); - }; - break; - case 'o':tmp=0; - if (optarguments!=NULL) tmp=atoi(optarguments); - OSCIL_SIZE=tmp; - if (OSCIL_SIZE<MAX_AD_HARMONICS*2) OSCIL_SIZE=MAX_AD_HARMONICS*2; - OSCIL_SIZE=(int) pow(2,ceil(log (OSCIL_SIZE-1.0)/log(2.0))); - if (tmp!=OSCIL_SIZE){ - cerr << "\nOSCIL_SIZE is wrong (must be 2^n) or too small. Adjusting to "; - cerr << OSCIL_SIZE << "." << endl; - } - break; - case 'S':swaplr=1; - break; - case 'D':dump.startnow(); - break; - case '?':cerr << "ERROR:Bad option or parameter.\n" << endl; - exitwithhelp=1; - break; - }; + usejackit=false; +#endif +#endif + break; + case 'l': + tmp=0; + if (optarguments!=NULL) { + snprintf(loadfile,1000,"%s",optarguments); + }; + break; + case 'L': + tmp=0; + if (optarguments!=NULL) { + snprintf(loadinstrument,1000,"%s",optarguments); + }; + break; + case 'r': + tmp=0; + if (optarguments!=NULL) tmp=atoi(optarguments); + if (tmp>=4000) { + SAMPLE_RATE=tmp; + } else { + cerr << "ERROR:Incorrect sample rate: " << optarguments << endl; + exit(1); + }; + break; + case 'b': + tmp=0; + if (optarguments!=NULL) tmp=atoi(optarguments); + if (tmp>=2) { + SOUND_BUFFER_SIZE=tmp; + } else { + cerr << "ERROR:Incorrect buffer size: " << optarguments << endl; + exit(1); + }; + break; + case 'o': + tmp=0; + if (optarguments!=NULL) tmp=atoi(optarguments); + OSCIL_SIZE=tmp; + if (OSCIL_SIZE<MAX_AD_HARMONICS*2) OSCIL_SIZE=MAX_AD_HARMONICS*2; + OSCIL_SIZE=(int) pow(2,ceil(log (OSCIL_SIZE-1.0)/log(2.0))); + if (tmp!=OSCIL_SIZE) { + cerr << "\nOSCIL_SIZE is wrong (must be 2^n) or too small. Adjusting to "; + cerr << OSCIL_SIZE << "." << endl; + } + break; + case 'S': + swaplr=1; + break; + case 'D': + dump.startnow(); + break; + case '?': + cerr << "ERROR:Bad option or parameter.\n" << endl; + exitwithhelp=1; + break; + }; }; - + if (exitwithhelp!=0) { - cout << "Usage: zynaddsubfx [OPTION]\n" << endl; - cout << " -h , --help \t\t\t\t display command-line help and exit" << endl; - cout << " -l file, --load=FILE\t\t\t loads a .xmz file" << endl; - cout << " -L file, --load-instrument=FILE\t\t loads a .xiz file" << endl; - cout << " -r SR, --sample-rate=SR\t\t set the sample rate SR" << endl; - cout << " -b BS, --buffer-size=SR\t\t set the buffer size (granularity)" << endl; - cout << " -o OS, --oscil-size=OS\t\t set the ADsynth oscil. size" << endl; - cout << " -S , --swap\t\t\t\t swap Left <--> Right" << endl; - cout << " -D , --dump\t\t\t\t Dumps midi note ON/OFF commands" << endl; - cout << " -U , --no-gui\t\t\t\t Run ZynAddSubFX without user interface" << endl; + cout << "Usage: zynaddsubfx [OPTION]\n" << endl; + cout << " -h , --help \t\t\t\t display command-line help and exit" << endl; + cout << " -l file, --load=FILE\t\t\t loads a .xmz file" << endl; + cout << " -L file, --load-instrument=FILE\t\t loads a .xiz file" << endl; + cout << " -r SR, --sample-rate=SR\t\t set the sample rate SR" << endl; + cout << " -b BS, --buffer-size=SR\t\t set the buffer size (granularity)" << endl; + cout << " -o OS, --oscil-size=OS\t\t set the ADsynth oscil. size" << endl; + cout << " -S , --swap\t\t\t\t swap Left <--> Right" << endl; + cout << " -D , --dump\t\t\t\t Dumps midi note ON/OFF commands" << endl; + cout << " -U , --no-gui\t\t\t\t Run ZynAddSubFX without user interface" << endl; #ifdef JACKAUDIOOUT #ifdef OSSAUDIOOUT - cout << " -A , --not-use-jack\t\t\t Use OSS/ALSA instead of JACK" << endl; + cout << " -A , --not-use-jack\t\t\t Use OSS/ALSA instead of JACK" << endl; #endif #endif #ifdef OS_WINDOWS - cout << "\nWARNING: On Windows systems, only short comandline parameters works." << endl; - cout << " eg. instead '--buffer-size=512' use '-b 512'" << endl; + cout << "\nWARNING: On Windows systems, only short comandline parameters works." << endl; + cout << " eg. instead '--buffer-size=512' use '-b 512'" << endl; #endif - cout << '\n' << endl; - return(0); + cout << '\n' << endl; + return(0); }; - + //--------- - + initprogram(); #ifdef USE_LASH #ifdef ALSAMIDIIN ALSAMidiIn* alsamidi = dynamic_cast<ALSAMidiIn*>(Midi); if (alsamidi) - lash->setalsaid(alsamidi->getalsaid()); + lash->setalsaid(alsamidi->getalsaid()); #endif #ifdef JACKAUDIOOUT lash->setjackname(JACKgetname()); #endif #endif - if (strlen(loadfile)>1){ + if (strlen(loadfile)>1) { int tmp=master->loadXML(loadfile); - if (tmp<0) { - fprintf(stderr,"ERROR:Could not load master file %s .\n",loadfile); - exit(1); - } else { - master->applyparameters(); + if (tmp<0) { + fprintf(stderr,"ERROR:Could not load master file %s .\n",loadfile); + exit(1); + } else { + master->applyparameters(); #ifndef DISABLE_GUI - if (noui==0) ui->refresh_master_ui(); + if (noui==0) ui->refresh_master_ui(); #endif - cout << "Master file loaded." << endl; - }; + cout << "Master file loaded." << endl; + }; }; - if (strlen(loadinstrument)>1){ - int loadtopart=0; + if (strlen(loadinstrument)>1) { + int loadtopart=0; int tmp=master->part[loadtopart]->loadXMLinstrument(loadinstrument); - if (tmp<0) { - cerr << "ERROR:Could not load instrument file " << loadinstrument << '.' << endl; - exit(1); - } else { - master->part[loadtopart]->applyparameters(); + if (tmp<0) { + cerr << "ERROR:Could not load instrument file " << loadinstrument << '.' << endl; + exit(1); + } else { + master->part[loadtopart]->applyparameters(); #ifndef DISABLE_GUI - if (noui==0) ui->refresh_master_ui(); + if (noui==0) ui->refresh_master_ui(); #endif - cout << "Instrument file loaded." << endl; - }; + cout << "Instrument file loaded." << endl; + }; }; - + #if !(defined(NONEMIDIIN)||defined(WINMIDIIN)||defined(VSTMIDIIN)) pthread_create(&thr1,NULL,thread1,NULL); @@ -584,32 +605,32 @@ int main(int argc, char *argv[]){ if (!usejackit) pthread_create(&thr2,NULL,thread2,NULL); #endif -/*It is not working and I don't know why -//drop the suid-root permisions -#if !(defined(JACKAUDIOOUT)||defined(PAAUDIOOUT)||defined(VSTAUDIOOUT)|| (defined (WINMIDIIN)) ) - setuid(getuid()); - seteuid(getuid()); -// setreuid(getuid(),getuid()); -// setregid(getuid(),getuid()); -#endif -*/ + /*It is not working and I don't know why + //drop the suid-root permisions + #if !(defined(JACKAUDIOOUT)||defined(PAAUDIOOUT)||defined(VSTAUDIOOUT)|| (defined (WINMIDIIN)) ) + setuid(getuid()); + seteuid(getuid()); + // setreuid(getuid(),getuid()); + // setregid(getuid(),getuid()); + #endif + */ if (noui==0) pthread_create(&thr3,NULL,thread3,NULL); pthread_create(&thr4,NULL,thread4,NULL); #ifdef WINMIDIIN - InitWinMidi(master); + InitWinMidi(master); #endif - while (Pexitprogram==0){ + while (Pexitprogram==0) { #ifdef OS_LINUX - usleep(100000); + usleep(100000); #elif OS_WINDOWS - Sleep(100); + Sleep(100); #endif - }; - + }; + #ifdef WINMIDIIN - StopWinMidi(); + StopWinMidi(); #endif exitprogram(); @@ -617,7 +638,7 @@ int main(int argc, char *argv[]){ }; -#else +#else #include "Output/VSTaudiooutput.h" @@ -626,16 +647,17 @@ extern "C" __declspec(dllexport) AEffect *main_plugin(audioMasterCallback audioM int instances=-1; -AEffect *main (audioMasterCallback audioMaster){ +AEffect *main (audioMasterCallback audioMaster) +{ // if (audioMaster(0,audioMasterVersion,0,0,0,0)!=0) { // return(0); // }; - if (instances==-1){ - Midi=new NULLMidiIn(); - denormalkillbuf=new REALTYPE [SOUND_BUFFER_SIZE]; - for (int i=0;i<SOUND_BUFFER_SIZE;i++) denormalkillbuf[i]=(RND-0.5)*1e-16; - instances=0; + if (instances==-1) { + Midi=new NULLMidiIn(); + denormalkillbuf=new REALTYPE [SOUND_BUFFER_SIZE]; + for (int i=0;i<SOUND_BUFFER_SIZE;i++) denormalkillbuf[i]=(RND-0.5)*1e-16; + instances=0; }; if (instances!=0) return(0);//don't allow multiple instances @@ -646,76 +668,79 @@ AEffect *main (audioMasterCallback audioMaster){ }; void* hInstance; -BOOL WINAPI DllMain (HINSTANCE hInst,DWORD dwReason,LPVOID lpvReserved){ +BOOL WINAPI DllMain (HINSTANCE hInst,DWORD dwReason,LPVOID lpvReserved) +{ hInstance=hInst; return(1); }; -void *thread(void *arg){ +void *thread(void *arg) +{ VSTSynth *vs=(VSTSynth *) arg; -/* FILE *a=fopen("aaaa1","a"); - fprintf(a,"%lx %lx %lx -i=%d\n",vs,0,vs->vmaster,instances); - fflush(a);fclose(a); -*/ + /* FILE *a=fopen("aaaa1","a"); + fprintf(a,"%lx %lx %lx -i=%d\n",vs,0,vs->vmaster,instances); + fflush(a);fclose(a); + */ vs->ui=new MasterUI(vs->vmaster,&vs->Pexitprogram); -/* a=fopen("aaaa1","a"); - fprintf(a,"%lx %lx %lx\n",vs,vs->ui->master,vs->vmaster); - fflush(a);fclose(a); -*/ + /* a=fopen("aaaa1","a"); + fprintf(a,"%lx %lx %lx\n",vs,vs->ui->master,vs->vmaster); + fflush(a);fclose(a); + */ vs->ui->showUI(); -/* a=fopen("aaaa1","a"); - fprintf(a,"%lx %lx %lx\n",vs,vs->ui,vs->vmaster); - fflush(a);fclose(a); -*/ + /* a=fopen("aaaa1","a"); + fprintf(a,"%lx %lx %lx\n",vs,vs->ui,vs->vmaster); + fflush(a);fclose(a); + */ while (vs->Pexitprogram==0) Fl::wait(0.01); delete(vs->ui); Fl::wait(0.01); -/* a=fopen("aaaa1","a"); - fprintf(a,"EXIT\n"); - fflush(a);fclose(a); -*/ + /* a=fopen("aaaa1","a"); + fprintf(a,"EXIT\n"); + fflush(a);fclose(a); + */ + - pthread_exit(0); return(0); }; //Parts of the VSTSynth class -VSTSynth::VSTSynth (audioMasterCallback audioMaster):AudioEffectX(audioMaster,1,0){ +VSTSynth::VSTSynth (audioMasterCallback audioMaster):AudioEffectX(audioMaster,1,0) +{ instances++; - if (audioMaster){ - setNumInputs(0); - setNumOutputs(2); - setUniqueID('ZASF'); - canProcessReplacing(); + if (audioMaster) { + setNumInputs(0); + setNumOutputs(2); + setUniqueID('ZASF'); + canProcessReplacing(); // hasVu(false); // hasClip(false); - isSynth(true); + isSynth(true); + + programsAreChunks(true); - programsAreChunks(true); - - }; + }; - SAMPLE_RATE=config.cfg.SampleRate; + SAMPLE_RATE=config.cfg.SampleRate; SOUND_BUFFER_SIZE=config.cfg.SoundBufferSize; OSCIL_SIZE=config.cfg.OscilSize; swaplr=config.cfg.SwapStereo; this->Pexitprogram=0; - + this->vmaster=new Master(); this->vmaster->swaplr=swaplr; - + // FILE *a=fopen("aaaa0","a"); // fprintf(a,"%lx %lx %lx\n",this,this->ui,this->ui->masterwindow); @@ -729,61 +754,69 @@ VSTSynth::VSTSynth (audioMasterCallback audioMaster):AudioEffectX(audioMaster,1, -VSTSynth::~VSTSynth(){ +VSTSynth::~VSTSynth() +{ this->Pexitprogram=1; - + Sleep(200);//wait the thread to finish - + // pthread_mutex_lock(&vmaster->mutex); - delete(this->vmaster); + delete(this->vmaster); instances--; }; -long VSTSynth::processEvents(VstEvents *events){ - for (int i=0;i<events->numEvents;i++){ +long VSTSynth::processEvents(VstEvents *events) +{ + for (int i=0;i<events->numEvents;i++) { - //debug stuff + //debug stuff // FILE *a=fopen("events","a"); // fprintf(a,"%lx\n",events->events[i]->type); // fflush(a);fclose(a); - if ((events->events[i])->type != kVstMidiType) continue; - VstMidiEvent *ev= (VstMidiEvent*) events->events[i]; - unsigned char *data= (unsigned char *)ev->midiData; - int status=data[0]/16; - int cmdchan=data[0]&0x0f; - int cntl; - - pthread_mutex_lock(&vmaster->mutex); - switch(status){ - case 0x8:vmaster->NoteOff(cmdchan,data[1]&0x7f); - break; - case 0x9:if (data[2]==0) vmaster->NoteOff(cmdchan,data[1]&0x7f); - else vmaster->NoteOn(cmdchan,data[1]&0x7f,data[2]&0x7f); - break; - case 0xB: cntl=Midi->getcontroller(data[1]&0x7f); - vmaster->SetController(cmdchan,cntl,data[2]&0x7f); - break; - case 0xE: vmaster->SetController(cmdchan,C_pitchwheel,data[1]+data[2]*(long int) 128-8192); - break; - }; - pthread_mutex_unlock(&vmaster->mutex); - + if ((events->events[i])->type != kVstMidiType) continue; + VstMidiEvent *ev= (VstMidiEvent*) events->events[i]; + unsigned char *data= (unsigned char *)ev->midiData; + int status=data[0]/16; + int cmdchan=data[0]&0x0f; + int cntl; + + pthread_mutex_lock(&vmaster->mutex); + switch (status) { + case 0x8: + vmaster->NoteOff(cmdchan,data[1]&0x7f); + break; + case 0x9: + if (data[2]==0) vmaster->NoteOff(cmdchan,data[1]&0x7f); + else vmaster->NoteOn(cmdchan,data[1]&0x7f,data[2]&0x7f); + break; + case 0xB: + cntl=Midi->getcontroller(data[1]&0x7f); + vmaster->SetController(cmdchan,cntl,data[2]&0x7f); + break; + case 0xE: + vmaster->SetController(cmdchan,C_pitchwheel,data[1]+data[2]*(long int) 128-8192); + break; + }; + pthread_mutex_unlock(&vmaster->mutex); + }; -return(1); + return(1); }; -long VSTSynth::getChunk(void** data,bool isPreset){ +long VSTSynth::getChunk(void** data,bool isPreset) +{ int size=0; size=vmaster->getalldata((char **)data); return((long)size); }; -long VSTSynth::setChunk(void *data,long size,bool isPreset){ +long VSTSynth::setChunk(void *data,long size,bool isPreset) +{ vmaster->putalldata((char*)data,size); return(0); };