我最近在关于iOS中使用multiroute的问题上发布了这个问题,并且我认为我解决了它,但是我发现它并没有完全解决:AVAudioEngine多通道映射
我遇到的问题是multiroute仅适用于前两个输出通道。我正在尝试使其适用于4通道音频接口。
我已经成功地使用AVAudioPlayer将音频路由到USB接口的每个输出。
var avplayer = AVAudioPlayer()
@IBAction func avAudioPlayerPlay(_ sender: Any)
{
let audioSession = AVAudioSession.sharedInstance()
let route = audioSession.currentRoute
// set the session category
do
{
//try audioSession.setCategory(.multiRoute)
try audioSession.setCategory(.multiRoute, options: .mixWithOthers)
}
catch
{
print("unable to set category", error)
return
}
// activate the audio session - turns on multiroute I believe
do
{
try audioSession.setActive(true)
//try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
}
catch
{
print("unable to set active", error)
return
}
//audio interface + headphone jack
let outputs:[AVAudioSessionChannelDescription] = [
route.outputs[0].channels![2], // 3rd channel on Audio Interface
route.outputs[1].channels![1] // Right Channel of Headphones
]
guard let filePath: String = Bundle.main.path(forResource: "audio", ofType: "m4a") else { return }
let fileURL: URL = URL(fileURLWithPath: filePath)
do
{
avplayer = try AVAudioPlayer(contentsOf: fileURL)
}
catch
{
print("play error", error)
return
}
avplayer.channelAssignments = outputs
let result = avplayer.play()
print(result)
}
但是我无法使用AVAudioEngine使其工作:
private func getOutputChannelMapIndices(_ names:[String?]) -> [Int]
{
let session = AVAudioSession.sharedInstance()
let route = session.currentRoute
let outputPorts = route.outputs
var channelMapIndices:[Int] = []
for name in names
{
var chIndex = 0
for outputPort in outputPorts
{
guard let channels = outputPort.channels else
{
continue
}
for channel in channels
{
print(channel.channelName)
if channel.channelName == name
{
if names.count > channelMapIndices.count
{
channelMapIndices.append(chIndex)
}
}
chIndex += 1
}
}
}
return channelMapIndices
}
@IBAction func nodesPlay(_ sender: Any)
{
let channelNames = [
"UMC204HD 192k 3",
"Headphones Left",
"Headphones Right",
nil
]
let audioSession = AVAudioSession.sharedInstance()
// set the session category
do
{
//try audioSession.setCategory(.multiRoute)
try audioSession.setCategory(.multiRoute, options: .mixWithOthers)
}
catch
{
print("unable to set category", error)
return
}
// activate the audio session - turns on multiroute I believe
do
{
try audioSession.setActive(true)
//try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
}
catch
{
print("unable to set active", error)
return
}
let channelMapIndices = getOutputChannelMapIndices(channelNames)
print("channelMapIndices: ", channelMapIndices)
engine = AVAudioEngine()
output = engine.outputNode
mixer = engine.mainMixerNode
player = AVAudioPlayerNode()
engine.attach(player)
guard let filePath: String = Bundle.main.path(forResource: "audio", ofType: "m4a") else { return }
let fileURL: URL = URL(fileURLWithPath: filePath)
let file = try! AVAudioFile(forReading: fileURL)
let outputNumChannels = output.outputFormat(forBus: 0).channelCount
print("outputNumChannels:" , outputNumChannels)
var outputChannelMap:[Int] = Array(repeating: -1, count: Int(outputNumChannels))
let numberOfSourceChannels = file.processingFormat.channelCount
print("numberOfSourceChannels: ", numberOfSourceChannels)
var sourceChIndex = 0
for chIndex in channelMapIndices
{
if chIndex < outputNumChannels && sourceChIndex < numberOfSourceChannels
{
outputChannelMap[chIndex] = sourceChIndex
sourceChIndex += 1
}
}
print("outputChannelMap: ", outputChannelMap)
if let au = output.audioUnit
{
let propSize = UInt32(MemoryLayout.size(ofValue: outputChannelMap))
print("propSize:", propSize)
let result = AudioUnitSetProperty(au, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Global, 0, &outputChannelMap, propSize)
print("result: ", result)
}
let channelLayout = AVAudioChannelLayout(layoutTag: kAudioChannelLayoutTag_DiscreteInOrder | UInt32(numberOfSourceChannels))
let format = AVAudioFormat(streamDescription: file.processingFormat.streamDescription, channelLayout: channelLayout)
engine.connect(player, to: mixer, format:format)
engine.connect(mixer, to: output, format:format)
player.scheduleFile(file, at: nil, completionHandler: nil)
do
{
try engine.start()
}
catch
{
print("can't start", error)
return
}
player.play()
}
如果有人能够解释为什么我似乎无法在输出3或4播放任何音频,我将不胜感激。
请注意,这段代码的许多内容都是从这里翻译过来的:https://forums.developer.apple.com/thread/15416
kAudioOutputUnitProperty_ChannelMap
之前,它的值是多少?输出单元上的kAudioUnitProperty_StreamFormat
有多少个通道? - sbooth