Skip to content

modmatrix

Modulation matrix opcode with optimizations for sparse matrices.

The opcode can be used to let a large number of k-rate modulator variables modulate a large number of k-rate parameter variables, with arbitrary scaling of each modulator-to-parameter connection. Csound ftables are used to hold both the input (parameter) variables, the modulator variables, and the scaling coefficients. Output variables are written to another Csound ftable.

Syntax

modmatrix iresfn, isrcmodfn, isrcparmfn, imodscale, inum_mod, \
          inum_parm, kupdate

Initialization

iresfn -- ftable number for the parameter output variables

isrcmodfn -- ftable number for the modulation source variables

isrcparmfn -- ftable number for the parameter input variables

imodscale -- scaling/routing coefficient matrix. This is also a csound ftable, used as a matrix of inum_mod rows and inum_parm columns.

inum_mod -- number of modulation variables

inum_parm -- number of parmeter (input and output) variables.

The arguments inum_mod and inum_parm do not have to be set to power-of-two values.

Performance

kupdate -- flag to update the scaling coefficients. When the flag is set to a nonzero value, the scaling coefficients are read directly from the imodscale ftable. When the flag is set to zero, the scaling coefficients are scanned, and an optimized scaling matrix stored internally in the opcode.

For each modulator in isrcmodfn, scale it with the coefficient (in imodscale) determining to what degree it should influence each parameter. Then sum all modulators for each parameter and add the resulting modulator value to the input parameter value read from iscparmfn. Finally, write the output parameter values to table iresfn.

The following tables give insight into the processing performed by the modmatrix opcode, for a simplified example using 3 parameter and 2 modulators. Let’s call the parameters "cps1", "cps2", and "cutoff", and the modulators "lfo1" and "lfo2".

The input variables may at a given point in time have these values:

cps1 cps2 cutoff
isrcparmfn 400 800 3

... while the modulator variables have these values:

lfo1 lfo2
isrcmodfn 0.5 -0.2

The scaling/routing coefficients used:

imodscale cps1 cps2 cutoff
lfo1 40 0 -2
lfo2 -50 100 3

... and the resulting output values:

cps1 cps2 cutoff
iresfn 430 780 1.4
lfo2 -50 100 3

The output value for "cps1" is calculated as 400+(0.540)+(-0.2-50), similarly for "cps2" 800+(0.50)+(-0.2100), and for cutoff: 3+(0.5-2)+(-0.23)

The imodscale ftable may be specified in the score like this:

f1  0  8  -2  200 0 2 50 300 -1.5

Or more conveniently using ftgen in the orchestra:

gimodscale ftgen 0, 0, 8, -2, 200, 0, 2, 50, 300, -1.5

Obviously, the parameter and modulator variables need not be static values, and similarly, the scaling routing coefficient table may be continuously rewritten using opcodes like tablew.

Examples

Here is an example of the modmatrix opcode. It uses the file modmatrix.csd.

Example of the modmatrix opcode.
<CsoundSynthesizer>
<CsOptions>
; Select audio flags here according to platform
; Audio out   Audio in
;-odac           -iadc    ;;;RT audio I/O
; For Non-realtime ouput leave only the line below:
 -o modmatrix.wav -W ;;; for file output any platform
</CsOptions>
<CsInstruments>

        sr      =       44100
        kr      =       441
        ksmps   =       100
        nchnls  =       2
        0dbfs   =       1

; basic waveforms
giSine  ftgen   0, 0, 65537, 10, 1      ; sine wave
giSaw   ftgen   0, 0, 4097, 7, 1, 4096, -1      ; saw (linear)
giSoftSaw ftgen 0, 0, 65537, 30, giSaw, 1, 10   ; soft saw (only 10 first harmonics)

; modmatrix tables
giMaxNumParam   = 128
giMaxNumMod     = 32
giParam_In ftgen 0, 0, giMaxNumParam, 2, 0      ; input parameters table
; output parameters table (parameter values with added modulators)
giParam_Out ftgen 0, 0, giMaxNumParam, 2, 0     
giModulators ftgen 0, 0, giMaxNumMod, 2, 0       ; modulators table
; modulation scaling and routing (mod matrix) table, start with empty table
giModScale ftgen 0, 0, giMaxNumParam*giMaxNumMod, -2, 0         

;********************************************
; generate the modulator signals
;********************************************
        instr 1

; LFO1, 1.5 Hz, normalized range (0.0 to 1.0)
kLFO1   oscil   0.5, 1.5, giSine                ; generate LFO signal
kLFO1   = kLFO1+0.5                             ; offset

; LFO2, 0.4 Hz, normalized range (0.0 to 1.0)
kLFO2   oscil   0.5, 0.4, giSine                ; generate LFO signal
kLFO2   = kLFO2+0.5                             ; offset


; write modulators to table
        tablew  kLFO1, 0, giModulators
        tablew  kLFO2, 1, giModulators

        endin

;********************************************
; set parameter values
;********************************************
        instr 2

; Here we can set the parameter values
icps1   = p4
icps2   = p5
icutoff = p6

; write parameters to table
        tableiw icps1, 0, giParam_In
        tableiw icps2, 1, giParam_In
        tableiw icutoff, 2, giParam_In

        endin

;********************************************
; mod matrix edit
;********************************************
        instr 3

; Here we can write to the modmatrix table by using tablew or tableiw

iLfo1ToCps1     = p4
iLfo1ToCps2     = p5
iLfo1ToCutoff   = p6
iLfo2ToCps1     = p7
iLfo2ToCps2     = p8
iLfo2ToCutoff   = p9

        tableiw iLfo1ToCps1, 0, giModScale
        tableiw iLfo1ToCps2, 1, giModScale
        tableiw iLfo1ToCutoff, 2, giModScale
        tableiw iLfo2ToCps1, 3, giModScale
        tableiw iLfo2ToCps2, 4, giModScale
        tableiw iLfo2ToCutoff, 5, giModScale

; and set the update flag for modulator matrix 
; ***(must update to enable changes)
ktrig   init 1
        chnset  ktrig, "modulatorUpdateFlag"
ktrig   = 0

        endin

;********************************************
; mod matrix
;********************************************
        instr 4

; get the update flag
kupdate chnget  "modulatorUpdateFlag"           

; run the mod matrix 
inum_mod        = 2
inum_parm       = 3
        modmatrix giParam_Out, giModulators, giParam_In, \
        giModScale, inum_mod, inum_parm, kupdate

; and reset the update flag
        chnset  0, "modulatorUpdateFlag"  ; reset the update flag

        endin

;********************************************
; audio generator to test values
;********************************************
        instr 5

; basic parameters
        iamp    = ampdbfs(-5)

; read modulated parameters from table
        kcps1   table   0, giParam_Out
        kcps2   table   1, giParam_Out
        kcutoff table   2, giParam_Out

; set filter parameters
        kCF_freq1       = kcps1*kcutoff
        kCF_freq2       = kcps2*kcutoff
        kReso           = 0.7
        kDist           = 0.3

; oscillators and filters
        a1      oscili  iamp, kcps1, giSoftSaw
        a1      lpf18   a1, kCF_freq1, kReso, kDist

        a2      oscili  iamp, kcps2, giSoftSaw
        a2      lpf18   a2, kCF_freq2, kReso, kDist

                outs    a1, a2

        endin

</CsInstruments>
<CsScore>

;********************************************
; set initial parameters
;       cps1    cps2    cutoff
i2 0 1  400     800     3

;********************************************
; set modmatrix values
;       lfo1ToCps1 lfo1ToCps2 lfo1ToCut lfo2ToCps1 lfo2ToCps2 lfo2ToCut
i3 0 1  40         0          -2        -50        100        3

;********************************************
; start "always on" instruments
#define SCORELEN # 20 #  ; set length of score

i1 0 $SCORELEN                  ; start modulators
i4 0 $SCORELEN                  ; start mod matrix
i5 0 $SCORELEN                  ; start audio oscillator

e       

</CsScore>
</CsoundSynthesizer>

See also

Miscellaneous opcodes

Credits

By:

Oeyvind Brandtsegg and Thom Johansen

New in version 5.12