Instruments Simplified with Python Decorators

Python can be molded to look like an audio synthesis language with the help of decorators. In my last post, I showed an instrument graph built within a Python iterator class. However, Iterator classes are too clunky looking, and require more work than should be necessary for creating a simple graph. Read and download this blog’s example script here.

So how does it look in comparison?

def MyInstr(dur=1.0, amp=1.0, freq=440, tune=12):
    a1 = Sine(amp * 0.5, freq)
    a2 = Sine(amp * 0.5, freq * 2 ** (tune / 12.0))
    return Multiply(Sum(a1, a2), RiseFall(dur, 0.5))

The @Instr decorator signals to both the human and the computer that the proceeding definition is an instrument class. Much easier to deal with than having to fiddle around with class methods __init__(), __iter__() and next(). There’s less code to write, and far less chance to break the internals of an iterator class. And it more closely resembles an audio synthesis language. Here’s a near equivalent version written in Csound:

instr MyInstr
    idur = p3
    iamp = p4
    ifreq = p5
    itune = p6
    a1 oscils iamp * 0.5, ifreq, 0
    a2 oscils iamp * 0.5, ifreq * 2 ^ (itune / 12), 0
    kenv linseg 0, idur * 0.5, 1, idur * 0.5, 0
    out kenv * (a1 + a2)

What’s going on exactly? Well, to be honest, decorators have been eluding me for the past two weeks. It wasn’t until last night as I was halfway through watching Eddie Izzard’s Dress to Kill that it suddenly clicked. So any explanation I give will be insufficient. I’ll just say that @Instr refers to a generic graph iterator class designed by me that creates a new iterator class that assimilates def MyInstr. If you want to know more, you can read Bruce Eckel’s Introduction to Python Decorators.

Question: Cake or death?