diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index c4e1346e..1230cb59 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -3210,7 +3210,7 @@ bool DivEngine::moveSampleDown(int which) { void DivEngine::noteOn(int chan, int ins, int note, int vol) { if (chan<0 || chan>=chans) return; BUSY_BEGIN; - pendingNotes.push(DivNoteEvent(chan,ins,note,vol,true)); + pendingNotes.push_back(DivNoteEvent(chan,ins,note,vol,true)); if (!playing) { reset(); freelance=true; @@ -3222,7 +3222,7 @@ void DivEngine::noteOn(int chan, int ins, int note, int vol) { void DivEngine::noteOff(int chan) { if (chan<0 || chan>=chans) return; BUSY_BEGIN; - pendingNotes.push(DivNoteEvent(chan,-1,-1,-1,false)); + pendingNotes.push_back(DivNoteEvent(chan,-1,-1,-1,false)); if (!playing) { reset(); freelance=true; @@ -3274,7 +3274,7 @@ void DivEngine::autoNoteOn(int ch, int ins, int note, int vol) { if ((!midiPoly) || (isViable[finalChan] && chan[finalChan].midiNote==-1 && (insInst->type==DIV_INS_OPL || getChannelType(finalChan)==finalChanType || notInViableChannel))) { chan[finalChan].midiNote=note; chan[finalChan].midiAge=midiAgeCounter++; - pendingNotes.push(DivNoteEvent(finalChan,ins,note,vol,true)); + pendingNotes.push_back(DivNoteEvent(finalChan,ins,note,vol,true)); return; } if (++finalChan>=chans) { @@ -3295,7 +3295,7 @@ void DivEngine::autoNoteOn(int ch, int ins, int note, int vol) { chan[candidate].midiNote=note; chan[candidate].midiAge=midiAgeCounter++; - pendingNotes.push(DivNoteEvent(candidate,ins,note,vol,true)); + pendingNotes.push_back(DivNoteEvent(candidate,ins,note,vol,true)); } void DivEngine::autoNoteOff(int ch, int note, int vol) { @@ -3307,7 +3307,7 @@ void DivEngine::autoNoteOff(int ch, int note, int vol) { //if (ch<0 || ch>=chans) return; for (int i=0; i #include #include -#include +#include #define addWarning(x) \ if (warnings.empty()) { \ @@ -357,7 +357,7 @@ class DivEngine { DivAudioExportModes exportMode; double exportFadeOut; std::map conf; - std::queue pendingNotes; + std::deque pendingNotes; bool isMuted[DIV_MAX_CHANS]; std::mutex isBusy, saveLock; String configPath; diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index f4c4968d..7fb9583d 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -1010,10 +1010,27 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) { //output->midiOut->send(TAMidiMessage(TA_MIDI_CLOCK,0,0)); } + if (!pendingNotes.empty()) { + bool isOn[DIV_MAX_CHANS]; + memset(isOn,0,DIV_MAX_CHANS*sizeof(bool)); + + for (int i=pendingNotes.size()-1; i>=0; i--) { + if (pendingNotes[i].channel<0 || pendingNotes[i].channel>=chans) continue; + if (pendingNotes[i].on) { + isOn[pendingNotes[i].channel]=true; + } else { + if (isOn[pendingNotes[i].channel]) { + logV("erasing off -> on sequence in %d",pendingNotes[i].channel); + pendingNotes.erase(pendingNotes.begin()+i); + } + } + } + } + while (!pendingNotes.empty()) { DivNoteEvent& note=pendingNotes.front(); if (note.channel<0 || note.channel>=chans) { - pendingNotes.pop(); + pendingNotes.pop_front(); continue; } if (note.on) { @@ -1033,7 +1050,7 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) { dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF,note.channel)); } } - pendingNotes.pop(); + pendingNotes.pop_front(); } if (!freelance) { @@ -1245,7 +1262,7 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi case TA_MIDI_NOTE_OFF: { if (chan<0 || chan>=chans) break; if (midiIsDirect) { - pendingNotes.push(DivNoteEvent(chan,-1,-1,-1,false)); + pendingNotes.push_back(DivNoteEvent(chan,-1,-1,-1,false)); } else { autoNoteOff(msg.type&15,msg.data[0]-12,msg.data[1]); } @@ -1260,13 +1277,13 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi if (chan<0 || chan>=chans) break; if (msg.data[1]==0) { if (midiIsDirect) { - pendingNotes.push(DivNoteEvent(chan,-1,-1,-1,false)); + pendingNotes.push_back(DivNoteEvent(chan,-1,-1,-1,false)); } else { autoNoteOff(msg.type&15,msg.data[0]-12,msg.data[1]); } } else { if (midiIsDirect) { - pendingNotes.push(DivNoteEvent(chan,ins,msg.data[0]-12,msg.data[1],true)); + pendingNotes.push_back(DivNoteEvent(chan,ins,msg.data[0]-12,msg.data[1],true)); } else { autoNoteOn(msg.type&15,ins,msg.data[0]-12,msg.data[1]); }