diff --git a/src/engine/engine.h b/src/engine/engine.h index 561cef222..9b85d0837 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -37,7 +37,7 @@ #include #include #include -#include +#include "fixedQueue.h" class DivWorkPool; @@ -176,14 +176,28 @@ struct DivChannelState { }; struct DivNoteEvent { - int channel, ins, note, volume; - bool on; + signed char channel; + unsigned char ins; + signed char note, volume; + bool on, nop, pad1, pad2; DivNoteEvent(int c, int i, int n, int v, bool o): channel(c), ins(i), note(n), volume(v), - on(o) {} + on(o), + nop(false), + pad1(false), + pad2(false) {} + DivNoteEvent(): + channel(-1), + ins(0), + note(0), + volume(0), + on(false), + nop(true), + pad1(false), + pad2(false) {} }; struct DivDispatchContainer { @@ -428,7 +442,7 @@ class DivEngine { DivAudioExportModes exportMode; double exportFadeOut; DivConfig conf; - std::deque pendingNotes; + FixedQueue pendingNotes; // bitfield unsigned char walked[8192]; bool isMuted[DIV_MAX_CHANS]; diff --git a/src/engine/fixedQueue.h b/src/engine/fixedQueue.h index ad43f160d..03a1ed3a1 100644 --- a/src/engine/fixedQueue.h +++ b/src/engine/fixedQueue.h @@ -27,11 +27,14 @@ template struct FixedQueue { size_t readPos, writePos; T data[items]; + T& operator[](size_t pos); T& front(); T& back(); bool pop(); bool push(const T& item); + bool erase(size_t pos); + bool pop_front(); bool pop_back(); bool push_front(const T& item); @@ -44,6 +47,13 @@ template struct FixedQueue { writePos(0) {} }; +template T& FixedQueue::operator[](size_t pos) { + if (pos>=size()) { + logW("accessing invalid position. bug!"); + } + return data[(readPos+pos)%items]; +} + template T& FixedQueue::front() { return data[readPos]; } @@ -53,6 +63,36 @@ template T& FixedQueue::back() { return data[writePos-1]; } +template bool FixedQueue::erase(size_t pos) { + size_t curSize=size(); + if (pos>=curSize) { + logW("accessing invalid position. bug!"); + return false; + } + if (pos==0) { + return pop_front(); + } + if (pos==curSize-1) { + return pop_back(); + } + + for (size_t i=0, p=(readPos+pos)%items, p1=(readPos+pos+1)%items; i<=curSize; i++) { + if (p>=items) p-=items; + if (p1>=items) p1-=items; + data[p]=data[p1]; + p++; + p1++; + } + + if (writePos>0) { + writePos--; + } else { + writePos=items-1; + } + + return true; +} + template bool FixedQueue::pop() { if (readPos==writePos) return false; if (++readPos>=items) readPos=0; diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 5009ba9f4..12a110b5b 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -1346,8 +1346,8 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) { 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); + //logV("erasing off -> on sequence in %d",pendingNotes[i].channel); + pendingNotes[i].nop=true; } } } @@ -1355,7 +1355,7 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) { while (!pendingNotes.empty()) { DivNoteEvent& note=pendingNotes.front(); - if (note.channel<0 || note.channel>=chans) { + if (note.nop || note.channel<0 || note.channel>=chans) { pendingNotes.pop_front(); continue; } @@ -1847,7 +1847,7 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi } } } - logD("%.2x",msg.type); + //logD("%.2x",msg.type); output->midiIn->queue.pop(); } diff --git a/src/engine/sample.h b/src/engine/sample.h index bca881650..3b5a356d3 100644 --- a/src/engine/sample.h +++ b/src/engine/sample.h @@ -24,7 +24,7 @@ #include "defines.h" #include "safeWriter.h" #include "dataErrors.h" -#include +#include "fixedQueue.h" enum DivSampleLoopMode: unsigned char { DIV_SAMPLE_LOOP_FORWARD=0, @@ -144,8 +144,8 @@ struct DivSample { unsigned int samples; - std::deque undoHist; - std::deque redoHist; + FixedQueue undoHist; + FixedQueue redoHist; /** * put sample data. diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 84d3561b6..576068f66 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -2207,7 +2207,7 @@ void FurnaceGUI::pushRecentFile(String path) { if (path.find(backupPath)==0) return; for (int i=0; i<(int)recentFile.size(); i++) { if (recentFile[i]==path) { - recentFile.erase(recentFile.begin()+i); + recentFile.erase(i); i--; } } @@ -3948,7 +3948,7 @@ bool FurnaceGUI::loop() { nextFile=item; showWarning("Unsaved changes! Save changes before opening file?",GUI_WARN_OPEN_DROP); } else { - recentFile.erase(recentFile.begin()+i); + recentFile.erase(i); i--; if (load(item)>0) { showError(fmt::sprintf("Error while loading file! (%s)",lastError)); diff --git a/src/gui/gui.h b/src/gui/gui.h index 1cd703f57..6f4bad90e 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -27,7 +27,6 @@ #include "imgui_impl_sdl2.h" #include #include -#include #include #include #include @@ -874,6 +873,18 @@ struct UndoStep { std::vector ord; std::vector pat; std::vector other; + + UndoStep(): + type(GUI_UNDO_CHANGE_ORDER), + cursor(), + selStart(), + selEnd(), + order(0), + nibble(false), + oldOrdersLen(0), + newOrdersLen(0), + oldPatLen(0), + newPatLen(0) {} }; // -1 = any @@ -1323,7 +1334,7 @@ class FurnaceGUI { std::vector sysSearchResults; std::vector newSongSearchResults; - std::deque recentFile; + FixedQueue recentFile; std::vector makeInsTypeList; std::vector availRenderDrivers; std::vector availAudioDrivers; @@ -1391,7 +1402,7 @@ class FurnaceGUI { String backupPath; std::mutex midiLock; - std::queue midiQueue; + FixedQueue midiQueue; MIDIMap midiMap; int learning; @@ -2005,8 +2016,8 @@ class FurnaceGUI { int oldOrdersLen; DivOrders oldOrders; DivPattern* oldPat[DIV_MAX_CHANS]; - std::deque undoHist; - std::deque redoHist; + FixedQueue undoHist; + FixedQueue redoHist; // sample editor specific double sampleZoom;