I have successfully used AVAudioPlayerNode
to play stereo and mono files. I would like to use files with 3+ channels (surround files) and be able to route the audio in a non-linear way. For instance, I could assign file channel 0 to output channel 2, and file channel 4 to output channel 1.
The number of outputs of the audio interface will be unknown (2-40), and this is why I need to be able to allow the user to route the audio as they see fit. And the solution in WWDC 2015 507 of having the user change the routing in Audio Midi Setup is not a viable solution.
There's only 1 possibility that I can think of (and I am open to others): creating one player per channel, and loading each with only one channels' worth of buffers similar to this post. But even by the posters admission, there are issues.
So I'm looking for a way to copy each channel of a file into an AudioBuffer like:
let file = try AVAudioFile(forReading: audioURL)
let fullBuffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat,
frameCapacity: AVAudioFrameCount(file.length))
try file.read(into: fullBuffer)
// channel 0
let buffer0 = AVAudioPCMBuffer(pcmFormat: file.processingFormat,
frameCapacity: AVAudioFrameCount(file.length))
// this doesn't work, unable to get fullBuffer channel and copy
// error on subscripting mBuffers
buffer0.audioBufferList.pointee.mBuffers.mData = fullBuffer.audioBufferList.pointee.mBuffers[0].mData
// repeat above buffer code for each channel from the fullBuffer
I was able to figure it out, so here's the code to make it work. Note: the code below separates a stereo (2 channel) file. This could easily be expanded to handle an unknown number of channels.