Adding a lot of MIDI files should hopefully be faster now.

CQTexperiment
Chris Moeller 2016-06-19 12:58:17 -07:00
parent 03b825ced3
commit 597a342838
6 changed files with 137 additions and 11 deletions

View File

@ -51,8 +51,14 @@ class midi_processor
static bool process_lds( std::vector<uint8_t> const& p_file, midi_container & p_out );
static bool process_gmf( std::vector<uint8_t> const& p_file, midi_container & p_out );
static bool process_syx( std::vector<uint8_t> const& p_file, midi_container & p_out );
static bool process_standard_midi_count( std::vector<uint8_t> const& p_file, size_t & track_count );
static bool process_riff_midi_count( std::vector<uint8_t> const& p_file, size_t & track_count );
static bool process_xmi_count( std::vector<uint8_t> const& p_file, size_t & track_count );
public:
static bool process_track_count( std::vector<uint8_t> const& p_file, const char * p_extension, size_t & track_count );
static bool process_file( std::vector<uint8_t> const& p_file, const char * p_extension, midi_container & p_out );
static bool process_syx_file( std::vector<uint8_t> const& p_file, midi_container & p_out );

View File

@ -67,3 +67,52 @@ bool midi_processor::process_syx_file( std::vector<uint8_t> const& p_file, midi_
}
else return false;
}
bool midi_processor::process_track_count( std::vector<uint8_t> const& p_file, const char * p_extension, size_t & track_count )
{
track_count = 0;
if ( is_standard_midi( p_file ) )
{
return process_standard_midi_count( p_file, track_count );
}
else if ( is_riff_midi( p_file ) )
{
return process_riff_midi_count( p_file, track_count );
}
else if ( is_hmp( p_file ) )
{
track_count = 1;
return true;
}
else if ( is_hmi( p_file ) )
{
track_count = 1;
return true;
}
else if ( is_xmi( p_file ) )
{
return process_xmi_count( p_file, track_count );
}
else if ( is_mus( p_file ) )
{
track_count = 1;
return true;
}
else if ( is_mids( p_file ) )
{
track_count = 1;
return true;
}
else if ( is_lds( p_file, p_extension ) )
{
track_count = 1;
return true;
}
else if ( is_gmf( p_file ) )
{
track_count = 1;
return true;
}
else return false;
}

View File

@ -17,10 +17,43 @@ bool midi_processor::is_riff_midi( std::vector<uint8_t> const& p_file )
return is_standard_midi( test );
}
bool midi_processor::process_riff_midi_count( std::vector<uint8_t> const& p_file, size_t & track_count )
{
track_count = 0;
uint32_t file_size = p_file[ 4 ] | ( p_file[ 5 ] << 8 ) | ( p_file[ 6 ] << 16 ) | ( p_file[ 7 ] << 24 );
std::vector<uint8_t>::const_iterator it = p_file.begin() + 12;
std::vector<uint8_t>::const_iterator body_end = p_file.begin() + 8 + file_size;
std::vector<uint8_t> extra_buffer;
while ( it != body_end )
{
if ( body_end - it < 8 ) return false;
uint32_t chunk_size = it[ 4 ] | ( it[ 5 ] << 8 ) | ( it[ 6 ] << 16 ) | ( it[ 7 ] << 24 );
if ( (unsigned long)(body_end - it) < chunk_size ) return false;
if ( it[ 0 ] == 'd' && it[ 1 ] == 'a' && it[ 2 ] == 't' && it[ 3 ] == 'a' )
{
std::vector<uint8_t> midi_file;
midi_file.assign( it + 8, it + 8 + chunk_size );
return process_standard_midi_count( midi_file, track_count );
}
else
{
it += chunk_size;
if ( chunk_size & 1 && it != body_end ) ++it;
}
}
return false;
}
static const char * riff_tag_mappings[][2] =
{
{ "IALB", "album" },
{ "IARL", "archival_location" },
{ "IALB", "album" },
{ "IARL", "archival_location" },
{ "IART", "artist" },
{ "ITRK", "tracknumber" },
{ "ICMS", "commissioned" },

View File

@ -9,6 +9,26 @@ bool midi_processor::is_standard_midi( std::vector<uint8_t> const& p_file )
return true;
}
bool midi_processor::process_standard_midi_count( std::vector<uint8_t> const& p_file, size_t & track_count )
{
track_count = 0;
if ( p_file[ 0 ] != 'M' || p_file[ 1 ] != 'T' || p_file[ 2 ] != 'h' || p_file[ 3 ] != 'd' ) return false;
if ( p_file[ 4 ] != 0 || p_file[ 5 ] != 0 || p_file[ 6 ] != 0 || p_file[ 7 ] != 6 ) return false; /*throw exception_io_data("Bad MIDI header size");*/
std::vector<uint8_t>::const_iterator it = p_file.begin() + 8;
uint16_t form = ( it[0] << 8 ) | it[1];
if ( form > 2 ) return false;
uint16_t track_count_16 = ( it[2] << 8 ) | it[3];
if ( form == 2 ) track_count = track_count_16;
else track_count = 1;
return true;
}
bool 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 )
{
midi_track track;

View File

@ -163,9 +163,29 @@ static bool read_iff_stream( std::vector<uint8_t> const& p_file, iff_stream & p_
return true;
}
bool midi_processor::process_xmi_count( std::vector<uint8_t> const& p_file, size_t & track_count )
{
track_count = 0;
iff_stream xmi_file;
if ( !read_iff_stream( p_file, xmi_file ) ) return false;
const iff_chunk & form_chunk = xmi_file.find_chunk( "FORM" );
if ( memcmp( form_chunk.m_type, "XDIR", 4 ) ) return false; /*throw exception_io_data( "XMI IFF not XDIR type" );*/
const iff_chunk & cat_chunk = xmi_file.find_chunk( "CAT " );
if ( memcmp( cat_chunk.m_type, "XMID", 4 ) ) return false; /*throw exception_io_data( "XMI CAT chunk not XMID type" );*/
unsigned _track_count = cat_chunk.get_chunk_count( "FORM" );
track_count = _track_count;
return true;
}
bool midi_processor::process_xmi( std::vector<uint8_t> const& p_file, midi_container & p_out )
{
iff_stream xmi_file;
iff_stream xmi_file;
if ( !read_iff_stream( p_file, xmi_file ) ) return false;
const iff_chunk & form_chunk = xmi_file.find_chunk( "FORM" );

View File

@ -40,10 +40,10 @@
id<CogSource> source = [audioSourceClass audioSourceForURL:url];
if (![source open:url])
return 0;
return [NSArray array];
if (![source seekable])
return 0;
return [NSArray array];
[source seek:0 whence:SEEK_END];
long size = [source tell];
@ -53,18 +53,16 @@
data.resize( size );
[source read:&data[0] amount:size];
midi_container midi_file;
size_t track_count = 0;
if ( !midi_processor::process_file( data, [[url pathExtension] UTF8String], midi_file) )
return 0;
if ( !midi_processor::process_track_count( data, [[url pathExtension] UTF8String], track_count) )
return [NSArray array];
long track_count = midi_file.get_subsong_count();
NSMutableArray *tracks = [NSMutableArray array];
long i;
for (i = 0; i < track_count; i++) {
[tracks addObject:[NSURL URLWithString:[[url absoluteString] stringByAppendingFormat:@"#%li", midi_file.get_subsong( i )]]];
[tracks addObject:[NSURL URLWithString:[[url absoluteString] stringByAppendingFormat:@"#%li", i]]];
}
return tracks;