ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

A framework and common functionality for parsing event-based music streams. More...

#include <midiparser.h>

Inheritance diagram for MidiParser:
Collaboration diagram for MidiParser:

List of all members.

Public Types

enum  {
  mpMalformedPitchBends = 1, mpAutoLoop = 2, mpSmartJump = 3, mpCenterPitchWheelOnUnload = 4,
  mpSendSustainOffOnNotesOff = 5
}
 

Configuration options for MidiParser The following options can be set to modify MidiParser's behavior.

More...
typedef void(* XMidiCallbackProc )(byte eventData, void *refCon)
typedef void(* XMidiNewTimbreListProc )(MidiDriver_BASE *driver, const byte *timbreListPtr, uint32 timbreListSize)

Public Member Functions

 MidiParser ()
virtual ~MidiParser ()
virtual bool loadMusic (byte *data, uint32 size)=0
virtual void unloadMusic ()
virtual void property (int prop, int value)
void setMidiDriver (MidiDriver_BASE *driver)
void setTimerRate (uint32 rate)
void setTempo (uint32 tempo)
void onTimer ()
bool isPlaying () const
void stopPlaying ()
bool setTrack (int track)
bool jumpToTick (uint32 tick, bool fireEvents=false, bool stopNotes=true, bool dontSendNoteOn=false)
uint32 getPPQN ()
virtual uint32 getTick ()

Static Public Member Functions

static void defaultXMidiCallback (byte eventData, void *refCon)
static MidiParsercreateParser_SMF ()
static MidiParsercreateParser_XMIDI (XMidiCallbackProc proc=defaultXMidiCallback, void *refCon=0, XMidiNewTimbreListProc newTimbreListProc=NULL, MidiDriver_BASE *newTimbreListDriver=NULL)
static MidiParsercreateParser_QT ()
static void timerCallback (void *data)

Protected Member Functions

virtual void resetTracking ()
virtual void allNotesOff ()
virtual void parseNextEvent (EventInfo &info)=0
virtual bool processEvent (const EventInfo &info, bool fireEvents=true)
void activeNote (byte channel, byte note, bool active)
void hangingNote (byte channel, byte note, uint32 ticksLeft, bool recycle=true)
void hangAllActiveNotes ()
virtual void sendToDriver (uint32 b)
void sendToDriver (byte status, byte firstOp, byte secondOp)
uint32 read4high (byte *&data)
 Platform independent BE uint32 read-and-advance.
uint16 read2low (byte *&data)
 Platform independent LE uint16 read-and-advance.

Static Protected Member Functions

static uint32 readVLQ (byte *&data)

Protected Attributes

uint16 _activeNotes [128]
 Each uint16 is a bit mask for channels that have that note on.
NoteTimer _hangingNotes [32]
 Maintains expiration info for up to 32 notes.
byte _hangingNotesCount
 Count of hanging notes, used to optimize expiration.
MidiDriver_BASE_driver
 The device to which all events will be transmitted.
uint32 _timerRate
 The time in microseconds between onTimer() calls. Obtained from the MidiDriver.
uint32 _ppqn
 Pulses Per Quarter Note. (We refer to "pulses" as "ticks".).
uint32 _tempo
 Microseconds per quarter note.
uint32 _psecPerTick
 Microseconds per tick (_tempo / _ppqn).
bool _autoLoop
 For lightweight clients that don't provide their own flow control.
bool _smartJump
 Support smart expiration of hanging notes when jumping.
bool _centerPitchWheelOnUnload
 Center the pitch wheels when unloading a song.
bool _sendSustainOffOnNotesOff
 Send a sustain off on a notes off event, stopping hanging notes.
byte_tracks [120]
 Multi-track MIDI formats are supported, up to 120 tracks.
byte _numTracks
 Count of total tracks for multi-track MIDI formats. 1 for single-track formats.
byte _activeTrack
 Keeps track of the currently active track, in multi-track formats.
Tracker _position
 The current time/position in the active track.
EventInfo _nextEvent
 The next event to transmit.
bool _abortParse
 If a jump or other operation interrupts parsing, flag to abort.
bool _jumpingToTick
 True if currently inside jumpToTick.

Detailed Description

