Sound Art: Creating Sounds Using Csound
The goal of this project is to make one or more sounds lasting at least 3 seconds. The sounds can consist of multiple notes and different pitches, if you wish. The goal is to make an interesting sound or set of sounds you could use in your game.
Csound is installed on all of the dwarves and macs in the CS lab. You can install Csound on your own computer (Csound web site). For Macs you have the option of MacCCound or using MacPorts to install it.
Csound is a programming language developed to facilitate the creation of sounds from scratch. It is an old-style programming language with obtuse notation, but it is easy to build up extremely complex sounds with minimal coding.
A Csound file has two parts: the orchestra, and the score. The orchestra section consists of a set of numbered instruments. Think of each instrument as a function that defines a particular method of creating a sound.
The score specifies the set of notes to be played. This includes the instrument, start time, duration, pitch, amplitude, and any other information required by the instrument. Each note is on its own line. Think of each note as a function call to an instrument function.
Once you have an orchestra and a score, Csound will generate a sound file based on the instructions you have provided.
The orchestra defines a collection of instruments. Think of each instrument as a function with a set of parameters. In Python we could define a function with a bunch of arguments as follows.
def instr1( p0, p1, p2, p3, p4, p5, p6, p7): # body of function here return
In Csound, we define the instrument function using different notation. The following is an instrument with five parameters that drives an oscillator at the frequency (pitch) and amplitude (volume) specified by the parameters p4 and p5.
instr 1 a1 oscil p4, p5, 1 out a1 endin
Unlike python, where parameters are explicit in the function definition and have user-defined names, in Csound the parameters are implicit and have the pre-defined names p1, p2, p3, and so on.
Nevertheless, an instrument is simply a function with a set of parameters that we can use to control the quality and nature of the sounds the instrument creates. In the instrument above, the parameter p4 controls the amplitude (volume) of the oscillator and the parameter p5 controls the frequency (pitch). The last argument to the oscillator is the function table to use when generating the periodic waveform.
In order to play an instrument, we have to have a score, just as a violinist needs sheet music to know which pitches and rhythms to use.
Csound uses a very simple approach to defining notes and rhythms. Each note has an instrument, a start time and a duration. The meaning of any parameters beyond the first three are user defined. In the instrument defined above, for example, p4 is used to control amplitude and p5 is used to control pitch.
The following is a score file for instrument 1 that plays three different notes, one after another, with each note having a duration of 1s. Each note has a different pitch, and the middle note has a lower volume than the other two.
; function table 1 (comments start with a semi-colon) ; index start samples GEN max amplitude f 1 0 8192 10 1 ; Note Instr Start Dur Amp Freq i 1 0 1 10000 440 i 1 1 1 3000 660 i 1 2 1 16000 220 e
The function table line defines a sine wave that is available for use by instruments and functions such as an oscillator. There are many ways to create waveforms and use them, but you can do a lot with a simple sine wave.
In the example above, the three notes do not overlap. However, Csound permits you to play as many notes as you wish simultaneously. In the example below there are three distinct parts to the sound, each lasting one second, and each part contains 4 different pitches.
When playing multiple notes simultaneously, the sum of the amplitudes must be less than 32000 or the resulting sound will be distorted.
; function table 1 ; index start samples GEN max amplitude f 1 0 8192 10 1 ; Note Instr Start Dur Amp Freq i 1 0 1 8000 440 i 1 0 1 10000 330 i 1 0 1 4000 660 i 1 0 1 2000 220 i 1 1 1 2000 400 i 1 1 1 1000 600 i 1 1 1 2000 200 i 1 1 1 2000 100 i 1 2 1 6000 160 i 1 2 1 4000 320 i 1 2 1 8000 80 i 1 2 1 6000 40 e
Giving acoustic shape to the sounds created by an instrument is part of making a sound interesting. Consider an instrument that consists of five oscillators that generate three pitches close to the main pitch value, one lower harmonic, and one higher harmonic. The orchestra file is given below. You can use either of the score file above.
instr 1 a1 oscil p4*0.4, p5, 1 a2 oscil p4*0.2, p5*1.006, 1 a3 oscil p4*0.2, p5*0.992, 1 a4 oscil p4*0.1, p5*2.0, 1 a5 oscil p4*0.1, p5*0.5, 1 aout = a1 + a2 + a3 + a4 + a5 out aout endin
Note the multipliers on p4, which adjusts the relative strength of the different oscillators (which sum to 1). Note also the multipliers on p5, which adjusts the frequency of the oscillators relative to the desired pitch. The variable aout is just the sum of the five oscillators. The sound this creates using the first score file above is linked below.
The function linen creates an envelope we can use to multiply the amplitude of each oscillator over the duration of the note. The linen function takes four arguments: amplitude, rise time, total duration, and decay time. It allows you to create a trapezoid in time. An expression like:
k1 linen 1, 0.1*p3, p3, 0.9*p3
Creates a symmetric trapezoid that takes 10% of the total duration time (p3) to rise from 0 to 1, holds until 90% of the tutal duration time, and then takes 10% of the total duration time to decay to 0.
The example below uses three different envelopes to control the shape of the different oscillators. The first envelope, k1, has a quick rise, a long hold, and a quick decay. The second envelope, k2, has a long rise, short hold, and a quick decay. The third envelope, h3, rises half the time and then falls half the time. The shapes of the envelopes are shown below
instr 1 k1 linen 1, 0.1*p3, p3, 0.9*p3 k2 linen 1, 0.8*p3, p3, 0.9*p3 k3 linen 1, 0.5*p3, p3, 0.5*p3 a1 oscil p4*0.4*k1, p5, 1 a2 oscil p4*0.2*k1, p5*1.006, 1 a3 oscil p4*0.2*k1, p5*0.992, 1 a4 oscil p4*0.1*k2, p5*2.0, 1 a5 oscil p4*0.1*k3, p5*0.5, 1 aout = a1 + a2 + a3 + a4 + a5 out aout endin
|k1 linen 1, 0.1*p3, p3, 0.9*p3||k2 linen 1, 0.8*p3, p3, 0.9*p3||k3 linen 1, 0.5*p3, p3, 0.5*p3|
The sound this instrument creates using the first score file is given below. Note the difference in the sound.
Finally, here are some other examples of other types of sounds.
Creating Other Sounds
There are many other ways to generate signals. You don't have to use anything but a set of oscillators for the assignment, but if you're interested, here are some functions to try out in an instrument.
These functions all work similarly to the oscil function. The parameters and example code are given on the associated help web site. You can use the functions by themselves, mess with the parameters, mix the functions together, or add envelopes to manipulate the sounds.