diff --git a/scripts/string_model.py b/scripts/string_model.py new file mode 100644 index 0000000..38a0f90 --- /dev/null +++ b/scripts/string_model.py @@ -0,0 +1,35 @@ + +import scipy.signal as sig +import matplotlib.pyplot as plt +import numpy as np + +# simple first order step response simulation +# www.halvorsen.blog/documents/programming/python/resources/powerpoints/State Space Models with Python.pdf + +# simulation Parameters +x0 = [0, 0] +start = 0 +stop = 30 +step = 1 + +t = np.arange(start,stop,step) +K = 3 +T = 4 + +# state-space Model +A = [[-1/T, 0], [0, 0]] +B = [[K/T], [0]] +C = [[1, 0]] +D = 0 +sys = sig.StateSpace(A, B, C, D) + +# step Response +t, y = sig.step(sys, x0, t) + +# plotting +plt.plot(t, y) +plt.title("Step Response") +plt.xlabel("t") +plt.ylabel("y") +plt.grid() +plt.show() diff --git a/src/synth/Instrument.cpp b/src/synth/Instrument.cpp index 6f46d52..b0700b6 100644 --- a/src/synth/Instrument.cpp +++ b/src/synth/Instrument.cpp @@ -28,7 +28,7 @@ bool Instrument::isActive() { float Instrument::process(bool& scopeTrigger) { if(active_ && envelope_ < 1.0f) envelope_ += 0.01f; - if(!active_ && envelope_ > 0.0f) envelope_ -= 0.01f; + if(!active_ && envelope_ > 0.0f) envelope_ -= 0.0004f; phase_ += phaseIncrement_; if(phase_ > 2.0f * pi) { @@ -37,6 +37,10 @@ float Instrument::process(bool& scopeTrigger) { } if(!isActive()) return 0.0f; - return sin(phase_) * envelope_; + + // float sample = sin(phase_); + float sample = phase_ / pi - 1.0f; // saw + + return sample * envelope_; } diff --git a/src/synth/Synth.cpp b/src/synth/Synth.cpp index b16d9c2..5707c77 100644 --- a/src/synth/Synth.cpp +++ b/src/synth/Synth.cpp @@ -10,12 +10,19 @@ Synth::Synth(ConfigService* config, LoggerService* logger, ScopeBuffer* scope, N void Synth::handleNoteEvent(const NoteEvent& event) { - Voice* v = findVoiceByNote(event.note); - if(v != nullptr) v->noteOff(); + // Voice* v = findVoiceByNote(event.note); + // if(v != nullptr) v->noteOff(); + + // stop all voices that are currently playing this note + for(Voice& v : voices_) { + if(v.isActive() && v.note() == event.note) { + v.noteOff(); + } + } if(event.type == NoteEventType::NoteOn) { - v = findFreeVoice(); + Voice* v = findFreeVoice(); if(v != nullptr) v->noteOn(event.note, event.velocity); }