1 /* -------------------------------------------------------------------------------
2 * DFM-1 Digital Filter Module
3 * Copyright (C) 2010, 2011
4 *
5 * Tony Hardie-Bick <tony@entitysynth.net> - Java version
6 * Jonny Stutters <jstutters@jeremah.co.uk> - SuperCollider port
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * ------------------------------------------------------------------------------ */
21
22 #include <cmath>
23 #include <ctime>
24 #include <iostream>
25 #include "NoiseGen.h"
26
27 /* Look-up tables */
28
29 const int32_t NoiseGen::kn[] = {
30
31 1991057938, 0, 1611602771, 1826899878, 1918584482, 1969227037, 2001281515, 2023368125,
32 2039498179, 2051788381, 2061460127, 2069267110, 2075699398, 2081089314, 2085670119, 2089610331,
33 2093034710, 2096037586, 2098691595, 2101053571, 2103168620, 2105072996, 2106796166, 2108362327,
34 2109791536, 2111100552, 2112303493, 2113412330, 2114437283, 2115387130, 2116269447, 2117090813,
35 2117856962, 2118572919, 2119243101, 2119871411, 2120461303, 2121015852, 2121537798, 2122029592,
36 2122493434, 2122931299, 2123344971, 2123736059, 2124106020, 2124456175, 2124787725, 2125101763,
37 2125399283, 2125681194, 2125948325, 2126201433, 2126441213, 2126668298, 2126883268, 2127086657,
38 2127278949, 2127460589, 2127631985, 2127793506, 2127945490, 2128088244, 2128222044, 2128347141,
39 2128463758, 2128572095, 2128672327, 2128764606, 2128849065, 2128925811, 2128994934, 2129056501,
40 2129110560, 2129157136, 2129196237, 2129227847, 2129251929, 2129268426, 2129277255, 2129278312,
41 2129271467, 2129256561, 2129233410, 2129201800, 2129161480, 2129112170, 2129053545, 2128985244,
42 2128906855, 2128817916, 2128717911, 2128606255, 2128482298, 2128345305, 2128194452, 2128028813,
43 2127847342, 2127648860, 2127432031, 2127195339, 2126937058, 2126655214, 2126347546, 2126011445,
44 2125643893, 2125241376, 2124799783, 2124314271, 2123779094, 2123187386, 2122530867, 2121799464,
45 2120980787, 2120059418, 2119015917, 2117825402, 2116455471, 2114863093, 2112989789, 2110753906,
46 2108037662, 2104664315, 2100355223, 2094642347, 2086670106, 2074676188, 2054300022, 2010539237
47
48 };
49
50 const double NoiseGen::wn[] = {
51
52 1.72904052154279800e-09, 1.26809284470029200e-10, 1.68975177731846410e-10, 1.98626884424791160e-10,
53 2.22324317925000040e-10, 2.42449361254489800e-10, 2.60161319006320950e-10, 2.76119887117039770e-10,
54 2.90739628177159950e-10, 3.04299704143766170e-10, 3.16997952139542940e-10, 3.28980205271130800e-10,
55 3.40357381218340840e-10, 3.51216022136647230e-10, 3.61625099505651850e-10, 3.71640576349598000e-10,
56 3.81308564311059900e-10, 3.90667568099488270e-10, 3.99750118699769100e-10, 4.08583986159844030e-10,
57 4.17193096401606540e-10, 4.25598235345926260e-10, 4.33817597392551050e-10, 4.41867218125288600e-10,
58 4.49761319626658200e-10, 4.57512588945882870e-10, 4.65132404814001000e-10, 4.72631023848117600e-10,
59 4.80017734723256700e-10, 4.87300986779874800e-10, 4.94488498053897300e-10, 5.01587346611961600e-10,
60 5.08604048242456000e-10, 5.15544622919539000e-10, 5.22414651970631600e-10, 5.29219327500630500e-10,
61 5.35963495331289000e-10, 5.42651692482061900e-10, 5.49288180034602100e-10, 5.55876972076077300e-10,
62 5.62421861298358800e-10, 5.68926441734655000e-10, 5.75394129037560300e-10, 5.81828178639089800e-10,
63 5.88231702081217000e-10, 5.94607681762499600e-10, 6.00958984310830300e-10, 6.07288372762788500e-10,
64 6.13598517705413500e-10, 6.19892007515592100e-10, 6.26171357814942800e-10, 6.32439020243540100e-10,
65 6.38697390643573500e-10, 6.44948816733738200e-10, 6.51195605346469700e-10, 6.57440029292859800e-10,
66 6.63684333913987400e-10, 6.69930743372330100e-10, 6.76181466732744400e-10, 6.82438703879113700e-10,
67 6.88704651310073300e-10, 6.94981507855166700e-10, 7.01271480351315500e-10, 7.07576789318556000e-10,
68 7.13899674673584900e-10, 7.20242401519748600e-10, 7.26607266052704700e-10, 7.32996601622086400e-10,
69 7.39412784991122800e-10, 7.45858242838353900e-10, 7.52335458548348800e-10, 7.58846979341765200e-10,
70 7.65395423799226300e-10, 7.71983489838440000e-10, 7.78613963209838100e-10, 7.85289726582899700e-10,
71 7.92013769303409800e-10, 7.98789197911353600e-10, 8.05619247520217000e-10, 8.12507294171396800e-10,
72 8.19456868292574500e-10, 8.26471669406662500e-10, 8.33555582258784500e-10, 8.40712694553299100e-10,
73 8.47947316521837200e-10, 8.55264002577609400e-10, 8.62667575351936300e-10, 8.70163152457442400e-10,
74 8.77756176380328400e-10, 8.85452447973727800e-10, 8.93258164108036900e-10, 9.01179960135660500e-10,
75 9.09224957951138100e-10, 9.17400820578600500e-10, 9.25715814404012600e-10, 9.34178880398847200e-10,
76 9.42799715966631400e-10, 9.51588869399888300e-10, 9.60557849383125300e-10, 9.69719252545394400e-10,
77 9.79086912790890000e-10, 9.88676077068772400e-10, 9.98503613453542500e-10, 1.00858825899144730e-09,
78 1.01895091686213820e-09, 1.02961501520066680e-09, 1.04060694369998740e-09, 1.05195658927280390e-09,
79 1.06369799919308710e-09, 1.07587021016458190e-09, 1.08851829606072830e-09, 1.10169470781350440e-09,
80 1.11546100955971630e-09, 1.12989016134932160e-09, 1.14506957000672370e-09, 1.16110524260223480e-09,
81 1.17812756094561300e-09, 1.19629950538507560e-09, 1.21582869832955640e-09, 1.23698562908049660e-09,
82 1.26013233006085250e-09, 1.28576968442051530e-09, 1.31462018496771830e-09, 1.34778395622108550e-09,
83 1.38706353150670430e-09, 1.43574031918163800e-09, 1.50086590302229930e-09, 1.60309479380911230e-09
84
85 };
86
87 const double NoiseGen::fn[] = {
88
89 1.00000000000000000e+00, 9.63599693127085300e-01, 9.36282681685058900e-01, 9.13043647971739600e-01,
90 8.92281650784025700e-01, 8.73243048910069100e-01, 8.55500607869450300e-01, 8.38783605295989400e-01,
91 8.22907211381408800e-01, 8.07738294682960300e-01, 7.93177011771304800e-01, 7.79146085929687500e-01,
92 7.65584173897704300e-01, 7.52441559174611200e-01, 7.39677243672647100e-01, 7.27256918344184600e-01,
93 7.15151507410498400e-01, 7.03336099016158000e-01, 6.91789143436675000e-01, 6.80491840997334100e-01,
94 6.69427667348890400e-01, 6.58582000050088000e-01, 6.47941821110222500e-01, 6.37495477335042300e-01,
95 6.27232485249927300e-01, 6.17143370818880900e-01, 6.07219536625120300e-01, 5.97453150944516700e-01,
96 5.87837054434706600e-01, 5.78364681119763100e-01, 5.69029991067950900e-01, 5.59827412704086900e-01,
97 5.50751793114604500e-01, 5.41798355025425500e-01, 5.32962659383836100e-01, 5.24240572672984100e-01,
98 5.15628238244001800e-01, 5.07122051075569000e-01, 4.98718635470979500e-01, 4.90414825283844100e-01,
99 4.82207646329485200e-01, 4.74094300693016950e-01, 4.66072152689456100e-01, 4.58138716267872060e-01,
100 4.50291643682039200e-01, 4.42528715275468440e-01, 4.34847830249990850e-01, 4.27246998304996000e-01,
101 4.19724332049574400e-01, 4.12278040102661100e-01, 4.04906420807223100e-01, 3.97607856493873400e-01,
102 3.90380808237314700e-01, 3.83223811055901300e-01, 3.76135469510562700e-01, 3.69114453664472300e-01,
103 3.62159495369317700e-01, 3.55269384847917200e-01, 3.48442967546326640e-01, 3.41679141231550400e-01,
104 3.34976853313589200e-01, 3.28335098372850240e-01, 3.21752915875984900e-01, 3.15229388065010900e-01,
105 3.08763638006181100e-01, 3.02354827786483540e-01, 2.96002156846933000e-01, 2.89704860442959840e-01,
106 2.83462208223233000e-01, 2.77273502919188100e-01, 2.71138079138384600e-01, 2.65055302255589200e-01,
107 2.59024567396204830e-01, 2.53045298507325770e-01, 2.47116947512321400e-01, 2.41238993545439820e-01,
108 2.35410942263479080e-01, 2.29632325232116130e-01, 2.23902699385008420e-01, 2.18221646554305430e-01,
109 2.12588773071730300e-01, 2.07003709439926520e-01, 2.01466110074313670e-01, 1.95975653116277740e-01,
110 1.90532040319137170e-01, 1.85134997008992200e-01, 1.79784272123295450e-01, 1.74479638330789500e-01,
111 1.69220892237365000e-01, 1.64007854683420380e-01, 1.58840371139479300e-01, 1.53718312208181660e-01,
112 1.48641574242342260e-01, 1.43610080090627760e-01, 1.38623779984594600e-01, 1.33682652583439370e-01,
113 1.28786706195943200e-01, 1.23935980202867820e-01, 1.19130546707650830e-01, 1.14370512448866010e-01,
114 1.09656021014840270e-01, 1.04987255409421320e-01, 1.00364441028655870e-01, 9.57878491217314400e-02,
115 9.12578008268302400e-02, 8.67746718947801900e-02, 8.23388982422356600e-02, 7.79509825139734000e-02,
116 7.36115018841134000e-02, 6.93211173935779100e-02, 6.50805852130680700e-02, 6.08907703480404060e-02,
117 5.67526634810498500e-02, 5.26674019030510100e-02, 4.86362958598678050e-02, 4.46608622004914250e-02,
118 4.07428680744441750e-02, 3.68843887866562000e-02, 3.30878861462257500e-02, 2.93563174400068500e-02,
119 2.56932919359342700e-02, 2.21033046159270980e-02, 1.85921027370112880e-02, 1.51672980105465680e-02,
120 1.18394786578848620e-02, 8.62448441285988500e-03, 5.54899522077134500e-03, 2.66962908388092300e-03
121
122 };
123
124 /**
125 * Generates gaussian noise using the Ziggurat method.
126 *
127 * An implementation of the Ziggurat algorithm by George Marsaglia and Wai
128 * Wan Tsang. The code used is a minimally translated version of their C
129 * program in the paper: "The Ziggurat Method for Generating Random
130 * Variables", Journal of Statistical Software, vol. 5 (2000), No. 8.
131 * The only significant difference is that a random number generator
132 * with a longer period has been used, and look-up tables are precalculated.
133 *
134 * @see <a href="http://www.jstatsoft.org/v05/i08">The Ziggurat Method</a>.
135 * @see <a href="http://en.wikipedia.org/wiki/Ziggurat_algorithm">Wikipedia</a>.
136 * @see <a href="http://seehuhn.de/pages/ziggurat">An implementation for GSL</a>
137 * @see <a href="http://www.jstatsoft.org/v12/i07/paper">A comment by Leong et al</a>
138 * @see <a href="http://www.doornik.com/research/ziggurat.pdf">Improved Ziggurat Method</a>
139 *
140 * @param ng noise generator state
141 * @return next number (standard deviation = 1.0).
142 */
143
rnor(NoiseGenState * ng)144 double NoiseGen::rnor(NoiseGenState* ng) {
145
146 int32_t hz = xor128(ng);
147 int32_t iz = hz & 127;
148
149 return (std::abs((float)hz) < kn[iz]) ? hz * wn[iz] : nfix(hz, iz, ng);
150
151 }
152
153 /**
154 * Generates a random integer.
155 *
156 * A random number generator with period 2^128-1.
157 *
158 * @param ng noise generator state, must be non-zero
159 * @return random integer in range -2^31 to 2^31-1
160 *
161 * @see <a href="http://www.jstatsoft.org/v08/i14">Xorshift RNGs</a>
162 */
163
xor128(NoiseGenState * ng)164 int32_t NoiseGen::xor128(NoiseGenState* ng) {
165
166 uint32_t t = (ng->x ^ (ng->x << 15));
167
168 ng->x = ng->y;
169 ng->y = ng->z;
170 ng->z = ng->w;
171
172 return (ng->w = (ng->w ^ (ng->w >> 21)) ^ (t ^ (t >> 4)));
173
174 }
175
176 /**
177 * Generates a unipolar random floating point number.
178 *
179 * @param ng noise generator state
180 * @return random value between 0 and 1
181 */
182
uni(NoiseGenState * ng)183 double NoiseGen::uni(NoiseGenState* ng) {
184
185 const double k = 1.0 / 4294967296.0; // 1 / 2^32
186 return 0.5 + xor128(ng) * k;
187
188 }
189
190 /**
191 * Fixes normal distribution.
192 *
193 * If the first random number lies outside a rectangular central
194 * region of the ziggurat, this method is called to populate the
195 * curved region at the edge.
196 *
197 * @param hz random number -2^31..2^31
198 * @param iz random number 0..127
199 * @param ng noise generator state
200 * @return Random number
201 */
202
nfix(int32_t hz,int32_t iz,NoiseGenState * ng)203 double NoiseGen::nfix(int32_t hz, int32_t iz, NoiseGenState* ng) {
204
205 const double r = 3.442619855899;
206
207 double x, y;
208
209 for (;;) {
210
211 x = hz * wn[iz];
212
213 if (iz == 0) {
214
215 do {
216
217 x = -log(uni(ng)) * 0.2904764516147;
218 y = -log(uni(ng));
219
220 } while (y + y < x * x);
221
222 return (hz > 0) ? r + x : -r - x;
223
224 }
225
226 if (fn[iz] + uni(ng) * (fn[iz - 1] - fn[iz]) < exp(-0.5 * x * x)) {
227 return x;
228 }
229
230 hz = xor128(ng);
231 iz = hz & 127;
232
233 if (std::abs((float)hz) < kn[iz]) {
234 return hz * wn[iz];
235 }
236
237 }
238
239 }
240
241 /**
242 * Counter for randomizing state initialization.
243 */
244
245 int NoiseGen::counter = 0;
246
247 /**
248 * Initialize noise generator state.
249 *
250 * This initializes a noise generator state to a different set of
251 * values each time it is called.
252 *
253 * @param ng noise generator state
254 */
255
initialize(NoiseGenState * ng)256 void NoiseGen::initialize(NoiseGenState* ng) {
257
258 /* Create state values which will be different for each initialization */
259
260 ng->x = (uint32_t) NoiseGen::counter++;
261 ng->y = (uint32_t) NoiseGen::counter++;
262 ng->z = (uint32_t) NoiseGen::counter++;
263 ng->w = (uint32_t) (NoiseGen::counter++ * (int)time(NULL));
264
265 /* At least one of the state values must be non-zero */
266 if ((ng->x | ng->y | ng->z) == 0) ng->x = 1;
267
268 }
269
270 /**
271 * Initialize noise generator state.
272 *
273 * This initializes a noise generator state using a seed value so it
274 * can be used to generate a repeatable pseudorandom sequence.
275 *
276 * @param seed seed value for noise generator
277 * @param ng noise generator state
278 */
279
initialize(int seed,NoiseGenState * ng)280 void NoiseGen::initialize(int seed, NoiseGenState *ng) {
281
282 ng->x = (uint32_t) seed++;
283 ng->y = (uint32_t) seed++;
284 ng->z = (uint32_t) seed++;
285 ng->w = (uint32_t) seed++;
286
287 /* At least one of the state values must be non-zero */
288 if ((ng->x | ng->y | ng->z) == 0) ng->x = 1;
289
290 }
291
292 /**
293 * Correlates noise distribution with the normal distribution.
294 *
295 * This method is for checking class functionality. It correlates noise
296 * generator output with the normal distribution. The higher the number
297 * of events tested, the closer the correlation should be to 1.0.
298 *
299 * @param numberOfEvents Number of noise generator events for test
300 * @return Correlation with normal distribution
301 */
302
correlationTest(int numberOfEvents)303 double NoiseGen::correlationTest(int numberOfEvents) {
304
305 const int numberOfBuckets = 1024;
306
307 /* The width of the bell curve at the inflexion points as a proportion
308 * of the test range. This is set to a value such as 0.2, so that some
309 * of the tail of the distribution is included in the test (the width
310 * is also the standard deviation). */
311 const double width = 0.2;
312
313 NoiseGenState* ng = new NoiseGenState;
314 NoiseGen::initialize(0, ng);
315
316 double buckets[numberOfBuckets];
317 double normal[numberOfBuckets];
318
319 /* Clear buckets */
320 for (int b = 0; b < numberOfBuckets; b++) {
321 buckets[b] = 0;
322 }
323
324 const int halfNumberOfBuckets = numberOfBuckets / 2;
325
326 /* Create normal distribution with unity height and variance */
327 for (int b = 0; b < numberOfBuckets; b++) {
328 double x = (double)(b - halfNumberOfBuckets) / (double)(halfNumberOfBuckets);
329 normal[b] = exp(-(x * x) / (2.0 * width * width));
330 }
331
332 /* Run test */
333
334 for (int e = 0; e < numberOfEvents; e++) {
335
336 int32_t r = (int32_t)round(NoiseGen::rnor(ng) * halfNumberOfBuckets * width);
337 r += halfNumberOfBuckets;
338 if (r >= 0 && r < numberOfBuckets) {
339 buckets[r]++;
340 }
341 }
342
343 /* Calculate correlation (three pass method) */
344
345 /* 1. Calculate averages */
346
347 double sumBuckets = 0;
348 double sumNormal = 0;
349
350 for (int b = 0; b < numberOfBuckets; b++) {
351 sumBuckets += buckets[b];
352 sumNormal += normal[b];
353 }
354
355 double averageBuckets = sumBuckets / (double)numberOfBuckets;
356 double averageNormal = sumNormal / (double)numberOfBuckets;
357
358 /* 2. Calculate standard deviations and move averages to zero */
359
360 double sdBuckets = 0;
361 double sdNormal = 0;
362
363 for (int b = 0; b < numberOfBuckets; b++) {
364 buckets[b] -= averageBuckets;
365 sdBuckets += buckets[b] * buckets[b];
366 normal[b] -= averageNormal;
367 sdNormal += normal[b] * normal[b];
368 }
369
370 sdBuckets = sqrt(sdBuckets / numberOfBuckets);
371 sdNormal = sqrt(sdNormal / numberOfBuckets);
372
373 /* 3. Accumulate products and calculate correlation */
374
375 double sumProducts = 0;
376 double rSdP = 1.0 / (sdBuckets * sdNormal);
377
378 for (int b = 0; b < numberOfBuckets; b++) {
379 sumProducts += buckets[b] * normal[b] * rSdP;
380 }
381
382 std::cout << "correlationTest result: " << sumProducts / (double)numberOfBuckets << std::endl;
383 return sumProducts / (double)numberOfBuckets; // Pearson correlation coefficient
384
385 }
386
387 /**
388 * Tests class functionality.
389 *
390 * This is a quick test, which takes less than a second to run. If
391 * this test passes, the class is probably working correctly.
392 */
393
quickTest()394 bool NoiseGen::quickTest() {
395
396 const int numberOfEvents = 1000000;
397 const double correlationThreshold = 0.999;
398
399 return (correlationTest(numberOfEvents) > correlationThreshold);
400
401 }
402
403 /**
404 * Tests class implementation in great detail.
405 *
406 * This is a long test, taking several seconds. If successful, the
407 * class can reasonably be assumed to be working in every detail.
408 */
409
longTest()410 bool NoiseGen::longTest() {
411
412 /* A subtle error in the calculation of the distribution's tails
413 * can be introduced by changing the first log function in nfix()
414 * to include the 0.2904 factor. This test should fail when this
415 * is done, and pass otherwise. */
416
417 const int numberOfEvents = 360000000;
418 const double correlationThreshold = 0.9999985;
419
420 return (correlationTest(numberOfEvents) > correlationThreshold);
421
422 }
423
424