CCRMA

Introduction to CLM and Lisp


Lecture Slides

A series of images of the lecture slides... [NOTE: not all of this will be covered in the first lecture]


Links to online documentation

FM resources

Here are a couple of links to interesting stuff about Frequency Modulation:

Common Lisp resources

Common Lisp is the computer language underlying Common Lisp Music, Common Music and Common Music Notation. Here are some links with information about the language itself:

  • Common Lisp: Second Edition (local)

    this is the "Common Lisp Bible", everything there is to know about Common Lisp is here, in excruciating detail. Jump directly to the table of contents to see what's there. Or to the global index if you want to search for a specific construct.

  • Hyperspec (local)

    another complete reference text for the Common Lisp language. Jump directly to the table of contents.

Touretsky's book, "Common Lisp: A Gentle Introduction to Symbolic Computation" is actually online as either ps or pdf files. WARNING: DO NOT PRINT THIS AT CCRMA!, it is 600 pages long and does not print cleanly as a whole, please do not waste paper and tie up the printer. You have been warned. There is a local copy for you to open in a pdf or Postscript viewer at: "/usr/ccrma/lisp/docs/touretzky/" (you do not need to download it again from the link below).

Some info about Common Lisp's loop macro:

The definite reference to the loop macro in Steele's book.

Common Lisp concepts you will need to know

We will go through this in the first lecture...

  • basic lisp syntax (parenthesis)
  • structure of a function definition
  • the let statement (local variables - local bindings)
  • defining a global variable (defparameter)
  • setting the value of a variable (setf)

Things you will need to do

If you use the recommended method of running your lisp interpreter inside the xemacs editor you will need to customize the xemacs configuration file. Why xemacs? Xemacs can run your lisp interpreter in a window inside xemacs - it is easy to switch between the code and the interpreter and the same editing commands that you use to edit code can be used to edit previously entered commands in the interpreter. Xemacs can highlight syntax, it shows matching parenthesis and can highligh regions. Xemacs can automatically indent your code - this is very important to "see" the structure of a lisp program (when you start a new line type [tab] and the cursor will jump to the proper indentation level automatically).

How to use xemacs

A complete tutorial is beyond the scope of this page, but here is a very useful link with the most useful commands:

Almost all of these commands are also available as menu entries or icons you can click on, if you want to excercise your mouse. I find it faster to just type (obviously there is a learning curve while you memorize the key sequences).

A .emacs file

Here is the .emacs configuration file that I used for starting the lisp interpreter and interacting with it. Just insert this code at the end of your ~/.xemacs/init.el file and restart xemacs (or merge the contents with what you currently have in your configuration file if you have customized it). With this in place you should be able to ([ctl]-x means press the control key and x at the same time):

  • [ctl]-x [ctl]-l to start the lisp interpreter inside xemacs
  • in a lisp mode buffer (or in other words, while editing a file that ends in .lisp or .ins) highlight some lisp code and then type [ctl]-c [ctl]-r and the hightlighted region will be sent to the lisp interpreter and evaluated
  • in a lisp mode buffer put your cursor inside some lisp code and then type [ctl]-c [ctl]-e and the enclosing top level form will be sent to the lisp interpreter and evaluated

Check the emacs cheat sheet for a list of the most commonly used commands...

A very simple CLM instrument

"Simp" is a bare bones CLM instrument, just a sine wave oscillator with an envelope. Analyzing simp will teach you a lot about lisp and CLM. There are two approaches: build simp one step at a time, or take the whole thing apart and explain what each part does. Both approaches are taken in the following two sections:

Dissecting simp

A very tiny instrument written in clm-2 and a lot of information on how it is built...

Building simp

The step by step process of building a clm instrument one piece at a time (as done in class). Includes some comments on what each version adds to the preceding one. simpbuild.ins.

Running CLM instruments

This is a typical cycle for compiling and running clm instruments:

  • start xemacs
  • [ctl]-x [ctl]-l to start the lisp interpreter
  • edit the instrument file (make changes if necessary, save)
  • go to the lisp buffer ([ctl]-x [ctl]-l will take you there)
  • type :cl name-of-file to compile and load the file
  • use with-sound to test the instruments...

