Handling MIDI CC data


#1

I have a synth plugin and up until now, I’ve been handling MIDI CC data by looking up what parameter is controlled by that particular CC# and then doing a

param->setValueNotifyingHost((float)controllerValue / 127.0f);

This has been working just fine. But now I have a user running Cubase on a Mac that says my plugin is “generating MIDI data” when he plays back a track with MIDI CC data controlling a parameter.

I KNOW that my plugin does not have a MIDI out, but I’m wondering if I’m generating that MIDI data by calling setValueNotifyingHost()?

So, is that the correct way to handle MIDI CC data inside the plugin? If not, I assume that I should then be changing the value of the parameter without notifying the host? And if that’s correct, how? There doesn’t seem to be a setValueWithoutNotifyingHost(), as setValue() is just a virtual function.

More info: It seems that Logic does not exhibit this behavior. But then again, he’s shown me the same example of other plugins not creating MIDI data like mine does in Cubase.

I feel like I’m missing something.


#3

I am a little confused:
are you taking the midi data from the processBlock or from a MidiInput device?
Both are valid approaches, but the midi data in the processBlock is usually saved somewhere in the host, so this user might see an echo of some previously recorded midi data?
If you take the MidiInput from the device, you circumvent the host’s midi routing, so you have to know your host and your users, to judge, if that is a good thing…


#4

I’m sorry, yes, the MIDI data that comes in processBlock.


#5

Are you clearing the MidiBuffer at the end of the processBlock()?

IIRC, anything left in the MidiBuffer at the end of the processBlock() is outputted as generated MIDI


#6

No, I don’t explicitly do a clear() on the MIDI buffer at the end of processNextBlock, but then again neither does the Synthesiser code, which I’m basically copying…unless the iterator does that.

What I’ve found is that if I update my parameters with setValue() instead of setValueNotifyingHost() when I receive a MIDI controller event for a mapped parameter, it works properly…meaning, it doesn’t generate new MIDI data. Although, I’m still a little fuzzy on this whole thing because Logic doesn’t doesn’t exhibit this behavior, but Cubase & Sonar do.

Maybe Jules or someone else can explain this, but it seems to me that handling MIDI CC data and handling a UI gesture change on a parameter would be similar situations …meaning that my code should notify the host that the parameter has changed, but if I do that with CC data, my users report that my plugin is “creating duplicate MIDI data”.


#7

Is this the VST3 format?

I am aware that in VST3 the plug-in can only receive CCs through a set of special parameters that are explicitly mapped to a corresponding CC.

In JUCE the VST3 wrapper takes care of that, and that could explain why this happens only in SONAR or Cubase (which both support VST3) while it does not happen in Logic which only opens AUs: it’s possible that, if you “move” that parameter internally, then it does translate in the generation of CCs that are then sent to the host?

More about this subject has been discussed here: (unfortunately I don’t remember much of the discussion there, even if I took part in it. Ah, my memory…)


#8

In consideration of my post above, you may attempt a simple workaround:

In juce_VST3_Wrapper.cpp,

find the function initialiseMidiControllerMappings()

and where it invokes parameters.addParameter() replace the parameter that is currently set as Vst::ParameterInfo::kCanAutomate with a simple 0.

This change should effectively detach from the automation the parameter that is internally added to the VST3 to intercept CCs, which IMHO is not needed (and in my own fork of JUCE is working fairly well that way).


#9

I’ll look at that a little later, but I’ve been working with VST2, not VST3.