numOutputChannels is zero!

Hi,
I am writing a vst synth plugin and also testing it as a standalone app.
don’t seem to be able to populate the AudioBuffer because numOutputChannels is zero, also when
running in the vst in Cubase.

here’s my processBlock code:

void WaveFaktoryAudioProcessor::processBlock (juce::AudioBuffer& buffer, juce::MidiBuffer& midiMessages)
{
juce::ScopedNoDenormals noDenormals;
auto numInputChannels = getTotalNumInputChannels();
auto numOutputChannels = getTotalNumOutputChannels();

processMidi(midiMessages);
//synthEngine.nextAudioBlock(numInputChannels, numOutputChannels, buffer);

for (auto i = numInputChannels; i < numOutputChannels; ++i)
    buffer.clear(i, 0, buffer.getNumSamples());

for (int channel = 0; channel < numOutputChannels; ++channel)
{
    auto* channelData = buffer.getWritePointer(channel);

    for (auto sample = 0; sample < buffer.getNumSamples(); ++sample)
    {
        //channelData[sample] = 0.0f; 
        channelData[sample] = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
        //channelData[sample] = std::sin(sample/100);
    }
}

}

In Projucer, I have marked this as a Synth, requiring keyboard focus.
What could be wrong?

  • What does your override (if any) of isBusesLayoutSupported look like?
  • Are you passing a custom BusesProperties to the AudioProcessor base class constructor in the constructor of WaveFaktoryAudioProcessor?

isBusesLayoutSupported is not overridden:

#ifndef JucePlugin_PreferredChannelConfigurations
bool WaveFaktoryAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const
{
#if JucePlugin_IsMidiEffect
juce::ignoreUnused (layouts);
return true;
#else
// This is the place where you check if the layout is supported.
// In this template code we only support mono or stereo.
// Some plugin hosts, such as certain GarageBand versions, will only
// load plugins that support stereo bus layouts.
if (layouts.getMainOutputChannelSet() != juce::AudioChannelSet::mono()
&& layouts.getMainOutputChannelSet() != juce::AudioChannelSet::stereo())
return false;

// This checks if the input layout matches the output layout

#if ! JucePlugin_IsSynth
if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet())
return false;
#endif

return true;

#endif
}
#endif

And no custom Busesproperties (where JucePlugin_IsMidiEffect = 1):

#ifndef JucePlugin_PreferredChannelConfigurations
: AudioProcessor (BusesProperties()
#if ! JucePlugin_IsMidiEffect
#if ! JucePlugin_IsSynth
.withInput (“Input”, juce::AudioChannelSet::stereo(), true)
#endif
.withOutput (“Output”, juce::AudioChannelSet::stereo(), true)
#endif
)
#endif

If you’ve enabled JucePlugin_IsMidiEffect then your BusesProperties will have no inputs or outputs. I’d recommend removing the #if lines completely, and directly specifying the input and output layout that you want.

Ok, but then this piece of code in juce_AudioSampleBuffer.h gives me an error, the value of numChannels is 0:

void clear (int channel, int startSample, int numSamples) noexcept
{
    jassert (isPositiveAndBelow (channel, numChannels));
    jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);

    if (! isClear)
        FloatVectorOperations::clear (channels[channel] + startSample, numSamples);
} 

I have removed the #if statements, ending up with:

WaveFaktoryAudioProcessor::WaveFaktoryAudioProcessor()
: AudioProcessor (BusesProperties()
.withInput (“Input”, juce::AudioChannelSet::stereo(), true)
.withOutput (“Output”, juce::AudioChannelSet::stereo(), true))
{
}

and with

bool WaveFaktoryAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const
{
if (layouts.getMainOutputChannelSet() != juce::AudioChannelSet::mono() &&
layouts.getMainOutputChannelSet() != juce::AudioChannelSet::stereo())
{
return false;
}
else
{
return true;
}
}

I decided to start from scratch with just the “plugin is a Synth” checked.
Think that I just checked too many things in Projucer :blush:
This seems to work OK

As a side note, maybe it’s a good time for the juce team to remove that macro mess and if needed replace it with some simple code for those who really need it instead of cluttering all other projects.

I imagine a function that you call from isBusesLayoutSupported, e.g.:

bool allowedBuses (juce::Array<BusesLayout> layouts);

But preferred for the user would be to just keep implementing isBusesSupported properly.

2 Likes