我目前正在处理音频样本.
我从AVAssetReader获取它们并使用类似这样的CMSampleBuffer:
我从AVAssetReader获取它们并使用类似这样的CMSampleBuffer:
guard let sampleBuffer = readerOutput.copyNextSampleBuffer() else { guard reader.status == .completed else { return nil } // Completed // samples is an array of Int16 let samples = sampleData.withUnsafeBytes { Array(UnsafeBufferPointer<Int16>( start: $0,count: sampleData.count / MemoryLayout<Int16>.size)) } // The only way I found to convert [Int16] -> [Float]... return samples.map { Float($0) / Float(Int16.max)} } guard let blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer) else { return nil } let length = CMBlockBufferGetDataLength(blockBuffer) let sampleBytes = UnsafeMutablePointer<UInt8>.allocate(capacity: length) CMBlockBuffercopyDataBytes(blockBuffer,length,sampleBytes) sampleData.append(sampleBytes,count: length) }
正如你所见,我发现只有转换[Int16] – > [Float] issamples.map {Float($0)/ Float(Int16.max),但这样做我的处理时间也在增加.是否存在将Int16的指针强制转换为Float指针的其他方法?
解决方法
“强制转换”或“重新绑定”指针只会改变内存的方式
解释.您想从整数计算浮点值,
新值具有不同的内存表示(也是不同的
尺寸).
解释.您想从整数计算浮点值,
新值具有不同的内存表示(也是不同的
尺寸).
因此,您必须以某种方式迭代所有输入值
并计算新值.你可以做的是省略数组
创建:
let samples = sampleData.withUnsafeBytes { UnsafeBufferPointer<Int16>(start: $0,count: sampleData.count / MemoryLayout<Int16>.size) } return samples.map { Float($0) / Float(Int16.max) }
import Accelerate // ... let numSamples = sampleData.count / MemoryLayout<Int16>.size var factor = Float(Int16.max) var floats: [Float] = Array(repeating: 0.0,count: numSamples) // Int16 array to Float array: sampleData.withUnsafeBytes { vDSP_vflt16($0,1,&floats,vDSP_Length(numSamples)) } // Scaling: vDSP_vsdiv(&floats,&factor,vDSP_Length(numSamples))
我不知道这是否更快,你必须检查.
(更新:正如ColGraff在他的回答中所展示的那样更快.)
显式循环也比使用map快得多:
let factor = Float(Int16.max) let samples = sampleData.withUnsafeBytes { UnsafeBufferPointer<Int16>(start: $0,count: sampleData.count / MemoryLayout<Int16>.size) } var floats: [Float] = Array(repeating: 0.0,count: samples.count) for i in 0..<samples.count { floats[i] = Float(samples[i]) / factor } return floats
您的情况下的另一个选项可能是使用CMBlockBufferGetDataPointer()而不是CMBlockBuffercopyDataBytes()分配内存.