======2. Variante Oszilloskop====== Es gibt verschiedene graphische Benutzeroberflächen, die abhängig von Ereignissen andere Programme aufrufen können. Hier habe ich mich für **gtk** entschieden, es gibt noch Qt, tk und wx (komische Namen). Man kann matplotlib mitteilen, welche dieser Oberflächen er verwenden soll. Nur darin unterscheidet sich der Vorspann des Programms von der 1. Variante: #!/usr/bin/python # coding=utf8 from __future__ import division ### Audio-Modul import pyaudio ############## # Graphik und Berechnungen import matplotlib ### Wir müssen uns hier für ein Graphik-System ('backend') entscheiden, ### wenn wir dieses die Ereigniskontroll übernehmen lassen wollen: 'gtk' matplotlib.use('GTKAgg') import gobject import matplotlib.pyplot as plt import numpy as np ### Zeit import time ########################### ### GLOBALE VARIABLEN CHANNELS=1 RATE=44100 DAUER=1 ANZAHL=DAUER*RATE # ANZAHL der Frames, CHUNK=2**11 # globale Variablen, schlechter Programmierstil, hier aber ganz # praktisch: Nach Aufnahme oder Lesen werden diese Variablen # entsprechend gesetzt. Der für die graphische Anzeige zuständige Teil unterscheidet sich nur wenig, aber in bedeutsamer Weise von der 1. Variante. Die Klasse `Anzeige` hat nun eine weitere Methode `zeichnen`. Die zeichnen-Methode des globalen Anzeige-Objekts wird mit dem so genannten `idle`-Event verknüpft, d.h. immer dann aufgerufen, wenn sonst nichts zu tun ist. class Anzeige(object): '''Anzeige-Objekt, zeigt 'chunk' frames an, x-Achse beschriftet mit den korrekten Zeiten. Das zweite Argument ist die Sample-Rate''' def __init__(self,chunk,rate): self.fig,self.ax=plt.subplots(1,1) self.ax = plt.axes(ylim=(-1,1),xlim=(0,chunk/RATE)) self.xwerte=np.arange(chunk)/RATE self.kurve, = self.ax.plot(self.xwerte,np.zeros(chunk), lw=2) self.fig.canvas.draw() plt.pause(0.001) self.chunk=chunk def update(self,data): '''Plottet 'data' ''' self.kurve.set_data(self.xwerte,data/2**16) def zeichnen(self,*args): self.fig.canvas.draw() return True ################## ### Anzeige setup, hier wird das 'idle'-Event (=nichts weiter ### zu tun) mit dem Zeichnen des momentanen Plots verbunden anzeige=Anzeige(CHUNK,RATE) gobject.idle_add(anzeige.zeichnen) Der Audio-Teil unterscheidet sich nicht von der 1. Variante, siehe dort. Das Hauptprogramm tut nun nichts anderes mehr, als die beiden unabhängigen Prozesse (Mikrophon auslesen, Bild anzeigen) nebeneinander laufen zu lassen. Die Prozesse sind nicht synchron. Es kann sein, dass die Bilder sehr viel häufiger neu gezeichnet werden als neue Audio-Daten kommen. Das macht aber nichts. Da beide Prozesse schon gestartet wurden, muss nur dafür gesorgt werden, dass das Programm nicht beendet wird und die graphische Oberfläche aktiv bleibt: plt.show() Dieser Methodenaufruf wird erst beendet, wenn man das Graphikfenster schließt. Anschließend kann man wieder, wie in der 1. Variante, die beiden Prozesse sauber beenden.