重叠添加 - 使用哪个长度?

信息处理 fft 音频处理 快速卷积 重叠相加
2022-02-20 14:29:39

我正在做实时音频。假设我有一个信号x(n)它以 512 块(siobuffer)的形式传递给程序过滤器/FFT 方法。在这个块中,我想将信号与滤波器进行卷积u(n)(脉冲响应)长度为 8192K。所以我将 asio 块从 513 零填充到 8192K,对两个数组进行 FFT 并将结果相乘。在IFFT之后,我得到了卷积信号y(n)我想传递给输出 asio 缓冲区的长度为 8192K(也可以说长度为 512)。

现在我的问题来了:要使用多少重叠添加?据我了解,我必须将整个 8192K 添加到最后一个字节,不是吗?这意味着我划分y(n)8192 x 512 分成 16 个块,然后将所有这些 512 个块重叠添加到下一个处理的输入块中。当我读到一般的重叠添加时,总会有人们有输出的例子y(n)只比输入长一点,所以它们通常重叠添加大约 1.5 个输入块。

我的想法有错误吗?我是否只需要重叠添加部分y(n),或者我必须每次重叠添加我所有的 16 个块?

1个回答

你在这里有很多选择

  1. 您可以将脉冲响应和信号归零到 16k、FFT 和乘法。但这非常低效。请记住,滤波器和信号的长度之和必须等于或小于 FFT 大小,因此 8k FFT 不起作用。如果您可以将 8k 脉冲响应截断至 7.5k,情况会好一些。然后你可以使用 8k FFT,因为 7.5k+512 <= 8k
  2. 您可以继续累积 512k 缓冲区,直到您有 8k 信号。然后将零填充到 16k、FFT 和乘法。这要便宜得多,但也会大大增加延迟,您需要在不同的线程中进行处理。

通常,这里的最佳选择是分段重叠添加或块卷积器。这大致像这样工作

  1. 将你的 8k 脉冲响应分成 16 个块,每块 512 个。零填充到 1024 和 FFT。现在你有 16 个频域传递函数向量Hk(z),k=0,1,2...15
  2. 在每一帧 n,你都会得到一个新的信号块xn(t)长度为 512。零填充到 1024 和 FFT。现在有了频域信号向量Xn(z). 确保你也保留最后 15 帧,所以你有Xn(z),Xn1(z)...Xn15(z)
  3. 现在将信号向量与传递函数向量相乘并将所有结果相加。Yn(z)=Xn(z)H0(z)+Xn1(z)H1(z)+...+Xn15(z)H15(z)
  4. 逆 FFT,得到 1024 个时域样本,yn(t)
  5. 管理重叠。创建输出作为前 512 个样本yn(t)加上前一帧的最后 512 个yn1(t). 保留当前帧的最后 512 个样本,yn(t),作为下一帧的重叠。

这种方法非常有效,因为您只需每帧执行两次 1k FFT,而且它还可以保持低延迟。有一些方法可以通过利用输入数据是真实的而不是复杂的来进一步改进这一点,但这可能应该是一个不同的问题。

如果您不想手动管理重叠,请改用重叠保存。 https://en.wikipedia.org/wiki/Overlap%E2%80%93save_method