libsmf

- Main Page
- Data Structures
- Files

- File List
- Globals

smf.c
Go to the documentation of this file.
1 /*-
2 * Copyright (c) 2007, 2008 Edward Tomasz Napierała <trasz@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * ALTHOUGH THIS SOFTWARE IS MADE OF WIN AND SCIENCE, IT IS PROVIDED BY THE
15 * AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
18 * THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
20 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
21 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 */
27
35 /* Reference: http://www.borg.com/~jglatt/tech/midifile.htm */
36
37 #include <stdlib.h>
38 #include <string.h>
39 #include <assert.h>
40 #include <math.h>
41 #include <errno.h>
42 #ifdef __MINGW32__
43 #include <windows.h>
44 #else /* ! __MINGW32__ */
45 #include <arpa/inet.h>
46 #endif /* ! __MINGW32__ */
47 #include "smf.h"
48 #include "smf_private.h"
49
54 smf_t *
55 smf_new(void)
56 {
57 int cantfail;
58
59 smf_t *smf = malloc(sizeof(smf_t));
60 if (smf == NULL) {
61 g_critical("Cannot allocate smf_t structure: %s", strerror(errno));
62 return (NULL);
63 }
64
65 memset(smf, 0, sizeof(smf_t));
66
67 smf->tracks_array = g_ptr_array_new();
68 assert(smf->tracks_array);
69
70 smf->tempo_array = g_ptr_array_new();
71 assert(smf->tempo_array);
72
73 cantfail = smf_set_ppqn(smf, 120);
74 assert(!cantfail);
75
76 cantfail = smf_set_format(smf, 0);
77 assert(!cantfail);
78
79 smf_init_tempo(smf);
80
81 return (smf);
82 }
83
87 void
88 smf_delete(smf_t *smf)
89 {
90 /* Remove all the tracks, from last to first. */
91 while (smf->tracks_array->len > 0)
92 smf_track_delete(g_ptr_array_index(smf->tracks_array, smf->tracks_array->len - 1));
93
94 smf_fini_tempo(smf);
95
96 assert(smf->tracks_array->len == 0);
97 assert(smf->number_of_tracks == 0);
98 g_ptr_array_free(smf->tracks_array, TRUE);
99 g_ptr_array_free(smf->tempo_array, TRUE);
100
101 memset(smf, 0, sizeof(smf_t));
102 free(smf);
103 }
104
109 smf_track_t *
110 smf_track_new(void)
111 {
112 smf_track_t *track = malloc(sizeof(smf_track_t));
113 if (track == NULL) {
114 g_critical("Cannot allocate smf_track_t structure: %s", strerror(errno));
115 return (NULL);
116 }
117
118 memset(track, 0, sizeof(smf_track_t));
119 track->next_event_number = -1;
120
121 track->events_array = g_ptr_array_new();
122 assert(track->events_array);
123
124 return (track);
125 }
126
130 void
131 smf_track_delete(smf_track_t *track)
132 {
133 assert(track);
134 assert(track->events_array);
135
136 /* Remove all the events, from last to first. */
137 while (track->events_array->len > 0)
138 smf_event_delete(g_ptr_array_index(track->events_array, track->events_array->len - 1));
139
140 if (track->smf)
141 smf_track_remove_from_smf(track);
142
143 assert(track->events_array->len == 0);
144 assert(track->number_of_events == 0);
145 g_ptr_array_free(track->events_array, TRUE);
146
147 memset(track, 0, sizeof(smf_track_t));
148 free(track);
149 }
150
151
155 void
156 smf_add_track(smf_t *smf, smf_track_t *track)
157 {
158 int cantfail;
159
160 assert(track->smf == NULL);
161
162 track->smf = smf;
163 g_ptr_array_add(smf->tracks_array, track);
164
165 smf->number_of_tracks++;
166 track->track_number = smf->number_of_tracks;
167
168 if (smf->number_of_tracks > 1) {
169 cantfail = smf_set_format(smf, 1);
170 assert(!cantfail);
171 }
172 }
173
177 void
178 smf_track_remove_from_smf(smf_track_t *track)
179 {
180 int i, j;
181 smf_track_t *tmp;
182 smf_event_t *ev;
183
184 assert(track->smf != NULL);
185
186 track->smf->number_of_tracks--;
187
188 assert(track->smf->tracks_array);
189 g_ptr_array_remove(track->smf->tracks_array, track);
190
191 /* Renumber the rest of the tracks, so they are consecutively numbered. */
192 for (i = track->track_number; i <= track->smf->number_of_tracks; i++) {
193 tmp = smf_get_track_by_number(track->smf, i);
194 tmp->track_number = i;
195
196 /*
197 * Events have track numbers too. I guess this wasn't a wise
198 * decision. ;-/
199 */
200 for (j = 1; j <= tmp->number_of_events; j++) {
201 ev = smf_track_get_event_by_number(tmp, j);
202 ev->track_number = i;
203 }
204 }
205
206 track->track_number = -1;
207 track->smf = NULL;
208 }
209
216 smf_event_t *
217 smf_event_new(void)
218 {
219 smf_event_t *event = malloc(sizeof(smf_event_t));
220 if (event == NULL) {
221 g_critical("Cannot allocate smf_event_t structure: %s", strerror(errno));
222 return (NULL);
223 }
224
225 memset(event, 0, sizeof(smf_event_t));
226
227 event->delta_time_pulses = -1;
228 event->time_pulses = -1;
229 event->time_seconds = -1.0;
230 event->track_number = -1;
231
232 return (event);
233 }
234
242 smf_event_t *
243 smf_event_new_from_pointer(void *midi_data, int len)
244 {
245 smf_event_t *event;
246
247 event = smf_event_new();
248 if (event == NULL)
249 return (NULL);
250
251 event->midi_buffer_length = len;
252 event->midi_buffer = malloc(event->midi_buffer_length);
253 if (event->midi_buffer == NULL) {
254 g_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno));
255 smf_event_delete(event);
256
257 return (NULL);
258 }
259
260 memcpy(event->midi_buffer, midi_data, len);
261
262 return (event);
263 }
264
281 smf_event_t *
282 smf_event_new_from_bytes(int first_byte, int second_byte, int third_byte)
283 {
284 int len;
285
286 smf_event_t *event;
287
288 event = smf_event_new();
289 if (event == NULL)
290 return (NULL);
291
292 if (first_byte < 0) {
293 g_critical("First byte of MIDI message cannot be < 0");
294 smf_event_delete(event);
295
296 return (NULL);
297 }
298
299 if (first_byte > 255) {
300 g_critical("smf_event_new_from_bytes: first byte is %d, which is larger than 255.", first_byte);
301 return (NULL);
302 }
303
304 if (!is_status_byte(first_byte)) {
305 g_critical("smf_event_new_from_bytes: first byte is not a valid status byte.");
306 return (NULL);
307 }
308
309
310 if (second_byte < 0)
311 len = 1;
312 else if (third_byte < 0)
313 len = 2;
314 else
315 len = 3;
316
317 if (len > 1) {
318 if (second_byte > 255) {
319 g_critical("smf_event_new_from_bytes: second byte is %d, which is larger than 255.", second_byte);
320 return (NULL);
321 }
322
323 if (is_status_byte(second_byte)) {
324 g_critical("smf_event_new_from_bytes: second byte cannot be a status byte.");
325 return (NULL);
326 }
327 }
328
329 if (len > 2) {
330 if (third_byte > 255) {
331 g_critical("smf_event_new_from_bytes: third byte is %d, which is larger than 255.", third_byte);
332 return (NULL);
333 }
334
335 if (is_status_byte(third_byte)) {
336 g_critical("smf_event_new_from_bytes: third byte cannot be a status byte.");
337 return (NULL);
338 }
339 }
340
341 event->midi_buffer_length = len;
342 event->midi_buffer = malloc(event->midi_buffer_length);
343 if (event->midi_buffer == NULL) {
344 g_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno));
345 smf_event_delete(event);
346
347 return (NULL);
348 }
349
350 event->midi_buffer[0] = first_byte;
351 if (len > 1)
352 event->midi_buffer[1] = second_byte;
353 if (len > 2)
354 event->midi_buffer[2] = third_byte;
355
356 return (event);
357 }
358
362 void
363 smf_event_delete(smf_event_t *event)
364 {
365 if (event->track != NULL)
366 smf_event_remove_from_track(event);
367
368 if (event->midi_buffer != NULL) {
369 memset(event->midi_buffer, 0, event->midi_buffer_length);
370 free(event->midi_buffer);
371 }
372
373 memset(event, 0, sizeof(smf_event_t));
374 free(event);
375 }
376
380 static gint
381 events_array_compare_function(gconstpointer aa, gconstpointer bb)
382 {
383 smf_event_t *a, *b;
384
385 /* "The comparison function for g_ptr_array_sort() doesn't take the pointers
386 from the array as arguments, it takes pointers to the pointers in the array." */
387 a = (smf_event_t *)*(gpointer *)aa;
388 b = (smf_event_t *)*(gpointer *)bb;
389
390 if (a->time_pulses < b->time_pulses)
391 return (-1);
392
393 if (a->time_pulses > b->time_pulses)
394 return (1);
395
396 /*
397 * We need to preserve original order, otherwise things will break
398 * when there are several events with the same ->time_pulses.
399 * XXX: This is an ugly hack; we should remove sorting altogether.
400 */
401
402 if (a->event_number < b->event_number)
403 return (-1);
404
405 if (a->event_number > b->event_number)
406 return (1);
407
408 return (0);
409 }
410
411 /*
412 * An assumption here is that if there is an EOT event, it will be at the end of the track.
413 */
414 static void
415 remove_eot_if_before_pulses(smf_track_t *track, int pulses)
416 {
417 smf_event_t *event;
418
419 event = smf_track_get_last_event(track);
420
421 if (event == NULL)
422 return;
423
424 if (!smf_event_is_eot(event))
425 return;
426
427 if (event->time_pulses > pulses)
428 return;
429
430 smf_event_remove_from_track(event);
431 }
432
440 void
441 smf_track_add_event(smf_track_t *track, smf_event_t *event)
442 {
443 int i, last_pulses = 0;
444
445 assert(track->smf != NULL);
446 assert(event->track == NULL);
447 assert(event->delta_time_pulses == -1);
448 assert(event->time_pulses >= 0);
449 assert(event->time_seconds >= 0.0);
450
451 remove_eot_if_before_pulses(track, event->time_pulses);
452
453 event->track = track;
454 event->track_number = track->track_number;
455
456 if (track->number_of_events == 0) {
457 assert(track->next_event_number == -1);
458 track->next_event_number = 1;
459 }
460
461 if (track->number_of_events > 0)
462 last_pulses = smf_track_get_last_event(track)->time_pulses;
463
464 track->number_of_events++;
465
466 /* Are we just appending element at the end of the track? */
467 if (last_pulses <= event->time_pulses) {
468 event->delta_time_pulses = event->time_pulses - last_pulses;
469 assert(event->delta_time_pulses >= 0);
470 g_ptr_array_add(track->events_array, event);
471 event->event_number = track->number_of_events;
472
473 /* We need to insert in the middle of the track. XXX: This is slow. */
474 } else {
475 /* Append, then sort according to ->time_pulses. */
476 g_ptr_array_add(track->events_array, event);
477 g_ptr_array_sort(track->events_array, events_array_compare_function);
478
479 /* Renumber entries and fix their ->delta_pulses. */
480 for (i = 1; i <= track->number_of_events; i++) {
481 smf_event_t *tmp = smf_track_get_event_by_number(track, i);
482 tmp->event_number = i;
483
484 if (tmp->delta_time_pulses != -1)
485 continue;
486
487 if (i == 1) {
488 tmp->delta_time_pulses = tmp->time_pulses;
489 } else {
490 tmp->delta_time_pulses = tmp->time_pulses -
491 smf_track_get_event_by_number(track, i - 1)->time_pulses;
492 assert(tmp->delta_time_pulses >= 0);
493 }
494 }
495
496 /* Adjust ->delta_time_pulses of the next event. */
497 if (event->event_number < track->number_of_events) {
498 smf_event_t *next_event = smf_track_get_event_by_number(track, event->event_number + 1);
499 assert(next_event);
500 assert(next_event->time_pulses >= event->time_pulses);
501 next_event->delta_time_pulses -= event->delta_time_pulses;
502 assert(next_event->delta_time_pulses >= 0);
503 }
504 }
505
506 if (smf_event_is_tempo_change_or_time_signature(event)) {
507 if (smf_event_is_last(event))
508 maybe_add_to_tempo_map(event);
509 else
510 smf_create_tempo_map_and_compute_seconds(event->track->smf);
511 }
512 }
513
523 int
524 smf_track_add_eot_delta_pulses(smf_track_t *track, int delta)
525 {
526 smf_event_t *event;
527
528 event = smf_event_new_from_bytes(0xFF, 0x2F, 0x00);
529 if (event == NULL)
530 return (-1);
531
532 smf_track_add_event_delta_pulses(track, event, delta);
533
534 return (0);
535 }
536
537 int
538 smf_track_add_eot_pulses(smf_track_t *track, int pulses)
539 {
540 smf_event_t *event, *last_event;
541
542 last_event = smf_track_get_last_event(track);
543 if (last_event != NULL) {
544 if (last_event->time_pulses > pulses)
545 return (-2);
546 }
547
548 event = smf_event_new_from_bytes(0xFF, 0x2F, 0x00);
549 if (event == NULL)
550 return (-3);
551
552 smf_track_add_event_pulses(track, event, pulses);
553
554 return (0);
555 }
556
557 int
558 smf_track_add_eot_seconds(smf_track_t *track, double seconds)
559 {
560 smf_event_t *event, *last_event;
561
562 last_event = smf_track_get_last_event(track);
563 if (last_event != NULL) {
564 if (last_event->time_seconds > seconds)
565 return (-2);
566 }
567
568 event = smf_event_new_from_bytes(0xFF, 0x2F, 0x00);
569 if (event == NULL)
570 return (-1);
571
572 smf_track_add_event_seconds(track, event, seconds);
573
574 return (0);
575 }
576
580 void
581 smf_event_remove_from_track(smf_event_t *event)
582 {
583 int i, was_last;
584 smf_event_t *tmp;
585 smf_track_t *track;
586
587 assert(event->track != NULL);
588 assert(event->track->smf != NULL);
589
590 track = event->track;
591 was_last = smf_event_is_last(event);
592
593 /* Adjust ->delta_time_pulses of the next event. */
594 if (event->event_number < track->number_of_events) {
595 tmp = smf_track_get_event_by_number(track, event->event_number + 1);
596 assert(tmp);
597 tmp->delta_time_pulses += event->delta_time_pulses;
598 }
599
600 track->number_of_events--;
601 g_ptr_array_remove(track->events_array, event);
602
603 if (track->number_of_events == 0)
604 track->next_event_number = -1;
605
606 /* Renumber the rest of the events, so they are consecutively numbered. */
607 for (i = event->event_number; i <= track->number_of_events; i++) {
608 tmp = smf_track_get_event_by_number(track, i);
609 tmp->event_number = i;
610 }
611
612 if (smf_event_is_tempo_change_or_time_signature(event)) {
613 /* XXX: This will cause problems, when there is more than one Tempo Change event at a given time. */
614 if (was_last)
615 remove_last_tempo_with_pulses(event->track->smf, event->time_pulses);
616 else
617 smf_create_tempo_map_and_compute_seconds(track->smf);
618 }
619
620 event->track = NULL;
621 event->event_number = -1;
622 event->delta_time_pulses = -1;
623 event->time_pulses = -1;
624 event->time_seconds = -1.0;
625 }
626
630 int
631 smf_event_is_tempo_change_or_time_signature(const smf_event_t *event)
632 {
633 if (!smf_event_is_metadata(event))
634 return (0);
635
636 assert(event->midi_buffer_length >= 2);
637
638 if (event->midi_buffer[1] == 0x51 || event->midi_buffer[1] == 0x58)
639 return (1);
640
641 return (0);
642 }
643
651 int
652 smf_set_format(smf_t *smf, int format)
653 {
654 assert(format == 0 || format == 1);
655
656 if (smf->number_of_tracks > 1 && format == 0) {
657 g_critical("There is more than one track, cannot set format to 0.");
658 return (-1);
659 }
660
661 smf->format = format;
662
663 return (0);
664 }
665
673 int
674 smf_set_ppqn(smf_t *smf, int ppqn)
675 {
676 assert(ppqn > 0);
677
678 smf->ppqn = ppqn;
679
680 return (0);
681 }
682
691 smf_event_t *
692 smf_track_get_next_event(smf_track_t *track)
693 {
694 smf_event_t *event, *next_event;
695
696 /* End of track? */
697 if (track->next_event_number == -1)
698 return (NULL);
699
700 assert(track->next_event_number >= 1);
701 assert(track->number_of_events > 0);
702
703 event = smf_track_get_event_by_number(track, track->next_event_number);
704
705 assert(event != NULL);
706
707 /* Is this the last event in the track? */
708 if (track->next_event_number < track->number_of_events) {
709 next_event = smf_track_get_event_by_number(track, track->next_event_number + 1);
710 assert(next_event);
711
712 track->time_of_next_event = next_event->time_pulses;
713 track->next_event_number++;
714 } else {
715 track->next_event_number = -1;
716 }
717
718 return (event);
719 }
720
726 static smf_event_t *
727 smf_peek_next_event_from_track(smf_track_t *track)
728 {
729 smf_event_t *event;
730
731 /* End of track? */
732 if (track->next_event_number == -1)
733 return (NULL);
734
735 assert(track->next_event_number >= 1);
736 assert(track->events_array->len != 0);
737
738 event = smf_track_get_event_by_number(track, track->next_event_number);
739
740 return (event);
741 }
742
747 smf_track_t *
748 smf_get_track_by_number(const smf_t *smf, int track_number)
749 {
750 smf_track_t *track;
751
752 assert(track_number >= 1);
753
754 if (track_number > smf->number_of_tracks)
755 return (NULL);
756
757 track = (smf_track_t *)g_ptr_array_index(smf->tracks_array, track_number - 1);
758
759 assert(track);
760
761 return (track);
762 }
763
768 smf_event_t *
769 smf_track_get_event_by_number(const smf_track_t *track, int event_number)
770 {
771 smf_event_t *event;
772
773 assert(event_number >= 1);
774
775 if (event_number > track->number_of_events)
776 return (NULL);
777
778 event = g_ptr_array_index(track->events_array, event_number - 1);
779
780 assert(event);
781
782 return (event);
783 }
784
788 smf_event_t *
789 smf_track_get_last_event(const smf_track_t *track)
790 {
791 smf_event_t *event;
792
793 if (track->number_of_events == 0)
794 return (NULL);
795
796 event = smf_track_get_event_by_number(track, track->number_of_events);
797
798 return (event);
799 }
800
806 smf_track_t *
807 smf_find_track_with_next_event(smf_t *smf)
808 {
809 int i, min_time = 0;
810 smf_track_t *track = NULL, *min_time_track = NULL;
811
812 /* Find track with event that should be played next. */
813 for (i = 1; i <= smf->number_of_tracks; i++) {
814 track = smf_get_track_by_number(smf, i);
815
816 assert(track);
817
818 /* No more events in this track? */
819 if (track->next_event_number == -1)
820 continue;
821
822 if (track->time_of_next_event < min_time || min_time_track == NULL) {
823 min_time = track->time_of_next_event;
824 min_time_track = track;
825 }
826 }
827
828 return (min_time_track);
829 }
830
834 smf_event_t *
835 smf_get_next_event(smf_t *smf)
836 {
837 smf_event_t *event;
838 smf_track_t *track = smf_find_track_with_next_event(smf);
839
840 if (track == NULL) {
841 #if 0
842 g_debug("End of the song.");
843 #endif
844
845 return (NULL);
846 }
847
848 event = smf_track_get_next_event(track);
849
850 assert(event != NULL);
851
852 event->track->smf->last_seek_position = -1.0;
853
854 return (event);
855 }
856
861 void
862 smf_skip_next_event(smf_t *smf)
863 {
864 void *notused;
865
866 notused = smf_get_next_event(smf);
867 }
868
873 smf_event_t *
874 smf_peek_next_event(smf_t *smf)
875 {
876 smf_event_t *event;
877 smf_track_t *track = smf_find_track_with_next_event(smf);
878
879 if (track == NULL) {
880 #if 0
881 g_debug("End of the song.");
882 #endif
883
884 return (NULL);
885 }
886
887 event = smf_peek_next_event_from_track(track);
888
889 assert(event != NULL);
890
891 return (event);
892 }
893
898 void
899 smf_rewind(smf_t *smf)
900 {
901 int i;
902 smf_track_t *track = NULL;
903 smf_event_t *event;
904
905 assert(smf);
906
907 smf->last_seek_position = 0.0;
908
909 for (i = 1; i <= smf->number_of_tracks; i++) {
910 track = smf_get_track_by_number(smf, i);
911
912 assert(track != NULL);
913
914 if (track->number_of_events > 0) {
915 track->next_event_number = 1;
916 event = smf_peek_next_event_from_track(track);
917 assert(event);
918 track->time_of_next_event = event->time_pulses;
919 } else {
920 track->next_event_number = -1;
921 track->time_of_next_event = 0;
922 #if 0
923 g_warning("Warning: empty track.");
924 #endif
925 }
926 }
927 }
928
933 int
934 smf_seek_to_event(smf_t *smf, const smf_event_t *target)
935 {
936 smf_event_t *event;
937
938 smf_rewind(smf);
939
940 #if 0
941 g_debug("Seeking to event %d, track %d.", target->event_number, target->track->track_number);
942 #endif
943
944 for (;;) {
945 event = smf_peek_next_event(smf);
946
947 /* There can't be NULL here, unless "target" is not in this smf. */
948 assert(event);
949
950 if (event != target)
951 smf_skip_next_event(smf);
952 else
953 break;
954 }
955
956 smf->last_seek_position = event->time_seconds;
957
958 return (0);
959 }
960
965 int
966 smf_seek_to_seconds(smf_t *smf, double seconds)
967 {
968 smf_event_t *event;
969
970 assert(seconds >= 0.0);
971
972 if (seconds == smf->last_seek_position) {
973 #if 0
974 g_debug("Avoiding seek to %f seconds.", seconds);
975 #endif
976 return (0);
977 }
978
979 smf_rewind(smf);
980
981 #if 0
982 g_debug("Seeking to %f seconds.", seconds);
983 #endif
984
985 for (;;) {
986 event = smf_peek_next_event(smf);
987
988 if (event == NULL) {
989 g_critical("Trying to seek past the end of song.");
990 return (-1);
991 }
992
993 if (event->time_seconds < seconds)
994 smf_skip_next_event(smf);
995 else
996 break;
997 }
998
999 smf->last_seek_position = seconds;
1000
1001 return (0);
1002 }
1003
1008 int
1009 smf_seek_to_pulses(smf_t *smf, int pulses)
1010 {
1011 smf_event_t *event;
1012
1013 assert(pulses >= 0);
1014
1015 smf_rewind(smf);
1016
1017 #if 0
1018 g_debug("Seeking to %d pulses.", pulses);
1019 #endif
1020
1021 for (;;) {
1022 event = smf_peek_next_event(smf);
1023
1024 if (event == NULL) {
1025 g_critical("Trying to seek past the end of song.");
1026 return (-1);
1027 }
1028
1029 if (event->time_pulses < pulses)
1030 smf_skip_next_event(smf);
1031 else
1032 break;
1033 }
1034
1035 smf->last_seek_position = event->time_seconds;
1036
1037 return (0);
1038 }
1039
1043 int
1044 smf_get_length_pulses(const smf_t *smf)
1045 {
1046 int pulses = 0, i;
1047
1048 for (i = 1; i <= smf->number_of_tracks; i++) {
1049 smf_track_t *track;
1050 smf_event_t *event;
1051
1052 track = smf_get_track_by_number(smf, i);
1053 assert(track);
1054
1055 event = smf_track_get_last_event(track);
1056 /* Empty track? */
1057 if (event == NULL)
1058 continue;
1059
1060 if (event->time_pulses > pulses)
1061 pulses = event->time_pulses;
1062 }
1063
1064 return (pulses);
1065 }
1066
1070 double
1071 smf_get_length_seconds(const smf_t *smf)
1072 {
1073 int i;
1074 double seconds = 0.0;
1075
1076 for (i = 1; i <= smf->number_of_tracks; i++) {
1077 smf_track_t *track;
1078 smf_event_t *event;
1079
1080 track = smf_get_track_by_number(smf, i);
1081 assert(track);
1082
1083 event = smf_track_get_last_event(track);
1084 /* Empty track? */
1085 if (event == NULL)
1086 continue;
1087
1088 if (event->time_seconds > seconds)
1089 seconds = event->time_seconds;
1090 }
1091
1092 return (seconds);
1093 }
1094
1099 int
1100 smf_event_is_last(const smf_event_t *event)
1101 {
1102 if (smf_get_length_pulses(event->track->smf) <= event->time_pulses)
1103 return (1);
1104
1105 return (0);
1106 }
1107
1111 const char *
1112 smf_get_version(void)
1113 {
1114 return (SMF_VERSION);
1115 }
1116
smf_rewind
void smf_rewind(smf_t *smf)
Rewinds the SMF.
Definition: smf.c:899
smf_track_get_event_by_number
smf_event_t * smf_track_get_event_by_number(const smf_track_t *track, int event_number)
Definition: smf.c:769
smf_get_length_seconds
double smf_get_length_seconds(const smf_t *smf)
Definition: smf.c:1071
smf_track_struct::next_event_number
int next_event_number
Definition: smf.h:285
smf_event_is_tempo_change_or_time_signature
int smf_event_is_tempo_change_or_time_signature(const smf_event_t *event)
Definition: smf.c:631
smf_struct::format
int format
Definition: smf.h:231
smf_track_add_event
void smf_track_add_event(smf_track_t *track, smf_event_t *event)
Adds the event to the track and computes ->delta_pulses.
Definition: smf.c:441
smf_track_struct::events_array
GPtrArray * events_array
Definition: smf.h:289
smf_set_ppqn
int smf_set_ppqn(smf_t *smf, int ppqn)
Sets the PPQN ("Division") field of MThd header.
Definition: smf.c:674
smf_track_add_event_delta_pulses
void smf_track_add_event_delta_pulses(smf_track_t *track, smf_event_t *event, int pulses)
Adds event to the track at the time "pulses" clocks from the previous event in this track...
Definition: smf_tempo.c:403
smf_struct::tempo_array
GPtrArray * tempo_array
Private, used by smf_tempo.c.
Definition: smf.h:252
smf_event_struct::midi_buffer
unsigned char * midi_buffer
Pointer to the buffer containing MIDI message.
Definition: smf.h:322
smf_track_add_eot_delta_pulses
int smf_track_add_eot_delta_pulses(smf_track_t *track, int delta)
Add End Of Track metaevent.
Definition: smf.c:524
smf_struct
Represents a "song", that is, collection of one or more tracks.
Definition: smf.h:230
smf_track_remove_from_smf
void smf_track_remove_from_smf(smf_track_t *track)
Detaches track from the smf.
Definition: smf.c:178
smf_seek_to_pulses
int smf_seek_to_pulses(smf_t *smf, int pulses)
Seeks the SMF to the given position.
Definition: smf.c:1009
smf_track_struct
Represents a single track.
Definition: smf.h:271
smf_struct::tracks_array
GPtrArray * tracks_array
Private, used by smf.c.
Definition: smf.h:247
smf_seek_to_event
int smf_seek_to_event(smf_t *smf, const smf_event_t *target)
Seeks the SMF to the given event.
Definition: smf.c:934
smf_add_track
void smf_add_track(smf_t *smf, smf_track_t *track)
Appends smf_track_t to smf.
Definition: smf.c:156
smf_struct::ppqn
int ppqn
These fields are extracted from "division" field of MThd header.
Definition: smf.h:234
smf_track_add_eot_pulses
int smf_track_add_eot_pulses(smf_track_t *track, int pulses)
Definition: smf.c:538
smf_event_is_metadata
int smf_event_is_metadata(const smf_event_t *event) WARN_UNUSED_RESULT
Definition: smf_decode.c:57
smf_track_struct::track_number
int track_number
Definition: smf.h:274
smf_init_tempo
void smf_init_tempo(smf_t *smf)
Definition: smf_tempo.c:367
smf_event_delete
void smf_event_delete(smf_event_t *event)
Detaches event from its track and frees it.
Definition: smf.c:363
smf_create_tempo_map_and_compute_seconds
void smf_create_tempo_map_and_compute_seconds(smf_t *smf)
Definition: smf_tempo.c:235
smf_event_struct::event_number
int event_number
Number of this event in the track.
Definition: smf.h:306
smf_track_struct::smf
smf_t * smf
Definition: smf.h:272
smf_event_new_from_pointer
smf_event_t * smf_event_new_from_pointer(void *midi_data, int len)
Allocates an smf_event_t structure and fills it with "len" bytes copied from "midi_data".
Definition: smf.c:243
smf_track_struct::time_of_next_event
int time_of_next_event
Absolute time of next event on events_queue.
Definition: smf.h:288
maybe_add_to_tempo_map
void maybe_add_to_tempo_map(smf_event_t *event)
Definition: smf_tempo.c:125
smf_event_is_eot
int smf_event_is_eot(const smf_event_t *event) WARN_UNUSED_RESULT
Definition: smf_save.c:475
smf_event_struct::time_pulses
int time_pulses
Time, in pulses, since the start of the song.
Definition: smf.h:313
smf_event_new_from_bytes
smf_event_t * smf_event_new_from_bytes(int first_byte, int second_byte, int third_byte)
Allocates an smf_event_t structure and fills it with at most three bytes of data. ...
Definition: smf.c:282
smf_delete
void smf_delete(smf_t *smf)
Frees smf and all it's descendant structures.
Definition: smf.c:88
smf_get_version
const char * smf_get_version(void)
Definition: smf.c:1112
smf_track_new
smf_track_t * smf_track_new(void)
Allocates new smf_track_t structure.
Definition: smf.c:110
smf_event_struct::midi_buffer_length
int midi_buffer_length
Length of the MIDI message in the buffer, in bytes.
Definition: smf.h:325
smf_struct::number_of_tracks
int number_of_tracks
Definition: smf.h:237
smf_event_new
smf_event_t * smf_event_new(void)
Allocates new smf_event_t structure.
Definition: smf.c:217
remove_last_tempo_with_pulses
void remove_last_tempo_with_pulses(smf_t *smf, int pulses)
Definition: smf_tempo.c:173
smf_track_add_event_pulses
void smf_track_add_event_pulses(smf_track_t *track, smf_event_t *event, int pulses)
Adds event to the track at the time "pulses" clocks from the start of song.
Definition: smf_tempo.c:419
smf_track_struct::number_of_events
int number_of_events
Definition: smf.h:275
smf_struct::last_seek_position
double last_seek_position
Definition: smf.h:248
smf.h
Public interface declaration for libsmf, Standard MIDI File format library.
smf_get_length_pulses
int smf_get_length_pulses(const smf_t *smf)
Definition: smf.c:1044
smf_seek_to_seconds
int smf_seek_to_seconds(smf_t *smf, double seconds)
Seeks the SMF to the given position.
Definition: smf.c:966
smf_event_is_last
int smf_event_is_last(const smf_event_t *event)
Definition: smf.c:1100
is_status_byte
int is_status_byte(const unsigned char status)
Returns 1 if the given byte is a valid status byte, 0 otherwise.
Definition: smf_load.c:251
smf_track_get_next_event
smf_event_t * smf_track_get_next_event(smf_track_t *track)
Returns next event from the track given and advances next event counter.
Definition: smf.c:692
smf_find_track_with_next_event
smf_track_t * smf_find_track_with_next_event(smf_t *smf)
Searches for track that contains next event, in time order.
Definition: smf.c:807
smf_get_track_by_number
smf_track_t * smf_get_track_by_number(const smf_t *smf, int track_number)
Definition: smf.c:748
smf_event_struct::time_seconds
double time_seconds
Time, in seconds, since the start of the song.
Definition: smf.h:316
smf_event_struct
Represents a single MIDI event or metaevent.
Definition: smf.h:301
smf_event_remove_from_track
void smf_event_remove_from_track(smf_event_t *event)
Detaches event from its track.
Definition: smf.c:581
smf_track_get_last_event
smf_event_t * smf_track_get_last_event(const smf_track_t *track)
Definition: smf.c:789
smf_private.h
Private header.
smf_fini_tempo
void smf_fini_tempo(smf_t *smf)
Definition: smf_tempo.c:342
smf_track_add_event_seconds
void smf_track_add_event_seconds(smf_track_t *track, smf_event_t *event, double seconds)
Adds event to the track at the time "seconds" seconds from the start of song.
Definition: smf_tempo.c:437
smf_track_delete
void smf_track_delete(smf_track_t *track)
Detaches track from its smf and frees it.
Definition: smf.c:131
smf_track_add_eot_seconds
int smf_track_add_eot_seconds(smf_track_t *track, double seconds)
Definition: smf.c:558
smf_event_struct::track_number
int track_number
Tracks are numbered consecutively, starting from 1.
Definition: smf.h:319
smf_peek_next_event
smf_event_t * smf_peek_next_event(smf_t *smf)
Definition: smf.c:874
smf_new
smf_t * smf_new(void)
Allocates new smf_t structure.
Definition: smf.c:55
smf_event_struct::delta_time_pulses
int delta_time_pulses
Note that the time fields are invalid, if event is not attached to a track.
Definition: smf.h:310
smf_set_format
int smf_set_format(smf_t *smf, int format)
Sets "Format" field of MThd header to the specified value.
Definition: smf.c:652
smf_event_struct::track
smf_track_t * track
Pointer to the track, or NULL if event is not attached.
Definition: smf.h:303
smf
smf_t * smf
Definition: smfsh.c:56
smf_get_next_event
smf_event_t * smf_get_next_event(smf_t *smf)
Definition: smf.c:835
smf_skip_next_event
void smf_skip_next_event(smf_t *smf)
Advance the "next event counter".
Definition: smf.c:862