KISS FFT 解释的输出

信息处理 过滤器 声音的 fft C
2022-02-11 23:12:33

我正在通过包含 320 个样本的数据包中的套接字连接接收 PCM 数据。声音的采样率为每秒 8000 个样本。我正在做这样的事情:

int size = 160 * 2;//160;
int isinverse = 1;
kiss_fft_scalar zero;
memset(&zero,0,sizeof(zero));
kiss_fft_cpx fft_in[size];
kiss_fft_cpx fft_out[size];
kiss_fft_cpx fft_reconstructed[size];

kiss_fftr_cfg fft = kiss_fftr_alloc(size*2 ,0 ,0,0);
kiss_fftr_cfg ifft = kiss_fftr_alloc(size*2,isinverse,0,0);

for (int i = 0; i < size; i++) {
    fft_in[i].r = zero;
    fft_in[i].i = zero;
    fft_out[i].r = zero;
    fft_out[i].i = zero;
    fft_reconstructed[i].r = zero;
    fft_reconstructed[i].i = zero;
}

// got my data through socket connection

for (int i = 0; i < size; i++) {
     // samples are type of short
     fft_in[i].r = samples[i];
     fft_in[i].i = zero;
     fft_out[i].r = zero;
     fft_out[i].i = zero;
 }

 kiss_fftr(fft, (kiss_fft_scalar*) fft_in, fft_out);
 kiss_fftri(ifft, fft_out, (kiss_fft_scalar*)fft_reconstructed);

 // lets normalize samples
 for (int i = 0; i < size; i++) {
     samples[i] = rint(fft_reconstructed[i].r/(size*2));
 }

之后我填充 OpenAL 缓冲区并播放它们。一切正常,但我想对 和 之间的音频进行一些kiss_fftr过滤kiss_fftri我认为的起点是将声音从时域转换为频域,但我真的不明白我从kiss_fftr函数接收到什么样的数据。每个复数中存储了哪些信息,它的实部和虚部可以告诉我有关频率的信息。而且我不知道哪些频率被覆盖(什么频率跨度)fft_out- 哪些索引对应于哪些频率。

我是信号处理和傅里叶变换主题的新手。

有什么帮助吗?

3个回答

您可能想要研究的是使用重叠相加或重叠保存方法的 FFT 快速卷积。您需要将每个 FFT 的长度扩展为所需滤波器的脉冲长度。这是因为 (1) FFT/IFFT 卷积是循环的,并且 (2) FFT 阵列结果中的每个索引对应于几乎所有频率(Sinc 形响应),而不仅仅是一个(即使大部分集中在一个附近),所以任何单个 bin 修改将在整个频率响应中泄漏(某些精确的周期性频率除外)。

FFT 的每个输出“桶”代表一个频带。最左边的桶代表 DC,下一个是非常低的频率,下一个是更高的频率,等等。每一步都是固定的赫兹数。如果f是采样频率并且N(通常应该是 2 的幂)是 FFT输入桶的数量,就会有N/2输出桶(每个都有实部和虚部),最高输出桶对应的频率为f/2.

所以kiss_fftr的输出就是你的“频域”信息。

至于实部与虚部,这与该频率与所有其他频率的相位/时序有关。如果您考虑一个漂亮的平滑正弦波形,并在某个时刻查看它,表示当前时间的垂直线将在波峰、波谷、中途附近或中间的某个地方撞击波。

如果我们将峰值定义为 1.0 实数和 0.0 虚数,则谷值将是 -1.0 实数和 0.0 虚数,中途将是 0.0 实数和 +/- 1.0 虚数(+/- 取决于您是在下降斜坡上还是在上升一个)。(实际上,我怀疑“官方”版本的 1.0 real 会在上升的中途,但这种方式很难解释,而且参考点也有些随意。)

在您的情况下,您似乎使用的N是 320 的幂 - 而不是 2 的幂。我不是这方面的专家,但我的印象是,虽然在概念上您可以在非 2 的幂缓冲区上进行 FFT ,实际上许多 FFT 算法都不能很好地处理它。(而且我不希望作为一个相当原始的算法的kiss_fft 能够“很好地处理它”。)但正如我所说,我不是专家,所以也许其他人在这一点上有一些意见。

一个问题可能是该 kiss_fftr()函数需要一个常规kiss_fft_scalar数组而不是 akiss_fft_cpx array作为输入参数。