CLM stuff you should look up

  • definstrument (how to define a CLM instrument)
  • oscil (a sinewave oscillator)
  • env (a piecewise linear envelope)
  • outa (basic one channel output)
  • with-sound (how to get everything working)
  • the run loop

CM stuff you should look up

Here is the dictionary where all of Common Music functions and macros are documented.
  • hertz (converts from anything to frequencies)
  • keynum (converts from anything to key numbers)
  • note (converts anything to note names)
  • pick (pick a random argument - and see pickl as well)

Cellular Automata

First of all some references on cellular automata:

Some topics:

  • the basic building block: a cell (it has memory, remembers its own state)
  • a lattice of cells (how to arrange them)
  • rules: define the next state of the cells (generations)
  • neighbourhood: defines the scope of the rules

Unidimensional automata

Here's the example I developed over last class. It implements a one-dimensional automata. Each cell of the automata is a small state machine with just two states. The transition between states is determined by the state of its two adjoining neighbors...

fabric.lisp

And a very good explanation of what's going on by Matt Wright:

fabric.html


Some synthesis methods

Additive and Wavetable Synthesis

Periodic waveform synthesis

f(t)=sum,k=0,...(Ak*sin(kwt+Qk)) [Moore 210]

Partial based synthesis

f(t)=sum,k=0,...(Ak*sin(wkt+Qk)) [Moore 210]

Time varying synthesis

Ak=f(t)
Wk=f(t)
Qk=f(t)

Modulation Synthesis

Ring Modulation

Amplitude Modulation

Simple Frequency Modulation


Examples

  • A very simple wavetable instrument (wavetable.ins)
  • A very simple three partial additive instrument (additive.ins)
  • The frequency sweep instrument used for the aliasing examples (sweep.clm)

Examples from the clm distribution:

The "complete add" clm example instrument from the clm distribution (add.ins)
This instrument accepts an array of envelopes for the frequency of the partials and another array of envelopes for the amplitude of the partials. With both arrays you can generate completely arbitrary sounds (at the heavy price of having to specify everything in complete detail!).
Fancier additive synthesis instrument (badd.ins)
This one also includes controls for vibrato...
For a very entertaining example of what you can do with a few sine waves take a look at the following instruments and note lists:

Copy these two instruments to your own area and compile and load them into lisp. After you are done load this clm score into lisp: bird.clm (remember you can type "q" followed by "return" to halt playback of the resulting soundfile). Load the soundfile into "snd" and take a look at the spectrum in "sonogram" mode... each bird song has its own set of pitch "inflections". You can incorporate a whole forest full of birds into your piece!

Another fancy example that uses additive synthesis (and some frequency modulation):

Copy these three instruments to your own area and compile and load them into lisp. After you are done load this clm score into lisp: bag.clm. It will take half a minute or so for the note list to compile... it _is_ loud so be careful. Have fun!

  • A very simple ring modulation instrument (ringmod.ins)
  • A very simple ring modulation instrument with wavetable oscillators (ringmodw.ins)
  • A very simple amplitude modulation instrument (ampmod.ins)
  • A very simple amplitude modulation instrument with wavetable oscillators (ampmodw.ins)
  • A very simple frequency modulation instrument (fmmod.ins)

Here are a bunch of fm instruments, mostly coming from the clm area ("/usr/ccrma/lisp/src/clm-2"). You should explore, there's a wealth of information and examples hiding there...

bell.ins

The eternal "fm bell". Here is the header of the instrument and a short description of its parameters:

