-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding perlin noise replacement for fastled functions #4594
base: main
Are you sure you want to change the base?
Conversation
needs a proper scaling analysis of all steps in all resolutions to minimize errors.
WalkthroughThe changes update the noise generation methods across multiple modules. In the audio reactive component and various LED effect modules, calls to Changes
Possibly related PRs
Tip ⚡🧪 Multi-step agentic review comment chat (experimental)
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (8)
wled00/FX.cpp (2)
6224-6224
: Minor suggestion regarding type usage.Storing
sizeof(float)
in anunsigned
works, but typicallysize_t
is used for sizes. This is non-blocking.
6648-6648
: Consider clarifying the expression with parentheses.
strip.now * SEGMENT.speed/64 * SEGLEN/255
can be read in multiple ways due to left-to-right associativity. Adding parentheses would help avoid confusion.wled00/fcn_declare.h (1)
517-525
: Add brief usage notes for new Perlin noise prototypes.
These new function declarations look logically consistent and match the changes elsewhere in the PR.
However, consider documenting the parameter ranges and expected outputs (especially foris16bit
in the_raw
variations) to help maintain clarity for future developers.wled00/util.cpp (5)
622-625
: Add short overview of newly added Perlin functions.
The comment block reference is good, but consider briefly summarizing the main differences from typical noise functions, including performance rationale and approximate numeric range.
626-626
: Prefer a compile-time constant over a macro.
Usingconstexpr int PERLIN_SHIFT = 1;
instead of#define
can help with type safety and debugging.-#define PERLIN_SHIFT 1 +constexpr int PERLIN_SHIFT = 1;
637-645
: Validate hashing approach for 1D gradient.
This approach looks correct for single-dimension Perlin. Ensure that the prime multipliers align well with your random/hashing goals, and confirm no collisions degrade the noise distribution.Would you like a test snippet or additional analysis to confirm uniform distribution?
664-669
: Confirm numeric stability insmoothstep
.
This simplified cubic polynomial is standard, but the bit shifts are quite tight. If you find any banding artifacts, consider minor adjustments or an alternate polynomial.
694-724
:perlin2D_raw
matches 1D logic well.
Everything appears consistent. Check for any off-by-one or wrap-around issues if using extremely high x, y values.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
usermods/audioreactive/audio_reactive.cpp
(1 hunks)wled00/FX.cpp
(30 hunks)wled00/fcn_declare.h
(1 hunks)wled00/util.cpp
(2 hunks)wled00/wled.cpp
(0 hunks)
💤 Files with no reviewable changes (1)
- wled00/wled.cpp
⏰ Context from checks skipped due to timeout of 90000ms (19)
- GitHub Check: wled_build / Build Enviornments (usermods)
- GitHub Check: wled_build / Build Enviornments (esp32s3_4M_qspi)
- GitHub Check: wled_build / Build Enviornments (esp32s3dev_16MB_opi)
- GitHub Check: wled_build / Build Enviornments (esp32dev_V4)
- GitHub Check: wled_build / Build Enviornments (esp32c3dev)
- GitHub Check: wled_build / Build Enviornments (esp01_1m_full_compat)
- GitHub Check: wled_build / Build Enviornments (esp32_wrover)
- GitHub Check: wled_build / Build Enviornments (esp32s3dev_8MB_opi)
- GitHub Check: wled_build / Build Enviornments (lolin_s2_mini)
- GitHub Check: wled_build / Build Enviornments (esp01_1m_full_160)
- GitHub Check: wled_build / Build Enviornments (esp32dev)
- GitHub Check: wled_build / Build Enviornments (esp32_eth)
- GitHub Check: wled_build / Build Enviornments (nodemcuv2)
- GitHub Check: wled_build / Build Enviornments (esp8266_2m)
- GitHub Check: wled_build / Build Enviornments (esp8266_2m_160)
- GitHub Check: wled_build / Build Enviornments (esp8266_2m_compat)
- GitHub Check: wled_build / Build Enviornments (nodemcuv2_compat)
- GitHub Check: wled_build / Build Enviornments (esp01_1m_full)
- GitHub Check: wled_build / Build Enviornments (nodemcuv2_160)
🔇 Additional comments (39)
usermods/audioreactive/audio_reactive.cpp (1)
872-872
: Improved performance by replacing inoise8 with perlin8 for simulated audio.This change aligns with the PR's objective of replacing FastLED's inoise functions with faster Perlin noise implementations. For simulated microphone input, using perlin8() should provide better performance while maintaining similar random noise patterns needed for audio simulation.
wled00/FX.cpp (28)
2186-2186
: Looks good.No significant concerns regarding shifting from
inoise8
toperlin8
.
2206-2206
: Double-check potential wrap-around insin8_t(noise * 3)
.When multiplying
noise
by 3, the value can exceed 255 and wrap around. If wrap-around behavior is intentional, no change is needed. Otherwise, consider clamping or casting to ensure the result stays within the expected range.
2224-2224
: Implementation appears consistent.Replacing
inoise16
withperlin16
is straightforward here.
2245-2245
: No issues detected.Transition to
perlin16
with a right shift for the final 8-bit value looks appropriate.
2260-2260
: Confirm expected range for color palette index.Unlike other places where
perlin16(...) >> 8
is used, this call passes the full 16-bit value intocolor_from_palette()
without shifting. If that’s intentional, please verify that the function uses the entire 16-bit range as intended. Otherwise, consider shifting or casting.
4122-4122
: Change is acceptable.Using
perlin8(...)/16
formodVal
to randomize the wave is a fine adaptation.
4191-4191
: Implementation looks correct.Noise-based index generation is consistent with the rest of the code.
4802-4802
: No concerns here.
perlin16
usage with mapped output aligns with the intended effect logic.
5060-5060
: No issues noted.Simple two-argument
perlin8
call looks fine.
5453-5457
: Transition to newperlin8()
calls is clear.These random offsets for generating mapped coordinates appear intentional.
5513-5513
: Seems straightforward.
perlin8(x * scale, y * scale, strip.now / (16 - SEGMENT.speed/16))
is consistent with other usage patterns.
5535-5538
: Change is valid.Three-argument calls to
perlin8
for separate axes are standard here.
5583-5583
: Change looks good.New noise-based palette indexing is consistent with other segments.
5700-5701
: Conversion logic is acceptable.Replacing
inoise8_raw
withperlin8
and applying an offset/division is a normal approach for adjusting the noise range.
6238-6245
: Verify float-to-int conversions in indexing.
abs8(u1 - j * sinus)
suggests an implicit float → int cast. Confirm that truncation is intended before taking% cols
. If so, explicitly cast to avoid ambiguity.
6394-6398
: Implementation looks fine.Incorporation of
perlin8
with audio reactivity handling is done consistently.
6476-6476
: No issues identified.Simultaneous use of multiple Perlin inputs appears deliberate.
6498-6498
: All good.Mirrors the gravity logic from the preceding chunk.
6620-6620
: Looks correct.Noise-based indexing for sound-based expansions is consistent.
6679-6679
: No concerns.Logic is coherent with other perlin8 usage.
7095-7095
: Implementation is consistent.Noise-based location mapping for the new bin approach is fine.
7545-7545
: Implementation is sound.Combining
perlin16 >> 8
into 8-bit data is standard.
8050-8050
: No concerns with applying wind force.Shifting the
perlin8(...)
result by 7 after scaling is consistent with the rest of the code.
8059-8059
: Change is appropriate.
perlin8()
for turbulence is a standard approach in these effects.
8276-8277
: Approved.Gravity-based randomization using Perlin noise is in line with the rest of this PR.
8348-8352
: Potential overflow inint8_t
fields.
baseheight
and additionalperlin8
calls can sum up to 510, exceeding the range ofint8_t
. If both are up to 255, the result will overflow. Consider clamping or using a larger type, e.g.int16_t
.Apply this diff if you want to cast and clamp:
- int8_t xslope = (baseheight + (int16_t)perlin8(xnoise - 10, ynoise, SEGENV.aux0)); - int8_t yslope = (baseheight + (int16_t)perlin8(xnoise, ynoise - 10, SEGENV.aux0)); + int16_t xslope = baseheight + perlin8(xnoise - 10, ynoise, SEGENV.aux0); + int16_t yslope = baseheight + perlin8(xnoise, ynoise - 10, SEGENV.aux0); + if (xslope < -128) xslope = -128; + else if (xslope > 127) xslope = 127; + if (yslope < -128) yslope = -128; + else if (yslope > 127) yslope = 127;
9720-9720
: No issues present.Noise-based
xgravity
logic is consistent with the rest of the effect design.
10072-10072
: Change is acceptable.Adding a randomized hue offset from Perlin noise is consistent with the approach in other modes.
wled00/util.cpp (10)
509-509
: Confirm output range suitability.
Replacinginoise8
withperlin8
can subtly alter the output distribution. Ensure the resulting effect still aligns with the target audio visualization, as Perlin noise might differ slightly at extremes.
514-514
: Validate consistency with previous visual/audio effects.
Similar to line 509, confirm that the changes introduced byperlin8
preserve the intended effect behavior under different timing or input parameters.
628-635
: Check for boundary cases inhashToGradient
.
The function is concise and efficient. Performance seems strong for a small integer-based approach. Just make sure extreme corner cases (e.g. large input hash) don’t cause unexpected intermediate overflows.
647-653
: Cross-check potential integer overflow ingradient2D
.
The function accounts for two coordinates; it appears you are hashing them together with distinct prime factors. The logic is consistent with the 1D approach. No immediate issues seen.
655-662
: Hash combination ingradient3D
.
Using multiple prime-based shifts to incorporate x, y, z is a solid strategy. The scale factor in the return statement (line 661) looks correct for typical Perlin usage.
671-674
: Check inline usage inlerpPerlin
.
The linear interpolation approach is clear. Having it inlined helps performance. No immediate concerns.
676-692
: Wrap logic inperlin1D_raw
carefully.
Theis16bit
branching is effective for controlling wrap-around in small coordinate spaces. Be sure all call sites pass the correct boolean and expect the unscaled raw range.
726-770
:perlin3D_raw
complexity.
The logic is more involved, but it follows the same approach as the 1D and 2D implementations. The large arithmetic is carefully bit-shifted. Keep an eye on performance if used in tight loops, but overall this should be acceptable.
772-783
: Ensure scaling constants remain consistent inperlin16
.
These scale factors (e.g.1159
,1537
,1731
) appear carefully chosen. If you further tweak the hashing or random steps, re-verify these constants to preserve the approximate output range.
785-795
: Double-check final offsets inperlin8
.
After scaling down to 8 bits, the offset constants (e.g.+ 32769
) ensure the range stays within 0–255. Encouraging thorough real-world testing to verify no unexpected boundary saturations occur.
I would have preferred if you'd use |
the final goal is to replace fastled, then it does not make sense to me to keep the legacy function names. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (5)
wled00/FX.cpp (5)
2206-2206
: Confirm shift-by-8 logic aligns with desired color range.
This usage discards the lower 8 bits from the 16-bit Perlin output. Ensure this is producing the intended intensity curve.
2224-2224
: Avoid using magic number 4223 for Z-coordinate.
Consider extracting4223
into a named constant for clarity.- unsigned noise = perlin16(real_x, 0, 4223) >> 8; + static const uint16_t PERLIN_Z_BASE = 4223; + unsigned noise = perlin16(real_x, 0, PERLIN_Z_BASE) >> 8;
4122-4122
: Replace repeated expression(i*10 + i*10)
withi*20
.
For clarity, consider simplifying the multiplication.- if (moder == 1) modVal = (perlin8(i*10 + i*10) /16); + if (moder == 1) modVal = (perlin8(i*20) /16);
6399-6402
: Add parentheses to clarify operator precedence.
Using parentheses can help ensure the correct order of multiplication and division, especially with(1 + SEGMENT.intensity/64)* perlin8(...) / 2
.- unsigned thisVal = (1 + SEGMENT.intensity/64) * perlin8(i * 45 , t , t)/2; + unsigned thisVal = ((1 + (SEGMENT.intensity/64)) * perlin8(i * 45, t, t)) / 2;
6653-6653
: Check arithmetic order when multiplying bySEGLEN/255
.
Potential goals might be better served by careful ordering or casting.- unsigned index = perlin8(i*SEGMENT.speed/64, strip.now*SEGMENT.speed/64*SEGLEN/255); + unsigned index = perlin8((i*SEGMENT.speed)/64, (strip.now*SEGMENT.speed/64)*(SEGLEN/255));
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
wled00/FX.cpp
(28 hunks)wled00/fcn_declare.h
(2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (18)
- GitHub Check: wled_build / Build Enviornments (lolin_s2_mini)
- GitHub Check: wled_build / Build Enviornments (usermods)
- GitHub Check: wled_build / Build Enviornments (esp32s3_4M_qspi)
- GitHub Check: wled_build / Build Enviornments (esp32s3dev_8MB_opi)
- GitHub Check: wled_build / Build Enviornments (esp32c3dev)
- GitHub Check: wled_build / Build Enviornments (esp32s3dev_16MB_opi)
- GitHub Check: wled_build / Build Enviornments (esp8266_2m_160)
- GitHub Check: wled_build / Build Enviornments (esp8266_2m_compat)
- GitHub Check: wled_build / Build Enviornments (esp32dev)
- GitHub Check: wled_build / Build Enviornments (esp32_wrover)
- GitHub Check: wled_build / Build Enviornments (esp01_1m_full_compat)
- GitHub Check: wled_build / Build Enviornments (esp32_eth)
- GitHub Check: wled_build / Build Enviornments (esp01_1m_full_160)
- GitHub Check: wled_build / Build Enviornments (nodemcuv2_compat)
- GitHub Check: wled_build / Build Enviornments (esp01_1m_full)
- GitHub Check: wled_build / Build Enviornments (nodemcuv2_160)
- GitHub Check: wled_build / Build Enviornments (esp8266_2m)
- GitHub Check: wled_build / Build Enviornments (nodemcuv2)
🔇 Additional comments (27)
wled00/FX.cpp (23)
2186-2186
: Check for potential overflow with large SEGLEN.
IfSEGLEN
is large, theni * SEGLEN
might overflow the parameter's expected range. Verify if wrap-around is the intended effect.
2245-2245
: Looks consistent with the other Perlin calls.
The shift-by-8 follows the established pattern of reducing 16-bit noise to 8-bit.
2260-2260
: Check consistency with other>> 8
cases.
Other code samples shift the 16-bit result down. Verify if retaining the full 16-bit range is intentional here.
4191-4191
: Replacement ofinoise8
withperlin8
is straightforward.
Everything looks good here; logic and parameters remain consistent.
4802-4802
: EnsureSEGMENT.speed
never reaches 260 or higher.
Because(260 - SEGMENT.speed)
is used in division, verify that it doesn’t become zero in corner cases.
5060-5060
: No immediate issues with this change.
The switch frominoise8
toperlin8
appears consistent, and the indexing logic remains intact.
5453-5457
: Double-check float vs integer usage inperlin8
calls.
strip.now * speed
is a float expression, butperlin8
typically expects integer parameters. Confirm that the cast or truncation is acceptable.
5513-5513
: Check integer division by(16 - SEGMENT.speed/16)
.
Ensure that(16 - SEGMENT.speed/16)
never goes to zero and is used as intended when speed is high.
5535-5538
: Potential risk for small denominators.
(256 - SEGMENT.speed)
and similar expressions can become small. Confirm that it never becomes zero or negative.
5583-5583
: Check_speed
for zero-safety.
(SEGENV.step / _speed)
could divide by zero if_speed
is 0. Verify_speed
is guaranteed nonzero.
5700-5701
: Verify the new scaling logic.
Previously, noise was halved. Now you subtract 127 and scale by/3
. Ensure these changes still produce the intended “bump” effect.
6481-6481
: Change frominoise8
toperlin8
is correctly implemented.
No issues spotted with parameter usage.
6503-6503
: Change frominoise8
toperlin8
is correctly implemented.
No issues spotted with parameter usage.
6625-6625
: Straightforward substitution toperlin8
.
Calculation forvolumeSmth
+ offsets remains consistent.
6684-6684
: All good here.
Noise usage and palette application remain functionally consistent.
7100-7100
: Looks fine for mapping.
Just ensure the mapped range [7500..58000] is correct for largeSEGLEN
.
7550-7550
: Use of>> 8
is consistent with the other 16-bit noise calls.
No issues spotted in scaling or palette usage.
8055-8055
: Centering noise around zero.
Casting toint16_t
and subtracting 127 is a valid approach to get signed wind speed from noise.
8064-8064
: Same pattern of re-centering noise.
Implementation looks consistent with the standard approach.
8281-8282
: Gravity anchored by Perlin noise.
Logic is consistent; no issues spotted.
8353-8357
: Particle forces from Perlin noise.
The usage of additional Perlin calls for slopes is stable.
9725-9725
: Simple shift frominoise8
toperlin8
.
No concerns with subtracting 128 to anchorxgravity
.
10077-10077
: Beware of largemids
values.
When multiplied and then shifted by 9, the final hue increment could overflow ifmids
orperlin8
output is high. Verify that’s acceptable.wled00/fcn_declare.h (4)
489-490
: Good addition of FastLED compatibility aliases.The inclusion of these legacy aliases (
inoise8
->perlin8
andinoise16
->perlin16
) provides backward compatibility with existing code that uses FastLED's noise functions, making the transition smoother.
519-521
: Well-structured raw Perlin noise function declarations.The raw Perlin noise function declarations provide a good foundation for the noise generation system. The
is16bit
parameter allows for flexibility in output precision, and the 32-bit input parameters provide sufficient precision for complex noise patterns.
522-524
: Good 16-bit Perlin noise API with multiple dimensionality options.The 16-bit Perlin noise functions provide higher precision output and support for 1D, 2D, and 3D noise generation, which offers flexibility for various visual effects.
525-527
: Appropriate 8-bit Perlin noise functions with performance considerations.The 8-bit functions use 16-bit input parameters (as opposed to 32-bit in the 16-bit variants), which is a good balance between precision and performance for 8-bit output scenarios.
did anyone have a chance to test this? |
If you are wanting others to test, I think it would be helpful if you could add some notes as what/how to test Otherwise let's merge in and see if anyone complains 😜 |
that is what I was trying with the
part in the commit comment :) I mostly tested on 2D FX and those look fine to me. I was hoping someone could run it on a different setup with a different perspective as I may be biased from all the earlier tests. |
I would say the graphs are more accurate way to compare than looking at the effects and they look close enough to my eyes |
I created integer-math based perlin noise functions to replace the 8-bit optimized fastled inoise functions.
They execute about twice as fast and use no look-up tables. The functions are slightly different from the originals but I tried to match them as good as possible. Here is a comparison of the outputs:
saves about 2.7k of flash as a bonus.
These FX use perlin noise, please check if you can spot obvious differences. They are very subtle and I can only spot them in a direct side-by-side comparison.
Summary by CodeRabbit
New Features
Refactor
Chores