-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpykovsky.py
More file actions
executable file
·113 lines (85 loc) · 3 KB
/
Copy pathpykovsky.py
File metadata and controls
executable file
·113 lines (85 loc) · 3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
from PMIDI.Composer import Sequencer
import time
import random
C_SCALE = ['C', 'D', 'E', 'F', 'G', 'A', 'B']
CHORDS = {'C': ['C', 'E', 'G'],
'D': ['D', 'F', 'A'],
'd': ['D', 'F', 'A'],
'E': ['E', 'G', 'B'],
'F': ['F', 'A', 'C'],
'G': ['G', 'B', 'D'],
'A': ['A', 'C', 'E'],
'a': ['A', 'C', 'E'],
'B': ['B', 'D', 'F']}
F_PROG = [[5, 5, 5, 4, 4, 4, 6, 6, 1, 3],
[5, 5, 5, 4, 4, 6, 6, 1, 3],
[6, 6, 6, 4, 4, 1, 2, 5],
[5, 5, 5, 1, 1, 2, 2, 3, 6],
[1, 1, 1, 4, 4, 6, 6, 2, 3],
[2, 2, 2, 5, 5, 3, 3, 4, 4, 1],
[1, 1, 1, 3, 3, 3, 6, 6, 2, 4]]
def get_next_chord(chord):
""" Gets a chord to add to the progression based on the fundamental progression rules """
num = C_SCALE.index(chord)
candidates = F_PROG[num-1]
return C_SCALE[random.choice(candidates)]
def add_chord(meas, chord_name):
""" Adds a chord to the measure """
for note in CHORDS[chord_name]:
meas.NewNote(0, 64, note, 5)
def create_base(inst):
""" Creates the chord progression """
strophe = []
chorus = []
chord = C_SCALE[0]
for i in range(4):
strophe.append(chord)
chord = get_next_chord(chord)
for i in range(4):
chorus.append(chord)
chord = get_next_chord(chord)
chord_progression = strophe + strophe + chorus + strophe
for c in chord_progression:
meas = inst.NewMeasure()
add_chord(meas, c)
return chord_progression
def get_rdm_note(chord, last_note):
""" Gets a random note based on the current chord """
if random.randint(1,10) <= 6:
# chord note
return random.choice(CHORDS[chord])
else:
# scale note
n = C_SCALE.index(last_note)
return C_SCALE[n+random.choice(range(-n, 6-n)[2:5])]
def create_melody(inst, chord_progression):
""" Creates the melody for the chord progression """
for chord in chord_progression:
meas = inst.NewMeasure()
last_note = random.choice(CHORDS[chord])
pos = 0
while pos < 64:
dur = random.choice([8, 8, 16, 16])
last_note = get_rdm_note(chord, last_note)
if random.randint(1,10) <= 8: # 20% silence
meas.NewNote(pos, dur, last_note, 5)
pos += dur
# create the sequencer
seq = Sequencer()
# create a new song
song = seq.NewSong()
# add an instrument to the song
b_inst = song.NewVoice()
cp = create_base(b_inst)
print cp
bajo = song.NewVoice()
for c in cp:
meas = bajo.NewMeasure()
meas.NewNote(0, 32, c, 3)
meas.NewNote(32, 32, c, 3)
m_inst = song.NewVoice()
create_melody(m_inst, cp)
# play the song
seq.Play()
# wait; the song plays asynchronously
time.sleep(30)