COSMO Workshop at NIME2019

Welcome to Introduction to effect processing with Csound and the cosmo-dsp library - a workshop at NIME 2019. In this workshop, participants will get a basic introduction to Csound and how they can use the cosmo-dsp library to quickly build simple and more complex effect processing patches. The modular design of the library makes it very quick to set up a complex patch, while at the same time keeping it open for further customisation.

Since Csound is integrable in a multitude of platforms (eg. Win, Linux, Mac, IOS, Android, Bela, Intel Galileo) and also into other programming languages (python, c/ c++, Unity, web, VST/AU (Cabbage), Max/MSP, and more), platforms can easily be interchanged when using Csound based set ups. To top it off, Csound has a guarantee for backwards compatibility (code from 1986 still runs on the latest version from late 2018), so your patches are easy to move in both time and space!


COSMO - Csound On Stage Music Operator from Bernt Isak Wærstad on Vimeo.


Table of contents

What is COSMO?

The COSMO Project (Csound On Stage: Music Operator) is an open-source DIY project providing hardware- and software frameworks for designing and building embedded standalone Csound instruments for on stage use cases.To make this project more accessible to musicians with little or no programming experience, an effect library (named cosmo-dsp ) consisting of readymade “plug-and-play” effect modules was designed. Using Csound code wrapped as UDOs (User Defined Opcodes) and normalized parameter controls (similar to CV in modular synths) allows for a very flexible and easy way of patching effects together using very few lines of code.

What is Csound?

Csound is an audio software and programming language for sound synthesis and composition. It was developed by Barry Vercoe at MIT Media Lab in 1986, but its roots go all the way back to the Music Software developed by Max Matthews at Bell Labs from 1957 and onwards.

Today Csound is developed by a group of core developers with a wider community of volunteers contributing. One of the main principles in Csound development is to guarantee backwards compatibility. You can still run Csound source files from 1986 on the latest Csound release.

Although Csound has a strong tradition as a tool for composing electro-acoustic pieces and traditionally has been used in a non-interactive score driven context, nowadays it is mostly used in a real-time context. Csound can run on various different hardware and software platforms including all major operating systems as well as Android and iOS. Csound can also be called through other programming languages such as Python, Lua, C/C++, Java, etc. and is now also supported on the Bela platform!

Installing Csound and cosmo-dsp

Go to https://csound.com/download.html and download the appropriate installer for your system. Follow the instructions given by the installer. Open the terminal/command line and type in csound. If Csound installed correctly, you should see something like this:

0dBFS level = 32768.0
--Csound version 6.10 (double samples) Dec 21 2017 
[commit: 3bc82359c20c6c35cf0240b9fe8c8fb4ad29ddf4]
libsndfile-1.0.25
Usage:      csound [-flags] orchfile scorefile
Legal flags are:
--help      print long usage options
--version   print version details
-U unam     run utility program unam
-C          use Cscore processing of scorefile
-j N        use N threads in performance
-I          I-time only orch run
-n          no sound onto disk
-i fnam     sound input filename
-o fnam     sound output filename
-b N        sample frames (or -kprds) per software sound I/O buffer
-B N        samples per hardware sound I/O buffer
-A          create an AIFF format output soundfile
-W          create a WAV format output soundfile
-J          create an IRCAM format output soundfile
-h          no header on output soundfile
-c          8-bit signed_char sound samples
-8          8-bit unsigned_char sound samples
-u          ulaw sound samples
-s          short_int sound samples
-l          long_int sound samples
-f          float sound samples
-3          24bit sound samples
-r N        orchestra srate override
-k N        orchestra krate override
-K          do not generate PEAK chunks
-v          verbose orch translation
-m N        tty message level. Sum of:
            1=note amps, 2=out-of-range msg, 4=warnings
            0/32/64/96=note amp format (raw,dB,colors)
            128=print benchmark information
