diff options
author | Vitaly Novichkov <admin@wohlnet.ru> | 2018-07-08 06:39:42 +0300 |
---|---|---|
committer | Vitaly Novichkov <admin@wohlnet.ru> | 2018-07-08 06:39:42 +0300 |
commit | 75dda861e1ea98c4dbc0123fc20516d0ddf70463 (patch) | |
tree | 671129787379ea4de41906f544c6a5a3b1475a81 /src/midi_sequencer.hpp | |
parent | 4664f286e238e97d0d6b3bc4dff5f0640a277e7f (diff) | |
download | libADLMIDI-75dda861e1ea98c4dbc0123fc20516d0ddf70463.tar.gz libADLMIDI-75dda861e1ea98c4dbc0123fc20516d0ddf70463.tar.bz2 libADLMIDI-75dda861e1ea98c4dbc0123fc20516d0ddf70463.zip |
[Experimental] Complex loop support
Diffstat (limited to 'src/midi_sequencer.hpp')
-rw-r--r-- | src/midi_sequencer.hpp | 123 |
1 files changed, 113 insertions, 10 deletions
diff --git a/src/midi_sequencer.hpp b/src/midi_sequencer.hpp index 8b3c4a1..8cb8c6e 100644 --- a/src/midi_sequencer.hpp +++ b/src/midi_sequencer.hpp @@ -123,7 +123,14 @@ class BW_MidiSequencer //! [Non-Standard] Loop End point ST_LOOPEND = 0xE2,//size == 0 <CUSTOM> //! [Non-Standard] Raw OPL data - ST_RAWOPL = 0xE3//size == 0 <CUSTOM> + ST_RAWOPL = 0xE3,//size == 0 <CUSTOM> + + //! [Non-Standard] Loop Start point with support of multi-loops + ST_LOOPSTACK_BEGIN = 0xE4,//size == 1 <CUSTOM> + //! [Non-Standard] Loop End point with support of multi-loops + ST_LOOPSTACK_END = 0xE5,//size == 0 <CUSTOM> + //! [Non-Standard] Loop End point with support of multi-loops + ST_LOOPSTACK_BREAK = 0xE6,//size == 0 <CUSTOM> }; //! Main type of event uint8_t type; @@ -285,7 +292,9 @@ public: //! Id-Software Music File Format_IMF, //! EA-MUS format - Format_RSXX + Format_RSXX, + //! AIL's XMIDI format (act same as MIDI, but with exceptions) + Format_XMIDI }; private: @@ -309,9 +318,9 @@ private: //! Delay after song playd before rejecting the output stream requests double m_postSongWaitDelay; - //! Loop start time + //! Global loop start time double m_loopStartTime; - //! Loop end time + //! Global loop end time double m_loopEndTime; //! Pre-processed track data storage @@ -338,12 +347,106 @@ private: double m_tempoMultiplier; //! Is song at end bool m_atEnd; - //! Loop start has reached - bool m_loopStart; - //! Loop end has reached, reset on handling - bool m_loopEnd; - //! Are loop points invalid? - bool m_invalidLoop; /*Loop points are invalid (loopStart after loopEnd or loopStart and loopEnd are on same place)*/ + + /** + * @brief Loop stack entry + */ + struct LoopStackEntry + { + //! is infinite loop + bool infinity; + //! Count of loops left to break. <0 - infinite loop + int loops; + //! Start position snapshot to return back + Position startPosition; + //! Loop start tick + uint64_t start; + //! Loop end tick + uint64_t end; + }; + + struct LoopState + { + //! Loop start has reached + bool caughtStart; + //! Loop end has reached, reset on handling + bool caughtEnd; + + //! Loop start has reached + bool caughtStackStart; + //! Loop next has reached, reset on handling + bool caughtStackEnd; + //! Loop break has reached, reset on handling + bool caughtStackBreak; + //! Skip next stack loop start event handling + bool skipStackStart; + + //! Are loop points invalid? + bool invalidLoop; /*Loop points are invalid (loopStart after loopEnd or loopStart and loopEnd are on same place)*/ + + //! Stack of nested loops + std::vector<LoopStackEntry> stack; + //! Current level on the loop stack (<0 - out of loop, 0++ - the index in the loop stack) + int stackLevel; + + /** + * @brief Reset loop state to initial + */ + void reset() + { + caughtStart = false; + caughtEnd = false; + caughtStackStart = false; + caughtStackEnd = false; + caughtStackBreak = false; + skipStackStart = false; + } + + void fullReset() + { + reset(); + invalidLoop = false; + stack.clear(); + stackLevel = -1; + } + + bool isStackEnd() + { + if(caughtStackEnd && (stackLevel >= 0) && (stackLevel < static_cast<int>(stack.size()))) + { + const LoopStackEntry &e = stack[stackLevel]; + if(e.infinity || (!e.infinity && e.loops > 0)) + return true; + } + return false; + } + + void stackUp(int count = 1) + { + stackLevel += count; + } + + void stackDown(int count = 1) + { + stackLevel -= count; + } + + LoopStackEntry &getCurStack() + { + if((stackLevel >= 0) && (stackLevel < static_cast<int>(stack.size()))) + return stack[stackLevel]; + if(stack.empty()) + { + LoopStackEntry d; + d.loops = 0; + d.infinity = 0; + d.start = 0; + d.end = 0; + stack.push_back(d); + } + return stack[0]; + } + } m_loop; //! Whether the nth track has playback disabled std::vector<bool> m_trackDisable; |