2 * Copyright (c) 2007, 2008 Edward Tomasz NapieraĆa <trasz@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
31 * Standard MIDI File writer.
35 /* Reference: http://www.borg.com/~jglatt/tech/midifile.htm */
42 #ifdef PLATFORM_WINDOWS
45 #include <arpa/inet.h>
48 #include "smf_private.h"
50 #define MAX_VLQ_LENGTH 128
53 * Extends (reallocates) smf->file_buffer and returns pointer to the newly added space,
54 * that is, pointer to the first byte after the previous buffer end. Returns NULL in case
58 smf_extend(smf_t *smf, const int length)
60 int i, previous_file_buffer_length = smf->file_buffer_length;
61 char *previous_file_buffer = (char*)smf->file_buffer;
63 /* XXX: Not terribly efficient. */
64 smf->file_buffer_length += length;
65 smf->file_buffer = realloc(smf->file_buffer, smf->file_buffer_length);
66 if (smf->file_buffer == NULL) {
67 g_critical("realloc(3) failed: %s", strerror(errno));
68 smf->file_buffer_length = 0;
72 /* Fix up pointers. XXX: omgwtf. */
73 for (i = 1; i <= smf->number_of_tracks; i++) {
75 track = smf_get_track_by_number(smf, i);
76 if (track->file_buffer != NULL)
77 track->file_buffer = (char *)track->file_buffer + ((char *)smf->file_buffer - previous_file_buffer);
80 return ((char *)smf->file_buffer + previous_file_buffer_length);
84 * Appends "buffer_length" bytes pointed to by "buffer" to the smf, reallocating storage as needed. Returns 0
85 * if everything went ok, different value if there was any problem.
88 smf_append(smf_t *smf, const void *buffer, const int buffer_length)
92 dest = smf_extend(smf, buffer_length);
94 g_critical("Cannot extend track buffer.");
98 memcpy(dest, buffer, buffer_length);
104 * Appends MThd header to the track. Returns 0 if everything went ok, different value if not.
107 write_mthd_header(smf_t *smf)
109 struct mthd_chunk_struct mthd_chunk;
111 memcpy(mthd_chunk.mthd_header.id, "MThd", 4);
112 mthd_chunk.mthd_header.length = htonl(6);
113 mthd_chunk.format = htons(smf->format);
114 mthd_chunk.number_of_tracks = htons(smf->number_of_tracks);
115 mthd_chunk.division = htons(smf->ppqn);
117 return (smf_append(smf, &mthd_chunk, sizeof(mthd_chunk)));
121 * Extends (reallocates) track->file_buffer and returns pointer to the newly added space,
122 * that is, pointer to the first byte after the previous buffer end. Returns NULL in case
126 track_extend(smf_track_t *track, const int length)
132 buf = smf_extend(track->smf, length);
136 track->file_buffer_length += length;
137 if (track->file_buffer == NULL)
138 track->file_buffer = buf;
144 * Appends "buffer_length" bytes pointed to by "buffer" to the track, reallocating storage as needed. Returns 0
145 * if everything went ok, different value if there was any problem.
148 track_append(smf_track_t *track, const void *buffer, const int buffer_length)
152 dest = track_extend(track, buffer_length);
154 g_critical("Cannot extend track buffer.");
158 memcpy(dest, buffer, buffer_length);
164 smf_format_vlq(unsigned char *buf, int length, unsigned long value)
167 unsigned long buffer;
169 /* Taken from http://www.borg.com/~jglatt/tech/midifile/vari.htm */
170 buffer = value & 0x7F;
172 while ((value >>= 7)) {
174 buffer |= ((value & 0x7F) | 0x80);
188 /* + 1, because "i" is an offset, not a count. */
193 smf_event_new_textual(int type, const char *text)
195 int vlq_length, text_length, copied_length;
198 assert(type >= 1 && type <= 9);
200 text_length = strlen(text);
202 event = smf_event_new();
206 /* "2 +" is for leading 0xFF 0xtype. */
207 event->midi_buffer_length = 2 + text_length + MAX_VLQ_LENGTH;
208 event->midi_buffer = (uint8_t*)malloc(event->midi_buffer_length);
209 if (event->midi_buffer == NULL) {
210 g_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno));
211 smf_event_delete(event);
216 event->midi_buffer[0] = 0xFF;
217 event->midi_buffer[1] = type;
219 vlq_length = smf_format_vlq(event->midi_buffer + 2, MAX_VLQ_LENGTH - 2, text_length);
220 copied_length = snprintf((char *)event->midi_buffer + vlq_length + 2, event->midi_buffer_length - vlq_length - 2, "%s", text);
223 (void) copied_length; /* stop gcc warning about unusued vars for non-debug build */
225 assert(copied_length == text_length);
228 event->midi_buffer_length = 2 + vlq_length + text_length;
234 * Appends value, expressed as Variable Length Quantity, to event->track.
237 write_vlq(smf_event_t *event, unsigned long value)
239 unsigned char buf[MAX_VLQ_LENGTH];
242 vlq_length = smf_format_vlq(buf, MAX_VLQ_LENGTH, value);
244 return (track_append(event->track, buf, vlq_length));
248 * Appends event time as Variable Length Quantity. Returns 0 if everything went ok,
249 * different value in case of error.
252 write_event_time(smf_event_t *event)
254 assert(event->delta_time_pulses >= 0);
256 return (write_vlq(event, event->delta_time_pulses));
260 write_sysex_contents(smf_event_t *event)
263 unsigned char sysex_status = 0xF0;
265 assert(smf_event_is_sysex(event));
267 ret = track_append(event->track, &sysex_status, 1);
271 /* -1, because length does not include status byte. */
272 ret = write_vlq(event, event->midi_buffer_length - 1);
276 ret = track_append(event->track, event->midi_buffer + 1, event->midi_buffer_length - 1);
284 * Appends contents of event->midi_buffer wrapped into 0xF7 MIDI event.
287 write_escaped_event_contents(smf_event_t *event)
290 unsigned char escape_status = 0xF7;
292 if (smf_event_is_sysex(event))
293 return (write_sysex_contents(event));
295 ret = track_append(event->track, &escape_status, 1);
299 ret = write_vlq(event, event->midi_buffer_length);
303 ret = track_append(event->track, event->midi_buffer, event->midi_buffer_length);
311 * Appends contents of event->midi_buffer. Returns 0 if everything went 0,
312 * different value in case of error.
315 write_event_contents(smf_event_t *event)
317 if (smf_event_is_system_realtime(event) || smf_event_is_system_common(event))
318 return (write_escaped_event_contents(event));
320 return (track_append(event->track, event->midi_buffer, event->midi_buffer_length));
324 * Writes out an event.
327 write_event(smf_event_t *event)
331 ret = write_event_time(event);
335 ret = write_event_contents(event);
343 * Writes out MTrk header, except of MTrk chunk length, which is written by write_mtrk_length().
346 write_mtrk_header(smf_track_t *track)
348 struct chunk_header_struct mtrk_header;
350 memcpy(mtrk_header.id, "MTrk", 4);
352 return (track_append(track, &mtrk_header, sizeof(mtrk_header)));
356 * Updates MTrk chunk length of a given track.
359 write_mtrk_length(smf_track_t *track)
361 struct chunk_header_struct *mtrk_header;
363 assert(track->file_buffer != NULL);
364 assert(track->file_buffer_length >= 6);
366 mtrk_header = (struct chunk_header_struct *)track->file_buffer;
367 mtrk_header->length = htonl(track->file_buffer_length - sizeof(struct chunk_header_struct));
373 * Writes out the track.
376 write_track(smf_track_t *track)
381 ret = write_mtrk_header(track);
385 while ((event = smf_track_get_next_event(track)) != NULL) {
386 ret = write_event(event);
391 ret = write_mtrk_length(track);
399 * Takes smf->file_buffer and saves it to the file.
402 write_file(smf_t *smf, FILE* stream)
404 if (fwrite(smf->file_buffer, 1, smf->file_buffer_length, stream) != smf->file_buffer_length) {
405 g_critical("fwrite(3) failed: %s", strerror(errno));
414 free_buffer(smf_t *smf)
419 /* Clear the pointers. */
420 memset(smf->file_buffer, 0, smf->file_buffer_length);
421 free(smf->file_buffer);
422 smf->file_buffer = NULL;
423 smf->file_buffer_length = 0;
425 for (i = 1; i <= smf->number_of_tracks; i++) {
426 track = smf_get_track_by_number(smf, i);
428 track->file_buffer = NULL;
429 track->file_buffer_length = 0;
436 * \return Nonzero, if all pointers supposed to be NULL are NULL. Triggers assertion if not.
439 pointers_are_clear(smf_t *smf)
444 if (smf->file_buffer != NULL) {
445 fprintf (stderr, "SFB != null but == %p\n", smf->file_buffer);
447 assert(smf->file_buffer == NULL);
448 assert(smf->file_buffer_length == 0);
450 for (i = 1; i <= smf->number_of_tracks; i++) {
451 track = smf_get_track_by_number(smf, i);
453 assert(track != NULL);
454 assert(track->file_buffer == NULL);
455 assert(track->file_buffer_length == 0);
464 * \return Nonzero, if event is End Of Track metaevent.
467 smf_event_is_eot(const smf_event_t *event)
469 if (event->midi_buffer_length != 3)
472 if (event->midi_buffer[0] != 0xFF || event->midi_buffer[1] != 0x2F || event->midi_buffer[2] != 0x00)
479 * Check if SMF is valid and add missing EOT events.
481 * \return 0, if SMF is valid.
484 smf_validate(smf_t *smf)
486 int trackno, eot_found;
491 if (smf->format < 0 || smf->format > 2) {
492 g_critical("SMF error: smf->format is less than zero of greater than two.");
496 if (smf->number_of_tracks < 1) {
497 g_critical("SMF error: number of tracks is less than one.");
501 if (smf->format == 0 && smf->number_of_tracks > 1) {
502 g_critical("SMF error: format is 0, but number of tracks is more than one.");
506 if (smf->ppqn <= 0) {
507 g_critical("SMF error: PPQN has to be > 0.");
511 for (trackno = 1; trackno <= smf->number_of_tracks; trackno++) {
512 track = smf_get_track_by_number(smf, trackno);
517 for (eventno = 1; eventno <= track->number_of_events; eventno++) {
518 event = smf_track_get_event_by_number(track, eventno);
521 if (!smf_event_is_valid(event)) {
522 g_critical("Event #%" G_GSIZE_FORMAT " on track #%d is invalid.", eventno, trackno);
526 if (smf_event_is_eot(event)) {
528 g_critical("Duplicate End Of Track event on track #%d.", trackno);
537 if (smf_track_add_eot_delta_pulses(track, 0)) {
538 g_critical("smf_track_add_eot_delta_pulses failed.");
550 #define CHECK(cond) if (!(cond)) { return -1; }
553 check_smf_event_is_identical(const smf_event_t *a, const smf_event_t *b)
555 CHECK(a->event_number == b->event_number);
556 CHECK(a->delta_time_pulses == b->delta_time_pulses);
557 CHECK(abs((long)(a->time_pulses - b->time_pulses)) <= 2);
558 CHECK(fabs(a->time_seconds - b->time_seconds) <= 0.01);
559 CHECK(a->track_number == b->track_number);
560 CHECK(a->midi_buffer_length == b->midi_buffer_length);
561 CHECK(memcmp(a->midi_buffer, b->midi_buffer, a->midi_buffer_length) == 0);
566 check_smf_track_is_identical(const smf_track_t *a, const smf_track_t *b)
570 CHECK(a->track_number == b->track_number);
571 CHECK(a->number_of_events == b->number_of_events);
573 for (i = 1; i <= a->number_of_events; i++)
574 check_smf_event_is_identical(smf_track_get_event_by_number(a, i), smf_track_get_event_by_number(b, i));
580 check_smf_is_identical(const smf_t *a, const smf_t *b)
584 CHECK(a->format == b->format);
585 CHECK(a->ppqn == b->ppqn);
586 CHECK(a->frames_per_second == b->frames_per_second);
587 CHECK(a->resolution == b->resolution);
588 CHECK(a->number_of_tracks == b->number_of_tracks);
590 for (i = 1; i <= a->number_of_tracks; i++)
591 check_smf_track_is_identical(smf_get_track_by_number(a, i), smf_get_track_by_number(b, i));
593 /* We do not need to compare tempos explicitly, as tempo is always computed from track contents. */
598 check_smf_saved_correctly(const smf_t *smf, FILE* file)
603 saved = smf_load (file);
607 ret = check_smf_is_identical(smf, saved);
617 * Writes the contents of SMF to the file given.
619 * \param file File descriptor.
620 * \return 0, if saving was successfull.
623 smf_save(smf_t *smf, FILE* file)
630 assert(pointers_are_clear(smf));
632 if (smf_validate(smf))
635 if (write_mthd_header(smf))
638 for (i = 1; i <= smf->number_of_tracks; i++) {
639 track = smf_get_track_by_number(smf, i);
641 assert(track != NULL);
643 error = write_track(track);
650 error = write_file(smf, file);
658 if (check_smf_saved_correctly(smf, file)) {
659 g_warning("SMF warning: Did not save correctly, possible data loss.");