From 1e6cdd841b60fc32f27e5300d835bbc3d6ff0fa8 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Wed, 14 Oct 2020 20:04:59 +0200 Subject: [PATCH] Implement MIDI sending to VST from UI --- vst/SfizzVstEditor.cpp | 16 +++++++++--- vst/SfizzVstEditor.h | 2 +- vst/SfizzVstProcessor.cpp | 51 ++++++++++++++++++++++++++++++++++++++- vst/SfizzVstProcessor.h | 2 ++ 4 files changed, 66 insertions(+), 5 deletions(-) diff --git a/vst/SfizzVstEditor.cpp b/vst/SfizzVstEditor.cpp index 1d0a127f..9746cdf9 100644 --- a/vst/SfizzVstEditor.cpp +++ b/vst/SfizzVstEditor.cpp @@ -176,10 +176,20 @@ void SfizzVstEditor::uiEndSend(EditId id) getController()->endEdit(pid); } -void SfizzVstEditor::uiSendMIDI(const uint8_t* msg, uint32_t len) +void SfizzVstEditor::uiSendMIDI(const uint8_t* data, uint32_t len) { - // TODO send MIDI... - + SfizzVstController* ctl = getController(); + + Steinberg::OPtr msg { ctl->allocateMessage() }; + if (!msg) { + fprintf(stderr, "[Sfizz] UI could not allocate message\n"); + return; + } + + msg->setMessageID("MidiMessage"); + Vst::IAttributeList* attr = msg->getAttributes(); + attr->setBinary("Data", data, len); + ctl->sendMessage(msg); } /// diff --git a/vst/SfizzVstEditor.h b/vst/SfizzVstEditor.h index 9c918765..a0730220 100644 --- a/vst/SfizzVstEditor.h +++ b/vst/SfizzVstEditor.h @@ -40,7 +40,7 @@ protected: void uiSendValue(EditId id, const EditValue& v) override; void uiBeginSend(EditId id) override; void uiEndSend(EditId id) override; - void uiSendMIDI(const uint8_t* msg, uint32_t len) override; + void uiSendMIDI(const uint8_t* data, uint32_t len) override; private: void loadSfzFile(const std::string& filePath); diff --git a/vst/SfizzVstProcessor.cpp b/vst/SfizzVstProcessor.cpp index 441fd9df..6f729a27 100644 --- a/vst/SfizzVstProcessor.cpp +++ b/vst/SfizzVstProcessor.cpp @@ -22,8 +22,10 @@ static const char defaultSfzText[] = "sample=*sine" "\n" "ampeg_attack=0.02 ampeg_release=0.1" "\n"; +enum { kMidiEventMaximumSize = 4 }; + SfizzVstProcessor::SfizzVstProcessor() - : _fifoToWorker(64 * 1024) + : _fifoToWorker(64 * 1024), _fifoMidiFromUi(64 * 1024) { setControllerClass(SfizzVstController::cid); } @@ -181,6 +183,8 @@ tresult PLUGIN_API SfizzVstProcessor::process(Vst::ProcessData& data) else synth.disableFreeWheeling(); + processMidiFromUi(); + if (Vst::IParameterChanges* pc = data.inputParameterChanges) processControllerChanges(*pc); @@ -373,6 +377,40 @@ void SfizzVstProcessor::processEvents(Vst::IEventList& events) } } +void SfizzVstProcessor::processMidiFromUi() +{ + sfz::Sfizz& synth = *_synth; + + for (uint32 size = 0; _fifoMidiFromUi.peek(size) && + _fifoMidiFromUi.size_used() >= sizeof(size) + size; ) { + _fifoMidiFromUi.discard(sizeof(size)); + + if (size > kMidiEventMaximumSize) { + _fifoMidiFromUi.discard(size); + continue; + } + + uint8_t data[kMidiEventMaximumSize] = {}; + _fifoMidiFromUi.get(data, size); + + // interpret the MIDI message + switch (data[0] & 0xf0) { + case 0x80: + synth.noteOff(0, data[1] & 0x7f, data[2] & 0x7f); + break; + case 0x90: + synth.noteOn(0, data[1] & 0x7f, data[2] & 0x7f); + break; + case 0xb0: + synth.cc(0, data[1] & 0x7f, data[2] & 0x7f); + break; + case 0xe0: + synth.pitchWheel(0, (data[2] << 7) + data[1] - 8192); + break; + } + } +} + int SfizzVstProcessor::convertVelocityFromFloat(float x) { return std::min(127, std::max(0, (int)(x * 127.0f))); @@ -425,6 +463,17 @@ tresult PLUGIN_API SfizzVstProcessor::notify(Vst::IMessage* message) reply->getAttributes()->setBinary("File", _state.scalaFile.data(), _state.scalaFile.size()); sendMessage(reply); } + else if (!std::strcmp(id, "MidiMessage")) { + const void* data = nullptr; + uint32 size = 0; + result = attr->getBinary("Data", data, size); + if (size < kMidiEventMaximumSize) { + if (_fifoMidiFromUi.size_free() >= sizeof(size) + size) { + _fifoMidiFromUi.put(size); + _fifoMidiFromUi.put(reinterpret_cast(data), size); + } + } + } return result; } diff --git a/vst/SfizzVstProcessor.h b/vst/SfizzVstProcessor.h index 1eb68cea..7f388621 100644 --- a/vst/SfizzVstProcessor.h +++ b/vst/SfizzVstProcessor.h @@ -35,6 +35,7 @@ public: void processParameterChanges(Vst::IParameterChanges& pc); void processControllerChanges(Vst::IParameterChanges& pc); void processEvents(Vst::IEventList& events); + void processMidiFromUi(); static int convertVelocityFromFloat(float x); tresult PLUGIN_API notify(Vst::IMessage* message) override; @@ -58,6 +59,7 @@ private: volatile bool _workRunning = false; Ring_Buffer _fifoToWorker; RTSemaphore _semaToWorker; + Ring_Buffer _fifoMidiFromUi; std::mutex _processMutex; // file modification periodic checker