How do I store the Midi Input in a data structure that persists the lifetime of the session?

What I want to accomplish in a plugin is as follows:

  1. All Midi Input Events should be stored in a data structure (MidiMessageSequence?)
  2. While saving each event, I may make some modification when the message is ‘Note On’ or I work on the entire sequence of midi events as a whole.
  3. The data structure should persist till I close the plugin.

What I am doing currently

  1. I keep a public MidiMessageSequence variable tempSequence.
  2. In the processBlock I add the event to the sequence using
    tempSequence.addEvent(message.getMessage()) with for (auto messages : midibuffer)'.
    This ‘midibuffer’ is the buffer from processBlock.
  3. Then I have a button in the GUI which when clicked gives an option to save a file to which the MidiMessageSequence is stored. I use the approach shown here.
  4. The exact code I am using is as follows :
std::cout << "save button clicked" << std::endl;
    chooser = std::make_unique<juce::FileChooser> ("Select location to save file...",
                                                       juce::File{},
                                                       "*.mid");
   auto chooserFlags = juce::FileBrowserComponent::openMode | juce::FileBrowserComponent::saveMode ;
   chooser->launchAsync (chooserFlags, [this] (const juce::FileChooser& fc)
   {
     auto file = fc.getResult();
     juce::MidiFile midiFile;           
     midiFile.addTrack(audioProcessor.tempSequence);
     juce::FileOutputStream myStream (fc.getResult());
     midiFile.writeTo (myStream);
   
   }); 

The main questions regarding above are :

  1. Will tempSequence keep the added MidiMessage Events?
  2. If yes, is the approach of saving the file correct?

Update
When I add the following line just before saving tempSequence, it does show more than 0 number of events. This means the format of midi getting saved is wrong.

std::cout << audioProcessor.tempSequence.getNumEvents() << std::endl;

Q : Is the way I am adding events to the MidiMessageSequence object wrong?

I’d advice you to don’t use the MidiMessageSequence. Depending on how long your runtime is, you’ll might run into some serious runtime issues because adding a new message to the sequence is in O(n) so it gets worse the more events you add. Try using a linked list to avoid this issue and either append from front to back or use a double linked list.

Concerning the saving: how exactly do you know it is not working? Is the midi file empty and the size is 0B or cannot it just not be loaded. You might need to change the format of the midi file. Check out the docs of juce::MidiFile, it actually reads quite fast.

1 Like

What other object can I use to store Midi Input? MidiMessageCollector?

For the saving part, when I open the midi file in MidiYodi it shows no notes. When I simply double click to play it (usually plays on my Machine), it shows incorrect format.

I don’t see anything in the juce::MidiFIle which talks about the format or type of the midi file