| @@ -17,12 +17,63 @@ is can be used to change the tone quality of the algorithm. · 16 unmodified lines |
| 17 | This tangles to =chaosnoise.c= and =chaosnoise.h=. Defining | 17 | This tangles to =chaosnoise.c= and =chaosnoise.h=. Defining |
| 18 | =SK_CHAOSNOISE_PRIV= will expose the core struct in the | 18 | =SK_CHAOSNOISE_PRIV= will expose the core struct in the |
| 19 | header file. | 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 | * Struct | 48 | * Struct |
| 21 | Data for ChaosNoise is contained in a struct called | 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 | * Filter Memory | 63 | * Filter Memory |
| 24 | chaosnoise is technically a 2-pole filter, requiring | 64 | chaosnoise is technically a 2-pole filter, requiring |
| 25 | memory for 2 samples of signal. | 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 | * Sample and Hold Constants and Parameters | 77 | * Sample and Hold Constants and Parameters |
| 27 | The signal is clocked with a sample and hold generator. This | 78 | The signal is clocked with a sample and hold generator. This |
| 28 | sample and hold will use a fixed-point phasor to keep track | 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 | A 32-bit integer called =phs= keeps track of the phase | 84 | A 32-bit integer called =phs= keeps track of the phase |
| 34 | position. | 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 | The constant =SK_CHAOSNOISE_PHSMAX= defines the maximum | 97 | The constant =SK_CHAOSNOISE_PHSMAX= defines the maximum |
| 37 | length (and resolution) of the phasor, set to be | 98 | length (and resolution) of the phasor, set to be |
| 38 | =0x1000000=. | 99 | =0x1000000=. |
| 39 | | 100 | |
| | 101 | #+NAME: macros |
| | 102 | #+BEGIN_SRC c |
| | 103 | #define SK_CHAOSNOISE_PHSMAX 0x1000000L |
| | 104 | #+END_SRC |
| | 105 | |
| 40 | The constant =SK_CHAOSNOISE_PHSMSK= defines the masking | 106 | The constant =SK_CHAOSNOISE_PHSMSK= defines the masking |
| 41 | value of the phasor, set to be =0x0FFFFFF=. | 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 | The floating point value =maxlens= is | 114 | The floating point value =maxlens= is |
| 44 | =SK_CHAOSNOISE_PHSMAX=, converted to seconds. It is used | 115 | =SK_CHAOSNOISE_PHSMAX=, converted to seconds. It is used |
| 45 | to calculate the increment amount for the phase position. | 116 | to calculate the increment amount for the phase position. |
| 46 | When a rate value (in units of Hz, or cycles/second) get | 117 | When a rate value (in units of Hz, or cycles/second) get |
| 47 | multiplied by this value, the result is a value in units | 118 | multiplied by this value, the result is a value in units |
| 48 | of phase cycles. | 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 | * Parameters | 130 | * Parameters |
| 50 | ** Chaos | 131 | ** Chaos |
| 51 | The =chaos= parameter is variable that controls the chaos | 132 | The =chaos= parameter is variable that controls the chaos |
| 52 | level. It is typically a value between 1 and 2. | 133 | level. It is typically a value between 1 and 2. |
| 53 | | 134 | |
| 54 | It can be set with =sk_chaosnoise_chaos=. | 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 | ** Rate | 159 | ** Rate |
| 56 | The =rate= value controls the rate of computation. This | 160 | The =rate= value controls the rate of computation. This |
| 57 | is a value measure in Hertz. | 161 | is a value measure in Hertz. |
| 58 | | 162 | |
| 59 | It can be set with =sk_chaosnoise_rate=. | 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 | * Initialization | 187 | * Initialization |
| 61 | Initialized with =sk_chaosnoise_init=. Sampling rate and an | 188 | Initialized with =sk_chaosnoise_init=. Sampling rate and an |
| 62 | initial value must be supplied as arguments. The initial | 189 | initial value must be supplied as arguments. The initial |
| 63 | value is a floating point value that expects to be in range | 190 | value is a floating point value that expects to be in range |
| 64 | 0-1. | 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 | * Computation | 205 | * Computation |
| 66 | A single sample of audio is computed with | 206 | A single sample of audio is computed with |
| 67 | =sk_chaosnoise_tick=. | 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 | First, the phasor value is updated by an increment value, | 229 | First, the phasor value is updated by an increment value, |
| 70 | computed with =rate*maxlens=. | 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 | If the phasor reaches (or goes above) the end, a new | 237 | If the phasor reaches (or goes above) the end, a new |
| 73 | sample gets computed. | 238 | sample gets computed. |
| 74 | | 239 | |
| @@ -84,5 +249,22 @@ set to be =0.05=. · 9 unmodified lines |
| 84 | After the output value is computed, the coefficients are | 249 | After the output value is computed, the coefficients are |
| 85 | updated. | 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 | The output is always set to be the filter memory variable | 264 | The output is always set to be the filter memory variable |
| 88 | =y[0]=. | 265 | =y[0]=. |
| | 266 | |
| | 267 | #+NAME: copy_to_out |
| | 268 | #+BEGIN_SRC c |
| | 269 | out = cn->y[0]; |
| | 270 | #+END_SRC |