====Ton zu Bild==== ===Projektmitglieder=== * Claire Melchior * Mascha Pachael * Laila Kulsvehagen * Lenny Leass ===Ziel=== Wir wollen Tonsignale in Bilder umwandeln. Hierbei ist es uns am wichtigsten, dass die entstehenden Bilder ästhetisch interessant sind. ===Ansätze=== Zuerst müssen die Tonsignale in Daten umgewandelt werden, die dann in unserem Programm verarbeitet werden können. Diese Daten können dann auf verschiedene Arten verwendet werden, um Bilder zu generieren. ===Theoretischer Hintergrund=== Zuerst mussten wir uns damit auseinandersetzen, wie Schall mathematisch beschrieben werden kann. Wir haben uns die Begriffe Periode, Frequenz, Amplitude etc. noch einmal vergegenwärtigt. ==Fourier-Analyse== Grundlage für die Verarbeitung und Analyse von Tonsignalen ist die Fourier-Analyse. Sie bietet eine Möglichkeit, Schallsignale in ihre Teilfrequenzen zu zerlegen. Somit kann man z.B. Grundtöne bestimmen, Obertonspektren vergleichen, und vieles mehr. ===Unser Programm=== Um Töne aufnehmen deren Daten verarbeiten zu können, verwenden wir das Modul pyaudio. Für die Verarbeitung der Daten verwenden wir das Modul numpy. Für die Generierung und Darstellung der Bilder verwenden wir das Modul matplotlib. Ein Funktion zum Aufnehmen von Tönen kann z.B. so aussehen: from __future__ import division import pyaudio import numpy as np def recordsnd(filename, time): ''' Nimmt eine time Sekunden lange Schallsequenz auf (mit der Samplerate 44100 Hz) auf, speichert sie in der Datei filename und gibt die Aufnahme als numpy-array mit Werten zwischen -1 und 1 zurück ''' CHANNELS = 1 RATE = 44100 DAUER=time ANZAHL=int(RATE*DAUER) p = pyaudio.PyAudio() raw_input("Aufnehmen "+str(time)+ " Sekunden): Eingabetaste drücken...") stream = p.open(format =pyaudio.paInt16 , channels = CHANNELS, rate = RATE, input = True, frames_per_buffer = 1024)#ANZAHL) yy=stream.read(ANZAHL) y=np.fromstring(yy,dtype=np.short) if CHANNELS==2: y=y.reshape((y.shape[0]//2,2)) print("Aufgenomen: " + str(ANZAHL) + " Frames") stream.close() p.terminate() yy=np.array(y,dtype='d')/32768.0 if filename!=None: wavwrite(filename, yy) return yy Den numpy-array, den wir hierdurch erhalten, können wir uns mit matplotlib anzeigen lassen, z.B. so: import matplotlib.pyplot as plt y = recordsnd(None,1) y = y[:2000] y = y.reshape(len(y), 1) + y.reshape(1, len(y)) ax = plt.axes() ax.imshow(y) plt.show() Wenn wir nun auch die Fourier-Analyse ins Spiel bringen, können wir noch interessantere Bilder erzeugen: y = recordsnd(None,1) y = y[:512] y = np.abs(np.fft.fft(y)) y = np.concatenate((y[-50:],y[:50]),axis=0) y = y.reshape(len(y),1) + y.reshape(1,len(y)) ax = plt.axes() ax.imshow(y) plt.show() Nun brauchen wir eine Methode, um Tondaten kontinuierlich verarbeiten und anzeigen zu lassen. Zunächst erstellen wir ein Anzeigeobjekt, zusammen mit einer Methode, wie sich dieses aktualisiert: class Anzeige(object): def __init__(self,chunk,rate): self.chunk=chunk self.pixels = np.random.rand(chunk,chunk) plt.pause(0.001) self.rate=rate self.fig = plt.figure() self.ax = self.fig.add_axes((0,0.25,0.5,0.5)) plt.axis("off") self.ax2 = self.fig.add_axes((0.5,0.25,0.5,0.5)) plt.axis("off") #self.image = self.ax.imshow(self.pixels) self.fig.canvas.draw() self.noch_kein_erstes_bild_da=True def update(self,data): l=len(data) self.fourier = np.abs(np.fft.fft(data, axis=0)) self.fourier = np.concatenate((self.fourier[-50:,0],self.fourier[:50,0]),axis=0) l2 = len(self.fourier) self.fourier2 = self.fourier.reshape((l2,1))+self.fourier.reshape((1,l2)) self.pixels=data.reshape((l,1))+data.reshape((1,l)) if self.noch_kein_erstes_bild_da: self.image = self.ax.imshow(self.pixels) self.image.set_cmap("spectral") self.fourier_image = self.ax2.imshow(self.fourier2) self.fourier_image.set_cmap("spectral") self.noch_kein_erstes_bild_da=False self.fig.canvas.draw() plt.pause(0.05) self.image.set_data(self.pixels) self.fourier_image.set_data(self.fourier2) anzeige=Anzeige(CHUNK,RATE) Dann erstellen wir eine callback-funktion, welche unser Anzeige-objekt sich mit neuen Daten aktualisieren lässt: def micro_callback(in_data, frame_count, time_info, status): if CHANNELS==2: y=y.reshape((y.shape[0]//2,2)) else: y=y.reshape((y.shape[0],1)) anzeige.update(y) return (in_data, pyaudio.paContinue) Nun wird ein Audiostream gestartet, welcher, immer wenn CHUNK frames vom Mikrophon gelesen wurden, unsere callback-funktion aufruft: p = pyaudio.PyAudio() stream = p.open(format=pyaudio.paInt16 , channels=CHANNELS, rate=RATE, input=True, output=False, stream_callback=micro_callback, frames_per_buffer=CHUNK) stream.start_stream() time.sleep(0.5) Schließlich startet unsere Hauptschleife, welche das Anzeige-objekt so lange darstellt, wie der Stream aktiv ist: while stream.is_active(): anzeige.fig.canvas.draw() anzeige.fig.canvas.flush_events() ===Das Endprodukt=== {{ws1415:projekte_im_wintersemester_2014_15:bild2.png}} [[Protokolle]]