在Linux和/或Python中生成吉他和弦的最简单方法

14 投票
3 回答
5037 浏览
提问于 2025-04-16 21:28

我想要实现的目标是让我的Python应用程序播放一个吉他和弦。我知道(或者可以计算出)这个和弦的频率,如果需要的话。

我在想,即使我从底层开始,产生多个正确频率的正弦波,听起来也可能不对,因为声音的包络(也就是声音的起伏变化)也需要正确,否则听起来就像是嗡嗡声,而不是吉他的声音。

让我感到兴奋的是,Linux的sox命令可以用以下方式产生一个相当不错的单音:

play -n synth 0 pluck E3

所以我真正想问的是,

a) 有没有办法让play命令播放整个和弦(最好是稍微错开的开始时间,以模拟拨片拨弦的效果)——我还没有找到办法,但也许有一些bash的技巧可以让它正确发声。如果可以做到这一点,我就满足于从我的代码中调用一个bash命令(我不想重复造轮子)。

b) (更好的是)在Python中有没有办法实现这个(吉他和弦的声音)?我见过一些可用的Python MIDI库,但老实说,MIDI并不适合我想要的声音,至少从我目前的了解来看。

3 个回答

4

a) 有没有办法让播放命令同时播放一个和弦...?

如果你的声音系统支持的话,你可以同时运行多个命令来输出声音。如果你使用的是ALSA(一个声音驱动),你需要在你的~/.asoundrc文件中设置dmix或其他类似的选项。可以使用subprocess.Popen来启动多个子进程。如果这是一个假设的bash脚本,你可以这样做:

command1 &
command2 &
...

b) (更好的是)在python中有没有办法实现这个(吉他和弦的声音)?

可以把音符编译成MIDI格式,然后通过像FluidSynth这样的软件合成器来输出声音。

7

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

14

手册中给出了这个例子:

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个通道的播放时间稍微延迟了一下,然后把它们混合成一个单一的音频通道。

最终的效果是一个相当不错的吉他和弦;当然,你可以很容易地改变音符或延迟的时间。你还可以调整“吉他”的延音和音色,或者添加一个过载效果——具体细节可以查看手册。

撰写回答