Last active
October 15, 2015 16:08
-
-
Save rnapier/399676bd389c270e7b66 to your computer and use it in GitHub Desktop.
FFT in Swift (protecting against deallocation)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// FFT.swift | |
// Signal | |
// | |
// Created by Rob Napier on 7/24/14. | |
// Copyright (c) 2014 Rob Napier. All rights reserved. | |
// | |
import Accelerate | |
internal func spectrumForValues(signal: [Double]) -> [Double] { | |
// Find the largest power of two in our samples | |
let log2N = vDSP_Length(log2(Double(signal.count))) | |
let n = 1 << log2N | |
let fftLength = n / 2 | |
// This is expensive; factor it out if you need to call this function a lot | |
let fftsetup = create_fftsetupD(log2N, FFTRadix(kFFTRadix2)) | |
var fft = [Double](count:Int(n), repeatedValue:0.0) | |
// Generate a split complex vector from the real data | |
var realp = [Double](count:Int(fftLength), repeatedValue:0.0) | |
var imagp = realp | |
withExtendedLifetimes(realp, imagp) { | |
var splitComplex = DSPDoubleSplitComplex(realp:&realp, imagp:&imagp) | |
ctozD(ConstUnsafePointer(signal), 2, &splitComplex, 1, fftLength) | |
// Take the fft | |
fft_zripD(fftsetup, &splitComplex, 1, log2N, FFTDirection(kFFTDirection_Forward)) | |
// Normalize | |
var normFactor = 1.0 / Double(2 * n) | |
vsmulD(splitComplex.realp, 1, &normFactor, splitComplex.realp, 1, fftLength) | |
vsmulD(splitComplex.imagp, 1, &normFactor, splitComplex.imagp, 1, fftLength) | |
// Zero out Nyquist | |
splitComplex.imagp[0] = 0.0 | |
// Convert complex FFT to magnitude | |
vDSP_zvmagsD(&splitComplex, 1, &fft, 1, fftLength) | |
} | |
// Cleanup | |
destroy_fftsetupD(fftsetup) | |
return fft | |
} | |
// To get rid of the `() -> () in` casting | |
func withExtendedLifetime<T>(x: T, f: () -> ()) { | |
return Swift.withExtendedLifetime(x, f) | |
} | |
// In the spirit of withUnsafePointers | |
func withExtendedLifetimes<A0, A1>(arg0: A0, arg1: A1, f: () -> ()) { | |
return withExtendedLifetime(arg0) { withExtendedLifetime(arg1, f) } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment