Real-Time Analog Modeling

Hans Mikelson

csm.bat anmod.orc anmod.sco


Analog modeling has recently become a popular form of synthesis which allows a great deal of expression in performance. This article describes using Csound's analog modeling opcodes, vco and moogvcf. I tested these instruments using Gabriel Maldonado's DirectCsound 2.6 running on a Dell 300 MHz Pentium II computer with an AWE64 Soundblaster value card and Windows 95. I used an Alesis Quadrasynth + Piano as the controller keyboard with control knobs 1 and 2 assigned to continuous controllers 50 and 56.

Command line

The first step in using Csound for real-time performance is to determine an appropriate command line. I use the following command saved in a batch file:

csound -+K -+q -b128 -+p6 -+O %1.orc %1.sco 

The flag -+K with no number following tells DirectCsound to prompt for the desired MIDI input device. The flag -+q with no number following tells DirectCsound to prompt for the desired audio output device. The flag -b128 allows for 128 byte buffers. The flag -+p6 allows for six buffers. After some experimenting I found that setting buffer size to128 bytes and setting the number of buffers to 6 with a 44100 sample rate provided a good compromise between responsiveness and sound quality. The flag -+O suppresses all output for better real-time performance. I like to save this command line as a batch file, csm.bat so DirectCsound can be activated by typing the command:

csm anmod

Analog modeling

Csound maps MIDI channels to instruments so that MIDI channel 1 controls instr 1, MIDI channel 2 controls instr 2 etc. The first step is to obtain the MIDI values for velocity and pitch. The veloc opcode returns the MIDI note velocity. This is then passed through a table to allow for different velocity response curves. The opcode cpsmidi returns the MIDI note frequency.

ivel   veloc                              ; Velocity

iamp   tablei   ivel, 3                   ; Convert to amplitude

ifqc   cpsmidi                            ; Get the note in cps

The next step is to generate an amplitude envelope. For real-time performance the linenr envelope is used for the amplitude envelope since it allows for midi controlled note length. In this case I use it as a de-click envelope.

;               Amp   Rise, Dec, AtDec

kamp   linenr   iamp, .05,  .05, .05      ; Declick envelope

The next step is to read from the MIDI continuous controllers. In this instrument I use continuous controller 50 to modulate frequency and continuous controller 56 to modulate resonance. The opcode midictrl is used to read the MIDI continuous controller value. I use a table look-up to change the range of the continuous controller for frequency. I also generate an exponential envelope for sweeping the filter.

; Low pass filter frequency

kfce   expseg   .2, .1, 1, .2, .8, .1, .8 ; Fco envelope

kfcs   midictrl 50, 10                    ; Fco controller

kfco   tablei   kfce*kfcs, 2              ; Change scaling form 0-127 to 20-20000

; Low pass filter resonance

krzs   midictrl 56, 20                    ; Q controller

krez   =        krzs*.01                  ; Adjust 0-127 to 0-1.27

The final step is to use the analog modeling opcodes. The vco opcode below is used to generate a sawtooth wave. This signal is then passed through the moogvcf four pole resonant low pass filter before output using outs.

;             Amp Fqc   Wave PW   Sine Delay

asig   vco     1, ifqc, 1,   1,   1,   .1     ; Oscillator 1

aout   moogvcf asig, kfco,   krez               ; Filter 1

Stereo Pad

Instrument 2 simulates an analog stereo pad. Detuned frequencies are generated for the left and right channels to produce a wide stereo impression.

ifqcl  =        ifqc*.998                 ; Stereo detuning for left oscillator

ifqcr  =        ifqc*1.002                ; Stereo detuning for right oscillator

A low frequency oscillator is used to sweep the cut-off frequency which gives some animation to the sound.

klfo2  oscil    .2, .5, 1                 ; Low frequency sweep

kfc2   tablei   kfce*kfcs*(1+klfo2), 2    ; Change scaling form 0-127 to 20-20000

The resolution of MIDI is only 127 values. This coarse resolution sometimes results in a stepping sound when a control knob is swept. This stepping can be eliminated using the port command to smooth out the control value.

kfco   port     kfc4, .01

In this instrument I use MIDI controller 1, the mod wheel to add vibrato to the sound.

kmw    midictrl 1                         ; Modwheel

klfo1  oscil    kmw*.0001, 6, 1

kvbr   =        1+klfo1

The vco opcode is used next to generate three sawtooth oscillator signals. The third oscillator is added and subtracted from the left and right channels respectively before they are passed through the moogvcf filter.

asig2  vco     1, ifqcl*kvbr*1.01, 1,    1,   1,   iofqc  ; Oscillator 3

;             Amp Fqc              Wave  PW   Sine Delay

asigl  vco     1, ifqcl*kvbr, 1,    1,   1,   iofqc  ; Oscillator 1

aoutl  moogvcf asigl+asig2, kfco, krezm              ; Filter 1

asigr vco      1,  ifqcr*kvbr, 1,   1,   1,   iofqc ; Oscillator 2

aoutr  moogvcf asigr-asig2, kfco, krezm              ; Filter 2

Output is then generated for the left and right channels. This allows for a rich stereo pad sound.

Pulse Width Modulation

The next instrument implements pulse width modulation with portamento. To implement portamento I first initialize a global variable gifqc to 440 in the header of the orchestra. I can than use this variable to store the last frequency. Pitch is swept between the last frequency and the current frequency by the linseg opcode. The time it takes to get to the next frequency depends on how far apart the two frequencies are.

ifqco  init     gifqc                     ; Get the old frequency

ifqc   cpsmidi                            ; Get the note in cps

gifqc  =        ifqc                      ; Update the global frequency

idfqc  =        abs(ifqco-ifqc)           ; Calculate the difference between frequencies

kfqc   linseg   ifqco, .001*idfqc, ifqc, .1, ifqc ; Linear pitch portamento

I next modulate the pulse width with a low frequency sine wave to create a pulse width modulation effect.

klfo1  oscil    .4, kfqc*.005, 1

kpw    =        1+klfo1

The rate of modulation depends on the pitch of the instrument so higher pitches have faster modulation rate.

Other Filters

Some of Csound's other filters can be used in place of moogvcf. The opcodes rezzy, lowres, lowresx, vlowres and even pareq can produce analog sounding filters. I provide some examples of these in the orchestra file. You could also create your own filters using biquad.


Using analog modeling in real-time gives an opportunity to really test the quality of the opcodes. The instruments presented here have an analog sound and the moogvcf filter has a good self oscillation sound. For comparison purposes I used a Waldorf Pulse which has an all analog signal path and an analog four pole resonant low pass filter. In terms of analog sound quality the Pulse sound is fatter, warmer, more up front and grittier. The Csound analog modeling opcodes are fairly fat sounding and are extremely flexible. This type of flexibility can only be approached with the most expensive modular analog synthesizers.