From efe169c36a145696e64892d53d8c90556a9e7b91 Mon Sep 17 00:00:00 2001 From: Vitaly Novichkov Date: Wed, 4 Jul 2018 03:42:23 +0300 Subject: Continue documenting, and apply some minor fixes on other files --- src/midi_sequencer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/midi_sequencer.hpp') diff --git a/src/midi_sequencer.hpp b/src/midi_sequencer.hpp index 89b4619..6eeefa9 100644 --- a/src/midi_sequencer.hpp +++ b/src/midi_sequencer.hpp @@ -354,7 +354,7 @@ public: /** * @brief Sets the RT interface - * @param interface Pre-Initialized interface structure (pointer will be taken) + * @param intrf Pre-Initialized interface structure (pointer will be taken) */ void setInterface(const BW_MidiRtInterface *intrf); -- cgit v1.2.3 From 7cb0fe9dad9f7ef24d1142d866450305102bf3a9 Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Sat, 7 Jul 2018 02:03:01 +0200 Subject: sequencer API to turn tracks on/off/solo --- src/midi_sequencer.hpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'src/midi_sequencer.hpp') diff --git a/src/midi_sequencer.hpp b/src/midi_sequencer.hpp index 6eeefa9..71e06b5 100644 --- a/src/midi_sequencer.hpp +++ b/src/midi_sequencer.hpp @@ -343,6 +343,11 @@ private: //! Are loop points invalid? bool m_invalidLoop; /*Loop points are invalid (loopStart after loopEnd or loopStart and loopEnd are on same place)*/ + //! Whether the nth track has playback disabled + std::vector m_trackDisable; + //! Index of solo track, or max for disabled + size_t m_trackSolo; + //! File parsing errors string (adding into m_errorString on aborting of the process) std::string m_parsingErrorsString; //! Common error string @@ -364,6 +369,26 @@ public: */ FileFormat getFormat(); + /** + * @brief Returns the number of tracks + * @return Track count + */ + size_t getTrackCount() const; + + /** + * @brief Sets whether a track is playing + * @param track Track identifier + * @param enable Whether to enable track playback + * @return true on success, false if there was no such track + */ + bool setTrackEnabled(size_t track, bool enable); + + /** + * @brief Enables or disables solo on a track + * @param track Identifier of solo track, or max to disable + */ + void setSoloTrack(size_t track); + /** * @brief Get the list of CMF instruments (CMF only) * @return Array of raw CMF instruments entries -- cgit v1.2.3 From e8367d5048b6df7d16ec62a35161d846c41d8358 Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Sat, 7 Jul 2018 18:41:15 +0200 Subject: exception for SMF track 0 when format != 2 --- src/midi_sequencer.hpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/midi_sequencer.hpp') diff --git a/src/midi_sequencer.hpp b/src/midi_sequencer.hpp index 71e06b5..8b3c4a1 100644 --- a/src/midi_sequencer.hpp +++ b/src/midi_sequencer.hpp @@ -291,6 +291,8 @@ public: private: //! Music file format type. MIDI is default. FileFormat m_format; + //! SMF format identifier. + unsigned m_smfFormat; //! Current position Position m_currentPosition; -- cgit v1.2.3 From 75dda861e1ea98c4dbc0123fc20516d0ddf70463 Mon Sep 17 00:00:00 2001 From: Vitaly Novichkov Date: Sun, 8 Jul 2018 06:39:42 +0300 Subject: [Experimental] Complex loop support --- src/midi_sequencer.hpp | 123 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 113 insertions(+), 10 deletions(-) (limited to 'src/midi_sequencer.hpp') 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 //! [Non-Standard] Raw OPL data - ST_RAWOPL = 0xE3//size == 0 + ST_RAWOPL = 0xE3,//size == 0 + + //! [Non-Standard] Loop Start point with support of multi-loops + ST_LOOPSTACK_BEGIN = 0xE4,//size == 1 + //! [Non-Standard] Loop End point with support of multi-loops + ST_LOOPSTACK_END = 0xE5,//size == 0 + //! [Non-Standard] Loop End point with support of multi-loops + ST_LOOPSTACK_BREAK = 0xE6,//size == 0 }; //! 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 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(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(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 m_trackDisable; -- cgit v1.2.3 From 9fdaf5361c57438bf7f5bafaf6bb9a79b6bb7493 Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Mon, 9 Jul 2018 20:20:55 +0200 Subject: xmi: handle AIL callback trigger --- src/midi_sequencer.hpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'src/midi_sequencer.hpp') diff --git a/src/midi_sequencer.hpp b/src/midi_sequencer.hpp index 8cb8c6e..2c75da4 100644 --- a/src/midi_sequencer.hpp +++ b/src/midi_sequencer.hpp @@ -131,6 +131,8 @@ class BW_MidiSequencer ST_LOOPSTACK_END = 0xE5,//size == 0 //! [Non-Standard] Loop End point with support of multi-loops ST_LOOPSTACK_BREAK = 0xE6,//size == 0 + //! [Non-Standard] Callback Trigger + ST_CALLBACK_TRIGGER = 0xE7,//size == 1 }; //! Main type of event uint8_t type; @@ -453,6 +455,19 @@ private: //! Index of solo track, or max for disabled size_t m_trackSolo; + /** + * @brief Handler of callback trigger events + * @param userData Pointer to user data (usually, context of something) + * @param trigger Value of the event which triggered this callback. + * @param track Identifier of the track which triggered this callback. + */ + typedef void (*TriggerHandler)(void *userData, unsigned trigger, size_t track); + + //! Handler of callback trigger events + TriggerHandler m_triggerHandler; + //! User data of callback trigger events + void *m_triggerUserData; + //! File parsing errors string (adding into m_errorString on aborting of the process) std::string m_parsingErrorsString; //! Common error string @@ -494,6 +509,13 @@ public: */ void setSoloTrack(size_t track); + /** + * @brief Defines a handler for callback trigger events + * @param handler Handler to invoke from the sequencer when triggered, or NULL. + * @param userData Instance of the library + */ + void setTriggerHandler(TriggerHandler handler, void *userData); + /** * @brief Get the list of CMF instruments (CMF only) * @return Array of raw CMF instruments entries -- cgit v1.2.3 From 64cf77dd2e516af0f1b47285a39f5031e3cee86f Mon Sep 17 00:00:00 2001 From: Vitaly Novichkov Date: Wed, 11 Jul 2018 02:37:22 +0300 Subject: MIDI Sequencer: Split the loadMIDI function --- src/midi_sequencer.hpp | 80 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) (limited to 'src/midi_sequencer.hpp') diff --git a/src/midi_sequencer.hpp b/src/midi_sequencer.hpp index 2c75da4..b49c536 100644 --- a/src/midi_sequencer.hpp +++ b/src/midi_sequencer.hpp @@ -229,11 +229,27 @@ class BW_MidiSequencer //! MIDI Output interface context const BW_MidiRtInterface *m_interface; + /** + * @brief Prepare internal events storage for track data building + * @param trackCount Count of tracks + */ + void buildSmfSetupReset(size_t trackCount); + /** * @brief Build MIDI track data from the raw track data storage * @return true if everything successfully processed, or false on any error */ - bool buildTrackData(const std::vector > &trackData); + bool buildSmfTrackData(const std::vector > &trackData); + + /** + * @brief Build the time line from off loaded events + * @param tempos Pre-collected list of tempo events + * @param loopStartTicks Global loop start tick (give zero if no global loop presented) + * @param loopEndTicks Global loop end tick (give zero if no global loop presented) + */ + void buildTimeLine(const std::vector &tempos, + uint64_t loopStartTicks = 0, + uint64_t loopEndTicks = 0); /** * @brief Parse one event from raw MIDI track stream @@ -648,6 +664,68 @@ public: * @param tempo Tempo multiplier: 1.0 - original tempo. >1 - faster, <1 - slower */ void setTempo(double tempo); + +private: + /** + * @brief Load file as Id-software-Music-File (Wolfenstein) + * @param fr Context with opened file + * @return true on successful load + */ + bool parseIMF(FileAndMemReader &fr); + + /** + * @brief Load file as EA MUS + * @param fr Context with opened file + * @return true on successful load + */ + bool parseRSXX(FileAndMemReader &fr); + + /** + * @brief Load file as Creative Music Format + * @param fr Context with opened file + * @return true on successful load + */ + bool parseCMF(FileAndMemReader &fr); + + /** + * @brief Load file as GMF (ScummVM) + * @param fr Context with opened file + * @return true on successful load + */ + bool parseGMF(FileAndMemReader &fr); + + /** + * @brief Load file as Standard MIDI file + * @param fr Context with opened file + * @return true on successful load + */ + bool parseSMF(FileAndMemReader &fr); + + /** + * @brief Load file as RIFF MIDI + * @param fr Context with opened file + * @return true on successful load + */ + bool parseRMI(FileAndMemReader &fr); + +#ifndef BWMIDI_DISABLE_MUS_SUPPORT + /** + * @brief Load file as DMX MUS file (Doom) + * @param fr Context with opened file + * @return true on successful load + */ + bool parseMUS(FileAndMemReader &fr); +#endif + +#ifndef BWMIDI_DISABLE_XMI_SUPPORT + /** + * @brief Load file as AIL eXtended MIdi + * @param fr Context with opened file + * @return true on successful load + */ + bool parseXMI(FileAndMemReader &fr); +#endif + }; #endif /* BISQUIT_AND_WOHLSTANDS_MIDI_SEQUENCER_HHHHPPP */ -- cgit v1.2.3 From 35aacd58e6a4617c6032f940d32a25b10ecd2374 Mon Sep 17 00:00:00 2001 From: Vitaly Novichkov Date: Wed, 11 Jul 2018 03:20:02 +0300 Subject: Sequencer: Minor fix of comments --- src/midi_sequencer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/midi_sequencer.hpp') diff --git a/src/midi_sequencer.hpp b/src/midi_sequencer.hpp index b49c536..2009892 100644 --- a/src/midi_sequencer.hpp +++ b/src/midi_sequencer.hpp @@ -688,7 +688,7 @@ private: bool parseCMF(FileAndMemReader &fr); /** - * @brief Load file as GMF (ScummVM) + * @brief Load file as GMD/MUS files (ScummVM) * @param fr Context with opened file * @return true on successful load */ -- cgit v1.2.3 From e098e4285af6d565d7b603279ec6e9770ce88436 Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Tue, 31 Jul 2018 02:31:47 +0200 Subject: fix some warnings --- src/midi_sequencer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/midi_sequencer.hpp') diff --git a/src/midi_sequencer.hpp b/src/midi_sequencer.hpp index 2009892..a8cbfac 100644 --- a/src/midi_sequencer.hpp +++ b/src/midi_sequencer.hpp @@ -132,7 +132,7 @@ class BW_MidiSequencer //! [Non-Standard] Loop End point with support of multi-loops ST_LOOPSTACK_BREAK = 0xE6,//size == 0 //! [Non-Standard] Callback Trigger - ST_CALLBACK_TRIGGER = 0xE7,//size == 1 + ST_CALLBACK_TRIGGER = 0xE7//size == 1 }; //! Main type of event uint8_t type; -- cgit v1.2.3