From dde00782d43534de235ad3086ad19b68fe03713c Mon Sep 17 00:00:00 2001 From: Jono Targett Date: Wed, 29 May 2024 23:15:37 +0930 Subject: [PATCH] Live detector working --- scripts/filters.py | 13 +++++++++---- scripts/live.py | 43 ++++++++++++++++++++++++++++++++----------- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/scripts/filters.py b/scripts/filters.py index 763fca7..efb937f 100644 --- a/scripts/filters.py +++ b/scripts/filters.py @@ -2,13 +2,18 @@ import numpy as np from scipy.signal import butter, lfilter, decimate -def anti_alias(data, sample_rate, max_frequency): +def anti_alias(data, sample_rate, max_frequency, order=5): FILTER_HEADROOM = 1.2 nyquist_rate = 2 * max_frequency downsample_factor = 1 if sample_rate > nyquist_rate: - filtered_data = lowpass_filter(data, max_frequency * FILTER_HEADROOM, sample_rate) + filtered_data = lowpass_filter( + data, + max_frequency * FILTER_HEADROOM, + sample_rate, + order + ) downsample_factor = int(sample_rate / nyquist_rate) filtered_data = decimate(filtered_data, downsample_factor) @@ -18,9 +23,9 @@ def anti_alias(data, sample_rate, max_frequency): return filtered_data, sample_rate, downsample_factor -def smoothing_filter(data, window_size=256): +def smoothing_filter(data, window_size=256, mode='same'): window = np.ones(window_size) / window_size - return np.convolve(data, window, mode='same') + return np.convolve(data, window, mode=mode) # Stolen from selcald def note(freq, length, amp=1.0, rate=44100): diff --git a/scripts/live.py b/scripts/live.py index 8519af3..33718a1 100755 --- a/scripts/live.py +++ b/scripts/live.py @@ -5,12 +5,13 @@ import threading import numpy as np import signal as sig from tones import TONES -from filters import anti_alias, bandpass_filter, note +from filters import anti_alias, bandpass_filter, note, smoothing_filter from scipy import signal from scipy.signal import butter, lfilter, decimate import pyqtgraph as pg from pyqtgraph.Qt import QtGui, QtWidgets, mkQApp +import time keep_running = True def signal_handler(sig, frame): @@ -40,11 +41,13 @@ class DetectorGui(QtWidgets.QMainWindow): self.tone_data = {} self.tone_lines = {} + self.tone_pens = {} for tone,color in zip(TONES.keys(), colors): - self.tone_data[tone] = np.zeros(int(10000), dtype=np.float64) #np.array([], dtype=np.float64) + self.tone_data[tone] = np.zeros(1000, dtype=np.float64) #np.array([], dtype=np.float64) #np.zeros(int(10000), dtype=np.float64) self.tone_lines[tone] = self.plot.plot(self.tone_data[tone], pen=pg.mkPen(color=color), name=tone) legend.addItem(self.tone_lines[tone], tone) + self.tone_pens[tone] = pg.mkPen(color=color) self.plot.setLabel('left', 'Signal Correlation') self.plot.setLabel('bottom', 'Time (samples)') @@ -64,11 +67,19 @@ class DetectorGui(QtWidgets.QMainWindow): self.tone_lines[tone].setData(self.tone_data[tone]) def push_tones(self, tone, values): + s = time.perf_counter() #self.tone_data[tone] = np.append(self.tone_data[tone], values) + a = time.perf_counter() self.tone_data[tone] = np.roll(self.tone_data[tone], -len(values)) self.tone_data[tone][-len(values):] = values self.tone_lines[tone].setData(self.tone_data[tone]) + #self.tone_lines[tone].setData(values) + g = time.perf_counter() + + #print(a-s, g-a) + + #self.plot.plot(values, pen=self.tone_pens[tone]) mkQApp("Correlation matrix display") @@ -91,27 +102,37 @@ def read_audio_from_stdin(chunk_size, process_chunk): process_chunk(audio_chunk) sample_rate = 44100 -note_length = 0.1 -N = 256 -cumsum_convolution = np.ones(N)/N +note_length = 0.5 +guard_duration = 0.01 def process_audio_chunk(audio_chunk): global gui data = audio_chunk + sample_rate = 44100 - data, sample_rate, decimation = anti_alias(data, sample_rate, 4800) + s = time.perf_counter() + data, sample_rate, decimation = anti_alias(data, sample_rate, 4800, 8) + data = data / (np.max(data) + 0.0001) pure_signals = {tone:note(freq, note_length, rate=sample_rate) for tone,freq in TONES.items()} - correlations = {tone:np.abs(signal.correlate(data, pure, mode='same')) for tone,pure in pure_signals.items()} - massaged = {tone:decimate(np.convolve(correlation, cumsum_convolution, mode='valid'), 4) for tone,correlation in correlations.items()} + aa = time.perf_counter() - print('processing done') + correlations = {tone:smoothing_filter(np.abs(signal.correlate(data, pure, mode='same')), 64) for tone,pure in pure_signals.items()} + corr = time.perf_counter() - for tone,massage in massaged.items(): - gui.push_tones(tone, massage ) + guard_samples = int(guard_duration * sample_rate) + for tone,massage in correlations.items(): + #gui.push_tones(tone, massage) + gui.push_tone(tone, np.mean(massage)) + gui.push_tones(tone, massage[guard_samples:-guard_samples:100]) + draw = time.perf_counter() + + #print(aa-s, corr-aa, draw-corr) + if draw - s > 0.1: + print("FAILED") if __name__ == '__main__': sig.signal(sig.SIGINT, signal_handler)