在Linux和/或Python中生成吉他和弦的最简单方法
我想要实现的目标是让我的Python应用程序播放一个吉他和弦。我知道(或者可以计算出)这个和弦的频率,如果需要的话。
我在想,即使我从底层开始,产生多个正确频率的正弦波,听起来也可能不对,因为声音的包络(也就是声音的起伏变化)也需要正确,否则听起来就像是嗡嗡声,而不是吉他的声音。
让我感到兴奋的是,Linux的sox命令可以用以下方式产生一个相当不错的单音:
play -n synth 0 pluck E3
所以我真正想问的是,
a) 有没有办法让play命令播放整个和弦(最好是稍微错开的开始时间,以模拟拨片拨弦的效果)——我还没有找到办法,但也许有一些bash的技巧可以让它正确发声。如果可以做到这一点,我就满足于从我的代码中调用一个bash命令(我不想重复造轮子)。
b) (更好的是)在Python中有没有办法实现这个(吉他和弦的声音)?我见过一些可用的Python MIDI库,但老实说,MIDI并不适合我想要的声音,至少从我目前的了解来看。
3 个回答
a) 有没有办法让播放命令同时播放一个和弦...?
如果你的声音系统支持的话,你可以同时运行多个命令来输出声音。如果你使用的是ALSA(一个声音驱动),你需要在你的~/.asoundrc
文件中设置dmix或其他类似的选项。可以使用subprocess.Popen
来启动多个子进程。如果这是一个假设的bash脚本,你可以这样做:
command1 &
command2 &
...
b) (更好的是)在python中有没有办法实现这个(吉他和弦的声音)?
可以把音符编译成MIDI格式,然后通过像FluidSynth这样的软件合成器来输出声音。
a) 一种比较“黑科技”的方法是启动一个后台进程来运行每个 play
命令。因为后台进程不会让命令行等它完成,所以你可以同时运行多个 play
命令。像这样就可以实现:
for p in "C3" "E3" "G3"; do ( play -n synth 3 pluck $p & ); done
我看到ninjagecko在我写这段话的时候基本上也发了同样的内容。
b) 关于MIDI数据,有一个关键点需要理解:它更像是制作声音的高级食谱,而不是声音本身。换句话说,每个MIDI音符都包含音高、音量、开始和结束时间,以及其他一些信息。实际的声音是由合成器产生的,而不同的合成器产生的声音质量也不同。如果你对MIDI文件产生的声音不满意,那不是MIDI的问题,而是你的合成器的问题,所以你只需要找一个更好的合成器。(实际上,这通常需要花钱;大多数免费的或便宜的合成器效果都很差。)
另一种选择是深入研究,换句话说,自己实现一个算法来创建吉他的声音。为此,你需要了解一下数字信号处理,特别是像Karplus-Strong算法(这是创建合成拨弦声音的众多方法之一)。这是一个很有趣的主题,但如果你对声音合成的了解仅限于 play
和创建MIDI文件,那你需要学习一些新东西。此外,Python可能不是最好的选择,因为执行速度非常重要。
如果你对数字信号处理感兴趣,可以下载并试试ChucK。
手册中给出了这个例子:
play -n synth pl G2 pl B2 pl D3 pl G3 pl D4 pl G4 \
delay 0 .05 .1 .15 .2 .25 remix - fade 0 4 .1 norm -1
这个例子创建了6个同时运行的合成器实例(作为独立的音频通道),其中5个通道的播放时间稍微延迟了一下,然后把它们混合成一个单一的音频通道。
最终的效果是一个相当不错的吉他和弦;当然,你可以很容易地改变音符或延迟的时间。你还可以调整“吉他”的延音和音色,或者添加一个过载效果——具体细节可以查看手册。