我一直在尝试使用AVAudioEngine来处理烧录的16位流数据。
但传递给AVAudioFormat连接功能总是会崩溃。
代码如下:
let AUDIO_OUTPUT_SAMPLE_RATE = 44100
let AUDIO_OUTPUT_CHANNELS = 2
let AUDIO_OUTPUT_BITS = 16
var audioEngine: AVAudioEngine?
var audioPlayer: AVAudioPlayerNode?
...
audioEngine = AVAudioEngine()
audioPlayer = AVAudioPlayerNode()
audioEngine?.attach(audioPlayer!)
let mixer = audioEngine?.mainMixerNode
mixer!.outputVolume = 1.0
let stereoFormat = AVAudioFormat(commonFormat: .pcmFormatInt16, sampleRate: Double(AUDIO_OUTPUT_SAMPLE_RATE), channels: 2, interleaved: false)
audioEngine!.connect(audioPlayer!, to: mixer!, format: stereoFormat)
...
audioEngine!。connect(...)正在崩溃
我正在使用Xcode 8 beta 6,OS X El Capitan,而且,这种情况都来自于模拟器和设备。
这是崩溃消息的一部分:
ERROR: >avae> AVAudioNode.mm:751: AUSetFormat: error -10868
*** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'error -10868'
...
3 AVFAudio 0x000000011e0a5630 _Z19AVAE_RaiseExceptionP8NSStringz + 176
4 AVFAudio 0x000000011e0f270d _ZN19AVAudioNodeImplBase11AUSetFormatEP28OpaqueAudioComponentInstancejjP13AVAudioFormat + 213
5 AVFAudio 0x000000011e0f2630 _ZN19AVAudioNodeImplBase15SetOutputFormatEmP13AVAudioFormat + 46
6 AVFAudio 0x000000011e0f9663 _ZN21AVAudioPlayerNodeImpl15SetOutputFormatEmP13AVAudioFormat + 25
7 AVFAudio 0x000000011e099cfd _ZN18AVAudioEngineGraph8_ConnectEP19AVAudioNodeImplBaseS1_jjP13AVAudioFormat + 2377
8 AVFAudio 0x000000011e09d15f _ZN18AVAudioEngineGraph7ConnectEP11AVAudioNodeS1_mmP13AVAudioFormat + 355
9 AVFAudio 0x000000011e0fc80e _ZN17AVAudioEngineImpl7ConnectEP11AVAudioNodeS1_mmP13AVAudioFormat + 348
从音频文件播放缓冲区和格式没问题。
我做的错误是什么?
感谢。
答案 0 :(得分:2)
-10868, a.k.a. kAudioUnitErr_FormatNotSupported
, so it looks like your PCMFormatInt16
isn't appreciated. Changing it to .PCMFormatFloat32
does work.
答案 1 :(得分:1)
您无需自己创建音频格式,
从实际音频数据(pcm 缓冲区或音频文件)中获取音频格式
<块引用>来自 WWDC 2016 的音频格式,提供卓越的音频体验
来自 WWDC 2015 的实际音频格式理论,Core Audio 的新功能
答案 2 :(得分:0)
从Apple,AVAudioPlayerNode
在播放缓冲区时,有一个隐含的假设,即缓冲区的采样率与节点的输出格式相同。
然后打印AVAudioPlayerNode
的输出格式,即engine.mainMixerNode.inputFormat
open func connectNodes() {
print(engine.mainMixerNode.inputFormat(forBus: 0))
engine.connect(playerNode, to: engine.mainMixerNode, format: readFormat)
}
结果是
因此选择.pcmFormatFloat32
而不是.pcmFormatInt16
答案 3 :(得分:0)
您可以使用烧录的 16 位音频格式,但您应该先将其转换。
// Setup your own format
let inputFormat = AVAudioFormat(
commonFormat: .pcmFormatInt16,
sampleRate: 44100,
channels: AVAudioChannelCount(2),
interleaved: true
)!
let engine = AVAudioEngine()
// Use system format as output format
let outputFormat = engine.mainMixerNode.outputFormat(forBus: 0)
self.converter = AVAudioConverter(from: inputFormat, to: outputFormat)!
self.playerNode = AVAudioPlayerNode()
engine.attach(playerNode)
engine.connect(playerNode, to: engine.mainMixerNode, format: nil)
...
// Prepare input and output buffer
let inputBuffer = AVAudioPCMBuffer(pcmFormat: inputFormat, frameCapacity: maxSamplesPerBuffer)!
let outputBuffer = AVAudioPCMBuffer(pcmFormat: outputFormat, frameCapacity: maxSamplesPerBuffer)!
// When you fill your Int16 buffer with data, send it to converter
self.converter.convert(to: outputBuffer, error: nil) { inNumPackets, outStatus in
outStatus.pointee = .haveData
return inputBuffer
}
// Now in outputBuffer sound in system format and we can play it
self.playerNode.scheduleBuffer(outputBuffer)