Простое на месте дискретное преобразование Фурье (ДПФ) - PullRequest
6 голосов
/ 28 апреля 2010

Я пишу очень простой DFT на месте. Я использую формулу, показанную здесь: http://en.wikipedia.org/wiki/Discrete_Fourier_transform#Definition вместе с формулой Эйлера, чтобы избежать необходимости использовать класс комплексных чисел только для этого. Пока у меня есть это:

private void fft(double[] data)
        {
            double[] real = new double[256];
            double[] imag = new double[256];
            double pi_div_128 = -1 * Math.PI / 128;
            for (int k = 0; k < 256; k++)
            {
                for (int n = 0; n < 256; n++)
                {
                    real[k] += data[k] * Math.Cos(pi_div_128 * k * n);
                    imag[k] += data[k] * Math.Sin(pi_div_128 * k * n);
                }
                data[k] = Math.Sqrt(real[k] * real[k] + imag[k] * imag[k]);
            }
        }

Но термины Math.Cos и Math.Sin в конечном итоге оказываются как положительными, так и отрицательными, поэтому, когда я добавляю эти термины, умноженные на данные [k], они отменяются, и я просто получаю какое-то непристойно небольшое значение. Я вижу, как это происходит, но я не могу понять, как мой код, возможно, неправильно представляет математику. Любая помощь приветствуется. К вашему сведению, я должен написать свое собственное, я понимаю, что могу получить готовые БПФ.

Ответы [ 2 ]

9 голосов
/ 28 апреля 2010

Я полагаю, у вас есть ошибка в этом разделе

for (int n = 0; n < 256; n++)
{
    real[k] += data[k] * Math.Cos(pi_div_128 * k * n);
    imag[k] += data[k] * Math.Sin(pi_div_128 * k * n);
}

Вы должны заменить данные [k] на данные [n]

EDIT:

Вы также уничтожаете Ваши данные в строке:

data[k] = Math.Sqrt(real[k] * real[k] + imag[k] * imag[k]);

Вы должны хранить модули ваших комплексных чисел где-то еще или позже. Если модуль - это все, что вам нужно, и вы хотите сохранить его в данных []. Вы должны закодировать другой цикл после вычисления преобразования., Все данные [] необходимы для вычисления каждого действительного [k] и imag [k].

7 голосов
/ 16 августа 2012
private double[] dft(double[] data)
{
    int n = data.Length;
    int m = n;// I use m = n / 2d;
    double[] real = new double[n];
    double[] imag = new double[n];
    double[] result = new double[m];
    double pi_div = 2.0 * Math.PI / n;
    for (int w = 0; w < m; w++)
    {
        double a = w * pi_div;
        for (int t = 0; t < n; t++)
        {
            real[w] += data[t] * Math.Cos(a * t);
            imag[w] += data[t] * Math.Sin(a * t);
        }
        result[w] = Math.Sqrt(real[w] * real[w] + imag[w] * imag[w]) / n;
    }
    return result;
}
...