Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

MidiParser Class Reference

#include <midiparser.h>

Inheritance diagram for MidiParser:

AGOS::MidiParser_S1D MidiParser_SMF MidiParser_XMIDI Scumm::MidiParser_EUP

List of all members.

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:

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

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 269 of file midiparser.h.

Public Types

enum  { mpMalformedPitchBends = 1, mpAutoLoop = 2, mpSmartJump = 3, mpCenterPitchWheelOnUnload = 4 }
 Configuration options for MidiParser. More...

Public Member Functions

uint32 getPPQN ()
virtual uint32 getTick ()
bool jumpToTick (uint32 tick, bool fireEvents=false)
virtual bool loadMusic (byte *data, uint32 size)=0
void onTimer ()
virtual void property (int prop, int value)
void setMidiDriver (MidiDriver *driver)
void setTempo (uint32 tempo)
void setTimerRate (uint32 rate)
bool setTrack (int track)
virtual void unloadMusic ()

Static Public Member Functions

static MidiParsercreateParser_SMF ()
static MidiParsercreateParser_XMIDI ()
static void timerCallback (void *data)

Protected Member Functions

void activeNote (byte channel, byte note, bool active)
virtual void allNotesOff ()
void hangAllActiveNotes ()
void hangingNote (byte channel, byte note, uint32 ticks_left, bool recycle=true)
virtual void parseNextEvent (EventInfo &info)=0
uint16 read2low (byte *&data)
 Platform independent LE uint16 read-and-advance.
uint32 read4high (byte *&data)
 Platform independent BE uint32 read-and-advance.
virtual void resetTracking ()

Static Protected Member Functions

static uint32 readVLQ (byte *&data)

Protected Attributes

bool _abort_parse
 If a jump or other operation interrupts parsing, flag to abort.
byte _active_track
 Keeps track of the currently active track, in multi-track formats.
bool _autoLoop
 For lightweight clients that don't provide their own flow control.
bool _centerPitchWheelOnUnload
 Center the pitch wheels when unloading a song.
 The device to which all events will be transmitted.
EventInfo _next_event
byte _num_tracks
 Count of total tracks for multi-track MIDI formats. 1 for single-track formats.
Tracker _position
 The current time/position in the active track.
uint32 _ppqn
 Pulses Per Quarter Note. (We refer to "pulses" as "ticks".).
uint32 _psec_per_tick
 Microseconds per tick (_tempo / _ppqn).
bool _smartJump
 Support smart expiration of hanging notes when jumping.
uint32 _tempo
 Microseconds per quarter note.
uint32 _timer_rate
 The time in microseconds between onTimer() calls. Obtained from the MidiDriver.
byte * _tracks [120]
 Multi-track MIDI formats are supported, up to 120 tracks.

Private Attributes

uint16 _active_notes [128]
 Each uint16 is a bit mask for channels that have that note on.
NoteTimer _hanging_notes [32]
byte _hanging_notes_count
 Count of hanging notes, used to optimize expiration.

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

Generated by  Doxygen 1.6.0   Back to index