Music 220b: Winter 2001
Fernando Lopez-Lezcano, instructor
Christopher Burns, teaching assistant
Tamara Smyth, teaching assistant
Week 3: arrays
Lisp's preferred data structure is the list. However, Common Lisp does provide a variety of other data structures which we can use, including arrays. Arrays are often useful inside the run loop of a CLM instrument; when the run loop is compiled to C, an array can be accessed much more efficiently than an equivalent list.
Arrays are a bit like a row of mailboxes: a series of slots where you can store data. (In this case, "data" can mean almost anything: in CLM we might want to have arrays of soundfiles, or arrays of filters, or arrays of microtonal scales). Each slot has its own number, and you can move data in and out of that slot by referring to the associated number. Arrays can also be multidimensional: think of the mailboxes in the CCRMA lobby as a two-dimensional array.
So how do arrays work? Well, as with unit generators, and most other Lisp structures, we create them first, and then we use them afterwards.
Creating an array: make-array
Ordinarily, we'll want to attach a name to an array, so that we can refer to it when we need it. As a result, we'll proceed by using (setf) to attach our array to a name. The array itself is created with (make-array):
CM(1): (setf array-1 (make-array 4)) ; a one-dimensional array with four elements #(NIL NIL NIL NIL) CM(4): (setf array-2 (make-array (list 3 5))) ; a two-dimensional array: three by five #2A((NIL NIL NIL NIL NIL) (NIL NIL NIL NIL NIL) (NIL NIL NIL NIL NIL)) CM(5): (setf array-3 (make-array 4 :initial-element 7)) ; initializing the array with all elements set to 7 #(7 7 7 7) CM(6): (setf array-4 (make-array 5 :initial-contents '(1 2 3 4 5))) ; specifying a more complex set of initial elements #(1 2 3 4 5)
Accessing an array: aref
To work with an existing array, we use (aref) (or array reference). We can either use aref alone to look at the contents of our array, or we can use aref in conjunction with setf to change the values in the array. The syntax for aref is (aref array-name array-indexes) -- remember that the first index to an array is zero, and that multidimensional arrays require more than one index. For example:
CM(7): (aref array-4 0) 1 CM(8): (aref array-4 1) 2 CM(10): (aref array-1 1) NIL CM(11): (setf (aref array-1 1) 'foo) FOO CM(12): (aref array-1 1) FOO CM(13): (setf (aref array-2 0 0) 'first-element) FIRST-ELEMENT CM(14): (aref array-2 0 0) FIRST-ELEMENT
Imagine that this code were part of a CLM instrument. What frequencies does this produce? At what total amplitude?
(let* ((oscillator-bank (make-array 10))) ; initialization phase (loop for k from 0 to 9 do (setf (aref oscillator-bank k) (make-oscil :frequency (+ 20 (* k 40)))))) (run ; run loop (loop for i from beg to end do (setf current-sample 0.0) (loop for h from 0 to 9 do (incf current-sample (* 0.1 (oscil (aref oscillator-bank h))))) (outa i current-sample)))