Fixed some MIDI looping issues, and added support for RPG Maker loops

This commit is contained in:
Chris Moeller 2013-12-14 19:56:59 -08:00
parent a87312b2da
commit 142a144b08
3 changed files with 59 additions and 22 deletions

View file

@ -555,23 +555,12 @@ void midi_container::serialize_as_stream( unsigned long subsong, std::vector<mid
{ {
const midi_event & event = track[ j ]; const midi_event & event = track[ j ];
if ( event.m_type == midi_event::control_change && if ( event.m_type == midi_event::control_change &&
( event.m_data[ 0 ] == 110 || event.m_data[ 0 ] == 111 ) ) event.m_data[ 0 ] == 110 )
{ {
if ( event.m_data[ 0 ] == 110 ) if ( event.m_data[ 1 ] != 0 && event.m_data[ 1 ] != 1 && event.m_data[ 1 ] != 127 )
{ {
if ( event.m_data[ 1 ] != 0 && event.m_data[ 1 ] != 1 && event.m_data[ 1 ] != 127 ) skip_track = true;
{ break;
skip_track = true;
break;
}
}
else
{
if ( event.m_data[ 1 ] == 0 || event.m_data[ 1 ] == 1 )
{
skip_track = true;
break;
}
} }
} }
} }
@ -1041,7 +1030,7 @@ void midi_container::get_meta_data( unsigned long subsong, midi_meta_data & p_ou
p_out.append( m_extra_meta_data ); p_out.append( m_extra_meta_data );
} }
void midi_container::scan_for_loops( bool p_xmi_loops, bool p_marker_loops ) void midi_container::scan_for_loops( bool p_xmi_loops, bool p_marker_loops, bool p_rpgmaker_loops )
{ {
std::vector<uint8_t> data; std::vector<uint8_t> data;
@ -1056,6 +1045,54 @@ void midi_container::scan_for_loops( bool p_xmi_loops, bool p_marker_loops )
m_timestamp_loop_end[ i ] = ~0UL; m_timestamp_loop_end[ i ] = ~0UL;
} }
if ( p_rpgmaker_loops )
{
bool emidi_commands_found = false;
for ( unsigned long i = 0; i < m_tracks.size(); ++i )
{
unsigned long subsong = 0;
if ( m_form == 2 ) subsong = i;
const midi_track & track = m_tracks[ i ];
for ( unsigned long j = 0; j < track.get_count(); ++j )
{
const midi_event & event = track[ j ];
if ( event.m_type == midi_event::control_change &&
( event.m_data[ 0 ] == 110 || event.m_data[ 0 ] == 111 ) )
{
if ( event.m_data[ 0 ] == 110 ||
( event.m_data[ 0 ] == 111 && event.m_data[ 1 ] > 1 ) )
{
emidi_commands_found = true;
break;
}
if ( event.m_data[ 1 ] == 0 )
{
if ( m_timestamp_loop_start[ subsong ] == ~0UL || m_timestamp_loop_start[ subsong ] > event.m_timestamp )
{
m_timestamp_loop_start[ subsong ] = event.m_timestamp;
}
}
else
{
if ( m_timestamp_loop_end[ subsong ] == ~0UL || m_timestamp_loop_end[ subsong ] < event.m_timestamp )
{
m_timestamp_loop_end[ subsong ] = event.m_timestamp;
}
}
}
}
if ( emidi_commands_found )
{
m_timestamp_loop_start[ subsong ] = ~0UL;
m_timestamp_loop_end[ subsong ] = ~0UL;
break;
}
}
}
if ( p_xmi_loops ) if ( p_xmi_loops )
{ {
for ( unsigned long i = 0; i < m_tracks.size(); ++i ) for ( unsigned long i = 0; i < m_tracks.size(); ++i )
@ -1072,14 +1109,14 @@ void midi_container::scan_for_loops( bool p_xmi_loops, bool p_marker_loops )
{ {
if ( event.m_data[ 0 ] == 0x74 ) if ( event.m_data[ 0 ] == 0x74 )
{ {
if ( m_timestamp_loop_start[ subsong ] == ~0u || m_timestamp_loop_start[ subsong ] > event.m_timestamp ) if ( m_timestamp_loop_start[ subsong ] == ~0UL || m_timestamp_loop_start[ subsong ] > event.m_timestamp )
{ {
m_timestamp_loop_start[ subsong ] = event.m_timestamp; m_timestamp_loop_start[ subsong ] = event.m_timestamp;
} }
} }
else else
{ {
if ( m_timestamp_loop_end[ subsong ] == ~0u || m_timestamp_loop_end[ subsong ] < event.m_timestamp ) if ( m_timestamp_loop_end[ subsong ] == ~0UL || m_timestamp_loop_end[ subsong ] < event.m_timestamp )
{ {
m_timestamp_loop_end[ subsong ] = event.m_timestamp; m_timestamp_loop_end[ subsong ] = event.m_timestamp;
} }
@ -1110,14 +1147,14 @@ void midi_container::scan_for_loops( bool p_xmi_loops, bool p_marker_loops )
if ( data_count == 9 && !strncasecmp( (const char *) &data[0], "loopStart", 9 ) ) if ( data_count == 9 && !strncasecmp( (const char *) &data[0], "loopStart", 9 ) )
{ {
if ( m_timestamp_loop_start[ subsong ] == ~0u || m_timestamp_loop_start[ subsong ] > event.m_timestamp ) if ( m_timestamp_loop_start[ subsong ] == ~0UL || m_timestamp_loop_start[ subsong ] > event.m_timestamp )
{ {
m_timestamp_loop_start[ subsong ] = event.m_timestamp; m_timestamp_loop_start[ subsong ] = event.m_timestamp;
} }
} }
else if ( data_count == 7 && !strncasecmp( (const char *) &data[0], "loopEnd", 7 ) ) else if ( data_count == 7 && !strncasecmp( (const char *) &data[0], "loopEnd", 7 ) )
{ {
if ( m_timestamp_loop_end[ subsong ] == ~0u || m_timestamp_loop_end[ subsong ] < event.m_timestamp ) if ( m_timestamp_loop_end[ subsong ] == ~0UL || m_timestamp_loop_end[ subsong ] < event.m_timestamp )
{ {
m_timestamp_loop_end[ subsong ] = event.m_timestamp; m_timestamp_loop_end[ subsong ] = event.m_timestamp;
} }

View file

@ -241,7 +241,7 @@ public:
void get_meta_data( unsigned long subsong, midi_meta_data & p_out ); void get_meta_data( unsigned long subsong, midi_meta_data & p_out );
void scan_for_loops( bool p_xmi_loops, bool p_marker_loops ); void scan_for_loops( bool p_xmi_loops, bool p_marker_loops, bool p_rpgmaker_loops );
static void encode_delta( std::vector<uint8_t> & p_out, unsigned long delta ); static void encode_delta( std::vector<uint8_t> & p_out, unsigned long delta );
}; };

View file

@ -48,7 +48,7 @@
int track_num = [[[s url] fragment] intValue]; //What if theres no fragment? Assuming we get 0. int track_num = [[[s url] fragment] intValue]; //What if theres no fragment? Assuming we get 0.
midi_file.scan_for_loops( true, true ); midi_file.scan_for_loops( true, true, true );
framesLength = midi_file.get_timestamp_end( track_num, true ); framesLength = midi_file.get_timestamp_end( track_num, true );