跳到主要内容

程序员的乐理

1 音符 Note 与音程 Interval

1.1 音符 Note

  定义一个音符类 Note,包含两个成员:音名 name 与升降数 acc。音名取值于 AG 七个字母,升降数取任意自然数。音符有友好名称:

  • Note.name 开头。
  • Note.acc 是正数,则添加 Note.acc"#";若是负数,则添加 -Note.acc"b"

Note(name="G", acc=-1) 的友好名称是 Gb

  友好名称十分重要,请尽快熟悉音符的友好名称。

1.2 音程 Interval

  音程是用来描述两个音符之间距离的度量。例如需要度量音符 CEb 之间的“距离”是多远?此时就要定义音程概念。

  定义一个音程类 Interval,包含两个成员:度 num 与质量 quality。度取任意正整数,质量取任意自然数。音程有友好名称:以 Note.num 结尾,前缀由下表给出。

质量 quality-3-2-1012
num 模 8 余 1、4、5 或 7ddddddPAAA
num 模 8 余 2、3、6 或 0dddmMAAA

若希望表达更高或更低的质量,叠加 Ad 即可。友好名称的规则略微复杂,但也请熟练掌握。

Interval(num=3, quality=-1) 的友好名称是 m3Interval(num=4, quality=1) 的友好名称是 A4

 在中文里,PMm 的名称分别是“纯”“大”“小”。AAAddd 的名称分别是“增”“倍增”“减”“倍减”。例如 P5 称为“纯五度”,M6 称为“大六度”。

  友好名称十分重要,请尽快熟悉音符与音程的友好名称。

1.3 音符的减法、音符与音程的加法

  定义两个音符之间的减法运算 Note - Note -> Interval。返回值 Interval 由下面规则给出:

  • 给定字符串 ...ABCDEFGABCDEFG...,返回值的 num 是该字符串中,以减数 Note.name 开头、以被减数 Note.name 结尾的最小子串长度。换言之就是从减数开始,数多少个字母,可以数到被减数。
  • 返回值的 quality 是被减数 Note.acc 与减数 Note.acc 之差。

Gb - C = d5,即 Note(name="G", acc=-1) - Note(name="C", acc=0) = Interval(num=5, quality=-1)。这是因为字符串 CDEFG 长度为 5。而 quality-1 - 0 = -1

B - C = M7,即 Note(name="B", acc=0) - Note(name="C", acc=0) = Interval(num=7, quality=0)。这是因为字符串 CDEFGAB 长度为 7。而 quality0 - 0 = 0

  用相反的方法,可以定义音符与之间的加法运算 Note + Interval -> Note

C + P4 = F。这是因为 C 开头长度为 4 的字符串 CDEF 能“数到” F,而 quality0 + 0 = 0

C + m9 = Db,是因为 C 开头长度为 9 的字符串 CDEFGABCD 能“数到” Db,而 quality0 - 1 = -1

  友好名称十分重要,请尽快熟悉音符与音程的友好名称,以及尽快熟练掌握它们的运算规则。

2 和弦 Chord 与音阶 Scale

2.1 和弦 Chord

  和弦是按照一定规则排列的至多 7 个音的集合。定义和弦类 Chord,包含两个成员:根音 root 与和弦音程 intervals。根音 root 可以是任意音符 Note,和弦音程 intervals 是长度为 7 的音程元组,每一个元素必须依次为纯一度、某种三度(或空)、某种五度(或空)、某种七度(或空)、某种九度(或空)、某种十一度(或空)、某种十三度(或空)。

Chord(C, [P1, M3, P5, M7, M9, None, None])Chord(G, [P1, None, None, m7, M9, M11, None]) 都是合法的和弦。

  和弦音 Chord.notes 是长度为 7 的音符元组,分别是根音、根音加该种三度、该音加该种五度、……、根音加该种十三度。

2.2 和弦的友好名称

P1m3d5m3P5M3P5M3A5
Nonedim 减三和弦m 小三和弦- 大三和弦aug 增三和弦
d7dim7 减七和弦
m7m7 小七和弦7 属七和弦aug7 增七和弦
M7mM7 小大七和弦M7 大七和弦augM7 增大七和弦

3 演奏音符

演奏音符 DisplayNote