【发布时间】:2018-10-18 13:14:40
【问题描述】:
我正在使用 AVCaptureSession 捕获音频。在用于处理捕获的数据的回调函数中,我将流放入数据结构(字节缓冲区)中。看起来 Data 是 UInt8(对于字节缓冲区有意义),但我相信流数据是 UInt32。
我不确定我应该执行以下哪一项,但我无法让其中任何一项发挥作用。我:
- 将 Data 转换为 UInt32 而不是 UInt8?
- 从数据中读取时,需要 4 个字节来制作 UInt32?
- 将我的捕获会话更改为 UInt8?
- 放弃数据结构,自己做?
我的回调函数是:
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
var audioBufferList = AudioBufferList()
var data = Data()
var blockBuffer: CMBlockBuffer?
// Put the sample buffer in to a list of audio buffers (audioBufferList)
CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer, bufferListSizeNeededOut: nil, bufferListOut: &audioBufferList, bufferListSize: MemoryLayout<AudioBufferList>.size, blockBufferAllocator: nil, blockBufferMemoryAllocator: nil, flags: 0, blockBufferOut: &blockBuffer)
// Extract the BufferList in to an array of buffers
let buffers = UnsafeBufferPointer<AudioBuffer>(start: &audioBufferList.mBuffers, count: Int(audioBufferList.mNumberBuffers))
// for each buffer, extract the frame. There should only be one buffer as we are recording in mono!
for audioBuffer in buffers {
assert(audioBuffer.mNumberChannels == 1) // it should always be 1 for mono channel
let frame = audioBuffer.mData?.assumingMemoryBound(to: UInt8.self)
data.append(frame!, count: Int(audioBuffer.mDataByteSize) / 8)
}
// limit how much of the sample we pass through.
viewDelegate?.gotSoundData(data.prefix(MAX_POINTS))
}
所有的gotSoundData都从视图到多个子视图进行处理
func addSamples(samples: Data) {
//if (isHidden) { return }
samples.forEach { sample in
[...process each byte...]
}
}
我可以看到 Data.append 有定义:
mutating func append(_ bytes: UnsafePointer<UInt8>, count: Int)
【问题讨论】:
-
你确定是 8bit 而不是 16bit?
-
我在描述中添加了数据是 Uint8。我不确定流在什么位置。现在找不到。想知道我是否对 CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer 上的 UInt32 标志感到困惑。我移植的旧 AudioUnit 代码是 SInt16。
-
好的 - 我会说你是对的,它是 16 位的。我还没有发现任何要说的东西,但是帧是 1024 个样本,它的大小是 2048 字节......每个样本 16 位。问题仍然存在……我如何一次读取 2 个字节的数据。
-
所以可能是
let pData = UnsafeMutablePointer<Int16>(yourBuffer.data),然后是let sampleArray = UnsafeMutableBufferPointer<Int16>( start: pData, count: Int(yourBuffer.mDataByteSize)/sizeof(Int16))。然后sampleArray是您的 16 位值数组。 -
第一行失败,因为 yourBuffer 是 UnsafeMutableRawPointer(从 UnsafeBufferPointer
返回)不能成为 UnsafeMutablePointer。