A framework and common functionality for parsing event-based music streams.

The MidiParser provides a framework in which to load, parse and traverse event-based music data. Note the avoidance of the phrase "MIDI data." Despite its name, MidiParser derivatives can be used to manage a wide variety of event-based music formats. It is, however, based on the premise that the format in question can be played in the form of specification MIDI events.

In order to use MidiParser to parse your music format, follow these steps:

STEP 1: Write a MidiParser derivative. The MidiParser base class provides functionality considered common to the task of parsing event-based music. In order to parse a particular format, create a derived class that implements, at minimum, the following format-specific methods:

  • loadMusic
  • parseNextEvent

In addition to the above functions, the derived class may also override the default MidiParser behavior for the following methods:

  • resetTracking
  • allNotesOff
  • unloadMusic
  • property
  • getTick

Please see the documentation for these individual functions for more information on their use.

The naming convention for classes derived from MidiParser is MidiParser_XXX, where "XXX" is some short designator for the format the class will support. For instance, the MidiParser derivative for parsing the Standard MIDI File format is MidiParser_SMF.

STEP 2: Create an object of your derived class. Each MidiParser object can parse at most one (1) song at a time. However, a MidiParser object can be reused to play another song once it is no longer needed to play whatever it was playing. In other words, MidiParser objects do not have to be destroyed and recreated from one song to the next.

STEP 3: Specify a MidiDriver to send events to. MidiParser works by sending MIDI and meta events to a MidiDriver. In the simplest configuration, you can plug a single MidiParser directly into the output MidiDriver being used. However, you can only plug in one at a time; otherwise channel conflicts will occur. Furthermore, meta events that may be needed to interactively control music flow cannot be handled because they are being sent directly to the output device.

If you need more control over the MidiParser while it's playing, you can create your own "pseudo-MidiDriver" and place it in between your MidiParser and the output MidiDriver. The MidiParser will send events to your pseudo-MidiDriver, which in turn must send them to the output MidiDriver (or do whatever special handling is required).

To specify the MidiDriver to send music output to, use the MidiParser::setMidiDriver method.

STEP 4: Specify the onTimer call rate. MidiParser bases the timing of its parsing on an external clock. Every time MidiParser::onTimer is called, a bit more music is parsed. You must specify how many microseconds will occur between each call to onTimer, in order to ensure an accurate music tempo.

To set the onTimer call rate, in microseconds, use the MidiParser::setTimerRate method. The onTimer call rate will typically match the timer rate for the output MidiDriver used. This rate can be obtained by calling MidiDriver::getBaseTempo.

STEP 5: Load the music. MidiParser requires that the music data already be loaded into memory. The client code is responsible for memory management on this block of memory. That means that the client code must ensure that the data remain in memory while the MidiParser is using it, and properly freed after it is no longer needed. Some MidiParser variants may require internal buffers as well; memory management for those buffers is the responsibility of the MidiParser object.

