使用 Accelerate 和 vDSP_desamp() 进行音频处理
Audio Processing with Accelerate and vDSP_desamp()
我对 vdsp 框架完全陌生,我正在尝试通过构建来学习。我的目标是按以下方式处理信号:
- 100 阶带通 FIR
- 按因子缩减采样:2
据我从 Apple 的文档中了解到,函数 vDSP_desamp() 是我正在寻找的(它可以同时执行两个步骤,对吧?)
我该如何正确使用它?
以下是我的想法:
给定一个 AudioBufferList *audio
和一个长度为 [101] 的滤波器系数数组 filterCoeffs
:
vDSP_desamp((float*)audio->mBuffers[0].mData, 2, &filterCoeffs, (float*)audio->mBuffers[0].mData, frames, 101);
这是对方法的正确使用吗?
我是否需要为此过程实施循环缓冲区?
非常欢迎任何指向要阅读的内容的指导/方向/指针。
谢谢
阅读文档,vDSP_desamp()
确实是复合抽取和FIR操作。两者一起做是一个好主意,因为它减少了内存访问,并且有消除大量计算的余地。
这里的假设是 FIR 滤波器已经用 (P-1)/2
群延迟重铸。这样做的结果是要计算 C(n)
函数需要访问 A(n*I+p)
其中(使用文档的术语):
`A[0..x-1]`: input sample array
`C[0..n-1]`: output sample array
`P`: number of filter coefficients
`I`: Decimation factor
很明显,如果您将 CoreAudio 缓冲区传递给它,它将 运行 离开缓冲区末尾 200 个输入样本。最好的情况是产生 100 个垃圾样本,最坏的情况是 SIGSEGV
.
所以,简单的答案是否定的。您不能单独使用 vDSP_desamp()
。
您的选择是:
Assemble 将需要的样本 放入缓冲区,然后为 N
输出样本调用 vDSP_desamp()
。这涉及从两个 CoreAudio 缓冲区复制样本。如果您担心延迟,您可以重铸 FIR 以使用 100 个先前的样本,或者,它们可以来自下一个缓冲区。
尽你所能使用vDSP_desamp()
,并计算当过滤器覆盖两个缓冲区时更复杂的情况。
两次调用 vDSP_desamp()
- 一次是简单的情况,另一次是组装输入缓冲区,其中样本环绕相邻的 CoreAudio 缓冲区
我看不出你如何使用循环缓冲区来解决这个问题:你仍然有缓冲区环绕的情况需要处理,并且仍然需要将所有样本复制到其中。
哪个更快取决于 CoreAudio 提供的音频缓冲区的大小。我的直觉是,对于小缓冲区和小过滤器长度,vDSP_desamp()
可能不值得,但您需要进行测量才能确定。
当我过去在 iOS 实现这种事情时,我发现了一个
手动抽取和滤波操作在事物的宏伟计划中相当微不足道,并且没有进一步优化。
我对 vdsp 框架完全陌生,我正在尝试通过构建来学习。我的目标是按以下方式处理信号:
- 100 阶带通 FIR
- 按因子缩减采样:2
据我从 Apple 的文档中了解到,函数 vDSP_desamp() 是我正在寻找的(它可以同时执行两个步骤,对吧?)
我该如何正确使用它?
以下是我的想法:
给定一个 AudioBufferList *audio
和一个长度为 [101] 的滤波器系数数组 filterCoeffs
:
vDSP_desamp((float*)audio->mBuffers[0].mData, 2, &filterCoeffs, (float*)audio->mBuffers[0].mData, frames, 101);
这是对方法的正确使用吗? 我是否需要为此过程实施循环缓冲区? 非常欢迎任何指向要阅读的内容的指导/方向/指针。 谢谢
阅读文档,vDSP_desamp()
确实是复合抽取和FIR操作。两者一起做是一个好主意,因为它减少了内存访问,并且有消除大量计算的余地。
这里的假设是 FIR 滤波器已经用 (P-1)/2
群延迟重铸。这样做的结果是要计算 C(n)
函数需要访问 A(n*I+p)
其中(使用文档的术语):
`A[0..x-1]`: input sample array
`C[0..n-1]`: output sample array
`P`: number of filter coefficients
`I`: Decimation factor
很明显,如果您将 CoreAudio 缓冲区传递给它,它将 运行 离开缓冲区末尾 200 个输入样本。最好的情况是产生 100 个垃圾样本,最坏的情况是 SIGSEGV
.
所以,简单的答案是否定的。您不能单独使用 vDSP_desamp()
。
您的选择是:
Assemble 将需要的样本 放入缓冲区,然后为
N
输出样本调用vDSP_desamp()
。这涉及从两个 CoreAudio 缓冲区复制样本。如果您担心延迟,您可以重铸 FIR 以使用 100 个先前的样本,或者,它们可以来自下一个缓冲区。尽你所能使用
vDSP_desamp()
,并计算当过滤器覆盖两个缓冲区时更复杂的情况。两次调用
vDSP_desamp()
- 一次是简单的情况,另一次是组装输入缓冲区,其中样本环绕相邻的 CoreAudio 缓冲区
我看不出你如何使用循环缓冲区来解决这个问题:你仍然有缓冲区环绕的情况需要处理,并且仍然需要将所有样本复制到其中。
哪个更快取决于 CoreAudio 提供的音频缓冲区的大小。我的直觉是,对于小缓冲区和小过滤器长度,vDSP_desamp()
可能不值得,但您需要进行测量才能确定。
当我过去在 iOS 实现这种事情时,我发现了一个 手动抽取和滤波操作在事物的宏伟计划中相当微不足道,并且没有进一步优化。