Exploring Tied Notes in Csound

Steven Yi
Email: stevenyi AT gmail.com

Introduction

One of the features of Csound which I find very useful in my
own work is the tied notes capability in Csound score. By using the
tied notes feature, the user can add expressive possibilities
to their music, such as legato phrasing and continous pitch glissandi.
By designing instruments that can work with both tied and non-tied
notes, we will be creating instruments that can interpret musical ideas
in more than simply one way.

Setting up your scores and instruments does require
understanding how to write scores with tied notes as well as designing
instruments to work with these notes. This article will cover how to
write tied-note scores, how to design instruments to work with both
tied and non-tied notes, and provides examples for
the reader to study and experiment with. The user is
encouraged to take
the ideas from this article and expand upon them for their own personal
musical needs.

I. Tied Notes in Csound Score

Usage

To use the tied notes feature of Csound is fairly simple: all
that one needs to do is make the p3 field of a note(i-statement)
negative. What this will do is tie a note to the next note following it
that has the the same instrument number. You can tie a group
of notes together by making all of the p3 fields negative except the
last note.

For example, the passage here
consists of four notes that are not tied:

i1 0 1 8.00 80i1 + . 8.02 80i1 + . 8.04 80i1 + . 8.04 80

To tie the first three notes together, simply change the above score to
the following:

i1 0 -1 8.00 80i1 + . 8.02 80i1 + 1 8.04 80i1 + 1 8.04 80

Technical Details

In Csound, everytime a note is processed, a chain of data
structs are put together for each opcode in the instrument. These
structs hold information that the opcodes uses when processing. For
example, for
the oscil opcode, the struct will hold what ftable to use,
what
frequency the opcode runs through the table, what amplitude to generate
at, as well the phase (where in the table it currently is in its
processing).

Normally for every note, when Csound sees the note, it checks
to see what instrument it is for, find that instrument's definition
from the orchestra, and then allocates a fresh chain of structs for
each of the opcodes in that instrument.

When two notes are tied together, the second note does not get
a fresh chain of structs. Rather, it is given the previous note's chain
of structs. By having the previous note's information, the new note can
continue to process and generate sound where the previous note left
off, or reference the information from the previous note to help
determine what to do in the current note.

Also, a key point, a flag is set in the note's instance that
marks it as being tied or not. We'll be using Csound opcodes in the
next section to check that flag to determine if a note has been tied or
not.

II. Some Essential Information

From the previous section we find that tying notes together in the
score is not so difficult to do, and it allows for notes of an
instrument to inherit a previous note's data. With that
information we'll be able to add some expressive possibilities
to our instrument designs, but first we'll need to cover a few
essential concepts before we can move on to learning how to design
instruments to take advantage of Csound's tied-notes feature.

Tied Notes and Duration

One
thing to be very
careful about
when working with tied notes is that your instrument code does not
assume p3 is positive. If your instrument has references to p3 with
that assumption, when you go to build tied-note instruments, you may
find that your instruments don't produce sound correctly because they
assume the note's duration is a positive value. For
instrument
code that depends on the duration of the note, It is recommended to
always first assign p3 to an i-time variable and to use the absolute
value of p3 to guarantee that the instrument will read the duration
correctly. For example, if your instrument contained code such
as
this:

kenv linseg 0.0, .05, 1, p3 - .1, 1, .05, 0.0

Your instrument may not work as envisioned. Instead, use code like
this:

idur = abs(p3)kenv linseg 0.0, .05, 1, idur - .1, 1, .05, 0.0

This code is guaranteed to work regardless if the note is tied
or not.

Csound Tie Opcodes

For our instruments to take advantage of the tied notes feature of
Csound, they'll first have to know if their note is tied or not. To do
this, we use the tival opcode:

ir tival

which returns either a 1 or 0 if the note has been tied or not,
repectively. Csound also has one other opcode that works with
tied notes, tigoto:

tigoto label

