Common Music 3

Introduction

Common Music 3 is a software environment for real time and score file (non-real time) algorithmic composition. It is implemented in JUCE, by Julian Storer, and S7 Scheme / SndLib, by William Schottstaedt.

The distinguishing features of Common Music 3 (CM3) compared with the previous (CM2) branch are:

Composition Toolbox

The following functions have been added to Scheme to facilitate algorithmic music composition.

Numbers

fit (num, min, max &opt mode = 1)
→ number or list

Returns num or list of same bounded by min and max according to mode. If min <= num <= max then num is returned. Otherwise, if mode is 1 then the outlying num is wrapped between min and max, i.e. fit returns the remainder of number modulus the boundary range. If mode is 2, then the min and max boundaries reflect the outlying value back into range. If mode is 3 then the boundary value (min or max) is returned.

int (num)
→ number or list

Rounds floating point num or list of the same to the nearest integer.

float (num)
→ number or list

Coerces num or list of the same to a floating point value.

quantize (num, step)
→ number or list

Quantizes num or list of the same to be a multiple of step.

decimals (num, places)
→ number or list

Returns floating point num rounded to places fractional digits.

plus (num...)
plus (list)
plus (list, num)
→ number

Returns the addition of zero or more nums. If a single list of numbers is given they are summed together. Otherwise a list is returned of num added to every element in list.

times (num...)
times (list)
times (list, num)
→ number

Returns the multiplication of zero or more nums. If a single list of numbers is given they are multiplied together. Otherwise a list is returned of num multiplied with every element in list.

minus (num ...)
minus (list)
minus (list, num)
minus (num, list)
→ number

Returns the subtraction of one or more nums. If a single number is given its inverse is returned. If a single list of numbers is given the cumulative subtraction is returned. Otherwise a list is returned of num subtracted from every element in list or every number in list subtracted from num.

divide (num...)
divide (list)
divide (list, num)
divide (num, list)
→ number

Returns the division of one or more nums. If a single number is given its inverse is returned. If a single list of numbers is given the cumulative division is returned. Otherwise a list is returned of every number in list divided by num or every number in list divided into num.

deltas (num...)
deltas (list)
→ list

Returns a list of the deltas (differences) between adjacent numbers in nums. The number of items returned will therefore be one less than the number of items specified to the function.

less? (num...)
less? (list)
→ boolean

Returns true if the numbers in nums... or in a single list of numbers are in monotonically increasing order, otherwise returns false.

greater? (num...)
greater? (list)
→ boolean

Returns true if the numbers in nums... or in a single list of numbers are in monotonically decreasing order, otherwise returns false.

less=? (num...)
less=? (list)
→ boolean

Returns true if the numbers in nums... or in a single list of numbers are in monotonically nondecreasing order, otherwise returns false.

greater=? (num...)
greater=? (list)
→ boolean

Returns true if the numbers in nums... or in a single list of numbers are in monotonically non-increasing order, otherwise returns false.

log10 (num)
→ number

Returns log 10 of num.

log2 (num)
→ number

Returns log 2 of num.

pi
→ 3.141592653589793

The value of pi as a double float.

most-positive-fixnum
→ Implementation dependent value

The largest positive fixed point integer representable in this Lisp implementation.

most-negative-fixnum
→ Implementation dependent value

The largest negative fixed point integer representable in this Lisp implementation.

Lists

first (list)
→ element

Returns the first element in list. Similar accessors exist for these other common element positions: second, third, fourth, fifth, sixth, seventh, eighth, ninth and tenth.

last (list)
→ element

Returns the last element in list. Note that this is not the same as Common Lisp's version (see tail).

nth (list, pos)
→ element

Returns the element at pos position (zero based) in list. Note that this is not the same as Common Lisp's version which (confusingly) reverses the arguments.

butlast (list)
→ list

Returns a list of all but the last element in list.

rest (list)
→ list

Returns a list of all but the first element in list.

tail (list)
→ list

Returns the tail (last cdr) of list.

unique (list)
→ list

Return a copy of list with duplicate elements removed.

concat (...)
→ list

Concatenates its inputs, which can be lists and non-lists, into a single list.

list-set! (list, pos, val)
→ element

Sets the element at pos position in list to val.

sort (list &opt comparator = less?)
→ list

Returns a sorted copy of list given a pairwise comparator function that is passed two arguments and returns true if the value in its first argument should appear before the value in the second argument in the sorted results, otherwise false. The default comparator is less?.

Mapping and Transformation

note (ref)
→ string or list

Returns the note (string) of ref, which can be a note, key or list of the same. A note name consists of a pitch class letter (c d e f g a b), an optional sharp or flat letter (s f) an optional quarter tone inflection (< or >) and an octave number (00 to 9). Note names can be specified as strings, symbols or keywords. Octave numbers inside note lists can be omitted, in which case the current note's octave defaults to the last octave specified, or to octave 4.

key (ref)
→ number or list

Returns the key (number) of ref, which can be a note, hertz or list of the same. A floating point key kkk.cc is interpreted as the frequency cc cents above the integer key number kkk, e.g. 60.5 is 50 cents above Middle C.

hz (ref)
→ number or list

Returns the hertz value of ref, which can be a note, key or list of the same.

pc (ref)
→ number or list

Returns pitch class (0-11) of ref, which can be a note, key or list of the same.

rest? (ref)
→ bool

Returns true if ref is a 'musical rest' marker (r or the key number -1).

transpose (ref, amount)
→ number or list

Transposes ref by amount. If freq and amount are both pitch classes then the transposition occurs in pitch class (mod 12) space. Otherwise nkl should be a key, note or list of the same and it is transposed by amount.

invert (ref)
→ number or list

If ref is a pitch class or list of pitch classes the pitch class complement(s) are returned. Otherwise nkl should be a list of notes or keys and the (strict) inversions around the first key or note in the list is returned.

retrograde (list)
→ list

Returns a version of list with its elements reversed.