To load the music into the MidiParser, use the MidiParser::loadMusic method, specifying a memory pointer to the music data and the size of the data. (NOTE: Some MidiParser variants don't require a size, and 0 is fine. However, when writing client code to use MidiParser, it is best to assume that a valid size will be required.

Convention requires that each implementation of MidiParser::loadMusic automatically set up default tempo and current track. This effectively means that the MidiParser will start playing as soon as timer events start coming in.

STEP 6: Activate a timer source for the MidiParser. The easiest timer source to use is the timer of the output MidiDriver. You can attach the MidiDriver's timer output directly to a MidiParser by calling MidiDriver::setTimerCallback. In this case, the timer_proc will be the static method MidiParser::timerCallback, and timer_param will be a pointer to your MidiParser object.

This configuration only allows one MidiParser to be driven by the MidiDriver at a time. To drive more MidiDrivers, you will need to create a "pseudo-MidiDriver" as described earlier, In such a configuration, the pseudo-MidiDriver should be set as the timer recipient in MidiDriver::setTimerCallback, and could then call MidiParser::onTimer for each MidiParser object.

STEP 7: Music shall begin to play! Congratulations! At this point everything should be hooked up and the MidiParser should generate music. Note that there is no way to "stop" the MidiParser. You can "pause" the MidiParser simply by not sending timer events to it, or you can call MidiParser::unloadMusic to permanently stop the music. (This method resets everything and detaches the MidiParser from the memory block containing the music data.)

Definition at line 265 of file midiparser.h.


Member Typedef Documentation

typedef void(* MidiParser::XMidiCallbackProc)(byte eventData, void *refCon)

Definition at line 372 of file midiparser.h.

typedef void(* MidiParser::XMidiNewTimbreListProc)(MidiDriver_BASE *driver, const byte *timbreListPtr, uint32 timbreListSize)

Definition at line 373 of file midiparser.h.


Member Enumeration Documentation

anonymous enum

Configuration options for MidiParser The following options can be set to modify MidiParser's behavior.

Enumerator:
mpMalformedPitchBends 

Events containing a pitch bend command should be treated as single-byte padding before the real event.

This allows the MidiParser to work with some malformed SMF files from Simon 1/2.

mpAutoLoop 

Sets auto-looping, which can be used by lightweight clients that don't provide their own flow control.

mpSmartJump 

Sets smart jumping, which intelligently expires notes that are active when a jump is made, rather than just cutting them off.

mpCenterPitchWheelOnUnload 

Center the pitch wheels when unloading music in preparation for the next piece of music.

mpSendSustainOffOnNotesOff 

Sends a sustain off event when a notes off event is triggered.

Stops hanging notes.

Definition at line 338 of file midiparser.h.


Constructor & Destructor Documentation

MidiParser::MidiParser (  ) 

Definition at line 34 of file midiparser.cpp.

virtual MidiParser::~MidiParser (  )  [inline, virtual]

Definition at line 376 of file midiparser.h.


Member Function Documentation

void MidiParser::activeNote ( byte  channel,
byte  note,
bool  active 
) [protected]

Definition at line 100 of file midiparser.cpp.

void MidiParser::allNotesOff (  )  [protected, virtual]

Definition at line 275 of file midiparser.cpp.

MidiParser * MidiParser::createParser_QT (  )  [static]

Definition at line 494 of file midiparser_qt.cpp.

static MidiParser* MidiParser::createParser_SMF (  )  [static]
static MidiParser* MidiParser::createParser_XMIDI ( XMidiCallbackProc  proc = defaultXMidiCallback,
void *  refCon = 0,
XMidiNewTimbreListProc  newTimbreListProc = NULL,
MidiDriver_BASE newTimbreListDriver = NULL 
) [static]
static void MidiParser::defaultXMidiCallback ( byte  eventData,
void *  refCon 
) [static]
uint32 MidiParser::getPPQN (  )  [inline]

Definition at line 393 of file midiparser.h.

virtual uint32 MidiParser::getTick (  )  [inline, virtual]

Definition at line 394 of file midiparser.h.

void MidiParser::hangAllActiveNotes (  )  [protected]

Definition at line 350 of file midiparser.cpp.

void MidiParser::hangingNote ( byte  channel,
byte  note,
uint32  ticksLeft,
bool  recycle = true 
) [protected]

Definition at line 121 of file midiparser.cpp.

bool MidiParser::isPlaying (  )  const [inline]

Definition at line 387 of file midiparser.h.

bool MidiParser::jumpToTick ( uint32  tick,
bool  fireEvents = false,
bool  stopNotes = true,
bool  dontSendNoteOn = false 
)

Definition at line 386 of file midiparser.cpp.

virtual bool MidiParser::loadMusic ( byte data,
uint32  size 
) [pure virtual]
void MidiParser::onTimer (  ) 

Definition at line 165 of file midiparser.cpp.

virtual void MidiParser::parseNextEvent ( EventInfo info  )  [protected, pure virtual]
bool MidiParser::processEvent ( const EventInfo info,
bool  fireEvents = true 
) [protected, virtual]

Definition at line 235 of file midiparser.cpp.

void MidiParser::property ( int  prop,
int  value 
) [virtual]

Definition at line 57 of file midiparser.cpp.

uint16 MidiParser::read2low ( byte *&  data  )  [inline, protected]

Platform independent LE uint16 read-and-advance.

This helper function reads Little Endian 16-bit numbers from a memory pointer, at the same time advancing the pointer.

Definition at line 326 of file midiparser.h.

uint32 MidiParser::read4high ( byte *&  data  )  [inline, protected]

Platform independent BE uint32 read-and-advance.

This helper function reads Big Endian 32-bit numbers from a memory pointer, at the same time advancing the pointer.

Definition at line 314 of file midiparser.h.

uint32 MidiParser::readVLQ ( byte *&  data  )  [static, protected]

Definition at line 85 of file midiparser.cpp.

void MidiParser::resetTracking (  )  [protected, virtual]

Definition at line 311 of file midiparser.cpp.

void MidiParser::sendToDriver ( uint32  b  )  [protected, virtual]

Definition at line 74 of file midiparser.cpp.

void MidiParser::sendToDriver ( byte  status,
byte  firstOp,
byte  secondOp 
) [inline, protected]

Definition at line 304 of file midiparser.h.

void MidiParser::setMidiDriver ( MidiDriver_BASE driver  )  [inline]

Definition at line 382 of file midiparser.h.

void MidiParser::setTempo ( uint32  tempo  ) 

Definition at line 78 of file midiparser.cpp.

void MidiParser::setTimerRate ( uint32  rate  )  [inline]

Definition at line 383 of file midiparser.h.

bool MidiParser::setTrack ( int  track  ) 

Definition at line 315 of file midiparser.cpp.

void MidiParser::stopPlaying (  ) 

Definition at line 345 of file midiparser.cpp.

static void MidiParser::timerCallback ( void *  data  )  [inline, static]

Definition at line 401 of file midiparser.h.

void MidiParser::unloadMusic (  )  [virtual]

Definition at line 453 of file midiparser.cpp.


Member Data Documentation

bool MidiParser::_abortParse [protected]

If a jump or other operation interrupts parsing, flag to abort.

Definition at line 289 of file midiparser.h.

uint16 MidiParser::_activeNotes[128] [protected]

Each uint16 is a bit mask for channels that have that note on.

Definition at line 267 of file midiparser.h.

Keeps track of the currently active track, in multi-track formats.

Definition at line 283 of file midiparser.h.

bool MidiParser::_autoLoop [protected]

For lightweight clients that don't provide their own flow control.

Definition at line 277 of file midiparser.h.

Center the pitch wheels when unloading a song.

Definition at line 279 of file midiparser.h.

The device to which all events will be transmitted.

Definition at line 272 of file midiparser.h.

Maintains expiration info for up to 32 notes.

Used for "Smart Jump" and MIDI formats that do not include explicit Note Off events.

Definition at line 268 of file midiparser.h.

Count of hanging notes, used to optimize expiration.

Definition at line 270 of file midiparser.h.

bool MidiParser::_jumpingToTick [protected]

True if currently inside jumpToTick.

Definition at line 290 of file midiparser.h.

The next event to transmit.

Events are preparsed so each event is parsed only once; this permits simulated events in certain formats.

Definition at line 286 of file midiparser.h.

Count of total tracks for multi-track MIDI formats. 1 for single-track formats.

Definition at line 282 of file midiparser.h.

The current time/position in the active track.

Definition at line 285 of file midiparser.h.

Pulses Per Quarter Note. (We refer to "pulses" as "ticks".).

Definition at line 274 of file midiparser.h.

Microseconds per tick (_tempo / _ppqn).

Definition at line 276 of file midiparser.h.

Send a sustain off on a notes off event, stopping hanging notes.

Definition at line 280 of file midiparser.h.

bool MidiParser::_smartJump [protected]

Support smart expiration of hanging notes when jumping.

Definition at line 278 of file midiparser.h.

Microseconds per quarter note.

Definition at line 275 of file midiparser.h.

The time in microseconds between onTimer() calls. Obtained from the MidiDriver.

Definition at line 273 of file midiparser.h.

byte* MidiParser::_tracks[120] [protected]

Multi-track MIDI formats are supported, up to 120 tracks.

Definition at line 281 of file midiparser.h.


The documentation for this class was generated from the following files:


Generated on Sat Jun 22 2019 05:02:36 for ResidualVM by doxygen 1.7.1
curved edge   curved edge