I am trying to use AVAudioEngine for what SEEMS to be a simple task, but AVAE is acting broken.
It is most likely that my CA-NooB thought process or code is broken.
I am trying to connect multiple USB input/output "sound cards" to a Mac, and route the audio from the "cards" between each other using AVAudioEngine. The Mac's "default" audio device is not involved.
Let's call the USB widgets A,B,C and D.
(The particular USB widgets I am using each have 1 input channel and 2 output channels, and use C-Media innards)
For right now, I am just trying to get A->A, B->B, C->C, etc to work.
I can create this configuration in HALLab.app, and it works.
HALLab implies that it is using an "AudioEngine" to do its work.
(If only the source to HALLab was still available…)
I have assembled units A,B,C,D into input and output aggregate devices in Audio MIDI Setup, and (thanks to some code from Mike Ash) managed to connect them as the currentDevices of an Audio Engine instance's inputNode and outputNode.
But Mike's code is for direct hardware devices, not aggregate, if that matters.
CORE PROBLEM: I cannot convince the AVAE that I have more than _one_ sub-device's worth of channels. All of the AVAE-level methods that discuss channel count return the count of a single sub-device, ("A") not the complete set {A,B,C,D}. It is always the first sub-device in the aggregate device.
And sure enough, only one works: A->A.
Lower-level code that iterates through AudioEngine.inputNode's sub-devices->buffers and totals the channel counts returns the correct (AFAIK) numbers. And of course Audio MIDI Setup displays the correct values.
For simplicity I currently have the AVAE's inputNode connected to its outputNode, skipping the mixer. (Got the same results with the mixer).
I have flailed around in lower level AUProperties, setting channel maps and fiddling with formats/layout tags, but the only result has been occasionally "breaking" my one operating sub-device and altering the AVAE’s GraphDescription.
Currently, the AudioEngine's GraphDescription reads:
________ GraphDescription ________ AVAudioEngineGraph 0x600000183740: initialized = 1, running = 1, number of nodes = 3
******** output chain ********
node 0x6080000a3a80 {'auou' 'ahal' 'appl'}, 'I' inputs = 1 (bus0) <- (bus1) 0x6180000a8160, {'auou' 'ahal' 'appl'}, [ 8 ch, 44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
node 0x6180000a8160 {'auou' 'ahal' 'appl'}, 'I' outputs = 2 (bus0) -> (bus0) 0x0, {}, [ 8 ch, 44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved] (bus1) -> (bus0) 0x6080000a3a80, {'auou' 'ahal' 'appl'}, [ 8 ch, 44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
******** input chain ********
node 0x6180000a8160 {'auou' 'ahal' 'appl'}, 'I' outputs = 2 (bus0) -> (bus0) 0x0, {}, [ 8 ch, 44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved] (bus1) -> (bus0) 0x6080000a3a80, {'auou' 'ahal' 'appl'}, [ 8 ch, 44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
node 0x6080000a3a80 {'auou' 'ahal' 'appl'}, 'I' inputs = 1 (bus0) <- (bus1) 0x6180000a8160, {'auou' 'ahal' 'appl'}, [ 8 ch, 44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
******** other nodes ********
node 0x6180000cbc90 {'aumx' 'mcmx' 'appl'}, 'U' ______________________________________
I can't honestly interpret this with any confidence.
I do seem to have convinced the AVAI that I have 8 channels, but still only one channel-pair actually functions.
To shorten this post, I have put:
A zip of my project and... A PDF that graphically explains what I am trying to accomplish and... A copy of the text of this posting at:
Since this is just a "proof of concept" project, all of the meat is at the top of AppDelegate.m in -doTests.
I have created a few utility functions that AppDelegate.m uses — they are in "Audio Utilities.m".
"So what is the question already?"
a) Can this be done? 2) If so, where am I going wrong, OR, what would an outline of the correct strategy look like?
(And anyone wanting a small contract to educate me via functioning code should feel free to make an informal proposal. I can probably wheedle some modest dollars out of management. Reach me directly at email@hidden or email@hidden)
|