Effect Sends
What Are Sends?
A send
in monolith is pretty much what a send would be in
your typical DAW. It's a thing that allows you to send one
or more audio signals to some sort of audio effect to be
processed. Common examples of this include a reverb and
delay.
The gist of making a send in monolith involves making a send cable, writing stuff to that send cable, then sending the output of that cable to some kind of audio processor.
The Nitty Gritty Bits
Usually sending is done with scheme code, which calls runt code, which makes calls to graforge C library.
At the graforge level, a send is a cable containing an audio buffer that gets thrown around a patch after it has been created.
The "send" aspect is the unique part of all this. When a signal gets sent to the send cable, it's really taking the buffer contents of the signal, and adding it the contents of send cable buffer. The send amount attenuates the signal being copied.
By the time, the send cable reaches the processor, the buffer contains the sum of all signals ready to be processed.
When the patch goes around again to compute another block of audio, the send cable buffer is zeroed out before anything is written to it, and the process begins again.
Example: A reverb Send
Say you want to make a reverb send.
The first thing you need to do is create a send cable, and
save it to a register. A new cable can be created with
cabtmp
. cabtmp
creates a cable with a buffer. to prevent
buffers from being overwritten, they must be held with
bhold
(if the buffer is not from the pool, this will be
ignored). cabset
stores the cable in the register
REG-REV
.
(define REG-REV 0)
(define (rev-init)
(cabset (bhold (cabtmp (const 0))) (param REG-REV)))
Throw a signal with rev-throw
. This function will pop
the last signal on the stack and mix it into the send
cable.
The actual sending is done with a thing called cthrow
.
(define (rev-throw amt)
(cthrow
zz
(amt)
(lambda () (cabget REG-REV))))
Finally, process the values from the send cable, and clear
the send cable. Cables must be cleared with cabclr
,
otherwise buffers from the buffer pools will be unable
to be reclaimed. cabclr
is mixes the behavior of cabget
and bunhold
. It expects a register ID where the cable is,
and not the cable itself.
(define (rev-process)
(cabget REG-REV)
(cabget REG-REV)
(revsc zz zz (param 0.95) (param 10000))
(bdrop)
(dcblock zz)
(mul zz 0.5)
(cabclr REG-REV))
Automatically making send cables with mkcab
The scheme function monolith:mkcab
can be used
to create a cable and assign it to a free
register.
The following can be used to create an initial cable
and store the register address to a REV-CAB
:
(set! REV-CAB (monolith:mkcab (lambda () (const 0)) 0))