gpt4 book ai didi

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

转载 作者:搜寻专家 更新时间:2023-10-31 08:19:42 25 4
gpt4 key购买 nike

我目前正在处理音频样本。我从 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, 0, length, sampleBytes)

sampleData.append(sampleBytes, count: length)
}

如您所见,我发现转换 [Int16] -> [Float] 的唯一方法是 samples.map { Float($0)/Float(Int16.max) 但是通过这样做我的处理时间在增加。是否存在将 Int16 指针转换为 Float 指针的其他方法?

最佳答案

“转换”或“重新绑定(bind)”指针只会改变内存的方式解释。您想从整数计算浮点值,新值有不同的内存表示(也有不同的尺寸)。

因此,您必须以某种方式遍历所有输入值并计算新值。您可以做的是省略 Array创建:

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, 1, vDSP_Length(numSamples))
}
// Scaling:
vDSP_vsdiv(&floats, 1, &factor, &floats, 1, 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()进入分配的内存。

关于swift - 如何将 Int16 音频样本数据转换为浮点音频样本数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45863240/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com