This opcode is a part of the goto family of opcodes and will go to the
label given if the note has been tied. This is generally used
to skip a block of initialization code which may follow the tigoto line
and the label that tigoto points to. This might not make
sense at the moment but in context of instruments designed for
tied-note usage that we'll explore later in this article, knowing how
and why to use this opcode will hopefully be made clear.

Fractional Instrument Numbers

To help with using the tied notes feature in Csound, it is
possible
to use fractional instrument numbers when writing your i-statements in
your SCO so that if you would like two have multiple lines of tied
notes using the same instrument but would like to have them separated,
you can add a fraction to the instrument number. For example:

In the above score fragment, there are two musical ideas, one
consisting of four tied notes of duration .25 each, and one note of
duration 1. The notes for instrument 1.1 are all tied to each
other, and since the second musical idea of the note of duration1 is
labeled inststrument 1.2, the notes with 1.1 will not tie to it.

This feature is used prominently in the glissandi instrument example.

Understanding Instrument Initialization Time

To understand how to take advantage of the tied notes
information, I'd like to discuss a little bit about how Csound
initializes instrument instances when it reads in notes, as I think
it's important to clarify at this point how this works in case there is
any questions the reader may have.

When Csound goes to to perform a note, the instrument for
that note is looked up and the instrument definition is found.
From the instrument definition, a chain of data structs--one
data struct for each opcode--is allocated for the instrument and then
attached to the note instance. For notes which are untied,
these structs usually come in uninitialized with any preset values.
After the data structs are allocated, an initialization time
pass is done and all opcodes with i-time functions will run.
Afterwards, the note is then added to the set of active
notes, and when the engine goes to perform, the note will only be
running at control (k-) and audio (a-) rates until the note is finished
and deallocated. (This is unless a reinit is called an
another i-time pass is explicitly invoked.
This is beyond the scope of this article and if interested
the reader is encouraged to look up the reinit opcode in the manual to
further explore this idea.)

For opcodes in Csound, they are able to operate at either
initialization time (i-rate), or performance time (k- and a-rate), or
any combination of those three rates. Most every opcode in
Csound has an init-time phase, even those which generally run at k- or
a-rate.
Those opcodes which are generally used for performance-time
operations--such as oscilators and envelope generators--generally use
their initialization time phase to do basic setup of their data struct
which later gets used when they are running at performance-time. This
may include setting what frequency to use, resetting the current phase
to 0, allocating memory to use for delayed samples (such as used in a
filter), etc.

For tied notes, two key aspects initialization time play a
part in how to design instruments to take advantage of the tied note
feature in Csound. When notes are tied together, the chain of data
structs from the previous note is reused, but all initialization that
an opcode normally goes through will occur as usual, unless the opcode supports
skipping initialization and is set to do so. This means
that for our instruments, if we are using opcodes that support a skip
intialization flag (one can look at the user's manual to see if the
opcodes being used in your instrument support this), we will most
likely be utilizing that flag to skip initialization. If we
don't do so, then opcodes that run through their normal initialization
won't pick up where they were in the previous note, so we may get phase
discontinuities in oscilators or cleared out delay lines, both of which
may produce audible pops as well as simply unintended sonic results.

The second aspect of initialization time to keep in mind for
tied notes is that since initialization time runs for every opcode
unless told otherwise, and performance time runs as it normally would
if the note was tied or not, then it is at initialization time when we
need to do all our work for the tied note. An example of
things we'll be doing at initialization time are evaluating what type
of note is being performed and conditionally using different amplitude
envelopes as well as setting up portomento pitch glides (as is commonly
used in monosynth mode in MIDI synthesizers).

Now that we've had a brief overview of Csound's instrument
initialization time, let's see what we can do with the opcodes
mentioned above and the information we've covered to create some
instruments that can take advantage of Csound's tied-notes feature.

III. Instrument Design

To take advantage of Csound's tied notes, our instruments will be using
the tival and tigoto opcodes to detect what type of note we have as
well as to conditionally intialize what our note will do, depending on
the context of the note. By doing this, we'll be able to do
things such as emulate MIDI monosynth mode as well as to create
continous glissandi sound masses.

Design Goal

For this article, we'll be making two different types of
instruments, described below.

