Creating Rhythmic Noise

Over a year ago, when I first tried the OLPC/Sugar software, I was fascinated by the activities in TamTam applications. Had any of them been available in my time, I may even have liked attending school.

The TamTam activity builds on top of the Csound framework to allow children to explore sounds and music. As I explored the Csound tutorial by Michel Gogins, I came across his comment, “Of all the languages I have used, both in my career as a programmer and in my career as an algorithmic composer, Python has been by far the easiest and most productive language to learn and to use.”

Gogins also writes, “Csound must be considered as one of the most powerful musical instruments ever created.” Hence, the motivation for this article. We will explore how to create noise and, we hope, you will go on to compose music :-) In the current state of the world, we need even more music.

To know a bit about the people behind the code, go to: www.csounds.com/journal/2006spring/meetTheCsound5Developers.html.

Getting started

You will need to install the following packages: csound and csound-python.

Csound requires an XML-like configuration file with three sections. Create a minimal file, tutorial.csd:

<CsoundSynthesizer>
<CsOptions>
</CsOptions>
<CsInstruments>
</CsInstruments>
<CsScore>
</CsScore>
</CsoundSynthesizer>

You will be satisfied with the default options. The instruments section is where we define the ‘orchestra’, which comprises all the instruments that will be used to create our musical masterpiece. These are the same as the contents of myfile.orc in the beginner’s articles in www.csounds.com/journal/articleIndex.html.

The score section will contain a list of instructions for the instruments in the orchestra. These are the same as the contents of myfile.sco, mentioned in the articles mentioned earlier.

Create the same simple instrument as in the beginners’ introduction:

<CsInstruments>
sr=44100 ; Sample Rate
kr=22050 ; Control Rate
ksmps=2  ; sr/kr As far as I know this is always the case
nchnls=2 ; 1=mono, 2=stereo, 4=quad
     instr 1              ; Instrument 1 begins here
aout  oscil 10000, 440, 1  ; An oscillator
     outs  aout, aout     ; Output the results to a stereo sound file
     endin                ; Instrument 1 ends here
</CsInstruments>

The first four lines have header information, which controls the output format. The remaining lines are the definition of the instrument, which is a simple oscillator operating at a frequency of 440Hz and a volume of 10000, about a third of the maximum. (Volume is represented as a 16-bit integer.) The third parameter to the oscil command/opcode identifies the waveform table to be used in the score given below. The oscillator is given a variable name aout. The same sound is passed to both the channels.

Now, add the score:

<CsScore>
f 1  0   16384   10  1 ; table #, start time, the size, generator, parameter
i 1  0   1 ; instrument #, start time, duration
</CsScore>

f is the waveform table, which is available at the start of performance with 16,384 samples. The generator value 10 with parameter 1 corresponds to a sine wave in Csound.

The i line is an instrument event with the instrument number, the start time and the duration in seconds as the parameters.

You can run the following script, get a wave file and play it:

$ csound -Wo tutorial.wav tutorial.cs
$ aplay tutorial.wav

Controlling Csound using Python

Write the following code in tutorial.py. This is pretty useless as all it does is replace the command line for executing Csound. But have patience.

# Import the Csound API extension module.
import csnd

# Create an instance of Csound.
csound = csnd.CppSound()

# Enable Csound to print console messages
csound.setPythonMessageCallback()

# Load the tutorial piece created earlier.
csound.load(‘tutorial.csd’)

# Set the Csound command for off-line rendering.
csound.setCommand(‘csound -Wo tutorial.wav temp.orc temp.sco’)

# Export the .orc and .sco file for performance
csound.exportForPerformance()

# Actually run the performance.
csound.perform()

We will now add code to generate the score algorithmically. However, our current instrument is pretty hopeless. So, you will need to refine the instrument in tutorial.csd as follows:

     instr 1
iamp = p4
ifqc = p5
itabl1 = p6
aout oscil iamp, ifqc, itabl1
outs aout, aout
     endin

The new oscillator uses the amplitude, frequency and waveform table reference as parameters. The variables in Csound have a strict format reminiscent of Fortran. Local variables start with the letters ‘i’, ‘k’ or ‘a’. A variable starting with the letter ‘i’ is initialised to a value when the instrument is started, and does not usually change. The letter ‘a’ indicates an audio rate variable and the letter ‘k’ indicates a control rate variable.

