From 87a2c10faece67a4aac90fea234163eab745f1bd Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 12 Oct 2014 22:08:10 +0100 Subject: [PATCH] vst-plugin: MIDI Out support (TESTING) --- source/plugin/carla-vst.cpp | 71 +++++++++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 10 deletions(-) diff --git a/source/plugin/carla-vst.cpp b/source/plugin/carla-vst.cpp index 446e3690a..79559e529 100644 --- a/source/plugin/carla-vst.cpp +++ b/source/plugin/carla-vst.cpp @@ -52,6 +52,8 @@ using juce::SharedResourcePointer; static uint32_t d_lastBufferSize = 0; static double d_lastSampleRate = 0.0; +static const int32_t kVstMidiEventSize = static_cast(sizeof(VstMidiEvent)); + // ----------------------------------------------------------------------- class NativePlugin @@ -70,6 +72,7 @@ public: fMidiEventCount(0), fTimeInfo(), fVstRect(), + fMidiOutEvents(), fStateChunk(nullptr), sJuceInitialiser(), leakDetector_NativePlugin() @@ -284,14 +287,14 @@ public: if (fMidiEventCount >= kMaxMidiEvents) break; - fMidiEvents[fMidiEventCount].port = 0; - fMidiEvents[fMidiEventCount].time = static_cast(vstMidiEvent->deltaFrames); - fMidiEvents[fMidiEventCount].size = 3; + const uint32_t j(fMidiEventCount++); - for (uint32_t j=0; j < 3; ++j) - fMidiEvents[fMidiEventCount].data[j] = static_cast(vstMidiEvent->midiData[j]); + fMidiEvents[j].port = 0; + fMidiEvents[j].time = static_cast(vstMidiEvent->deltaFrames); + fMidiEvents[j].size = 3; - fMidiEventCount += 1; + for (uint32_t k=0; k<3; ++k) + fMidiEvents[fMidiEventCount].data[k] = static_cast(vstMidiEvent->midiData[k]); } } break; @@ -305,13 +308,10 @@ public: return 1; if (std::strcmp(canDo, "receiveVstTimeInfo") == 0) return 1; -#if 0 - // TODO - MIDI Out if (std::strcmp(canDo, "sendVstEvents") == 0) return 1; if (std::strcmp(canDo, "sendVstMidiEvent") == 0) return 1; -#endif } break; } @@ -373,12 +373,43 @@ public: fTimeInfo.bbt.barStartTick = fTimeInfo.bbt.ticksPerBeat*fTimeInfo.bbt.beatsPerBar*(fTimeInfo.bbt.bar-1); } + const uint32_t oldMidiEventCount(fMidiEventCount); + if (fHandle != nullptr) fDescriptor->process(fHandle, const_cast(inputs), outputs, static_cast(sampleFrames), fMidiEvents, fMidiEventCount); - // TODO: MIDI Out + const uint32_t newMidiEventCount(fMidiEventCount); fMidiEventCount = 0; + carla_zeroStruct(fMidiEvents, kMaxMidiEvents*2); + + CARLA_SAFE_ASSERT_RETURN(newMidiEventCount == oldMidiEventCount,); + + fMidiOutEvents.numEvents = 0; + + // reverse lookup MIDI events + for (uint32_t i = (kMaxMidiEvents*2)-1; i >= newMidiEventCount; --i) + { + if (fMidiEvents[i].data[0] == 0) + break; + + NativeMidiEvent& midiEvent(fMidiEvents[i]); + VstMidiEvent& vstMidiEvent(fMidiOutEvents.mdata[i]); + + vstMidiEvent.type = kVstMidiType; + vstMidiEvent.byteSize = kVstMidiEventSize; + + uint8_t j=0; + for (; j(midiEvent.data[j]); + for (; j<4; ++j) + vstMidiEvent.midiData[j] = 0; + + ++(fMidiOutEvents.numEvents); + } + + if (fMidiOutEvents.numEvents > 0) + fAudioMaster(fEffect, audioMasterProcessEvents, 0, 0, &fMidiOutEvents, 0.0f); } protected: @@ -476,6 +507,26 @@ private: NativeTimeInfo fTimeInfo; ERect fVstRect; + struct FixedVstEvents { + int32_t numEvents; + intptr_t reserved; + VstEvent* data[kMaxMidiEvents*2]; + VstMidiEvent mdata[kMaxMidiEvents*2]; + + FixedVstEvents() + : numEvents(0), + reserved(0), + data(), + mdata() + { + for (uint32_t i=0; i(mdata, kMaxMidiEvents*2); + } + + CARLA_DECLARE_NON_COPY_STRUCT(FixedVstEvents); + } fMidiOutEvents; + char* fStateChunk; SharedResourcePointer sJuceInitialiser;