Legato Instruments

Up until this point in the book, we’ve been using Csound to play one detached note at a time. But as most musicians who use synthesizers are aware, most commercial synths can operate in a one-voice legato mode, sometimes called mono mode. When set to this mode, the synth responds to only one note at a time on the MIDI keyboard. When you press a new key before releasing the old one, the pitch will move up or down to the pitch dictated by the new key—but the tone will continue without interruption. In particular, the envelope generators won’t retrigger (although in some instruments each envelope generator can be set to retrigger in legato mode, or not). Instead of hearing two discrete notes, you’ll hear one sustaining note with a pitch change. And the pitch change need not be abrupt: The pitch may glide smoothly up or down from the old pitch to the new one.

Can Csound duplicate this trick? Certainly. Designing legato instruments is not as easy as pressing a Mono Mode button, however. In order to create a legato instrument in Csound, we’ll have to unleash four or five new techniques and deploy them all at once. In this section we’ll look at how to create legato lines from the Csound score; in Chapter 10 we’ll return to the subject and show how to make a monophonic legato instrument that can be played from a MIDI keyboard.

The code examples, both here and in Chapter 10, will be a little more thorough than many of the examples in this book. Taking a few minutes to enter them into the text editor you’re using for your Csound work will help you understand the concepts. A great deal more can be done with legato instruments than these examples demonstrate, but they will help get you on the right track.

The ideas in this section are adapted from the chapter “Designing Legato Instruments in Csound” by Richard Dobson in The Csound Book (MIT Press, 2000) , and from Steven Yi’s article “Exploring Tied Notes in Csound” in the Fall 2005 issue of The Csound Journal.

Let’s look at the techniques one at a time.

First, the value for p3 in an i-statement in the score can be negative rather than positive. If it’s negative, Csound assumes that the note will be tied to a following note that will use the same instrument (that is, the following note will have the same p1 value). Since p3 is reserved for the duration of a note event, setting a negative duration might seem odd, but the negative value is simply a flag that alerts Csound to what you have in mind. Having set a negative p3, of course, you can’t simply use the symbol p3 in your orchestra code the way you normally would. A line opcode with a negative value for its duration argument, for example, wouldn’t do anything, or at least it wouldn’t do what you expected. In this situation, it’s advisable to create, in the instrument, an i-time value for duration like this:


  idur = abs(p3)

The abs opcode returns the absolute value of p3.

The final note in a string of notes that are to be played legato should be given a positive p3, as usual.


image

Buzzword The absolute value of a number is the distance of the number from 0. The absolute value is either the same as the number (if the number is positive) or −1 times the number (if the original number is negative). Thus the absolute value of 3.7 is 3.7, and the absolute value of −6 is 6.


Second—and again, this may seem odd at first—the value for p1 in a score doesn’t have to be an integer. Each instrument in the orchestra is defined using an integer as its identifier, but after defining instr 1 we can use values for p1 such as 1.1, 1.2, and so on. Csound will interpret these numbers as referring to distinct instances of the instrument. This distinction is of importance mainly if we’re defining a legato instrument using a negative p3 value. For instance, if we do this:


  i 1.1  0    -1
  i 1.1  1    .
  i 1.1  2    1
  i 1.2  0.5  3

then Csound will understand that the first three i-statements are to be played by the same instance of instrument 1, while the last statement, even though it is to be played in the middle of the legato sequence, and by the same instrument, is not part of the legato note stream.

Third, the opcode tival returns 1 if a note is tied from a previous note, and 0 otherwise. In other words, tival lets us see whether the previous note had a negative p3. Also useful is the opcode tigoto. This is a goto statement (see the section “Logic and Flow Control” in Chapter 6) that passes control to the named label only when the note is tied from a previous note. In other words, tigoto is shorthand. This code:


  tigoto slur

has the same result as this:


  itie tival
  if itie == 1 igoto slur

The label slur is an arbitrarily named label that you would use in your code.

Fourth, a good way to give a Csound instrument access to the data in p-fields for the previous and following notes in a legato line is to use the special symbols npx and ppx in the score, replacing x with the number of the desired p-field for the next i-statement (npx) or the previous i-statement (ppx). This is explained in the page in the manual called “Next-P and Previous-P Symbols.”

In the example, we’re going to use a nifty user-defined opcode (UDO) written by Steven Yi called tieStatus. This opcode senses the status of the current note. If the note is freestanding (not tied to a previous or following note), tieStatus returns −1. If the note is the first note in a legato group, tieStatus returns 0. If it’s a middle note in a legato line, tieStatus returns 1. If it’s the last note, tieStatus returns 2.

