Programming assignment 1
Animate Arts 2 / Spring 2005

Out: Thursday, April 14
Due: Wednesday, April 20, 11:59pm

In this assignment, you'll get experience writing imperative style code by writing a simple sequencer, similar to the SuperCollider assignment.  We will use Microsoft's Managed DirectX libraries to do the actual playing of sounds.  And rather than synthesize our own sounds, we'll just play back wav files.  We've given you a couple of wav files to start with, but you should feel free to use your own if you prefer.

You should start by taking the attached file and opening it in Meta.  There are parts that you need to fill in, so if you do Execute All, you'll get an error.  But do it anyway and just click the close box on the debugger window when you get the error.  Now it's loaded all the code you need up through problem 1.  Speaking of which ...

Problem 1

Read through the first part of the code up through the first place it says "fill this in here".  Ignore the stuff that's printed in gray.  The parts you should pay attention to are :

The play procedure

The play procedure is supposed to play a sound file over and over any, but shifting its pitch each time so that it plays a melody.  The code we've given you for the play procedure looks like this:

[define play “Play specified pattern using the wave file and the specified tempo”
             [wave-file pattern beats-per-minute →
                   «This will load the sound file into a buffer object called buffer and
                      place its base frequency in baseFreq»
                   [with* buffer = [new SecondaryBuffer wave-file device]
                             baseFreq = buffer.Frequency
                       «Fill this in here»
                       ]]]

The first line of course gives the arguments to play:

So the idea is that if you type:

[play analog-bass
         [list 0 1 2 3]
         60]

It will play the analog bass sound for one second, then play it shifted up a half step for a second, then two half-steps for a second, and finally, three half-steps for a second.

Let's go back to the code.  The with expression then sets up two variables:

You can play the sound by saying: [start-buffer buffer].  However, you can also shift its pitch by changing its sampling rate, which is stored in the field buffer.Frequency, to some number that's higher or lower than baseFreq, the original sampling rate.  That means you need to know what frequency you want to play it at.  For this assignment, we'll just be shifting the original frequency up and down, which is what the shift-frequency procedure we mentioned above is for.  If you say [shift-frequency baseFreq 1], you'll get back the frequency which is the original frequency shifted up one half-step (one piano key's worth of pitch).  If you say [shift-frequency baseFreq 2], it shifts it up two half.steps (i.e. a whole step), and if you say [shift-frequency baseFreq -2], it shifts it down two half-steps.

You can also restart the sound from the beginning by saying [buffer.SetCurrentPosition 0] and then calling start-buffer again.  However, before changing the position or the frequency, you have to do [buffer.Stop] (just because, sorry).

Your job for problem 1 is to finish the play procedure.  In particular, it should iterate through the list of numbers in pattern, and for each number, it should:

Remember that you can iterate over the list by using while to repeatedly run a piece of code and get to remove elements from a list (see lecture 2).

Once you've written play, try out the test case we've written underneath it to make sure it works.

Problem 2

Okay, this problem is much simpler.  Just modify your code for play to let you put rests (silences) into the list.  Change the code so that if one of the elements of the list is null, then it waits the same period of time, but it doesn't play any sound.

Problem 3

Okay, so all we need now is write the equivalents of SuperCollider's Pseq, Prand, etc.  If you read the next chunk of code, you'll see we've given you the following procedures:

Your job is to fill in the code for the next two procedures, random-without-repetition, which should behave like the Pxrand procedure from SuperCollider, and reverse, which should return a list that's just like it's input, only where the elements are reversed.

Freestyle

Now have fun playing with the pattern procedures.  You can also try different sound files and you should feel free to try your own .wav files.  This part is sort of a reprise of the audio assignment, but you don't need to put as much work into it.  Just have fun and choose one pattern/sound file combination that you like.

Turning it in

Upload your code to the assignments web site.  If you used your own wav file, upload that too.