scale (num, start, step...)
scale (num, start, list &opt limit = #f, mode = 1)
→ list

Returns a list of num keys starting on start and incremented by each step (positive or negative) or list of steps provided. If a limit key is provided then scale degrees will always lie between start and limit according to mode (see fit).

scale-order (list &opt mode = 1)
→ list

Returns a list of notes, keys or hertz values ordered according to mode, where 1 means ascending order, -1 means descending order and 0 means random order.

rhythm (rhy &opt tempo = 60, beat = 1/4)
→ number

Returns the value of rhy converted to beat units (typically seconds) at a specified tempo. Rhy can be any fraction of a whole note, a rhythmic symbol or a list of the same. A fraction of a whole note is simply a ratio, e.g. 1/4=quarter note, 1/8=eighth note, 3/2=three half-notes, 7/25=seven twenty-fifths notes, and so on. A rhythmic symbol consists of a metric letter (w=whole,h=half, q=quarter, e=eighth, s=sixteenth, t=thirty-second, x=sixty-fourth) optionally preceded by a triplet marker (t) and optionally followed by one or more dots (.). Expressions involving symbols can be formed using +, -, *, / to join the rhythmic tokens. Examples: q=quarter, tq=triplet quarter, e.=dotted-eighth, ts.=triplet dotted sixteenth, h...=triple dotted half, s+tq=sixteenth plus triplet quarter, w-ts=whole minus triplet sixteenth, w*4=four whole notes.

in-tempo (beats, tempo)
→ number

Scales a beat value by a metronome tempo value: beats*(60/tempo)

rescale (x, x1, x2, y1, y2 &opt base = 1)
→ number or list

Returns a floating point value between y1 and y2 that is proportional to a floating point x or list of the same lying between x1 and x2. If base is 1 the rescaling is linear otherwise its exponential where base > 1 produce increasing spread as x approaches x2 and values < 1 produce decreasing spread.

discrete (x, x1, x2, i1, i2, &opt base = 1)
discrete (x, x1, x2, list)
→ integer, element or list

Similar to rescale except floating point x is mapped onto integer values between i1 and i2, or onto the elements in list.

segs (num, sum &opt mode = 1, base = 2)
→ list

Returns num segments adding up to sum, where the relationship between each segment is determined by mode. If mode is 1 then the segments are exponentially related, where base values greater than 1 produce exponentially increasing segments, and reciprocals produce exponentially decreasing segments. If mode is 2 then the segments returned are related by the geometric series. If mode is 3 then random segments that add up to sum are returned.

interp (x, x1, y1 ...)
interp (x, list &opt base = 1)
→ number

Returns the interpolated y value of x in a series of x1 y1 ... coordinate pairs or envelope list of the same. If the coordinates are specified as a list then an optional base can control the type of interpolation (linear or exponential) used. See rescale for more information.

ratio->cents (scaler)
→ number or list

Converts a frequency ratio scaler or list of the same to the equivalent in cents.

ratio->steps (scaler)
→ number or list

Converts a frequency ratio scaler or list of the same to the equivalent in half-steps.

cents->ratio (cents)
→ number or list

Converts a cent value or list of the same to the equivalent frequency scaler.

harmonics (h1, h2 &optkey fund = 1, invert = #f, order = #f, keys = #f)
→ list

Returns a list of ratios, hertz values, or key numbers based on the harmonic series between the harmonic numbers h1 and h2 inclusive. If 0 < h1 < h2 then values will belong to the overtone series, otherwise if 0 > h1 > h2 then values will belong to the "undertone" series. If fund is 1 then the values returned will be frequency ratios, otherwise the series will be based on that hertz value. If invert is true then the ratios between h1 and h2 are reciprocals, i.e. "flipped". If order is false then the overtone series are in increasing order and undertones are in decreasing order. Otherwise, if order is 1 then the list is always ascending, if it is -1 the list always descending, and if it is 0 the list order is randomized. If keys is true then the values returned will be coerced to keynums.

Randomness

All functions that perform random selection use a common random number generator whose current seed can be acquired or set using random-seed. Reseeding the random generator will cause the random number generator to repeat the same sequence of numbers based on that seed.

Uniform Distribution

ran (&opt num = 1.0)
→ number

Returns a random number between 0 and num (exclusive). If num is an integer greater than 1 then an integer will be returned otherwise a floating point value is returned.

between (a, b)
→ number

Returns a randomly chosen number between a and b (exclusive). The value of b can be less than a.

vary (value, pct &opt mode = 0)
→ number or list

Returns a random number that deviates from value or list of the same by up to pct (1=100%) according to mode. If mode is 0 then value is at the center of what could be returned. If mode is -1 then value is the maximum possible value, otherwise mode 1 places value at the minimum of what could be returned.

drunk (num, width &optkey low = #f, high = #f, mode = #f avoid = #f)
→ number

Returns a random value constrained to lie between num - width and num + width. Calling the function and passing the previous value of num implements a random walk (see also ranbrown). If low and high are provided they specify lower and upper bounds on the value returned. If the value exceeds either limit then the mode determines how the out-of-bounds value is handled. Possible values for mode are:

If avoid is a value between -width and width then random value chosen will never be equal to it.

odds (num &opt true = #t, false = #f)
→ value

Returns true value if a randomly chosen number between 0.0 and 1.0 is less than num else returns false value.

pick (arg...)
pick (list)
→ value

Returns a randomly selected arg as the value of the function. If just one argument is given it should be a list and a randomly selected value from the list is returned.

shuffle (args...)
shuffle (list)
→ list

Returns a version of args... or a list of the same with the elements randomly reordered.

shuffle! (list)
→ list

Like shuffle except that list is destructively modified by the random reordering.

tendency (x, low, high &opt gen = ran, args...)
→ void

Returns a random lying between the values of x in the low and high envelopes. If low or high are constant for any x they may be numbers rather than envelopes. Gen is an optional random function that will be applied to args... to generate the random number between low and high.

Nonuniform Distributions

ranpink ()
→ float

Returns a pinkish (1/f) value between -1 and 1.

ranbrown ()
→ float

Returns a brownish (1/f2) value between -1 and 1.

ranlow ()
→ float

Returns a value between 0 and 1 with lower values more likely.

ranhigh ()
→ float

Returns a value between 0 and 1 with higher values more likely.

ranmiddle ()
→ float

Returns a value between 0 and 1 with middle values more likely.

rangauss (&opt a = 1, b = 0)
→ float

Returns unbounded value from the normal distribution with standard deviation a (sigma) and mean b (mu).

ranexp (&opt lambda = 1)
→ float

Returns a value greater than 0 from the exponential distribution with stretching factor lambda.

ranbeta (&opt a = .5, b = .5)
→ float

Returns value between 0 and 1 from the beta distribution.

rangamma (&opt k = 1)
→ float

Returns value greater than 0 from the gamma distribution.

rancauchy ()
→ float

Returns an unbounded value from the Cauchy distribution.

ranpoisson (&opt lambda = 1)
→ float

Returns an unbounded integer value from the Poisson distribution with shape factor lambda.

Seeding

random-seed (&opt seed = #f)
→ list

Returns or sets the current seed used by the random number generator. If seed is specified it should be a single integer or an actual seed list that was returned by this function. Reseeding the generator with a saved seed list will regenerate the identical series of random numbers that the seed originally produced.

Patterns

Patterns are objects that generate data in different orderings. Data can be constants (numbers, symbols, lists, etc), sub-patterns, or thunks (functions of zero arguments). Use next to return the next value from a pattern; constant data are simply returned from the pattern, sub-patterns produce local orderings within the larger pattern and thunks are called to produce data.

PatternDescription
Cycle generates its elements in a continuous loop
Linegenerates its elements sequentially and sticks on last element
Heapgenerates random permutations of its elements
Palindromegenerates its elements forwards and backwards
Rotationgenerates systematic permutations of its elements
Weightinggenerates elements from a weighted random distribution
Markovgenerates nth order Markov chains of its elements
Graphgenerates elements from a directed graph
Repeaterrepeats data generated by a pattern
make-cycle (items &optkey for = #f, limit = #f)
→ pattern

Returns a pattern that generates its elements in a continual loop. Items is the list of data to generate and can include sub-patterns. For sets the number of internal reads that will make up the next period, or chunk, of data returned from the pattern. This value can be a number or pattern of numbers and defaults to the length of items. Limit sets an optional limit on the number of periods that the pattern will generate; once this limit has been reached the pattern returns an end of data marker instead of data.

make-line (items &optkey for = #f, limit = #f)
→ pattern

Returns a pattern that generates items sequentially and sticks on the last item.

make-heap (items &optkey for = #f, limit = #f)
→ pattern

Generates random permutations of its items (sampling without replacement).

make-palindrome (items &optkey for = #f, limit = #f, elide = #f)
→ pattern

Returns a pattern that generates items forwards and backwards. Elide determines what happens to the first and last items when the pattern reverses itself. If the value is false then these items are repeated. If the value is true then neither item is directly repeated. Otherwise the value can should be a two element list {bool bool} specifying the repeat value for the first and last item.

make-weighting (items &optkey for = #f, limit = #f)
→ pattern

Returns a weighting pattern that generates items from a weighted distribution. Each item can be an item, sub-pattern, or list:

{item [weight 1] [min 1] [max #f]}

where item is the thing to generate, weight is its weight in the distribution relative to the other items in the pattern, min is the minimum number of times that item must be directly selected before another item can be considered, and max is the maximum number of times that item can be directly selected before another item must be selected.

make-rotation (items &optkey for = #f, limit = #f, rotate = {0})
→ pattern

Returns a pattern that rotates its items according to rotate, which can be a list or a pattern of lists of the format:

{start [step 1] [width 1] [end]}

make-markov (items &optkey for = #f, limit = #f, past = {})
→ pattern

Returns a pattern that generates its items according to (nth order) transitions lists:

{past ... -> {next weight} ...}

Items appearing before -> in the rule are the past choice(s) that trigger the transition and items following -> make up the weighted distribution determining the transition's next outcome. If past it supplied it will be the initial past choices to match the transitions against, otherwise the first transition rule is used.

markov-analyze (list &optkey order = 1, mode = 1)
→ void, pattern or list

Analyzes a list of data for a specified Markov order (0-n) and computes a table capturing the Markov transitions rules that generates a version data for the supplied order. Returns results according to mode. If mode is 1 then the transition table is printed in an easy to read row and column format. If mode is 2 then a markov pattern containing the table is returned. If mode is 3 then the table is returned as a list of items suitable for passing to make-markov.

make-graph (items &optkey for = #f, limit = #f)
→ pattern

Returns a pattern that generates its items from a directed graph of nodes with transition patterns. Each node is a list:

{item to [id]}

where item is the item or pattern to generate, to is an id or pattern of ids identifying which node should follow the current node in the graph, and id is a unique identifier for the node which defaults to the node's position in items starting from 1.

make-repeater (pattern &optkey for = 1, repeat = #f, limit = #f)
→ pattern

Returns a specialized pattern that repeats periods of data generated from a specified pattern. For specifies how may elements of data will constitute one period of elements returned by the repeater. The total number of elements in the repeater's period will be equal to this value times the number of elements returned by the pattern. Alternately, repeat specifies how many times each period will be repeated before a new period is generated. The repeat initialization causes the for initialization to be ignored.

next (pattern, &opt chunk = #f)
→ element or list

Returns one or more elements from pattern according to chunk. If chunk is false then the next element from pattern is returned. If chunk is a number then that many elements are read from the pattern and returned in a list. Otherwise if chunk is true then the next period's worth of data is returned in a list.

eop? (pattern)
→ boolean

Returns true if pattern is at the end of its current period. Pattern can be a pattern or the value returned from the pattern by next.

eod? (pattern)
→ boolean

Returns true if pattern is at the end of its data. This condition can only happen if the pattern was created with a repeat value explicitly provided. Pattern can be a pattern or the value returned from the pattern by next.

promise (expr)
→ function

Turns expr into a function of zero arguments that, when called, returns the value of expr. Use promise to embed expressions in pattern data, when a promise is read by next the value it returns becomes the value of next.

Spectral Composition

The following functions create, access or modify spectrum objects. A spectrum holds a sequence of frequencies, an (optional) sequence of amplitudes and an (optional) time value. A spectrum can be sent to and from plotter displays for graphic editing and converted to other representations, for example to lists of notes and keys.

Creating Spectra

fm-spectrum (carrier, ratio, index)
→ spectrum

Returns a spectrum generated by Frequency Modulation given a carrier in hertz, a modulation ratio and an fm index.

rm-spectrum (freq1, freq2)
→ spectrum

Returns a spectrum generated by ring modulation, where freq1 and freq2 can be spectrum objects, lists of hertz values or single hertz values.

import-spear-frames (file)
→ list

Imports SPEAR frame data in file as a list of spectrum objects.

export-spear-frames (spectra, file)
→ list

Exports on or more spectrum objects in spectra to a file suitable for importing into SPEAR. Since spectra do not have partials.

spectrum-copy (spectrum)
→ spectrum

Returns a copy of spectrum.

Accessing Spectral Information

spectrum-size (spectrum)
→ integer

Returns the number of frequency and amplitude pairs in spectrum.

spectrum-time (spectrum)
→ float or #f

Returns the time of spectrum or false if there is none.

spectrum-maxfreq (spectrum)
→ float

Returns the highest frequency in spectrum.

spectrum-minfreq (spectrum)
→ float

Returns the lowest frequency in spectrum.

spectrum-maxamp (spectrum)
→ float

Returns the highest amplitude in spectrum or 0.0 if there are no amplitudes.

spectrum-minamp (spectrum)
→ float

Returns the lowest amplitude in spectrum or 0.0 if there are no amplitudes.

spectrum-freqs (spectrum)
→ list

Returns the frequency values of spectrum.

spectrum-amps (spectrum)
→ list

Returns the amplitude values of spectrum.

spectrum-pairs (spectrum)
→ list

Returns a list containing the frequencies and amplitudes of spectrum formatted as pairs: (f1 a1 ... fn an).

Modifying and Transforming Spectral Information

spectrum-keys (spectrum &optkey order = 1, thresh = 0.0, quant = #f, unique = #f, min = #f, max = #f)
→ list

Returns a list of the frequency components of spectrum converted to keys. Order specifies the scale order the keys will be returned in. Threshold specifies the minimum amplitude that frequencies must possess in order to be returned as keys. If threshold is a list (min max) then components whose amplitudes are greater than max are also suppressed. If quant is a number between 0.0 and 1.0 then key values are quantized to that fractional cent value, e.g. quant .5 returns key numbers quantized to the nearest quarter-tone and quant 1 returns key numbers rounded to the nearest integer. If unique is true then no duplicate key numbers will be returned. If a min key is specified then spectral values lower than that will be octave shifted upward until they equal or exceed it. If a max key is specified then spectral components above it will be octave shifted downward until they are equal to or lower than it.

spectrum-add! (spectrum, freq, amp)
→ spectrum

Adds a pair of freq and amp values into spectrum. If freq already exists in spectrum then amp is added to its current amplitude.

spectrum-flip! (spectrum)
→ spectrum

Inverts the frequencies in spectrum while preserving the minimum and maximum frequency boundaries.

spectrum-invert! (spectrum &optkey point = #f)
→ spectrum

Inverts frequencies in spectrum around point, or around the first partial if point is false.

spectrum-rescale! (spectrum &optkey min = #t, max = #t)
→ spectrum

Rescales frequencies in spectrum to lie between the new min and max values. If #t is specified it means that the current min or max value is preserved in the rescaling.

Cellular Automata

make-automata (cells, transfunc &optkey title = #f, colormap = {}, backgroundcolor = "white", cellsize = 50, cellbordersize = 1, rows = 1)
→ automata

Creates a cellular automata containing the specified initial integer cellstates and using the transition function transfunc to produce all subsequent states for cells in the automata. For 2D automata cellstates is a list of lists where each sublist defines a row of initial states.

The transition function transfunc is called automatically and passed two arguments, the automata and the index of the current cell, and must return the next state of the cell at index. Inside the transition function you can use the function cell-state to access the current state of any cell in the automata.

To associate a graphical window with an automata provide the optional window and colormap arguments, where window is the title (string) of the new window and colormap is a list of state and color pairs: (state1 color1 state2 color2 ... stateN colorN). Note that an error is signaled if window is already open, and that the color map must contain all possible states of the automata along with their colors in the window. Colors are symbols or strings, the list of all colors is available in the globals *colors* variable. The backgroundcolor argument is a string or symbol naming the background color for the window. The cellsize argument is the size in pixels of each cell in the state window display. The cellbordersize argument is the size in pixels of space between each cell in the state window. The rows argument applies to 1-dimensional automata only, and specifies the number of successive generations to display in the window, where each generation is shown as a cell "row".

Once an automata has been created use state to read successive states from it.

See the Help>Examples>Cellular Automata menu for examples of using cellular automata.

state (automata &optkey all = #f)
→ integer or list

Return the next integer state from automata or a list of all the states in the current generation if all is true.

cell-state (automata, index &optkey neighbor = 0)
→ integer

Returns the current integer state of the automata cell at index. If neighboring cells to index must be accessed provide a positive or negative neighbor increment to index . Cell addresses are always accessed mod the size of the cell array so you do not have to perform bounds checking when you specify a neighbor increment. For 2D automata each index and neighbor is a two dimensional xy point. You specify 2D points and 2D increments using the xy function, i.e. (cell-state index (xy -1 -1)) would access the value of the north-west neighbor of the cell at index in a 2D automata.

xy (x, y)
→ integer

Encodes x and y values -+2768 as a single point (integer) value.

Environment

print (expr {, expr}*)
→ void

Prints one or more expressions to the Console window.

now ()
→ float

Returns a current time stamp. Note that now values are not used by the scheduler or in processes, which have their own notion of elapsed time.

mouse-button (&optkey upval = #f, downval = #t)
→ object

Returns downval if the mouse button is currently depressed, otherwise returns upval.

mouse-x (&optkey minval = 0.0, maxval = 1.0, warp = 1.0)
→ float

Returns the screen mouse x position scaled minval to maxval, where minval is the value returned when the mouse is full-left on the screen and maxval is the value at full-right. If warp is 1 the interpolation is linear, otherwise values greater than 1 produce increasing exponential spread towards the right and values less than 1 produce decreasing spread.

mouse-y (&optkey minval = 0.0, maxval = 1.0, warp = 1.0)
→ float

Returns the screen mouse y position scaled minval to maxval, where minval is the value returned when the mouse at the top of the screen and maxval is the value at the bottom. If warp is 1 the interpolation is linear, otherwise values greater than 1 produce increasing exponential spread towards the bottom and values less than 1 produce decreasing spread.

shell (command)
→ void

Calls operating system's shell interpreter to execute user's command.

load (file)
→ void

Loads a Lisp or SAL file. If file has no directory component and the current working directory does not contain file then the embedded distribution will be searched for the file to load.

chdir (directory)
→ void

Changes the current working directory to directory (string).

pwd ()
→ string

Returns the full pathname string of the current working directory.

directory (spec &opt recurse = #f)
→ list

Returns a list of absolute filenames matching wildcard spec. If recurse is true then subdirectories are recursively searched.

file-version (filename &optkey version = #t, nooverwrite = #f)
→ string

Returns a variant of filename with a version number appended to its name. If vers is #t then successive version numbers are appended (starting with 1), if vers is a number then that number is used as the version number, else if vers is false then no version number is appended to the name. If nooverwrite is true the versioned file name is guaranteed to be for a new file, i.e. if that name is used for output no existing file will be overwritten.

Iteration

An (essentially) complete implementation of the Common Lisp loop macro is provided in Scheme and SAL.

loop [with-decl] {stepping}* {stopping}* {action}+ [finally] end
(loop {clause}*)
→ loop dependent value

Defines an iteration. Optional local variables can be declared using the with statement followed by zero or more stepping statements, zero or more stopping statements, one or more action statements, an optional finally statement and terminated with the required end tag.

stepping statements
repeat expr sets the iteration limit to expr
for var = expr [then expr2] sets var to the value of expr on each iteration. If then is specified expr is the initial value and expr2 are the subsequent values
for var in expr increments var over elements the list expr
for var [from expr] [to | below expr] [by expr] increments var from an on optional starting value to an ending value by an optional amount
stopping statements
while expr iteration continues while expr is true
until expr iteration stops when expr is true
conditional statements
when expr action executed if expr is true
until expr action executed if expr is false
action statements
do expr... scheme expressions
any SAL statement SAL statements execute but do not return values
finally statements
finally statement executes statement as soon as iteration has completed

Audio

Depending on the which particular Audio Target you are working with, audio data can be generated in four different ways:

  1. sending data to an open audio port in real time.
  2. sending data to an open audio file (non-real time).
  3. sprouting processes to send audio to an open audio port in real time.
  4. sprouting processes to send audio to an open audio file (non-real time).

Here are small examples of each method:

; example 1: sending data to the open Midi Port in real time

loop for i below 10
  send("mp:midi", i * .1, key: between(60,90))
end

; example 2: sending data to a Midi File (non-real time)

file "test.mid" ()
  loop for i below 10
    send("mp:midi", i * .1, key: between(60,90))
  end
end

; example 3: sprouting process to send data to the open Midi Port in real time

process simp(num, low, high)
  repeat num
  send("mp:midi", key: between(60,90))
  wait .1
end

sprout(simp(10, 60, 90)

; example 4: sprouting process to send data to a Midi File (non-real time)

sprout(simp(10,60, 90), "test.mid")

Which method you use depends on what you want to accomplish and which methods the Audio Port in question supports. Here is a table that shows the capabilities of each Audio Target:

audio target real time port? score file? (non-real time)
Midi yes yes
Fomus no yes
CLM no yes
Csound no yes
OSC yes no

Sending Audio Data

Every audio target implements a set of methods that you can route data to. This routing is accomplished using the send macro or by calling the underlying method functions directly. Using send has two advantages: (1) it clearly identifies code that sends data to audio ports (2) it can check arguments at read time so keyword argument errors are caught before any code actually executes.

send ("target:method" ...)
→ void

The first argument to send is its message, a literal string or symbol in the format target:method that identifies a specific audio resource and a method to receive the data you pass to it. Each message is also implemented by a function with the same name that can be called directly to achieve the same effect. The difference between using a send message and calling the underlying message function is (1) for some messages the send macro can perform argument testing at eval time rather than run time and (2) using send makes it very clear that the code is sending audio information.

For example, the following two calls are equivalent:

send("mp:midi", key: between(60, 90))
mp:midi(key: between(60, 90))

Midi Out

Before sending anything to the Midi Out port select use the Audio>Midi Out> menu to select an output device. You can test that the connection actually works by using the Ports>Midi Out>Test to send a random burst of messages to the output device.

mp:midi (&optkey time = 0, dur = .5, key = 60, amp = .5, chan = 0)
→ void

Send note data to midi port. Note: if a process using mp:midi is sprouted in the context of a Fomus score then mp:midi will automatically route its note date to the Fomus score, with the midi channel number used as the Fomus part id.

mp:on (&optkey time = 0, key = 60, amp = .5, chan = 0)
→ void

Send note on data to midi port. Supports floating point keynums and tunings

mp:off (&optkey time = 0, key = 60, vel = 127, chan = 0)
→ void

Sends note off data to midi port.

mp:prog (&optkey time = 0, val = 0, chan = 0)
→ void

Sends program change value to midi port.

mp:ctrl (&optkey time = 0, num = 0, val = 0, chan = 0)
→ void

Sends control change data to midi port.

mp:touch (&optkey time = 0, val = 0, chan = 0)
→ void

Sends after touch value to midi port.

mp:press (&optkey time = 0, val = 0, chan = 0)
→ void

Sends channel pressure value to midi port.

mp:bend (&optkey time = 0, val = 8192, chan = 0)
→ void

Sends pitch bend value 0-16383 to midi port.

mp:instruments (prog ...)
→ void

Sends up to sixteen program changes out the Midi port and updates the port's instrument table. The position of each value specifies the channel it is sent to, i.e. the first program change is sent to channel 0 and so on. To skip a particular channel provide #f as its program change value, otherwise the value should be either a program change (integer 0-127) or a GM instrument name (string), in which case the first instrument that matches or contains name as a substring will be selected.

mp:tuning (divisions)
→ void

Divides midi frequency space into divisions steps per semitone and automatically quantizes floating point key numbers in midi data to the nearest tuning step as they are sent out the port. A division of 1 implements standard semitonal tuning, 2 implements quarter-tone tuning, and so on. The maximum divisions of 16 per semitone provides a tuning step size of 6.25 cents, very close to the minimum perceivable frequency change (see table below.) For example, in quartertone tuning there are a total of 8 midi channels available (channel numbers 0 to 7, each with their own instrument assignment) and fractional keynum values k.0 < k.5 (e.g. 60.0 < 60.5) are quantized to the semitone and k.5 < K.0 (e.g. 60.5 < 61.0) are tuned to the quartertone. In some configurations it is possible to send both standard tuning in parallel with microtonal tuning by using any remaining "standard" channels numbers for semitonal output. Channel tuning is very efficient because it claims certain channels and "pretunes" them for the appropirate divisions.

divisions tuning step microtuned
channel #
standard
channel #
1 semi tone 0-15
2 quarter tone (50 cents) 0-7
3 third tone (33 cents) 0-4 15
4 fourth tone (25 cents) 0-3
5 fifth tone (20 cents) 0-2 15
6 sixth tone (16.6 cents) 0-1 12-15
7 seventh tone (14.28 cents) 0-1 14-15
8 eighth tone (12.5 cents) 0-1
9 ninth tone (11.1 cents) 0 9-15
10 tenth tone (10 cents) 0 10-15
11 eleventh tone (9.09 cents) 0 11-15
12 twelfth tone (8.33 cents) 0 12-15
13 thirteeth tone (7.69 cents) 0 13-15
14 fourteenth tone (7.14 cents) 0 14-15
15 fifteenth tone (6.66 cents) 0 15
16 sixteenth tone (6.25 cents) 0

Midi In

mp:receiver (function)
mp:receiver (opcode, function)
→ void

Causes function to receive incoming MIDI messages. To clear an existing receiver specify #f as the function. Otherwise function should be a procedure of one argument; this procedure will be called asynchronously and passed a list of message values (channel data1 data2 ...) for each message that arrives at the MIDI input port.

To associate the receiver with a specific type of message precede function by the MIDI status byte opcode 8-15 that it should handle. MIDI opcodes 8-15 are also available as constants: mm:off, mm:on, mm:touch, mm:ctrl, mm:prog, mm:press, mm:bend. If no opcode is given then function becomes the "default" receiver and is called on any message that is not otherwise handled by an opcode receiver. Message data for a default receiver will include the opcode of the message received: (opcode channel data1 data2 ...). Note that it possible to have several receivers, including a default receiver, in effect at the same time, each handling a different type of message.

To clear all current receivers call mp:receiver with no arguments.

mp:receiver? (&opt opcode = #f)
→ boolean or list

Returns true if a receiver for opcode is currently in effect otherwise false. If called without any opcode then a list containing the opcodes of all current receivers is returned. The default receiver, if any, is indicated by an opcode of 0.

mp:inchans (chan ...)
→ void

Enables MIDI input only on the specified channels. Channel values are integers between 0 and 15. Specify a single #t value to enable all channels and #f to disable all channels.

mp:inops (opcode ...)
→ void

Enables MIDI input only for the specified MIDI opcodes. Opcodes are integers between #x8 and #xE (mm:off mm:on mm:touch mm:ctrl mm:prog mm:press mm:bend). Specify a single #t to enable all opcode types and #f to disable all opcodes.

midifile-header (file)
→ list

Returns a list of MIDI header information from the specified file. The format of this list is (tracks format tempo timesig maxtime) where tracks is the number of tracks in the file, format is the time format of the file (if positive its the number of ticks per quarter else its SMPTE), tempo is the initial tempo or #f , and maxtime the maximum time stamp found in any track.

midifile-import (file, track, values)
→ list

Returns a list of MIDI values from the specified track (zero based) in file. Messages that match (contain) the specified values are processed, messages that do not match do not appear in the returned list. Values can be a single value, a single list of values or a list of lists of values. Each individual value can be a string, symbol, or keyword as defined below. To return more that one value from messages specify a single list of values. In this case lists of data are returned, where each data list is a match for the specfied values. If a list of lists of values is specified then any message that matches any of those value lists are collected as described above.

Value Matching Messages Description
"op" all the opcode of the message. Channel message opcodes are: note = 9, aftertouch = 10, controller = 11, program = 12, pressure = 13, pitchbend = 14. Meta message opcodes are: seqnum = 0, text = 1, copyright = 2, trackname = 3, instname = 4, lyrics = 5, marker = 6, cue = 7, chanprefix = 32, tempo = 81, timesignature = 88, keysignature = 89.
"time" all the start time of the message in seconds
"delta" all the time increment from the previous message
"chan" channel messages the channel of the message 0-15
"rhythm" notes the time increment from the previous note
"dur" notes the duration of the note
"key" notes the key number of the note
"amp" notes the amplitude of the note 0.0-1.0
"vel" notes the key velocity the note 0-127
"touch" after touches the after touch value 0-127
"ctrl1" control changes the controller number 0-127
"ctrl2" control changes the controller value 0-127
"prog" program changes the program value 0-127
"press" channel pressures the pressure value 0-16383
"bend" pitch bends the pitch bend value 0-16383
"seqnum" seqnum meta events the sequence number
"text" text meta events (opcodes 1-7) the text string of the message
"chanpre" channel meta events the channel prefix number
"tempo" tempo meta events the tempo as quarters per second
"timesig" time signatures a time signature list (numerator denominator)
"keysig" key signatures a key signature -7 to 7

Example

;; find out what kind of messages are in track 0
midifile-import("zincline-1.mid", 0, "op")

;; import the start times, key numbers and durations of all notes in track 1
midifile-import("zincline-1.mid", 1, {"time" "key" "dur"})

;; import all tempo changes and program changes from track 0
midifile-import("zincline-1.mid", 0, {{"op" "tempo"} {"op" "prog" "chan"}})

CLM/SndLib

Use Audio>SndLib>Instruments... to load instruments before working with them. To send data to a SndLib instrument specify the instrument name as a send message or call the instrument (function) directly. For example, the following calls are equivalent:

send("wave", 0, 1, 440, .1)
wave(0, 1, 440, .1)

SndLib Audio File Options

Any CLM with-sound option can be passed as an argument to sprout when you generate an audio file. The most common options are listed here and are also available in the Audio>SndLib> menu.

srate:
The sampling rate to use.
channels:
The number of audio channels to write.
play:
Play the audio file after writing it.

Fomus

Fomus generates musical scores for LilyPond, Sibelius and Finale from symbolic score information input by the user interactively or by running musical processes. Use the Audio>Fomus> menu to configure your Fomus environment and manage its score output. For more information see the examples in Help>Examples>Fomus Examples and the tutorial in Help>Tutorials>Fomus. To send data to Fomus use the send messages listed below or call the underlying message functions directly. For example, the following calls are equivalent:

send("fms:note", 0, 1, 60)
fms:note(0, 1, 60)

Fomus Events

fms:note (dur, pitch &optkey time = 0, part, voice = 1, dyn = 0, grace, marks = {}, sets = {})
→ void

Send a note event to the currently selected score at time. Parameters dur and pitch are required. The optional parameters marks and sets are lists of marks and settings.

fms:rest (dur &optkey time = 0, part, voice = 1, grace, marks = {}, sets = {})
→ void

Send a rest event to the currently selected score at time.

fms:mark (&optkey time = 0, dur = 0, part , voice = 1, grace , marks = {}, sets = {})
→ void

Send a mark event to the currently selected score at time.

fms:meas (&optkey time = 0, dur = 0, sets = {})
→ void

Send a measure to the currently selected to score at time.

Fomus Objects

fms:part (&optkey sets = {})
→ void

Create a new part to use in the currently selected score. A part with id default exists (with instrument default) if no other parts are defined.

fms:inst (&optkey sets = {})
→ void

Create a new instrument to use in the currently selected score. An instrument with id default and a grand staff exists if no other instruments are defined.

fms:percinst (&optkey sets = {})
→ void

Create a new percussion instrument to use in the currently selected score.

fms:metapart (&optkey sets = {})
→ void

Create a new metapart to use in the currently selected score.

fms:setting (set, value &optkey append = #f)
→ void

Change the value of one or more global settings in the currently selected score.

fms:measdef (&optkey sets = {})
→ void

Create a new measure definition to use in the currently selected score. Measdefs are more useful in .fms files than in processes.

Fomus Commands

fms:new-score (file)
→ void

Create a brand new empty score with output file.

fms:load-score (file)
→ void

Load a .fms file into a new score.

fms:select-score (file)
→ void

Select the first score with output file. A new empty score is created if one with that name does not already exist.

fms:save-score (file)
→ void

Save the score to a .fms file, Fomus's native file format. The file can be edited and/or reloaded with the load-score command.

fms:merge-score (fromfile &optkey time = 0)
→ void

Merge the contents of the score identified by fromfile into the current score. Contents include note events, measures and possibly parts if they don't already exist. The optional time argument shifts the events in time by the specified amount.

fms:run ()
→ void

Run Fomus on the currently selected score. If an output file has not been specified, this produces an error.

fms:clear-score ()
→ void

Clears note events and measures (but not part or instrument definitions) from the currently selected score.

fms:delete-score ()
→ void

Delete the currently selected Fomus score.

OSC (Open Sound Control)

The OSC port provides input and output communication with other processes via the Open Sound Control protocol. To send and receive OSC messages first open an OSC connection via Audio>OSC>Open Connection... or by sending the "osc:open" message to the port from code. For example, the following calls are equivalent:

send("osc:open", 7779, 7770)
osc:open(7779, 7770)

See the Help>Examples>OSC menu for examples of using OSC.

osc:open (serverport, targetport)
→ void

Opens an OSC connection with serverport as the CM application's input port and targetport as its output port. If the target is not on the local machine then targetport can be a string "host:port", where host is the host's network name or IP address and port is the port to route data to on that machine.

osc:close ()
→ void

Closes an open OSC connection.

osc:message (path, data ...)
osc:message (list)
→ void

Sends an OSC message consisting of an OSC path (string) followed by zero or more optionally tagged data values. Message values can be specified as separate arguments or in a single list argument to the function. Scheme values integer, float, string, symbol, character, boolean true, boolean false all map directly to their OSC equivalents and do not need tagging. To distinguish between different OSC types for a particular scheme value (e.g. 32 bit vs 64 bit integers), precede the Scheme value by the appropriate OSC data tag as shown in the table below. Lists holding OSC blobs or OSC four-byte midi messages must be tagged as such using :b or :m, respectively. The special OSC tags :T :F :N :I are themselves data, i.e. they not take Scheme values.

OSC Tag Osc Type
:i 32 bit integer
:h 64 bit integer
:f 32 bit float
:d 64 bit float (double)
:c character
:s string
:S symbol
:b blob
:m midi
:T OSC true
:F OSC false
:N OSC nil
:I OSC infinitude
osc:bundle (time, message ...)
osc:bundle (time, list)
→ void

Sends an OSC bundle consisting of a time tag (number) followed by one or more OSC messages . To send an "immediate" bundle, specify 0 as the time tag. Otherwise the relative time value will be converted to an OSC time value based on January 1 1900. Messages can be specified as separate arguments or in a single list argument to the function.

osc:receiver (function)
osc:receiver (path, function)
→ void

Causes function to receive incoming OSC messages. To clear an existing receiver specify #f as the function. Otherwise function should be a procedure of one argument; this procedure will be called asynchronously and passed a list of message values (data1 data2 ...) for each message that arrives at the OSC input port. To associate the receiver with a specific type of message precede function by the OSC path (string) that it should handle. If no path is given then function becomes the "default" receiver and is called on any message that is not otherwise handled by a specific path receiver. Message data for a default receiver will include the path of the message received: (path data1 data2 ...). Note that it possible to have several receivers, including a default receiver, in effect at the same time, each handling a different type of message.

To clear all current receivers call osc:receiver with no arguments.

osc:receiver? (&opt path)
→ boolean or list

Returns true if a receiver for path is currently in effect otherwise false. If called without any path then a list containing the paths of all current receivers is returned. The default receiver, if any, is indicated by a path of "/".

Csound

Csound score files can be written and played in all versions of CM. Use the Audio>Csound>Settings... dialog to configure the Csound environment, or pass the options directly to the scorefile when you generate it with sprout.

To send data to Csound use the messages listed below or call the underlying message functions directly. For example, the following calls are equivalent:

send("cs:i", 1, 0, 1, 440, 1000)
cs:i(1, 0, 1, 440, 1000)
cs:i (ins, start, dur ...)
→ void

Sends instrument data to Csound. The first value should be the instrument's number followed by the rest of its pfield values.

cs:f (num ...)
→ void

Sends function table data to Csound. Similar to "cs:i" in all other respects.

cs:event (list)
→ void

Sends an event list to Csound. The first element in the list must be the event's type, either i or f. Similar to "cs:i" and "cs:f" in all other respects.

Csound Scorefile Options

The following scorefile options are available in the Audio>Csound> menu and can be passed to Csound scores when you generate them using sprout or file.

play:
Send the scorefile to Csound after it is written.
orchestra:
Use this file as the Csound .orc file when the scorefile is played.
header:
Include this string as the header of the scorefile.
write:
Specify #f to put data in an internal score without writing it as a file. This lets you build a score incrementally, over consecutive sprouts, and to export score data to an editor window or the clipboard.

The Scheduler

The main entry point into the scheduler is called sprout. Sprout schedules processes to run in real time, or in faster-than real time if a file (string) is specified as the third argument to the function. When the scheduler runs faster-than real time then the time values inside processes are still treated as if they were seconds but the scheduling clock is running as fast as it can, i.e. is does not actually wait that amount of (real) time before calling the next process in the queue.

sprout (process &opt ahead = 0, id = #f)
sprout (process, file ...)
sprout (process, ahead, file ...)
→ void

Adds process to the scheduler to start executing ahead seconds from now. Both process and ahead can be lists, in which case processes and start time are paired in a left-to-right order.

If a file is not specified then the process(es) will run in real time. In this case id can be used to identify the process(es) in the scheduling queue; tagged processes can then be selectively removed from the scheduler using stop.

If a file is specified then the scheduler will run in faster-than real time and all output will be sent to the open file. CM currently supports the following file types:

Following file comes zero or more keyword options pairs suitable for the audio target selected by file:

sprout-hook (&opt hook = #f)
→ #f or procedure

Gets or sets the current hook function associated with sprouting. If called without any argument the current hook is return or #f if no hook is set. Otherwise, if hook is a function, it will be called each time sprout is involked and passed the current output file or #f if no file was specified to sprout. To clear the current sprout hook specify #f as the hook.

stop (id...)
→ void

Stops processes currently running in the scheduling queue. If no ids are given all the processes are stopped and any pending events in the midi output queue are also flushed. Otherwise only processes with the specified ids are stopped. Note that multiple processes can share a common id, in which cases all the processes with that id are stopped.

Stops all processes that are currently running and flushes any pending events in the output queue.

pause ()
→ void

Suspends the process scheduler.

cont ()
→ void

Resumes the scheduler if it is currently paused.

Processes

Processes are iterative functions you sprout into the scheduler to execute. Processes can run in real time or in faster-than real time, depending on how they are sprouted.

In SAL you create a process using the process statement. In Scheme you create a process using the process macro. The following two examples are equivalent process definitions:

SAL process definition

process simp (reps, rate, low, hi)
  repeat reps
      send("mp:midi", key: between(low, hi))
      wait rate
  end

sprout( simp(20, .5, 60, 80))

Scheme process definition

(define (simp reps rate low hi)
  (process repeat reps
           do
           (send "mp:midi" :key (between low hi))
           (wait rate)))

(sprout (simp 20 .5 60 80))
process name ({parameters}*) {iteration}+ end
→ function

Returns an iterative function to execute in the scheduler in real time or faster-than real time. Parameters consists of zero or more required parameters, optionally followed by &optkey and any optkey arguments. Following the parameter list comes a series of iteration clauses as documented under loop and with the following two additional features:

wait time
→ void

Causes the process to wait time seconds before the next iteration. To stop the process provide negative time value. This function only exists within the lexical scope of a process definition.

Expressions defined within the body of a process have access to elapsed, a (load) function that returns the time of the current process iteration:

elapsed (&opt scoretime? = #f)
→ seconds

Returns the amount of time since the process was first sprouted, or the absolute score time (the time since the initial sprout) if the optional scoretime argument is #t This function only exists within the lexical scope of a process definition.

Plotting

Plot windows support the graphic display, editing and audio playback of multi-dimensional data sets. Commands to create new plots, open existing plots (.xml) or plot Midi files are in the Console's File menu. See Help>Examples>Plotting for various examples of plot coding.

For any plotting window:

The functions defined below provided an API for working with plots in Scheme or SAL buffers.

plot ({setting}* {pointlist {setting}*}*)
→ void

Creates a new plot given zero or more global plot settings followed by optional layers of plotting data with layer-specific settings. Each pointlist is a list in one of the following formats:

( (v1 v2 ... vn) ...)
Each sublist defines a point record containing a value for every field of plotted data.
(x1 y1 x2 y2 ... xn yn)
A flat list of x y point data.

A setting is a plotting keyword followed by its value. In general, setting values can be specified as symbols, keywords or strings. Settings that appear before the first point list are treated as global settings, ie they apply to the window and/or to all the point lists. Settings specified after a point list apply only to that layer of points.

plot supports following settings:

title: string
Specifies the window title or the title of the point layer if it appears after a point list.
xaxis: type | (type from to by ticks)
Specifies the horizontal axis type and (optionally) its characteristics.
Available axis types and their default characteristics
type from tobyticks
unit 0 1 .25 5
percent 0 100 25 5
keynum 0 127 12 1
midi 0 127 16 2
seconds 0 60 1 4
ordinal 0 length 1 1
circle -1 1 .25 4
See the fields: setting for complete control over record fields and axes.
yaxis: type | (type from to by ticks)
Specifies the vertical axis type and (optionally) its characteristics. See the fields: setting for complete control over record fields and axes.
layer: points
A list of points defining a layer in the plot
color: name | "rgb"
The color for drawing the specified plot list.
style: name
The style for drawing point records.
  • envelope (points connected by lines)
  • line (lines only)
  • point (points only)
  • hbox (horizontal boxes, requires 3 fields of data)
  • impulse (vertical lines)
  • histogram (vertical lines with points)
fields: ((field1 axisinfo...)(field2 axisinfo...) ...)
Provides full control over the interpretation of the data fields in point records. The left to right order of fields corresponds to the left-to-right values in the point records. Name is the name of the field in the record and axisinfo is its axis information as described in the xaxis and yaxis settings above. To force field to share the axis of a (leftward) field specify the name of that field as the axisinfo.
plot-data (title &opt all = #t)
→ list

Returns the point data from the plot window whose title is specified. If all is false then only the points in the topmost (focus) layer will be returned otherwise all layer data will be returned.

plot-hook (title, function, userdata...)
→ list

Associates function with Control-Option-Mouseclick inside the plot window named title. When a Control-Option-Mouseclick occurs, function will be be called automatically and passed the X and Y values of the mouse click along with any additional values specified in userdata. The function (hook) should return a list of fully specified point records to add to the window, or an empty list if no points should be added.

SAL (version 2)

Sal is a minimalist language for algorithmic music composition. It provides infix expressions and a handful of control statements and reserved symbols:

begin
below
by
else
end
file
finally
for
from
function
if
in
loop
process
repeat
then
to
unless
until
variable
wait
when
while
with

Expressions

Numbers

SAL number representation includes integers, floats and ratios (e.g 1/2, 1/3, 11/17).

Arithmetic and Logical Expressions

Arithmetic and logical expressions are infix. Operators must be delimited from their operands using spaces and/or parentheses (in other words, 2 + 4 is addition and 2+4 is nothing.) Standard operator precedence rules apply if no parentheses are provided. The following math and logic operators are defined:

operatormeaning
+ addition
- subtraction
* multiplication
/ division
% modulus (remainder after division)
^ exponentiation
= equal
!= not equal
> greater than
< less than
>= greater than or equal
<= less than or equal
~= general (looks like) equality
& logical and
| logical or
! logical not

Booleans

#t is boolean true and #f is boolean false.

Conditional Values

#? (test, true [, false])

Strings

A string of uninterpreted characters enclosed within "", e.g. "Hi ho!".

Symbols

Alphanumeric names for variables and functions, e.g. foo and 23-skidoo

Scheme Keywords (constants)

:symbol

Constant Lists

Sequences of data enclosed within {}, e.g. {1 2 3}. May contain numbers, booleans, symbols, strings, and other lists. Quasi-quotation in constant lists is supported. Use #$ to unquote and #^ to unquote-splice.

List element notation

A variable followed by an index inside [], e.g. foo[1]

Function call notation

A function name followed by zero or more comma-delimited arguments enclosed within ().

Assignment

set variable op value [, variable op value ...]
→ void

Assigns each variable to value according to the assignment operator op:

operatormeaning
= set variable to value
+= increment variable by value
*= scale variable by value
&= concatenate value onto the end of the list in variable
^= splice the list value onto the end of the list in variable
@= concatenate value onto the front of the list in variable
<= minimize variable with respect to value
>= maximize variable with respect to value

Conditionals

if (test) ... [else ...] end
→ value of last expression

If test is true execute statements otherwise execute optional else statements. See also: conditional value. Note that the parentheses around the test expression are required.

Sequencing

begin [with ...] ... end
→ value of last expression

Sequences one or more SAL statements as a single statement. The optional with statement is a local variable declaration that can appear at the start of block statements like begin, loop, function and process:

with var [= expr] {, var [= expr]}*
→ void

which will Define one or more local variables (within the surrounding block), optionally setting inital values to expr (or to false if expr is not provided).

Definitions

variable var [= expr] {, var [= expr]}*
→ value of last expression

Defines one or more variables as "global" within the current context.

function name ({parameters}*) [with ...] {statement}+ end
→ void

A function definition consists of the name of the function, a parameter list containing zero or more required parameters optionally followed by &optkey and any optkey argument. Following the parameter list comes the statements to be executed when the function is called. The first of these statements can be a with declaration. The last statement in the body of the function becomes the value of the function call.

Files

file "file.ext" ({keyword value}*) [with ...] {statement}+ end
→ void

A score file definition. The string "file.ext" is the pathname of the file to create, where file can include a directory component and ext must be one of the supported score file types. Following the name of the file comes zero or more keyword options as suitable for the type of file being created. Inside the body of file you can write any expressions that send data to the currently open score file.

Appendix

A. Documentation Meta-syntax

B. Function Arguments

Several different types of function arguments are supported:

Required arguments

Required arguments must be specified, that is, each required argument must have an explicit value provided in the function call.

Optional arguments

Optional arguments may be specified or not. If not, they receive a default value, which is #f (false) if not otherwise indicated.

Optional/keyword arguments

Opt/key arguments are optional arguments that can be specified positionally or by preceding the argument value by its keyword name. In Scheme keyword argument names start with a colon and in SAL they end with a colon. For example, if a function foo has two opt/key arguments a and b then in SAL the function could be called in any of the following ways:

foo() foo(4) foo(2,3) foo(a: 3) foo(b: 99) foo(a: 2, b: 4) foo(b: 99, a: 2)

and in Scheme:

(foo) (foo 4) (foo 2 3) (foo :a 3) (foo :b 99) (foo :a 2 :b 4) (foo :b 99 :a 2)

Variable arguments

A variable argument takes zero or more values. A variable argument is shown in the documentation as ... which means 'the rest of the arguments'.

C. Table of SAL, Scheme and Common Lisp

A. Translation table for SAL, Scheme and Common Lisp entities.
SAL Scheme 1 Common Lisp 2
Booleans #f #f nil
#t #t t
Keywords foobar: #:foobar or :foobar :foobar
Lists {} '() () or nil
{a b {1 2 3} c} '(a b (1 2 3) e) '(a b (1 2 3) e)
{a #$ ran(100) c} `(a ,(random 100) c} `(a ,(random 100) c)
{a #^ list(ran(100), ran(100)) c} `(a ,@ (list (random 100) (random 100)) c} `(a ,@(list (random 100) (random 100)) c)
Arithmetic 1 + 2 (+ 1 2) (+ 1 2)
- 1 (- 1) (- 1)
1 + 2 + 3 * 4 (+ 1 2 (* 3 4)) (+ 1 2 (* 3 4))
3 ^ 4 (expt 3 4) (expt 3 4)
3 % 4 (modulo 3 4) (mod 3 4)
a = b (= a b) (= a b)
a / b != b * c (not (= (/ a b) (* b c))) (/= (/ a b) (* b c))
a ~= b (equal a b) (equal a b)
Logic a | b (or a b) (or a b)
! a | b (or (not a) b) (or (not a) b)
a & b | ! c (or (and a b) (not c)) (or (and a b) (not c))
Function calls list() (list) (list)
list(10) (list 10) (list 10)
list(1, 2 + 3, 4) (list 1 (+ 2 3) 4) (list 1 (+ 2 3) 4)
list(1, 2, random(10)) (list 1 2 (random 10)) (list 1 2 (random 10))
Conditionals if (a = b)
  list(1,2)
else
  list(3,4)
end
(if (= a b)
  (list 1 2)
  (list 3 4))
(if (= a b)
  (list 1 2)
  (list 3 4))
#?(a = b, -99, 2) (if (= a b) -99 2) (if (= a b) -99 2)
Global variables variable a (define a #f) (defparameter a nil)
Function definitions function foo (a)
  a + ran(10)
end
(define (foo a)
  (+ a (random 10)))
(defun foo (a)
  (+ a (random 10)))
Code blocks begin
  ...
end
(begin
  ...
  )
(progn
  ...
  )
begin
  with a = 1, b = a + 2
  ...
end
(let* ((a 1)
       (b (+ a 2))
  ...
  )
(let* ((a 1)
       (b (+ a 2))
  ...
  )
Assignment set a = 123 (set! a 123) (setf a 123)
set a = 123, b = a (set! a 123)
(set! b a)
(setf a 123 b a)
set a += 123 (set! a (+ a 123)) (incf a 123)
set a *= 123 (set! a (* a 123)) (setf a (* a 123))
set a &= 123 (set! a (append a (list 123))) (setf a (append a (list 123)))
set a @= 123 (set! a (cons 123 a)) (push 123 a)
set a <= 123 (set! a (min 123 a)) (setf a (min 123 a))
set a >= 123 (set! a (max 123 a)) (setf a (max 123 a))
Iteration loop ... end (loop ...) (loop ... )
1. Reference Scheme implementation: Chicken Scheme
2. Reference Common Lisp: Steel Bank Common Lisp (SBCL)

Index

b

between, butlast

c

cell-state, cents->ratio, chdir, concat, cont, cs:event, cs:f, cs:i

d

decimals, deltas, directory, discrete, divide, drunk

e

elapsed, eod?, eop?, export-spear-frames

f

file-version, first, fit, float, fm-spectrum, fms:clear-score, fms:delete-score, fms:inst, fms:load-score, fms:mark, fms:meas, fms:measdef, fms:merge-score, fms:metapart, fms:new-score, fms:note, fms:part, fms:percinst, fms:rest, fms:run, fms:save-score, fms:select-score, fms:setting

g

greater=?, greater?

h

harmonics, hz

i

import-spear-frames, in-tempo, int, interp, invert

k

key

l

last, less=?, less?, list-set!, load, log10, log2

m

make-automata, make-cycle, make-graph, make-heap, make-list, make-markov, make-palindrome, make-repeater, make-rotation, make-spectrum, make-weighting, markov-analyze, midifile-header, midifile-import, minus, most-negative-fixnum, most-positive-fixnum, mouse-button, mouse-x, mouse-y, mp:bend, mp:ctrl, mp:inchans, mp:inops, mp:instruments, mp:midi, mp:off, mp:on, mp:press, mp:prog, mp:receiver, mp:receiver?, mp:touch

n

next, note, now, nth

o

odds, osc:bundle, osc:close, osc:message, osc:open, osc:receiver, osc:receiver?

p

pause, pc, pi, pick, plot, plot-data, plot-hook, plus, print, promise, pwd

q

quantize

r

ran, ranbeta, ranbrown, rancauchy, random-seed, ranexp, rangamma, rangauss, ranhigh, ranlow, ranmiddle, ranpink, ranpoisson, ratio->cents, ratio->steps, rescale, rest, rest?, retrograde, rhythm, rm-spectrum

s

scale, scale-order, segs, send, shell, shuffle, shuffle!, sort, sort!, spectrum-add!, spectrum-amps, spectrum-copy, spectrum-flip!, spectrum-freqs, spectrum-invert!, spectrum-keys, spectrum-maxamp, spectrum-maxfreq, spectrum-minamp, spectrum-minfreq, spectrum-pairs, spectrum-rescale!, spectrum-size, spectrum-time, sprout, sprout-hook, state, stop

t

tail, tendency, times, transpose

u

unique

v

vary

x

xy


Valid XHTML 1.0 Strict