Juce Audio Plugin 1.1 demo - MIDI pass through assert


#1

Apologies in advance for the novice question. I’m hitting the assert at JuceVstWrapper.cpp line 465 when running the Juce Audio Plugin framework demo under VSThost, suggesting the filter is trying to output MIDI messages when it shouldn’t.

As far as I can tell, the plug in shouldn’t be outputting any MIDI messages:

void DemoJuceFilter::initialiseFilterInfo (FilterInfo& info) { ... info.producesMidiOutput = false;

Does this mean DemoJuceFilter::processBlock() should be calling midiMessages.clear() at some point?

Cheers,

Steve.


#2

yeah… that assert’s completely wrong if you’ve got midi coming in but not going out. Feel free to chop it out and I’ll do the same.


#3

Struck me the assert looked sensible, but the filter should either stop passing the messages through, or just announce that it produces messages. I thought probably the former, and it seemed like the following change would be okay in DemoJuceFilter::processBlock ()

// if any midi messages come in, record the last one, and fire off a change message // to our UI component, which will pick up this new message and repaint itself. if (midiMessages.size() > 0) { lastMidiMessage = *midiMessages.getLast(); sendChangeMessage (this); midiMessages.clear(); // change: stop messages from being passed on }
Cheers,

Steve.


#4

I suppose so - but rather than making all the plugins clear the array (which gets done by the wrapper code later anyway), how about this as a smarter assertion:

    void process (float** inputs, float** outputs, 
                  const long numSamples, const bool accumulate)
    {

        const int numMidiEventsComingIn = midiEvents.size();


        jassert (activePlugins.contains (this));

        {
            const AudioSampleBuffer input (inputs, numInputChans, numSamples);
            AudioSampleBuffer output (outputs, numOutputChans, numSamples);

            const ScopedLock sl (filter->getCallbackLock());
            filter->processBlock (input, output, accumulate, midiEvents);
        }

        if (midiEvents.size() > 0)
        {
            if (producesMidi)
            {
                ensureOutgoingEventSize (midiEvents.size());
                outgoingEvents->numEvents = midiEvents.size();

                for (int i = 0; i < midiEvents.size(); ++i)
                {
                    const MidiMessage* const m = midiEvents.getUnchecked(i);

                    VstMidiEvent* const vme = (VstMidiEvent*) outgoingEvents->events[i];

                    vme->midiData[0] = m->getRawData()[0];
                    vme->midiData[1] = m->getRawData()[1];
                    vme->midiData[2] = m->getRawData()[2];
                    vme->midiData[3] = m->getRawData()[3];
                    vme->deltaFrames = roundDoubleToInt (m->getTimeStamp());

                    jassert (vme->deltaFrames >= 0 && vme->deltaFrames < numSamples);
                }

                sendVstEventsToHost (outgoingEvents);
            }
            else
            {

                // if your plugin creates midi messages, you'll need to set its
                // "producesMidi" flag to true..
                jassert (midiEvents.size() <= numMidiEventsComingIn);

            }

            midiEvents.clear();
        }
    }

#5

That would certainly keep it simpler for the filter creator, but might miss (for example) an error where a filter is processing incoming MIDI events on a 1:1 basis (maybe just remapping a CC event for example), but where info.producesMidiOutput is incorrectly set to false?

Steve.


#6

Hmm. True. But the only other way to catch it would be to have separate in and out buffers. (Not sure if that’d be a better or worse way of doing it)


#7

I thought the original assert was fine to be honest, and that it’s down to the filter to clear the buffer down. Seemed pretty reasonable to me, as long as the demo filter is in line with that. Input/output buffers would seem like sledgehammer/walnut territory?


#8