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