Developing a fully featured multieffects unit in Csound

by Josep M Comajuncosas

Printer friendly

This article presents one of the most complex Csound devices I've evere designed, namely a multieffects with GUI capable of handling up to 8 simultaneous effects with flexible routing capabilities. The Csound code (for CsoundAV) is freely available at my website

Don't expect it to replace any commercial gear, it is pretty demanding and requires sr=kr, so most of the Csound speed benefits are lost.

Goals

Provide a GUI for any Csound processor
Provide a realtime multieffects with flexible routing and feedback capabilities

Provide an attractive multieffects easy enough to be used by non-Csounders

 

Yet to do

Add a menu to choose the input signal and allow stereo and multichannel input/output (mono by now)
Add much more effects! (just 8 by now)
Add snapshots for the whole machine
Add customizable automatisation, save a performance for later recall, add a timeline editor...

 

Working with the Multixf

This step by step tutorial will show you how easy is to work with the machine. In fact no Csound knowledge at all is necessary for that!

first make sure all the files are in the Csound directory or in the path

drag&drop MultiFx.csd onto the Csound icon, then select the audio driver if required

the main window apperars, nothing sounds by now
to get any sound you must, at least, route the input (which is assumed to go to slot 1) to the output (taken from slot 8). The routing matrix works like in AudioMulch: files are inputs and columns outputs, so you must click on the [1,8] button (1). You must also activate the default empty effects (2,3). Notice the Vu-meters and the routing lights in each slot
let's try something different...apply a bit reduction to the input with the Cruncher effect. To do that first select the effect from the Fx1 box, then activate it with the button on the right Now the GUI for the effect appears in the Fx1 box, set bit depth to 50% and foldover to 0% just to play a bit with the controls
reroute the first slot to slots 2 and 3 in parallel and then route their outputs to slot 8. Now the actual signal routing is

1(in)->2->8(out) and 1(in)->3->8(out)

apply different comb filters to both slots and postprocess them with a parametric Eq in slot 8, for example with the following values

Much more complex configurations are possible of course, and once the MultiFx machine will be fully loaded with my expected 100 effects you can imagine its possibilities! Now it's up to you to experiment with it...


A more technical insight into the Csound MultiFx machine

I'll briefly describe how the MultiFx works and what does it do when you activate a new effect for example. Some tricks were necessary, sometimes for convenience, I encourage you to study the source code.

 

Main data structures

 

za space

1 single location to store the dry audio signal to be sent to the multieffects

 

zk space

128 locations, to allow up to 16 (16*8=128) different controls (knobs, buttons, sliders) for each effect

 

specific tables

200 giFxfnBypass, size 8 stores the active/bypass booleans
201 giFxRecvCount, size 8 stores the number of input channels for each slot
202 giFxSendCount, size 8 stores the number of output channels for each slot
203 giFxfnChnls, size 8 stores the processed signal at each slot output
204 giFxfnChnlsIn, size 8 stores the inputs to each slot
205 giFxfnChnlsOut, size 8 stores the output of each slot
206,207 giRftFiles, size 64 stores the active booleans for the routing matrix, in 8 files of 8
208 giRftCols, size 64 stores the active booleans for the routing matrix, in 8 columns of 8
209 giRftFilesh, size 64 stores the booleans of reception (8 each slot)
210 giRftColsh, size 64 stores the booleans of emission (8 each slot)
211 giFxftSel, size 8 stores the preset number of each slot
212 giFxftPrevSel, size 8 stores the previous preset number of each slot
213 giFxftControllers, size 128 stores all the controllers like the 128 zk locations

I think tables 209 and 210 are not used actually, as well as 213 (?)

 

Program flow

 

Throughout the performance: instrs 1,2,3 are active

instr 1 : default effect and control routing
instr 1 is called 8 times at startup.
each instance activates the default effect for one of the 8 slots
stores the values of the controllers of each effect into the zk space
every 0.1 seconds, update the vectors of active input (table 206) and output (table 208) channels according to the routing matrix state, and
update the active/bypass table (200)

