是否有一种众所周知的合成弓弦乐器(如小提琴(的算法?
我知道,对于弹拨的琴弦(例如吉他(,有一种karplus强算法,我过去已经成功地实现了它。
理想情况下,我想要一个描述用于生成/合成数字信号的计算机程序的算法。
例如,karplus强算法可以概括如下:
-
确定要合成的频率的周期长度,并创建一个大小正好相同的缓冲区
-
用随机数(白噪声(填充缓冲区
-
在缓冲区上迭代,每次平均每个点与下一个点,然后将其输出到输出流。
-
在施加一些阻尼的同时,重复所需的时间
我想知道弓弦是否也存在类似的情况。
脚注:
现在,我对弦如何产生声音的物理原理一无所知,所以我不知道如何推导出这样的算法。对于karplus强算法,我只是在原始论文中读了一下,并应用了它"盲目地";。我从来没有想到,从一段时间的噪音开始,并不断地阻尼它,会产生一种如此类似于弹拨琴弦的声音。
编辑:
和往常一样,近距离游行已经开始。
在投票结束此问题之前,请考虑以下事项:
-
这个问题与物理学无关。这与弦的振动机制无关,也与产生声音的弓和空气的相互作用无关。
-
这个问题是关于是否存在一种特定的众所周知的合成声音的算法。严格来说,这是一个关于编程的问题。
奇怪的是,我能在Stanford chuck网站上找到一些关于这个的东西。
该代码是用一种名为ChucK的语言编写的,这种语言显然是专门用于音频编程的。您必须运行才能使用此代码段。但以下是它在chuck中的实现:
// patch
Bowed bow => dac;
// scale
[0, 2, 4, 7, 8, 11] @=> int scale[];
// infinite time loop
while( true )
{
// set
Math.random2f( 0, 1 ) => bow.bowPressure;
Math.random2f( 0, 1 ) => bow.bowPosition;
Math.random2f( 0, 12 ) => bow.vibratoFreq;
Math.random2f( 0, 1 ) => bow.vibratoGain;
Math.random2f( 0, 1 ) => bow.volume;
// print
<<< "---", "" >>>;
<<< "bow pressure:", bow.bowPressure() >>>;
<<< "bow position:", bow.bowPosition() >>>;
<<< "vibrato freq:", bow.vibratoFreq() >>>;
<<< "vibrato gain:", bow.vibratoGain() >>>;
<<< "volume:", bow.volume() >>>;
// set freq
scale[Math.random2(0,scale.size()-1)] + 57 => Std.mtof => bow.freq;
// go
.8 => bow.noteOn;
// advance time
Math.random2f(.8, 2)::second => now;
}
编辑:以上只是实现,它的源文件在这里。
不是一个算法,但有一个开源库(在非常自由的许可证下(,它在C++中为包括弓弦在内的多种乐器实现合成算法。
合成工具包(STK(
官方主页:https://ccrma.stanford.edu/software/stk/
Github链接:https://github.com/thestk/stk
带有与弓弦乐器合成相关代码的文件:
- include/Bowed.h
- src/Bowed.cpp
- include/BowTable.h
代码中的注释引用了两篇论文:
- Reed Bore和弓弦机构的有效模拟朱利叶斯·史密斯(1986((PDF(
- 论弓弦动力学的基本原理;吉姆·伍德豪斯(1979((PDF(
Julius Smith在他的(standford(网站上也有关于弓弦合成的信息:
弓弦部分的";物理音频信号处理";书籍
MUS420讲座弯弦的数字波导建模