Hi everyone!
I’m creating an organ plugin and I’m having some trouble using three MidiKeyboardComponent
objects at once. Right now I’m creating three keyboards (upper manual, lower manual, pedal board), and the result looks like I’d expect:
I started by declaring three public MidiKeyboardState
objects in PluginProcessor.h
:
juce::MidiKeyboardState keyboardStateUpperManual;
juce::MidiKeyboardState keyboardStateLowerManual;
juce::MidiKeyboardState keyboardStatePedalBoard;
Then in In PluginEditor.h
, I’ve declared three MidiKeyboard
objects and three MidiKeyboardState
objects.
juce::MidiKeyboard midikeyboardUpperManual;
juce::MidiKeyboard midikeyboardLowerManual;
juce::MidiKeyboard midikeyboardPedalBoard;
juce::MidiKeyboardState keyboardStateUpperManual;
juce::MidiKeyboardState keyboardStateLowerManual;
juce::MidiKeyboardState keyboardStatePedalBoard;
In PluginEditor.cpp
I’ve modified the constructor like this to initialize the six objects:
OpenB3AudioProcessorEditor::OpenB3AudioProcessorEditor (OpenB3AudioProcessor& p)
: AudioProcessorEditor (&p),
audioProcessor (p),
midiKeyboardUpperManual(audioProcessor.keyboardStateUpperManual, juce::MidiKeyboardComponent::horizontalKeyboard),
midiKeyboardLowerManual(audioProcessor.keyboardStateLowerManual, juce::MidiKeyboardComponent::horizontalKeyboard),
midiKeyboardPedalBoard(audioProcessor.keyboardStatePedalBoard, juce::MidiKeyboardComponent::horizontalKeyboard)
...
And I’ve configured each MidiKeyboard
with a different MIDI channel:
midiKeyboardUpperManual.setMidiChannel(1);
midiKeyboardLowerManual.setMidiChannel(2);
midiKeyboardPedalBoard.setMidiChannel(3);
In PluginProcessor.cpp, inside processBlock, I call processNextMidiBuffer
on each keyboard state to add its MIDI messages to the midi buffer. Then based on the channel number, I choose to what manual I should send the note on/note off messages:
keyboardStateUpperManual.processNextMidiBuffer (midiMessages, 0, buffer.getNumSamples(), true);
keyboardStateLowerManual.processNextMidiBuffer (midiMessages, 0, buffer.getNumSamples(), true);
keyboardStatePedalBoard.processNextMidiBuffer (midiMessages, 0, buffer.getNumSamples(), true);
for (const auto metadata : midiMessages) { juce::MidiMessage message = metadata.getMessage(); switch (message.getChannel()) { case 1: // Upper Manual std::cout << "You're playing the upper manual" << std::endl; if (message.isNoteOn()) beatrix->note_on(message.getNoteNumber()-36); else if(message.isNoteOff()) beatrix->note_off(message.getNoteNumber()-36); break; case 2: // Lower Manual std::cout << "You're playing the lower manual" << std::endl; if (message.isNoteOn()) beatrix->note_on(message.getNoteNumber()+28); else if(message.isNoteOff()) beatrix->note_off(message.getNoteNumber()+28); break; case 3: // Pedal Board std::cout << "You're playing the pedal board" << std::endl; if (message.isNoteOn()) beatrix->note_on(message.getNoteNumber()+92); else if(message.isNoteOff()) beatrix->note_off(message.getNoteNumber()+92); break; default: break; } }
From the console and from the organ sound, I can confirm that the right notes are played (each manual has a different register setting, so I can tell).
Now to the problem: when I press a note on the upper manual, I can clearly see that the same notes are being pressed on the keyboards of the lower manual and pedal board. When I press a note on the lower manual, the same notes are pressed on the pedal board. When I press a note on the pedal board, the behavior is correct (only pedal board notes are showed as pressed).
Since in all three cases, the organ plays the right notes, I conclude that this is a GUI problem. I must have made some mistake with the usage of MidiKeyboard
and/or MidiKeyboardState
.
Would anybody be so kind to share their thoughts? Thank you so much