Score Statements

Csound score code is like orchestra code in one important way: Each score statement is on a line by itself. Csound has no special “line terminator” character. The carriage-return/line-feed character (normally invisible) that you create by hitting the Enter or Return key on your keyboard terminates one score statement and begins a new one. Blank lines are ignored. Anything that appears on a line after a semicolon is a comment and is also ignored. Comments can also be entered using C-style syntax, in which a comment begins with the character pair /* and ends with */:


  /* This is a comment. */

Each score statement begins with a letter or with a curly bracket; curly brackets have a special meaning, as explained in the section “Looping Score Sections,” later in this chapter. The characters that can begin a score statement are: a, b, e, f, i, m, n, q, r, s, t, v, x, {, and }.

Following each of these characters, you’ll enter zero or more numbers or other symbols, separated by spaces or tab characters. It’s a matter of coding style whether you place a space after the initial letter and before the first number; it makes no difference to Csound. These two lines are equivalent:


  i1  0 2 0.6
  i 1 0 2 0.6

The numbers in a score statement are referred to as p-fields. They’re numbered consecutively beginning with 1. Thus it makes sense to talk about p1, p2, and so on. The meanings of the values in the p-fields depend on the type of statement and, in the case of i- and f-statements, on the values in other p-fields. That may sound a bit intimidating if you’re new to Csound, but the process of putting numbers into p-fields is actually very straightforward.

With a couple of exceptions, any other symbols used in a score statement will be translated into numbers by the preprocessor, so the score as actually performed consists primarily of lines of numbers.


image

Tip Csound score lines that contain more than a few numbers can get very hard to read. For this reason, you may want to separate the numbers and other symbols with tab characters, so that they will align in neat vertical columns and therefore be easier to read and edit. On the line before a score statement or a series of similar statements, you can insert a comment, also divided up by tabs, to label the columns. The result might look something like this:

     ;      start  dur   amp  pitch  atk   rel   pan
     i 101  3      2.25  0.7  6.09   0.03  0.17  0.2
     i 101  3.25   2.0   0.7  7.00   0.03  0.17  0.8

Unlike a score in conventional music notation, where the left-to-right and top-to-bottom order of notes on staves is significant, Csound score statements can be typed out in any order that’s convenient for you. If you’re writing a polyphonic passage, for instance, in which notes will sound as chords, it makes no difference whether you enter all of the note events for the first chord, then all of the events for the second chord, and so on; or, alternatively, enter all of the notes for the top chord voice, then proceed to enter all of the notes for the second chord voice, and so on.

This freedom has to be wrapped in a few caveats, however. First, Csound scores can be divided into sections by the s-statement. It’s only within a given section that you can place statements in whatever order you like. Second, if you’re using shortcut symbols to carry values from one statement to the next, as explained in the “Carry Symbols” section later in this chapter, the statements obviously need to be listed in a certain order. Third, the placement of a b-statement or v-statement at a specific point in an event list does make a difference in how the p-fields in subsequent events are interpreted (see below). Fourth, the np and pp symbols, discussed below, refer to the previous and following lines, so changing the order of the lines may change the values that will be substituted for these symbols as the score is being processed.

The i-statement

By far the most common statement in a Csound score is the i-statement. In composing a given piece you may need only a few i-statements, or you may need hundreds of them. Each i-statement invokes an instance of an instrument that is defined in the orchestra. The number in p-field 1 is the number of the instrument. For example, this line:


  i 21 3 1.2

has the number 21 in p1, so it causes instrument 21 to play a note (or to do whatever it does, which may or may not include producing an audio output).

An i-statement must have values in at least the first three p-fields. p1 designates the instrument, p2 is the start time of the event, and p3 is the length of the event. The meanings of these p-fields are fixed. An i-statement can include other p-fields, if desired. The meanings of p4, p5, and so on are defined by the instrument itself, so they will quite likely be different for i21 than for i19. (And of course i21 in one orchestra may be entirely different from i21 in a different orchestra. What matters is how the current instrument uses the data in the p-fields.)

Some Csound users prefer to grab the values in the p-fields and assign them local variable names at the start of the instr code, like this:


  instr 1
  idur = p3
  iamp = p4
  ifreq = cpspch(p5)
  ipan = p6
  ;... and so on

Other composers just use the symbols p3, p4, and so on wherever they’re needed in the instrument code. This is purely a matter of coding style; it makes no difference, but naming the values in your orchestra code will make the code easier to read, edit, and debug.

You may be wondering: Start time? Duration? How are these numbers defined? The answer is, by default Csound interprets these values as seconds. An i-statement with a p2 of 3, as shown above, will cause an event to begin precisely three seconds after the start of the score (or the start of the current section of the score).

For music that doesn’t rely on a conventional structure of bars and beats, using seconds for p2 and p3 may work perfectly well. If your music is metrical in nature, though, you can change the default using a t-statement.

The t-statement

