Hey guys,
I’m working on a project where essentially what I need to do is parse a midi file (it is a midi recording of a two handed piano piece) and split it up into its voices. Fortunately the voices do not overlap much so I have hardcoded 4 sequences for each voice. I then iterate through the midi file and check each event to see if it is the next note in one the expected sequences and if so I copy it to a new midi sequence. After all that is done I add each sequence to a new midi file and output 4 midi files. However, I seem to be losing the time structure or perhaps the note-off events when I copy each voice over. I’m not sure exactly. The following is done in the process function:
const MidiMessageSequence* eventList;
eventList = inputFile.getTrack(0);
inputFile.convertTimestampTicksToSeconds();
extractVoices(eventList); //Separate voices into individual midi sequences
outputFile1.setTicksPerQuarterNote(inputFile.getTimeFormat());
outputFile2.setTicksPerQuarterNote(inputFile.getTimeFormat());
outputFile3.setTicksPerQuarterNote(inputFile.getTimeFormat());
outputFile4.setTicksPerQuarterNote(inputFile.getTimeFormat());
outputFile1.addTrack(rightHandSequence);
outputFile2.addTrack(leftHandTopSequence);
outputFile3.addTrack(leftHandMiddleSequence);
outputFile4.addTrack(leftHandBottomSequence);
File file;
file = File::createFileWithoutCheckingPath("right hand.mid");
FileOutputStream stream1(file);
stream1.flush();
stream1.setPosition(0);
outputFile1.writeTo(stream1);
file = File::createFileWithoutCheckingPath("left hand top.mid");
FileOutputStream stream2(file);
stream2.flush();
stream2.setPosition(0);
outputFile2.writeTo(stream2);
file = File::createFileWithoutCheckingPath("left hand middle.mid");
FileOutputStream stream3(file);
stream3.flush();
stream3.setPosition(0);
outputFile3.writeTo(stream3);
file = File::createFileWithoutCheckingPath("left hand bottom.mid");
FileOutputStream stream4(file);
stream4.flush();
stream4.setPosition(0);
outputFile4.writeTo(stream4);
And here is the extract voices function:
void extractVoices(const MidiMessageSequence* midiSequence)
{
MidiMessageSequence::MidiEventHolder* currentEvent;
MidiMessage currentMessage;
int noteNumber;
int i = 0;
int j = 0;
int k = 0;
int l = 0;
for(int event = 0; event < midiSequence->getNumEvents(); event++)
{
currentEvent = midiSequence->getEventPointer(event);
currentMessage = currentEvent->message;
noteNumber = currentMessage.getNoteNumber();
if(currentMessage.isNoteOn())
{
/*See if current note belongs to one of the predefined voice sequences*/
if(noteNumber == galopSequenceRH[i])
{
rightHandSequence.addEvent(currentMessage, currentMessage.getTimeStamp());
rightHandSequence.updateMatchedPairs();
i++;
}
else if(noteNumber == galopSequenceLHTop[j])
{
leftHandTopSequence.addEvent(currentMessage, currentMessage.getTimeStamp());
leftHandTopSequence.updateMatchedPairs();
j++;
}
else if(noteNumber == galopSequenceLHMiddle[k])
{
leftHandMiddleSequence.addEvent(currentMessage, currentMessage.getTimeStamp());
leftHandMiddleSequence.updateMatchedPairs();
k++;
}
else if(noteNumber == galopSequenceLHBottom[l])
{
leftHandBottomSequence.addEvent(currentMessage, currentMessage.getTimeStamp());
leftHandBottomSequence.updateMatchedPairs();
l++;
}
}
}
}
