-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmusic_gui.py
171 lines (126 loc) · 4.62 KB
/
music_gui.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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
from Tkinter import *
from functools import partial
from mingus.midi import fluidsynth
import mingus.core.progressions as progressions
from mingus.containers import NoteContainer
from mingus.containers.Track import Track
from chordmodel import *
from mingus.midi import MidiFileOut
import tkFileDialog
from chordparser import number
roman = {
0:"I",
2:"ii",
4:"iii",
5:"IV",
7:"V",
9:"vi",
11:"vii",
}
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
fluidsynth.init("ChoriumRevA.SF2")
roman_num = [0,2,4,5,7,9,11]
self.progression = []
self.buttons = {}
self.prog_var = StringVar()
self.display = Label( master, textvariable = self.prog_var).pack()
self.uniprog_var = StringVar()
self.unidisplay = Label( master, textvariable = self.uniprog_var).pack()
self.sug_var = StringVar()
self.sug_label = Label( master, textvariable = self.sug_var).pack()
#### Chord Buttons ####
self.key_btn = Listbox(frame)
self.key_btn.bind("<<ListboxSelect>>", self.display_progression)
self.key_btn.pack(side=BOTTOM)
for k in number.keys():
self.key_btn.insert(END, k)
for ch in roman_num:
btn = Button(frame, text=roman[ch], command=partial( self.print_ch, ch ) )
btn.pack(side=LEFT)
self.buttons[ ch ] = btn
#### other buttons ####
self.pop = Button(frame, text='Del', command=self.pop_ch)
self.pop.pack(side=BOTTOM)
self.play = Button(frame, text='Play', command=self.play_prog)
self.play.pack(side=TOP)
self.sugg = Button(frame, text='?', command=self.suggest)
self.sugg.pack(side=BOTTOM)
self.save_btn = Button(frame, text='Save', command=self.save_midi)
self.save_btn.pack(side=TOP)
#### Checkbox buttons for intervals ####
self.add7_var = BooleanVar()
self.add7 = Checkbutton( master, text="+ 7", variable = self.add7_var )
self.add7.pack()
self.maj_var = BooleanVar()
self.maj = Checkbutton( master, text="Major", variable = self.maj_var )
self.maj.pack()
def get_key(self):
try:
sel = map(int, self.key_btn.curselection())
print sel
return number.keys()[sel[0]]
except IndexError:
return 'C'
def get_progression(self, prog):
return [ roman[ch[0]] + ch[1] for ch in prog ]
def display_progression(self, nop=None):
s = []
pr = self.get_progression(self.progression)
for ch in progressions.to_chords(pr, self.get_key()):
c = NoteContainer(ch)
s.append(c.determine(True)[0])
self.prog_var.set( ' '.join( s ) )
self.uniprog_var.set(' '.join( pr ))
#### Callbacks ####
def print_ch( self, ch ):
''' Append chord and modifier to progressioni and print updated progression to terminal.
'''
mod = ''
mod = mod + ('M' if self.maj_var.get() else '')
mod = mod + ('7' if self.add7_var.get() else '')
self.progression.append(( ch, mod ))
self.display_progression()
print ch
def pop_ch( self ):
''' Pop last chord off progression list.
'''
self.progression.pop()
self.display_progression()
def play_prog( self ):
''' Saves chords to track and plays using fluidsynth.
'''
ch = progressions.to_chords(self.get_progression(self.progression), self.get_key())
nc = map(NoteContainer, ch)
t = Track()
for chord in nc:
t.add_notes(chord)
fluidsynth.play_Track(t)
def save_midi( self ):
'''Opens save dialog, converts progression list to chords in track, saves track midi.
'''
file_name = tkFileDialog.asksaveasfilename()
ch = progressions.to_chords(self.get_progression(self.progression), self.get_key())
nc = map(NoteContainer, ch)
t = Track()
for chord in nc:
t.add_notes(chord)
MidiFileOut.write_Track( file_name,t)
def suggest( self ):
'''Combines list of unique suggestions and save in sug_var (which displays as label)
'''
concise = frequencies( self.get_progression(next_chord(self.progression)) )
self.sug_var.set( ' '.join(["%s: %s" % (k, v) for k, v in concise.iteritems()] ))
def frequencies( chords ):
'''Tracks frequency of unique chords and returns a dictionary of the chord (universal notation) and its count.
'''
initial = {}
for ch in chords:
value = initial.setdefault( ch, 0 )
initial[ ch ] = value + 1
return initial
root = Tk()
app = App(root)
root.mainloop()