Csound

Csound is an open-source audio programming language for sound synthesis and music composition. Though its historical use score-driven, more recently it has been used for interactive audio in real-time contexts. Csound is one of the four main languages supported by Bela, thanks to the contributions of Bernt Isak Wærstad, Alex Hofmann, Victor Lazarini, and Bela developer Guilio Moro.

This page is adapted from a Bela and Csound tutorial written by Bernt Isak and Alex Hofmann, and provides an introduction to coding interactive Bela projects with Csound.

Table of contents

  1. What is Csound?
  2. Writing a Csound instrument
    1. A simple instrument
  3. Csound and Bela
    1. Getting started
    2. Bela inputs and outputs in Csound
    3. Building a simple effect processor using the COSMO DSP Library
    4. Building a MIDI controlled synthesizer
    5. Good programming practices for Csound on Bela
  4. Projects made with Csound and Bela
    1. Augmented Tenor-Saxophone (COSMO)
    2. Trampeklang
    3. Electroacoustic guitar (COSMO)
    4. The Half-Physler

What is Csound?

Csound is an open source 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 III Software developed by Max Matthews in 1961.

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, meaning that Csound source files written decades ago will still run 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, including Android and iOS. Csound can also be called through other programming languages such as Python, Lua, C/C++, Java, and is supported by the Bela platform.

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.

The fun starts in the <CsInstruments> section, where we start 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 called opcodes. 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 simple instrument

Here we will start right into writing a first simple instrument which uses a pink noise generator, a simple sine oscillator, two LFOs and an opcode for stereo panning. The output of an opcode is assigned to a variable; for example aNoise is the holder for the audio signal generated by the pinker opcode.

Csound has specific variable types for the data to hold. The first letter of a variable name sets the type: in this case, aNoise expects an a-rate, or audio, signal. Other types you will often find are k-rate (control rate) signals (which are updated less frequently to save computing power), and i-rate signals, which can only be set once when the instrument is instantiated.

In the CsScore section instruments can be called by their name or number. In this case instr 1 is called 4 times with different settings for p4 and p5. This is the most straight forward way to run instruments, although other options like triggering by MIDI events and triggering live-events from within other instruments is worth checking out.

<CsoundSynthesizer>

<CsOptions>
-odac -iadc
</CsOptions>

<CsInstruments>

sr = 44100
ksmps = 8
nchnls = 2
0dbfs = 1.0

instr 1
  aNoise pinker                 ; pink noise
  aSin poscil 0.4, p4           ; sine oscillator
  aLFO1 lfo 0.7, p5, 3          ; LFO - square (unipolar)
  aLFO2 lfo 0.7, .3, 2          ; LFO - square (bipolar)
  aSig = (aLFO1 * aNoise) + (aLFO2 * aSin)  ; crazy mixing
  aSigL, aSigR pan2 aSig, aLFO1-aLFO2       ; insane panning
  outs aSigL, aSigR             ; stereo output
endin

</CsInstruments>

<CsScore>
;Ins St Dur sinFq lfoFq
  i1 0  2    250    2
  i1 +  2     50   10
  i1 +  2   1500   .5
  i1 +  1     50   10
</CsScore>

</CsoundSynthesizer>

Csound and Bela

Running Csound on Bela came from the COSMO-project (Csound On Stage: Music Operator), a project devoted to making hardware and software frameworks for making embedded, standalone Csound instruments to use on stage. The COSMO team originally worked with Raspberry Pis but this always required some custom hardware (to achieve better sound quality, acceptably low latency, and individual controller inputs). These music-specific hardware requirements are already present on Bela.

Getting started

Csound is now fully supported in the Bela IDE. To create a new, blank Csoun project, go to the Project Explorer tab, click New project, and select Csound as the project type. Then, give your project a name, and click Create project.

Bela IDE with the Csound template project loaded

Bela inputs and outputs in Csound

To communicate with the analog channels on the Bela, we’ll use the Csound channel system.

