CoreAudio Device output channel names


#1

Juce has always reported “output 1, output 2” etc for CoreAudio output channel names, even if the driver provides proper channel names. The following change to juce_mac_CoreAudio.cpp (line 156 and onwards) enables reporting of proper CoreAudio driver channel names:

for (unsigned int j = 0; j < b.mNumberChannels; ++j)
{
	if (input)
	{
		if (activeInputChans[chanNum])
		{
			inputChannelInfo [activeChans].streamNum = i;
			inputChannelInfo [activeChans].dataOffsetSamples = j;
			inputChannelInfo [activeChans].dataStrideSamples = b.mNumberChannels;
			++activeChans;
			numInputChannelInfos = activeChans;
		}
		
		
		char channelName[256]; 
		UInt32 dataSize = sizeof(channelName); 
		OSStatus error = AudioDeviceGetProperty(deviceID, 
												chanNum + 1, 
												false, 
												kAudioDevicePropertyChannelName, 
												&dataSize, 
												&channelName );
		if (error == noErr) 
			inChanNames.add(String(channelName));
		else
			inChanNames.add (T("Input ") + String (chanNum + 1));
	}
	else
	{
		if (activeOutputChans[chanNum])
		{
			outputChannelInfo [activeChans].streamNum = i;
			outputChannelInfo [activeChans].dataOffsetSamples = j;
			outputChannelInfo [activeChans].dataStrideSamples = b.mNumberChannels;
			++activeChans;
			numOutputChannelInfos = activeChans;
		}
		
		char channelName[256]; 
		UInt32 dataSize = sizeof(channelName); 
		OSStatus error = AudioDeviceGetProperty(deviceID, 
												chanNum + 1, 
												false, 
												kAudioDevicePropertyChannelName, 
												&dataSize, 
												&channelName );
		if (error == noErr) 
			outChanNames.add(String(channelName));
		else
			outChanNames.add (T("Output ") + String (chanNum + 1));
	}
	
	++chanNum;
}

#2

Thanks - I’d been meaning to get around to adding that.

But according to the docs, kAudioDevicePropertyChannelName is listed as a property that will get deprecated in the future… do you know of any other way of getting the name?


#3

[quote]Thanks - I’d been meaning to get around to adding that.

But according to the docs, kAudioDevicePropertyChannelName is listed as a property that will get deprecated in the future… do you know of any other way of getting the name?[/quote]

There is a kAudioDevicePropertyChannelNameCFString, which is supposed to take over from this one. To my experience, there are no drivers who implement this however, so the version I posted works most reliably. One could check this property before however, and if that fails - fallback to my version.


#4

Ok, interesting. Thanks!


#5

Hmm - looks to me like your version won’t get the input channel names correctly. Maybe try this:

[code] for (unsigned int j = 0; j < b.mNumberChannels; ++j)
{
String name;

                    {
                        uint8 channelName [256];
                        zerostruct (channelName);
                        UInt32 nameSize = sizeof (channelName);

                        if (AudioDeviceGetProperty (deviceID, chanNum + 1, input, kAudioDevicePropertyChannelName, 
                                                    &nameSize, &channelName) == noErr)
                            name = String::fromUTF8 (channelName, nameSize);
                    }

                    if (input)
                    {
                        if (activeInputChans[chanNum])
                        {
                            inputChannelInfo [activeChans].streamNum = i;
                            inputChannelInfo [activeChans].dataOffsetSamples = j;
                            inputChannelInfo [activeChans].dataStrideSamples = b.mNumberChannels;
                            ++activeChans;
                            numInputChannelInfos = activeChans;
                        }

                        if (name.isEmpty())
                            name << "Input " << (chanNum + 1);

                        inChanNames.add (name);
                    }
                    else
                    {
                        if (activeOutputChans[chanNum])
                        {
                            outputChannelInfo [activeChans].streamNum = i;
                            outputChannelInfo [activeChans].dataOffsetSamples = j;
                            outputChannelInfo [activeChans].dataStrideSamples = b.mNumberChannels;
                            ++activeChans;
                            numOutputChannelInfos = activeChans;
                        }

                        if (name.isEmpty())
                            name << "Output " << (chanNum + 1);

                        outChanNames.add (name);
                    }[/code]

#6

I just remembered, that when I was using the CFString version, I didn’t get an error message from some drivers though, they just reported an empty “” string, so if you want to do this, you will need to check for this empty string, and if it is indeed empty - fallback to the “old” method.

If this fails, just fallback to “Output channelNo” strategy.