ScummVM API documentation
midiparser.h
1/* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
23
24#ifndef AUDIO_MIDIPARSER_H
25#define AUDIO_MIDIPARSER_H
26
27#include "common/scummsys.h"
28#include "common/endian.h"
29#include "common/stream.h"
30
31#define AUDIO_MIDIPARSER_MAXIMUM_SUBTRACKS 35
32
33class MidiDriver_BASE;
34
45//
46// Support entities
47//
49
61struct Tracker {
63 const byte * _playPos;
67
68 void clear() {
69 _playPos = nullptr;
73 }
74
75 void stopTracking() {
76 _playPos = nullptr;
77 }
78
79 bool isTracking() const {
80 return _playPos != nullptr;
81 }
82 };
83
84 uint32 _playTime;
85 uint32 _playTick;
89 SubtrackStatus _subtracks[AUDIO_MIDIPARSER_MAXIMUM_SUBTRACKS];
90
91 Tracker() { clear(); }
92
94 void clear() {
95 _playTime = 0;
96 _playTick = 0;
99
100 for (int i = 0; i < AUDIO_MIDIPARSER_MAXIMUM_SUBTRACKS; i++) {
101 _subtracks[i].clear();
102 }
103 }
104
105 bool isTracking() const {
106 for (int i = 0; i < AUDIO_MIDIPARSER_MAXIMUM_SUBTRACKS; i++) {
107 if (_subtracks[i].isTracking())
108 return true;
109 }
110 return false;
111 }
112
113 bool isTracking(uint8 subtrack) const {
114 assert(subtrack < AUDIO_MIDIPARSER_MAXIMUM_SUBTRACKS);
115 return _subtracks[subtrack].isTracking();
116 }
117
118 void stopTracking() {
119 for (int i = 0; i < AUDIO_MIDIPARSER_MAXIMUM_SUBTRACKS; i++) {
120 _subtracks[i].stopTracking();
121 }
122 }
123
124 void stopTracking(uint8 subtrack) {
125 assert(subtrack < AUDIO_MIDIPARSER_MAXIMUM_SUBTRACKS);
126 _subtracks[subtrack].stopTracking();
127 }
128};
129
135struct EventInfo {
136 const byte * start;
138 uint8 subtrack;
139 uint32 delta;
140 byte event;
142 union {
143 struct {
144 byte param1;
145 byte param2;
146 } basic;
147 struct {
148 byte type;
149 const byte * data;
150 } ext;
151 };
152 uint32 length;
156 bool loop;
157 bool noop;
159
160 byte channel() const { return event & 0x0F; }
161 byte command() const { return event >> 4; }
162
163 void clear() {
164 start = nullptr;
165 delta = 0;
166 event = 0;
167 basic.param1 = 0;
168 basic.param2 = 0;
169 ext.type = 0;
170 ext.data = nullptr;
171 length = 0;
172 loop = false;
173 noop = false;
174 }
175
176 EventInfo() : subtrack(0) { clear(); }
177};
178
186struct NoteTimer {
187 byte channel;
188 byte note;
189 uint32 timeLeft;
190 NoteTimer() : channel(0), note(0), timeLeft(0) {}
191};
192
193
194
195
197//
198// MidiParser declaration
199//
201
355protected:
356 static const uint8 MAXIMUM_TRACKS = 120;
357 static const uint8 MAXIMUM_SUBTRACKS = AUDIO_MIDIPARSER_MAXIMUM_SUBTRACKS;
358
359 uint16 _activeNotes[128];
363
365 uint32 _timerRate;
366 uint32 _ppqn;
367 uint32 _tempo;
369 uint32 _sysExDelay;
380 const byte *_tracks[MAXIMUM_TRACKS][MAXIMUM_SUBTRACKS];
382 byte _numSubtracks[MAXIMUM_TRACKS];
384
389 EventInfo _nextSubtrackEvents[MAXIMUM_SUBTRACKS];
395 bool _doParse;
396 bool _pause;
397
406
407protected:
408 static uint32 readVLQ(const byte * &data);
409 virtual void resetTracking();
410 virtual void allNotesOff();
411 virtual void parseNextEvent(EventInfo &info) = 0;
416 virtual void determineNextEvent();
423 virtual void rebaseTracking();
424 virtual bool processEvent(const EventInfo &info, bool fireEvents = true);
425
426 void activeNote(byte channel, byte note, bool active);
427 void hangingNote(byte channel, byte note, uint32 ticksLeft, bool recycle = true);
428 void hangAllActiveNotes();
429
435 virtual void onTrackStart(uint8 track) { };
436
437 virtual void sendToDriver(uint32 b);
438 void sendToDriver(byte status, byte firstOp, byte secondOp) {
439 sendToDriver(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
440 }
441 virtual void sendMetaEventToDriver(byte type, const byte *data, uint16 length);
442
449 uint32 read4high(const byte * &data) {
450 uint32 val = READ_BE_UINT32(data);
451 data += 4;
452 return val;
453 }
454
461 uint16 read2low(const byte * &data) {
462 uint16 val = READ_LE_UINT16(data);
463 data += 2;
464 return val;
465 }
466
467public:
473 enum {
479
485
491
497
507
514 };
515
516public:
517 typedef void (*XMidiCallbackProc)(byte eventData, void *refCon);
518
519 MidiParser(int8 source = -1);
520 virtual ~MidiParser() { stopPlaying(); }
521
522 virtual bool loadMusic(const byte *data, uint32 size) = 0;
523 virtual void unloadMusic();
524 virtual void property(int prop, int value);
531 virtual int32 determineDataSize(Common::SeekableReadStream *stream) { return -1; };
532
533 virtual void setMidiDriver(MidiDriver_BASE *driver) { _driver = driver; }
534 void setTimerRate(uint32 rate) { _timerRate = rate; }
535 virtual void setTempo(uint32 tempo);
536 virtual void onTimer();
537
538 bool isPlaying() const { return (_position.isTracking() && _doParse); }
568
569 bool setTrack(int track);
570 byte getActiveTrack() { return _activeTrack; }
571 bool jumpToTick(uint32 tick, bool fireEvents = false, bool stopNotes = true, bool dontSendNoteOn = false);
578 virtual bool hasJumpIndex(uint8 index) { return false; }
585 virtual bool jumpToIndex(uint8 index, bool stopNotes = true) { return false; }
586
587 void setLoopSection(uint32 startPoint, uint32 endPoint = 0);
588 void setLoopSectionMicroseconds(uint32 startPoint, uint32 endPoint = 0);
589 void clearLoopSection();
590
591 uint32 getPPQN() { return _ppqn; }
592 virtual uint32 getTick() { return _position._playTick; }
593
594 static void defaultXMidiCallback(byte eventData, void *refCon);
595
596 static MidiParser *createParser_SMF(int8 source = -1);
597 static MidiParser *createParser_XMIDI(XMidiCallbackProc proc = defaultXMidiCallback, void *refCon = 0, int source = -1);
598 static MidiParser *createParser_QT(int8 source = -1);
599 static MidiParser *createParser_HMP(int8 source = -1);
600 static void timerCallback(void *data) { ((MidiParser *)data)->onTimer(); }
601};
603#endif
Definition: stream.h:745
Definition: mididrv.h:114
Definition: midiparser.h:354
virtual bool jumpToIndex(uint8 index, bool stopNotes=true)
Definition: midiparser.h:585
bool _autoLoop
For lightweight clients that don't provide their own flow control.
Definition: midiparser.h:370
virtual void rebaseTracking()
uint32 _psecPerTick
Microseconds per tick (_tempo / _ppqn).
Definition: midiparser.h:368
EventInfo _nextSubtrackEvents[MAXIMUM_SUBTRACKS]
Definition: midiparser.h:389
void pausePlaying()
bool _disableAllNotesOffMidiEvents
Don't send All Notes Off MIDI messages.
Definition: midiparser.h:378
bool _jumpingToTick
True if currently inside jumpToTick.
Definition: midiparser.h:394
@ mpDisableAutoStartPlayback
Definition: midiparser.h:513
@ mpSendSustainOffOnNotesOff
Definition: midiparser.h:496
@ mpCenterPitchWheelOnUnload
Definition: midiparser.h:490
@ mpDisableAllNotesOffMidiEvents
Definition: midiparser.h:506
@ mpAutoLoop
Definition: midiparser.h:478
@ mpSmartJump
Definition: midiparser.h:484
byte _numSubtracks[MAXIMUM_TRACKS]
The number of subtracks for each track.
Definition: midiparser.h:382
byte _hangingNotesCount
Count of hanging notes, used to optimize expiration.
Definition: midiparser.h:362
uint16 _activeNotes[128]
Each uint16 is a bit mask for channels that have that note on.
Definition: midiparser.h:359
const byte * _tracks[MAXIMUM_TRACKS][MAXIMUM_SUBTRACKS]
Multi-track MIDI formats are supported, up to 120 tracks with 20 subtracks each.
Definition: midiparser.h:380
uint32 _loopStartPoint
Start point (in ticks) of the looping section of the track.
Definition: midiparser.h:371
bool _pause
True if the parser has paused parsing.
Definition: midiparser.h:396
uint32 _loopStartPointMs
Start point (in microseconds) of the looping section of the track.
Definition: midiparser.h:373
byte _activeTrack
Keeps track of the currently active track, in multi-track formats.
Definition: midiparser.h:383
int8 _source
Definition: midiparser.h:405
uint32 _ppqn
Pulses Per Quarter Note. (We refer to "pulses" as "ticks".)
Definition: midiparser.h:366
uint32 _sysExDelay
Number of microseconds until the next SysEx event can be sent.
Definition: midiparser.h:369
uint32 read4high(const byte *&data)
Definition: midiparser.h:449
bool _sendSustainOffOnNotesOff
Send a sustain off on a notes off event, stopping hanging notes.
Definition: midiparser.h:377
EventInfo * _nextEvent
Definition: midiparser.h:386
Tracker _position
The current time/position in the active track.
Definition: midiparser.h:385
bool _abortParse
If a jump or other operation interrupts parsing, flag to abort.
Definition: midiparser.h:393
bool _disableAutoStartPlayback
Do not automatically start playback after parsing MIDI data or setting the track.
Definition: midiparser.h:379
void stopPlaying()
virtual int32 determineDataSize(Common::SeekableReadStream *stream)
Definition: midiparser.h:531
NoteTimer _hangingNotes[32]
Used for "Smart Jump" and MIDI formats that do not include explicit Note Off events.
Definition: midiparser.h:360
void resumePlaying()
uint32 _tempo
Microseconds per quarter note.
Definition: midiparser.h:367
bool _smartJump
Support smart expiration of hanging notes when jumping.
Definition: midiparser.h:375
virtual void onTrackStart(uint8 track)
Definition: midiparser.h:435
virtual bool hasJumpIndex(uint8 index)
Definition: midiparser.h:578
virtual void determineNextEvent()
uint32 _loopEndPointMs
End point (in microseconds) of the looping section of the track.
Definition: midiparser.h:374
uint32 _loopEndPoint
End point (in ticks) of the looping section of the track.
Definition: midiparser.h:372
uint16 read2low(const byte *&data)
Definition: midiparser.h:461
byte _numTracks
Count of total tracks for multi-track MIDI formats. 1 for single-track formats.
Definition: midiparser.h:381
bool _centerPitchWheelOnUnload
Center the pitch wheels when unloading a song.
Definition: midiparser.h:376
bool startPlaying()
uint32 _timerRate
The time in microseconds between onTimer() calls. Obtained from the MidiDriver.
Definition: midiparser.h:365
bool _doParse
True if the parser should be parsing; false if it should not be active.
Definition: midiparser.h:395
MidiDriver_BASE * _driver
The device to which all events will be transmitted.
Definition: midiparser.h:364
Definition: midiparser.h:135
byte command() const
Separates the command code from the event.
Definition: midiparser.h:161
bool loop
Indicates that this event loops (part of) the MIDI data.
Definition: midiparser.h:156
uint8 subtrack
The subtrack containing this event.
Definition: midiparser.h:138
byte type
For META events, this indicates the META type.
Definition: midiparser.h:148
byte param1
The first parameter in a simple MIDI message.
Definition: midiparser.h:144
const byte * data
For META and SysEx events, this points to the start of the data.
Definition: midiparser.h:149
byte param2
The second parameter in a simple MIDI message.
Definition: midiparser.h:145
byte channel() const
Separates the MIDI channel from the event.
Definition: midiparser.h:160
byte event
Definition: midiparser.h:140
const byte * start
For delta-based MIDI streams (e.g. SMF and XMIDI), this points to the delta.
Definition: midiparser.h:136
bool noop
Definition: midiparser.h:157
uint32 length
Definition: midiparser.h:152
uint32 delta
The number of ticks after the previous event that this event should occur.
Definition: midiparser.h:139
Definition: midiparser.h:186
byte channel
The MIDI channel on which the note was played.
Definition: midiparser.h:187
uint32 timeLeft
The time, in microseconds, remaining before the note should be turned off.
Definition: midiparser.h:189
byte note
The note number for the active note.
Definition: midiparser.h:188
Definition: midiparser.h:62
const byte * _playPos
A pointer to the next event to be parsed.
Definition: midiparser.h:63
uint32 _lastEventTick
The tick at which the last parsed event occurs.
Definition: midiparser.h:65
uint32 _lastEventTime
The time, in microseconds, of the last event that was parsed.
Definition: midiparser.h:64
byte _runningStatus
Cached MIDI command, for MIDI streams that rely on implied event codes.
Definition: midiparser.h:66
Definition: midiparser.h:61
uint32 _playTick
Current MIDI tick; may be in between event ticks.
Definition: midiparser.h:85
uint32 _playTime
Current time in microseconds; may be in between event times.
Definition: midiparser.h:84
void clear()
Clears all data; used by the constructor for initialization.
Definition: midiparser.h:94
uint32 _lastEventTick
The tick at which the last parsed event across all subtracks occurs.
Definition: midiparser.h:88
uint32 _lastEventTime
Definition: midiparser.h:86