Skip to content
Menno Knevel edited this page Jul 20, 2023 · 27 revisions

Author: Menno Knevel

Looking for more subtle control over the sounds i create, and trying to get viable sounds, in The Csound Book i came across a few options. Options like: when louder then brighter, when softer then darker. Or just the opposite! And another option is: when louder, then amplify certain frequencies more, when softer de-emphasize those frequencies.... Because electronically created sounds sometimes need some randomness, more 'life' to be interesting, to give them depth. Other times sounds are more effective sec - when repeated as a hammer for example like the kick drum in Blue Monday from New Order.

Using tied notes, or legato, is yet another tool to sculpt sound textures. In The Csound Book there is a chapter on the subject, Designing Legato Instruments in Csound by Richard Dobson. Steven Yi wrote an article elaborating on the subject: Exploring Tied Notes in Csound. Check out the example here as it is on his Instrument 2 i am building further.

Instrument 2 is the Monosynth. When the duration (p3) is negative, in Csound this means that the note is held and tied to the next note. It does this by taking the initialization data from that 1st note, keep those data and take these data to the next note it is tied to. By creating fractional Instruments, for example Instrument 2.0, 2.1, 2.2 etcetera, more than one note of the same Instrument can sound at the same time. In a way, these fractional Instruments move independently, they do not get in each others hair. This way it is possible to create chords where some notes are tied and others are not.

In the Tied Note Monosynth example from Steven Yi (my reference), a few properties of the note are addressed: pitch, amplitude and duration

idur	= abs(p3)
ipch	= cpspch(p4)
iamp	= ampdb(p5)

In the Monosynth, p3 can be negative (held note for ties) or positive (standalone note); idur (duration) will always be positive. Thus idur can be used for gliding from one value to another as idur is always a positive value. In the Monosynth example, the pitch value that morphs into another pitch is using the linseg opcode:

kpchline   linseg   ioldpch, .05, inewpch, idur - .05,  inewpch

The tieStatus UDO is used for decisions on the envelope generator ADSR. Idea is that whether a note is tied or not, both the standalone note or tied-notes-group will get the same kind of ADSR in treating the tied notes as one entity. Just like the standalone note is one entity. It is up to the user to decide what to do with ADSR, amplitude-, pitch- or filter-movements in case of a standalone note, the first tied note, middle tied note and the last note that is being tied to.

In my example, the construction of pitch-splitting into old pitch and pitch-to-move-to is chosen for amplitude of the notes and cutoff frequencies of the filter as well. The filter must also get the signal (iskip) meaning no re-initialization in case of ties. If this is not done, very short but audible clicks will be the result as the filter is reset after each note:

click

And it should look like this!

Noclick

(For reasons of space, all rendered wave file images are 2 channel mono, but only one channel is shown.)

And this is what is all about: the human ear is a measuring tool! It is incredible sensitive to clicks and pops. Sudden pitch or amplitude or filter changes jumps will be detected. So all sudden jumps from one value to another are to be avoided, and this can be achieved by transitions. Transitions from one value to an other, in pitch, amplitude and filter frequency.

For this goal, the same transition system is chosen for pitch, amplitude and filter frequency.

kpchline   transeg   ioldpch, i(<portamentopitch>)*idur, -(i(<pitchenvelopetype>)), inewpch, idur - i(<portamentopitch>)*idur, i(<pitchenvelopetype>), inewpch

kcutline  transeg   ioldfrq, i(<portamentofilter>)*idur, -(i(<filterenvelopetype>)), inewfrq, idur - i(<portamentofilter>)*idur,  i(<filterenvelopetype>), inewfrq

kampline  transeg   ioldamp, i(<portamentoamp>)*idur, -(i(<ampenvelopetype>)), inewamp, idur - i(<portamentoamp>)*idur, i(<ampenvelopetype>), inewamp

Here are 3 sounding examples and what they look like as FrozenObjects. Each time the same block of 5 notes, showing different portamento times and portamento envelope types (slow <--> fast) for pitch, amplitude and filter cutoff frequency. The last note is a standalone ('normal') note:

Example 1

FrozenTies1

Example 2 slightly different settings

FrozenTies1

Example 3 where notes have a longer release time

FrozenTies1


I found it to be useful to have a few bigger 'building blocks' available when building Blue Instruments. A few readymade modules that represent a complete idea, like an ADSR, a filter, a tremolo and a vibrato unit. Reminding of the analogue synthesizers and their modules like VCF, VCA, LFO and the like. I've build a few Blue Modules. They are not exactly 'plug-and-play' and you always have to do some re-coding to make them part of your instrument. But is is a good start. They are called Blue Modules, and they can be found here: https://github.com/tjingboem/Blue-modules

One of these Modules is the TiedNotes Module.There are several TiedNotes Modules; one with a linear ADSR, another with an exponential ADSR and one with an exponential ADSR where the release continues after the the duration of the note- the Midi behavior. These Modules all include the ADSR that they need to function, and the can be foud here: https://github.com/tjingboem/Blue-modules/tree/main/dynamics

TieModule

A Blue file is also available. This particular TiedNotes Module contains another Blue Module, the ADSR Module, that, of course, can be replaced with an ADSR of your liking; I like this particular ADSR because the attack can be set to 0 and not 0.001, so i use this one.

There is a caveat when working with Csounds' Tied Note system: not all oscillators have the re-initialization system implemented yet. The pvs streaming opcodes, soundfont (sfplay and the like), ATS opcodes and a few more do not have this feature (yet). But all filters are capable of skipping the re-initialization.

Clone this wiki locally