00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00035
00036
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <assert.h>
00040 #include <math.h>
00041 #include <errno.h>
00042 #ifdef __MINGW32__
00043 #include <windows.h>
00044 #else
00045 #include <arpa/inet.h>
00046 #endif
00047 #include "smf.h"
00048 #include "smf_private.h"
00049
00050 #define MAX_VLQ_LENGTH 128
00051
00057 static void *
00058 smf_extend(smf_t *smf, const int length)
00059 {
00060 int i, previous_file_buffer_length = smf->file_buffer_length;
00061 char *previous_file_buffer = smf->file_buffer;
00062
00063
00064 smf->file_buffer_length += length;
00065 smf->file_buffer = realloc(smf->file_buffer, smf->file_buffer_length);
00066 if (smf->file_buffer == NULL) {
00067 g_critical("realloc(3) failed: %s", strerror(errno));
00068 smf->file_buffer_length = 0;
00069 return (NULL);
00070 }
00071
00072
00073 for (i = 1; i <= smf->number_of_tracks; i++) {
00074 smf_track_t *track;
00075 track = smf_get_track_by_number(smf, i);
00076 if (track->file_buffer != NULL)
00077 track->file_buffer = (char *)track->file_buffer + ((char *)smf->file_buffer - previous_file_buffer);
00078 }
00079
00080 return ((char *)smf->file_buffer + previous_file_buffer_length);
00081 }
00082
00087 static int
00088 smf_append(smf_t *smf, const void *buffer, const int buffer_length)
00089 {
00090 void *dest;
00091
00092 dest = smf_extend(smf, buffer_length);
00093 if (dest == NULL) {
00094 g_critical("Cannot extend track buffer.");
00095 return (-1);
00096 }
00097
00098 memcpy(dest, buffer, buffer_length);
00099
00100 return (0);
00101 }
00102
00106 static int
00107 write_mthd_header(smf_t *smf)
00108 {
00109 struct mthd_chunk_struct mthd_chunk;
00110
00111 memcpy(mthd_chunk.mthd_header.id, "MThd", 4);
00112 mthd_chunk.mthd_header.length = htonl(6);
00113 mthd_chunk.format = htons(smf->format);
00114 mthd_chunk.number_of_tracks = htons(smf->number_of_tracks);
00115 mthd_chunk.division = htons(smf->ppqn);
00116
00117 return (smf_append(smf, &mthd_chunk, sizeof(mthd_chunk)));
00118 }
00119
00125 static void *
00126 track_extend(smf_track_t *track, const int length)
00127 {
00128 void *buf;
00129
00130 assert(track->smf);
00131
00132 buf = smf_extend(track->smf, length);
00133 if (buf == NULL)
00134 return (NULL);
00135
00136 track->file_buffer_length += length;
00137 if (track->file_buffer == NULL)
00138 track->file_buffer = buf;
00139
00140 return (buf);
00141 }
00142
00147 static int
00148 track_append(smf_track_t *track, const void *buffer, const int buffer_length)
00149 {
00150 void *dest;
00151
00152 dest = track_extend(track, buffer_length);
00153 if (dest == NULL) {
00154 g_critical("Cannot extend track buffer.");
00155 return (-1);
00156 }
00157
00158 memcpy(dest, buffer, buffer_length);
00159
00160 return (0);
00161 }
00162
00163 static int
00164 format_vlq(unsigned char *buf, int length, unsigned long value)
00165 {
00166 int i;
00167 unsigned long buffer;
00168
00169
00170 buffer = value & 0x7F;
00171
00172 while ((value >>= 7)) {
00173 buffer <<= 8;
00174 buffer |= ((value & 0x7F) | 0x80);
00175 }
00176
00177 for (i = 0;; i++) {
00178 buf[i] = buffer;
00179
00180 if (buffer & 0x80)
00181 buffer >>= 8;
00182 else
00183 break;
00184 }
00185
00186 assert(i <= length);
00187
00188
00189 return (i + 1);
00190 }
00191
00192 smf_event_t *
00193 smf_event_new_textual(int type, const char *text)
00194 {
00195 int vlq_length, text_length, copied_length;
00196 smf_event_t *event;
00197
00198 assert(type >= 1 && type <= 9);
00199
00200 text_length = strlen(text);
00201
00202 event = smf_event_new();
00203 if (event == NULL)
00204 return (NULL);
00205
00206
00207 event->midi_buffer_length = 2 + text_length + MAX_VLQ_LENGTH;
00208 event->midi_buffer = malloc(event->midi_buffer_length);
00209 if (event->midi_buffer == NULL) {
00210 g_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno));
00211 smf_event_delete(event);
00212
00213 return (NULL);
00214 }
00215
00216 event->midi_buffer[0] = 0xFF;
00217 event->midi_buffer[1] = type;
00218
00219 vlq_length = format_vlq(event->midi_buffer + 2, MAX_VLQ_LENGTH - 2, text_length);
00220 copied_length = snprintf((char *)event->midi_buffer + vlq_length + 2, event->midi_buffer_length - vlq_length - 2, "%s", text);
00221
00222 assert(copied_length == text_length);
00223
00224 event->midi_buffer_length = 2 + vlq_length + text_length;
00225
00226 return event;
00227 }
00228
00232 static int
00233 write_vlq(smf_event_t *event, unsigned long value)
00234 {
00235 unsigned char buf[MAX_VLQ_LENGTH];
00236 int vlq_length;
00237
00238 vlq_length = format_vlq(buf, MAX_VLQ_LENGTH, value);
00239
00240 return (track_append(event->track, buf, vlq_length));
00241 }
00242
00247 static int
00248 write_event_time(smf_event_t *event)
00249 {
00250 assert(event->delta_time_pulses >= 0);
00251
00252 return (write_vlq(event, event->delta_time_pulses));
00253 }
00254
00255 static int
00256 write_sysex_contents(smf_event_t *event)
00257 {
00258 int ret;
00259 unsigned char sysex_status = 0xF0;
00260
00261 assert(smf_event_is_sysex(event));
00262
00263 ret = track_append(event->track, &sysex_status, 1);
00264 if (ret)
00265 return (ret);
00266
00267
00268 ret = write_vlq(event, event->midi_buffer_length - 1);
00269 if (ret)
00270 return (ret);
00271
00272 ret = track_append(event->track, event->midi_buffer + 1, event->midi_buffer_length - 1);
00273 if (ret)
00274 return (ret);
00275
00276 return (0);
00277 }
00278
00282 static int
00283 write_escaped_event_contents(smf_event_t *event)
00284 {
00285 int ret;
00286 unsigned char escape_status = 0xF7;
00287
00288 if (smf_event_is_sysex(event))
00289 return (write_sysex_contents(event));
00290
00291 ret = track_append(event->track, &escape_status, 1);
00292 if (ret)
00293 return (ret);
00294
00295 ret = write_vlq(event, event->midi_buffer_length);
00296 if (ret)
00297 return (ret);
00298
00299 ret = track_append(event->track, event->midi_buffer, event->midi_buffer_length);
00300 if (ret)
00301 return (ret);
00302
00303 return (0);
00304 }
00305
00310 static int
00311 write_event_contents(smf_event_t *event)
00312 {
00313 if (smf_event_is_system_realtime(event) || smf_event_is_system_common(event))
00314 return (write_escaped_event_contents(event));
00315
00316 return (track_append(event->track, event->midi_buffer, event->midi_buffer_length));
00317 }
00318
00322 static int
00323 write_event(smf_event_t *event)
00324 {
00325 int ret;
00326
00327 ret = write_event_time(event);
00328 if (ret)
00329 return (ret);
00330
00331 ret = write_event_contents(event);
00332 if (ret)
00333 return (ret);
00334
00335 return (0);
00336 }
00337
00341 static int
00342 write_mtrk_header(smf_track_t *track)
00343 {
00344 struct chunk_header_struct mtrk_header;
00345
00346 memcpy(mtrk_header.id, "MTrk", 4);
00347
00348 return (track_append(track, &mtrk_header, sizeof(mtrk_header)));
00349 }
00350
00354 static int
00355 write_mtrk_length(smf_track_t *track)
00356 {
00357 struct chunk_header_struct *mtrk_header;
00358
00359 assert(track->file_buffer != NULL);
00360 assert(track->file_buffer_length >= 6);
00361
00362 mtrk_header = (struct chunk_header_struct *)track->file_buffer;
00363 mtrk_header->length = htonl(track->file_buffer_length - sizeof(struct chunk_header_struct));
00364
00365 return (0);
00366 }
00367
00371 static int
00372 write_track(smf_track_t *track)
00373 {
00374 int ret;
00375 smf_event_t *event;
00376
00377 ret = write_mtrk_header(track);
00378 if (ret)
00379 return (ret);
00380
00381 while ((event = smf_track_get_next_event(track)) != NULL) {
00382 ret = write_event(event);
00383 if (ret)
00384 return (ret);
00385 }
00386
00387 ret = write_mtrk_length(track);
00388 if (ret)
00389 return (ret);
00390
00391 return (0);
00392 }
00393
00397 static int
00398 write_file(smf_t *smf, const char *file_name)
00399 {
00400 FILE *stream;
00401
00402 stream = fopen(file_name, "wb+");
00403 if (stream == NULL) {
00404 g_critical("Cannot open input file: %s", strerror(errno));
00405
00406 return (-1);
00407 }
00408
00409 if (fwrite(smf->file_buffer, 1, smf->file_buffer_length, stream) != smf->file_buffer_length) {
00410 g_critical("fwrite(3) failed: %s", strerror(errno));
00411
00412 return (-2);
00413 }
00414
00415 if (fclose(stream)) {
00416 g_critical("fclose(3) failed: %s", strerror(errno));
00417
00418 return (-3);
00419 }
00420
00421 return (0);
00422 }
00423
00424 static void
00425 free_buffer(smf_t *smf)
00426 {
00427 int i;
00428 smf_track_t *track;
00429
00430
00431 memset(smf->file_buffer, 0, smf->file_buffer_length);
00432 free(smf->file_buffer);
00433 smf->file_buffer = NULL;
00434 smf->file_buffer_length = 0;
00435
00436 for (i = 1; i <= smf->number_of_tracks; i++) {
00437 track = smf_get_track_by_number(smf, i);
00438 assert(track);
00439 track->file_buffer = NULL;
00440 track->file_buffer_length = 0;
00441 }
00442 }
00443
00444 #ifndef NDEBUG
00445
00449 static int
00450 pointers_are_clear(smf_t *smf)
00451 {
00452 int i;
00453
00454 smf_track_t *track;
00455 assert(smf->file_buffer == NULL);
00456 assert(smf->file_buffer_length == 0);
00457
00458 for (i = 1; i <= smf->number_of_tracks; i++) {
00459 track = smf_get_track_by_number(smf, i);
00460
00461 assert(track != NULL);
00462 assert(track->file_buffer == NULL);
00463 assert(track->file_buffer_length == 0);
00464 }
00465
00466 return (1);
00467 }
00468
00469 #endif
00470
00474 int
00475 smf_event_is_eot(const smf_event_t *event)
00476 {
00477 if (event->midi_buffer_length != 3)
00478 return (0);
00479
00480 if (event->midi_buffer[0] != 0xFF || event->midi_buffer[1] != 0x2F || event->midi_buffer[2] != 0x00)
00481 return (0);
00482
00483 return (1);
00484 }
00485
00491 static int
00492 smf_validate(smf_t *smf)
00493 {
00494 int trackno, eventno, eot_found;
00495 smf_track_t *track;
00496 smf_event_t *event;
00497
00498 if (smf->format < 0 || smf->format > 2) {
00499 g_critical("SMF error: smf->format is less than zero of greater than two.");
00500 return (-1);
00501 }
00502
00503 if (smf->number_of_tracks < 1) {
00504 g_critical("SMF error: number of tracks is less than one.");
00505 return (-2);
00506 }
00507
00508 if (smf->format == 0 && smf->number_of_tracks > 1) {
00509 g_critical("SMF error: format is 0, but number of tracks is more than one.");
00510 return (-3);
00511 }
00512
00513 if (smf->ppqn <= 0) {
00514 g_critical("SMF error: PPQN has to be > 0.");
00515 return (-4);
00516 }
00517
00518 for (trackno = 1; trackno <= smf->number_of_tracks; trackno++) {
00519 track = smf_get_track_by_number(smf, trackno);
00520 assert(track);
00521
00522 eot_found = 0;
00523
00524 for (eventno = 1; eventno <= track->number_of_events; eventno++) {
00525 event = smf_track_get_event_by_number(track, eventno);
00526 assert(event);
00527
00528 if (!smf_event_is_valid(event)) {
00529 g_critical("Event #%d on track #%d is invalid.", eventno, trackno);
00530 return (-5);
00531 }
00532
00533 if (smf_event_is_eot(event)) {
00534 if (eot_found) {
00535 g_critical("Duplicate End Of Track event on track #%d.", trackno);
00536 return (-6);
00537 }
00538
00539 eot_found = 1;
00540 }
00541 }
00542
00543 if (!eot_found) {
00544 if (smf_track_add_eot_delta_pulses(track, 0)) {
00545 g_critical("smf_track_add_eot_delta_pulses failed.");
00546 return (-6);
00547 }
00548 }
00549
00550 }
00551
00552 return (0);
00553 }
00554
00555 #ifndef NDEBUG
00556
00557 static void
00558 assert_smf_event_is_identical(const smf_event_t *a, const smf_event_t *b)
00559 {
00560 assert(a->event_number == b->event_number);
00561 assert(a->delta_time_pulses == b->delta_time_pulses);
00562 assert(abs(a->time_pulses - b->time_pulses) <= 2);
00563 assert(fabs(a->time_seconds - b->time_seconds) <= 0.01);
00564 assert(a->track_number == b->track_number);
00565 assert(a->midi_buffer_length == b->midi_buffer_length);
00566 assert(memcmp(a->midi_buffer, b->midi_buffer, a->midi_buffer_length) == 0);
00567 }
00568
00569 static void
00570 assert_smf_track_is_identical(const smf_track_t *a, const smf_track_t *b)
00571 {
00572 int i;
00573
00574 assert(a->track_number == b->track_number);
00575 assert(a->number_of_events == b->number_of_events);
00576
00577 for (i = 1; i <= a->number_of_events; i++)
00578 assert_smf_event_is_identical(smf_track_get_event_by_number(a, i), smf_track_get_event_by_number(b, i));
00579 }
00580
00581 static void
00582 assert_smf_is_identical(const smf_t *a, const smf_t *b)
00583 {
00584 int i;
00585
00586 assert(a->format == b->format);
00587 assert(a->ppqn == b->ppqn);
00588 assert(a->frames_per_second == b->frames_per_second);
00589 assert(a->resolution == b->resolution);
00590 assert(a->number_of_tracks == b->number_of_tracks);
00591
00592 for (i = 1; i <= a->number_of_tracks; i++)
00593 assert_smf_track_is_identical(smf_get_track_by_number(a, i), smf_get_track_by_number(b, i));
00594
00595
00596 }
00597
00598 static void
00599 assert_smf_saved_correctly(const smf_t *smf, const char *file_name)
00600 {
00601 smf_t *saved;
00602
00603 saved = smf_load(file_name);
00604 assert(saved != NULL);
00605
00606 assert_smf_is_identical(smf, saved);
00607
00608 smf_delete(saved);
00609 }
00610
00611 #endif
00612
00619 int
00620 smf_save(smf_t *smf, const char *file_name)
00621 {
00622 int i, error;
00623 smf_track_t *track;
00624
00625 smf_rewind(smf);
00626
00627 assert(pointers_are_clear(smf));
00628
00629 if (smf_validate(smf))
00630 return (-1);
00631
00632 if (write_mthd_header(smf))
00633 return (-2);
00634
00635 for (i = 1; i <= smf->number_of_tracks; i++) {
00636 track = smf_get_track_by_number(smf, i);
00637
00638 assert(track != NULL);
00639
00640 error = write_track(track);
00641 if (error) {
00642 free_buffer(smf);
00643 return (error);
00644 }
00645 }
00646
00647 error = write_file(smf, file_name);
00648
00649 free_buffer(smf);
00650
00651 if (error)
00652 return (error);
00653
00654 #ifndef NDEBUG
00655 assert_smf_saved_correctly(smf, file_name);
00656 #endif
00657
00658 return (0);
00659 }
00660