zynaddsubfx

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

commit 6074c71718d92b39999321e279d1c838c05aa277
parent 7861d85c91fda0c016d9e3d92cf893eb2175e0fb
Author: Daniel Sheeler <[email protected]>
Date:   Sun,  9 Sep 2018 13:44:09 -0500

fix legato pops due to random panning

Added a random seed parameter to SynthParameters

Diffstat:
Msrc/Misc/Part.cpp | 4++--
Msrc/Synth/ADnote.cpp | 29+++++++++++++++++------------
Msrc/Synth/OscilGen.cpp | 2+-
Msrc/Synth/PADnote.cpp | 6+++---
Msrc/Synth/SUBnote.cpp | 2+-
Msrc/Synth/SynthNote.cpp | 17++++++++++++-----
Msrc/Synth/SynthNote.h | 19++++++++++++++-----
Msrc/Tests/AdNoteTest.h | 2+-
Msrc/Tests/MemoryStressTest.h | 2+-
Msrc/Tests/PadNoteTest.h | 2+-
Msrc/Tests/SubNoteTest.h | 2+-
Msrc/Tests/UnisonTest.h | 4++--
12 files changed, 56 insertions(+), 35 deletions(-)

diff --git a/src/Misc/Part.cpp b/src/Misc/Part.cpp @@ -507,7 +507,7 @@ bool Part::NoteOn(unsigned char note, //Adjust Existing Notes if(doingLegato) { - LegatoParams pars = {notebasefreq, vel, portamento, note, true}; + LegatoParams pars = {notebasefreq, vel, portamento, note, true, prng()}; notePool.applyLegato(pars); return true; } @@ -523,7 +523,7 @@ bool Part::NoteOn(unsigned char note, continue; SynthParams pars{memory, ctl, synth, time, notebasefreq, vel, - portamento, note, false}; + portamento, note, false, prng()}; const int sendto = Pkitmode ? item.sendto() : 0; try { diff --git a/src/Synth/ADnote.cpp b/src/Synth/ADnote.cpp @@ -45,6 +45,8 @@ ADnote::ADnote(ADnoteParameters *pars_, SynthParams &spars, NoteEnabled = ON; basefreq = spars.frequency; velocity = spars.velocity; + initial_seed = spars.seed; + current_prng_state = spars.seed; stereo = pars.GlobalPar.PStereo; NoteGlobalPar.Detune = getdetune(pars.GlobalPar.PDetuneType, @@ -53,8 +55,8 @@ ADnote::ADnote(ADnoteParameters *pars_, SynthParams &spars, bandwidthDetuneMultiplier = pars.getBandwidthDetuneMultiplier(); if(pars.GlobalPar.PPanning == 0) - NoteGlobalPar.Panning = RND; - else + NoteGlobalPar.Panning = getRandom(); + else NoteGlobalPar.Panning = pars.GlobalPar.PPanning / 128.0f; @@ -509,7 +511,8 @@ void ADnote::setupVoiceMod(int nvoice, bool first_run) SynthNote *ADnote::cloneLegato(void) { SynthParams sp{memory, ctl, synth, time, legato.param.freq, velocity, - (bool)portamento, legato.param.midinote, true}; + (bool)portamento, legato.param.midinote, true, + initial_seed }; return memory.alloc<ADnote>(&pars, sp); } @@ -527,6 +530,8 @@ void ADnote::legatonote(LegatoParams lpars) portamento = lpars.portamento; midinote = lpars.midinote; basefreq = lpars.frequency; + initial_seed = lpars.seed; + current_prng_state = lpars.seed; if(velocity > 1.0f) velocity = 1.0f; @@ -537,9 +542,9 @@ void ADnote::legatonote(LegatoParams lpars) pars.GlobalPar.PDetune); bandwidthDetuneMultiplier = pars.getBandwidthDetuneMultiplier(); - if(pars.GlobalPar.PPanning == 0) - NoteGlobalPar.Panning = RND; - else + if(pars.GlobalPar.PPanning == 0) { + NoteGlobalPar.Panning = getRandom(); + } else NoteGlobalPar.Panning = pars.GlobalPar.PPanning / 128.0f; NoteGlobalPar.Filter->updateSense(velocity, @@ -700,9 +705,9 @@ void ADnote::legatonote(LegatoParams lpars) if(pars.VoicePar[nvoice].PVolumeminus != 0) NoteVoicePar[nvoice].Volume = -NoteVoicePar[nvoice].Volume; - if(pars.VoicePar[nvoice].PPanning == 0) - NoteVoicePar[nvoice].Panning = RND; // random panning - else + if(pars.VoicePar[nvoice].PPanning == 0) { + NoteVoicePar[nvoice].Panning = getRandom(); + } else NoteVoicePar[nvoice].Panning = pars.VoicePar[nvoice].PPanning / 128.0f; @@ -859,9 +864,9 @@ void ADnote::initparameters(WatchManager *wm, const char *prefix) if(param.PVolumeminus) vce.Volume = -vce.Volume; - if(param.PPanning == 0) - vce.Panning = RND; // random panning - else + if(param.PPanning == 0) { + vce.Panning = getRandom(); + } else vce.Panning = param.PPanning / 128.0f; newamplitude[nvoice] = 1.0f; diff --git a/src/Synth/OscilGen.cpp b/src/Synth/OscilGen.cpp @@ -793,7 +793,7 @@ void OscilGen::shiftharmonics(fft_t *freqs) } else for(int i = 0; i < synth.oscilsize / 2 - 1; ++i) { - int oldh = i + ::abs(harmonicshift); + int oldh = i + ::abs(harmonicshift); if(oldh >= (synth.oscilsize / 2 - 1)) h = 0.0f; else { diff --git a/src/Synth/PADnote.cpp b/src/Synth/PADnote.cpp @@ -41,7 +41,7 @@ void PADnote::setup(float freq, float velocity_, int portamento_, int midinote, - bool legato, + bool legato, WatchManager *wm, const char *prefix) { @@ -196,8 +196,8 @@ void PADnote::setup(float freq, SynthNote *PADnote::cloneLegato(void) { - SynthParams sp{memory, ctl, synth, time, legato.param.freq, velocity, - (bool)portamento, legato.param.midinote, true}; + SynthParams sp{memory, ctl, synth, time, legato.param.freq, velocity, + (bool)portamento, legato.param.midinote, true, legato.param.seed}; return memory.alloc<PADnote>(&pars, sp, interpolation); } diff --git a/src/Synth/SUBnote.cpp b/src/Synth/SUBnote.cpp @@ -196,7 +196,7 @@ void SUBnote::setup(float freq, SynthNote *SUBnote::cloneLegato(void) { SynthParams sp{memory, ctl, synth, time, legato.param.freq, velocity, - portamento, legato.param.midinote, true}; + portamento, legato.param.midinote, true, legato.param.seed}; return memory.alloc<SUBnote>(&pars, sp); } diff --git a/src/Synth/SynthNote.cpp b/src/Synth/SynthNote.cpp @@ -10,6 +10,7 @@ of the License, or (at your option) any later version. */ #include "SynthNote.h" +#include "../Misc/Util.h" #include "../globals.h" #include <cstring> #include <new> @@ -20,11 +21,11 @@ namespace zyn { SynthNote::SynthNote(SynthParams &pars) :memory(pars.memory), legato(pars.synth, pars.frequency, pars.velocity, pars.portamento, - pars.note, pars.quiet), ctl(pars.ctl), synth(pars.synth), time(pars.time) + pars.note, pars.quiet, pars.seed), ctl(pars.ctl), synth(pars.synth), time(pars.time) {} SynthNote::Legato::Legato(const SYNTH_T &synth_, float freq, float vel, int port, - int note, bool quiet) + int note, bool quiet, prng_t seed) :synth(synth_) { // Initialise some legato-specific vars @@ -38,6 +39,7 @@ SynthNote::Legato::Legato(const SYNTH_T &synth_, float freq, float vel, int port param.vel = vel; param.portamento = port; param.midinote = note; + param.seed = seed; lastfreq = 0.0f; silent = quiet; } @@ -90,7 +92,7 @@ void SynthNote::Legato::apply(SynthNote &note, float *outl, float *outr) decounter = -10; msg = LM_ToNorm; LegatoParams pars{param.freq, param.vel, param.portamento, - param.midinote, false}; + param.midinote, false, param.seed}; note.legatonote(pars); break; } @@ -132,7 +134,7 @@ void SynthNote::Legato::apply(SynthNote &note, float *outl, float *outr) //previous freq during the fadeout. float catchupfreq = param.freq * (param.freq / lastfreq); LegatoParams pars{catchupfreq, param.vel, param.portamento, - param.midinote, false}; + param.midinote, false, param.seed}; note.legatonote(pars); break; } @@ -152,7 +154,7 @@ void SynthNote::Legato::apply(SynthNote &note, float *outl, float *outr) void SynthNote::setVelocity(float velocity_) { legato.setSilent(true); //Let legato.update(...) returns 0. LegatoParams pars{legato.getFreq(), velocity_, - legato.getPortamento(), legato.getMidinote(), true}; + legato.getPortamento(), legato.getMidinote(), true, legato.getSeed()}; try { legatonote(pars); } catch (std::bad_alloc &ba) { @@ -161,4 +163,9 @@ void SynthNote::setVelocity(float velocity_) { legato.setDecounter(0); //avoid chopping sound due fade-in } +float SynthNote::getRandom() { + current_prng_state = prng_r(current_prng_state); + return (current_prng_state / (INT32_MAX * 1.0f)); +} + } diff --git a/src/Synth/SynthNote.h b/src/Synth/SynthNote.h @@ -13,7 +13,7 @@ #ifndef SYNTH_NOTE_H #define SYNTH_NOTE_H #include "../globals.h" - +#include "../Misc/Util.h" namespace zyn { class Allocator; @@ -29,6 +29,7 @@ struct SynthParams bool portamento;//True if portamento is used for this note int note; //Integer value of the note bool quiet; //Initial output condition for legato notes + prng_t seed; //Random seed }; struct LegatoParams @@ -38,6 +39,7 @@ struct LegatoParams bool portamento; int midinote; bool externcall; + prng_t seed; }; class SynthNote @@ -68,6 +70,9 @@ class SynthNote /* For polyphonic aftertouch needed */ void setVelocity(float velocity_); + /* Random numbers with own seed */ + float getRandom(); + //Realtime Safe Memory Allocator For notes class Allocator &memory; protected: @@ -76,7 +81,7 @@ class SynthNote { public: Legato(const SYNTH_T &synth_, float freq, float vel, int port, - int note, bool quiet); + int note, bool quiet, prng_t seed); void apply(SynthNote &note, float *outl, float *outr); int update(LegatoParams pars); @@ -92,9 +97,10 @@ class SynthNote } fade; public: struct { // Note parameters - float freq, vel; - bool portamento; - int midinote; + float freq, vel; + bool portamento; + int midinote; + prng_t seed; } param; const SYNTH_T &synth; @@ -103,10 +109,13 @@ class SynthNote float getVelocity() {return param.vel; } bool getPortamento() {return param.portamento; } int getMidinote() {return param.midinote; } + prng_t getSeed() {return param.seed;} void setSilent(bool silent_) {silent = silent_; } void setDecounter(int decounter_) {decounter = decounter_; } } legato; + prng_t initial_seed; + prng_t current_prng_state; const Controller &ctl; const SYNTH_T &synth; const AbsTime &time; diff --git a/src/Tests/AdNoteTest.h b/src/Tests/AdNoteTest.h @@ -91,7 +91,7 @@ class AdNoteTest:public CxxTest::TestSuite //lets go with.... 50! as a nice note testnote = 50; float freq = 440.0f * powf(2.0f, (testnote - 69.0f) / 12.0f); - SynthParams pars{memory, *controller, *synth, *time, freq, 120, 0, testnote, false}; + SynthParams pars{memory, *controller, *synth, *time, freq, 120, 0, testnote, false, prng()}; note = new ADnote(defaultPreset, pars); diff --git a/src/Tests/MemoryStressTest.h b/src/Tests/MemoryStressTest.h @@ -86,7 +86,7 @@ class AdNoteTest:public CxxTest::TestSuite unsigned char testnote = 42; float freq = 440.0f * powf(2.0f, (testnote - 69.0f) / 12.0f); - SynthParams pars{memory, *controller, *synth, *time, freq, 120, 0, testnote, false}; + SynthParams pars{memory, *controller, *synth, *time, freq, 120, 0, testnote, false, prng()}; std::vector<ADnote*> notes; diff --git a/src/Tests/PadNoteTest.h b/src/Tests/PadNoteTest.h @@ -104,7 +104,7 @@ class PadNoteTest:public CxxTest::TestSuite //lets go with.... 50! as a nice note testnote = 50; float freq = 440.0f * powf(2.0f, (testnote - 69.0f) / 12.0f); - SynthParams pars_{memory, *controller, *synth, *time, freq, 120, 0, testnote, false}; + SynthParams pars_{memory, *controller, *synth, *time, freq, 120, 0, testnote, false, prng()}; note = new PADnote(pars, pars_, interpolation); } diff --git a/src/Tests/SubNoteTest.h b/src/Tests/SubNoteTest.h @@ -78,7 +78,7 @@ class SubNoteTest:public CxxTest::TestSuite testnote = 50; float freq = 440.0f * powf(2.0f, (testnote - 69.0f) / 12.0f); - SynthParams pars{memory, *controller, *synth, *time, freq, 120, 0, testnote, false}; + SynthParams pars{memory, *controller, *synth, *time, freq, 120, 0, testnote, false, prng()}; note = new SUBnote(defaultPreset, pars); this->pars = defaultPreset; } diff --git a/src/Tests/UnisonTest.h b/src/Tests/UnisonTest.h @@ -84,7 +84,7 @@ class AdNoteTest:public CxxTest::TestSuite void run_test(int a, int b, int c, int d, int e, int f, float values[4]) { sprng(0); - + const int ADnote_unison_sizes[] = {1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 25, 30, 40, 50, 0}; params->VoicePar[0].Unison_size = ADnote_unison_sizes[a]; @@ -94,7 +94,7 @@ class AdNoteTest:public CxxTest::TestSuite params->VoicePar[0].Unison_vibratto_speed = e; params->VoicePar[0].Unison_invert_phase = f; - SynthParams pars{memory, *controller, *synth, *time, freq, 120, 0, testnote, false}; + SynthParams pars{memory, *controller, *synth, *time, freq, 120, 0, testnote, false, prng()}; note = new ADnote(params, pars); note->noteout(outL, outR); TS_ASSERT_DELTA(outL[80], values[0], 1e-5);