class App(PCMSessionDelegate): BUFFER_LENGTH = 64 DB_OFFSET = -10.0 * math.log10(32768.0) def __init__(self): self.root = tk.Tk() self.root.protocol('WM_DELETE_WINDOW', self.shutdown) self.content = ttk.Frame(self.root, width=300, height=500) self.content.grid(column=0, row=0, sticky=(tk.N, tk.S, tk.E, tk.W)) self.root.columnconfigure(0, weight=1) self.root.rowconfigure(0, weight=1) pcm = PCMSystem() self.devices = OrderedDict() for dev in pcm.inputs(): self.devices[dev.name] = dev print(f'Device : {dev.name} {dev.maxIn} {dev.rate}') self.currentDevice = tk.StringVar() self.currentDevice.set(self[0].name) self.cards = ttk.Combobox(self.content, textvariable=self.currentDevice, values=self.names, justify=tk.LEFT) self.cards.bind('<<ComboboxSelected>>', self.changeCard) self.cards.grid(column=0, row=0, columnspan=4, sticky=(tk.N, tk.S, tk.E, tk.W)) self.graph = Graph(self.content) self.graph.grid(column=0, row=1, columnspan=4, sticky=(tk.N, tk.S, tk.E, tk.W)) self.graph.bind('<Button-1>', self.onClick) self.spec = tk.Toplevel(self.root, width=800, height=300) self.spectrum = SpectrumView(self.spec, bounds=Range(-120, -60), xflen=513) self.spectrum.configure(width=800, height=300) self.spectrum.pack() gradient = Gradient(Stop(Colour.Blue, offset=0), Stop(Colour.Green, offset=0.5), Stop(Colour.Yellow, offset=0.8), Stop(Colour.Red, offset=0.9)) self.spectro = tk.Toplevel(self.root, width=800, height=400) self.spectrogram = Spectrogram(self.spectro, bounds=Range(-120, -60), gradient=gradient, xflen=513) self.spectrogram.configure(width=800, height=400) self.spectrogram.pack() self.fft = SpectralBase(fftSize=1024, viewers=[self.spectrum, self.spectrogram]) self.startButton = ttk.Button(self.content, text='Start', command=self.start) self.stopButton = ttk.Button(self.content, text='Stop', command=self.stop) self.clearButton = ttk.Button(self.content, text='Clear', command=self.graph.clear) self.clearButton.grid(column=0, row=2, sticky=(tk.N, tk.S, tk.W)) self.startButton.grid(column=2, row=2, sticky=(tk.N, tk.S, tk.E)) self.stopButton.grid(column=3, row=2, sticky=(tk.N, tk.S, tk.E, tk.W)) for column in [0, 2, 3]: self.content.columnconfigure(column, weight=1) self.content.rowconfigure(1, weight=1) self.mean = [] self.timer = None self.samples = [] self.raw = [] self.session = PCMSession(self[0], delegate=self) def onClick(self, event): print(f'Click on {event.widget}') canvas = event.widget x = canvas.canvasx(event.x) y = canvas.canvasy(event.y) print(f'{self.graph.size} : ({event.x},{event.y}) -> ({x},{y})') @property def names(self): return list(self.devices.keys()) def __getitem__(self, index): if type(index) == str: return self.devices[index] else: return self.devices[self.names[index]] def changeCard(self, event=None): try: if self.session is None: return dev = self[self.currentDevice.get()] if dev == self.session.pcm: return else: print(f'Changing to {dev}') self.stop() self.session = PCMSession(dev) self.spec.setSampleRate(self.session.samplerate) self.start() except: print(f'{event}') def __call__(self, n, time, data=[]): if len(data) > 0: self.samples.extend(data) self.fft.add(data) #d=datetime.now() #print(f'{d.hour}:{d.minute}:{d.second}:{d.microsecond} : {len(data)}') def update(self): if len(self.samples) > 0: data = np.mean(self.samples, axis=1) self.samples = [] value = np.mean(data, axis=0) #print(f'Samples {min(data)} {max(data)}') self.graph.add(value) #raw=self.raw[:] #self.raw=[] #self.fft.add(raw) def start(self): self.stop() # make sure we're in a known state self.timer = MultiTimer(interval=0.05, function=self.update, runonstart=False) self.timer.start() self.fft.start() self.session.start() print(f'Started {self.session}') def stop(self): if self.session: self.session.stop() if self.timer: self.timer.stop() if self.fft: self.fft.stop() self.timer = None def shutdown(self): self.stop() self.root.destroy() def run(self): try: self.start() self.root.mainloop() except: pass finally: self.stop()