ScummVM API documentation
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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 20
32 
33 class MidiDriver_BASE;
34 
44 //
46 // Support entities
47 //
49 
61 struct Tracker {
62  struct SubtrackStatus {
63  byte * _playPos;
64  uint32 _lastEventTime;
65  uint32 _lastEventTick;
67 
68  void clear() {
69  _playPos = nullptr;
70  _lastEventTime = 0;
71  _lastEventTick = 0;
72  _runningStatus = 0;
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;
86  uint32 _lastEventTime;
87  uint32 _lastEventTick;
89  SubtrackStatus _subtracks[AUDIO_MIDIPARSER_MAXIMUM_SUBTRACKS];
90 
91  Tracker() { clear(); }
92 
94  void clear() {
95  _playTime = 0;
96  _playTick = 0;
97  _lastEventTime = 0;
98  _lastEventTick = 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 
135 struct EventInfo {
136  byte * start;
137  uint8 subtrack;
139  uint32 delta;
140  byte event;
141  union {
143  struct {
144  byte param1;
145  byte param2;
146  } basic;
147  struct {
148  byte type;
149  byte * data;
150  } ext;
151  };
152  uint32 length;
153  bool loop;
157  bool noop;
158 
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 
186 struct 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 
354 class MidiParser {
355 protected:
356  static const uint8 MAXIMUM_TRACKS = 120;
357  static const uint8 MAXIMUM_SUBTRACKS = AUDIO_MIDIPARSER_MAXIMUM_SUBTRACKS;
358 
359  uint16 _activeNotes[128];
360  NoteTimer _hangingNotes[32];
361  byte _hangingNotesCount;
363 
365  uint32 _timerRate;
366  uint32 _ppqn;
367  uint32 _tempo;
368  uint32 _psecPerTick;
369  uint32 _sysExDelay;
370  bool _autoLoop;
371  bool _smartJump;
376  byte *_tracks[MAXIMUM_TRACKS][MAXIMUM_SUBTRACKS];
377  byte _numTracks;
378  byte _numSubtracks[MAXIMUM_TRACKS];
380 
383  EventInfo _nextSubtrackEvents[MAXIMUM_SUBTRACKS];
386  bool _abortParse;
391  bool _doParse;
392  bool _pause;
393 
401  int8 _source;
402 
403 protected:
404  static uint32 readVLQ(byte * &data);
405  virtual void resetTracking();
406  virtual void allNotesOff();
407  virtual void parseNextEvent(EventInfo &info) = 0;
412  virtual void determineNextEvent();
419  virtual void rebaseTracking();
420  virtual bool processEvent(const EventInfo &info, bool fireEvents = true);
421 
422  void activeNote(byte channel, byte note, bool active);
423  void hangingNote(byte channel, byte note, uint32 ticksLeft, bool recycle = true);
424  void hangAllActiveNotes();
425 
431  virtual void onTrackStart(uint8 track) { };
432 
433  virtual void sendToDriver(uint32 b);
434  void sendToDriver(byte status, byte firstOp, byte secondOp) {
435  sendToDriver(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
436  }
437  virtual void sendMetaEventToDriver(byte type, byte *data, uint16 length);
438 
445  uint32 read4high(byte * &data) {
446  uint32 val = READ_BE_UINT32(data);
447  data += 4;
448  return val;
449  }
450 
457  uint16 read2low(byte * &data) {
458  uint16 val = READ_LE_UINT16(data);
459  data += 2;
460  return val;
461  }
462 
463 public:
469  enum {
474  mpAutoLoop = 2,
475 
480  mpSmartJump = 3,
481 
486  mpCenterPitchWheelOnUnload = 4,
487 
492  mpSendSustainOffOnNotesOff = 5,
493 
502  mpDisableAllNotesOffMidiEvents = 6,
503 
509  mpDisableAutoStartPlayback = 7
510  };
511 
512 public:
513  typedef void (*XMidiCallbackProc)(byte eventData, void *refCon);
514 
515  MidiParser(int8 source = -1);
516  virtual ~MidiParser() { stopPlaying(); }
517 
518  virtual bool loadMusic(byte *data, uint32 size) = 0;
519  virtual void unloadMusic();
520  virtual void property(int prop, int value);
527  virtual int32 determineDataSize(Common::SeekableReadStream *stream) { return -1; };
528 
529  virtual void setMidiDriver(MidiDriver_BASE *driver) { _driver = driver; }
530  void setTimerRate(uint32 rate) { _timerRate = rate; }
531  virtual void setTempo(uint32 tempo);
532  virtual void onTimer();
533 
534  bool isPlaying() const { return (_position.isTracking() && _doParse); }
541  bool startPlaying();
545  void stopPlaying();
558  void pausePlaying();
563  void resumePlaying();
564 
565  bool setTrack(int track);
566  bool jumpToTick(uint32 tick, bool fireEvents = false, bool stopNotes = true, bool dontSendNoteOn = false);
573  virtual bool hasJumpIndex(uint8 index) { return false; }
580  virtual bool jumpToIndex(uint8 index, bool stopNotes = true) { return false; }
581 
582  uint32 getPPQN() { return _ppqn; }
583  virtual uint32 getTick() { return _position._playTick; }
584 
585  static void defaultXMidiCallback(byte eventData, void *refCon);
586 
587  static MidiParser *createParser_SMF(int8 source = -1);
588  static MidiParser *createParser_XMIDI(XMidiCallbackProc proc = defaultXMidiCallback, void *refCon = 0, int source = -1);
589  static MidiParser *createParser_QT(int8 source = -1);
590  static void timerCallback(void *data) { ((MidiParser *) data)->onTimer(); }
591 };
593 #endif
uint32 _lastEventTime
The time, in microseconds, of the last event that was parsed.
Definition: midiparser.h:64
uint32 _sysExDelay
Number of microseconds until the next SysEx event can be sent.
Definition: midiparser.h:369
Definition: midiparser.h:186
uint32 length
Definition: midiparser.h:152
uint32 _playTick
Current MIDI tick; may be in between event ticks.
Definition: midiparser.h:85
byte type
For META events, this indicates the META type.
Definition: midiparser.h:148
int8 _source
Definition: midiparser.h:401
bool _autoLoop
For lightweight clients that don&#39;t provide their own flow control.
Definition: midiparser.h:370
Definition: midiparser.h:61
byte _activeTrack
Keeps track of the currently active track, in multi-track formats.
Definition: midiparser.h:379
bool _smartJump
Support smart expiration of hanging notes when jumping.
Definition: midiparser.h:371
bool _disableAutoStartPlayback
Do not automatically start playback after parsing MIDI data or setting the track. ...
Definition: midiparser.h:375
Tracker _position
The current time/position in the active track.
Definition: midiparser.h:381
uint32 _ppqn
Pulses Per Quarter Note. (We refer to "pulses" as "ticks".)
Definition: midiparser.h:366
virtual bool jumpToIndex(uint8 index, bool stopNotes=true)
Definition: midiparser.h:580
virtual bool hasJumpIndex(uint8 index)
Definition: midiparser.h:573
byte note
The note number for the active note.
Definition: midiparser.h:188
bool _doParse
True if the parser should be parsing; false if it should not be active.
Definition: midiparser.h:391
uint32 _lastEventTime
Definition: midiparser.h:86
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
uint32 _timerRate
The time in microseconds between onTimer() calls. Obtained from the MidiDriver.
Definition: midiparser.h:365
uint32 read4high(byte *&data)
Definition: midiparser.h:445
Definition: stream.h:745
bool _centerPitchWheelOnUnload
Center the pitch wheels when unloading a song.
Definition: midiparser.h:372
Definition: midiparser.h:135
uint32 _lastEventTick
The tick at which the last parsed event occurs.
Definition: midiparser.h:65
byte * _playPos
A pointer to the next event to be parsed.
Definition: midiparser.h:63
virtual void onTrackStart(uint8 track)
Definition: midiparser.h:431
bool _pause
True if the parser has paused parsing.
Definition: midiparser.h:392
byte * data
For META and SysEx events, this points to the start of the data.
Definition: midiparser.h:149
byte _numTracks
Count of total tracks for multi-track MIDI formats. 1 for single-track formats.
Definition: midiparser.h:377
virtual int32 determineDataSize(Common::SeekableReadStream *stream)
Definition: midiparser.h:527
void clear()
Clears all data; used by the constructor for initialization.
Definition: midiparser.h:94
byte param1
The first parameter in a simple MIDI message.
Definition: midiparser.h:144
uint32 _psecPerTick
Microseconds per tick (_tempo / _ppqn).
Definition: midiparser.h:368
uint32 _playTime
Current time in microseconds; may be in between event times.
Definition: midiparser.h:84
Definition: mididrv.h:112
MidiDriver_BASE * _driver
The device to which all events will be transmitted.
Definition: midiparser.h:364
uint32 _tempo
Microseconds per quarter note.
Definition: midiparser.h:367
uint16 read2low(byte *&data)
Definition: midiparser.h:457
EventInfo * _nextEvent
Definition: midiparser.h:382
byte event
Definition: midiparser.h:140
uint32 delta
The number of ticks after the previous event that this event should occur.
Definition: midiparser.h:139
Definition: midiparser.h:62
byte * start
Definition: midiparser.h:136
byte channel
The MIDI channel on which the note was played.
Definition: midiparser.h:187
bool _sendSustainOffOnNotesOff
Send a sustain off on a notes off event, stopping hanging notes.
Definition: midiparser.h:373
byte _runningStatus
Cached MIDI command, for MIDI streams that rely on implied event codes.
Definition: midiparser.h:66
bool _jumpingToTick
True if currently inside jumpToTick.
Definition: midiparser.h:390
bool _disableAllNotesOffMidiEvents
Don&#39;t send All Notes Off MIDI messages.
Definition: midiparser.h:374
byte command() const
Separates the command code from the event.
Definition: midiparser.h:161
uint32 timeLeft
The time, in microseconds, remaining before the note should be turned off.
Definition: midiparser.h:189
Definition: midiparser.h:354
bool noop
Definition: midiparser.h:157