2016-09-21 8 views
3

Я несу в несоответствующем результате в реализации Surge функции DFT; Я использую реализацию Surge, которая кажется мне простой.Результат DFT с использованием vDSP от Swift от реального значения входа (реализация всплеска)

Когда я вычислить величины для фиктивных данных я получаю:

var xx = [1.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0] 

{0,6, 0,082842712474619, 0,2, 0,482842712474619, 0,2, 0,482842712474619, 0,2, 0,082842712474619, 0,0, 0,2}

Который как раз кажется неправильным следуя «если он реальный в одном домене, он сопряжен симметрично в другом»

Когда я делаю то же самое:

В Mathematica:

x = {1., 0., 1., 0., 0., 1., 0., 0., 0., 1.} 
Norm /@ Fourier[x, FourierParameters -> {-1, 1}] 

{0,4, 0,117557, 0,154336, 0,190211, 0,214896, 0, 0,214896, 0,190211, 0,154336 , 0,117557}

В R:

x = c(1,0,1,0,0,1,0,0,0,1) 
abs(fft(x)/length(x)) 

"0,400000" "0,117557" "0,154336" "0,190211" "0,214896" "0,000000" "0,214896" "0,190211" "0.154336" "0.117557"

Также с помощью JTransforms:

double[] x = { 1., 0., 1., 0., 0., 1., 0., 0., 0., 1. }; 
double[] output = new double[x.length]; 
DoubleFFT_1D fftDo = new DoubleFFT_1D(x.length); 
double[] fft = new double[x.length * 2]; 
System.arraycopy(x, 0, fft, 0, x.length); 
fftDo.realForwardFull(fft); 

0,4 0,11755705045849463 0,1543361918426817 0,19021130325903074 0,21489611417496346 0,0 0,21489611417496346 0,19021130325903074 0,1543361918426817 0,11755705045849463

Свифт реализация в нагон:

public func fft(_ input: [Double]) -> [Double] { 
    var real = [Double](input) 
    var imaginary = [Double](repeating: 0.0, count: input.count) 
    var splitComplex = DSPDoubleSplitComplex(realp: &real, imagp: &imaginary) 

    let length = vDSP_Length(floor(log2(Float(input.count)))) 
    let radix = FFTRadix(kFFTRadix2) 
    let weights = vDSP_create_fftsetupD(length, radix) 
    vDSP_fft_zipD(weights!, &splitComplex, 1, length, FFTDirection(FFT_FORWARD)) 

    var magnitudes = [Double](repeating: 0.0, count: input.count) 
    vDSP_zvmagsD(&splitComplex, 1, &magnitudes, 1, vDSP_Length(input.count)) 

    var normalizedMagnitudes = [Double](repeating: 0.0, count: input.count) 
    vDSP_vsmulD(sqrt(magnitudes), 1, [2.0/Double(input.count)], &normalizedMagnitudes, 1, vDSP_Length(input.count)) 

    vDSP_destroy_fftsetupD(weights) 

    return normalizedMagnitudes 
} 

Я пропускаю что-то очевидное?

Спасибо

+3

Похоже, ваш код Swift/vDSP предполагает длину, равную 2. Попробуйте работать с N = 16 вместо N = 10. –

+1

Это действительно продвижение, спасибо! Результат равен двум. Но что, если я хочу какую-то произвольную длину ввода? –

+0

Многие реализации FFT поддерживают только мощности 2 длины - когда вам нужно использовать другой размер, тогда типичный метод состоит в том, чтобы набивать ваши входные данные нулями до следующего значения 2. Это дает достоверные результаты, хотя данные в частотной области эффективно интерполируется по большему количеству точек. –

ответ

3

Похоже, ваш код Swift/vDSP принимает длину, которая является степенью 2. Если вы пытаетесь работать с N = 16 вместо N = 10, то вы должны получить правильные результаты, которые затем соответствуют другим реализациям FFT.

Многие реализации FFT поддерживают только мощность 2 длины - когда вам нужно использовать другой размер, тогда типичный метод состоит в том, чтобы набивать ваши входные данные с нулями до следующей мощности 2. Это дает достоверные результаты, хотя частота данные домена эффективно интерполируются по большему количеству точек (это появляется, чтобы иметь более высокое разрешение по частоте, чем тогда нет реальных точек данных, но это только результат интерполяции). Дополнительный бонус заключается в том, что реализации FFT обычно наиболее эффективны при работе с полномочиями 2, и часто быстрее использовать дополнительную мощность 2 БПФ, чем более короткий произвольный размер.

+0

Что делать, если мы прокладываем оставшиеся ячейки с повторением элементов массива от 0 до M, где M равно 2^k - N? –

+0

Нет, не делай этого. –

+0

У меня возникают те же проблемы, что и мой код MATLAB даст разные результаты, чем версия Swift, но я знал, что длина должна быть равна 2. Используя мощность 2, поскольку длина не исправляет операцию кода вообще. – SwiftMatt