FastLED 3.9.12
Loading...
Searching...
No Matches
noise.cpp
Go to the documentation of this file.
1
3
4#include <string.h>
5
6#if defined(__clang__)
7// Clang doesn't have variable length arrays. Therefore we need to emulate them using
8// alloca.
9#define VARIABLE_LENGTH_ARRAY_NEEDS_EMULATION 1
10#else
11// Else, assume the compiler is gcc, which has variable length arrays
12#define VARIABLE_LENGTH_ARRAY_NEEDS_EMULATION 0
13#endif
14
15#if !VARIABLE_LENGTH_ARRAY_NEEDS_EMULATION
16#define VARIABLE_LENGTH_ARRAY(TYPE, NAME, SIZE) TYPE NAME[SIZE]
17#elif __has_include(<alloca.h>)
18#include <alloca.h>
19#define VARIABLE_LENGTH_ARRAY(TYPE, NAME, SIZE) \
20 TYPE* NAME = reinterpret_cast<TYPE*>(alloca(sizeof(TYPE) * (SIZE)))
21#elif __has_include(<cstdlib>)
22#include <cstdlib>
23#define VARIABLE_LENGTH_ARRAY(TYPE, NAME, SIZE) \
24 TYPE* NAME = reinterpret_cast<TYPE*>(alloca(sizeof(TYPE) * (SIZE)))
25#else
26#error "Compiler does not allow variable type arrays."
27#endif
28
29
30
32#define FASTLED_INTERNAL
33#include "FastLED.h"
34
35
36// Compiler throws a warning about stack usage possibly being unbounded even
37// though bounds are checked, silence that so users don't see it
38#pragma GCC diagnostic push
39#if defined(__GNUC__) && (__GNUC__ >= 6)
40 #pragma GCC diagnostic ignored "-Wstack-usage="
41#else
42 #pragma GCC diagnostic ignored "-Wunknown-warning-option"
43#endif
44
45
46
48#define P(x) FL_PGM_READ_BYTE_NEAR(p + x)
49
51
52
53FL_PROGMEM static uint8_t const p[] = {
54 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225,
55 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148,
56 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32,
57 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175,
58 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122,
59 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54,
60 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169,
61 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64,
62 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212,
63 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213,
64 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,
65 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104,
66 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241,
67 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157,
68 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93,
69 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180,
70 151};
71
72
73// Start Doxygen define hiding
75
76#if FASTLED_NOISE_ALLOW_AVERAGE_TO_OVERFLOW == 1
77#define AVG15(U,V) (((U)+(V)) >> 1)
78#else
79// See if we should use the inlined avg15 for AVR with MUL instruction
80#if defined(__AVR__) && (LIB8_ATTINY == 0)
81#define AVG15(U,V) (avg15_inline_avr_mul((U),(V)))
82// inlined copy of avg15 for AVR with MUL instruction; cloned from math8.h
83// Forcing this inline in the 3-D 16bit noise produces a 12% speedup overall,
84// at a cost of just +8 bytes of net code size.
85static int16_t inline __attribute__((always_inline)) avg15_inline_avr_mul( int16_t i, int16_t j)
86{
87 asm volatile(
88 /* first divide j by 2, throwing away lowest bit */
89 "asr %B[j] \n\t"
90 "ror %A[j] \n\t"
91 /* now divide i by 2, with lowest bit going into C */
92 "asr %B[i] \n\t"
93 "ror %A[i] \n\t"
94 /* add j + C to i */
95 "adc %A[i], %A[j] \n\t"
96 "adc %B[i], %B[j] \n\t"
97 : [i] "+r" (i)
98 : [j] "r" (j) );
99 return i;
100}
101#else
102#define AVG15(U,V) (avg15((U),(V)))
103#endif
104#endif
105
106// See fastled_config.h for notes on this;
107// "#define FASTLED_NOISE_FIXED 1" is the correct value
108#if FASTLED_NOISE_FIXED == 0
109#define EASE8(x) (FADE(x) )
110#define EASE16(x) (FADE(x) )
111#else
112#define EASE8(x) (ease8InOutQuad(x) )
113#define EASE16(x) (ease16InOutQuad(x))
114#endif
115//
116// #define FADE_12
117#define FADE_16
118
119#ifdef FADE_12
120#define FADE logfade12
121#define LERP(a,b,u) lerp15by12(a,b,u)
122#else
123#define FADE(x) scale16(x,x)
124#define LERP(a,b,u) lerp15by16(a,b,u)
125#endif
126
127// end Doxygen define hiding
129
130static int16_t inline __attribute__((always_inline)) grad16(uint8_t hash, int16_t x, int16_t y, int16_t z) {
131#if 0
132 switch(hash & 0xF) {
133 case 0: return (( x) + ( y))>>1;
134 case 1: return ((-x) + ( y))>>1;
135 case 2: return (( x) + (-y))>>1;
136 case 3: return ((-x) + (-y))>>1;
137 case 4: return (( x) + ( z))>>1;
138 case 5: return ((-x) + ( z))>>1;
139 case 6: return (( x) + (-z))>>1;
140 case 7: return ((-x) + (-z))>>1;
141 case 8: return (( y) + ( z))>>1;
142 case 9: return ((-y) + ( z))>>1;
143 case 10: return (( y) + (-z))>>1;
144 case 11: return ((-y) + (-z))>>1;
145 case 12: return (( y) + ( x))>>1;
146 case 13: return ((-y) + ( z))>>1;
147 case 14: return (( y) + (-x))>>1;
148 case 15: return ((-y) + (-z))>>1;
149 }
150#else
151 hash = hash&15;
152 int16_t u = hash<8?x:y;
153 int16_t v = hash<4?y:hash==12||hash==14?x:z;
154 if(hash&1) { u = -u; }
155 if(hash&2) { v = -v; }
156
157 return AVG15(u,v);
158#endif
159}
160
161static int16_t inline __attribute__((always_inline)) grad16(uint8_t hash, int16_t x, int16_t y) {
162 hash = hash & 7;
163 int16_t u,v;
164 if(hash < 4) { u = x; v = y; } else { u = y; v = x; }
165 if(hash&1) { u = -u; }
166 if(hash&2) { v = -v; }
167
168 return AVG15(u,v);
169}
170
171static int16_t inline __attribute__((always_inline)) grad16(uint8_t hash, int16_t x) {
172 hash = hash & 15;
173 int16_t u,v;
174 if(hash > 8) { u=x;v=x; }
175 else if(hash < 4) { u=x;v=1; }
176 else { u=1;v=x; }
177 if(hash&1) { u = -u; }
178 if(hash&2) { v = -v; }
179
180 return AVG15(u,v);
181}
182
183// selectBasedOnHashBit performs this:
184// result = (hash & (1<<bitnumber)) ? a : b
185// but with an AVR asm version that's smaller and quicker than C
186// (and probably not worth including in lib8tion)
187static int8_t inline __attribute__((always_inline)) selectBasedOnHashBit(uint8_t hash, uint8_t bitnumber, int8_t a, int8_t b) {
188 int8_t result;
189#if !defined(__AVR__)
190 result = (hash & (1<<bitnumber)) ? a : b;
191#else
192 asm volatile(
193 "mov %[result],%[a] \n\t"
194 "sbrs %[hash],%[bitnumber] \n\t"
195 "mov %[result],%[b] \n\t"
196 : [result] "=r" (result)
197 : [hash] "r" (hash),
198 [bitnumber] "M" (bitnumber),
199 [a] "r" (a),
200 [b] "r" (b)
201 );
202#endif
203 return result;
204}
205
206static int8_t inline __attribute__((always_inline)) grad8(uint8_t hash, int8_t x, int8_t y, int8_t z) {
207#if 0
208 switch(hash & 0xF) {
209 case 0: return (( x) + ( y))>>1;
210 case 1: return ((-x) + ( y))>>1;
211 case 2: return (( x) + (-y))>>1;
212 case 3: return ((-x) + (-y))>>1;
213 case 4: return (( x) + ( z))>>1;
214 case 5: return ((-x) + ( z))>>1;
215 case 6: return (( x) + (-z))>>1;
216 case 7: return ((-x) + (-z))>>1;
217 case 8: return (( y) + ( z))>>1;
218 case 9: return ((-y) + ( z))>>1;
219 case 10: return (( y) + (-z))>>1;
220 case 11: return ((-y) + (-z))>>1;
221 case 12: return (( y) + ( x))>>1;
222 case 13: return ((-y) + ( z))>>1;
223 case 14: return (( y) + (-x))>>1;
224 case 15: return ((-y) + (-z))>>1;
225 }
226#else
227
228 hash &= 0xF;
229
230 int8_t u, v;
231 //u = (hash&8)?y:x;
232 u = selectBasedOnHashBit( hash, 3, y, x);
233
234#if 1
235 v = hash<4?y:hash==12||hash==14?x:z;
236#else
237 // Verbose version for analysis; generates idenitical code.
238 if( hash < 4) { // 00 01 02 03
239 v = y;
240 } else {
241 if( hash==12 || hash==14) { // 0C 0E
242 v = x;
243 } else {
244 v = z; // 04 05 06 07 08 09 0A 0B 0D 0F
245 }
246 }
247#endif
248
249 if(hash&1) { u = -u; }
250 if(hash&2) { v = -v; }
251
252 return avg7(u,v);
253#endif
254}
255
256static int8_t inline __attribute__((always_inline)) grad8(uint8_t hash, int8_t x, int8_t y)
257{
258 // since the tests below can be done bit-wise on the bottom
259 // three bits, there's no need to mask off the higher bits
260 // hash = hash & 7;
261
262 int8_t u,v;
263 if( hash & 4) {
264 u = y; v = x;
265 } else {
266 u = x; v = y;
267 }
268
269 if(hash&1) { u = -u; }
270 if(hash&2) { v = -v; }
271
272 return avg7(u,v);
273}
274
275static int8_t inline __attribute__((always_inline)) grad8(uint8_t hash, int8_t x)
276{
277 // since the tests below can be done bit-wise on the bottom
278 // four bits, there's no need to mask off the higher bits
279 // hash = hash & 15;
280
281 int8_t u,v;
282 if(hash & 8) {
283 u=x; v=x;
284 } else {
285 if(hash & 4) {
286 u=1; v=x;
287 } else {
288 u=x; v=1;
289 }
290 }
291
292 if(hash&1) { u = -u; }
293 if(hash&2) { v = -v; }
294
295 return avg7(u,v);
296}
297
298
299#ifdef FADE_12
300uint16_t logfade12(uint16_t val) {
301 return scale16(val,val)>>4;
302}
303
304static int16_t inline __attribute__((always_inline)) lerp15by12( int16_t a, int16_t b, fract16 frac)
305{
306 //if(1) return (lerp(frac,a,b));
307 int16_t result;
308 if( b > a) {
309 uint16_t delta = b - a;
310 uint16_t scaled = scale16(delta,frac<<4);
311 result = a + scaled;
312 } else {
313 uint16_t delta = a - b;
314 uint16_t scaled = scale16(delta,frac<<4);
315 result = a - scaled;
316 }
317 return result;
318}
319#endif
320
321static int8_t inline __attribute__((always_inline)) lerp7by8( int8_t a, int8_t b, fract8 frac)
322{
323 // int8_t delta = b - a;
324 // int16_t prod = (uint16_t)delta * (uint16_t)frac;
325 // int8_t scaled = prod >> 8;
326 // int8_t result = a + scaled;
327 // return result;
328 int8_t result;
329 if( b > a) {
330 uint8_t delta = b - a;
331 uint8_t scaled = scale8( delta, frac);
332 result = a + scaled;
333 } else {
334 uint8_t delta = a - b;
335 uint8_t scaled = scale8( delta, frac);
336 result = a - scaled;
337 }
338 return result;
339}
340
341int16_t inoise16_raw(uint32_t x, uint32_t y, uint32_t z)
342{
343 // Find the unit cube containing the point
344 uint8_t X = (x>>16)&0xFF;
345 uint8_t Y = (y>>16)&0xFF;
346 uint8_t Z = (z>>16)&0xFF;
347
348 // Hash cube corner coordinates
349 uint8_t A = P(X)+Y;
350 uint8_t AA = P(A)+Z;
351 uint8_t AB = P(A+1)+Z;
352 uint8_t B = P(X+1)+Y;
353 uint8_t BA = P(B) + Z;
354 uint8_t BB = P(B+1)+Z;
355
356 // Get the relative position of the point in the cube
357 uint16_t u = x & 0xFFFF;
358 uint16_t v = y & 0xFFFF;
359 uint16_t w = z & 0xFFFF;
360
361 // Get a signed version of the above for the grad function
362 int16_t xx = (u >> 1) & 0x7FFF;
363 int16_t yy = (v >> 1) & 0x7FFF;
364 int16_t zz = (w >> 1) & 0x7FFF;
365 uint16_t N = 0x8000L;
366
367 u = EASE16(u); v = EASE16(v); w = EASE16(w);
368
369 // skip the log fade adjustment for the moment, otherwise here we would
370 // adjust fade values for u,v,w
371 int16_t X1 = LERP(grad16(P(AA), xx, yy, zz), grad16(P(BA), xx - N, yy, zz), u);
372 int16_t X2 = LERP(grad16(P(AB), xx, yy-N, zz), grad16(P(BB), xx - N, yy - N, zz), u);
373 int16_t X3 = LERP(grad16(P(AA+1), xx, yy, zz-N), grad16(P(BA+1), xx - N, yy, zz-N), u);
374 int16_t X4 = LERP(grad16(P(AB+1), xx, yy-N, zz-N), grad16(P(BB+1), xx - N, yy - N, zz - N), u);
375
376 int16_t Y1 = LERP(X1,X2,v);
377 int16_t Y2 = LERP(X3,X4,v);
378
379 int16_t ans = LERP(Y1,Y2,w);
380
381 return ans;
382}
383
384uint16_t inoise16(uint32_t x, uint32_t y, uint32_t z) {
385 int32_t ans = inoise16_raw(x,y,z);
386 ans = ans + 19052L;
387 uint32_t pan = ans;
388 // pan = (ans * 220L) >> 7. That's the same as:
389 // pan = (ans * 440L) >> 8. And this way avoids a 7X four-byte shift-loop on AVR.
390 // Identical math, except for the highest bit, which we don't care about anyway,
391 // since we're returning the 'middle' 16 out of a 32-bit value anyway.
392 pan *= 440L;
393 return (pan>>8);
394
395 // // return scale16by8(pan,220)<<1;
396 // return ((inoise16_raw(x,y,z)+19052)*220)>>7;
397 // return scale16by8(inoise16_raw(x,y,z)+19052,220)<<1;
398}
399
400int16_t inoise16_raw(uint32_t x, uint32_t y)
401{
402 // Find the unit cube containing the point
403 uint8_t X = x>>16;
404 uint8_t Y = y>>16;
405
406 // Hash cube corner coordinates
407 uint8_t A = P(X)+Y;
408 uint8_t AA = P(A);
409 uint8_t AB = P(A+1);
410 uint8_t B = P(X+1)+Y;
411 uint8_t BA = P(B);
412 uint8_t BB = P(B+1);
413
414 // Get the relative position of the point in the cube
415 uint16_t u = x & 0xFFFF;
416 uint16_t v = y & 0xFFFF;
417
418 // Get a signed version of the above for the grad function
419 int16_t xx = (u >> 1) & 0x7FFF;
420 int16_t yy = (v >> 1) & 0x7FFF;
421 uint16_t N = 0x8000L;
422
423 u = EASE16(u); v = EASE16(v);
424
425 int16_t X1 = LERP(grad16(P(AA), xx, yy), grad16(P(BA), xx - N, yy), u);
426 int16_t X2 = LERP(grad16(P(AB), xx, yy-N), grad16(P(BB), xx - N, yy - N), u);
427
428 int16_t ans = LERP(X1,X2,v);
429
430 return ans;
431}
432
433uint16_t inoise16(uint32_t x, uint32_t y) {
434 int32_t ans = inoise16_raw(x,y);
435 ans = ans + 17308L;
436 uint32_t pan = ans;
437 // pan = (ans * 242L) >> 7. That's the same as:
438 // pan = (ans * 484L) >> 8. And this way avoids a 7X four-byte shift-loop on AVR.
439 // Identical math, except for the highest bit, which we don't care about anyway,
440 // since we're returning the 'middle' 16 out of a 32-bit value anyway.
441 pan *= 484L;
442 return (pan>>8);
443
444 // return (uint32_t)(((int32_t)inoise16_raw(x,y)+(uint32_t)17308)*242)>>7;
445 // return scale16by8(inoise16_raw(x,y)+17308,242)<<1;
446}
447
448int16_t inoise16_raw(uint32_t x)
449{
450 // Find the unit cube containing the point
451 uint8_t X = x>>16;
452
453 // Hash cube corner coordinates
454 uint8_t A = P(X);
455 uint8_t AA = P(A);
456 uint8_t B = P(X+1);
457 uint8_t BA = P(B);
458
459 // Get the relative position of the point in the cube
460 uint16_t u = x & 0xFFFF;
461
462 // Get a signed version of the above for the grad function
463 int16_t xx = (u >> 1) & 0x7FFF;
464 uint16_t N = 0x8000L;
465
466 u = EASE16(u);
467
468 int16_t ans = LERP(grad16(P(AA), xx), grad16(P(BA), xx - N), u);
469
470 return ans;
471}
472
473uint16_t inoise16(uint32_t x) {
474 return ((uint32_t)((int32_t)inoise16_raw(x) + 17308L)) << 1;
475}
476
477int8_t inoise8_raw(uint16_t x, uint16_t y, uint16_t z)
478{
479 // Find the unit cube containing the point
480 uint8_t X = x>>8;
481 uint8_t Y = y>>8;
482 uint8_t Z = z>>8;
483
484 // Hash cube corner coordinates
485 uint8_t A = P(X)+Y;
486 uint8_t AA = P(A)+Z;
487 uint8_t AB = P(A+1)+Z;
488 uint8_t B = P(X+1)+Y;
489 uint8_t BA = P(B) + Z;
490 uint8_t BB = P(B+1)+Z;
491
492 // Get the relative position of the point in the cube
493 uint8_t u = x;
494 uint8_t v = y;
495 uint8_t w = z;
496
497 // Get a signed version of the above for the grad function
498 int8_t xx = ((uint8_t)(x)>>1) & 0x7F;
499 int8_t yy = ((uint8_t)(y)>>1) & 0x7F;
500 int8_t zz = ((uint8_t)(z)>>1) & 0x7F;
501 uint8_t N = 0x80;
502
503 u = EASE8(u); v = EASE8(v); w = EASE8(w);
504
505 int8_t X1 = lerp7by8(grad8(P(AA), xx, yy, zz), grad8(P(BA), xx - N, yy, zz), u);
506 int8_t X2 = lerp7by8(grad8(P(AB), xx, yy-N, zz), grad8(P(BB), xx - N, yy - N, zz), u);
507 int8_t X3 = lerp7by8(grad8(P(AA+1), xx, yy, zz-N), grad8(P(BA+1), xx - N, yy, zz-N), u);
508 int8_t X4 = lerp7by8(grad8(P(AB+1), xx, yy-N, zz-N), grad8(P(BB+1), xx - N, yy - N, zz - N), u);
509
510 int8_t Y1 = lerp7by8(X1,X2,v);
511 int8_t Y2 = lerp7by8(X3,X4,v);
512
513 int8_t ans = lerp7by8(Y1,Y2,w);
514
515 return ans;
516}
517
518uint8_t inoise8(uint16_t x, uint16_t y, uint16_t z) {
519 //return scale8(76+(inoise8_raw(x,y,z)),215)<<1;
520 int8_t n = inoise8_raw( x, y, z); // -64..+64
521 n+= 64; // 0..128
522 uint8_t ans = qadd8( n, n); // 0..255
523 return ans;
524}
525
526int8_t inoise8_raw(uint16_t x, uint16_t y)
527{
528 // Find the unit cube containing the point
529 uint8_t X = x>>8;
530 uint8_t Y = y>>8;
531
532 // Hash cube corner coordinates
533 uint8_t A = P(X)+Y;
534 uint8_t AA = P(A);
535 uint8_t AB = P(A+1);
536 uint8_t B = P(X+1)+Y;
537 uint8_t BA = P(B);
538 uint8_t BB = P(B+1);
539
540 // Get the relative position of the point in the cube
541 uint8_t u = x;
542 uint8_t v = y;
543
544 // Get a signed version of the above for the grad function
545 int8_t xx = ((uint8_t)(x)>>1) & 0x7F;
546 int8_t yy = ((uint8_t)(y)>>1) & 0x7F;
547 uint8_t N = 0x80;
548
549 u = EASE8(u); v = EASE8(v);
550
551 int8_t X1 = lerp7by8(grad8(P(AA), xx, yy), grad8(P(BA), xx - N, yy), u);
552 int8_t X2 = lerp7by8(grad8(P(AB), xx, yy-N), grad8(P(BB), xx - N, yy - N), u);
553
554 int8_t ans = lerp7by8(X1,X2,v);
555
556 return ans;
557 // return scale8((70+(ans)),234)<<1;
558}
559
560
561
562uint8_t inoise8(uint16_t x, uint16_t y) {
563 //return scale8(69+inoise8_raw(x,y),237)<<1;
564 int8_t n = inoise8_raw( x, y); // -64..+64
565 n+= 64; // 0..128
566 uint8_t ans = qadd8( n, n); // 0..255
567 return ans;
568}
569
570// output range = -64 .. +64
571int8_t inoise8_raw(uint16_t x)
572{
573 // Find the unit cube containing the point
574 uint8_t X = x>>8;
575
576 // Hash cube corner coordinates
577 uint8_t A = P(X);
578 uint8_t AA = P(A);
579 uint8_t B = P(X+1);
580 uint8_t BA = P(B);
581
582 // Get the relative position of the point in the cube
583 uint8_t u = x;
584
585 // Get a signed version of the above for the grad function
586 int8_t xx = ((uint8_t)(x)>>1) & 0x7F;
587 uint8_t N = 0x80;
588
589 u = EASE8( u);
590
591 int8_t ans = lerp7by8(grad8(P(AA), xx), grad8(P(BA), xx - N), u);
592
593 return ans;
594}
595
596uint8_t inoise8(uint16_t x) {
597 int8_t n = inoise8_raw(x); //-64..+64
598 n += 64; // 0..128
599 uint8_t ans = qadd8(n,n); // 0..255
600 return ans;
601}
602
603// struct q44 {
604// uint8_t i:4;
605// uint8_t f:4;
606// q44(uint8_t _i, uint8_t _f) {i=_i; f=_f; }
607// };
608
609// uint32_t mul44(uint32_t v, q44 mulby44) {
610// return (v *mulby44.i) + ((v * mulby44.f) >> 4);
611// }
612//
613// uint16_t mul44_16(uint16_t v, q44 mulby44) {
614// return (v *mulby44.i) + ((v * mulby44.f) >> 4);
615// }
616
617void fill_raw_noise8(uint8_t *pData, uint8_t num_points, uint8_t octaves, uint16_t x, int scale, uint16_t time) {
618 uint32_t _xx = x;
619 uint32_t scx = scale;
620 for(int o = 0; o < octaves; ++o) {
621 for(int i = 0,xx=_xx; i < num_points; ++i, xx+=scx) {
622 pData[i] = qadd8(pData[i],inoise8(xx,time)>>o);
623 }
624
625 _xx <<= 1;
626 scx <<= 1;
627 }
628}
629
630void fill_raw_noise16into8(uint8_t *pData, uint8_t num_points, uint8_t octaves, uint32_t x, int scale, uint32_t time) {
631 uint32_t _xx = x;
632 uint32_t scx = scale;
633 for(int o = 0; o < octaves; ++o) {
634 for(int i = 0,xx=_xx; i < num_points; ++i, xx+=scx) {
635 uint32_t accum = (inoise16(xx,time))>>o;
636 accum += (pData[i]<<8);
637 if(accum > 65535) { accum = 65535; }
638 pData[i] = accum>>8;
639 }
640
641 _xx <<= 1;
642 scx <<= 1;
643 }
644}
645
660void fill_raw_2dnoise8(uint8_t *pData, int width, int height, uint8_t octaves, q44 freq44, fract8 amplitude, int skip, uint16_t x, int16_t scalex, uint16_t y, int16_t scaley, uint16_t time) {
661 if(octaves > 1) {
662 fill_raw_2dnoise8(pData, width, height, octaves-1, freq44, amplitude, skip+1, x*freq44, freq44 * scalex, y*freq44, freq44 * scaley, time);
663 } else {
664 // amplitude is always 255 on the lowest level
665 amplitude=255;
666 }
667
668 scalex *= skip;
669 scaley *= skip;
670
671 fract8 invamp = 255-amplitude;
672 uint16_t xx = x;
673 for(int i = 0; i < height; ++i, y+=scaley) {
674 uint8_t *pRow = pData + (i*width);
675 xx = x;
676 for(int j = 0; j < width; ++j, xx+=scalex) {
677 uint8_t noise_base = inoise8(xx,y,time);
678 noise_base = (0x80 & noise_base) ? (noise_base - 127) : (127 - noise_base);
679 noise_base = scale8(noise_base<<1,amplitude);
680 if(skip == 1) {
681 pRow[j] = scale8(pRow[j],invamp) + noise_base;
682 } else {
683 for(int ii = i; ii<(i+skip) && ii<height; ++ii) {
684 uint8_t *pRow = pData + (ii*width);
685 for(int jj=j; jj<(j+skip) && jj<width; ++jj) {
686 pRow[jj] = scale8(pRow[jj],invamp) + noise_base;
687 }
688 }
689 }
690 }
691 }
692}
693
694void fill_raw_2dnoise8(uint8_t *pData, int width, int height, uint8_t octaves, uint16_t x, int scalex, uint16_t y, int scaley, uint16_t time) {
695 fill_raw_2dnoise8(pData, width, height, octaves, q44(2,0), 128, 1, x, scalex, y, scaley, time);
696}
697
698void fill_raw_2dnoise16(uint16_t *pData, int width, int height, uint8_t octaves, q88 freq88, fract16 amplitude, int skip, uint32_t x, int32_t scalex, uint32_t y, int32_t scaley, uint32_t time) {
699 if(octaves > 1) {
700 fill_raw_2dnoise16(pData, width, height, octaves-1, freq88, amplitude, skip, x *freq88 , scalex *freq88, y * freq88, scaley * freq88, time);
701 } else {
702 // amplitude is always 255 on the lowest level
703 amplitude=65535;
704 }
705
706 scalex *= skip;
707 scaley *= skip;
708 fract16 invamp = 65535-amplitude;
709 for(int i = 0; i < height; i+=skip, y+=scaley) {
710 uint16_t *pRow = pData + (i*width);
711 for(int j = 0,xx=x; j < width; j+=skip, xx+=scalex) {
712 uint16_t noise_base = inoise16(xx,y,time);
713 noise_base = (0x8000 & noise_base) ? noise_base - (32767) : 32767 - noise_base;
714 noise_base = scale16(noise_base<<1, amplitude);
715 if(skip==1) {
716 pRow[j] = scale16(pRow[j],invamp) + noise_base;
717 } else {
718 for(int ii = i; ii<(i+skip) && ii<height; ++ii) {
719 uint16_t *pRow = pData + (ii*width);
720 for(int jj=j; jj<(j+skip) && jj<width; ++jj) {
721 pRow[jj] = scale16(pRow[jj],invamp) + noise_base;
722 }
723 }
724 }
725 }
726 }
727}
728
731int32_t nmin=11111110;
734int32_t nmax=0;
735
736void fill_raw_2dnoise16into8(uint8_t *pData, int width, int height, uint8_t octaves, q44 freq44, fract8 amplitude, int skip, uint32_t x, int32_t scalex, uint32_t y, int32_t scaley, uint32_t time) {
737 if(octaves > 1) {
738 fill_raw_2dnoise16into8(pData, width, height, octaves-1, freq44, amplitude, skip+1, x*freq44, scalex *freq44, y*freq44, scaley * freq44, time);
739 } else {
740 // amplitude is always 255 on the lowest level
741 amplitude=255;
742 }
743
744 scalex *= skip;
745 scaley *= skip;
746 uint32_t xx;
747 fract8 invamp = 255-amplitude;
748 for(int i = 0; i < height; i+=skip, y+=scaley) {
749 uint8_t *pRow = pData + (i*width);
750 xx = x;
751 for(int j = 0; j < width; j+=skip, xx+=scalex) {
752 uint16_t noise_base = inoise16(xx,y,time);
753 noise_base = (0x8000 & noise_base) ? noise_base - (32767) : 32767 - noise_base;
754 noise_base = scale8(noise_base>>7,amplitude);
755 if(skip==1) {
756 pRow[j] = qadd8(scale8(pRow[j],invamp),noise_base);
757 } else {
758 for(int ii = i; ii<(i+skip) && ii<height; ++ii) {
759 uint8_t *pRow = pData + (ii*width);
760 for(int jj=j; jj<(j+skip) && jj<width; ++jj) {
761 pRow[jj] = scale8(pRow[jj],invamp) + noise_base;
762 }
763 }
764 }
765 }
766 }
767}
768
769void fill_raw_2dnoise16into8(uint8_t *pData, int width, int height, uint8_t octaves, uint32_t x, int scalex, uint32_t y, int scaley, uint32_t time) {
770 fill_raw_2dnoise16into8(pData, width, height, octaves, q44(2,0), 171, 1, x, scalex, y, scaley, time);
771}
772
773void fill_noise8(CRGB *leds, int num_leds,
774 uint8_t octaves, uint16_t x, int scale,
775 uint8_t hue_octaves, uint16_t hue_x, int hue_scale,
776 uint16_t time) {
777
778 if (num_leds <= 0) return;
779
780 for (int j = 0; j < num_leds; j += 255) {
781 const int LedsRemaining = num_leds - j;
782 const int LedsPer = LedsRemaining > 255 ? 255 : LedsRemaining; // limit to 255 max
783
784 if (LedsPer <= 0) continue;
785 VARIABLE_LENGTH_ARRAY(uint8_t, V, LedsPer);
786 VARIABLE_LENGTH_ARRAY(uint8_t, H, LedsPer);
787
788 memset(V, 0, LedsPer);
789 memset(H, 0, LedsPer);
790
791 fill_raw_noise8(V, LedsPer, octaves, x, scale, time);
792 fill_raw_noise8(H, LedsPer, hue_octaves, hue_x, hue_scale, time);
793
794 for (int i = 0; i < LedsPer; ++i) {
795 leds[i + j] = CHSV(H[i], 255, V[i]);
796 }
797 }
798}
799
800void fill_noise16(CRGB *leds, int num_leds,
801 uint8_t octaves, uint16_t x, int scale,
802 uint8_t hue_octaves, uint16_t hue_x, int hue_scale,
803 uint16_t time, uint8_t hue_shift) {
804
805 if (num_leds <= 0) return;
806
807 for (int j = 0; j < num_leds; j += 255) {
808 const int LedsRemaining = num_leds - j;
809 const int LedsPer = LedsRemaining > 255 ? 255 : LedsRemaining; // limit to 255 max
810 if (LedsPer <= 0) continue;
811 VARIABLE_LENGTH_ARRAY(uint8_t, V, LedsPer);
812 VARIABLE_LENGTH_ARRAY(uint8_t, H, LedsPer);
813
814 memset(V, 0, LedsPer);
815 memset(H, 0, LedsPer);
816
817 fill_raw_noise16into8(V, LedsPer, octaves, x, scale, time);
818 fill_raw_noise8(H, LedsPer, hue_octaves, hue_x, hue_scale, time);
819
820 for (int i = 0; i < LedsPer; ++i) {
821 leds[i + j] = CHSV(H[i] + hue_shift, 255, V[i]);
822 }
823 }
824}
825
826void fill_2dnoise8(CRGB *leds, int width, int height, bool serpentine,
827 uint8_t octaves, uint16_t x, int xscale, uint16_t y, int yscale, uint16_t time,
828 uint8_t hue_octaves, uint16_t hue_x, int hue_xscale, uint16_t hue_y, uint16_t hue_yscale,uint16_t hue_time,bool blend) {
829 const size_t array_size = (size_t)height * width;
830 if (array_size <= 0) return;
831 VARIABLE_LENGTH_ARRAY(uint8_t, V, array_size);
832 VARIABLE_LENGTH_ARRAY(uint8_t, H, array_size);
833
834 memset(V,0,height*width);
835 memset(H,0,height*width);
836
837 fill_raw_2dnoise8((uint8_t*)V,width,height,octaves,x,xscale,y,yscale,time);
838 fill_raw_2dnoise8((uint8_t*)H,width,height,hue_octaves,hue_x,hue_xscale,hue_y,hue_yscale,hue_time);
839
840 int w1 = width-1;
841 int h1 = height-1;
842 for(int i = 0; i < height; ++i) {
843 int wb = i*width;
844 for(int j = 0; j < width; ++j) {
845 CRGB led(CHSV(H[(h1-i)*width + (w1-j)], 255, V[i*width + j]));
846
847 int pos = j;
848 if(serpentine && (i & 0x1)) {
849 pos = w1-j;
850 }
851
852 if(blend) {
853 // Safer blending to avoid potential undefined behavior
854 CRGB temp = leds[wb+pos];
855 temp.nscale8(128); // Scale by 50%
856 led.nscale8(128);
857 leds[wb+pos] = temp + led;
858 } else {
859 leds[wb+pos] = led;
860 }
861 }
862 }
863}
864
865
866void fill_2dnoise16(CRGB *leds, int width, int height, bool serpentine,
867 uint8_t octaves, uint32_t x, int xscale, uint32_t y, int yscale, uint32_t time,
868 uint8_t hue_octaves, uint16_t hue_x, int hue_xscale, uint16_t hue_y, uint16_t hue_yscale,uint16_t hue_time, bool blend, uint16_t hue_shift) {
869
870 VARIABLE_LENGTH_ARRAY(uint8_t, V, height*width);
871 VARIABLE_LENGTH_ARRAY(uint8_t, H, height*width);
872
873 memset(V,0,height*width);
874 memset(H,0,height*width);
875
876 fill_raw_2dnoise16into8((uint8_t*)V,width,height,octaves,q44(2,0),171,1,x,xscale,y,yscale,time);
877 // fill_raw_2dnoise16into8((uint8_t*)V,width,height,octaves,x,xscale,y,yscale,time);
878 // fill_raw_2dnoise8((uint8_t*)V,width,height,hue_octaves,x,xscale,y,yscale,time);
879 fill_raw_2dnoise8((uint8_t*)H,width,height,hue_octaves,hue_x,hue_xscale,hue_y,hue_yscale,hue_time);
880
881
882 int w1 = width-1;
883 int h1 = height-1;
884 hue_shift >>= 8;
885
886 for(int i = 0; i < height; ++i) {
887 int wb = i*width;
888 for(int j = 0; j < width; ++j) {
889 CRGB led(CHSV(hue_shift + (H[(h1-i)*width + (w1-j)]), 196, V[i*width + j]));
890
891 int pos = j;
892 if(serpentine && (i & 0x1)) {
893 pos = w1-j;
894 }
895
896 if(blend) {
897 leds[wb+pos] >>= 1; leds[wb+pos] += (led>>=1);
898 } else {
899 leds[wb+pos] = led;
900 }
901 }
902 }
903}
904
906
907#pragma GCC diagnostic pop
central include file for FastLED, defines the CFastLED class/object
Template class for representing fractional ints.
Definition qfx.h:16
#define FL_PROGMEM
PROGMEM keyword for storage.
CRGB blend(const CRGB &p1, const CRGB &p2, fract8 amountOfP2)
Computes a new color blended some fraction of the way between two other colors.
qfx< uint8_t, 4, 4 > q44
A 4.4 integer (4 bits integer, 4 bits fraction)
Definition qfx.h:48
uint8_t fract8
ANSI: unsigned short _Fract.
Definition types.h:36
uint16_t fract16
ANSI: unsigned _Fract.
Definition types.h:46
LIB8STATIC_ALWAYS_INLINE uint8_t qadd8(uint8_t i, uint8_t j)
Add one byte to another, saturating at 0xFF.
Definition math8.h:31
LIB8STATIC_ALWAYS_INLINE int8_t avg7(int8_t i, int8_t j)
Calculate an integer average of two signed 7-bit integers (int8_t).
Definition math8.h:306
void fill_raw_noise8(uint8_t *pData, uint8_t num_points, uint8_t octaves, uint16_t x, int scale, uint16_t time)
Fill a 1D 8-bit buffer with noise, using inoise8()
Definition noise.cpp:617
void fill_raw_2dnoise16into8(uint8_t *pData, int width, int height, uint8_t octaves, q44 freq44, fract8 amplitude, int skip, uint32_t x, int32_t scalex, uint32_t y, int32_t scaley, uint32_t time)
Fill a 2D 8-bit buffer with noise, using inoise16()
Definition noise.cpp:736
void fill_raw_2dnoise8(uint8_t *pData, int width, int height, uint8_t octaves, q44 freq44, fract8 amplitude, int skip, uint16_t x, int16_t scalex, uint16_t y, int16_t scaley, uint16_t time)
Fill a 2D 8-bit buffer with noise, using inoise8()
Definition noise.cpp:660
void fill_2dnoise8(CRGB *leds, int width, int height, bool serpentine, uint8_t octaves, uint16_t x, int xscale, uint16_t y, int yscale, uint16_t time, uint8_t hue_octaves, uint16_t hue_x, int hue_xscale, uint16_t hue_y, uint16_t hue_yscale, uint16_t hue_time, bool blend)
Fill an LED matrix with random colors, using 8-bit noise.
Definition noise.cpp:826
void fill_2dnoise16(CRGB *leds, int width, int height, bool serpentine, uint8_t octaves, uint32_t x, int xscale, uint32_t y, int yscale, uint32_t time, uint8_t hue_octaves, uint16_t hue_x, int hue_xscale, uint16_t hue_y, uint16_t hue_yscale, uint16_t hue_time, bool blend, uint16_t hue_shift)
Fill an LED matrix with random colors, using 16-bit noise.
Definition noise.cpp:866
void fill_noise8(CRGB *leds, int num_leds, uint8_t octaves, uint16_t x, int scale, uint8_t hue_octaves, uint16_t hue_x, int hue_scale, uint16_t time)
Fill an LED array with random colors, using 8-bit noise.
Definition noise.cpp:773
void fill_noise16(CRGB *leds, int num_leds, uint8_t octaves, uint16_t x, int scale, uint8_t hue_octaves, uint16_t hue_x, int hue_scale, uint16_t time, uint8_t hue_shift)
Fill an LED array with random colors, using 16-bit noise.
Definition noise.cpp:800
void fill_raw_2dnoise16(uint16_t *pData, int width, int height, uint8_t octaves, q88 freq88, fract16 amplitude, int skip, uint32_t x, int32_t scalex, uint32_t y, int32_t scaley, uint32_t time)
Fill a 2D 16-bit buffer with noise, using inoise16()
Definition noise.cpp:698
void fill_raw_noise16into8(uint8_t *pData, uint8_t num_points, uint8_t octaves, uint32_t x, int scale, uint32_t time)
Fill a 1D 8-bit buffer with noise, using inoise16()
Definition noise.cpp:630
int8_t inoise8_raw(uint16_t x, uint16_t y, uint16_t z)
8-bit, fixed point implementation of Perlin's noise without scaling.
Definition noise.cpp:477
int16_t inoise16_raw(uint32_t x, uint32_t y, uint32_t z)
16-bit, fixed point implementation of Perlin's noise without scaling.
Definition noise.cpp:341
uint16_t inoise16(uint32_t x, uint32_t y, uint32_t z)
16-bit, fixed point implementation of Perlin's noise.
Definition noise.cpp:384
uint8_t inoise8(uint16_t x, uint16_t y, uint16_t z)
8-Bit, fixed point implementation of Perlin's noise.
Definition noise.cpp:518
LIB8STATIC uint16_t scale16(uint16_t i, fract16 scale)
Scale a 16-bit unsigned value by an 16-bit value, which is treated as the numerator of a fraction who...
Definition scale8.h:540
LIB8STATIC_ALWAYS_INLINE uint8_t scale8(uint8_t i, fract8 scale)
Scale one byte by a second one, which is treated as the numerator of a fraction whose denominator is ...
Definition scale8.h:34
#define FASTLED_NAMESPACE_END
End of the FastLED namespace.
Definition namespace.h:16
#define FASTLED_NAMESPACE_BEGIN
Start of the FastLED namespace.
Definition namespace.h:14
#define P(x)
Reads a single byte from the p array.
Definition noise.cpp:48
int32_t nmin
Unused.
Definition noise.cpp:731
int32_t nmax
Unused.
Definition noise.cpp:734
Representation of an HSV pixel (hue, saturation, value (aka brightness)).
Definition chsv.h:16
Representation of an RGB pixel (Red, Green, Blue)
Definition crgb.h:54
CRGB & nscale8(uint8_t scaledown)
Scale down a RGB to N/256ths of its current brightness, using "plain math" dimming rules.
Definition crgb.cpp:58