Q: Каково математическое соотношение между амплитудами cos и синусоидальной волны БПФ-выхода - PullRequest
0 голосов
/ 05 марта 2020

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

Используемые мной данные имеют 1024 выборки, что дает мне свойства 512 cos-волн и 512 синусоидальных волн (например, данные по амплитуде, фазе и периоду для каждой волны).

Чтобы сэкономить на хранении данных, я пытаюсь найти / понять математическое соотношение между амплитудами волн. Вместо того, чтобы сохранять каждую амплитуду для каждой синусоидальной и косинусоидальной волны, я хотел бы просто сохранить некоторые коэффициенты, которые позже я смогу использовать для перестройки амплитуд в коде.

БПФ Синусоидальные волны с амплитудами

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

Поскольку у меня есть все исходные данные вместе со сгенерированными свойствами каждой волны, есть ли простая формула, которую я могу использовать, или преобразование, которое я могу выполнить, чтобы сгенерировать амплитуды в коде после того, как я выполнил БПФ? Я знаю, что амплитуды связаны с действительными и мнимыми значениями, однако я не могу хранить все действительные и мнимые значения из-за требований к пространству.

В качестве примера того, как я сохраняю эту проблему для данных периода, Я обнаружил, что период каждой волны просто Math.Power (waveIndex, -1). Поэтому для периодов волн мне не нужно хранить данные, я могу просто восстановить их в коде.

В настоящее время я не могу найти взаимосвязь между амплитудами в синусоидальной волне или даже взаимосвязь между cos и синусоидальными амплитудами, однако теория и математика, лежащие в основе БПФ, мне недоступны, поэтому я надеюсь, что существует простая формула или Концепция, которую я могу реализовать.

После ответов, которые я добавил нижеприведенный код, который я использую для получения значений синусоидальной и косоволны, этот фрагмент кода может помочь тем, кто отвечает.

internal void GetSineAndCosWavesBasic(double[] outReal, double[] outImag, int numWaves, out double[,] sineValues, out double[,] cosValues)
    {
        // the real and imag values from Cooley-Tukey decimation-in-time radix-2 FFT are passed in
        // and we want to generate the cos and sine values for each sample  for each wave

        var length = outReal.Length;
        var lengthDouble = (double)length;
        var halfLength = lengthDouble / 2.0;

        sineValues = new double[numWaves, length];
        cosValues = new double[numWaves, length];

        var Pi2 = 2 * Math.PI;

        for (var waveIdx = 0; waveIdx < numWaves; waveIdx++)
        {
            for (var sampleIdx = 0; sampleIdx < length; sampleIdx++)
            {
                // first value case and middle value case
                var reX = outReal[waveIdx] / halfLength;
                if (sampleIdx == 0)
                {
                    reX = outReal[waveIdx] / lengthDouble;
                }
                else if (sampleIdx == halfLength)
                {
                    reX = outReal[waveIdx] / lengthDouble;
                }

                // precompute the value that gets sine/cos applied 
                var tmp = (Pi2 * waveIdx * sampleIdx) / lengthDouble;

                // get the instant cos and sine values
                var valueCos = Math.Cos(tmp) * reX;
                var valueSin = Math.Sin(tmp) * (-outImag[waveIdx] / halfLength);

                // update the sine and cos values for this wave for this sample
                cosValues[waveIdx, sampleIdx] = valueCos;
                sineValues[waveIdx, sampleIdx] = valueSin;
            }
        }
    }

И ниже показано, как я получаю значения амплитуды и фазы, хотя в настоящее время я нигде их не использую.

    internal void CalculateMagAndPhaseBasic(double[] outReal, double[] outImag, out double[] mag, out double[] phase)
    {
        // the real and imag values from Cooley-Tukey decimation-in-time radix-2 FFT are passed in
        // and we want to generate the magnitude and phase values

        var length = outReal.Length;

        mag = new double[(length / 2) +1];
        phase = new double[(length / 2) + 1];

        for (var i = 0; i <= length / 2; i++)
        {
            mag[i] = Math.Pow((outReal[i] * outReal[i]) + (outImag[i] * outImag[i]), 0.5);
            phase[i] = Math.Atan2(outImag[i], outReal[i]);
        }
    }

Ответы [ 2 ]

0 голосов
/ 05 марта 2020

Выход БПФ имеет столько же степеней свободы, что и вход. Не существует простой формулы (кроме самого БПФ), которая связывает результаты БПФ только друг с другом, поскольку все выходы БПФ могут измениться при изменении любого из входов БПФ.

Отношение между синусом и Косинус каждого результата комплексного бина БПФ связан с фазой синусоидального входного компонента на этой частоте (в центре бина) по кругу относительно начала и конца. Если фаза изменяется, то и синус, и косинус могут изменяться. Смотрите: atan2 ()

0 голосов
/ 05 марта 2020

На самом деле, fft просто возвращает вам комплексные коэффициенты S(w)=a+jb

Для точки N fft, abs(S(w)) * 2/N будет (близко к) амплитуде синусоидальной составляющей на частоте w.

Предполагается, что синусоидальная составляющая имеет частоту, близкую к центру ячейки БПФ, в противном случае мощность будет «разделена» между двумя соседними ячейками.

И что частота интересует присутствует через все фтф окно.

...