Effect Sends

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