swift – 如何将Int16音频样本的数据转换为浮点音频样本数组

我目前正在处理音频样本.
我从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) }

一个选择是使用来自的vDSP函数
加速框架:

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()分配内存.

相关文章

软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘...
现实生活中,我们听到的声音都是时间连续的,我们称为这种信...
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿...
【Android App】实战项目之仿抖音的短视频分享App(附源码和...
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至...
因为我既对接过session、cookie,也对接过JWT,今年因为工作...