instr 2 : effects container and signal routing
receives the raw signal from the za channel 0
for each slot:
skip if the active/bypass button is set to bypass, otherwise...
get the vector of active input channels (except for slot 1, skip to the end if its sum equals 0)(table 201)
get the vector of active output channels (except for slot 8, skip to the end if its sum equals 0)(table 202)
get the vector of all the audio channels (tabñe 203)
compute the actual effect input as the scalar product of the vector of active input channels and the vector of audio channels, divided by the number of active channels
scale the result by the input gain (set by the gain slider)
compute and display the input RMS level
write the signal into the effect input table (204)
get the processed signal from the effect output table (205) and scale it according to the output gain slider
compute and display the input RMS level

outputs the processed signal from slot 8 to the main output

instr 3 : audio input
generates the signal to be processed and sends it to the za channel 0

 

Actions performed when a new effect is selected: instr 12 is activated

instr 12
Updates the menu
turns the instrument off

 

Actions performed when the effect is loaded

instr 4 to 11 (depending on the slot) is activated
updates the list of effects (table 211)
deactivates the previous effect instrument
activates the new effect instrument
updates all the effect interfaces
turns the instrument off

 

Effect instruments

each effect is defined in 8 instruments numbered as
20+100*i*Fx_number where 0<=i<=7

for example, the default effect (0) is defined in instruments
20,120,220,320,420,520,620,720

this offset gives space for 100 different effects, and allows a proper routing from low to high numbered effects without added 1-sample delays.

Each instrument is called from the GUI with the slot number as its p4 field, which is used to properly read and write in the appropiate tables (204 and 205).
For example, the default (bypass) effect is just four lines of code

andx init p4-1
aFxIn tab andx,giFxfnChnlsIn
aFxOut=aFxIn
tabw aFxOut,andx,giFxfnChnlsOut

 

A look at the effects themselves

 

Default

 

Each empty box shows RMS input level and routed input channels (top left hand corner) and RMS output level and routed output channels (bottom right hand corner). There are also input and output gain faders calibrated from -144dB to about +6dB, and gain at 3/4 of 0dB (the defaul level). The button deactivates the effect, it works as a bypass, ie. it is no longer computed to save some Cpu.

 

Cruncher

 
Cruncher is useful for extremely lo-fi effects. It performs bith depth reduction (16 to 4 bits) and adds artificial aliasing (downsampling up to a factor of 16).

 

Direct Convolver

 

Direct Convolver is likely to be rewritten soon. It performs direct convolution of the input with a 16-point impulse response randomly modified with the IR mod knobs.

 

Feigenbaum Ringmod

 

Another unconventional effect. The input is ring modulated with an indexed iterated function, the formula is ax = sin(ar * ax) iterated four times and scaled. Selecting different indexing frequencies, amplitudes and initial condicions a variety of effects is obtained, ranging from periodic or chaotic vibratos to richly harmonic or even chaotic distortion. The indexed area helps to find periodic windows.

 

Morpheable filter

 

The morpheable filter crossfades between the lowpass, bandpass and highpass outputs of a two pole state variable filter. The Cutoff/Morph area allows simultaneous control of the cutoff frequency and the crossfade level. Resonance is adjusted separately.

 

variable Comb/Allpass

 

Comb and allpass filters with dynamic control over the attenuation and the delay time. As the original opcodes are buggy it is implemented in orchestra code. The delay taps use cubic interpolation. Notice it consumes larges amounts of memory as each effect allocates 20 secs.

 

Zoelter's Parametric Equalizer

 

Zoelter's equalizer is a frontend of the pareq opcode, with added tanh() soft saturation.

 

Rober Bristow Johnson's Parametric Equalizer

 

A more sophisticated parametric equalizer with Lowpass, Highpass, Band, Notch, Low and High Shelf modes and frequency, gain, Q and slope factor controls.

 

BreakBeat Cutter

 

BreakBeat Cutter is a frontend of the bbcutm opcode. Notice that the "apply changes" button must be pressed each time you want to reinitialize the opcode with new i-time parameters, ie. they cannot be continuously modified.