handle note data on any track and don't hard-code to track 1

This commit is contained in:
Chris Danford
2007-05-16 19:40:28 +00:00
parent 66894d80ed
commit 16194d7e53
+70 -26
View File
@@ -587,6 +587,24 @@ namespace Guitar
channel_aftertouch = 0xD, channel_aftertouch = 0xD,
pitch_bend = 0xE, pitch_bend = 0xE,
}; };
enum MetaEventType
{
sequence_number = 0x00,
text_event = 0x01,
copyright_notice = 0x02,
track_name = 0x03,
instrument_name = 0x04,
lyrics = 0x05,
marker = 0x06,
cue_point = 0x07,
midi_channel_prefix = 0x20,
end_of_track = 0x2F,
set_tempo = 0x51,
smpte_offset = 0x54,
time_signature = 0x58,
key_signature = 0x59,
sequencer_specific = 0x7F,
};
struct MidiEvent struct MidiEvent
{ {
long count; long count;
@@ -681,48 +699,74 @@ static bool LoadFromMidi( const RString &sPath, Song &songOut )
* step is helpful. */ * step is helpful. */
vector<MidiEvent> vMidiEvent[NUM_GuitarDifficulty][NUM_NoteNumberType]; vector<MidiEvent> vMidiEvent[NUM_GuitarDifficulty][NUM_NoteNumberType];
/* Iterate through each track looking for the track that contains notes by checking the track name.
* This is usually track 1, but sometimes is track 2. */
for( int iTrack = 1; iTrack<(int)midi.getNumberOfTracks(); iTrack++ )
{ {
std::vector<unsigned char> event; std::vector<unsigned char> event;
int iTrack = 1; // this track should be named "T1 GEMS" or "PART GUITAR"
unsigned long count = midi.getNextEvent( &event, iTrack ); unsigned long count = midi.getNextEvent( &event, iTrack );
double fSeconds = midi.getTickSeconds( iTrack ); double fSeconds = midi.getTickSeconds( iTrack );
while( event.size() ) while( event.size() )
{ {
MidiEventType midiEventType = (MidiEventType)(event[0] >> 4); if( event[0] == 0xFF ) // meta event
//uint8_t uMidiChannel = event[0] & 0xF; // currently unused
uint8_t uParam1 = event[1]; // meaning is MidiEventType-specific
uint8_t uParam2 = event[2]; // currently unused, meaning is MidiEventType-specific
switch( midiEventType )
{ {
case note_off: uint8_t uMetaEventType = event[1];
case note_on: switch( uMetaEventType )
{ {
const uint8_t &uNoteNumber = uParam1; case track_name:
const uint8_t &uVelocity = uParam2;
// velocity == 0, by convention, means note-off
if( uVelocity == 0 )
midiEventType = note_off;
GuitarDifficulty gd;
NoteNumberType nnt;
if( NoteNumberToDifficultyAndNoteNumberType( uNoteNumber, gd, nnt ) )
{ {
MidiEvent event = { count, midiEventType }; uint8_t uStringLength = event[2];
//float fBeat = NoteRowToBeat( MidiCountToNoteRow(count) ); RString s;
vMidiEvent[gd][nnt].push_back( event ); for( int i=3; i<3 + uStringLength; i++ )
s += event[i];
if( s != "T1 GEMS" && s != "PART GUITAR" )
goto skip_track;
} }
break;
default:
LOG->Trace( "Unhandled MIDI meta event type %X", uMetaEventType );
}
}
else
{
MidiEventType midiEventType = (MidiEventType)(event[0] >> 4);
//uint8_t uMidiChannel = event[0] & 0xF; // currently unused
uint8_t uParam1 = event[1]; // meaning is MidiEventType-specific
uint8_t uParam2 = event[2]; // currently unused, meaning is MidiEventType-specific
switch( midiEventType )
{
case note_off:
case note_on:
{
const uint8_t &uNoteNumber = uParam1;
const uint8_t &uVelocity = uParam2;
// velocity == 0, by convention, means note-off
if( uVelocity == 0 )
midiEventType = note_off;
GuitarDifficulty gd;
NoteNumberType nnt;
if( NoteNumberToDifficultyAndNoteNumberType( uNoteNumber, gd, nnt ) )
{
MidiEvent event = { count, midiEventType };
//float fBeat = NoteRowToBeat( MidiCountToNoteRow(count) );
vMidiEvent[gd][nnt].push_back( event );
}
}
break;
default:
LOG->Trace( "Unhandled MIDI event type %X", midiEventType );
break;
} }
break;
default:
LOG->Trace( "Unhandled MIDI event type %X", midiEventType );
break;
} }
count += midi.getNextEvent( &event, iTrack ); count += midi.getNextEvent( &event, iTrack );
fSeconds = midi.getTickSeconds( iTrack ); fSeconds = midi.getTickSeconds( iTrack );
} }
skip_track:
;
} }