Parsing MIDI file and generating new MIDI file

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++;
            }
        }
    }
}
1 Like

Of course right after I post this I figure out that the time stamp conversion to seconds was screwing everything up. However, I think I am still losing the note-off events…

1 Like

And for some reason I cannot get the output to maintain the event timing/tempo. I need the output sequences to maintain the relative timing/tempo exactly.