Hi,
I’m a newbie to JUCE and I’ve been trying to develop a MIDI plugin to transform some of the incoming events and let others pass through. Unfortunately, it seems that only Note On and Note Off messages pass through, all other message types seem to be implicitly filtered out. I must be doing something wrong but I can’t figure it out. I simplified my code to the bare minimum so that it only counts incoming events by type. Here is the main parts of the processor code:
//==============================================================================
MidiTestAudioProcessor::MidiTestAudioProcessor()
:
#ifndef JucePlugin_PreferredChannelConfigurations
AudioProcessor (BusesProperties()
#if ! JucePlugin_IsMidiEffect
#if ! JucePlugin_IsSynth
.withInput ("Input", AudioChannelSet::stereo(), true)
#endif
.withOutput ("Output", AudioChannelSet::stereo(), true)
#endif
),
#endif
parameters(
*this,
nullptr,
Identifier("MidiTest"),
{
std::make_unique<AudioParameterInt>("allMidiMessageCount", "allMidiMessageCount", 0, 15, 0),
std::make_unique<AudioParameterInt>("noteOnCount", "noteOnCount", 0, 15, 0),
std::make_unique<AudioParameterInt>("noteOffCount", "noteOffCount", 0, 15, 0),
std::make_unique<AudioParameterInt>("programChangeCount", "programChangeCount", 0, 15, 0),
std::make_unique<AudioParameterInt>("ccCount", "ccCount", 0, 15, 0),
std::make_unique<AudioParameterInt>("otherCount", "otherCount", 0, 15, 0),
}
)
{
allMidiMessageCountParameter = static_cast<AudioParameterInt*>(parameters.getParameter("allMidiMessageCount"));
++parameterCount;
noteOnCountParameter = static_cast<AudioParameterInt*>(parameters.getParameter("noteOnCount"));
++parameterCount;
noteOffCountParameter = static_cast<AudioParameterInt*>(parameters.getParameter("noteOffCount"));
++parameterCount;
programChangeCountParameter = static_cast<AudioParameterInt*>(parameters.getParameter("programChangeCount"));
++parameterCount;
ccCountParameter = static_cast<AudioParameterInt*>(parameters.getParameter("ccCount"));
++parameterCount;
otherCountParameter = static_cast<AudioParameterInt*>(parameters.getParameter("otherCount"));
++parameterCount;
}
MidiTestAudioProcessor::~MidiTestAudioProcessor()
{
}
void MidiTestAudioProcessor::processBlock (AudioBuffer<float>&, MidiBuffer& midiBuffer)
{
if (!midiBuffer.getNumEvents())
return;
int allMidiMessageCount = 0;
int noteOnCount = 0;
int noteOffCount = 0;
int programChangeCount = 0;
int ccCount = 0;
int otherCount = 0;
MidiMessage midiMessage;
int samplePosition;
for (MidiBuffer::Iterator iterator(midiBuffer); iterator.getNextEvent(midiMessage, samplePosition);)
{
++allMidiMessageCount;
if (midiMessage.isNoteOn())
++noteOnCount;
else if (midiMessage.isNoteOff())
++noteOffCount;
else if (midiMessage.isProgramChange())
++programChangeCount;
else if (midiMessage.isController())
++ccCount;
else
++otherCount;
}
allMidiMessageCountParameter->beginChangeGesture();
allMidiMessageCountParameter->setValueNotifyingHost(allMidiMessageCountParameter->convertTo0to1(static_cast<float>(allMidiMessageCount)));
allMidiMessageCountParameter->endChangeGesture();
noteOnCountParameter->beginChangeGesture();
noteOnCountParameter->setValueNotifyingHost(noteOnCountParameter->convertTo0to1(static_cast<float>(noteOnCount)));
noteOnCountParameter->endChangeGesture();
noteOffCountParameter->beginChangeGesture();
noteOffCountParameter->setValueNotifyingHost(noteOffCountParameter->convertTo0to1(static_cast<float>(noteOffCount)));
noteOffCountParameter->endChangeGesture();
programChangeCountParameter->beginChangeGesture();
programChangeCountParameter->setValueNotifyingHost(programChangeCountParameter->convertTo0to1(static_cast<float>(programChangeCount)));
programChangeCountParameter->endChangeGesture();
ccCountParameter->beginChangeGesture();
ccCountParameter->setValueNotifyingHost(ccCountParameter->convertTo0to1(static_cast<float>(ccCount)));
ccCountParameter->endChangeGesture();
otherCountParameter->beginChangeGesture();
otherCountParameter->setValueNotifyingHost(otherCountParameter->convertTo0to1(static_cast<float>(otherCount)));
otherCountParameter->endChangeGesture();
}
The main part of the jucer file looks like:
<JUCERPROJECT id="Vmc7LZ" name="MidiTest" projectType="audioplug" jucerVersion="5.4.1" pluginFormats="buildVST3" pluginCharacteristicsValue="pluginProducesMidiOut,pluginWantsMidiIn" pluginVST3Category="Fx,Instrument,Tools" cppLanguageStandard="latest" bundleIdentifier="com.PbrSoft.MidiTest" companyName="PbrSoft" pluginManufacturer="PbrSoft">
I’m compiling the VST3 of the plugin using MS Visual Studio on Windows 7 SP1, the running it on Cubase 7.5 (64 bits) set up like this:
MidiTest plugin loaded as a Rack instrument
Midi track 01
Input: Midi controller port
Output: MidiTest plugin
Midi plugin: Midi Monitor (to show incoming messages)
Midi track 02
Input: MidiTest plugin
Output: output midi port
Midi plugin: Midi Monitor (to show output from MidiTest plugin)
I also noticed that Program Changes messages are never included in the MidiBuffer passed to processBlock(), most probably because they are filtered out before during the plugin preset management logic. Is there a way to tell JUCE to skip preset management logic and to include Program Changes messages in the MidiBuffer passed to processBlock()?
Thanks,
Paul