Mercurial > hg > chourdakisreiss2016
comparison training-sessions/dave-ronan/ui.py @ 0:246d5546657c
initial commit, needs cleanup
author | Emmanouil Theofanis Chourdakis <e.t.chourdakis@qmul.ac.uk> |
---|---|
date | Wed, 14 Dec 2016 13:15:48 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:246d5546657c |
---|---|
1 # -*- coding: utf-8 -*- | |
2 """ | |
3 Created on Thu Jun 11 11:03:04 2015 | |
4 | |
5 @author: mmxgn | |
6 """ | |
7 | |
8 | |
9 | |
10 from essentia.standard import YamlInput, YamlOutput, AudioLoader, AudioWriter | |
11 from essentia import Pool | |
12 import matplotlib | |
13 matplotlib.use("TkAgg") | |
14 from matplotlib.figure import Figure | |
15 from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg | |
16 from mapping import * | |
17 | |
18 from sys import argv, exit | |
19 | |
20 from numpy import * | |
21 from matplotlib.pyplot import * | |
22 | |
23 from Tkinter import * | |
24 import tkMessageBox, tkFileDialog | |
25 | |
26 from numpy.core._internal import _gcd as gcd | |
27 | |
28 import os | |
29 import subprocess | |
30 from scikits.audiolab import Format, Sndfile | |
31 from scipy.signal import fftconvolve | |
32 from glob import glob | |
33 | |
34 | |
35 def zafar(lx, rx, d1, g1, da, G, gc, m): | |
36 """ Rafii & Pardo Reverberator (2009) controlled by High Level parameters | |
37 Inputs: | |
38 lx : left channel input | |
39 rx : right channel input | |
40 d1 : delay of first comb filter in samples | |
41 g1 : gain of first comb filters | |
42 da : delay of allpass filter in samples | |
43 G : dry/wet mix gain | |
44 gc : lowpass filter gain | |
45 m : difference between left and right channel phases | |
46 | |
47 Outputs: | |
48 ly: left channel output | |
49 ry: right channel output | |
50 """ | |
51 | |
52 def calculate_parameters(d1,g1): | |
53 | |
54 d2 = int(round((1.5)**(-1)*d1)) | |
55 | |
56 while gcd(d2,d1) != 1: | |
57 d2 += 1 | |
58 | |
59 d3 = int(round((1.5)**(-2)*d1)) | |
60 | |
61 while gcd(d3, d2) != 1 or gcd(d3, d1) != 1: | |
62 d3 += 1 | |
63 | |
64 d4 = int(round((1.5)**(-3)*d1)) | |
65 | |
66 while gcd(d4, d3) != 1 or gcd(d4, d2) != 1 or gcd(d4, d1) != 1: | |
67 d4 += 1 | |
68 | |
69 | |
70 d5 = int(round((1.5)**(-4)*d1)) | |
71 | |
72 while gcd(d5, d4) != 1 or gcd(d5, d3) != 1 or gcd(d5, d2) != 1 or gcd(d5, d1) != 1: | |
73 d5 += 1 | |
74 | |
75 d6 = int(round((1.5)**(-5)*d1)) | |
76 while gcd(d6, d5) != 1 or gcd(d6, d4) != 1 or gcd(d6, d3) != 1 or gcd(d6, d2) != 1 or gcd(d6, d1) != 1: | |
77 d6 += 1 | |
78 g2 = g1**(1.5)**(-1)*g1 | |
79 g3 = g1**(1.5)**(-2)*g1 | |
80 g4 = g1**(1.5)**(-3)*g1 | |
81 g5 = g1**(1.5)**(-4)*g1 | |
82 g6 = g1**(1.5)**(-5)*g1 | |
83 | |
84 return (d1, d2, d3, d4, d5, d6, g1, g2, g3, g4, g5, g6) | |
85 def comb_array(x, g1, d1): | |
86 | |
87 (d1,d2,d3,d4,d5,d6,g1,g2,g3,g4,g5,g6) = calculate_parameters(d1,g1) | |
88 | |
89 | |
90 | |
91 c1out = comb(x, g1, d1) | |
92 c2out = comb(x, g2, d2) | |
93 c3out = comb(x, g3, d3) | |
94 c4out = comb(x, g4, d4) | |
95 c5out = comb(x, g5, d5) | |
96 c6out = comb(x, g6, d6) | |
97 | |
98 | |
99 Lc1 = len(c1out) | |
100 Lc2 = len(c2out) | |
101 Lc3 = len(c3out) | |
102 Lc4 = len(c4out) | |
103 Lc5 = len(c5out) | |
104 Lc6 = len(c6out) | |
105 | |
106 Lc = max(Lc1, Lc2, Lc3, Lc4, Lc5, Lc6) | |
107 | |
108 y = zeros((Lc, )) | |
109 | |
110 y[0:Lc1] = c1out | |
111 y[0:Lc2] += c2out | |
112 y[0:Lc3] += c3out | |
113 y[0:Lc4] += c4out | |
114 y[0:Lc5] += c5out | |
115 y[0:Lc6] += c6out | |
116 | |
117 return y | |
118 | |
119 def comb(x, g, d): | |
120 LEN = len(x)+d | |
121 # print d | |
122 y = zeros((LEN,)) | |
123 for n in range(0, LEN): | |
124 if n - d < 0: | |
125 y[n] = 0 | |
126 else: | |
127 y[n] = x[n-d] + g*y[n-d] | |
128 | |
129 return y | |
130 | |
131 def allpass(x, g, d): | |
132 LENx = len(x) | |
133 LENy = LENx+d | |
134 y = zeros((LENy,)) | |
135 for n in range(0, LENy): | |
136 if n-d < 0: | |
137 y[n] = -g*x[n] | |
138 elif n >= LENx: | |
139 y[n] = x[n-d] + g*y[n-d] | |
140 else: | |
141 y[n] = x[n-d] - g*x[n] + g*y[n-d] | |
142 | |
143 return y | |
144 | |
145 def lowpass(x, g): | |
146 LEN = len(x) | |
147 y = zeros((LEN,)) | |
148 | |
149 for n in range(0, LEN): | |
150 if n-1 < 0: | |
151 y[n] = (1-g)*x[n] | |
152 else: | |
153 y[n] = (1-g)*x[n] + g*y[n-1] | |
154 | |
155 return y | |
156 | |
157 ga = 1./sqrt(2.) | |
158 | |
159 cin = 0.5*lx + 0.5*rx | |
160 cout = comb_array(cin, g1, d1) | |
161 | |
162 | |
163 ra = allpass(cout, ga, da+m/2) | |
164 la = allpass(cout, ga, da-m/2) | |
165 | |
166 ral = lowpass(ra, gc) | |
167 lal = lowpass(la, gc) | |
168 | |
169 ralg = G*ral | |
170 lalg = G*lal | |
171 | |
172 ry = ralg[0:len(rx)] + (1-G)*rx | |
173 ly = lalg[0:len(lx)] + (1-G)*lx | |
174 | |
175 return (ry, ly) | |
176 | |
177 class UI: | |
178 | |
179 def __init__(self, master, directory): | |
180 self.master = master | |
181 | |
182 self.directory = directory | |
183 | |
184 | |
185 | |
186 yamlinput = YamlInput(filename="session.yaml") | |
187 | |
188 try: | |
189 self.sessionpool = yamlinput() | |
190 try: | |
191 self.files_to_visit = self.sessionpool['files_to_visit'] | |
192 except: | |
193 self.files_to_visit = [] | |
194 | |
195 try: | |
196 self.visited_files = self.sessionpool['visited_files'] | |
197 except: | |
198 self.visited_files = [] | |
199 | |
200 | |
201 | |
202 except: | |
203 print "[II] Could not open sessionpool file, creating a new one" | |
204 self.sessionpool = Pool() | |
205 self.files_to_visit = glob("%s/*.wav" % directory) | |
206 for i in self.files_to_visit: | |
207 self.sessionpool.add('files_to_visit', i) | |
208 self.visited_files = [] | |
209 | |
210 if len(self.files_to_visit) == 0: | |
211 tkMessageBox.showinfo("","No files to visit") | |
212 master.destroy() | |
213 return | |
214 | |
215 filename = self.files_to_visit[-1] | |
216 self.filename = filename | |
217 # visited_files.append(filename) | |
218 self.label_top = Label(master, text="") | |
219 self.label_top.grid(row=0, column=0, columnspan=6) | |
220 | |
221 self.load_song(filename) | |
222 | |
223 | |
224 # Top Label | |
225 | |
226 self.label_top.config( text="Training song: %s (sampleRate: %.0f, nChannels: %d) - %d songs left" % (filename, self.SR, self.numChannels, len(self.files_to_visit)-1)) | |
227 | |
228 # High Level Parameters | |
229 | |
230 | |
231 | |
232 # Sliders | |
233 self.scale_T60 = Scale(master, to_=T60_min, from_=T60_max, resolution=0.01, label="RT60", showvalue=False) | |
234 self.scale_T60.bind("<ButtonRelease-1>",self.callback_update_parameters_high) | |
235 self.scale_T60.grid(row=1,column=0,rowspan=23,sticky=N+S+E+W) | |
236 | |
237 self.scale_D = Scale(master, to_=D_min, from_=D_max, resolution=0.01, label="D", showvalue=False) | |
238 self.scale_D.bind("<ButtonRelease-1>",self.callback_update_parameters_high) | |
239 self.scale_D.grid(row=1,column=1,rowspan=23,sticky=N+S+E+W) | |
240 | |
241 self.scale_C = Scale(master, to_=C_min, from_=C_max, resolution=0.01, label="C", showvalue=False) | |
242 self.scale_C.bind("<ButtonRelease-1>",self.callback_update_parameters_high) | |
243 self.scale_C.grid(row=1,column=2,rowspan=23,sticky=N+S+E+W) | |
244 | |
245 self.scale_Tc = Scale(master, to_=Tc_min, from_=Tc_max, resolution=0.01, label="T_c", showvalue=False) | |
246 self.scale_Tc.bind("<ButtonRelease-1>",self.callback_update_parameters_high) | |
247 self.scale_Tc.grid(row=1,column=3,rowspan=23,sticky=N+S+E+W) | |
248 | |
249 self.scale_SC = Scale(master, to_=SC_min, from_=SC_max, resolution=0.01, label="SC", showvalue=False) | |
250 self.scale_SC.bind("<ButtonRelease-1>",self.callback_update_parameters_high) | |
251 self.scale_SC.grid(row=1,column=4,rowspan=23,sticky=N+S+E+W) | |
252 | |
253 | |
254 # Fine Tuning (coefficients) | |
255 | |
256 # Labels | |
257 #self.label_p = Label(master, text="Coefficients Fine Tuning:") | |
258 #self.label_p.grid(row=13,column=1,sticky=N+W) | |
259 | |
260 | |
261 self.label_legend1 = Label(master, text="Legend:") | |
262 self.label_legend1.grid(row=2,column=6,sticky=N+E+W) | |
263 self.label_legend2 = Label(master, text="RT60: Reverberation time") | |
264 self.label_legend2.grid(row=3,column=6,sticky=N+W) | |
265 self.label_legend3 = Label(master, text="D: Echo density") | |
266 self.label_legend3.grid(row=4,column=6,sticky=N+W) | |
267 self.label_legend4 = Label(master, text="C: Clarity") | |
268 self.label_legend4.grid(row=5,column=6,sticky=N+W) | |
269 self.label_legend5 = Label(master, text="Tc: Central Time") | |
270 self.label_legend5.grid(row=6,column=6,sticky=N+W) | |
271 self.label_legend6 = Label(master, text="SC: Spectral Centroid") | |
272 self.label_legend6.grid(row=7,column=6,sticky=N+W) | |
273 | |
274 | |
275 | |
276 | |
277 # Sliders | |
278 self.scale_d1 = Scale(master, to_=d1_min, from_=d1_max, resolution=0.01, label="d1", showvalue=False)#, command=self.callback_update_parameters) | |
279 self.scale_d1.bind("<ButtonRelease-1>",self.callback_update_parameters) | |
280 # self.scale_d1.grid(row=16,column=0,rowspan=8,sticky=N+S+E+W) | |
281 self.scale_g1 = Scale(master,to_=g1_min, from_=g1_max, resolution=0.001, label="g1", showvalue=False)#, command=self.callback_update_parameters) | |
282 self.scale_g1.bind("<ButtonRelease-1>",self.callback_update_parameters) | |
283 | |
284 # self.scale_g1.grid(row=16,column=1,rowspan=8,sticky=N+S+E+W) | |
285 self.scale_da = Scale(master, to_=da_min, from_=da_max, resolution=0.001, label="da", showvalue=False)#, command=self.callback_update_parameters) | |
286 self.scale_da.bind("<ButtonRelease-1>",self.callback_update_parameters) | |
287 | |
288 # self.scale_da.grid(row=16,column=2,rowspan=8,sticky=N+S+E+W) | |
289 self.scale_G = Scale(master,to_=G_min, from_=G_max, resolution=0.001, label="G", showvalue=False)#, command=self.callback_update_parameters) | |
290 self.scale_G.bind("<ButtonRelease-1>",self.callback_update_parameters) | |
291 | |
292 # self.scale_G.grid(row=16,column=3,rowspan=8,sticky=N+S+E+W) | |
293 self.scale_gc = Scale(master, to_=gc_min, from_=gc_max, resolution=0.001, label="gc", showvalue=False)#, command=self.callback_update_parameters) | |
294 self.scale_gc.bind("<ButtonRelease-1>",self.callback_update_parameters) | |
295 | |
296 # self.scale_gc.grid(row=16,column=4,rowspan=8,sticky=N+S+E+W) | |
297 | |
298 | |
299 # Labels | |
300 | |
301 self.T60 = T60_min | |
302 self.D = D_max | |
303 self.C = C_max | |
304 self.Tc = (Tc_max-Tc_min)/2.0 | |
305 self.SC = SC_max | |
306 | |
307 | |
308 | |
309 | |
310 self.label_T60 = Label(master, text="Reverberation Time: ") | |
311 # self.label_T60.grid(row=2,column=6,sticky=N+S+E+W) | |
312 self.label_D = Label(master, text="Echo Density: ") | |
313 # self.label_D.grid(row=3,column=6,sticky=N+S+E+W) | |
314 self.label_C = Label(master, text="Clarity: ") | |
315 # self.label_C.grid(row=4,column=6,sticky=N+S+E+W) | |
316 self.label_Tc = Label(master, text="Central Time: ") | |
317 # self.label_Tc.grid(row=5,column=6,sticky=N+S+E+W) | |
318 self.label_SC = Label(master, text="Spectral Centroid: ") | |
319 # self.label_SC.grid(row=6,column=6,sticky=N+S+E+W) | |
320 | |
321 | |
322 self.label_d1 = Label(master, text="d_1: ") | |
323 # self.label_d1.grid(row=7, column=6, sticky=N+S+E+W) | |
324 | |
325 self.label_g1 = Label(master, text="g_1: ") | |
326 # self.label_g1.grid(row=8, column=6, sticky=N+S+E+W) | |
327 | |
328 self.label_da = Label(master, text="d_a: ") | |
329 # self.label_da.grid(row=9, column=6, sticky=N+S+E+W) | |
330 | |
331 self.label_gc = Label(master, text="gc: ") | |
332 # self.label_gc.grid(row=10, column=6, sticky=N+S+E+W) | |
333 | |
334 self.label_G = Label(master, text="G: ") | |
335 # self.label_G.grid(row=11, column=6, sticky=N+S+E+W) | |
336 | |
337 # Buttons | |
338 | |
339 self.button_plot_impulse = Button(master, text="Plot Impulse",command=self.callback_plot_impulse, width=15).grid(row=13,column=6,sticky=N+S+E+W) | |
340 # self.button_plot_raw = Button(master, text="Plot Raw", width=15,command=self.callback_plot_raw).grid(row=16,column=6,sticky=N+S+E+W) | |
341 # self.button_plot_reverb = Button(master, text="Plot Reverb", width=15, command=self.callback_plot_reverb).grid(row=17, column=6,sticky=N+S+E+W) | |
342 self.button_play_raw = Button(master, text="Play Raw", bg="green", fg="white", width=15, command=self.callback_play_raw).grid(row=18, column=6,sticky=N+S+E+W) | |
343 self.button_play_reverb = Button(master, text="Play Reverb", bg="green", fg="white", width=15, command=self.callback_play_reverb).grid(row=19, column=6,sticky=N+S+E+W) | |
344 self.button_stop = Button(master, text="Stop Playing", bg="red", fg="white", width=15, command=self.callback_stop).grid(row=20, column=6,sticky=N+S+E+W) | |
345 self.button_save = Button(master, text="Save", fg="white", bg="orange", width=15, command=self.callback_save).grid(row=21, column=6,sticky=N+S+E+W) | |
346 self.button_reset = Button(master, text="Undo", width=15, command=self.callback_reset).grid(row=22, column=6,sticky=N+S+E+W) | |
347 self.button_next = Button(master, text="Next >>", width=15, command=self.callback_next).grid(row=23, column=6,sticky=N+S+E+W) | |
348 | |
349 | |
350 | |
351 # Figure | |
352 | |
353 self.figure = Figure( dpi=50) | |
354 | |
355 self.figure.text(0.5,0.5,'No plot selected', weight = "bold", horizontalalignment='center') | |
356 | |
357 | |
358 self.canvas = FigureCanvasTkAgg(self.figure, master=root) | |
359 self.canvas.show() | |
360 self.canvas.get_tk_widget().grid(row=0, column=7, rowspan=17, padx=20,sticky=E+W+N+S) | |
361 self.canvas._tkcanvas.grid(row=0, column=7, rowspan=23) | |
362 | |
363 # Toolbar for canvas | |
364 | |
365 self.toolbar_frame = Frame(master) | |
366 self.toolbar_frame.grid(row=23,column=7,sticky=E+W+N+S, padx=19) | |
367 self.toolbar = NavigationToolbar2TkAgg(self.canvas, self.toolbar_frame) | |
368 | |
369 | |
370 | |
371 Grid.columnconfigure(master, 7, weight=1) | |
372 Grid.rowconfigure(master, 1, weight=1) | |
373 | |
374 # Status bar | |
375 | |
376 self.status_bar_text = Label(text="Ready.") | |
377 self.status_bar_text.grid(row=18, column=0, columnspan = 8, sticky=N+S+E, padx=10) | |
378 | |
379 self.lastplot = '' | |
380 self.parameterschanged_render = True | |
381 self.pendingactions = [] | |
382 | |
383 # Initial values | |
384 d1t = 0.05 | |
385 self.d1 = d1t*self.SR | |
386 dat = 0.012 | |
387 self.da = dat*self.SR | |
388 g1 = 0.5 | |
389 self.g1 = g1 | |
390 G = 0.5 | |
391 self.G = G | |
392 gc = 0.01 | |
393 self.gc = gc | |
394 | |
395 | |
396 # self.scale_d1.set(d1t) | |
397 # self.scale_da.set(dat) | |
398 # self.scale_g1.set(g1) | |
399 # self.scale_gc.set(gc) | |
400 # self.scale_G.set(G) | |
401 | |
402 t = zeros((self.SR*120,)) | |
403 t[0] = 1 | |
404 | |
405 self.impulse = t | |
406 | |
407 | |
408 | |
409 # Presets | |
410 self.presets=[] | |
411 self.var_presets = StringVar() | |
412 self.drop_presets = OptionMenu(master, self.var_presets, self.presets, command=self.callback_load_preset) | |
413 self.drop_presets.grid(row=0, column=6, sticky=N+S+E+W) | |
414 self.callback_load_presets() | |
415 | |
416 | |
417 # Preset options | |
418 self.button_save_preset = Button(master, text="Save Preset", command=self.callback_save_preset) | |
419 self.button_save_preset.grid(row=1, column=6, sticky=N+E+W) | |
420 | |
421 # Pool | |
422 self.pool = Pool() | |
423 self.pool.set('filename', self.filename) | |
424 self.pool.set('sampleRate', self.SR) | |
425 self.pool.set('nChannels', self.numChannels) | |
426 | |
427 | |
428 | |
429 | |
430 # Finally | |
431 self.callback_update_parameters_high(None) | |
432 self.plot_impulse() | |
433 | |
434 | |
435 | |
436 | |
437 | |
438 def pyaudio_callback_raw(self, in_data, frame_count, time_info, status): | |
439 if self.player_command == 'Stop': | |
440 return (0, pyaudio.paAbort) | |
441 | |
442 data = self.audio[self.player_idx:self.player_idx+frame_count, :] | |
443 | |
444 data = reshape(data, (data.shape[0]*data.shape[1], 1)) | |
445 | |
446 # print data | |
447 self.player_idx += frame_count | |
448 | |
449 | |
450 return (data, pyaudio.paContinue) | |
451 | |
452 | |
453 def play_reverb(self): | |
454 | |
455 self.calculate_impulse_response() | |
456 ly, ry = self.impulse_response_left_channel, self.impulse_response_right_channel | |
457 | |
458 lx = self.audio[:,0] | |
459 rx = self.audio[:,1] | |
460 | |
461 print "Convolving left channel" | |
462 l_out = fftconvolve(ly, lx) | |
463 | |
464 if max(l_out) > 1.0: | |
465 l_out = l_out/max(l_out) | |
466 | |
467 # l_out = l_out/max(l_out) | |
468 | |
469 print "Convolving right channel" | |
470 r_out = fftconvolve(ry, rx) | |
471 | |
472 if max(r_out) > 1.0: | |
473 r_out = r_out/max(r_out) | |
474 # r_out = r_out/max(r_out) | |
475 | |
476 | |
477 | |
478 lim = min(len(l_out), len(r_out)) | |
479 | |
480 | |
481 | |
482 if self.numChannels == 1: | |
483 audio_out = l_out[0:lim] | |
484 else: | |
485 audio_out = concatenate((matrix(l_out[0:lim]).T, | |
486 matrix(r_out[0:lim]).T | |
487 ), | |
488 axis=1) | |
489 | |
490 reverb_filename = "%s_reverb_%s" % (self.filename.split('.')[0], self.filename.split('.')[1]) | |
491 | |
492 audio_file = Sndfile(reverb_filename, 'w', Format(self.filename.split('.')[1]), self.numChannels, self.SR) | |
493 audio_file.write_frames(audio_out) | |
494 audio_file.close() | |
495 | |
496 self.reverberated_audio = audio_out | |
497 | |
498 self.reverb_filename = reverb_filename | |
499 | |
500 self.playerprocess = subprocess.Popen("mplayer %s" % reverb_filename, | |
501 stdout = subprocess.PIPE, | |
502 shell=True, | |
503 preexec_fn=os.setsid) | |
504 | |
505 def play_raw(self): | |
506 self.playerprocess = subprocess.Popen("mplayer %s" % self.filename, | |
507 stdout = subprocess.PIPE, | |
508 shell=True, | |
509 preexec_fn=os.setsid) | |
510 | |
511 | |
512 | |
513 | |
514 | |
515 def remove_action_from_status(self, text): | |
516 | |
517 self.pendingactions.remove(text) | |
518 | |
519 if len(self.pendingactions) == 0: | |
520 self.status_bar_text.config(text='Ready.') | |
521 elif len(self.pendingactions) == 1: | |
522 self.status_bar_text.config(text=self.pendingactions[0]+'.') | |
523 else: | |
524 self.status_bar_text.config(text=reduce(lambda h,t: h+','+t, self.pendingactions)+'.') | |
525 | |
526 | |
527 def add_action_to_status(self, text): | |
528 | |
529 self.pendingactions.append(text) | |
530 | |
531 if len(self.pendingactions) == 0: | |
532 self.status_bar_text.config(text='Ready.') | |
533 elif len(self.pendingactions) == 1: | |
534 self.status_bar_text.config(text=text+'.') | |
535 else: | |
536 self.status_bar_text.config(text=reduce(lambda h,t: h+', '+t, self.pendingactions)+'.') | |
537 | |
538 print self.pendingactions, len(self.pendingactions) | |
539 | |
540 | |
541 def load_song(self, filename): | |
542 tup = AudioLoader(filename=filename)() | |
543 self.audio = tup[0] | |
544 self.SR = tup[1] | |
545 global SC_max | |
546 SC_max = self.SR/4.0 | |
547 self.numChannels = tup[2] | |
548 self.label_top.config(text="Training song: %s (sampleRate: %.0f, nChannels: %d) \n %d songs left" % (filename, self.SR, self.numChannels, len(self.files_to_visit)-1),wraplength=500) | |
549 self.saved = False | |
550 | |
551 | |
552 | |
553 | |
554 def estimate_T60(self, d1, g1, gc, G, SR): | |
555 ga = 1/sqrt(2) | |
556 return d1/SR/log(g1)*log(10**-3/ga/(1-gc)/G) | |
557 | |
558 def calculate_parameters(self,d1,g1): | |
559 | |
560 d2 = int(round((1.5)**(-1)*d1)) | |
561 | |
562 while gcd(d2,d1) != 1: | |
563 d2 += 1 | |
564 | |
565 d3 = int(round((1.5)**(-2)*d1)) | |
566 | |
567 while gcd(d3, d2) != 1 or gcd(d3, d1) != 1: | |
568 d3 += 1 | |
569 | |
570 d4 = int(round((1.5)**(-3)*d1)) | |
571 | |
572 while gcd(d4, d3) != 1 or gcd(d4, d2) != 1 or gcd(d4, d1) != 1: | |
573 d4 += 1 | |
574 | |
575 | |
576 d5 = int(round((1.5)**(-4)*d1)) | |
577 | |
578 while gcd(d5, d4) != 1 or gcd(d5, d3) != 1 or gcd(d5, d2) != 1 or gcd(d5, d1) != 1: | |
579 d5 += 1 | |
580 | |
581 d6 = int(round((1.5)**(-5)*d1)) | |
582 while gcd(d6, d5) != 1 or gcd(d6, d4) != 1 or gcd(d6, d3) != 1 or gcd(d6, d2) != 1 or gcd(d6, d1) != 1: | |
583 d6 += 1 | |
584 g2 = g1**(1.5)**(-1)*g1 | |
585 g3 = g1**(1.5)**(-2)*g1 | |
586 g4 = g1**(1.5)**(-3)*g1 | |
587 g5 = g1**(1.5)**(-4)*g1 | |
588 g6 = g1**(1.5)**(-5)*g1 | |
589 | |
590 return (d1, d2, d3, d4, d5, d6, g1, g2, g3, g4, g5, g6) | |
591 def estimate_C(self, g1, G, gc): | |
592 g2 = g1**(1.5)**(-1)*g1 | |
593 g3 = g1**(1.5)**(-2)*g1 | |
594 g4 = g1**(1.5)**(-3)*g1 | |
595 g5 = g1**(1.5)**(-4)*g1 | |
596 g6 = g1**(1.5)**(-5)*g1 | |
597 gains = zeros((6,1)) | |
598 gains[0] = g1 | |
599 gains[1] = g2 | |
600 gains[2] = g3 | |
601 gains[3] = g4 | |
602 gains[4] = g5 | |
603 gains[5] = g6 | |
604 | |
605 return -10*log10(G**2*(1-gc)/(1+gc)*sum(1/(1-gains**2))) | |
606 | |
607 | |
608 def estimate_D(self, d1, g1, da, SR): | |
609 kS = 20.78125 | |
610 | |
611 | |
612 return kS*0.1/d1/da*self.SR**2 | |
613 | |
614 def estimate_Tc(self, d1, g1, da, SR): | |
615 delays = zeros((6,)) | |
616 gains = zeros((6,1)) | |
617 (delays[0],delays[1],delays[2],delays[3],delays[4],delays[5],gains[0],gains[1],gains[2],gains[3],gains[4],gains[5]) = self.calculate_parameters(d1,g1) | |
618 return sum(delays/SR*gains**2/(1-gains**2)**2)/sum(gains**2/(1-gains**2)) + da/SR | |
619 | |
620 def update_parameters_high(self, _): | |
621 | |
622 self.T60_old = self.T60 | |
623 self.D_old = self.D | |
624 self.C_old = self.C | |
625 self.Tc_old = self.Tc | |
626 self.SC_old = self.SC | |
627 | |
628 T60 = self.scale_T60.get() | |
629 D = self.scale_D.get() | |
630 C = self.scale_C.get() | |
631 Tc = self.scale_Tc.get() | |
632 SC = self.scale_SC.get() | |
633 print self.SR | |
634 print (T60, D, C, Tc, SC) | |
635 (d1t, dat, g1, gc, G) = inverse_mapping(T60,D,C,Tc,SC,SR=self.SR) | |
636 | |
637 print "da",(d1t, dat, g1, gc, G) | |
638 | |
639 self.scale_d1.set(d1t) | |
640 self.scale_da.set(dat) | |
641 self.scale_g1.set(g1) | |
642 self.scale_gc.set(gc) | |
643 self.scale_G.set(G) | |
644 self.parameterschanged_render = True | |
645 | |
646 def callback_update_parameters_high(self, _): | |
647 print("callback_update_parameters_high") | |
648 self.update_parameters_high(_) | |
649 | |
650 | |
651 self.update_parameters(_) | |
652 | |
653 self.callback_plot_impulse() | |
654 | |
655 def update_parameters(self, _): | |
656 SR = self.SR | |
657 d1t = self.scale_d1.get() | |
658 | |
659 d1 = round(d1t*SR) | |
660 g1 = self.scale_g1.get() | |
661 dat = self.scale_da.get() | |
662 da = round(dat*SR) | |
663 G = self.scale_G.get() | |
664 gc = self.scale_gc.get() | |
665 | |
666 | |
667 T60 = self.estimate_T60(d1,g1,gc,G,SR) | |
668 D = self.estimate_D(d1, g1, da, SR) | |
669 C = self.estimate_C(g1, G, gc) | |
670 Tc = self.estimate_Tc(d1,g1,da,SR) | |
671 SC = self.estimate_SC(gc, SR) | |
672 | |
673 | |
674 self.d1_old = self.d1 | |
675 self.G_old = self.G | |
676 self.gc_old = self.gc | |
677 self.g1_old = self.g1 | |
678 self.da_old = self.da | |
679 | |
680 self.d1 = d1 | |
681 self.G = G | |
682 self.gc = gc | |
683 self.g1 = g1 | |
684 self.da = da | |
685 | |
686 | |
687 | |
688 self.pool.set('parameters.d1', d1t) | |
689 self.pool.set('parameters.G', G) | |
690 self.pool.set('parameters.gc', gc) | |
691 self.pool.set('parameters.g1', g1) | |
692 self.pool.set('parameters.da', dat) | |
693 | |
694 | |
695 | |
696 self.T60 = T60 | |
697 self.D = D | |
698 self.Tc = Tc | |
699 self.SC = SC | |
700 self.C = C | |
701 | |
702 self.pool.set('parameters.T60', T60) | |
703 self.pool.set('parameters.D', D) | |
704 self.pool.set('parameters.C', C) | |
705 self.pool.set('parameters.Tc', Tc) | |
706 self.pool.set('parameters.SC', SC) | |
707 | |
708 self.label_T60.config(text="Reverberation Time: %.3fs" % T60) | |
709 self.label_D.config(text="Echo Density: %.3f at 0.1s" % D) | |
710 self.label_C.config(text="Clarity: %.3f dB" % C) | |
711 self.label_Tc.config(text="Central Time: %.3fs" % Tc) | |
712 self.label_SC.config(text="Spectral Centroid: %.3f Hz" % SC) | |
713 | |
714 self.label_d1.config(text="d_1: %.3fs" % d1t) | |
715 self.label_g1.config(text="g_1: %.3f" % g1) | |
716 self.label_da.config(text="d_a: %.3fs" % dat) | |
717 self.label_gc.config(text="g_c: %.3f" % gc) | |
718 self.label_G.config(text="G: %.3f" % G) | |
719 self.lastplot = '' | |
720 | |
721 | |
722 self.parameterschanged_render = True | |
723 | |
724 | |
725 | |
726 def callback_update_parameters(self,_): | |
727 self.update_parameters(_) | |
728 | |
729 | |
730 def estimate_SC(self, gc, SR): | |
731 n = arange(0, SR/2+1) | |
732 return sum(n/(1+gc**2-2*gc*cos(2*pi*n/SR)))/sum(1/(1+gc**2-2*gc*cos(2*pi*n/SR))) | |
733 | |
734 | |
735 | |
736 | |
737 def say_hi(self): | |
738 print "Hi, there" | |
739 | |
740 | |
741 | |
742 def callback_save_preset(self): | |
743 print self.presets | |
744 name= tkFileDialog.asksaveasfilename(defaultextension=".pre",filetypes=[("presets",".pre")]) | |
745 print name | |
746 p = Pool() | |
747 p.set('d1',self.scale_d1.get()) | |
748 p.set('g1',self.scale_g1.get()) | |
749 p.set('da',self.scale_da.get()) | |
750 p.set('gc',self.scale_gc.get()) | |
751 p.set('G',self.scale_G.get()) | |
752 y = YamlOutput(filename=name) | |
753 y(p) | |
754 | |
755 self.callback_load_presets() | |
756 | |
757 #f.write(p) | |
758 #f.close() | |
759 | |
760 | |
761 def callback_load_presets(self): | |
762 presets = glob('*.pre') | |
763 | |
764 self.presets = tuple([os.path.splitext(f)[0] for f in presets]) | |
765 | |
766 | |
767 self.drop_presets.destroy() | |
768 | |
769 if len(self.presets) == 0: | |
770 # self.drop_presets = OptionMenu(root, self.var_presets, ('No presets') ,command=self.callback_load_preset) | |
771 pass | |
772 else: | |
773 self.drop_presets = OptionMenu(root, self.var_presets, *tuple(self.presets),command=self.callback_load_preset) | |
774 self.drop_presets.grid(row=0, column=6,sticky=S+W+E) | |
775 | |
776 | |
777 def callback_load_preset(self, preset): | |
778 self.var_presets.set(preset) | |
779 print "loading preset:", preset | |
780 | |
781 p = YamlInput(filename = '%s.pre' % preset)() | |
782 | |
783 self.scale_d1.set(p['d1']) | |
784 self.scale_g1.set(p['g1']) | |
785 self.scale_da.set(p['da']) | |
786 self.scale_gc.set(p['gc']) | |
787 self.scale_G.set(p['G']) | |
788 | |
789 self.callback_update_parameters(None) | |
790 | |
791 self.scale_T60.set(self.T60) | |
792 self.scale_D.set(self.D) | |
793 self.scale_C.set(self.C) | |
794 self.scale_Tc.set(self.Tc) | |
795 self.scale_SC.set(self.SC) | |
796 | |
797 self.plot_impulse() | |
798 | |
799 def callback_plot_impulse(self): | |
800 self.plot_impulse() | |
801 | |
802 def calculate_impulse_response(self): | |
803 self.add_action_to_status('Calculating impulse response') | |
804 N = self.numChannels | |
805 SR = self.SR | |
806 T = 1.0/self.SR | |
807 | |
808 delta = self.impulse[0:int(self.T60*self.SR)] | |
809 | |
810 | |
811 d1 = int(self.d1) | |
812 g1 = self.g1 | |
813 da = int(self.da) | |
814 G = self.G | |
815 gc = self.gc | |
816 | |
817 mt = 0.002 | |
818 m = int(mt*SR) | |
819 | |
820 (ly, ry) = zafar(delta,delta,d1,g1,da,G,gc,m) | |
821 | |
822 limt = 2*self.T60 | |
823 | |
824 lim = int(limt*SR) | |
825 t = arange(0, lim)*T | |
826 | |
827 padded_y = zeros(shape(t)) | |
828 padded_y[0:len(ly)] = ly | |
829 | |
830 | |
831 padded_y = zeros(shape(t)) | |
832 padded_y[0:len(ry)] = ry | |
833 | |
834 ry = padded_y | |
835 | |
836 self.impulse_response_left_channel = ly | |
837 self.impulse_response_right_channel = ry | |
838 | |
839 | |
840 self.remove_action_from_status('Calculating impulse response') | |
841 | |
842 | |
843 | |
844 def plot_impulse(self): | |
845 if self.lastplot != 'impulse': | |
846 self.add_action_to_status('Plotting impulse response') | |
847 N = self.numChannels | |
848 SR = self.SR | |
849 T = 1.0/self.SR | |
850 limt = max(self.T60,1.0) | |
851 | |
852 lim = int(limt*SR) | |
853 delta = self.impulse[0:int(lim)] | |
854 # print "delta:" | |
855 # print delta | |
856 | |
857 d1 = int(self.d1) | |
858 g1 = self.g1 | |
859 da = int(self.da) | |
860 G = self.G | |
861 gc = self.gc | |
862 | |
863 mt = 0.002 | |
864 m = int(mt*SR) | |
865 | |
866 print "Calculating zafar" | |
867 (ly, ry) = zafar(delta,delta,d1,g1,da,G,gc,m) | |
868 | |
869 print "Stopped calculating zafar"#ly.shape | |
870 | |
871 # print "lim:", lim | |
872 | |
873 t = arange(0, lim)*T | |
874 # print t | |
875 | |
876 # Pad ly to t | |
877 # print "Shape ly" | |
878 # print ly | |
879 # print len(ly) | |
880 padded_y = zeros(shape(t)) | |
881 padded_y[0:len(ly)] = ly | |
882 | |
883 print "Padded y" | |
884 #print padded_y | |
885 | |
886 # ly = padded_y | |
887 | |
888 # Pad ry to t | |
889 | |
890 padded_y = zeros(shape(t)) | |
891 padded_y[0:len(ry)] = ry | |
892 | |
893 ry = padded_y | |
894 | |
895 | |
896 | |
897 self.figure.clear() | |
898 | |
899 # print "Passed A" | |
900 subplt0 = self.figure.add_subplot(2,1,1) | |
901 # subplt0.ion() | |
902 | |
903 subplt0.plot(t[1:lim],abs(ly[1:lim])) | |
904 subplt0.set_title('Left Channel') | |
905 subplt0.set_xlabel('time (s)') | |
906 subplt0.set_ylabel('amplitude') | |
907 subplt0.axvspan(self.d1/self.SR,self.d1/self.SR+0.1, alpha=0.1,color='cyan') | |
908 subplt0.axvline(self.Tc, color='red', linestyle='--') | |
909 subplt0.axvline(self.d1/self.SR+0.1, color='cyan', linestyle='--') | |
910 subplt0.axhline(0.001, color='black', linestyle='--') | |
911 subplt0.axvline(self.d1/self.SR, color='cyan', linestyle='--') | |
912 | |
913 subplt0.annotate('Central Time (Tc)', xy=(self.Tc, 0.25), xytext=(self.Tc+0.01, 0.25), arrowprops=dict(facecolor='black',width=1)) | |
914 # subplt0.annotate('Echo Density (D) Measurement Range', xytext=(self.d1/self.SR, 0.62), arrowprops=dict(facecolor='black',width=1)) | |
915 | |
916 # | |
917 | |
918 subplt1 = self.figure.add_subplot(2,1,2,sharex=subplt0) | |
919 subplt1.set_title('Right Channel') | |
920 | |
921 subplt1.plot(t[1:lim],abs(ry[1:lim])) | |
922 subplt1.set_xlabel('time (s)') | |
923 subplt1.set_ylabel('amplitude') | |
924 subplt1.axvspan(self.d1/self.SR,self.d1/self.SR+0.1, alpha=0.1,color='cyan') | |
925 | |
926 subplt1.axvline(self.Tc, color='red', linestyle='--') | |
927 subplt1.axvline(self.d1/self.SR+0.1, color='cyan', linestyle='--') | |
928 subplt1.axvline(self.d1/self.SR, color='cyan', linestyle='--') | |
929 subplt1.axhline(0.001, color='black', linestyle='--') | |
930 | |
931 | |
932 self.figure.suptitle("Reverberation Impulse Response") | |
933 | |
934 # print "Passed B" | |
935 # | |
936 self.remove_action_from_status('Plotting impulse response') | |
937 self.canvas.draw() | |
938 | |
939 self.lastplot = 'impulse' | |
940 # | |
941 # thread.exit_thread() | |
942 | |
943 | |
944 | |
945 def plot_raw(self): | |
946 if self.lastplot != 'raw': | |
947 self.add_action_to_status('Plotting raw') | |
948 N = self.numChannels | |
949 print "Channels: %d" % N | |
950 L = len(self.audio[:,0]) | |
951 | |
952 | |
953 | |
954 | |
955 self.figure.clear() | |
956 | |
957 T = 1.0/self.SR | |
958 t = arange(0, L)*T | |
959 | |
960 oldsubplt = None | |
961 for n in range(0, N): | |
962 if oldsubplt is not None: | |
963 subplt = self.figure.add_subplot(N,1,n+1,sharex=oldsubplt) | |
964 else: | |
965 subplt = self.figure.add_subplot(N,1,n+1) | |
966 subplt.plot(t,self.audio[:,n]) | |
967 subplt.set_title('Channel %d' % n) | |
968 subplt.set_xlabel('time (s)') | |
969 subplt.set_ylabel('amplitude') | |
970 | |
971 oldsubplt = subplt | |
972 | |
973 | |
974 self.figure.suptitle('Raw Signal') | |
975 self.canvas.draw() | |
976 | |
977 self.lastplot = 'raw' | |
978 self.remove_action_from_status('Plotting raw') | |
979 # thread.exit_thread() | |
980 def callback_plot_raw(self): | |
981 try: | |
982 #thread.start_new_thread(self.plot_raw, ()) | |
983 self.plot_raw() | |
984 except: | |
985 print "[EE] Could not start new thread" | |
986 | |
987 | |
988 | |
989 # show() | |
990 | |
991 def plot_reverb(self): | |
992 if self.lastplot != 'reverb': | |
993 self.add_action_to_status('Plotting reverberated signal') | |
994 | |
995 self.calculate_impulse_response() | |
996 ly, ry = self.impulse_response_left_channel, self.impulse_response_right_channel | |
997 | |
998 lx = self.audio[:,0] | |
999 rx = self.audio[:,1] | |
1000 | |
1001 print "Concolving left channel" | |
1002 l_out = fftconvolve(ly, lx) | |
1003 | |
1004 print "Convolving right channel" | |
1005 r_out = fftconvolve(ry, rx) | |
1006 | |
1007 | |
1008 | |
1009 lim = min(len(l_out), len(r_out)) | |
1010 # N = self.numChannels | |
1011 # SR = self.SR | |
1012 # T = 1.0/self.SR | |
1013 # | |
1014 # | |
1015 # d1 = int(self.d1) | |
1016 # g1 = self.g1 | |
1017 # da = int(self.da) | |
1018 # G = self.G | |
1019 # gc = self.gc | |
1020 # | |
1021 # mt = 0.002 | |
1022 # m = int(mt*SR) | |
1023 # | |
1024 # lchannel = ravel(self.audio[:,0]) | |
1025 # rchannel = ravel(self.audio[:,1]) | |
1026 # | |
1027 # print "Calculating zafar" | |
1028 # | |
1029 # if self.parameterschanged_render == True: | |
1030 # (ly, ry) = zafar(lchannel,rchannel,d1,g1,da,G,gc,m) | |
1031 # | |
1032 # self.reverberated_signal_left_channel = ly | |
1033 # self.reverberated_signal_right_channel = ry | |
1034 # | |
1035 # self.parameterschanged_render = 0 | |
1036 # else: | |
1037 # ly = self.reverberated_signal_left_channel | |
1038 # ry = self.reverberated_signal_right_channel | |
1039 # | |
1040 # print "Stopped calculating zafar"#ly.shape | |
1041 # # limt = self.T60 | |
1042 # | |
1043 # lim = int(limt*SR) | |
1044 | |
1045 # lim = len(lchannel) | |
1046 # print "lim:", lim | |
1047 T = 1/self.SR | |
1048 t = arange(0, lim)*T | |
1049 # print t | |
1050 | |
1051 # Pad ly to t | |
1052 # print "Shape ly" | |
1053 ## print ly | |
1054 # print len(ly) | |
1055 # padded_y = zeros(shape(t)) | |
1056 # padded_y[0:len(ly)] = ly | |
1057 | |
1058 # print "Padded y" | |
1059 #print padded_y | |
1060 | |
1061 # ly = padded_y | |
1062 | |
1063 # Pad ry to t | |
1064 | |
1065 # padded_y = zeros(shape(t)) | |
1066 # padded_y[0:len(ry)] = ry | |
1067 | |
1068 # ry = padded_y | |
1069 # | |
1070 | |
1071 | |
1072 self.figure.clear() | |
1073 | |
1074 # print "Passed A" | |
1075 subplt0 = self.figure.add_subplot(2,1,1) | |
1076 | |
1077 subplt0.semilogy(t,l_out[0:lim]) | |
1078 subplt0.set_title('Left Channel') | |
1079 subplt0.set_xlabel('time (s)') | |
1080 subplt0.set_ylabel('amplitude') | |
1081 | |
1082 | |
1083 subplt1 = self.figure.add_subplot(2,1,2,sharex=subplt0) | |
1084 subplt1.set_title('Right Channel') | |
1085 | |
1086 subplt1.semilogy(t,r_out[0:lim]) | |
1087 subplt1.set_xlabel('time (s)') | |
1088 subplt1.set_ylabel('amplitude') | |
1089 | |
1090 self.figure.suptitle("Reverberated Signal") | |
1091 | |
1092 self.remove_action_from_status('Plotting reverberated signal') | |
1093 self.canvas.draw() | |
1094 | |
1095 self.lastplot = 'reverb' | |
1096 # thread.exit_thread() | |
1097 def callback_plot_reverb(self): | |
1098 self.plot_reverb() | |
1099 | |
1100 def callback_play_raw(self): | |
1101 print "[II] Called callback_play_raw" | |
1102 try: | |
1103 self.playerprocess.terminate() | |
1104 except: | |
1105 pass | |
1106 self.play_raw() | |
1107 | |
1108 def callback_play_reverb(self): | |
1109 | |
1110 print "[II] Called callback_play_reverb" | |
1111 try: | |
1112 self.playerprocess.terminate() | |
1113 except: | |
1114 pass | |
1115 | |
1116 self.play_reverb() | |
1117 | |
1118 def callback_stop(self): | |
1119 self.playerprocess.terminate() | |
1120 | |
1121 def callback_save(self): | |
1122 outf = "%s_parameters.yaml" % self.filename.split('.')[0] | |
1123 outr = "%s_original_reverb.wav.2" % self.filename.split('.')[0] | |
1124 out = YamlOutput(filename=outf) | |
1125 out(self.pool) | |
1126 print "[II] Parameters Saved" | |
1127 | |
1128 self.calculate_impulse_response() | |
1129 ly, ry = self.impulse_response_left_channel, self.impulse_response_right_channel | |
1130 | |
1131 lx = self.audio[:,0] | |
1132 rx = self.audio[:,1] | |
1133 | |
1134 print "Convolving left channel" | |
1135 l_out = fftconvolve(ly, lx) | |
1136 #l_out = l_out/max(l_out) | |
1137 if max(l_out) > 1.0: | |
1138 l_out = l_out/max(l_out) | |
1139 | |
1140 print "Convolving right channel" | |
1141 r_out = fftconvolve(ry, rx) | |
1142 | |
1143 if max(r_out) > 1.0: | |
1144 r_out = r_out/max(r_out) | |
1145 #r_out = r_out/max(r_out) | |
1146 | |
1147 # print "maxrout", max(r_out) | |
1148 | |
1149 | |
1150 | |
1151 lim = min(len(l_out), len(r_out)) | |
1152 | |
1153 | |
1154 | |
1155 if self.numChannels == 1: | |
1156 audio_out = l_out[0:lim] | |
1157 else: | |
1158 audio_out = concatenate((matrix(l_out[0:lim]).T, | |
1159 matrix(r_out[0:lim]).T | |
1160 ), | |
1161 axis=1) | |
1162 | |
1163 audio_file = Sndfile(outr, 'w', Format(self.filename.split('.')[1]), self.numChannels, self.SR) | |
1164 audio_file.write_frames(audio_out) | |
1165 audio_file.close() | |
1166 | |
1167 print "[II] File %s saved" % outr | |
1168 | |
1169 | |
1170 | |
1171 self.saved = True | |
1172 | |
1173 def callback_reset(self): | |
1174 d1 = self.d1 | |
1175 g1 = self.g1 | |
1176 da = self.da | |
1177 G = self.G | |
1178 gc = self.gc | |
1179 | |
1180 self.d1 = self.d1_old | |
1181 self.g1 = self.g1_old | |
1182 self.G = self.G_old | |
1183 self.gc = self.gc_old | |
1184 self.da = self.da_old | |
1185 | |
1186 self.T60 = self.T60_old | |
1187 self.D = self.D_old | |
1188 self.C = self.C_old | |
1189 self.Tc = self.Tc_old | |
1190 self.SC = self.SC_old | |
1191 | |
1192 self.scale_d1.set(self.d1/self.SR) | |
1193 self.scale_g1.set(self.g1) | |
1194 self.scale_da.set(self.da/self.SR) | |
1195 self.scale_G.set(self.G) | |
1196 self.scale_gc.set(self.gc) | |
1197 | |
1198 | |
1199 self.scale_T60.set(self.T60) | |
1200 self.scale_C.set(self.C) | |
1201 self.scale_D.set(self.D) | |
1202 self.scale_Tc.set(self.Tc) | |
1203 self.scale_SC.set(self.SC) | |
1204 | |
1205 self.callback_update_parameters_high(None) | |
1206 | |
1207 | |
1208 def callback_next(self): | |
1209 if self.saved == False: | |
1210 tkMessageBox.showerror("File not saved", "You need to save your changes first") | |
1211 return | |
1212 | |
1213 | |
1214 self.visited_files.append(self.filename) | |
1215 self.sessionpool.add('visited_files', self.filename) | |
1216 self.files_to_visit.pop() | |
1217 self.sessionpool.remove('files_to_visit') | |
1218 for i in self.files_to_visit: | |
1219 self.sessionpool.add('files_to_visit', i) | |
1220 outp = YamlOutput(filename="session.yaml")(self.sessionpool) | |
1221 | |
1222 if len(self.files_to_visit) == 0: | |
1223 tkMessageBox.showinfo("Congratulations!", "You finished the training session!") | |
1224 self.master.destroy() | |
1225 return | |
1226 self.filename = self.files_to_visit[-1] | |
1227 self.load_song(self.filename) | |
1228 | |
1229 | |
1230 | |
1231 | |
1232 if __name__ == "__main__": | |
1233 if len(argv) != 2: | |
1234 print "[EE] Wrong number of arguments" | |
1235 print "[II] Correct syntax is:" | |
1236 print "[II] \t%s <trainingdir>" | |
1237 print "[II] where <trainingdir> contains the segments in .wav format and their corresponding .yaml files" | |
1238 | |
1239 exit(-1) | |
1240 | |
1241 print "[II] Using directory: %s" % argv[1] | |
1242 root = Tk() | |
1243 app = UI(root, argv[1]) | |
1244 root.mainloop() |