The t- in this score statement stands for “tempo.” Each section of a Csound score (sections are terminated by s-statements, or by the e-statement that can optionally be used to end the entire score) can contain one t-statement. Using multiple t-statements within a section can cause Csound to get very confused, so don’t do it.

A t-statement defines the tempo of a section in beats per minute. The tempo can remain fixed throughout the section, or it can speed up or slow down in whatever manner you like. The meanings of the p-fields in the t-statement are as follows:

image p1, which is implicitly the start time of the t-statement, must be 0, because the music has to have a tempo from the very start.

image p2 is the initial tempo in beats per minute (bpm).

image p3, p5, p7, and so on are times in beats. These numbers must be in non-decreasing order.

image p4, p6, p8, and so on are the tempi in bpm that Csound will adopt at the time noted in the preceding p-field.

If a section contains no t-statement, it is assumed to have an implicit t-statement of:


  t 0 60

That is, the tempo is 60 bpm, or one beat per second. An s-statement, which ends a section, renders a preceding t-statement irrelevant: Each section needs its own t-statement.

The term “non-decreasing” in the list above is significant. Setting two odd-numbered p-fields in succession to the same value is often useful, as it produces a sudden tempo change. Consider this line, for instance:


  t 0 180 2 180 2 60 4 60 4 180

The tempo is 180 bpm at the beginning of the section. At the end of two beats, it’s still 180 bpm, but then it changes abruptly to 60 bpm. After two more beats it’s still 60 bpm, but then, at beat 4, it changes abruptly back to 180 bpm. If we neglect to tell Csound that the tempo hasn’t changed between beats 0 and 2 or between beats 2 and 4, it will produce a smooth ritard followed by a smooth accelerando:


  t 0 180 2 60 4 180

Here, the music will start at 180 bpm, but it will immediately begin slowing down, so that it reaches 60 bpm at the end of two beats. During the next two beats it will speed up again gradually, until it reaches 180 bpm at beat 4.

It’s important to understand that the value for p3 in an i-statement, when it is received by your instrument code, will have been adjusted by the preprocessor so that it is in seconds. In other words, p3 is in beats only while you’re writing the score. Within the instrument, it’s always a value in seconds. Except when the tempo is 60 bpm, the value of p3 will always be different from the value as stated in the score. This fact can have important consequences in programming envelope generators, for example.

The f-statement

The f-statement is one of the means of invoking Csound’s GEN routines. See Chapter 7 for more on GEN routines, which can also be invoked using the ftgen family of opcodes from within the orchestra. The syntax of f-statements is similar to the syntax used with ftgen, except that the arguments to opcodes are separated by commas, while the p-fields of an f-statement are not. Here is a typical f-statement:


  f 1 0 8192 10 1

The value for p1 is the number of the function-table that is created by the f-statement. p2 is the time at which the f-statement will run, p3 is the size of the table that will be created, and p4 is the number of the GEN routine that will be used to generate the table. The meanings of p5, p6, and so on are determined entirely by which GEN routine is being used.

Normally, p1 will be unique. That is, you might include half a dozen f-statements in your score—f1, f2, f3, f11, f12, and f101, for instance. If you reuse a value in p1, the new f-statement will override the old one. As a result, the data placed in the f-table by the first f-statement will be replaced by new data. This is sometimes useful. If you’re creating a waveform in an f-table, for instance, you could create one waveform at the start of the score and a different waveform at a later point, by reusing the p1 value. The sound of any instrument that used this f-table would depend on whether the i-statement playing the instrument occurred before or after the second f-statement. For example:


  f1 0 8192 10 1
  f1 8 8192 10 1 2 3 4 5

For the first eight seconds of the section (or eight beats, if a t-statement is being used to set the tempo), f-table 1 contains a sine wave. After eight seconds, the table suddenly contains a rather thin-sounding waveform containing partials 1 through 5 in increasing amplitude. (For details on how the p-fields produce this waveform, look up GEN 10 in the manual.)

An f-statement with a p1 of 0 produces no f-table, but it can be useful in one specific situation: If you want the score to run for a while, even though the last i-statement has ended, you can enter an f0 statement. For instance:


  f0 3600

This line will cause the score to remain active for 60 minutes (assuming the tempo is a default 60 bpm). If your instruments are responding to real-time MIDI input, such an f-statement will keep Csound running during your performance, even if there are no i-statements at all in the score. Another way to accomplish the same thing is with an e-statement that has a p1 of 3600.

If the value in p4 of the f-statement is positive, the data in the function-table will be rescaled to a range of ±1 after it is created. If the value is negative, however, rescaling is skipped. For more on this topic, see the “Post-Normalization” sidebar in Chapter 7.

Warping the Score with b- and v-

It’s relatively easy to confuse yourself using b-statements and v-statements. They’re useful mainly for organizing playback in complex scores. The b-statement resets the clock (either forward or backward) for subsequent i-statements, thus changing the meanings of p2 in those i-statements. The v-statement warps both p2 and p3 of i-statements. The b- and v-statements each have only one p-field.