(definstrument fm-bell (start-time duration frequency amplitude 
			amp-env index-env index
		        &optional (degree 0.0)
				  (distance 1.0)
				  (reverb-amount 0.005))

Mandatory parameters

start-time
starting time in seconds
duration
duration of the note in seconds
frequency
frequency of the note in Hertz
amplitude
amplitude of the note (between 0 and 1)
amp-env
amplitude envelope. A list of time-value coordinates that determines the evolution of loudness over time. The time values are relative and are scaled to the duration of the note (for example I usually use a time axis that stretches between 0 and 1).
index-env
modulation index envelope. A list of time-value coordinates that determines the evolution of modulation index over time. The modulation index controls the "brightness" of the sound (the higher the index the brighter the resulting sound).
index
modulation index. The scaler for the index envelope.

Optional parameters

degree
angle in degrees from where the sound is coming from in a stereo rendition. "0" is left and "90" is right; "45" is right in the middle of the stereo field.
distance
distance in feet from where the sound is coming from.
reverb-amount
amount of reverberation added to the sound. For this to work you must have a reverberator loaded and the with-sound call has to specify it.

Some random with-sound's

doesn't sound like a bell...

  (with-sound()(fm-bell 0 4 440 0.1 
                        '(0 0 0.05 1 0.2 0.4 0.8 0.2 1 0)
                        '(0 0 0.02 1 0.2 0.2 0.8 0.1 1 0)
                        1))
so let's tweak envelopes a bit...

  (with-sound()(fm-bell 0 4 440 0.1 
                        '(0 0 0.002 1 0.2 0.4 0.8 0.2 1 0)
                        '(0 0 0.001 1 0.1 0.08 0.8 0.01 1 0)
                        1))
maybe try a duller bell?

  (with-sound()(fm-bell 0 4 440 0.1 
                        '(0 0 0.002 1 0.2 0.4 0.8 0.2 1 0)
                        '(0 0 0.001 1 0.1 0.08 0.8 0.01 1 0)
                        0.3))
but with a different envelope and a lower frequency it's not a bell any longer... (but sounds like the typical fm wow)

  (with-sound()(fm-bell 0 4 78 0.1 
                        '(0 0 0.3 1 0.4 0.9 0.8 0.2 1 0)
                        '(0 0 0.35 1 0.38 0.9 0.8 0.01 1 0)
                        0.7))

drum.ins

A drum simulation. Here is the header of the instrument and a short description of its parameters:

(definstrument fm-drum (start-time duration frequency amplitude index 
			&optional 
                        (high nil)
                        (degree 0.0)
                        (distance 1.0)
                        (reverb-amount 0.01))

Mandatory parameters

start-time
duration
frequency
amplitude
index
modulation index.

Optional parameters

high
"t" introduces an upwards glissando in the end of the note (the glissando function is a constant hardwired into the instrument, it could be made a parameter, of course).
degree
distance
reverb-amount

Some example with-sound's

  (with-sound ()
              (fm-drum 0 1.5 55 .3 5 nil)
              (fm-drum 2 1.5 66 .3 4 t))

gong.ins

A very nice gong simulation. Here is the header of the instrument and a short description of its parameters:

(definstrument gong (start-time duration frequency amplitude
		     &key 
                     (degree 0.0)
                     (distance 1.0)
                     (reverb-amount 0.005))

Mandatory parameters

start-time
duration
frequency
amplitude

Optional parameters

degree
distance
reverb-amount

Some example with-sound's

  (with-sound () (gong 0 3 261.61 .6))

Fm violin

A generic and very versatile fm instrument created by Bill Schottstaedt. A nice example of multipurpose coding. Almost everything has reasonable defaults but can be changed. If you examine the code you'll see another feature common to good instruments. The key parameters are defaulted to the value of special (global) variables. That opens the possibility of globally changing the behaviour of a bunch of notes by just encasing them in a "let" with redefinitions of those global variables. Here is the header of the instrument and a short description of its parameters (which has plenty off):

(definstrument fm-violin
  (startime dur frequency amplitude 
   &key
   (fm-index                   fm-violin-fm-index)
   (amp-env                    fm-violin-amp-env)
   (periodic-vibrato-rate      fm-violin-periodic-vibrato-rate)
   (random-vibrato-rate        fm-violin-random-vibrato-rate)
   (periodic-vibrato-amplitude fm-violin-periodic-vibrato-amplitude)
   (random-vibrato-amplitude   fm-violin-random-vibrato-amplitude)
   (noise-amount               fm-violin-noise-amount)
   (ind-noise-freq             fm-violin-ind-noise-freq)
   (ind-noise-amount           fm-violin-ind-noise-amount)
   (amp-noise-freq             fm-violin-amp-noise-freq)
   (amp-noise-amount           fm-violin-amp-noise-amount)
   (noise-freq                 fm-violin-noise-freq)
   (gliss-env                  fm-violin-gliss-env)
   (glissando-amount           fm-violin-glissando-amount)
   (fm1-env                    fm-violin-fm1-env)
   (fm2-env                    fm-violin-fm2-env)
   (fm3-env                    fm-violin-fm3-env)
   (fm1-rat                    fm-violin-fm1-rat)
   (fm2-rat                    fm-violin-fm2-rat)
   (fm3-rat                    fm-violin-fm3-rat)
   (fm1-index                  fm-violin-index1)
   (fm2-index                  fm-violin-index2)
   (fm3-index                  fm-violin-index3)
   (base                       fm-violin-base)
   (frobber                    fm-violin-frobber)
   (reverb-amount              fm-violin-reverb-amount)
   (index-type                 fm-violin-index-type)
   (degree                     nil)
   (distance                   1.0)
   (no-waveshaping             nil)
   (denoise                    fm-violin-denoise)
   (denoise-dur                .1) ;used to be .5 
   (denoise-amp                .005)
   &allow-other-keys)

Mandatory parameters

startime
dur
frequency
amplitude

Optional parameters

fm-violin-fm-index 1.0
overall modulation index.
fm-violin-amp-env '(0 0 25 1 75 1 100 0)
amplitude envelope.
fm-violin-periodic-vibrato-rate 5.0
periodic vibrato frequency (periodic vibrato is a triangular wave).
fm-violin-random-vibrato-rate 16.0
random vibrato rate (random noise added to the vibrato).
fm-violin-periodic-vibrato-amplitude 0.0025
amplitude of the periodic vibrato.
fm-violin-random-vibrato-amplitude 0.005
amplitude of the random vibrato.
fm-violin-noise-amount 0.0
add index and amplitude noise (internal movement of the sound).
fm-violin-noise-freq 1000.0
bandwidth of the index and amplitude noise.
fm-violin-ind-noise-amount 0.0
index noise amount
fm-violin-ind-noise-freq 10.0
bandwidth of index noise.
fm-violin-amp-noise-amount 0.0
amplitude noise amount
fm-violin-amp-noise-freq 20.0
bandwidth of amplitude noise.
fm-violin-gliss-env '(0 0 100 0)
glissando envelope (pitch envelope)
fm-violin-glissando-amount 0.0
scaler for the pitch envelope.
fm-violin-fm1-env '(0 1 25 .4 75 .6 100 0)
index envelope for first modulator
fm-violin-fm2-env fm-violin-fm1-env
fm-violin-fm3-env fm-violin-fm1-env
fm-violin-fm1-rat 1.0
modulator / carrier frequency ratio for first modulator.
fm-violin-fm2-rat 3.0
fm-violin-fm3-rat 4.0
fm-violin-base nil
kind of interpolation to be done between envelope points.
fm-violin-frobber nil
fm-violin-reverb-amount 0.01
reverberation amount.
fm-violin-index-type :violin
fm-violin-denoise nil
whether to try to reduce quantization noise in envelopes.
fm-violin-index1 nil
modulation index for the first modulator.
fm-violin-index2 nil
fm-violin-index3 nil

Some example with-sound's

For a compilation of examples on how the fm-violin can sound load the fmviolin.clm file. The 20 Mbyte soundfile created by loading fmviolin.clm into lisp after compiling and loading both v.ins and jcrev.ins is at /usr/ccrma/web/html/courses/220b/lectures/1/examples/fmviolin.snd (this will save you some time since the soundfile take quite a long time to be created). Start a copy of "snd" and load the file in it to play the example. Please be aware that for this example to work you will also have to compile and load a reverberator (jcrev.ins). If you want to play with the lisp code inside fmviolin.clm I strongly suggest you take apart the file and create a small with-sound for each example you are interested in... the whole soundfile is almost 20Mbytes long.


Fm voice

Chowning's fm voice instrument.

(definstrument fm-voice (beg dur pitch amp
                         vowel-1 sex-1
                         ampfun1 ampfun2 ampfun3
                         indxfun skewfun vibfun ranfun
			 dis pcrev deg vibscl pcran
                         skewscl ranpower glissfun glissamt)

Some example with-sound's

(let ((ampf '(0 0 1 1 2 1 3 0))) 
   (with-sound (:wait t) (fm-voice 0 1 300 .8 3 1
           ampf ampf ampf ampf ampf ampf ampf
           1 0 0 .25 1 .01 0 ampf .01)))

©2000-2004 Fernando Lopez-Lezcano. All Rights Reserved.
nando@ccrma.stanford.edu