Dies ist eine alte Version des Dokuments!
ALT
#-*- coding: utf-8 -*- from PIL import Image import random def loadImage(filename): '''INPUT:Dateiname Lädt das Bild und gibt es zurück.''' image = Image.open(filename) return image.convert('RGBA') def picInfo(image): '''INPUT:Bild Gibt eine Liste der Pixel als Tupel zurück.''' pixels = list(image.getdata()) return pixels def average(pixels): '''INPUT: Liste mit allen Pixeln des Bildes. Gibt den Durchschnitt über alle Pixel zurück.''' s = 0 #speichert die Summe for tupel in pixels: for num in tupel: s += num return s/(len(pixels)*len(pixels[0])) def getMax(pixel): '''INPUT:Ein Pixel der Form (r, g, b, alpha) Gibt den Farbanteil zurück, der überwiegt.''' pmax = max(pixel[:-1]) #Das Maximum der Farbanteile maxl = [] #Alle Farbanteile, die diesem Maximalwert entsprechen. for p in enumerate(pixel[:-1]): if p[1] == pmax: maxl.append(p) return random.choice(maxl) #Gib einen zufälligen Wert aller Maximalwerte zurück.
#-*- coding: utf-8 -*- from __future__ import division frequenzen={} frequenzen["c"]=[261.626] frequenzen["d"]=[293.665] frequenzen["e"]=[329.628] frequenzen["f"]=[349.228] frequenzen["g"]=[391.995] frequenzen["a"]=[440.000] frequenzen["h"]=[493.883] intervalle={} intervalle['sekunde']=[9/8] intervalle['gterz']=[5/4] #große terz intervalle['quarte']=[4/3] intervalle['quinte']=[3/2] intervalle['gsexte']=[5/3] #große sexte intervalle['gseptime']=[15/8] #große septime intervalle['oktave']=[2] def getFreq(note): return float(frequenzen[note][0]) def getRatio(intervall): return float(intervalle[intervall][0])
from __future__ import division from PIL import Image import random class Bild(): def __init__(self, filename): self.image = Image.open(filename).convert('RGBA') self.pixels = self.picInfo() def picInfo(self): '''Gibt eine Liste der Pixel als Tupel zurück.''' pixels = list(self.image.getdata()) return pixels def average(self): '''Gibt den Durchschnitt über alle Pixel zurück.''' s = 0 #speichert die Summe for tupel in self.pixels: for num in tupel: s += num return s/(len(self.pixels)*len(self.pixels[0])) def getMax(self): '''Gibt eine Liste mit einem Eintrag für jeden Pixelzurück, wo der überwiegenden Farbanteil und die dazugehörige Komponente gespeichert wird. Wenn es mehrere gleiche Werte gibt, wird einer zufällig gezogen''' maxList = [] for pixel in self.pixels: pmax = max(pixel[:-1]) #Das Maximum der Farbanteile maxl = [] #Alle Farbanteile, die diesem Maximalwert entsprechen. for p in enumerate(pixel[:-1]): if p[1] == pmax: maxl.append(p) maxList.append(random.choice(maxl)) #Gib einen zufälligen Wert aller Maximalwerte zurück. return maxList
#-*- coding: utf-8 -*- from __future__ import division import schallwerkzeuge as swz import numpy as np class Sound(): def __init__(self, sounds): if len(sounds) > 0: sound = np.zeros(len(sounds[0])) for s in sounds: sound += s/len(sounds) self.sound = sound else: self.sound = np.array([]) def play(self): '''Spielt die Sounddatei ab.''' swz.playsnd(self.sound, swz.RATE) def save(self, filename): '''Speichert den Sound in einer .wav-datei''' swz.wavwrite(filename, self.sound) def appendSound(self, sounds): '''Fügt am Ende des Sounds weitere sounds hinzu.''' sound = np.zeros(sounds[0].size) for s in sounds: sound += s/len(sounds) self.sound = np.append(np.append(self.sound,np.zeros(300)), sound) def addSound(self, sounds): '''Mischt den bestehenden Sound mit anderen.''' sound = np.zeros(len(sounds[0])) for s in sounds: sound += s(len(sounds) + 1) sound += self.sound/(len(sounds) + 1) self.sound = sound def length(self): '''Gibt die Länge des Sounds in Sekunden zurück''' return self.sound.size/swz.RATE
Von Stefan bereitgestellt
#!/usr/bin/python # coding=utf8 ## Verhalten von / wie in Python 3 a/b = float from __future__ import division from math import pi ### Audio-Module import pyaudio from scipy.io import wavfile ### Fourier, Numerik import numpy.fft as FFT import numpy as np ############## # Graphik import matplotlib.pyplot as plt ### CHANNELS=1 RATE=44100 DAUER=1 ANZAHL=DAUER*RATE # ANZAHL der Frames, GRENZE=0.02*RATE # globale Variablen, schlechter Programmierstil, hier aber ganz # praktisch: Nach Aufnahme oder Lesen werden diese Variablen # entsprechend gesetzt. def recordsnd(filename, time): ''' Nimmt eine time Sekunden lange Schallsequenz auf (mit der Samplerate 48000 Hz) auf und speichert, speichert sie in der Datei filename und gibt die Aufnahme als numpy-array mit Werten zwischen -1 und 1 zurück ''' global ANZAHL global RATE global DAUER global CHANNELS 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 def wavwrite(filename, y): '''Schreibt ein wav-File aus einem numpy-array''' wavfile.write(filename, RATE, np.array(y*2**15, dtype=int)) def wavread(filename): '''Liest ein wav-File in ein numpy-Array''' global ANZAHL global RATE global DAUER global CHANNELS RATE,y=wavfile.read(filename) ANZAHL=y.shape[0] if len(y.shape)==2: CHANNELS=y.shape[1] else: CHANNELS=1 DAUER=ANZAHL/RATE return np.array(y,dtype=np.float)/2**15 def playsnd(y, r): ''' spielt das numpy-array (bzw. Vektor) y als Klang mit der Samplerate r [Hz] ab. ''' #testkommentar def callback(in_data, frame_count, time_info, status): data = (32767*klanggen.generate(frame_count/RATE)).astype(np.int16) return (data.copy(), pyaudio.paContinue) p = pyaudio.PyAudio() CHUNK=2**12 stream = p.open(format =pyaudio.paInt16 , channels = CHANNELS, rate = r, output = True, frames_per_buffer=CHUNK) #callback=callback)#ANZAHL) yy=np.array(y.flatten()*2**15,dtype=np.short) for i in range(0,len(yy),CHUNK): stream.write(yy[i:i+CHUNK].tostring(order='F')) stream.close() p.terminate() def inspectsnd(y): '''Zeigt einen Plot von y''' n=y.shape[0] fig=plt.Figure(figsize=(6,4),dpi=100) ax=fig.add_subplot(111) x=np.arange(0,n,1)/np.float32(RATE) plt.plot(x,y) plt.show() def inspectspec(y): '''zeigt einen Plot des DFT-Spektrums von y''' global RATE # Vorbereitungen, um ein Fenster zum Plotten zu kriegen plt.figure(1) n=len(y) window=np.blackman(n) sumw=sum(window*window) A=FFT.fft(y*window) B2=(A*np.conjugate(A)).real sumw*=2.0 sumw/=1/np.float(RATE) # sample rate B2=B2/sumw x=np.arange(0,n/2,1)/np.float(n)*RATE eps=1e-8 plt.plot(x, np.log10(B2[0:n/2]+eps)) plt.show() def sinewave(f,r,d): '''erzeugt die Daten einer Sinusschwingung mit Frequenz f, Dauer d und Samplerate r''' global RATE global DAUER global ANZAHL RATE=r DAUER=d ANZAHL=DAUER*RATE y=np.zeros(r*d) lastzero = 0 for i in range(0,int(r*d)): y[i]=np.sin(2*pi*f*i/float(r))*window(i,r*d) return y def window(i, l, grenze=0.01): '''Lässt die Sinuswelle an den Rändern gegen 0 laufen, damit das "Klacken" beim Zusammenfügen von Bildern nicht entsteht.''' global RATE global GRENZE GRENZE = grenze*RATE m = min(i, l-i) if (m < GRENZE): return (m/GRENZE)**(2/3) else: return 1
Testklasse, die aus beliebigen Bildern eine Folge von Dreiklängen erzeugt.
#-*- coding: utf-8 -*- from __future__ import division import frequenzen as freq from bild import Bild import schallwerkzeuge as swz from sound import Sound pic = Bild('allfarben.png') win = Bild('ico-win.png') def dreiKlang (i,grundton,l): #l=1 Tonlänge '''erzeugt einen Dreiklang. Dabei repräsentiert 0 die Tonika, 1 die Subdominante und 2 die Dominante.''' toene = 3 #Anzahl der Töne des Dreiklangs gfreq = freq.getFreq(grundton) #Frequenz des Grundtons grundton = swz.sinewave(gfreq,swz.RATE, l) if i == 0: #Tonika terz = swz.sinewave(gfreq*freq.getRatio('gterz'), swz.RATE, l) quinte = swz.sinewave(gfreq*freq.getRatio('quinte'), swz.RATE, l) return Sound([grundton, terz, quinte]) elif i == 1: #Subdominante quarte = swz.sinewave(gfreq*freq.getRatio('quarte'), swz.RATE, l) sexte = swz.sinewave(gfreq*freq.getRatio('gsexte'), swz.RATE, l) return Sound([grundton, quarte, sexte]) elif i == 2: #Dominante sekunde = swz.sinewave(gfreq*freq.getRatio('sekunde'), swz.RATE, l) quinte = swz.sinewave(gfreq*freq.getRatio('quinte'), swz.RATE, l) septime = swz.sinewave(gfreq*freq.getRatio('gseptime'), swz.RATE, l) return Sound([sekunde, quinte, septime]) def playSound(bild, l=1): s = Sound([]) for maxi in bild.getMax(): #dreiKlang(maxi[0], 'c').play() s.appendSound([dreiKlang(maxi[0], 'c', l).sound], swz.GRENZE) #print s.length() #print s.sound s.play()
Nur überarbeitete Strukturen
def appendSoundP(self, sounds): '''Fügt am Ende des Sounds weitere sounds hinzu.''' sound = np.zeros(sounds[0].size) for s in sounds: sound += s/len(sounds) self.sound = np.append(self.sound, sound) def appendSound(self, sounds, grenze): if (self.sound.size-grenze < 0 or sounds[0].size-grenze < 0): print 'zu kurz.' self.appendSoundP(sounds) return print 'lang genug.' sound2 = self.addSounds(sounds) soundganz = np.append(np.append(self.sound[:self.sound.size-grenze], np.zeros(grenze)),sound2[grenze:]) soundsum = np.zeros(soundganz.size) for i in range(int(grenze)): soundsum[self.sound.size-grenze+i] = (self.sound[self.sound.size-grenze+i] + sound2[i]) soundganz += soundsum self.sound = soundganz def technoAppend(self, sounds, grenze): '''Klingt einfach nur lustig''' if (self.sound.size-grenze < 0 or sounds[0].size-grenze < 0): print 'zu kurz.' self.appendSoundP(sounds) return print 'lang genug.' sound2 = self.addSounds(sounds) soundganz = np.append(self.sound, sound2[grenze:]) soundmult = np.zeros(soundganz.size) soundmult.fill(1) for i in range(int(grenze)): soundganz[self.sound.size-grenze+i] += sound2[i] soundmult[self.sound.size-grenze+i] = soundganz[self.sound.size+i]-1 soundganz -= soundmult self.sound = soundganz
Nur überarbeitete Strukturen
def pixList(self): '''Teilt Pixels in Bildspalten auf''' (width,height)=self.image.size plraster=[] for i in range (width): hl=self.pixels[i::width] plraster.append(hl) return plraster
def farbraume (self, z=2): #z Anzahl der Teilbereiche pro Farbkomponente '''Wenn man sich den RGB-Farbraum als Würfel vorstellt, so kann man diesen in kleinere Würfel zerlegen. Diese Methode zerlegt den Würfel in z*z*z kleine Würfel und ordnet jedem Pixel den Würfel zu, in dem er liegt.''' farbraume = [] for i in range (z): for j in range (z): for k in range (z): farbraume.append((i,j,k)) konvpixel = [] for pixel in self.pixels: r = pixel[0] g = pixel[1] b = pixel[2] for i in range(z): if (256/z)*i <= r and r < (256*(i+1))/z: rl = i #rot if (256/z)*i <= g and g < (256*(i+1))/z: gl = i #grün if (256/z)*i <= b and b < (256*(i+1))/z: bl = i #blau konvpixel.append((rl,gl,bl)) return [farbraume.index(tupel) for tupel in konvpixel]
from __future__ import division from bild import Bild import matplotlib.pyplot as plt import numpy as np from sound import * import frequenzen as freq import zufallszahlen as zahlen import rhythm def normMatrix(matrix): '''normiert die Spalten der Matrix, so dass die Summe aller elemente einer Spalte genau 1 ergibt, das Verhaeltnis zwischen den Spalten aber noch erhalten bleibt.''' matrixcopy = [] for col in matrix: colcopy = [] nenner = sum(col) if nenner != 0: for element in col: colcopy.append(element/nenner) matrixcopy.append(colcopy) else: colcopy = [1/len(col) for x in range(len(col))] print colcopy return matrixcopy def step(matrix, vec, step = 1): '''berechnet den Vector der Notenwahrscheinlichkeit nach step Noten''' for i in range(step): retvec = [] for y in range(len(matrix[0])): retvec.append(sum([matrix[x][y]*vec[x] for x in range(len(matrix))])) vec = retvec[:] return vec def nextTune(matrix, vec, val): '''val muss zwischen 0 und 1 liegen. Dann berechnet diese Methode den naechsten Ton, der gespielt wird.''' element = 0 probvec = step(matrix, vec) print sum(probvec), " >= ", val while sum(probvec[:element+1]) < val: element += 1 if (element == len(probvec)-1): return element #print 'Tonhoehe berechnet.' return element def generateMelodie(pic, nums, tunes = 24): '''nums muss eine Liste mit zahlen zwischen 0 und 1 sein''' matrix = pic.transformImage(tunes, tunes) matrix = normMatrix(matrix) melodie = [] vec = genVector(9, tunes) for num in nums: melodie.append(nextTune(matrix, vec, num)) vec = genVector(melodie[-1]) print 'Ton wurde der Melodie hinzugefuegt.' #print 'Melodie erzeugt.' return melodie def generateTune(pic, notes = 240, tunes = 24, length = 1, mode = 'sinus'): '''generiert ein Sound object, mit einer durch markov ketten erstellte melodie''' nums = zahlen.zufallsZahl(pic, notes) print nums print 'Zufallszahlen generiert.' melodie = generateMelodie(pic, nums, tunes) print 'Melodie erzeugt.' rhythmus = rhythm.generateRhythm(pic, len(nums), length, 4) print 'Rhythmus erzeugt.' tonlage = 1 s = Sound(np.array([])) for i in range(len(melodie)): ton = melodie[i] laenge = rhythmus[i] tune = createTune(freq.getFreq(freq.buchstaben[ton%8][0])*2**(tonlage-ton//8), laenge, mode = mode) #print max(tune) s.appendSound([tune], swz.GRENZE) print 'Fertig.' return s def genVector(eins, length = 24): '''generiert einen Vector der Laenge length mit einer 1 an der stelle eins''' vec = [0 for i in range(length)] vec[eins] = 1 return vec def genRandList(length, maximum): return [(np.random.random_integers(maximum+1)-1)/maximum for x in range(length)]
Zufallszahlen für Markov-ketten