c - 如何用karplus strong算法实现插值延迟线和全通滤波器?

标签 c filter signal-processing delay sound-synthesis

好的,我已经用 C 实现了 karplus strong 算法。这是一个模拟拨弦声音的简单算法。你从一个长度为 n 的环形缓冲区开始(n = 采样频率/你想要的频率),通过一个简单的两点平均滤波器 y[n] = (x[n] + x[n-1])/2,输出它,然后反馈到延迟线。冲洗并重复。随着时间的推移,这会消除噪音,从而产生自然的弹拨弦音。

但我注意到,对于整数延迟线长度,几个高音可以匹配到相同的延迟长度。此外,整数延迟长度不允许平滑变化的音高(如颤音或滑音)我已经阅读了几篇关于 karplus 算法扩展的论文,他们都在谈论使用插值延迟线进行小数延迟或全通滤波器

http://quod.lib.umich.edu/cgi/p/pod/dod-idx?c=icmc;idno=bbp2372.1997.068
http://www.jaffe.com/Jaffe-Smith-Extensions-CMJ-1983.pdf
http://www.music.mcgill.ca/~gary/courses/projects/618_2009/NickDonaldson/index.html

我以前实现过内插延迟线,但仅限于波形缓冲区不变的波表。我只是以不同的速度逐步解决延迟问题。但让我感到困惑的是,当谈到 KS 算法时,论文似乎在谈论实际改变延迟长度,而不仅仅是我逐步通过它的速率。 ks 算法使事情变得复杂,因为我应该不断地将值反馈回延迟线。

那么我将如何着手实现呢?我是将内插值反馈回去还是什么?我是否完全摆脱了两点平均低通滤波器?

全通滤波器如何工作?我应该用全通滤波器替换 2 点平均滤波器吗?如何使用线性插值方法或全通滤波器方法在远距离音高之间滑行?

最佳答案

数字信号处理算法通常以方框图表示是有充分理由的——这是一种很好的思考方式。在对它们进行编码时,将每个 block 视为具有固定输入和输出的独立单元。我认为您的一些问题来自尝试过早地组合系统的各种元素。

这是 Karplus Strong 的框图。

Wikipedia Karplus Strong block diagram

对于延迟 block ,您需要实现一个分数延迟线。这将包括它自己的低通滤波器,但这是延迟线如何实现的细节。 Karplus Strong 效果还需要一个低通滤波器。这些过滤器的特性会有所不同。不要试图结合。顺便说一句,您选择的平均低通滤波器具有较差的频率响应,引入了“梳状滤波器”效应。您可能想要设计更复杂的 FIR 或 IIR 滤波器。

So how would I go about implementing this? Do I feed the interpolated value back in or what? Do I get rid of the two point averaging low pass filter completely?

您确实将经过插值和求和的样本送回延迟线,就像方框图所示。在某些情况下,这可能会开始增加系统的净增益,您可能需要“规范化”延迟的输出,以使其不会失控,如果您担心的话。

有许多有效的策略可以实现分数延迟线,包括您提到的插值和全通滤波。这个想法是您需要将 readwrite 索引维护到延迟线中。延迟线的长度不是内存缓冲区的总长度,而是索引之间的差模延迟线的总长度。使延迟线尽可能大,不要担心调整它的大小。

我发现将读取和写入视为永不回绕或过期的自由运行计数器最方便,因为这样

current_delay_length = (write - read) % total_delay_length
current_read_sample = delay_line[read % total_delay_length]

其中 % 是模数。如果写入和读取计数器是浮点值或设置为定点,则写入和读取计数器也可以包含小数长度。无论如何,这使得修改延迟线的长度变得容易。确保强制执行最小延迟很重要(写入 > 读取)。

信不信由你,您将通过改变步进延迟线的速率来改变延迟线的长度,就像固定长度的缓冲区一样。通常,您会稍微调整读取索引。它不应该落后于写指针超过缓冲区长度或超过它,否则你会遇到小故障。但是您可以在写指针之后自由地将读指针移动到任何地方。改变调制会得到不同的效果。

我强调,滑音等效果来自于延迟线的读写索引是如何操作的,而不是它是如何实现的。您将从全通滤波器或线性内插延迟线获得类似的声音。例如,更好的分数延迟线将减少混叠噪声并支持读取指针的更快速变化。

关于c - 如何用karplus strong算法实现插值延迟线和全通滤波器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6675445/

相关文章:

java - 如何正确地将滤镜应用于图像阵列?

ios - 处理来自移动麦克风的音频输入而不将其保存到文件中

c - 循环重复 printf 但不重复 scanf

c - 结构体和字符串的问题

c - C中的面向对象编程

arrays - Swift Array.filter 方法

c - 未初始化的值是由堆栈分配矩阵 mult 创建的

python - 根据行条件过滤 pandas 列

Python 高通滤波器

audio - .wav 样本的解释