【问题标题】:KissFFT (kiss_fftr to kiss_fftri) - How to reconstruct the original signal?KissFFT (kiss_fftr to kiss_fftri) - 如何重建原始信号?
【发布时间】:2012-06-07 14:58:34
【问题描述】:

我在理解如何正确使用 KissFFT (1.2.9) 时遇到了一些麻烦。我现在想要实现的只是执行 FFT,然后立即执行 iFFT 以再次重建原始信号。下面的代码 sn-p 演示了我在做什么:

void test(short* timeDomainData, int length)
{
    // Create the configurations for FFT and iFFT...
    kiss_fftr_cfg fftConfiguration = kiss_fftr_alloc( length, 0, NULL, NULL );
    kiss_fftr_cfg ifftConfiguration = kiss_fftr_alloc( length, 1, NULL, NULL );

    // Allocate space for the FFT results (frequency bins)...
    kiss_fft_cpx* fftBins = new kiss_fft_cpx[ length / 2 + 1 ];

    // FFT...
    kiss_fftr( fftConfiguration, timeDomainData, fftBins );

    // iFFT...
    kiss_fftri( ifftConfiguration, fftBins, timeDomainData );
}

我发现这实际上在运行时崩溃了。我发现在创建 KissFFT 配置时将大小除以 2 可以停止崩溃:

kiss_fftr_cfg fftConfiguration = kiss_fftr_alloc( length / 2, 0, NULL, NULL );
kiss_fftr_cfg ifftConfiguration = kiss_fftr_alloc( length / 2, 1, NULL, NULL );

但是,当我播放重建的音频数据时,它几乎是无声的,带有奇怪的噼啪声。

谁能指出我正确的方向?

非常感谢, P

编辑 1:这就是我包含 KissFFT 头文件并定义 FIXED_POINT 变量的方式:

#define FIXED_POINT 16
#include "kiss_fftr.h"

这确保 typedef 的“kiss_fft_scalar”类型被强制为 int16_t(短)。

编辑 2: 目标平台是 Android,所以我还在我的 Android.mk 文件中添加了以下内容:

LOCAL_CPPFLAGS += -DFIXED_POINT

【问题讨论】:

    标签: fft kissfft ifft


    【解决方案1】:

    我注意到你寄来的是短裤。您确定您已编译所有内容以使用 int16_t 作为 DATATYPE 吗?有时预处理器环境不匹配会导致问题。

    此外,定点版本向下两个方向(fwd,inv)。因此,如果您希望重建您的信号,您将需要将事物乘以 nfft 的总数。 我建议分两个阶段乘以饱和度。

    例如如果您正在执行大小为 1024 的 FFT+IFFT,则在 FFT 之后乘以 32,然后在 IFFT 之后再乘以 32。

    【讨论】:

    • 马克 - 我真的希望你能回应。我确定我已经设置了正确的数据类型,我已经用我如何包含 KissFFT 标头和定义 FIXED_POINT 变量的代码示例更新了我的原始帖子。 (我更新了原始帖子,因为这些 cmets 不允许我添加代码 sn-ps)。几个问题:我的意思是什么?你是如何推断出 32 的值的?我的 FFT 大小是 16384...谢谢,P
    • 嗨,马克,虽然我非常感谢您的意见,但我还是不明白您的回复?
    • 很抱歉碰到这个问题,但我仍然没有答案。我知道必须进行缩放,但我不明白,找不到答案,您的回复也没有描述 什么 需要缩放以及缩放多少。互联网上大多数关于 Kiss FFT 和缩放的问题的回答都是“你读过自述文件吗?”......马克,如果你写了这个库,那么你能否提供一个代码 sn-p 来执行 FFT一组短裤,然后用 iFFT 重建原始信号?谢谢,P
    • 数据必须进行缩放。由于 FFT 是线性的,您可以数学地在 FFT 或 IFFT 之前或之后进行。但是,在定点处理中,您可能无法在没有溢出的情况下缩放值并表示有限范围内的值。这就是为什么我建议将扩展分成多个阶段。
    • 这不是为我编写代码的情况——谢谢你。但是,您已经发布了 Kiss FFT,并且有 很多 人对此有问题。简单地写“阅读自述文件”并对直接问题给出非直接的答案只会损害图书馆的声誉。我将对此进行最后一次尝试,否则我将不得不像许多其他人和我一样在同一条船上使用另一个图书馆。
    【解决方案2】:

    我不确定静音,但如果你得到很多噼啪声,那可能是因为你正在独立处理相邻的块,而不是使用 Overlap-Add,在那里你有效地在每个块之间交叉淡入淡出以获得更平滑的特性。

    【讨论】:

    • 如果他不是在处理频域数据,那么缓冲区边界不应该有任何不连续性。
    • 确实如此。在实施一些过滤或转换之后,它可能需要重叠添加。但是在这种情况下,它不会解释点击次数。 FFT 调用崩溃的事实表明其中一个缓冲区的大小不正确。 Nfft 是否大于长度?
    • 啊,是的,重叠添加...我很熟悉这种技术,但我希望我不需要使用它。允许用户修改以下频率:31.5, 63, 125, 250, 500, 1000, 2000, 4000, 8000, 16000 (ISO 1/3 Octave)。在幕后,我正在平滑 16(31.5 之前的 1 个)和 20000Hz(16000 之后的 1 个)之间的频率区间的值。那么,如果用户在 31.5 之前或 16000 之后无法修改任何内容,我还需要重叠添加吗?
    • 我不确定,我对重叠添加有点生疏了。如果您只是进行简单的过滤,那么您可能不需要它。如果您正在进行信号分析和重建(就像我过去所做的那样),那么 OA 会提供更好的结果,因为它有效地允许在帧之间进行插值。
    • 如果您直接更改频域中的值,那么是的——您需要重叠添加(或其他减轻吉布现象的方法)。但这不是问的问题。
    【解决方案3】:

    我正在努力在 Android 中做同样的事情,还没有做到(参见 here!),但我可以在您的代码中看到一个问题:“fftBins”需要是“长度”大小。原因是它是原始变换,而不是频率幅度/相位......我想?还是我记错了?

    【讨论】:

    • 啊 - 一位开发人员在傅立叶变换中迷路了!现在我感觉好多了,因为我知道我并不孤单! 'fftBins' 的大小是正确的 - 第一个 bin 是 DC(零)然后你有一组对称 bin 的前半部分。我不完全确定为什么结果是对称的(这与它是一个“真实的”变换有关),但我知道在 FFT 之后给定的 bin 只会被镜像。
    • 请查看您要求的完整示例here. 我认为频谱确实包含镜像,因此需要与输入的长度相同,这可以解释您的崩溃。
    猜你喜欢
    • 1970-01-01
    • 2019-01-14
    • 2020-05-29
    • 1970-01-01
    • 2021-04-22
    • 1970-01-01
    • 2019-01-30
    • 1970-01-01
    • 2013-06-20
    相关资源
    最近更新 更多