In Swift 4 I'm creating a DSPSplitComplex to use in vDSP_fft_zip(), but it's being immediately overwritten the next time I create another DSPSplitComplex.
( DSPSplitComplex structure has 2 UnsafeMutablePointer<Float>
)
//--Create the DSPSplitComplex
var A = [Float](repeating:0, count:32);
var B = [Float](repeating:0, count:32)
var splitComplex1 = DSPSplitComplex(realp: &A, imagp: &B)
//--Perform fft
log2Size = vDSP_Length(log2f(Float(32)))
setupFFT = vDSP_create_fftsetup(log2Size, FFTRadix(FFT_RADIX2))!;
vDSP_fft_zip(setupFFT, & splitComplex1, 1, log2Size, FFTDirection(FFT_FORWARD));
//--Create another DSPSplitComplex
var C = [Float](repeating:0, count:32);
var D = [Float](repeating:0, count:32)
var splitComplex2 = DSPSplitComplex(realp: &C, imagp: &D)
I can now see in the debugger that the UnsafeMutablePointer of splitComplex2.realp
is the same address as splitComplex1.realp
, and consequently anything I do with splitComplex2 overwrites splitComplex1
I guess the clue might be in the title 'unsafe', but if it's actually unusable, then what is the correct strategy for storing the contents of the returned DSPSplitComplex?
I guess creating new [Float] arrays from them is a way to make a permanent copy
let arrary = Array(UnsafeBufferPointer(start: splitComplex1.realp, count: 32))
...but it seems, despite reading the Swift docs, I'm still misunderstanding the point of UnsafeMutablePointer, as why would vDSP_fft_zip() return something that is unusable from the get-go?
Your way of creating DSPSplitComplex
is wrong.
When you pass Array<Float>
to UnsafeMutablePointer<Float>
using &
, the address passed to the function is only valid within the function.
So, in your code, two addresses passed DSPSplitComplex(realp: &A, imagp: &B)
are not valid when the initializer of DSPSplitComplex
finished.
To avoid this sort of behavior, you can try something like this:
var A = [Float](repeating:0, count:32)
var B = [Float](repeating:0, count:32)
A.withUnsafeMutableBufferPointer {aumbp in
B.withUnsafeMutableBufferPointer {bumbp in
var splitComplex1 = DSPSplitComplex(realp: aumbp.baseAddress!, imagp: bumbp.baseAddress!)
//--Perform fft
let log2Size = vDSP_Length(log2f(Float(32)))
let setupFFT = vDSP_create_fftsetup(log2Size, FFTRadix(FFT_RADIX2))!
vDSP_fft_zip(setupFFT, &splitComplex1, 1, log2Size, FFTDirection(FFT_FORWARD))
}
}
Or else, you can allocate UnsafeMutableBufferPointer<Float>
s and use them instead of Array<Float>
.