17313c254b
* Moved all module settings to a new config.py file * Completely overhauled visualize.py and added a new radiate effect that colours the radiative beats according the beat frequency. * Improved some constants like the decay constant to be parametric so that they scale to any led strip size * Added temporal dithering to Beat.update_pixels() so that it now supports fractional speed values. Being limited to integral values was starting to become a problem. * Overhauled and simplified the LED module. * When updating pixels, the LED module no longer sends UDP packets for pixels that have not changed. This optimization reduces the packet load significantly and should allow for higher refresh rates. * Renamed lookup_table.npy to gamm_table.npy to better reflect that the table is used for gamma correction of the LED strip
60 lines
2.0 KiB
Python
60 lines
2.0 KiB
Python
from __future__ import print_function
|
|
from __future__ import division
|
|
import numpy as np
|
|
from scipy.interpolate import interp1d
|
|
import matplotlib
|
|
matplotlib.use('TkAgg')
|
|
import matplotlib.pylab as plt
|
|
plt.style.use('lawson')
|
|
import microphone as mic
|
|
import config
|
|
|
|
# FFT statistics for a few previous updates
|
|
_ys_historical_energy = np.zeros(shape=(config.N_SUBBANDS, config.N_HISTORY))
|
|
|
|
|
|
def beat_detect(ys):
|
|
global _ys_historical_energy
|
|
# Beat energy criterion
|
|
current_energy = ys * ys
|
|
mean_energy = np.mean(_ys_historical_energy, axis=1)
|
|
has_beat_energy = current_energy > mean_energy * config.ENERGY_THRESHOLD
|
|
_ys_historical_energy = np.roll(_ys_historical_energy, shift=1, axis=1)
|
|
_ys_historical_energy[:, 0] = current_energy
|
|
# Beat variance criterion
|
|
ys_variance = np.var(_ys_historical_energy, axis=1)
|
|
has_beat_variance = ys_variance > config.VARIANCE_THRESHOLD
|
|
# Combined energy + variance detection
|
|
has_beat = has_beat_energy * has_beat_variance
|
|
return has_beat
|
|
|
|
|
|
def fft(data):
|
|
"""Returns |fft(data)|"""
|
|
yL, yR = np.split(np.abs(np.fft.fft(data)), 2)
|
|
ys = np.add(yL, yR[::-1])
|
|
xs = np.arange(int(config.MIC_RATE / config.FPS) / 2, dtype=float)
|
|
xs *= float(config.MIC_RATE) / int(config.MIC_RATE / config.FPS)
|
|
return xs, ys
|
|
|
|
|
|
# def fft(data):
|
|
# """Returns |fft(data)|"""
|
|
# yL, yR = np.split(np.abs(np.fft.fft(data)), 2)
|
|
# ys = np.add(yL, yR[::-1])
|
|
# xs = np.arange(mic.CHUNK / 2, dtype=float) * float(mic.RATE) / mic.CHUNK
|
|
# return xs, ys
|
|
|
|
|
|
def fft_log_partition(data, fmin=30, fmax=20000, subbands=64):
|
|
"""Returns FFT partitioned into subbands that are logarithmically spaced"""
|
|
xs, ys = fft(data)
|
|
xs_log = np.logspace(np.log10(fmin), np.log10(fmax), num=subbands * 32)
|
|
f = interp1d(xs, ys)
|
|
ys_log = f(xs_log)
|
|
X, Y = [], []
|
|
for i in range(0, subbands * 32, 32):
|
|
X.append(np.mean(xs_log[i:i + 32]))
|
|
Y.append(np.mean(ys_log[i:i + 32]))
|
|
return np.array(X), np.array(Y)
|