Oxford Laptop Orchestra : Lecture 1 : Music and Programming

· by joe · Read in about 18 min · (3762 Words)

I’m very excited to be involved with the nascent Oxford Laptop Orchestra. This project, run by and for students at the University of Oxford, follows on from the work of the Princeton Laptop Orchestra. PLOrk, as its known, and now OxLork, is an effort to reproduce the form of performance embodied by a real orchestra or chamber group — that is, a number of individuals performing in concert, in a certain arrangement in space — with modern advances in electroacoustic music. At a PLOrk performance, musicians will sit, each with a laptop and a specially developed speaker, and make music together. So shall OxLork be!

There are two components to the PLOrk project. The first is the specially designed hemispherical speakers (six of which have been purchased by the University of Oxford) and the second is a custom-built programming language, designed to allow musicians and computer scientists to make music. The language, ChucK, is very flexible and enables the creation of a wide variety of electronic musical things. And I use the word things advisedly.

I am teaching ChucK to the participants of OxLork, nearly all straight music students. I hope we can work together and get to the point where all the participants are fluent with ChucK and able to write their own programs. I’m giving a series of lectures, one a week at the Faculty of Music. I’m making these available on my blog rather than stuck behind a wall inside Oxford internal systems because I think the approach I’m taking could be very much of use to musicians beyond the project.

This is going to be very opinionated. But also objective where it needs to be.

The first lecture was delivered on the 17th of October. I had a very bad cold at the time, and my fuzzy head made it quite difficult to talk in a straight line. Here is what I would have said, had I said the following.

Lecture 1

Music, Programming and Creativity

I am a software developer. I spend my working day programming computers one way or another. Programming is a very general and broad subject and I am lucky enough to be working on solving quite a wide of problems for interesting clients. I spend the rest of my time, as much as possible, playing music. I’ve always had an interest in combining the two. When I was a bit younger I used to make electronic music in my bedroom. At university I did my damnedest to skew as much of my computing science degree toward music as possible. The resulting project, probably the single project that has consumed most of my time over the years, is folktunefinder.com, a search engine for finding folk tunes if you know some of the melody.

I believe that programming and music both stem from a particular kind of creative urge. I feel that the kind of satisfaction I get in writing a program feels very similar to the kind of satisfaction I get in writing a piece of music (although I haven’t done this for a long time!). Similarly, using a program I have written, and listening to a piece of music I have written tend to produce the same kinds of feelings. A certain familiarity of the way a system or piece of music goes, a certain recognition of the thought processes that went into defining it.

Creative Intent

Writing a piece of music and writing a program are both the expression of creative intent. A programmer or composer has something inside themselves, and they want to express it. The means and form by which it is expressed are vastly different, but I think they emanate from the same instinct to _build_ something. A program is constructed with a degree of intent, method, accident, creativity and refinement in much the same way that a piece of music is constructed. You can admire both on their expressive and structural merits.

Programmers and musicians both have a creative spark. Even people writing software that runs every night on a mainframe in a bank have this. Except those that don’t. Then again, I’m sure you might be able to say similar things about certain composers.

You, the audience are musicians. I believe you have something in you that could be channeled into writing programs in ChucK. Not least because ChucK is designed for creative expression.

What is a Program?

A program is a list of instructions that a programmer writes down, gives to a computer, and the computer can execute. A computer takes these instructions and data and does what it’s meant to, or at least what was asked of it. The result is more data. All programs are composed of three types of actions:

  1. doing something to a piece of data
  2. taking decisions based on some data
  3. jumping around to another bit of the program

A piece of Western notated music has some very similar features.

  1. it instructs a musician to play a given note
  2. it instructs a musician to alter the way they are playing it (dynamics, tempo)
  3. it instructs the musician to jump around the score (repeat bars, DC al fine)

As musicians you will already have understood and internalised these concepts. You know how to follow a stave. The composer is writing down their instructions in a clear sequence, left to right, and you are executing them. This is equivalent to a program. A very simple program, but a real program nonetheless.

Two kinds of programs

There are two types of program. The first kind takes data, does something to it, and then folds its arms. It’s done its job and finished. A batch-running program that calculates bank transfers overnight, or a scientific mathematics machine, or an MP3 encoder are examples of this.

The other kind is an on-line program. It takes data continually and reacts to it throughout the length of the program. Most software you use day to day does this. Your phone responds to your finger jabbing it. Your web browser reacts to your clicks.

In ChucK you can make both kinds of program. We’re going to focus on the first kind, but we’ll move onto the second kind soon enough.

