【问题标题】:Signal after processing with FFT and then IFFT is not the same用FFT和IFFT处理后的信号不一样
【发布时间】:2015-12-01 04:15:51
【问题描述】:

我想对虚拟场景进行声音模拟。因此,我想以频率相关的方式将我的系统计算的脉冲响应与来自简单 .wav 文件的输入信号进行卷积。据我了解 DSP 最好的方法是使用 FFT 将输入信号转换为其频谱,以某种方式对其应用脉冲响应函数并将其返回。

我的问题是,在对我的信号进行 FFT 和 iFFT 之后,信号与原始输入信号不同。原始声音在新信号中是有一定的辨识度的,但由于 FFT 和 iFFT 之后的错误数字,它非常“模糊”。我从http://rosettacode.org/wiki/Fast_Fourier_transform#C.2B.2B 中获取了 C++ 中 FFT 的“第一”(就地、广度优先、频率抽取)实现示例。

下面是我的FFT实现的内码使用代码:

CArray signal = CArray(output_size);
for (int i = 0; i < format.FrameCount; ++i) {
   signal[i] = Complex((double)(is_8_bit ? sample_data_8[i] : sample_data_16[i]), 0);
}

fft(signal);
ifft(signal);

存在以下typedef

typedef std::complex<double> Complex;
typedef std::valarray<Complex> CArray;

由于我从上述网站获取代码,我认为错误不可能在 FFT 的实现范围内。我认为它必须与我输入的数据类型和/或复数有关。

由于我的系统没有实现“阶段”并且我读到它们可以被忽略并且仍然可以返回一个有用的值,所以我用 0 的虚部初始化复数。

我是否犯了一个根本性的错误,或者是数据类型或不应该出现的舍入之类的错误?

【问题讨论】:

  • 采样率是多少?
  • @alexm 采样率为 22050Hz。
  • 这只是一次拍摄,但要使 FFT 正常工作,您需要为其提供 2^n 个样本。
  • 您在现场提供的第二个 FFT 函数对我来说无法正常工作!
  • @Logman 您的意思是“(就地、广度优先、频率抽取)”方法吗?目前,这种方法实际上为我抛出了内存分配异常;你也一样吗?第一个“分而治之”是我正在使用的。对不起,应该另外指出。第一个为我编译并执行,但不知何故似乎没有给我想要的结果。我还尝试了 48Hz 和 2^n 样本,不幸的是两者都有相似的结果。

标签: c++ signal-processing fft convolution


【解决方案1】:

请测试这是否不仅仅是缩放错误。在许多情况下(但不是全部),FFT 和 iFFT 是在不除以样本数的情况下实现的,因此对于长度为 N 的信号,只有

iFFT(FFT(signal))/N

返回原始的signal


对于严肃的转型工作,查找零填充和窗口。

【讨论】:

  • “频率抽取”算法中的归一化部分在某种程度上是个问题。如果我插入一个 2^n 样本,它就可以工作。我尝试再次使用原始源,执行 iFFT(FFT(signal)) 然后将每个样本除以 signal.size() 但这并没有得到正确的结果。如果我误解了 /N 部分,请告知我。谢谢你的条款。我会查一下。
  • 是的,这似乎是正确的程序。有或没有除以 N=signal.size() 的变体应该始终如一地工作。文档应显示是否允许二元或一般长度。一般长度需要更大的库,如 FFTW 或 Spiral 实现几种不同的 FFT 算法(Bluestein、Winograd、Rader(?))。为普通的 Cooley-Tukey 实现提供非二元长度可能会产生奇怪的结果。
【解决方案2】:

要获得正确的结果,您需要有 2^n 个样本。如果您的样本少于 2^n 个,则只需在信号末尾添加零。例如信号 (1,0,1,1,1) 将是 (1,0,1,1,1,0,0,0)。

【讨论】:

    猜你喜欢
    • 2014-09-21
    • 1970-01-01
    • 2013-07-02
    • 2011-10-11
    • 1970-01-01
    • 2022-11-19
    • 2011-07-01
    • 1970-01-01
    • 2012-08-11
    相关资源
    最近更新 更多