rev |
line source |
nuclear@0
|
1 /*-
|
nuclear@0
|
2 * Copyright (c) 2007, 2008 Edward Tomasz NapieraĆa <trasz@FreeBSD.org>
|
nuclear@0
|
3 * All rights reserved.
|
nuclear@0
|
4 *
|
nuclear@0
|
5 * Redistribution and use in source and binary forms, with or without
|
nuclear@0
|
6 * modification, are permitted provided that the following conditions
|
nuclear@0
|
7 * are met:
|
nuclear@0
|
8 * 1. Redistributions of source code must retain the above copyright
|
nuclear@0
|
9 * notice, this list of conditions and the following disclaimer.
|
nuclear@0
|
10 * 2. Redistributions in binary form must reproduce the above copyright
|
nuclear@0
|
11 * notice, this list of conditions and the following disclaimer in the
|
nuclear@0
|
12 * documentation and/or other materials provided with the distribution.
|
nuclear@0
|
13 *
|
nuclear@0
|
14 * ALTHOUGH THIS SOFTWARE IS MADE OF WIN AND SCIENCE, IT IS PROVIDED BY THE
|
nuclear@0
|
15 * AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
nuclear@0
|
16 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
nuclear@0
|
17 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
nuclear@0
|
18 * THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
nuclear@0
|
19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
nuclear@0
|
20 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
nuclear@0
|
21 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
nuclear@0
|
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
nuclear@0
|
23 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
nuclear@0
|
24 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
nuclear@0
|
25 *
|
nuclear@0
|
26 */
|
nuclear@0
|
27
|
nuclear@0
|
28 /**
|
nuclear@0
|
29 * \file
|
nuclear@0
|
30 *
|
nuclear@0
|
31 * Public interface declaration for libsmf, Standard MIDI File format library.
|
nuclear@0
|
32 */
|
nuclear@0
|
33
|
nuclear@0
|
34 /**
|
nuclear@0
|
35 *
|
nuclear@0
|
36 * \mainpage libsmf - general usage instructions
|
nuclear@0
|
37 *
|
nuclear@0
|
38 * An smf_t structure represents a "song". Every valid smf contains one or more tracks.
|
nuclear@0
|
39 * Tracks contain zero or more events. Libsmf doesn't care about actual MIDI data, as long
|
nuclear@0
|
40 * as it is valid from the MIDI specification point of view - it may be realtime message,
|
nuclear@0
|
41 * SysEx, whatever.
|
nuclear@0
|
42 *
|
nuclear@0
|
43 * The only field in smf_t, smf_track_t, smf_event_t and smf_tempo_t structures your
|
nuclear@0
|
44 * code may modify is event->midi_buffer and event->midi_buffer_length. Do not modify
|
nuclear@0
|
45 * other fields, _ever_. You may read them, though. Do not declare static instances
|
nuclear@0
|
46 * of these types, i.e. never do something like this: "smf_t smf;". Always use
|
nuclear@0
|
47 * "smf_t *smf = smf_new();". The same applies to smf_track_t and smf_event_t.
|
nuclear@0
|
48 *
|
nuclear@0
|
49 * Say you want to load a Standard MIDI File (.mid) file and play it back somehow. This is (roughly)
|
nuclear@0
|
50 * how you do this:
|
nuclear@0
|
51 *
|
nuclear@0
|
52 * \code
|
nuclear@0
|
53 * smf_t *smf;
|
nuclear@0
|
54 * smf_event_t *event;
|
nuclear@0
|
55 *
|
nuclear@0
|
56 * smf = smf_load(file_name);
|
nuclear@0
|
57 * if (smf == NULL) {
|
nuclear@0
|
58 * Whoops, something went wrong.
|
nuclear@0
|
59 * return;
|
nuclear@0
|
60 * }
|
nuclear@0
|
61 *
|
nuclear@0
|
62 * while ((event = smf_get_next_event(smf)) != NULL) {
|
nuclear@0
|
63 * if (smf_event_is_metadata(event))
|
nuclear@0
|
64 * continue;
|
nuclear@0
|
65 *
|
nuclear@0
|
66 * wait until event->time_seconds.
|
nuclear@0
|
67 * feed_to_midi_output(event->midi_buffer, event->midi_buffer_length);
|
nuclear@0
|
68 * }
|
nuclear@0
|
69 *
|
nuclear@0
|
70 * smf_delete(smf);
|
nuclear@0
|
71 *
|
nuclear@0
|
72 * \endcode
|
nuclear@0
|
73 *
|
nuclear@0
|
74 * Saving works like this:
|
nuclear@0
|
75 *
|
nuclear@0
|
76 * \code
|
nuclear@0
|
77 *
|
nuclear@0
|
78 * smf_t *smf;
|
nuclear@0
|
79 * smf_track_t *track;
|
nuclear@0
|
80 * smf_event_t *event;
|
nuclear@0
|
81 *
|
nuclear@0
|
82 * smf = smf_new();
|
nuclear@0
|
83 * if (smf == NULL) {
|
nuclear@0
|
84 * Whoops.
|
nuclear@0
|
85 * return;
|
nuclear@0
|
86 * }
|
nuclear@0
|
87 *
|
nuclear@0
|
88 * for (int i = 1; i <= number of tracks; i++) {
|
nuclear@0
|
89 * track = smf_track_new();
|
nuclear@0
|
90 * if (track == NULL) {
|
nuclear@0
|
91 * Whoops.
|
nuclear@0
|
92 * return;
|
nuclear@0
|
93 * }
|
nuclear@0
|
94 *
|
nuclear@0
|
95 * smf_add_track(smf, track);
|
nuclear@0
|
96 *
|
nuclear@0
|
97 * for (int j = 1; j <= number of events you want to put into this track; j++) {
|
nuclear@0
|
98 * event = smf_event_new_from_pointer(your MIDI message, message length);
|
nuclear@0
|
99 * if (event == NULL) {
|
nuclear@0
|
100 * Whoops.
|
nuclear@0
|
101 * return;
|
nuclear@0
|
102 * }
|
nuclear@0
|
103 *
|
nuclear@0
|
104 * smf_track_add_event_seconds(track, event, seconds since start of the song);
|
nuclear@0
|
105 * }
|
nuclear@0
|
106 * }
|
nuclear@0
|
107 *
|
nuclear@0
|
108 * ret = smf_save(smf, file_name);
|
nuclear@0
|
109 * if (ret) {
|
nuclear@0
|
110 * Whoops, saving failed for some reason.
|
nuclear@0
|
111 * return;
|
nuclear@0
|
112 * }
|
nuclear@0
|
113 *
|
nuclear@0
|
114 * smf_delete(smf);
|
nuclear@0
|
115 *
|
nuclear@0
|
116 * \endcode
|
nuclear@0
|
117 *
|
nuclear@0
|
118 * There are two basic ways of getting MIDI data out of smf - sequential or by track/event number. You may
|
nuclear@0
|
119 * mix them if you need to. First one is used in the example above - seek to the point from which you want
|
nuclear@0
|
120 * the playback to start (using smf_seek_to_seconds(), smf_seek_to_pulses() or smf_seek_to_event()) and then
|
nuclear@0
|
121 * do smf_get_next_event() in loop, until it returns NULL. Calling smf_load() causes the smf to be rewound
|
nuclear@0
|
122 * to the start of the song.
|
nuclear@0
|
123 *
|
nuclear@0
|
124 * Getting events by number works like this:
|
nuclear@0
|
125 *
|
nuclear@0
|
126 * \code
|
nuclear@0
|
127 *
|
nuclear@0
|
128 * smf_track_t *track = smf_get_track_by_number(smf, track_number);
|
nuclear@0
|
129 * smf_event_t *event = smf_track_get_event_by_number(track, event_number);
|
nuclear@0
|
130 *
|
nuclear@0
|
131 * \endcode
|
nuclear@0
|
132 *
|
nuclear@0
|
133 * To create new event, use smf_event_new(), smf_event_new_from_pointer() or smf_event_new_from_bytes().
|
nuclear@0
|
134 * First one creates an empty event - you need to manually allocate (using malloc(3)) buffer for
|
nuclear@0
|
135 * MIDI data, write MIDI data into it, put the address of that buffer into event->midi_buffer,
|
nuclear@0
|
136 * and the length of MIDI data into event->midi_buffer_length. Note that deleting the event
|
nuclear@0
|
137 * (using smf_event_delete()) will free the buffer.
|
nuclear@0
|
138 *
|
nuclear@0
|
139 * Second form does most of this for you: it takes an address of the buffer containing MIDI data,
|
nuclear@0
|
140 * allocates storage and copies MIDI data into it.
|
nuclear@0
|
141 *
|
nuclear@0
|
142 * Third form is useful for manually creating short events, up to three bytes in length, for
|
nuclear@0
|
143 * example Note On or Note Off events. It simply takes three bytes and creates MIDI event containing
|
nuclear@0
|
144 * them. If you need to create MIDI message that takes only two bytes, pass -1 as the third byte.
|
nuclear@0
|
145 * For one byte message (System Realtime), pass -1 as second and third byte.
|
nuclear@0
|
146 *
|
nuclear@0
|
147 * To free an event, use smf_event_delete().
|
nuclear@0
|
148 *
|
nuclear@0
|
149 * To add event to the track, use smf_track_add_event_delta_pulses(), smf_track_add_event_pulses(),
|
nuclear@0
|
150 * or smf_track_add_event_seconds(). The difference between them is in the way you specify the time of
|
nuclear@0
|
151 * the event - with the first one, you specify it as an interval, in pulses, from the previous event
|
nuclear@0
|
152 * in this track; with the second one, you specify it as pulses from the start of the song, and with the
|
nuclear@0
|
153 * last one, you specify it as seconds from the start of the song. Obviously, the first version can
|
nuclear@0
|
154 * only append events at the end of the track.
|
nuclear@0
|
155 *
|
nuclear@0
|
156 * To remove an event from the track it's attached to, use smf_event_remove_from_track(). You may
|
nuclear@0
|
157 * want to free the event (using smf_event_delete()) afterwards.
|
nuclear@0
|
158 *
|
nuclear@0
|
159 * To create new track, use smf_track_new(). To add track to the smf, use smf_add_track().
|
nuclear@0
|
160 * To remove track from its smf, use smf_track_remove_from_smf(). To free the track structure,
|
nuclear@0
|
161 * use smf_track_delete().
|
nuclear@0
|
162 *
|
nuclear@0
|
163 * Note that libsmf keeps things consistent. If you free (using smf_track_delete()) a track that
|
nuclear@0
|
164 * is attached to an smf and contains events, libsmf will detach the events, free them, detach
|
nuclear@0
|
165 * the track, free it etc.
|
nuclear@0
|
166 *
|
nuclear@0
|
167 * Tracks and events are numbered consecutively, starting from one. If you remove a track or event,
|
nuclear@0
|
168 * the rest of tracks/events will get renumbered. To get the number of a given event in its track, use event->event_number.
|
nuclear@0
|
169 * To get the number of track in its smf, use track->track_number. To get the number of events in the track,
|
nuclear@0
|
170 * use track->number_of_events. To get the number of tracks in the smf, use smf->number_of_tracks.
|
nuclear@0
|
171 *
|
nuclear@0
|
172 * In SMF File Format, each track has to end with End Of Track metaevent. If you load SMF file using smf_load(),
|
nuclear@0
|
173 * that will be the case. If you want to create or edit an SMF, you don't need to worry about EOT events;
|
nuclear@0
|
174 * libsmf automatically takes care of them for you. If you try to save an SMF with tracks that do not end
|
nuclear@0
|
175 * with EOTs, smf_save() will append them. If you try to add event that happens after EOT metaevent, libsmf
|
nuclear@0
|
176 * will remove the EOT. If you want to add EOT manually, you can, of course, using smf_track_add_eot_seconds()
|
nuclear@0
|
177 * or smf_track_add_eot_pulses().
|
nuclear@0
|
178 *
|
nuclear@0
|
179 * Each event carries three time values - event->time_seconds, which is seconds since the start of the song,
|
nuclear@0
|
180 * event->time_pulses, which is PPQN clocks since the start of the song, and event->delta_pulses, which is PPQN clocks
|
nuclear@0
|
181 * since the previous event in that track. These values are invalid if the event is not attached to the track.
|
nuclear@0
|
182 * If event is attached, all three values are valid. Time of the event is specified when adding the event
|
nuclear@0
|
183 * (using smf_track_add_event_seconds(), smf_track_add_event_pulses() or smf_track_add_event_delta_pulses()); the remaining
|
nuclear@0
|
184 * two values are computed from that.
|
nuclear@0
|
185 *
|
nuclear@0
|
186 * Tempo related stuff happens automatically - when you add a metaevent that
|
nuclear@0
|
187 * is Tempo Change or Time Signature, libsmf adds that event to the tempo map. If you remove
|
nuclear@0
|
188 * Tempo Change event that is in the middle of the song, the rest of the events will have their
|
nuclear@0
|
189 * event->time_seconds recomputed from event->time_pulses before smf_event_remove_from_track() function returns.
|
nuclear@0
|
190 * Adding Tempo Change in the middle of the song works in a similar way.
|
nuclear@0
|
191 *
|
nuclear@0
|
192 * MIDI data (event->midi_buffer) is always kept in normalized form - it always begins with status byte
|
nuclear@0
|
193 * (no running status), there are no System Realtime events embedded in them etc. Events like SysExes
|
nuclear@0
|
194 * are in "on the wire" form, without embedded length that is used in SMF file format. Obviously
|
nuclear@0
|
195 * libsmf "normalizes" MIDI data during loading and "denormalizes" (adding length to SysExes, escaping
|
nuclear@0
|
196 * System Common and System Realtime messages etc) during writing.
|
nuclear@0
|
197 *
|
nuclear@0
|
198 * Note that you always have to first add the track to smf, and then add events to the track.
|
nuclear@0
|
199 * Doing it the other way around will trip asserts. Also, try to add events at the end of the track and remove
|
nuclear@0
|
200 * them from the end of the track, that's much more efficient.
|
nuclear@0
|
201 *
|
nuclear@0
|
202 * All the libsmf functions have prefix "smf_". First argument for routines whose names start with
|
nuclear@0
|
203 * "smf_event_" is "smf_event_t *", for routines whose names start with "smf_track_" - "smf_track_t *",
|
nuclear@0
|
204 * and for plain "smf_" - "smf_t *". The only exception are smf_whatever_new routines.
|
nuclear@0
|
205 * Library does not use any global variables and is thread-safe,
|
nuclear@0
|
206 * as long as you don't try to work on the same SMF (smf_t and its descendant tracks and events) from several
|
nuclear@0
|
207 * threads at once without protecting it with mutex. Library depends on glib and nothing else. License is
|
nuclear@0
|
208 * BSD, two clause, which basically means you can use it freely in your software, both Open Source (including
|
nuclear@0
|
209 * GPL) and closed source.
|
nuclear@0
|
210 *
|
nuclear@0
|
211 */
|
nuclear@0
|
212
|
nuclear@0
|
213 #ifndef SMF_H
|
nuclear@0
|
214 #define SMF_H
|
nuclear@0
|
215
|
nuclear@0
|
216 #ifdef __cplusplus
|
nuclear@0
|
217 extern "C" {
|
nuclear@0
|
218 #endif
|
nuclear@0
|
219
|
nuclear@0
|
220 #include <stdio.h>
|
nuclear@0
|
221
|
nuclear@0
|
222 #if defined(__GNUC__) && __GNUC__ >= 4
|
nuclear@0
|
223 #define WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
|
nuclear@0
|
224 #else
|
nuclear@0
|
225 #define WARN_UNUSED_RESULT
|
nuclear@0
|
226 #endif
|
nuclear@0
|
227
|
nuclear@0
|
228 struct FakeGPtrArray;
|
nuclear@0
|
229
|
nuclear@0
|
230 /** Represents a "song", that is, collection of one or more tracks. */
|
nuclear@0
|
231 struct smf_struct {
|
nuclear@0
|
232 int format;
|
nuclear@0
|
233
|
nuclear@0
|
234 /** These fields are extracted from "division" field of MThd header. Valid is _either_ ppqn or frames_per_second/resolution. */
|
nuclear@0
|
235 int ppqn;
|
nuclear@0
|
236 int frames_per_second;
|
nuclear@0
|
237 int resolution;
|
nuclear@0
|
238 int number_of_tracks;
|
nuclear@0
|
239
|
nuclear@0
|
240 /** These are private fields using only by loading and saving routines. */
|
nuclear@0
|
241 FILE *stream;
|
nuclear@0
|
242 void *file_buffer;
|
nuclear@0
|
243 int file_buffer_length;
|
nuclear@0
|
244 int next_chunk_offset;
|
nuclear@0
|
245 int expected_number_of_tracks;
|
nuclear@0
|
246
|
nuclear@0
|
247 /** Private, used by smf.c. */
|
nuclear@0
|
248 struct FakeGPtrArray *tracks_array;
|
nuclear@0
|
249 double last_seek_position;
|
nuclear@0
|
250
|
nuclear@0
|
251 /** Private, used by smf_tempo.c. */
|
nuclear@0
|
252 /** Array of pointers to smf_tempo_struct. */
|
nuclear@0
|
253 struct FakeGPtrArray *tempo_array;
|
nuclear@0
|
254 };
|
nuclear@0
|
255
|
nuclear@0
|
256 typedef struct smf_struct smf_t;
|
nuclear@0
|
257
|
nuclear@0
|
258 /** Describes a single tempo or time signature change. */
|
nuclear@0
|
259 struct smf_tempo_struct {
|
nuclear@0
|
260 int time_pulses;
|
nuclear@0
|
261 double time_seconds;
|
nuclear@0
|
262 int microseconds_per_quarter_note;
|
nuclear@0
|
263 int numerator;
|
nuclear@0
|
264 int denominator;
|
nuclear@0
|
265 int clocks_per_click;
|
nuclear@0
|
266 int notes_per_note;
|
nuclear@0
|
267 };
|
nuclear@0
|
268
|
nuclear@0
|
269 typedef struct smf_tempo_struct smf_tempo_t;
|
nuclear@0
|
270
|
nuclear@0
|
271 /** Represents a single track. */
|
nuclear@0
|
272 struct smf_track_struct {
|
nuclear@0
|
273 smf_t *smf;
|
nuclear@0
|
274
|
nuclear@0
|
275 int track_number;
|
nuclear@0
|
276 int number_of_events;
|
nuclear@0
|
277
|
nuclear@0
|
278 /** These are private fields using only by loading and saving routines. */
|
nuclear@0
|
279 void *file_buffer;
|
nuclear@0
|
280 int file_buffer_length;
|
nuclear@0
|
281 int last_status; /* Used for "running status". */
|
nuclear@0
|
282
|
nuclear@0
|
283 /** Private, used by smf.c. */
|
nuclear@0
|
284 /** Offset into buffer, used in parse_next_event(). */
|
nuclear@0
|
285 int next_event_offset;
|
nuclear@0
|
286 int next_event_number;
|
nuclear@0
|
287
|
nuclear@0
|
288 /** Absolute time of next event on events_queue. */
|
nuclear@0
|
289 int time_of_next_event;
|
nuclear@0
|
290 struct FakeGPtrArray *events_array;
|
nuclear@0
|
291
|
nuclear@0
|
292 /** API consumer is free to use this for whatever purpose. NULL in freshly allocated track.
|
nuclear@0
|
293 Note that tracks might be deallocated not only explicitly, by calling smf_track_delete(),
|
nuclear@0
|
294 but also implicitly, e.g. when calling smf_delete() with tracks still added to
|
nuclear@0
|
295 the smf; there is no mechanism for libsmf to notify you about removal of the track. */
|
nuclear@0
|
296 void *user_pointer;
|
nuclear@0
|
297 };
|
nuclear@0
|
298
|
nuclear@0
|
299 typedef struct smf_track_struct smf_track_t;
|
nuclear@0
|
300
|
nuclear@0
|
301 /** Represents a single MIDI event or metaevent. */
|
nuclear@0
|
302 struct smf_event_struct {
|
nuclear@0
|
303 /** Pointer to the track, or NULL if event is not attached. */
|
nuclear@0
|
304 smf_track_t *track;
|
nuclear@0
|
305
|
nuclear@0
|
306 /** Number of this event in the track. Events are numbered consecutively, starting from one. */
|
nuclear@0
|
307 int event_number;
|
nuclear@0
|
308
|
nuclear@0
|
309 /** Note that the time fields are invalid, if event is not attached to a track. */
|
nuclear@0
|
310 /** Time, in pulses, since the previous event on this track. */
|
nuclear@0
|
311 int delta_time_pulses;
|
nuclear@0
|
312
|
nuclear@0
|
313 /** Time, in pulses, since the start of the song. */
|
nuclear@0
|
314 int time_pulses;
|
nuclear@0
|
315
|
nuclear@0
|
316 /** Time, in seconds, since the start of the song. */
|
nuclear@0
|
317 double time_seconds;
|
nuclear@0
|
318
|
nuclear@0
|
319 /** Tracks are numbered consecutively, starting from 1. */
|
nuclear@0
|
320 int track_number;
|
nuclear@0
|
321
|
nuclear@0
|
322 /** Pointer to the buffer containing MIDI message. This is freed by smf_event_delete. */
|
nuclear@0
|
323 unsigned char *midi_buffer;
|
nuclear@0
|
324
|
nuclear@0
|
325 /** Length of the MIDI message in the buffer, in bytes. */
|
nuclear@0
|
326 int midi_buffer_length;
|
nuclear@0
|
327
|
nuclear@0
|
328 /** API consumer is free to use this for whatever purpose. NULL in freshly allocated event.
|
nuclear@0
|
329 Note that events might be deallocated not only explicitly, by calling smf_event_delete(),
|
nuclear@0
|
330 but also implicitly, e.g. when calling smf_track_delete() with events still added to
|
nuclear@0
|
331 the track; there is no mechanism for libsmf to notify you about removal of the event. */
|
nuclear@0
|
332 void *user_pointer;
|
nuclear@0
|
333 };
|
nuclear@0
|
334
|
nuclear@0
|
335 typedef struct smf_event_struct smf_event_t;
|
nuclear@0
|
336
|
nuclear@0
|
337 /* Routines for manipulating smf_t. */
|
nuclear@0
|
338 smf_t *smf_new(void) WARN_UNUSED_RESULT;
|
nuclear@0
|
339 void smf_delete(smf_t *smf);
|
nuclear@0
|
340
|
nuclear@0
|
341 int smf_set_format(smf_t *smf, int format) WARN_UNUSED_RESULT;
|
nuclear@0
|
342 int smf_set_ppqn(smf_t *smf, int format) WARN_UNUSED_RESULT;
|
nuclear@0
|
343
|
nuclear@0
|
344 char *smf_decode(const smf_t *smf) WARN_UNUSED_RESULT;
|
nuclear@0
|
345
|
nuclear@0
|
346 smf_track_t *smf_get_track_by_number(const smf_t *smf, int track_number) WARN_UNUSED_RESULT;
|
nuclear@0
|
347
|
nuclear@0
|
348 smf_event_t *smf_peek_next_event(smf_t *smf) WARN_UNUSED_RESULT;
|
nuclear@0
|
349 smf_event_t *smf_get_next_event(smf_t *smf) WARN_UNUSED_RESULT;
|
nuclear@0
|
350 void smf_skip_next_event(smf_t *smf);
|
nuclear@0
|
351
|
nuclear@0
|
352 void smf_rewind(smf_t *smf);
|
nuclear@0
|
353 int smf_seek_to_seconds(smf_t *smf, double seconds) WARN_UNUSED_RESULT;
|
nuclear@0
|
354 int smf_seek_to_pulses(smf_t *smf, int pulses) WARN_UNUSED_RESULT;
|
nuclear@0
|
355 int smf_seek_to_event(smf_t *smf, const smf_event_t *event) WARN_UNUSED_RESULT;
|
nuclear@0
|
356
|
nuclear@0
|
357 int smf_get_length_pulses(const smf_t *smf) WARN_UNUSED_RESULT;
|
nuclear@0
|
358 double smf_get_length_seconds(const smf_t *smf) WARN_UNUSED_RESULT;
|
nuclear@0
|
359 int smf_event_is_last(const smf_event_t *event) WARN_UNUSED_RESULT;
|
nuclear@0
|
360
|
nuclear@0
|
361 void smf_add_track(smf_t *smf, smf_track_t *track);
|
nuclear@0
|
362 void smf_track_remove_from_smf(smf_track_t *track);
|
nuclear@0
|
363
|
nuclear@0
|
364 /* Routines for manipulating smf_track_t. */
|
nuclear@0
|
365 smf_track_t *smf_track_new(void) WARN_UNUSED_RESULT;
|
nuclear@0
|
366 void smf_track_delete(smf_track_t *track);
|
nuclear@0
|
367
|
nuclear@0
|
368 smf_event_t *smf_track_get_next_event(smf_track_t *track) WARN_UNUSED_RESULT;
|
nuclear@0
|
369 smf_event_t *smf_track_get_event_by_number(const smf_track_t *track, int event_number) WARN_UNUSED_RESULT;
|
nuclear@0
|
370 smf_event_t *smf_track_get_last_event(const smf_track_t *track) WARN_UNUSED_RESULT;
|
nuclear@0
|
371
|
nuclear@0
|
372 void smf_track_add_event_delta_pulses(smf_track_t *track, smf_event_t *event, int pulses);
|
nuclear@0
|
373 void smf_track_add_event_pulses(smf_track_t *track, smf_event_t *event, int pulses);
|
nuclear@0
|
374 void smf_track_add_event_seconds(smf_track_t *track, smf_event_t *event, double seconds);
|
nuclear@0
|
375 int smf_track_add_eot_delta_pulses(smf_track_t *track, int delta) WARN_UNUSED_RESULT;
|
nuclear@0
|
376 int smf_track_add_eot_pulses(smf_track_t *track, int pulses) WARN_UNUSED_RESULT;
|
nuclear@0
|
377 int smf_track_add_eot_seconds(smf_track_t *track, double seconds) WARN_UNUSED_RESULT;
|
nuclear@0
|
378 void smf_event_remove_from_track(smf_event_t *event);
|
nuclear@0
|
379
|
nuclear@0
|
380 /* Routines for manipulating smf_event_t. */
|
nuclear@0
|
381 smf_event_t *smf_event_new(void) WARN_UNUSED_RESULT;
|
nuclear@0
|
382 smf_event_t *smf_event_new_from_pointer(void *midi_data, int len) WARN_UNUSED_RESULT;
|
nuclear@0
|
383 smf_event_t *smf_event_new_from_bytes(int first_byte, int second_byte, int third_byte) WARN_UNUSED_RESULT;
|
nuclear@0
|
384 smf_event_t *smf_event_new_textual(int type, const char *text);
|
nuclear@0
|
385 void smf_event_delete(smf_event_t *event);
|
nuclear@0
|
386
|
nuclear@0
|
387 int smf_event_is_valid(const smf_event_t *event) WARN_UNUSED_RESULT;
|
nuclear@0
|
388 int smf_event_is_metadata(const smf_event_t *event) WARN_UNUSED_RESULT;
|
nuclear@0
|
389 int smf_event_is_system_realtime(const smf_event_t *event) WARN_UNUSED_RESULT;
|
nuclear@0
|
390 int smf_event_is_system_common(const smf_event_t *event) WARN_UNUSED_RESULT;
|
nuclear@0
|
391 int smf_event_is_sysex(const smf_event_t *event) WARN_UNUSED_RESULT;
|
nuclear@0
|
392 int smf_event_is_eot(const smf_event_t *event) WARN_UNUSED_RESULT;
|
nuclear@0
|
393 int smf_event_is_textual(const smf_event_t *event) WARN_UNUSED_RESULT;
|
nuclear@0
|
394 char *smf_event_decode(const smf_event_t *event) WARN_UNUSED_RESULT;
|
nuclear@0
|
395 char *smf_event_extract_text(const smf_event_t *event) WARN_UNUSED_RESULT;
|
nuclear@0
|
396
|
nuclear@0
|
397 /* Routines for loading SMF files. */
|
nuclear@0
|
398 smf_t *smf_load(const char *file_name) WARN_UNUSED_RESULT;
|
nuclear@0
|
399 smf_t *smf_load_from_memory(const void *buffer, const int buffer_length) WARN_UNUSED_RESULT;
|
nuclear@0
|
400
|
nuclear@0
|
401 /* Routine for writing SMF files. */
|
nuclear@0
|
402 int smf_save(smf_t *smf, const char *file_name) WARN_UNUSED_RESULT;
|
nuclear@0
|
403
|
nuclear@0
|
404 /* Routines for manipulating smf_tempo_t. */
|
nuclear@0
|
405 smf_tempo_t *smf_get_tempo_by_pulses(const smf_t *smf, int pulses) WARN_UNUSED_RESULT;
|
nuclear@0
|
406 smf_tempo_t *smf_get_tempo_by_seconds(const smf_t *smf, double seconds) WARN_UNUSED_RESULT;
|
nuclear@0
|
407 smf_tempo_t *smf_get_tempo_by_number(const smf_t *smf, int number) WARN_UNUSED_RESULT;
|
nuclear@0
|
408 smf_tempo_t *smf_get_last_tempo(const smf_t *smf) WARN_UNUSED_RESULT;
|
nuclear@0
|
409
|
nuclear@0
|
410 const char *smf_get_version(void) WARN_UNUSED_RESULT;
|
nuclear@0
|
411
|
nuclear@0
|
412 #ifdef __cplusplus
|
nuclear@0
|
413 }
|
nuclear@0
|
414 #endif
|
nuclear@0
|
415
|
nuclear@0
|
416 #endif /* SMF_H */
|
nuclear@0
|
417
|