-d          suppress all displays
-g          suppress graphics, use ascii displays
-G          suppress graphics, use Postscript displays
-x fnam     extract from score.srt using extract file 'fnam'
-t N        use uninterpreted beats of the score, initially at tempo N
-t 0        use score.srt for sorted score rather than a temporary
-L dnam     read Line-oriented realtime score events from device 'dnam'
-M dnam     read MIDI realtime events from device 'dnam'
-F fnam     read MIDIfile event stream from file 'fnam'
-R          continually rewrite header while writing soundfile (WAV/AIFF)
-H#         print heartbeat style 1, 2 or 3 at each soundfile write
-N          notify (ring the bell) when score or miditrack is done
-T          terminate the performance when miditrack is done
-D          defer GEN01 soundfile loads until performance time
-Q dnam     select MIDI output device
-z          list opcodes in this version
-Z          dither output
flag defaults: csound -s -otest -b1024 -B4096 -m135

Csound Command ERROR:    insufficient arguments
end of score.		   overall amps:      0.0
    overall samples out of range:        0
0 errors in performance
Elapsed time at end of performance: real: 0.002s, CPU: 0.001s

We have prepared a zip file with the whole cosmo-dsp repository and some examples for the NIME 2019 workshop, which you can download here

Writing a Csound instrument

Csound documents are simple text documents starting with the XML type tag <CsoundSynthesizer> and are then structured into 3 sections: <CsOptions>, <CsInstruments> and <CsScore>

<CsoundSynthesizer>

<CsOptions>
</CsOptions>

<CsInstruments>
</CsInstruments>  

<CsScore>
</CsScore>

</CsoundSynthesizer>

Each section of Csound code has its on syntax and grammar. The first couple of lines in <CsOptions> are mainly some hardware/software settings, which for now we can ignore.

Where the fun starts is in the <CsInstruments> section with defining instruments (or setting up patches). An new instrument is defined between the instr and endin lines (see example below). Instruments are built by combining signal processing modules which are called opcodes in Csound. There are thousands of opcodes available for different kinds of oscillators, filters, envelopes, delays, reverbs, sample manipulation tools and so on. The Csound Reference Manual provides more information and examples for each available opcode.

A very simple Csound instrument

Here is a complete example of a very simple Csound instrument which takes in audio from the sound card, scale it and passes it back out

<CsoundSynthesizer>
<CsOptions>
-iadc0 ; Set up audio in
-odac0 ; Set up audio out
-b128 ; Buffer size
</CsOptions>
<CsInstruments>
ksmps  	= 32 ; Vector size
0dbfs	= 1 ; Set 0dbfs reference to 1
nchnls 	= 2 ; Number of audio channels

instr 1 ; Start a definition of instrument with number 1

    ; Control variable for gaining the signal
    kGain = 0.1 
    
    ; Opcode (ins) for getting stereo sound in
    aL, aR ins  

    aL *= kGain ; Gaining left channel
    aR *= kGain ; Gaining right channel

    ; Opcode (outs) for sending stereo sound out
    outs aL, aR 
    
endin ; End instrument definition

</CsInstruments>
<CsScore>
; Set instrument 1 to run for 86400 seconds (24 hours)
i1 0 86400
</CsScore>
</CsoundSynthesizer>

NB! If you’re not wearing a headset you’ll get a feedback sound - make sure to turn down the volume on your computer!

To run this example, open your terminal/command line, navigate to the example folder you downloaded earlier and type

csound VerySimpleCsoundInstrument.csd

A simple effect processor using the COSMO dsp-library

The cosmo-dsp repository comprises a library of ready-made audio effects (e.g Reverb, Delay, Distortion, Filters etc.). All effects are set up as independendant modules that can be combined to a custom setup of effects. To make it as much plug and play as possible, all arguments are also normalized (0-1) and scaled properly inside the effect so that the user can use them immediately.

To use one of the readymade effects, you first need to download the file containing the desired effect, place it with your csd file and include it using #include like this:

#include "Reverb.udo"

Alternatively you can download the whole repository and include all the effects like this:

#include "cosmo-dsp/DSP-Library/Includes/cosmo-dsp.inc"

Once we have included the effect library, we can use a single line to add any of the available effects like this:

aL, aR Reverb aL, aR, 0.9, 0.5, 0.5 

Here is a complete modified version of the last example, where a reverb effect is applied to the incoming audio signal:

<CsoundSynthesizer>
<CsOptions>
-iadc0 -odac0 -Ma -b128
</CsOptions>
<CsInstruments>
ksmps  	= 32
0dbfs	= 1
nchnls 	= 2

#include "cosmo-dsp/DSP-Library/Includes/cosmo-dsp.inc"

