libsmf
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
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 *
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
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)
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
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
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 *
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
364 {
365  if (event->track != NULL)
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 
431 }
432 
440 void
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++) {
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 -
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 
507  if (smf_event_is_last(event))
508  maybe_add_to_tempo_map(event);
509  else
511  }
512 }
513 
523 int
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
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
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 
613  /* XXX: This will cause problems, when there is more than one Tempo Change event at a given time. */
614  if (was_last)
616  else
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
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 *
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 *
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 *
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 *
836 {
837  smf_event_t *event;
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
863 {
864  void *notused;
865 
866  notused = smf_get_next_event(smf);
867 }
868 
873 smf_event_t *
875 {
876  smf_event_t *event;
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
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
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
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
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
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
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 *
1113 {
1114  return (SMF_VERSION);
1115 }
1116 
void smf_rewind(smf_t *smf)
Rewinds the SMF.
Definition: smf.c:899
smf_event_t * smf_track_get_event_by_number(const smf_track_t *track, int event_number)
Definition: smf.c:769
double smf_get_length_seconds(const smf_t *smf)
Definition: smf.c:1071
int next_event_number
Definition: smf.h:285
int smf_event_is_tempo_change_or_time_signature(const smf_event_t *event)
Definition: smf.c:631
int format
Definition: smf.h:231
void smf_track_add_event(smf_track_t *track, smf_event_t *event)
Adds the event to the track and computes -&gt;delta_pulses.
Definition: smf.c:441
GPtrArray * events_array
Definition: smf.h:289
int smf_set_ppqn(smf_t *smf, int ppqn)
Sets the PPQN (&quot;Division&quot;) field of MThd header.
Definition: smf.c:674
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 &quot;pulses&quot; clocks from the previous event in this track...
Definition: smf_tempo.c:403
GPtrArray * tempo_array
Private, used by smf_tempo.c.
Definition: smf.h:252
unsigned char * midi_buffer
Pointer to the buffer containing MIDI message.
Definition: smf.h:322
int smf_track_add_eot_delta_pulses(smf_track_t *track, int delta)
Add End Of Track metaevent.
Definition: smf.c:524
Represents a &quot;song&quot;, that is, collection of one or more tracks.
Definition: smf.h:230
void smf_track_remove_from_smf(smf_track_t *track)
Detaches track from the smf.
Definition: smf.c:178
int smf_seek_to_pulses(smf_t *smf, int pulses)
Seeks the SMF to the given position.
Definition: smf.c:1009
Represents a single track.
Definition: smf.h:271
GPtrArray * tracks_array
Private, used by smf.c.
Definition: smf.h:247
int smf_seek_to_event(smf_t *smf, const smf_event_t *target)
Seeks the SMF to the given event.
Definition: smf.c:934
void smf_add_track(smf_t *smf, smf_track_t *track)
Appends smf_track_t to smf.
Definition: smf.c:156
int ppqn
These fields are extracted from &quot;division&quot; field of MThd header.
Definition: smf.h:234
int smf_track_add_eot_pulses(smf_track_t *track, int pulses)
Definition: smf.c:538
int smf_event_is_metadata(const smf_event_t *event) WARN_UNUSED_RESULT
Definition: smf_decode.c:57
int track_number
Definition: smf.h:274
void smf_init_tempo(smf_t *smf)
Definition: smf_tempo.c:367
void smf_event_delete(smf_event_t *event)
Detaches event from its track and frees it.
Definition: smf.c:363
void smf_create_tempo_map_and_compute_seconds(smf_t *smf)
Definition: smf_tempo.c:235
int event_number
Number of this event in the track.
Definition: smf.h:306
smf_t * smf
Definition: smf.h:272
smf_event_t * smf_event_new_from_pointer(void *midi_data, int len)
Allocates an smf_event_t structure and fills it with &quot;len&quot; bytes copied from &quot;midi_data&quot;.
Definition: smf.c:243
int time_of_next_event
Absolute time of next event on events_queue.
Definition: smf.h:288
void maybe_add_to_tempo_map(smf_event_t *event)
Definition: smf_tempo.c:125
int smf_event_is_eot(const smf_event_t *event) WARN_UNUSED_RESULT
Definition: smf_save.c:475
int time_pulses
Time, in pulses, since the start of the song.
Definition: smf.h:313
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
void smf_delete(smf_t *smf)
Frees smf and all it&#39;s descendant structures.
Definition: smf.c:88
const char * smf_get_version(void)
Definition: smf.c:1112
smf_track_t * smf_track_new(void)
Allocates new smf_track_t structure.
Definition: smf.c:110
int midi_buffer_length
Length of the MIDI message in the buffer, in bytes.
Definition: smf.h:325
int number_of_tracks
Definition: smf.h:237
smf_event_t * smf_event_new(void)
Allocates new smf_event_t structure.
Definition: smf.c:217
void remove_last_tempo_with_pulses(smf_t *smf, int pulses)
Definition: smf_tempo.c:173
void smf_track_add_event_pulses(smf_track_t *track, smf_event_t *event, int pulses)
Adds event to the track at the time &quot;pulses&quot; clocks from the start of song.
Definition: smf_tempo.c:419
int number_of_events
Definition: smf.h:275
double last_seek_position
Definition: smf.h:248
Public interface declaration for libsmf, Standard MIDI File format library.
int smf_get_length_pulses(const smf_t *smf)
Definition: smf.c:1044
int smf_seek_to_seconds(smf_t *smf, double seconds)
Seeks the SMF to the given position.
Definition: smf.c:966
int smf_event_is_last(const smf_event_t *event)
Definition: smf.c:1100
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_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_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_track_t * smf_get_track_by_number(const smf_t *smf, int track_number)
Definition: smf.c:748
double time_seconds
Time, in seconds, since the start of the song.
Definition: smf.h:316
Represents a single MIDI event or metaevent.
Definition: smf.h:301
void smf_event_remove_from_track(smf_event_t *event)
Detaches event from its track.
Definition: smf.c:581
smf_event_t * smf_track_get_last_event(const smf_track_t *track)
Definition: smf.c:789
Private header.
void smf_fini_tempo(smf_t *smf)
Definition: smf_tempo.c:342
void smf_track_add_event_seconds(smf_track_t *track, smf_event_t *event, double seconds)
Adds event to the track at the time &quot;seconds&quot; seconds from the start of song.
Definition: smf_tempo.c:437
void smf_track_delete(smf_track_t *track)
Detaches track from its smf and frees it.
Definition: smf.c:131
int smf_track_add_eot_seconds(smf_track_t *track, double seconds)
Definition: smf.c:558
int track_number
Tracks are numbered consecutively, starting from 1.
Definition: smf.h:319
smf_event_t * smf_peek_next_event(smf_t *smf)
Definition: smf.c:874
smf_t * smf_new(void)
Allocates new smf_t structure.
Definition: smf.c:55
int delta_time_pulses
Note that the time fields are invalid, if event is not attached to a track.
Definition: smf.h:310
int smf_set_format(smf_t *smf, int format)
Sets &quot;Format&quot; field of MThd header to the specified value.
Definition: smf.c:652
smf_track_t * track
Pointer to the track, or NULL if event is not attached.
Definition: smf.h:303
smf_t * smf
Definition: smfsh.c:56
smf_event_t * smf_get_next_event(smf_t *smf)
Definition: smf.c:835
void smf_skip_next_event(smf_t *smf)
Advance the &quot;next event counter&quot;.
Definition: smf.c:862