Line wrap at 100 lines so I can read things :).
Formatting changes only. git-svn-id: svn://localhost/ardour2/branches/3.0@4562 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
cdbb1f898e
commit
1fd221ed1c
@ -46,8 +46,8 @@
|
||||
* of these types, i.e. never do something like this: "smf_t smf;". Always use
|
||||
* "smf_t *smf = smf_new();". The same applies to smf_track_t and smf_event_t.
|
||||
*
|
||||
* Say you want to load a Standard MIDI File (.mid) file and play it back somehow. This is (roughly)
|
||||
* how you do this:
|
||||
* Say you want to load a Standard MIDI File (.mid) file and play it back somehow.
|
||||
* This is (roughly) how you do this:
|
||||
*
|
||||
* \code
|
||||
* smf_t *smf;
|
||||
@ -115,11 +115,11 @@
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
* There are two basic ways of getting MIDI data out of smf - sequential or by track/event number. You may
|
||||
* mix them if you need to. First one is used in the example above - seek to the point from which you want
|
||||
* the playback to start (using smf_seek_to_seconds(), smf_seek_to_pulses() or smf_seek_to_event()) and then
|
||||
* do smf_get_next_event() in loop, until it returns NULL. Calling smf_load() causes the smf to be rewound
|
||||
* to the start of the song.
|
||||
* There are two basic ways of getting MIDI data out of smf - sequential or by track/event number.
|
||||
* You may mix them if you need to. First one is used in the example above - seek to the point
|
||||
* from which you want the playback to start (using smf_seek_to_seconds(), smf_seek_to_pulses()
|
||||
* or smf_seek_to_event()) and then do smf_get_next_event() in loop, until it returns NULL.
|
||||
* Calling smf_load() causes the smf to be rewound to the start of the song.
|
||||
*
|
||||
* Getting events by number works like this:
|
||||
*
|
||||
@ -130,83 +130,86 @@
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
* To create new event, use smf_event_new(), smf_event_new_from_pointer() or smf_event_new_from_bytes().
|
||||
* First one creates an empty event - you need to manually allocate (using malloc(3)) buffer for
|
||||
* MIDI data, write MIDI data into it, put the address of that buffer into event->midi_buffer,
|
||||
* and the length of MIDI data into event->midi_buffer_length. Note that deleting the event
|
||||
* (using smf_event_delete()) will free the buffer.
|
||||
* To create new event, use smf_event_new(), smf_event_new_from_pointer() or
|
||||
* smf_event_new_from_bytes(). First one creates an empty event - you need to manually allocate
|
||||
* (using malloc(3)) buffer for MIDI data, write MIDI data into it, put the address of that
|
||||
* buffer into event->midi_buffer, and the length of MIDI data into event->midi_buffer_length.
|
||||
* Note that deleting the event (using smf_event_delete()) will free the buffer.
|
||||
*
|
||||
* Second form does most of this for you: it takes an address of the buffer containing MIDI data,
|
||||
* allocates storage and copies MIDI data into it.
|
||||
*
|
||||
* Third form is useful for manually creating short events, up to three bytes in length, for
|
||||
* example Note On or Note Off events. It simply takes three bytes and creates MIDI event containing
|
||||
* them. If you need to create MIDI message that takes only two bytes, pass -1 as the third byte.
|
||||
* For one byte message (System Realtime), pass -1 as second and third byte.
|
||||
* example Note On or Note Off events. It simply takes three bytes and creates MIDI event
|
||||
* containing them. If you need to create MIDI message that takes only two bytes, pass -1 as
|
||||
* the third byte. For one byte message (System Realtime), pass -1 as second and third byte.
|
||||
*
|
||||
* To free an event, use smf_event_delete().
|
||||
*
|
||||
* To add event to the track, use smf_track_add_event_delta_pulses(), smf_track_add_event_pulses(),
|
||||
* or smf_track_add_event_seconds(). The difference between them is in the way you specify the time of
|
||||
* the event - with the first one, you specify it as an interval, in pulses, from the previous event
|
||||
* in this track; with the second one, you specify it as pulses from the start of the song, and with the
|
||||
* last one, you specify it as seconds from the start of the song. Obviously, the first version can
|
||||
* only append events at the end of the track.
|
||||
* or smf_track_add_event_seconds(). The difference between them is in the way you specify the
|
||||
* time of the event - with the first one, you specify it as an interval, in pulses, from the
|
||||
* previous event in this track; with the second one, you specify it as pulses from the start
|
||||
* of the song, and with the last one, you specify it as seconds from the start of the song.
|
||||
* Obviously, the first version can only append events at the end of the track.
|
||||
*
|
||||
* To remove an event from the track it's attached to, use smf_event_remove_from_track(). You may
|
||||
* want to free the event (using smf_event_delete()) afterwards.
|
||||
* To remove an event from the track it's attached to, use smf_event_remove_from_track().
|
||||
* You may want to free the event (using smf_event_delete()) afterwards.
|
||||
*
|
||||
* To create new track, use smf_track_new(). To add track to the smf, use smf_add_track().
|
||||
* To remove track from its smf, use smf_track_remove_from_smf(). To free the track structure,
|
||||
* use smf_track_delete().
|
||||
*
|
||||
* Note that libsmf keeps things consistent. If you free (using smf_track_delete()) a track that
|
||||
* is attached to an smf and contains events, libsmf will detach the events, free them, detach
|
||||
* the track, free it etc.
|
||||
* Note that libsmf keeps things consistent. If you free (using smf_track_delete()) a track
|
||||
* that is attached to an smf and contains events, libsmf will detach the events, free them,
|
||||
* detach the track, free it etc.
|
||||
*
|
||||
* Tracks and events are numbered consecutively, starting from one. If you remove a track or event,
|
||||
* the rest of tracks/events will get renumbered. To get the number of a given event in its track, use event->event_number.
|
||||
* To get the number of track in its smf, use track->track_number. To get the number of events in the track,
|
||||
* use track->number_of_events. To get the number of tracks in the smf, use smf->number_of_tracks.
|
||||
* Tracks and events are numbered consecutively, starting from one. If you remove a track
|
||||
* or event, the rest of tracks/events will get renumbered. To get the number of a given
|
||||
* event in its track, use event->event_number. To get the number of track in its smf, use
|
||||
* track->track_number. To get the number of events in the track, use track->number_of_events.
|
||||
* To get the number of tracks in the smf, use smf->number_of_tracks.
|
||||
*
|
||||
* In SMF File Format, each track has to end with End Of Track metaevent. If you load SMF file using smf_load(),
|
||||
* that will be the case. If you want to create or edit an SMF, you don't need to worry about EOT events;
|
||||
* libsmf automatically takes care of them for you. If you try to save an SMF with tracks that do not end
|
||||
* with EOTs, smf_save() will append them. If you try to add event that happens after EOT metaevent, libsmf
|
||||
* will remove the EOT. If you want to add EOT manually, you can, of course, using smf_track_add_eot_seconds()
|
||||
* In SMF File Format, each track has to end with End Of Track metaevent. If you load SMF file
|
||||
* using smf_load(), that will be the case. If you want to create or edit an SMF, you don't
|
||||
* need to worry about EOT events; libsmf automatically takes care of them for you. If you
|
||||
* try to save an SMF with tracks that do not end with EOTs, smf_save() will append them.
|
||||
* If you try to add event that happens after EOT metaevent, libsmf will remove the EOT.
|
||||
* If you want to add EOT manually, you can, of course, using smf_track_add_eot_seconds()
|
||||
* or smf_track_add_eot_pulses().
|
||||
*
|
||||
* Each event carries three time values - event->time_seconds, which is seconds since the start of the song,
|
||||
* event->time_pulses, which is PPQN clocks since the start of the song, and event->delta_pulses, which is PPQN clocks
|
||||
* since the previous event in that track. These values are invalid if the event is not attached to the track.
|
||||
* If event is attached, all three values are valid. Time of the event is specified when adding the event
|
||||
* (using smf_track_add_event_seconds(), smf_track_add_event_pulses() or smf_track_add_event_delta_pulses()); the remaining
|
||||
* two values are computed from that.
|
||||
* Each event carries three time values - event->time_seconds, which is seconds since
|
||||
* the start of the song, event->time_pulses, which is PPQN clocks since the start of
|
||||
* the song, and event->delta_pulses, which is PPQN clocks since the previous event
|
||||
* in that track. These values are invalid if the event is not attached to the track.
|
||||
* If event is attached, all three values are valid. Time of the event is specified when
|
||||
* adding the event (using smf_track_add_event_seconds(), smf_track_add_event_pulses() or
|
||||
* smf_track_add_event_delta_pulses()); the remaining two values are computed from that.
|
||||
*
|
||||
* Tempo related stuff happens automatically - when you add a metaevent that
|
||||
* is Tempo Change or Time Signature, libsmf adds that event to the tempo map. If you remove
|
||||
* Tempo Change event that is in the middle of the song, the rest of the events will have their
|
||||
* event->time_seconds recomputed from event->time_pulses before smf_event_remove_from_track() function returns.
|
||||
* Tempo related stuff happens automatically - when you add a metaevent that is Tempo Change or
|
||||
* Time Signature, libsmf adds that event to the tempo map. If you remove Tempo Change event
|
||||
* that is in the middle of the song, the rest of the events will have their event->time_seconds
|
||||
* recomputed from event->time_pulses before smf_event_remove_from_track() function returns.
|
||||
* Adding Tempo Change in the middle of the song works in a similar way.
|
||||
*
|
||||
* MIDI data (event->midi_buffer) is always kept in normalized form - it always begins with status byte
|
||||
* (no running status), there are no System Realtime events embedded in them etc. Events like SysExes
|
||||
* are in "on the wire" form, without embedded length that is used in SMF file format. Obviously
|
||||
* libsmf "normalizes" MIDI data during loading and "denormalizes" (adding length to SysExes, escaping
|
||||
* System Common and System Realtime messages etc) during writing.
|
||||
*
|
||||
* MIDI data (event->midi_buffer) is always kept in normalized form - it always begins with
|
||||
* status byte (no running status), there are no System Realtime events embedded in them etc.
|
||||
* Events like SysExes are in "on the wire" form, without embedded length that is used in SMF
|
||||
* file format. Obviously libsmf "normalizes" MIDI data during loading and "denormalizes" (adding
|
||||
* length to SysExes, escaping System Common and System Realtime messages etc) during writing.
|
||||
*
|
||||
* Note that you always have to first add the track to smf, and then add events to the track.
|
||||
* Doing it the other way around will trip asserts. Also, try to add events at the end of the track and remove
|
||||
* them from the end of the track, that's much more efficient.
|
||||
*
|
||||
* All the libsmf functions have prefix "smf_". First argument for routines whose names start with
|
||||
* "smf_event_" is "smf_event_t *", for routines whose names start with "smf_track_" - "smf_track_t *",
|
||||
* and for plain "smf_" - "smf_t *". The only exception are smf_whatever_new routines.
|
||||
* Library does not use any global variables and is thread-safe,
|
||||
* as long as you don't try to work on the same SMF (smf_t and its descendant tracks and events) from several
|
||||
* threads at once without protecting it with mutex. Library depends on glib and nothing else. License is
|
||||
* BSD, two clause, which basically means you can use it freely in your software, both Open Source (including
|
||||
* GPL) and closed source.
|
||||
* Doing it the other way around will trip asserts. Also, try to add events at the end of the
|
||||
* track and remove them from the end of the track, that's much more efficient.
|
||||
*
|
||||
* All the libsmf functions have prefix "smf_". First argument for routines whose names start
|
||||
* with "smf_event_" is "smf_event_t *", for routines whose names start with "smf_track_" -
|
||||
* "smf_track_t *", and for plain "smf_" - "smf_t *". The only exception are smf_whatever_new
|
||||
* routines. Library does not use any global variables and is thread-safe, as long as you
|
||||
* don't try to work on the same SMF (smf_t and its descendant tracks and events) from several
|
||||
* threads at once without protecting it with mutex. Library depends on glib and nothing else.
|
||||
* License is BSD, two clause, which basically means you can use it freely in your software,
|
||||
* both Open Source (including GPL) and closed source.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -231,7 +234,8 @@ extern "C" {
|
||||
struct smf_struct {
|
||||
int format;
|
||||
|
||||
/** These fields are extracted from "division" field of MThd header. Valid is _either_ ppqn or frames_per_second/resolution. */
|
||||
/** These fields are extracted from "division" field of MThd header.
|
||||
* Valid is _either_ ppqn or frames_per_second/resolution. */
|
||||
uint16_t ppqn;
|
||||
int frames_per_second;
|
||||
int resolution;
|
||||
@ -297,7 +301,7 @@ struct smf_event_struct {
|
||||
/** Pointer to the track, or NULL if event is not attached. */
|
||||
smf_track_t *track;
|
||||
|
||||
/** Number of this event in the track. Events are numbered consecutively, starting from one. */
|
||||
/** Number of this event in the track. Events are numbered consecutively, starting from 1. */
|
||||
size_t event_number;
|
||||
|
||||
/** Note that the time fields are invalid, if event is not attached to a track. */
|
||||
@ -354,7 +358,7 @@ smf_track_t *smf_track_new(void) WARN_UNUSED_RESULT;
|
||||
void smf_track_delete(smf_track_t *track);
|
||||
|
||||
smf_event_t *smf_track_get_next_event(smf_track_t *track) WARN_UNUSED_RESULT;
|
||||
smf_event_t *smf_track_get_event_by_number(const smf_track_t *track, size_t event_number) WARN_UNUSED_RESULT;
|
||||
smf_event_t *smf_track_get_event_by_number(const smf_track_t *track, size_t num) WARN_UNUSED_RESULT;
|
||||
smf_event_t *smf_track_get_last_event(const smf_track_t *track) WARN_UNUSED_RESULT;
|
||||
|
||||
void smf_track_add_event_delta_pulses(smf_track_t *track, smf_event_t *event, uint32_t delta);
|
||||
@ -368,7 +372,7 @@ void smf_event_remove_from_track(smf_event_t *event);
|
||||
/* Routines for manipulating smf_event_t. */
|
||||
smf_event_t *smf_event_new(void) WARN_UNUSED_RESULT;
|
||||
smf_event_t *smf_event_new_from_pointer(void *midi_data, size_t len) WARN_UNUSED_RESULT;
|
||||
smf_event_t *smf_event_new_from_bytes(int first_byte, int second_byte, int third_byte) WARN_UNUSED_RESULT;
|
||||
smf_event_t *smf_event_new_from_bytes(int byte1, int byte2, int byte3) WARN_UNUSED_RESULT;
|
||||
smf_event_t *smf_event_new_textual(int type, const char *text);
|
||||
void smf_event_delete(smf_event_t *event);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user