From e874ed3b2c3f9599b746371f4d3df61e4e806101 Mon Sep 17 00:00:00 2001 From: Scott Lawson Date: Thu, 29 Dec 2016 15:51:38 -0700 Subject: [PATCH] Resolved issues with Python 3.5 compatibility Fixed some bugs that occurred in Python 3.5 but were not present in Python 2.7. Most compatiblity issues were caused by incompatible type casting of numpy arrays. --- python/led.py | 2 +- python/visualization.py | 52 ++++++++++++++++++++++++++++------------- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/python/led.py b/python/led.py index e3e4971..b2b3458 100644 --- a/python/led.py +++ b/python/led.py @@ -15,7 +15,7 @@ pixels = np.tile(1, (3, config.N_PIXELS)) def update(): global pixels, _prev_pixels - pixels = np.clip(pixels, 0, 255) + pixels = np.clip(pixels, 0, 255).astype(int) m = '' p = _gamma[pixels] if config.GAMMA_CORRECTION else np.copy(pixels) for i in range(config.N_PIXELS): diff --git a/python/visualization.py b/python/visualization.py index 0baf103..3cc353c 100644 --- a/python/visualization.py +++ b/python/visualization.py @@ -75,13 +75,13 @@ b_filt = dsp.ExpFilter(np.tile(0.01, config.N_PIXELS // 2), alpha_decay=0.25, alpha_rise=0.99) p_filt = dsp.ExpFilter(np.tile(1, (3, config.N_PIXELS // 2)), alpha_decay=0.05, alpha_rise=0.8) -p = np.tile(1, (3, config.N_PIXELS // 2)) +p = np.tile(1.0, (3, config.N_PIXELS // 2)) gain = dsp.ExpFilter(np.tile(0.01, config.N_FFT_BINS), alpha_decay=0.001, alpha_rise=0.99) def largest_indices(ary, n): - """Returns the n largest indices from a numpy array.""" + """Returns indices of the n largest values in the given a numpy array""" flat = ary.flatten() indices = np.argpartition(flat, -n)[-n:] indices = indices[np.argsort(-flat[indices])] @@ -89,11 +89,12 @@ def largest_indices(ary, n): def visualize_max(y): + """Experimental sandbox effect. Not recommended for use""" y = np.copy(interpolate(y, config.N_PIXELS // 2)) * 255.0 ind = largest_indices(y, 15) - y[ind] *= -1 - y[y > 0] = 0 - y[ind] *= -1 + y[ind] *= -1.0 + y[y > 0] = 0.0 + y[ind] *= -1.0 # Blur the color channels with different strengths r = gaussian_filter1d(y, sigma=0.25) g = gaussian_filter1d(y, sigma=0.10) @@ -111,14 +112,15 @@ def visualize_max(y): led.pixels[0, :] = pixel_r led.pixels[1, :] = pixel_g led.pixels[2, :] = pixel_b + led.update() # Update the GUI plots GUI.curve[0][0].setData(y=pixel_r) GUI.curve[0][1].setData(y=pixel_g) GUI.curve[0][2].setData(y=pixel_b) - led.update() def visualize_scroll(y): + """Effect that originates in the center and scrolls outwards""" global p y = gaussian_filter1d(y, sigma=1.0)**3.0 y = np.copy(y) @@ -134,11 +136,17 @@ def visualize_scroll(y): p[0, 0] = r p[1, 0] = g p[2, 0] = b + # Update the LED strip led.pixels = np.concatenate((p[:, ::-1], p), axis=1) led.update() + # Update the GUI plots + GUI.curve[0][0].setData(y=np.concatenate((p[0, :][::-1], p[0, :]))) + GUI.curve[0][1].setData(y=np.concatenate((p[1, :][::-1], p[1, :]))) + GUI.curve[0][2].setData(y=np.concatenate((p[2, :][::-1], p[2, :]))) def visualize_energy(y): + """Effect that expands from the center with increasing sound energy""" global p y = gaussian_filter1d(y, sigma=1.0)**3.0 gain.update(y) @@ -147,22 +155,28 @@ def visualize_energy(y): r = int(np.mean(y[:len(y) // 3])) g = int(np.mean(y[len(y) // 3: 2 * len(y) // 3])) b = int(np.mean(y[2 * len(y) // 3:])) - p[0, :r] = 255 - p[0, r:] = 0 - p[1, :g] = 255 - p[1, g:] = 0 - p[2, :b] = 255 - p[2, b:] = 0 + p[0, :r] = 255.0 + p[0, r:] = 0.0 + p[1, :g] = 255.0 + p[1, g:] = 0.0 + p[2, :b] = 255.0 + p[2, b:] = 0.0 p_filt.update(p) p = p_filt.value.astype(int) p[0, :] = gaussian_filter1d(p[0, :], sigma=4.0) p[1, :] = gaussian_filter1d(p[1, :], sigma=4.0) p[2, :] = gaussian_filter1d(p[2, :], sigma=4.0) + # Update LED pixel arrays led.pixels = np.concatenate((p[:, ::-1], p), axis=1) led.update() + # Update the GUI plots + GUI.curve[0][0].setData(y=np.concatenate((p[0, :][::-1], p[0, :]))) + GUI.curve[0][1].setData(y=np.concatenate((p[1, :][::-1], p[1, :]))) + GUI.curve[0][2].setData(y=np.concatenate((p[2, :][::-1], p[2, :]))) def visualize_spectrum(y): + """Effect that maps the Mel filterbank frequencies onto the LED strip""" y = np.copy(interpolate(y, config.N_PIXELS // 2)) * 255.0 # Blur the color channels with different strengths r = gaussian_filter1d(y, sigma=0.25) @@ -179,11 +193,11 @@ def visualize_spectrum(y): led.pixels[0, :] = pixel_r led.pixels[1, :] = pixel_g led.pixels[2, :] = pixel_b + led.update() # Update the GUI plots GUI.curve[0][0].setData(y=pixel_r) GUI.curve[0][1].setData(y=pixel_g) GUI.curve[0][2].setData(y=pixel_b) - led.update() mel_gain = dsp.ExpFilter(np.tile(1e-1, config.N_FFT_BINS), @@ -194,7 +208,7 @@ volume = dsp.ExpFilter(config.MIN_VOLUME_THRESHOLD, def microphone_update(stream): global y_roll, prev_rms, prev_exp - # Normalize new audio samples + # Retrieve and normalize the new audio samples y = np.fromstring(stream.read(samples_per_frame, exception_on_overflow=False), dtype=np.int16) y = y / 2.0**15 @@ -209,19 +223,25 @@ def microphone_update(stream): led.pixels = np.tile(0, (3, config.N_PIXELS)) led.update() else: + # Transform audio input into the frequency domain XS, YS = dsp.fft(y_data, window=np.hamming) + # Remove half of the FFT data because of symmetry YS = YS[:len(YS) // 2] XS = XS[:len(XS) // 2] + # Construct a Mel filterbank from the FFT data YS = np.atleast_2d(np.abs(YS)).T * dsp.mel_y.T + # Scale data to values more suitable for visualization YS = np.sum(YS, axis=0)**2.0 mel = YS**0.5 mel = gaussian_filter1d(mel, sigma=1.0) + # Normalize the Mel filterbank to make it volume independent mel_gain.update(np.max(mel)) mel = mel / mel_gain.value + # Visualize the filterbank output visualize_spectrum(mel) # visualize_max(mel) # visualize_scroll(mel) - # visualize_energy(mel) + visualize_energy(mel) GUI.app.processEvents() print('FPS {:.0f} / {:.0f}'.format(frames_per_second(), config.FPS)) @@ -235,8 +255,8 @@ y_roll = np.random.rand(config.N_ROLLING_HISTORY, samples_per_frame) / 1e16 if __name__ == '__main__': import pyqtgraph as pg + # Create GUI plot for visualizing LED strip output GUI = gui.GUI(width=800, height=400, title='Audio Visualization') - # Audio plot GUI.add_plot('Color Channels') r_pen = pg.mkPen((255, 30, 30, 200), width=6) g_pen = pg.mkPen((30, 255, 30, 200), width=6)