FFT计算错误-Swift [英] FFT Calculating incorrectly - Swift

查看:71
本文介绍了FFT计算错误-Swift的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试进行快速的快速傅立叶变换.我的计算基于.当我采用相同的语气并使用python时,我得到的东西看起来更正确.python代码如下:

I am trying to take the fast Fast Fourier Transform. I am basing my calculation off of the . When i take the same tone and use python I get something that looks way more correct. The python code looks like:

import numpy as np
import scipy.io.wavfile
import numpy.fft
import matplotlib.pyplot as plt

FILENAME = 'beep.wav'

fs, data = scipy.io.wavfile.read(FILENAME)
data = data[:801]
spacing = 1 / float(fs)
freq = numpy.fft.rfft(data)
freq_power = np.abs(freq)
a = 1 / (2 * spacing)
b = (len(data) + 1) // 2
freq_axis = np.linspace(0, a, b)
plt.plot(freq_axis, freq_power)
plt.show()

快速代码如下

import Accelerate
public func sqrt(x: [Float]) -> [Float] {
var results = [Float](count: x.count, repeatedValue: 0.0)
vvsqrtf(&results, x, [Int32(x.count)])

return results
}

public func fft(input: [Float]) -> [Float] {
var real = [Float](input)
var imaginary = [Float](count: input.count, repeatedValue: 0.0)
var splitComplex = DSPSplitComplex(realp: &real, imagp: &imaginary)

let length = vDSP_Length(floor(log2(Float(input.count))))
let radix = FFTRadix(kFFTRadix2)
let weights = vDSP_create_fftsetup(length, radix)
println(weights)
vDSP_fft_zip(weights, &splitComplex, 1, 8, FFTDirection(FFT_FORWARD))

var magnitudes = [Float](count: input.count, repeatedValue: 0.0)
vDSP_zvmags(&splitComplex, 1, &magnitudes, 1, vDSP_Length(input.count))

var normalizedMagnitudes = [Float](count: input.count, repeatedValue: 0.0)
vDSP_vsmul(sqrt(magnitudes), 1, [2.0 / Float(input.count)], &normalizedMagnitudes, 1, vDSP_Length(input.count))
vDSP_destroy_fftsetup(weights)

return normalizedMagnitudes
}

重申.快速代码是给出意外结果的代码.我在做什么错了?

To reiterate. The swift code is the code giving unexpected results. What am I doing wrong?

推荐答案

您似乎正在将Swift Float数组与Accelerate框架一起使用,但您可能需要使用 UnsafeMutablePointer< Float> 分配向量code>类型,因为Accelerate框架是一个Objective C框架.这是一个如何执行此操作的示例.

It looks like you are using Swift Float arrays with the Accelerate framework, but you might instead need to allocate your vectors using UnsafeMutablePointer<Float> types since the Accelerate framework is an Objective C framework. Here is an example how to do this.

public func sqrt(x: [Float]) -> [Float] {
    // convert swift array to C vector
    var temp = UnsafeMutablePointer<Float>.alloc(x.count)
    for (var i=0;i<x.count;i++) {
        temp[i] = x[i];
    }
    var count = UnsafeMutablePointer<Int32>.alloc(1)
    count[0] = Int32(x.count)
    vvsqrtf(temp, temp, count)
    // convert C vector to swift array
    var results = [Float](count: x.count, repeatedValue: 0.0)
    for (var i=0;i<x.count;i++) {
        results[i] = temp[i];
    }
    // Free memory
    count.dealloc(1)
    temp.dealloc(x.count)
    return results
}

在整个代码中使用 UnsafeMutablePointer< Float> 类型来获取数据矢量,对于性能而言会更好,而不是像我在此示例中那样在函数调用中来回转换.另外,您还应该保存FFT设置并重用它,以提高性能.

It will work out better for performance to use the UnsafeMutablePointer<Float> types throughout your code for your vectors of data rather than converting back and forth in function calls as I did for this example. Also you should save your FFT setup and reuse that as well for better performance.

由于您使用的是vDSP FFT,因此您可能还喜欢 vDSP_zvabs API,该API可从FFT结果计算以dB为单位的幅度.

Since you're using the vDSP FFT you might also like the vDSP_zvabs API which calculates magnitude in dB from the FFT results.

最后,请务必阅读有关加速框架FFT API的数据打包和缩放的链接. https://developer.apple.com/library/mac/documentation/Performance/Conceptual/vDSP_Programming_Guide/UsingFourierTransforms/UsingFourierTransforms.html

Finally be sure to read this link on data packing and scaling for the Accelerate framework FFT APIs. https://developer.apple.com/library/mac/documentation/Performance/Conceptual/vDSP_Programming_Guide/UsingFourierTransforms/UsingFourierTransforms.html

为了提高性能,vDSP API不会输出最明显的标度值(因为无论如何您肯定会在其他地方对数据进行标度),它们会将一些额外的数据打包到一些FFT点中.

To improve performance, the vDSP APIs do not output the most obvious scale values (since you will undoubtedly be scaling the data anyway somewhere else) and they pack in some extra data into a few of the FFT points.

这篇关于FFT计算错误-Swift的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