instr 1 
	aL, aR ins

	; Reverb arguments: decay, cutoff, mix
	aL, aR Reverb aL, aR, 0.9, 0.5, 0.5 

	outs aL, aR
endin


</CsInstruments>
<CsScore>
i1 0 86400
</CsScore>
</CsoundSynthesizer>

The name and a quick explanation of the arguments can be found in the header of each .udo file in the COSMO dsp-library (e.g. Reverb.udo ). A full list of all the effects available and their arguments can be found at https://github.com/cosmoproject/cosmo-dsp/blob/master/DSP-Library/README.md.

A simple effect processor with MIDI control

Now that we have added an effect, its time to add some parameter control. To get control data from a MIDI controller (CC), we first need to add the -M flag in the <CsOptions> section:

<CsOptions>
-Ma
</CsOptions>

We can either specify a specific MIDI device by using number or, like here, just use a to open all available MIDI devices

To read in actual MIDI control data, we can use the ctrl7 opcode:

kMIDI_pot ctrl7 1, 64, 0, 1

The first argument is MIDI channel, second the CC number, third minimum value and fourth maximum value. If you don’t know these values, use a MIDI monitor - see Links section.

Since all arguments are normalized between 0 and 1, we’re setting the maximum value to be 1 instead of 127, which is the normal MIDI maximum value. Here is a complete example of a Reverb effect where the dry/wet mix is controlled by a MIDI controller on channel 1 and CC 64.

<CsoundSynthesizer>
<CsOptions>
-iadc0 -odac0 -Ma -b128
</CsOptions>
<CsInstruments>
ksmps  	= 32
0dbfs	= 1
nchnls 	= 2

#include "cosmo-dsp/DSP-Library/Includes/cosmo-dsp.inc"

instr 1 
	aL, aR ins

	kMix ctrl7 1, 64, 0, 1

	; Reverb arguments: decay, cutoff, mix
	aL, aR Reverb aL, aR, 0.9, 0.5, kMix 

	outs aL, aR
endin


</CsInstruments>
<CsScore>
i1 0 86400
</CsScore>
</CsoundSynthesizer>

NB! If you’re not wearing a headset you’ll get a feedback sound - make sure to turn down the volume on your computer!

To run this example, open your terminal/command line, navigate to the example folder you downloaded earlier and type

csound SimpleCOSMOExample.csd

The same approach applies to any of the other effects found at https://github.com/cosmoproject/cosmo-dsp/tree/master/DSP-Library/Effects and you can combine them in any order.

An advanced COSMO effect processing examples

<CsoundSynthesizer>
<CsOptions>
-iadc0 -odac0 -Ma -b128
</CsOptions>
<CsInstruments>
ksmps = 64
nchnls = 2
0dbfs = 1

#include "cosmo-dsp/DSP-Library/Includes/cosmo-dsp.inc"

instr 1
    aL, aR ins

    kModFreq ctrl7 1, 77, 0, 1
    kModFreqMulti ctrl7 1, 78, 0, 1
    kModMix ctrl7 1, 79, 0, 1

    kLPfreq ctrl7 1, 80, 1, 0

    kDlyTime ctrl7 1, 81, 0, 1
    kDlyFeed ctrl7 1, 82, 0, 1
    kDlyMix ctrl7 1, 83, 0, 1 

    kPhaserMix ctrl7 1, 84, 0, 1

    ; Arguments: ModOffset, ModFreq, ModFreqMulti, Mix 
    aL, aR Ampmod aL, aR, 0, kModFreq, kModFreqMulti, kModMix

    ; Arguments: DelayTime, Feedback, Filter, Mix 
    aL, aR TapeDelay aL, aR, kDlyTime, kDlyFeed, 0.5, kDlyMix

    ; Arguments: Cutoff frequency, Resonance, Distortion
    aL, aR Lowpass aL, aR, kLPfreq, 0.3, 0.5

    ; Arguments: Rate, Resonance, Notches, Wave, Mix, Mode 
    aL, aR Phaser aL, aR, 0.2, 0.6, 0, 0, kPhaserMix, 0

    outs aL,aR
endin

</CsInstruments>
<CsScore>
; Set instrument 1 to run for 86400 seconds (24 hours)
i1 0 86400
</CsScore>
</CsoundSynthesizer>
Written on June 3, 2019