An orchestra statement in Csound has the format:
label: result opcode argument1, argument2, ... ;comments
The label is optional and identifies the basic statement that follows as the potential target of a go-to operation (see Program Control Statements). A label has no effect on the statement per se.
Comments are optional and are for the purpose of letting the user document his orchestra code. Comments always begin with a semicolon (;) and extend to the end of the line.
The remainder (result, opcode, and arguments) form the basic statement. This also is optional, i.e. a line may have only a label or comment or be entirely blank. If present, the basic statement must be complete on one line. The opcode determines the operation to be performed; it usually takes some number of input values (arguments); and it usually has a result field variable to which it sends output values at some fixed rate. There are four possible rates:
(1) once only, at orchestra setup time (effectively a permanent assignment);
(2) once at the beginning of each note (at initialization (init) time: I-rate);
(3) once every performance-time control loop (perf time control rate, or K-rate);
(4) once each sound sample of every control loop (perf time audio rate, or A-rate).
Many generators and the Csound command itself specify filenames to be read from or written to. These are optionally full pathnames, whose target directory is fully specified. When not fullpath, filenames are sought in several directories in order, depending on their type and on the setting of certain environment variables. The latter are optional, but they can serve to partition and organize the directories so that source files can be shared rather than duplicated in several user directories. The environment variables can define directories for soundfiles (SFDIR), sound samples (SSDIR), and sound analysis (SADIR). The search order is:
Soundfiles being written are placed in SFDIR (if it exists), else the current directory. Soundfiles for reading are sought in the current directory, then SSDIR, then SFDIR. Analysis control files for reading are sought in the current directory, then SADIR.
In Csound there are nine statement types, each of which provides a heading for the descriptive sections that follow in this chapter:
assignment statements signal generator statements orchestra header statements signal modifier statements instrument block statements signal display statements program control statements soundfile access statements duration control statements
Throughout this document, opcodes are indicated in boldface and their argument and result mnemonics, when mentioned in the text, are given in italics. Argument names are generally mnemonic (amp, phs), and the result is denoted the letter r. Both are preceded by a type qualifier i, k, aor x (e.g. kamp, iphs, ar). The prefix idenotes scalar values valid at note Init time; prefixes k or a denote control (scalar) and audio (vector) values, modified and referenced continuously throughout performance (i.e. at every control period while the instrument is active). Arguments are used at the prefix-listed times; results are created at their listed times, then remain available for use as inputs elsewhere. The validity of inputs is defined by the following:
All arguments, unless otherwise stated, can be expressions whose results conform to the above. Most opcodes (such as linen and oscil) can be used in more than one mode, which one being determined by the prefix of the result symbol.
An orchestra program in Csound is comprised of orchestra header statements which set various global parameters, followed by a number of instrument blocks representing different instrument types. An instrument block, in turn, is comprised of ordinary statements that set values, control the logical flow, or invoke the various signal processing subroutines that lead to audio output.
An orchestra header statement operates once only, at orchestra setup time. It is most commonly an assignment of some value to a global reserved symbol, e.g. sr = 20000. All orchestra header statements belong to a pseudo instrument 0, an init pass of which is run prior to all other instruments at score time 0. Any ordinary statement can serve as an orchestra header statement, eg. gifreq = cpspch(8.09) provided it is an init-time only operation.
An ordinary statement runs at either init time or performance time or both. Operations which produce a result formally run at the rate of that result (that is, at init time for I-rate results; at performance time for K- and A-rate results), with the sole exception of the init opcode. Most generators and modifiers, however, produce signals that depend not only on the instantaneous value of their arguments but also on some preserved internal state. These performance-time units therefore have an implicit init-time component to set up that state. The run time of an operation which produces no result is apparent in the opcode.
Arguments are values that are sent to an operation. Most arguments will accept arithmetic expressions composed of constants, variables, reserved globals, value converters, arithmetic operations and conditional values.
constants are floating point numbers, such as 1, 3.14159, or -73.45. They are available continuously and do not change in value.
variables are named cells containing numbers. They are available continuously and may be updated at one of the four update rates (setup only, I-rate, K-rate, or A-rate). I- and K-rate variables are scalars (i.e. they take on only one value at any given time) and are primarily used to store and recall controlling data, that is, data that changes at the note rate (for I-variables) or at the control rate (for K-variables). I- and K-variables are therefore useful for storing note parameter values, pitches, durations, slow-moving frequencies, vibratos, etc. A-variables, on the other hand, are arrays or vectors of information. Though renewed on the same perf-time control pass as K-variables, these array cells represent a finer resolution of time by dividing the control period into sample periods (see ksmps ). A-variables are used to store and recall data changing at the audio sampling rate (e.g. output signals of oscillators, filters, etc.).
A further distinction is that between local and global variables. local variables are private to a particular instrument, and cannot be read from or written into by any other instrument. Their values are preserved, and they may carry information from pass to pass (e.g. from initialization time to performance time) within a single instrument. Local variable names begin with the letter p, i, k, or a. The same local variable name may appear in two or more different instrument blocks without conflict.
global variables are cells that are accessible by all instruments. The names are either like local names preceded by the letter g, or are special reserved symbols. Global variables are used for broadcasting general values, for communicating between instruments (semaphores), or for sending sound from one instrument to another (e.g. mixing prior to reverberation).
Given these distinctions, there are eight forms of local and global variables
: type when renewable Local Global reserved symbols permanent -- rsymbol score parameter fields I-time pnumber -- init variables I-time iname giname control signals P-time, K-rate kname gkname audio signals P-time, A-rate aname ganame
where rsymbol is a special reserved symbol (e.g. sr, kr), number is a positive integer referring to a score statement pfield, and name is a string of letters and/or digits with local or global meaning. As might be inferred, score parameters are local I-variables whose values are copied from the invoking score statement just prior to the Init pass through an instrument.
Expressions may be composed to any depth . Each part of an expression is evaluated at its own proper rate. For instance, if the terms within a sub-expression all change at the control rate or slower, the sub-expression will be evaluated only at the control rate; that result might then be used in an audio-rate evaluation. For example, in
k1 + abs(int(p5) + frac(p5) * 100/12 + sqrt(k1))
the 100/12 would be evaluated at orch init, the p5 expressions evaluated at note I-time, and the remainder of the expression evaluated every k-period. The whole might occur in a unit generator argument position, or be part of an assignment statement .
- a + a a && b (logical AND; not audio-rate) a || b (logical OR; not audio-rate) a + b a - b a * b a / b
where the arguments a and b may be further expressions.
Arithmetic operators perform operations of change-sign (negate), don't-change-sign, logical AND logical OR, add, subtract, multiply and divide. Note that a value or an expression may fall between two of these operators, either of which could take it as its left or right argument, as in
a + b * c.
In such cases three rules apply:
Parentheses may be used as above to force particular groupings.
ir ipow iarg, kpow kr kpow karg, kpow, [inorm] ar apow aarg, kpow, [inorm]
Computes xarg to the power of kpow and scales the result by inorm.
inorm - The number to divide the result (default to 1). This is especially useful if you are doing powers of a- or k- signals where samples out of range are extremely common!
iarg - If you are using ipow this is the base.
karg - If you are using kpow this is the base.
aarg - If you are using apow this is the base.
1. i2t2 ipow 2,2 ; Computes 2^2. 2. kline line 0, 1, 4 kexp kpow kline, 2, 4
This feeds a linear function to kpow and scales that to the line's peak value. The output will be an exponential curve with the same range as the input line.
3. iamp ipow 10, 2 a1 oscil iamp, 100, 1 a2 apow a1, 2, iamp out a2
This will output a sine with its negative part folded over the amp axis. The peak value will be iamp = 10^2 = 100.
(a > b ? v1 : v2) (a < b ? v1 : v2) (a > = b ? v1 : v2) (a < = b ? v1 : v2) (a = = b ? v1 : v2) (a ! = b ? v1 : v2)
where a, b, v1 and v2 may be expressions, but a, b not audio-rate.
In the above conditionals, a and b are first compared. If the indicated relation is true (a greater than b, a less than b, a greater than or equal to b, a less than or equal to b, a equal to b, a not equal to b), then the conditional expression has the value of v1; if the relation is false, the expression has the value of v2. (For convenience, a sole `=` will function as `= =`.)
NB.: If v1 or v2 are expressions, these will be evaluated before the conditional is determined.
In terms of binding strength, all conditional operators (i.e. the relational operators (>,<, etc.), and ?, and : ) are weaker than the arithmetic and logical operators (+, -, *, /, && and ||).
(k1 < p5/2 + p6 ? k1 : p7)
binds the terms p5/2 and p6. It will return the value k1 below this threshold, else the value p7.
ir = iarg kr = karg ar = xarg kr init iarg ar init iarg ir tival ir divz ia, ib, isubst (these not yet implemented) kr divz ka, kb, ksubst ar divz xa, xb, ksubst
= (simple assignment) - Put the value of the expression iarg (karg, xarg) into the named result. This provides a means of saving an evaluated result for later use.
init - Put the value of the I-time expression iarg into a K- or A-variable, i.e., initialize the result. Note that init provides the only case of an Init-time statement being permitted to write into a Perftime (K- or A-rate) result cell; the statement has no effect at Perf-time.
tival - Put the value of the instrument's internal "tie-in" flag into the named I-variable. Assigns 1 if this note has been 'tied' onto a previously held note ( see I Statement); assigns 0 if no tie actually took place. ( See also tigoto.)
divz - Whenever b is not zero, set the result to the value a / b; when b is zero, set it to the value of subst instead.
kcps = i2/3 + cpsoct(k2 + octpch(p5))
sr = n1 kr = n2 ksmps = n3 nchnls = n4
These statements are global value assignments, made at the beginning of an orchestra, before any instrument block is defined. Their function is to set certain reserved symbol variables that are required for performance. Once set, these reserved symbols can be used in expressions anywhere in the orchestra.
sr = (optional) - set sampling rate to n1 samples per second per channel. The default value is 10000.
kr = (optional) - set control rate to n2 samples per second. The default value is 1000.
ksmps = (optional) - set the number of samples in a Control Period to n3. This value must equal sr/kr. The default value is 10.
nchnls = (optional) - set number of channels of audio output to n4. (1 = mono, 2 = stereo, 4 = quadraphonic.) The default value is 1 (mono).
In addition, any global variable can be initialized by an init-time assignment anywhere before the first instr statement.
All of the above assignments are run as instrument 0 (i - pass only)
at the start of real performance.
sr = 10000 kr = 500 ksmps = 20 gi1 = sr/2. ga init 0 gitranspose = octpch(.0l)
instr i, j, ... . . < body . of . instrument > . endin
These statements delimit an instrument block. They must always occur in pairs.
instr - begin an instrument block defining instruments i, j, ...
i, j, ... must be numbers, not expressions. Any positive integer is legal, and in any order, but excessively high numbers are best avoided.
endin - end the current instrument block.
Note:
There may be any number of instrument blocks in an orchestra.
Instruments can be defined in any order (but they will always be both initialized and performed in ascending instrument number order).
Instrument blocks cannot be nested (i.e. one block cannot contain another).
igoto label igoto label tigoto label kgoto label goto label if ia R ib igoto label if ka R kb kgoto label if ia R ib goto label timout istrt, idur, label reinit label rigoto label rireturn
igoto label tigoto label kgoto label goto label if ia R ib igoto label if ka R kb kgoto label if ia R ib goto label timout istrt, idur, label
where label is in the same instrument block and is not an expression, and where R is one of the Relational operators (>, <, >=, <=, ==, !=) (and = for convenience, see also under Conditional values).
These statements are used to control the order in which statements in an instrument block are to be executed. I-time and P-time passes can be controlled separately as follows:
igoto - During the I-time pass only, unconditionally transfer control to the statement labeled by label.
tigoto - similar to igoto, but effective only during an I-time pass at which a new note is being 'tied' onto a previously held note ( see I Statement); no-op when a tie has not taken place. Allows an instrument to skip initialization of units according to whether a proposed tie was in fact successful (see also tival, delay).
kgoto - During the P-time passes only, unconditionally transfer control to the statement labeled by label.
goto - (combination of igoto and kgoto) Transfer control to label on every pass.
if...igoto - conditional branch at I-time, depending on the truth value of the logical expression ia R ib. The branch is taken only if the result is true.
if...kgoto - conditional branch during P-time, depending on the truth value of the logical expression ka R kb. The branch is taken only if the result is true.
if...goto - combination of the above. Condition tested on every pass.
timout - conditional branch during P-time, depending on elapsed note time. istrt and idur specify time in seconds. The branch to label will become effective at time istrt, and will remain so for just idur seconds. Note that timout can be reinitialized for multiple activation within a single note ( see example under reinit).
if k3 > p5 + 10 kgoto next
reinit label rigoto label rireturn
These statements permit an instrument to reinitialize itself during performance.
reinit - whenever this statement is encountered during a P-time pass, performance is temporarily suspended while a special Initialization pass, beginning at label and continuing to rireturn or endin, is executed. Performance will then be resumed from where it left off.
rigoto - similar to igoto, but effective only during a reinit pass (i.e., No-op at standard I-time). This statement is useful for bypassing units that are not to be reinitialized.
rireturn - terminates a reinit pass (i.e., No-op at standard I-time). This statement, or an endin, will cause normal performance to be resumed.
The following statements will generate an exponential control signal whose value moves from 440 to 880 exactly ten times over the duration p3.
reset: timout 0, p3 /10, contin ;after p3/10 seconds, reinit reset ; reinit both timout contin: expon 440, p3/10,880 ; and expon rireturn ; then resume perf
ihold turnoff
These statements permit the current note to modify its own duration. ihold - this I-time statement causes a finite-duration note to become a `held' note. It thus has the same effect as a negative p3 ( see Score I-statement), except that p3 here remains positive and the instrument reclassifies itself to being held indefinitely. The note can be turned off explicitly with turnoff, or its space taken over by another note of the same instrument number (i.e. it is tied into that note). Effective at I-time only; no-op during a reinit pass.
turnoff - this P-time statement enables an instrument to turn itself off. Whether of finite duration or 'held', the note currently being performed by this instrument is immediately removed from the active note list. No other notes are affected.
The following statements will cause a note to terminate when a control signal passes a certain threshold (here the Nyquist frequency).
k1 expon 440, p3/10,880 ; begin gliss and continue if k1 < sr/2 kgoto contin ; until Nyquist detected turnoff ; then quit contin: a1 oscil a1, k1, 1
ftlen(x) (init-rate args only) int(x) (init- or control-rate args only) frac(x) (init- or control-rate args only) dbamp(x) (init- or control-rate args only) i(x) (control-rate args only) abs(x) (no rate restriction) exp(x) (no rate restriction) log(x) (no rate restriction) sqrt(x) (no rate restriction) sin(x) (no rate restriction) cos(x) (no rate restriction) ampdb(x) (no rate restriction)
where the argument within the parentheses may be an expression.
Value converters perform arithmetic translation from units of one kind to units of another. The result can then be a term in a further expression.
Note that for log, sqrt, and ftlen the argument value is restricted. Note also that ftlen will always return a power-of-2 value, i.e. the function table guard point (see F statement) is not included.
octpch(pch) (init- or control-rate args only) pchoct(oct) (init- or control-rate args only) cpspch(pch) (init- or control-rate args only) octcps(cps) (init- or control-rate args only) cpsoct(oct) (no rate restriction)
where the argument within the parentheses may be a further expression.
These are really value converters with a special function of manipulating pitch data.
Data concerning pitch and frequency can exist in any of the following forms:
name abbreviation octave point pitch-class (8ve.pc) pch octave point decimal oct cycles per second cps
The first two forms consist of a whole number, representing octave registration, followed by a specially interpreted fractional part. For pch, the fraction is read as two decimal digits representing the 12 equal-tempered pitch classes from .00 for C to.11 for B. For oct, the fraction is interpreted as a true decimal fractional part of an octave. The two fractional forms are thus related by the factor 100/12. In both forms, the fraction is preceded by a whole number octave index such that 8.00 represents Middle C,9.00 the C above, etc. Thus A440 can be represented alternatively by 440 (cps),8.09 (pch), 8.75 (oct), or 7.21 (pch), etc. Microtonal divisions of the pch semitone can be encoded by using more than two decimal places.
The mnemonics of the pitch conversion units are derived from morphemes of the forms involved, the second morpheme describing the source and the first morpheme the object (result). Thus
cpspch(8.09)
will convert the pitch argument 8.09 to its cps (or Hertz) equivalent, giving the value of 440. Since the argument is constant over the duration of the note, this conversion will take place at I-time, before any samples for the current note are produced. By contrast, the conversion
cpsoct(8.75 + K1)
which gives the value of A440 transposed by the octave interval K1 will repeat the calculation every, K-period since that is the rate at which K1 varies.
N.B. The conversion from pch or oct into cps is not a linear operation but involves an exponential process that could be time-consuming when executed repeatedly. Csound now uses a built-in table lookup to do this efficiently, even at audio rates.
icps cps2pch ipch, iequal icps cpsxpch ipch, iequal, irepeat, ibase
Converts a pitch-class notation into cycles-per-second for equal divisions of the octave (for cps2pch) or for equal divisions of any interval. There is a restriction of no more than 100 equal divisions.
ipch - Input number of the form 8ve.pc, indicating an `octave' and which note in the octave.
iequal - if positive, the number of equal intervals into which the `octave' is divided. Must be less than or equal to 100. if negative is the number of a table of frequency multipliers
irepeat - Number indicating the interval which is the `octave'. The integer 2 corresponds to octave divisions, 3 to a twelveth, 4 is two octaves, and so on. This need not be an integer, but must be positive.
ibase - The frequency which corresponds to pitch 0.0
Note: 1. The following are essentially the same
ia = cpspch(8.02) ib cps2pch 8.02, 12 ic cpsxpch 8.02, 12, 2, 1.02197503906
2. These are opcodes not functions.
3. Negative values of ipch are allowed, but not negative irepeat, iequal or ibase.
inote cps2pch p5, 19 ; convert oct.pch to cps in 19ET inote cpsxpch p5, 12, 3, 261.62561 ; Pierce scale centered ; on middle A inote cpsxpch p5, 21, 4, 16.35160062496 ; 10.5ET scale
The use of a table allows exotic scales by mapping frequencies in a table. For example the table:
f2 0 16 -2 1 1.1 1.2 1.3 1.4 1.6 1.7 1.8 1.9
can be used with:
ip cps2pch p4, -2
to get a 10 note scale of unequal divisions.
ival notnum ival veloc icps cpsmidi icps cpsmidib kcps cpsmidib [irange] ioct octmidi ioct octmidib koct octmidib [irange] ipch pchmidi ipch pchmidib kpch pchmidib [irange] iamp ampmidi iscal[, ifn] kaft aftouch iscal kchpr chpress iscal kbend pchbend iscal ival midictrl inum[, initial] kval midictrl inum[, initial] kval midictrlsc inum[, iscal][, ioffset][, initial]
Get a value from the MIDI event that activated this instrument, or from a continuous MIDI controller, and convert it to a locally useful format.
iscal - I-time scaling factor.
ifn (optional) - function table number of a normalized translation table, by which the incoming value is first interpreted. The default value is 0, denoting no translation.
inum - MIDI controller number.
initial - the initial value of the controller.
irange - the pitch bend range in semitones.
notnum, veloc - get the MIDI byte value (0 - 127) denoting the note number or velocity of the current event.
cpsmidi, octmidi, pchmidi - get the note number of the current MIDI event, expressed in cps, oct, or pch units for local processing.
cpsmidib, octmidib, pchmidib - get the note number of the current MIDI event, modify it by the current pitch-bend value, and express the result in cps, oct, or pch units. Available as an I-time value or as a continuous ksig value.
ampmidi - get the velocity of the current MIDI event, optionally pass it through a normalized translation table, and return an amplitude value in the range 0 - iscal.
aftouch, chpress, pchbend - get the current after-touch, channel pressure, or pitch-bend value for this channel, rescaled to the range 0 - iscal. Note that this access to pitch-bend data is independent of the MIDI pitch, enabling the value here to be used for any arbitrary purpose.
midictrl - get the current value (0 - 127) of a specified MIDI controller.
midictrlsc - get a scaled and offset value of a controller.
Barry Vercoe - Mike Berry
MIT - Mills
May 1997