handle "velocity==0 means note-off". Makes for better handling of the case where notes overlap

This commit is contained in:
Chris Danford
2007-04-25 05:44:24 +00:00
parent 7f6a237cdd
commit 3014b3f9d8
+36 -30
View File
@@ -4,7 +4,7 @@
* MIDI event info is explained here: http://www.sonicspot.com/guide/midifiles.html * MIDI event info is explained here: http://www.sonicspot.com/guide/midifiles.html
* Explanation of MIDI "running status" here: http://www.borg.com/~jglatt/tech/midispec/run.htm * Explanation of MIDI "running status" and note-on velocity==0 meaning: http://www.borg.com/~jglatt/tech/midispec/run.htm
* Guitar track mappings are explained here: http://www.scorehero.com/forum/viewtopic.php?t=1179 * Guitar track mappings are explained here: http://www.scorehero.com/forum/viewtopic.php?t=1179
@@ -650,9 +650,9 @@ static bool LoadFromMidi( const RString &sPath, Song &songOut )
while( event.size() ) while( event.size() )
{ {
MidiEventType midiEventType = (MidiEventType)(event[0] >> 4); MidiEventType midiEventType = (MidiEventType)(event[0] >> 4);
//uint8_t uMidiChannel = event[0] & 0xF; // currently unused uint8_t uMidiChannel = event[0] & 0xF; // currently unused
uint8_t uParam1 = event[1]; // meaning is MidiEventType-specific uint8_t uParam1 = event[1]; // meaning is MidiEventType-specific
//uint8_t uParam2 = event[2]; // currently unused, meaning is MidiEventType-specific uint8_t uParam2 = event[2]; // currently unused, meaning is MidiEventType-specific
switch( midiEventType ) switch( midiEventType )
{ {
@@ -660,7 +660,11 @@ static bool LoadFromMidi( const RString &sPath, Song &songOut )
case note_on: case note_on:
{ {
const uint8_t &uNoteNumber = uParam1; const uint8_t &uNoteNumber = uParam1;
//const uint8_t &uVelocity = uParam2; // currently unused const uint8_t &uVelocity = uParam2;
// velocity == 0, by convention, means note-off
if( uVelocity == 0 )
midiEventType = note_off;
GuitarDifficulty gd; GuitarDifficulty gd;
NoteNumberType nnt; NoteNumberType nnt;
@@ -693,7 +697,7 @@ static bool LoadFromMidi( const RString &sPath, Song &songOut )
if( nnt >= NUM_FRETS ) if( nnt >= NUM_FRETS )
continue; // data other than the frets is not handled yet continue; // data other than the frets is not handled yet
bool bTrackIsOn = false; bool bNonTerminatedNote = false;
long countOfLastNote = 0; long countOfLastNote = 0;
FOREACH_CONST( MidiEvent, vMidiEvent[gd][nnt], iter ) FOREACH_CONST( MidiEvent, vMidiEvent[gd][nnt], iter )
{ {
@@ -722,67 +726,69 @@ static bool LoadFromMidi( const RString &sPath, Song &songOut )
long count = iter->count; long count = iter->count;
float fBeat = NoteRowToBeat( MidiCountToNoteRow(count) ); float fBeat = NoteRowToBeat( MidiCountToNoteRow(count) );
bool bNoteHandled = false; bool bNoteHandled = false;
if( bTrackIsOn ) long length = count - countOfLastNote;
{
if( midiEventType == note_off || midiEventType == note_on )
{
// end this track
long length = count - countOfLastNote;
// Check for termination of a sustain note
switch( midiEventType )
{
case note_off:
case note_on:
if( bNonTerminatedNote )
{
if( length >= 240 ) if( length >= 240 )
{ {
TapNote tn = TAP_ORIGINAL_HOLD_HEAD; TapNote tn = TAP_ORIGINAL_HOLD_HEAD;
tn.iDuration = MidiCountToNoteRow( length ); tn.iDuration = MidiCountToNoteRow( length );
noteData.SetTapNote( nnt, MidiCountToNoteRow(countOfLastNote), tn ); noteData.SetTapNote( nnt, MidiCountToNoteRow(countOfLastNote), tn );
if( gd == expert && fBeat >= 9*4-2 && nnt == yellow ) // if( gd == expert && fBeat >= 27*4-2 && nnt == green )
LOG->Trace( "Added hold at %f", fBeat ); // LOG->Trace( "Added hold at %f, length %d", fBeat, length );
} }
bTrackIsOn = false; bNonTerminatedNote = false;
countOfLastNote = 0;
bNoteHandled = true; bNoteHandled = true;
} }
break;
} }
else
switch( midiEventType )
{ {
if( midiEventType == note_on ) case note_on:
{ {
// start this track
TapNote tn = TAP_ORIGINAL_TAP; TapNote tn = TAP_ORIGINAL_TAP;
// We're about to add a tap note. If the previous note was a sustain note that ended // We're about to add a tap note. If the previous note was a sustain note that ended
// on this row, then make the sustain note one row shorter so that it doesn't end on // on this row, then make the sustain note shorter so that it doesn't end on
// the same row as the tap note we're about to add. NoteData cannot handle a // the same row as the tap note we're about to add. NoteData cannot handle a
// hold note ending on the same row as a tap note. // hold note ending on the same row as a tap note.
NoteData::iterator begin, end; NoteData::iterator begin, end;
noteData.GetTapNoteRangeInclusive( nnt, MidiCountToNoteRow(count), MidiCountToNoteRow(count), begin, end, true ); noteData.GetTapNoteRangeInclusive( nnt, MidiCountToNoteRow(count), MidiCountToNoteRow(count), begin, end, true );
for( NoteData::iterator iter = begin; iter != end; iter++ ) for( NoteData::iterator iter = begin; iter != end; iter++ )
{ {
if( gd == expert && fBeat >= 9*4-2 && nnt == yellow ) // if( gd == expert && fBeat >= 27*4-2 && nnt == green )
LOG->Trace( "shortening hold at %f", fBeat ); // LOG->Trace( "shortening hold at %f, length %d", fBeat, length );
ASSERT( iter->second.type == TapNote::hold_head ); ASSERT( iter->second.type == TapNote::hold_head );
ASSERT( iter->first + iter->second.iDuration == MidiCountToNoteRow(count) ); iter->second.iDuration = MidiCountToNoteRow(count) - iter->first - 2;
iter->second.iDuration -= 2;
} }
noteData.SetTapNote( nnt, MidiCountToNoteRow(count), tn ); noteData.SetTapNote( nnt, MidiCountToNoteRow(count), tn );
if( gd == expert && fBeat >= 9*4-2 && nnt == yellow ) // if( gd == expert && fBeat >= 27*4-2 && nnt == green )
LOG->Trace( "Added tap at %f", fBeat ); // LOG->Trace( "Added tap at %f, length %d", fBeat, length );
bTrackIsOn = true; bNonTerminatedNote = true;
countOfLastNote = count;
bNoteHandled = true; bNoteHandled = true;
} }
} }
countOfLastNote = count;
if( !bNoteHandled ) if( !bNoteHandled )
{ LOG->Warn( "Unexpected MIDI event type %X at count %ld", midiEventType, count );
LOG->Trace( "Unexpected MIDI event type %X at count %ld", midiEventType, count );
}
} }
} }