python - 为什么 Swift 中的 FFT 与 Python 中的不同?

标签 python swift signal-processing fft accelerate-framework

我正在尝试使用 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/

相关文章:

iphone - 使用 iPhone 识别 20-24 Hz 范围内的声音频率

matlab - 离散余弦变换一维Matlab

ios - Objective C : How to create self. 以编程方式在安全区域内查看

swift - 如何在 Swift 中使用 copyCGImageAtTime 从视频创建缩略图?

iphone - 如何获取iPhone的信号强度并在App Store中发布应用程序?

python - 网络爬虫在列表之间提取

arrays - 为什么在 swift4 中有一个数组为空和错误?

python - __builtin__.iterator 不存在?

python - Shodan.py 搜索在打印匹配列表时不打印完整的结果集

Python:获取默认网关的MAC地址