我正在尝试使用vDSP_desamp()
例程对不断捕获的音频信号执行下采样。根据加速框架文档,此例程执行 FIR 滤波和抽取。
但是我有一个冲突,因为 API 没有为循环缓冲区提供输入参数,据我所知,需要该参数来保留样本历史记录以执行 FIR 过滤。 这让我相信在每次函数调用期间都会重置示例历史记录,或者可能正在应用与我所知道的算法不同的算法。
不幸的是,该功能是一个完整的黑匣子,没有给出有关如何执行滤波或如何确保信号连续性的提示。
您认为如果我用前一个缓冲区的最后 N 个样本(N 是滤波器抽头的数量(填充每一帧就足够了吗,以获得过滤连续性? 我会在调用 vDSP_desamp()
后丢弃这些填充样本输出,但我想在处理填充样本后应该正确初始化样本历史行。
欢迎任何关于vDSP_desamp()
内部的提示。
为什么说这个函数是一个完整的黑匣子?文档显示了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]
都是从A[n*I + 0]
到A[n*I + P-1]
P
输入值的函数。 假设您希望下一次调用中的第一个输出值以与当前调用相同的模式继续,只需考虑当前调用中的最后一个输出值(最后一个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
来继续处理数据。
要复制的值数是您在 A[N*I]
之后(包括(A
的值数。 例如,如果您在 A
中有Number
值,则可以使用:
memcpy(A+N*I, A, (Number - N*I) * sizeof *A);
然后将新数据放在A[Number - N*I]
及以后。(如果源和目标范围重叠,则需要使用 memmove
而不是 memcpy
,但这在vDSP_desamp中是不寻常的;通常连续调用共享的数据只是整个缓冲区的一小部分。
注意:伪代码表示操作的基本数学。出于性能原因,vDSP 例程中的实际算术可能会以不同的方式排列。因此,实际结果的舍入误差可能与直接使用伪代码计算的值不同。