~~NOTOC~~
====== Code ======
==== BILDINFO ====
//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.
==== FREQUENZEN ====
#-*- 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])
==== Bild ====
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
==== Sound ====
#-*- 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
==== Schallwerkzeuge ====
//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
==== Dreiklaenge ====
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()
==== Soundv2 ====
//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
==== Bildv2 ====
//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
==== Farbräume ====
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]
==== Synthesizer ====
def tune(f, d, r=44100, mode='sinus'):
vol = 1
waves = []
waves.append(sinewave(f, r, d))
if mode == 'organ':
while vol >= 0.1:
vol *= 0.7
waves.append(sinewave(f*freq.getRatio('quinte'), r, d, vol=vol/2))
f *= freq.getRatio('oktave')
waves.append(sinewave(f, r, d, vol = vol))
if '#' in mode: #bei #a-z1,b-z2,c-z3,d-z4,g-z5,t-z6,e-z7 wird der a-te, b-te, ..., e-te oberton hinzugefügt mit z1, z2,..., z7 % lautstärke
toene = mode[1:].split(',')
for ton in toene:
waves.append(sinewave(f*2**int(ton[:ton.index('-')]), r, d, vol=int(ton[ton.index('-'):])/100))
return wave
==== MARKOV ====
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 ====
Zufallszahlen für Markov-ketten
# -*- coding: cp1252 -*-
#Zufallszahl für Markov-Kette
#-*- coding: utf-8 -*-
from __future__ import division
from PIL import Image
import random
from bild import Bild
import numpy as np
def spaltenBreite(bild, spalten = 240):
'''Spaltenbreite der Pixel die zusammengefasst wird!'''
n = bild.bBreite()
b = int((n-(n%spalten))/spalten)
if b == 0:
return 1
return b
def spalten(bild, spaltenum = 240):
spalten = []
pic = bild.rasterList(bild.farbraume(4))
sBreite = spaltenBreite(bild, spaltenum)
ende = bild.bBreite()-bild.bBreite()%sBreite
if ende == 0:
ende = bild.bBreite()
for i in range(0, ende, sBreite):
spalte = []
for x in range(sBreite):
if (i+x < len(pic)):
spalte += pic[i+x]
spalten.append(spalte)
return spalten
def zufallsZahl(bild, spaltenum = 240):
n = bild.bBreite()
b = spaltenBreite(bild, spaltenum)
l = int(bild.bHohe())
r = b * l
spalter = []
spaltenliste = spalten(bild, spaltenum)
for spalte in spaltenliste:
spalter.append(sum(spalte)/len(spalte))
zZahl = []
for spalte in range(len(spalter)):
varianz = 0
for y in range(r):
x1 = spalter[spalte]
x2 = spaltenliste[spalte][y]
varianz += 1/r*(x1 - x2)**2
zZahl.append(varianz)
maximum = max(zZahl)
return [num/maximum for num in zZahl]