[VST3] Sidechain input is declared incorrectly and not forwarded to the DSP
Summary
The current VST3 wrapper does not provide functional sidechain support.
Although YUP can declare multiple audio input buses, secondary input buses are currently:
- declared as regular main input buses instead of VST3 auxiliary buses;
- not forwarded to the audio processor when there is no matching output bus;
- not represented separately in
AudioProcessContext.
As a result, a DAW may not expose the secondary input as a sidechain, and even when the host sends sidechain audio, the DSP cannot access it.
Severity
P0 / Blocking
This prevents the implementation of standard sidechain-based processors such as compressors, gates, dynamic equalizers, envelope followers, and external-key detectors.
Current behavior
Secondary inputs are declared as main buses
The VST3 wrapper currently registers input buses using:
addAudioInput (
bus.getName(),
speakerArrForChannels (bus.getNumChannels()));
Because no bus type is specified, the Steinberg API uses Vst::kMain.
This means that all input buses are exposed as main inputs instead of declaring secondary inputs as Vst::kAux.
Sidechain audio is discarded during processing
The processing code copies input buses to output buses using matching bus indices:
for (int busIdx = 0;
busIdx < std::min (data.numInputs, data.numOutputs);
++busIdx)
{
// Copy input bus to matching output bus.
}
For a typical sidechain plugin layout:
Input 0 Main stereo input
Input 1 Stereo sidechain input
Output 0 Main stereo output
std::min(data.numInputs, data.numOutputs) evaluates to 1.
Only Input 0 is copied. Input 1, containing the sidechain signal, is never read.
The DSP context exposes only one in-place audio buffer
AudioProcessContext currently exposes a single audio buffer:
AudioBuffer<FloatType>& audio;
It does not provide access to:
- individual input buses;
- individual output buses;
- the main input;
- auxiliary inputs;
- sidechain activation state.
Even if the wrapper preserved the sidechain samples, the processor API currently has no way to consume them.
Expected behavior
A plugin should be able to declare the following VST3 layout:
Input 0 kMain Stereo Active by default
Input 1 kAux Stereo Inactive by default
Output 0 kMain Stereo Active by default
During processing, the DSP should receive separate views for:
- the main input;
- the sidechain input;
- the main output.
The sidechain buffer must remain accessible even though it has no corresponding output bus.
Proposed solution
1. Add a role to AudioBus
Introduce an explicit bus role:
class AudioBus
{
public:
enum class Role
{
Main,
Auxiliary
};
AudioBus (
Type type,
Direction direction,
String name,
int numChannels,
Role role = Role::Main,
bool defaultActive = true);
Role getRole() const noexcept;
bool isDefaultActive() const noexcept;
};
The generic Auxiliary role can be used for sidechains, reference inputs, or other non-main audio buses.
2. Map auxiliary buses to Vst::kAux
The VST3 wrapper should register buses using their explicit role:
const auto vstBusType =
bus.getRole() == AudioBus::Role::Auxiliary
? Steinberg::Vst::kAux
: Steinberg::Vst::kMain;
const auto flags =
bus.isDefaultActive()
? Steinberg::Vst::BusInfo::kDefaultActive
: 0;
addAudioInput (
bus.getName(),
speakerArrForChannels (bus.getNumChannels()),
vstBusType,
flags);
Main buses must be registered before auxiliary buses.
3. Replace the single-buffer processing model with bus-aware views
AudioProcessContext should expose separate input and output buses:
template <typename SampleType>
struct AudioProcessContext
{
Span<AudioBusBufferView<const SampleType>> inputs;
Span<AudioBusBufferView<SampleType>> outputs;
int numSamples = 0;
auto getMainInput() const;
auto getMainOutput() const;
auto getAuxiliaryInput (int index) const;
};
A sidechain compressor could then use:
const auto mainInput = context.getMainInput();
const auto sidechain = context.getAuxiliaryInput (0);
const auto mainOutput = context.getMainOutput();
compressor.process (
mainInput,
sidechain,
mainOutput,
context.numSamples);
4. Handle inactive or unavailable buses safely
The wrapper must support:
- inactive sidechain buses;
- null channel pointers;
- missing buffers;
- mono and stereo auxiliary inputs;
- VST3 silence flags;
- runtime bus activation and deactivation.
An inactive sidechain should provide deterministic silence to the DSP and must never cause a crash.
Reproduction layout
Create a processor with:
Main input: Stereo
Sidechain input: Stereo
Main output: Stereo
Load it in a VST3 host and route another track to the sidechain input.
Actual result
- The secondary input may not appear as a standard sidechain.
- The sidechain signal is not available to the processor.
- Only the main input reaches the DSP.
Expected result
- The host exposes the auxiliary input as a sidechain.
- Sidechain samples are available separately from the main input.
- The processor can use the sidechain signal to control gain reduction.
Acceptance criteria
Regression tests
Add an automated test using:
Main input: constant signal
Sidechain: impulse or sine wave
Expected: gain reduction occurs only when the sidechain signal is present
The test should also verify that disabling the auxiliary bus restores the unkeyed processing behavior without reallocating or recreating the processor.
Additional note
Changing only the VST3 bus type from kMain to kAux is not sufficient.
That change may make the sidechain input visible in the host, but the audio data will still be discarded before reaching the processor. The fix must cover both VST3 bus declaration and the internal multibus processing architecture.
[VST3] Sidechain input is declared incorrectly and not forwarded to the DSP
Summary
The current VST3 wrapper does not provide functional sidechain support.
Although YUP can declare multiple audio input buses, secondary input buses are currently:
AudioProcessContext.As a result, a DAW may not expose the secondary input as a sidechain, and even when the host sends sidechain audio, the DSP cannot access it.
Severity
P0 / Blocking
This prevents the implementation of standard sidechain-based processors such as compressors, gates, dynamic equalizers, envelope followers, and external-key detectors.
Current behavior
Secondary inputs are declared as main buses
The VST3 wrapper currently registers input buses using:
addAudioInput ( bus.getName(), speakerArrForChannels (bus.getNumChannels()));Because no bus type is specified, the Steinberg API uses
Vst::kMain.This means that all input buses are exposed as main inputs instead of declaring secondary inputs as
Vst::kAux.Sidechain audio is discarded during processing
The processing code copies input buses to output buses using matching bus indices:
For a typical sidechain plugin layout:
std::min(data.numInputs, data.numOutputs)evaluates to1.Only
Input 0is copied.Input 1, containing the sidechain signal, is never read.The DSP context exposes only one in-place audio buffer
AudioProcessContextcurrently exposes a single audio buffer:It does not provide access to:
Even if the wrapper preserved the sidechain samples, the processor API currently has no way to consume them.
Expected behavior
A plugin should be able to declare the following VST3 layout:
During processing, the DSP should receive separate views for:
The sidechain buffer must remain accessible even though it has no corresponding output bus.
Proposed solution
1. Add a role to
AudioBusIntroduce an explicit bus role:
The generic
Auxiliaryrole can be used for sidechains, reference inputs, or other non-main audio buses.2. Map auxiliary buses to
Vst::kAuxThe VST3 wrapper should register buses using their explicit role:
Main buses must be registered before auxiliary buses.
3. Replace the single-buffer processing model with bus-aware views
AudioProcessContextshould expose separate input and output buses:A sidechain compressor could then use:
4. Handle inactive or unavailable buses safely
The wrapper must support:
An inactive sidechain should provide deterministic silence to the DSP and must never cause a crash.
Reproduction layout
Create a processor with:
Load it in a VST3 host and route another track to the sidechain input.
Actual result
Expected result
Acceptance criteria
Vst::kAux.Regression tests
Add an automated test using:
The test should also verify that disabling the auxiliary bus restores the unkeyed processing behavior without reallocating or recreating the processor.
Additional note
Changing only the VST3 bus type from
kMaintokAuxis not sufficient.That change may make the sidechain input visible in the host, but the audio data will still be discarded before reaching the processor. The fix must cover both VST3 bus declaration and the internal multibus processing architecture.