Type 1 -
Monosynth Instruments

This type of instrument will emulate MIDI synthesizers which
support
monosynth mode (which in themselves are a mode to emulate older analog
synths which only supported one voice at a time). For those unfamiliar
with monosynths and MIDI's monosynth mode, these are instruments which
generally:

allow only one voice at a time to be played; if a new note
is
initiated before the previous note is finished, the new note takes over
the old note and the new note uses the new note's parameters (pitch,
amplitude, etc.)

have an amplitude attack on the first note and a release on
the last note

generally portomento from one pitch to the next

While this is a simplified explanation, I think it is enough to get an
idea of what we'll be aiming for in designing our tied note instrument.

Type 2 -
Glissandi
Instruments

This type of instrument will be based on the type 1 instrument
from
above, but will differ mainly in its treatment of pitch.
Rather
than a fixed time for shifting of pitch when a new note is played, a
duration dependent glissandi time will be implemented. This
will
allow us to express continous pitch glissandi and create sound masses
common in avant-garde musical techniques (for example, those found in
music by Iannis Xenakis or Krzysztof Penderecki).

General Instrument Design

For tied note instruments, we'll follow a general template of design.
The sections of code will be:

Further initialization setup of instrument, using tie
status and
type of note to determine what to do for treatment of pitch and
amplitude, as well as to do first-note initialization or not

Audio signal generation and processing code

There are three instruments in the example CSD file.
The first
of which is a non-tied-note instrument which we'll be using as the
basis for the other two instruments. This instrument is
designed
pretty much in a way that is commonly found in many Csound examples.
The audio generation code is not too remarkable, a VCO2
running
through a moogladder filter and also a feedbacked delay for a bit of
body and color. It does not follow the plan above as it is not a tied
note instrument.

The second instrument will take the design from the first
instrument
and modify it to handle tied notes and do so in a way to behave like
traditional monosynths. The third instrument also builds on
the
first instrument but is modified to behave in a way to allow continous
glissandi.

Determining Type of Note

Besides knowing if a note has been tied to by the previous note or not,
I've found it useful to know the "type" of notes and instrument is
getting. The type of note is something I have classified in
the following table:

Note Type

Type Code

Explanation

Normal Note

-1

This note is a free-standing note and is neither
tied-from or tied-to any other notes.

Initial Note

0

This note is the first note in a group of tied notes.
This note is tied to the next note but is not tied from any other note.

Middle Note

1

This note is contained within a group of tied notes and
is neither the initial or ending note of the group. This note is both
tied to the next note and tied from previous note.

End Note

2

This note is the final note in a group of tied notes.
This not is tied from a previous note but is not tied to any
other notes.

To determine the type of note a note is, you will both have to get it's
tie status by using tival as well as looking at the p3 value of the
note. tival tells us if the note is currently being tied from a
previous note, while looking to see if p3 is negative will tell us if
the note is tied to the next note for the instrument.

How to use this information is summarized in the following table:

Note Type

How to Detect Note Type

Normal Note

tival is 0 and p3 > 0

Initial Note

tival is 0 and p3 < 0

Middle Note

tival is 1 and p3 < 0

End Note

tival is 1 and p3 > 0

I have written a small User-Defined Opcode to aid in developing
tied-note instruments. It uses the above scheme to determine
the
type of note currently being processed and returns the type code as
defined in the first table. The code is listed below:

opcode tieStatus,i,0

itie tival

if (itie == 0 && p3 < 0) ithen ; this is an initial note within a group of tied notes itiestatus = 0

We will be using the note's type information to design our
instrument
to work with scores that contain notes both tied and untied.

Implementing the Monosynth Instrument

For the monosynth instrument, we'll want it to perform like a
normal
instrument when there is no tied notes. When there is a series of tied
notes, we have two main concerns for the instrument, one of which is
our treatement of pitch, the other other of amplitude.

For pitch, we will use a simple scheme of using the linseg
opcode to
move linearly from the previous notes value to the new notes value (I
used a .05 second time for transitioning to the new pitch value), then
to hold on the new pitch value for the duration of the note.
The
way this instrument is coded, the pitch line will always use the same
scheme regardless of note type.