The analog input channels are named analogIn0 to analogIn7, and analog output channels are analogOut0 to analogOut7. To read values, we use the chnget opcode, and to write values we’ll use the chnset opcode. (Note that these are a-rate channels, so a downsampling is needed if you want to use the input values as k-rate control signals.)

	;------------------------------------------------------
	;  	Simple AM synth with analoge in and out
	;------------------------------------------------------

	instr 1

		; Analog in 0 controls carrier frequency
		aCarFreq chnget "analogIn0"
		aCarFreq = (aCarFreq * 1000) + 50
		kCarFreq = k(aCarFreq) ; downsampling from a-rate to k-rate

		; Analog in 1 controls modulator frequency
		aModFreq chnget "analogIn1"
		aModFreq *= 100
		kModFreq = k(aModFreq)

		; Analog in 2 controls modulator amount
		aAM_vol init 1
		aAM_vol chnget "analogIn2"


		; Modulator
		aMod oscil aAM_vol*0.5, kModFreq
		aMod += 0.5

		; Carrier with envelope
		kEnv adsr 0.1, 0, 0.8, 0.3
		aCar poscil 0.8*kEnv, kCarFreq
		aOut = aCar * aMod

		; Set LED to blink in time
		; with modulation frequency

		chnset aMod, "analogOut0"

		outs aOut, aOut

	endin

Building a simple effect processor using the COSMO DSP Library

The cosmo-dsp repository is a library of ready-made audio effects, such as Reverb, Delay, Distortion, Filters and so on. All effects are set up as independent modules that can be combined to a custom setup of effects. To make it as 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 an include statement:

#include "Reverb.udo"

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 ).

Since all arguments are normalized, we can directly use the analogIn values to control the paramters of the effect. Here is a complete example of a Reverb effect where the dry/wet mix is controlled by a potentiometer connected to the first analog in of a Bela system:

	<CsoundSynthesizer>
	<CsOptions>
	-m0d
	</CsOptions>
	<CsInstruments>
	ksmps  	= 16
	0dbfs	= 1
	nchnls 	= 2

	#include "../DSP-Library/Effects/Reverb.udo"

	instr 1
		aL, aR ins

		aPot0 chnget "analogIn0"
		kMix = k(aPot0)

		; 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>

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

Building a MIDI controlled synthesizer

One advantage of Csound is that it’s really quick to write a MIDI synthesizer. This comes in very handy in combination with Bela - just connect any class-compliant MIDI keyboard to Bela’s USB port, load a Csound instrument, and use your MIDI keyboard to play your Csound project like a synth.

In <CsOptions> you can select the MIDI device you’d like to use to control Csound. By default the MIDI channel defines the instrument number that’s called for each pressed key, but this can be changed by setting massign.

To avoid CPU overload by triggering too many voices in parallel, the maxalloc option allows to restrict the maximum number of voices. In this example, it’s set to 4 voices:

<CsoundSynthesizer>
<CsOptions>
-Mhw:1,0,0 -+rtmidi=NULL --daemon
</CsOptions>
<CsInstruments>

; Initialize global variables.
sr = 44100
ksmps = 8
nchnls = 2
0dbfs = 1

seed 0 ; init random function
maxalloc 1, 4 ; restrict to maximum 4 voices

;------------------------------------------------------
; Instrument will be played by MIDI notes on Channel 1
;------------------------------------------------------
instr 1
	iFreq cpsmidi
	iAmp ampmidi 0.3

	; Three detuned sawtooth oscillators
	aOut1 = vco2(iAmp, iFreq)
	aOut2 = vco2(iAmp, iFreq*1.004)
	aOut3 = vco2(iAmp, iFreq*0.995)

	; Envelope
	aOut = aOut1 + aOut2*0.5 + aOut3*0.5
	aEnv linsegr 0, 0.01, 0.1, 0.2, 0

	; Filter LFO and envelope
	kLFO = lfo(50, 1.2, 0)
	aFiltEnv linsegr 100, 1.2, 1000, 0.2, 0

	; Korg35 resonant low-pass filter
	aOut = K35_lpf(aOut, aFiltEnv+kLFO, 9.4, 0, 1)

	; Voice panning
	iPan random 0.2, 0.8;
	aOutL, aOutR pan2 aOut, iPan

	; Output
	outs aOutL*aEnv, aOutR*aEnv
