根据其他用户的评论,我整理了我的代码并将其压缩成可读的。我有一个complexFloatArray类,用来存储复杂向量的数组

class complexFloatArray {
    var reals: [Float]
    var imaginaries: [Float]

    init(reals: [Float], imaginaries: [Float]){
    self.reals = reals
    self.imaginaries = imaginaries
    }
}

然后我在这个类的扩展中定义了一些函数。一是:
func useAsDSPSplitComplex<R>(_ closure: (inout DSPSplitComplex) -> R) -> R {
    return reals.withUnsafeMutableBufferPointer { realBufferPointer in
        return imaginaries.withUnsafeMutableBufferPointer { imaginaryBufferPointer in
            var dspSplitComplex = DSPSplitComplex(realp: realBufferPointer.baseAddress!, imagp: imaginaryBufferPointer.baseAddress!)
            return closure(&dspSplitComplex)
        }
    }
}

其思想是,当对complexFloatArray的实例调用时,它会创建一个DSPSplitComplex指针,用于Accelerate框架。
最后,我有一个加速函数,我想用它(vDSP_zrvmul)把复数向量乘以实向量。
func floatMultiply(with other: [Float]) -> complexFloatArray {
    assert(self.count == other.count, "Multiplied Vectors Must have the same size!")

    var result = complexFloatArray.zeros(count: other.count)

    self.useAsDSPSplitComplex { selfPointer in
        result.useAsDSPSplitComplex { resultPointer in
            vDSP_zrvmul(
                &selfPointer, complexFloatArray.stride,
                other, complexFloatArray.stride,
                &resultPointer, complexFloatArray.stride,
                vDSP_Length(result.count))
        }

    }

    return result
}

我使用以下方法调用函数:
var kernel = sine.floatMultiply(with: gauss)