With that preamble, we’re ready to take a look at the example. As usual, I’ve omitted the opening and closing tags from the .csd file.


  sr = 44100
  ksmps = 4
  nchnls = 2
  0dbfs = 1

  opcode tieStatus,i,0
  itie tival
  if (itie == 0 && p3 < 0) then
    ; this is an initial note within a group of tied notes
    itiestatus = 0
  elseif (p3 < 0 && itie == 1) then
    ; this is a middle note within a group of tied notes
    itiestatus = 1
  elseif (p3 > 0 && itie == 1) then
    ; this is an end note out of a group of tied notes
    itiestatus = 2
  elseif (p3 > 0 && itie == 0) then
    ; this note is a stand-alone note
    itiestatus = -1
  endif
  xout itiestatus
  endop

  instr 1
  idur = abs(p3)
  itiestatus tieStatus
  ipitch = cpspch(p5)
  iprevpitch = cpspch(p6)
  ipitchramptime = p8
  iamp = p4
  inextamp = p7
  iatk = 0.03

  iphas = -1
  tigoto slur
  iphas = 0

  slur:
  if itiestatus == -1 then
    kamp linsegr 0, iatk, iamp, idur - iatk, iamp, iatk, 0
  elseif itiestatus == 0 then
    kamp linseg 0, iatk, iamp, idur - iatk, inextamp
  else
    kamp line iamp, idur, inextamp
  endif

  kpitch linseg iprevpitch, ipitchramptime, ipitch
  asig oscili kamp, kpitch, 1, iphas
  outs asig, asig
  endin

  </CsInstruments>
  <CsScore>

  ; a waveform with a few low harmonics:
  f1 0 8192 10 1 0.95 0.1 0.05
  ; a legato line:
  ;          dur   amp   pitch   prevpch   nextamp   glide time
  i 1.1 0    -1    0.6   7.09    7.09      np4       0.1
  i 1.1 +    .     0.3   8.00    pp5       np4       0.2
  i 1.1 +    .     0.7   7.07    pp5       np4       0.1
  i 1.1 +    2     0.2   7.10    pp5       0         0.3

  ; play some shorter non-legato notes in a lower octave:
  i 1.2 0    0.3   0.2  5.09  5.09      0         0.01
  i 1.2 0.5
  i 1.2 1
  i 1.2 1.5
  i 1.2 2
  i 1.2 2.5
  i 1.2 3
  i 1.2 3.5

The first four i-statements create a legato line using instrument 1. During each note, the amplitude of the tone glides smoothly up or down toward the amplitude of the next note thanks to the np4 symbol. At the beginning of each note, the pitch glides up or down from the previous pitch at a rate determined by p8.

At the same time, instrument 1 is playing a series of non-legato notes in a lower octave. One peculiarity of this implementation should be noted: Because linseg is being used to glide the pitch in the legato line, the value of p8 has to be non-zero even in the i-statements where p1 is 1.2. If p8 is 0, linseg will refuse to operate.

In the instrument code, the call to tieStatus is used to decide what kind of amplitude envelope to create. If we’re playing an isolated, non-legato note, we’ll use linsegr to generate a conventional envelope with an attack and a release. If this is the first note in the line, we’ll start with an attack ramp up from 0. Otherwise, we’ll ramp up or down from the current amplitude to the amplitude of the following note. The score defines p7 (inextamp) as 0 for the last note in the line, so it will fade out smoothly to silence.

The usage of tigoto is not strictly necessary, as the value of iphas could have been set in the if/then/else block. But this code is a little more concise.

The point of the value iphas—and this is a vital concept—is that it is needed as an argument to oscili. This argument is optional, and in most of the examples in this book it isn’t used. But in a legato instrument it’s needed. You would also need it if your legato instrument is using an LFO to create vibrato, and for the same reason. As the manual explains, a negative value for this argument causes the initialization of oscili to be skipped. When initialization is skipped, oscili will continue cycling through the waveform (which is created in the score by GEN 10) without resetting its phase to the start of the waveform. If you omit this argument, you will almost certainly hear a click at the beginning of the new note. The click will occur because there’s a discontinuity in the waveform—a vertical jump from one audio value to another. If you comment out the final , iphas in the oscili line, you’ll hear the clicks.

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

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