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 class MidiDriver_BASE;
32 
42 //
44 // Support entities
45 //
47 
58 struct Tracker {
59  byte * _playPos;
60  uint32 _playTime;
61  uint32 _playTick;
62  uint32 _lastEventTime;
63  uint32 _lastEventTick;
65 
66  Tracker() { clear(); }
67 
69  void clear() {
70  _playPos = 0;
71  _playTime = 0;
72  _playTick = 0;
73  _lastEventTime = 0;
74  _lastEventTick = 0;
75  _runningStatus = 0;
76  }
77 };
78 
84 struct EventInfo {
85  byte * start;
86  uint32 delta;
88  byte event;
89  union {
91  struct {
92  byte param1;
93  byte param2;
94  } basic;
95  struct {
96  byte type;
97  byte * data;
98  } ext;
99  };
100  uint32 length;
101  bool loop;
105  bool noop;
106 
108  byte channel() const { return event & 0x0F; }
109  byte command() const { return event >> 4; }
110 
111  EventInfo() : start(0), delta(0), event(0), length(0), loop(false), noop(false) { basic.param1 = 0; basic.param2 = 0; ext.type = 0; ext.data = 0; }
112 };
113 
121 struct NoteTimer {
122  byte channel;
123  byte note;
124  uint32 timeLeft;
125  NoteTimer() : channel(0), note(0), timeLeft(0) {}
126 };
127 
128 
129 
130 
132 //
133 // MidiParser declaration
134 //
136 
289 class MidiParser {
290 protected:
291  static const uint8 MAXIMUM_TRACKS = 120;
292 
293  uint16 _activeNotes[128];
294  NoteTimer _hangingNotes[32];
295  byte _hangingNotesCount;
297 
299  uint32 _timerRate;
300  uint32 _ppqn;
301  uint32 _tempo;
302  uint32 _psecPerTick;
303  uint32 _sysExDelay;
304  bool _autoLoop;
305  bool _smartJump;
310  byte *_tracks[MAXIMUM_TRACKS];
311  byte _numTracks;
313 
316  bool _abortParse;
320  bool _doParse;
321  bool _pause;
322 
330  int8 _source;
331 
332 protected:
333  static uint32 readVLQ(byte * &data);
334  virtual void resetTracking();
335  virtual void allNotesOff();
336  virtual void parseNextEvent(EventInfo &info) = 0;
337  virtual bool processEvent(const EventInfo &info, bool fireEvents = true);
338 
339  void activeNote(byte channel, byte note, bool active);
340  void hangingNote(byte channel, byte note, uint32 ticksLeft, bool recycle = true);
341  void hangAllActiveNotes();
342 
348  virtual void onTrackStart(uint8 track) { };
349 
350  virtual void sendToDriver(uint32 b);
351  void sendToDriver(byte status, byte firstOp, byte secondOp) {
352  sendToDriver(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
353  }
354  virtual void sendMetaEventToDriver(byte type, byte *data, uint16 length);
355 
362  uint32 read4high(byte * &data) {
363  uint32 val = READ_BE_UINT32(data);
364  data += 4;
365  return val;
366  }
367 
374  uint16 read2low(byte * &data) {
375  uint16 val = READ_LE_UINT16(data);
376  data += 2;
377  return val;
378  }
379 
380 public:
386  enum {
391  mpAutoLoop = 2,
392 
397  mpSmartJump = 3,
398 
403  mpCenterPitchWheelOnUnload = 4,
404 
409  mpSendSustainOffOnNotesOff = 5,
410 
419  mpDisableAllNotesOffMidiEvents = 6,
420 
426  mpDisableAutoStartPlayback = 7
427  };
428 
429 public:
430  typedef void (*XMidiCallbackProc)(byte eventData, void *refCon);
431 
432  MidiParser(int8 source = -1);
433  virtual ~MidiParser() { stopPlaying(); }
434 
435  virtual bool loadMusic(byte *data, uint32 size) = 0;
436  virtual void unloadMusic();
437  virtual void property(int prop, int value);
444  virtual int32 determineDataSize(Common::SeekableReadStream *stream) { return -1; };
445 
446  virtual void setMidiDriver(MidiDriver_BASE *driver) { _driver = driver; }
447  void setTimerRate(uint32 rate) { _timerRate = rate; }
448  virtual void setTempo(uint32 tempo);
449  virtual void onTimer();
450 
451  bool isPlaying() const { return (_position._playPos != 0 && _doParse); }
458  bool startPlaying();
462  void stopPlaying();
475  void pausePlaying();
480  void resumePlaying();
481 
482  bool setTrack(int track);
483  bool jumpToTick(uint32 tick, bool fireEvents = false, bool stopNotes = true, bool dontSendNoteOn = false);
490  virtual bool hasJumpIndex(uint8 index) { return false; }
497  virtual bool jumpToIndex(uint8 index, bool stopNotes = true) { return false; }
498 
499  uint32 getPPQN() { return _ppqn; }
500  virtual uint32 getTick() { return _position._playTick; }
501 
502  static void defaultXMidiCallback(byte eventData, void *refCon);
503 
504  static MidiParser *createParser_SMF(int8 source = -1);
505  static MidiParser *createParser_XMIDI(XMidiCallbackProc proc = defaultXMidiCallback, void *refCon = 0, int source = -1);
506  static MidiParser *createParser_QT(int8 source = -1);
507  static void timerCallback(void *data) { ((MidiParser *) data)->onTimer(); }
508 };
510 #endif
uint32 _sysExDelay
Number of microseconds until the next SysEx event can be sent.
Definition: midiparser.h:303
Definition: midiparser.h:121
uint32 length
Definition: midiparser.h:100
uint32 _playTick
Current MIDI tick; may be in between event ticks.
Definition: midiparser.h:61
byte type
For META events, this indicates the META type.
Definition: midiparser.h:96
int8 _source
Definition: midiparser.h:330
bool _autoLoop
For lightweight clients that don&#39;t provide their own flow control.
Definition: midiparser.h:304
Definition: midiparser.h:58
byte _activeTrack
Keeps track of the currently active track, in multi-track formats.
Definition: midiparser.h:312
byte _runningStatus
Cached MIDI command, for MIDI streams that rely on implied event codes.
Definition: midiparser.h:64
bool _smartJump
Support smart expiration of hanging notes when jumping.
Definition: midiparser.h:305
bool _disableAutoStartPlayback
Do not automatically start playback after parsing MIDI data or setting the track. ...
Definition: midiparser.h:309
Tracker _position
The current time/position in the active track.
Definition: midiparser.h:314
uint32 _ppqn
Pulses Per Quarter Note. (We refer to "pulses" as "ticks".)
Definition: midiparser.h:300
virtual bool jumpToIndex(uint8 index, bool stopNotes=true)
Definition: midiparser.h:497
virtual bool hasJumpIndex(uint8 index)
Definition: midiparser.h:490
byte note
The note number for the active note.
Definition: midiparser.h:123
bool _doParse
True if the parser should be parsing; false if it should not be active.
Definition: midiparser.h:320
uint32 _lastEventTime
The time, in microseconds, of the last event that was parsed.
Definition: midiparser.h:62
byte param2
The second parameter in a simple MIDI message.
Definition: midiparser.h:93
byte channel() const
Separates the MIDI channel from the event.
Definition: midiparser.h:108
uint32 _timerRate
The time in microseconds between onTimer() calls. Obtained from the MidiDriver.
Definition: midiparser.h:299
uint32 read4high(byte *&data)
Definition: midiparser.h:362
Definition: stream.h:745
bool _centerPitchWheelOnUnload
Center the pitch wheels when unloading a song.
Definition: midiparser.h:306
Definition: midiparser.h:84
EventInfo _nextEvent
Definition: midiparser.h:315
virtual void onTrackStart(uint8 track)
Definition: midiparser.h:348
bool _pause
True if the parser has paused parsing.
Definition: midiparser.h:321
byte * data
For META and SysEx events, this points to the start of the data.
Definition: midiparser.h:97
byte _numTracks
Count of total tracks for multi-track MIDI formats. 1 for single-track formats.
Definition: midiparser.h:311
virtual int32 determineDataSize(Common::SeekableReadStream *stream)
Definition: midiparser.h:444
void clear()
Clears all data; used by the constructor for initialization.
Definition: midiparser.h:69
byte param1
The first parameter in a simple MIDI message.
Definition: midiparser.h:92
uint32 _psecPerTick
Microseconds per tick (_tempo / _ppqn).
Definition: midiparser.h:302
uint32 _playTime
Current time in microseconds; may be in between event times.
Definition: midiparser.h:60
Definition: mididrv.h:102
MidiDriver_BASE * _driver
The device to which all events will be transmitted.
Definition: midiparser.h:298
uint32 _tempo
Microseconds per quarter note.
Definition: midiparser.h:301
uint16 read2low(byte *&data)
Definition: midiparser.h:374
uint32 _lastEventTick
The tick at which the last parsed event occurs.
Definition: midiparser.h:63
byte event
Definition: midiparser.h:88
byte * _playPos
A pointer to the next event to be parsed.
Definition: midiparser.h:59
byte * start
Definition: midiparser.h:85
byte channel
The MIDI channel on which the note was played.
Definition: midiparser.h:122
bool _sendSustainOffOnNotesOff
Send a sustain off on a notes off event, stopping hanging notes.
Definition: midiparser.h:307
bool _jumpingToTick
True if currently inside jumpToTick.
Definition: midiparser.h:319
bool _disableAllNotesOffMidiEvents
Don&#39;t send All Notes Off MIDI messages.
Definition: midiparser.h:308
byte command() const
Separates the command code from the event.
Definition: midiparser.h:109
uint32 timeLeft
The time, in microseconds, remaining before the note should be turned off.
Definition: midiparser.h:124
Definition: midiparser.h:289
bool noop
Definition: midiparser.h:105