smflite
diff src/smf.c @ 0:4264abea8b06
smf-lite initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 26 Jan 2012 11:25:11 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/smf.c Thu Jan 26 11:25:11 2012 +0200 1.3 @@ -0,0 +1,1116 @@ 1.4 +/*- 1.5 + * Copyright (c) 2007, 2008 Edward Tomasz NapieraĆa <trasz@FreeBSD.org> 1.6 + * All rights reserved. 1.7 + * 1.8 + * Redistribution and use in source and binary forms, with or without 1.9 + * modification, are permitted provided that the following conditions 1.10 + * are met: 1.11 + * 1. Redistributions of source code must retain the above copyright 1.12 + * notice, this list of conditions and the following disclaimer. 1.13 + * 2. Redistributions in binary form must reproduce the above copyright 1.14 + * notice, this list of conditions and the following disclaimer in the 1.15 + * documentation and/or other materials provided with the distribution. 1.16 + * 1.17 + * ALTHOUGH THIS SOFTWARE IS MADE OF WIN AND SCIENCE, IT IS PROVIDED BY THE 1.18 + * AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 1.19 + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 1.20 + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 1.21 + * THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.22 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 1.23 + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 1.24 + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 1.25 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 1.26 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 1.27 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.28 + * 1.29 + */ 1.30 + 1.31 +/** 1.32 + * \file 1.33 + * 1.34 + * Various functions. 1.35 + * 1.36 + */ 1.37 + 1.38 +/* Reference: http://www.borg.com/~jglatt/tech/midifile.htm */ 1.39 + 1.40 +#include <stdlib.h> 1.41 +#include <string.h> 1.42 +#include <assert.h> 1.43 +#include <math.h> 1.44 +#include <errno.h> 1.45 +#ifdef __MINGW32__ 1.46 +#include <windows.h> 1.47 +#else /* ! __MINGW32__ */ 1.48 +#include <arpa/inet.h> 1.49 +#endif /* ! __MINGW32__ */ 1.50 +#include "smf.h" 1.51 +#include "smf_private.h" 1.52 + 1.53 +/** 1.54 + * Allocates new smf_t structure. 1.55 + * \return pointer to smf_t or NULL. 1.56 + */ 1.57 +smf_t * 1.58 +smf_new(void) 1.59 +{ 1.60 + int cantfail; 1.61 + 1.62 + smf_t *smf = malloc(sizeof(smf_t)); 1.63 + if (smf == NULL) { 1.64 + fg_critical("Cannot allocate smf_t structure: %s", strerror(errno)); 1.65 + return (NULL); 1.66 + } 1.67 + 1.68 + memset(smf, 0, sizeof(smf_t)); 1.69 + 1.70 + smf->tracks_array = fg_ptr_array_new(); 1.71 + assert(smf->tracks_array); 1.72 + 1.73 + smf->tempo_array = fg_ptr_array_new(); 1.74 + assert(smf->tempo_array); 1.75 + 1.76 + cantfail = smf_set_ppqn(smf, 120); 1.77 + assert(!cantfail); 1.78 + 1.79 + cantfail = smf_set_format(smf, 0); 1.80 + assert(!cantfail); 1.81 + 1.82 + smf_init_tempo(smf); 1.83 + 1.84 + return (smf); 1.85 +} 1.86 + 1.87 +/** 1.88 + * Frees smf and all it's descendant structures. 1.89 + */ 1.90 +void 1.91 +smf_delete(smf_t *smf) 1.92 +{ 1.93 + /* Remove all the tracks, from last to first. */ 1.94 + while (smf->tracks_array->len > 0) 1.95 + smf_track_delete(fg_ptr_array_index(smf->tracks_array, smf->tracks_array->len - 1)); 1.96 + 1.97 + smf_fini_tempo(smf); 1.98 + 1.99 + assert(smf->tracks_array->len == 0); 1.100 + assert(smf->number_of_tracks == 0); 1.101 + fg_ptr_array_free(smf->tracks_array, TRUE); 1.102 + fg_ptr_array_free(smf->tempo_array, TRUE); 1.103 + 1.104 + memset(smf, 0, sizeof(smf_t)); 1.105 + free(smf); 1.106 +} 1.107 + 1.108 +/** 1.109 + * Allocates new smf_track_t structure. 1.110 + * \return pointer to smf_track_t or NULL. 1.111 + */ 1.112 +smf_track_t * 1.113 +smf_track_new(void) 1.114 +{ 1.115 + smf_track_t *track = malloc(sizeof(smf_track_t)); 1.116 + if (track == NULL) { 1.117 + fg_critical("Cannot allocate smf_track_t structure: %s", strerror(errno)); 1.118 + return (NULL); 1.119 + } 1.120 + 1.121 + memset(track, 0, sizeof(smf_track_t)); 1.122 + track->next_event_number = -1; 1.123 + 1.124 + track->events_array = fg_ptr_array_new(); 1.125 + assert(track->events_array); 1.126 + 1.127 + return (track); 1.128 +} 1.129 + 1.130 +/** 1.131 + * Detaches track from its smf and frees it. 1.132 + */ 1.133 +void 1.134 +smf_track_delete(smf_track_t *track) 1.135 +{ 1.136 + assert(track); 1.137 + assert(track->events_array); 1.138 + 1.139 + /* Remove all the events, from last to first. */ 1.140 + while (track->events_array->len > 0) 1.141 + smf_event_delete(fg_ptr_array_index(track->events_array, track->events_array->len - 1)); 1.142 + 1.143 + if (track->smf) 1.144 + smf_track_remove_from_smf(track); 1.145 + 1.146 + assert(track->events_array->len == 0); 1.147 + assert(track->number_of_events == 0); 1.148 + fg_ptr_array_free(track->events_array, TRUE); 1.149 + 1.150 + memset(track, 0, sizeof(smf_track_t)); 1.151 + free(track); 1.152 +} 1.153 + 1.154 + 1.155 +/** 1.156 + * Appends smf_track_t to smf. 1.157 + */ 1.158 +void 1.159 +smf_add_track(smf_t *smf, smf_track_t *track) 1.160 +{ 1.161 + int cantfail; 1.162 + 1.163 + assert(track->smf == NULL); 1.164 + 1.165 + track->smf = smf; 1.166 + fg_ptr_array_add(smf->tracks_array, track); 1.167 + 1.168 + smf->number_of_tracks++; 1.169 + track->track_number = smf->number_of_tracks; 1.170 + 1.171 + if (smf->number_of_tracks > 1) { 1.172 + cantfail = smf_set_format(smf, 1); 1.173 + assert(!cantfail); 1.174 + } 1.175 +} 1.176 + 1.177 +/** 1.178 + * Detaches track from the smf. 1.179 + */ 1.180 +void 1.181 +smf_track_remove_from_smf(smf_track_t *track) 1.182 +{ 1.183 + int i, j; 1.184 + smf_track_t *tmp; 1.185 + smf_event_t *ev; 1.186 + 1.187 + assert(track->smf != NULL); 1.188 + 1.189 + track->smf->number_of_tracks--; 1.190 + 1.191 + assert(track->smf->tracks_array); 1.192 + fg_ptr_array_remove(track->smf->tracks_array, track); 1.193 + 1.194 + /* Renumber the rest of the tracks, so they are consecutively numbered. */ 1.195 + for (i = track->track_number; i <= track->smf->number_of_tracks; i++) { 1.196 + tmp = smf_get_track_by_number(track->smf, i); 1.197 + tmp->track_number = i; 1.198 + 1.199 + /* 1.200 + * Events have track numbers too. I guess this wasn't a wise 1.201 + * decision. ;-/ 1.202 + */ 1.203 + for (j = 1; j <= tmp->number_of_events; j++) { 1.204 + ev = smf_track_get_event_by_number(tmp, j); 1.205 + ev->track_number = i; 1.206 + } 1.207 + } 1.208 + 1.209 + track->track_number = -1; 1.210 + track->smf = NULL; 1.211 +} 1.212 + 1.213 +/** 1.214 + * Allocates new smf_event_t structure. The caller is responsible for allocating 1.215 + * event->midi_buffer, filling it with MIDI data and setting event->midi_buffer_length properly. 1.216 + * Note that event->midi_buffer will be freed by smf_event_delete. 1.217 + * \return pointer to smf_event_t or NULL. 1.218 + */ 1.219 +smf_event_t * 1.220 +smf_event_new(void) 1.221 +{ 1.222 + smf_event_t *event = malloc(sizeof(smf_event_t)); 1.223 + if (event == NULL) { 1.224 + fg_critical("Cannot allocate smf_event_t structure: %s", strerror(errno)); 1.225 + return (NULL); 1.226 + } 1.227 + 1.228 + memset(event, 0, sizeof(smf_event_t)); 1.229 + 1.230 + event->delta_time_pulses = -1; 1.231 + event->time_pulses = -1; 1.232 + event->time_seconds = -1.0; 1.233 + event->track_number = -1; 1.234 + 1.235 + return (event); 1.236 +} 1.237 + 1.238 +/** 1.239 + * Allocates an smf_event_t structure and fills it with "len" bytes copied 1.240 + * from "midi_data". 1.241 + * \param midi_data Pointer to MIDI data. It sill be copied to the newly allocated event->midi_buffer. 1.242 + * \param len Length of the buffer. It must be proper MIDI event length, e.g. 3 for Note On event. 1.243 + * \return Event containing MIDI data or NULL. 1.244 + */ 1.245 +smf_event_t * 1.246 +smf_event_new_from_pointer(void *midi_data, int len) 1.247 +{ 1.248 + smf_event_t *event; 1.249 + 1.250 + event = smf_event_new(); 1.251 + if (event == NULL) 1.252 + return (NULL); 1.253 + 1.254 + event->midi_buffer_length = len; 1.255 + event->midi_buffer = malloc(event->midi_buffer_length); 1.256 + if (event->midi_buffer == NULL) { 1.257 + fg_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno)); 1.258 + smf_event_delete(event); 1.259 + 1.260 + return (NULL); 1.261 + } 1.262 + 1.263 + memcpy(event->midi_buffer, midi_data, len); 1.264 + 1.265 + return (event); 1.266 +} 1.267 + 1.268 +/** 1.269 + * Allocates an smf_event_t structure and fills it with at most three bytes of data. 1.270 + * For example, if you need to create Note On event, do something like this: 1.271 + * 1.272 + * smf_event_new_from_bytes(0x90, 0x3C, 0x7f); 1.273 + * 1.274 + * To create event for MIDI message that is shorter than three bytes, do something 1.275 + * like this: 1.276 + * 1.277 + * smf_event_new_from_bytes(0xC0, 0x42, -1); 1.278 + * 1.279 + * \param first_byte First byte of MIDI message. Must be valid status byte. 1.280 + * \param second_byte Second byte of MIDI message or -1, if message is one byte long. 1.281 + * \param third_byte Third byte of MIDI message or -1, if message is two bytes long. 1.282 + * \return Event containing MIDI data or NULL. 1.283 + */ 1.284 +smf_event_t * 1.285 +smf_event_new_from_bytes(int first_byte, int second_byte, int third_byte) 1.286 +{ 1.287 + int len; 1.288 + 1.289 + smf_event_t *event; 1.290 + 1.291 + event = smf_event_new(); 1.292 + if (event == NULL) 1.293 + return (NULL); 1.294 + 1.295 + if (first_byte < 0) { 1.296 + fg_critical("First byte of MIDI message cannot be < 0"); 1.297 + smf_event_delete(event); 1.298 + 1.299 + return (NULL); 1.300 + } 1.301 + 1.302 + if (first_byte > 255) { 1.303 + fg_critical("smf_event_new_from_bytes: first byte is %d, which is larger than 255.", first_byte); 1.304 + return (NULL); 1.305 + } 1.306 + 1.307 + if (!is_status_byte(first_byte)) { 1.308 + fg_critical("smf_event_new_from_bytes: first byte is not a valid status byte."); 1.309 + return (NULL); 1.310 + } 1.311 + 1.312 + 1.313 + if (second_byte < 0) 1.314 + len = 1; 1.315 + else if (third_byte < 0) 1.316 + len = 2; 1.317 + else 1.318 + len = 3; 1.319 + 1.320 + if (len > 1) { 1.321 + if (second_byte > 255) { 1.322 + fg_critical("smf_event_new_from_bytes: second byte is %d, which is larger than 255.", second_byte); 1.323 + return (NULL); 1.324 + } 1.325 + 1.326 + if (is_status_byte(second_byte)) { 1.327 + fg_critical("smf_event_new_from_bytes: second byte cannot be a status byte."); 1.328 + return (NULL); 1.329 + } 1.330 + } 1.331 + 1.332 + if (len > 2) { 1.333 + if (third_byte > 255) { 1.334 + fg_critical("smf_event_new_from_bytes: third byte is %d, which is larger than 255.", third_byte); 1.335 + return (NULL); 1.336 + } 1.337 + 1.338 + if (is_status_byte(third_byte)) { 1.339 + fg_critical("smf_event_new_from_bytes: third byte cannot be a status byte."); 1.340 + return (NULL); 1.341 + } 1.342 + } 1.343 + 1.344 + event->midi_buffer_length = len; 1.345 + event->midi_buffer = malloc(event->midi_buffer_length); 1.346 + if (event->midi_buffer == NULL) { 1.347 + fg_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno)); 1.348 + smf_event_delete(event); 1.349 + 1.350 + return (NULL); 1.351 + } 1.352 + 1.353 + event->midi_buffer[0] = first_byte; 1.354 + if (len > 1) 1.355 + event->midi_buffer[1] = second_byte; 1.356 + if (len > 2) 1.357 + event->midi_buffer[2] = third_byte; 1.358 + 1.359 + return (event); 1.360 +} 1.361 + 1.362 +/** 1.363 + * Detaches event from its track and frees it. 1.364 + */ 1.365 +void 1.366 +smf_event_delete(smf_event_t *event) 1.367 +{ 1.368 + if (event->track != NULL) 1.369 + smf_event_remove_from_track(event); 1.370 + 1.371 + if (event->midi_buffer != NULL) { 1.372 + memset(event->midi_buffer, 0, event->midi_buffer_length); 1.373 + free(event->midi_buffer); 1.374 + } 1.375 + 1.376 + memset(event, 0, sizeof(smf_event_t)); 1.377 + free(event); 1.378 +} 1.379 + 1.380 +/** 1.381 + * Used for sorting track->events_array. 1.382 + */ 1.383 +static gint 1.384 +events_array_compare_function(gconstpointer aa, gconstpointer bb) 1.385 +{ 1.386 + smf_event_t *a, *b; 1.387 + 1.388 + /* "The comparison function for fg_ptr_array_sort() doesn't take the pointers 1.389 + from the array as arguments, it takes pointers to the pointers in the array." */ 1.390 + a = (smf_event_t *)*(gpointer *)aa; 1.391 + b = (smf_event_t *)*(gpointer *)bb; 1.392 + 1.393 + if (a->time_pulses < b->time_pulses) 1.394 + return (-1); 1.395 + 1.396 + if (a->time_pulses > b->time_pulses) 1.397 + return (1); 1.398 + 1.399 + /* 1.400 + * We need to preserve original order, otherwise things will break 1.401 + * when there are several events with the same ->time_pulses. 1.402 + * XXX: This is an ugly hack; we should remove sorting altogether. 1.403 + */ 1.404 + 1.405 + if (a->event_number < b->event_number) 1.406 + return (-1); 1.407 + 1.408 + if (a->event_number > b->event_number) 1.409 + return (1); 1.410 + 1.411 + return (0); 1.412 +} 1.413 + 1.414 +/* 1.415 + * An assumption here is that if there is an EOT event, it will be at the end of the track. 1.416 + */ 1.417 +static void 1.418 +remove_eot_if_before_pulses(smf_track_t *track, int pulses) 1.419 +{ 1.420 + smf_event_t *event; 1.421 + 1.422 + event = smf_track_get_last_event(track); 1.423 + 1.424 + if (event == NULL) 1.425 + return; 1.426 + 1.427 + if (!smf_event_is_eot(event)) 1.428 + return; 1.429 + 1.430 + if (event->time_pulses > pulses) 1.431 + return; 1.432 + 1.433 + smf_event_remove_from_track(event); 1.434 +} 1.435 + 1.436 +/** 1.437 + * Adds the event to the track and computes ->delta_pulses. Note that it is faster 1.438 + * to append events to the end of the track than to insert them in the middle. 1.439 + * Usually you want to use smf_track_add_event_seconds or smf_track_add_event_pulses 1.440 + * instead of this one. Event needs to have ->time_pulses and ->time_seconds already set. 1.441 + * If you try to add event after an EOT, EOT event will be automatically deleted. 1.442 + */ 1.443 +void 1.444 +smf_track_add_event(smf_track_t *track, smf_event_t *event) 1.445 +{ 1.446 + int i, last_pulses = 0; 1.447 + 1.448 + assert(track->smf != NULL); 1.449 + assert(event->track == NULL); 1.450 + assert(event->delta_time_pulses == -1); 1.451 + assert(event->time_pulses >= 0); 1.452 + assert(event->time_seconds >= 0.0); 1.453 + 1.454 + remove_eot_if_before_pulses(track, event->time_pulses); 1.455 + 1.456 + event->track = track; 1.457 + event->track_number = track->track_number; 1.458 + 1.459 + if (track->number_of_events == 0) { 1.460 + assert(track->next_event_number == -1); 1.461 + track->next_event_number = 1; 1.462 + } 1.463 + 1.464 + if (track->number_of_events > 0) 1.465 + last_pulses = smf_track_get_last_event(track)->time_pulses; 1.466 + 1.467 + track->number_of_events++; 1.468 + 1.469 + /* Are we just appending element at the end of the track? */ 1.470 + if (last_pulses <= event->time_pulses) { 1.471 + event->delta_time_pulses = event->time_pulses - last_pulses; 1.472 + assert(event->delta_time_pulses >= 0); 1.473 + fg_ptr_array_add(track->events_array, event); 1.474 + event->event_number = track->number_of_events; 1.475 + 1.476 + /* We need to insert in the middle of the track. XXX: This is slow. */ 1.477 + } else { 1.478 + /* Append, then sort according to ->time_pulses. */ 1.479 + fg_ptr_array_add(track->events_array, event); 1.480 + fg_ptr_array_sort(track->events_array, events_array_compare_function); 1.481 + 1.482 + /* Renumber entries and fix their ->delta_pulses. */ 1.483 + for (i = 1; i <= track->number_of_events; i++) { 1.484 + smf_event_t *tmp = smf_track_get_event_by_number(track, i); 1.485 + tmp->event_number = i; 1.486 + 1.487 + if (tmp->delta_time_pulses != -1) 1.488 + continue; 1.489 + 1.490 + if (i == 1) { 1.491 + tmp->delta_time_pulses = tmp->time_pulses; 1.492 + } else { 1.493 + tmp->delta_time_pulses = tmp->time_pulses - 1.494 + smf_track_get_event_by_number(track, i - 1)->time_pulses; 1.495 + assert(tmp->delta_time_pulses >= 0); 1.496 + } 1.497 + } 1.498 + 1.499 + /* Adjust ->delta_time_pulses of the next event. */ 1.500 + if (event->event_number < track->number_of_events) { 1.501 + smf_event_t *next_event = smf_track_get_event_by_number(track, event->event_number + 1); 1.502 + assert(next_event); 1.503 + assert(next_event->time_pulses >= event->time_pulses); 1.504 + next_event->delta_time_pulses -= event->delta_time_pulses; 1.505 + assert(next_event->delta_time_pulses >= 0); 1.506 + } 1.507 + } 1.508 + 1.509 + if (smf_event_is_tempo_change_or_time_signature(event)) { 1.510 + if (smf_event_is_last(event)) 1.511 + maybe_add_to_tempo_map(event); 1.512 + else 1.513 + smf_create_tempo_map_and_compute_seconds(event->track->smf); 1.514 + } 1.515 +} 1.516 + 1.517 +/** 1.518 + * Add End Of Track metaevent. Using it is optional, libsmf will automatically 1.519 + * add EOT to the tracks during smf_save, with delta_pulses 0. If you try to add EOT 1.520 + * in the middle of the track, it will fail and nonzero value will be returned. 1.521 + * If you try to add EOT after another EOT event, it will be added, but the existing 1.522 + * EOT event will be removed. 1.523 + * 1.524 + * \return 0 if everything went ok, nonzero otherwise. 1.525 + */ 1.526 +int 1.527 +smf_track_add_eot_delta_pulses(smf_track_t *track, int delta) 1.528 +{ 1.529 + smf_event_t *event; 1.530 + 1.531 + event = smf_event_new_from_bytes(0xFF, 0x2F, 0x00); 1.532 + if (event == NULL) 1.533 + return (-1); 1.534 + 1.535 + smf_track_add_event_delta_pulses(track, event, delta); 1.536 + 1.537 + return (0); 1.538 +} 1.539 + 1.540 +int 1.541 +smf_track_add_eot_pulses(smf_track_t *track, int pulses) 1.542 +{ 1.543 + smf_event_t *event, *last_event; 1.544 + 1.545 + last_event = smf_track_get_last_event(track); 1.546 + if (last_event != NULL) { 1.547 + if (last_event->time_pulses > pulses) 1.548 + return (-2); 1.549 + } 1.550 + 1.551 + event = smf_event_new_from_bytes(0xFF, 0x2F, 0x00); 1.552 + if (event == NULL) 1.553 + return (-3); 1.554 + 1.555 + smf_track_add_event_pulses(track, event, pulses); 1.556 + 1.557 + return (0); 1.558 +} 1.559 + 1.560 +int 1.561 +smf_track_add_eot_seconds(smf_track_t *track, double seconds) 1.562 +{ 1.563 + smf_event_t *event, *last_event; 1.564 + 1.565 + last_event = smf_track_get_last_event(track); 1.566 + if (last_event != NULL) { 1.567 + if (last_event->time_seconds > seconds) 1.568 + return (-2); 1.569 + } 1.570 + 1.571 + event = smf_event_new_from_bytes(0xFF, 0x2F, 0x00); 1.572 + if (event == NULL) 1.573 + return (-1); 1.574 + 1.575 + smf_track_add_event_seconds(track, event, seconds); 1.576 + 1.577 + return (0); 1.578 +} 1.579 + 1.580 +/** 1.581 + * Detaches event from its track. 1.582 + */ 1.583 +void 1.584 +smf_event_remove_from_track(smf_event_t *event) 1.585 +{ 1.586 + int i, was_last; 1.587 + smf_event_t *tmp; 1.588 + smf_track_t *track; 1.589 + 1.590 + assert(event->track != NULL); 1.591 + assert(event->track->smf != NULL); 1.592 + 1.593 + track = event->track; 1.594 + was_last = smf_event_is_last(event); 1.595 + 1.596 + /* Adjust ->delta_time_pulses of the next event. */ 1.597 + if (event->event_number < track->number_of_events) { 1.598 + tmp = smf_track_get_event_by_number(track, event->event_number + 1); 1.599 + assert(tmp); 1.600 + tmp->delta_time_pulses += event->delta_time_pulses; 1.601 + } 1.602 + 1.603 + track->number_of_events--; 1.604 + fg_ptr_array_remove(track->events_array, event); 1.605 + 1.606 + if (track->number_of_events == 0) 1.607 + track->next_event_number = -1; 1.608 + 1.609 + /* Renumber the rest of the events, so they are consecutively numbered. */ 1.610 + for (i = event->event_number; i <= track->number_of_events; i++) { 1.611 + tmp = smf_track_get_event_by_number(track, i); 1.612 + tmp->event_number = i; 1.613 + } 1.614 + 1.615 + if (smf_event_is_tempo_change_or_time_signature(event)) { 1.616 + /* XXX: This will cause problems, when there is more than one Tempo Change event at a given time. */ 1.617 + if (was_last) 1.618 + remove_last_tempo_with_pulses(event->track->smf, event->time_pulses); 1.619 + else 1.620 + smf_create_tempo_map_and_compute_seconds(track->smf); 1.621 + } 1.622 + 1.623 + event->track = NULL; 1.624 + event->event_number = -1; 1.625 + event->delta_time_pulses = -1; 1.626 + event->time_pulses = -1; 1.627 + event->time_seconds = -1.0; 1.628 +} 1.629 + 1.630 +/** 1.631 + * \return Nonzero if event is Tempo Change or Time Signature metaevent. 1.632 + */ 1.633 +int 1.634 +smf_event_is_tempo_change_or_time_signature(const smf_event_t *event) 1.635 +{ 1.636 + if (!smf_event_is_metadata(event)) 1.637 + return (0); 1.638 + 1.639 + assert(event->midi_buffer_length >= 2); 1.640 + 1.641 + if (event->midi_buffer[1] == 0x51 || event->midi_buffer[1] == 0x58) 1.642 + return (1); 1.643 + 1.644 + return (0); 1.645 +} 1.646 + 1.647 +/** 1.648 + * Sets "Format" field of MThd header to the specified value. Note that you 1.649 + * don't really need to use this, as libsmf will automatically change format 1.650 + * from 0 to 1 when you add the second track. 1.651 + * \param smf SMF. 1.652 + * \param format 0 for one track per file, 1 for several tracks per file. 1.653 + */ 1.654 +int 1.655 +smf_set_format(smf_t *smf, int format) 1.656 +{ 1.657 + assert(format == 0 || format == 1); 1.658 + 1.659 + if (smf->number_of_tracks > 1 && format == 0) { 1.660 + fg_critical("There is more than one track, cannot set format to 0."); 1.661 + return (-1); 1.662 + } 1.663 + 1.664 + smf->format = format; 1.665 + 1.666 + return (0); 1.667 +} 1.668 + 1.669 +/** 1.670 + * Sets the PPQN ("Division") field of MThd header. This is mandatory, you 1.671 + * should call it right after smf_new. Note that changing PPQN will change time_seconds 1.672 + * of all the events. 1.673 + * \param smf SMF. 1.674 + * \param ppqn New PPQN. 1.675 + */ 1.676 +int 1.677 +smf_set_ppqn(smf_t *smf, int ppqn) 1.678 +{ 1.679 + assert(ppqn > 0); 1.680 + 1.681 + smf->ppqn = ppqn; 1.682 + 1.683 + return (0); 1.684 +} 1.685 + 1.686 +/** 1.687 + * Returns next event from the track given and advances next event counter. 1.688 + * Do not depend on End Of Track event being the last event on the track - it 1.689 + * is possible that the track will not end with EOT if you haven't added it 1.690 + * yet. EOTs are added automatically during smf_save(). 1.691 + * 1.692 + * \return Event or NULL, if there are no more events left in this track. 1.693 + */ 1.694 +smf_event_t * 1.695 +smf_track_get_next_event(smf_track_t *track) 1.696 +{ 1.697 + smf_event_t *event, *next_event; 1.698 + 1.699 + /* End of track? */ 1.700 + if (track->next_event_number == -1) 1.701 + return (NULL); 1.702 + 1.703 + assert(track->next_event_number >= 1); 1.704 + assert(track->number_of_events > 0); 1.705 + 1.706 + event = smf_track_get_event_by_number(track, track->next_event_number); 1.707 + 1.708 + assert(event != NULL); 1.709 + 1.710 + /* Is this the last event in the track? */ 1.711 + if (track->next_event_number < track->number_of_events) { 1.712 + next_event = smf_track_get_event_by_number(track, track->next_event_number + 1); 1.713 + assert(next_event); 1.714 + 1.715 + track->time_of_next_event = next_event->time_pulses; 1.716 + track->next_event_number++; 1.717 + } else { 1.718 + track->next_event_number = -1; 1.719 + } 1.720 + 1.721 + return (event); 1.722 +} 1.723 + 1.724 +/** 1.725 + * Returns next event from the track given. Does not change next event counter, 1.726 + * so repeatedly calling this routine will return the same event. 1.727 + * \return Event or NULL, if there are no more events left in this track. 1.728 + */ 1.729 +static smf_event_t * 1.730 +smf_peek_next_event_from_track(smf_track_t *track) 1.731 +{ 1.732 + smf_event_t *event; 1.733 + 1.734 + /* End of track? */ 1.735 + if (track->next_event_number == -1) 1.736 + return (NULL); 1.737 + 1.738 + assert(track->next_event_number >= 1); 1.739 + assert(track->events_array->len != 0); 1.740 + 1.741 + event = smf_track_get_event_by_number(track, track->next_event_number); 1.742 + 1.743 + return (event); 1.744 +} 1.745 + 1.746 +/** 1.747 + * \return Track with a given number or NULL, if there is no such track. 1.748 + * Tracks are numbered consecutively starting from one. 1.749 + */ 1.750 +smf_track_t * 1.751 +smf_get_track_by_number(const smf_t *smf, int track_number) 1.752 +{ 1.753 + smf_track_t *track; 1.754 + 1.755 + assert(track_number >= 1); 1.756 + 1.757 + if (track_number > smf->number_of_tracks) 1.758 + return (NULL); 1.759 + 1.760 + track = (smf_track_t *)fg_ptr_array_index(smf->tracks_array, track_number - 1); 1.761 + 1.762 + assert(track); 1.763 + 1.764 + return (track); 1.765 +} 1.766 + 1.767 +/** 1.768 + * \return Event with a given number or NULL, if there is no such event. 1.769 + * Events are numbered consecutively starting from one. 1.770 + */ 1.771 +smf_event_t * 1.772 +smf_track_get_event_by_number(const smf_track_t *track, int event_number) 1.773 +{ 1.774 + smf_event_t *event; 1.775 + 1.776 + assert(event_number >= 1); 1.777 + 1.778 + if (event_number > track->number_of_events) 1.779 + return (NULL); 1.780 + 1.781 + event = fg_ptr_array_index(track->events_array, event_number - 1); 1.782 + 1.783 + assert(event); 1.784 + 1.785 + return (event); 1.786 +} 1.787 + 1.788 +/** 1.789 + * \return Last event on the track or NULL, if track is empty. 1.790 + */ 1.791 +smf_event_t * 1.792 +smf_track_get_last_event(const smf_track_t *track) 1.793 +{ 1.794 + smf_event_t *event; 1.795 + 1.796 + if (track->number_of_events == 0) 1.797 + return (NULL); 1.798 + 1.799 + event = smf_track_get_event_by_number(track, track->number_of_events); 1.800 + 1.801 + return (event); 1.802 +} 1.803 + 1.804 +/** 1.805 + * Searches for track that contains next event, in time order. In other words, 1.806 + * returns the track that contains event that should be played next. 1.807 + * \return Track with next event or NULL, if there are no events left. 1.808 + */ 1.809 +smf_track_t * 1.810 +smf_find_track_with_next_event(smf_t *smf) 1.811 +{ 1.812 + int i, min_time = 0; 1.813 + smf_track_t *track = NULL, *min_time_track = NULL; 1.814 + 1.815 + /* Find track with event that should be played next. */ 1.816 + for (i = 1; i <= smf->number_of_tracks; i++) { 1.817 + track = smf_get_track_by_number(smf, i); 1.818 + 1.819 + assert(track); 1.820 + 1.821 + /* No more events in this track? */ 1.822 + if (track->next_event_number == -1) 1.823 + continue; 1.824 + 1.825 + if (track->time_of_next_event < min_time || min_time_track == NULL) { 1.826 + min_time = track->time_of_next_event; 1.827 + min_time_track = track; 1.828 + } 1.829 + } 1.830 + 1.831 + return (min_time_track); 1.832 +} 1.833 + 1.834 +/** 1.835 + * \return Next event, in time order, or NULL, if there are none left. 1.836 + */ 1.837 +smf_event_t * 1.838 +smf_get_next_event(smf_t *smf) 1.839 +{ 1.840 + smf_event_t *event; 1.841 + smf_track_t *track = smf_find_track_with_next_event(smf); 1.842 + 1.843 + if (track == NULL) { 1.844 +#if 0 1.845 + g_debug("End of the song."); 1.846 +#endif 1.847 + 1.848 + return (NULL); 1.849 + } 1.850 + 1.851 + event = smf_track_get_next_event(track); 1.852 + 1.853 + assert(event != NULL); 1.854 + 1.855 + event->track->smf->last_seek_position = -1.0; 1.856 + 1.857 + return (event); 1.858 +} 1.859 + 1.860 +/** 1.861 + * Advance the "next event counter". This is functionally the same as calling 1.862 + * smf_get_next_event and ignoring the return value. 1.863 + */ 1.864 +void 1.865 +smf_skip_next_event(smf_t *smf) 1.866 +{ 1.867 + void *notused; 1.868 + 1.869 + notused = smf_get_next_event(smf); 1.870 +} 1.871 + 1.872 +/** 1.873 + * \return Next event, in time order, or NULL, if there are none left. Does 1.874 + * not advance position in song. 1.875 + */ 1.876 +smf_event_t * 1.877 +smf_peek_next_event(smf_t *smf) 1.878 +{ 1.879 + smf_event_t *event; 1.880 + smf_track_t *track = smf_find_track_with_next_event(smf); 1.881 + 1.882 + if (track == NULL) { 1.883 +#if 0 1.884 + g_debug("End of the song."); 1.885 +#endif 1.886 + 1.887 + return (NULL); 1.888 + } 1.889 + 1.890 + event = smf_peek_next_event_from_track(track); 1.891 + 1.892 + assert(event != NULL); 1.893 + 1.894 + return (event); 1.895 +} 1.896 + 1.897 +/** 1.898 + * Rewinds the SMF. What that means is, after calling this routine, smf_get_next_event 1.899 + * will return first event in the song. 1.900 + */ 1.901 +void 1.902 +smf_rewind(smf_t *smf) 1.903 +{ 1.904 + int i; 1.905 + smf_track_t *track = NULL; 1.906 + smf_event_t *event; 1.907 + 1.908 + assert(smf); 1.909 + 1.910 + smf->last_seek_position = 0.0; 1.911 + 1.912 + for (i = 1; i <= smf->number_of_tracks; i++) { 1.913 + track = smf_get_track_by_number(smf, i); 1.914 + 1.915 + assert(track != NULL); 1.916 + 1.917 + if (track->number_of_events > 0) { 1.918 + track->next_event_number = 1; 1.919 + event = smf_peek_next_event_from_track(track); 1.920 + assert(event); 1.921 + track->time_of_next_event = event->time_pulses; 1.922 + } else { 1.923 + track->next_event_number = -1; 1.924 + track->time_of_next_event = 0; 1.925 +#if 0 1.926 + g_warning("Warning: empty track."); 1.927 +#endif 1.928 + } 1.929 + } 1.930 +} 1.931 + 1.932 +/** 1.933 + * Seeks the SMF to the given event. After calling this routine, smf_get_next_event 1.934 + * will return the event that was the second argument of this call. 1.935 + */ 1.936 +int 1.937 +smf_seek_to_event(smf_t *smf, const smf_event_t *target) 1.938 +{ 1.939 + smf_event_t *event; 1.940 + 1.941 + smf_rewind(smf); 1.942 + 1.943 +#if 0 1.944 + g_debug("Seeking to event %d, track %d.", target->event_number, target->track->track_number); 1.945 +#endif 1.946 + 1.947 + for (;;) { 1.948 + event = smf_peek_next_event(smf); 1.949 + 1.950 + /* There can't be NULL here, unless "target" is not in this smf. */ 1.951 + assert(event); 1.952 + 1.953 + if (event != target) 1.954 + smf_skip_next_event(smf); 1.955 + else 1.956 + break; 1.957 + } 1.958 + 1.959 + smf->last_seek_position = event->time_seconds; 1.960 + 1.961 + return (0); 1.962 +} 1.963 + 1.964 +/** 1.965 + * Seeks the SMF to the given position. For example, after seeking to 1.0 seconds, 1.966 + * smf_get_next_event will return first event that happens after the first second of song. 1.967 + */ 1.968 +int 1.969 +smf_seek_to_seconds(smf_t *smf, double seconds) 1.970 +{ 1.971 + smf_event_t *event; 1.972 + 1.973 + assert(seconds >= 0.0); 1.974 + 1.975 + if (seconds == smf->last_seek_position) { 1.976 +#if 0 1.977 + g_debug("Avoiding seek to %f seconds.", seconds); 1.978 +#endif 1.979 + return (0); 1.980 + } 1.981 + 1.982 + smf_rewind(smf); 1.983 + 1.984 +#if 0 1.985 + g_debug("Seeking to %f seconds.", seconds); 1.986 +#endif 1.987 + 1.988 + for (;;) { 1.989 + event = smf_peek_next_event(smf); 1.990 + 1.991 + if (event == NULL) { 1.992 + fg_critical("Trying to seek past the end of song."); 1.993 + return (-1); 1.994 + } 1.995 + 1.996 + if (event->time_seconds < seconds) 1.997 + smf_skip_next_event(smf); 1.998 + else 1.999 + break; 1.1000 + } 1.1001 + 1.1002 + smf->last_seek_position = seconds; 1.1003 + 1.1004 + return (0); 1.1005 +} 1.1006 + 1.1007 +/** 1.1008 + * Seeks the SMF to the given position. For example, after seeking to 10 pulses, 1.1009 + * smf_get_next_event will return first event that happens after the first ten pulses. 1.1010 + */ 1.1011 +int 1.1012 +smf_seek_to_pulses(smf_t *smf, int pulses) 1.1013 +{ 1.1014 + smf_event_t *event; 1.1015 + 1.1016 + assert(pulses >= 0); 1.1017 + 1.1018 + smf_rewind(smf); 1.1019 + 1.1020 +#if 0 1.1021 + g_debug("Seeking to %d pulses.", pulses); 1.1022 +#endif 1.1023 + 1.1024 + for (;;) { 1.1025 + event = smf_peek_next_event(smf); 1.1026 + 1.1027 + if (event == NULL) { 1.1028 + fg_critical("Trying to seek past the end of song."); 1.1029 + return (-1); 1.1030 + } 1.1031 + 1.1032 + if (event->time_pulses < pulses) 1.1033 + smf_skip_next_event(smf); 1.1034 + else 1.1035 + break; 1.1036 + } 1.1037 + 1.1038 + smf->last_seek_position = event->time_seconds; 1.1039 + 1.1040 + return (0); 1.1041 +} 1.1042 + 1.1043 +/** 1.1044 + * \return Length of SMF, in pulses. 1.1045 + */ 1.1046 +int 1.1047 +smf_get_length_pulses(const smf_t *smf) 1.1048 +{ 1.1049 + int pulses = 0, i; 1.1050 + 1.1051 + for (i = 1; i <= smf->number_of_tracks; i++) { 1.1052 + smf_track_t *track; 1.1053 + smf_event_t *event; 1.1054 + 1.1055 + track = smf_get_track_by_number(smf, i); 1.1056 + assert(track); 1.1057 + 1.1058 + event = smf_track_get_last_event(track); 1.1059 + /* Empty track? */ 1.1060 + if (event == NULL) 1.1061 + continue; 1.1062 + 1.1063 + if (event->time_pulses > pulses) 1.1064 + pulses = event->time_pulses; 1.1065 + } 1.1066 + 1.1067 + return (pulses); 1.1068 +} 1.1069 + 1.1070 +/** 1.1071 + * \return Length of SMF, in seconds. 1.1072 + */ 1.1073 +double 1.1074 +smf_get_length_seconds(const smf_t *smf) 1.1075 +{ 1.1076 + int i; 1.1077 + double seconds = 0.0; 1.1078 + 1.1079 + for (i = 1; i <= smf->number_of_tracks; i++) { 1.1080 + smf_track_t *track; 1.1081 + smf_event_t *event; 1.1082 + 1.1083 + track = smf_get_track_by_number(smf, i); 1.1084 + assert(track); 1.1085 + 1.1086 + event = smf_track_get_last_event(track); 1.1087 + /* Empty track? */ 1.1088 + if (event == NULL) 1.1089 + continue; 1.1090 + 1.1091 + if (event->time_seconds > seconds) 1.1092 + seconds = event->time_seconds; 1.1093 + } 1.1094 + 1.1095 + return (seconds); 1.1096 +} 1.1097 + 1.1098 +/** 1.1099 + * \return Nonzero, if there are no events in the SMF after this one. 1.1100 + * Note that may be more than one "last event", if they occur at the same time. 1.1101 + */ 1.1102 +int 1.1103 +smf_event_is_last(const smf_event_t *event) 1.1104 +{ 1.1105 + if (smf_get_length_pulses(event->track->smf) <= event->time_pulses) 1.1106 + return (1); 1.1107 + 1.1108 + return (0); 1.1109 +} 1.1110 + 1.1111 +/** 1.1112 + * \return Version of libsmf. 1.1113 + */ 1.1114 +const char * 1.1115 +smf_get_version(void) 1.1116 +{ 1.1117 + return (SMF_VERSION); 1.1118 +} 1.1119 +