Common Music Reference Manual
 

Top Objects Processes IO Scales Data Patterns Plotter Utilities Index

1  Objects and Musical Structure

Common Music is an object oriented system that represents compositional data in the Common Lisp Object System (CLOS). An object is a unit of storage that is created out of a more general description called a class. A class declares the set of characteristics that are instantiated whenever an object of that class is created. These characteristics are referred to as slots or instance variables.

When a class is created it may be declared to be a specialization of one or more classes. These other classes are called superclasses and the specialization is called the subclass. The superclass-to-subclass relationship says that every characteristic defined in the superclass is automatically inherited by the subclass. Of course, the subclass may add additional characteristics not found in the superclass.

Figure 1-1:  A graph of Common Music's superclass->subclass hierarchy.

As one gains familiarity with the system it becomes natural to want to add new class definitions. The defobject macro provides a simple mechanism to do this. Look at the files "cm:examples;beep.lisp" and "cm:examples;fm.ins" for examples of creating new event classes for Csound and CLM.

1.1 Creating Objects

Use the Lisp function make-instance or the new macro to create objects:

new class {init value}* [Macro]

Allocates and initalizes a new CLOS object. class is the unquoted class name (symbol) of the type of object to create. Following class comes zero or more slot initialization pairs where init is the unquoted symbol or keyword name of the initialization and value is its value. For each pair init is not evaluated and value is evaluated.

Slot initializations for all objects:

time number
Sets the start time of object. time can also be specified as start.

Slot initializations for all container classes:

name {string | symbol}
An optional name for the object. name can also be specified as named.
Other initializations are possible based on the class of object being created.

Example 1-1

