Linking the bypass states is a little bit more complicated. My solution:
In my bypass control I define:
void BypassSchalter::OnMouseDown(float x, float y, const IMouseMod& mod)
{
double new_state = (GetValue() < 0.5 ? 1.0 : 0.0);
SetValue(new_state);
SetDirty(true);
#ifdef VST3_API
IPlugVST3* p = dynamic_cast<IPlugVST3*>(GetDelegate());
if (p != nullptr) {
p->BeginInformHostOfParamChange(kBypassParam);
p->InformHostOfParamChange(kBypassParam, new_state);
p->EndInformHostOfParamChange(kBypassParam);
while (p->GetBypassed() != new_state) {
// Sometimes the param change doesn't work (timimg?). Wait and try it again...
std::this_thread::sleep_for(std::chrono::milliseconds(5));
p->BeginInformHostOfParamChange(kBypassParam);
p->InformHostOfParamChange(kBypassParam, new_state);
p->EndInformHostOfParamChange(kBypassParam);
}
}
#endif
}
I the DSP thread I define an ISender, which sends the current host bypass state to my bypass control:
void Oberton::ProcessBlock(sample** inputs, sample** outputs, int nFrames)
{
bool bypass = (GetParam(kInternalBypass)->Value() > 0.5);
#ifdef VST3_API
if (bypass != GetBypassed()) {
bypass = GetBypassed();
mBypassData.vals[0] = (bypass ? 1.0 : 0.0);
mBypassSender.PushData(mBypassData);
}
#endif
// DPS code, which respects the bypass variable
}
A little complicated, but I see no other way, Has someone other ideas?
Btw. here the patch for iPlug2, which I mentioned in the previous post:
diff --git a/IPlug/IPlugProcessor.h b/IPlug/IPlugProcessor.h
index afc0e10a4..7779261e7 100644
--- a/IPlug/IPlugProcessor.h
+++ b/IPlug/IPlugProcessor.h
@@ -112,8 +112,11 @@ public:
/** @return \c true if the plugin is currently bypassed*/
bool GetBypassed() const { return mBypassed; }
+ /** @return \c true if ProcessBlock should be called even if the plugin is currently bypassed*/
+ bool GetProcessIfBypassed() const { return mProcessIfBypassed; }
+
/** @return \c true if the plugin is currently rendering off-line */
- bool GetRenderingOffline() const { return mRenderingOffline; };
+ bool GetRenderingOffline() const { return mRenderingOffline; }
#pragma mark -
/** @return The number of samples elapsed since start of project timeline. */
@@ -264,6 +267,7 @@ protected:
void SetSampleRate(double sampleRate) { mSampleRate = sampleRate; }
void SetBlockSize(int blockSize);
void SetBypassed(bool bypassed) { mBypassed = bypassed; }
+ void SetProcessIfBypassed(bool process) { mProcessIfBypassed = process; }
void SetTimeInfo(const ITimeInfo& timeInfo) { mTimeInfo = timeInfo; }
void SetRenderingOffline(bool renderingOffline) { mRenderingOffline = renderingOffline; }
const WDL_String& GetChannelLabel(ERoute direction, int idx) { return mChannelData[direction].Get(idx)->mLabel; }
@@ -287,6 +291,8 @@ private:
int mTailSize = 0;
/** \c true if the plug-in is bypassed */
bool mBypassed = false;
+ /** \c true if the plug-in should call ProcessBlock even if bypassed */
+ bool mProcessIfBypassed = false;
/** \c true if the plug-in is rendering off-line*/
bool mRenderingOffline = false;
/** A list of IOConfig structures populated by ParseChannelIOStr in the IPlugProcessor constructor */
diff --git a/IPlug/VST3/IPlugVST3_ProcessorBase.cpp b/IPlug/VST3/IPlugVST3_ProcessorBase.cpp
index 56267d38a..dbd3f99ec 100644
--- a/IPlug/VST3/IPlugVST3_ProcessorBase.cpp
+++ b/IPlug/VST3/IPlugVST3_ProcessorBase.cpp
@@ -398,7 +398,7 @@ void IPlugVST3ProcessorBase::ProcessAudio(ProcessData& data, ProcessSetup& setup
chanOffset += busChannels;
}
- if (GetBypassed())
+ if (GetBypassed() && !GetProcessIfBypassed())
{
if (sampleSize == kSample32)
PassThroughBuffers(0.f, data.numSamples); // single precision