此代码导致内存泄漏和应用程序崩溃:
var outputSamples = [Float]()
assetReader.startReading()
while assetReader.status == .reading {
let trackOutput = assetReader.outputs.first!
if let sampleBuffer = trackOutput.copyNextSampleBuffer(),
let blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer) {
let blockBufferLength = CMBlockBufferGetDataLength(blockBuffer)
let sampleLength = CMSampleBufferGetNumSamples(sampleBuffer) * channelCount(from: assetReader)
var data = Data(capacity: blockBufferLength)
data.withUnsafeMutableBytes { (blockSamples: UnsafeMutablePointer<Int16>) in
CMBlockBufferCopyDataBytes(blockBuffer, atOffset: 0, dataLength: blockBufferLength, destination: blockSamples)
CMSampleBufferInvalidate(sampleBuffer)
let processedSamples = process(blockSamples,
ofLength: sampleLength,
from: assetReader,
downsampledTo: targetSampleCount)
outputSamples += processedSamples
}
}
}
var paddedSamples = [Float](repeating: silenceDbThreshold, count: targetSampleCount)
paddedSamples.replaceSubrange(0..<min(targetSampleCount, outputSamples.count), with: outputSamples)
这是由于copyNextSampleBuffer()和The Create Rule。
反过来,我们不能在Swift中使用CFRelease()。我之所以理解为什么只链接到Objective-C规则的原因。
有没有办法在Swift中手动释放CMSampleBuffer?
这不是一个真正的解决方案,因为看起来手动释放内存是不可能的,并且当读取不安全的可变字节时,使用while循环与assetReader结果导致内存不被释放。
该问题通过一种解决方法解决:将音频文件转换为CAF格式,然后将其暴露给while循环。
缺点:它需要一秒钟,音频文件越长 - 花费的时间就越多。
好处:它只使用了极少量的内存,这首先是问题所在。
灵感来自:https://stackoverflow.com/users/2907715/carpsen90在Extract meter levels from audio file回答