VST Midi Out Performance


#1

Hey everyone!

 

I'm brand new to JUCE, I'd just like to say that it's amazing how relatively painless getting everything set up with the IntroJucer and VS2013 was.  It's an extraordinarly impressive framework.

 

Anyways, I'm making a simple VST that turns a Novation Launchpad into a spectrum analyzer.  It basically just does a FFT, does some processing to downsample the results to something that can be displayed on an 8 x 8 grid, then dumps that out via MIDI note on messages to activate the Launchpad's LEDs.  

 

I've got everything working nicely, except I've run into a snag where dumping out more than around 50 MIDI messages per second starts spiking the CPU like crazy.  I've narrowed it down to the MIDI output being the problem; if I change the MIDI out port on the VST wrapper so that it's not sending to my Launchpad, CPU use is negligable as I would expect.  Just in general, the MIDI output seems to be using way more cycles than it should.


I'm likely doing something wrong, but I haven't been able to figure out what's going on. Here's a snippet of my code that's generating the MIDI output:
 


void LaunchpadLightsAudioProcessor::dumpGridStateToMidi(MidiBuffer& midiMessages)
{
    midiMessages.clear();
    midiMessages.ensureSize(3 * (64 + 2));
    for (int row = 0; row < 8; ++row)
    {
        for (int col = 0; col < 8; ++col)
        {
            if (colorGrid[row][col] != lastColorGrid[row][col])
            {
                MidiMessage ledUpdate(144, rowColToMidiNote[row][col], colorGrid[row][col]);
                ledUpdate.setChannel(1);
                midiMessages.addEvent(ledUpdate, midiMessages.getLastEventTime() + 1);
                lastColorGrid[row][col] = colorGrid[row][col];
            }
        }
    }
}

Any kind of help or direction is appreciated!

Some other potentially relevant info:

  • That method is being called from processBlock, but not on every processBlock, it's called about 24 times per second.
  • 32-bit Windows VST2
  • Host is FL Studio 11 32 bit
  • According to the Launchpad Programmer's Reference Guide, "Launchpad uses a low-speed version of USB. A limitation of this is that it accepts a maximum of 400 messages per second."

#2

Glad you like it!

MidiBuffer::getLastEventTime() is an O(N) operation - if you call it every time you add a message, your algorithm becomes O(N*N).

And you wouldn't want to do that anyway.. You can't just take a bunch of midi events and dump them on consecutive samples, you should give each one a time that's actually meaningful.


#3

Okay, thanks, I fixed that N2 issue.  Now I'm dumping all the messages on sample 0.  The way I have it set up, the Launchpad is being updated 24 frames per second.  Each frame has a maximum possible 64 messages, but in reality it's far less than that.  I'd like all the messages in each frame to get sent as quickly as possible.

In any case, it didn't fix the performance problems.  I'm beginning to suspect that it's a USB/MIDI driver issue, because without the hardware hooked up, the VST does the same processing and the performance hit is negligible.  With the hardware the CPU regularly spikes to 80 - 90% when a large amount of messages are being sent.  But, in this case, large isn't really that large.  Just around 200 - 400 messages per second.