| @@ -17,12 +17,63 @@ is can be used to change the tone quality of the algorithm. · 16 unmodified lines |
| 17 | 17 | This tangles to =chaosnoise.c= and =chaosnoise.h=. Defining |
| 18 | 18 | =SK_CHAOSNOISE_PRIV= will expose the core struct in the |
| 19 | 19 | header file. |
| 20 | + |
| 21 | +#+NAME: chaosnoise.c |
| 22 | +#+BEGIN_SRC c :tangle chaosnoise.c |
| 23 | +#include <math.h> |
| 24 | +#define SK_CHAOSNOISE_PRIV |
| 25 | +#include "chaosnoise.h" |
| 26 | +<<macros>> |
| 27 | +<<funcs>> |
| 28 | +#+END_SRC |
| 29 | + |
| 30 | +#+NAME: chaosnoise.h |
| 31 | +#+BEGIN_SRC c :tangle chaosnoise.h |
| 32 | +#ifndef SK_CHAOSNOISE_H |
| 33 | +#define SK_CHAOSNOISE_H |
| 34 | + |
| 35 | +#ifndef SKFLT |
| 36 | +#define SKFLT float |
| 37 | +#endif |
| 38 | + |
| 39 | +<<typedefs>> |
| 40 | +<<funcdefs>> |
| 41 | + |
| 42 | +#ifdef SK_CHAOSNOISE_PRIV |
| 43 | +<<structs>> |
| 44 | +#endif |
| 45 | + |
| 46 | +#endif |
| 47 | +#+END_SRC |
| 20 | 48 | * Struct |
| 21 | 49 | Data for ChaosNoise is contained in a struct called |
| 22 | | −=chaosnoise=. |
| 50 | +=sk_chaosnoise=. |
| 51 | + |
| 52 | +#+NAME: typedefs |
| 53 | +#+BEGIN_SRC c |
| 54 | +typedef struct sk_chaosnoise sk_chaosnoise; |
| 55 | +#+END_SRC |
| 56 | + |
| 57 | +#+NAME: structs |
| 58 | +#+BEGIN_SRC c |
| 59 | +struct sk_chaosnoise { |
| 60 | + <<sk_chaosnoise>> |
| 61 | +}; |
| 62 | +#+END_SRC |
| 23 | 63 | * Filter Memory |
| 24 | 64 | chaosnoise is technically a 2-pole filter, requiring |
| 25 | 65 | memory for 2 samples of signal. |
| 66 | + |
| 67 | +#+NAME: sk_chaosnoise |
| 68 | +#+BEGIN_SRC c |
| 69 | +SKFLT y[2]; |
| 70 | +#+END_SRC |
| 71 | + |
| 72 | +#+NAME: init |
| 73 | +#+BEGIN_SRC c |
| 74 | +cn->y[0] = init; |
| 75 | +cn->y[1] = 0; |
| 76 | +#+END_SRC |
| 26 | 77 | * Sample and Hold Constants and Parameters |
| 27 | 78 | The signal is clocked with a sample and hold generator. This |
| 28 | 79 | sample and hold will use a fixed-point phasor to keep track |
| @@ -33,42 +84,156 @@ found in these pages. · 4 unmodified lines |
| 33 | 84 | A 32-bit integer called =phs= keeps track of the phase |
| 34 | 85 | position. |
| 35 | 86 | |
| 87 | +#+NAME: sk_chaosnoise |
| 88 | +#+BEGIN_SRC c |
| 89 | +long phs; |
| 90 | +#+END_SRC |
| 91 | + |
| 92 | +#+NAME: init |
| 93 | +#+BEGIN_SRC c |
| 94 | +cn->phs = 0; |
| 95 | +#+END_SRC |
| 96 | + |
| 36 | 97 | The constant =SK_CHAOSNOISE_PHSMAX= defines the maximum |
| 37 | 98 | length (and resolution) of the phasor, set to be |
| 38 | 99 | =0x1000000=. |
| 39 | 100 | |
| 101 | +#+NAME: macros |
| 102 | +#+BEGIN_SRC c |
| 103 | +#define SK_CHAOSNOISE_PHSMAX 0x1000000L |
| 104 | +#+END_SRC |
| 105 | + |
| 40 | 106 | The constant =SK_CHAOSNOISE_PHSMSK= defines the masking |
| 41 | 107 | value of the phasor, set to be =0x0FFFFFF=. |
| 42 | 108 | |
| 109 | +#+NAME: macros |
| 110 | +#+BEGIN_SRC c |
| 111 | +#define SK_CHAOSNOISE_PHSMSK 0x0FFFFFFL |
| 112 | +#+END_SRC |
| 113 | + |
| 43 | 114 | The floating point value =maxlens= is |
| 44 | 115 | =SK_CHAOSNOISE_PHSMAX=, converted to seconds. It is used |
| 45 | 116 | to calculate the increment amount for the phase position. |
| 46 | 117 | When a rate value (in units of Hz, or cycles/second) get |
| 47 | 118 | multiplied by this value, the result is a value in units |
| 48 | 119 | of phase cycles. |
| 120 | + |
| 121 | +#+NAME: sk_chaosnoise |
| 122 | +#+BEGIN_SRC c |
| 123 | +SKFLT maxlens; |
| 124 | +#+END_SRC |
| 125 | + |
| 126 | +#+NAME: init |
| 127 | +#+BEGIN_SRC c |
| 128 | +cn->maxlens = SK_CHAOSNOISE_PHSMAX / (SKFLT) sr; |
| 129 | +#+END_SRC |
| 49 | 130 | * Parameters |
| 50 | 131 | ** Chaos |
| 51 | 132 | The =chaos= parameter is variable that controls the chaos |
| 52 | 133 | level. It is typically a value between 1 and 2. |
| 53 | 134 | |
| 54 | 135 | It can be set with =sk_chaosnoise_chaos=. |
| 136 | + |
| 137 | +#+NAME: funcdefs |
| 138 | +#+BEGIN_SRC c |
| 139 | +void sk_chaosnoise_chaos(sk_chaosnoise *cn, SKFLT chaos); |
| 140 | +#+END_SRC |
| 141 | + |
| 142 | +#+NAME: funcs |
| 143 | +#+BEGIN_SRC c |
| 144 | +void sk_chaosnoise_chaos(sk_chaosnoise *cn, SKFLT chaos) |
| 145 | +{ |
| 146 | + cn->chaos = chaos; |
| 147 | +} |
| 148 | +#+END_SRC |
| 149 | + |
| 150 | +#+NAME: sk_chaosnoise |
| 151 | +#+BEGIN_SRC c |
| 152 | +SKFLT chaos; |
| 153 | +#+END_SRC |
| 154 | + |
| 155 | +#+NAME: init |
| 156 | +#+BEGIN_SRC c |
| 157 | +sk_chaosnoise_chaos(cn, 1.5); |
| 158 | +#+END_SRC |
| 55 | 159 | ** Rate |
| 56 | 160 | The =rate= value controls the rate of computation. This |
| 57 | 161 | is a value measure in Hertz. |
| 58 | 162 | |
| 59 | 163 | It can be set with =sk_chaosnoise_rate=. |
| 164 | + |
| 165 | +#+NAME: funcdefs |
| 166 | +#+BEGIN_SRC c |
| 167 | +void sk_chaosnoise_rate(sk_chaosnoise *cn, SKFLT rate); |
| 168 | +#+END_SRC |
| 169 | + |
| 170 | +#+NAME: funcs |
| 171 | +#+BEGIN_SRC c |
| 172 | +void sk_chaosnoise_rate(sk_chaosnoise *cn, SKFLT rate) |
| 173 | +{ |
| 174 | + cn->rate = rate; |
| 175 | +} |
| 176 | +#+END_SRC |
| 177 | + |
| 178 | +#+NAME: sk_chaosnoise |
| 179 | +#+BEGIN_SRC c |
| 180 | +SKFLT rate; |
| 181 | +#+END_SRC |
| 182 | + |
| 183 | +#+NAME: init |
| 184 | +#+BEGIN_SRC c |
| 185 | +sk_chaosnoise_rate(cn, 8000); |
| 186 | +#+END_SRC |
| 60 | 187 | * Initialization |
| 61 | 188 | Initialized with =sk_chaosnoise_init=. Sampling rate and an |
| 62 | 189 | initial value must be supplied as arguments. The initial |
| 63 | 190 | value is a floating point value that expects to be in range |
| 64 | 191 | 0-1. |
| 192 | + |
| 193 | +#+NAME: funcdefs |
| 194 | +#+BEGIN_SRC c |
| 195 | +void sk_chaosnoise_init(sk_chaosnoise *cn, int sr, SKFLT init); |
| 196 | +#+END_SRC |
| 197 | + |
| 198 | +#+NAME: funcs |
| 199 | +#+BEGIN_SRC c |
| 200 | +void sk_chaosnoise_init(sk_chaosnoise *cn, int sr, SKFLT init) |
| 201 | +{ |
| 202 | + <<init>> |
| 203 | +} |
| 204 | +#+END_SRC |
| 65 | 205 | * Computation |
| 66 | 206 | A single sample of audio is computed with |
| 67 | 207 | =sk_chaosnoise_tick=. |
| 68 | 208 | |
| 209 | +#+NAME: funcdefs |
| 210 | +#+BEGIN_SRC c |
| 211 | +SKFLT sk_chaosnoise_tick(sk_chaosnoise *cn); |
| 212 | +#+END_SRC |
| 213 | + |
| 214 | +#+NAME: funcs |
| 215 | +#+BEGIN_SRC c |
| 216 | +SKFLT sk_chaosnoise_tick(sk_chaosnoise *cn) |
| 217 | +{ |
| 218 | + SKFLT out; |
| 219 | + out = 0; |
| 220 | + |
| 221 | + <<update_phasor>> |
| 222 | + <<compute_noise>> |
| 223 | + <<copy_to_out>> |
| 224 | + |
| 225 | + return out; |
| 226 | +} |
| 227 | +#+END_SRC |
| 228 | + |
| 69 | 229 | First, the phasor value is updated by an increment value, |
| 70 | 230 | computed with =rate*maxlens=. |
| 71 | 231 | |
| 232 | +#+NAME: update_phasor |
| 233 | +#+BEGIN_SRC c |
| 234 | +cn->phs += floor(cn->rate * cn->maxlens); |
| 235 | +#+END_SRC |
| 236 | + |
| 72 | 237 | If the phasor reaches (or goes above) the end, a new |
| 73 | 238 | sample gets computed. |
| 74 | 239 | |
| @@ -84,5 +249,22 @@ set to be =0.05=. · 9 unmodified lines |
| 84 | 249 | After the output value is computed, the coefficients are |
| 85 | 250 | updated. |
| 86 | 251 | |
| 252 | +#+NAME: compute_noise |
| 253 | +#+BEGIN_SRC c |
| 254 | +if (cn->phs >= SK_CHAOSNOISE_PHSMAX) { |
| 255 | + SKFLT y; |
| 256 | + |
| 257 | + cn->phs &= SK_CHAOSNOISE_PHSMSK; |
| 258 | + y = fabs(cn->chaos * cn->y[0] - cn->y[1] - 0.05); |
| 259 | + cn->y[1] = cn->y[0]; |
| 260 | + cn->y[0] = y; |
| 261 | +} |
| 262 | +#+END_SRC |
| 263 | + |
| 87 | 264 | The output is always set to be the filter memory variable |
| 88 | 265 | =y[0]=. |
| 266 | + |
| 267 | +#+NAME: copy_to_out |
| 268 | +#+BEGIN_SRC c |
| 269 | +out = cn->y[0]; |
| 270 | +#+END_SRC |