Swift vDSP enum: FFT forward & inverse example

Hi,


1. I set up for a fast Fourier transform of a real [Double] time domain signal of count numSamples:


setupFFT = vDSP.FFT(
            log2n: vDSP_Length(log2(Float(numSamples))),
            radix: .radix2,
            ofType: DSPDoubleSplitComplex.self
        )

2. I take the forward transform and get 2 [Double] arrays for real & imaginary spectral parts, each of count (numSamples/2):


realParts.withUnsafeMutableBufferPointer { realPtr in
            imagParts.withUnsafeMutableBufferPointer { imagPtr in
                var complexSignal = DSPDoubleSplitComplex(realp: realPtr.baseAddress!,
                                                          imagp: imagPtr.baseAddress!)
                xData.withUnsafeBytes {
                    vDSP.convert(
                        interleavedComplexVector: [DSPDoubleComplex]($0.bindMemory(to: DSPDoubleComplex.self)),
                        toSplitComplexVector: &complexSignal
                    )
                }
                setupFFT?.transform(input: complexSignal, output: &complexSignal, direction: .forward)
            }
        }

3. Lastly I take the inverse transform of the complex spectrum. The part that's tricky is getting real time domain signal from the complex parts:


var outputData = [Double](repeating: 0.0, count: specSamples*2)
        realParts.withUnsafeMutableBufferPointer { realPtr in
            imagParts.withUnsafeMutableBufferPointer { imagPtr in
                var complexSignal = DSPDoubleSplitComplex(realp: realPtr.baseAddress!,
                                                          imagp: imagPtr.baseAddress!)
                setupFFT?.transform(input: complexSignal, output: &complexSignal, direction: .inverse)
                // How do we use the Swift vDSP convert the split complex spectrum with N/2 complex samples
                // to a real time domain signal with N real samples?
                // This is what I imagine although it's not proper Swift:
                outputData.withUnsafeMutableBytes { outputPtr in
                    vDSP.convert(splitComplexVector: complexSignal, toInterleavedComplexVector: outputPtr.baseAddress!.bindMemory(to: DSPDoubleComplex.self))
                }
            }
        }

Lines 10-12 do not compile, is there a proper casting and is this the best way to use the 2020 Swift vDSP enum? Thanks,


Paul

Replies

The doc says you need to pass an inout [DSPDoubleComplex] to the second argument.


static func convert(splitComplexVector: DSPDoubleSplitComplex, toInterleavedComplexVector: inout [DSPDoubleComplex])


var outputData = [DSPDoubleComplex](repeating: DSPDoubleComplex(real: 0, imag: 0), count: specSamples)
realParts.withUnsafeMutableBufferPointer { realPtr in
    imagParts.withUnsafeMutableBufferPointer { imagPtr in
        var complexSignal = DSPDoubleSplitComplex(realp: realPtr.baseAddress!,
                                                  imagp: imagPtr.baseAddress!)
        setupFFT?.transform(input: complexSignal, output: &complexSignal, direction: .inverse)
        vDSP.convert(splitComplexVector: complexSignal, toInterleavedComplexVector: &outputData)
    }
}