smflite

view src/smf_load.c @ 2:d9e0d0500a78

added COPYING and README
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 26 Jan 2012 15:51:53 +0200
parents
children
line source
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 */
28 /**
29 * \file
30 *
31 * Standard MIDI File format loader.
32 *
33 */
35 /* Reference: http://www.borg.com/~jglatt/tech/midifile.htm */
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"
51 /**
52 * Returns pointer to the next SMF chunk in smf->buffer, based on length of the previous one.
53 * Returns NULL in case of error.
54 */
55 static struct chunk_header_struct *
56 next_chunk(smf_t *smf)
57 {
58 struct chunk_header_struct *chunk;
59 void *next_chunk_ptr;
61 assert(smf->file_buffer != NULL);
62 assert(smf->file_buffer_length > 0);
63 assert(smf->next_chunk_offset >= 0);
65 if (smf->next_chunk_offset + sizeof(struct chunk_header_struct) >= smf->file_buffer_length) {
66 fg_critical("SMF warning: no more chunks left.");
67 return (NULL);
68 }
70 next_chunk_ptr = (unsigned char *)smf->file_buffer + smf->next_chunk_offset;
72 chunk = (struct chunk_header_struct *)next_chunk_ptr;
74 if (!isalpha(chunk->id[0]) || !isalpha(chunk->id[1]) || !isalpha(chunk->id[2]) || !isalpha(chunk->id[3])) {
75 fg_critical("SMF error: chunk signature contains at least one non-alphanumeric byte.");
76 return (NULL);
77 }
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);
85 if (smf->next_chunk_offset > smf->file_buffer_length) {
86 fg_critical("SMF warning: malformed chunk; truncated file?");
87 smf->next_chunk_offset = smf->file_buffer_length;
88 }
90 return (chunk);
91 }
93 /**
94 * Returns 1, iff signature of the "chunk" is the same as string passed as "signature".
95 */
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);
102 return (0);
103 }
105 /**
106 * Verifies if MThd header looks OK. Returns 0 iff it does.
107 */
108 static int
109 parse_mthd_header(smf_t *smf)
110 {
111 int len;
112 struct chunk_header_struct *mthd, *tmp_mthd;
114 /* Make sure compiler didn't do anything stupid. */
115 assert(sizeof(struct chunk_header_struct) == 8);
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 fg_critical("SMF error: file is too short, it cannot be a MIDI file.");
124 return (-1);
125 }
127 tmp_mthd = smf->file_buffer;
129 if (!chunk_signature_matches(tmp_mthd, "MThd")) {
130 fg_critical("SMF error: MThd signature not found, is that a MIDI file?");
132 return (-2);
133 }
135 /* Ok, now use next_chunk(). */
136 mthd = next_chunk(smf);
137 if (mthd == NULL)
138 return (-3);
140 assert(mthd == tmp_mthd);
142 len = ntohl(mthd->length);
143 if (len != 6) {
144 fg_critical("SMF error: MThd chunk length %d, must be 6.", len);
146 return (-4);
147 }
149 return (0);
150 }
152 /**
153 * Parses MThd chunk, filling "smf" structure with values extracted from it. Returns 0 iff everything went OK.
154 */
155 static int
156 parse_mthd_chunk(smf_t *smf)
157 {
158 signed char first_byte_of_division, second_byte_of_division;
160 struct mthd_chunk_struct *mthd;
162 assert(sizeof(struct mthd_chunk_struct) == 14);
164 if (parse_mthd_header(smf))
165 return (1);
167 mthd = (struct mthd_chunk_struct *)smf->file_buffer;
169 smf->format = ntohs(mthd->format);
170 if (smf->format < 0 || smf->format > 2) {
171 fg_critical("SMF error: bad MThd format field value: %d, valid values are 0-2, inclusive.", smf->format);
172 return (-1);
173 }
175 if (smf->format == 2) {
176 fg_critical("SMF file uses format #2, no support for that yet.");
177 return (-2);
178 }
180 smf->expected_number_of_tracks = ntohs(mthd->number_of_tracks);
181 if (smf->expected_number_of_tracks <= 0) {
182 fg_critical("SMF error: bad number of tracks: %d, must be greater than zero.", smf->expected_number_of_tracks);
183 return (-3);
184 }
186 /* XXX: endianess? */
187 first_byte_of_division = *((signed char *)&(mthd->division));
188 second_byte_of_division = *((signed char *)&(mthd->division) + 1);
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 }
200 if (smf->ppqn == 0) {
201 fg_critical("SMF file uses FPS timing instead of PPQN, no support for that yet.");
202 return (-4);
203 }
205 return (0);
206 }
208 /**
209 * Interprets Variable Length Quantity pointed at by "buf" and puts its value into "value" and number
210 * of bytes consumed into "len", making sure it does not read past "buf" + "buffer_length".
211 * Explanation of Variable Length Quantities is here: http://www.borg.com/~jglatt/tech/midifile/vari.htm
212 * Returns 0 iff everything went OK, different value in case of error.
213 */
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;
220 assert(buffer_length > 0);
222 for (;;) {
223 if (c >= buf + buffer_length) {
224 fg_critical("End of buffer in extract_vlq().");
225 return (-1);
226 }
228 val = (val << 7) + (*c & 0x7F);
230 if (*c & 0x80)
231 c++;
232 else
233 break;
234 };
236 *value = val;
237 *len = c - buf + 1;
239 if (*len > 4) {
240 fg_critical("SMF error: Variable Length Quantities longer than four bytes are not supported yet.");
241 return (-2);
242 }
244 return (0);
245 }
247 /**
248 * Returns 1 if the given byte is a valid status byte, 0 otherwise.
249 */
250 int
251 is_status_byte(const unsigned char status)
252 {
253 return (status & 0x80);
254 }
256 static int
257 is_sysex_byte(const unsigned char status)
258 {
259 if (status == 0xF0)
260 return (1);
262 return (0);
263 }
265 static int
266 is_escape_byte(const unsigned char status)
267 {
268 if (status == 0xF7)
269 return (1);
271 return (0);
272 }
274 /**
275 * Just like expected_message_length(), but only for System Exclusive messages.
276 * Note that value returned by this thing here is the length of SysEx "on the wire",
277 * not the number of bytes that this sysex takes in the file - in SMF format sysex
278 * contains VLQ telling how many bytes it takes, "on the wire" format does not have
279 * this.
280 */
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;
286 assert(status == 0xF0);
288 if (buffer_length < 3) {
289 fg_critical("SMF error: end of buffer in expected_sysex_length().");
290 return (-1);
291 }
293 if (extract_vlq(second_byte, buffer_length, &sysex_length, &len))
294 return (-1);
296 if (consumed_bytes != NULL)
297 *consumed_bytes = len;
299 /* +1, because the length does not include status byte. */
300 return (sysex_length + 1);
301 }
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 }
310 /**
311 * Returns expected length of the midi message (including the status byte), in bytes, for the given status byte.
312 * The "second_byte" points to the expected second byte of the MIDI message. "buffer_length" is the buffer
313 * length limit, counting from "second_byte". Returns value < 0 iff there was an error.
314 */
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));
321 /* We cannot use this routine for sysexes. */
322 assert(!is_sysex_byte(status));
324 /* We cannot use this routine for escaped events. */
325 assert(!is_escape_byte(status));
327 /* Buffer length may be zero, for e.g. realtime messages. */
328 assert(buffer_length >= 0);
330 /* Is this a metamessage? */
331 if (status == 0xFF) {
332 if (buffer_length < 2) {
333 fg_critical("SMF error: end of buffer in expected_message_length().");
334 return (-1);
335 }
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 }
344 if ((status & 0xF0) == 0xF0) {
345 switch (status) {
346 case 0xF2: /* Song Position Pointer. */
347 return (3);
349 case 0xF1: /* MTC Quarter Frame. */
350 case 0xF3: /* Song Select. */
351 return (2);
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);
362 default:
363 fg_critical("SMF error: unknown 0xFx-type status byte '0x%x'.", status);
364 return (-2);
365 }
366 }
368 /* Filter out the channel. */
369 status &= 0xF0;
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);
379 case 0xC0: /* Program Change. */
380 case 0xD0: /* Channel Pressure. */
381 return (2);
383 default:
384 fg_critical("SMF error: unknown status byte '0x%x'.", status);
385 return (-3);
386 }
387 }
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;
395 status = *buf;
397 assert(is_sysex_byte(status));
399 c++;
401 message_length = expected_sysex_length(status, c, buffer_length - 1, &vlq_length);
403 if (message_length < 0)
404 return (-3);
406 c += vlq_length;
408 if (vlq_length + message_length >= buffer_length) {
409 fg_critical("End of buffer in extract_sysex_event().");
410 return (-5);
411 }
413 event->midi_buffer_length = message_length;
414 event->midi_buffer = malloc(event->midi_buffer_length);
415 if (event->midi_buffer == NULL) {
416 fg_critical("Cannot allocate memory in extract_sysex_event(): %s", strerror(errno));
417 return (-4);
418 }
420 event->midi_buffer[0] = status;
421 memcpy(event->midi_buffer + 1, c, message_length - 1);
423 *len = vlq_length + message_length;
425 return (0);
426 }
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;
434 status = *buf;
436 assert(is_escape_byte(status));
438 c++;
440 message_length = expected_escaped_length(status, c, buffer_length - 1, &vlq_length);
442 if (message_length < 0)
443 return (-3);
445 c += vlq_length;
447 if (vlq_length + message_length >= buffer_length) {
448 fg_critical("End of buffer in extract_escaped_event().");
449 return (-5);
450 }
452 event->midi_buffer_length = message_length;
453 event->midi_buffer = malloc(event->midi_buffer_length);
454 if (event->midi_buffer == NULL) {
455 fg_critical("Cannot allocate memory in extract_escaped_event(): %s", strerror(errno));
456 return (-4);
457 }
459 memcpy(event->midi_buffer, c, message_length);
461 if (smf_event_is_valid(event)) {
462 fg_critical("Escaped event is invalid.");
463 return (-1);
464 }
466 if (smf_event_is_system_realtime(event) || smf_event_is_system_common(event)) {
467 fg_warning("Escaped event is not System Realtime nor System Common.");
468 }
470 *len = vlq_length + message_length;
472 return (0);
473 }
476 /**
477 * Puts MIDI data extracted from from "buf" into "event" and number of consumed bytes into "len".
478 * In case valid status is not found, it uses "last_status" (so called "running status").
479 * Returns 0 iff everything went OK, value < 0 in case of error.
480 */
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;
487 assert(buffer_length > 0);
489 /* Is the first byte the status byte? */
490 if (is_status_byte(*c)) {
491 status = *c;
492 c++;
494 } else {
495 /* No, we use running status then. */
496 status = last_status;
497 }
499 if (!is_status_byte(status)) {
500 fg_critical("SMF error: bad status byte (MSB is zero).");
501 return (-1);
502 }
504 if (is_sysex_byte(status))
505 return (extract_sysex_event(buf, buffer_length, event, len, last_status));
507 if (is_escape_byte(status))
508 return (extract_escaped_event(buf, buffer_length, event, len, last_status));
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));
513 if (message_length < 0)
514 return (-3);
516 if (message_length - 1 > buffer_length - (c - buf)) {
517 fg_critical("End of buffer in extract_midi_event().");
518 return (-5);
519 }
521 event->midi_buffer_length = message_length;
522 event->midi_buffer = malloc(event->midi_buffer_length);
523 if (event->midi_buffer == NULL) {
524 fg_critical("Cannot allocate memory in extract_midi_event(): %s", strerror(errno));
525 return (-4);
526 }
528 event->midi_buffer[0] = status;
529 memcpy(event->midi_buffer + 1, c, message_length - 1);
531 *len = c + message_length - 1 - buf;
533 return (0);
534 }
536 /**
537 * Locates, basing on track->next_event_offset, the next event data in track->buffer,
538 * interprets it, allocates smf_event_t and fills it properly. Returns smf_event_t
539 * or NULL, if there was an error. Allocating event means adding it to the track;
540 * see smf_event_new().
541 */
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;
548 smf_event_t *event = smf_event_new();
549 if (event == NULL)
550 goto error;
552 c = start = (unsigned char *)track->file_buffer + track->next_event_offset;
554 assert(track->file_buffer != NULL);
555 assert(track->file_buffer_length > 0);
556 assert(track->next_event_offset > 0);
558 buffer_length = track->file_buffer_length - track->next_event_offset;
559 assert(buffer_length > 0);
561 /* First, extract time offset from previous event. */
562 if (extract_vlq(c, buffer_length, &time, &len))
563 goto error;
565 c += len;
566 buffer_length -= len;
568 if (buffer_length <= 0)
569 goto error;
571 /* Now, extract the actual event. */
572 if (extract_midi_event(c, buffer_length, event, &len, track->last_status))
573 goto error;
575 c += len;
576 buffer_length -= len;
577 track->last_status = event->midi_buffer[0];
578 track->next_event_offset += c - start;
580 smf_track_add_event_delta_pulses(track, event, time);
582 return (event);
584 error:
585 if (event != NULL)
586 smf_event_delete(event);
588 return (NULL);
589 }
591 /**
592 * Takes "len" characters starting in "buf", making sure it does not access past the length of the buffer,
593 * and makes ordinary, zero-terminated string from it. May return NULL if there was any problem.
594 */
595 static char *
596 make_string(const unsigned char *buf, const int buffer_length, int len)
597 {
598 char *str;
600 assert(buffer_length > 0);
601 assert(len > 0);
603 if (len > buffer_length) {
604 fg_critical("End of buffer in make_string().");
606 len = buffer_length;
607 }
609 str = malloc(len + 1);
610 if (str == NULL) {
611 fg_critical("Cannot allocate memory in make_string().");
612 return (NULL);
613 }
615 memcpy(str, buf, len);
616 str[len] = '\0';
618 return (str);
619 }
621 /**
622 * \return 1, if passed a metaevent containing text, that is, Text, Copyright,
623 * Sequence/Track Name, Instrument, Lyric, Marker, Cue Point, Program Name,
624 * or Device Name; 0 otherwise.
625 */
626 int
627 smf_event_is_textual(const smf_event_t *event)
628 {
629 if (!smf_event_is_metadata(event))
630 return (0);
632 if (event->midi_buffer_length < 4)
633 return (0);
635 if (event->midi_buffer[3] < 1 && event->midi_buffer[3] > 9)
636 return (0);
638 return (1);
639 }
641 /**
642 * Extracts text from "textual metaevents", such as Text or Lyric.
643 *
644 * \return Zero-terminated string extracted from "text events" or NULL, if there was any problem.
645 */
646 char *
647 smf_event_extract_text(const smf_event_t *event)
648 {
649 int string_length = -1, length_length = -1;
651 if (!smf_event_is_textual(event))
652 return (NULL);
654 if (event->midi_buffer_length < 3) {
655 fg_critical("smf_event_extract_text: truncated MIDI message.");
656 return (NULL);
657 }
659 extract_vlq((void *)&(event->midi_buffer[2]), event->midi_buffer_length - 2, &string_length, &length_length);
661 if (string_length <= 0) {
662 fg_critical("smf_event_extract_text: truncated MIDI message.");
663 return (NULL);
664 }
666 return (make_string((void *)(&event->midi_buffer[2] + length_length), event->midi_buffer_length - 2 - length_length, string_length));
667 }
669 /**
670 * Verify if the next chunk really is MTrk chunk, and if so, initialize some track variables and return 0.
671 * Return different value otherwise.
672 */
673 static int
674 parse_mtrk_header(smf_track_t *track)
675 {
676 struct chunk_header_struct *mtrk;
678 /* Make sure compiler didn't do anything stupid. */
679 assert(sizeof(struct chunk_header_struct) == 8);
680 assert(track->smf != NULL);
682 mtrk = next_chunk(track->smf);
684 if (mtrk == NULL)
685 return (-1);
687 if (!chunk_signature_matches(mtrk, "MTrk")) {
688 fg_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]);
691 return (-2);
692 }
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);
698 return (0);
699 }
701 /**
702 * Return 1 if event is end-of-the-track, 0 otherwise.
703 */
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);
710 return (0);
711 }
713 /**
714 * \return Nonzero, if event is as long as it should be, from the MIDI specification point of view.
715 * Does not work for SysExes - it doesn't recognize internal structure of SysEx.
716 */
717 int
718 smf_event_length_is_valid(const smf_event_t *event)
719 {
720 assert(event);
721 assert(event->midi_buffer);
723 if (event->midi_buffer_length < 1)
724 return (0);
726 /* We cannot use expected_message_length on sysexes. */
727 if (smf_event_is_sysex(event))
728 return (1);
730 if (event->midi_buffer_length != expected_message_length(event->midi_buffer[0],
731 &(event->midi_buffer[1]), event->midi_buffer_length - 1)) {
733 return (0);
734 }
736 return (1);
737 }
739 /**
740 * \return Nonzero, if MIDI data in the event is valid, 0 otherwise. For example,
741 * it checks if event length is correct.
742 */
743 /* XXX: this routine requires some more work to detect more errors. */
744 int
745 smf_event_is_valid(const smf_event_t *event)
746 {
747 assert(event);
748 assert(event->midi_buffer);
749 assert(event->midi_buffer_length >= 1);
751 if (!is_status_byte(event->midi_buffer[0])) {
752 fg_critical("First byte of MIDI message is not a valid status byte.");
754 return (0);
755 }
757 if (!smf_event_length_is_valid(event))
758 return (0);
760 return (1);
761 }
763 /**
764 * Parse events and put it on the track.
765 */
766 static int
767 parse_mtrk_chunk(smf_track_t *track)
768 {
769 smf_event_t *event;
771 if (parse_mtrk_header(track))
772 return (-1);
774 for (;;) {
775 event = parse_next_event(track);
777 /* Couldn't parse an event? */
778 if (event == NULL) {
779 fg_critical("Unable to parse MIDI event; truncating track.");
780 if (smf_track_add_eot_delta_pulses(track, 0) != 0) {
781 fg_critical("smf_track_add_eot_delta_pulses failed.");
782 return (-2);
783 }
784 break;
785 }
787 assert(smf_event_is_valid(event));
789 if (event_is_end_of_track(event))
790 break;
791 }
793 track->file_buffer = NULL;
794 track->file_buffer_length = 0;
795 track->next_event_offset = -1;
797 return (0);
798 }
800 /**
801 * Allocate buffer of proper size and read file contents into it. Close file afterwards.
802 */
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");
808 if (stream == NULL) {
809 fg_critical("Cannot open input file: %s", strerror(errno));
811 return (-1);
812 }
814 if (fseek(stream, 0, SEEK_END)) {
815 fg_critical("fseek(3) failed: %s", strerror(errno));
817 return (-2);
818 }
820 *file_buffer_length = ftell(stream);
821 if (*file_buffer_length == -1) {
822 fg_critical("ftell(3) failed: %s", strerror(errno));
824 return (-3);
825 }
827 if (fseek(stream, 0, SEEK_SET)) {
828 fg_critical("fseek(3) failed: %s", strerror(errno));
830 return (-4);
831 }
833 *file_buffer = malloc(*file_buffer_length);
834 if (*file_buffer == NULL) {
835 fg_critical("malloc(3) failed: %s", strerror(errno));
837 return (-5);
838 }
840 if (fread(*file_buffer, 1, *file_buffer_length, stream) != *file_buffer_length) {
841 fg_critical("fread(3) failed: %s", strerror(errno));
843 return (-6);
844 }
846 if (fclose(stream)) {
847 fg_critical("fclose(3) failed: %s", strerror(errno));
849 return (-7);
850 }
852 return (0);
853 }
855 /**
856 * Creates new SMF and fills it with data loaded from the given buffer.
857 * \return SMF or NULL, if loading failed.
858 */
859 smf_t *
860 smf_load_from_memory(const void *buffer, const int buffer_length)
861 {
862 int i;
864 smf_t *smf = smf_new();
866 smf->file_buffer = (void *)buffer;
867 smf->file_buffer_length = buffer_length;
868 smf->next_chunk_offset = 0;
870 if (parse_mthd_chunk(smf))
871 return (NULL);
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);
878 smf_add_track(smf, track);
880 /* Skip unparseable chunks. */
881 if (parse_mtrk_chunk(track)) {
882 fg_warning("SMF warning: Cannot load track.");
883 smf_track_delete(track);
884 }
886 track->file_buffer = NULL;
887 track->file_buffer_length = 0;
888 track->next_event_offset = -1;
889 }
891 if (smf->expected_number_of_tracks != smf->number_of_tracks) {
892 fg_warning("SMF warning: MThd header declared %d tracks, but only %d found; continuing anyway.",
893 smf->expected_number_of_tracks, smf->number_of_tracks);
895 smf->expected_number_of_tracks = smf->number_of_tracks;
896 }
898 smf->file_buffer = NULL;
899 smf->file_buffer_length = 0;
900 smf->next_chunk_offset = -1;
902 return (smf);
903 }
905 /**
906 * Loads SMF file.
907 *
908 * \param file_name Path to the file.
909 * \return SMF or NULL, if loading failed.
910 */
911 smf_t *
912 smf_load(const char *file_name)
913 {
914 int file_buffer_length;
915 void *file_buffer;
916 smf_t *smf;
918 if (load_file_into_buffer(&file_buffer, &file_buffer_length, file_name))
919 return (NULL);
921 smf = smf_load_from_memory(file_buffer, file_buffer_length);
923 memset(file_buffer, 0, file_buffer_length);
924 free(file_buffer);
926 if (smf == NULL)
927 return (NULL);
929 smf_rewind(smf);
931 return (smf);
932 }