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]