zynaddsubfx

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

commit 542e497ce79a13ff8b0dd7fc39c1c83d268e7dce
parent ce7a8a9ea54470e81ec801debaf2ea6965d5bdfc
Author: fundamental <mark.d.mccurry@gmail.com>
Date:   Sat, 14 Feb 2015 15:46:55 -0500

Part: Replace Legato Note Pseudo-Stack

Old std::list is replaced with a short[256] to avoid any
possible allocations

Diffstat:
Msrc/Misc/MiddleWare.cpp | 1+
Msrc/Misc/Part.cpp | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Msrc/Misc/Part.h | 9+++++++--
3 files changed, 69 insertions(+), 28 deletions(-)

diff --git a/src/Misc/MiddleWare.cpp b/src/Misc/MiddleWare.cpp @@ -31,6 +31,7 @@ #include <string> #include <future> #include <atomic> +#include <list> #include <err.h> diff --git a/src/Misc/Part.cpp b/src/Misc/Part.cpp @@ -174,6 +174,8 @@ Part::Part(Allocator &alloc, Microtonal *microtonal_, FFTwrapper *fft_) partoutl = new float [synth->buffersize]; partoutr = new float [synth->buffersize]; + monomemClear(); + for(int n = 0; n < NUM_KIT_ITEMS; ++n) { kit[n].Pname = new char [PART_MAX_NAME_LEN]; kit[n].adpars = nullptr; @@ -194,7 +196,7 @@ Part::Part(Allocator &alloc, Microtonal *microtonal_, FFTwrapper *fft_) partfxinputr[n] = new float [synth->buffersize]; } - killallnotes = 0; + killallnotes = false; oldfreq = -1.0f; @@ -349,37 +351,31 @@ void Part::NoteOn(unsigned char note, unsigned char velocity, int masterkeyshift) { - int pos; - // Legato and MonoMem used vars: int posb = POLIPHONY - 1; // Just a dummy initial value. bool legatomodevalid = false; //true when legato mode is determined applicable. bool doinglegato = false; // true when we determined we do a legato note. bool ismonofirstnote = false; /*(In Mono/Legato) true when we determined - no other notes are held down or sustained.*/ + no other notes are held down or sustained.*/ int lastnotecopy = lastnote; //Useful after lastnote has been changed. if(!Pnoteon || !inRange(note, Pminkey, Pmaxkey)) return; // MonoMem stuff: - if(Ppolymode == 0) { // If Poly is off - monomemnotes.push_back(note); // Add note to the list. + if(!Ppolymode) { // If Poly is off + monomemPush(note); // Add note to the list. monomem[note].velocity = velocity; // Store this note's velocity. - monomem[note].mkeyshift = masterkeyshift; /* Store masterkeyshift too, - I'm not sure why though... */ + monomem[note].mkeyshift = masterkeyshift; /* Store masterkeyshift too*/ if((partnote[lastpos].status != KEY_PLAYING) && (partnote[lastpos].status != KEY_RELASED_AND_SUSTAINED)) ismonofirstnote = true; // No other keys are held or sustained. - } - else - // Poly mode is On so just make sure the list is empty. - if(not monomemnotes.empty()) - monomemnotes.clear(); + } else if(!monomemEmpty()) + monomemClear(); lastnote = note; - pos = -1; + int pos = -1; for(int i = 0; i < POLIPHONY; ++i) if(partnote[i].status == KEY_OFF) { pos = i; @@ -542,7 +538,7 @@ void Part::NoteOn(unsigned char note, } if(ci == 0) { // No legato were performed at all, so pretend nothing happened: - monomemnotes.pop_back(); // Remove last note from the list. + monomemPop(monomemBack()); // Remove last note from the list. lastnote = lastnotecopy; // Set lastnote back to previous value. } } @@ -653,13 +649,13 @@ void Part::NoteOn(unsigned char note, void Part::NoteOff(unsigned char note) //relase the key { // This note is released, so we remove it from the list. - if(!monomemnotes.empty()) - monomemnotes.remove(note); + if(!monomemEmpty()) + monomemPop(note); for(int i = POLIPHONY - 1; i >= 0; i--) //first note in, is first out if there are same note multiple times if((partnote[i].status == KEY_PLAYING) && (partnote[i].note == note)) { if(!ctl.sustain.sustain) { //the sustain pedal is not pushed - if(!Ppolymode && !monomemnotes.empty()) + if(!Ppolymode && !monomemEmpty()) MonoMemRenote();//Play most recent still active note else RelaseNotePos(i); @@ -812,8 +808,8 @@ void Part::SetController(unsigned int type, int par) void Part::RelaseSustainedKeys() { // Let's call MonoMemRenote() on some conditions: - if((Ppolymode == 0) && (not monomemnotes.empty())) - if(monomemnotes.back() != lastnote) // Sustain controller manipulation would cause repeated same note respawn without this check. + if(Ppolymode == 0 && !monomemEmpty()) + if(monomemBack() != lastnote) // Sustain controller manipulation would cause repeated same note respawn without this check. MonoMemRenote(); // To play most recent still held note. for(int i = 0; i < POLIPHONY; ++i) @@ -837,8 +833,8 @@ void Part::RelaseAllKeys() // (Made for Mono/Legato). void Part::MonoMemRenote() { - unsigned char mmrtempnote = monomemnotes.back(); // Last list element. - monomemnotes.pop_back(); // We remove it, will be added again in NoteOn(...). + unsigned char mmrtempnote = monomemBack(); // Last list element. + monomemPop(mmrtempnote); // We remove it, will be added again in NoteOn(...). if(Pnoteon == 0) RelaseNotePos(lastpos); else @@ -924,7 +920,7 @@ void Part::setkeylimit(unsigned char Pkeylimit) */ void Part::AllNotesOff() { - killallnotes = 1; + killallnotes = true; } void Part::RunNote(unsigned int k) @@ -1007,8 +1003,7 @@ void Part::ComputePartSmps() partoutr[i] = partfxinputr[NUM_PART_EFX][i]; } - //Kill All Notes if killallnotes!=0 - if(killallnotes != 0) { + if(killallnotes) { for(int i = 0; i < synth->buffersize; ++i) { float tmp = (synth->buffersize_f - i) / synth->buffersize_f; partoutl[i] *= tmp; @@ -1016,7 +1011,7 @@ void Part::ComputePartSmps() } for(int k = 0; k < POLIPHONY; ++k) KillNotePos(k); - killallnotes = 0; + killallnotes = false; for(int nefx = 0; nefx < NUM_PART_EFX; ++nefx) partefx[nefx]->cleanup(); } @@ -1225,6 +1220,46 @@ void Part::kill_rt(void) KillNotePos(k); } +void Part::monomemPush(char note) +{ + for(int i=0; i<256; ++i) + if(monomemnotes[i]==note) + return; + + for(int i=254;i>=0; --i) + monomemnotes[i+1] = monomemnotes[i]; + monomemnotes[0] = note; +} + +void Part::monomemPop(char note) +{ + int note_pos=-1; + for(int i=0; i<256; ++i) + if(monomemnotes[i]==note) + note_pos = i; + if(note_pos != -1) { + for(int i=note_pos; i<256; ++i) + monomemnotes[i] = monomemnotes[i+1]; + monomemnotes[255] = -1; + } +} + +char Part::monomemBack(void) const +{ + return monomemnotes[0]; +} + +bool Part::monomemEmpty(void) const +{ + return monomemnotes[0] == -1; +} + +void Part::monomemClear(void) +{ + for(int i=0; i<256; ++i) + monomemnotes[i] = -1; +} + void Part::getfromXMLinstrument(XMLwrapper *xml) { if(xml->enterbranch("INFO")) { diff --git a/src/Misc/Part.h b/src/Misc/Part.h @@ -29,7 +29,6 @@ #include "../Params/Controller.h" #include <functional> -#include <list> // For the monomemnotes list. /** Part implementation*/ class Part @@ -176,7 +175,13 @@ class Part bool lastlegatomodevalid; // To keep track of previous legatomodevalid. // MonoMem stuff - std::list<unsigned char> monomemnotes; // A list to remember held notes. + void monomemPush(char note); + void monomemPop(char note); + char monomemBack(void) const; + bool monomemEmpty(void) const; + void monomemClear(void); + + short monomemnotes[256]; // A list to remember held notes. struct { unsigned char velocity; int mkeyshift; // I'm not sure masterkeyshift should be remembered.