使用 getter 时 UnsafeMutableBufferPointer 变慢
UnsafeMutableBufferPointer slow when using getter
我有一个带有自定义 AURenderCallback 的 AVAudioEngine。当我 运行 引擎时,cpu 出现尖峰,这似乎与 UnsafeMutableBufferPointer.getter 和 .setter 动作有关:
func performRender(ioActionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>, inTimeStamp: UnsafePointer<AudioTimeStamp>, inBusNumber: UInt32, inNumberFrames: UInt32, ioData: UnsafeMutablePointer<AudioBufferList>?) -> OSStatus {
let blI = UnsafeMutableAudioBufferListPointer(ioData)
let numSamples = Int((blI?[0].mDataByteSize)! / UInt32(MemoryLayout<Float32>.stride))
for input in 0 ..< blI!.count{
let bI = blI?[input]
guard let inputData = bI?.mData else {
//assert(false)
return kAudioUnitErr_Uninitialized
}
let samplesBI = UnsafeMutablePointer<Float32>(inputData.assumingMemoryBound(to: Float32.self))
let samplesI = UnsafeMutableBufferPointer<Float32>(start: samplesBI, count: numSamples)
for sampleIndex in 0 ..< samplesI.count {
samplesI[sampleIndex] *= 0.5
}
}
return noErr
}
什么会导致这种获取和设置指针数据的低效行为?由于它处理的是音频样本,因此效率低下会导致音频信号出现断断续续的情况。
可以跳过UnsafeMutableBufferPointer()调用,直接索引样本指针:
let bufferListPtr = UnsafeMutableAudioBufferListPointer(ioData)
...
let mBuffer : AudioBuffer = bufferListPtr[0]
let count = Int(mBuffer.mDataByteSize) / yourSampleSizeInBytes
let dataPointer = UnsafeMutableRawPointer(mBuffer.mData)
if let dptr = dataPointer {
let sampleArray = dptr.assumingMemoryBound(to: yourSampleType.self)
for i in 0..<(count) {
let x = sampleArray[i]
let y = myModifySample( x )
sampleArray[i] = y
}
}
我将 Int16 用于 mySampleType(大小 = 2 字节),但它也适用于 4 字节类型的 Float。
直接使用原始内存指针可能会避免一些缓冲区getter/setter效率低下(以及验证,所以要小心!)。
我有一个带有自定义 AURenderCallback 的 AVAudioEngine。当我 运行 引擎时,cpu 出现尖峰,这似乎与 UnsafeMutableBufferPointer.getter 和 .setter 动作有关:
func performRender(ioActionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>, inTimeStamp: UnsafePointer<AudioTimeStamp>, inBusNumber: UInt32, inNumberFrames: UInt32, ioData: UnsafeMutablePointer<AudioBufferList>?) -> OSStatus {
let blI = UnsafeMutableAudioBufferListPointer(ioData)
let numSamples = Int((blI?[0].mDataByteSize)! / UInt32(MemoryLayout<Float32>.stride))
for input in 0 ..< blI!.count{
let bI = blI?[input]
guard let inputData = bI?.mData else {
//assert(false)
return kAudioUnitErr_Uninitialized
}
let samplesBI = UnsafeMutablePointer<Float32>(inputData.assumingMemoryBound(to: Float32.self))
let samplesI = UnsafeMutableBufferPointer<Float32>(start: samplesBI, count: numSamples)
for sampleIndex in 0 ..< samplesI.count {
samplesI[sampleIndex] *= 0.5
}
}
return noErr
}
什么会导致这种获取和设置指针数据的低效行为?由于它处理的是音频样本,因此效率低下会导致音频信号出现断断续续的情况。
可以跳过UnsafeMutableBufferPointer()调用,直接索引样本指针:
let bufferListPtr = UnsafeMutableAudioBufferListPointer(ioData)
...
let mBuffer : AudioBuffer = bufferListPtr[0]
let count = Int(mBuffer.mDataByteSize) / yourSampleSizeInBytes
let dataPointer = UnsafeMutableRawPointer(mBuffer.mData)
if let dptr = dataPointer {
let sampleArray = dptr.assumingMemoryBound(to: yourSampleType.self)
for i in 0..<(count) {
let x = sampleArray[i]
let y = myModifySample( x )
sampleArray[i] = y
}
}
我将 Int16 用于 mySampleType(大小 = 2 字节),但它也适用于 4 字节类型的 Float。
直接使用原始内存指针可能会避免一些缓冲区getter/setter效率低下(以及验证,所以要小心!)。