Audio Suite multichannel crash


#1

We have an upcoming plugin that uses multiple output buses. The ideal layout is a stereo input, a stereo sidechain input, a stereo output, and then a low/mid/high stereo output. In total 2 buses in, 4 buses out. In a situation where a host doesn’t allow for multiple outputs/inputs we revert to stereo (or mono) in, stereo (or mono) out.

This seems to all be working correctly except in Pro Tool when a user uses the plugin in Audio Suite. We then get a hard crash in the juce AAX wrapper where it’s trying to clear output busses 2/3/4. I assume there’s an issue where Audio Suite instances of a plugin can’t use multiple output buses. We’d be fine not allowing this in Audio Suite but I can’t figure out a way to disable it without also disabling it for normal PT situations.

Additionally, what is the relationship between specifying desired bus configurations in the plugin processor constructor vs. saying explicitly what is/isn’t allowable in the overridden isBusesLayoutSupported function? We currently both suggest the optimal layout AND use the isBusesLayoutSupported function, however I’m seeing that some hosts don’t seem to use isBusesLayoutSupported at all (juce plugin host for instance).

What is the preferred method to specify something like this (i.e. use stereo+sidechain in, stereo + low + mid + high out preferably, however if that’s not available then use stereo+sidechain in, stereo out OR if that’s not available just use stereo in, stereo out)? And of course the same would go for mono, just with less inputs/outputs.

The relevant crash is here where the AAX wrapper is trying to clear bus 1 and gets a bad access:

Here is a copy of what our constructor suggested bus layout looks like:

UAPluginProcessor(BusesProperties().withInput (“Input”, AudioChannelSet::stereo())
.withOutput (“Output”, AudioChannelSet::stereo())
.withOutput (“Low”, AudioChannelSet::stereo())
.withOutput (“Mid”, AudioChannelSet::stereo())
.withOutput (“High”, AudioChannelSet::stereo())
.withInput (“Sidechain”, AudioChannelSet::stereo()))

Here is a copy of what our isBusesLayoutSupported function looks like:

int input = layouts.getMainInputChannelSet().size();
int sidechain = layouts.getChannelSet(true, 1).size();
int output = layouts.getChannelSet(false, 0).size();
int outputBusses = layouts.outputBuses.size();
//AudioChannelSet::stereo()

if (layouts.getMainInputChannelSet()  == AudioChannelSet::disabled()
	|| layouts.getMainOutputChannelSet() == AudioChannelSet::disabled())
{
	return false;
}

if(layouts.inputBuses.size() > 2 || (outputBusses != 1 && outputBusses != 4))
{
	return false;
}

if(outputBusses != 1)
{
	return false;
}

if(input > 2 || sidechain > 2 || output > 2)
{
	return false;
}

if(input == 2 && output == 1)
{
	//don't allow stereo->mono track in PT
	return false;
}

if(outputBusses == 4)
{
	//first make sure they're all the same size
	int matchSize = layouts.getChannelSet(false, 1).size();
	if(layouts.getChannelSet(false, 2).size() != matchSize)
	{
		return false;
	}
	if(layouts.getChannelSet(false, 3).size() != matchSize)
	{
		return false;
	}
	
	for(int i = 1;i<4;i++)
	{
		//ok we allow mono main and stereo aux for Logic but not stereo main and mono aux
		int auxSize = layouts.getChannelSet(false, i).size();
		if(output == 1)
		{
			if(auxSize != 1 && auxSize != 2)
			{
				return false;
			}
		}
		else
		{
			if(auxSize != 2)
			{
				return false;
			}
		}
	}
}

return true;

#2

Just keep in mind PT side-chain is always mono.

It would be useful to see your channel layout code.

You can easily disable AudioSuite by adding :
‘JucePlugin_AAXDisableAudioSuite’


#3

We just have a blank Channel Configuration in the Jucer in order to do it the programmatic way. Is that what you’re referring to? I was under the impression that if the Jucer configuration is blank then everything is determined by the constructor and isBusesLayoutSupported. It’s also not crashing because of what we’re doing in the processing callback because it still crashes on the memory zero thing in the wrapper if we disable all processing. I’ll try to reproduce it with a blank demo project and post it here. Thanks.


#4

Here’s a blank demo project version which recreates the crash. If you build an AAX version then open it with audio suite and click the preview in the bottom left (or process) then it will crash in the AAX wrapper at this location:

                for (int i = numIns; i < numOuts; ++i)
                    zeromem (channels[i], (size_t) bufferSize * sizeof (float));

This is the repo link:

And here is a signed AAX:

https://drive.google.com/open?id=1VAQR7aDkAgNn5T0d_gh1Ft1WMThDO_Y_


#5

Just bumping this. Is anyone at JUCE able to replicate this with our example project? It’s currently blocking a release for us.


#6

I was able to reproduce the crash, it looks like the output channel pointers are null when the plug-in is running in AudioSuite but I don’t know enough about AAX and AudioSuite plug-ins to be able to say why this is happening or even if this is the expected behaviour.

From looking at the AAX SDK, adding full AudioSuite compatibility to JUCE’s AAX wrapper is a lot of work and not something that’s on our roadmap. However, it would be good for plug-ins to have a way of querying whether they are running in AudioSuite and I think that should be possible. Would that be a suitable workaround for you guys? You could then disable the output buses in that case.


#7

However,
Audiosuite has 2 APIs. The one currently used in JUCE suppose to just wrap around normal aax. Each one has different advantages and disadvantages.


#8

There’s not really any explicit support for AudioSuite in the JUCE AAX wrapper. From looking at this thread from a few years ago it looks like it just sort of happened without us adding anything, hence why it may not work correctly in some situations like the above.

As you’ve done quite a lot of work with AudioSuite do you guys know if there’s a reason why the output channels aren’t being passed to the plug-in? Is this documented anywhere?


#9

That might be the fastest solution on our end. I think we will visit the Sound Radix branch for the future but simply having a flag to know if/if-not it’s AudioSuite would be a nice workaround for the time being. Please let me know what’s the easiest way to pull that off. Thanks.


#10

@ed95 - CHostProcessor is a completely different API.
We also did our best to minimize our changes to juce codebase and again, AudioSuite using CHostProcessor vs AudioSuite using AAX API is a different beast.
I’ve made a patch on my spare personal time that seems to be the right approach (after reading Avid’s docs).
feel free to use it without any restrictions to fix this issue.

@Amusesmile you can try the patch, just to double-check it.

0001-Fix-AAX-as-AudioSuite-not-supporting-additional-buse.patch (1.7 KB)


#11

Thanks, I came to the same conclusions. I’ve pushed this commit to develop which should sort things out.

@Amusesmile You’ll need to modify your isBusesLayoutSupported() to cope with the disabled output buses, there’s also a PluginHostType::isInAAXAudioSuite() method that you can use to query whether you’re running in AudioSuite if you want to have different behaviour for that case.

Let me know if this fixes things for you.


#12

Hey I just wanted to thank everyone who chimed in here. @ed95 I was able to work with what you pushed. It took a while to figure out how it was implemented but since the multiple outputs are still present but set to AudioChannelSet::disabled(). That’s perfect now that I understand how it works so we just check that in isBusesLayoutSupported and the processing callback to prevent doing anything with them if they’re not enabled. Very cool. @ttg many thanks for the info and we’ll plan to switch to your fork in the near future. Cheers.