zynaddsubfx

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

commit 10b7437b8ec86e5df53e93b7a1a114824dbd2e0f
parent 33ff1071bdbdc6a1a94968d089a134df178345ec
Author: fundamental <[email protected]>
Date:   Sun, 11 Jul 2010 17:43:15 -0400

Legato: Now a mostly contained class in SynthNote

* Legato data private, few methods to update legato and apply it to SynthNotes
* TODO eliminate all of the redundancy involved with legatonote(...)

Diffstat:
Msrc/Synth/ADnote.cpp | 99+++----------------------------------------------------------------------------
Msrc/Synth/PADnote.cpp | 101+++----------------------------------------------------------------------------
Msrc/Synth/SUBnote.cpp | 135+++++++++++--------------------------------------------------------------------
Msrc/Synth/SynthNote.cpp | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/Synth/SynthNote.h | 39+++++++++++++++++++++++----------------
5 files changed, 153 insertions(+), 329 deletions(-)

diff --git a/src/Synth/ADnote.cpp b/src/Synth/ADnote.cpp @@ -412,31 +412,10 @@ void ADnote::legatonote(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.update(freq, velocity, portamento_, midinote_, externcall)) + return; portamento = portamento_; midinote = midinote_; @@ -1851,79 +1830,7 @@ int ADnote::noteout(REALTYPE *outl, REALTYPE *outr) // Apply legato-specific sound signal modifications - if(legato.silent) // Silencer - if(legato.msg != LM_FadeIn) { - memset(outl, 0, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - memset(outr, 0, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - } - 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; - legatonote(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. - legatonote(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; - } + legato.apply(*this,outl,outr); // Check if the global amplitude is finished. diff --git a/src/Synth/PADnote.cpp b/src/Synth/PADnote.cpp @@ -165,31 +165,10 @@ void PADnote::legatonote(REALTYPE freq, 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; - } + if(legato.update(freq, velocity, portamento_, midinote, externcall)) + return; portamento = portamento_; this->velocity = velocity; @@ -493,81 +472,7 @@ int PADnote::noteout(REALTYPE *outl, REALTYPE *outr) // 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; - } - 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; - legatonote(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; - 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. - legatonote(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; - } - + legato.apply(*this,outl,outr); // Check if the global amplitude is finished. // If it does, disable the note diff --git a/src/Synth/SUBnote.cpp b/src/Synth/SUBnote.cpp @@ -38,9 +38,6 @@ SUBnote::SUBnote(SUBnoteParameters *parameters, { ready = false; - tmpsmp = new REALTYPE[SOUND_BUFFER_SIZE]; - tmprnd = new REALTYPE[SOUND_BUFFER_SIZE]; - pars = parameters; ctl = ctl_; portamento = portamento_; @@ -190,32 +187,9 @@ void SUBnote::legatonote(REALTYPE freq, 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.update(freq, velocity, portamento_, midinote, externcall)) + return; portamento = portamento_; @@ -356,7 +330,6 @@ void SUBnote::legatonote(REALTYPE freq, /////////////// oldamplitude = newamplitude; - } @@ -364,8 +337,6 @@ SUBnote::~SUBnote() { if(NoteEnabled != OFF) KillNote(); - delete [] tmpsmp; - delete [] tmprnd; } /* @@ -590,22 +561,22 @@ void SUBnote::computecurrentparameters() */ int SUBnote::noteout(REALTYPE *outl, REALTYPE *outr) { - int i; - memcpy(outl, denormalkillbuf, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); memcpy(outr, denormalkillbuf, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); if(NoteEnabled == OFF) return 0; + REALTYPE *tmprnd = getTmpBuffer(); + REALTYPE *tmpsmp = getTmpBuffer(); //left channel - for(i = 0; i < SOUND_BUFFER_SIZE; i++) + for(int i = 0; i < SOUND_BUFFER_SIZE; i++) tmprnd[i] = RND * 2.0 - 1.0; for(int n = 0; n < numharmonics; n++) { memcpy(tmpsmp, tmprnd, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); for(int nph = 0; nph < numstages; nph++) filter(lfilter[nph + n * numstages], tmpsmp); - for(i = 0; i < SOUND_BUFFER_SIZE; i++) + for(int i = 0; i < SOUND_BUFFER_SIZE; i++) outl[i] += tmpsmp[i]; } @@ -614,13 +585,13 @@ int SUBnote::noteout(REALTYPE *outl, REALTYPE *outr) //right channel if(stereo != 0) { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) + for(int i = 0; i < SOUND_BUFFER_SIZE; i++) tmprnd[i] = RND * 2.0 - 1.0; for(int n = 0; n < numharmonics; n++) { memcpy(tmpsmp, tmprnd, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); for(int nph = 0; nph < numstages; nph++) filter(rfilter[nph + n * numstages], tmpsmp); - for(i = 0; i < SOUND_BUFFER_SIZE; i++) + for(int i = 0; i < SOUND_BUFFER_SIZE; i++) outr[i] += tmpsmp[i]; } if(GlobalFilterR != NULL) @@ -628,12 +599,14 @@ int SUBnote::noteout(REALTYPE *outl, REALTYPE *outr) } else memcpy(outr, outl, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); + returnTmpBuffer(tmprnd); + returnTmpBuffer(tmpsmp); if(firsttick != 0) { int n = 10; if(n > SOUND_BUFFER_SIZE) n = SOUND_BUFFER_SIZE; - for(i = 0; i < n; i++) { + for(int i = 0; i < n; i++) { REALTYPE ampfadein = 0.5 - 0.5 * cos( (REALTYPE) i / (REALTYPE) n * PI); outl[i] *= ampfadein; @@ -644,7 +617,7 @@ int SUBnote::noteout(REALTYPE *outl, REALTYPE *outr) if(ABOVE_AMPLITUDE_THRESHOLD(oldamplitude, newamplitude)) { // Amplitude interpolation - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { + for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { REALTYPE tmpvol = INTERPOLATE_AMPLITUDE(oldamplitude, newamplitude, i, @@ -654,7 +627,7 @@ int SUBnote::noteout(REALTYPE *outl, REALTYPE *outr) } } else { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { + for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { outl[i] *= newamplitude * panning; outr[i] *= newamplitude * (1.0 - panning); } @@ -664,83 +637,11 @@ int SUBnote::noteout(REALTYPE *outl, REALTYPE *outr) computecurrentparameters(); // Apply legato-specific sound signal modifications - if(legato.silent) // Silencer - if(legato.msg != LM_FadeIn) { - memset(outl, 0, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - memset(outr, 0, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - } - 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; - legatonote(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. - legatonote(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; - } + legato.apply(*this,outl,outr); // Check if the note needs to be computed more if(AmpEnvelope->finished() != 0) { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { //fade-out + 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; @@ -756,11 +657,11 @@ int SUBnote::noteout(REALTYPE *outl, REALTYPE *outr) void SUBnote::relasekey() { AmpEnvelope->relasekey(); - if(FreqEnvelope != NULL) + if(FreqEnvelope) FreqEnvelope->relasekey(); - if(BandWidthEnvelope != NULL) + if(BandWidthEnvelope) BandWidthEnvelope->relasekey(); - if(GlobalFilterEnvelope != NULL) + if(GlobalFilterEnvelope) GlobalFilterEnvelope->relasekey(); } diff --git a/src/Synth/SynthNote.cpp b/src/Synth/SynthNote.cpp @@ -1,11 +1,12 @@ #include "SynthNote.h" #include "../globals.h" +#include <cstring> -SynthNote::SynthNote(REALTYPE freq, REALTYPE vel, int port, int note, bool quiet) +SynthNote::SynthNote(REALTYPE freq, REALTYPE vel, int port, int note, bool quiet) :legato(freq,vel,port,note,quiet) {} -SynthNote::Legato::Legato(REALTYPE freq, REALTYPE vel, int port, +SynthNote::Legato::Legato(REALTYPE freq, REALTYPE vel, int port, int note, bool quiet) { // Initialise some legato-specific vars @@ -21,3 +22,106 @@ SynthNote::Legato::Legato(REALTYPE freq, REALTYPE vel, int port, param.midinote = note; silent = quiet; } + +int SynthNote::Legato::update(REALTYPE freq, REALTYPE velocity, int portamento_, + int midinote_, bool externcall) +{ + if(externcall) + msg = LM_Norm; + if(msg != LM_CatchUp) { + lastfreq = param.freq; + param.freq = freq; + param.vel = velocity; + param.portamento = portamento_; + param.midinote = midinote_; + if(msg == LM_Norm) { + if(silent) { + fade.m = 0.0; + msg = LM_FadeIn; + } + else { + fade.m = 1.0; + msg = LM_FadeOut; + return 1; + } + } + if(msg == LM_ToNorm) + msg = LM_Norm; + } + return 0; +} + +void SynthNote::Legato::apply(SynthNote &note, REALTYPE *outl, REALTYPE *outr) +{ + if(silent) // Silencer + if(msg != LM_FadeIn) { + memset(outl, 0, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); + memset(outr, 0, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); + } + switch(msg) { + case LM_CatchUp: // Continue the catch-up... + if(decounter == -10) + decounter = fade.length; + //Yea, could be done without the loop... + for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { + decounter--; + if(decounter < 1) { + // Catching-up done, we can finally set + // the note to the actual parameters. + decounter = -10; + msg = LM_ToNorm; + note.legatonote(param.freq, param.vel, param.portamento, + param.midinote, false); + break; + } + } + break; + case LM_FadeIn: // Fade-in + if(decounter == -10) + decounter = fade.length; + silent = false; + for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { + decounter--; + if(decounter < 1) { + decounter = -10; + msg = LM_Norm; + break; + } + fade.m += fade.step; + outl[i] *= fade.m; + outr[i] *= fade.m; + } + break; + case LM_FadeOut: // Fade-out, then set the catch-up + if(decounter == -10) + decounter = fade.length; + for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { + decounter--; + if(decounter < 1) { + for(int j = i; j < SOUND_BUFFER_SIZE; j++) { + outl[j] = 0.0; + outr[j] = 0.0; + } + decounter = -10; + silent = true; + // Fading-out done, now set the catch-up : + decounter = fade.length; + msg = LM_CatchUp; + //This freq should make this now silent note to catch-up/resync + //with the heard note for the same length it stayed at the + //previous freq during the fadeout. + REALTYPE catchupfreq = param.freq * (param.freq / lastfreq); + note.legatonote(catchupfreq, param.vel, param.portamento, + param.midinote, false); + break; + } + fade.m -= fade.step; + outl[i] *= fade.m; + outr[i] *= fade.m; + } + break; + default: + break; + } +} + diff --git a/src/Synth/SynthNote.h b/src/Synth/SynthNote.h @@ -47,22 +47,29 @@ class SynthNote * false when parameters need to be computed.*/ bool ready; protected: - // Legato vars - struct Legato{ - Legato(REALTYPE freq, REALTYPE vel, int port, - int note, bool quiet); - 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 transitions + class Legato{ + public: + Legato(REALTYPE freq, REALTYPE vel, int port, + int note, bool quiet); + + void apply(SynthNote &note, REALTYPE *outl, REALTYPE *outr); + int update(REALTYPE freq, REALTYPE velocity, int portamento_, + int midinote_, bool externalcall); + + private: + 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; };