For a simple example of how to use a b-statement, imagine that you’ve written out a series of i-statements that define, perhaps, a complex two-bar bass line. You’d like the bass line to repeat every two bars. You could achieve this by block-copying the code and then editing all of the p2 data in each pasted copy, but that would be time-consuming. Instead, you could simply make several copies of the data and then (assuming the bass riff is two bars of 4/4 time) separate them using b-statements. Rather than write out a series of notes, which would take up several pages when repeated, I’ll substitute comment lines:


  ;... the notes in the first riff, in which the first note presumably
  ; begins at time 0
  b 8
  ;... the same i-statements again, with the first note again beginning at
  ; time 0, except that “time 0” is now interpreted as “time 8”
  b 16
  ;... the same i-statements yet again
  b 24
  ;... and so forth
  b 0
  ;... and now the clock has been reset back to the start of the section,
  ; ready to receive the notes for another instrument...

When you organize the score this way, the bass line will play several times in a row. Conversely, if you forget a b-statement, you’ll hear two repetitions on top of one another, which will just make the bass line louder. The structure above can be used in combination with score macros, as discussed later in this chapter.

A b-statement can have a negative p1, thus setting the clock backward. (Notes that would fall before the beginning of the section are simply skipped.) A b-statement with a p1 of 0 cancels a previous b-statement and returns the clock for the section to what it would normally be. That is, the p2 of subsequent i-statements will be interpreted normally.

The p1 in a v-statement must be positive. It is used as a multiplier for p2 and p3 in the following i-statements. For instance, consider this simple score:


  ;     dur  amp   pitch
  i1 0  1    0.8   7.00
  i1 1  1    0.8   7.02
  i1 2  1    0.8   7.04
  i1 3  1    0.8   7.05
  v 0.5
  i1 4  1    0.8   7.07
  i1 5  1    0.8   7.09
  i1 6  1    0.8   7.11
  i1 7  1    0.8   8.00

In the absence of the v-statement, the eight notes would (assuming p5 is being processed by the cpspch opcode) play a C major scale with a steady rhythm. However, the v-statement warps p2 and p3 in the last four notes. What Csound plays, once the score has been processed, is this:


  ;      dur  amp  pitch
  i1 0   1    0.8  7.00
  i1 1   1    0.8  7.02
  i1 2   1    0.8  7.04
  i1 3   1    0.8  7.05
  i1 2   0.5  0.8  7.07
  i1 2.5 0.5  0.8  7.09
  i1 3   0.5  0.8  7.11
  i1 3.5 0.5  0.8  8.00

The fifth note event now starts at the same time as the third one (beat 2), and the seventh note event at the same time as the fourth one (beat 3). Don’t forget—once the b- and v-statements have been processed, Csound doesn’t much care what order events are written in in the score. You could write the score exactly as shown above if you like, but it looks a bit of a jumble. It will be sorted before it’s played. After sorting, it will look like this:


  i1 0   1    0.8  7.00
  i1 1   1    0.8  7.02
  i1 2   1    0.8  7.04
  i1 2   0.5  0.8  7.07
  i1 2.5 0.5  0.8  7.09
  i1 3   1    0.8  7.05
  i1 3   0.5  0.8  7.11
  i1 3.5 0.5  0.8  8.00

The a- and x-statements

The a-statement and x-statement are likely to be most useful while you’re developing a piece. The a-statement advances the playback by a given amount without producing any output, and the x-statement skips the remainder of a section. Suppose you’re developing a longish piece and want to listen to your work starting two minutes in, without having to wait for two minutes each time playback starts. At the beginning of the score, assuming a tempo of 60 bpm, you could enter:


  a 0 0 120

In an a-statement, p1 is meaningless. p2 is the time at which the advance is to begin (in this case it’s 0, meaning the start of the piece), and p3 is the number of beats to advance.

In a similar way, an x-statement can be used to skip the rest of a section if you don’t want to listen to it right now.

The s- and e-statements

In a score that includes several independent sections, each section can be terminated with an s-statement. The score as a whole can be terminated with an e-statement.

Csound will not output any sound that overlaps between one section and the next; the s-statement will always produce a brief moment of silence. I don’t find this very satisfying musically, but in some circumstances it may not matter. The advantage of the s-statement is that each section keeps track of its own times (in p2 for each event), starting over at 0.

The e-statement seems, at first glance, even less useful. However, both the s-statement and the e-statement can include a p-field. This optional field is the number of beats after the end of the last event in the section or score during which Csound will continue to run. This p-field can be very useful if you’ve started an audio processing instrument, such as a reverb, in the orchestra header using the alwayson opcode. Normally you’ll want the reverb to continue to run for a couple of seconds after the end of the last event. If the final event in the section ends at beat 200, for example, and you want the reverb to linger, you can end the section like this:


  s 203

This will cause the section to last for three beats after the end of the last note. Using this p-field in an e-statement is especially useful when you’re playing Csound live (using MIDI or some other performance input). A score can contain no events at all. If it ends like this:


  e 600

then it will run for 10 minutes, waiting for performance input.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.2.225