For amplitude, our concerns are a little tricker.
Depending on
the note type, we will generate amplitude envelopes differently:

Amplitude
Envelope Properties

Note Type

Type Code

Handling of Amplitude

Normal Note

-1

Use ADSR

Initial Note

0

Use same attack and decay time as ADSR, holding sustain
value until end of note

Middle Note

1

Linearly move from old amplitude value to new amplitude
value in same amount of time as portamento time

End Note

2

Like middle, move to new amplitude in same amount of
time as
portamento time, but also do a release to zero in the same amount of
time as ADSR's release time

In the instrument, the tieStatus User-Defined Opcode is used
get the
type of note. From there, the type of note is used in conditional code
(a chain of if-then's) to determine what manner of amplitude envelope
to generate.

After this, the instrument pretty much operates like the
non-tied-note version, except that opcodes which support skipping
initialization do so when in a series of tied notes.

Implementing the Glissandi Instrument

For the glissandi instrument, our amplitude envelope scheme is
similar to the one used in the monosynth example, though we've also
made linear changes for the amplitude value given in, such that the
overall amplitude of the note is determined as a product of both the
ampltiude envelope (which is a value between 0 to 1) and the line from
the old amplitude value to the new amplitude value (which is a
value in decibels). This give a smooth amplitude change over
time.

For pitch, the implementation of this instrument for tied
notes is to glide from the old pitch to the new pitch in the duration
of the note. Now, with this example, the instrument has an
issue in that the first note of a tied-note group will stay on its
initial note and there is no method to have a glissandi on the first
note. The design can be modified to take in to use two pitch
fields, only using the second field if the first of a group of tied
notes. This is done already in the author's personal
instruments, but for this article it is left as-is for the sake of
simplicity.

IV. Examples

Notes on the Examples

The examples include three instruments: a normal non-tied-note
instrument, a monosynth instrument, and a glissandi instrument.
The score sections are as follows:

Melodic Line
for Instrument 1 using regular notes
A standard score as
would be used in normal Csound usage

Melodic Line
for Instrument 1 using tied notes
A tied note score
but using a normal non-tied-note instrument. Notice there are
click in the notes, demonstrating that simply tying the notes in the
score is not enough and may cause inadvertent problems. The melodic
line is given a fracitional instrument number so as note to interfere
with the held chords.

Melodic Line
for
Instrument 2 (monosynth) using regular notes
A standard score used with our Type 1 instrument. The audio result is
the same as score example 1, demonstrating that this instrument is
capable of working with non-tied notes.

Melodic Line
for Instrument 2 (monosynth) using tied notes A tied
note score used with
our Type 1 monosynth instrument. The melodic line is phrased
together using groups of tied notes, and the audible results resemble
those of monosynths, using portomento between note pitches.

Sound Mass
for Instrument 3 (glissandi) using tied notes -
This example uses the Type 2 glissandi instrument to create sound
masses of microtonally inflected glissandi clouds. There are many
lines and different fractional instrument numbers are used to allow for
distinct lines to be created without the lines getting tied to each
other inadvertently. The score
was
generated using the author's Orchestral Composition library, written in
Python and included with the author's blue music composition
environment.

Some other notes:

For examples 1-4 above, a setting of chords is given using
instrument 1 beneath the melodic lines.

These examples were created and tested
using Csound5.

The generated score may seem very verbose, but it is
because when
blue generates a CSD, it exapnds all the Csound SCO features (i.e. "+",
".", ">"). The author generally takes advantage of
these
Csound SCO features liberally in his own work and encourages users
unfamiliar with these features to take advantage of them, as they make
SCO writing faster. The original score fragments can be
viewed
either by opening the blue project file in blue, or opening it in a
text editor, as the project file is in an XML format.

Acknowledgements

I would like to thank Richard Dobson for his chapter in The Csound Book,
"Designing Legato Instruments in Csound", as it helped a great deal in
understanding Csound's tied-notes functionality.