首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >问:快速傅立叶变换输出的cos和正弦波的振幅之间的数学关系是什么?

问:快速傅立叶变换输出的cos和正弦波的振幅之间的数学关系是什么?
EN

Stack Overflow用户
提问于 2020-03-06 01:46:41
回答 2查看 102关注 0票数 0

我已经使用自定义的FFT实现分解了一些时间序列数据。通过设计,我的FFT实现提供了一组cos和正弦波,然后我可以将它们相加,以重新生成原始信号。这工作得很好,没有问题,所以我知道提取的正弦波和cos波在振幅、周期和相位方面是正确的。

我使用的数据有1024个样本,它给出了512个cos波和512个正弦波的属性(例如,每个波的振幅、相位和周期数据)。

为了节省数据存储,我试图找到/理解波的振幅之间的数学关系。而不是必须保存每个正弦和cos波的每个振幅,我想简单地保存一些系数,我可以用来在代码中重建振幅。

FFT Sine Waves with Amplitudes

从上图可以看出,有一组功率曲线系数大致符合振幅数据,但对于我的用例来说,这是不够准确的。

由于我有所有的源数据以及每个波的生成属性,在执行完FFT之后,是否有可以使用的简单公式或可以执行的转换来生成代码中的振幅?我知道振幅与实值和虚值有关,但是由于空间要求,我不能存储所有的实值和虚值。

作为我如何将这个问题保存到周期数据的示例,我发现每个波的周期是简单的Math.Power(waveIndex,-1)。因此,对于波形周期,我不需要存储数据,只需在代码中重新生成即可。

我目前找不到正弦波中振幅之间的关系,甚至找不到cos和正弦振幅之间的关系,但是FFT背后的理论和数学超出了我的能力范围,所以我希望有一个简单的公式或概念可以实现。

在回复之后,我添加了下面的代码,用于获取正弦和cos波值,此代码片段可能会帮助那些回复。

代码语言:javascript
复制
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;
            }
        }
    }

下面是我如何获得幅值和相位值的,尽管我目前没有在任何地方使用它们。

代码语言:javascript
复制
    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]);
        }
    }
EN

回答 2

Stack Overflow用户

发布于 2020-03-06 02:13:56

实际上,快速傅立叶变换只返回复系数S(w)=a+jb

对于N点快速傅立叶变换,abs(S(w)) * 2/N将是(接近)频率为w的正弦分量的幅度。

这假设正弦分量的频率接近fft bin的中心,否则功率将在两个相邻bin之间“分割”。

你感兴趣的频率是通过所有的fft窗口呈现的。

票数 0
EN

Stack Overflow用户

发布于 2020-03-06 02:23:52

FFT的输出与输入具有相同的自由度。没有简单的公式(除了FFT本身)可以将FFT结果彼此关联,因为如果任何FFT输入发生变化,所有FFT输出都会发生变化。

每个FFT复数bin结果的正弦和余弦之间的关系与该频率( bin中心)的正弦输入分量的相位有关,相对于起始和结束循环。如果相位改变,正弦和余弦分量也会改变。请参阅: atan2()

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60551270

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档