二、基本调式
TL;DR: 自然大调指的是1234567,自然小调指的是6712345,旋律小调是自然小调的4、5可能升半音成#4、#5形成的调式。
0. 音名与唱名
嗯,之前说过音名的主体是CDEFGAB七个,它们之前的关系是差2、2、1、2、2、2、1个半音;那么同样是七个的,我们熟知的另一套术语,是 do re mi fa sol la si,或者写成数字的1234567或者罗马数字的I II III IV V VI VII,名字叫“唱名”,两套术语之间的对应关系是什么呢?
不同的著作可能有不同的说法,但是在我这里规定为:
- CDEFGAB(包括其升降形式)是音名,表示的是绝对音高
- 1234567(包括其升降形式)是唱名,表示的是相对音高
音名一般用于实际演奏,唱名用于演唱或分析。在不同的调性(移调转调)中,1可能对应不同的音名,比如在C自然大调中,1234567对应CDEFGAB;在B自然大调中,1234567对应B#C#DE#F#G#A。
1. 自然大调
自然大调就是由“差2、2、1、2、2、2、1个半音”的音构成、且认为“八度”是一个周期的调式,写成唱名就是1234567,就是钢琴的白键。它的“自然”更多地体现在历史传承上而不是物理上的自然。绝大多数调式都可以认为是自然大调的变体。有一个隐藏假设有必要提一下:
- “八度”周期。指的是,从1234567往上或往下延伸(解析延拓),还是 \dot1\dot2\dot3\dot4\dot5\dot6\dot7 或 \underset{\bullet}1\underset{\bullet}2\underset{\bullet}3\underset{\bullet}4\underset{\bullet}5\underset{\bullet}6\underset{\bullet}7 ,以八度为一个周期。这个性质在大多数调式都是适用的,但是也有一些奇怪的调式并非如此,比如以五度为一个周期。
让我们用更好听的方式来听一听示例:
自然大调示例:小红帽(节选)
from ctypes import windll, c_longlong, pointer
from enum import Enum
kernel32 = windll.kernel32
Sleep = kernel32.Sleep
QueryPerformanceCounter = kernel32.QueryPerformanceCounter
QueryPerformanceFrequency = kernel32.QueryPerformanceFrequency
winmm = windll.winmm
midiOutOpen = winmm.midiOutOpen
midiOutClose = winmm.midiOutClose
midiOutShortMsg = winmm.midiOutShortMsg
class Notes(Enum):
C1 = 24
bD1 = 25
D1 = 26
bE1 = 27
E1 = 28
F1 = 29
bG1 = 30
G1 = 31
bA1 = 32
A1 = 33
bB1 = 34
B1 = 35
C2 = 36
bD2 = 37
D2 = 38
bE2 = 39
E2 = 40
F2 = 41
bG2 = 42
G2 = 43
bA2 = 44
A2 = 45
bB2 = 46
B2 = 47
C3 = 48
bD3 = 49
D3 = 50
bE3 = 51
E3 = 52
F3 = 53
bG3 = 54
G3 = 55
bA3 = 56
A3 = 57
bB3 = 58
B3 = 59
C4 = 60
bD4 = 61
D4 = 62
bE4 = 63
E4 = 64
F4 = 65
bG4 = 66
G4 = 67
bA4 = 68
A4 = 69
bB4 = 70
B4 = 71
C5 = 72
bD5 = 73
D5 = 74
bE5 = 75
E5 = 76
F5 = 77
bG5 = 78
G5 = 79
bA5 = 80
A5 = 81
bB5 = 82
B5 = 83
C6 = 84
bD6 = 85
D6 = 86
bE6 = 87
E6 = 88
F6 = 89
bG6 = 90
G6 = 91
bA6 = 92
A6 = 93
bB6 = 94
B6 = 95
class Velocities(Enum):
pppp = 8
ppp = 20
pp = 31
p = 42
mp = 53
mf = 64
f = 80
ff = 96
fff = 112
ffff = 127
class Instrument(Enum):
AcousticGrandPiano = 0
BrightAcousticPiano = 1
ElectricGrandPiano = 2
HonkyTonkPiano = 3
RhodesPiano = 4
ChorusedPiano = 5
Harpsichord = 6
Clavinet = 7
Celesta = 8
Glockenspiel = 9
MusicBox = 10
Vibraphone = 11
Marimba = 12
Xylophone = 13
TubularBells = 14
Dulcimer = 15
DrawbarOrgan = 16
PercussiveOrgan = 17
RockOrgan = 18
ChurchOrgan = 19
ReedOrgan = 20
Accordion = 21
Harmonica = 22
TangoAccordion = 23
AcousticGuitarNylon = 24
AcousticGuitarSteel = 25
ElectricGuitarJazz = 26
ElectricGuitarClean = 27
ElectricGuitarMuted = 28
OverdrivenGuitar = 29
DistortionGuitar = 30
GuitarHarmonics = 31
AcousticBass = 32
ElectricBassFinger = 33
ElectricBassPick = 34
FretlessBass = 35
SlapBass1 = 36
SlapBass2 = 37
SynthBass1 = 38
SynthBass2 = 39
Violin = 40
Viola = 41
Cello = 42
Contrabass = 43
TremoloStrings = 44
PizzicatoStrings = 45
OrchestralHarp = 46
Timpani = 47
StringEnsemble1 = 48
StringEnsemble2 = 49
SynthStrings1 = 50
SynthStrings2 = 51
ChoirAahs = 52
VoiceOohs = 53
SynthVoice = 54
OrchestraHit = 55
Trumpet = 56
Trombone = 57
Tuba = 58
MutedTrumpet = 59
FrenchHorn = 60
BrassSection = 61
SynthBrass1 = 62
SynthBrass2 = 63
SopranoSax = 64
AltoSax = 65
TenorSax = 66
BaritoneSax = 67
Oboe = 68
EnglishHorn = 69
Bassoon = 70
Clarinet = 71
Piccolo = 72
Flute = 73
Recorder = 74
PanFlute = 75
BlownBottle = 76
Shakuhachi = 77
Whistle = 78
Ocarina = 79
Lead1Square = 80
Lead2Sawtooth = 81
Lead3Calliope = 82
Lead4Chiff = 83
Lead5Charang = 84
Lead6Voice = 85
Lead7Fifths = 86
Lead8BassLead = 87
Pad1NewAge = 88
Pad2Warm = 89
Pad3Polysynth = 90
Pad5Bowed = 92
Pad6Metallic = 93
Pad7Halo = 94
Pad8Sweep = 95
FX1Rain = 96
FX2Soundtrack = 97
FX3Crystal = 98
FX4Atmosphere = 99
FX5Brightness = 100
FX6Goblins = 101
FX7Echoes = 102
FX8SciFi = 103
Sitar = 104
Banjo = 105
Shamisen = 106
Koto = 107
Kalimba = 108
Bagpipe = 109
Fiddle = 110
Shanai = 111
TinkleBell = 112
Agogo = 113
SteelDrums = 114
Woodblock = 115
TaikoDrum = 116
MelodicTom = 117
SynthDrum = 118
ReverseCymbal = 119
GuitarFretNoise = 120
BreathNoise = 121
Seashore = 122
BirdTweet = 123
TelephoneRing = 124
Helicopter = 125
Applause = 126
Gunshot = 127
class Player:
def __init__(self, tracks, tempo):
val = c_longlong()
QueryPerformanceFrequency(pointer(val))
self.frequency = 1000 / val.value
self.hmo = c_longlong()
midiOutOpen(pointer(self.hmo), 0, 0, 0, 0)
for i, instrument in enumerate(tracks):
self.ChangeInstrument(i, instrument.value)
self.tick = 60000 / tempo
self.stamp = 0
self.total_tick = 0
def timestamp(self) -> float:
val = c_longlong()
QueryPerformanceCounter(pointer(val))
return val.value
def reset_timer_wait(self):
self.total_tick = 0
self.stamp = self.timestamp()
def timer_wait(self, d):
self.total_tick += d
t = d - 20
if t > 0:
Sleep(int(t))
while (self.timestamp() - self.stamp) * self.frequency < self.total_tick:
pass
def close(self):
midiOutClose(self.hmo)
def SendMidiEvent(self, bStatus, bData1, bData2):
return midiOutShortMsg(self.hmo, bStatus | (bData1 << 8) | (bData2 << 16))
def NoteOn(self, track, note, velocity):
return self.SendMidiEvent(0x90 | track, note, velocity)
def NoteOff(self, track, note):
return self.SendMidiEvent(0x80 | track, note, 0)
def ChangeInstrument(self, track, instrument):
return self.SendMidiEvent(0xC0 | track, instrument, 0)
def play(self, records):
self.reset_timer_wait()
notes = []
for record in records:
note = record[0]
if note == 0: # proceed
val = record[2] + (record[3] << 8)
while val != 0:
min_time = val
for rec in notes:
if rec[2] < min_time:
min_time = rec[2]
self.timer_wait(self.tick * min_time)
val -= min_time
new_notes = []
for rec in notes:
rec[2] -= min_time
if rec[2] == 0:
self.NoteOff(rec[1], rec[0].value)
else:
new_notes.append(rec)
notes = new_notes
else:
notes.append(record)
self.NoteOn(record[1], note.value, record[3].value)
def proceed(d):
return [0, 0, d, 0]
if __name__ == '__main__':
tempo = 240
tracks = [
Instrument.AcousticGuitarSteel,
]
player = Player(tracks, tempo)
player.play([
[Notes.C4, 0, 1, Velocities.ff],
proceed(1),
[Notes.D4, 0, 1, Velocities.f],
proceed(1),
[Notes.E4, 0, 1, Velocities.f],
proceed(1),
[Notes.F4, 0, 1, Velocities.f],
proceed(1),
[Notes.G4, 0, 2, Velocities.ff],
proceed(2),
[Notes.E4, 0, 1, Velocities.f],
proceed(1),
[Notes.C4, 0, 1, Velocities.f],
proceed(1),
[Notes.C5, 0, 2, Velocities.ff],
proceed(2),
[Notes.A4, 0, 1, Velocities.f],
proceed(1),
[Notes.F4, 0, 1, Velocities.f],
proceed(1),
[Notes.G4, 0, 1, Velocities.ff],
proceed(1),
[Notes.G4, 0, 1, Velocities.f],
proceed(1),
[Notes.E4, 0, 2, Velocities.f],
proceed(2),
[Notes.C4, 0, 1, Velocities.ff],
proceed(1),
[Notes.D4, 0, 1, Velocities.f],
proceed(1),
[Notes.E4, 0, 1, Velocities.f],
proceed(1),
[Notes.F4, 0, 1, Velocities.f],
proceed(1),
[Notes.G4, 0, 1, Velocities.ff],
proceed(1),
[Notes.E4, 0, 1, Velocities.f],
proceed(1),
[Notes.D4, 0, 1, Velocities.f],
proceed(1),
[Notes.C4, 0, 1, Velocities.f],
proceed(1),
[Notes.D4, 0, 2, Velocities.ff],
proceed(2),
[Notes.E4, 0, 2, Velocities.f],
proceed(2),
[Notes.D4, 0, 2, Velocities.ff],
proceed(2),
[Notes.G4, 0, 2, Velocities.f],
proceed(2),
[Notes.C4, 0, 1, Velocities.ff],
proceed(1),
[Notes.D4, 0, 1, Velocities.f],
proceed(1),
[Notes.E4, 0, 1, Velocities.f],
proceed(1),
[Notes.F4, 0, 1, Velocities.f],
proceed(1),
[Notes.G4, 0, 2, Velocities.ff],
proceed(2),
[Notes.E4, 0, 1, Velocities.f],
proceed(1),
[Notes.C4, 0, 1, Velocities.f],
proceed(1),
[Notes.C5, 0, 2, Velocities.ff],
proceed(2),
[Notes.A4, 0, 1, Velocities.f],
proceed(1),
[Notes.F4, 0, 1, Velocities.f],
proceed(1),
[Notes.G4, 0, 2, Velocities.ff],
proceed(2),
[Notes.E4, 0, 2, Velocities.f],
proceed(2),
[Notes.C4, 0, 1, Velocities.ff],
proceed(1),
[Notes.D4, 0, 1, Velocities.f],
proceed(1),
[Notes.E4, 0, 1, Velocities.f],
proceed(1),
[Notes.F4, 0, 1, Velocities.f],
proceed(1),
[Notes.G4, 0, 1, Velocities.ff],
proceed(1),
[Notes.E4, 0, 1, Velocities.f],
proceed(1),
[Notes.D4, 0, 1, Velocities.f],
proceed(1),
[Notes.C4, 0, 1, Velocities.f],
proceed(1),
[Notes.D4, 0, 2, Velocities.ff],
proceed(2),
[Notes.E4, 0, 2, Velocities.f],
proceed(2),
[Notes.C4, 0, 2, Velocities.ff],
proceed(2),
[Notes.C4, 0, 2, Velocities.f],
proceed(2),
])
Sleep(1000)
player.close()
传统观点认为,在满足用音为1234567的前提下,自然大调的乐曲的特征有(从严格到宽松):
- 主旋律的音以1开始、以1结尾;上面的《小红帽》就是一个典型的例子
- 主旋律的音不一定以1开始,但是以1结尾;典型的例子是4536251和弦进行的歌曲,之后会细讲
- 主旋律的音不一定以1开始或结尾,但是主旋律与1关系密切,这时候可能没有直接的套路来判断;可能的例子是,一首歌没有结尾(比如选择用循环渐弱的方式结尾)
新兴观点会之后讲。
传统观点认为自然大调乐曲的特征是“具有光辉,明朗的色彩”。空客在此指出,音乐风格是综合特征,不应机械地理解;而“调式”是一个非常灵活的量,最多只能确定一个大方向,具体的判断仍需自底而上地分析。
2. 自然小调
自然小调可以认为是自然大调的最常见的变体,由“差2、1、2、2、1、2、2个半音”的音阶构成,同样认为“八度”是一个周期,写成唱名是6712345。
可以发现,自然小调就是以自然大调的6开头的调式,其音高构成的集合与自然大调完全相同,只不过主音不同。
自然小调示例:青春舞曲(节选)
from ctypes import windll, c_longlong, pointer
from enum import Enum
kernel32 = windll.kernel32
Sleep = kernel32.Sleep
QueryPerformanceCounter = kernel32.QueryPerformanceCounter
QueryPerformanceFrequency = kernel32.QueryPerformanceFrequency
winmm = windll.winmm
midiOutOpen = winmm.midiOutOpen
midiOutClose = winmm.midiOutClose
midiOutShortMsg = winmm.midiOutShortMsg
class Notes(Enum):
C1 = 24
bD1 = 25
D1 = 26
bE1 = 27
E1 = 28
F1 = 29
bG1 = 30
G1 = 31
bA1 = 32
A1 = 33
bB1 = 34
B1 = 35
C2 = 36
bD2 = 37
D2 = 38
bE2 = 39
E2 = 40
F2 = 41
bG2 = 42
G2 = 43
bA2 = 44
A2 = 45
bB2 = 46
B2 = 47
C3 = 48
bD3 = 49
D3 = 50
bE3 = 51
E3 = 52
F3 = 53
bG3 = 54
G3 = 55
bA3 = 56
A3 = 57
bB3 = 58
B3 = 59
C4 = 60
bD4 = 61
D4 = 62
bE4 = 63
E4 = 64
F4 = 65
bG4 = 66
G4 = 67
bA4 = 68
A4 = 69
bB4 = 70
B4 = 71
C5 = 72
bD5 = 73
D5 = 74
bE5 = 75
E5 = 76
F5 = 77
bG5 = 78
G5 = 79
bA5 = 80
A5 = 81
bB5 = 82
B5 = 83
C6 = 84
bD6 = 85
D6 = 86
bE6 = 87
E6 = 88
F6 = 89
bG6 = 90
G6 = 91
bA6 = 92
A6 = 93
bB6 = 94
B6 = 95
class Velocities(Enum):
pppp = 8
ppp = 20
pp = 31
p = 42
mp = 53
mf = 64
f = 80
ff = 96
fff = 112
ffff = 127
class Instrument(Enum):
AcousticGrandPiano = 0
BrightAcousticPiano = 1
ElectricGrandPiano = 2
HonkyTonkPiano = 3
RhodesPiano = 4
ChorusedPiano = 5
Harpsichord = 6
Clavinet = 7
Celesta = 8
Glockenspiel = 9
MusicBox = 10
Vibraphone = 11
Marimba = 12
Xylophone = 13
TubularBells = 14
Dulcimer = 15
DrawbarOrgan = 16
PercussiveOrgan = 17
RockOrgan = 18
ChurchOrgan = 19
ReedOrgan = 20
Accordion = 21
Harmonica = 22
TangoAccordion = 23
AcousticGuitarNylon = 24
AcousticGuitarSteel = 25
ElectricGuitarJazz = 26
ElectricGuitarClean = 27
ElectricGuitarMuted = 28
OverdrivenGuitar = 29
DistortionGuitar = 30
GuitarHarmonics = 31
AcousticBass = 32
ElectricBassFinger = 33
ElectricBassPick = 34
FretlessBass = 35
SlapBass1 = 36
SlapBass2 = 37
SynthBass1 = 38
SynthBass2 = 39
Violin = 40
Viola = 41
Cello = 42
Contrabass = 43
TremoloStrings = 44
PizzicatoStrings = 45
OrchestralHarp = 46
Timpani = 47
StringEnsemble1 = 48
StringEnsemble2 = 49
SynthStrings1 = 50
SynthStrings2 = 51
ChoirAahs = 52
VoiceOohs = 53
SynthVoice = 54
OrchestraHit = 55
Trumpet = 56
Trombone = 57
Tuba = 58
MutedTrumpet = 59
FrenchHorn = 60
BrassSection = 61
SynthBrass1 = 62
SynthBrass2 = 63
SopranoSax = 64
AltoSax = 65
TenorSax = 66
BaritoneSax = 67
Oboe = 68
EnglishHorn = 69
Bassoon = 70
Clarinet = 71
Piccolo = 72
Flute = 73
Recorder = 74
PanFlute = 75
BlownBottle = 76
Shakuhachi = 77
Whistle = 78
Ocarina = 79
Lead1Square = 80
Lead2Sawtooth = 81
Lead3Calliope = 82
Lead4Chiff = 83
Lead5Charang = 84
Lead6Voice = 85
Lead7Fifths = 86
Lead8BassLead = 87
Pad1NewAge = 88
Pad2Warm = 89
Pad3Polysynth = 90
Pad5Bowed = 92
Pad6Metallic = 93
Pad7Halo = 94
Pad8Sweep = 95
FX1Rain = 96
FX2Soundtrack = 97
FX3Crystal = 98
FX4Atmosphere = 99
FX5Brightness = 100
FX6Goblins = 101
FX7Echoes = 102
FX8SciFi = 103
Sitar = 104
Banjo = 105
Shamisen = 106
Koto = 107
Kalimba = 108
Bagpipe = 109
Fiddle = 110
Shanai = 111
TinkleBell = 112
Agogo = 113
SteelDrums = 114
Woodblock = 115
TaikoDrum = 116
MelodicTom = 117
SynthDrum = 118
ReverseCymbal = 119
GuitarFretNoise = 120
BreathNoise = 121
Seashore = 122
BirdTweet = 123
TelephoneRing = 124
Helicopter = 125
Applause = 126
Gunshot = 127
class Player:
def __init__(self, tracks, tempo):
val = c_longlong()
QueryPerformanceFrequency(pointer(val))
self.frequency = 1000 / val.value
self.hmo = c_longlong()
midiOutOpen(pointer(self.hmo), 0, 0, 0, 0)
for i, instrument in enumerate(tracks):
self.ChangeInstrument(i, instrument.value)
self.tick = 60000 / tempo
self.stamp = 0
self.total_tick = 0
def timestamp(self) -> float:
val = c_longlong()
QueryPerformanceCounter(pointer(val))
return val.value
def reset_timer_wait(self):
self.total_tick = 0
self.stamp = self.timestamp()
def timer_wait(self, d):
self.total_tick += d
t = d - 20
if t > 0:
Sleep(int(t))
while (self.timestamp() - self.stamp) * self.frequency < self.total_tick:
pass
def close(self):
midiOutClose(self.hmo)
def SendMidiEvent(self, bStatus, bData1, bData2):
return midiOutShortMsg(self.hmo, bStatus | (bData1 << 8) | (bData2 << 16))
def NoteOn(self, track, note, velocity):
return self.SendMidiEvent(0x90 | track, note, velocity)
def NoteOff(self, track, note):
return self.SendMidiEvent(0x80 | track, note, 0)
def ChangeInstrument(self, track, instrument):
return self.SendMidiEvent(0xC0 | track, instrument, 0)
def play(self, records):
self.reset_timer_wait()
notes = []
for record in records:
note = record[0]
if note == 0: # proceed
val = record[2] + (record[3] << 8)
while val != 0:
min_time = val
for rec in notes:
if rec[2] < min_time:
min_time = rec[2]
self.timer_wait(self.tick * min_time)
val -= min_time
new_notes = []
for rec in notes:
rec[2] -= min_time
if rec[2] == 0:
self.NoteOff(rec[1], rec[0].value)
else:
new_notes.append(rec)
notes = new_notes
else:
notes.append(record)
self.NoteOn(record[1], note.value, record[3].value)
def proceed(d):
return [0, 0, d, 0]
if __name__ == '__main__':
tempo = 240
tracks = [
Instrument.Trumpet,
]
player = Player(tracks, tempo)
player.play([
[Notes.A4, 0, 1, Velocities.ff],
proceed(1),
[Notes.B4, 0, 1, Velocities.f],
proceed(1),
[Notes.C5, 0, 1, Velocities.f],
proceed(1),
[Notes.D5, 0, 1, Velocities.f],
proceed(1),
[Notes.E5, 0, 2, Velocities.ff],
proceed(2),
[Notes.A5, 0, 2, Velocities.f],
proceed(2),
[Notes.E5, 0, 1, Velocities.ff],
proceed(1),
[Notes.E5, 0, 2, Velocities.f],
proceed(2),
[Notes.D5, 0, 1, Velocities.f],
proceed(1),
[Notes.E5, 0, 1, Velocities.fff],
proceed(4),
[Notes.E5, 0, 1, Velocities.ff],
proceed(1),
[Notes.D5, 0, 1, Velocities.f],
proceed(1),
[Notes.B4, 0, 1, Velocities.f],
proceed(1),
[Notes.C5, 0, 1, Velocities.f],
proceed(1),
[Notes.E5, 0, 1, Velocities.ff],
proceed(1),
[Notes.D5, 0, 1, Velocities.f],
proceed(1),
[Notes.C5, 0, 1, Velocities.f],
proceed(1),
[Notes.B4, 0, 1, Velocities.f],
proceed(1),
[Notes.A4, 0, 2, Velocities.ff],
proceed(2),
[Notes.A4, 0, 2, Velocities.f],
proceed(2),
[Notes.A4, 0, 2, Velocities.ff],
proceed(4),
])
Sleep(1000)
player.close()
同样,传统观点认为,在满足用音为1234567的前提下,自然小调的乐曲的特征有(从严格到宽松):
- 主旋律的音以6开始、以6结尾;上面的《青春舞曲》就是一个典型的例子
- 主旋律的音不一定以6开始,但是以6结尾;典型的例子是以1或3开头
- 主旋律的音不一定以6开始或结尾,但是主旋律与6关系密切
传统观点认为自然小调乐曲特征是“该调式具有柔和、暗淡的听觉特征,常表现出忧郁、唯美的音乐情感”,显然也是片面的——上面那个示例直接以67123开头、以6结尾,显然非常符合自然小调的定义;然而或许带有一点忧伤,但绝不是“柔和”、“暗淡”的。
3. 和声小调与旋律小调
和声小调和旋律小调都是自然小调的变体,其“变”之处在于有时会将自然小调的4、5升一个半音,变成#4、#5;具体在什么样的情况下会变,不确定,要看乐曲的走向。
传统观点严格区分和声小调与旋律小调,认为和声小调只升5,而且是在任何情况下都升这个5,而旋律小调在上行音阶升4和5、在下行音阶维持不变。这种判断规则过于死板,空客在此不矛采用,并且不区分和声小调与旋律小调,下统称为“旋律小调”。
旋律小调示例:绿袖子(主歌)
from ctypes import windll, c_longlong, pointer
from enum import Enum
kernel32 = windll.kernel32
Sleep = kernel32.Sleep
QueryPerformanceCounter = kernel32.QueryPerformanceCounter
QueryPerformanceFrequency = kernel32.QueryPerformanceFrequency
winmm = windll.winmm
midiOutOpen = winmm.midiOutOpen
midiOutClose = winmm.midiOutClose
midiOutShortMsg = winmm.midiOutShortMsg
class Notes(Enum):
C1 = 24
bD1 = 25
D1 = 26
bE1 = 27
E1 = 28
F1 = 29
bG1 = 30
G1 = 31
bA1 = 32
A1 = 33
bB1 = 34
B1 = 35
C2 = 36
bD2 = 37
D2 = 38
bE2 = 39
E2 = 40
F2 = 41
bG2 = 42
G2 = 43
bA2 = 44
A2 = 45
bB2 = 46
B2 = 47
C3 = 48
bD3 = 49
D3 = 50
bE3 = 51
E3 = 52
F3 = 53
bG3 = 54
G3 = 55
bA3 = 56
A3 = 57
bB3 = 58
B3 = 59
C4 = 60
bD4 = 61
D4 = 62
bE4 = 63
E4 = 64
F4 = 65
bG4 = 66
G4 = 67
bA4 = 68
A4 = 69
bB4 = 70
B4 = 71
C5 = 72
bD5 = 73
D5 = 74
bE5 = 75
E5 = 76
F5 = 77
bG5 = 78
G5 = 79
bA5 = 80
A5 = 81
bB5 = 82
B5 = 83
C6 = 84
bD6 = 85
D6 = 86
bE6 = 87
E6 = 88
F6 = 89
bG6 = 90
G6 = 91
bA6 = 92
A6 = 93
bB6 = 94
B6 = 95
class Velocities(Enum):
pppp = 8
ppp = 20
pp = 31
p = 42
mp = 53
mf = 64
f = 80
ff = 96
fff = 112
ffff = 127
class Instrument(Enum):
AcousticGrandPiano = 0
BrightAcousticPiano = 1
ElectricGrandPiano = 2
HonkyTonkPiano = 3
RhodesPiano = 4
ChorusedPiano = 5
Harpsichord = 6
Clavinet = 7
Celesta = 8
Glockenspiel = 9
MusicBox = 10
Vibraphone = 11
Marimba = 12
Xylophone = 13
TubularBells = 14
Dulcimer = 15
DrawbarOrgan = 16
PercussiveOrgan = 17
RockOrgan = 18
ChurchOrgan = 19
ReedOrgan = 20
Accordion = 21
Harmonica = 22
TangoAccordion = 23
AcousticGuitarNylon = 24
AcousticGuitarSteel = 25
ElectricGuitarJazz = 26
ElectricGuitarClean = 27
ElectricGuitarMuted = 28
OverdrivenGuitar = 29
DistortionGuitar = 30
GuitarHarmonics = 31
AcousticBass = 32
ElectricBassFinger = 33
ElectricBassPick = 34
FretlessBass = 35
SlapBass1 = 36
SlapBass2 = 37
SynthBass1 = 38
SynthBass2 = 39
Violin = 40
Viola = 41
Cello = 42
Contrabass = 43
TremoloStrings = 44
PizzicatoStrings = 45
OrchestralHarp = 46
Timpani = 47
StringEnsemble1 = 48
StringEnsemble2 = 49
SynthStrings1 = 50
SynthStrings2 = 51
ChoirAahs = 52
VoiceOohs = 53
SynthVoice = 54
OrchestraHit = 55
Trumpet = 56
Trombone = 57
Tuba = 58
MutedTrumpet = 59
FrenchHorn = 60
BrassSection = 61
SynthBrass1 = 62
SynthBrass2 = 63
SopranoSax = 64
AltoSax = 65
TenorSax = 66
BaritoneSax = 67
Oboe = 68
EnglishHorn = 69
Bassoon = 70
Clarinet = 71
Piccolo = 72
Flute = 73
Recorder = 74
PanFlute = 75
BlownBottle = 76
Shakuhachi = 77
Whistle = 78
Ocarina = 79
Lead1Square = 80
Lead2Sawtooth = 81
Lead3Calliope = 82
Lead4Chiff = 83
Lead5Charang = 84
Lead6Voice = 85
Lead7Fifths = 86
Lead8BassLead = 87
Pad1NewAge = 88
Pad2Warm = 89
Pad3Polysynth = 90
Pad5Bowed = 92
Pad6Metallic = 93
Pad7Halo = 94
Pad8Sweep = 95
FX1Rain = 96
FX2Soundtrack = 97
FX3Crystal = 98
FX4Atmosphere = 99
FX5Brightness = 100
FX6Goblins = 101
FX7Echoes = 102
FX8SciFi = 103
Sitar = 104
Banjo = 105
Shamisen = 106
Koto = 107
Kalimba = 108
Bagpipe = 109
Fiddle = 110
Shanai = 111
TinkleBell = 112
Agogo = 113
SteelDrums = 114
Woodblock = 115
TaikoDrum = 116
MelodicTom = 117
SynthDrum = 118
ReverseCymbal = 119
GuitarFretNoise = 120
BreathNoise = 121
Seashore = 122
BirdTweet = 123
TelephoneRing = 124
Helicopter = 125
Applause = 126
Gunshot = 127
class Player:
def __init__(self, tracks, tempo):
val = c_longlong()
QueryPerformanceFrequency(pointer(val))
self.frequency = 1000 / val.value
self.hmo = c_longlong()
midiOutOpen(pointer(self.hmo), 0, 0, 0, 0)
for i, instrument in enumerate(tracks):
self.ChangeInstrument(i, instrument.value)
self.tick = 60000 / tempo
self.stamp = 0
self.total_tick = 0
def timestamp(self) -> float:
val = c_longlong()
QueryPerformanceCounter(pointer(val))
return val.value
def reset_timer_wait(self):
self.total_tick = 0
self.stamp = self.timestamp()
def timer_wait(self, d):
self.total_tick += d
t = d - 20
if t > 0:
Sleep(int(t))
while (self.timestamp() - self.stamp) * self.frequency < self.total_tick:
pass
def close(self):
midiOutClose(self.hmo)
def SendMidiEvent(self, bStatus, bData1, bData2):
return midiOutShortMsg(self.hmo, bStatus | (bData1 << 8) | (bData2 << 16))
def NoteOn(self, track, note, velocity):
return self.SendMidiEvent(0x90 | track, note, velocity)
def NoteOff(self, track, note):
return self.SendMidiEvent(0x80 | track, note, 0)
def ChangeInstrument(self, track, instrument):
return self.SendMidiEvent(0xC0 | track, instrument, 0)
def play(self, records):
self.reset_timer_wait()
notes = []
for record in records:
note = record[0]
if note == 0: # proceed
val = record[2] + (record[3] << 8)
while val != 0:
min_time = val
for rec in notes:
if rec[2] < min_time:
min_time = rec[2]
self.timer_wait(self.tick * min_time)
val -= min_time
new_notes = []
for rec in notes:
rec[2] -= min_time
if rec[2] == 0:
self.NoteOff(rec[1], rec[0].value)
else:
new_notes.append(rec)
notes = new_notes
else:
notes.append(record)
self.NoteOn(record[1], note.value, record[3].value)
def proceed(d):
return [0, 0, d, 0]
if __name__ == '__main__':
tempo = 240
tracks = [
Instrument.BrightAcousticPiano,
]
player = Player(tracks, tempo)
player.play([
[Notes.A3, 0, 2, Velocities.f],
proceed(2),
[Notes.C4, 0, 4, Velocities.ff],
proceed(4),
[Notes.D4, 0, 2, Velocities.f],
proceed(2),
[Notes.E4, 0, 3, Velocities.ff],
proceed(3),
[Notes.bG4, 0, 1, Velocities.f],
proceed(1),
[Notes.E4, 0, 2, Velocities.f],
proceed(2),
[Notes.D4, 0, 4, Velocities.ff],
proceed(4),
[Notes.B3, 0, 2, Velocities.f],
proceed(2),
[Notes.G3, 0, 3, Velocities.ff],
proceed(3),
[Notes.A3, 0, 1, Velocities.f],
proceed(1),
[Notes.B3, 0, 2, Velocities.f],
proceed(2),
[Notes.C4, 0, 4, Velocities.ff],
proceed(4),
[Notes.A3, 0, 2, Velocities.f],
proceed(2),
[Notes.A3, 0, 3, Velocities.ff],
proceed(3),
[Notes.bA3, 0, 1, Velocities.f],
proceed(1),
[Notes.A3, 0, 2, Velocities.f],
proceed(2),
[Notes.B3, 0, 4, Velocities.ff],
proceed(4),
[Notes.bA3, 0, 2, Velocities.f],
proceed(2),
[Notes.E3, 0, 4, Velocities.ff],
proceed(4),
[Notes.A3, 0, 2, Velocities.f],
proceed(2),
[Notes.C4, 0, 4, Velocities.ff],
proceed(4),
[Notes.D4, 0, 2, Velocities.f],
proceed(2),
[Notes.E4, 0, 3, Velocities.ff],
proceed(3),
[Notes.bG4, 0, 1, Velocities.f],
proceed(1),
[Notes.E4, 0, 2, Velocities.f],
proceed(2),
[Notes.D4, 0, 4, Velocities.ff],
proceed(4),
[Notes.B3, 0, 2, Velocities.f],
proceed(2),
[Notes.G3, 0, 3, Velocities.ff],
proceed(3),
[Notes.A3, 0, 1, Velocities.f],
proceed(1),
[Notes.B3, 0, 2, Velocities.f],
proceed(2),
[Notes.C4, 0, 3, Velocities.ff],
proceed(3),
[Notes.B3, 0, 1, Velocities.f],
proceed(1),
[Notes.A3, 0, 2, Velocities.f],
proceed(2),
[Notes.bA3, 0, 2, Velocities.ff],
proceed(2),
[Notes.bG3, 0, 2, Velocities.f],
proceed(2),
[Notes.bA3, 0, 2, Velocities.f],
proceed(2),
[Notes.A3, 0, 6, Velocities.ff],
proceed(6),
[Notes.A3, 0, 4, Velocities.ff],
proceed(4),
])
Sleep(1000)
player.close()
旋律小调的判断就相对容易,因为本身就是在自然小调的基础上进行微调,所以只要抓住关键音#4、#5即可判断,一般来说,有相当比例的#4、#5则为旋律小调。不过也要注意例外:如果#4远多于#5且#4有时不跟3、6一起出现,则有可能是两种教会调式:Lydian调式/Dorian调式。
传统观点认为,和声小调“能产生紧张、戏剧性的音乐效果,比自然小调更强调小调色彩”,而旋律小调“主要用于表现悲伤、愁绪等情感”。可以发现,很多话都是说了等于没说,具体问题还是需要具体分析。
下一章打算开个插曲讲一下局部的音程关系,然后一章是节奏型,然后是复杂调式,然后是和弦等等。