Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FastLED/FastLED.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kriegsman <kriegsman@users.noreply.github.com>2018-05-16 18:59:45 +0300
committerMark Kriegsman <kriegsman@users.noreply.github.com>2018-05-16 18:59:45 +0300
commitf718faf1cde3479aae1fb3f173996e6f55183406 (patch)
tree2df41bc7e88a01a4ce54b7817fa3589ddf478dcd
parentd41619400bbe77fe14dd1ccdca7521b152f460ef (diff)
Fix discontinuties in noise functions, both 8- and 16- bit versions. If you need the old behavior, you can edit fastled_config.h and change FASTLED_NOISE_FIXED to 0. Fixes #416. Thanks to everyone who reported this and helped track it down.
-rw-r--r--fastled_config.h9
-rw-r--r--lib8tion.h16
-rw-r--r--noise.cpp46
3 files changed, 58 insertions, 13 deletions
diff --git a/fastled_config.h b/fastled_config.h
index 690a21d0..99500c94 100644
--- a/fastled_config.h
+++ b/fastled_config.h
@@ -46,6 +46,15 @@
#define FASTLED_BLEND_FIXED 1
// #define FASTLED_BLEND_FIXED 0
+// Use this toggle whether to use 'fixed' FastLED 8- and 16-bit noise functions.
+// The prior noise functions had some math errors that led to 'discontinuities' in the
+// output, which by definition should be smooth and continuous. The bug led to
+// noise function output that had 'edges' and glitches in it. This is now fixed, and the
+// fix is enabled by default. However, if for some reason you wish to run with the old
+// noise code, including the glitches, you can disable the bugfix here.
+#define FASTLED_NOISE_FIXED 1
+//#define FASTLED_NOISE_FIXED 0
+
// Use this to determine how many times FastLED will attempt to re-transmit a frame if interrupted
// for too long by interrupts.
#ifndef FASTLED_INTERRUPT_RETRY_COUNT
diff --git a/lib8tion.h b/lib8tion.h
index c54f6b01..9397f4f3 100644
--- a/lib8tion.h
+++ b/lib8tion.h
@@ -615,6 +615,22 @@ LIB8STATIC uint8_t ease8InOutQuad(uint8_t val) {
#error "No implementation for ease8InOutQuad available."
#endif
+/// ease16InOutQuad: 16-bit quadratic ease-in / ease-out function
+// C implementation at this point
+LIB8STATIC uint16_t ease16InOutQuad( uint16_t i)
+{
+ uint16_t j = i;
+ if( j & 0x8000 ) {
+ j = 65535 - j;
+ }
+ uint16_t jj = scale16( j, j);
+ uint16_t jj2 = jj << 1;
+ if( i & 0x8000 ) {
+ jj2 = 65535 - jj2;
+ }
+ return jj2;
+}
+
/// ease8InOutCubic: 8-bit cubic ease-in / ease-out function
/// Takes around 18 cycles on AVR
diff --git a/noise.cpp b/noise.cpp
index 7a8ba79c..6509019a 100644
--- a/noise.cpp
+++ b/noise.cpp
@@ -52,6 +52,15 @@ static int16_t inline __attribute__((always_inline)) avg15_inline_avr_mul( int1
#endif
#endif
+// See fastled_config.h for notes on this;
+// "#define FASTLED_NOISE_FIXED 1" is the correct value
+#if FASTLED_NOISE_FIXED == 0
+#define EASE8(x) (FADE(x) )
+#define EASE16(x) (FADE(x) )
+#else
+#define EASE8(x) (ease8InOutQuad(x) )
+#define EASE16(x) (ease16InOutQuad(x))
+#endif
//
// #define FADE_12
#define FADE_16
@@ -300,8 +309,7 @@ int16_t inoise16_raw(uint32_t x, uint32_t y, uint32_t z)
int16_t zz = (w >> 1) & 0x7FFF;
uint16_t N = 0x8000L;
- u = FADE(u); v = FADE(v); w = FADE(w);
-
+ u = EASE16(u); v = EASE16(v); w = EASE16(w);
// skip the log fade adjustment for the moment, otherwise here we would
// adjust fade values for u,v,w
@@ -357,7 +365,7 @@ int16_t inoise16_raw(uint32_t x, uint32_t y)
int16_t yy = (v >> 1) & 0x7FFF;
uint16_t N = 0x8000L;
- u = FADE(u); v = FADE(v);
+ u = EASE16(u); v = EASE16(v);
int16_t X1 = LERP(grad16(P(AA), xx, yy), grad16(P(BA), xx - N, yy), u);
int16_t X2 = LERP(grad16(P(AB), xx, yy-N), grad16(P(BB), xx - N, yy - N), u);
@@ -400,7 +408,7 @@ int16_t inoise16_raw(uint32_t x)
int16_t xx = (u >> 1) & 0x7FFF;
uint16_t N = 0x8000L;
- u = FADE(u);
+ u = EASE16(u);
int16_t ans = LERP(grad16(P(AA), xx), grad16(P(BA), xx - N), u);
@@ -437,9 +445,8 @@ int8_t inoise8_raw(uint16_t x, uint16_t y, uint16_t z)
int8_t zz = ((uint8_t)(z)>>1) & 0x7F;
uint8_t N = 0x80;
- // u = FADE(u); v = FADE(v); w = FADE(w);
- u = scale8_LEAVING_R1_DIRTY(u,u); v = scale8_LEAVING_R1_DIRTY(v,v); w = scale8(w,w);
-
+ u = EASE8(u); v = EASE8(v); w = EASE8(w);
+
int8_t X1 = lerp7by8(grad8(P(AA), xx, yy, zz), grad8(P(BA), xx - N, yy, zz), u);
int8_t X2 = lerp7by8(grad8(P(AB), xx, yy-N, zz), grad8(P(BB), xx - N, yy - N, zz), u);
int8_t X3 = lerp7by8(grad8(P(AA+1), xx, yy, zz-N), grad8(P(BA+1), xx - N, yy, zz-N), u);
@@ -480,9 +487,8 @@ int8_t inoise8_raw(uint16_t x, uint16_t y)
int8_t yy = ((uint8_t)(y)>>1) & 0x7F;
uint8_t N = 0x80;
- // u = FADE(u); v = FADE(v); w = FADE(w);
- u = scale8_LEAVING_R1_DIRTY(u,u); v = scale8(v,v);
-
+ u = EASE8(u); v = EASE8(v);
+
int8_t X1 = lerp7by8(grad8(P(AA), xx, yy), grad8(P(BA), xx - N, yy), u);
int8_t X2 = lerp7by8(grad8(P(AB), xx, yy-N), grad8(P(BB), xx - N, yy - N), u);
@@ -492,8 +498,13 @@ int8_t inoise8_raw(uint16_t x, uint16_t y)
// return scale8((70+(ans)),234)<<1;
}
+
+
uint8_t inoise8(uint16_t x, uint16_t y) {
return scale8(69+inoise8_raw(x,y),237)<<1;
+// int8_t n = inoise8_raw( x, y);
+// uint8_t ans = qadd8( n, n);
+// return ans;
}
int8_t inoise8_raw(uint16_t x)
@@ -514,8 +525,8 @@ int8_t inoise8_raw(uint16_t x)
int8_t xx = ((uint8_t)(x)>>1) & 0x7F;
uint8_t N = 0x80;
- u = scale8(u,u);
-
+ u = EASE8( u);
+
int8_t ans = lerp7by8(grad8(P(AA), xx), grad8(P(BA), xx - N), u);
return ans;
@@ -523,7 +534,16 @@ int8_t inoise8_raw(uint16_t x)
}
uint8_t inoise8(uint16_t x) {
- return scale8(69+inoise8_raw(x), 255)<<1;
+// return scale8(69+inoise8_raw(x), 255)<<1;
+ int8_t n = inoise8_raw(x);
+
+ //uint8_t ans = scale8(69+n, 255)<<1;
+ //if( n < -64) n = -64;
+ //if( n > 63 ) n = 63;
+
+ uint8_t ans = qadd8(n,n);
+
+ return ans;
}
// struct q44 {