i am creating a multi input and multi output plugin and have in the introjucer the following {12,12}. When testing the plugin an assertion occurs in the function findAllCompatibleLayoutsForBus in the file juce_PluginBusUtilities.h. In this function the first line says:
const int maxNumChannels = 9;
Is the number of channels limited to 8 ? That would be too bad. My plugin needs just one bus with lots of channels, input and output wise. 32 should be the min. Maximum and 64 would be better.
In earlier Juce version i had at least 32 ins and 32 outs... (64 not tested) ...
I've been working on fixing recently. The fix will have no maximum limit of channels. It will also give you more control on how your AudioProcessor will behave as a VST-2 plug-in. Stay tuned!
when ioChanged is triggered i get this called for setting the inputs/outputs busses... but getChannelSet(true, 0) try to obtain a reference of an item in a juce array with 0 size (i have no inputs in this configuration {0, 2}).
Several times in the guide at the beginning of this posts, the method setPreferredBusArrangement() in the base AudioProcessor class is referred to as the method to call to accept the layout change from our, overridden, version of setPreferredBusArrangement().
Why isn't that "accepting" method named accordingly (perhaps acceptBusArrangementIfPossible()) and made non-virtual and protected in the base AudioProcessor class?
The base class implementation of setPreferredBusArrangement() would then result in a simple call forward to this acceptBusArrangementIfPossible() method (to retain the default behaviour), and all the derived versions of setPreferredBusArrangement() would call this accepting method instead of the base class' setPreferredBusArrangement(), which would make the code a little clearer and less prone to mistakenly calling the derived version instead, IMHO.
Speaking in code:
class AudioProcessor // this is the JUCE AudioProcessor class
{
public:
virtual bool setPreferredBusArrangement (whatever)
{
/* the base class tries to accept whatever change,
to retain its current default behavior and also
in order not to break existing code */
return acceptBusArrangementIfPossible (whatever);
}
protected:
// This is protected so that only this and derived classes can call this.
// Notice this is non-virtual so no mistakes of calling on base/dervied classes.
bool acceptBusArrangementIfPossible (whatever)
{
/* this does whatever the current
AudioProcessor::setPreferredBusArrangement()
does in order to accept changes */
}
};
class DerivedAudioProcessor // this is the AudioProcessor class that implements our plug-ins
{
bool setPreferredBusArrangement (whatever) override
{
if (reason)
return false; // deny change in bus arrangement because of 'reason'
/* below is the case of a change requiring a change on another bus,
thus the outcome is subordinate to the other bus change being accepted
*/
if (whatever == requires_another_change)
return acceptBusArrangementIfPossible (another bus change);
// otherwise, try to accept the change
return acceptBusArrangementIfPossible (whatever);
}
};
Please also note that this change would not break existing code, because any call made explicitly to the base AudioProcessor::setPreferredBusArragement() would retain its current meaning of "accept that", because of its default implementation that forwards the call to this proposed acceptBusArrangementIfPossible()
all the fixes should be in this release apart from things involving the AudioProcessorGraph or hosting multi-bus plug-ins. Also, we haven’t touched the API in this release - but we will rename a few things going forward to avoid confusion. This will also get rid of the macros being using in AudioProcessor.cpp.
In addition, this release offers more control for VST-2 plug-ins if you use the setBusArrangement API. See examples/PluginSamples/GainPlugin for this. For example, if JUCE detects that you are using the setBusArrangement API, then the layout set in the constructor of your plug-in will be the default VST-2 plug-in layout. You can also indirectly specify the maximum number of supported channels in the setPreferredBusArrangement callback. See the example for more details.
I believe I hit the exact same problem (“VST with no input buses”) with 4.2. The crash happens after setLatencySamples() has been called, or more specifically after the ioChanged() function has been called asynchronously.
No individual output buses (i.e. only a main output bus).
No sidechain inputs
So, as soon as there is only a main output bus, I have to add also a sidechain input bus, or else the plugin crashes as soon as anything triggers the asyncUpdate in VST wrapper and ends up in ioChanged().
This is reproducible in the MultiOutSynth example, if you simply set the maxMidiChannel = 1 instead of 16 (in which case it will only get a main output bus). And then call setLatencySamples(1000) from prepareToPlay(). Crash!