diff --git a/python/mel_visualization.py b/python/mel_visualization.py index 57543e8..e19f1ac 100644 --- a/python/mel_visualization.py +++ b/python/mel_visualization.py @@ -13,7 +13,7 @@ import gui _time_prev = time.time() * 1000.0 """The previous time that the frames_per_second() function was called""" -_fps = dsp.ExpFilter(val=config.FPS, alpha_decay=0.01, alpha_rise=0.01) +_fps = dsp.ExpFilter(val=config.FPS, alpha_decay=0.002, alpha_rise=0.002) """The low-pass filter used to estimate frames-per-second""" @@ -68,58 +68,40 @@ def interpolate(y, new_length): return z -def normalize(f): - """Returns a histogram normalized numpy.array""" - lmin = float(f.min()) - lmax = float(f.max()) - return np.floor((f - lmin) / (lmax - lmin) * 255.0) - - -# r_filt = dsp.ExpFilter(np.tile(0.01, config.N_PIXELS), -# alpha_decay=0.075, alpha_rise=0.6) -# g_filt = dsp.ExpFilter(np.tile(0.01, config.N_PIXELS), -# alpha_decay=0.25, alpha_rise=0.9) -# b_filt = dsp.ExpFilter(np.tile(0.01, config.N_PIXELS), -# alpha_decay=0.5, alpha_rise=0.95) -r_filt = dsp.ExpFilter(np.tile(0.01, config.N_PIXELS), - alpha_decay=0.1, alpha_rise=0.6) -g_filt = dsp.ExpFilter(np.tile(0.01, config.N_PIXELS), +r_filt = dsp.ExpFilter(np.tile(0.01, config.N_PIXELS // 2), + alpha_decay=0.05, alpha_rise=0.6) +g_filt = dsp.ExpFilter(np.tile(0.01, config.N_PIXELS // 2), alpha_decay=0.75, alpha_rise=0.95) -b_filt = dsp.ExpFilter(np.tile(0.01, config.N_PIXELS), - alpha_decay=0.2, alpha_rise=0.4) +b_filt = dsp.ExpFilter(np.tile(0.01, config.N_PIXELS // 2), + alpha_decay=0.2, alpha_rise=0.7) def visualize(y): - y = np.copy(interpolate(y, config.N_PIXELS)) * 255.0 + y = np.copy(interpolate(y, config.N_PIXELS // 2)) * 255.0 # Blur the color channels with different strengths - r = gaussian_filter1d(y, sigma=1.0) + r = gaussian_filter1d(y, sigma=0.0) g = gaussian_filter1d(y, sigma=0.0) - b = gaussian_filter1d(y, sigma=0.0) - # Take the geometric mean of the raw and normalized histograms - # r = np.sqrt(r * normalize(r)) - # g = np.sqrt(g * normalize(g)) - # b = np.sqrt(b * normalize(b)) - r = np.roll(g, 0) - g = np.roll(g, 0) - b = np.roll(g, 0) + b = gaussian_filter1d(y, sigma=1.0) # Update the low pass filters for each color channel r_filt.update(r) g_filt.update(g) b_filt.update(b) + # Pixel values + pixel_r = np.concatenate((r_filt.value[::-1], r_filt.value)) + pixel_g = np.concatenate((g_filt.value[::-1], g_filt.value)) + pixel_b = np.concatenate((b_filt.value[::-1], b_filt.value)) # Update the LED strip values - led.pixels[:, 0] = r_filt.value - led.pixels[:, 1] = g_filt.value - led.pixels[:, 2] = b_filt.value + led.pixels[0, :] = pixel_r + led.pixels[1, :] = pixel_g + led.pixels[2, :] = pixel_b # Update the GUI plots - GUI.curve[0][0].setData(x=range(len(r_filt.value)), y=r_filt.value) - GUI.curve[0][1].setData(x=range(len(g_filt.value)), y=g_filt.value) - GUI.curve[0][2].setData(x=range(len(b_filt.value)), y=b_filt.value) + 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_PIXELS), - alpha_decay=0.01, alpha_rise=0.99) -# mel_gain = dsp.ExpFilter(np.tile(1e-1, config.N_PIXELS), -# alpha_decay=0.01, alpha_rise=0.99) +mel_gain = dsp.ExpFilter(np.tile(1e-1, config.N_SUBBANDS), + alpha_decay=0.01, alpha_rise=0.85) volume = dsp.ExpFilter(config.MIN_VOLUME_THRESHOLD, alpha_decay=0.02, alpha_rise=0.02) @@ -127,10 +109,13 @@ rms = dsp.ExpFilter(0.1, alpha_decay=0.001, alpha_rise=0.001) exp = dsp.ExpFilter(0.5, alpha_decay=0.001, alpha_rise=0.001) prev_rms = 1.0 prev_exp = 1.0 + + def microphone_update(stream): global y_roll, prev_rms, prev_exp # Normalize new audio samples - y = np.fromstring(stream.read(samples_per_frame), dtype=np.int16) + y = np.fromstring(stream.read(samples_per_frame, + exception_on_overflow=False), dtype=np.int16) y = y / 2.0**15 # Construct a rolling window of audio samples y_roll = np.roll(y_roll, -1, axis=0) @@ -143,15 +128,13 @@ def microphone_update(stream): visualize(np.tile(0.0, config.N_PIXELS)) else: XS, YS = dsp.fft(y_data, window=np.hamming) - # Construct Mel filterbank - YS = YS[XS >= 0.0] - XS = XS[XS >= 0.0] + YS = YS[:len(YS) // 2] + XS = XS[:len(XS) // 2] YS = np.atleast_2d(np.abs(YS)).T * dsp.mel_y.T YS = np.sum(YS, axis=0)**2.0 - mel = np.concatenate((YS[::-1], YS)) - mel = interpolate(mel, config.N_PIXELS) - # mel = mel**0.4 + mel = YS mel = mel**exp.value + mel = gaussian_filter1d(mel, sigma=1.0) mel_gain.update(np.max(mel)) mel = mel / mel_gain.value rms.update(np.sqrt(np.mean(mel**2.0))) @@ -159,18 +142,13 @@ def microphone_update(stream): exp.update(exp.value * 1.2) elif rms.value < 5e-2: exp.update(exp.value * 0.8) - rms_delta = '^' if rms.value - prev_rms > 0 else 'v' exp_delta = '^' if exp.value - prev_exp > 0 else 'v' - print('|{}| {:.0e}, |{}| {:.2}'.format(rms_delta, rms.value, exp_delta, exp.value)) - # WHAT IF I TAKE THE TEMPORAL VARIANCE OF EACH INDIVIDUAL BIN - # AND THEN CALCULATE THE COVARIANCE OF HOW THE DIFFERENT BIN VARIANCES - # CHANGE TOGETHER - # COULD COLOR BY COVARIANCE? BLUE PIXELS CHANGE TOGETHER, ETC + print('|{}| {:.0e}, |{}| {:.2}\t\t{:.2f}'.format( + rms_delta, rms.value, exp_delta, exp.value, frames_per_second())) prev_exp = exp.value prev_rms = rms.value visualize(mel) - GUI.app.processEvents() #print('FPS {:.0f} / {:.0f}'.format(frames_per_second(), config.FPS)) @@ -194,6 +172,9 @@ if __name__ == '__main__': GUI.add_curve(plot_index=0, pen=g_pen) GUI.add_curve(plot_index=0, pen=b_pen) GUI.plot[0].setRange(xRange=(0, config.N_PIXELS), yRange=(-5, 275)) + GUI.curve[0][0].setData(x=range(config.N_PIXELS)) + GUI.curve[0][1].setData(x=range(config.N_PIXELS)) + GUI.curve[0][2].setData(x=range(config.N_PIXELS)) # Initialize LEDs led.update() # Start listening to live audio stream