July 23, 2006

Live Coding with Python

For those of you who may be unfamiliar with the concept, live coding is the act of writing software while it is executing, often as part of a performance. Some electronic music bands live-program their music in languages like ChucK and SuperCollider. However, it can also be a useful method for learning and experimenting with code, because the results of your changes are immediately apparent.

The Python language seems ideal for such an endeavor due to its flexibility, readability, and of course it’s fun, playful nature. I googled around for an existing implementation or tutorial and finding none, decided to throw my two cents in.

The first thing that’s needed in a live coding experiment is a sequencer; a program responsible for reading in your changes and executing the program at an interval as you write it.

A basic sequencer in python might look something like this:

terminate = 0
iteration = 0
delay = 1

from time import sleep
try:
import dynamic_app
except ImportError:
dynamic_app = None

while terminate == 0:
iteration = iteration + 1
try:
reload (dynamic_app)
except:
print "New code is broken, using last working version"
terminate = dynamic_app.play(iteration)
sleep(2)

This will run a program called dynamic_app.py once every second until the global terminate is set to nonzero. If you introduce an error, it will run the last working code until you figure out what went wrong and fix it.

dynamic_app.py could look something like this:

def play(iteration):
if iteration > 5:
return 1
else:
print iteration, "snakes on a plane"
return 0

This would produce the output:

1 snakes on a plane
2 snakes on a plane
3 snakes on a plane
4 snakes on a plane
5 snakes on a plane

Now just raise the maximum iteration to 60 and spend a minute playing around with dynamic_app.py while the sequencer runs in the background. Save your changes as often as you like and see them reflected a second later in the output console.

If you’re interested in applying this concept to music (trust me, its hours of fun), try using this slightly more sophisticated sequencer:

## seq.py - basic sequencer for executing live code in musical time
## Written 2006 Logan Koester

from time import sleep
try:
import demosong # imports demosong.py. this filename should be dynamic too.
except ImportError:
demosong = None

def bpm_timer(bpm):
bps = 60.0 / bpm
return bps

terminate = 0
beats = 0
verbose = 0
bpm = 0
steps = 0
bar = 0 # a counter

while terminate == 0:
#once per bar execution

if verbose != demosong.verbose:
if verbose == 1:
print "Verbose output ON"
verbose = demosong.verbose

if beats != demosong.beats:
if verbose == 1:
print "Beats per bar changed from ", beats, " to ", demosong.beats
beats = demosong.beats # beats per bar

for beat in range(beats):
# once per beat execution

if bpm != demosong.bpm:
if verbose == 1:
print "BPM changed from ", bpm, " to ", demosong.bpm
bpm = demosong.bpm

if steps != demosong.steps:
if verbose == 1:
print "Steps per beat changed from ", steps, " to ", demosong.steps
steps = demosong.steps # steps per beat

for step in range(steps):
try:
reload (demosong)
except:
print "Oh snap!"
# once per step execution
demosong.play(step, beat, bar)
sleep(bpm_timer(bpm))

bar = bar + 1

Click here for an example of how you can use this sequencer to build a drum pattern (flash required).

For a basic drum machine this should suffice, but you’ll really need to add threading and a decent realtime buffer for more complicated jams. You’ll probably also want to create a library of useful functions (synths, samplers, effects, preset rhythms and melodies) to reduce the code overhead in the song file. Let me know what you come up with!

Sorry the code indentation got busted when I moved to Wordpress. I’ll see about getting that fixed when I have time.

Comment by Logan — December 21, 2006 @ 6:58 am

As your example clearly shows, this does actually NOT suffice for even the most simple drum machine. The timing is off in a really horrible way. However, for the purpose of a livecoding session where you don’t care whether your changes take 200ms more or less to become audible (updating between bars is actually nifty, I think), you can simply render into a buffer and then make the buffer large enough to avoid gaps. In python, eliminating gaps can easily be accomplished with pygame.mixer.Channel.queue(). Now you’re working only with buffers and your timing is sample accurate, the best case.

However, what irks me about pygame.mixer.Sound is that it only accepts sounds from files/file objects. I’d like my buffer to wrap a Numeric array that I can manipulate as I please. So now I’m wondering … is there any Python lib I could use instead of pygame? Anyone have a hint? Unfortunately PyOpenAl isn’t developed any longer … :-(

Comment by nex — May 19, 2007 @ 12:41 pm

medical transcription software rhode island
http://www.zloyonline.info - 1995 ford truck vin meaning

Comment by innopesparp — October 30, 2007 @ 6:03 am

Leave a reply

Inspiration

6pli Tumblr Aptana IDE Markus Homm Mint Humanized Rawkus Records // All Things Hip Hop // www.rawkus.com The New York Times WeShouldDoItAll Justinsomnia Deluxe Digital Media Democracy Internet Tv Take More Photos fluxiom - capture, manage, access and deliver content across your enterprise Olivier Danchin Jason Santa Maria Tubetorial Ajaxian Raincity Studios 88 Miles - Simple time tracking Welcome to Zopa (UK) - The first lending and borrowing exchange Inspirational design for a web2.0 homepage