使用 FFT 转换到频域,然后 IFFT 回到时域 C++

信息处理 fft C
2022-01-31 10:32:21

我在 stackoverflow.com 上发布了同样的问题,但收效甚微,所以我想我会在这里尝试!

我正在使用 C++/C 对一些应该是激光脉冲输出的数据执行正向和反向 FFT。

这个想法是获取输出,使用前向 FFT 转换到频域,对相位应用线性最佳拟合(首先展开它),然后从相位信息中减去这个最佳拟合。

然后将得到的相位和幅度转换回时域,最终目标是通过相位补偿压缩脉冲。

我试图在 MATLAB 中这样做没有成功,结果转向了 C++。前向 FFT 工作正常,我从 C++ 中的 Numerical recipes 中获取了基本配方,并使用了一个函数来修改它以适应复杂的输入,如下所示:

void fft(Complex* DataIn, Complex* DataOut, int fftSize, int InverseTransform, int fftShift)
{

        double* Data  = new double[2*fftSize+3];
        Data[0] == 0.0;


        for(int i=0; i<fftSize; i++)
        {
                Data[i*2+1]  = real(DataIn[i]);
                Data[i*2+2]  = imag(DataIn[i]);
        }

        fft_basic(Data, fftSize, InverseTransform);

        for(int i=0; i<fftSize; i++)
        {
                DataOut[i] = Complex(Data[2*i+1], Data[2*i+2]);
        }

        //Swap the fft halfes
        if(fftShift==1)
        {
                Complex* temp = new Complex[fftSize];
                for(int i=0; i<fftSize/2; i++)
                {
                        temp[i+fftSize/2] = DataOut[i];
                }
                for(int i=fftSize/2; i<fftSize; i++)
                {
                        temp[i-fftSize/2] = DataOut[i];
                }
                for(int i=0; i<fftSize; i++)
                {
                        DataOut[i] = temp[i];
                }
                delete[] temp;
        }
        delete[] Data;
}

使用ftt_basic()取自“数值食谱 C++”的函数。输入变量InverseTransform只是 FFT 的方向:正向或反向。

我的问题是输入的形式似乎会影响反向 FFT 的输出。这可能是一个精度问题,但我环顾四周,它似乎并没有影响到其他任何人。

将正向 FFT 的输出直接反馈回反向 FFT 会产生与输入相同的脉冲。

然而,将前向 FFT 的功率输出real^2+imag^2复制到一个数组中,这样:

Reverse_fft_input[i]=complex(real(forwardsoutput[i]),imag(forwardsoutput[i]));

然后将其用作反向 FFT 的输入会产生规则的耦合脉冲,但幅度和周期错误。

最后,获取正向 FFT 的输出并复制如下:

Reverse_fft_input[i]=complex( Amplitude[i]*cos(phase[i]), Amplitude[i]*sin(phase[i]));

其中Amplitude[i]=(real^2+imag^2)^0.5phase[i]=atan(imag/real)在时域中产生非常混乱的输出,峰值朝向中间,类似于频域中的功率谱。

我的问题是,是 cos 和 sin 函数的精度导致反向 fft 的输出变成这样吗?所有变量都存储为“double”类型。为什么复杂数据的不同输入方式存在如此巨大的差异,为什么只有直接反馈到反向FFT时,时域数据才与原始数据相同?输入到前锋FFT?

谢谢你。

(我会张贴图片,但不幸的是我还不能这样做......)

2个回答

有几件事:

  1. 您的 Data[] 数组似乎从偏移量“1”开始。这对于 C++ 来说是不寻常的,其中“0”是第一个索引。matlab从1开始。这可能是fft_basic的调用约定的一部分,但是有点奇怪
  2. 对功率谱进行傅里叶逆变换(正向变换的幅度平方)可为您提供自相关。这与相位补偿完全无关。错误的算法。
  3. 您无法将相位计算为 atan(imag/real),因为您会得到一半的象限错误。正确的函数是 atan2(imag, real),它考虑了实部和虚部的相对符号。
  4. 加入合唱团:先在 Matlab 中求解,然后移植到 C++