Turtles all the way up

Another feature of programing languages and music is that they are all composed of small, atomic, individual instructions which combine together to form structures, and can end up being very abstract. In this respect programming languages and natural [human] languages have a lot in common. If you delve into a program you will find very simple and easy to understand instructions, and very simple ways of combining them. But these combinations may be made in very interesting and abstract ways, resulting in a system that is far removed from the individual instructions of which it is composed.

The same is very much true of music. Rachmaninov and Debussy’s works are made out of crotchets and quavers, but the end result is in some cases almost unrecognisably removed from the raw ingredients. The process of creating an impressionist or romantic piece of music is phenomenally abstract. The combinations of timbres can result in something quite unimaginable. At the other end of the spectrum we have Bach, where the individual notes are very much laid bare, but nonetheless he is capable of creating large, complex and brilliant structures.

Violins. How do they work?

Sound is the movement of air molecules. If we confine ourselves to musical sound for the moment, we can say that a sound is is regular movement at a given frequency (or set of frequencies). The faster a resonant object vibrates, the higher the note.

Let’s take a violin string. A violin string has several properties that make it an excellent candidate for being attached to a violin. Firstly, it is elastic. If you pull it, it stretches and then bounces back. Secondly, you can pull it tight, tight enough that it makes an audible sound when plucked. Seeing as it’s such a good candidate, we’ll string the violin and tighten it.

When you pull the string back, it will ‘give’. You’re increasing the tension in the string, and it doesn’t much like that, so when you let go, it’ll immediately spring back to its resting position. Because it’s elastic and resonant, it’ll overshoot a bit, and end up tight again. It’ll repeat this process, vibrating backward and forward until it runs out of energy. Let’s say for the sake of argument that it moves back and forward 440 times a second. You will recognise that as a perfectly in-tune A (unless you’re European, in which case you might consider it a bit flat).

So our string is moving backward and forwards, it’s causing an equivalent vibration in the air and that’s causing an equivalent vibration in the ear drum (let’s ignore the vibration of the body of the violin for now). With a bit of hand-waving (no point nit-picking just now), we can say that when the string moves one way, the ear drum moves one way, and when it moves back, the ear drum moves back. There is a direct correspondence between the movement, both in terms of frequency and in terms of loudness, between the string, the air, and the ear.

Thanks to the wonders of modern technology, we can move the violin into the next room and still be able to hear it. We just need to find a microphone, some cable, an amplifier and a speaker. The diaphragm of the microphone moves backwards and forwards with the string and it produces a voltage in the cable that rises and falls with the diaphragm of the microphone. The amplifier boosts the voltage on the cable so it has more energy, enough to move the diaphragm on the speaker accordingly.

Thanks to yet more wonderful leaps and bounds, we can not only displace the violinist in space, we can also displace her in time (although at the time of writing, only in one direction). If we replace the speaker moving backward and forward with an arm attached to a needle, we can scratch out a groove in a vinyl record. The groove moves left when the string moves left, the groove moves right when the string moves right.

A week later, we put the record it in a record player, where a needle, effectively attached to a microphone does the reverse.

If you skim-read all that stuff about the violin, I don’t blame you (although if you did, you should fess up and read it) the thing to take away from this is that the medium we’re using to represent the signal, whether that’s the air, the voltage in the wire, or the groove carved out of vinyl, changes in proportion to the signal. The change in the medium is _analogous_ to the signal. You may be ahead of me here. We’re talking analogue. That’s what analogue means. The medium is an analogue for the signal.

You know what Digital means, right?

Whenever I mention the word ‘digital’ to my grandmother, and let me assure you it only ever happens by accident, she says ‘Yes well of course to me ‘digital’ means counting on your fingers,’ and she’s always surprised and a bit disappointed when I say ‘me too’.

Digital means storing things as numbers. If we could go to back to our microphone-speaker situation, get the permission of the person the wire belongs to, chop it, and put a volt-meter across it, and if we could somehow freeze time, we could measure the voltage at a given instant. We could write that number down, and increment time by a fraction of a second. If we measured the voltage thousands of times a second, and wrote it down, we would have effectively made a digital recording. We could then do the reverse, creating a given voltage in the wire and change it to be the sequence of measured voltage values, and feed it in to the amplifier. In doing that we would be playing back our digital recording.

Of course, we have computers to do that for us. Our analogue to digital converter __is a machine that measures the voltage many thousand times a second and stores it in electronic format. Similarly, a digital to analogue converter takes a sequence of numbers stored in electronic format and re-creates the changing voltage in a wire.

