ChaosNoise
Overview
The chaosnoise
algorithm is noise generator that uses
a chaos function to produce sound.
At it's core, chaosnoise is essentially an unstable 2-pole filter with a nonlinearity. In other words, it makes noise doing things DSP engineers work very hard to avoid under normal circumstances.
The underlying chaos function is largely based on the one
found in the Crackle Ugen found in SuperCollider. In this
implementation, however, there is an added rate
parameter
similar to the one found in bitnoise. This
is used to change the tone quality of the algorithm.
Tangled Files
This tangles to chaosnoise.c
and chaosnoise.h
. Defining
SK_CHAOSNOISE_PRIV
will expose the core struct in the
header file.
#include <math.h>
#define SK_CHAOSNOISE_PRIV
#include "chaosnoise.h"
<<macros>>
<<funcs>>
#ifndef SK_CHAOSNOISE_H
#define SK_CHAOSNOISE_H
#ifndef SKFLT
#define SKFLT float
#endif
<<typedefs>>
<<funcdefs>>
#ifdef SK_CHAOSNOISE_PRIV
<<structs>>
#endif
#endif
Struct
Data for ChaosNoise is contained in a struct called
sk_chaosnoise
.
typedef struct sk_chaosnoise sk_chaosnoise;
struct sk_chaosnoise {
<<sk_chaosnoise>>
};
Filter Memory
chaosnoise is technically a 2-pole filter, requiring memory for 2 samples of signal.
SKFLT y[2];
cn->y[0] = init;
cn->y[1] = 0;
Sample and Hold Constants and Parameters
The signal is clocked with a sample and hold generator. This sample and hold will use a fixed-point phasor to keep track of time, similar to the ones found in bitnoise and rline. More details on how this works can be found in these pages.
A 32-bit integer called phs
keeps track of the phase
position.
long phs;
cn->phs = 0;
The constant SK_CHAOSNOISE_PHSMAX
defines the maximum
length (and resolution) of the phasor, set to be
0x1000000
.
#define SK_CHAOSNOISE_PHSMAX 0x1000000L
The constant SK_CHAOSNOISE_PHSMSK
defines the masking
value of the phasor, set to be 0x0FFFFFF
.
#define SK_CHAOSNOISE_PHSMSK 0x0FFFFFFL
The floating point value maxlens
is
SK_CHAOSNOISE_PHSMAX
, converted to seconds. It is used
to calculate the increment amount for the phase position.
When a rate value (in units of Hz, or cycles/second) get
multiplied by this value, the result is a value in units
of phase cycles.
SKFLT maxlens;
cn->maxlens = SK_CHAOSNOISE_PHSMAX / (SKFLT) sr;
Parameters
Chaos
The chaos
parameter is variable that controls the chaos
level. It is typically a value between 1 and 2.
It can be set with sk_chaosnoise_chaos
.
void sk_chaosnoise_chaos(sk_chaosnoise *cn, SKFLT chaos);
void sk_chaosnoise_chaos(sk_chaosnoise *cn, SKFLT chaos)
{
cn->chaos = chaos;
}
SKFLT chaos;
sk_chaosnoise_chaos(cn, 1.5);
Rate
The rate
value controls the rate of computation. This
is a value measure in Hertz.
It can be set with sk_chaosnoise_rate
.
void sk_chaosnoise_rate(sk_chaosnoise *cn, SKFLT rate);
void sk_chaosnoise_rate(sk_chaosnoise *cn, SKFLT rate)
{
cn->rate = rate;
}
SKFLT rate;
sk_chaosnoise_rate(cn, 8000);
Initialization
Initialized with sk_chaosnoise_init
. Sampling rate and an
initial value must be supplied as arguments. The initial
value is a floating point value that expects to be in range
0-1.
void sk_chaosnoise_init(sk_chaosnoise *cn, int sr, SKFLT init);
void sk_chaosnoise_init(sk_chaosnoise *cn, int sr, SKFLT init)
{
<<init>>
}
Computation
A single sample of audio is computed with
sk_chaosnoise_tick
.
SKFLT sk_chaosnoise_tick(sk_chaosnoise *cn);
SKFLT sk_chaosnoise_tick(sk_chaosnoise *cn)
{
SKFLT out;
out = 0;
<<update_phasor>>
<<compute_noise>>
<<copy_to_out>>
return out;
}
First, the phasor value is updated by an increment value,
computed with rate*maxlens
.
cn->phs += floor(cn->rate * cn->maxlens);
If the phasor reaches (or goes above) the end, a new sample gets computed.
This uses the following difference equation:
Where
is the chaos value,
and
is a
nonlinearity set to be 0.05
.
After the output value is computed, the coefficients are updated.
if (cn->phs >= SK_CHAOSNOISE_PHSMAX) {
SKFLT y;
cn->phs &= SK_CHAOSNOISE_PHSMSK;
y = fabs(cn->chaos * cn->y[0] - cn->y[1] - 0.05);
cn->y[1] = cn->y[0];
cn->y[0] = y;
}
The output is always set to be the filter memory variable
y[0]
.
out = cn->y[0];