vDSP_desamp FIR 滤波器采样历史连续性

Posted

技术标签:

【中文标题】vDSP_desamp FIR 滤波器采样历史连续性【英文标题】:vDSP_desamp FIR filter sample history continuity 【发布时间】:2013-10-11 18:23:50 【问题描述】:

我正在尝试使用vDSP_desamp() 例程对不断捕获的音频信号进行下采样。根据 Accelerate-framework 文档,该例程执行 FIR 过滤和抽取。

但是我有一个冲突,因为 API 没有为循环缓冲区提供输入参数,据我所知,需要保留样本历史记录以执行 FIR 过滤。这使我相信样本历史记录在每次函数调用期间都会被重置,或者可能正在应用与我所知道的算法不同的算法。

不幸的是,该功能是一个完整的黑匣子,没有给出关于如何执行滤波或如何确保信号连续性的提示。

你认为如果我用前一个缓冲区的最后 N 个样本(N 是滤波器抽头的数量)填充每一帧就足够了,以获得过滤连续性吗?我会丢弃那些填充-调用vDSP_desamp()后的样本输出,但我猜应该在处理填充样本后正确初始化样本历史行。

欢迎任何关于vDSP_desamp()内部的提示。

【问题讨论】:

【参考方案1】:

为什么说函数是一个完整的黑盒? documentation 显示了 vDSP_desamp(A, I, F, C, N, P) 的伪代码:

for (n = 0; n < N; ++n)

    sum = 0;
    for (p = 0; p < P; ++p)
        sum += A[n*I+p] * F[p];
    C[n] = sum;

您还可以在任何最新的 OS X 系统上查看 /System/Library/Frameworks/Accelerate.framework/Frameworks/vecLib.framework/Headers/vDSP.h,以获取有关几乎所有 vDSP 例程的信息。它以不同的形式显示相同的东西:

for (n = 0; n < N; ++n)
    C[n] = sum(A[n*I+p] * F[p], 0 <= p < P);

由此可见,每个输出值C[n]P 输入值从A[n*I + 0]A[n*I + P-1] 的函数。假设您希望下一次调用中的第一个输出值以与当前调用相同的模式继续,只需考虑当前调用中的最后一个输出值(最后一个n 将是N-1,所以最后一个输出值将是C[N-1]),下一个值是C[N]。这个C[N] 将是从A[N*I + 0] 开始的输入值的函数,即A[N*I]

然后在下一次调用中将其与第一个输出值C[0] 匹配。 C[0] 将是从A[0*I + 0] 开始的输入值的函数,即A[0]

因此,要从当前调用结束的地方继续进行下一次调用,您需要将值从 A[N*I] 及以上复制到 A[0] 及以上。 (这假设您通过在其中移动数据然后附加新数据来重用数组A。您还可以通过将A+N*I 作为第一个参数传递给vDSP_desamp 来继续处理数据。)

要复制的值的数量是AA[N*I] 之后(包括)之后的值的数量。例如,如果您在 A 中有 Number 值,您可以使用:

memcpy(A+N*I, A, (Number - N*I) * sizeof *A);

然后将新数据放在A[Number - N*I] 及以后。 (如果源和目标范围重叠,您将需要使用memmove 而不是memcpy,但这对于 vDSP_desamp 来说是不寻常的;通常连续调用共享的数据只是整个缓冲区的一小部分。)


注意:伪代码表达了操作的基本数学。出于性能原因,vDSP 例程中的实际算术可能有不同的排列方式。所以实际结果可能与直接使用伪代码计算的值存在舍入误差。

【讨论】:

谢谢。你说的对。我不应该将其表述为“完整的黑匣子”,而是“该算法不符合我对 FIR 滤波的有限理解”。以我的经验,FIR 滤波器需要一个循环的样本历史线,但从你的解释来看,我现在明白样本历史线是隐式的,并且算法将输出延迟了一个样本(通过查看未来的样本,而不是过去)。感谢您的出色回应。

以上是关于vDSP_desamp FIR 滤波器采样历史连续性的主要内容,如果未能解决你的问题,请参考以下文章

FIR滤波器设计

用MATLAB设计对信号进行频谱分析和滤波处理的程序

FIR IP核使用

数字信号处理相关4(FPGA实现FIR滤波器)

语音通信语音通信系统包括语音硬件采样,抽样量化,PCM编码解码模块,FIR滤波,QPSK调制解调模块,语音增强模块以及语音信号还原

嵌入式STM32利用arm-dsp库进行FIR滤波