diff --git a/plugins/Cardinal/src/HostAudio.cpp b/plugins/Cardinal/src/HostAudio.cpp index 8e12603..4578a7f 100644 --- a/plugins/Cardinal/src/HostAudio.cpp +++ b/plugins/Cardinal/src/HostAudio.cpp @@ -139,7 +139,7 @@ struct HostAudio2 : HostAudio<2> { resetMeters = true; } - void processTerminalOutput(const ProcessArgs&) + void processTerminalOutput(const ProcessArgs&) override { const int blockFrames = pcontext->engine->getBlockFrames(); diff --git a/plugins/Cardinal/src/plugincontext.hpp b/plugins/Cardinal/src/plugincontext.hpp index 2d0eeba..dcba23b 100644 --- a/plugins/Cardinal/src/plugincontext.hpp +++ b/plugins/Cardinal/src/plugincontext.hpp @@ -55,7 +55,7 @@ struct CardinalPluginContext : rack::Context { double sampleRate; float parameters[kModuleParameters]; CardinalVariant variant; - bool playing, reset, bbtValid; + bool bypassed, playing, reset, bbtValid; int32_t bar, beat, beatsPerBar, beatType; uint64_t frame; double barStartTick, beatsPerMinute; diff --git a/src/CardinalPlugin.cpp b/src/CardinalPlugin.cpp index b7fab0f..4bfc747 100644 --- a/src/CardinalPlugin.cpp +++ b/src/CardinalPlugin.cpp @@ -343,6 +343,9 @@ struct Initializer void CardinalPluginContext::writeMidiMessage(const rack::midi::Message& message, const uint8_t channel) { + if (bypassed) + return; + const size_t size = message.bytes.size(); DISTRHO_SAFE_ASSERT_RETURN(size > 0,); DISTRHO_SAFE_ASSERT_RETURN(message.frame >= 0,); @@ -429,6 +432,7 @@ class CardinalPlugin : public CardinalBasePlugin #if DISTRHO_PLUGIN_NUM_INPUTS != 0 /* If host audio ins == outs we can get issues for inplace processing. * So allocate a float array that will serve as safe copy for those cases. + * Also used for bypass, so inputs are fully zero. */ float** fAudioBufferCopy; #endif @@ -439,6 +443,10 @@ class CardinalPlugin : public CardinalBasePlugin String fStateScreenshot; String fWindowSize; + // bypass handling + bool fWasBypassed; + MidiEvent bypassMidiEvents[16]; + #ifndef HEADLESS // real values, not VCV interpreted ones float fWindowParameters[kWindowParameterCount]; @@ -451,7 +459,8 @@ public: #if DISTRHO_PLUGIN_NUM_INPUTS != 0 fAudioBufferCopy(nullptr), #endif - fPreviousFrame(0) + fPreviousFrame(0), + fWasBypassed(false) { #ifndef HEADLESS fWindowParameters[kWindowParameterShowTooltips] = 1.0f; @@ -485,6 +494,16 @@ public: } } DISTRHO_SAFE_EXCEPTION("create unique temporary path"); + // initialize midi events used when entering bypassed state + std::memset(bypassMidiEvents, 0, sizeof(bypassMidiEvents)); + + for (uint8_t i=0; i<16; ++i) + { + bypassMidiEvents[i].size = 3; + bypassMidiEvents[i].data[0] = 0xB0 + i; + bypassMidiEvents[i].data[1] = 0x7B; + } + const float sampleRate = getSampleRate(); rack::settings::sampleRate = sampleRate; @@ -773,7 +792,7 @@ protected: // bypass if (index == kModuleParameters) - return 0.0f; + return context->bypassed ? 1.0f : 0.0f; #ifndef HEADLESS // window related parameters @@ -797,7 +816,10 @@ protected: // bypass if (index == kModuleParameters) + { + context->bypassed = value > 0.5f; return; + } #ifndef HEADLESS // window related parameters @@ -924,6 +946,8 @@ protected: { rack::contextSet(context); + const bool bypassed = context->bypassed; + { const TimePosition& timePos(getTimePosition()); @@ -977,10 +1001,28 @@ protected: for (int i=0; imidiEvents = midiEvents; - context->midiEventCount = midiEventCount; + if (bypassed) + { + if (fWasBypassed != bypassed) + { + context->midiEvents = bypassMidiEvents; + context->midiEventCount = 16; + } + else + { + context->midiEvents = nullptr; + context->midiEventCount = 0; + } + } + else + { + context->midiEvents = midiEvents; + context->midiEventCount = midiEventCount; + } context->engine->stepBlock(frames); + + fWasBypassed = bypassed; } void bufferSizeChanged(const uint32_t newBufferSize) override diff --git a/src/PluginContext.hpp b/src/PluginContext.hpp index da29fa4..e140759 100644 --- a/src/PluginContext.hpp +++ b/src/PluginContext.hpp @@ -52,7 +52,7 @@ struct CardinalPluginContext : rack::Context { double sampleRate; float parameters[kModuleParameters]; CardinalVariant variant; - bool playing, reset, bbtValid; + bool bypassed, playing, reset, bbtValid; int32_t bar, beat, beatsPerBar, beatType; uint64_t frame; double barStartTick, beatsPerMinute; @@ -79,6 +79,7 @@ struct CardinalPluginContext : rack::Context { #else #error cardinal variant not set #endif + bypassed(false), playing(false), reset(false), bbtValid(false),