使用 CMSampleBuffer 生成 Float32 数组(Float32 PCM 数据)
Generating Float32 Array (Float32 PCM data) using CMSampleBuffer
我从摄像头获得了音频数据格式为 CMSampleBuffer
的回调,但我无法将此数据转换为 PCM 数据。
我遵循了 Apple copyPCMData, UnsafeMutablePointer, AudioBufferList 提供的文档,但最后我得到的只是 0.0
。
这是我的代码:
private let pcmBufferPointer = UnsafeMutablePointer<AudioBufferList>.allocate(capacity: 1024)
init(....){
//...
let unsafeRawPointer = UnsafeMutableRawPointer.allocate(byteCount: 4, alignment: 0)
let audioBuffer = AudioBuffer(mNumberChannels: 1, mDataByteSize: 4, mData: unsafeRawPointer)
let audioBufferList = AudioBufferList(mNumberBuffers: 0, mBuffers: audioBuffer)
self.pcmBufferPointer.initialize(repeating: audioBufferList, count: 1024)
}
//CMSampleBuffer obtained from AVCaptureAudioDataOutputSampleBufferDelegate
private func audioFrom(sampleBuffer: CMSampleBuffer) -> Void {
let status = CMSampleBufferCopyPCMDataIntoAudioBufferList(sampleBuffer, 0, 1024, pcmBufferPointer)
if status == 0 {
Logger.log(key: "Audio Sample Buffer Status", message: "Buffer copied to pointer")
let dataValue = pcmBufferPointer[0].mBuffers.mData!.load(as: Float32.self) //Tried with Int, Int16, Int32, Int64 and Float too
Logger.log(key: "PCM Data Value", message: "Data value : \(dataValue)") //prints 0.0
}else{
Logger.log(key: "Audio Sample", message: "Buffer allocation failed with status \(status)")
}
}
终于成功了。
必须添加额外的步骤来将 AudioBufferList
指针转换为 AudioList
指针
if status == 0 {
let inputDataPtr = UnsafeMutableAudioBufferListPointer(pcmBufferPointer)
let mBuffers : AudioBuffer = inputDataPtr[0]
if let bufferPointer = UnsafeMutableRawPointer(mBuffers.mData){
let dataPointer = bufferPointer.assumingMemoryBound(to: Int16.self)
let dataArray = Array(UnsafeBufferPointer.init(start: dataPointer, count: 1024))
pcmArray.append(contentsOf: dataArray)
}else{
Logger.log(key: "Audio Sample", message: "Failed to generate audio sample")
}
}else{
Logger.log(key: "Audio Sample", message: "Buffer allocation failed with status \(status)")
}
以上代码仅适用于单通道 PCM 数据。对于 2 通道数据,请参考以下 GIST - https://gist.github.com/hotpaw2/ba815fc23b5d642705f2b1dedfaf0107
我从摄像头获得了音频数据格式为 CMSampleBuffer
的回调,但我无法将此数据转换为 PCM 数据。
我遵循了 Apple copyPCMData, UnsafeMutablePointer, AudioBufferList 提供的文档,但最后我得到的只是 0.0
。
这是我的代码:
private let pcmBufferPointer = UnsafeMutablePointer<AudioBufferList>.allocate(capacity: 1024)
init(....){
//...
let unsafeRawPointer = UnsafeMutableRawPointer.allocate(byteCount: 4, alignment: 0)
let audioBuffer = AudioBuffer(mNumberChannels: 1, mDataByteSize: 4, mData: unsafeRawPointer)
let audioBufferList = AudioBufferList(mNumberBuffers: 0, mBuffers: audioBuffer)
self.pcmBufferPointer.initialize(repeating: audioBufferList, count: 1024)
}
//CMSampleBuffer obtained from AVCaptureAudioDataOutputSampleBufferDelegate
private func audioFrom(sampleBuffer: CMSampleBuffer) -> Void {
let status = CMSampleBufferCopyPCMDataIntoAudioBufferList(sampleBuffer, 0, 1024, pcmBufferPointer)
if status == 0 {
Logger.log(key: "Audio Sample Buffer Status", message: "Buffer copied to pointer")
let dataValue = pcmBufferPointer[0].mBuffers.mData!.load(as: Float32.self) //Tried with Int, Int16, Int32, Int64 and Float too
Logger.log(key: "PCM Data Value", message: "Data value : \(dataValue)") //prints 0.0
}else{
Logger.log(key: "Audio Sample", message: "Buffer allocation failed with status \(status)")
}
}
终于成功了。
必须添加额外的步骤来将 AudioBufferList
指针转换为 AudioList
指针
if status == 0 {
let inputDataPtr = UnsafeMutableAudioBufferListPointer(pcmBufferPointer)
let mBuffers : AudioBuffer = inputDataPtr[0]
if let bufferPointer = UnsafeMutableRawPointer(mBuffers.mData){
let dataPointer = bufferPointer.assumingMemoryBound(to: Int16.self)
let dataArray = Array(UnsafeBufferPointer.init(start: dataPointer, count: 1024))
pcmArray.append(contentsOf: dataArray)
}else{
Logger.log(key: "Audio Sample", message: "Failed to generate audio sample")
}
}else{
Logger.log(key: "Audio Sample", message: "Buffer allocation failed with status \(status)")
}
以上代码仅适用于单通道 PCM 数据。对于 2 通道数据,请参考以下 GIST - https://gist.github.com/hotpaw2/ba815fc23b5d642705f2b1dedfaf0107