| @@ -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<int32_t>(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<uint32_t>(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<uint8_t>(vstMidiEvent->midiData[j]); | |||
| fMidiEvents[j].port = 0; | |||
| fMidiEvents[j].time = static_cast<uint32_t>(vstMidiEvent->deltaFrames); | |||
| fMidiEvents[j].size = 3; | |||
| fMidiEventCount += 1; | |||
| for (uint32_t k=0; k<3; ++k) | |||
| fMidiEvents[fMidiEventCount].data[k] = static_cast<uint8_t>(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<float**>(inputs), outputs, static_cast<uint32_t>(sampleFrames), fMidiEvents, fMidiEventCount); | |||
| // TODO: MIDI Out | |||
| const uint32_t newMidiEventCount(fMidiEventCount); | |||
| fMidiEventCount = 0; | |||
| carla_zeroStruct<NativeMidiEvent>(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.size; ++j) | |||
| vstMidiEvent.midiData[j] = static_cast<char>(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<kMaxMidiEvents*2; ++i) | |||
| data[i] = (VstEvent*)&mdata[i]; | |||
| carla_zeroStruct<VstMidiEvent>(mdata, kMaxMidiEvents*2); | |||
| } | |||
| CARLA_DECLARE_NON_COPY_STRUCT(FixedVstEvents); | |||
| } fMidiOutEvents; | |||
| char* fStateChunk; | |||
| SharedResourcePointer<ScopedJuceInitialiser_GUI> sJuceInitialiser; | |||