mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Fixed a bug where the AU/AUv3 wrapper would create a spurious input bus when no inputs where specified in the Projucer's legacy channel configuration field
This commit is contained in:
parent
a3ef455696
commit
b86e1331ac
3 changed files with 105 additions and 26 deletions
|
|
@ -117,7 +117,9 @@ class JuceAU : public AudioProcessorHolder,
|
|||
public:
|
||||
JuceAU (AudioUnit component)
|
||||
: AudioProcessorHolder(activePlugins.size() + activeUIs.size() == 0),
|
||||
MusicDeviceBase (component, (UInt32) juceFilter->getBusCount (true), (UInt32) juceFilter->getBusCount (false)),
|
||||
MusicDeviceBase (component,
|
||||
(UInt32) AudioUnitHelpers::getBusCount (juceFilter, true),
|
||||
(UInt32) AudioUnitHelpers::getBusCount (juceFilter, false)),
|
||||
isBypassed (false),
|
||||
mapper (*juceFilter)
|
||||
{
|
||||
|
|
@ -189,7 +191,7 @@ public:
|
|||
return err;
|
||||
|
||||
mapper.alloc();
|
||||
pulledSucceeded.calloc (static_cast<size_t> (juceFilter->getBusCount (true)));
|
||||
pulledSucceeded.calloc (static_cast<size_t> (AudioUnitHelpers::getBusCount (juceFilter, true)));
|
||||
|
||||
prepareToPlay();
|
||||
|
||||
|
|
@ -263,6 +265,11 @@ public:
|
|||
//==============================================================================
|
||||
bool BusCountWritable (AudioUnitScope scope) override
|
||||
{
|
||||
#ifdef JucePlugin_PreferredChannelConfigurations
|
||||
ignoreUnused (scope);
|
||||
|
||||
return false;
|
||||
#else
|
||||
bool isInput;
|
||||
|
||||
if (scopeToDirection (scope, isInput) != noErr)
|
||||
|
|
@ -274,8 +281,9 @@ public:
|
|||
if (isInput) return false;
|
||||
#endif
|
||||
|
||||
const int busCount = juceFilter->getBusCount (isInput);
|
||||
const int busCount = AudioUnitHelpers::getBusCount (juceFilter, isInput);
|
||||
return (juceFilter->canAddBus (isInput) || (busCount > 0 && juceFilter->canRemoveBus (isInput)));
|
||||
#endif
|
||||
}
|
||||
|
||||
OSStatus SetBusCount (AudioUnitScope scope, UInt32 count) override
|
||||
|
|
@ -286,9 +294,12 @@ public:
|
|||
if ((err = scopeToDirection (scope, isInput)) != noErr)
|
||||
return err;
|
||||
|
||||
if (count != (UInt32) juceFilter->getBusCount (isInput))
|
||||
if (count != (UInt32) AudioUnitHelpers::getBusCount (juceFilter, isInput))
|
||||
{
|
||||
const int busCount = juceFilter->getBusCount (isInput);
|
||||
#ifdef JucePlugin_PreferredChannelConfigurations
|
||||
return kAudioUnitErr_PropertyNotWritable;
|
||||
#else
|
||||
const int busCount = AudioUnitHelpers::getBusCount (juceFilter, isInput);
|
||||
|
||||
if ((! juceFilter->canAddBus (isInput)) && ((busCount == 0) || (! juceFilter->canRemoveBus (isInput))))
|
||||
return kAudioUnitErr_PropertyNotWritable;
|
||||
|
|
@ -328,7 +339,7 @@ public:
|
|||
if (err != noErr)
|
||||
{
|
||||
// restore bus state
|
||||
const int newBusCount = juceFilter->getBusCount (isInput);
|
||||
const int newBusCount = AudioUnitHelpers::getBusCount (juceFilter, isInput);
|
||||
for (int i = newBusCount; i != busCount; i += (busCount > newBusCount ? 1 : -1))
|
||||
{
|
||||
if (busCount > newBusCount)
|
||||
|
|
@ -346,6 +357,7 @@ public:
|
|||
|
||||
if (err != noErr)
|
||||
return err;
|
||||
#endif
|
||||
}
|
||||
|
||||
return noErr;
|
||||
|
|
@ -862,7 +874,7 @@ public:
|
|||
ComponentResult Version() override { return JucePlugin_VersionCode; }
|
||||
bool SupportsTail() override { return true; }
|
||||
Float64 GetTailTime() override { return juceFilter->getTailLengthSeconds(); }
|
||||
double getSampleRate() { return juceFilter->getBusCount (false) > 0 ? GetOutput(0)->GetStreamFormat().mSampleRate : 44100.0; }
|
||||
double getSampleRate() { return AudioUnitHelpers::getBusCount (juceFilter, false) > 0 ? GetOutput(0)->GetStreamFormat().mSampleRate : 44100.0; }
|
||||
|
||||
Float64 GetLatency() override
|
||||
{
|
||||
|
|
@ -1652,7 +1664,7 @@ private:
|
|||
busIdx = static_cast<int> (element);
|
||||
|
||||
if ((err = scopeToDirection (scope, isInput)) != noErr) return err;
|
||||
if (isPositiveAndBelow (busIdx, juceFilter->getBusCount (isInput))) return noErr;
|
||||
if (isPositiveAndBelow (busIdx, AudioUnitHelpers::getBusCount (juceFilter, isInput))) return noErr;
|
||||
|
||||
return kAudioUnitErr_InvalidElement;
|
||||
}
|
||||
|
|
@ -1736,8 +1748,8 @@ private:
|
|||
OSStatus syncAudioUnitWithProcessor()
|
||||
{
|
||||
OSStatus err = noErr;
|
||||
const int enabledInputs = juceFilter->getBusCount (true);
|
||||
const int enabledOutputs = juceFilter->getBusCount (false);
|
||||
const int enabledInputs = AudioUnitHelpers::getBusCount (juceFilter, true);
|
||||
const int enabledOutputs = AudioUnitHelpers::getBusCount (juceFilter, false);
|
||||
|
||||
if ((err = MusicDeviceBase::SetBusCount (kAudioUnitScope_Input, static_cast<UInt32> (enabledInputs))) != noErr)
|
||||
return err;
|
||||
|
|
@ -1758,8 +1770,8 @@ private:
|
|||
|
||||
OSStatus syncProcessorWithAudioUnit()
|
||||
{
|
||||
const int numInputBuses = juceFilter->getBusCount (true);
|
||||
const int numOutputBuses = juceFilter->getBusCount (false);
|
||||
const int numInputBuses = AudioUnitHelpers::getBusCount (juceFilter, true);
|
||||
const int numOutputBuses = AudioUnitHelpers::getBusCount (juceFilter, false);
|
||||
|
||||
const int numInputElements = static_cast<int> (GetScope(kAudioUnitScope_Input). GetNumberOfElements());
|
||||
const int numOutputElements = static_cast<int> (GetScope(kAudioUnitScope_Output).GetNumberOfElements());
|
||||
|
|
@ -1794,7 +1806,7 @@ private:
|
|||
return kAudioUnitErr_FormatNotSupported;
|
||||
#endif
|
||||
|
||||
if (! juceFilter->setBusesLayout (requestedLayouts))
|
||||
if (! AudioUnitHelpers::setBusesLayout (juceFilter, requestedLayouts))
|
||||
return kAudioUnitErr_FormatNotSupported;
|
||||
|
||||
// update total channel count
|
||||
|
|
@ -1898,7 +1910,7 @@ private:
|
|||
Array<Array<AudioChannelLayoutTag> >& layouts = isInput ? supportedInputLayouts : supportedOutputLayouts;
|
||||
layouts.clear();
|
||||
|
||||
const int numBuses = juceFilter->getBusCount (isInput);
|
||||
const int numBuses = AudioUnitHelpers::getBusCount (juceFilter, isInput);
|
||||
for (int busNr = 0; busNr < numBuses; ++busNr)
|
||||
{
|
||||
Array<AudioChannelLayoutTag> busLayouts;
|
||||
|
|
@ -1912,8 +1924,8 @@ private:
|
|||
{
|
||||
currentInputLayout.clear(); currentOutputLayout.clear();
|
||||
|
||||
currentInputLayout. resize (juceFilter->getBusCount (true));
|
||||
currentOutputLayout.resize (juceFilter->getBusCount (false));
|
||||
currentInputLayout. resize (AudioUnitHelpers::getBusCount (juceFilter, true));
|
||||
currentOutputLayout.resize (AudioUnitHelpers::getBusCount (juceFilter, false));
|
||||
|
||||
addSupportedLayoutTagsForDirection (true);
|
||||
addSupportedLayoutTagsForDirection (false);
|
||||
|
|
|
|||
|
|
@ -542,7 +542,7 @@ public:
|
|||
for (int dir = 0; dir < 2; ++dir)
|
||||
{
|
||||
const bool isInput = (dir == 0);
|
||||
const int n = processor.getBusCount (isInput);
|
||||
const int n = AudioUnitHelpers::getBusCount (&processor, isInput);
|
||||
Array<AudioChannelSet>& channelSets = (isInput ? layouts.inputBuses : layouts.outputBuses);
|
||||
|
||||
AUAudioUnitBusArray* auBuses = (isInput ? [getAudioUnit() inputBusses] : [getAudioUnit() outputBusses]);
|
||||
|
|
@ -578,7 +578,7 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
if (! processor.setBusesLayout (layouts))
|
||||
if (! AudioUnitHelpers::setBusesLayout (&getAudioProcessor(), layouts))
|
||||
{
|
||||
if (outError != nullptr)
|
||||
*outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:kAudioUnitErr_FormatNotSupported userInfo:nullptr];
|
||||
|
|
@ -596,7 +596,7 @@ public:
|
|||
|
||||
audioBuffer.prepare (totalInChannels, totalOutChannels, static_cast<int> (maxFrames));
|
||||
|
||||
double sampleRate = (jmax (processor.getBusCount (true), processor.getBusCount (false)) > 0 ?
|
||||
double sampleRate = (jmax (AudioUnitHelpers::getBusCount (&processor, true), AudioUnitHelpers::getBusCount (&processor, false)) > 0 ?
|
||||
[[[([inputBusses count] > 0 ? inputBusses : outputBusses) objectAtIndexedSubscript: 0] format] sampleRate] : 44100.0);
|
||||
|
||||
processor.setRateAndBufferSizeDetails (sampleRate, static_cast<int> (maxFrames));
|
||||
|
|
@ -869,7 +869,7 @@ private:
|
|||
{
|
||||
ScopedPointer<NSMutableArray<AUAudioUnitBus*> > array = [[NSMutableArray<AUAudioUnitBus*> alloc] init];
|
||||
AudioProcessor& processor = getAudioProcessor();
|
||||
const int n = processor.getBusCount (isInput);
|
||||
const int n = AudioUnitHelpers::getBusCount (&processor, isInput);
|
||||
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
|
|
@ -996,7 +996,7 @@ private:
|
|||
OwnedArray<BusBuffer>& busBuffers = isInput ? inBusBuffers : outBusBuffers;
|
||||
busBuffers.clear();
|
||||
|
||||
const int n = getAudioProcessor().getBusCount (isInput);
|
||||
const int n = AudioUnitHelpers::getBusCount (&getAudioProcessor(), isInput);
|
||||
const AUAudioFrameCount maxFrames = [getAudioUnit() maximumFramesToRender];
|
||||
|
||||
for (int busIdx = 0; busIdx < n; ++busIdx)
|
||||
|
|
|
|||
|
|
@ -324,8 +324,8 @@ struct AudioUnitHelpers
|
|||
|
||||
void alloc()
|
||||
{
|
||||
const int numInputBuses = processor.getBusCount (true);
|
||||
const int numOutputBuses = processor.getBusCount (false);
|
||||
const int numInputBuses = AudioUnitHelpers::getBusCount (&processor, true);
|
||||
const int numOutputBuses = AudioUnitHelpers::getBusCount (&processor, false);
|
||||
|
||||
initializeChannelMapArray (true, numInputBuses);
|
||||
initializeChannelMapArray (false, numOutputBuses);
|
||||
|
|
@ -611,10 +611,10 @@ struct AudioUnitHelpers
|
|||
{
|
||||
Array<AUChannelInfo> channelInfo;
|
||||
|
||||
const bool hasMainInputBus = (processor.getBusCount (true) > 0);
|
||||
const bool hasMainOutputBus = (processor.getBusCount (false) > 0);
|
||||
const bool hasMainInputBus = (AudioUnitHelpers::getBusCount (&processor, true) > 0);
|
||||
const bool hasMainOutputBus = (AudioUnitHelpers::getBusCount (&processor, false) > 0);
|
||||
|
||||
if ((! hasMainInputBus) && (! hasMainOutputBus))
|
||||
if ((! hasMainInputBus) && (! hasMainOutputBus))
|
||||
{
|
||||
// midi effect plug-in: no audio
|
||||
AUChannelInfo info;
|
||||
|
|
@ -743,6 +743,73 @@ struct AudioUnitHelpers
|
|||
|
||||
return channelInfo;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static int getBusCount (const AudioProcessor* juceFilter, bool isInput)
|
||||
{
|
||||
int busCount = juceFilter->getBusCount (isInput);
|
||||
|
||||
#ifdef JucePlugin_PreferredChannelConfigurations
|
||||
short configs[][2] = {JucePlugin_PreferredChannelConfigurations};
|
||||
const int numConfigs = sizeof (configs) / sizeof (short[2]);
|
||||
|
||||
bool hasOnlyZeroChannels = true;
|
||||
|
||||
for (int i = 0; i < numConfigs && hasOnlyZeroChannels == true; ++i)
|
||||
if (configs[i][isInput ? 0 : 1] != 0)
|
||||
hasOnlyZeroChannels = false;
|
||||
|
||||
busCount = jmin (busCount, hasOnlyZeroChannels ? 0 : 1);
|
||||
#endif
|
||||
|
||||
return busCount;
|
||||
}
|
||||
|
||||
static bool setBusesLayout (AudioProcessor* juceFilter, const AudioProcessor::BusesLayout& requestedLayouts)
|
||||
{
|
||||
#ifdef JucePlugin_PreferredChannelConfigurations
|
||||
AudioProcessor::BusesLayout copy (requestedLayouts);
|
||||
|
||||
for (int dir = 0; dir < 2; ++dir)
|
||||
{
|
||||
const bool isInput = (dir == 0);
|
||||
|
||||
const int actualBuses = juceFilter->getBusCount (isInput);
|
||||
const int auNumBuses = getBusCount (juceFilter, isInput);
|
||||
Array<AudioChannelSet>& buses = (isInput ? copy.inputBuses : copy.outputBuses);
|
||||
|
||||
for (int i = auNumBuses; i < actualBuses; ++i)
|
||||
buses.add (AudioChannelSet::disabled());
|
||||
}
|
||||
|
||||
return juceFilter->setBusesLayout (copy);
|
||||
#else
|
||||
return juceFilter->setBusesLayout (requestedLayouts);
|
||||
#endif
|
||||
}
|
||||
|
||||
static AudioProcessor::BusesLayout getBusesLayout (const AudioProcessor* juceFilter)
|
||||
{
|
||||
#ifdef JucePlugin_PreferredChannelConfigurations
|
||||
AudioProcessor::BusesLayout layout = juceFilter->getBusesLayout();
|
||||
|
||||
for (int dir = 0; dir < 2; ++dir)
|
||||
{
|
||||
const bool isInput = (dir == 0);
|
||||
|
||||
const int actualBuses = juceFilter->getBusCount (isInput);
|
||||
const int auNumBuses = getBusCount (juceFilter, isInput);
|
||||
Array<AudioChannelSet>& buses = (isInput ? layout.inputBuses : layout.outputBuses);
|
||||
|
||||
for (int i = auNumBuses; i < actualBuses; ++i)
|
||||
buses.removeLast();
|
||||
}
|
||||
|
||||
return layout;
|
||||
#else
|
||||
return juceFilter->getBusesLayout();
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
AudioUnitHelpers::AUChannelStreamOrder AudioUnitHelpers::StreamOrder::auChannelStreamOrder[] =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue