zynaddsubfx

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

commit 484feedebf8efac38f4fbb1205463328ec605ab3
parent 96795dbf6b1e21f768e9cc39eb7df7df4a492516
Author: Johannes Lorenz <[email protected]>
Date:   Sat, 22 Sep 2018 23:42:57 +0200

Merge branch 'master' of github.com:zynaddsubfx/zynaddsubfx

Diffstat:
Msrc/Misc/Master.cpp | 9+++++++++
Msrc/Misc/MiddleWare.cpp | 39+++++++++++++++++++--------------------
Msrc/Misc/Part.cpp | 4++--
Msrc/Plugin/ZynAddSubFX/ZynAddSubFX-UI-Zest.cpp | 12++++++------
Msrc/Synth/ADnote.cpp | 32+++++++++++++++++---------------
Msrc/Synth/OscilGen.cpp | 2+-
Msrc/Synth/PADnote.cpp | 20+++++++++++---------
Msrc/Synth/SUBnote.cpp | 5++---
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++--
Mzynaddsubfx-jack-multi.desktop | 1+
16 files changed, 100 insertions(+), 72 deletions(-)

diff --git a/src/Misc/Master.cpp b/src/Misc/Master.cpp @@ -639,6 +639,7 @@ void Master::saveAutomation(XMLwrapper &xml, const rtosc::AutomationMgr &midi) xml.beginbranch("slot", i); XmlNode params("params"); params["midi-cc"] = to_s(slot.midi_cc); + params["name"] = to_s(slot.name); xml.add(params); for(int j=0; j<midi.per_slot; ++j) { const auto &au = slot.automations[j]; @@ -689,8 +690,16 @@ void Master::loadAutomation(XMLwrapper &xml, rtosc::AutomationMgr &midi) } } for(auto node:xml.getBranch()) + { if(node.name == "params") + { slot.midi_cc = atoi(node["midi-cc"].c_str()); + if(node["name"] != "") + { + strncpy(slot.name, node["name"].c_str(), sizeof(slot.name) - 1); + } + } + } xml.exitbranch(); } } diff --git a/src/Misc/MiddleWare.cpp b/src/Misc/MiddleWare.cpp @@ -117,25 +117,24 @@ static int handler_function(const char *path, const char *types, lo_arg **argv, lo_message_serialise(msg, path, buffer, &size); if(!strcmp(buffer, "/path-search") && - !strcmp("ss", rtosc_argument_string(buffer))) { - auto reply_cb = [](const char* url, const char* types, const rtosc_arg_t* args) - { - char buffer[1024*20]; - size_t length = rtosc_amessage(buffer, sizeof(buffer), - "/paths", types, args); - if(length) { - lo_message msg = lo_message_deserialise((void*)buffer, - length, NULL); - lo_address addr = lo_address_new_from_url(url); - if(addr) - lo_send_message(addr, buffer, msg); - lo_address_free(addr); - lo_message_free(msg); - } - }; - rtosc::path_search(Master::ports, buffer, mw->activeUrl().c_str(), - reply_cb); - } else if(buffer[0]=='/' && strrchr(buffer, '/')[1]) { + !strcmp("ss", rtosc_argument_string(buffer))) + { + char reply_buffer[1024*20]; + std::size_t length = + rtosc::path_search(Master::ports, buffer, 128, + reply_buffer, sizeof(reply_buffer)); + if(length) { + lo_message msg = lo_message_deserialise((void*)reply_buffer, + length, NULL); + lo_address addr = lo_address_new_from_url(mw->activeUrl().c_str()); + if(addr) + lo_send_message(addr, reply_buffer, msg); + lo_address_free(addr); + lo_message_free(msg); + } + } + else if(buffer[0]=='/' && strrchr(buffer, '/')[1]) + { mw->transmitMsg(rtosc::Ports::collapsePath(buffer)); } @@ -1724,7 +1723,7 @@ void MiddleWareImpl::heartBeat(Master *master) //Last provided beat //Last acknowledged beat //Current offline status - + struct timespec time; monotonic_clock_gettime(&time); uint32_t now = (time.tv_sec-start_time_sec)*100 + 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/Plugin/ZynAddSubFX/ZynAddSubFX-UI-Zest.cpp b/src/Plugin/ZynAddSubFX/ZynAddSubFX-UI-Zest.cpp @@ -28,9 +28,9 @@ struct zest_handles { void (*zest_close)(zest_t*); void (*zest_setup)(zest_t*); void (*zest_draw)(zest_t*); - void (*zest_motion)(zest_t*, int x, int y); - void (*zest_scroll)(zest_t*, int x, int y, int dx, int dy); - void (*zest_mouse)(zest_t *z, int button, int action, int x, int y); + void (*zest_motion)(zest_t*, int x, int y, int mod); + void (*zest_scroll)(zest_t*, int x, int y, int dx, int dy, int mod); + void (*zest_mouse)(zest_t *z, int button, int action, int x, int y, int mod); void (*zest_key)(zest_t *z, char *key, bool press); void (*zest_resize)(zest_t *z, int w, int h); void (*zest_special)(zest_t *z, int key, int press); @@ -158,7 +158,7 @@ protected: bool onScroll(const ScrollEvent &ev) override { if(z.zest) - z.zest_scroll(z.zest, ev.pos.getX(), ev.pos.getY(), ev.delta.getX(), ev.delta.getY()); + z.zest_scroll(z.zest, ev.pos.getX(), ev.pos.getY(), ev.delta.getX(), ev.delta.getY(), ev.mod); return false; } @@ -173,14 +173,14 @@ protected: bool onMouse(const MouseEvent &m) override { if(z.zest) - z.zest_mouse(z.zest, m.button, m.press, m.pos.getX(), m.pos.getY()); + z.zest_mouse(z.zest, m.button, m.press, m.pos.getX(), m.pos.getY(), m.mod); return false; } bool onMotion(const MotionEvent &m) override { if(z.zest) - z.zest_motion(z.zest, m.pos.getX(), m.pos.getY()); + z.zest_motion(z.zest, m.pos.getX(), m.pos.getY(), m.mod); return false; } 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, @@ -669,9 +674,6 @@ void ADnote::legatonote(LegatoParams lpars) * VelF( velocity, pars.GlobalPar.PAmpVelocityScaleFunction); //velocity sensing - globalnewamplitude = NoteGlobalPar.Volume - * NoteGlobalPar.AmpEnvelope->envout_dB() - * NoteGlobalPar.AmpLfo->amplfoout(); { auto *filter = NoteGlobalPar.Filter; @@ -703,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; @@ -862,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) { @@ -73,7 +73,7 @@ void PADnote::setup(float freq, BendAdjust = BendAdj / 24.0f; float offset_val = (pars.POffsetHz - 64)/64.0f; OffsetHz = 15.0f*(offset_val * sqrtf(fabsf(offset_val))); - firsttime = true; + if(!legato) firsttime = true; realfreq = basefreq; if(!legato) NoteGlobalPar.Detune = getdetune(pars.PDetuneType, pars.PCoarseDetune, @@ -156,11 +156,13 @@ void PADnote::setup(float freq, * powf(0.1f, 3.0f * (1.0f - pars.PVolume / 96.0f)) //-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(); + if (!legato) { + NoteGlobalPar.AmpEnvelope->envout_dB(); //discard the first envelope output + globaloldamplitude = globalnewamplitude = NoteGlobalPar.Volume + * NoteGlobalPar.AmpEnvelope-> + envout_dB() + * NoteGlobalPar.AmpLfo->amplfoout(); + } if(!legato) { ScratchString pre = prefix; @@ -194,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 @@ -168,9 +168,8 @@ void SUBnote::setup(float freq, } //how much the amplitude is normalised (because the harmonics) - float reduceamp = setupFilters(pos, false); + float reduceamp = setupFilters(pos, legato); oldreduceamp = reduceamp; - volume /= reduceamp; oldpitchwheel = 0; @@ -197,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); diff --git a/zynaddsubfx-jack-multi.desktop b/zynaddsubfx-jack-multi.desktop @@ -1,5 +1,6 @@ [Desktop Entry] Name=ZynAddSubFX - Jack (multi channel) +Name[fr]=ZynAddSubFX - Jack (multi canaux) Comment=A powerful realtime software synthesizer Comment[fr]=Un synthétiseur logiciel temps-réel puissant Comment[pl]=Funkcjonalny syntezator wirtualny czasu rzeczywistego