So analogue means that the signal we’re representing is represented directly in the medium. Digital means that we’re encoding it into numbers before storing it in the medium. We could take two pieces of paper. On one we have an analogue representation of the sound, which could be represented as pen moving backwards and forwards over the paper in a squiggly line. The digital representation would be a long sequence of numbers.

If we damaged the paper, or spilled something on it, we would have made a change in the medium, and ruined our analogue recording. If we could play it back it would sound damaged. Our digital recording would survive though, because we could still make out the numbers and re-create the signal.

So yes, digital means counting on your fingers if you want it to.

As far as this course goes, everything that happens in your computer is digital. Everything that happens outside is analogue. The boundary is in the bit between the computer and the headphone socket, speakers, microphone etc. The sound is represented digitally as a stream of numbers that represent the voltage in the wire.

But what about ChucK?

We haven’t forgotten about ChucK. Now we’re going to make it do something.

What does this mean to you? You probably know how to play it without thinking. But let’s break it down into all of its component instructions.

  1. play the note ’D’
  2. wait for the length of time that you know to be a quaver
  3. stop playing the note ’D’
  4. start playing the note ‘E’
  5. wait for the length of time that you know to be a quaver
  6. stop playing the note ‘E’

Actually let’s not. No need to go all the way up to A. But you get the point. Lots of individual instructions are encoded in that simple piece of music.

We’re going to need an oscillator, something that makes a sound. We’re also going to need a digital to analogue converter, so we can get the sound out.

First sighting confirmed

SinOsc myOscillator;
myOscillator => dac;

There’s our sight of of ChucK. The first line means ‘create me an oscillator that produces a sine wave’. The second line means ‘connect it to the digital to analogue converter, aka the dac’. This is the equivalent of a ‘virtual violin’ except it makes a sine wave.

How do you make a ’D’ on a violin? You press the string down in a place that makes the string oscillate at the pitch of a D. We can say that the frequency is a property of the violin (no double-stopping!), and that’s a property we can change by altering where we put our finger down on the fingerboard.

Frequency is a property of the SinOsc too.

440 => myOscillator.freq;

This is taking the number 440 and assigning it to the freq property of the myOscillator. The syntax may look a bit odd, but it will sink in. Notice the semicolon at the end. That’s like a full-stop. It means you have finished the current statement.

So we have an oscillator, we’ve wired it up to our DAC and we’ve set its frequency to 440 vibrations a second, which is a concert A. What happens if we give this program to ChucK?

Nothing, it’ll exit immediately. You need to tell it to wait for a bit before exiting so that you have a chance to hear it. So here is our first complete ChucK program. You can copy and paste it into MiniAudicle, or into a text file and run it through ChucK.

SinOsc myOscillator;
myOscillator => dac;
440 => myOscillator.freq;
1::second => now;

Tada! Our first ChucK program. And it makes a noise. How many people’s first program makes a noise? Mine certainly didn’t.

You’ll have to take my word for it that the last line means ‘wait until a second has elapsed’.

Your very second ChucK program

Now let’s turn the above piece of music into a ChucK program. I know what the pitches are because Google.

So let’s perform our piece of music.

Here’s a complete ChucK program.

SinOsc myOscillator;
myOscillator => dac;

293 => myOscillator.freq;
0.5::second => now;

329 => myOscillator.freq;
0.5::second => now;

369 => myOscillator.freq;
0.5::second => now;

391 => myOscillator.freq;
0.5::second => now;

440 => myOscillator.freq;
1::second => now;

Brilliant. Not brilliant, but progress from silence. If you like the sound of sine waves.

Representing Concepts like ‘a D’.

As a musician you know how to spot a note called ’D’. You know how to press the string in such a way that the frequency at which it vibrates is 293 Hertz (Hertz means ‘cycles per second’). You have a concept of D.

You’ll know about variables from algebra.

x = 2 • y

and so on. You’ve got a label, x, and it has a value. We can do something similar in ChucK.

int d;
293 => d;

The first line means ‘make a variable called d which is an integer’. The second line means ‘take the number 293 and assign it to d’. You can now use the variable d rather than the number. Let’s extend our program to do this. I can’t put a sharp as the name of a variable, so I write f# as fs.

SinOsc myOscillator;
myOscillator => dac;

int d;
293  => d;

int e;
329  => e;

int fs;
369  => fs;

int g;
391  => g;

int a;
440  => a;

d => myOscillator.freq;
0.5::second => now;

e => myOscillator.freq;
0.5::second => now;

fs => myOscillator.freq;
0.5::second => now;

