Многоканальное сопоставление AVAudioEngine - PullRequest
0 голосов
/ 29 мая 2020

Я преобразовал код obj c в swift: https://forums.developer.apple.com/thread/15416 Мой аудиофайл будет воспроизводиться на моем iPhone, но когда я подключаю аудиоинтерфейс, у меня просто тишина. Мой аудиоинтерфейс имеет 4 выхода и будет воспроизводить звук в других приложениях. Вот преобразованный код:

let audioSession = AVAudioSession.sharedInstance()

 // set the session category
 do
 {
     try audioSession.setCategory(.multiRoute, options: .mixWithOthers)
 }
 catch
 {
     print("unable to set category", error)
     return
 }

 // activate the audio session
 do
 {
     try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
 }
 catch
 {
     print("unable to set active", error)
     return
 }

 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 numberOfSourceChannels = file.processingFormat.channelCount
 print("numberOfSourceChannels: ", numberOfSourceChannels)

 let outputNumChannels = output.outputFormat(forBus: 0).channelCount
 print("outputNumChannels:" , outputNumChannels)
 var outputChannelMap = [
     0,
     1,
     -1,
     -1
 ]

 if let au = output.audioUnit
 {
     let propSize = UInt32(MemoryLayout.size(ofValue: outputChannelMap))
     print("propSize:", propSize)
     AudioUnitSetProperty(au, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Global, 0, &outputChannelMap, propSize)
 }

 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()

Вот результат его запуска:

/private/var/containers/Bundle/Application/FF7AA751-35A3-4B70-92C3-2D8356DE835A/AVAudioEngineTest.app/audio.m4a
numberOfSourceChannels:  2
outputNumChannels: 4
propSize: 8

Моя конечная цель - иметь возможность выбирать, на каком выходе будет воспроизводиться узел. Что я делаю не так? Заранее спасибо.

1 Ответ

0 голосов
/ 03 июня 2020

Оказывается, с кодом все в порядке, кроме outputChannelMap. Я не понимал, как это должно работать. Вот несколько примеров того, как это должно работать:

//normal output
var outputChannelMap = [
    0,
    1
]

// left audio to left output only
outputChannelMap = [
    0,
    -1
]

// both audio channels to left output
outputChannelMap = [
    0,
    0
]

// both audio channels to right output
outputChannelMap = [
    1,
    1
]

//left audio channel to right output only
outputChannelMap = [
    1,
    -1
]

// left out right, right our left
outputChannelMap = [
    1,
    0
]

// right audio to left output only
outputChannelMap = [
    -1,
    0
]

// right audio  to right output only
outputChannelMap = [
    -1,
    1
]
...