swift - 调用函数后释放类变量
问题描述
我在swift中有一个功能,如下所示。有一个引用存在于此类实例中的变量的循环。(fftfilterbankReal 是类中的一个数组)。但是,经过一次后,我在代码行“for i in 0..”处出现“索引超出范围”的错误。
在调试器中,似乎在此循环的第二次迭代中,“self”下拉列表下没有变量。
如果我注释掉 'vDSP_zvmul(&kernel!, 1, &fft1Input, 1, &result, 1, vDSP_Length(r.count), 1)' 行,则循环运行,我可以随时调试并直观地看到 self 变量调试器。
我错过了什么似乎使这些变量消失了?我已经阅读了内存分配等内容,并且我的类变量是使用 'var' 声明的,仅此而已,因为这在 swift 中应该默认为强。
func convolveInput(realsamples:[Float], imagsamples:[Float]) -> [Float]{
realResult = Array(repeating: [], count: filterbankReal.count)
imagResult = Array(repeating: [], count: filterbankReal.count)
let x = realsamples
let y = imagsamples
var N = x.count
var logN = 16
var fft1Setup = vDSP_create_fftsetup(UInt(logN), FFTRadix(FFT_RADIX2))!
var paddedLength = x.count + filterbankReal.count - 1
var halfPaddedLength = paddedLength/2
var halfKernelLength = kernelLength/2
//setup Complex Buffer 1
var reals = [Float]()
var imags = [Float]()
for i in 0..<x.count{
reals.append(x[i])
imags.append(y[i])
}
var complexBuffer1 = DSPSplitComplex(realp: UnsafeMutablePointer(mutating: reals), imagp: UnsafeMutablePointer(mutating: imags))
//Perform FFT on incoming samples
var re = [Float](repeating:0.0, count: N)
var im = [Float](repeating:0.0, count: N)
var fft1Input = DSPSplitComplex(realp: UnsafeMutablePointer(mutating: re), imagp: UnsafeMutablePointer(mutating: im))
var fftlength = 10
vDSP_fft_zop(fft1Setup, &(complexBuffer1), 1, &fft1Input, 1, UInt(fftlength), Int32(FFT_FORWARD))
//Remove DC from FFT Signal
re.remove(at: 0)
im.remove(at: 0)
for i in 0..<self.fftfilterbankReal.count {
var r:[Float] = self.fftfilterbankReal[i]
var im:[Float] = self.fftfilterbankImag[i]
var kernel:DSPSplitComplex? = DSPSplitComplex(realp: &r, imagp: &im)
var res:Float = 0
var ims:Float = 0
var result:DSPSplitComplex = DSPSplitComplex(realp: &res, imagp: &ims)
vDSP_zvmul(&kernel!, 1, &fft1Input, 1, &result, 1, vDSP_Length(r.count), 1)
self.realResult[i].append(res)
self.imagResult[i].append(ims)
}
解决方案
在使用数组和指针时,您的代码是一种不良用法的展示。
例如:
var complexBuffer1 = DSPSplitComplex(realp: UnsafeMutablePointer(mutating: reals), imagp: UnsafeMutablePointer(mutating: imags))
或者:
var kernel:DSPSplitComplex? = DSPSplitComplex(realp: &r, imagp: &im)
DSPSplitComplex
分别持有实部和虚部的两个指针,不复制内容。您不应该为此类参数传递 Swift 数组。
你的代码中最关键的部分是......
var res:Float = 0
var ims:Float = 0
var result:DSPSplitComplex = DSPSplitComplex(realp: &res, imagp: &ims)
vDSP_zvmul(&kernel!, 1, &fft1Input, 1, &result, 1, vDSP_Length(r.count), 1)
vDSP_zvmul
生成N
(在您的代码中N
= vDSP_Length(r.count)
)复数,因此您需要准备一个可以容纳N
元素的区域。
使用当前代码调用vDSP_zvmul
后,您会破坏整个堆栈内容,这会导致您所经历的:
在调试器中,似乎在此循环的第二次迭代中,“self”下拉列表下没有变量。
您隐藏了代码的许多部分,因此很难猜测您真正想要做什么,但是如果我以更安全的方式重新编写您的代码,它将是这样的:
func convolveInput(realsamples:[Float], imagsamples:[Float]) -> [Float]{
realResult = Array(repeating: [], count: filterbankReal.count)
imagResult = Array(repeating: [], count: filterbankReal.count)
let x = realsamples
let y = imagsamples
var N = x.count
var logN = 16
var fft1Setup = vDSP_create_fftsetup(UInt(logN), FFTRadix(FFT_RADIX2))!
var paddedLength = x.count + filterbankReal.count - 1
var halfPaddedLength = paddedLength/2
var halfKernelLength = kernelLength/2
//setup Complex Buffer 1
var reals = UnsafeMutableBufferPointer<Float>.allocate(capacity: x.count)
defer {reals.deallocate()}
var imags = UnsafeMutableBufferPointer<Float>.allocate(capacity: y.count)
defer {imags.deallocate()}
_ = reals.initialize(from: x)
_ = imags.initialize(from: y)
var complexBuffer1 = DSPSplitComplex(realp: reals.baseAddress!, imagp: imags.baseAddress!)
//Perform FFT on incoming samples
var re = UnsafeMutableBufferPointer<Float>.allocate(capacity: N)
defer {re.deallocate()}
var im = UnsafeMutableBufferPointer<Float>.allocate(capacity: N)
defer {im.deallocate()}
var fft1Input = DSPSplitComplex(realp: re.baseAddress!, imagp: im.baseAddress!)
let fftlength = 10
vDSP_fft_zop(fft1Setup, &complexBuffer1, 1, &fft1Input, 1, UInt(fftlength), Int32(FFT_FORWARD))
//Remove DC from FFT Signal
fft1Input = DSPSplitComplex(realp: re.baseAddress!+1, imagp: im.baseAddress!+1)
for i in 0..<self.fftfilterbankReal.count {
self.fftfilterbankReal[i].withUnsafeMutableBufferPointer {rBuf in
self.fftfilterbankImag[i].withUnsafeMutableBufferPointer {imBuf in
var kernel = DSPSplitComplex(realp: rBuf.baseAddress!, imagp: imBuf.baseAddress!)
var res = UnsafeMutableBufferPointer<Float>.allocate(capacity: rBuf.count)
defer {res.deallocate()}
var ims = UnsafeMutableBufferPointer<Float>.allocate(capacity: rBuf.count)
defer {ims.deallocate()}
var result:DSPSplitComplex = DSPSplitComplex(realp: res.baseAddress!, imagp: ims.baseAddress!)
vDSP_zvmul(&kernel, 1, &fft1Input, 1, &result, 1, vDSP_Length(rBuf.count), 1)
//vDSP_zvmul generates `N` complex numbers,
// I do not understand what you really want to do...
self.realResult[i].append(res[0])
self.imagResult[i].append(ims[0])
}
}
}
//...
}
可能还有其他部分需要修复,但无论如何,请尝试看看你得到了什么。
推荐阅读
- reactjs - 在 React Native 应用程序中与 mailchimp 集成
- url - URL 中的“tracking=1”是什么意思?
- canvas - 如何在javafx的画布中逐渐绘制形状
- java - 如何使用 itext ColumnText 添加 pdf 标题的下划线?我将线的宽度设置为 100%,但它不起作用
- javascript - 提交表单前确认多个提交按钮
- sql - 如何摆脱 sql 中已删除表的痕迹(在 cmd 上)?
- php - 我想根据 date_collected 手的条目数完全没有
- html - 如何将增加的边距大小添加到一行按钮?
- javascript - 为什么我必须推迟 customElement 定义?
- cassandra - 如何启用 Opscenter 设置和重新平衡选项卡?