-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
124 lines (104 loc) · 4.61 KB
/
main.py
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
114
115
116
117
118
119
120
121
122
123
124
from mingus.core import progressions, keys
from mingus.containers import Note, NoteContainer, Bar, instrument
from mingus.midi import fluidsynth
from random import randint, random, choice
from custom_functions import custom_play_bars, format_chords, relative_modulation, parallel_modulation, \
step_modulation, is_mayor # My custom functions
# Defines Macros (Channels and Volumes)
CHORD_VOLUME = 65
MELODY_VOLUME = 100
PERC_VOLUME = 127
CHORD_CHANNEL = 1
MELODY_CHANNEL = 2
PERC_CHANNEL = 9
fluidsynth.init("GeneralUserGSv1.471.sf2", "pulseaudio")
# Chord Progressions Played and Scales
key_play = 'C'
minor_chords = ["Im", "IIdim", "III", "IVm", "Vm", "VI", "VII"]
mayor_chords = ["I", "IIm", "IIIm", "IV", "V", "VIm", "VIIdim"]
prog_play = progressions.to_chords([minor_chords, mayor_chords][is_mayor(key_play)], key_play)
prog_play = format_chords(prog_play, CHORD_VOLUME, CHORD_CHANNEL)
# prog_mayor = format_chords(prog_mayor, CHORD_VOLUME, CHORD_CHANNEL)
# prog_minor = format_chords(prog_minor, CHORD_VOLUME, CHORD_CHANNEL)
# prog_all = format_chords(prog_all, CHORD_VOLUME, CHORD_CHANNEL)
# prog_play = prog_mayor
notes_play = keys.get_notes(key_play)
# Initialize Bar structures to store chords and melody notes
improv = Bar(key_play, (4, 4))
chords = Bar(key_play, (4, 4))
# Defines lists with different types of note durations
validSubdivisions = [2, 4, 4 / 3, 8, 8 / 3, 16, 16 / 3, 32, 32 / 3]
binarySubdivisions = [2, 4, 8, 16, 32]
simpleSubdivisions = [4, 8, 16]
simpleRests = [4, 8]
just16 = [16]
# Defines a list of the indexes of instruments that sound good playing chords
chord_instruments = [*range(1, 28)] + [*range(29, 45)] + [*range(46, 108)] + [*range(109, 113)] + [114] + [119] + [
*range(122, 127)]
# Background Percussion
perc = Bar('C', (4, 4))
shaker = Note("A#", 5, None, PERC_VOLUME, PERC_CHANNEL)
perc.place_notes(Note("B", 1, None, PERC_VOLUME, PERC_CHANNEL), 8)
perc.place_notes(shaker, 4)
perc.place_notes(shaker, 8)
perc.place_notes(Note("B", 1, None, PERC_VOLUME, PERC_CHANNEL), 8)
perc.place_notes(shaker, 4)
perc.place_notes(shaker, 8)
while True:
# Set Instruments
chord_choice = randint(0, 127)
melody_choice = randint(0, 127)
fluidsynth.set_instrument(CHORD_CHANNEL, chord_choice)
fluidsynth.set_instrument(MELODY_CHANNEL, melody_choice)
# Random Chord Progression
while not (chords.is_full()):
chords.place_notes(NoteContainer(choice(prog_play)), 2)
# Randomly Improvised Melody
while not (improv.is_full()): # Improvises melody
if random() < 0.90: # 90% chance of playing note
improv.place_notes(Note(notes_play[randint(0, 6)], 5, None, MELODY_VOLUME, MELODY_CHANNEL),
choice(simpleSubdivisions))
else: # 10% Chance of silence
improv.place_notes(None, choice(simpleRests))
if random() < 0.3: # 30% chance of duplicated melody
midVal = len(improv.bar) // 2
for i in range(midVal):
improv[i + midVal] = improv[i][2]
# Print Current Chords, Melody Notes and Instruments
print_chords = []
for i in chords:
print_chords.append(i[2])
if len(i[2].determine()) > 0:
print_chords.append((i[2].determine())[0])
print("Current Key: %s " % key_play)
print("Current Chords: %s " % print_chords)
print("Current Melody: %s " % improv)
print("Chord Instrument: %i - %s " % (chord_choice, instrument.MidiInstrument.names[chord_choice]))
print("Melody Instrument: %i - %s " % (melody_choice, instrument.MidiInstrument.names[melody_choice]))
print()
# Play Everything
custom_play_bars([perc, improv, chords], 50)
# Chance of repeating melody next bar
if random() < 0.9:
improv.empty() # Resets melody 90% of the time
# Chance of changing keys
if random() < 0.2: # 20% Chance
dice = choice([*range(4)])
if dice == 0:
key_play = relative_modulation(key_play)
print("KEY MODULATION! - Relative Key.")
elif dice == 1:
key_play = parallel_modulation(key_play)
print("KEY MODULATION! - Parallel Key.")
elif dice == 2:
key_play = step_modulation(key_play, True)
print("KEY MODULATION! - Step Up.")
else:
key_play = step_modulation(key_play, False)
print("KEY MODULATION! - Step Down.")
notes_play = keys.get_notes(key_play)
prog_play = progressions.to_chords([minor_chords, mayor_chords][is_mayor(key_play)], key_play)
prog_play = format_chords(prog_play, CHORD_VOLUME, CHORD_CHANNEL)
if improv.is_full():
improv.empty()
chords.empty()