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 #include <ctype.h>
00043 #ifdef __MINGW32__
00044 #include <windows.h>
00045 #else
00046 #include <arpa/inet.h>
00047 #endif
00048 #include "smf.h"
00049 #include "smf_private.h"
00050
00055 static struct chunk_header_struct *
00056 next_chunk(smf_t *smf)
00057 {
00058 struct chunk_header_struct *chunk;
00059 void *next_chunk_ptr;
00060
00061 assert(smf->file_buffer != NULL);
00062 assert(smf->file_buffer_length > 0);
00063 assert(smf->next_chunk_offset >= 0);
00064
00065 if (smf->next_chunk_offset + sizeof(struct chunk_header_struct) >= smf->file_buffer_length) {
00066 g_critical("SMF warning: no more chunks left.");
00067 return (NULL);
00068 }
00069
00070 next_chunk_ptr = (unsigned char *)smf->file_buffer + smf->next_chunk_offset;
00071
00072 chunk = (struct chunk_header_struct *)next_chunk_ptr;
00073
00074 if (!isalpha(chunk->id[0]) || !isalpha(chunk->id[1]) || !isalpha(chunk->id[2]) || !isalpha(chunk->id[3])) {
00075 g_critical("SMF error: chunk signature contains at least one non-alphanumeric byte.");
00076 return (NULL);
00077 }
00078
00079
00080
00081
00082
00083 smf->next_chunk_offset += sizeof(struct chunk_header_struct) + ntohl(chunk->length);
00084
00085 if (smf->next_chunk_offset > smf->file_buffer_length) {
00086 g_critical("SMF warning: malformed chunk; truncated file?");
00087 smf->next_chunk_offset = smf->file_buffer_length;
00088 }
00089
00090 return (chunk);
00091 }
00092
00096 static int
00097 chunk_signature_matches(const struct chunk_header_struct *chunk, const char *signature)
00098 {
00099 if (!memcmp(chunk->id, signature, 4))
00100 return (1);
00101
00102 return (0);
00103 }
00104
00108 static int
00109 parse_mthd_header(smf_t *smf)
00110 {
00111 int len;
00112 struct chunk_header_struct *mthd, *tmp_mthd;
00113
00114
00115 assert(sizeof(struct chunk_header_struct) == 8);
00116
00117
00118
00119
00120
00121 if (smf->file_buffer_length < 6) {
00122 g_critical("SMF error: file is too short, it cannot be a MIDI file.");
00123
00124 return (-1);
00125 }
00126
00127 tmp_mthd = smf->file_buffer;
00128
00129 if (!chunk_signature_matches(tmp_mthd, "MThd")) {
00130 g_critical("SMF error: MThd signature not found, is that a MIDI file?");
00131
00132 return (-2);
00133 }
00134
00135
00136 mthd = next_chunk(smf);
00137 if (mthd == NULL)
00138 return (-3);
00139
00140 assert(mthd == tmp_mthd);
00141
00142 len = ntohl(mthd->length);
00143 if (len != 6) {
00144 g_critical("SMF error: MThd chunk length %d, must be 6.", len);
00145
00146 return (-4);
00147 }
00148
00149 return (0);
00150 }
00151
00155 static int
00156 parse_mthd_chunk(smf_t *smf)
00157 {
00158 signed char first_byte_of_division, second_byte_of_division;
00159
00160 struct mthd_chunk_struct *mthd;
00161
00162 assert(sizeof(struct mthd_chunk_struct) == 14);
00163
00164 if (parse_mthd_header(smf))
00165 return (1);
00166
00167 mthd = (struct mthd_chunk_struct *)smf->file_buffer;
00168
00169 smf->format = ntohs(mthd->format);
00170 if (smf->format < 0 || smf->format > 2) {
00171 g_critical("SMF error: bad MThd format field value: %d, valid values are 0-2, inclusive.", smf->format);
00172 return (-1);
00173 }
00174
00175 if (smf->format == 2) {
00176 g_critical("SMF file uses format #2, no support for that yet.");
00177 return (-2);
00178 }
00179
00180 smf->expected_number_of_tracks = ntohs(mthd->number_of_tracks);
00181 if (smf->expected_number_of_tracks <= 0) {
00182 g_critical("SMF error: bad number of tracks: %d, must be greater than zero.", smf->expected_number_of_tracks);
00183 return (-3);
00184 }
00185
00186
00187 first_byte_of_division = *((signed char *)&(mthd->division));
00188 second_byte_of_division = *((signed char *)&(mthd->division) + 1);
00189
00190 if (first_byte_of_division >= 0) {
00191 smf->ppqn = ntohs(mthd->division);
00192 smf->frames_per_second = 0;
00193 smf->resolution = 0;
00194 } else {
00195 smf->ppqn = 0;
00196 smf->frames_per_second = - first_byte_of_division;
00197 smf->resolution = second_byte_of_division;
00198 }
00199
00200 if (smf->ppqn == 0) {
00201 g_critical("SMF file uses FPS timing instead of PPQN, no support for that yet.");
00202 return (-4);
00203 }
00204
00205 return (0);
00206 }
00207
00214 static int
00215 extract_vlq(const unsigned char *buf, const int buffer_length, int *value, int *len)
00216 {
00217 int val = 0;
00218 const unsigned char *c = buf;
00219
00220 assert(buffer_length > 0);
00221
00222 for (;;) {
00223 if (c >= buf + buffer_length) {
00224 g_critical("End of buffer in extract_vlq().");
00225 return (-1);
00226 }
00227
00228 val = (val << 7) + (*c & 0x7F);
00229
00230 if (*c & 0x80)
00231 c++;
00232 else
00233 break;
00234 };
00235
00236 *value = val;
00237 *len = c - buf + 1;
00238
00239 if (*len > 4) {
00240 g_critical("SMF error: Variable Length Quantities longer than four bytes are not supported yet.");
00241 return (-2);
00242 }
00243
00244 return (0);
00245 }
00246
00250 int
00251 is_status_byte(const unsigned char status)
00252 {
00253 return (status & 0x80);
00254 }
00255
00256 static int
00257 is_sysex_byte(const unsigned char status)
00258 {
00259 if (status == 0xF0)
00260 return (1);
00261
00262 return (0);
00263 }
00264
00265 static int
00266 is_escape_byte(const unsigned char status)
00267 {
00268 if (status == 0xF7)
00269 return (1);
00270
00271 return (0);
00272 }
00273
00281 static int
00282 expected_sysex_length(const unsigned char status, const unsigned char *second_byte, const int buffer_length, int *consumed_bytes)
00283 {
00284 int sysex_length, len;
00285
00286 assert(status == 0xF0);
00287
00288 if (buffer_length < 3) {
00289 g_critical("SMF error: end of buffer in expected_sysex_length().");
00290 return (-1);
00291 }
00292
00293 if (extract_vlq(second_byte, buffer_length, &sysex_length, &len))
00294 return (-1);
00295
00296 if (consumed_bytes != NULL)
00297 *consumed_bytes = len;
00298
00299
00300 return (sysex_length + 1);
00301 }
00302
00303 static int
00304 expected_escaped_length(const unsigned char status, const unsigned char *second_byte, const int buffer_length, int *consumed_bytes)
00305 {
00306
00307 return (expected_sysex_length(status, second_byte, buffer_length, consumed_bytes) - 1);
00308 }
00309
00315 static int
00316 expected_message_length(unsigned char status, const unsigned char *second_byte, const int buffer_length)
00317 {
00318
00319 assert(is_status_byte(status));
00320
00321
00322 assert(!is_sysex_byte(status));
00323
00324
00325 assert(!is_escape_byte(status));
00326
00327
00328 assert(buffer_length >= 0);
00329
00330
00331 if (status == 0xFF) {
00332 if (buffer_length < 2) {
00333 g_critical("SMF error: end of buffer in expected_message_length().");
00334 return (-1);
00335 }
00336
00337
00338
00339
00340
00341 return (*(second_byte + 1) + 3);
00342 }
00343
00344 if ((status & 0xF0) == 0xF0) {
00345 switch (status) {
00346 case 0xF2:
00347 return (3);
00348
00349 case 0xF1:
00350 case 0xF3:
00351 return (2);
00352
00353 case 0xF6:
00354 case 0xF8:
00355 case 0xF9:
00356 case 0xFA:
00357 case 0xFB:
00358 case 0xFC:
00359 case 0xFE:
00360 return (1);
00361
00362 default:
00363 g_critical("SMF error: unknown 0xFx-type status byte '0x%x'.", status);
00364 return (-2);
00365 }
00366 }
00367
00368
00369 status &= 0xF0;
00370
00371 switch (status) {
00372 case 0x80:
00373 case 0x90:
00374 case 0xA0:
00375 case 0xB0:
00376 case 0xE0:
00377 return (3);
00378
00379 case 0xC0:
00380 case 0xD0:
00381 return (2);
00382
00383 default:
00384 g_critical("SMF error: unknown status byte '0x%x'.", status);
00385 return (-3);
00386 }
00387 }
00388
00389 static int
00390 extract_sysex_event(const unsigned char *buf, const int buffer_length, smf_event_t *event, int *len, int last_status)
00391 {
00392 int status, message_length, vlq_length;
00393 const unsigned char *c = buf;
00394
00395 status = *buf;
00396
00397 assert(is_sysex_byte(status));
00398
00399 c++;
00400
00401 message_length = expected_sysex_length(status, c, buffer_length - 1, &vlq_length);
00402
00403 if (message_length < 0)
00404 return (-3);
00405
00406 c += vlq_length;
00407
00408 if (vlq_length + message_length >= buffer_length) {
00409 g_critical("End of buffer in extract_sysex_event().");
00410 return (-5);
00411 }
00412
00413 event->midi_buffer_length = message_length;
00414 event->midi_buffer = malloc(event->midi_buffer_length);
00415 if (event->midi_buffer == NULL) {
00416 g_critical("Cannot allocate memory in extract_sysex_event(): %s", strerror(errno));
00417 return (-4);
00418 }
00419
00420 event->midi_buffer[0] = status;
00421 memcpy(event->midi_buffer + 1, c, message_length - 1);
00422
00423 *len = vlq_length + message_length;
00424
00425 return (0);
00426 }
00427
00428 static int
00429 extract_escaped_event(const unsigned char *buf, const int buffer_length, smf_event_t *event, int *len, int last_status)
00430 {
00431 int status, message_length, vlq_length;
00432 const unsigned char *c = buf;
00433
00434 status = *buf;
00435
00436 assert(is_escape_byte(status));
00437
00438 c++;
00439
00440 message_length = expected_escaped_length(status, c, buffer_length - 1, &vlq_length);
00441
00442 if (message_length < 0)
00443 return (-3);
00444
00445 c += vlq_length;
00446
00447 if (vlq_length + message_length >= buffer_length) {
00448 g_critical("End of buffer in extract_escaped_event().");
00449 return (-5);
00450 }
00451
00452 event->midi_buffer_length = message_length;
00453 event->midi_buffer = malloc(event->midi_buffer_length);
00454 if (event->midi_buffer == NULL) {
00455 g_critical("Cannot allocate memory in extract_escaped_event(): %s", strerror(errno));
00456 return (-4);
00457 }
00458
00459 memcpy(event->midi_buffer, c, message_length);
00460
00461 if (smf_event_is_valid(event)) {
00462 g_critical("Escaped event is invalid.");
00463 return (-1);
00464 }
00465
00466 if (smf_event_is_system_realtime(event) || smf_event_is_system_common(event)) {
00467 g_warning("Escaped event is not System Realtime nor System Common.");
00468 }
00469
00470 *len = vlq_length + message_length;
00471
00472 return (0);
00473 }
00474
00475
00481 static int
00482 extract_midi_event(const unsigned char *buf, const int buffer_length, smf_event_t *event, int *len, int last_status)
00483 {
00484 int status, message_length;
00485 const unsigned char *c = buf;
00486
00487 assert(buffer_length > 0);
00488
00489
00490 if (is_status_byte(*c)) {
00491 status = *c;
00492 c++;
00493
00494 } else {
00495
00496 status = last_status;
00497 }
00498
00499 if (!is_status_byte(status)) {
00500 g_critical("SMF error: bad status byte (MSB is zero).");
00501 return (-1);
00502 }
00503
00504 if (is_sysex_byte(status))
00505 return (extract_sysex_event(buf, buffer_length, event, len, last_status));
00506
00507 if (is_escape_byte(status))
00508 return (extract_escaped_event(buf, buffer_length, event, len, last_status));
00509
00510
00511 message_length = expected_message_length(status, c, buffer_length - (c - buf));
00512
00513 if (message_length < 0)
00514 return (-3);
00515
00516 if (message_length - 1 > buffer_length - (c - buf)) {
00517 g_critical("End of buffer in extract_midi_event().");
00518 return (-5);
00519 }
00520
00521 event->midi_buffer_length = message_length;
00522 event->midi_buffer = malloc(event->midi_buffer_length);
00523 if (event->midi_buffer == NULL) {
00524 g_critical("Cannot allocate memory in extract_midi_event(): %s", strerror(errno));
00525 return (-4);
00526 }
00527
00528 event->midi_buffer[0] = status;
00529 memcpy(event->midi_buffer + 1, c, message_length - 1);
00530
00531 *len = c + message_length - 1 - buf;
00532
00533 return (0);
00534 }
00535
00542 static smf_event_t *
00543 parse_next_event(smf_track_t *track)
00544 {
00545 int time = 0, len, buffer_length;
00546 unsigned char *c, *start;
00547
00548 smf_event_t *event = smf_event_new();
00549 if (event == NULL)
00550 goto error;
00551
00552 c = start = (unsigned char *)track->file_buffer + track->next_event_offset;
00553
00554 assert(track->file_buffer != NULL);
00555 assert(track->file_buffer_length > 0);
00556 assert(track->next_event_offset > 0);
00557
00558 buffer_length = track->file_buffer_length - track->next_event_offset;
00559 assert(buffer_length > 0);
00560
00561
00562 if (extract_vlq(c, buffer_length, &time, &len))
00563 goto error;
00564
00565 c += len;
00566 buffer_length -= len;
00567
00568 if (buffer_length <= 0)
00569 goto error;
00570
00571
00572 if (extract_midi_event(c, buffer_length, event, &len, track->last_status))
00573 goto error;
00574
00575 c += len;
00576 buffer_length -= len;
00577 track->last_status = event->midi_buffer[0];
00578 track->next_event_offset += c - start;
00579
00580 smf_track_add_event_delta_pulses(track, event, time);
00581
00582 return (event);
00583
00584 error:
00585 if (event != NULL)
00586 smf_event_delete(event);
00587
00588 return (NULL);
00589 }
00590
00595 static char *
00596 make_string(const unsigned char *buf, const int buffer_length, int len)
00597 {
00598 char *str;
00599
00600 assert(buffer_length > 0);
00601 assert(len > 0);
00602
00603 if (len > buffer_length) {
00604 g_critical("End of buffer in make_string().");
00605
00606 len = buffer_length;
00607 }
00608
00609 str = malloc(len + 1);
00610 if (str == NULL) {
00611 g_critical("Cannot allocate memory in make_string().");
00612 return (NULL);
00613 }
00614
00615 memcpy(str, buf, len);
00616 str[len] = '\0';
00617
00618 return (str);
00619 }
00620
00626 int
00627 smf_event_is_textual(const smf_event_t *event)
00628 {
00629 if (!smf_event_is_metadata(event))
00630 return (0);
00631
00632 if (event->midi_buffer_length < 4)
00633 return (0);
00634
00635 if (event->midi_buffer[3] < 1 && event->midi_buffer[3] > 9)
00636 return (0);
00637
00638 return (1);
00639 }
00640
00646 char *
00647 smf_event_extract_text(const smf_event_t *event)
00648 {
00649 int string_length = -1, length_length = -1;
00650
00651 if (!smf_event_is_textual(event))
00652 return (NULL);
00653
00654 if (event->midi_buffer_length < 3) {
00655 g_critical("smf_event_extract_text: truncated MIDI message.");
00656 return (NULL);
00657 }
00658
00659 extract_vlq((void *)&(event->midi_buffer[2]), event->midi_buffer_length - 2, &string_length, &length_length);
00660
00661 if (string_length <= 0) {
00662 g_critical("smf_event_extract_text: truncated MIDI message.");
00663 return (NULL);
00664 }
00665
00666 return (make_string((void *)(&event->midi_buffer[2] + length_length), event->midi_buffer_length - 2 - length_length, string_length));
00667 }
00668
00673 static int
00674 parse_mtrk_header(smf_track_t *track)
00675 {
00676 struct chunk_header_struct *mtrk;
00677
00678
00679 assert(sizeof(struct chunk_header_struct) == 8);
00680 assert(track->smf != NULL);
00681
00682 mtrk = next_chunk(track->smf);
00683
00684 if (mtrk == NULL)
00685 return (-1);
00686
00687 if (!chunk_signature_matches(mtrk, "MTrk")) {
00688 g_warning("SMF warning: Expected MTrk signature, got %c%c%c%c instead; ignoring this chunk.",
00689 mtrk->id[0], mtrk->id[1], mtrk->id[2], mtrk->id[3]);
00690
00691 return (-2);
00692 }
00693
00694 track->file_buffer = mtrk;
00695 track->file_buffer_length = sizeof(struct chunk_header_struct) + ntohl(mtrk->length);
00696 track->next_event_offset = sizeof(struct chunk_header_struct);
00697
00698 return (0);
00699 }
00700
00704 static int
00705 event_is_end_of_track(const smf_event_t *event)
00706 {
00707 if (event->midi_buffer[0] == 0xFF && event->midi_buffer[1] == 0x2F)
00708 return (1);
00709
00710 return (0);
00711 }
00712
00717 int
00718 smf_event_length_is_valid(const smf_event_t *event)
00719 {
00720 assert(event);
00721 assert(event->midi_buffer);
00722
00723 if (event->midi_buffer_length < 1)
00724 return (0);
00725
00726
00727 if (smf_event_is_sysex(event))
00728 return (1);
00729
00730 if (event->midi_buffer_length != expected_message_length(event->midi_buffer[0],
00731 &(event->midi_buffer[1]), event->midi_buffer_length - 1)) {
00732
00733 return (0);
00734 }
00735
00736 return (1);
00737 }
00738
00743
00744 int
00745 smf_event_is_valid(const smf_event_t *event)
00746 {
00747 assert(event);
00748 assert(event->midi_buffer);
00749 assert(event->midi_buffer_length >= 1);
00750
00751 if (!is_status_byte(event->midi_buffer[0])) {
00752 g_critical("First byte of MIDI message is not a valid status byte.");
00753
00754 return (0);
00755 }
00756
00757 if (!smf_event_length_is_valid(event))
00758 return (0);
00759
00760 return (1);
00761 }
00762
00766 static int
00767 parse_mtrk_chunk(smf_track_t *track)
00768 {
00769 smf_event_t *event;
00770
00771 if (parse_mtrk_header(track))
00772 return (-1);
00773
00774 for (;;) {
00775 event = parse_next_event(track);
00776
00777
00778 if (event == NULL) {
00779 g_critical("Unable to parse MIDI event; truncating track.");
00780 if (smf_track_add_eot_delta_pulses(track, 0) != 0) {
00781 g_critical("smf_track_add_eot_delta_pulses failed.");
00782 return (-2);
00783 }
00784 break;
00785 }
00786
00787 assert(smf_event_is_valid(event));
00788
00789 if (event_is_end_of_track(event))
00790 break;
00791 }
00792
00793 track->file_buffer = NULL;
00794 track->file_buffer_length = 0;
00795 track->next_event_offset = -1;
00796
00797 return (0);
00798 }
00799
00803 static int
00804 load_file_into_buffer(void **file_buffer, int *file_buffer_length, const char *file_name)
00805 {
00806 FILE *stream = fopen(file_name, "rb");
00807
00808 if (stream == NULL) {
00809 g_critical("Cannot open input file: %s", strerror(errno));
00810
00811 return (-1);
00812 }
00813
00814 if (fseek(stream, 0, SEEK_END)) {
00815 g_critical("fseek(3) failed: %s", strerror(errno));
00816
00817 return (-2);
00818 }
00819
00820 *file_buffer_length = ftell(stream);
00821 if (*file_buffer_length == -1) {
00822 g_critical("ftell(3) failed: %s", strerror(errno));
00823
00824 return (-3);
00825 }
00826
00827 if (fseek(stream, 0, SEEK_SET)) {
00828 g_critical("fseek(3) failed: %s", strerror(errno));
00829
00830 return (-4);
00831 }
00832
00833 *file_buffer = malloc(*file_buffer_length);
00834 if (*file_buffer == NULL) {
00835 g_critical("malloc(3) failed: %s", strerror(errno));
00836
00837 return (-5);
00838 }
00839
00840 if (fread(*file_buffer, 1, *file_buffer_length, stream) != *file_buffer_length) {
00841 g_critical("fread(3) failed: %s", strerror(errno));
00842
00843 return (-6);
00844 }
00845
00846 if (fclose(stream)) {
00847 g_critical("fclose(3) failed: %s", strerror(errno));
00848
00849 return (-7);
00850 }
00851
00852 return (0);
00853 }
00854
00859 smf_t *
00860 smf_load_from_memory(const void *buffer, const int buffer_length)
00861 {
00862 int i;
00863
00864 smf_t *smf = smf_new();
00865
00866 smf->file_buffer = (void *)buffer;
00867 smf->file_buffer_length = buffer_length;
00868 smf->next_chunk_offset = 0;
00869
00870 if (parse_mthd_chunk(smf))
00871 return (NULL);
00872
00873 for (i = 1; i <= smf->expected_number_of_tracks; i++) {
00874 smf_track_t *track = smf_track_new();
00875 if (track == NULL)
00876 return (NULL);
00877
00878 smf_add_track(smf, track);
00879
00880
00881 if (parse_mtrk_chunk(track)) {
00882 g_warning("SMF warning: Cannot load track.");
00883 smf_track_delete(track);
00884 }
00885
00886 track->file_buffer = NULL;
00887 track->file_buffer_length = 0;
00888 track->next_event_offset = -1;
00889 }
00890
00891 if (smf->expected_number_of_tracks != smf->number_of_tracks) {
00892 g_warning("SMF warning: MThd header declared %d tracks, but only %d found; continuing anyway.",
00893 smf->expected_number_of_tracks, smf->number_of_tracks);
00894
00895 smf->expected_number_of_tracks = smf->number_of_tracks;
00896 }
00897
00898 smf->file_buffer = NULL;
00899 smf->file_buffer_length = 0;
00900 smf->next_chunk_offset = -1;
00901
00902 return (smf);
00903 }
00904
00911 smf_t *
00912 smf_load(const char *file_name)
00913 {
00914 int file_buffer_length;
00915 void *file_buffer;
00916 smf_t *smf;
00917
00918 if (load_file_into_buffer(&file_buffer, &file_buffer_length, file_name))
00919 return (NULL);
00920
00921 smf = smf_load_from_memory(file_buffer, file_buffer_length);
00922
00923 memset(file_buffer, 0, file_buffer_length);
00924 free(file_buffer);
00925
00926 if (smf == NULL)
00927 return (NULL);
00928
00929 smf_rewind(smf);
00930
00931 return (smf);
00932 }
00933