1. Introduction.
2. The functions sets of the MFAPI library (Midi File API)
2.1. MFAPI functions for Midi file reading
2.1.1. File opening
2.1.2. Reading track by track
2.1.3. Reading a track event by event
2.1.4. Closing a Midi file
2.2. MFAPI functions for Midi file writing
2.2.1. Creating / opening a file
2.2.2. Writing a complete sequence to a file track
2.2.3. Writing a track event by event
2.2.4. Closing the file
3. Understand the date of events
3.1. Events date in a Midi File:
3.1.1. Time unit date representation in MIDIFile
3.1.2. Unit: fraction of a second
3.1.3. Unit: number of Pulses Per Quarter Note (PPQN)
3.2. Event date returned by MidiFileReadEv
3.3. Event date written by MidiFileWriteEv
1. Introduction.
This manual is useful to understand
how to use the MIDI Files functions library. To perform a task,
each paragrah explains the flow of functions
and the order they must be used. There is also a chapter discussing
about the date of event and time unit representation.
2. The functions sets of the MFAPI library
(Midi File API) :
The library
is composed of two sets of function, one for reading and the other
for writing Midi Files.
2.1. MFAPI functions for Midi file reading:
2.1.1. File opening :
The file must exits to read it. One must open
it for reading by a call to MidiFileOpen with the mode
MidiFileRead. Only reading operations are possible.
2.1.2. Reading track by track :
After a call to MidifileOpen, (in the
MidifileAppend mode) a full track can be read to
a MidiShare sequence with MidiFileReadTrack who return
the sequence. The sequence is allocated by MidiFileReadTrack.
The caller must free the sequence with MidiFreeSeq after
using it.With MidiFileReadTrack, the track events from
the first to the last, are allocated in the same order in the
sequence. Several successives track may be read using successives
call to MidiFileReadTrack.
2.1.3. Reading a track event by event :
As an alternative to read the events of a
track, one may use the following functions, MidiFileChooseTrack,
MidiFileOpenTrack,MidiFileReadEv and MidiFileCloseTrack.
With these functions events are read one by one. MidiFileChooseTrack
set the file pointer to the beginning of the designated track.
The function MidFileOpenTrack open a track and must be
used after a call to the function MidiFileChooseTrack or
MidiFileCloseTrack.
MidiFileReadEv read an event from the current track. The
track must opened with MidFileOpenTrack before the reading
of the first event. Several successives events may be read with
successives call to MidiFileReadEv.
When the event read is the last from the track, a next call to
MidiFileReadEv automaticaly close the track. The macro
IsTrackOpen informs if a track is opened. So if a end of
track was dectected , it is not necessary to use MidiFileCloseTrack
to close the track.
MidiFileCloseTrack close the reading of the current track
and set the file pointer to the beginning of the next track.
MidiFileCloseTrack
is useful during the reading of a track to immediately point to
the next track.
2.1.4. Closing a Midi file :
To close the Midi file reading MidiFileClose
must be used.
2.2. MFAPI functions for Midi file writing :
2.2.1. Creating / opening a file :
MidiFileCreate
must be used to create a new file. If the file exists it is destroyed.
To preserve the file content one must open it with MidiFileOpen
in the MidiFileAppend mode. With theses two functions
only write operations are possible.
2.2.2. Writing a complete sequence to a file track:
After a call to MidiFileCreate (or
MidifileOpen, in the MidifileAppend mode)
MidiFileWriteTrack adds a track at the end of the file.
With MidiFileWriteTrack, the sequence events from the first
to the last are written in the same order to the track. Several
successives track may be written by using several call to MidiFileWriteTrack.
2.2.3. Writing a track event by event :
As an alternative to write a track one may use
the following functions, MidiFileNewTrack,MidiFileWriteEv
et MidiFileCloseTrack.
MidFileNewTrack create un new track header at the end of
the file. MidFileNewTrack must be used after a call
to MidiFileCloseTrack. MidiFileWriteEv write an
event in the cuurent track. Successive events may be written using
successive call to MidiFileWriteEv. MidiFileCloseTrack
end writting of the current track.
2.2.4. Closing the file :
Use the MidiFileClose to end the file
writing.
3.Understand the date of events
The following paragrah give you important
informations about the date of events of the Midi file standard
and about the date used by the library functions.
3.1. Events date in a Midi File:
The event date in a standard Midi file is a value relative to
the date of the previous event. The date of the first event of
a track is relative to zero ie relative to the beginning of the
track.
example:
Let a track composed of 3 events with the respective date to the
previous one.
ev1: relative date: 10
ev2: relative date: 25
ev3: relative date: 5
Event ev1 must be played at the date 10 relative to the beginning
of the track.
Event ev2 must be played at the date 10+25=35 relative to the
beginning of the track.
Event ev3 must be played at the date 35+5=40 relative to the beginning
of the track.
3.1.1. Time unit date representation in MIDIFile
Time unit to represent the dates of events is indicated by the
field time of the MIDIFile descriptor (returned by MidiFileOpen
or MidiFileCreate).
The Midi file standard agree with 2 representation modes of unit
time. Unit may be expressed in fraction of a second in a representation
which correspond to SMPTE. This mode is useful to represent a
collection of meta events like Cue Point or other events which
are suitable in videos films or movies.
Otherwise, time unit may be expressed in Pulses Per Quarter Note
(PPQN). This mode of representation asociated with the tempo
meta event is fited to represent the date of musical events sequence
or song.
3.1.2. Unit: fraction of a second
The macro smpte(f) return true
when the field time represents time in fraction of a second.
The macro frame_par_sec(f) return the number of frames
per second,
(The nomber is a negative value expressed in 2 complement form).
The macro ticks_par_frame(f) return the number of pulses
per frame, f is the pointer on the MIDIFile descriptor. Knowing
that the date of an event is expressed in pulses per frame, the
two macros frame_par_sec and ticks_par_frame must
be used to evaluate the date in fraction of a second.
3.1.3. Unit: number of Pulses Per Quarter Note (PPQN)
The macro smpte(f) return false when time represents
unit in pulses per quarter note. The macro ticks_par_quarterNote(f)
return the number of pulses per quarter note (PPQN). f is the
pointer on the MIDIFile decriptor.
3.2. Event date returned by MidiFileReadEv:
The date of an event returned by MidiFileReadEv is evaluated
like this:
The date of an event is the sum of all the relatives dates of
the previous events. The result is a date relative to zero. That
is the date relative to the beginning of the track. This is the
date to which the event must be played.
Example:
Let a track composed of 3 events with owned date relative to the
previous one.
ev1: date: 10 ev2: date: 25 ev3: date : 5
On reading of the 1er event, the event date returned is :10
On reading of the 2d event, the event date returned is :35 (10+25)
On reading of the 3rd event, the event date returned is :40 (35+5)
The unit time of the date is indicated by the field time witch
may be read with the macros described in the previous paragraph.
To obtain an event, one must read the previous events from the
beginning of the track to the target event.
3.3. Event date written by MidiFileWriteEv:
The date of an event written by MidiFileReadEv is relative to the previous written event. The function
assume that the date owned by the event to write is relative to
zero ie relative to the beginning of the track.
The date of the written event is evaluated like this:
date (written_ev) = date (ev_to_write) - date (previous_written_ev)
Example:
Let a sequence composed of 3 events with the owned date relative
to the beginning of the track.
ev1: date: 10 ev2: date: 35 ev3: date: 40
The date of the 1er written event(ev1) is: 10
The date of the 2nd written event(ev2) is: 25 (35 - 10)
The date of the 3rd written event(ev3) is: 5 (40 - 35)
The function assume that the unit time of the date is indicated
by the field time witch may be read with the macros described
in the previous paragraph. So to be complient to the standard
Midi file and if it is necessary the caller must normalize the
variable time and the date of the event to write before a call
MidiFileWriteEv.