我正在尝试使用 Accelerate 框架将一些 python numpy 代码移植到 Swift。
我用python写
import numpy as np
frames = np.array([1.0, 2.0, 3.0, 4.0])
fftArray = np.fft.fft(frames, len(frames))
print(fftArray)
输出是:
[10.+0.j -2.+2.j -2.+0.j -2.-2.j]
所以在 Swift 中,我试图像这样计算 FFT:
import Foundation
import Accelerate
func fftAnalyzer(frameOfSamples: [Float]) {
// As above, frameOfSamples = [1.0, 2.0, 3.0, 4.0]
let analysisBuffer = frameOfSamples
let frameCount = frameOfSamples.count
var reals = [Float]()
var imags = [Float]()
for (idx, element) in analysisBuffer.enumerated() {
if idx % 2 == 0 {
reals.append(element)
} else {
imags.append(element)
}
}
var complexBuffer = DSPSplitComplex(realp: UnsafeMutablePointer(mutating: reals), imagp: UnsafeMutablePointer(mutating: imags))
let log2Size = Int(log2f(Float(frameCount)))
guard let fftSetup = vDSP_create_fftsetup(vDSP_Length(log2Size), Int32(kFFTRadix2)) else {
return []
}
// Perform a forward FFT
vDSP_fft_zrip(fftSetup, &(complexBuffer), 1, UInt(log2Size), Int32(FFT_FORWARD))
let realFloats = Array(UnsafeBufferPointer(start: complexBuffer.realp, count: Int(frameCount)))
let imaginaryFloats = Array(UnsafeBufferPointer(start: complexBuffer.imagp, count: Int(frameCount)))
print(realFloats)
print(imaginaryFloats)
// Release the setup
vDSP_destroy_fftsetup(fftSetup)
return realFloats
}
realFloats 和 imaginaryFloats 打印如下:
[20.0, -4.0, 0.0, 0.0]
[-4.0, 4.0, 0.0, 0.0]
关于我应该采取哪些不同的做法有什么想法吗?
最佳答案
我不擅长 numpy,但根据 the doc , fft
接受复数输入。那么它的等效项将是 vDSP_fft_zip
,而不是 vDSP_fft_zrip
。
并且您的代码导致缓冲区溢出或可能导致悬空指针,所有这些问题都已修复,我明白了:
func fftAnalyzer(frameOfSamples: [Float]) -> [Float] {
// As above, frameOfSamples = [1.0, 2.0, 3.0, 4.0]
let frameCount = frameOfSamples.count
let reals = UnsafeMutableBufferPointer<Float>.allocate(capacity: frameCount)
defer {reals.deallocate()}
let imags = UnsafeMutableBufferPointer<Float>.allocate(capacity: frameCount)
defer {imags.deallocate()}
_ = reals.initialize(from: frameOfSamples)
imags.initialize(repeating: 0.0)
var complexBuffer = DSPSplitComplex(realp: reals.baseAddress!, imagp: imags.baseAddress!)
let log2Size = Int(log2(Float(frameCount)))
print(log2Size)
guard let fftSetup = vDSP_create_fftsetup(vDSP_Length(log2Size), FFTRadix(kFFTRadix2)) else {
return []
}
defer {vDSP_destroy_fftsetup(fftSetup)}
// Perform a forward FFT
vDSP_fft_zip(fftSetup, &complexBuffer, 1, vDSP_Length(log2Size), FFTDirection(FFT_FORWARD))
let realFloats = Array(reals)
let imaginaryFloats = Array(imags)
print(realFloats)
print(imaginaryFloats)
return realFloats
}
打印
[10.0, -2.0, -2.0, -2.0] [0.0, 2.0, 0.0, -2.0]
关于python - 为什么 Swift 中的 FFT 与 Python 中的不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51804365/