diff --git a/modules/juce_audio_processors/format_types/juce_VST3Common.h b/modules/juce_audio_processors/format_types/juce_VST3Common.h index d9326458f0..caf15bb265 100644 --- a/modules/juce_audio_processors/format_types/juce_VST3Common.h +++ b/modules/juce_audio_processors/format_types/juce_VST3Common.h @@ -492,7 +492,9 @@ public: } } - static void toEventList (Steinberg::Vst::IEventList& result, MidiBuffer& midiBuffer) + static void toEventList (Steinberg::Vst::IEventList& result, MidiBuffer& midiBuffer, + Steinberg::Vst::IParameterChanges* parameterChanges = nullptr, + Steinberg::Vst::IMidiMapping* midiMapping = nullptr) { MidiBuffer::Iterator iterator (midiBuffer); MidiMessage msg; @@ -506,6 +508,28 @@ public: if (++numEvents > maxNumEvents) break; + if (midiMapping != nullptr && parameterChanges != nullptr) + { + Vst3MidiControlEvent controlEvent; + + if (toVst3ControlEvent (msg, controlEvent)) + { + Steinberg::Vst::ParamID controlParamID; + + if (midiMapping->getMidiControllerAssignment (0, createSafeChannel (msg.getChannel()), + controlEvent.controllerNumber, + controlParamID) == Steinberg::kResultOk) + { + Steinberg::int32 ignore; + + if (auto* queue = parameterChanges->addParameterData (controlParamID, ignore)) + queue->addPoint (midiEventPosition, controlEvent.paramValue, ignore); + } + + continue; + } + } + Steinberg::Vst::Event e = { 0 }; if (msg.isNoteOn()) @@ -534,12 +558,12 @@ public: e.data.size = (uint32) msg.getSysExDataSize(); e.data.type = Steinberg::Vst::DataEvent::kMidiSysEx; } - else if (msg.isAftertouch()) + else if (msg.isChannelPressure()) { e.type = Steinberg::Vst::Event::kPolyPressureEvent; e.polyPressure.channel = createSafeChannel (msg.getChannel()); e.polyPressure.pitch = createSafeNote (msg.getNoteNumber()); - e.polyPressure.pressure = normaliseMidiValue (msg.getAfterTouchValue()); + e.polyPressure.pressure = normaliseMidiValue (msg.getChannelPressureValue()); } else { @@ -566,6 +590,24 @@ private: static float normaliseMidiValue (int value) noexcept { return jlimit (0.0f, 1.0f, (float) value / 127.0f); } static int denormaliseToMidiValue (float value) noexcept { return roundToInt (jlimit (0.0f, 127.0f, value * 127.0f)); } + //============================================================================== + struct Vst3MidiControlEvent + { + Steinberg::Vst::CtrlNumber controllerNumber; + Steinberg::Vst::ParamValue paramValue; + }; + + static bool toVst3ControlEvent (const MidiMessage& msg, Vst3MidiControlEvent& result) + { + result.controllerNumber = -1; + + if (msg.isController()) result = { (Steinberg::Vst::CtrlNumber) msg.getControllerNumber(), msg.getControllerValue() / 127.0}; + else if (msg.isPitchWheel()) result = { Steinberg::Vst::kPitchBend, msg.getPitchWheelValue() / 16383.0}; + else if (msg.isAftertouch()) result = { Steinberg::Vst::kAfterTouch, msg.getAfterTouchValue() / 127.0}; + + return (result.controllerNumber != -1); + } + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiEventList) }; diff --git a/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp index 6a537be411..acd09e16d7 100644 --- a/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp @@ -1835,6 +1835,7 @@ struct VST3PluginInstance : public AudioPluginInstance componentHandler2 = nullptr; componentHandler = nullptr; processor = nullptr; + midiMapping = nullptr; editController2 = nullptr; editController = nullptr; } @@ -2558,6 +2559,7 @@ private: // Rudimentary interfaces: ComSmartPtr editController; ComSmartPtr editController2; + ComSmartPtr midiMapping; ComSmartPtr processor; ComSmartPtr componentHandler; ComSmartPtr componentHandler2; @@ -2649,6 +2651,7 @@ private: programListData.loadFrom (holder->component); unitData.loadFrom (holder->component); editController2.loadFrom (holder->component); + midiMapping.loadFrom (holder->component); componentHandler.loadFrom (holder->component); componentHandler2.loadFrom (holder->component); trackInfoListener.loadFrom (holder->component); @@ -2658,6 +2661,7 @@ private: if (programListData == nullptr) programListData.loadFrom (editController); if (unitData == nullptr) unitData.loadFrom (editController); if (editController2 == nullptr) editController2.loadFrom (editController); + if (midiMapping == nullptr) midiMapping.loadFrom (editController); if (componentHandler == nullptr) componentHandler.loadFrom (editController); if (componentHandler2 == nullptr) componentHandler2.loadFrom (editController); if (trackInfoListener == nullptr) trackInfoListener.loadFrom (editController); @@ -2784,7 +2788,9 @@ private: midiInputs->clear(); midiOutputs->clear(); - MidiEventList::toEventList (*midiInputs, midiBuffer); + MidiEventList::toEventList (*midiInputs, midiBuffer, + destination.inputParameterChanges, + midiMapping); destination.inputEvents = midiInputs; destination.outputEvents = midiOutputs;