Output Channel Selection Redux
Output Channel Selection Redux
- Subject: Output Channel Selection Redux
- From: Bob Ingraham <email@hidden>
- Date: Tue, 24 Feb 2009 15:38:48 -0700 (MST)
Hey All,
Thanks for the help thus far!
But I am just hitting a brick wall here. I think I'm on the right track with the SimpleSDK PlayFile example I've been modifying, but I just can't past the channel select problem using kAudioOutputUnitProperty_ChannelMap.
Any help would be most appreciated...
Scenario:
- Mac Pro with OS X 10.5.6 and XCode 3.1.2
- PCI device with 16 output channels (the "MOTU")
- Tried AudioQueue Services, but hit dead-end
- Using modified /Developer/Examples/CoreAudio/SimpleSDK/PlayFile code
Goal:
- Get PlayFile.cpp to play mono audio on a specific channel of the 16-channel MOTU
So far, I've modified the code to use the AUHAL audio unit as the output unit, and I've set it's Current Device to point to my 16-channel MOTU device.
The PlayFile app now plays my mono file (as stereo,) on channel 1 & 2 on the MOTU.
Failures:
- Trying to change the AUHAL channel layout to mono.
- Trying to change the AUHAL ChannelMap property to map mono channel 0 to AUHAL channel 3 (or whatever.)
The problem is, I don't the order of operations or when it's appropriate to issue the Layout and Channel Map prpoerty modification requests. My current order of ops is:
1. AUGraphAddNode (AUHAL) --> OK
2. AUGraphAddNode (Audio File Player) --> OK
3. AUGraphOpen --> OK
4. AUGraphNodeInfo (AUHAL Node) --> Done to get AudioUnit handle to AUHAL --> OK
5. AudioUnitSetProperty (AUHAL, CurrentDevice, MOTU-Audio-Device-ID) --> OK
6. AudioUnitGetProperty (AUHAL, SupportedNumChannels, Scope-Output, Element-0) -- > Fails with kAudioUnitErr_InvalidScope. Tried with Scope-Global and fails with kAudioUnitErr_InvalidProperty.
7. AudioUnitGetProperty (AUHAL, SupportedChannelLayoutTags, Scope-Output) --> Fails with kAudioUnitErr_InvalidElement or kAudioUnitErr_InvalidProperty depending on which element/scope I try.
8. AudioUnitSetProperty (AUHAL, AudioChannelLayout, Scope-Output, Element-1) --> Fails with kAudioUnitErr_InvalidProperty - guess it doesn't take bitmaps.
9. AudioUnitSetProperty (AUHAL, ChannelMap, Scope-Output, Element-1) --> OK, but doesn't work like I expect it to. I ask for audiochannel 0 to be mapped to device-channel 1, but it still plays on device-channel 0...
Code (modified MakeSimpleGraph subroutine from PlayFile.cpp):
void MakeSimpleGraph (AUGraph &theGraph, CAAudioUnit &fileAU, CAStreamBasicDescription &fileFormat, AudioFileID audioFile)
{
XThrowIfError (NewAUGraph (&theGraph), "NewAUGraph");
AudioUnit auOutput;
AudioDeviceID adiMOTU;
OSStatus err;
ComponentDescription myCd;
char fred[5];
AudioChannelLayoutTag tags[8];
UInt32 numTags, outSize, numElements, numChannels;
int i;
AudioChannelLayout chanLayout;
CAComponentDescription cd;
// output node
cd.componentType = kAudioUnitType_Output;
cd.componentSubType = kAudioUnitSubType_HALOutput;
cd.componentManufacturer = kAudioUnitManufacturer_Apple;
AUNode outputNode;
XThrowIfError (AUGraphAddNode (theGraph, &cd, &outputNode), "AUGraphAddNode");
// Get the Audio Device ID of the MOTU device
if ((err = GetMOTUDevice(&adiMOTU)) != noErr)
{
printf("Unable to locate MOTU Audio Device ID: %d\n", err);
return;
}
// file AU node
AUNode fileNode;
cd.componentType = kAudioUnitType_Generator;
cd.componentSubType = kAudioUnitSubType_AudioFilePlayer;
XThrowIfError (AUGraphAddNode (theGraph, &cd, &fileNode), "AUGraphAddNode");
// connect & setup
XThrowIfError (AUGraphOpen (theGraph), "AUGraphOpen");
// Get Audio Device of output node
err = AUGraphNodeInfo(theGraph, outputNode, &myCd, &auOutput);
if (err != noErr)
{
printf("Failed to obtain Graph Node Info: %d\n", err);
return;
}
printf("AUGraphNodeInfo: err = %d\n", err);
printf("Output Audio Unit: %x\n", auOutput);
printf("componentType: %s\n", ost2str(myCd.componentType, fred));
printf("componentSubType: %s\n", ost2str(myCd.componentSubType, fred));
printf("componentManufacturer: %s\n", ost2str(myCd.componentManufacturer, fred));
err = AudioUnitSetProperty(auOutput, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &adiMOTU, sizeof(adiMOTU));
if (err != noErr)
{
printf("Failed to set CurrentDevice of the output node: 0x%x\n", err);
//return;
}
// Get output element count
outSize = sizeof(numElements);
err = AudioUnitGetProperty(auOutput, kAudioUnitProperty_ElementCount, kAudioUnitScope_Output, 1, &numElements, &outSize);
if (err != noErr)
{
printf("Failed to get output scope element count: %d\n", err);
//return;
}
else
{
printf("Output Scope Elements = %u\n", numElements);
}
// Get Output Unit stream format
AudioStreamBasicDescription sFormat;
outSize = sizeof(sFormat);
err = AudioUnitGetProperty(auOutput, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &sFormat, &outSize);
if (err != noErr)
{
printf("Failed to get Audio Stream Format: %d\n", err);
}
else
{
printf("Audio Stream Format:\n");
printf("mSampleRate : %f\n", sFormat.mSampleRate);
printf("mFormatID : %s\n", ost2str(sFormat.mFormatID, fred));
printf("mFormatFlags : 0x%x\n", sFormat.mFormatFlags);
printf("mBytesPerPacket : %u\n", sFormat.mBytesPerPacket);
printf("mFramesPerPacket : %u\n", sFormat.mFramesPerPacket);
printf("mBytesPerFrame : %u\n", sFormat.mBytesPerFrame);
printf("mChannelsPerFrame: %u\n", sFormat.mChannelsPerFrame);
printf("mBitsPerChannel : %u\n", sFormat.mBitsPerChannel);
}
// Get output channel count
outSize = sizeof(numElements);
err = AudioUnitGetProperty(auOutput, kAudioUnitProperty_SupportedNumChannels, kAudioUnitScope_Output, 0, &numChannels, &outSize);
if (err != noErr)
{
printf("Failed to get output scope channel count: %d\n", err);
//return;
}
else
{
printf("Output Scope Channels = %u\n", numChannels);
}
// Get property size of LayoutTags
outSize = 0;
err = AudioUnitGetProperty(auOutput, kAudioUnitProperty_SupportedChannelLayoutTags, kAudioUnitScope_Global, 0, NULL, &outSize);
if (err != noErr)
{
printf("Failed to get size of supported Channel Layout Tags: %d\n", err);
//return;
}
else
{
printf("LayoutTags size = %u\n", outSize);
}
outSize = sizeof(tags);
memset(tags, 0, sizeof(tags));
err = AudioUnitGetProperty(auOutput, kAudioUnitProperty_SupportedChannelLayoutTags, kAudioUnitScope_Output, 1, &tags, &outSize);
if (err != noErr)
{
printf("Failed to get supported Channel Layout Tags: %d\n", err);
//return;
}
else
{
numTags = outSize/sizeof(AudioChannelLayoutTag);
printf("Number of Layout Tags: %d\n", numTags);
for (i=0; i < numTags; i++)
{
printf("Tag %d: %d\n", i, tags[i]);
}
}
// Set channel layout
memset(&chanLayout, 0, sizeof(chanLayout));
chanLayout.mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelBitmap | kAudioChannelLayoutTag_Mono;
chanLayout.mChannelBitmap = kAudioChannelBit_Left;
err = AudioUnitSetProperty(auOutput, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Output, 1, &chanLayout, sizeof(chanLayout));
if (err != noErr)
{
printf("Failed to set Audio Channel Layout: %d\n", err);
}
SInt32 *channelMap = NULL;
UInt32 numOfChannels = fileFormat.NumberChannels();
UInt32 mapSize = numOfChannels * sizeof(SInt32);
channelMap = (SInt32 *)malloc(mapSize);
for (i=0; i < numOfChannels; i++)
{
channelMap[i] = i+1;
}
//channelMap[desiredInputChannel] = deviceOutputChannel;
//channelMap[0] = 2;
//channelMap[1] = 3;
err = AudioUnitSetProperty(auOutput, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 1, channelMap, mapSize);
if (err != noErr)
{
printf("Failed to set Audio Channel Map: %d\n", err);
}
else
{
printf("Set Audio Channel Map OK!\n");
}
// install overload listener to detect when something is wrong
AudioUnit anAU;
XThrowIfError (AUGraphNodeInfo(theGraph, fileNode, NULL, &anAU), "AUGraphNodeInfo");
fileAU = CAAudioUnit (fileNode, anAU);
...
Debug Output:
bobis-mac-pro:Development bobi$ ./PlayFile ~/Downloads/English\ Small\ Business\ 3.mp3
playing file: /Users/bobi/Downloads/English Small Business 3.mp3
format: AudioStreamBasicDescription: 1 ch, 44100 Hz, '.mp3' (0x00000000) 0 bits/channel, 0 bytes/packet, 1152 frames/packet, 0 bytes/frame
Device: Built-in Line Input
Device: Built-in Digital Input
Device: Built-in Output
Device: Built-in Line Output
Device: Built-in Digital Output
Device: PCI-424
Found the MOTU Audio Device ID
AUGraphNodeInfo: err = 0
Output Audio Unit: 810000
componentType: auou
componentSubType: ahal
componentManufacturer: appl
Output Scope Elements = 2
Audio Stream Format:
mSampleRate : 44100.000000
mFormatID : lpcm
mFormatFlags : 0x29
mBytesPerPacket : 4
mFramesPerPacket : 1
mBytesPerFrame : 4
mChannelsPerFrame: 2
mBitsPerChannel : 32
Failed to get output scope channel count: -10866
Failed to get size of supported Channel Layout Tags: -10877
Failed to get supported Channel Layout Tags: -10879
Failed to set Audio Channel Layout: -10851
Set Audio Channel Map OK!
file duration: 672.208980 secs
Help!
Bob
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden