comparison experiment-reverb/code/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 import matplotlib
10 matplotlib.use("TkAgg")
11 from matplotlib.figure import Figure
12 from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
13
14 import pyaudio
15 from sys import argv, exit
16 from essentia.standard import YamlInput, YamlOutput, AudioLoader, AudioWriter
17 from essentia import Pool
18 from pca import *
19
20 from numpy import *
21 from sklearn import cluster
22 from sklearn.metrics import pairwise_distances
23 from sklearn.cluster import KMeans, MiniBatchKMeans
24 from matplotlib.pyplot import *
25 #from sklearn.mixture import GMM
26 from sklearn.naive_bayes import GaussianNB, MultinomialNB
27 from scipy.signal import decimate
28 from sklearn import cross_validation
29 from Tkinter import *
30 import tkMessageBox
31 import thread
32 from numpy.core._internal import _gcd as gcd
33 import time
34 import os
35 import subprocess
36 from scikits.audiolab import Format, Sndfile
37 from scipy.signal import fftconvolve
38 from glob import glob
39
40 def zafar(lx, rx, d1, g1, da, G, gc, m):
41 """ Rafii & Pardo Reverberator (2009) controlled by High Level parameters
42 Inputs:
43 lx : left channel input
44 rx : right channel input
45 d1 : delay of first comb filter in samples
46 g1 : gain of first comb filters
47 da : delay of allpass filter in samples
48 G : dry/wet mix gain
49 gc : lowpass filter gain
50 m : difference between left and right channel phases
51
52 Outputs:
53 ly: left channel output
54 ry: right channel output
55 """
56
57 def calculate_parameters(d1,g1):
58
59 d2 = int(round((1.5)**(-1)*d1))
60
61 while gcd(d2,d1) != 1:
62 d2 += 1
63
64 d3 = int(round((1.5)**(-2)*d1))
65
66 while gcd(d3, d2) != 1 or gcd(d3, d1) != 1:
67 d3 += 1
68
69 d4 = int(round((1.5)**(-3)*d1))
70
71 while gcd(d4, d3) != 1 or gcd(d4, d2) != 1 or gcd(d4, d1) != 1:
72 d4 += 1
73
74
75 d5 = int(round((1.5)**(-4)*d1))
76
77 while gcd(d5, d4) != 1 or gcd(d5, d3) != 1 or gcd(d5, d2) != 1 or gcd(d5, d1) != 1:
78 d5 += 1
79
80 d6 = int(round((1.5)**(-5)*d1))
81 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:
82 d6 += 1
83 g2 = g1**(1.5)**(-1)*g1
84 g3 = g1**(1.5)**(-2)*g1
85 g4 = g1**(1.5)**(-3)*g1
86 g5 = g1**(1.5)**(-4)*g1
87 g6 = g1**(1.5)**(-5)*g1
88
89 return (d1, d2, d3, d4, d5, d6, g1, g2, g3, g4, g5, g6)
90 def comb_array(x, g1, d1):
91
92 (d1,d2,d3,d4,d5,d6,g1,g2,g3,g4,g5,g6) = calculate_parameters(d1,g1)
93
94
95
96 c1out = comb(x, g1, d1)
97 c2out = comb(x, g2, d2)
98 c3out = comb(x, g3, d3)
99 c4out = comb(x, g4, d4)
100 c5out = comb(x, g5, d5)
101 c6out = comb(x, g6, d6)
102
103
104 Lc1 = len(c1out)
105 Lc2 = len(c2out)
106 Lc3 = len(c3out)
107 Lc4 = len(c4out)
108 Lc5 = len(c5out)
109 Lc6 = len(c6out)
110
111 Lc = max(Lc1, Lc2, Lc3, Lc4, Lc5, Lc6)
112
113 y = zeros((Lc, ))
114
115 y[0:Lc1] = c1out
116 y[0:Lc2] += c2out
117 y[0:Lc3] += c3out
118 y[0:Lc4] += c4out
119 y[0:Lc5] += c5out
120 y[0:Lc6] += c6out
121
122 return y
123
124 def comb(x, g, d):
125 LEN = len(x)+d
126 print d
127 y = zeros((LEN,))
128 for n in range(0, LEN):
129 if n - d < 0:
130 y[n] = 0
131 else:
132 y[n] = x[n-d] + g*y[n-d]
133
134 return y
135
136 def allpass(x, g, d):
137 LENx = len(x)
138 LENy = LENx+d
139 y = zeros((LENy,))
140 for n in range(0, LENy):
141 if n-d < 0:
142 y[n] = -g*x[n]
143 elif n >= LENx:
144 y[n] = x[n-d] + g*y[n-d]
145 else:
146 y[n] = x[n-d] - g*x[n] + g*y[n-d]
147
148 return y
149
150 def lowpass(x, g):
151 LEN = len(x)
152 y = zeros((LEN,))
153
154 for n in range(0, LEN):
155 if n-1 < 0:
156 y[n] = (1-g)*x[n]
157 else:
158 y[n] = (1-g)*x[n] + g*y[n-1]
159
160 return y
161
162 ga = 1./sqrt(2.)
163
164 cin = 0.5*lx + 0.5*rx
165 cout = comb_array(cin, g1, d1)
166
167
168 ra = allpass(cout, ga, da+m/2)
169 la = allpass(cout, ga, da-m/2)
170
171 ral = lowpass(ra, gc)
172 lal = lowpass(la, gc)
173
174 ralg = G*ral
175 lalg = G*lal
176
177 ry = ralg[0:len(rx)] + (1-G)*rx
178 ly = lalg[0:len(lx)] + (1-G)*lx
179
180 # ry = cout
181 # ly = cout
182
183
184
185 return (ry, ly)
186
187 class UI:
188
189 def __init__(self, master, directory):
190 self.master = master
191
192 self.directory = directory
193
194
195
196 yamlinput = YamlInput(filename="session.yaml")
197
198 try:
199 self.sessionpool = yamlinput()
200 try:
201 self.files_to_visit = self.sessionpool['files_to_visit']
202 except:
203 self.files_to_visit = []
204
205 try:
206 self.visited_files = self.sessionpool['visited_files']
207 except:
208 self.visited_files = []
209
210
211
212 except:
213 print "[II] Could not open sessionpool file, creating a new one"
214 self.sessionpool = Pool()
215 self.files_to_visit = glob("%s/*.wav" % directory)
216 for i in self.files_to_visit:
217 self.sessionpool.add('files_to_visit', i)
218 self.visited_files = []
219
220 if len(self.files_to_visit) == 0:
221 tkMessageBox.showinfo("","No files to visit")
222 master.destroy()
223 return
224
225 filename = self.files_to_visit[-1]
226 self.filename = filename
227 # visited_files.append(filename)
228 self.label_top = Label(master, text="")
229 self.label_top.grid(row=0, column=0, columnspan=6)
230
231 self.load_song(filename)
232
233
234 # Top Label
235
236 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))
237
238 # Sliders
239
240 self.scale_d1 = Scale(master, to_=0.01, from_=0.1, resolution=0.01, label="d1", showvalue=True)#, command=self.callback_update_parameters)
241 self.scale_d1.bind("<ButtonRelease-1>",self.callback_update_parameters)
242 self.scale_d1.grid(row=1,column=0,rowspan=17,sticky=N+S+E+W)
243 self.scale_g1 = Scale(master,to_=0.01, from_=0.99, resolution=0.01, label="g1", showvalue=True)#, command=self.callback_update_parameters)
244 self.scale_g1.bind("<ButtonRelease-1>",self.callback_update_parameters)
245
246 self.scale_g1.grid(row=1,column=1,rowspan=17,sticky=N+S+E+W)
247 self.scale_da = Scale(master, to_=0.006, from_=0.012, resolution=0.001, label="da", showvalue=True)#, command=self.callback_update_parameters)
248 self.scale_da.bind("<ButtonRelease-1>",self.callback_update_parameters)
249
250 self.scale_da.grid(row=1,column=2,rowspan=17,sticky=N+S+E+W)
251 self.scale_G = Scale(master,to_=0.01, from_=0.99, resolution=0.01, label="G", showvalue=True)#, command=self.callback_update_parameters)
252 self.scale_G.bind("<ButtonRelease-1>",self.callback_update_parameters)
253
254 self.scale_G.grid(row=1,column=3,rowspan=17,sticky=N+S+E+W)
255 self.scale_gc = Scale(master, to_=0.01, from_=0.99, resolution=0.01, label="gc", showvalue=True)#, command=self.callback_update_parameters)
256 self.scale_gc.bind("<ButtonRelease-1>",self.callback_update_parameters)
257
258 self.scale_gc.grid(row=1,column=4,rowspan=17,sticky=N+S+E+W)
259
260
261 # Labels
262
263 self.label_T60 = Label(master, text="Reverberation Time: ")
264 self.label_T60.grid(row=2,column=6,sticky=N+S+E+W)
265 self.label_D = Label(master, text="Echo Density: ")
266 self.label_D.grid(row=3,column=6,sticky=N+S+E+W)
267 self.label_C = Label(master, text="Clarity: ")
268 self.label_C.grid(row=4,column=6,sticky=N+S+E+W)
269 self.label_Tc = Label(master, text="Central Time: ")
270 self.label_Tc.grid(row=5,column=6,sticky=N+S+E+W)
271 self.label_SC = Label(master, text="Spectral Centroid: ")
272 self.label_SC.grid(row=6,column=6,sticky=N+S+E+W)
273
274
275 # Buttons
276
277 self.button_plot_impulse = Button(master, text="Plot Impulse",command=self.callback_plot_impulse, width=15).grid(row=7,column=6,sticky=N+S+E+W)
278 self.button_plot_raw = Button(master, text="Plot Raw", width=15,command=self.callback_plot_raw).grid(row=8,column=6,sticky=N+S+E+W)
279 self.button_plot_reverb = Button(master, text="Plot Reverb", width=15, command=self.callback_plot_reverb).grid(row=9, column=6,sticky=N+S+E+W)
280 self.button_play_raw = Button(master, text="Play Raw", bg="green", fg="white", width=15, command=self.callback_play_raw).grid(row=10, column=6,sticky=N+S+E+W)
281 self.button_play_reverb = Button(master, text="Play Reverb", bg="green", fg="white", width=15, command=self.callback_play_reverb).grid(row=11, column=6,sticky=N+S+E+W)
282 self.button_stop = Button(master, text="Stop Playing", bg="red", fg="white", width=15, command=self.callback_stop).grid(row=12, column=6,sticky=N+S+E+W)
283 self.button_save = Button(master, text="Save", fg="white", bg="orange", width=15, command=self.callback_save).grid(row=13, column=6,sticky=N+S+E+W)
284 self.button_reset = Button(master, text="Undo", width=15, command=self.callback_reset).grid(row=14, column=6,sticky=N+S+E+W)
285 self.button_next = Button(master, text="Next >>", width=15, command=self.callback_next).grid(row=15, column=6,sticky=N+S+E+W)
286
287
288
289 # Figure
290
291 self.figure = Figure( dpi=50)
292 self.figure.text(0.5,0.5,'No plot selected', weight = "bold", horizontalalignment='center')
293
294
295 # a tk.DrawingArea
296 self.canvas = FigureCanvasTkAgg(self.figure, master=root)
297 #self.canvas.get_tk_widget().config(height=500, width=640)
298 self.canvas.show()
299 self.canvas.get_tk_widget().grid(row=0, column=7, rowspan=17, padx=20,sticky=E+W+N+S)
300
301 # toolbar = NavigationToolbar2TkAgg( master, master )
302 # toolbar.update()
303 self.canvas._tkcanvas.grid(row=0, column=7, rowspan=17)
304 # self.scale_d1.pack()
305
306 # Toolbar for canvas
307
308 self.toolbar_frame = Frame(master)
309 self.toolbar_frame.grid(row=17,column=7,sticky=E+W+N+S, padx=19)
310 self.toolbar = NavigationToolbar2TkAgg(self.canvas, self.toolbar_frame)
311
312
313
314 Grid.columnconfigure(master, 7, weight=1)
315 Grid.rowconfigure(master, 1, weight=1)
316
317 # Status bar
318
319 self.status_bar_text = Label(text="Ready.")
320 self.status_bar_text.grid(row=18, column=0, columnspan = 8, sticky=N+S+E, padx=10)
321
322 self.lastplot = ''
323 self.parameterschanged_render = True
324 self.pendingactions = []
325
326 # Initial values
327
328 d1t = 0.05
329 self.d1 = d1t*self.SR
330 dat = 0.006
331 self.da = dat*self.SR
332 g1 = 0.5
333 self.g1 = g1
334 G = 0.5
335 self.G = G
336 gc = 0.5
337 self.gc = gc
338
339 self.scale_d1.set(d1t)
340 self.scale_da.set(dat)
341 self.scale_g1.set(g1)
342 self.scale_gc.set(gc)
343 self.scale_G.set(G)
344
345 t = zeros((self.SR*120,))
346 t[0] = 1
347
348 self.impulse = t
349
350 # self.callback_plot_impulse()
351
352
353 # Pyaudio object
354
355 # self.player = pyaudio.PyAudio()
356
357 # self.player_idx = 0
358 #
359 # self.playerprocess = None
360
361
362 # Pool
363
364 self.pool = Pool()
365 self.pool.set('filename', self.filename)
366 self.pool.set('sampleRate', self.SR)
367 self.pool.set('nChannels', self.numChannels)
368
369
370 # Finally
371 self.callback_update_parameters(None)
372
373
374
375
376
377 def pyaudio_callback_raw(self, in_data, frame_count, time_info, status):
378 if self.player_command == 'Stop':
379 return (0, pyaudio.paAbort)
380
381 data = self.audio[self.player_idx:self.player_idx+frame_count, :]
382
383 data = reshape(data, (data.shape[0]*data.shape[1], 1))
384
385 # print data
386 self.player_idx += frame_count
387
388
389 return (data, pyaudio.paContinue)
390
391
392 def play_reverb(self):
393
394 self.calculate_impulse_response()
395 ly, ry = self.impulse_response_left_channel, self.impulse_response_right_channel
396
397 lx = self.audio[:,0]
398 rx = self.audio[:,1]
399
400 print "Convolving left channel"
401 l_out = fftconvolve(ly, lx)
402
403 print "Convolving right channel"
404 r_out = fftconvolve(ry, rx)
405
406
407
408 lim = min(len(l_out), len(r_out))
409
410
411
412 if self.numChannels == 1:
413 audio_out = l_out[0:lim]
414 else:
415 audio_out = concatenate((matrix(l_out[0:lim]).T,
416 matrix(r_out[0:lim]).T
417 ),
418 axis=1)
419
420 reverb_filename = "%s_reverb_%s" % (self.filename.split('.')[0], self.filename.split('.')[1])
421
422 audio_file = Sndfile(reverb_filename, 'w', Format(self.filename.split('.')[1]), self.numChannels, self.SR)
423 audio_file.write_frames(audio_out)
424 audio_file.close()
425
426 self.reverberated_audio = audio_out
427 #
428 # audiowriter(audio_out)
429
430 self.reverb_filename = reverb_filename
431
432 self.playerprocess = subprocess.Popen("mplayer %s" % reverb_filename,
433 stdout = subprocess.PIPE,
434 shell=True,
435 preexec_fn=os.setsid)
436
437 def play_raw(self):
438 self.playerprocess = subprocess.Popen("mplayer %s" % self.filename,
439 stdout = subprocess.PIPE,
440 shell=True,
441 preexec_fn=os.setsid)
442
443
444
445
446
447 def remove_action_from_status(self, text):
448
449 self.pendingactions.remove(text)
450
451 if len(self.pendingactions) == 0:
452 self.status_bar_text.config(text='Ready.')
453 elif len(self.pendingactions) == 1:
454 self.status_bar_text.config(text=self.pendingactions[0]+'.')
455 else:
456 self.status_bar_text.config(text=reduce(lambda h,t: h+','+t, self.pendingactions)+'.')
457
458
459 def add_action_to_status(self, text):
460
461 self.pendingactions.append(text)
462
463 if len(self.pendingactions) == 0:
464 self.status_bar_text.config(text='Ready.')
465 elif len(self.pendingactions) == 1:
466 self.status_bar_text.config(text=text+'.')
467 else:
468 self.status_bar_text.config(text=reduce(lambda h,t: h+', '+t, self.pendingactions)+'.')
469
470 print self.pendingactions, len(self.pendingactions)
471
472
473 def load_song(self, filename):
474 # self.label_top.config(text="Training '%s'" % filename)
475 # print filename
476 #self.audio, self.SR, self.numChannels = AudioLoader(filename=filename)()
477 tup = AudioLoader(filename=filename)()
478 self.audio = tup[0]
479 self.SR = tup[1]
480 self.numChannels = tup[2]
481 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))
482 self.saved = False
483
484
485
486
487 def estimate_T60(self, d1, g1, gc, G, SR):
488 ga = 1/sqrt(2)
489 return d1/SR/log(g1)*log(10**-3/ga/(1-gc)/G)
490
491 def calculate_parameters(self,d1,g1):
492
493 d2 = int(round((1.5)**(-1)*d1))
494
495 while gcd(d2,d1) != 1:
496 d2 += 1
497
498 d3 = int(round((1.5)**(-2)*d1))
499
500 while gcd(d3, d2) != 1 or gcd(d3, d1) != 1:
501 d3 += 1
502
503 d4 = int(round((1.5)**(-3)*d1))
504
505 while gcd(d4, d3) != 1 or gcd(d4, d2) != 1 or gcd(d4, d1) != 1:
506 d4 += 1
507
508
509 d5 = int(round((1.5)**(-4)*d1))
510
511 while gcd(d5, d4) != 1 or gcd(d5, d3) != 1 or gcd(d5, d2) != 1 or gcd(d5, d1) != 1:
512 d5 += 1
513
514 d6 = int(round((1.5)**(-5)*d1))
515 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:
516 d6 += 1
517 g2 = g1**(1.5)**(-1)*g1
518 g3 = g1**(1.5)**(-2)*g1
519 g4 = g1**(1.5)**(-3)*g1
520 g5 = g1**(1.5)**(-4)*g1
521 g6 = g1**(1.5)**(-5)*g1
522
523 return (d1, d2, d3, d4, d5, d6, g1, g2, g3, g4, g5, g6)
524 def estimate_C(self, g1, G, gc):
525 g2 = g1**(1.5)**(-1)*g1
526 g3 = g1**(1.5)**(-2)*g1
527 g4 = g1**(1.5)**(-3)*g1
528 g5 = g1**(1.5)**(-4)*g1
529 g6 = g1**(1.5)**(-5)*g1
530 gains = zeros((6,1))
531 gains[0] = g1
532 gains[1] = g2
533 gains[2] = g3
534 gains[3] = g4
535 gains[4] = g5
536 gains[5] = g6
537
538 return -10*log10(G**2*(1-gc)/(1+gc)*sum(1/(1-gains**2)))
539
540 def estimate_D(self, d1, g1, da, SR):
541 Dm = zeros((6,10))
542 delays = zeros((6,))
543 gains = zeros((6,1))
544 (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)
545 for k in range(1, 7):
546 for m in range(1, 11):
547 Dm[k-1,m-1] = max(0.1-m*delays[k-1]/SR,0)
548
549 return 10/da*self.SR*sum(Dm)
550
551 def estimate_Tc(self, d1, g1, da, SR):
552 delays = zeros((6,))
553 gains = zeros((6,1))
554 (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)
555 return sum(delays/SR*gains**2/(1-gains**2)**2)/sum(gains**2/(1-gains**2)) + da/SR
556
557
558 def callback_update_parameters(self,_):
559 SR = self.SR
560 d1t = self.scale_d1.get()
561 print d1t
562
563 d1 = round(d1t*SR)
564 g1 = self.scale_g1.get()
565 dat = self.scale_da.get()
566 da = round(dat*SR)
567 G = self.scale_G.get()
568 gc = self.scale_gc.get()
569
570
571 T60 = self.estimate_T60(d1,g1,gc,G,SR)
572 D = self.estimate_D(d1, g1, da, SR)/10
573 C = self.estimate_C(g1, G, gc)
574 Tc = self.estimate_Tc(d1,g1,da,SR)
575 SC = self.estimate_SC(gc, SR)
576
577 self.d1_old = self.d1
578 self.G_old = self.G
579 self.gc_old = self.gc
580 self.g1_old = self.g1
581 self.da_old = self.da
582
583 self.d1 = d1
584 self.G = G
585 self.gc = gc
586 self.g1 = g1
587 self.da = da
588
589
590
591 self.pool.set('parameters.d1', d1t)
592 self.pool.set('parameters.G', G)
593 self.pool.set('parameters.gc', gc)
594 self.pool.set('parameters.g1', g1)
595 self.pool.set('parameters.da', dat)
596
597
598
599 self.T60 = T60
600 self.D = D
601 self.Tc = Tc
602 self.SC = SC
603 self.C = C
604
605 self.pool.set('parameters.T60', T60)
606 self.pool.set('parameters.D', D)
607 self.pool.set('parameters.C', C)
608 self.pool.set('parameters.Tc', Tc)
609 self.pool.set('parameters.SC', SC)
610
611 self.label_T60.config(text="Reverberation Time: %.3fs" % T60)
612 self.label_D.config(text="Echo Density: %.3f at 0.1s" % D)
613 self.label_C.config(text="Clarity: %.3f dB" % C)
614 self.label_Tc.config(text="Central Time: %.3fs" % Tc)
615 self.label_SC.config(text="Spectral Centroid: %.3f Hz" % SC)
616
617 self.lastplot = ''
618 self.parameterschanged_render = True
619 # self.callback_plot_impulse()
620
621
622 def estimate_SC(self, gc, SR):
623 n = arange(0, SR/2+1)
624 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)))
625
626
627
628
629 def say_hi(self):
630 print "Hi, there"
631
632 def callback_plot_impulse(self):
633 try:
634 thread.start_new_thread(self.plot_impulse, ())
635 except:
636 print "[EE] Could not start new thread"
637
638
639
640 def calculate_impulse_response(self):
641 self.add_action_to_status('Calculating impulse response')
642 N = self.numChannels
643 SR = self.SR
644 T = 1.0/self.SR
645
646 delta = self.impulse[0:int(self.T60*self.SR)]
647 print "delta:"
648 print delta
649
650 d1 = int(self.d1)
651 g1 = self.g1
652 da = int(self.da)
653 G = self.G
654 gc = self.gc
655
656 mt = 0.002
657 m = int(mt*SR)
658
659 (ly, ry) = zafar(delta,delta,d1,g1,da,G,gc,m)
660
661 limt = self.T60
662
663 lim = int(limt*SR)
664 t = arange(0, lim)*T
665
666 padded_y = zeros(shape(t))
667 padded_y[0:len(ly)] = ly
668
669
670 padded_y = zeros(shape(t))
671 padded_y[0:len(ry)] = ry
672
673 ry = padded_y
674
675 self.impulse_response_left_channel = ly
676 self.impulse_response_right_channel = ry
677
678
679 self.remove_action_from_status('Calculating impulse response')
680
681
682
683 def plot_impulse(self):
684 if self.lastplot != 'impulse':
685 self.add_action_to_status('Plotting impulse response')
686 N = self.numChannels
687 SR = self.SR
688 T = 1.0/self.SR
689
690 delta = self.impulse[0:int(self.T60*self.SR)]
691 print "delta:"
692 print delta
693
694 d1 = int(self.d1)
695 g1 = self.g1
696 da = int(self.da)
697 G = self.G
698 gc = self.gc
699
700 mt = 0.002
701 m = int(mt*SR)
702
703 print "Calculating zafar"
704 (ly, ry) = zafar(delta,delta,d1,g1,da,G,gc,m)
705
706 print "Stopped calculating zafar"#ly.shape
707 limt = self.T60
708
709 lim = int(limt*SR)
710 print "lim:", lim
711
712 t = arange(0, lim)*T
713 # print t
714
715 # Pad ly to t
716 print "Shape ly"
717 print ly
718 print len(ly)
719 padded_y = zeros(shape(t))
720 padded_y[0:len(ly)] = ly
721
722 print "Padded y"
723 #print padded_y
724
725 # ly = padded_y
726
727 # Pad ry to t
728
729 padded_y = zeros(shape(t))
730 padded_y[0:len(ry)] = ry
731
732 ry = padded_y
733
734
735
736 self.figure.clear()
737
738 print "Passed A"
739 subplt0 = self.figure.add_subplot(2,1,1)
740
741 subplt0.plot(t,abs(ly[0:lim]))
742 subplt0.set_title('Left Channel')
743 subplt0.set_xlabel('time (s)')
744 subplt0.set_ylabel('amplitude')
745 subplt0.axvspan(0,0.1, alpha=0.1,color='cyan')
746 subplt0.axvline(self.Tc, color='red', linestyle='--')
747 subplt0.axvline(0.1, color='cyan', linestyle='--')
748 subplt0.annotate('Central Time (Tc)', xy=(self.Tc, 0.5), xytext=(self.Tc+0.01, 0.52), arrowprops=dict(facecolor='black',width=1))
749 subplt0.annotate('Echo Density (D) Measurement Point ', xy=(0.1, 0.6), xytext=(.11, 0.62), arrowprops=dict(facecolor='black',width=1))
750
751 #
752
753 subplt1 = self.figure.add_subplot(2,1,2,sharex=subplt0)
754 subplt1.set_title('Right Channel')
755
756 subplt1.plot(t,abs(ry[0:lim]))
757 subplt1.set_xlabel('time (s)')
758 subplt1.set_ylabel('amplitude')
759 subplt1.axvspan(0,0.1, alpha=0.1,color='cyan')
760 subplt1.axvline(self.Tc, color='red', linestyle='--')
761 subplt1.axvline(0.1, color='cyan', linestyle='--')
762
763
764 self.figure.suptitle("Reverberation Impulse Response")
765
766 # print "Passed B"
767 #
768 self.remove_action_from_status('Plotting impulse response')
769 self.canvas.draw()
770
771 self.lastplot = 'impulse'
772 #
773 thread.exit_thread()
774
775
776
777 def plot_raw(self):
778 if self.lastplot != 'raw':
779 self.add_action_to_status('Plotting raw')
780 N = self.numChannels
781 print "Channels: %d" % N
782 L = len(self.audio[:,0])
783
784
785
786
787 self.figure.clear()
788
789 T = 1.0/self.SR
790 t = arange(0, L)*T
791
792 oldsubplt = None
793 for n in range(0, N):
794 if oldsubplt is not None:
795 subplt = self.figure.add_subplot(N,1,n+1,sharex=oldsubplt)
796 else:
797 subplt = self.figure.add_subplot(N,1,n+1)
798 subplt.plot(t,self.audio[:,n])
799 subplt.set_title('Channel %d' % n)
800 subplt.set_xlabel('time (s)')
801 subplt.set_ylabel('amplitude')
802
803 oldsubplt = subplt
804
805
806 self.figure.suptitle('Raw Signal')
807 self.canvas.draw()
808
809 self.lastplot = 'raw'
810 self.remove_action_from_status('Plotting raw')
811 thread.exit_thread()
812 def callback_plot_raw(self):
813 try:
814 thread.start_new_thread(self.plot_raw, ())
815 except:
816 print "[EE] Could not start new thread"
817
818
819
820 # show()
821
822 def plot_reverb(self):
823 if self.lastplot != 'reverb':
824 self.add_action_to_status('Plotting reverberated signal')
825
826 self.calculate_impulse_response()
827 ly, ry = self.impulse_response_left_channel, self.impulse_response_right_channel
828
829 lx = self.audio[:,0]
830 rx = self.audio[:,1]
831
832 print "Concolving left channel"
833 l_out = fftconvolve(ly, lx)
834
835 print "Convolving right channel"
836 r_out = fftconvolve(ry, rx)
837
838
839
840 lim = min(len(l_out), len(r_out))
841 # N = self.numChannels
842 # SR = self.SR
843 # T = 1.0/self.SR
844 #
845 #
846 # d1 = int(self.d1)
847 # g1 = self.g1
848 # da = int(self.da)
849 # G = self.G
850 # gc = self.gc
851 #
852 # mt = 0.002
853 # m = int(mt*SR)
854 #
855 # lchannel = ravel(self.audio[:,0])
856 # rchannel = ravel(self.audio[:,1])
857 #
858 # print "Calculating zafar"
859 #
860 # if self.parameterschanged_render == True:
861 # (ly, ry) = zafar(lchannel,rchannel,d1,g1,da,G,gc,m)
862 #
863 # self.reverberated_signal_left_channel = ly
864 # self.reverberated_signal_right_channel = ry
865 #
866 # self.parameterschanged_render = 0
867 # else:
868 # ly = self.reverberated_signal_left_channel
869 # ry = self.reverberated_signal_right_channel
870 #
871 # print "Stopped calculating zafar"#ly.shape
872 # # limt = self.T60
873 #
874 # lim = int(limt*SR)
875
876 # lim = len(lchannel)
877 # print "lim:", lim
878 T = 1/self.SR
879 t = arange(0, lim)*T
880 # print t
881
882 # Pad ly to t
883 # print "Shape ly"
884 ## print ly
885 # print len(ly)
886 # padded_y = zeros(shape(t))
887 # padded_y[0:len(ly)] = ly
888
889 # print "Padded y"
890 #print padded_y
891
892 # ly = padded_y
893
894 # Pad ry to t
895
896 # padded_y = zeros(shape(t))
897 # padded_y[0:len(ry)] = ry
898
899 # ry = padded_y
900 #
901
902
903 self.figure.clear()
904
905 print "Passed A"
906 subplt0 = self.figure.add_subplot(2,1,1)
907
908 subplt0.plot(t,l_out[0:lim])
909 subplt0.set_title('Left Channel')
910 subplt0.set_xlabel('time (s)')
911 subplt0.set_ylabel('amplitude')
912 # subplt0.axvspan(0,0.1, alpha=0.1,color='cyan')
913 # subplt0.axvline(self.Tc, color='red', linestyle='--')
914 # subplt0.axvline(0.1, color='cyan', linestyle='--')
915 # subplt0.annotate('Central Time (Tc)', xy=(self.Tc, 0.5), xytext=(self.Tc+0.01, 0.52), arrowprops=dict(facecolor='black',width=1))
916 # subplt0.annotate('Echo Density (D) Measurement Point ', xy=(0.1, 0.6), xytext=(.11, 0.62), arrowprops=dict(facecolor='black',width=1))
917
918 #
919
920 subplt1 = self.figure.add_subplot(2,1,2,sharex=subplt0)
921 subplt1.set_title('Right Channel')
922
923 subplt1.plot(t,r_out[0:lim])
924 subplt1.set_xlabel('time (s)')
925 subplt1.set_ylabel('amplitude')
926 # subplt1.axvspan(0,0.1, alpha=0.1,color='cyan')
927 # subplt1.axvline(self.Tc, color='red', linestyle='--')
928 # subplt1.axvline(0.1, color='cyan', linestyle='--')
929
930
931 self.figure.suptitle("Reverberated Signal")
932
933 # print "Passed B"
934 #
935 self.remove_action_from_status('Plotting reverberated signal')
936 self.canvas.draw()
937
938 self.lastplot = 'reverb'
939 #
940 thread.exit_thread()
941 def callback_plot_reverb(self):
942 try:
943 thread.start_new_thread(self.plot_reverb, ())
944 except:
945 print "[EE] Could not start new thread"
946
947
948 def callback_play_raw(self):
949 print "[II] Called callback_play_raw"
950 try:
951 self.playerprocess.terminate()
952 except:
953 pass
954 self.play_raw()
955
956 def callback_play_reverb(self):
957
958 print "[II] Called callback_play_reverb"
959 try:
960 self.playerprocess.terminate()
961 except:
962 pass
963
964 self.play_reverb()
965
966 def callback_stop(self):
967 self.playerprocess.terminate()
968
969 def callback_save(self):
970 outf = "%s_parameters.yaml" % self.filename.split('.')[0]
971 out = YamlOutput(filename=outf)
972 out(self.pool)
973 print "[II] Parameters Saved"
974 self.saved = True
975
976 def callback_reset(self):
977 d1 = self.d1
978 g1 = self.g1
979 da = self.da
980 G = self.G
981 gc = self.gc
982
983 self.d1 = self.d1_old
984 self.g1 = self.g1_old
985 self.G = self.G_old
986 self.gc = self.gc_old
987 self.da = self.da_old
988
989 self.scale_d1.set(self.d1/self.SR)
990 self.scale_g1.set(self.g1)
991 self.scale_da.set(self.da/self.SR)
992 self.scale_G.set(self.G)
993 self.scale_gc.set(self.gc)
994
995
996 def callback_next(self):
997 if self.saved == False:
998 tkMessageBox.showerror("File not saved", "You need to save your changes first")
999 return
1000
1001
1002 self.visited_files.append(self.filename)
1003 self.sessionpool.add('visited_files', self.filename)
1004 self.files_to_visit.pop()
1005 self.sessionpool.remove('files_to_visit')
1006 for i in self.files_to_visit:
1007 self.sessionpool.add('files_to_visit', i)
1008 outp = YamlOutput(filename="session.yaml")(self.sessionpool)
1009
1010 if len(self.files_to_visit) == 0:
1011 tkMessageBox.showinfo("Congratulations!", "You finished the training session!")
1012 self.master.destroy()
1013 return
1014 self.filename = self.files_to_visit[-1]
1015 self.load_song(self.filename)
1016
1017
1018
1019
1020 if __name__ == "__main__":
1021 if len(argv) != 2:
1022 print "[EE] Wrong number of arguments"
1023 print "[II] Correct syntax is:"
1024 print "[II] \t%s <trainingdir>"
1025 print "[II] where <trainingdir> contains the segments in .wav format and their corresponding .yaml files"
1026
1027 exit(-1)
1028
1029 print "[II] Using directory: %s" % argv[1]
1030 root = Tk()
1031 app = UI(root, argv[1])
1032 root.mainloop()
1033
1034 # app.player.terminate()
1035 # root.destroy()