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:
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.