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