-
-
Notifications
You must be signed in to change notification settings - Fork 77
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
WiP -Audio fastpath #40
Changes from 9 commits
fb03a37
40c96c1
f69142d
ac5aed8
0c58c12
e1cadbc
56b6290
91d36fa
7d0e627
4341d36
ca5a54b
f57c39c
63ffc6e
d4fb542
9a4c020
50b3c9d
04b55a5
d8bd451
237286f
4810a85
f050e60
c4664e5
f147d79
d5c33df
6317dcb
9f6278a
6d23eb6
2e6d58f
72f7f9c
175375e
40d1201
ef12aaa
894fdce
fc19340
63e63ad
d872629
e6fb6c4
4197f98
5edd5e6
71153ee
df26430
e2eb3e8
9cb6189
6d78e46
49f2e26
5081cfb
859adb3
d8bc5e2
1daeecc
c13a5d7
36c34b5
52fe8e2
1b8ebfd
63b03a4
c052da9
f877837
dc77c17
0f45b4f
55b0463
53c8f9f
be2da7b
62990cd
cfc1116
35f3f28
4d64efa
aded74d
143f842
b6f1a59
e6334d8
f0dd66e
4dc6a38
06344ae
7e1d15c
309e66b
af6091b
d8a6889
7465be7
82f9be5
337b117
5c79375
b473a40
d1b2759
7dcc8f1
d4a37ec
a9cdd21
6883996
47de28e
2410c22
3127c60
d51a41f
a7d627b
553f234
8aef434
708cd8e
310daa6
582b96f
1c53f14
3cc1d30
a84c361
ecf3317
29644cc
601499b
5fe12ee
a2e2ead
a45306b
c64f74a
9a832ed
9ed5dc7
c22c92e
0fb5edc
3295579
9a3a97e
99def64
9243b90
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -254,7 +254,11 @@ constexpr SRate_t SAMPLE_RATE = 22050; // Base sample rate in Hz - 22Khz | |
//constexpr SRate_t SAMPLE_RATE = 16000; // 16kHz - use if FFTtask takes more than 20ms. Physical sample time -> 32ms | ||
//constexpr SRate_t SAMPLE_RATE = 20480; // Base sample rate in Hz - 20Khz is experimental. Physical sample time -> 25ms | ||
//constexpr SRate_t SAMPLE_RATE = 10240; // Base sample rate in Hz - previous default. Physical sample time -> 50ms | ||
#ifndef WLEDMM_FASTPATH | ||
#define FFT_MIN_CYCLE 21 // minimum time before FFT task is repeated. Use with 22Khz sampling | ||
#else | ||
#define FFT_MIN_CYCLE 15 // reduce min time, to allow faster catch-up when I2S is lagging | ||
#endif | ||
//#define FFT_MIN_CYCLE 30 // Use with 16Khz sampling | ||
//#define FFT_MIN_CYCLE 23 // minimum time before FFT task is repeated. Use with 20Khz sampling | ||
//#define FFT_MIN_CYCLE 46 // minimum time before FFT task is repeated. Use with 10Khz sampling | ||
|
@@ -1129,8 +1133,13 @@ class AudioReactive : public Usermod { | |
{ | ||
float sampleAdj; // Gain adjusted sample value | ||
float tmpSample; // An interim sample variable used for calculatioins. | ||
#ifdef WLEDMM_FASTPATH | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any downside to this change? "Compromise" for speed or just masking changes behind flag until we have done enough testing to know if this should just be right value for all uses? |
||
constexpr float weighting = 0.35f; // slightly reduced filter strength, to reduce audio latency | ||
constexpr float weighting2 = 0.25f; | ||
#else | ||
const float weighting = 0.2f; // Exponential filter weighting. Will be adjustable in a future release. | ||
const float weighting2 = 0.073f; // Exponential filter weighting, for rising signal (a bit more robust against spikes) | ||
#endif | ||
const int AGC_preset = (soundAgc > 0)? (soundAgc-1): 0; // make sure the _compiler_ knows this value will not change while we are inside the function | ||
static bool isFrozen = false; | ||
static bool haveSilence = true; | ||
|
@@ -1732,7 +1741,11 @@ class AudioReactive : public Usermod { | |
|
||
// get AGC sensitivity and sound pressure | ||
static unsigned long lastEstimate = 0; | ||
#ifdef WLEDMM_FASTPATH | ||
if (millis() - lastEstimate > 7) { | ||
#else | ||
if (millis() - lastEstimate > 12) { | ||
#endif | ||
lastEstimate = millis(); | ||
agcSensitivity = getSensitivity(); | ||
if (limiterOn) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2243,7 +2243,7 @@ uint16_t mode_colortwinkle() { | |
} | ||
} | ||
} | ||
return FRAMETIME_FIXED; | ||
return FRAMETIME_FIXED_SLOW; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have all effects that use this constant been updated or just been changing one by one as you test? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just as I tested it. Some effects seem to be meant to be slow, like Halloween eyes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should they not be time-based rather than FPS based? |
||
} | ||
static const char _data_FX_MODE_COLORTWINKLE[] PROGMEM = "Colortwinkles@Fade speed,Spawn speed;;!;;m12=0"; //pixels | ||
|
||
|
@@ -3096,7 +3096,7 @@ uint16_t candle(bool multi) | |
} | ||
} | ||
|
||
return FRAMETIME_FIXED; | ||
return FRAMETIME_FIXED_SLOW; | ||
} | ||
|
||
|
||
|
@@ -6042,6 +6042,7 @@ uint16_t mode_ripplepeak(void) { // * Ripple peak. By Andrew Tuli | |
// printUmData(); | ||
|
||
if (SEGENV.call == 0) { | ||
SEGMENT.setUpLeds(); | ||
SEGENV.aux0 = 255; | ||
SEGMENT.custom1 = *binNum; | ||
SEGMENT.custom2 = *maxVol * 2; | ||
|
@@ -6052,8 +6053,9 @@ uint16_t mode_ripplepeak(void) { // * Ripple peak. By Andrew Tuli | |
*binNum = SEGMENT.custom1; // Select a bin. | ||
*maxVol = SEGMENT.custom2 / 2; // Our volume comparator. | ||
|
||
SEGMENT.fade_out(240); // Lower frame rate means less effective fading than FastLED | ||
SEGMENT.fade_out(240); | ||
//SEGMENT.fade_out(240); // Lower frame rate means less effective fading than FastLED | ||
//SEGMENT.fade_out(240); | ||
SEGMENT.fade_out(224); // should be the same as 240 applied twice | ||
|
||
for (int i = 0; i < SEGMENT.intensity/16; i++) { // Limit the number of ripples. | ||
if (samplePeak) ripples[i].state = 255; | ||
|
@@ -6066,7 +6068,8 @@ uint16_t mode_ripplepeak(void) { // * Ripple peak. By Andrew Tuli | |
ripples[i].pos = random16(SEGLEN); | ||
#ifdef ESP32 | ||
if (FFT_MajorPeak > 1) // log10(0) is "forbidden" (throws exception) | ||
ripples[i].color = (int)(log10f(FFT_MajorPeak)*128); | ||
//ripples[i].color = (int)(log10f(FFT_MajorPeak)*128); // not to self: buggy !! | ||
ripples[i].color = (int)(logf(FFT_MajorPeak)*32.0f); // works up to 10025 hz | ||
else ripples[i].color = 0; | ||
#else | ||
ripples[i].color = random8(); | ||
|
@@ -6476,8 +6479,12 @@ uint16_t mode_midnoise(void) { // Midnoise. By Andrew Tuline. | |
} | ||
float volumeSmth = *(float*) um_data->u_data[0]; | ||
|
||
SEGMENT.fade_out(SEGMENT.speed); | ||
SEGMENT.fade_out(SEGMENT.speed); | ||
if (SEGENV.call == 0) { | ||
SEGMENT.setUpLeds(); | ||
SEGMENT.fill(BLACK); | ||
} | ||
SEGMENT.fadeToBlackBy(SEGMENT.speed/2); | ||
//SEGMENT.fade_out(SEGMENT.speed); | ||
|
||
float tmpSound2 = volumeSmth * (float)SEGMENT.intensity / 256.0; // Too sensitive. | ||
tmpSound2 *= (float)SEGMENT.intensity / 128.0; // Reduce sensitity/length. | ||
|
@@ -6622,8 +6629,13 @@ uint16_t mode_plasmoid(void) { // Plasmoid. By Andrew Tuline. | |
} | ||
float volumeSmth = *(float*) um_data->u_data[0]; | ||
|
||
SEGMENT.fadeToBlackBy(32); | ||
|
||
if (SEGENV.call == 0) { | ||
SEGMENT.setUpLeds(); | ||
SEGMENT.fill(BLACK); | ||
} | ||
//SEGMENT.fadeToBlackBy(32); | ||
SEGMENT.fadeToBlackBy(48); | ||
|
||
plasmoip->thisphase += beatsin8(6,-4,4); // You can change direction and speed individually. | ||
plasmoip->thatphase += beatsin8(7,-4,4); // Two phase values to make a complex pattern. By Andrew Tuline. | ||
|
||
|
@@ -6832,7 +6844,7 @@ uint16_t mode_blurz(void) { // Blurz. By Andrew Tuline. | |
SEGMENT.setPixelColor(segLoc, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette((uint16_t)pixColor, false, PALETTE_SOLID_WRAP, 0),(uint8_t)pixIntensity)); // repaint center pixel after blur | ||
} else SEGMENT.blur(max(SEGMENT.intensity, (uint8_t)1)); // silence - just blur it again | ||
|
||
return FRAMETIME; | ||
return FRAMETIME_FIXED; | ||
} // mode_blurz() | ||
static const char _data_FX_MODE_BLURZ[] PROGMEM = "Blurz ☾@Fade rate,Blur;!,Color mix;!;1f;sx=48,ix=127,m12=0,si=0"; // Pixels, Beatsin | ||
#endif | ||
|
@@ -6921,7 +6933,10 @@ uint16_t mode_freqmap(void) { // Map FFT_MajorPeak to SEGLEN. | |
float my_magnitude = *(float*)um_data->u_data[5] / 4.0f; | ||
if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception) | ||
|
||
if (SEGENV.call == 0) SEGMENT.fill(BLACK); | ||
if (SEGENV.call == 0) { | ||
SEGMENT.setUpLeds(); | ||
SEGMENT.fill(BLACK); | ||
} | ||
int fadeoutDelay = (256 - SEGMENT.speed) / 32; | ||
if ((fadeoutDelay <= 1 ) || ((SEGENV.call % fadeoutDelay) == 0)) SEGMENT.fade_out(SEGMENT.speed); | ||
|
||
|
@@ -6944,7 +6959,7 @@ uint16_t mode_freqmap(void) { // Map FFT_MajorPeak to SEGLEN. | |
SEGMENT.setPixelColor(locn, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(SEGMENT.intensity+pixCol, false, PALETTE_SOLID_WRAP, 0), bright)); | ||
} | ||
|
||
return FRAMETIME; | ||
return FRAMETIME_FIXED; | ||
} // mode_freqmap() | ||
static const char _data_FX_MODE_FREQMAP[] PROGMEM = "Freqmap@Fade rate,Starting color;!,!;!;1f;m12=0,si=0"; // Pixels, Beatsin | ||
|
||
|
@@ -7068,8 +7083,8 @@ uint16_t mode_freqwave(void) { // Freqwave. By Andreas Pleschun | |
SEGMENT.fill(BLACK); | ||
} | ||
|
||
uint8_t secondHand = micros()/(256-SEGMENT.speed)/500 % 16; | ||
if((SEGMENT.speed > 254) || (SEGENV.aux0 != secondHand)) { // WLEDMM allow run run at full speed | ||
uint8_t secondHand = (SEGMENT.speed < 255) ? (micros()/(256-SEGMENT.speed)/500 % 16) : 0; | ||
if((SEGMENT.speed > 254) || (SEGENV.aux0 != secondHand)) { // WLEDMM allow to run at full speed | ||
SEGENV.aux0 = secondHand; | ||
|
||
float sensitivity = 0.5f * mapf(SEGMENT.custom3, 1, 31, 0.5, 10); // reduced resolution slider | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -57,10 +57,21 @@ | |
#endif | ||
|
||
/* Not used in all effects yet */ | ||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLEDMM_FASTPATH) // WLEDMM go faster on ESP32 | ||
#define WLED_FPS 120 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Default value that you can then update in the config? Do we have any way to "force" an update to this value so users get the benefit without needing to read release notes to know to change the value? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one is a very problematic constant ... it seems like just the the default value, however changing this also impacts some "internal clocking" code that may run faster - don't know how exactly that happens. In general, yes this value should be part of the config. It looks like WLED-internal legacy - maybe older WLED versions only had a define, then later it became a user setting but the old constant still stayed in the code... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, this was partly why I asked. I had a feeling it might have been a constant that became not-so-constant when gui option was added, but not 100% of the code changed to use the new runtime value |
||
#define FRAMETIME_FIXED (strip.getFrameTime() < 10 ? 12 : 24) | ||
#define WLED_FPS_SLOW 60 | ||
#define FRAMETIME_FIXED_SLOW (15) // = 66 FPS => 1000/66 | ||
//#define FRAMETIME _frametime | ||
#define FRAMETIME strip.getFrameTime() | ||
#else | ||
#define WLED_FPS 42 | ||
#define FRAMETIME_FIXED (1000/WLED_FPS) | ||
#define WLED_FPS_SLOW 42 | ||
#define FRAMETIME_FIXED_SLOW (1000/WLED_FPS_SLOW) | ||
//#define FRAMETIME _frametime | ||
#define FRAMETIME strip.getFrameTime() | ||
#endif | ||
|
||
/* each segment uses 52 bytes of SRAM memory, so if you're application fails because of | ||
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ | ||
|
@@ -560,7 +571,7 @@ typedef struct Segment { | |
void setPixelColor(float i, uint32_t c, bool aa = true); | ||
void setPixelColor(float i, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0, bool aa = true) { setPixelColor(i, RGBW32(r,g,b,w), aa); } | ||
void setPixelColor(float i, CRGB c, bool aa = true) { setPixelColor(i, RGBW32(c.r,c.g,c.b,0), aa); } | ||
uint32_t getPixelColor(int i); | ||
uint32_t __attribute__((pure)) getPixelColor(int i); // WLEDMM attribute added | ||
// 1D support functions (some implement 2D as well) | ||
void blur(uint8_t); | ||
void fill(uint32_t c); | ||
|
@@ -573,7 +584,7 @@ typedef struct Segment { | |
void addPixelColor(int n, CRGB c) { addPixelColor(n, RGBW32(c.r,c.g,c.b,0)); } // automatically inline | ||
void fadePixelColor(uint16_t n, uint8_t fade); | ||
uint8_t get_random_wheel_index(uint8_t pos); | ||
uint32_t color_from_palette(uint16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255); | ||
uint32_t __attribute__((pure)) color_from_palette(uint_fast16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255); | ||
uint32_t color_wheel(uint8_t pos); | ||
|
||
// 2D matrix | ||
|
@@ -583,14 +594,14 @@ typedef struct Segment { | |
void createjMap(); //WLEDMM jMap | ||
void deletejMap(); //WLEDMM jMap | ||
#ifndef WLED_DISABLE_2D | ||
uint16_t XY(uint16_t x, uint16_t y); // support function to get relative index within segment (for leds[]) | ||
uint16_t __attribute__((pure)) XY(uint16_t x, uint16_t y); // support function to get relative index within segment (for leds[]) // WLEDMM attribute pure | ||
void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color | ||
void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); } // automatically inline | ||
void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); } // automatically inline | ||
void setPixelColorXY(float x, float y, uint32_t c, bool aa = true); | ||
void setPixelColorXY(float x, float y, uint32_t c, bool aa = true, bool fast = true); | ||
void setPixelColorXY(float x, float y, byte r, byte g, byte b, byte w = 0, bool aa = true) { setPixelColorXY(x, y, RGBW32(r,g,b,w), aa); } | ||
void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), aa); } | ||
uint32_t getPixelColorXY(uint16_t x, uint16_t y); | ||
uint32_t __attribute__((pure)) getPixelColorXY(uint16_t x, uint16_t y); // WLEDMM attribute pure | ||
// 2D support functions | ||
void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend); | ||
void blendPixelColorXY(uint16_t x, uint16_t y, CRGB c, uint8_t blend) { blendPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), blend); } | ||
|
@@ -686,11 +697,11 @@ class WS2812FX { // 96 bytes | |
_length(DEFAULT_LED_COUNT), | ||
_brightness(DEFAULT_BRIGHTNESS), | ||
_transitionDur(750), | ||
_targetFps(WLED_FPS), | ||
_frametime(FRAMETIME_FIXED), | ||
_targetFps(WLED_FPS_SLOW), // WLEDMM | ||
_frametime(FRAMETIME_FIXED_SLOW), // WLEDMM | ||
_cumulativeFps(2), | ||
#ifdef ARDUINO_ARCH_ESP32 | ||
_cumulativeFps500(2*500), // WLEDMM more accurate FPS measurement for ESP32 | ||
_cumulativeFps500(2*500), // WLEDMM more accurate FPS measurement for ESP32 | ||
_lastShow500(0), | ||
#endif | ||
_isServicing(false), | ||
|
@@ -809,8 +820,8 @@ class WS2812FX { // 96 bytes | |
|
||
uint32_t | ||
now, | ||
timebase, | ||
getPixelColor(uint16_t); | ||
timebase; | ||
uint32_t __attribute__((pure)) getPixelColor(uint_fast16_t); // WLEDMM attribute pure = does not have side-effects | ||
|
||
inline uint32_t getLastShow(void) { return _lastShow; } | ||
inline uint32_t segColor(uint8_t i) { return _colors_t[i]; } | ||
|
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.
Any downside to this change? "Compromise" for speed or just masking changes behind flag until we have done enough testing to know if this should just be right value for all uses?
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.
yes, the downside is that the FFT task will block the core for longer (2ms in "standard", vs 7ms in "fastpath").
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.
If we are using the second core, is that an issue? What else (if anything) is using that core?