我在这里,阅读您在 2019 年(7 年后)的原始问题。您从 TIMEDOMAIN 数据 TD[] 开始,这是一组实时激光信号的等距采样幅度。让我们验证您的数据是什么样的。它是否有死区,后跟脉冲(0 到 2V?)。它是否类似于关闭时间的时钟,然后是准时脉冲?并且,数据采样是否“足够快”以使您获得 3 个良好的准时持续时间样本?假设每个脉冲获得 3 个良好的幅度样本,这些样本记录在 TD[array] 中。然后你取时域的 FFT,产生 FD[],频域数组结果。FD[0] 中的每个位置都有一个用途。FD[0] 是 DC 电平,FD[1] 显示存在最低 FINDABLE 频率,而 FD[N/2] 显示存在最高 FINDABLE 频率:“NYQUIST 频率”。FD[] 中的每个位置是 A + jB real + imag,每个频率 bin 的相位是 ARCTAN (B/A)。您手动访问每个 FD 阵列位置,并修改 REAL 部分(使用最佳拟合算法)并修改 IMAG 部分(使用最佳拟合算法)。那么您所做的就是改变每个贡献正弦波的幅度,并且因为每个 A 和 B 都已更改,所以每个 FD[location] 的相位 INFO 已被修改。假设您正确地将每个数组位置的每个 FD[].real 和 FD[].imag 从术语 [0] 更改为术语 [N/2] 并将镜像术语从 [N/2]+1 更改为末尾的数组。当您进行逆 FFT 时,您只是制作了修改后的频域信号的时域信号。由于您没有将任何条款归零,因此您只是“改变了” 原始时域信号的每个贡献正弦波的大小。如果您真的以足够的带宽对原始信号进行采样,那么您得到的结果应该类似于原始信号,每个脉冲的角更圆,脉冲幅度更低。仅仅说你有一个输入信号的时域数组是不够的。您还需要确保各种激光脉冲的每段关闭时间有超过 3 个幅度样本,并且每段开启时间有超过 3 个幅度样本。否则,您可能刚刚记录了实际激光信号活动的慢速混叠版本。如果您从未记录足够的激光信号样本,则 FFT 无法为您提供所需的 FREQ 信息。- 塞萨尔 如果您真的以足够的带宽对原始信号进行采样,那么您得到的结果应该类似于原始信号,每个脉冲的角更圆,脉冲幅度更低。仅仅说你有一个输入信号的时域数组是不够的。您还需要确保各种激光脉冲的每段关闭时间有超过 3 个幅度样本,并且每段开启时间有超过 3 个幅度样本。否则,您可能刚刚记录了实际激光信号活动的慢速混叠版本。如果您从未记录足够的激光信号样本,则 FFT 无法为您提供所需的 FREQ 信息。- 塞萨尔 如果您真的以足够的带宽对原始信号进行采样,那么您得到的结果应该类似于原始信号,每个脉冲的角更圆,脉冲幅度更低。仅仅说你有一个输入信号的时域数组是不够的。您还需要确保各种激光脉冲的每段关闭时间有超过 3 个幅度样本,并且每段开启时间有超过 3 个幅度样本。否则,您可能刚刚记录了实际激光信号活动的慢速混叠版本。如果您从未记录足够的激光信号样本,则 FFT 无法为您提供所需的 FREQ 信息。- 塞萨尔 具有较低幅度的脉冲。仅仅说你有一个输入信号的时域数组是不够的。您还需要确保各种激光脉冲的每段关闭时间有超过 3 个幅度样本,并且每段开启时间有超过 3 个幅度样本。否则,您可能刚刚记录了实际激光信号活动的慢速混叠版本。如果您从未记录足够的激光信号样本,则 FFT 无法为您提供所需的 FREQ 信息。- 塞萨尔 具有较低幅度的脉冲。仅仅说你有一个输入信号的时域数组是不够的。您还需要确保各种激光脉冲的每段关闭时间有超过 3 个幅度样本,并且每段开启时间有超过 3 个幅度样本。否则,您可能刚刚记录了实际激光信号活动的慢速混叠版本。如果您从未记录足够的激光信号样本,则 FFT 无法为您提供所需的 FREQ 信息。- 塞萨尔 您可能刚刚记录了实际激光信号活动的慢速混叠版本。如果您从未记录足够的激光信号样本,则 FFT 无法为您提供所需的 FREQ 信息。- 塞萨尔 您可能刚刚记录了实际激光信号活动的慢速混叠版本。如果您从未记录足够的激光信号样本,则 FFT 无法为您提供所需的 FREQ 信息。- 塞萨尔