|
From: Jerome F. <kin...@us...> - 2009-07-12 15:04:00
|
Update of /cvsroot/munt/mt32emu_smf2wav/libsmf/src In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv24527/src Modified Files: smf.h smf_decode.c smf_load.c Log Message: - Fixed several bugs in escaped message parsing, including adding support for continued sysex messages. Index: smf_decode.c =================================================================== RCS file: /cvsroot/munt/mt32emu_smf2wav/libsmf/src/smf_decode.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** smf_decode.c 28 Feb 2009 23:42:59 -0000 1.1 --- smf_decode.c 12 Jul 2009 15:03:54 -0000 1.2 *************** *** 109,112 **** --- 109,136 ---- } + int + smf_event_is_sysex_continuation(const smf_event_t *event) + { + assert(event->midi_buffer); + assert(event->midi_buffer_length > 0); + + if (event->midi_buffer[0] == 0xF7) + return (1); + + return (0); + } + + int + smf_event_is_unterminated_sysex(const smf_event_t *event) + { + assert(event->midi_buffer); + assert(event->midi_buffer_length > 0); + + if (!smf_event_is_sysex(event) && !smf_event_is_sysex_continuation(event)) + return 0; + + return event->midi_buffer[event->midi_buffer_length - 1] != 0xF7; + } + static char * smf_event_decode_textual(const smf_event_t *event, const char *name) Index: smf_load.c =================================================================== RCS file: /cvsroot/munt/mt32emu_smf2wav/libsmf/src/smf_load.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** smf_load.c 28 Feb 2009 23:42:59 -0000 1.1 --- smf_load.c 12 Jul 2009 15:03:54 -0000 1.2 *************** *** 296,306 **** } - static int - expected_escaped_length(const unsigned char status, const unsigned char *second_byte, const int buffer_length, int *consumed_bytes) - { - /* -1, because we do not want to account for 0x7F status. */ - return (expected_sysex_length(status, second_byte, buffer_length, consumed_bytes) - 1); - } - /** * Returns expected length of the midi message (including the status byte), in bytes, for the given status byte. --- 296,299 ---- *************** *** 383,387 **** static int ! extract_sysex_event(const unsigned char *buf, const int buffer_length, smf_event_t *event, int *len, int last_status) { int status, message_length, vlq_length; --- 376,380 ---- static int ! extract_sysex_event(const unsigned char *buf, const int buffer_length, smf_event_t *event, int *len, int last_status, int *has_unterminated_sysex) { int status, message_length, vlq_length; *************** *** 416,419 **** --- 409,414 ---- memcpy(event->midi_buffer + 1, c, message_length - 1); + *has_unterminated_sysex = event->midi_buffer[event->midi_buffer_length - 1] != 0xF7; + *len = vlq_length + message_length; *************** *** 422,426 **** static int ! extract_escaped_event(const unsigned char *buf, const int buffer_length, smf_event_t *event, int *len, int last_status) { int status, message_length, vlq_length; --- 417,421 ---- static int ! extract_escaped_event(const unsigned char *buf, const int buffer_length, smf_event_t *event, int *len, int last_status, int *has_unterminated_sysex) { int status, message_length, vlq_length; *************** *** 433,449 **** c++; ! message_length = expected_escaped_length(status, c, buffer_length - 1, &vlq_length); ! ! if (message_length < 0) return (-3); c += vlq_length; ! if (vlq_length + message_length >= buffer_length) { g_critical("End of buffer in extract_escaped_event()."); return (-5); } ! event->midi_buffer_length = message_length; event->midi_buffer = malloc(event->midi_buffer_length); if (event->midi_buffer == NULL) { --- 428,449 ---- c++; ! if (extract_vlq(c, buffer_length - 1, &message_length, &vlq_length) != 0) return (-3); + if (message_length < 1) { + g_critical("0-length escaped event in extract_escaped_event()."); + return (-4); + } + c += vlq_length; ! if (1 + vlq_length + message_length > buffer_length) { g_critical("End of buffer in extract_escaped_event()."); return (-5); } ! /* If *has_unterminated_sysex is non-zero, we want to add the F7 status byte to the start of the message ! so that it can be identified as such. */ ! event->midi_buffer_length = *has_unterminated_sysex ? message_length + 1 : message_length; event->midi_buffer = malloc(event->midi_buffer_length); if (event->midi_buffer == NULL) { *************** *** 451,467 **** return (-4); } ! memcpy(event->midi_buffer, c, message_length); ! ! if (smf_event_is_valid(event)) { g_critical("Escaped event is invalid."); return (-1); } ! if (smf_event_is_system_realtime(event) || smf_event_is_system_common(event)) { ! g_warning("Escaped event is not System Realtime nor System Common."); ! } ! ! *len = vlq_length + message_length; return (0); --- 451,471 ---- return (-4); } + if (*has_unterminated_sysex) { + event->midi_buffer[0] = 0xF7; + memcpy(event->midi_buffer + 1, c, message_length); + *has_unterminated_sysex = c[message_length - 1] != 0xF7; + } else { + memcpy(event->midi_buffer, c, message_length); + if (smf_event_is_system_realtime(event) || smf_event_is_system_common(event)) { + g_warning("Escaped event is not System Realtime nor System Common."); + } + } ! if (!smf_event_is_valid(event)) { g_critical("Escaped event is invalid."); return (-1); } ! *len = 1 + vlq_length + message_length; return (0); *************** *** 475,479 **** */ static int ! extract_midi_event(const unsigned char *buf, const int buffer_length, smf_event_t *event, int *len, int last_status) { int status, message_length; --- 479,483 ---- */ static int ! extract_midi_event(const unsigned char *buf, const int buffer_length, smf_event_t *event, int *len, int last_status, int *has_unterminated_sysex) { int status, message_length; *************** *** 498,505 **** if (is_sysex_byte(status)) ! return (extract_sysex_event(buf, buffer_length, event, len, last_status)); if (is_escape_byte(status)) ! return (extract_escaped_event(buf, buffer_length, event, len, last_status)); /* At this point, "c" points to first byte following the status byte. */ --- 502,509 ---- if (is_sysex_byte(status)) ! return (extract_sysex_event(buf, buffer_length, event, len, last_status, has_unterminated_sysex)); if (is_escape_byte(status)) ! return (extract_escaped_event(buf, buffer_length, event, len, last_status, has_unterminated_sysex)); /* At this point, "c" points to first byte following the status byte. */ *************** *** 565,569 **** /* Now, extract the actual event. */ ! if (extract_midi_event(c, buffer_length, event, &len, track->last_status)) goto error; --- 569,573 ---- /* Now, extract the actual event. */ ! if (extract_midi_event(c, buffer_length, event, &len, track->last_status, &track->has_unterminated_sysex)) goto error; *************** *** 719,724 **** return (0); ! /* We cannot use expected_message_length on sysexes. */ ! if (smf_event_is_sysex(event)) return (1); --- 723,728 ---- return (0); ! /* We cannot use expected_message_length on sysexes or sysex continuations. */ ! if (smf_event_is_sysex(event) || smf_event_is_sysex_continuation(event)) return (1); *************** *** 745,749 **** if (!is_status_byte(event->midi_buffer[0])) { ! g_critical("First byte of MIDI message is not a valid status byte."); return (0); --- 749,753 ---- if (!is_status_byte(event->midi_buffer[0])) { ! g_critical("First byte of MIDI message (%02X) is not a valid status byte.", event->midi_buffer[0] & 0xFF); return (0); Index: smf.h =================================================================== RCS file: /cvsroot/munt/mt32emu_smf2wav/libsmf/src/smf.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** smf.h 28 Feb 2009 23:42:59 -0000 1.1 --- smf.h 12 Jul 2009 15:03:54 -0000 1.2 *************** *** 279,282 **** --- 279,283 ---- int file_buffer_length; int last_status; /* Used for "running status". */ + int has_unterminated_sysex; /** Private, used by smf.c. */ *************** *** 377,380 **** --- 378,383 ---- int smf_event_is_system_common(const smf_event_t *event) WARN_UNUSED_RESULT; int smf_event_is_sysex(const smf_event_t *event) WARN_UNUSED_RESULT; + int smf_event_is_sysex_continuation(const smf_event_t *event) WARN_UNUSED_RESULT; + int smf_event_is_unterminated_sysex(const smf_event_t *event) WARN_UNUSED_RESULT; int smf_event_is_eot(const smf_event_t *event) WARN_UNUSED_RESULT; int smf_event_is_textual(const smf_event_t *event) WARN_UNUSED_RESULT; |