MIDI: Fix Standard MIDI issues correctly this time
parent
ee5054e12a
commit
d51ca224f5
|
@ -39,7 +39,7 @@ class midi_processor
|
|||
static bool is_gmf( std::vector<uint8_t> const& p_file );
|
||||
static bool is_syx( std::vector<uint8_t> const& p_file );
|
||||
|
||||
static void process_standard_midi_track( std::vector<uint8_t>::const_iterator & it, std::vector<uint8_t>::const_iterator end, midi_container & p_out );
|
||||
static void process_standard_midi_track( std::vector<uint8_t>::const_iterator & it, std::vector<uint8_t>::const_iterator end, midi_container & p_out, bool needs_end_marker );
|
||||
|
||||
static bool process_standard_midi( std::vector<uint8_t> const& p_file, midi_container & p_out );
|
||||
static bool process_riff_midi( std::vector<uint8_t> const& p_file, midi_container & p_out );
|
||||
|
|
|
@ -48,7 +48,7 @@ bool midi_processor::process_gmf( std::vector<uint8_t> const& p_file, midi_conta
|
|||
|
||||
std::vector<uint8_t>::const_iterator it = p_file.begin() + 7;
|
||||
|
||||
process_standard_midi_track( it, p_file.end(), p_out );
|
||||
process_standard_midi_track( it, p_file.end(), p_out, false );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -30,15 +30,10 @@ bool midi_processor::process_standard_midi_count( std::vector<uint8_t> const& p_
|
|||
return true;
|
||||
}
|
||||
|
||||
void midi_processor::process_standard_midi_track( std::vector<uint8_t>::const_iterator & it, std::vector<uint8_t>::const_iterator end, midi_container & p_out)
|
||||
void midi_processor::process_standard_midi_track( std::vector<uint8_t>::const_iterator & it, std::vector<uint8_t>::const_iterator end, midi_container & p_out, bool needs_end_marker )
|
||||
{
|
||||
bool needs_added_end_marker = true;
|
||||
|
||||
midi_track track;
|
||||
midi_event event;
|
||||
bool event_ready = false;
|
||||
unsigned current_timestamp = 0;
|
||||
unsigned next_timestamp;
|
||||
unsigned char last_event_code = 0xFF;
|
||||
|
||||
unsigned last_sysex_length = 0;
|
||||
|
@ -49,9 +44,9 @@ void midi_processor::process_standard_midi_track( std::vector<uint8_t>::const_it
|
|||
|
||||
for (;;)
|
||||
{
|
||||
if ( needs_added_end_marker && it == end ) goto trackerror;
|
||||
if ( !needs_end_marker && it == end ) break;
|
||||
int delta = decode_delta( it, end );
|
||||
if ( needs_added_end_marker && it == end ) goto trackerror;
|
||||
if ( !needs_end_marker && it == end ) break;
|
||||
|
||||
if ( delta < 0 )
|
||||
{
|
||||
|
@ -60,22 +55,18 @@ void midi_processor::process_standard_midi_track( std::vector<uint8_t>::const_it
|
|||
}
|
||||
|
||||
if ( delta > 1000000 )
|
||||
break;
|
||||
|
||||
next_timestamp = current_timestamp + delta;
|
||||
if ( it == end ) goto trackerror;
|
||||
|
||||
if ( event_ready )
|
||||
{
|
||||
track.add_event( event );
|
||||
event_ready = false;
|
||||
needs_end_marker = false;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
current_timestamp += delta;
|
||||
if ( it == end ) break;
|
||||
unsigned char event_code = *it++;
|
||||
unsigned data_bytes_read = 0;
|
||||
if ( event_code < 0x80 )
|
||||
{
|
||||
if ( last_event_code == 0xFF ) goto trackerror; /*throw exception_io_data("First MIDI track event short encoded");*/
|
||||
if ( last_event_code == 0xFF ) break; /*throw exception_io_data("First MIDI track event short encoded");*/
|
||||
buffer[ data_bytes_read++ ] = event_code;
|
||||
event_code = last_event_code;
|
||||
}
|
||||
|
@ -83,16 +74,15 @@ void midi_processor::process_standard_midi_track( std::vector<uint8_t>::const_it
|
|||
{
|
||||
if ( last_sysex_length )
|
||||
{
|
||||
event = midi_event( last_sysex_timestamp, midi_event::extended, 0, &buffer[0], last_sysex_length );
|
||||
event_ready = true;
|
||||
track.add_event( midi_event( last_sysex_timestamp, midi_event::extended, 0, &buffer[0], last_sysex_length ) );
|
||||
last_sysex_length = 0;
|
||||
}
|
||||
|
||||
last_event_code = event_code;
|
||||
if ( needs_added_end_marker && ( event_code & 0xF0 ) == 0xE0 ) continue;
|
||||
if ( !needs_end_marker && ( event_code & 0xF0 ) == 0xE0 ) continue;
|
||||
if ( data_bytes_read < 1 )
|
||||
{
|
||||
if ( it == end ) goto trackerror;
|
||||
if ( it == end ) break;
|
||||
buffer[ 0 ] = *it++;
|
||||
++data_bytes_read;
|
||||
}
|
||||
|
@ -102,42 +92,36 @@ void midi_processor::process_standard_midi_track( std::vector<uint8_t>::const_it
|
|||
case 0xD0:
|
||||
break;
|
||||
default:
|
||||
if ( it == end ) goto trackerror;
|
||||
if ( it == end ) break;
|
||||
buffer[ data_bytes_read ] = *it++;
|
||||
++data_bytes_read;
|
||||
}
|
||||
current_timestamp = next_timestamp;
|
||||
if ( event_ready )
|
||||
track.add_event( event );
|
||||
event = midi_event( current_timestamp, (midi_event::event_type)(( event_code >> 4 ) - 8), event_code & 0x0F, &buffer[0], data_bytes_read );
|
||||
event_ready = true;
|
||||
track.add_event( midi_event( current_timestamp, (midi_event::event_type)(( event_code >> 4 ) - 8), event_code & 0x0F, &buffer[0], data_bytes_read ) );
|
||||
}
|
||||
else if ( event_code == 0xF0 )
|
||||
{
|
||||
if ( last_sysex_length )
|
||||
{
|
||||
event = midi_event( last_sysex_timestamp, midi_event::extended, 0, &buffer[0], last_sysex_length );
|
||||
event_ready = true;
|
||||
track.add_event( midi_event( last_sysex_timestamp, midi_event::extended, 0, &buffer[0], last_sysex_length ) );
|
||||
last_sysex_length = 0;
|
||||
}
|
||||
|
||||
int data_count = decode_delta( it, end );
|
||||
if ( data_count < 0 ) goto trackerror; /*throw exception_io_data( "Invalid System Exclusive message" );*/
|
||||
if ( end - it < data_count ) goto trackerror;
|
||||
if ( data_count < 0 ) break; /*throw exception_io_data( "Invalid System Exclusive message" );*/
|
||||
if ( end - it < data_count ) break;
|
||||
buffer.resize( data_count + 1 );
|
||||
buffer[ 0 ] = 0xF0;
|
||||
std::copy( it, it + data_count, buffer.begin() + 1 );
|
||||
it += data_count;
|
||||
last_sysex_length = data_count + 1;
|
||||
current_timestamp = next_timestamp;
|
||||
last_sysex_timestamp = current_timestamp;
|
||||
}
|
||||
else if ( event_code == 0xF7 ) // SysEx continuation
|
||||
{
|
||||
if ( !last_sysex_length ) goto trackerror;
|
||||
if ( !last_sysex_length ) break;
|
||||
int data_count = decode_delta( it, end );
|
||||
if ( data_count < 0 ) goto trackerror;
|
||||
if ( end - it < data_count ) goto trackerror;
|
||||
if ( data_count < 0 ) break;
|
||||
if ( end - it < data_count ) break;
|
||||
buffer.resize( last_sysex_length + data_count );
|
||||
std::copy( it, it + data_count, buffer.begin() + last_sysex_length );
|
||||
it += data_count;
|
||||
|
@ -147,30 +131,25 @@ void midi_processor::process_standard_midi_track( std::vector<uint8_t>::const_it
|
|||
{
|
||||
if ( last_sysex_length )
|
||||
{
|
||||
event = midi_event( last_sysex_timestamp, midi_event::extended, 0, &buffer[0], last_sysex_length );
|
||||
event_ready = true;
|
||||
track.add_event( midi_event( last_sysex_timestamp, midi_event::extended, 0, &buffer[0], last_sysex_length ) );
|
||||
last_sysex_length = 0;
|
||||
}
|
||||
|
||||
if ( it == end ) goto trackerror;
|
||||
if ( it == end ) break;
|
||||
unsigned char meta_type = *it++;
|
||||
int data_count = decode_delta( it, end );
|
||||
if ( data_count < 0 ) break; /*throw exception_io_data( "Invalid meta message" );*/
|
||||
if ( end - it < data_count ) goto trackerror;
|
||||
if ( end - it < data_count ) break;
|
||||
buffer.resize( data_count + 2 );
|
||||
buffer[ 0 ] = 0xFF;
|
||||
buffer[ 1 ] = meta_type;
|
||||
std::copy( it, it + data_count, buffer.begin() + 2 );
|
||||
it += data_count;
|
||||
current_timestamp = next_timestamp;
|
||||
if ( event_ready )
|
||||
track.add_event( event );
|
||||
event = midi_event( current_timestamp, midi_event::extended, 0, &buffer[0], data_count + 2 );
|
||||
event_ready = true;
|
||||
track.add_event( midi_event( current_timestamp, midi_event::extended, 0, &buffer[0], data_count + 2 ) );
|
||||
|
||||
if ( meta_type == 0x2F )
|
||||
{
|
||||
needs_added_end_marker = false;
|
||||
needs_end_marker = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -178,19 +157,12 @@ void midi_processor::process_standard_midi_track( std::vector<uint8_t>::const_it
|
|||
{
|
||||
/* Sequencer specific events, single byte */
|
||||
buffer[ 0 ] = event_code;
|
||||
current_timestamp = next_timestamp;
|
||||
event = midi_event( current_timestamp, midi_event::extended, 0, &buffer[0], 1 );
|
||||
event_ready = true;
|
||||
track.add_event( midi_event( current_timestamp, midi_event::extended, 0, &buffer[0], 1 ) );
|
||||
}
|
||||
else break; /*throw exception_io_data("Unhandled MIDI status code");*/
|
||||
}
|
||||
|
||||
if ( event_ready )
|
||||
track.add_event( event );
|
||||
|
||||
trackerror:
|
||||
|
||||
if ( needs_added_end_marker )
|
||||
if ( !needs_end_marker )
|
||||
{
|
||||
buffer[ 0 ] = 0xFF;
|
||||
buffer[ 1 ] = 0x2F;
|
||||
|
@ -242,7 +214,7 @@ bool midi_processor::process_standard_midi( std::vector<uint8_t> const& p_file,
|
|||
|
||||
intptr_t track_data_offset = it - p_file.begin();
|
||||
|
||||
process_standard_midi_track( it, it + track_size, p_out );
|
||||
process_standard_midi_track( it, it + track_size, p_out, true );
|
||||
|
||||
track_data_offset += track_size;
|
||||
size_t messup_offset = it - p_file.begin();
|
||||
|
|
Loading…
Reference in New Issue