diff options
author | Wohlstand <admin@wohlnet.ru> | 2017-10-23 06:12:22 +0300 |
---|---|---|
committer | Wohlstand <admin@wohlnet.ru> | 2017-10-23 06:12:22 +0300 |
commit | a8dde37099558dc805dfa07eb870c2baf66f4fec (patch) | |
tree | ed96c31e202a5f8c7cebb3604144c0d414d361ab /src/adlmidi_private.hpp | |
parent | 490bac7421b5345e5b9035f1430520c751935534 (diff) | |
download | libADLMIDI-a8dde37099558dc805dfa07eb870c2baf66f4fec.tar.gz libADLMIDI-a8dde37099558dc805dfa07eb870c2baf66f4fec.tar.bz2 libADLMIDI-a8dde37099558dc805dfa07eb870c2baf66f4fec.zip |
Prepare to implement seekability - pre-parse all MIDI events before play
All parsed events will be stored into special time marked containers and will be sorted by type to avoid possible issues caused by incorrect order of meta or note-on/off events, etc.
Time markers are needed to easier detect seconds position to seek.
TODO: Fix IMF playback
Diffstat (limited to 'src/adlmidi_private.hpp')
-rw-r--r-- | src/adlmidi_private.hpp | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index cb91616..a6ea6ae 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -298,6 +298,106 @@ public: private: std::vector<AdlChannel> ch; std::vector<std::vector<uint8_t> > TrackData; + + /** + * @brief MIDI Event utility container + */ + class MidiEvent + { + public: + MidiEvent(); + + enum Types + { + T_UNKNOWN = 0x00, + T_NOTEOFF = 0x08, + T_NOTEON = 0x09, + T_NOTETOUCH = 0x0A, + T_CTRLCHANGE = 0x0B, + T_PATCHCHANGE = 0x0C, + T_CHANAFTTOUCH = 0x0D, + T_WHEEL = 0x0E, + + T_SYSEX = 0xF7, + T_SYSEX2 = 0xF0, + T_SPECIAL = 0xFF, + }; + enum SubTypes + { + ST_UNKNOWN = 0x00, + ST_ENDTRACK = 0x2F, + ST_TEMPOCHANGE = 0x51, + ST_META = 0x06, + + /* Non-standard, internal ADLMIDI usage only */ + ST_LOOPSTART = 0xE1, + ST_LOOPEND = 0xE2, + ST_RAWOPL = 0xE3, + }; + //! Main type of event + uint8_t type; + //! Sub-type of the event + uint8_t subtype; + //! Targeted MIDI channel + uint8_t channel; + + //! Reserved 5 bytes padding + uint8_t __padding[5]; + //! Raw data of this event + std::vector<uint8_t> data; + }; + + /** + * @brief A track position event contains a chain of MIDI events until next delay value + * + * Created with purpose to sort events by type in the same position + * (for example, to keep controllers always first than note on events or lower than note-off events) + */ + class MidiTrackPos + { + public: + MidiTrackPos(); + void reset(); + //! Absolute time position in seconds + double time; + //! Delay to next event in ticks + uint64_t delay; + //! Delay to next event in seconds + double timeDelay; + std::vector<MidiEvent> events; + /** + * @brief Sort events in this position + */ + void sortEvents(); + //! Next event that follows current + MidiTrackPos *next; + }; + + // Information about each track + struct PositionNew + { + bool began; + char padding[7]; + double wait; + struct TrackInfo + { + size_t ptr; + uint64_t delay; + int status; + char padding2[4]; + MidiTrackPos *pos; + TrackInfo(): ptr(0), delay(0), status(0), pos(NULL) {} + }; + std::vector<TrackInfo> track; + PositionNew(): began(false), wait(0.0), track() + {} + } CurrentPositionNew, LoopBeginPositionNew, trackBeginPositionNew; + + std::vector<std::vector<MidiTrackPos>> trackDataNew; + std::vector<int> trackDataNewStatus; + void buildTrackData(); + MidiEvent parseEvent(uint8_t **ptr, int &status); + public: MIDIplay(); ~MIDIplay() @@ -319,6 +419,7 @@ public: static uint64_t ReadBEint(const void *buffer, size_t nbytes); static uint64_t ReadLEint(const void *buffer, size_t nbytes); + uint64_t ReadVarLen(uint8_t **ptr); uint64_t ReadVarLen(size_t tk); uint64_t ReadVarLenEx(size_t tk, bool &ok); @@ -524,7 +625,9 @@ private: unsigned props_mask, int32_t select_adlchn = -1); bool ProcessEvents(); + bool ProcessEventsNew(); void HandleEvent(size_t tk); + void HandleEvent(size_t tk, MidiEvent &evt, int &status); // Determine how good a candidate this adlchannel // would be for playing a note from this instrument. |