There are also some special ‘p’ variables or parameters that send values from the score to the orchestra—p1, p2 and p3 are the instrument’s number, start time and their duration. The variables p4, p5, p6, etc, are flexible. They are used here for amplitude, frequency and the waveform table.

Now, add a call to add_score to the tutorial.py as follows:

csound.setCommand(‘csound -Wo tutorial.wav temp.orc temp.sco’)
add_score(csound)
# Export the .orc and .sco file for performance

Now, code an add_score method:

def add_score(csound):
     sarega = [130.8, 146.8, 164.8, 174.6, 195.0, 220.0, 246.9, 261.6]
     for time in range(8):
          csound.addNote(1, time, 1, 8000  , sarega[time], 1)

Your instrument will play the notes. Let us improve the instrument and put an envelope in each event. Modify the instrument definition in tutorial.csd as follows:

     instr 1
iamp = p4
ifqc = p5
itabl1 = p6
kamp linseg 0, .2, 1, .2, .8, p3-.5, .8, .2, 0
aout oscil iamp, ifqc, itabl1
     outs aout*kamp, aout*kamp
     endin

You can define an envelope using the opcode linseg, which represents the starting amplitude followed by pairs of time intervals and the amplitude at the end of the interval.

The control variable kamp starts with 0, rises to 1 in .2 seconds, then drops to .8 in the next .2 seconds, retaining that value until .2 seconds before the end. In the last .2 seconds, the value drops from .8 to 0. As you can imagine, an instrument can be programmed to generate pretty complex sounds for each event. You can get an idea of the programming possibilities by playing two frequencies close to each other. Replace the add_score method in the tutorial.py with:

def add_score(csound):
     sarega = [130.8, 146.8, 164.8, 174.6, 195.0, 220.0, 246.9, 261.6]
     for time in range(8):
          csound.addNote(1, time, 1, 8000 ,  sarega[time], 1)
          csound.addNote(1, time, 1, 8000 ,  sarega[time] + 5, 1)

Not surprisingly, you should hear beats.

Musicians do not work with frequencies. They work with octaves. So, let us define another instrument that uses a converter opcode to convert a number into a frequency. The whole number represents the octave, and the decimal part the semitone. So, at the instruments section in tutorial.csd, add the following:

     instr 2
iamp = p4
ifqc = cpspch(p5)
itabl1 = p6
kamp linseg 0, .2, 1, .2, .8, p3-.5, .8, .2, 0
asigl oscil iamp, ifqc*.999, itabl1
asigr oscil iamp, ifqc*1.001, itabl1
outs asigl*kamp, asigr*kamp
     endin

Notice that the definition has a different oscillator definition for the right and left channels. In the score section, include a second waveform table:

f2  0   16384   10  1 .5  .3333

This table is also a sine wave but includes the first and second harmonics with amplitudes that are a half and a third of the primary wave.

Now, modify the add_score method in tutorial.py to use both instruments:

def add_score(csound):
     sarega = [130.8, 146.8, 164.8, 174.6, 195.0, 220.0, 246.9, 261.6]
     pitch  = [8.00, 8.02, 8.04, 8.05, 8.07, 8.08, 8.11, 9.00]
     for time in range(8):
          csound.addNote(1, time, 1, 8000  , sarega[time], 1)
          csound.addNote(2, time, 2, 8000, pitch[time], 1)

The second instrument plays the same tones but at an octave higher. It also uses the second waveform table. You can explore various programming possibilities—like varying amplitudes, varying durations and varying the relative start time of instruments.

As you would have noticed, there is no constraint on the size of the orchestra you can single-handedly create. You can find some simple drum instruments at www.csounds.com/ezine/autumn1999/synthesis/index.html. So go ahead, try them and, may be, create a synthetic tabla!

Next month, we will explore playing around Soundfonts and Csound to create sounds.

All published articles are released under Creative Commons Attribution-NonCommercial 3.0 Unported License, unless otherwise noted.
Open Source For You is powered by WordPress, which gladly sits on top of a CentOS-based LEMP stack.

Creative Commons License.