Using
MidiShare Functions Library
MIDI Files Management



Table of contents


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.