libsmf
smf_load.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 #include <ctype.h>
43 #ifdef __MINGW32__
44 #include <windows.h>
45 #else /* ! __MINGW32__ */
46 #include <arpa/inet.h>
47 #endif /* ! __MINGW32__ */
48 #include "smf.h"
49 #include "smf_private.h"
50 
55 static struct chunk_header_struct *
56 next_chunk(smf_t *smf)
57 {
58  struct chunk_header_struct *chunk;
59  void *next_chunk_ptr;
60 
61  assert(smf->file_buffer != NULL);
62  assert(smf->file_buffer_length > 0);
63  assert(smf->next_chunk_offset >= 0);
64 
65  if (smf->next_chunk_offset + sizeof(struct chunk_header_struct) >= smf->file_buffer_length) {
66  g_critical("SMF warning: no more chunks left.");
67  return (NULL);
68  }
69 
70  next_chunk_ptr = (unsigned char *)smf->file_buffer + smf->next_chunk_offset;
71 
72  chunk = (struct chunk_header_struct *)next_chunk_ptr;
73 
74  if (!isalpha(chunk->id[0]) || !isalpha(chunk->id[1]) || !isalpha(chunk->id[2]) || !isalpha(chunk->id[3])) {
75  g_critical("SMF error: chunk signature contains at least one non-alphanumeric byte.");
76  return (NULL);
77  }
78 
79  /*
80  * XXX: On SPARC, after compiling with "-fast" option there will be SIGBUS here.
81  * Please compile with -xmemalign=8i".
82  */
83  smf->next_chunk_offset += sizeof(struct chunk_header_struct) + ntohl(chunk->length);
84 
85  if (smf->next_chunk_offset > smf->file_buffer_length) {
86  g_critical("SMF warning: malformed chunk; truncated file?");
88  }
89 
90  return (chunk);
91 }
92 
96 static int
97 chunk_signature_matches(const struct chunk_header_struct *chunk, const char *signature)
98 {
99  if (!memcmp(chunk->id, signature, 4))
100  return (1);
101 
102  return (0);
103 }
104 
108 static int
109 parse_mthd_header(smf_t *smf)
110 {
111  int len;
112  struct chunk_header_struct *mthd, *tmp_mthd;
113 
114  /* Make sure compiler didn't do anything stupid. */
115  assert(sizeof(struct chunk_header_struct) == 8);
116 
117  /*
118  * We could just do "mthd = smf->file_buffer;" here, but this way we wouldn't
119  * get useful error messages.
120  */
121  if (smf->file_buffer_length < 6) {
122  g_critical("SMF error: file is too short, it cannot be a MIDI file.");
123 
124  return (-1);
125  }
126 
127  tmp_mthd = smf->file_buffer;
128 
129  if (!chunk_signature_matches(tmp_mthd, "MThd")) {
130  g_critical("SMF error: MThd signature not found, is that a MIDI file?");
131 
132  return (-2);
133  }
134 
135  /* Ok, now use next_chunk(). */
136  mthd = next_chunk(smf);
137  if (mthd == NULL)
138  return (-3);
139 
140  assert(mthd == tmp_mthd);
141 
142  len = ntohl(mthd->length);
143  if (len != 6) {
144  g_critical("SMF error: MThd chunk length %d, must be 6.", len);
145 
146  return (-4);
147  }
148 
149  return (0);
150 }
151 
155 static int
156 parse_mthd_chunk(smf_t *smf)
157 {
158  signed char first_byte_of_division, second_byte_of_division;
159 
160  struct mthd_chunk_struct *mthd;
161 
162  assert(sizeof(struct mthd_chunk_struct) == 14);
163 
164  if (parse_mthd_header(smf))
165  return (1);
166 
167  mthd = (struct mthd_chunk_struct *)smf->file_buffer;
168 
169  smf->format = ntohs(mthd->format);
170  if (smf->format < 0 || smf->format > 2) {
171  g_critical("SMF error: bad MThd format field value: %d, valid values are 0-2, inclusive.", smf->format);
172  return (-1);
173  }
174 
175  if (smf->format == 2) {
176  g_critical("SMF file uses format #2, no support for that yet.");
177  return (-2);
178  }
179 
180  smf->expected_number_of_tracks = ntohs(mthd->number_of_tracks);
181  if (smf->expected_number_of_tracks <= 0) {
182  g_critical("SMF error: bad number of tracks: %d, must be greater than zero.", smf->expected_number_of_tracks);
183  return (-3);
184  }
185 
186  /* XXX: endianess? */
187  first_byte_of_division = *((signed char *)&(mthd->division));
188  second_byte_of_division = *((signed char *)&(mthd->division) + 1);
189 
190  if (first_byte_of_division >= 0) {
191  smf->ppqn = ntohs(mthd->division);
192  smf->frames_per_second = 0;
193  smf->resolution = 0;
194  } else {
195  smf->ppqn = 0;
196  smf->frames_per_second = - first_byte_of_division;
197  smf->resolution = second_byte_of_division;
198  }
199 
200  if (smf->ppqn == 0) {
201  g_critical("SMF file uses FPS timing instead of PPQN, no support for that yet.");
202  return (-4);
203  }
204 
205  return (0);
206 }
207 
214 static int
215 extract_vlq(const unsigned char *buf, const int buffer_length, int *value, int *len)
216 {
217  int val = 0;
218  const unsigned char *c = buf;
219 
220  assert(buffer_length > 0);
221 
222  for (;;) {
223  if (c >= buf + buffer_length) {
224  g_critical("End of buffer in extract_vlq().");
225  return (-1);
226  }
227 
228  val = (val << 7) + (*c & 0x7F);
229 
230  if (*c & 0x80)
231  c++;
232  else
233  break;
234  };
235 
236  *value = val;
237  *len = c - buf + 1;
238 
239  if (*len > 4) {
240  g_critical("SMF error: Variable Length Quantities longer than four bytes are not supported yet.");
241  return (-2);
242  }
243 
244  return (0);
245 }
246 
250 int
251 is_status_byte(const unsigned char status)
252 {
253  return (status & 0x80);
254 }
255 
256 static int
257 is_sysex_byte(const unsigned char status)
258 {
259  if (status == 0xF0)
260  return (1);
261 
262  return (0);
263 }
264 
265 static int
266 is_escape_byte(const unsigned char status)
267 {
268  if (status == 0xF7)
269  return (1);
270 
271  return (0);
272 }
273 
281 static int
282 expected_sysex_length(const unsigned char status, const unsigned char *second_byte, const int buffer_length, int *consumed_bytes)
283 {
284  int sysex_length, len;
285 
286  assert(status == 0xF0);
287 
288  if (buffer_length < 3) {
289  g_critical("SMF error: end of buffer in expected_sysex_length().");
290  return (-1);
291  }
292 
293  if (extract_vlq(second_byte, buffer_length, &sysex_length, &len))
294  return (-1);
295 
296  if (consumed_bytes != NULL)
297  *consumed_bytes = len;
298 
299  /* +1, because the length does not include status byte. */
300  return (sysex_length + 1);
301 }
302 
303 static int
304 expected_escaped_length(const unsigned char status, const unsigned char *second_byte, const int buffer_length, int *consumed_bytes)
305 {
306  /* -1, because we do not want to account for 0x7F status. */
307  return (expected_sysex_length(status, second_byte, buffer_length, consumed_bytes) - 1);
308 }
309 
315 static int
316 expected_message_length(unsigned char status, const unsigned char *second_byte, const int buffer_length)
317 {
318  /* Make sure this really is a valid status byte. */
319  assert(is_status_byte(status));
320 
321  /* We cannot use this routine for sysexes. */
322  assert(!is_sysex_byte(status));
323 
324  /* We cannot use this routine for escaped events. */
325  assert(!is_escape_byte(status));
326 
327  /* Buffer length may be zero, for e.g. realtime messages. */
328  assert(buffer_length >= 0);
329 
330  /* Is this a metamessage? */
331  if (status == 0xFF) {
332  if (buffer_length < 2) {
333  g_critical("SMF error: end of buffer in expected_message_length().");
334  return (-1);
335  }
336 
337  /*
338  * Format of this kind of messages is like this: 0xFF 0xwhatever 0xlength and then "length" bytes.
339  * Second byte points to this: ^^^^^^^^^^
340  */
341  return (*(second_byte + 1) + 3);
342  }
343 
344  if ((status & 0xF0) == 0xF0) {
345  switch (status) {
346  case 0xF2: /* Song Position Pointer. */
347  return (3);
348 
349  case 0xF1: /* MTC Quarter Frame. */
350  case 0xF3: /* Song Select. */
351  return (2);
352 
353  case 0xF6: /* Tune Request. */
354  case 0xF8: /* MIDI Clock. */
355  case 0xF9: /* Tick. */
356  case 0xFA: /* MIDI Start. */
357  case 0xFB: /* MIDI Continue. */
358  case 0xFC: /* MIDI Stop. */
359  case 0xFE: /* Active Sense. */
360  return (1);
361 
362  default:
363  g_critical("SMF error: unknown 0xFx-type status byte '0x%x'.", status);
364  return (-2);
365  }
366  }
367 
368  /* Filter out the channel. */
369  status &= 0xF0;
370 
371  switch (status) {
372  case 0x80: /* Note Off. */
373  case 0x90: /* Note On. */
374  case 0xA0: /* AfterTouch. */
375  case 0xB0: /* Control Change. */
376  case 0xE0: /* Pitch Wheel. */
377  return (3);
378 
379  case 0xC0: /* Program Change. */
380  case 0xD0: /* Channel Pressure. */
381  return (2);
382 
383  default:
384  g_critical("SMF error: unknown status byte '0x%x'.", status);
385  return (-3);
386  }
387 }
388 
389 static int
390 extract_sysex_event(const unsigned char *buf, const int buffer_length, smf_event_t *event, int *len, int last_status)
391 {
392  int status, message_length, vlq_length;
393  const unsigned char *c = buf;
394 
395  status = *buf;
396 
397  assert(is_sysex_byte(status));
398 
399  c++;
400 
401  message_length = expected_sysex_length(status, c, buffer_length - 1, &vlq_length);
402 
403  if (message_length < 0)
404  return (-3);
405 
406  c += vlq_length;
407 
408  if (vlq_length + message_length >= buffer_length) {
409  g_critical("End of buffer in extract_sysex_event().");
410  return (-5);
411  }
412 
413  event->midi_buffer_length = message_length;
414  event->midi_buffer = malloc(event->midi_buffer_length);
415  if (event->midi_buffer == NULL) {
416  g_critical("Cannot allocate memory in extract_sysex_event(): %s", strerror(errno));
417  return (-4);
418  }
419 
420  event->midi_buffer[0] = status;
421  memcpy(event->midi_buffer + 1, c, message_length - 1);
422 
423  *len = vlq_length + message_length;
424 
425  return (0);
426 }
427 
428 static int
429 extract_escaped_event(const unsigned char *buf, const int buffer_length, smf_event_t *event, int *len, int last_status)
430 {
431  int status, message_length, vlq_length;
432  const unsigned char *c = buf;
433 
434  status = *buf;
435 
436  assert(is_escape_byte(status));
437 
438  c++;
439 
440  message_length = expected_escaped_length(status, c, buffer_length - 1, &vlq_length);
441 
442  if (message_length < 0)
443  return (-3);
444 
445  c += vlq_length;
446 
447  if (vlq_length + message_length >= buffer_length) {
448  g_critical("End of buffer in extract_escaped_event().");
449  return (-5);
450  }
451 
452  event->midi_buffer_length = message_length;
453  event->midi_buffer = malloc(event->midi_buffer_length);
454  if (event->midi_buffer == NULL) {
455  g_critical("Cannot allocate memory in extract_escaped_event(): %s", strerror(errno));
456  return (-4);
457  }
458 
459  memcpy(event->midi_buffer, c, message_length);
460 
461  if (smf_event_is_valid(event)) {
462  g_critical("Escaped event is invalid.");
463  return (-1);
464  }
465 
467  g_warning("Escaped event is not System Realtime nor System Common.");
468  }
469 
470  *len = vlq_length + message_length;
471 
472  return (0);
473 }
474 
475 
481 static int
482 extract_midi_event(const unsigned char *buf, const int buffer_length, smf_event_t *event, int *len, int last_status)
483 {
484  int status, message_length;
485  const unsigned char *c = buf;
486 
487  assert(buffer_length > 0);
488 
489  /* Is the first byte the status byte? */
490  if (is_status_byte(*c)) {
491  status = *c;
492  c++;
493 
494  } else {
495  /* No, we use running status then. */
496  status = last_status;
497  }
498 
499  if (!is_status_byte(status)) {
500  g_critical("SMF error: bad status byte (MSB is zero).");
501  return (-1);
502  }
503 
504  if (is_sysex_byte(status))
505  return (extract_sysex_event(buf, buffer_length, event, len, last_status));
506 
507  if (is_escape_byte(status))
508  return (extract_escaped_event(buf, buffer_length, event, len, last_status));
509 
510  /* At this point, "c" points to first byte following the status byte. */
511  message_length = expected_message_length(status, c, buffer_length - (c - buf));
512 
513  if (message_length < 0)
514  return (-3);
515 
516  if (message_length - 1 > buffer_length - (c - buf)) {
517  g_critical("End of buffer in extract_midi_event().");
518  return (-5);
519  }
520 
521  event->midi_buffer_length = message_length;
522  event->midi_buffer = malloc(event->midi_buffer_length);
523  if (event->midi_buffer == NULL) {
524  g_critical("Cannot allocate memory in extract_midi_event(): %s", strerror(errno));
525  return (-4);
526  }
527 
528  event->midi_buffer[0] = status;
529  memcpy(event->midi_buffer + 1, c, message_length - 1);
530 
531  *len = c + message_length - 1 - buf;
532 
533  return (0);
534 }
535 
542 static smf_event_t *
543 parse_next_event(smf_track_t *track)
544 {
545  int time = 0, len, buffer_length;
546  unsigned char *c, *start;
547 
548  smf_event_t *event = smf_event_new();
549  if (event == NULL)
550  goto error;
551 
552  c = start = (unsigned char *)track->file_buffer + track->next_event_offset;
553 
554  assert(track->file_buffer != NULL);
555  assert(track->file_buffer_length > 0);
556  assert(track->next_event_offset > 0);
557 
558  buffer_length = track->file_buffer_length - track->next_event_offset;
559  assert(buffer_length > 0);
560 
561  /* First, extract time offset from previous event. */
562  if (extract_vlq(c, buffer_length, &time, &len))
563  goto error;
564 
565  c += len;
566  buffer_length -= len;
567 
568  if (buffer_length <= 0)
569  goto error;
570 
571  /* Now, extract the actual event. */
572  if (extract_midi_event(c, buffer_length, event, &len, track->last_status))
573  goto error;
574 
575  c += len;
576  buffer_length -= len;
577  track->last_status = event->midi_buffer[0];
578  track->next_event_offset += c - start;
579 
580  smf_track_add_event_delta_pulses(track, event, time);
581 
582  return (event);
583 
584 error:
585  if (event != NULL)
586  smf_event_delete(event);
587 
588  return (NULL);
589 }
590 
595 static char *
596 make_string(const unsigned char *buf, const int buffer_length, int len)
597 {
598  char *str;
599 
600  assert(buffer_length > 0);
601  assert(len > 0);
602 
603  if (len > buffer_length) {
604  g_critical("End of buffer in make_string().");
605 
606  len = buffer_length;
607  }
608 
609  str = malloc(len + 1);
610  if (str == NULL) {
611  g_critical("Cannot allocate memory in make_string().");
612  return (NULL);
613  }
614 
615  memcpy(str, buf, len);
616  str[len] = '\0';
617 
618  return (str);
619 }
620 
626 int
628 {
629  if (!smf_event_is_metadata(event))
630  return (0);
631 
632  if (event->midi_buffer_length < 4)
633  return (0);
634 
635  if (event->midi_buffer[3] < 1 && event->midi_buffer[3] > 9)
636  return (0);
637 
638  return (1);
639 }
640 
646 char *
648 {
649  int string_length = -1, length_length = -1;
650 
651  if (!smf_event_is_textual(event))
652  return (NULL);
653 
654  if (event->midi_buffer_length < 3) {
655  g_critical("smf_event_extract_text: truncated MIDI message.");
656  return (NULL);
657  }
658 
659  extract_vlq((void *)&(event->midi_buffer[2]), event->midi_buffer_length - 2, &string_length, &length_length);
660 
661  if (string_length <= 0) {
662  g_critical("smf_event_extract_text: truncated MIDI message.");
663  return (NULL);
664  }
665 
666  return (make_string((void *)(&event->midi_buffer[2] + length_length), event->midi_buffer_length - 2 - length_length, string_length));
667 }
668 
673 static int
674 parse_mtrk_header(smf_track_t *track)
675 {
676  struct chunk_header_struct *mtrk;
677 
678  /* Make sure compiler didn't do anything stupid. */
679  assert(sizeof(struct chunk_header_struct) == 8);
680  assert(track->smf != NULL);
681 
682  mtrk = next_chunk(track->smf);
683 
684  if (mtrk == NULL)
685  return (-1);
686 
687  if (!chunk_signature_matches(mtrk, "MTrk")) {
688  g_warning("SMF warning: Expected MTrk signature, got %c%c%c%c instead; ignoring this chunk.",
689  mtrk->id[0], mtrk->id[1], mtrk->id[2], mtrk->id[3]);
690 
691  return (-2);
692  }
693 
694  track->file_buffer = mtrk;
695  track->file_buffer_length = sizeof(struct chunk_header_struct) + ntohl(mtrk->length);
696  track->next_event_offset = sizeof(struct chunk_header_struct);
697 
698  return (0);
699 }
700 
704 static int
705 event_is_end_of_track(const smf_event_t *event)
706 {
707  if (event->midi_buffer[0] == 0xFF && event->midi_buffer[1] == 0x2F)
708  return (1);
709 
710  return (0);
711 }
712 
717 int
719 {
720  assert(event);
721  assert(event->midi_buffer);
722 
723  if (event->midi_buffer_length < 1)
724  return (0);
725 
726  /* We cannot use expected_message_length on sysexes. */
727  if (smf_event_is_sysex(event))
728  return (1);
729 
730  if (event->midi_buffer_length != expected_message_length(event->midi_buffer[0],
731  &(event->midi_buffer[1]), event->midi_buffer_length - 1)) {
732 
733  return (0);
734  }
735 
736  return (1);
737 }
738 
743 /* XXX: this routine requires some more work to detect more errors. */
744 int
746 {
747  assert(event);
748  assert(event->midi_buffer);
749  assert(event->midi_buffer_length >= 1);
750 
751  if (!is_status_byte(event->midi_buffer[0])) {
752  g_critical("First byte of MIDI message is not a valid status byte.");
753 
754  return (0);
755  }
756 
757  if (!smf_event_length_is_valid(event))
758  return (0);
759 
760  return (1);
761 }
762 
766 static int
767 parse_mtrk_chunk(smf_track_t *track)
768 {
769  smf_event_t *event;
770 
771  if (parse_mtrk_header(track))
772  return (-1);
773 
774  for (;;) {
775  event = parse_next_event(track);
776 
777  /* Couldn't parse an event? */
778  if (event == NULL) {
779  g_critical("Unable to parse MIDI event; truncating track.");
780  if (smf_track_add_eot_delta_pulses(track, 0) != 0) {
781  g_critical("smf_track_add_eot_delta_pulses failed.");
782  return (-2);
783  }
784  break;
785  }
786 
787  assert(smf_event_is_valid(event));
788 
789  if (event_is_end_of_track(event))
790  break;
791  }
792 
793  track->file_buffer = NULL;
794  track->file_buffer_length = 0;
795  track->next_event_offset = -1;
796 
797  return (0);
798 }
799 
803 static int
804 load_file_into_buffer(void **file_buffer, int *file_buffer_length, const char *file_name)
805 {
806  FILE *stream = fopen(file_name, "rb");
807 
808  if (stream == NULL) {
809  g_critical("Cannot open input file: %s", strerror(errno));
810 
811  return (-1);
812  }
813 
814  if (fseek(stream, 0, SEEK_END)) {
815  g_critical("fseek(3) failed: %s", strerror(errno));
816 
817  return (-2);
818  }
819 
820  *file_buffer_length = ftell(stream);
821  if (*file_buffer_length == -1) {
822  g_critical("ftell(3) failed: %s", strerror(errno));
823 
824  return (-3);
825  }
826 
827  if (fseek(stream, 0, SEEK_SET)) {
828  g_critical("fseek(3) failed: %s", strerror(errno));
829 
830  return (-4);
831  }
832 
833  *file_buffer = malloc(*file_buffer_length);
834  if (*file_buffer == NULL) {
835  g_critical("malloc(3) failed: %s", strerror(errno));
836 
837  return (-5);
838  }
839 
840  if (fread(*file_buffer, 1, *file_buffer_length, stream) != *file_buffer_length) {
841  g_critical("fread(3) failed: %s", strerror(errno));
842 
843  return (-6);
844  }
845 
846  if (fclose(stream)) {
847  g_critical("fclose(3) failed: %s", strerror(errno));
848 
849  return (-7);
850  }
851 
852  return (0);
853 }
854 
859 smf_t *
860 smf_load_from_memory(const void *buffer, const int buffer_length)
861 {
862  int i;
863 
864  smf_t *smf = smf_new();
865 
866  smf->file_buffer = (void *)buffer;
867  smf->file_buffer_length = buffer_length;
868  smf->next_chunk_offset = 0;
869 
870  if (parse_mthd_chunk(smf))
871  return (NULL);
872 
873  for (i = 1; i <= smf->expected_number_of_tracks; i++) {
874  smf_track_t *track = smf_track_new();
875  if (track == NULL)
876  return (NULL);
877 
878  smf_add_track(smf, track);
879 
880  /* Skip unparseable chunks. */
881  if (parse_mtrk_chunk(track)) {
882  g_warning("SMF warning: Cannot load track.");
883  smf_track_delete(track);
884  }
885 
886  track->file_buffer = NULL;
887  track->file_buffer_length = 0;
888  track->next_event_offset = -1;
889  }
890 
891  if (smf->expected_number_of_tracks != smf->number_of_tracks) {
892  g_warning("SMF warning: MThd header declared %d tracks, but only %d found; continuing anyway.",
894 
896  }
897 
898  smf->file_buffer = NULL;
899  smf->file_buffer_length = 0;
900  smf->next_chunk_offset = -1;
901 
902  return (smf);
903 }
904 
911 smf_t *
912 smf_load(const char *file_name)
913 {
914  int file_buffer_length;
915  void *file_buffer;
916  smf_t *smf;
917 
918  if (load_file_into_buffer(&file_buffer, &file_buffer_length, file_name))
919  return (NULL);
920 
921  smf = smf_load_from_memory(file_buffer, file_buffer_length);
922 
923  memset(file_buffer, 0, file_buffer_length);
924  free(file_buffer);
925 
926  if (smf == NULL)
927  return (NULL);
928 
929  smf_rewind(smf);
930 
931  return (smf);
932 }
933 
void smf_rewind(smf_t *smf)
Rewinds the SMF.
Definition: smf.c:899
SMF chunk, used only by smf_load.c and smf_save.c.
Definition: smf_private.h:59
int next_chunk_offset
Definition: smf.h:243
int last_status
Definition: smf.h:280
int format
Definition: smf.h:231
void * file_buffer
Definition: smf.h:241
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 chunk header, used only by smf_load.c and smf_save.c.
Definition: smf_private.h:53
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 "song", that is, collection of one or more tracks.
Definition: smf.h:230
Represents a single track.
Definition: smf.h:271
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 "division" field of MThd header.
Definition: smf.h:234
int smf_event_is_metadata(const smf_event_t *event) WARN_UNUSED_RESULT
Definition: smf_decode.c:57
void smf_event_delete(smf_event_t *event)
Detaches event from its track and frees it.
Definition: smf.c:363
smf_t * smf_load(const char *file_name)
Loads SMF file.
Definition: smf_load.c:912
int smf_event_is_system_common(const smf_event_t *event) WARN_UNUSED_RESULT
Definition: smf_decode.c:90
smf_t * smf
Definition: smf.h:272
int expected_number_of_tracks
Definition: smf.h:244
int smf_event_length_is_valid(const smf_event_t *event)
Definition: smf_load.c:718
int smf_event_is_sysex(const smf_event_t *event) WARN_UNUSED_RESULT
Definition: smf_decode.c:104
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 frames_per_second
Definition: smf.h:235
int number_of_tracks
Definition: smf.h:237
int next_event_offset
Private, used by smf.c.
Definition: smf.h:284
smf_event_t * smf_event_new(void)
Allocates new smf_event_t structure.
Definition: smf.c:217
int smf_event_is_system_realtime(const smf_event_t *event) WARN_UNUSED_RESULT
Definition: smf_decode.c:72
uint16_t number_of_tracks
Definition: smf_private.h:62
Public interface declaration for libsmf, Standard MIDI File format library.
int resolution
Definition: smf.h:236
int smf_event_is_textual(const smf_event_t *event)
Definition: smf_load.c:627
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
int file_buffer_length
Definition: smf.h:242
int file_buffer_length
Definition: smf.h:279
Represents a single MIDI event or metaevent.
Definition: smf.h:301
Private header.
void * file_buffer
These are private fields using only by loading and saving routines.
Definition: smf.h:278
uint16_t division
Definition: smf_private.h:63
void smf_track_delete(smf_track_t *track)
Detaches track from its smf and frees it.
Definition: smf.c:131
char * smf_event_extract_text(const smf_event_t *event)
Extracts text from "textual metaevents", such as Text or Lyric.
Definition: smf_load.c:647
smf_t * smf_load_from_memory(const void *buffer, const int buffer_length)
Creates new SMF and fills it with data loaded from the given buffer.
Definition: smf_load.c:860
smf_t * smf_new(void)
Allocates new smf_t structure.
Definition: smf.c:55
int smf_event_is_valid(const smf_event_t *event)
Definition: smf_load.c:745
smf_t * smf
Definition: smfsh.c:56