0e73fd1348
* Resolved an issue with the ESP8266 where gamma correction would be performed twice. Changed GAMMA_CORRECTION to SOFTWARE_GAMMA_CORRECTION to make a distinction between software and firmware gamma correction. The ESP8266 does firmware gamma correction and dithering, while the Raspberry Pi uses slightly more inferior software gamma correction. Changed the software gamma table to match the gamma table used in the ESP8266 firmware. * Improved the spectrum visualization by using one of the color channels to visualize the absolute value of the temporal derivative of the spectrum. Also added a feature to reject the "common mode" spectral components, which is analogous to the spectral DC component. * Signficantly improved the GUI and added a frequency adjustment slider. Adjusting the frequency range has a big impact on the visualization output. Recommend using a high frequency range (something like 4 kHz - 10 kHz) when running the scrol visualization.
53 lines
1.9 KiB
Python
53 lines
1.9 KiB
Python
from __future__ import print_function
|
|
import numpy as np
|
|
import config
|
|
import melbank
|
|
|
|
|
|
class ExpFilter:
|
|
"""Simple exponential smoothing filter"""
|
|
def __init__(self, val=0.0, alpha_decay=0.5, alpha_rise=0.5):
|
|
"""Small rise / decay factors = more smoothing"""
|
|
assert 0.0 < alpha_decay < 1.0, 'Invalid decay smoothing factor'
|
|
assert 0.0 < alpha_rise < 1.0, 'Invalid rise smoothing factor'
|
|
self.alpha_decay = alpha_decay
|
|
self.alpha_rise = alpha_rise
|
|
self.value = val
|
|
|
|
def update(self, value):
|
|
if isinstance(self.value, (list, np.ndarray, tuple)):
|
|
alpha = value - self.value
|
|
alpha[alpha > 0.0] = self.alpha_rise
|
|
alpha[alpha <= 0.0] = self.alpha_decay
|
|
else:
|
|
alpha = self.alpha_rise if value > self.value else self.alpha_decay
|
|
self.value = alpha * value + (1.0 - alpha) * self.value
|
|
return self.value
|
|
|
|
|
|
def rfft(data, window=None):
|
|
window = 1.0 if window is None else window(len(data))
|
|
ys = np.abs(np.fft.rfft(data * window))
|
|
xs = np.fft.rfftfreq(len(data), 1.0 / config.MIC_RATE)
|
|
return xs, ys
|
|
|
|
|
|
def fft(data, window=None):
|
|
window = 1.0 if window is None else window(len(data))
|
|
ys = np.fft.fft(data * window)
|
|
xs = np.fft.fftfreq(len(data), 1.0 / config.MIC_RATE)
|
|
return xs, ys
|
|
|
|
|
|
def create_mel_bank():
|
|
global samples, mel_y, mel_x
|
|
samples = int(config.MIC_RATE * config.N_ROLLING_HISTORY / (2.0 * config.FPS))
|
|
mel_y, (_, mel_x) = melbank.compute_melmat(num_mel_bands=config.N_FFT_BINS,
|
|
freq_min=config.MIN_FREQUENCY,
|
|
freq_max=config.MAX_FREQUENCY,
|
|
num_fft_bands=samples,
|
|
sample_rate=config.MIC_RATE)
|
|
samples = None
|
|
mel_y = None
|
|
mel_x = None
|
|
create_mel_bank() |