zynaddsubfx

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

commit 8e2d5b49dc03517c60f363b1048dcfc93277f48e
parent 752b97b4009b1e6651c7e689344ba05c00af41ec
Author: fundamental <mark.d.mccurry@gmail.com>
Date:   Fri, 27 May 2016 13:51:51 -0400

Envelope: Add Basic Watchpoint Support

Diffstat:
Msrc/Synth/ADnote.cpp | 29+++++++++++++++++++++--------
Msrc/Synth/Envelope.cpp | 41++++++++++++++++++++++++++++++++---------
Msrc/Synth/Envelope.h | 18+++++++++++-------
Msrc/Synth/PADnote.cpp | 27++++++++++++++++++---------
Msrc/Synth/SUBnote.cpp | 25+++++++++++++++++--------
Msrc/Synth/SUBnote.h | 3++-
Msrc/Synth/WatchPoint.h | 2+-
7 files changed, 102 insertions(+), 43 deletions(-)

diff --git a/src/Synth/ADnote.cpp b/src/Synth/ADnote.cpp @@ -819,7 +819,9 @@ void ADnote::initparameters(WatchManager *wm, const char *prefix) newamplitude[nvoice] = 1.0f; if(param.PAmpEnvelopeEnabled) { - vce.AmpEnvelope = memory.alloc<Envelope>(*param.AmpEnvelope, basefreq, synth.dt()); + vce.AmpEnvelope = memory.alloc<Envelope>(*param.AmpEnvelope, + basefreq, synth.dt(), wm, + (pre+"VoicePar"+nvoice+"/AmpEnvelope/").c_str); vce.AmpEnvelope->envout_dB(); //discard the first envelope sample newamplitude[nvoice] *= vce.AmpEnvelope->envout_dB(); } @@ -832,7 +834,9 @@ void ADnote::initparameters(WatchManager *wm, const char *prefix) /* Voice Frequency Parameters Init */ if(param.PFreqEnvelopeEnabled) - vce.FreqEnvelope = memory.alloc<Envelope>(*param.FreqEnvelope, basefreq, synth.dt()); + vce.FreqEnvelope = memory.alloc<Envelope>(*param.FreqEnvelope, + basefreq, synth.dt(), wm, + (pre+"VoicePar"+nvoice+"/FreqEnvelope/").c_str); if(param.PFreqLfoEnabled) vce.FreqLfo = memory.alloc<LFO>(*param.FreqLfo, basefreq, time, wm, @@ -848,7 +852,9 @@ void ADnote::initparameters(WatchManager *wm, const char *prefix) if(param.PFilterEnvelopeEnabled) { vce.FilterEnvelope = - memory.alloc<Envelope>(*param.FilterEnvelope, basefreq, synth.dt()); + memory.alloc<Envelope>(*param.FilterEnvelope, + basefreq, synth.dt(), wm, + (pre+"VoicePar"+nvoice+"/FilterEnvelope/").c_str); vce.Filter->addMod(*vce.FilterEnvelope); } @@ -898,13 +904,17 @@ void ADnote::initparameters(WatchManager *wm, const char *prefix) } if(param.PFMFreqEnvelopeEnabled) - vce.FMFreqEnvelope = memory.alloc<Envelope>(*param.FMFreqEnvelope, basefreq, synth.dt()); + vce.FMFreqEnvelope = memory.alloc<Envelope>(*param.FMFreqEnvelope, + basefreq, synth.dt(), wm, + (pre+"VoicePar"+nvoice+"/FMFreqEnvelope/").c_str); FMnewamplitude[nvoice] = vce.FMVolume * ctl.fmamp.relamp; if(param.PFMAmpEnvelopeEnabled ) { vce.FMAmpEnvelope = - memory.alloc<Envelope>(*param.FMAmpEnvelope, basefreq, synth.dt()); + memory.alloc<Envelope>(*param.FMAmpEnvelope, + basefreq, synth.dt(), wm, + (pre+"VoicePar"+nvoice+"/FMAmpEnvelope/").c_str); FMnewamplitude[nvoice] *= vce.FMAmpEnvelope->envout_dB(); } } @@ -1884,11 +1894,13 @@ void ADnote::Global::initparameters(const ADnoteGlobalParam &param, const char *prefix) { ScratchString pre = prefix; - FreqEnvelope = memory.alloc<Envelope>(*param.FreqEnvelope, basefreq, synth.dt()); + FreqEnvelope = memory.alloc<Envelope>(*param.FreqEnvelope, basefreq, + synth.dt(), wm, (pre+"GlobalPar/FreqEnvelope/").c_str); FreqLfo = memory.alloc<LFO>(*param.FreqLfo, basefreq, time, wm, (pre+"GlobalPar/FreqLfo/").c_str); - AmpEnvelope = memory.alloc<Envelope>(*param.AmpEnvelope, basefreq, synth.dt()); + AmpEnvelope = memory.alloc<Envelope>(*param.AmpEnvelope, basefreq, + synth.dt(), wm, (pre+"GlobalPar/AmpEnvelope/").c_str); AmpLfo = memory.alloc<LFO>(*param.AmpLfo, basefreq, time, wm, (pre+"GlobalPar/AmpLfo/").c_str); @@ -1898,7 +1910,8 @@ void ADnote::Global::initparameters(const ADnoteGlobalParam &param, Filter = memory.alloc<ModFilter>(*param.GlobalFilter, synth, time, memory, stereo, basefreq); - FilterEnvelope = memory.alloc<Envelope>(*param.FilterEnvelope, basefreq, synth.dt()); + FilterEnvelope = memory.alloc<Envelope>(*param.FilterEnvelope, basefreq, + synth.dt(), wm, (pre+"GlobalPar/FilterEnvelope/").c_str); FilterLfo = memory.alloc<LFO>(*param.FilterLfo, basefreq, time, wm, (pre+"GlobalPar/FilterLfo/").c_str); diff --git a/src/Synth/Envelope.cpp b/src/Synth/Envelope.cpp @@ -15,7 +15,9 @@ #include "Envelope.h" #include "../Params/EnvelopeParams.h" -Envelope::Envelope(EnvelopeParams &pars, float basefreq, float bufferdt) +Envelope::Envelope(EnvelopeParams &pars, float basefreq, float bufferdt, + WatchManager *m, const char *watch_prefix) + :watchOut(m, watch_prefix, "out") { envpoints = pars.Penvpoints; if(envpoints > MAX_ENVELOPE_POINTS) @@ -100,20 +102,28 @@ void Envelope::forceFinish(void) /* * Envelope Output */ -float Envelope::envout() +float Envelope::envout(bool doWatch) { float out; if(envfinish) { //if the envelope is finished envoutval = envval[envpoints - 1]; + if(doWatch) { + float pos[2] = {(float)envpoints - 1, envoutval}; + watchOut(pos, 2); + } return envoutval; } if((currentpoint == envsustain + 1) && !keyreleased) { //if it is sustaining now envoutval = envval[envsustain]; + if(doWatch) { + float pos[2] = {(float)envsustain, envoutval}; + watchOut(pos, 2); + } return envoutval; } - if(keyreleased && (forcedrelease != 0)) { //do the forced release + if(keyreleased && forcedrelease) { //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.00000001f) @@ -130,6 +140,12 @@ float Envelope::envout() if((currentpoint >= envpoints) || (envsustain < 0)) envfinish = true; } + + if(doWatch) { + float pos[2] = {(float)tmp + t, envoutval}; + watchOut(pos, 2); + } + return out; } if(inct >= 1.0f) @@ -149,6 +165,11 @@ float Envelope::envout() } envoutval = out; + + if(doWatch) { + float pos[2] = {(float)currentpoint + t, envoutval}; + watchOut(pos, 2); + } return out; } @@ -166,10 +187,10 @@ inline float Envelope::env_rap2dB(float rap) { float Envelope::envout_dB() { float out; - if(linearenvelope != 0) - return envout(); + if(linearenvelope) + return envout(true); - if((currentpoint == 1) && (!keyreleased || (forcedrelease == 0))) { //first point is always lineary interpolated + if((currentpoint == 1) && (!keyreleased || !forcedrelease)) { //first point is always lineary interpolated float v1 = env_dB2rap(envval[0]); float v2 = env_dB2rap(envval[1]); out = v1 + (v2 - v1) * t; @@ -186,9 +207,11 @@ float Envelope::envout_dB() envoutval = env_rap2dB(out); else envoutval = MIN_ENVELOPE_DB; - } - else - out = env_dB2rap(envout()); + } else + out = env_dB2rap(envout(false)); + + float pos[2] = {(float)currentpoint + t, out}; + watchOut(pos, 2); return out; } diff --git a/src/Synth/Envelope.h b/src/Synth/Envelope.h @@ -15,6 +15,7 @@ #define ENVELOPE_H #include "../globals.h" +#include "WatchPoint.h" /**Implementation of a general Envelope*/ class Envelope @@ -22,17 +23,18 @@ class Envelope public: /**Constructor*/ - Envelope(class EnvelopeParams &pars, float basefreq, float dt); + Envelope(class EnvelopeParams &pars, float basefreq, float dt, WatchManager *m=0, + const char *watch_prefix=0); /**Destructor*/ - ~Envelope(); - void releasekey(); + ~Envelope(void); + void releasekey(void); /**Push Envelope to finishing state*/ void forceFinish(void); - float envout(); - float envout_dB(); + float envout(bool doWatch=true); + float envout_dB(void); /**Determines the status of the Envelope * @return returns 1 if the envelope is finished*/ - bool finished() const; + bool finished(void) const; private: float env_rap2dB(float rap); float env_dB2rap(float db); @@ -44,12 +46,14 @@ class Envelope int linearenvelope; int currentpoint; //current envelope point (starts from 1) - int forcedrelease; + bool forcedrelease; bool keyreleased; //if the key was released bool envfinish; float t; // the time from the last point float inct; // the time increment float envoutval; //used to do the forced release + + VecWatchPoint watchOut; }; diff --git a/src/Synth/PADnote.cpp b/src/Synth/PADnote.cpp @@ -135,13 +135,19 @@ void PADnote::setup(float freq, ScratchString pre = prefix; - NoteGlobalPar.FreqEnvelope = memory.alloc<Envelope>(*pars.FreqEnvelope, basefreq, synth.dt()); - NoteGlobalPar.FreqLfo = memory.alloc<LFO>(*pars.FreqLfo, basefreq, time, wm, - (pre+"freqlfo/").c_str); - - NoteGlobalPar.AmpEnvelope = memory.alloc<Envelope>(*pars.AmpEnvelope, basefreq, synth.dt()); - NoteGlobalPar.AmpLfo = memory.alloc<LFO>(*pars.AmpLfo, basefreq, time, wm, - (pre+"amplfo/").c_str); + NoteGlobalPar.FreqEnvelope = + memory.alloc<Envelope>(*pars.FreqEnvelope, basefreq, synth.dt(), + wm, (pre+"FreqEnvelope/").c_str); + NoteGlobalPar.FreqLfo = + memory.alloc<LFO>(*pars.FreqLfo, basefreq, time, + wm, (pre+"FreqLfo/").c_str); + + NoteGlobalPar.AmpEnvelope = + memory.alloc<Envelope>(*pars.AmpEnvelope, basefreq, synth.dt(), + wm, (pre+"AmpEnvelope/").c_str); + NoteGlobalPar.AmpLfo = + memory.alloc<LFO>(*pars.AmpLfo, basefreq, time, + wm, (pre+"AmpLfo/").c_str); } NoteGlobalPar.Volume = 4.0f @@ -155,6 +161,7 @@ void PADnote::setup(float freq, * NoteGlobalPar.AmpLfo->amplfoout(); if(!legato) { + ScratchString pre = prefix; auto &flt = NoteGlobalPar.GlobalFilter; auto &env = NoteGlobalPar.FilterEnvelope; auto &lfo = NoteGlobalPar.FilterLfo; @@ -162,8 +169,10 @@ void PADnote::setup(float freq, flt = memory.alloc<ModFilter>(*pars.GlobalFilter, synth, time, memory, true, basefreq); //setup mod - env = memory.alloc<Envelope>(*pars.FilterEnvelope, basefreq, synth.dt()); - lfo = memory.alloc<LFO>(*pars.FilterLfo, basefreq, time); + env = memory.alloc<Envelope>(*pars.FilterEnvelope, basefreq, + synth.dt(), wm, (pre+"FilterEnvelope/").c_str); + lfo = memory.alloc<LFO>(*pars.FilterLfo, basefreq, time, + wm, (pre+"FilterLfo/").c_str); flt->addMod(*env); flt->addMod(*lfo); } diff --git a/src/Synth/SUBnote.cpp b/src/Synth/SUBnote.cpp @@ -20,6 +20,7 @@ #include "SUBnote.h" #include "Envelope.h" #include "ModFilter.h" +#include "../Containers/ScratchString.h" #include "../Params/Controller.h" #include "../Params/SUBnoteParameters.h" #include "../Params/FilterParams.h" @@ -35,7 +36,8 @@ SUBnote::SUBnote(const SUBnoteParameters *parameters, SynthParams &spars) GlobalFilter(nullptr), GlobalFilterEnvelope(nullptr), NoteEnabled(true), - lfilter(nullptr), rfilter(nullptr) + lfilter(nullptr), rfilter(nullptr), + wm(nullptr) { setup(spars.frequency, spars.velocity, spars.portamento, spars.note); } @@ -198,9 +200,9 @@ void SUBnote::setup(float freq, oldbandwidth = 64; if(!legato) { //normal note if(pars.Pfixedfreq == 0) - initparameters(basefreq); + initparameters(basefreq, wm); else - initparameters(basefreq / 440.0f * freq); + initparameters(basefreq / 440.0f * freq, wm); } else { if(pars.Pfixedfreq == 0) @@ -376,18 +378,25 @@ void SUBnote::filter(bpfilter &filter, float *smps) /* * Init Parameters */ -void SUBnote::initparameters(float freq) +void SUBnote::initparameters(float freq, WatchManager *wm) { - AmpEnvelope = memory.alloc<Envelope>(*pars.AmpEnvelope, freq, synth.dt()); + //TODO populate this base string + ScratchString pre; + AmpEnvelope = memory.alloc<Envelope>(*pars.AmpEnvelope, freq, + synth.dt(), wm, (pre+"AmpEnvelope/").c_str); if(pars.PFreqEnvelopeEnabled) - FreqEnvelope = memory.alloc<Envelope>(*pars.FreqEnvelope, freq, synth.dt()); + FreqEnvelope = memory.alloc<Envelope>(*pars.FreqEnvelope, freq, + synth.dt(), wm, (pre+"FreqEnvelope/").c_str); if(pars.PBandWidthEnvelopeEnabled) - BandWidthEnvelope = memory.alloc<Envelope>(*pars.BandWidthEnvelope, freq, synth.dt()); + BandWidthEnvelope = memory.alloc<Envelope>(*pars.BandWidthEnvelope, + freq, synth.dt(), wm, (pre+"BandWidthEnvelope/").c_str); if(pars.PGlobalFilterEnabled) { - GlobalFilterEnvelope = memory.alloc<Envelope>(*pars.GlobalFilterEnvelope, freq, synth.dt()); + GlobalFilterEnvelope = + memory.alloc<Envelope>(*pars.GlobalFilterEnvelope, freq, + synth.dt(), wm, (pre+"GlobalFilterEnvelope/").c_str); GlobalFilter = memory.alloc<ModFilter>(*pars.GlobalFilter, synth, time, memory, stereo, freq); diff --git a/src/Synth/SUBnote.h b/src/Synth/SUBnote.h @@ -43,7 +43,7 @@ class SUBnote:public SynthNote * Initialize envelopes and global filter * calls computercurrentparameters() */ - void initparameters(float freq); + void initparameters(float freq, WatchManager *wm); void KillNote(); const SUBnoteParameters &pars; @@ -101,6 +101,7 @@ class SUBnote:public SynthNote int oldpitchwheel, oldbandwidth; float globalfiltercenterq; float velocity; + WatchManager *wm; }; #endif diff --git a/src/Synth/WatchPoint.h b/src/Synth/WatchPoint.h @@ -13,7 +13,7 @@ #pragma once -class WatchManager; +struct WatchManager; namespace rtosc {class ThreadLink;} struct WatchPoint