上一篇文章 中我简单介绍了如何使用Mido这个库在Python中实现MIDI编程,分享了我的经验和心得,但是单音轨的纯音符堆砌听起来太单薄了,故本篇文章介绍如何轻松添加和弦音轨,使得乐曲更加饱满、丰富。
和弦,简单来讲就是三个及以上的不同音高的音符的组合。这些音符可以同时演奏,形成混响的效果,也可以按照一定的组合方式交替演奏。最常见的和弦有两种:三和弦和七和弦,前者由三个音符组成,又分为四种;后者由四个音符组成,又分为8种,具体分类见下面的表格:
名称 | 音程 |
---|---|
大三和弦 | 大三度、纯五度 |
小三和弦 | 小三度、纯五度 |
增三和弦 | 大三度、增五度 |
减三和弦 | 小三度、减五度 |
名称 | 音程 |
---|---|
大七和弦 | 大三度、完全五度、大七度 |
小七和弦 | 小三度、完全五度、小七度 |
属七和弦(大小七和弦) | 大三度、完全五度、小七度 |
小大七和弦 | 小三度、完全五度、大七度 |
半减七和弦 | 小三度、减五度、减七度 |
减七和弦 | 小三度、减五度、减七度 |
增七和弦 | 大三度、增五度、小七度 |
增大七和弦 | 大三度、增五度、大七度 |
下面这个图是 维基百科 的十二平均律表格,显示了不同音程名称与间隔半音数的对应关系:
结合十二平均律的音程名称和间隔半音数的对照关系,我们就可以动手写和弦了.
首先编写一个方程用于得到不同和弦对应的音程关系:
def get_chord_arrangement(name):
chord_dict = {
'maj3': [0, 4, 7, 0], # 大三和弦 根音-大三度-纯五度
'min3': [0, 3, 7, 0], # 小三和弦 根音-小三度-纯五度
'aug3': [0, 4, 8, 0], # 增三和弦 根音-大三度-增五度
'dim3': [0, 3, 6, 0], # 减三和弦 根音-小三度-减五度
'M7': [0, 4, 7, 11], # 大七和弦 根音-大三度-纯五度-大七度
'Mm7': [0, 4, 7, 10], # 属七和弦 根音-大三度-纯五度-小七度
'm7': [0, 3, 7, 10], # 小七和弦 根音-小三度-纯五度-小七度
'mM7': [0, 3, 7, 11], # 小大七和弦 根音-小三度-纯五度-大七度
'aug7': [0, 4, 8, 10], # 增七和弦 根音-大三度-增五度-小七度
'augM7': [0, 4, 8, 11], # 增大七和弦 根音-大三度-增五度-小七度
'm7b5': [0, 3, 6, 10], # 半减七和弦 根音-小三度-减五度-减七度
'dim7': [0, 3, 6, 9] # 减减七和弦 根音-小三度-减五度-减七度
}
chord = [0, 0, 0, 0]
try:
chord = chord_dict[name]
except:
print(traceback.format_exc())
return chord
返回值是一个长度为4的一维数组,每一个值表示这个音符与根音相差的半音数。
然后编写一个用于将和弦添加到音轨中的函数add_chord:
def add_chord(root, name, format, length, track, root_base=0, channel=3):
bpm = get_bpm(track)
major_notes = [0, 2, 2, 1, 2, 2, 2, 1]
notes = ['C', 'D', 'E', 'F', 'G', 'A', 'B']
notes_dict = {}
for i, note in enumerate(notes):
notes_dict[note] = 60 + sum(major_notes[0:i+1])
root_note = notes_dict[root] + root_base*12
chord = get_chord_arrangement(name)
meta_time = 60 * 60 * 10 / bpm
time = round(length / len(format) * meta_time)
for dis in format:
note = root_note + chord[dis]
track.append(Message('note_on', note=note, velocity=56, time=0, channel=channel))
track.append(Message('note_off', note=note, velocity=56, time=time, channel=channel))
在参数中:
对于《大海啊,故乡》,我按照 网上的吉他谱 为它添加了如下的和弦模式:
def chord(track):
format = [0, 1, 2, 3, 2, 1]
add_chord('C', 'M7', format, 3, track)
add_chord('E', 'm7', format, 3, track)
add_chord('C', 'M7', format, 3, track)
add_chord('D', 'm7', format, 3, track)
add_chord('G', 'Mm7', format, 3, track, -1)
add_chord('D', 'm7', format, 3, track)
add_chord('F', 'M7', format, 3, track, -1)
add_chord('C', 'M7', format, 3, track)
add_chord('C', 'M7', format, 3, track)
add_chord('G', 'M7', format, 3, track, -1)
add_chord('F', 'M7', format, 3, track, -1)
add_chord('G', 'M7', format, 3, track, -1)
add_chord('C', 'M7', format, 3, track)
add_chord('D', 'm7', format, 3, track)
add_chord('G', 'Mm7', format, 3, track)
add_chord('C', 'M7', format, 3, track)
add_chord('C', 'M7', format, 3, track)
add_chord('G', 'M7', format, 3, track, -1)
add_chord('F', 'M7', format, 3, track, -1)
add_chord('G', 'M7', format, 3, track, -1)
add_chord('C', 'M7', format, 3, track)
add_chord('D', 'm7', format, 3, track)
add_chord('G', 'Mm7', format, 3, track)
add_chord('C', 'M7', format, 3, track)
加上和弦之后,我的MIDI文件在MidiEditor中显示如下:
感谢阅读,完整的项目代码详见 Github - Truedick23/MusicCritique
和弦 - 维基百科
十二平均律 - 维基百科