其中sine是一个复数的loatarray,gauss是一个FloatArray,两者的长度都相等以创建morlet小波。然而,结果是一个充满零的complexFloatArray。
调试时,我可以在floatMultiply函数的任意点设置断点,并确认self和other(sine和gauss)都填充了vales。所以vDSP调用中的某个地方没有返回正确的结果。
对于完整性complexFloatArray.stride=1(该值在complexFloatArray类中声明)。
“zeros”是complexFloatArray中的一个函数,用于用一定长度的零填充数组。(数组(重复:0,计数:N)
有什么建议可以解释为什么这次电话的结果是零吗?
我现在已经包含了完整的代码,而不是给出不完整图片的片段。
ComplexFloatArray类的完整代码如下:
class ComplexFloatArray {
    var reals: [Float]
    var imaginaries: [Float]

    init(reals: [Float], imaginaries: [Float]){
    self.reals = reals
    self.imaginaries = imaginaries
    }
}

extension ComplexFloatArray {
    var count: Int {
    assert(reals.count == imaginaries.count)
    return reals.count
    }

    static let stride = 1

    func append(real: Float, imaginary: Float) {
        self.reals.append(real)
        self.imaginaries.append(imaginary)
    }

    func removeAtIndex(index: Int) {
        self.reals.remove(at: index)
        self.imaginaries.remove(at: index)
    }

    func useAsDSPSplitComplex<R>(_ closure: (inout DSPSplitComplex) -> R) -> R {
    return reals.withUnsafeMutableBufferPointer { realBufferPointer in
        return imaginaries.withUnsafeMutableBufferPointer { imaginaryBufferPointer in
            var dspSplitComplex = DSPSplitComplex(realp: realBufferPointer.baseAddress!, imagp: imaginaryBufferPointer.baseAddress!)
            return closure(&dspSplitComplex)
            }
        }
    }
}

extension ComplexFloatArray {
    convenience init() {
        self.init(reals:[], imaginaries:[])
    }

static func zeros(count: Int) -> ComplexFloatArray {
    return ComplexFloatArray(reals:Array(repeating: 0, count: count), imaginaries: Array(repeating:0, count:count))
    }
}

extension ComplexFloatArray {
    enum ComplexMultiplicationType: Int32 { case normal = 1, conjugate = -1}

    func ComplexMultiply(
        with other: ComplexFloatArray,
        multiplicationType: ComplexMultiplicationType = .normal
    ) -> ComplexFloatArray {
        assert(self.count == other.count, "Multiplied Vectors Must have the same size!")

        var result = ComplexFloatArray.zeros(count: self.count)

        self.useAsDSPSplitComplex { selfPointer in
            other.useAsDSPSplitComplex { otherPointer in
                result.useAsDSPSplitComplex { resultPointer in
                    vDSP_zvmul(
                    &selfPointer, ComplexFloatArray.stride,
                    &otherPointer, ComplexFloatArray.stride,
                    &resultPointer, ComplexFloatArray.stride,
                    vDSP_Length(result.count),
                    multiplicationType.rawValue)
                }
            }
        }

        return result
    }
}


extension ComplexFloatArray {

    func floatMultiply(
        with other: [Float]
        ) -> ComplexFloatArray {
        assert(self.count == other.count, "Multiplied Vectors Must have the same size!")

        var result = ComplexFloatArray.zeros(count: other.count)

        self.useAsDSPSplitComplex { selfPointer in
            result.useAsDSPSplitComplex { resultPointer in
                vDSP_zrvmul(
                    &selfPointer, ComplexFloatArray.stride,
                    other, ComplexFloatArray.stride,
                    &resultPointer, ComplexFloatArray.stride,
                    vDSP_Length(result.count))
            }
         }

        return result
    }
 }

extension ComplexFloatArray {
enum FourierTransformDirection: Int32  { case forward = 1, inverse = -1 }

    func outOfPlaceComplexFourierTransform(
        setup: FFTSetup,
        resultSize:Int,
        logSize: UInt,
        direction: FourierTransformDirection) -> ComplexFloatArray {

        var result = ComplexFloatArray.zeros(count:resultSize)

        self.useAsDSPSplitComplex { selfPointer in
            result.useAsDSPSplitComplex { resultPointer in
                vDSP_fft_zop(
                setup,
                &selfPointer,
                ComplexFloatArray.stride,
                &resultPointer,
                ComplexFloatArray.stride,
                logSize,
                direction.rawValue)
            }
        }
        return result
    }
}

我的CWT类的完整代码如下:
var nVoices = 96            //number of voices per octave
var kernelLength = 2048     //Length of N
var fs = globalSampleRate


class CWT{

    var timeArray:[Float] = []
    var sines: [ComplexFloatArray] = []
    var gaussian:[[Float]] = []
    var fftFilterBank:[ComplexFloatArray] = []
    var filterBank:[ComplexFloatArray] = []
    var convProduct:[ComplexFloatArray] = []
    var centreFreqs:[Float]=[]
    var phase:[Float] = []
    var magnitude:[Float] = []


    func synthesizeKernels(){

        timeArray = makeArray(from: ((1.0/Float(fs))*((-0.5)*Float(kernelLength))), to: ((1.0/Float(fs))*((0.5)*Float(kernelLength))), increment: 1/fs)

         centreFreqs = getCentreFreqs(N:timeArray.count)

         for i in 0..<centreFreqs.count {
            makeSine(freq: centreFreqs[i], N:timeArray.count, iteration: i)
            makeGaus(freq: centreFreqs[i], N:timeArray.count, iteration: i)
            makeMorlet(sine: sines[i], gauss: gaussian[i], count:timeArray.count, iteration: i)
            fftKernel(kernel: filterBank[i], N:timeArray.count, iteration:i)
        }
    }



    func convolveSignal(realSamples:[Float], imagSamples:[Float]) {

        let logN = 11
        let fft1Setup = vDSP_create_fftsetup(UInt(logN), FFTRadix(FFT_RADIX2))!
        var product = ComplexFloatArray.zeros(count: filterBank.count)
        var input = ComplexFloatArray(reals: realSamples, imaginaries: imagSamples)
        var fftOfSamples = ComplexFloatArray.zeros(count: input.count)
        fftOfSamples = input.outOfPlaceComplexFourierTransform(setup: fft1Setup, resultSize: input.count, logSize: UInt(logN), direction: ComplexFloatArray.FourierTransformDirection(rawValue: 1)!)

        fftOfSamples.removeAtIndex(index: 0)


        for i in 0..<self.filterBank.count {
            var kernel = fftFilterBank[i]
            var multiplyResult = kernel.ComplexMultiply(with: fftOfSamples)
            convProduct.append(multiplyResult)
        }
   }



    //HELPER FUNCTION FOR TIME ARRAY
    func makeArray(from:Float, to:Float, increment:Float) ->[Float]{
        var Array:[Float]=[]
        for i in stride(from: from, to: to, by: increment) {
            Array.append(i)
        }
        return Array
    }


    //MAKE COMPLEX SINE WAVE
    func makeSine(freq:Float, N:Int, iteration:Int) {
        var compSine = ComplexFloatArray.init()
        for i in 0..<timeArray.count{
            let x = 2 * Float.pi * freq * timeArray[i]
            compSine.append(real: cos(x), imaginary: sin(x))
        }
        sines.append(compSine)
    }



    //MAKE GAUSSIAN WINDOW
    func makeGaus(freq:Float, N:Int, iteration:Int) {
        var gaus:[Float] = Array(repeating:0, count:N)
        let s:Float = 7 / (2.0 * Float.pi * freq)
        let interimCalc: Float = Float(2)*Float(pow(s,2))
        for i in 0..<N{
            var u = pow(timeArray[i],2)
            u = (-u)
            let v = u / interimCalc
            gaus[i] = exp(v)
        }
        gaussian.append(gaus)

    }


    //CREATE CENTRE FREQUENCIES
    func getCentreFreqs(N:Int) ->[Float]{
        var CF:[Float] = []
        var filteredCF:[Float] = []
        var G:Float = pow(10,(3/10))
        var x = makeArray(from: -1000, to: 1350, increment: 1)

        for i in 0..<x.count {
            var fraction:Float = (Float(2*Float(x[i]))-Float(59.0)) / Float(2*nVoices)
            var fr:Float = Float(1000.0) * Float(powf(Float(G), Float(fraction)))
            CF.append(fr)
        }

        for i in 0..<CF.count {
            if (Float(20) < CF[i] && CF[i] < Float(20000))  {
                filteredCF.append(CF[i])
            }
        }
        return filteredCF
    }


    //MAKE COMPLEX MORLET WAVELET
    func makeMorlet(sine:ComplexFloatArray, gauss:[Float], count:Int, iteration:Int) {
        var kernel = sine.floatMultiply(with: gauss)
        filterBank.append(kernel)
    }


    //PERFORM FFT ON KERNEL
    func fftKernel(kernel: ComplexFloatArray, N:Int, iteration:Int) {
        var size = kernel.count
        var logSize = 11
        var FFTSetup = vDSP_create_fftsetup(vDSP_Length(logSize), FFTRadix(FFT_RADIX2))
        var output = kernel.outOfPlaceComplexFourierTransform(setup: FFTSetup!, resultSize: size, logSize: UInt(logSize), direction: ComplexFloatArray.FourierTransformDirection(rawValue: 1)!)
        output.removeAtIndex(index:0)
        fftFilterBank.append(output)

    }


    //Test Signal to Convolve - 1kHz Sine Wave
    func testSine(){
        var testTimeArray = makeArray(from: ((1.0/Float(fs))*((-0.5)*Float(kernelLength))), to: ((1.0/Float(fs))*((0.5)*Float(kernelLength))), increment: 1/fs)
        var testSine = ComplexFloatArray.zeros(count: testTimeArray.count)

        for i in 0..<testTimeArray.count{
            var x = 2 * Float.pi * 1000 * testTimeArray[i]
            testSine.reals[i] = cos(x)
            testSine.imaginaries[i] = sin(x)
        }
        convolveSignal(realSamples: testSine.reals, imagSamples:testSine.imaginaries)

    }
}

最后,在我的ViewController类中,我有以下内容:
class ViewController: UIViewController {

    var wavelet = CWT()

    func viewDidLoad(){
        wavelet.synthesizeKernels()
        wavelet.testSine()
    }
}

如果我调试这个并在makeMorlet函数上暂停,那么FloatMultiply的结果都是零,尽管在等式的左侧和右侧都有相同的长度值。

最佳答案

不幸的是,您的代码不能在默认设置的Xcode 10.2上运行。
线程1:同时访问0x600001170550,但修改需要独占访问
我不确定您是否将对内存的独占访问设置为关闭(仅限编译时强制),或者使用某些较旧版本的Xcode,但是Swift编译器会优化并生成代码,前提是独占强制完全有效。(因此,永远不要将对内存的独占访问设置为关闭。)
请仔细阅读本文:
Swift 5 Exclusivity Enforcement
您在count中执行ComplexFloatArray违反了此强制执行。在执行传递给reals.withUnsafeMutableBufferPointer的闭包时,不能访问reals,因为数组被该方法独占占用。
如果违反此规则,Swift运行时可能会显示任何类型的意外行为。
尝试更改count的实现,如下所示,并查看发生了什么:

class ComplexFloatArray {
    var reals: [Float]
    var imaginaries: [Float]

    init(reals: [Float], imaginaries: [Float]){
        self.reals = reals
        self.imaginaries = imaginaries

        assert(reals.count == imaginaries.count)
        self.count = reals.count
    }

    //Make `count` a stored property.
    var count: Int
}

extension ComplexFloatArray {
    //Remove this computed property.
//    var count: Int {
//        assert(reals.count == imaginaries.count)
//        return reals.count
//    }

    static let stride = 1

    func append(real: Float, imaginary: Float) {
        self.reals.append(real)
        self.imaginaries.append(imaginary)

        count += 1
    }

    func removeAtIndex(index: Int) {
        self.reals.remove(at: index)
        self.imaginaries.remove(at: index)

        count -= 1
    }

    //...
}

另外,您的代码使用建议的设置生成许多警告,您最好不要忽略它们。

09-04 16:09