Mozzi  version v1.1.0
sound synthesis library for Arduino
mozzi_rand.cpp
1 #include "mozzi_rand.h"
2 
4 
5 #if IS_STM32()
6 //#include <STM32ADC.h>
7 extern STM32ADC adc;
8 #elif IS_ESP8266()
9 #include <esp8266_peri.h>
10 #endif
11 
12 // moved these out of xorshift96() so xorshift96() can be reseeded manually
13 static unsigned long x=132456789, y=362436069, z=521288629;
14 // static unsigned long x= analogRead(A0)+123456789;
15 // static unsigned long y= analogRead(A1)+362436069;
16 // static unsigned long z= analogRead(A2)+521288629;
17 
18 /** @ingroup random
19 Random number generator. A faster replacement for Arduino's random function,
20 which is too slow to use with Mozzi.
21 Based on Marsaglia, George. (2003). Xorshift RNGs. http://www.jstatsoft.org/v08/i14/xorshift.pdf
22 @return a random 32 bit integer.
23 @todo check timing of xorshift96(), rand() and other PRNG candidates.
24  */
25 
26 unsigned long xorshift96()
27 { //period 2^96-1
28  // static unsigned long x=123456789, y=362436069, z=521288629;
29  unsigned long t;
30 
31  x ^= x << 16;
32  x ^= x >> 5;
33  x ^= x << 1;
34 
35  t = x;
36  x = y;
37  y = z;
38  z = t ^ x ^ y;
39 
40  return z;
41 }
42 
43 
44 /** @ingroup random
45 Initialises Mozzi's (pseudo)random number generator xorshift96(), which is used
46 in Mozzi's rand() function. This can be useful if you want random sequences to
47 be different on each run of a sketch, by seeding with fairly random input, such
48 as analogRead() on an unconnected pin (as explained in the Arduino documentation
49 for randomSeed(). randSeed is the same as xorshift96Seed(), but easier to
50 remember.
51 @param seed a number to use as a seed.
52 */
53 void randSeed(long seed)
54 {
55  x=seed;
56 }
57 
58 
59 #if defined (__AVR_ATmega644P__)
60 
61 // a less fancy version for gizduino (__AVR_ATmega644P__) which doesn't know INTERNAL
62 static long longRandom()
63 {
64  return ((long)analogRead(0)+63)*(analogRead(1)+97); // added offsets in case analogRead is 0
65 }
66 
67 #elif defined (__AVR_ATmega2560__)
68 /*
69 longRandom(), used as a seed generator, comes from:
70 http://arduino.cc/forum/index.php/topic,38091.0.html
71 // AUTHOR: Rob Tillaart
72 // PURPOSE: Simple Random functions based upon unreliable internal temp sensor
73 // VERSION: 0.1
74 // DATE: 2011-05-01
75 //
76 // Released to the public domain, use at own risk
77 //
78 */
79 static long longRandom()
80 {
81  //analogReference(INTERNAL2V56);
82  unsigned long rv = 0;
83  for (uint8_t i=0; i< 32; i++) rv |= ((analogRead(8)+2294) & 1L) << i; // added 2294 in case analogRead is 0
84  return rv;
85 }
86 
87 #elif IS_AVR()
88 
89 static long longRandom()
90 {
91  //analogReference(INTERNAL);
92  unsigned long rv = 0;
93  for (uint8_t i=0; i< 32; i++) rv |= ((analogRead(8)+1171) & 1L) << i; // added 1171 in case analogRead is 0
94  return rv;
95 }
96 
97 
98 #endif
99 
100 
101 /** @ingroup random
102 Initialises Mozzi's (pseudo)random number generator xorshift96(), which is used
103 in Mozzi's rand() function. This can be useful if you want random sequences to
104 be different on each run of a sketch, by seeding with a fairly random input.
105 randSeed() called without a parameter uses noise from reading the Arduino's
106 internal temperature as the seed, a technique discussed at
107 http://arduino.cc/forum/index.php/topic,38091.0.html, borrowing code put there
108 by Rob Tillaart.
109 @note It's not perfect, as discussed in the forum thread.
110 It might only work with some processors: (from the thread)
111 "...ATmega328P in DIP, possibly others but the duemilanove and uno will do it at least."
112 So far, gizduino's __AVR_ATmega644P__ chip doesn't like it, so we use (long)analogRead(0)*analogRead(1) for that instead.
113 It works to some degree on STM32 chips, but the produced seed is not very random at all. Again, using an appropriate
114 analogRead() (preferably on one or two floating input pins) is much more effective.
115 @todo add Teensy 3 code
116 */
117 void randSeed() {
118 #if IS_AVR()
119  ADCSRA &= ~ (1 << ADIE); // adc Disable Interrupt, re-enable at end
120  // this attempt at remembering analog_reference stops it working
121  // maybe needs a delay after changing analog reference in longRandom (Arduino reference suggests this)
122  // because the analog reads return 0
123  //uint8_t analog_reference_orig = ADMUX&192; // analog_reference is high 2 bits of ADMUX, store this because longRandom sets it to internal
124  x=longRandom();
125  y=longRandom();
126  z=longRandom();
127  //analogReference(analog_reference_orig); // change back to original
128  ADCSRA |= (1 << ADIE); // adc re-Enable Interrupt
129 #elif IS_STM32()
130  // Unfortunately the internal temp sensor on STM32s does _not_ appear to create a lot of noise.
131  // Ironically, the calls to calibrate help induce some random noise. You're still fairly likely to produce two equal
132  // random seeds in two subsequent runs, however.
133  adc.enableInternalReading();
134  float dummy = adc.readTemp();
135  int* dummy_int = (int*) &dummy;
136  x=*dummy_int;
137  adc.calibrate();
138  dummy = adc.readTemp();
139  y=*dummy_int;
140  adc.calibrate();
141  dummy = adc.readTemp();
142  z=*dummy_int;
143 #elif IS_ESP8266()
144  x = RANDOM_REG32;
145  y = random (0xFFFFFFFF) ^ RANDOM_REG32;
146  z = random (0xFFFFFFFF) ^ RANDOM_REG32;
147 #else
148 #warning Automatic random seeding not implemented on this platform
149 #endif
150 }
151 
152 
153 
154 /** @ingroup random
155 Initialises Mozzi's (pseudo)random number generator xorshift96() with a chosen seed number.
156 @param seed a number to use as a seed.
157 */
158 void xorshiftSeed(long seed)
159 {
160  x=seed;
161 }
162 
163 
164 
165 /** @ingroup random
166 Ranged random number generator, faster than Arduino's built-in random function, which is too slow for generating at audio rate with Mozzi.
167 @param minval the minimum signed uint8_t value of the range to be chosen from. Minval will be the minimum value possibly returned by the function.
168 @param maxval the maximum signed uint8_t value of the range to be chosen from. Maxval-1 will be the largest value possibly returned by the function.
169 @return a random int8_t between minval and maxval-1 inclusive.
170 */
172 {
173  return (int8_t) ((((int) (lowByte(xorshift96()))) * (maxval-minval))>>8) + minval;
174 }
175 
176 
177 /** @ingroup random
178 Ranged random number generator, faster than Arduino's built-in random function, which is too slow for generating at audio rate with Mozzi.
179 @param minval the minimum unsigned uint8_t value of the range to be chosen from. Minval will be the minimum value possibly returned by the function.
180 @param maxval the maximum unsigned uint8_t value of the range to be chosen from. Maxval-1 will be the largest value possibly returned by the function.
181 @return a random uint8_t between minval and maxval-1 inclusive.
182 */
184 {
185  return (uint8_t) ((((unsigned int) (lowByte(xorshift96()))) * (maxval-minval))>>8) + minval;
186 }
187 
188 
189 /** @ingroup random
190 Ranged random number generator, faster than Arduino's built-in random function, which is too slow for generating at audio rate with Mozzi.
191 @param minval the minimum signed int value of the range to be chosen from. Minval will be the minimum value possibly returned by the function.
192 @param maxval the maximum signed int value of the range to be chosen from. Maxval-1 will be the largest value possibly returned by the function.
193 @return a random int between minval and maxval-1 inclusive.
194 */
195 int rand( int minval, int maxval)
196 {
197  return (int) ((((xorshift96() & 0xFFFF) * (maxval-minval))>>16) + minval);
198 }
199 
200 
201 /** @ingroup random
202 Ranged random number generator, faster than Arduino's built-in random function, which is too slow for generating at audio rate with Mozzi.
203 @param minval the minimum unsigned int value of the range to be chosen from. Minval will be the minimum value possibly returned by the function.
204 @param maxval the maximum unsigned int value of the range to be chosen from. Maxval-1 will be the largest value possibly returned by the function.
205 @return a random unsigned int between minval and maxval-1 inclusive.
206 */
207 unsigned int rand(unsigned int minval, unsigned int maxval)
208 {
209  return (unsigned int) ((((xorshift96() & 0xFFFF) * (maxval-minval))>>16) + minval);
210 }
211 
212 
213 /** @ingroup random
214 Ranged random number generator, faster than Arduino's built-in random function, which is too slow for generating at audio rate with Mozzi.
215 @param maxval the maximum signed uint8_t value of the range to be chosen from. Maxval-1 will be the largest value possibly returned by the function.
216 @return a random int8_t between 0 and maxval-1 inclusive.
217 */
219 {
220  return (int8_t) ((((int) (lowByte(xorshift96()))) * maxval)>>8);
221 }
222 
223 
224 /** @ingroup random
225 Ranged random number generator, faster than Arduino's built-in random function, which is too slow for generating at audio rate with Mozzi.
226 @param maxval the maximum unsigned uint8_t value of the range to be chosen from. Maxval-1 will be the largest value possibly returned by the function.
227 @return a random uint8_t between 0 and maxval-1 inclusive.
228 */
230 {
231  return (uint8_t) ((((unsigned int) (lowByte(xorshift96()))) * maxval)>>8);
232 }
233 
234 
235 /** @ingroup random
236 Ranged random number generator, faster than Arduino's built-in random function, which is too slow for generating at audio rate with Mozzi.
237 @param maxval the maximum signed int value of the range to be chosen from. Maxval-1 will be the largest value possibly returned by the function.
238 @return a random int between 0 and maxval-1 inclusive.
239 */
240 int rand(int maxval)
241 {
242  return (int) (((xorshift96() & 0xFFFF) * maxval)>>16);
243 }
244 
245 
246 /** @ingroup random
247 Ranged random number generator, faster than Arduino's built-in random function, which is too slow for generating at audio rate with Mozzi.
248 @param maxval the maximum unsigned int value of the range to be chosen from. Maxval-1 will be the largest value possibly returned by the function.
249 @return a random unsigned int between 0 and maxval-1 inclusive.
250 */
251 unsigned int rand(unsigned int maxval)
252 {
253  return (unsigned int) (((xorshift96() & 0xFFFF) * maxval)>>16);
254 }
255 
256 
257 /** @ingroup random
258 Generates a random number in the range for midi notes.
259 @return a random value between 0 and 127 inclusive
260 */
262 {
263  return lowByte(xorshift96())>>1;
264 }
void xorshiftSeed(long seed)
Initialises Mozzi&#39;s (pseudo)random number generator xorshift96() with a chosen seed number...
Definition: mozzi_rand.cpp:158
void randSeed()
Initialises Mozzi&#39;s (pseudo)random number generator xorshift96(), which is used in Mozzi&#39;s rand() fun...
Definition: mozzi_rand.cpp:117
void randSeed(long seed)
Initialises Mozzi&#39;s (pseudo)random number generator xorshift96(), which is used in Mozzi&#39;s rand() fun...
Definition: mozzi_rand.cpp:53
int rand(int maxval)
Ranged random number generator, faster than Arduino&#39;s built-in random function, which is too slow for...
Definition: mozzi_rand.cpp:240
#define IS_STM32()
unsigned int rand(unsigned int minval, unsigned int maxval)
Ranged random number generator, faster than Arduino&#39;s built-in random function, which is too slow for...
Definition: mozzi_rand.cpp:207
#define IS_AVR()
unsigned long xorshift96()
Random number generator.
Definition: mozzi_rand.cpp:26
uint8_t randMidiNote()
Generates a random number in the range for midi notes.
Definition: mozzi_rand.cpp:261
unsigned int rand(unsigned int maxval)
Ranged random number generator, faster than Arduino&#39;s built-in random function, which is too slow for...
Definition: mozzi_rand.cpp:251
int rand(int minval, int maxval)
Ranged random number generator, faster than Arduino&#39;s built-in random function, which is too slow for...
Definition: mozzi_rand.cpp:195
#define IS_ESP8266()