Gav... efects to test audio
Anti-aliased setPixelColor() with support for normalized x & y
This commit is contained in:
parent
f9c933bf3b
commit
cdef8472e3
@ -739,7 +739,7 @@ class AudioReactive : public Usermod {
|
|||||||
// usermod exchangeable data
|
// usermod exchangeable data
|
||||||
// we will assign all usermod exportable data here as pointers to original variables or arrays and allocate memory for pointers
|
// we will assign all usermod exportable data here as pointers to original variables or arrays and allocate memory for pointers
|
||||||
um_data = new um_data_t;
|
um_data = new um_data_t;
|
||||||
um_data->u_size = 11;
|
um_data->u_size = 14;
|
||||||
um_data->u_type = new um_types_t[um_data->u_size];
|
um_data->u_type = new um_types_t[um_data->u_size];
|
||||||
um_data->u_data = new void*[um_data->u_size];
|
um_data->u_data = new void*[um_data->u_size];
|
||||||
um_data->u_data[0] = &maxVol;
|
um_data->u_data[0] = &maxVol;
|
||||||
@ -764,17 +764,20 @@ class AudioReactive : public Usermod {
|
|||||||
um_data->u_type[9] = UMT_BYTE;
|
um_data->u_type[9] = UMT_BYTE;
|
||||||
um_data->u_data[10] = &sampleAgc;
|
um_data->u_data[10] = &sampleAgc;
|
||||||
um_data->u_type[10] = UMT_FLOAT;
|
um_data->u_type[10] = UMT_FLOAT;
|
||||||
|
um_data->u_data[11] = &multAgc;
|
||||||
|
um_data->u_type[11] = UMT_FLOAT;
|
||||||
|
um_data->u_data[12] = &sampleReal;
|
||||||
|
um_data->u_type[12] = UMT_FLOAT;
|
||||||
|
um_data->u_data[13] = &sampleGain;
|
||||||
|
um_data->u_type[13] = UMT_FLOAT;
|
||||||
//...
|
//...
|
||||||
// these are values used by effects in soundreactive fork
|
// these are values used by effects in soundreactive fork
|
||||||
//float sampleReal = um_data->;
|
|
||||||
//float multAgc = um_data->;
|
|
||||||
//int16_t rawSampleAgc = um_data->;
|
//int16_t rawSampleAgc = um_data->;
|
||||||
//bool samplePeak = um_data->;
|
//bool samplePeak = um_data->;
|
||||||
//uint8_t squelch = um_data->;
|
//uint8_t squelch = um_data->;
|
||||||
//uint8_t soundSquelch = um_data->;
|
//uint8_t soundSquelch = um_data->;
|
||||||
//uint8_t binNum = um_data->;
|
//uint8_t binNum = um_data->;
|
||||||
//uint16_t *myVals = um_data->;
|
//uint16_t *myVals = um_data->;
|
||||||
//int16_t sample = um_data->;
|
|
||||||
|
|
||||||
// Reset I2S peripheral for good measure
|
// Reset I2S peripheral for good measure
|
||||||
i2s_driver_uninstall(I2S_NUM_0);
|
i2s_driver_uninstall(I2S_NUM_0);
|
||||||
|
301
wled00/FX.cpp
301
wled00/FX.cpp
@ -5977,6 +5977,287 @@ static const char *_data_FX_MODE_DRIFT_ROSE PROGMEM = "2D Drift Rose@Fade,Blur;;
|
|||||||
//************************* audio routines **********************************
|
//************************* audio routines **********************************
|
||||||
|
|
||||||
|
|
||||||
|
// float version of map()
|
||||||
|
static float mapf(float x, float in_min, float in_max, float out_min, float out_max){
|
||||||
|
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gravity struct requited for GRAV* effects
|
||||||
|
typedef struct Gravity {
|
||||||
|
int topLED;
|
||||||
|
int gravityCounter;
|
||||||
|
} gravity;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////
|
||||||
|
// * GRAVCENTER //
|
||||||
|
///////////////////////
|
||||||
|
uint16_t WS2812FX::mode_gravcenter(void) { // Gravcenter. By Andrew Tuline.
|
||||||
|
|
||||||
|
const uint16_t dataSize = sizeof(gravity);
|
||||||
|
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
||||||
|
Gravity* gravcen = reinterpret_cast<Gravity*>(SEGENV.data);
|
||||||
|
|
||||||
|
um_data_t *um_data;
|
||||||
|
float tmpSound = (float)inoise8(23333); // I have no idea what that does
|
||||||
|
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||||
|
//soundAgc = *(uint8_t*)um_data->u_data[9];
|
||||||
|
//sampleAgc = *(float*)um_data->u_data[10];
|
||||||
|
//sampleAvg = *(float*)um_data->u_data[8];
|
||||||
|
tmpSound = *(uint8_t*)um_data->u_data[9] ? *(float*)um_data->u_data[10] : *(float*)um_data->u_data[8];
|
||||||
|
}
|
||||||
|
|
||||||
|
fade_out(240);
|
||||||
|
|
||||||
|
float segmentSampleAvg = tmpSound * (float)SEGMENT.intensity / 255.0f;
|
||||||
|
segmentSampleAvg *= 0.125; // divide by 8, to compensate for later "sensitivty" upscaling
|
||||||
|
|
||||||
|
float mySampleAvg = mapf(segmentSampleAvg*2.0, 0, 32, 0, (float)SEGLEN/2.0); // map to pixels available in current segment
|
||||||
|
uint16_t tempsamp = constrain(mySampleAvg, 0, SEGLEN/2); // Keep the sample from overflowing.
|
||||||
|
uint8_t gravity = 8 - SEGMENT.speed/32;
|
||||||
|
|
||||||
|
for (int i=0; i<tempsamp; i++) {
|
||||||
|
uint8_t index = inoise8(i*segmentSampleAvg+millis(), 5000+i*segmentSampleAvg);
|
||||||
|
setPixelColor(i+SEGLEN/2, color_blend(SEGCOLOR(1), color_from_palette(index, false, PALETTE_SOLID_WRAP, 0), segmentSampleAvg*8));
|
||||||
|
setPixelColor(SEGLEN/2-i-1, color_blend(SEGCOLOR(1), color_from_palette(index, false, PALETTE_SOLID_WRAP, 0), segmentSampleAvg*8));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tempsamp >= gravcen->topLED)
|
||||||
|
gravcen->topLED = tempsamp-1;
|
||||||
|
else if (gravcen->gravityCounter % gravity == 0)
|
||||||
|
gravcen->topLED--;
|
||||||
|
|
||||||
|
if (gravcen->topLED >= 0) {
|
||||||
|
setPixelColor(gravcen->topLED+SEGLEN/2, color_from_palette(millis(), false, PALETTE_SOLID_WRAP, 0));
|
||||||
|
setPixelColor(SEGLEN/2-1-gravcen->topLED, color_from_palette(millis(), false, PALETTE_SOLID_WRAP, 0));
|
||||||
|
}
|
||||||
|
gravcen->gravityCounter = (gravcen->gravityCounter + 1) % gravity;
|
||||||
|
|
||||||
|
return FRAMETIME;
|
||||||
|
} // mode_gravcenter()
|
||||||
|
static const char *_data_FX_MODE_GRAVCENTER PROGMEM = " ♪ Gravcenter@Rate of fall,Sensitivity=128;,!;!";
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////
|
||||||
|
// * GRAVCENTRIC //
|
||||||
|
///////////////////////
|
||||||
|
uint16_t WS2812FX::mode_gravcentric(void) { // Gravcentric. By Andrew Tuline.
|
||||||
|
|
||||||
|
uint16_t dataSize = sizeof(gravity);
|
||||||
|
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
||||||
|
Gravity* gravcen = reinterpret_cast<Gravity*>(SEGENV.data);
|
||||||
|
|
||||||
|
um_data_t *um_data;
|
||||||
|
float tmpSound = (float)inoise8(23333); // I have no idea what that does
|
||||||
|
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||||
|
//soundAgc = *(uint8_t*)um_data->u_data[9];
|
||||||
|
//sampleAgc = *(float*)um_data->u_data[10];
|
||||||
|
//sampleAvg = *(float*)um_data->u_data[8];
|
||||||
|
tmpSound = *(uint8_t*)um_data->u_data[9] ? *(float*)um_data->u_data[10] : *(float*)um_data->u_data[8];
|
||||||
|
}
|
||||||
|
|
||||||
|
fade_out(240);
|
||||||
|
fade_out(240); // twice? really?
|
||||||
|
|
||||||
|
float segmentSampleAvg = tmpSound * (float)SEGMENT.intensity / 255.0;
|
||||||
|
segmentSampleAvg *= 0.125f; // divide by 8, to compensate for later "sensitivty" upscaling
|
||||||
|
|
||||||
|
float mySampleAvg = mapf(segmentSampleAvg*2.0, 0.0f, 32.0f, 0.0f, (float)SEGLEN/2.0); // map to pixels availeable in current segment
|
||||||
|
int tempsamp = constrain(mySampleAvg, 0, SEGLEN/2); // Keep the sample from overflowing.
|
||||||
|
uint8_t gravity = 8 - SEGMENT.speed/32;
|
||||||
|
|
||||||
|
for (int i=0; i<tempsamp; i++) {
|
||||||
|
uint8_t index = segmentSampleAvg*24+millis()/200;
|
||||||
|
setPixelColor(i+SEGLEN/2, color_from_palette(index, false, PALETTE_SOLID_WRAP, 0));
|
||||||
|
setPixelColor(SEGLEN/2-1-i, color_from_palette(index, false, PALETTE_SOLID_WRAP, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tempsamp >= gravcen->topLED)
|
||||||
|
gravcen->topLED = tempsamp-1;
|
||||||
|
else if (gravcen->gravityCounter % gravity == 0)
|
||||||
|
gravcen->topLED--;
|
||||||
|
|
||||||
|
if (gravcen->topLED >= 0) {
|
||||||
|
setPixelColor(gravcen->topLED+SEGLEN/2, CRGB::Gray);
|
||||||
|
setPixelColor(SEGLEN/2-1-gravcen->topLED, CRGB::Gray);
|
||||||
|
}
|
||||||
|
gravcen->gravityCounter = (gravcen->gravityCounter + 1) % gravity;
|
||||||
|
|
||||||
|
return FRAMETIME;
|
||||||
|
} // mode_gravcentric()
|
||||||
|
static const char *_data_FX_MODE_GRAVCENTRIC PROGMEM = " ♪ Gravcentric@Rate of fall,Sensitivity=128;!;!";
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////
|
||||||
|
// * GRAVIMETER //
|
||||||
|
///////////////////////
|
||||||
|
#ifndef SR_DEBUG_AGC
|
||||||
|
uint16_t WS2812FX::mode_gravimeter(void) { // Gravmeter. By Andrew Tuline.
|
||||||
|
|
||||||
|
uint16_t dataSize = sizeof(gravity);
|
||||||
|
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
||||||
|
Gravity* gravcen = reinterpret_cast<Gravity*>(SEGENV.data);
|
||||||
|
|
||||||
|
um_data_t *um_data;
|
||||||
|
float tmpSound = (float)inoise8(23333); // I have no idea what that does
|
||||||
|
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||||
|
//soundAgc = *(uint8_t*)um_data->u_data[9];
|
||||||
|
//sampleAgc = *(float*)um_data->u_data[10];
|
||||||
|
//sampleAvg = *(float*)um_data->u_data[8];
|
||||||
|
tmpSound = *(uint8_t*)um_data->u_data[9] ? *(float*)um_data->u_data[10] : *(float*)um_data->u_data[8];
|
||||||
|
}
|
||||||
|
|
||||||
|
fade_out(240);
|
||||||
|
|
||||||
|
float segmentSampleAvg = tmpSound * (float)SEGMENT.intensity / 255.0;
|
||||||
|
segmentSampleAvg *= 0.25; // divide by 4, to compensate for later "sensitivty" upscaling
|
||||||
|
|
||||||
|
float mySampleAvg = mapf(segmentSampleAvg*2.0, 0, 64, 0, (SEGLEN-1)); // map to pixels availeable in current segment
|
||||||
|
int tempsamp = constrain(mySampleAvg,0,SEGLEN-1); // Keep the sample from overflowing.
|
||||||
|
uint8_t gravity = 8 - SEGMENT.speed/32;
|
||||||
|
|
||||||
|
for (int i=0; i<tempsamp; i++) {
|
||||||
|
uint8_t index = inoise8(i*segmentSampleAvg+millis(), 5000+i*segmentSampleAvg);
|
||||||
|
setPixelColor(i, color_blend(SEGCOLOR(1), color_from_palette(index, false, PALETTE_SOLID_WRAP, 0), segmentSampleAvg*8));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tempsamp >= gravcen->topLED)
|
||||||
|
gravcen->topLED = tempsamp;
|
||||||
|
else if (gravcen->gravityCounter % gravity == 0)
|
||||||
|
gravcen->topLED--;
|
||||||
|
|
||||||
|
if (gravcen->topLED > 0) {
|
||||||
|
setPixelColor(gravcen->topLED, color_from_palette(millis(), false, PALETTE_SOLID_WRAP, 0));
|
||||||
|
}
|
||||||
|
gravcen->gravityCounter = (gravcen->gravityCounter + 1) % gravity;
|
||||||
|
|
||||||
|
return FRAMETIME;
|
||||||
|
} // mode_gravimeter()
|
||||||
|
#else
|
||||||
|
// This an abuse of the gravimeter effect for AGC debugging
|
||||||
|
// instead of sound volume, it uses the AGC gain multiplier as input
|
||||||
|
uint16_t WS2812FX::mode_gravimeter(void) { // Gravmeter. By Andrew Tuline.
|
||||||
|
|
||||||
|
uint16_t dataSize = sizeof(gravity);
|
||||||
|
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
||||||
|
Gravity* gravcen = reinterpret_cast<Gravity*>(SEGENV.data);
|
||||||
|
|
||||||
|
um_data_t *um_data;
|
||||||
|
uint16_t sample = 0;
|
||||||
|
uint8_t soundAgc = 0;
|
||||||
|
float sampleAgc = 0.0f, sampleAgv = 0.0f, multAgc = 0.0f, sampleReal = 0.0f;
|
||||||
|
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||||
|
sample = *(uint16_t*)um_data->u_data[2];
|
||||||
|
soundAgc = *(uint8_t*)um_data->u_data[9];
|
||||||
|
sampleAgc = *(float*)um_data->u_data[10];
|
||||||
|
sampleAvg = *(float*)um_data->u_data[8];
|
||||||
|
multAgc = *(float*)um_data->u_data[11];
|
||||||
|
sampleReal = *(float*)um_data->u_data[12];
|
||||||
|
sampleGain = *(float*)um_data->u_data[13];
|
||||||
|
}
|
||||||
|
|
||||||
|
fade_out(240);
|
||||||
|
|
||||||
|
float tmpSound = multAgc; // AGC gain
|
||||||
|
if (soundAgc == 0) {
|
||||||
|
if ((sampleAvg> 1.0f) && (sampleReal > 0.05f))
|
||||||
|
tmpSound = (float)sample / sampleReal; // current non-AGC gain
|
||||||
|
else
|
||||||
|
tmpSound = ((float)sampleGain/40.0f * (float)inputLevel/128.0f) + 1.0f/16.0f; // non-AGC gain from presets
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmpSound > 2) tmpSound = ((tmpSound -2.0f) / 2) +2; //compress ranges > 2
|
||||||
|
if (tmpSound > 1) tmpSound = ((tmpSound -1.0f) / 2) +1; //compress ranges > 1
|
||||||
|
|
||||||
|
float segmentSampleAvg = 64.0f * tmpSound * (float)SEGMENT.intensity / 128.0f;
|
||||||
|
float mySampleAvg = mapf(segmentSampleAvg, 0.0f, 128.0f, 0, (SEGLEN-1)); // map to pixels availeable in current segment
|
||||||
|
int tempsamp = constrain(mySampleAvg, 0, SEGLEN-1); // Keep the sample from overflowing.
|
||||||
|
|
||||||
|
//tempsamp = SEGLEN - tempsamp; // uncomment to invert direction
|
||||||
|
segmentSampleAvg = fmax(64.0f - fmin(segmentSampleAvg, 63),8); // inverted brightness
|
||||||
|
|
||||||
|
uint8_t gravity = 8 - SEGMENT.speed/32;
|
||||||
|
|
||||||
|
if (sampleAvg > 1) // disable bar "body" if below squelch
|
||||||
|
{
|
||||||
|
for (int i=0; i<tempsamp; i++) {
|
||||||
|
uint8_t index = inoise8(i*segmentSampleAvg+millis(), 5000+i*segmentSampleAvg);
|
||||||
|
setPixelColor(i, color_blend(SEGCOLOR(1), color_from_palette(index, false, PALETTE_SOLID_WRAP, 0), segmentSampleAvg*4.0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tempsamp >= gravcen->topLED)
|
||||||
|
gravcen->topLED = tempsamp;
|
||||||
|
else if (gravcen->gravityCounter % gravity == 0)
|
||||||
|
gravcen->topLED--;
|
||||||
|
|
||||||
|
if (gravcen->topLED > 0) {
|
||||||
|
setPixelColor(gravcen->topLED, color_from_palette(millis(), false, PALETTE_SOLID_WRAP, 0));
|
||||||
|
}
|
||||||
|
gravcen->gravityCounter = (gravcen->gravityCounter + 1) % gravity;
|
||||||
|
|
||||||
|
return FRAMETIME;
|
||||||
|
} // mode_gravimeter()
|
||||||
|
#endif
|
||||||
|
static const char *_data_FX_MODE_GRAVIMETER PROGMEM = " ♪ Gravimeter@Rate of fall,Sensitivity=128;,!;!";
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////
|
||||||
|
// ** Gravfreq //
|
||||||
|
///////////////////////
|
||||||
|
uint16_t WS2812FX::mode_gravfreq(void) { // Gravfreq. By Andrew Tuline.
|
||||||
|
|
||||||
|
uint16_t dataSize = sizeof(gravity);
|
||||||
|
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
||||||
|
Gravity* gravcen = reinterpret_cast<Gravity*>(SEGENV.data);
|
||||||
|
|
||||||
|
um_data_t *um_data;
|
||||||
|
uint8_t soundAgc = 0;
|
||||||
|
float sampleAgc = 0.0f, sampleAvg = 0.0f;
|
||||||
|
double FFT_MajorPeak = 0.0;
|
||||||
|
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||||
|
FFT_MajorPeak = *(double*)um_data->u_data[6];
|
||||||
|
soundAgc = *(uint8_t*)um_data->u_data[9];
|
||||||
|
sampleAgc = *(float*)um_data->u_data[10];
|
||||||
|
sampleAvg = *(float*)um_data->u_data[8];
|
||||||
|
} else {
|
||||||
|
// add support for no audio data
|
||||||
|
sampleAvg = inoise8(12345); // I have no idea what that does
|
||||||
|
}
|
||||||
|
|
||||||
|
fade_out(240);
|
||||||
|
|
||||||
|
float tmpSound = (soundAgc) ? sampleAgc : sampleAvg;
|
||||||
|
float segmentSampleAvg = tmpSound * (float)SEGMENT.intensity / 255.0;
|
||||||
|
segmentSampleAvg *= 0.125; // divide by 8, to compensate for later "sensitivty" upscaling
|
||||||
|
|
||||||
|
float mySampleAvg = mapf(segmentSampleAvg*2.0, 0,32, 0, (float)SEGLEN/2.0); // map to pixels availeable in current segment
|
||||||
|
int tempsamp = constrain(mySampleAvg,0,SEGLEN/2); // Keep the sample from overflowing.
|
||||||
|
uint8_t gravity = 8 - SEGMENT.speed/32;
|
||||||
|
|
||||||
|
for (int i=0; i<tempsamp; i++) {
|
||||||
|
|
||||||
|
uint8_t index = (log10((int)FFT_MajorPeak) - (3.71-1.78)) * 255; //int? shouldn't it be floor() or similar
|
||||||
|
|
||||||
|
setPixelColor(i+SEGLEN/2, color_from_palette(index, false, PALETTE_SOLID_WRAP, 0));
|
||||||
|
setPixelColor(SEGLEN/2-i-1, color_from_palette(index, false, PALETTE_SOLID_WRAP, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tempsamp >= gravcen->topLED)
|
||||||
|
gravcen->topLED = tempsamp-1;
|
||||||
|
else if (gravcen->gravityCounter % gravity == 0)
|
||||||
|
gravcen->topLED--;
|
||||||
|
|
||||||
|
if (gravcen->topLED >= 0) {
|
||||||
|
setPixelColor(gravcen->topLED+SEGLEN/2, CRGB::Gray);
|
||||||
|
setPixelColor(SEGLEN/2-1-gravcen->topLED, CRGB::Gray);
|
||||||
|
}
|
||||||
|
gravcen->gravityCounter = (gravcen->gravityCounter + 1) % gravity;
|
||||||
|
|
||||||
|
return FRAMETIME;
|
||||||
|
} // mode_gravfreq()
|
||||||
|
static const char *_data_FX_MODE_GRAVFREQ PROGMEM = " ♫ Gravfreq@Rate of fall,Sensivity=128;,!;!";
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////
|
/////////////////////////
|
||||||
// * 2D Waverly //
|
// * 2D Waverly //
|
||||||
/////////////////////////
|
/////////////////////////
|
||||||
@ -5996,12 +6277,12 @@ uint16_t WS2812FX::mode_2DWaverly(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data;
|
||||||
uint8_t *soundAgc = nullptr;
|
uint8_t soundAgc = 0;
|
||||||
float *sampleAgc, *sampleAvg;
|
float sampleAgc = 0.0f, sampleAvg = 0.0f;
|
||||||
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||||
soundAgc = (uint8_t*)um_data->u_data[9];
|
soundAgc = *(uint8_t*)um_data->u_data[9];
|
||||||
sampleAgc = (float*)um_data->u_data[10];
|
sampleAgc = *(float*)um_data->u_data[10];
|
||||||
sampleAvg = (float*)um_data->u_data[8];
|
sampleAvg = *(float*)um_data->u_data[8];
|
||||||
}
|
}
|
||||||
|
|
||||||
fadeToBlackBy(leds, SEGMENT.speed);
|
fadeToBlackBy(leds, SEGMENT.speed);
|
||||||
@ -6010,9 +6291,9 @@ uint16_t WS2812FX::mode_2DWaverly(void) {
|
|||||||
for (uint16_t i = 0; i < cols; i++) {
|
for (uint16_t i = 0; i < cols; i++) {
|
||||||
uint16_t thisVal = (1 + SEGMENT.intensity/64) * inoise8(i * 45 , t , t)/2;
|
uint16_t thisVal = (1 + SEGMENT.intensity/64) * inoise8(i * 45 , t , t)/2;
|
||||||
// use audio if available
|
// use audio if available
|
||||||
if (um_data && soundAgc) {
|
if (um_data) {
|
||||||
thisVal /= 32; // reduce intensity of inoise8()
|
thisVal /= 32; // reduce intensity of inoise8()
|
||||||
thisVal *= (*soundAgc) ? *sampleAgc : *sampleAvg;
|
thisVal *= (soundAgc) ? sampleAgc : sampleAvg;
|
||||||
}
|
}
|
||||||
uint16_t thisMax = map(thisVal, 0, 512, 0, rows);
|
uint16_t thisMax = map(thisVal, 0, 512, 0, rows);
|
||||||
|
|
||||||
@ -6178,6 +6459,10 @@ const char *WS2812FX::_modeData[MODE_COUNT] = {
|
|||||||
_data_FX_MODE_GHOST_RIDER,
|
_data_FX_MODE_GHOST_RIDER,
|
||||||
_data_FX_MODE_BLOBS,
|
_data_FX_MODE_BLOBS,
|
||||||
_data_FX_MODE_SCROLL_TEXT,
|
_data_FX_MODE_SCROLL_TEXT,
|
||||||
_data_FX_MODE_DRIFT_ROSE
|
_data_FX_MODE_DRIFT_ROSE,
|
||||||
|
_data_FX_MODE_GRAVCENTER,
|
||||||
|
_data_FX_MODE_GRAVCENTRIC,
|
||||||
|
_data_FX_MODE_GRAVIMETER,
|
||||||
|
_data_FX_MODE_GRAVFREQ
|
||||||
};
|
};
|
||||||
|
|
||||||
|
23
wled00/FX.h
23
wled00/FX.h
@ -267,8 +267,12 @@
|
|||||||
#define FX_MODE_BLOBS 144
|
#define FX_MODE_BLOBS 144
|
||||||
#define FX_MODE_SCROLL_TEXT 145
|
#define FX_MODE_SCROLL_TEXT 145
|
||||||
#define FX_MODE_DRFIT_ROSE 146
|
#define FX_MODE_DRFIT_ROSE 146
|
||||||
|
#define FX_MODE_GRAVCENTER 147
|
||||||
|
#define FX_MODE_GRAVCENTRIC 148
|
||||||
|
#define FX_MODE_GRAVIMETER 149
|
||||||
|
#define FX_MODE_GRAVFREQ 150
|
||||||
|
|
||||||
#define MODE_COUNT 147
|
#define MODE_COUNT 151
|
||||||
|
|
||||||
|
|
||||||
class WS2812FX {
|
class WS2812FX {
|
||||||
@ -667,6 +671,10 @@ class WS2812FX {
|
|||||||
_mode[FX_MODE_BLOBS] = &WS2812FX::mode_2Dfloatingblobs;
|
_mode[FX_MODE_BLOBS] = &WS2812FX::mode_2Dfloatingblobs;
|
||||||
_mode[FX_MODE_SCROLL_TEXT] = &WS2812FX::mode_2Dscrollingtext;
|
_mode[FX_MODE_SCROLL_TEXT] = &WS2812FX::mode_2Dscrollingtext;
|
||||||
_mode[FX_MODE_DRFIT_ROSE] = &WS2812FX::mode_2Ddriftrose;
|
_mode[FX_MODE_DRFIT_ROSE] = &WS2812FX::mode_2Ddriftrose;
|
||||||
|
_mode[FX_MODE_GRAVCENTER] = &WS2812FX::mode_gravcenter;
|
||||||
|
_mode[FX_MODE_GRAVCENTRIC] = &WS2812FX::mode_gravcentric;
|
||||||
|
_mode[FX_MODE_GRAVIMETER] = &WS2812FX::mode_gravimeter;
|
||||||
|
_mode[FX_MODE_GRAVFREQ] = &WS2812FX::mode_gravfreq;
|
||||||
|
|
||||||
_brightness = DEFAULT_BRIGHTNESS;
|
_brightness = DEFAULT_BRIGHTNESS;
|
||||||
currentPalette = CRGBPalette16(CRGB::Black);
|
currentPalette = CRGBPalette16(CRGB::Black);
|
||||||
@ -924,6 +932,7 @@ class WS2812FX {
|
|||||||
void
|
void
|
||||||
setUpMatrix(),
|
setUpMatrix(),
|
||||||
setPixelColorXY(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
|
setPixelColorXY(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
|
||||||
|
setPixelColorXY(float x, float y, byte r, byte g, byte b, byte w = 0, bool aa = false),
|
||||||
blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend),
|
blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend),
|
||||||
blur1d(CRGB* leds, fract8 blur_amount),
|
blur1d(CRGB* leds, fract8 blur_amount),
|
||||||
blur1d(uint16_t i, bool vertical, fract8 blur_amount, CRGB* leds=nullptr), // 1D box blur (with weight)
|
blur1d(uint16_t i, bool vertical, fract8 blur_amount, CRGB* leds=nullptr), // 1D box blur (with weight)
|
||||||
@ -944,6 +953,8 @@ class WS2812FX {
|
|||||||
|
|
||||||
inline void setPixelColorXY(uint16_t x, uint16_t y, uint32_t c) { setPixelColorXY(x, y, byte(c>>16), byte(c>>8), byte(c), byte(c>>24)); }
|
inline void setPixelColorXY(uint16_t x, uint16_t y, uint32_t c) { setPixelColorXY(x, y, byte(c>>16), byte(c>>8), byte(c), byte(c>>24)); }
|
||||||
inline void setPixelColorXY(uint16_t x, uint16_t y, CRGB c) { setPixelColorXY(x, y, c.red, c.green, c.blue); }
|
inline void setPixelColorXY(uint16_t x, uint16_t y, CRGB c) { setPixelColorXY(x, y, c.red, c.green, c.blue); }
|
||||||
|
inline void setPixelColorXY(float x, float y, uint32_t c, bool aa) { setPixelColorXY(x, y, byte(c>>16), byte(c>>8), byte(c), byte(c>>24), aa); }
|
||||||
|
inline void setPixelColorXY(float x, float y, CRGB c, bool aa) { setPixelColorXY(x, y, c.red, c.green, c.blue, aa); }
|
||||||
inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c) { drawLine(x0, y0, x1, y1, CRGB(byte(c>>16), byte(c>>8), byte(c))); }
|
inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c) { drawLine(x0, y0, x1, y1, CRGB(byte(c>>16), byte(c>>8), byte(c))); }
|
||||||
inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint32_t c) { drawCharacter(chr, x, y, CRGB(byte(c>>16), byte(c>>8), byte(c))); }
|
inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint32_t c) { drawCharacter(chr, x, y, CRGB(byte(c>>16), byte(c>>8), byte(c))); }
|
||||||
|
|
||||||
@ -954,6 +965,8 @@ class WS2812FX {
|
|||||||
uint32_t
|
uint32_t
|
||||||
getPixelColorXY(uint16_t, uint16_t);
|
getPixelColorXY(uint16_t, uint16_t);
|
||||||
|
|
||||||
|
// end 2D support
|
||||||
|
|
||||||
// 2D modes
|
// 2D modes
|
||||||
uint16_t
|
uint16_t
|
||||||
mode_2DBlackHole(void),
|
mode_2DBlackHole(void),
|
||||||
@ -986,7 +999,13 @@ class WS2812FX {
|
|||||||
mode_2Dscrollingtext(void),
|
mode_2Dscrollingtext(void),
|
||||||
mode_2Ddriftrose(void);
|
mode_2Ddriftrose(void);
|
||||||
|
|
||||||
// end 2D support
|
// audio modes
|
||||||
|
uint16_t
|
||||||
|
mode_gravcenter(void),
|
||||||
|
mode_gravcentric(void),
|
||||||
|
mode_gravimeter(void),
|
||||||
|
mode_gravfreq(void);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t crgb_to_col(CRGB fastled);
|
uint32_t crgb_to_col(CRGB fastled);
|
||||||
|
@ -184,6 +184,60 @@ void IRAM_ATTR WS2812FX::setPixelColorXY(uint16_t x, uint16_t y, byte r, byte g,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// anti-aliased version of setPixelColorXY()
|
||||||
|
void /*IRAM_ATTR*/ WS2812FX::setPixelColorXY(float x, float y, byte r, byte g, byte b, byte w, bool aa)
|
||||||
|
{
|
||||||
|
if (x<0.0f || x>1.0f || y<0.0f || y>1.0f) return; // not normalized
|
||||||
|
|
||||||
|
const uint16_t cols = SEGMENT.virtualWidth();
|
||||||
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
|
|
||||||
|
if (aa) {
|
||||||
|
uint16_t xL = floorf(x * (cols-1));
|
||||||
|
uint16_t xR = ceilf(x * (cols-1));
|
||||||
|
uint16_t yT = floorf(y * (rows-1));
|
||||||
|
uint16_t yB = ceilf(y * (rows-1));
|
||||||
|
uint32_t cXLYT = getPixelColorXY(xL, yT);
|
||||||
|
uint32_t cXRYT = getPixelColorXY(xR, yT);
|
||||||
|
uint32_t cXLYB = getPixelColorXY(xL, yB);
|
||||||
|
uint32_t cXRYB = getPixelColorXY(xR, yB);
|
||||||
|
|
||||||
|
if (xL!=xR && yT!=yB) {
|
||||||
|
// blend TL pixel
|
||||||
|
cXLYT = color_blend(RGBW32(r,g,b,w), cXLYT, sqrtf((x - floor(x))*(y - floorf(y)))*UINT16_MAX, true);
|
||||||
|
setPixelColorXY(xR, yT, R(cXLYT), G(cXLYT), B(cXLYT), W(cXLYT));
|
||||||
|
// blend TR pixel
|
||||||
|
cXRYT = color_blend(RGBW32(r,g,b,w), cXRYT, sqrtf((ceilf(x) - x)*(y - floorf(y)))*UINT16_MAX, true);
|
||||||
|
setPixelColorXY(xR, yT, R(cXRYT), G(cXRYT), B(cXRYT), W(cXRYT));
|
||||||
|
// blend BL pixel
|
||||||
|
cXLYB = color_blend(RGBW32(r,g,b,w), cXLYB, sqrtf((x - floor(x))*(ceil(y) - y))*UINT16_MAX, true);
|
||||||
|
setPixelColorXY(xL, yB, R(cXLYB), G(cXLYB), B(cXLYB), W(cXLYB));
|
||||||
|
// blend BR pixel
|
||||||
|
cXRYB = color_blend(RGBW32(r,g,b,w), cXRYB, sqrtf((ceilf(x) - x)*(ceil(y) - y))*UINT16_MAX, true);
|
||||||
|
setPixelColorXY(xR, yB, R(cXRYB), G(cXRYB), B(cXRYB), W(cXRYB));
|
||||||
|
} else if (xR!=xL && yT==yB) {
|
||||||
|
// blend L pixel
|
||||||
|
cXLYT = color_blend(RGBW32(r,g,b,w), cXLYT, (x - floor(x))*UINT16_MAX, true);
|
||||||
|
setPixelColorXY(xR, yT, R(cXLYT), G(cXLYT), B(cXLYT), W(cXLYT));
|
||||||
|
// blend R pixel
|
||||||
|
cXRYT = color_blend(RGBW32(r,g,b,w), cXRYT, (ceilf(x) - x)*UINT16_MAX, true);
|
||||||
|
setPixelColorXY(xR, yT, R(cXRYT), G(cXRYT), B(cXRYT), W(cXRYT));
|
||||||
|
} else if (xR==xL && yT!=yB) {
|
||||||
|
// blend T pixel
|
||||||
|
cXLYT = color_blend(RGBW32(r,g,b,w), cXLYT, (y - floorf(y))*UINT16_MAX, true);
|
||||||
|
setPixelColorXY(xR, yT, R(cXLYT), G(cXLYT), B(cXLYT), W(cXLYT));
|
||||||
|
// blend B pixel
|
||||||
|
cXLYB = color_blend(RGBW32(r,g,b,w), cXLYB, (ceil(y) - y)*UINT16_MAX, true);
|
||||||
|
setPixelColorXY(xL, yB, R(cXLYB), G(cXLYB), B(cXLYB), W(cXLYB));
|
||||||
|
} else {
|
||||||
|
// exact match (x & y land on a pixel)
|
||||||
|
setPixelColorXY(xL, yT, r, g, b, w);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setPixelColorXY((uint16_t)roundf(x * (cols-1)), (uint16_t)roundf(y * (rows-1)), r, g, b, w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// returns RGBW values of pixel
|
// returns RGBW values of pixel
|
||||||
uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) {
|
uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) {
|
||||||
if (SEGMENT.getOption(SEG_OPTION_TRANSPOSED)) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
|
if (SEGMENT.getOption(SEG_OPTION_TRANSPOSED)) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
|
||||||
|
Loading…
Reference in New Issue
Block a user