endin


</CsInstruments>
<CsScore>
</CsScore>
</CsoundSynthesizer>

Good programming practices for Csound on Bela

In a real-time audio system like Bela, accessing hardware other than the audio device should be avoided (printing to console, reading writing to harddisk, etc). In Csound, printing and other console messages can be suppressed by adding -m0d to the <CsOptions> section. Loading files from disk should also be avoided (for instance, loading audio files with diskin2), and should instead be loaded into memory with function table generators (see examples below). Using reinit to re-initialize i-rate variables should also be avoided as this can cause a mode switch, which normally leads to problems with real-time performance.

Below is an example of how to load and playback a file from memory using function table and the loscil opcode (see https://csound.com/docs/manual/loscil.html for a thorough explanation):

;------------------------------------------------------
;	Playback of a stereo sound file (looping)
;------------------------------------------------------

instr 1
	iftable = 1
	asigL, asigR loscil .8, 1, iftable, 1, 1

    outs asigL, asigR
endin

</CsInstruments>
<CsScore>
i1 0 86400
f1 0 0 1 "soundfile.wav" 0 0 0
</CsScore>

Projects made with Csound and Bela

Augmented Tenor-Saxophone (COSMO)

Based on the effects collection in the COSMO library, [Alex Hofmann]((https://iwk.mdw.ac.at/alex-hofmann/) built a Tenor-Saxophone with integrated live electronics. Inside the bell of the instrument he mounted a Bela unit,with speaker and microphone, all powered by a regular 5V mobile phone charging battery. On Bela a Csound patch is running that processes his playing in real time, either by adding modulation effects or by live-sampling and playback.

Augmented Tenor-Saxophone

The structure of the saxophone part of the 12 minute performance was chosen by an algorithm, which randlomly picks voice samples with instructions out of three categories (tempo, dynamics, tonal material). Verbal instructions such as “Fast, loud, three tones!” give cues to the player but are also hearabel for the audience. Furthermore, this setup allows the performer to move freely on stage or even walk into the audience, as all live-electronic parts are inside the saxophone. A full version of a 12 minute performance with this augmented Tenor-Saxophone at the Linux Audio Conference 2018 can be found here.

A video with excerpts from a performance with the augmented Tenor-Saxophone at the Linux Audio Conference 2018:

Trampeklang

Trampeklang is an interactive sound installation for kids commisioned by Oslo Philharmonic Orchestra. It was designed and built by Bernt Isak Wærstad and Peter Baden using custom built wooden platforms with velostat material for pressure sensing and Csound for triggering and playback of different sounds (from a sound back chosen by the operator). Everything in this installation ran on Bela.

Trampeklang

A short video showing Trampeklang in use during Oslo Philaharmonic kid’s day:

Electroacoustic guitar (COSMO)

Bernt Isak Wærstad used DIY electronics and custom processing software written in Csound (COSMO) combined with an acoustic guitar to create a new electroacoustic instrument, extending the traditional guitar and exploring the cross-sections between electronic and acoustic timbres. The instrument was first used for a concert at the MultiNO festival in Oslo in January 2018 and have later been presented through a performance at the NIME conference at Virginia Tech in June 2018.

The Half-Physler

The Half-Physler is a hybrid acoustic-virtual instrument. A physical model of a tube resonator is running on a Bela Mini, whereas a clarinet reed with a bending sensor together with an actuator is used as the excitation mechanism similar to real single-reed instruments. The physical model is provided as an opcode for Csound. The performer can control the coupling between the reed and the virtual tube by pressing the reed against the shaker. A slider and potentiometers on the 3D printed enclosure allow to shape the tube-resonator in a way beyond the possibilities with real acoustic instruments, such as morphing a cylinder into a cone.

The Half-Physler was developed at the Department of Music Acoustics at the University of Music and Performing Arts Vienna.