######################################################################### ## ## ## Open source sound creation tools ## ## Written 2002 - Ed Colmar ## ## ## ## www.edcolmar.com ## ## ## ## This file may be freely distributed and modified so long as this ## ## header information remains intact. ## ## ## ## I would also appreciate credits on any published work that ## ## Contains elements generated or processed by this software. ## ## ## ######################################################################### ## This script will take an input waveform and fill it with a ## fractal terrain generating algorythm. ## It can be used with empty files as well, if you only want the sound of ## the terrain algorythm. ## This was inspired by the graphical 3d terrain generation algorythms ## Essentially it will check to see how long the sample is, ## then calculates the number of passes it will take to compute the result. ## It initially randomly chooses the values for the starting sample and the ## last sample in the longest cycle. ## Then it goes through one level at a time dividing the previous level in half ## It averages out the endpoints to find the middle value, then adds a random value to it. ## Version 003 adds the ability to add texture to the existing wave. ## you do need to normalize it down a bit depending on the randoffset ## values you set. Generally when working with an existing sound ## Startoffset should be less than 1000 and randoffset should be less than 100 ## INIT snack and TK. import random import tkSnack from Tkinter import * from string import split root = Tk() tkSnack.initializeSnack(root) soundbuffer = tkSnack.Sound() soundbuffer.read('source1.wav') ## This is the maximum amount to shift the random values randstartoffset = 10000 randoffset = 7500 ## this little method will generate a random value in the range of -1 to 1 def randomsampledata(): """ generate a random value """ plusvalue = random.random() if plusvalue >= .5: plusval = 1 else: plusval = -1 randomval = random.random() randomval = randomval * plusval return randomval ## first calculate the available sample length. (must be a binary multiple) samplelength = soundbuffer.length() levels =0 multiplier =1 looping =1 while looping: samplelength = int(samplelength/2) multiplier=multiplier *2 levels=levels+1 if samplelength <= 1: looping = 0 print "It will take %i levels to compute the result" % levels levelmax = levels nearest_endpoint = multiplier print "out of a source sample length: %i" % soundbuffer.length() print "we can use %i samples" % nearest_endpoint ## now we set the initial sample values (first and last) ## samples after the nearest endpoint will be unused startsamplevalue = int(randomsampledata() * randstartoffset) endsamplevalue = int(randomsampledata() * randstartoffset) existingstartval= soundbuffer.sample(1) existingendval=soundbuffer.sample(nearest_endpoint) startval = startsamplevalue + existingstartval endval = endsamplevalue + existingendval if startval > 32767: starval=32767 elif startval < -32768: startval=-32768 if endval > 32767: endval=32767 elif endval < -32768: endval=-32768 soundbuffer.sample(1, startval) soundbuffer.sample(nearest_endpoint, endval) ## Now we start looping over the levels multiplier = 1 for level in range(levels): ## each level represents twice as much sample data as the previous level centerdivisor = nearest_endpoint / (multiplier * 2) leftbuffer = 0 rightbuffer = centerdivisor + centerdivisor for increment in range(multiplier): incrementoffset = increment + 1 ## Each increment has its own centerpoint leftsamplelocation = leftbuffer rightsamplelocation = rightbuffer leftsampledata = soundbuffer.sample(leftsamplelocation) rightsampledata = soundbuffer.sample(rightsamplelocation) levelmultiplier = levelmax - level ## now calculate the midpoint value midsamplevalue = int(((rightsampledata + leftsampledata) / 2) + (randomsampledata() * randoffset )) midsamplelocation = (leftsamplelocation + rightsamplelocation) / 2 existingmidvalue = soundbuffer.sample(midsamplelocation) midval = existingmidvalue + midsamplevalue print "------------------ LEVEL %i -- INCREMENT %i ------" % (level+1, incrementoffset) if midval > 32767: midval = 32767 print "CLIPPING" elif midval < -32768: midval = -32768 print "CLIPPING" soundbuffer.sample(midsamplelocation, midval) ##print "centerdivisor: %i" % centerdivisor ##print "leftsamplelocation: %i" % leftsamplelocation ##print "rightsamplelocation: %i" % rightsamplelocation ##print "leftsampledata: %i" % leftsampledata ##print "rightsampledata: %i" % rightsampledata ##print "midsamplelocation: %i" % midsamplelocation ##print "midsamplevalue: %i" % midsamplevalue leftbuffer = leftbuffer + centerdivisor + centerdivisor rightbuffer = rightbuffer + centerdivisor + centerdivisor ## End increment loop multiplier = multiplier * 2 print " ][ saving file: plasma.wav" soundbuffer.write('plasma.wav') print " ][ freeing memory " soundbuffer.destroy()