Implement MIDI sending to VST from UI

This commit is contained in:
Jean Pierre Cimalando 2020-10-14 20:04:59 +02:00
parent 82f579bf0a
commit 1e6cdd841b
4 changed files with 66 additions and 5 deletions

View file

@ -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<Vst::IMessage> 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);
}
///

View file

@ -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);

View file

@ -22,8 +22,10 @@ static const char defaultSfzText[] =
"<region>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<const uint8_t*>(data), size);
}
}
}
return result;
}

View file

@ -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