I’ve been doing some basic experiments creating MIDI events on the fly from inside the processBlock callback, stashing them away so that I can actually send them out later on. In my first attempt, I just used the STL priority_queue with the default Vector to contain MidiMessage objects. I found that quite soon, MainStage (part of Logic Studio) would display overloads, audio would cut out for a while, sometimes come back later. I also found occasional timing glitches.
After eliminating everything else from the processBlock, I concluded that I might be having a problem due to the STL reallocating memory, etc. I was able to improve things noticibly by reserving space in the vector, but I still saw the problem, just less frequently.
I then threw out the STL (no big loss!) and created a simple array-based priority queue. This improved things dramtically and rather than the few minutes of things working OK, I was able to get 15-20 minutes or so with mostly no problems but I would “occasionally” see a very minor timing delay.
Ultimately, MainStage crashed and, looking at the stack trace, I noted that the crash happened during a MidiMessage copy constructor. I realized that even the MidiMessage class uses dynamic allocation to store the MIDI data.
So I have a couple of questions:
- What’s the recommended approach for managing memory inside the processBlock callback if one needs to create lots of MidiMessage events?
- This issue sort of hints at the notion of having a base MidiMessage class and then subclassing it with various implementations to handle simple MIDI events vs. sysex. The former could work using a simple array (on the stack). Is there a reason it wasn’t done this way or is this just legacy?