? (new seq name 'foo)
#<SEQ: Foo>

? (new midi keynum (between 32 89) time 1 duration 3)
#E(midi :time 1 :duration 3 :keynum 53 :amplitude 64 :channel 0)

? (new pattern q w e h e.. in random returning #'rhythm)
#<RANDOM @ x4C357A6>

? (new i ins 22 time 33 duration .2)
#<I22 33 0.2>

#e (class {slot value}*) [Macro]

Creates a musical event from the specified class and initialization pairs. The print-object method for event subclasses prints events as #e expressions. The format of this expression can be controlled using the *e-format* variable. If the value is t all bound slots in the event are printed. If the value is :terse then only those slots whose values differ from their :initform values are printed. If the value is :parameters then only bound slots that are parameters are printed. If the value is :terse-parameters then only parameters whose values differ from their :initform values are printed. The default value of *e-format* is :parameters.

copy-object object [Function]

Returns a copy of object. Slot values in the new and old objects are identical, that is the slot values are transferred not copied. copy-object uses allocate-instance to create the new object and fill-object to set its slot values.

1.1.1 Setting Slot Values

Slot values in events can be changed using Lisp's setf with slot-value or by using CM's terser sv macro:

sv object slot &optional value &rest others [Macro]

Returns or sets the value of slot in object. slot is the unevaluated symbol name of the slot. If value is provided it becomes the value of slot. others are additional slots and values to set in the object. sv returns the value of the last form evaluated.

Example 1-2

? (setf x (new midi time 0 keynum 23 duration 4))
#E(midi :time 0 :duration 4 :keynum 23 :amplitude 64 :channel 0)

? (sv x keynum)
23

? (sv x keynum 40 amplitude .4 channel 3)
3

? x
#E(midi :time 0 :duration 4 :keynum 40 :amplitude 0.4 :channel 3)

fill-object new old [Function]

Fills slots in new with slot values from old.

1.1.2 Referencing Named Objects

Instances of most composite classes can be named. A named object can be referenced using the #! macro or the find-object function:

#! name [Macro]

Returns the object named name. #! references may be included in quoted lists.

Example 1-3

? (new seq named 'foo)
#<SEQ: Foo>

? (setf x '(a v #!foo 4))
(A V #<SEQ: Foo> 4)

? (io "test.midi")
#<MIDIFILE: "home:test.midi">

? #!test.midi
#<MIDIFILE: "home:test.midi">

find-object name &optional error [Function]

Returns the object named name. If error is t then find-object signals an error if there is no object in the dictionary, otherwise nil is returned if an object is not found.

list-named-objects &optional type [Function]

Returns a list of objects from the system dictionary. If type is specified only objects of that type will be returned.

Example 1-4

? (list-named-objects)
(#<MIDI-FILE "home:test.midi"> <SEQ: Foo> <process: Bif>)

? (list-named-objects 'seq)
(#<SEQ: Foo>)

1.2 Event Classes

An event is an object that represents musical sound. The slots of an event represent the various attributes of sound that the event describes. Some slots in an event are declared to be output parameters that produce values in musical output.

Common Music defines several event classes to use with synthesis languages such as CLM, CSound and MIDI. These event classes can be specialized by the user and new event classes can be defined using the defobject macro.

midi [Class]

Creates a MIDI Note On and Note Off pair out of a more general representation of frequency, duration and amplitude.

midi supports the following slot initializations:

time number
Sets the start time of object. time can also be specified as start.
keynum {keynum | note}
Frequency expressed as a keynum or note. The treatment of floating point keynums depends on the current value of divisions-per-semitone in the MIDI file or port. If the value is 1 (the default) then floating point key numbers are rounded to the closest MIDI keynum. If the value is between 2 and 16 then floating point key numbers produce microtones at the specified resolution. In this case the channel of the MIDI note is ignored and data is automatically routed to the proper microtuned channel.
duration number
The duration of the note in seconds.
amplitude number
A logical amplitude 0.0 < 1.0 or an integer velocity 0 to 127. Defaults to 64.
channel integer
A MIDI channel number between 0 and 31. Defaults to 0.

i [Class]

An event class for CSound i-statements.

i provides the following initializations:

ins number
Sets the i-statement number. ins can also be specified as p1.
time number
Sets the start time of object. time can also be specified as start or p2.
duration number
Sets the duration of object. duration can also be specified as p3.
Use defobject to define i-statements for orchestra specific instruments. Subclasses of i can be named anything as long the ins slot has a value. See the file "cm:examples;beep.cm" and "cm:examples;beep.orc" for an example.

f [Class]

An event class that implements CSound f-statements.

f provides the following initializations:

number number
Sets the f number. number can also be specified as p1.
time number
Sets the start time of object. time can also be specified as start or p2.
size number
Sets the size of the ftable. size can also be specified as p3.

ins [Class]

An event class that implements output to CLM score files (.clm) and sound files (.aiff). definstrument automatically declares a subclass of ins with the same name as the instrument and with slots defined for every lambda parameter in the instrument.

1.3 Container Classes

Container classes implement aggregation of musical material. The seq, pattern, process, io classes all implement different containment strategies.

seq [Class]

A seq holds time sorted subobjects.

seq supports the following slot initializations:

subobjects list
A list of subobjects.

Example 1-5

? (new seq named 'foo time 32
       subobjects (for i below 10 collect (new midi time i)))
#<SEQ: Foo>

process [Class]

process implements the description of music in terms of programming code. The process object automatically creates a new process function each time it is scheduled to produce events. Processes can be created using the defprocess macro.

process supports the following slot initializations:

closure function
A function to call to produce a process function. The closure must accept one argument, the process object.

1.4 Object Utilities

There are a number of functions to support the creation and manipulation of objects.

defobject name supers slots &rest options [Macro]

Defines a new class of object. name is the name for the new class. supers a list of superclasses or (). slots is a list of slot specification or (). Each slot can be either the name of a slot or a list in the form:
(slot &key :initform :accessor :reader :writer :initarg)
defobject automatically declares slot and its keyword as initialization names for new and make-instance. Following slots comes an optional :parameters specification:
(:parameters &rest slots)
slots determines both the order and slot names that are to be process as output parameters in score file generation. The slots listed in slots are considered required parameters unless preceded by a lambda keyword &optional, &key or &rest. A required parameter means that an error is signaled if the slot is unbound during score generation. &optional parameters are ignored if unbound. &key parameters are also optional but the slot value is preceded by its keyword in the output file. A single &rest parameter is a list of values that are "spread" over a number of parameters in the output file. See the file beep.cm for an example CSound defobject.

subobjects seq [Function]

Returns the subobjects of seq. Use (setf subobjects) to set the subobjects of seq.

Example 1-6

? (new seq named 'foo)
#<SEQ: Foo>

? (setf (subobjects #!foo) (for i below 10 collect (new midi time i)))

subholders seq [Function]

Returns the subobjects of seq that are holders.

list-subobjects seq &key :start :end :start-time :end-time :stream [Function]

Lists subobjects of seq to stream, which defaults to the standard output. :start and :end are optional start and end positions (zero based) to list. :start-time and :end-time are optional starting and ending times to list. Positions and times are mutually exclusive.

map-subobjects function seq &key :recurse :key :test :type [Function]

Maps function over the subobjects of seq. If :recurse is t then mapping is recursively applied to all subcontainers of seq. If :test is supplied then only those objects for which :test returns true are mapped. If :type is supplied instead of :test then only objects of that type are mapped. If :key is supplied it is first applied to each mapped object and the results are passed to function. map-subobjects does not return a value.

Example 1-7

;; collect keynums of all midi notes in #!foo.

? (let ((nums '())) 
    (map-subobjects #'(lambda (x) (push x nums)) #!foo :key #'midi-keynum :type 'midi)
    (nreverse nums))

map-subholders function seq &key :recurse :key [Function]

Maps function over the composite objects in seq. If :recurse is t then mapping i recursively applied to subholders of seq. If :key is supplied it is first applied to each mapped subholder and the results are passed to function.

insert-object object container [Function]

Inserts object into subobject of container. objectmust have a time value.

append-object object container [Function]

Appends object to the subobjects of container. append-object does not check time values.

remove-object object container [Function]

Removes object from the subobjects of container.

remove-subobjects object [Function]

Removes all subobjects from object.

save-object object file [Function]

Saves object and all its subobjects to file. object can be a seq or a list of seqs.


Common Music Homepage  |  © 2002 Heinrich Taube Last Modified: 20 May 2002