zynaddsubfx

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

commit 9eaf05283d4403c4b3a607edbffb5943df486a35
parent 9a7be8c75448418852ae37476d5ec734ceafd940
Author: Daniel Sheeler <dsheeler@pobox.com>
Date:   Fri,  9 Mar 2018 19:50:21 -0600

Make envelope watchpoints output correct values.

Implement watchpoints for SUBnote envelopes.
gitignore swp files and qtcreator files.

Diffstat:
M.gitignore | 6++++++
Msrc/Misc/Part.cpp | 6+++---
Msrc/Synth/ADnote.cpp | 33+++++++++++++++------------------
Msrc/Synth/Envelope.cpp | 54++++++++++++++++++++++++++++++++++++++++--------------
Msrc/Synth/Envelope.h | 4+++-
Msrc/Synth/SUBnote.cpp | 26+++++++++++++-------------
Msrc/Synth/SUBnote.h | 7++++---
Msrc/Synth/WatchPoint.cpp | 10+++++-----
8 files changed, 89 insertions(+), 57 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,6 +1,12 @@ *.o *~ *.bc +*.swp +*.config +*.creator +*.creator.user +*.files +*.includes src/zynaddsubfx src/Tests/runner src/Tests/runner.cpp diff --git a/src/Misc/Part.cpp b/src/Misc/Part.cpp @@ -133,7 +133,7 @@ static const Ports partPorts = { p->Ppolymode = 0; p->Plegatomode = 1; }}}, - {"clear:", rProp(internal) rDoc("Reset Part To Defaults"), 0, + {"clear:", rProp(internal) rDoc("Reset Part To Defaults"), 0, [](const char *, RtData &d) { //XXX todo forward this event for middleware to handle @@ -534,7 +534,7 @@ bool Part::NoteOn(unsigned char note, wm, (pre+"kit"+i+"/adpars/").c_str), 0, i}); if(item.Psubenabled) notePool.insertNote(note, sendto, - {memory.alloc<SUBnote>(kit[i].subpars, pars), 1, i}); + {memory.alloc<SUBnote>(kit[i].subpars, pars, wm, (pre+"kit"+i+"/subpars/").c_str), 1, i}); if(item.Ppadenabled) notePool.insertNote(note, sendto, {memory.alloc<PADnote>(kit[i].padpars, pars, interpolation, wm, @@ -571,7 +571,7 @@ void Part::NoteOff(unsigned char note) //release the key if(!ctl.sustain.sustain) { //the sustain pedal is not pushed if((isMonoMode() || isLegatoMode()) && !monomemEmpty()) MonoMemRenote();//Play most recent still active note - else + else notePool.release(desc); } else { //the sustain pedal is pushed diff --git a/src/Synth/ADnote.cpp b/src/Synth/ADnote.cpp @@ -216,7 +216,7 @@ void ADnote::setupVoice(int nvoice) voice.filterbypass = param.Pfilterbypass; setupVoiceMod(nvoice); - + voice.FMVoice = param.PFMVoice; voice.FMFreqEnvelope = NULL; voice.FMAmpEnvelope = NULL; @@ -508,7 +508,7 @@ void ADnote::setupVoiceMod(int nvoice, bool first_run) SynthNote *ADnote::cloneLegato(void) { - SynthParams sp{memory, ctl, synth, time, legato.param.freq, velocity, + SynthParams sp{memory, ctl, synth, time, legato.param.freq, velocity, (bool)portamento, legato.param.midinote, true}; return memory.alloc<ADnote>(&pars, sp); } @@ -520,7 +520,6 @@ SynthNote *ADnote::cloneLegato(void) void ADnote::legatonote(LegatoParams lpars) { //ADnoteParameters &pars = *partparams; - // Manage legato stuff if(legato.update(lpars)) return; @@ -543,7 +542,7 @@ void ADnote::legatonote(LegatoParams lpars) else NoteGlobalPar.Panning = pars.GlobalPar.PPanning / 128.0f; - NoteGlobalPar.Filter->updateSense(velocity, + NoteGlobalPar.Filter->updateSense(velocity, pars.GlobalPar.PFilterVelocityScale, pars.GlobalPar.PFilterVelocityScaleFunction); @@ -587,7 +586,6 @@ void ADnote::legatonote(LegatoParams lpars) 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) @@ -657,7 +655,6 @@ void ADnote::legatonote(LegatoParams lpars) * logf(50.0f)) - 1.0f) / synth.buffersize_f / 10.0f * synth.samplerate_f); } - /// initparameters(); /////////////// @@ -672,7 +669,7 @@ void ADnote::legatonote(LegatoParams lpars) * VelF( velocity, pars.GlobalPar.PAmpVelocityScaleFunction); //velocity sensing - + globaloldamplitude = globalnewamplitude; globalnewamplitude = NoteGlobalPar.Volume * NoteGlobalPar.AmpEnvelope->envout_dB() * NoteGlobalPar.AmpLfo->amplfoout(); @@ -1564,15 +1561,15 @@ inline void ADnote::ComputeVoicePinkNoise(int nvoice) float *tw = tmpwave_unison[k]; float *f = &pinking[nvoice][k > 0 ? 7 : 0]; for(int i = 0; i < synth.buffersize; ++i) { - float white = (RND-0.5)/4.0; - f[0] = 0.99886*f[0]+white*0.0555179; - f[1] = 0.99332*f[1]+white*0.0750759; - f[2] = 0.96900*f[2]+white*0.1538520; - f[3] = 0.86650*f[3]+white*0.3104856; - f[4] = 0.55000*f[4]+white*0.5329522; - f[5] = -0.7616*f[5]-white*0.0168980; - tw[i] = f[0]+f[1]+f[2]+f[3]+f[4]+f[5]+f[6]+white*0.5362; - f[6] = white*0.115926; + float white = (RND-0.5)/4.0; + f[0] = 0.99886*f[0]+white*0.0555179; + f[1] = 0.99332*f[1]+white*0.0750759; + f[2] = 0.96900*f[2]+white*0.1538520; + f[3] = 0.86650*f[3]+white*0.3104856; + f[4] = 0.55000*f[4]+white*0.5329522; + f[5] = -0.7616*f[5]-white*0.0168980; + tw[i] = f[0]+f[1]+f[2]+f[3]+f[4]+f[5]+f[6]+white*0.5362; + f[6] = white*0.115926; } } } @@ -1983,7 +1980,7 @@ void ADnote::Global::initparameters(const ADnoteGlobalParam &param, Volume = 4.0f * powf(0.1f, 3.0f * (1.0f - param.PVolume / 96.0f)) //-60 dB .. 0 dB * VelF(velocity, param.PAmpVelocityScaleFunction); //sensing - Filter = memory.alloc<ModFilter>(*param.GlobalFilter, synth, time, memory, + Filter = memory.alloc<ModFilter>(*param.GlobalFilter, synth, time, memory, stereo, basefreq); FilterEnvelope = memory.alloc<Envelope>(*param.FilterEnvelope, basefreq, @@ -1993,7 +1990,7 @@ void ADnote::Global::initparameters(const ADnoteGlobalParam &param, Filter->addMod(*FilterEnvelope); Filter->addMod(*FilterLfo); - + { Filter->updateSense(velocity, param.PFilterVelocityScale, param.PFilterVelocityScaleFunction); diff --git a/src/Synth/Envelope.cpp b/src/Synth/Envelope.cpp @@ -32,7 +32,7 @@ Envelope::Envelope(EnvelopeParams &pars, float basefreq, float bufferdt, if(!pars.Pfreemode) pars.converttofree(); - int mode = pars.Envmode; + mode = pars.Envmode; //for amplitude envelopes if((mode == 1) && !linearenvelope) @@ -101,26 +101,54 @@ void Envelope::forceFinish(void) envfinish = true; } +void Envelope::watch(float time, float value) +{ + float pos[2]; + float factor1; + float factor2; + pos[0] = time; + switch(mode) { + case 2: + pos[1] = 1 - value / -40.f; + watchOut(pos, 2); + break; + case 3: + factor1 = log(value/100. + 1.) / (6. * log(2)); + factor2 = log(1. - value/100.) / (6. * log(2)); + pos[1] = ((0.5 * factor1) >= 0) ? (0.5 * factor1 + 0.5) : (0.5 - factor2 * 0.5); + watchOut(pos, 2); + break; + case 4: + pos[1] = (value + 6.) / 12.f; + watchOut(pos, 2); + break; + case 5: + pos[1] = (value + 10.) / 20.f; + watchOut(pos, 2); + break; + default: + pos[1] = value; + watchOut(pos, 2); + } +} + /* * Envelope Output */ 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); + watch(envpoints - 1, envoutval); } 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); + watch(envsustain, envoutval); } return envoutval; } @@ -144,8 +172,7 @@ float Envelope::envout(bool doWatch) } if(doWatch) { - float pos[2] = {(float)tmp + t, envoutval}; - watchOut(pos, 2); + watch(tmp + t, envoutval); } return out; @@ -169,8 +196,7 @@ float Envelope::envout(bool doWatch) envoutval = out; if(doWatch) { - float pos[2] = {(float)currentpoint + t, envoutval}; - watchOut(pos, 2); + watch(currentpoint + t, envoutval); } return out; } @@ -201,13 +227,13 @@ float Envelope::envout_dB() envoutval = EnvelopeParams::env_rap2dB(out); else envoutval = MIN_ENVELOPE_DB; + out = envoutval; } else - out = EnvelopeParams::env_dB2rap(envout(false)); + out = envout(false); - float pos[2] = {(float)currentpoint + t, out}; - watchOut(pos, 2); + watch(currentpoint + t, out); + return EnvelopeParams::env_dB2rap(out); - return out; } bool Envelope::finished() const diff --git a/src/Synth/Envelope.h b/src/Synth/Envelope.h @@ -23,7 +23,6 @@ namespace zyn { class Envelope { public: - /**Constructor*/ Envelope(class EnvelopeParams &pars, float basefreq, float dt, WatchManager *m=0, const char *watch_prefix=0); @@ -37,6 +36,8 @@ class Envelope /**Determines the status of the Envelope * @return returns 1 if the envelope is finished*/ bool finished(void) const; + void watch(float time, float value); + private: int envpoints; int envsustain; //"-1" means disabled @@ -44,6 +45,7 @@ class Envelope float envval[MAX_ENVELOPE_POINTS]; // [0.0f .. 1.0f] float envstretch; int linearenvelope; + int mode; int currentpoint; //current envelope point (starts from 1) bool forcedrelease; diff --git a/src/Synth/SUBnote.cpp b/src/Synth/SUBnote.cpp @@ -34,7 +34,8 @@ namespace zyn { -SUBnote::SUBnote(const SUBnoteParameters *parameters, SynthParams &spars) +SUBnote::SUBnote(const SUBnoteParameters *parameters, SynthParams &spars, WatchManager *wm, const char *prefix + ) :SynthNote(spars), pars(*parameters), AmpEnvelope(nullptr), FreqEnvelope(nullptr), @@ -42,10 +43,9 @@ SUBnote::SUBnote(const SUBnoteParameters *parameters, SynthParams &spars) GlobalFilter(nullptr), GlobalFilterEnvelope(nullptr), NoteEnabled(true), - lfilter(nullptr), rfilter(nullptr), - wm(nullptr) + lfilter(nullptr), rfilter(nullptr) { - setup(spars.frequency, spars.velocity, spars.portamento, spars.note); + setup(spars.frequency, spars.velocity, spars.portamento, spars.note, false, wm, prefix); } float SUBnote::setupFilters(int *pos, bool automation) @@ -91,7 +91,9 @@ void SUBnote::setup(float freq, float velocity, int portamento_, int midinote, - bool legato) + bool legato, + WatchManager *wm, + const char *prefix) { this->velocity = velocity; portamento = portamento_; @@ -175,9 +177,9 @@ void SUBnote::setup(float freq, oldbandwidth = 64; if(!legato) { //normal note if(pars.Pfixedfreq == 0) - initparameters(basefreq, wm); + initparameters(basefreq, wm, prefix); else - initparameters(basefreq / 440.0f * freq, wm); + initparameters(basefreq / 440.0f * freq, wm, prefix); } else { if(pars.Pfixedfreq == 0) @@ -188,8 +190,6 @@ void SUBnote::setup(float freq, if(GlobalFilter) GlobalFilter->updateNoteFreq(basefreq); } - - oldamplitude = newamplitude; } SynthNote *SUBnote::cloneLegato(void) @@ -207,7 +207,7 @@ void SUBnote::legatonote(LegatoParams pars) try { setup(pars.frequency, pars.velocity, pars.portamento, pars.midinote, - true); + true, wm); } catch (std::bad_alloc &ba) { std::cerr << "failed to set legato note parameter in SUBnote: " << ba.what() << std::endl; } @@ -353,10 +353,9 @@ void SUBnote::filter(bpfilter &filter, float *smps) /* * Init Parameters */ -void SUBnote::initparameters(float freq, WatchManager *wm) +void SUBnote::initparameters(float freq, WatchManager *wm, const char *prefix) { - //TODO populate this base string - ScratchString pre; + ScratchString pre = prefix; AmpEnvelope = memory.alloc<Envelope>(*pars.AmpEnvelope, freq, synth.dt(), wm, (pre+"AmpEnvelope/").c_str); @@ -478,6 +477,7 @@ void SUBnote::computecurrentparameters() oldbandwidth = ctl.bandwidth.data; oldpitchwheel = ctl.pitchwheel.data; } + oldamplitude = newamplitude; newamplitude = volume * AmpEnvelope->envout_dB() * 2.0f; //Filter diff --git a/src/Synth/SUBnote.h b/src/Synth/SUBnote.h @@ -22,7 +22,8 @@ namespace zyn { class SUBnote:public SynthNote { public: - SUBnote(const SUBnoteParameters *parameters, SynthParams &pars); + SUBnote(const SUBnoteParameters *parameters, SynthParams &pars, + WatchManager *wm = 0, const char *prefix = 0); ~SUBnote(); SynthNote *cloneLegato(void); @@ -38,14 +39,14 @@ class SUBnote:public SynthNote float velocity, int portamento_, int midinote, - bool legato = false); + bool legato = false, WatchManager *wm = 0, const char *prefix = 0); float setupFilters(int *pos, bool automation); void computecurrentparameters(); /* * Initialize envelopes and global filter * calls computercurrentparameters() */ - void initparameters(float freq, WatchManager *wm); + void initparameters(float freq, WatchManager *wm, const char *prefix); void KillNote(); const SUBnoteParameters &pars; diff --git a/src/Synth/WatchPoint.cpp b/src/Synth/WatchPoint.cpp @@ -50,7 +50,7 @@ bool WatchPoint::is_active(void) return false; } - + FloatWatchPoint::FloatWatchPoint(WatchManager *ref, const char *prefix, const char *id) :WatchPoint(ref, prefix, id) {} @@ -58,7 +58,7 @@ FloatWatchPoint::FloatWatchPoint(WatchManager *ref, const char *prefix, const ch VecWatchPoint::VecWatchPoint(WatchManager *ref, const char *prefix, const char *id) :WatchPoint(ref, prefix, id) {} - + WatchManager::WatchManager(thrlnk *link) :write_back(link), new_active(false) { @@ -67,7 +67,7 @@ WatchManager::WatchManager(thrlnk *link) memset(data_list, 0, sizeof(data_list)); memset(deactivate, 0, sizeof(deactivate)); } - + void WatchManager::add_watch(const char *id) { //Don't add duplicate watchs @@ -136,7 +136,7 @@ bool WatchManager::active(const char *id) const return false; } - + int WatchManager::samples(const char *id) const { for(int i=0; i<MAX_WATCH; ++i) @@ -144,7 +144,7 @@ int WatchManager::samples(const char *id) const return sample_list[i]; return 0; } - + void WatchManager::satisfy(const char *id, float f) { //printf("trying to satisfy '%s'\n", id);