Previous: Get started
SNDC files are composed of nodes. A node is an instance of a particular module. A node has a name, a list of inputs and a list of outputs.
Let’s go back to our test.sndc
file:
o: osc {
function: "sin";
freq: 440;
duration: 1;
}
Here, we instantiated a node named o
, instance of the module osc
. The osc
module defines several inputs among which function
, freq
and duration
are
required. In the test file above, we have set the values of those inputs as
follows:
function
is set to the string "sin"
, which tells the node o
to generate
a sinusoidal signal.freq
is set to the number 440, which sets the signal frequency to a
constant 440Hz.duration
is set to the number 1, which tells the node to generate one
second worth of the signal.Let’s experiment a bit and add another node after o
:
o: osc {
function: "sin";
freq: 440;
duration: 1;
}
o2: osc {
function: "sin";
freq: 220;
duration: 1;
}
And play it:
$ sndc_play test.sndc
We can hear a single tone again, but this time at frequency 220Hz. The 440Hz
tone has disappeared despite still being instantiated in the file, and processed
by sndc
.
This is because sndc
only plays the output of the last node of the file,
ignoring all other nodes above. So, how can we play both sounds at once?
To play both sounds at once, we are going to need to mix them, with the mix
module.
First, let’s ask sndc
what the inputs and outputs of the mix
module are:
$ sndc -h mix
[effect] mix - Mixer for up to 8 input buffers
Inputs:
input0 [BUFFER] [REQUIRED]
input #0
input1 [BUFFER] [OPTIONAL]
input #1
input2 [BUFFER] [OPTIONAL]
input #2
input3 [BUFFER] [OPTIONAL]
input #3
input4 [BUFFER] [OPTIONAL]
input #4
input5 [BUFFER] [OPTIONAL]
input #5
input6 [BUFFER] [OPTIONAL]
input #6
input7 [BUFFER] [OPTIONAL]
input #7
gain0 [BUFFER | FLOAT] [OPTIONAL]
gain #0, def 1
gain1 [BUFFER | FLOAT] [OPTIONAL]
gain #1, def 1
gain2 [BUFFER | FLOAT] [OPTIONAL]
gain #2, def 1
gain3 [BUFFER | FLOAT] [OPTIONAL]
gain #3, def 1
gain4 [BUFFER | FLOAT] [OPTIONAL]
gain #4, def 1
gain5 [BUFFER | FLOAT] [OPTIONAL]
gain #5, def 1
gain6 [BUFFER | FLOAT] [OPTIONAL]
gain #6, def 1
gain7 [BUFFER | FLOAT] [OPTIONAL]
gain #7, def 1
Outputs:
out [BUFFER] output buffer w/ all inputs mixed
sndc -h <module>
can be used to query the specification of all built-in
modules. In the mix
help above, we can see a list of inputs with their names,
types, whether they are optional or required, and a short description.
We can also see a single output named out
.
Let’s try and print the help for the osc
module that we have used so far:
$ sndc -h osc
[generator] osc - A generator for sine, saw and square waves
Inputs:
function [STRING] [REQUIRED]
waveform: 'sin', 'square', 'saw' or 'input'
waveform [BUFFER] [OPTIONAL]
buffer containing waveform, used when 'input' is specified in 'function'
freq [BUFFER | FLOAT] [REQUIRED]
frequency in Hz
amplitude [BUFFER | FLOAT] [OPTIONAL]
amplitude in unit
p_offset [FLOAT] [OPTIONAL]
period offset, in period (1. = full period)
a_offset [FLOAT] [OPTIONAL]
amplitude offset, a constant that gets added to the resulting signal
duration [FLOAT] [REQUIRED]
duration of resulting signal in seconds
sampling [FLOAT] [OPTIONAL]
sampling rate, def 44100Hz
interp [STRING] [OPTIONAL]
interpolation of the resulting buffer, 'step', 'linear' or 'sine'
param0 [BUFFER | FLOAT] [OPTIONAL]
wave parameter 0
param1 [BUFFER | FLOAT] [OPTIONAL]
wave parameter 1
param2 [BUFFER | FLOAT] [OPTIONAL]
wave parameter 2
param3 [BUFFER | FLOAT] [OPTIONAL]
wave parameter 3
param4 [BUFFER | FLOAT] [OPTIONAL]
wave parameter 4
param5 [BUFFER | FLOAT] [OPTIONAL]
wave parameter 5
Outputs:
out [BUFFER] output signal
There is quite a lot going on here, but we can see only three REQUIRED
inputs:
function
, freq
and duration
, exactly the ones we have used in our test
file. While there is no surprise regarding the type of function
and
duration
, we can see that freq
has BUFFER | FLOAT
as a type: it can accept
either, as we will see later.
Now that we understand better the inputs and output of osc
and mix
modules,
we can try and add a mix
node in our test file, and mix both tones together.
o: osc {
function: "sin";
freq: 440;
duration: 1;
}
o2: osc {
function: "sin";
freq: 220;
duration: 1;
}
m: mix {
input0: o.out;
input1: o2.out;
}
We’ve added a new node named m
at the end of the file, instance of module
mix
. We’ve set two of its inputs: input0
and input1
, but the value we’ve
given them is not a number or a string. It’s a reference to the output of
previous nodes.
If you look at the help for the osc
module above, you will see one output:
out
, of type BUFFER
. In the mix
help, you will see that input0
and
input1
both take in BUFFER
, so this connection is valid: the types match. We
refer to nodes' output with nodeName.outputName
.
Let’s play the file now:
$ sndc_play test.sndc
We can hear both tones together.
At that point, the obvious question probably is, “how do I see the list of
available modules?”. Fortunately, there is a simple command for this, sndc -l
:
$ sndc -l
Available modules:
- debug:
print - Prints input buffer to specified file for plotting/analysis
satwarn - Outputs warning in stderr if input buffer is saturating
- effect:
echo - Produces a series of exponentially decaying echoes
envelop - Apply envelop to input signal
mix - Mixer for up to 8 input buffers
reverb - Implementation of the Freeverb algorithm
slider - Mix 2 input buffers according to a specified gain profile
- filter:
biquad - Bi-quadratic filter, two poles and two zeroes
fft_filter - Generic FFT-based lowpass / highpass filter
filter - Generic lowpass/bandpass/highpass filter
simplelp - Low pass filter using simple and fast diff equation
- generator:
noise - Noise generator
osc - A generator for sine, saw and square waves
- math:
binop - Binary operation between two buffers or numbers
convol - Convolution of an input buffer with a kernel
fft - Compute the fast Fourier transform of input buffer
func - A generator for mathematical functions
ifft - Compute the inverse Fourier transform of input buffers
- sequencer:
drumbox - Simple drum machine that sequences its input samples
keyboard - Melodic sequencer for a given intrument node
layout - A generic layout helper to mix layers together
monoseq - Takes a simple single-voice pattern and generates corresponding buffers of frequency and amplitude to feed into
a mono synthesizer
nodeseq - Executes a node and appends outputs at given times
- util:
note - A simple note to frequency converter
resize - Extend or crop input buffer
reverse - Reverse the input buffer
sampler - External sample buffer loader
var - Variable, copies its input value to its output value
This command returns a list of all available, built-in modules. Each of those
module has an associated help that can be displayed with sndc -h <module>
as
we saw above. The modules are loosely sorted by category: there are generators
which produce a signal, filters
which apply different transformations on the
frequencies of the input signal, effects
with the familiar reverb
, echo
and so on.
Next: A simple police siren