g => myOscillator.freq;
0.5::second => now;

a => myOscillator.freq;
1::second => now;

That’s much nicer. We’re encoding some musical knowledge in variables and then using them.

Give me half a second

The 0.5::second still a bit ugly. We’re going to define a variable called quaver, which we’ll use to store the concept of ‘half a second’. The type of that value isn’t exactly an integer, it’s a special type called a duration, shortened to dur.

dur quaver;
0.5::second => quaver;

We can then write

quaver => now;

to pause for the duration of a quaver.

What about a crotchet? Let’s dig out Eric Taylor.

dur crotchet;
quaver * 2 => crotchet;

The asterisk means multiply. Our complete program again:

SinOsc myOscillator;
myOscillator => dac;

dur quaver;
0.5::second => quaver;

dur crotchet;
quaver * 2 => crotchet;

int d;
293  => d;

int e;
329  => e;

int fs;
369  => fs;

int g;
391  => g;

int a;
440  => a;

d => myOscillator.freq;
quaver => now;

e => myOscillator.freq;
quaver => now;

fs => myOscillator.freq;
quaver => now;

g => myOscillator.freq;
quaver => now;

a => myOscillator.freq;
crotchet => now;

Good. We’ve extricated out numbers from the music. It’s almost obvious what it means.

Adding a bit of structure

Let’s make our piece of music a bit more adventurous.

You already have what you need to do this. You could just copy and paste. You could but you shouldn’t because the music doesn’t say ‘play D, E, F#, G, A, D, E, F#, G, A’, it says ‘play this bar then play it again’. If the notes on the stave were copied and pasted then copy and pasting the code might be a good equivalent, but we want to make this accurate as possible.

What we’re going to do here is create a function, which is a block of code, that plays the notes in the first bar. That function just wraps up the sequence of notes into a re-usable component. We can then execute that function twice.

The function syntax here is magic, I’ll explain it in a future lecture. Trust me.

function void bar_one()
{
    d => myOscillator.freq;
    quaver => now;

    e => myOscillator.freq;
    quaver => now;

    fs => myOscillator.freq;
    quaver => now;

    g => myOscillator.freq;
    quaver => now;

    a => myOscillator.freq;
    crotchet => now;
}

There’s our function. When I write it in my code, the computer says ‘there’s a function, I’ll store it for later’. It doesn’t actually run (or ‘call’ or ‘execute’) it until you tell it to.

I can call it by writing:

bar_one();

This will execute the function. The program will wait until the function has finished running, it only does one thing at once (unless we explicitly tell it to). If I call _barone() twice, it will execute it, and then execute it again. Here is my full code:

SinOsc myOscillator;
myOscillator => dac;

int d;
293  => d;

int e;
329  => e;

int fs;
369  => fs;

int g;
391  => g;

int a;
440  => a;

dur quaver;
0.5::second => quaver;

dur crotchet;
quaver * 2 => crotchet;

function void bar_one()
{
    d => myOscillator.freq;
    quaver => now;

    e => myOscillator.freq;
    quaver => now;

    fs => myOscillator.freq;
    quaver => now;

    g => myOscillator.freq;
    quaver => now;

    a => myOscillator.freq;
    crotchet => now;
}

bar_one();
bar_one();

There you go.

We’re assuming a quaver is half a second. That’s the equivalent of a quaver = 120 BMP. We could instead write:

1::minute / 120 => quaver;

The slash means ‘divide’. Try it.

Faster! Faster!

Variables in programming languages such as ChucK are better than algebra, and not just because you get to use a computer. The value of variables can vary. How about we change the value of our quaver half way through?

SinOsc myOscillator;
myOscillator => dac;

int d;
293  => d;

int e;
329  => e;

int fs;
369  => fs;

int g;
391  => g;

int a;
440  => a;

dur quaver;
dur crotchet;

function void bar_one()
{
    d => myOscillator.freq;
    quaver => now;

    e => myOscillator.freq;
    quaver => now;

    fs => myOscillator.freq;
    quaver => now;

    g => myOscillator.freq;
    quaver => now;

    a => myOscillator.freq;
    crotchet => now;
}

1::minute / 120 => quaver;
quaver * 2 => crotchet;

bar_one();

1::minute / 240 => quaver;
quaver * 2 => crotchet;

bar_one();

If you don’t understand what’s happening here, just look at it and think for a few minutes. You’ll twig it fairly soon. If you do, well done.

Fin.

This concludes today’s lernin’. Try running this in ChucK. Change things around. You might even enjoy it.

Read more