1

How can I convert the following pointers initialization from Swift 2 to Swift 3?

var values: [Double] ... var valuesAsComplex : UnsafeMutablePointer<DSPDoubleComplex>? values.withUnsafeBufferPointer { (resultPointer: UnsafeBufferPointer<Double>) -> Void in valuesAsComplex = UnsafeMutablePointer<DSPDoubleComplex>( resultPointer.baseAddress ) } 

Update: Thank your for all the answers. Permanently rebinding the pointer as @Aderstedt suggests works but returning the result doesn't. Any ideas?

// Create result var result = [Double](repeating: 0.0, count: N/2) var resultAsComplex : UnsafeMutablePointer<DSPDoubleComplex>? result.withUnsafeMutableBytes { resultAsComplex = $0.baseAddress?.bindMemory(to: DSPDoubleComplex.self, capacity: result.count) } // Do complex->real inverse FFT. vDSP_fft_zripD(fftSetup!, &tempSplitComplex, 1, LOG_N, FFTDirection(FFT_INVERSE)); // This leaves result in packed format. Here we unpack it into a real vector. vDSP_ztocD(&tempSplitComplex, 1, resultAsComplex!, 2, N2); // Neither the forward nor inverse FFT does any scaling. Here we compensate for that. var scale : Double = 0.5/Double(N); vDSP_vsmulD(&result, 1, &scale, &result, 1, vDSP_Length(N)); return result 
7
  • Can you provide a self-contained example demonstrating the problem? With input, output and expected output? Commented Feb 22, 2017 at 21:21
  • Thank you @martin-r !!! I want to create a heart rate monitor using the iOS camera. I'm reading images from the back camera at 30fps and storing the average hue from the image in an array and in order to remove noise I want to create a bandpass filter using FFT and the Accelerate framework. I shared my code in github github.com/codifilo/camera-heart-rate/blob/master/… Commented Feb 23, 2017 at 5:30
  • What exactly does not work? – Please note that questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See also: How to create a minimal reproducible example. Commented Feb 23, 2017 at 6:50
  • I'm sorry, you're right @martin-r. I created an example with the shortest code necessary to reproduce the issue. Running the following example it crashes sometimes with a message " malloc: *** error for object 0x101011a00: incorrect checksum for freed object - object was probably modified after being freed." in the File FFT.swift line 131 The sample just tries to compute the FFT transform of an array and it returns the same values but with some frequencies filtered. The project is here. github.com/codifilo/fft-example/blob/master/FFTExample/… Commented Feb 23, 2017 at 7:40
  • I see only a FFT class with several methods in that repository. Where is the code that I have to run to reproduce the problem? Commented Feb 23, 2017 at 7:48

1 Answer 1

1

You have to "rebind" the pointer:

values.withUnsafeMutableBufferPointer { $0.baseAddress!.withMemoryRebound(to: DSPDoubleComplex.self, capacity: values.count/2) { valuesAsComplex in // ... } } 

Inside the closure valuesAsComplex is a UnsafeMutablePointer<DSPDoubleComplex> and can be passed to DSP functions.

You must not pass the pointer to the element storage to the outside of the closure as the documentation clearly states:

The pointer argument is valid only for the duration of the closure’s execution.

That may work by chance, but there is no guarantee that after the execution of the closure, the elements storage is still at the same memory address (or that the array even exists, since the pointer is not a strong reference which ensures the lifetime of the storage).


In your case that would be

 tempSplitComplex = DSPDoubleSplitComplex(realp: &mag, imagp: &phase) vDSP_ztocD(&tempSplitComplex, 1, &tempComplex, 2, N2); tempComplex.withUnsafeMutableBufferPointer { $0.baseAddress!.withMemoryRebound(to: Double.self, capacity: values.count * 2) { complexAsDouble in vDSP_rectD(complexAsDouble, 2, complexAsDouble, 2, N2); } } vDSP_ctozD(&tempComplex, 2, &tempSplitComplex, 1, N2); 

and

 var result = [Double](repeating: 0.0, count: N/2) result.withUnsafeMutableBufferPointer { $0.baseAddress!.withMemoryRebound(to: DSPDoubleComplex.self, capacity: result.count/2) { resultAsComplex in vDSP_ztocD(&tempSplitComplex, 1, resultAsComplex, 2, N2); } } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.