Jac*_*ngs 6 avfoundation ios swift avaudioengine
此方法处理来自AVAudioEngine的输入节点上的installTap的回调.我已经确认我正在获取mono float32/48000hz缓冲区数据,我想将其转换为mono int16/16000hz.
var converter: AVAudioConverter? = nil
var convertBuffer: AVAudioPCMBuffer? = nil
let targetFormat = AVAudioFormat(commonFormat: AVAudioCommonFormat.pcmFormatInt16, sampleRate: 16000, channels: 1, interleaved: false)
func recordCallback(buffer: AVAudioPCMBuffer, time: AVAudioTime) {
if converter == nil {
convertBuffer = AVAudioPCMBuffer(pcmFormat: targetFormat, frameCapacity: buffer.frameCapacity)
convertBuffer?.frameLength = convertBuffer!.frameCapacity
converter = AVAudioConverter(from: buffer.format, to: convertBuffer!.format)
converter?.sampleRateConverterAlgorithm = AVSampleRateConverterAlgorithm_Normal
converter?.sampleRateConverterQuality = .max
}
guard let convertBuffer = convertBuffer else { return }
log.info("Converter: \(self.converter!)")
log.info("Converter buffer: \(self.convertBuffer!)")
log.info("Converter buffer format: \(self.convertBuffer!.format)")
log.info("Source buffer: \(buffer)")
log.info("Source buffer format: \(buffer.format)")
do {
try converter!.convert(to: convertBuffer, from: buffer)
} catch let error {
log.error("Conversion error: \(error)")
observer?.onError(EngineRecordTaskError.ConversionError(error: error))
return
}
…
}
Run Code Online (Sandbox Code Playgroud)
这给了我一个有用的错误:
Conversion error: Error Domain=NSOSStatusErrorDomain Code=-50 "(null)"
Run Code Online (Sandbox Code Playgroud)
如果我使用替代方法.convert(to:error:withInputFrom :),它不会填充NSError,也不会填充目标缓冲区 - 无提示失败.
记录信息:
Converter: <AVAudioConverter: 0x17001cd40>
Converter buffer: <AVAudioPCMBuffer@0x17021e310: 9600/9600 bytes>
Converter buffer format: <AVAudioFormat 0x17448ba90: 1 ch, 16000 Hz, Int16>
Source buffer: <AVAudioPCMBuffer@0x17021e1b0: 19200/19200 bytes>
Source buffer format: <AVAudioFormat 0x174480910: 1 ch, 48000 Hz, Float32>
Conversion error: Error Domain=NSOSStatusErrorDomain Code=-50 "(null)"
Run Code Online (Sandbox Code Playgroud)
调试器的其他信息:
(lldb) po buffer.frameCapacity
4800
(lldb) po convertBuffer.frameCapacity
4800
(lldb) po buffer.frameLength
4800
(lldb) po convertBuffer.frameLength
4800
Run Code Online (Sandbox Code Playgroud)
这是我尝试的转换的替代代码:
var conversionError: NSError? = nil
converter!.convert(to: convertBuffer, error: &conversionError, withInputFrom: { (_, _) in
return buffer
})
if let conversionError = conversionError {
log.error("Conversion error: \(conversionError)")
observer?.onError(EngineRecordTaskError.ConversionError(error: conversionError))
return
}
Run Code Online (Sandbox Code Playgroud)
convert从头文件中的讨论:
输出缓冲区的 frameCapacity 应该至少与 inputBuffer 的 frameLength 一样大。如果转换涉及编解码器或采样率转换,则必须改用 convertToBuffer:error:withInputFromBlock:。
您正在从 48kHz 转换为 16kHz,这算作速率转换,因此您必须使用convertToBuffer:
let inputBlock: AVAudioConverterInputBlock = { inNumPackets, outStatus in
outStatus.pointee = AVAudioConverterInputStatus.haveData
return buffer
}
var error: NSError? = nil
let status: AVAudioConverterOutputStatus = converter!.convert(to: convertBuffer, error: &error, withInputFrom: inputBlock)
// TODO: check status
Run Code Online (Sandbox Code Playgroud)
psNSError在苹果上创建新的代码和字符串肯定非常昂贵- 他们的预算无法涵盖“速率转换需要 convertToBuffer”消息。
| 归档时间: |
|
| 查看次数: |
939 次 |
| 最近记录: |