Merge branch 'dev' of https://github.com/blazoncek/WLED into 0_14
- remove conditional audio compile - Random Cycle bugfix - AudioReactive updates - global gamma flags
This commit is contained in:
commit
51d3268eed
@ -24,7 +24,7 @@
|
||||
// #define MIC_LOGGER // MIC sampling & sound input debugging (serial plotter)
|
||||
// #define FFT_SAMPLING_LOG // FFT result debugging
|
||||
// #define SR_DEBUG // generic SR DEBUG messages
|
||||
// #define NO_MIC_LOGGER // exclude MIC_LOGGER from SR_DEBUG
|
||||
|
||||
|
||||
#ifdef SR_DEBUG
|
||||
#define DEBUGSR_PRINT(x) Serial.print(x)
|
||||
@ -85,41 +85,51 @@ const float agcSampleSmooth[AGC_NUM_PRESETS] = { 1/12.f, 1/6.f, 1/16.f}; //
|
||||
static AudioSource *audioSource = nullptr;
|
||||
static volatile bool disableSoundProcessing = false; // if true, sound processing (FFT, filters, AGC) will be suspended. "volatile" as its shared between tasks.
|
||||
|
||||
// audioreactive variables shared with FFT task
|
||||
static float micDataReal = 0.0f; // MicIn data with full 24bit resolution - lowest 8bit after decimal point
|
||||
static float sampleReal = 0.0f; // "sampleRaw" as float, to provide bits that are lost otherwise (before amplification by sampleGain or inputLevel). Needed for AGC.
|
||||
static float multAgc = 1.0f; // sample * multAgc = sampleAgc. Our AGC multiplier
|
||||
static float sampleAvg = 0.0f; // Smoothed Average sample - sampleAvg < 1 means "quiet" (simple noise gate)
|
||||
|
||||
// peak detection
|
||||
static bool samplePeak = false; // Boolean flag for peak - used in effects. Responding routine may reset this flag. Auto-reset after strip.getMinShowDelay()
|
||||
static uint8_t maxVol = 10; // Reasonable value for constant volume for 'peak detector', as it won't always trigger (deprecated)
|
||||
static uint8_t binNum = 8; // Used to select the bin for FFT based beat detection (deprecated)
|
||||
static bool udpSamplePeak = false; // Boolean flag for peak. Set at the same tiem as samplePeak, but reset by transmitAudioData
|
||||
static unsigned long timeOfPeak = 0; // time of last sample peak detection.
|
||||
static void detectSamplePeak(void); // peak detection function (needs scaled FFT reasults in vReal[])
|
||||
static void autoResetPeak(void); // peak auto-reset function
|
||||
|
||||
static int16_t sampleRaw = 0; // Current sample. Must only be updated ONCE!!! (amplified mic value by sampleGain and inputLevel)
|
||||
static int16_t rawSampleAgc = 0; // not smoothed AGC sample
|
||||
static float sampleAvg = 0.0f; // Smoothed Average sampleRaw
|
||||
static float sampleAgc = 0.0f; // Smoothed AGC sample
|
||||
|
||||
////////////////////
|
||||
// Begin FFT Code //
|
||||
////////////////////
|
||||
|
||||
#ifdef UM_AUDIOREACTIVE_USE_NEW_FFT
|
||||
// lib_deps += https://github.com/kosme/arduinoFFT#develop @ 1.9.2
|
||||
#define FFT_SPEED_OVER_PRECISION // enables use of reciprocals (1/x etc), and an a few other speedups
|
||||
#define FFT_SQRT_APPROXIMATION // enables "quake3" style inverse sqrt
|
||||
#define sqrt(x) sqrtf(x) // little hack that reduces FFT time by 50% on ESP32 (as alternative to FFT_SQRT_APPROXIMATION)
|
||||
#else
|
||||
// lib_deps += https://github.com/blazoncek/arduinoFFT.git
|
||||
#endif
|
||||
#include "arduinoFFT.h"
|
||||
|
||||
// FFT Variables
|
||||
// FFT Output variables shared with animations
|
||||
#define NUM_GEQ_CHANNELS 16 // number of frequency channels. Don't change !!
|
||||
static float FFT_MajorPeak = 1.0f; // FFT: strongest (peak) frequency
|
||||
static float FFT_Magnitude = 0.0f; // FFT: volume (magnitude) of peak frequency
|
||||
static uint8_t fftResult[NUM_GEQ_CHANNELS]= {0};// Our calculated freq. channel result table to be used by effects
|
||||
|
||||
// FFT Constants
|
||||
constexpr uint16_t samplesFFT = 512; // Samples in an FFT batch - This value MUST ALWAYS be a power of 2
|
||||
constexpr uint16_t samplesFFT_2 = 256; // meaningfull part of FFT results - only the "lower half" contains useful information.
|
||||
|
||||
static float FFT_MajorPeak = 1.0f;
|
||||
static float FFT_Magnitude = 0.0f;
|
||||
|
||||
// These are the input and output vectors. Input vectors receive computed results from FFT.
|
||||
static float vReal[samplesFFT] = {0.0f};
|
||||
static float vImag[samplesFFT] = {0.0f};
|
||||
static float fftBin[samplesFFT_2] = {0.0f};
|
||||
static float vReal[samplesFFT] = {0.0f}; // FFT sample inputs / freq output - these are our raw result bins
|
||||
static float vImag[samplesFFT] = {0.0f}; // imaginary parts
|
||||
|
||||
// the following are observed values, supported by a bit of "educated guessing"
|
||||
//#define FFT_DOWNSCALE 0.65f // 20kHz - downscaling factor for FFT results - "Flat-Top" window @20Khz, old freq channels
|
||||
|
||||
#define FFT_DOWNSCALE 0.46f // downscaling factor for FFT results - for "Flat-Top" window @22Khz, new freq channels
|
||||
#define LOG_256 5.54517744
|
||||
|
||||
@ -128,13 +138,11 @@ static float windowWeighingFactors[samplesFFT] = {0.0f};
|
||||
#endif
|
||||
|
||||
// Try and normalize fftBin values to a max of 4096, so that 4096/16 = 256.
|
||||
// Oh, and bins 0,1,2 are no good, so we'll zero them out.
|
||||
static float fftCalc[16] = {0.0f};
|
||||
static uint8_t fftResult[16] = {0}; // Our calculated result table, which we feed to the animations.
|
||||
static float fftCalc[NUM_GEQ_CHANNELS] = {0.0f};
|
||||
static float fftAvg[NUM_GEQ_CHANNELS] = {0.0f}; // Calculated frequency channel results, with smoothing (used if dynamics limiter is ON)
|
||||
#ifdef SR_DEBUG
|
||||
static float fftResultMax[16] = {0.0f}; // A table used for testing to determine how our post-processing is working.
|
||||
static float fftResultMax[NUM_GEQ_CHANNELS] = {0.0f}; // A table used for testing to determine how our post-processing is working.
|
||||
#endif
|
||||
static float fftAvg[16] = {0.0f};
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
static unsigned long fftTime = 0;
|
||||
@ -142,7 +150,7 @@ static unsigned long sampleTime = 0;
|
||||
#endif
|
||||
|
||||
// Table of multiplication factors so that we can even out the frequency response.
|
||||
static float fftResultPink[16] = { 1.70f, 1.71f, 1.73f, 1.78f, 1.68f, 1.56f, 1.55f, 1.63f, 1.79f, 1.62f, 1.80f, 2.06f, 2.47f, 3.35f, 6.83f, 9.55f };
|
||||
static float fftResultPink[NUM_GEQ_CHANNELS] = { 1.70f, 1.71f, 1.73f, 1.78f, 1.68f, 1.56f, 1.55f, 1.63f, 1.79f, 1.62f, 1.80f, 2.06f, 2.47f, 3.35f, 6.83f, 9.55f };
|
||||
|
||||
// Create FFT object
|
||||
#ifdef UM_AUDIOREACTIVE_USE_NEW_FFT
|
||||
@ -161,12 +169,12 @@ static float mapf(float x, float in_min, float in_max, float out_min, float out_
|
||||
static float fftAddAvg(int from, int to) {
|
||||
float result = 0.0f;
|
||||
for (int i = from; i <= to; i++) {
|
||||
result += fftBin[i];
|
||||
result += vReal[i];
|
||||
}
|
||||
return result / float(to - from + 1);
|
||||
}
|
||||
|
||||
// FFT main code
|
||||
// FFT main task
|
||||
void FFTcode(void * parameter)
|
||||
{
|
||||
DEBUGSR_PRINT("FFT started on core: "); DEBUGSR_PRINTLN(xPortGetCoreID());
|
||||
@ -237,9 +245,9 @@ void FFTcode(void * parameter)
|
||||
#endif
|
||||
FFT_MajorPeak = constrain(FFT_MajorPeak, 1.0f, 11025.0f); // restrict value to range expected by effects
|
||||
|
||||
for (int i = 0; i < samplesFFT_2; i++) { // Values for bins 0 and 1 are WAY too large. Might as well start at 3.
|
||||
for (int i = 0; i < samplesFFT; i++) {
|
||||
float t = fabsf(vReal[i]); // just to be sure - values in fft bins should be positive any way
|
||||
fftBin[i] = t / 16.0f; // Reduce magnitude. Want end result to be linear and ~4096 max.
|
||||
vReal[i] = t / 16.0f; // Reduce magnitude. Want end result to be scaled linear and ~4096 max.
|
||||
} // for()
|
||||
|
||||
// mapping of FFT result bins to frequency channels
|
||||
@ -292,14 +300,14 @@ void FFTcode(void * parameter)
|
||||
// don't use the last bins from 216 to 255. They are usually contaminated by aliasing (aka noise)
|
||||
#endif
|
||||
} else { // noise gate closed - just decay old values
|
||||
for (int i=0; i < 16; i++) {
|
||||
for (int i=0; i < NUM_GEQ_CHANNELS; i++) {
|
||||
fftCalc[i] *= 0.85f; // decay to zero
|
||||
if (fftCalc[i] < 4.0f) fftCalc[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// post-processing of frequency channels (pink noise adjustment, AGC, smooting, scaling)
|
||||
for (int i=0; i < 16; i++) {
|
||||
for (int i=0; i < NUM_GEQ_CHANNELS; i++) {
|
||||
|
||||
if (sampleAvg > 1) { // noise gate open
|
||||
// Adjustment for frequency curves.
|
||||
@ -378,11 +386,43 @@ void FFTcode(void * parameter)
|
||||
fftTime = (fftTimeInMillis*3 + fftTime*7)/10; // smooth
|
||||
}
|
||||
#endif
|
||||
// run peak detection
|
||||
autoResetPeak();
|
||||
detectSamplePeak();
|
||||
|
||||
} // for(;;)
|
||||
} // FFTcode()
|
||||
} // for(;;)ever
|
||||
} // FFTcode() task end
|
||||
|
||||
|
||||
////////////////////
|
||||
// Peak detection //
|
||||
////////////////////
|
||||
|
||||
// peak detection is called from FFT task when vReal[] contains valid FFT results
|
||||
static void detectSamplePeak(void) {
|
||||
// Poor man's beat detection by seeing if sample > Average + some value.
|
||||
if ((sampleAvg > 1) && (maxVol > 0) && (binNum > 1) && (vReal[binNum] > maxVol) && ((millis() - timeOfPeak) > 100)) {
|
||||
// This goes through ALL of the 255 bins - but ignores stupid settings
|
||||
// Then we got a peak, else we don't. The peak has to time out on its own in order to support UDP sound sync.
|
||||
samplePeak = true;
|
||||
timeOfPeak = millis();
|
||||
udpSamplePeak = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void autoResetPeak(void) {
|
||||
uint16_t MinShowDelay = MAX(50, strip.getMinShowDelay()); // Fixes private class variable compiler error. Unsure if this is the correct way of fixing the root problem. -THATDONFC
|
||||
if (millis() - timeOfPeak > MinShowDelay) { // Auto-reset of samplePeak after a complete frame has passed.
|
||||
samplePeak = false;
|
||||
if (audioSyncEnabled == 0) udpSamplePeak = false; // this is normally reset by transmitAudioData
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////
|
||||
// usermod class //
|
||||
////////////////////
|
||||
|
||||
//class name. Use something descriptive and leave the ": public Usermod" part :)
|
||||
class AudioReactive : public Usermod {
|
||||
|
||||
@ -453,40 +493,36 @@ class AudioReactive : public Usermod {
|
||||
double FFT_MajorPeak; // 08 Bytes
|
||||
};
|
||||
|
||||
WiFiUDP fftUdp;
|
||||
|
||||
// set your config variables to their boot default value (this can also be done in readFromConfig() or a constructor if you prefer)
|
||||
bool enabled = false;
|
||||
bool initDone = false;
|
||||
|
||||
// variables for UDP sound sync
|
||||
WiFiUDP fftUdp; // UDP object for sound sync (from WiFi UDP, not Async UDP!)
|
||||
bool udpSyncConnected = false;// UDP connection status -> true if connected to multicast group
|
||||
unsigned long lastTime = 0; // last time of running UDP Microphone Sync
|
||||
const uint16_t delayMs = 10; // I don't want to sample too often and overload WLED
|
||||
uint16_t audioSyncPort= 11988;// default port for UDP sound sync
|
||||
|
||||
// used for AGC
|
||||
int last_soundAgc = -1; // used to detect AGC mode change (for resetting AGC internal error buffers)
|
||||
double control_integrated = 0.0; // persistent across calls to agcAvg(); "integrator control" = accumulated error
|
||||
|
||||
// variables used by getSample() and agcAvg()
|
||||
int16_t micIn = 0; // Current sample starts with negative values and large values, which is why it's 16 bit signed
|
||||
double sampleMax = 0.0; // Max sample over a few seconds. Needed for AGC controler.
|
||||
float micLev = 0.0f; // Used to convert returned value to have '0' as minimum. A leveller
|
||||
float expAdjF = 0.0f; // Used for exponential filter.
|
||||
float sampleReal = 0.0f; // "sampleRaw" as float, to provide bits that are lost otherwise (before amplification by sampleGain or inputLevel). Needed for AGC.
|
||||
int16_t sampleRaw = 0; // Current sample. Must only be updated ONCE!!! (amplified mic value by sampleGain and inputLevel)
|
||||
int16_t rawSampleAgc = 0; // not smoothed AGC sample
|
||||
float sampleAgc = 0.0f; // Smoothed AGC sample
|
||||
|
||||
// variables used in effects
|
||||
uint8_t maxVol = 10; // Reasonable value for constant volume for 'peak detector', as it won't always trigger (deprecated)
|
||||
uint8_t binNum = 8; // Used to select the bin for FFT based beat detection (deprecated)
|
||||
bool samplePeak = 0; // Boolean flag for peak. Responding routine must reset this flag
|
||||
float volumeSmth = 0.0f; // either sampleAvg or sampleAgc depending on soundAgc; smoothed sample
|
||||
int16_t volumeRaw = 0; // either sampleRaw or rawSampleAgc depending on soundAgc
|
||||
float my_magnitude =0.0f; // FFT_Magnitude, scaled by multAgc
|
||||
|
||||
bool udpSamplePeak = 0; // Boolean flag for peak. Set at the same tiem as samplePeak, but reset by transmitAudioData
|
||||
int16_t micIn = 0; // Current sample starts with negative values and large values, which is why it's 16 bit signed
|
||||
double sampleMax = 0.0; // Max sample over a few seconds. Needed for AGC controler.
|
||||
uint32_t timeOfPeak = 0;
|
||||
unsigned long lastTime = 0; // last time of running UDP Microphone Sync
|
||||
float micLev = 0.0f; // Used to convert returned value to have '0' as minimum. A leveller
|
||||
float expAdjF = 0.0f; // Used for exponential filter.
|
||||
|
||||
bool udpSyncConnected = false;
|
||||
uint16_t audioSyncPort = 11988;
|
||||
|
||||
// used for AGC
|
||||
uint8_t lastMode = 0; // last known effect mode
|
||||
int last_soundAgc = -1;
|
||||
double control_integrated = 0.0; // persistent across calls to agcAvg(); "integrator control" = accumulated error
|
||||
unsigned long last_update_time = 0;
|
||||
unsigned long last_kick_time = 0;
|
||||
uint8_t last_user_inputLevel = 0;
|
||||
|
||||
// used to feed "Info" Page
|
||||
unsigned long last_UDPTime = 0; // time of last valid UDP sound sync datapacket
|
||||
float maxSample5sec = 0.0f; // max sample (after AGC) in last 5 seconds
|
||||
@ -503,6 +539,10 @@ class AudioReactive : public Usermod {
|
||||
static const char UDP_SYNC_HEADER_v1[];
|
||||
|
||||
// private methods
|
||||
|
||||
////////////////////
|
||||
// Debug support //
|
||||
////////////////////
|
||||
void logAudio()
|
||||
{
|
||||
#ifdef MIC_LOGGER
|
||||
@ -525,7 +565,7 @@ class AudioReactive : public Usermod {
|
||||
|
||||
#ifdef FFT_SAMPLING_LOG
|
||||
#if 0
|
||||
for(int i=0; i<16; i++) {
|
||||
for(int i=0; i<NUM_GEQ_CHANNELS; i++) {
|
||||
Serial.print(fftResult[i]);
|
||||
Serial.print("\t");
|
||||
}
|
||||
@ -551,11 +591,11 @@ class AudioReactive : public Usermod {
|
||||
|
||||
int maxVal = minimumMaxVal;
|
||||
int minVal = 0;
|
||||
for(int i = 0; i < 16; i++) {
|
||||
for(int i = 0; i < NUM_GEQ_CHANNELS; i++) {
|
||||
if(fftResult[i] > maxVal) maxVal = fftResult[i];
|
||||
if(fftResult[i] < minVal) minVal = fftResult[i];
|
||||
}
|
||||
for(int i = 0; i < 16; i++) {
|
||||
for(int i = 0; i < NUM_GEQ_CHANNELS; i++) {
|
||||
Serial.print(i); Serial.print(":");
|
||||
Serial.printf("%04ld ", map(fftResult[i], 0, (scaleValuesFromCurrentMaxVal ? maxVal : defaultScalingFromHighValue), (mapValuesToPlotterSpace*i*scalingToHighValue)+0, (mapValuesToPlotterSpace*i*scalingToHighValue)+scalingToHighValue-1));
|
||||
}
|
||||
@ -574,6 +614,10 @@ class AudioReactive : public Usermod {
|
||||
} // logAudio()
|
||||
|
||||
|
||||
//////////////////////
|
||||
// Audio Processing //
|
||||
//////////////////////
|
||||
|
||||
/*
|
||||
* A "PI controller" multiplier to automatically adjust sound sensitivity.
|
||||
*
|
||||
@ -668,7 +712,7 @@ class AudioReactive : public Usermod {
|
||||
last_soundAgc = soundAgc;
|
||||
} // agcAvg()
|
||||
|
||||
|
||||
// post-processing and filtering of MIC sample (micDataReal) from FFTcode()
|
||||
void getSample()
|
||||
{
|
||||
float sampleAdj; // Gain adjusted sample value
|
||||
@ -729,24 +773,6 @@ class AudioReactive : public Usermod {
|
||||
if (sampleMax < 0.5f) sampleMax = 0.0f;
|
||||
|
||||
sampleAvg = ((sampleAvg * 15.0f) + sampleAdj) / 16.0f; // Smooth it out over the last 16 samples.
|
||||
|
||||
// Fixes private class variable compiler error. Unsure if this is the correct way of fixing the root problem. -THATDONFC
|
||||
uint16_t MinShowDelay = strip.getMinShowDelay();
|
||||
|
||||
if (millis() - timeOfPeak > MinShowDelay) { // Auto-reset of samplePeak after a complete frame has passed.
|
||||
samplePeak = false;
|
||||
udpSamplePeak = false;
|
||||
}
|
||||
//if (userVar1 == 0) samplePeak = 0;
|
||||
|
||||
// Poor man's beat detection by seeing if sample > Average + some value.
|
||||
if ((maxVol > 0) && (binNum > 1) && (fftBin[binNum] > maxVol) && (millis() > (timeOfPeak + 100))) {
|
||||
// This goes through ALL of the 255 bins - but ignores stupid settings
|
||||
// Then we got a peak, else we don't. The peak has to time out on its own in order to support UDP sound sync.
|
||||
samplePeak = true;
|
||||
timeOfPeak = millis();
|
||||
udpSamplePeak = true;
|
||||
}
|
||||
} // getSample()
|
||||
|
||||
|
||||
@ -781,6 +807,26 @@ class AudioReactive : public Usermod {
|
||||
}
|
||||
|
||||
|
||||
//////////////////////
|
||||
// UDP Sound Sync //
|
||||
//////////////////////
|
||||
|
||||
// try to establish UDP sound sync connection
|
||||
void connectUDPSoundSync(void) {
|
||||
// This function tries to establish a UDP sync connection if needed
|
||||
// necessary as we also want to transmit in "AP Mode", but the standard "connected()" callback only reacts on STA connection
|
||||
static unsigned long last_connection_attempt = 0;
|
||||
|
||||
if ((audioSyncPort <= 0) || ((audioSyncEnabled & 0x03) == 0)) return; // Sound Sync not enabled
|
||||
if (udpSyncConnected) return; // already connected
|
||||
if (!(apActive || interfacesInited)) return; // neither AP nor other connections availeable
|
||||
if (millis() - last_connection_attempt < 15000) return; // only try once in 15 seconds
|
||||
|
||||
// if we arrive here, we need a UDP connection but don't have one
|
||||
last_connection_attempt = millis();
|
||||
connected(); // try to start UDP
|
||||
}
|
||||
|
||||
void transmitAudioData()
|
||||
{
|
||||
if (!udpSyncConnected) return;
|
||||
@ -795,7 +841,7 @@ class AudioReactive : public Usermod {
|
||||
udpSamplePeak = false; // Reset udpSamplePeak after we've transmitted it
|
||||
transmitData.reserved1 = 0;
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
for (int i = 0; i < NUM_GEQ_CHANNELS; i++) {
|
||||
transmitData.fftResult[i] = (uint8_t)constrain(fftResult[i], 0, 254);
|
||||
}
|
||||
|
||||
@ -808,12 +854,10 @@ class AudioReactive : public Usermod {
|
||||
return;
|
||||
} // transmitAudioData()
|
||||
|
||||
|
||||
static bool isValidUdpSyncVersion(const char *header) {
|
||||
return strncmp_P(header, PSTR(UDP_SYNC_HEADER), 6) == 0;
|
||||
}
|
||||
|
||||
|
||||
bool receiveAudioData() // check & process new data. return TRUE in case that new audio data was received.
|
||||
{
|
||||
if (!udpSyncConnected) return false;
|
||||
@ -839,13 +883,7 @@ class AudioReactive : public Usermod {
|
||||
sampleAgc = volumeSmth;
|
||||
multAgc = 1.0f;
|
||||
|
||||
// auto-reset sample peak. Need to do it here, because getSample() is not running
|
||||
uint16_t MinShowDelay = strip.getMinShowDelay();
|
||||
if (millis() - timeOfPeak > MinShowDelay) { // Auto-reset of samplePeak after a complete frame has passed.
|
||||
samplePeak = false;
|
||||
udpSamplePeak = false;
|
||||
}
|
||||
//if (userVar1 == 0) samplePeak = 0;
|
||||
autoResetPeak();
|
||||
// Only change samplePeak IF it's currently false.
|
||||
// If it's true already, then the animation still needs to respond.
|
||||
if (!samplePeak) {
|
||||
@ -855,7 +893,7 @@ class AudioReactive : public Usermod {
|
||||
}
|
||||
|
||||
//These values are only available on the ESP32
|
||||
for (int i = 0; i < 16; i++) fftResult[i] = receivedPacket->fftResult[i];
|
||||
for (int i = 0; i < NUM_GEQ_CHANNELS; i++) fftResult[i] = receivedPacket->fftResult[i];
|
||||
|
||||
my_magnitude = fmaxf(receivedPacket->FFT_Magnitude, 0.0f);
|
||||
FFT_Magnitude = my_magnitude;
|
||||
@ -869,6 +907,10 @@ class AudioReactive : public Usermod {
|
||||
}
|
||||
|
||||
|
||||
//////////////////////
|
||||
// usermod functions//
|
||||
//////////////////////
|
||||
|
||||
public:
|
||||
//Functions called by WLED or other usermods
|
||||
|
||||
@ -961,6 +1003,7 @@ class AudioReactive : public Usermod {
|
||||
disableSoundProcessing = true;
|
||||
}
|
||||
|
||||
if (enabled) connectUDPSoundSync();
|
||||
initDone = true;
|
||||
}
|
||||
|
||||
@ -971,6 +1014,11 @@ class AudioReactive : public Usermod {
|
||||
*/
|
||||
void connected()
|
||||
{
|
||||
if (udpSyncConnected) { // clean-up: if open, close old UDP sync connection
|
||||
udpSyncConnected = false;
|
||||
fftUdp.stop();
|
||||
}
|
||||
|
||||
if (audioSyncPort > 0 && (audioSyncEnabled & 0x03)) {
|
||||
#ifndef ESP8266
|
||||
udpSyncConnected = fftUdp.beginMulticast(IPAddress(239, 0, 0, 1), audioSyncPort);
|
||||
@ -1004,7 +1052,7 @@ class AudioReactive : public Usermod {
|
||||
if (strip.isUpdating() && (millis() - lastUMRun < 2)) return; // be nice, but not too nice
|
||||
|
||||
// suspend local sound processing when "real time mode" is active (E131, UDP, ADALIGHT, ARTNET)
|
||||
if ( (realtimeOverride == REALTIME_OVERRIDE_NONE) // please odd other orrides here if needed
|
||||
if ( (realtimeOverride == REALTIME_OVERRIDE_NONE) // please add other overrides here if needed
|
||||
&&( (realtimeMode == REALTIME_MODE_GENERIC)
|
||||
||(realtimeMode == REALTIME_MODE_E131)
|
||||
||(realtimeMode == REALTIME_MODE_UDP)
|
||||
@ -1067,9 +1115,13 @@ class AudioReactive : public Usermod {
|
||||
if (soundAgc) my_magnitude *= multAgc;
|
||||
if (volumeSmth < 1 ) my_magnitude = 0.001f; // noise gate closed - mute
|
||||
|
||||
limitSampleDynamics(); // optional - makes volumeSmth very smooth and fluent
|
||||
}
|
||||
limitSampleDynamics();
|
||||
} // if (!disableSoundProcessing)
|
||||
|
||||
autoResetPeak(); // auto-reset sample peak after strip minShowDelay
|
||||
if (!udpSyncConnected) udpSamplePeak = false; // reset UDP samplePeak while UDP is unconnected
|
||||
|
||||
connectUDPSoundSync(); // ensure we have a connection - if needed
|
||||
|
||||
// UDP Microphone Sync - receive mode
|
||||
if ((audioSyncEnabled & 0x02) && udpSyncConnected) {
|
||||
@ -1092,7 +1144,7 @@ class AudioReactive : public Usermod {
|
||||
}
|
||||
#endif
|
||||
|
||||
// peak sample from last 5 seconds
|
||||
// Info Page: keep max sample from last 5 seconds
|
||||
if ((millis() - sampleMaxTimer) > CYCLE_SAMPLEMAX) {
|
||||
sampleMaxTimer = millis();
|
||||
maxSample5sec = (0.15 * maxSample5sec) + 0.85 *((soundAgc) ? sampleAgc : sampleAvg); // reset, and start with some smoothing
|
||||
@ -1100,6 +1152,7 @@ class AudioReactive : public Usermod {
|
||||
} else {
|
||||
if ((sampleAvg >= 1)) maxSample5sec = fmaxf(maxSample5sec, (soundAgc) ? rawSampleAgc : sampleRaw); // follow maximum volume
|
||||
}
|
||||
|
||||
//UDP Microphone Sync - transmit mode
|
||||
if ((audioSyncEnabled & 0x01) && (millis() - lastTime > 20)) {
|
||||
// Only run the transmit code IF we're in Transmit mode
|
||||
@ -1137,8 +1190,9 @@ class AudioReactive : public Usermod {
|
||||
memset(fftCalc, 0, sizeof(fftCalc));
|
||||
memset(fftAvg, 0, sizeof(fftAvg));
|
||||
memset(fftResult, 0, sizeof(fftResult));
|
||||
for(int i=(init?0:1); i<16; i+=2) fftResult[i] = 16; // make a tiny pattern
|
||||
for(int i=(init?0:1); i<NUM_GEQ_CHANNELS; i+=2) fftResult[i] = 16; // make a tiny pattern
|
||||
inputLevel = 128; // resset level slider to default
|
||||
autoResetPeak();
|
||||
|
||||
if (init && FFT_Task) {
|
||||
vTaskSuspend(FFT_Task); // update is about to begin, disable task to prevent crash
|
||||
@ -1186,6 +1240,10 @@ class AudioReactive : public Usermod {
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Settings and Info Page //
|
||||
////////////////////////////
|
||||
|
||||
/*
|
||||
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
|
||||
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
|
||||
|
299
wled00/FX.cpp
299
wled00/FX.cpp
@ -30,6 +30,7 @@
|
||||
|
||||
#define IBN 5100
|
||||
#define PALETTE_SOLID_WRAP (strip.paletteBlend == 1 || strip.paletteBlend == 3)
|
||||
#define indexToVStrip(index, stripNr) ((index) | (int((stripNr)+1)<<16))
|
||||
|
||||
// effect utility functions
|
||||
uint8_t sin_gap(uint16_t in) {
|
||||
@ -1926,10 +1927,7 @@ uint16_t mode_palette()
|
||||
for (int i = 0; i < SEGLEN; i++)
|
||||
{
|
||||
uint8_t colorIndex = (i * 255 / SEGLEN) - counter;
|
||||
|
||||
if (noWrap) colorIndex = map(colorIndex, 0, 255, 0, 240); //cut off blend at palette "end"
|
||||
|
||||
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(colorIndex, false, true, 255));
|
||||
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(colorIndex, false, noWrap, 255));
|
||||
}
|
||||
return FRAMETIME;
|
||||
}
|
||||
@ -1966,59 +1964,59 @@ static const char _data_FX_MODE_PALETTE[] PROGMEM = "Palette@Cycle speed,;1,2,3;
|
||||
// in step 3 above) (Effect Intensity = Sparking).
|
||||
uint16_t mode_fire_2012()
|
||||
{
|
||||
const uint16_t cols = strip.isMatrix ? SEGMENT.virtualWidth() : 1;
|
||||
const uint16_t rows = strip.isMatrix ? SEGMENT.virtualHeight() : SEGMENT.virtualLength();
|
||||
|
||||
uint32_t it = strip.now >> 5; //div 32
|
||||
//uint16_t q = cols>>2; // a quarter of flames
|
||||
|
||||
if (!SEGENV.allocateData(cols*rows)) return mode_static(); //allocation failed
|
||||
|
||||
uint16_t strips = SEGMENT.nrOfVStrips();
|
||||
if (!SEGENV.allocateData(strips * SEGLEN)) return mode_static(); //allocation failed
|
||||
byte* heat = SEGENV.data;
|
||||
|
||||
if (it != SEGENV.step) {
|
||||
SEGENV.step = it;
|
||||
uint8_t ignition = max(3,rows/10); // ignition area: 10% of segment length or minimum 3 pixels
|
||||
uint32_t it = strip.now >> 5; //div 32
|
||||
|
||||
struct virtualStrip {
|
||||
static void runStrip(uint16_t stripNr, byte* heat, uint32_t it) {
|
||||
|
||||
if (it != SEGENV.step)
|
||||
{
|
||||
uint8_t ignition = max(3,SEGLEN/10); // ignition area: 10% of segment length or minimum 3 pixels
|
||||
|
||||
for (int f = 0; f < cols; f++) {
|
||||
// Step 1. Cool down every cell a little
|
||||
for (int i = 0; i < rows; i++) {
|
||||
uint8_t cool = (((20 + SEGMENT.speed/3) * 16) / rows);
|
||||
/*
|
||||
// 2D enhancement: cool sides of the flame a bit more
|
||||
if (cols>5) {
|
||||
if (f < q) cool = qadd8(cool, 2*(uint16_t)((cool * (q-f))/cols)); // cool segment sides a bit more
|
||||
if (f > 3*q) cool = qadd8(cool, 2*(uint16_t)((cool * (cols-f))/cols)); // cool segment sides a bit more
|
||||
for (int i = 0; i < SEGLEN; i++) {
|
||||
uint8_t cool = random8((((20 + SEGMENT.speed/3) * 16) / SEGLEN)+2);
|
||||
uint8_t minTemp = 0;
|
||||
if (i<ignition) {
|
||||
cool /= (ignition-i); // ignition area cools slower
|
||||
minTemp = 4*(ignition-i) + 8; // and should not become black
|
||||
}
|
||||
*/
|
||||
uint8_t temp = qsub8(heat[i+rows*f], random8(0, cool + 2));
|
||||
heat[i+rows*f] = (temp==0 && i<ignition) ? random8(1,16) : temp; // prevent ignition area from becoming black
|
||||
uint8_t temp = qsub8(heat[i], cool);
|
||||
heat[i] = i<ignition && temp<minTemp ? minTemp : temp; // prevent ignition area from becoming black
|
||||
}
|
||||
|
||||
// Step 2. Heat from each cell drifts 'up' and diffuses a little
|
||||
for (int k = rows -1; k > 1; k--) {
|
||||
heat[k+rows*f] = (heat[k+rows*f - 1] + (heat[k+rows*f - 2]<<1) ) / 3; // heat[k-2] multiplied by 2
|
||||
for (int k = SEGLEN -1; k > 1; k--) {
|
||||
heat[k] = (heat[k - 1] + (heat[k - 2]<<1) ) / 3; // heat[k-2] multiplied by 2
|
||||
}
|
||||
|
||||
// Step 3. Randomly ignite new 'sparks' of heat near the bottom
|
||||
if (random8() <= SEGMENT.intensity) {
|
||||
uint8_t y = random8(ignition);
|
||||
heat[y+rows*f] = qadd8(heat[y+rows*f], random8(160,255));
|
||||
}
|
||||
heat[y] = qadd8(heat[y], random8(160,255));
|
||||
}
|
||||
}
|
||||
|
||||
for (int f = 0; f < cols; f++) {
|
||||
// Step 4. Map from heat cells to LED colors
|
||||
for (int j = 0; j < rows; j++) {
|
||||
CRGB color = ColorFromPalette(SEGPALETTE, /*MIN(*/heat[j+rows*f]/*,240)*/, 255, LINEARBLEND);
|
||||
if (strip.isMatrix) SEGMENT.setPixelColorXY(f, rows -j -1, color);
|
||||
else SEGMENT.setPixelColor(j, color);
|
||||
for (int j = 0; j < SEGLEN; j++) {
|
||||
SEGMENT.setPixelColor(indexToVStrip(j, stripNr), ColorFromPalette(SEGPALETTE, MIN(heat[j],240), 255, NOBLEND));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (int stripNr=0; stripNr<strips; stripNr++)
|
||||
virtualStrip::runStrip(stripNr, &heat[stripNr * SEGLEN], it);
|
||||
|
||||
if (it != SEGENV.step)
|
||||
SEGENV.step = it;
|
||||
|
||||
return FRAMETIME;
|
||||
}
|
||||
static const char _data_FX_MODE_FIRE_2012[] PROGMEM = "Fire 2012@Cooling,Spark rate;1,2,3;!;sx=120,ix=64,1d,2d";
|
||||
static const char _data_FX_MODE_FIRE_2012[] PROGMEM = "Fire 2012@Cooling,Spark rate;1,2,3;!;sx=120,ix=64,mp12=1,1d"; //bars
|
||||
|
||||
|
||||
// ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb
|
||||
@ -2849,7 +2847,7 @@ uint16_t mode_bouncing_balls(void) {
|
||||
}
|
||||
|
||||
int pos = roundf(balls[i].height * (SEGLEN - 1));
|
||||
if (SEGLEN<32) SEGMENT.setPixelColor(pos | int((stripNr+1)<<16), color); // encode virtual strip into index
|
||||
if (SEGLEN<32) SEGMENT.setPixelColor(indexToVStrip(pos, stripNr), color); // encode virtual strip into index
|
||||
else SEGMENT.setPixelColor(balls[i].height + (stripNr+1)*10.0f, color);
|
||||
}
|
||||
}
|
||||
@ -2942,49 +2940,48 @@ typedef struct Spark {
|
||||
uint8_t colIndex;
|
||||
} spark;
|
||||
|
||||
#define maxNumPopcorn 21 // max 21 on 16 segment ESP8266
|
||||
/*
|
||||
* POPCORN
|
||||
* modified from https://github.com/kitesurfer1404/WS2812FX/blob/master/src/custom/Popcorn.h
|
||||
*/
|
||||
uint16_t mode_popcorn(void) {
|
||||
const uint16_t cols = strip.isMatrix ? SEGMENT.virtualWidth() : 1;
|
||||
const uint16_t rows = strip.isMatrix ? SEGMENT.virtualHeight() : SEGMENT.virtualLength();
|
||||
|
||||
//allocate segment data
|
||||
uint16_t maxNumPopcorn = 21; // max 21 on 16 segment ESP8266
|
||||
uint16_t strips = SEGMENT.nrOfVStrips();
|
||||
uint16_t dataSize = sizeof(spark) * maxNumPopcorn;
|
||||
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
||||
if (!SEGENV.allocateData(dataSize * strips)) return mode_static(); //allocation failed
|
||||
|
||||
Spark* popcorn = reinterpret_cast<Spark*>(SEGENV.data);
|
||||
|
||||
float gravity = -0.0001 - (SEGMENT.speed/200000.0); // m/s/s
|
||||
gravity *= rows; //SEGLEN
|
||||
|
||||
bool hasCol2 = SEGCOLOR(2);
|
||||
SEGMENT.fill(hasCol2 ? BLACK : SEGCOLOR(1));
|
||||
|
||||
struct virtualStrip {
|
||||
static void runStrip(uint16_t stripNr, Spark* popcorn) {
|
||||
float gravity = -0.0001 - (SEGMENT.speed/200000.0); // m/s/s
|
||||
gravity *= SEGLEN;
|
||||
|
||||
uint8_t numPopcorn = SEGMENT.intensity*maxNumPopcorn/255;
|
||||
if (numPopcorn == 0) numPopcorn = 1;
|
||||
|
||||
for (int i = 0; i < numPopcorn; i++) {
|
||||
for(int i = 0; i < numPopcorn; i++) {
|
||||
if (popcorn[i].pos >= 0.0f) { // if kernel is active, update its position
|
||||
popcorn[i].pos += popcorn[i].vel;
|
||||
popcorn[i].vel += gravity;
|
||||
} else { // if kernel is inactive, randomly pop it
|
||||
if (random8() < 2) { // POP!!!
|
||||
popcorn[i].pos = 0.01f;
|
||||
popcorn[i].posX = random16(cols);
|
||||
|
||||
uint16_t peakHeight = 128 + random8(128); //0-255
|
||||
peakHeight = (peakHeight * (rows -1)) >> 8;
|
||||
peakHeight = (peakHeight * (SEGLEN -1)) >> 8;
|
||||
popcorn[i].vel = sqrt(-2.0 * gravity * peakHeight);
|
||||
popcorn[i].velX = 0;
|
||||
|
||||
if (SEGMENT.palette) {
|
||||
if (SEGMENT.palette)
|
||||
{
|
||||
popcorn[i].colIndex = random8();
|
||||
} else {
|
||||
byte col = random8(0, NUM_COLORS);
|
||||
if (!hasCol2 || !SEGCOLOR(col)) col = 0;
|
||||
if (!SEGCOLOR(2) || !SEGCOLOR(col)) col = 0;
|
||||
popcorn[i].colIndex = col;
|
||||
}
|
||||
}
|
||||
@ -2992,18 +2989,19 @@ uint16_t mode_popcorn(void) {
|
||||
if (popcorn[i].pos >= 0.0f) { // draw now active popcorn (either active before or just popped)
|
||||
uint32_t col = SEGMENT.color_wheel(popcorn[i].colIndex);
|
||||
if (!SEGMENT.palette && popcorn[i].colIndex < NUM_COLORS) col = SEGCOLOR(popcorn[i].colIndex);
|
||||
|
||||
uint16_t ledIndex = popcorn[i].pos;
|
||||
if (ledIndex < rows) {
|
||||
if (strip.isMatrix) SEGMENT.setPixelColorXY(uint16_t(popcorn[i].posX), rows - 1 - ledIndex, col);
|
||||
else SEGMENT.setPixelColor(ledIndex, col);
|
||||
if (ledIndex < SEGLEN) SEGMENT.setPixelColor(indexToVStrip(ledIndex, stripNr), col);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (int stripNr=0; stripNr<strips; stripNr++)
|
||||
virtualStrip::runStrip(stripNr, &popcorn[stripNr * maxNumPopcorn]);
|
||||
|
||||
return FRAMETIME;
|
||||
}
|
||||
static const char _data_FX_MODE_POPCORN[] PROGMEM = "Popcorn@!,!;!,!,!;!;1d,2d";
|
||||
static const char _data_FX_MODE_POPCORN[] PROGMEM = "Popcorn@!,!;!,!,!;!;mp12=1,1d"; //bar
|
||||
|
||||
|
||||
//values close to 100 produce 5Hz flicker, which looks very candle-y
|
||||
@ -3375,91 +3373,84 @@ static const char _data_FX_MODE_EXPLODING_FIREWORKS[] PROGMEM = "Fireworks 1D@Gr
|
||||
*/
|
||||
uint16_t mode_drip(void)
|
||||
{
|
||||
const uint16_t cols = strip.isMatrix ? SEGMENT.virtualWidth() : 1;
|
||||
const uint16_t rows = strip.isMatrix ? SEGMENT.virtualHeight() : SEGMENT.virtualLength();
|
||||
|
||||
//allocate segment data
|
||||
uint8_t numDrops = 4;
|
||||
uint16_t dataSize = sizeof(spark) * numDrops;
|
||||
if (!SEGENV.allocateData(dataSize * cols)) return mode_static(); //allocation failed
|
||||
uint16_t strips = SEGMENT.nrOfVStrips();
|
||||
const int maxNumDrops = 4;
|
||||
uint16_t dataSize = sizeof(spark) * maxNumDrops;
|
||||
if (!SEGENV.allocateData(dataSize * strips)) return mode_static(); //allocation failed
|
||||
Spark* drops = reinterpret_cast<Spark*>(SEGENV.data);
|
||||
|
||||
SEGMENT.fill(SEGCOLOR(1));
|
||||
|
||||
Spark* drops = reinterpret_cast<Spark*>(SEGENV.data);
|
||||
struct virtualStrip {
|
||||
static void runStrip(uint16_t stripNr, Spark* drops) {
|
||||
|
||||
numDrops = 1 + (SEGMENT.intensity >> 6); // 255>>6 = 3
|
||||
uint8_t numDrops = 1 + (SEGMENT.intensity >> 6); // 255>>6 = 3
|
||||
|
||||
float gravity = -0.0005 - (SEGMENT.speed/50000.0);
|
||||
gravity *= rows-1;
|
||||
gravity *= SEGLEN-1;
|
||||
int sourcedrop = 12;
|
||||
|
||||
for (int k=0; k < cols; k++) {
|
||||
for (size_t j=0; j < numDrops; j++) {
|
||||
uint16_t idx = k*numDrops + j;
|
||||
|
||||
if (drops[idx].colIndex == 0) { //init
|
||||
drops[idx].pos = rows-1; // start at end
|
||||
drops[idx].vel = 0; // speed
|
||||
drops[idx].col = sourcedrop; // brightness
|
||||
drops[idx].colIndex = 1; // drop state (0 init, 1 forming, 2 falling, 5 bouncing)
|
||||
for (int j=0;j<numDrops;j++) {
|
||||
if (drops[j].colIndex == 0) { //init
|
||||
drops[j].pos = SEGLEN-1; // start at end
|
||||
drops[j].vel = 0; // speed
|
||||
drops[j].col = sourcedrop; // brightness
|
||||
drops[j].colIndex = 1; // drop state (0 init, 1 forming, 2 falling, 5 bouncing)
|
||||
}
|
||||
|
||||
uint32_t col = color_blend(BLACK, SEGCOLOR(0), sourcedrop);
|
||||
if (strip.isMatrix) SEGMENT.setPixelColorXY(k, 0, col);
|
||||
else SEGMENT.setPixelColor(rows-1, col);// water source
|
||||
SEGMENT.setPixelColor(indexToVStrip(SEGLEN-1, stripNr), color_blend(BLACK,SEGCOLOR(0), sourcedrop));// water source
|
||||
if (drops[j].colIndex==1) {
|
||||
if (drops[j].col>255) drops[j].col=255;
|
||||
SEGMENT.setPixelColor(indexToVStrip(uint16_t(drops[j].pos), stripNr), color_blend(BLACK,SEGCOLOR(0),drops[j].col));
|
||||
|
||||
if (drops[idx].colIndex == 1) {
|
||||
if (drops[idx].col > 255) drops[idx].col = 255;
|
||||
col = color_blend(BLACK,SEGCOLOR(0),drops[idx].col);
|
||||
if (strip.isMatrix) SEGMENT.setPixelColorXY(k, rows - 1 - uint16_t(drops[idx].pos), col);
|
||||
else SEGMENT.setPixelColor(uint16_t(drops[idx].pos), col);
|
||||
drops[j].col += map(SEGMENT.speed, 0, 255, 1, 6); // swelling
|
||||
|
||||
drops[idx].col += map(SEGMENT.speed, 0, 255, 1, 6); // swelling
|
||||
|
||||
if (random8() < drops[idx].col/10) { // random drop
|
||||
drops[idx].colIndex = 2; //fall
|
||||
drops[idx].col = 255;
|
||||
if (random8() < drops[j].col/10) { // random drop
|
||||
drops[j].colIndex=2; //fall
|
||||
drops[j].col=255;
|
||||
}
|
||||
}
|
||||
if (drops[idx].colIndex > 1) { // falling
|
||||
if (drops[idx].pos > 0) { // fall until end of segment
|
||||
drops[idx].pos += drops[idx].vel;
|
||||
if (drops[idx].pos < 0) drops[idx].pos = 0;
|
||||
drops[idx].vel += gravity; // gravity is negative
|
||||
if (drops[j].colIndex > 1) { // falling
|
||||
if (drops[j].pos > 0) { // fall until end of segment
|
||||
drops[j].pos += drops[j].vel;
|
||||
if (drops[j].pos < 0) drops[j].pos = 0;
|
||||
drops[j].vel += gravity; // gravity is negative
|
||||
|
||||
for (int i = 1; i < 7 - drops[idx].colIndex; i++) { // some minor math so we don't expand bouncing droplets
|
||||
uint16_t pos = constrain(uint16_t(drops[idx].pos) +i, 0, rows-1); //this is BAD, returns a pos >= SEGLEN occasionally
|
||||
col = color_blend(BLACK, SEGCOLOR(0), drops[idx].col/i);
|
||||
if (strip.isMatrix) SEGMENT.setPixelColorXY(k, rows - 1 - pos, col);
|
||||
else SEGMENT.setPixelColor(pos, col); //spread pixel with fade while falling
|
||||
for (int i=1;i<7-drops[j].colIndex;i++) { // some minor math so we don't expand bouncing droplets
|
||||
uint16_t pos = constrain(uint16_t(drops[j].pos) +i, 0, SEGLEN-1); //this is BAD, returns a pos >= SEGLEN occasionally
|
||||
SEGMENT.setPixelColor(indexToVStrip(pos, stripNr), color_blend(BLACK,SEGCOLOR(0),drops[j].col/i)); //spread pixel with fade while falling
|
||||
}
|
||||
|
||||
if (drops[idx].colIndex > 2) { // during bounce, some water is on the floor
|
||||
col = color_blend(SEGCOLOR(0), BLACK, drops[idx].col);
|
||||
if (strip.isMatrix) SEGMENT.setPixelColorXY(k, rows - 1, col);
|
||||
else SEGMENT.setPixelColor(0, col);
|
||||
if (drops[j].colIndex > 2) { // during bounce, some water is on the floor
|
||||
SEGMENT.setPixelColor(indexToVStrip(0, stripNr), color_blend(SEGCOLOR(0),BLACK,drops[j].col));
|
||||
}
|
||||
} else { // we hit bottom
|
||||
if (drops[idx].colIndex > 2) { // already hit once, so back to forming
|
||||
drops[idx].colIndex = 0;
|
||||
drops[idx].col = sourcedrop;
|
||||
if (drops[j].colIndex > 2) { // already hit once, so back to forming
|
||||
drops[j].colIndex = 0;
|
||||
drops[j].col = sourcedrop;
|
||||
|
||||
} else {
|
||||
|
||||
if (drops[idx].colIndex == 2) { // init bounce
|
||||
drops[idx].vel = -drops[idx].vel/4;// reverse velocity with damping
|
||||
drops[idx].pos += drops[idx].vel;
|
||||
if (drops[j].colIndex==2) { // init bounce
|
||||
drops[j].vel = -drops[j].vel/4;// reverse velocity with damping
|
||||
drops[j].pos += drops[j].vel;
|
||||
}
|
||||
drops[idx].col = sourcedrop*2;
|
||||
drops[idx].colIndex = 5; // bouncing
|
||||
drops[j].col = sourcedrop*2;
|
||||
drops[j].colIndex = 5; // bouncing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (int stripNr=0; stripNr<strips; stripNr++)
|
||||
virtualStrip::runStrip(stripNr, &drops[stripNr*maxNumDrops]);
|
||||
|
||||
return FRAMETIME;
|
||||
}
|
||||
static const char _data_FX_MODE_DRIP[] PROGMEM = "Drip@Gravity,# of drips;!,!;!;1d,2d";
|
||||
static const char _data_FX_MODE_DRIP[] PROGMEM = "Drip@Gravity,# of drips;!,!;!;mp12=1,1d"; //bar
|
||||
|
||||
|
||||
/*
|
||||
@ -3493,7 +3484,7 @@ uint16_t mode_tetrix(void) {
|
||||
if (SEGENV.call == 0) {
|
||||
drop->stack = 0; // reset brick stack size
|
||||
drop->step = 0;
|
||||
//for (int i=0; i<SEGLEN; i++) SEGMENT.setPixelColor(i | int((stripNr+1)<<16), SEGCOLOR(1)); // will fill virtual strip only
|
||||
//for (int i=0; i<SEGLEN; i++) SEGMENT.setPixelColor(indexToVStrip(i, stripNr), SEGCOLOR(1)); // will fill virtual strip only
|
||||
}
|
||||
|
||||
if (drop->step == 0) { // init brick
|
||||
@ -3518,11 +3509,8 @@ uint16_t mode_tetrix(void) {
|
||||
if (drop->step == 2) { // falling
|
||||
if (drop->pos > drop->stack) { // fall until top of stack
|
||||
drop->pos -= drop->speed; // may add gravity as: speed += gravity
|
||||
if (uint16_t(drop->pos) < drop->stack) drop->pos = drop->stack;
|
||||
for (int i=int(drop->pos); i<SEGLEN; i++) {
|
||||
uint32_t col = i<int(drop->pos)+drop->brick ? SEGMENT.color_from_palette(drop->col, false, false, 0) : SEGCOLOR(1);
|
||||
SEGMENT.setPixelColor(i | int((stripNr+1)<<16), col);
|
||||
}
|
||||
if (uint16_t(drop->pos) < drop->aux1) drop->pos = drop->aux1;
|
||||
for (int i=int(drop->pos); i<SEGLEN; i++) SEGMENT.setPixelColor(i | int((stripNr+1)<<16), i<int(drop->pos)+drop->aux0 ? drop->col : SEGCOLOR(1));
|
||||
} else { // we hit bottom
|
||||
drop->step = 0; // proceed with next brick, go back to init
|
||||
drop->stack += drop->brick; // increase the stack size
|
||||
@ -3534,7 +3522,7 @@ uint16_t mode_tetrix(void) {
|
||||
drop->brick = 0; // reset brick size (no more growing)
|
||||
if (drop->step > millis()) {
|
||||
// allow fading of virtual strip
|
||||
for (int i=0; i<SEGLEN; i++) SEGMENT.blendPixelColor(i | int((stripNr+1)<<16), SEGCOLOR(1), 25); // 10% blend with Bg color
|
||||
for (int i=0; i<SEGLEN; i++) SEGMENT.blendPixelColor(i | int((stripNr+1)<<16), SEGCOLOR(1), 25); // 10% blend
|
||||
} else {
|
||||
drop->stack = 0; // reset brick stack size
|
||||
drop->step = 0; // proceed with next brick
|
||||
@ -5931,7 +5919,6 @@ static const char _data_FX_MODE_2DDRIFTROSE[] PROGMEM = "Drift Rose@Fade,Blur;;;
|
||||
#endif // WLED_DISABLE_2D
|
||||
|
||||
|
||||
#ifndef WLED_DISABLE_AUDIO
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/******************** audio enhanced routines ************************/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -6258,7 +6245,7 @@ uint16_t mode_gravcentric(void) { // Gravcentric. By Andrew
|
||||
|
||||
return FRAMETIME;
|
||||
} // mode_gravcentric()
|
||||
static const char _data_FX_MODE_GRAVCENTRIC[] PROGMEM = "Gravcentric@Rate of fall,Sensitivity;!;!;ix=128,mp12=2,ssim=0,1d,vo"; // Circle, Beatsin
|
||||
static const char _data_FX_MODE_GRAVCENTRIC[] PROGMEM = "Gravcentric@Rate of fall,Sensitivity;!;!;ix=128,mp12=3,ssim=0,1d,vo"; // Corner, Beatsin
|
||||
|
||||
|
||||
///////////////////////
|
||||
@ -6394,7 +6381,7 @@ uint16_t mode_midnoise(void) { // Midnoise. By Andrew Tuline.
|
||||
|
||||
return FRAMETIME;
|
||||
} // mode_midnoise()
|
||||
static const char _data_FX_MODE_MIDNOISE[] PROGMEM = "Midnoise@Fade rate,Maximum length;,!;!;ix=128,mp12=2,ssim=0,1d,vo"; // Circle, Beatsin
|
||||
static const char _data_FX_MODE_MIDNOISE[] PROGMEM = "Midnoise@Fade rate,Maximum length;,!;!;ix=128,mp12=1,ssim=0,1d,vo"; // Bar, Beatsin
|
||||
|
||||
|
||||
//////////////////////
|
||||
@ -6519,7 +6506,7 @@ uint16_t mode_plasmoid(void) { // Plasmoid. By Andrew Tuline.
|
||||
}
|
||||
float volumeSmth = *(float*) um_data->u_data[0];
|
||||
|
||||
SEGMENT.fadeToBlackBy(64);
|
||||
SEGMENT.fadeToBlackBy(32);
|
||||
|
||||
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.
|
||||
@ -6615,11 +6602,6 @@ uint16_t mode_puddles(void) { // Puddles. By Andrew Tuline.
|
||||
static const char _data_FX_MODE_PUDDLES[] PROGMEM = "Puddles@Fade rate,Puddle size;!,!;!;mp12=0,ssim=0,1d,vo"; // Pixels, Beatsin
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/******************** audio only routines ************************/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef USERMOD_AUDIOREACTIVE
|
||||
|
||||
//////////////////////
|
||||
// * PIXELS //
|
||||
//////////////////////
|
||||
@ -6671,7 +6653,8 @@ uint16_t mode_blurz(void) { // Blurz. By Andrew Tuline.
|
||||
SEGENV.aux0 = 0;
|
||||
}
|
||||
|
||||
SEGMENT.fade_out(SEGMENT.speed);
|
||||
int fadeoutDelay = (256 - SEGMENT.speed) / 32;
|
||||
if ((fadeoutDelay <= 1 ) || ((SEGENV.call % fadeoutDelay) == 0)) SEGMENT.fade_out(SEGMENT.speed);
|
||||
|
||||
SEGENV.step += FRAMETIME;
|
||||
if (SEGENV.step > SPEED_FORMULA_L) {
|
||||
@ -6739,7 +6722,9 @@ 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)
|
||||
|
||||
SEGMENT.fade_out(SEGMENT.speed);
|
||||
if (SEGENV.call == 0) SEGMENT.fill(BLACK);
|
||||
int fadeoutDelay = (256 - SEGMENT.speed) / 32;
|
||||
if ((fadeoutDelay <= 1 ) || ((SEGENV.call % fadeoutDelay) == 0)) SEGMENT.fade_out(SEGMENT.speed);
|
||||
|
||||
int locn = (log10f((float)FFT_MajorPeak) - 1.78f) * (float)SEGLEN/(MAX_FREQ_LOG10 - 1.78f); // log10 frequency range is from 1.78 to 3.71. Let's scale to SEGLEN.
|
||||
if (locn < 1) locn = 0; // avoid underflow
|
||||
@ -6754,7 +6739,7 @@ uint16_t mode_freqmap(void) { // Map FFT_MajorPeak to SEGLEN.
|
||||
|
||||
return FRAMETIME;
|
||||
} // mode_freqmap()
|
||||
static const char _data_FX_MODE_FREQMAP[] PROGMEM = "Freqmap@Fade rate,Starting color;,!;!;mp12=2,ssim=0,1d,fr"; // Circle, Beatsin
|
||||
static const char _data_FX_MODE_FREQMAP[] PROGMEM = "Freqmap@Fade rate,Starting color;,!;!;mp12=0,ssim=0,1d,fr"; // Pixels, Beatsin
|
||||
|
||||
|
||||
///////////////////////
|
||||
@ -6809,7 +6794,7 @@ uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Plesch
|
||||
|
||||
return FRAMETIME;
|
||||
} // mode_freqmatrix()
|
||||
static const char _data_FX_MODE_FREQMATRIX[] PROGMEM = "Freqmatrix@Time delay,Sound effect,Low bin,High bin,Sensivity;;;mp12=0,ssim=0,1d,fr"; // Pixels, Beatsin
|
||||
static const char _data_FX_MODE_FREQMATRIX[] PROGMEM = "Freqmatrix@Time delay,Sound effect,Low bin,High bin,Sensivity;;;mp12=3,ssim=0,1d,fr"; // Corner, Beatsin
|
||||
|
||||
|
||||
//////////////////////
|
||||
@ -6830,7 +6815,10 @@ uint16_t mode_freqpixels(void) { // Freqpixel. By Andrew Tuline.
|
||||
if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception)
|
||||
|
||||
uint16_t fadeRate = 2*SEGMENT.speed - SEGMENT.speed*SEGMENT.speed/255; // Get to 255 as quick as you can.
|
||||
SEGMENT.fade_out(fadeRate);
|
||||
|
||||
if (SEGENV.call == 0) SEGMENT.fill(BLACK);
|
||||
int fadeoutDelay = (256 - SEGMENT.speed) / 64;
|
||||
if ((fadeoutDelay <= 1 ) || ((SEGENV.call % fadeoutDelay) == 0)) SEGMENT.fade_out(fadeRate);
|
||||
|
||||
for (int i=0; i < SEGMENT.intensity/32+1; i++) {
|
||||
uint16_t locn = random16(0,SEGLEN);
|
||||
@ -6962,7 +6950,7 @@ uint16_t mode_gravfreq(void) { // Gravfreq. By Andrew Tuline.
|
||||
|
||||
return FRAMETIME;
|
||||
} // mode_gravfreq()
|
||||
static const char _data_FX_MODE_GRAVFREQ[] PROGMEM = "Gravfreq@Rate of fall,Sensivity;,!;!;ix=128,mp12=2,ssim=0,1d,fr"; // Circle, Beatsin
|
||||
static const char _data_FX_MODE_GRAVFREQ[] PROGMEM = "Gravfreq@Rate of fall,Sensivity;,!;!;ix=128,mp12=0,ssim=0,1d,fr"; // Pixels, Beatsin
|
||||
|
||||
|
||||
//////////////////////
|
||||
@ -6976,7 +6964,10 @@ uint16_t mode_noisemove(void) { // Noisemove. By: Andrew Tuli
|
||||
}
|
||||
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
|
||||
|
||||
SEGMENT.fade_out(224); // Just in case something doesn't get faded.
|
||||
if (SEGENV.call == 0) SEGMENT.fill(BLACK);
|
||||
//SEGMENT.fade_out(224); // Just in case something doesn't get faded.
|
||||
int fadeoutDelay = (256 - SEGMENT.speed) / 96;
|
||||
if ((fadeoutDelay <= 1 ) || ((SEGENV.call % fadeoutDelay) == 0)) SEGMENT.fadeToBlackBy(4+ SEGMENT.speed/4);
|
||||
|
||||
uint8_t numBins = map(SEGMENT.intensity,0,255,0,16); // Map slider to fftResult bins.
|
||||
for (int i=0; i<numBins; i++) { // How many active bins are we using.
|
||||
@ -7002,13 +6993,16 @@ uint16_t mode_rocktaves(void) { // Rocktaves. Same note from eac
|
||||
float FFT_MajorPeak = *(float*) um_data->u_data[4];
|
||||
float my_magnitude = *(float*) um_data->u_data[5] / 16.0f;
|
||||
|
||||
SEGMENT.fadeToBlackBy(64); // Just in case something doesn't get faded.
|
||||
if (SEGENV.call == 0) SEGMENT.fill(BLACK);
|
||||
SEGMENT.fadeToBlackBy(16); // Just in case something doesn't get faded.
|
||||
|
||||
float frTemp = FFT_MajorPeak;
|
||||
uint8_t octCount = 0; // Octave counter.
|
||||
uint8_t volTemp = 0;
|
||||
|
||||
if (my_magnitude > 32) volTemp = 255; // We need to squelch out the background noise.
|
||||
volTemp = 32.0f + my_magnitude * 1.5f; // brightness = volume (overflows are handled in next lines)
|
||||
if (my_magnitude < 48) volTemp = 0; // We need to squelch out the background noise.
|
||||
if (my_magnitude > 144) volTemp = 255; // everything above this is full brightness
|
||||
|
||||
while ( frTemp > 249 ) {
|
||||
octCount++; // This should go up to 5.
|
||||
@ -7024,7 +7018,7 @@ uint16_t mode_rocktaves(void) { // Rocktaves. Same note from eac
|
||||
|
||||
return FRAMETIME;
|
||||
} // mode_rocktaves()
|
||||
static const char _data_FX_MODE_ROCKTAVES[] PROGMEM = "Rocktaves@;,!;!;mp12=0,ssim=0,1d,fr"; // Pixels, Beatsin
|
||||
static const char _data_FX_MODE_ROCKTAVES[] PROGMEM = "Rocktaves@;,!;!;mp12=1,ssim=0,1d,fr"; // Bar, Beatsin
|
||||
|
||||
|
||||
///////////////////////
|
||||
@ -7108,10 +7102,13 @@ uint16_t mode_2DGEQ(void) { // By Will Tatam. Code reduction by Ewoud Wijma.
|
||||
rippleTime = true;
|
||||
}
|
||||
|
||||
SEGMENT.fadeToBlackBy(SEGMENT.speed);
|
||||
if (SEGENV.call == 0) SEGMENT.fill(BLACK);
|
||||
int fadeoutDelay = (256 - SEGMENT.speed) / 64;
|
||||
if ((fadeoutDelay <= 1 ) || ((SEGENV.call % fadeoutDelay) == 0)) SEGMENT.fadeToBlackBy(SEGMENT.speed);
|
||||
|
||||
for (int x=0; x < cols; x++) {
|
||||
uint8_t band = map(x, 0, cols-1, 0, NUM_BANDS - 1);
|
||||
if (NUM_BANDS < 16) band = map(band, 0, NUM_BANDS - 1, 0, 15); // always use full range. comment out this line to get the previous behaviour.
|
||||
band = constrain(band, 0, 15);
|
||||
uint16_t colorIndex = band * 17;
|
||||
uint16_t barHeight = map(fftResult[band], 0, 255, 0, rows); // do not subtract -1 from rows here
|
||||
@ -7193,14 +7190,7 @@ uint16_t mode_2DFunkyPlank(void) { // Written by ??? Adapted by Wil
|
||||
} // mode_2DFunkyPlank
|
||||
static const char _data_FX_MODE_2DFUNKYPLANK[] PROGMEM = "Funky Plank@Scroll speed,,# of bands;;;ssim=0,2d,fr"; // Beatsin
|
||||
|
||||
#endif // WLED_DISABLE_2D
|
||||
|
||||
|
||||
//end audio only routines
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef WLED_DISABLE_2D
|
||||
/////////////////////////
|
||||
// 2D Akemi //
|
||||
/////////////////////////
|
||||
@ -7305,7 +7295,6 @@ uint16_t mode_2DAkemi(void) {
|
||||
static const char _data_FX_MODE_2DAKEMI[] PROGMEM = "Akemi@Color speed,Dance;Head palette,Arms & Legs,Eyes & Mouth;Face palette;ssim=0,2d,fr"; //beatsin
|
||||
#endif // WLED_DISABLE_2D
|
||||
|
||||
#endif // WLED_DISABLE_AUDIO
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// mode data
|
||||
@ -7487,16 +7476,14 @@ void WS2812FX::setupEffectData() {
|
||||
addEffect(FX_MODE_2DMETABALLS, &mode_2Dmetaballs, _data_FX_MODE_2DMETABALLS);
|
||||
addEffect(FX_MODE_2DPULSER, &mode_2DPulser, _data_FX_MODE_2DPULSER);
|
||||
addEffect(FX_MODE_2DDRIFT, &mode_2DDrift, _data_FX_MODE_2DDRIFT);
|
||||
|
||||
// --- 2D audio effects ---
|
||||
#ifndef WLED_DISABLE_AUDIO
|
||||
addEffect(FX_MODE_2DWAVERLY, &mode_2DWaverly, _data_FX_MODE_2DWAVERLY);
|
||||
addEffect(FX_MODE_2DSWIRL, &mode_2DSwirl, _data_FX_MODE_2DSWIRL);
|
||||
addEffect(FX_MODE_2DAKEMI, &mode_2DAkemi, _data_FX_MODE_2DAKEMI);
|
||||
#endif
|
||||
addEffect(FX_MODE_2DGEQ, &mode_2DGEQ, _data_FX_MODE_2DGEQ);
|
||||
addEffect(FX_MODE_2DFUNKYPLANK, &mode_2DFunkyPlank, _data_FX_MODE_2DFUNKYPLANK);
|
||||
#endif // WLED_DISABLE_2D
|
||||
|
||||
#ifndef WLED_DISABLE_AUDIO
|
||||
// --- 1D audio effects ---
|
||||
addEffect(FX_MODE_PIXELWAVE, &mode_pixelwave, _data_FX_MODE_PIXELWAVE);
|
||||
addEffect(FX_MODE_JUGGLES, &mode_juggles, _data_FX_MODE_JUGGLES);
|
||||
@ -7511,29 +7498,15 @@ void WS2812FX::setupEffectData() {
|
||||
addEffect(FX_MODE_RIPPLEPEAK, &mode_ripplepeak, _data_FX_MODE_RIPPLEPEAK);
|
||||
addEffect(FX_MODE_GRAVCENTER, &mode_gravcenter, _data_FX_MODE_GRAVCENTER);
|
||||
addEffect(FX_MODE_GRAVCENTRIC, &mode_gravcentric, _data_FX_MODE_GRAVCENTRIC);
|
||||
#endif // WLED_DISABLE_AUDIO
|
||||
|
||||
#ifdef USERMOD_AUDIOREACTIVE
|
||||
// --- WLED-SR audio reactive usermod only effects ---
|
||||
#ifdef WLED_DISABLE_AUDIO
|
||||
#error Incompatible options: WLED_DISABLE_AUDIO and USERMOD_AUDIOREACTIVE
|
||||
#endif
|
||||
#ifdef WLED_DISABLE_2D
|
||||
#error AUDIOREACTIVE usermod requires 2D support.
|
||||
#endif
|
||||
addEffect(FX_MODE_PIXELS, &mode_pixels, _data_FX_MODE_PIXELS);
|
||||
addEffect(FX_MODE_FREQWAVE, &mode_freqwave, _data_FX_MODE_FREQWAVE);
|
||||
addEffect(FX_MODE_FREQMATRIX, &mode_freqmatrix, _data_FX_MODE_FREQMATRIX);
|
||||
addEffect(FX_MODE_2DGEQ, &mode_2DGEQ, _data_FX_MODE_2DGEQ);
|
||||
addEffect(FX_MODE_WATERFALL, &mode_waterfall, _data_FX_MODE_WATERFALL);
|
||||
addEffect(FX_MODE_FREQPIXELS, &mode_freqpixels, _data_FX_MODE_FREQPIXELS);
|
||||
addEffect(FX_MODE_NOISEMOVE, &mode_noisemove, _data_FX_MODE_NOISEMOVE);
|
||||
addEffect(FX_MODE_FREQMAP, &mode_freqmap, _data_FX_MODE_FREQMAP);
|
||||
addEffect(FX_MODE_GRAVFREQ, &mode_gravfreq, _data_FX_MODE_GRAVFREQ);
|
||||
addEffect(FX_MODE_DJLIGHT, &mode_DJLight, _data_FX_MODE_DJLIGHT);
|
||||
addEffect(FX_MODE_2DFUNKYPLANK, &mode_2DFunkyPlank, _data_FX_MODE_2DFUNKYPLANK);
|
||||
addEffect(FX_MODE_BLURZ, &mode_blurz, _data_FX_MODE_BLURZ);
|
||||
addEffect(FX_MODE_ROCKTAVES, &mode_rocktaves, _data_FX_MODE_ROCKTAVES);
|
||||
//addEffect(FX_MODE_CUSTOMEFFECT, &mode_customEffect, _data_FX_MODE_CUSTOMEFFECT); //WLEDSR Custom Effects
|
||||
#endif // USERMOD_AUDIOREACTIVE
|
||||
}
|
||||
|
90
wled00/FX.h
90
wled00/FX.h
@ -275,67 +275,39 @@
|
||||
#define FX_MODE_2DMETABALLS 142 // non audio
|
||||
#define FX_MODE_2DPULSER 143 // non audio
|
||||
#define FX_MODE_2DDRIFT 144 // non audio
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_AUDIO
|
||||
#ifndef WLED_DISABLE_2D
|
||||
#define FX_MODE_2DWAVERLY 145 // audio enhanced
|
||||
#define FX_MODE_2DSWIRL 146 // audio enhanced
|
||||
#define FX_MODE_2DAKEMI 147 // audio enhanced
|
||||
// 148 & 149 reserved
|
||||
#endif
|
||||
#define FX_MODE_PIXELWAVE 150 // audio enhanced
|
||||
#define FX_MODE_JUGGLES 151 // audio enhanced
|
||||
#define FX_MODE_MATRIPIX 152 // audio enhanced
|
||||
#define FX_MODE_GRAVIMETER 153 // audio enhanced
|
||||
#define FX_MODE_PLASMOID 154 // audio enhanced
|
||||
#define FX_MODE_PUDDLES 155 // audio enhanced
|
||||
#define FX_MODE_MIDNOISE 156 // audio enhanced
|
||||
#define FX_MODE_NOISEMETER 157 // audio enhanced
|
||||
#define FX_MODE_NOISEFIRE 158 // audio enhanced
|
||||
#define FX_MODE_PUDDLEPEAK 159 // audio enhanced
|
||||
#define FX_MODE_RIPPLEPEAK 160 // audio enhanced
|
||||
#define FX_MODE_GRAVCENTER 161 // audio enhanced
|
||||
#define FX_MODE_GRAVCENTRIC 162 // audio enhanced
|
||||
#endif
|
||||
#define FX_MODE_2DGEQ 148 // audio enhanced
|
||||
#define FX_MODE_2DFUNKYPLANK 149 // audio enhanced
|
||||
#endif //WLED_DISABLE_2D
|
||||
#define FX_MODE_PIXELWAVE 150 // audio enhanced
|
||||
#define FX_MODE_JUGGLES 151 // audio enhanced
|
||||
#define FX_MODE_MATRIPIX 152 // audio enhanced
|
||||
#define FX_MODE_GRAVIMETER 153 // audio enhanced
|
||||
#define FX_MODE_PLASMOID 154 // audio enhanced
|
||||
#define FX_MODE_PUDDLES 155 // audio enhanced
|
||||
#define FX_MODE_MIDNOISE 156 // audio enhanced
|
||||
#define FX_MODE_NOISEMETER 157 // audio enhanced
|
||||
#define FX_MODE_NOISEFIRE 158 // audio enhanced
|
||||
#define FX_MODE_PUDDLEPEAK 159 // audio enhanced
|
||||
#define FX_MODE_RIPPLEPEAK 160 // audio enhanced
|
||||
#define FX_MODE_GRAVCENTER 161 // audio enhanced
|
||||
#define FX_MODE_GRAVCENTRIC 162 // audio enhanced
|
||||
#define FX_MODE_PIXELS 163 // audio enhanced
|
||||
#define FX_MODE_FREQWAVE 164 // audio enhanced
|
||||
#define FX_MODE_FREQMATRIX 165 // audio enhanced
|
||||
#define FX_MODE_WATERFALL 166 // audio enhanced
|
||||
#define FX_MODE_FREQPIXELS 167 // audio enhanced
|
||||
#define FX_MODE_BINMAP 168 // audio enhanced
|
||||
#define FX_MODE_NOISEMOVE 169 // audio enhanced
|
||||
#define FX_MODE_FREQMAP 170 // audio enhanced
|
||||
#define FX_MODE_GRAVFREQ 171 // audio enhanced
|
||||
#define FX_MODE_DJLIGHT 172 // audio enhanced
|
||||
#define FX_MODE_BLURZ 173 // audio enhanced
|
||||
#define FX_MODE_ROCKTAVES 174 // audio enhanced
|
||||
|
||||
#ifndef USERMOD_AUDIOREACTIVE
|
||||
|
||||
#ifndef WLED_DISABLE_AUDIO
|
||||
#define MODE_COUNT 163
|
||||
#else
|
||||
#ifndef WLED_DISABLE_2D
|
||||
#define MODE_COUNT 145
|
||||
#else
|
||||
#define MODE_COUNT 118
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifdef WLED_DISABLE_AUDIO
|
||||
#error Incompatible options: WLED_DISABLE_AUDIO and USERMOD_AUDIOREACTIVE
|
||||
#endif
|
||||
#ifdef WLED_DISABLE_2D
|
||||
#error AUDIOREACTIVE usermod requires 2D support.
|
||||
#endif
|
||||
#define FX_MODE_2DGEQ 148
|
||||
#define FX_MODE_2DFUNKYPLANK 149
|
||||
#define FX_MODE_PIXELS 163
|
||||
#define FX_MODE_FREQWAVE 164
|
||||
#define FX_MODE_FREQMATRIX 165
|
||||
#define FX_MODE_WATERFALL 166
|
||||
#define FX_MODE_FREQPIXELS 167
|
||||
#define FX_MODE_BINMAP 168
|
||||
#define FX_MODE_NOISEMOVE 169
|
||||
#define FX_MODE_FREQMAP 170
|
||||
#define FX_MODE_GRAVFREQ 171
|
||||
#define FX_MODE_DJLIGHT 172
|
||||
#define FX_MODE_BLURZ 173
|
||||
#define FX_MODE_ROCKTAVES 174
|
||||
//#define FX_MODE_CUSTOMEFFECT 175 //WLEDSR Custom Effects
|
||||
|
||||
#define MODE_COUNT 175
|
||||
#endif
|
||||
#define MODE_COUNT 175
|
||||
|
||||
typedef enum mapping1D2D {
|
||||
M12_Pixels = 0,
|
||||
@ -647,8 +619,6 @@ class WS2812FX { // 96 bytes
|
||||
public:
|
||||
|
||||
WS2812FX() :
|
||||
gammaCorrectBri(false),
|
||||
gammaCorrectCol(true),
|
||||
paletteFade(0),
|
||||
paletteBlend(0),
|
||||
milliampsPerLed(55),
|
||||
@ -747,8 +717,6 @@ class WS2812FX { // 96 bytes
|
||||
inline void appendSegment(const Segment &seg = Segment()) { _segments.push_back(seg); }
|
||||
|
||||
bool
|
||||
gammaCorrectBri,
|
||||
gammaCorrectCol,
|
||||
checkSegmentAlignment(void),
|
||||
hasRGBWBus(void),
|
||||
hasCCTBus(void),
|
||||
|
@ -208,6 +208,7 @@ void Segment::setUpLeds() {
|
||||
|
||||
CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
||||
static unsigned long _lastPaletteChange = 0; // perhaps it should be per segment
|
||||
static CRGBPalette16 randomPalette = CRGBPalette16(DEFAULT_COLOR);
|
||||
byte tcp[72];
|
||||
if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0;
|
||||
if (pal > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0;
|
||||
@ -229,30 +230,31 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
||||
targetPalette = PartyColors_p; break;
|
||||
case 1: //periodically replace palette with a random one. Doesn't work with multiple FastLED segments
|
||||
if (millis() - _lastPaletteChange > 5000 /*+ ((uint32_t)(255-intensity))*100*/) {
|
||||
targetPalette = CRGBPalette16(
|
||||
CHSV(random8(), 255, random8(128, 255)),
|
||||
CHSV(random8(), 255, random8(128, 255)),
|
||||
CHSV(random8(), 192, random8(128, 255)),
|
||||
CHSV(random8(), 255, random8(128, 255)));
|
||||
randomPalette = CRGBPalette16(
|
||||
CHSV(random8(), random8(160, 255), random8(128, 255)),
|
||||
CHSV(random8(), random8(160, 255), random8(128, 255)),
|
||||
CHSV(random8(), random8(160, 255), random8(128, 255)),
|
||||
CHSV(random8(), random8(160, 255), random8(128, 255)));
|
||||
_lastPaletteChange = millis();
|
||||
} break;
|
||||
}
|
||||
targetPalette = randomPalette; break;
|
||||
case 2: {//primary color only
|
||||
CRGB prim = strip.gammaCorrectCol ? gamma32(colors[0]) : colors[0];
|
||||
CRGB prim = gamma32(colors[0]);
|
||||
targetPalette = CRGBPalette16(prim); break;}
|
||||
case 3: {//primary + secondary
|
||||
CRGB prim = strip.gammaCorrectCol ? gamma32(colors[0]) : colors[0];
|
||||
CRGB sec = strip.gammaCorrectCol ? gamma32(colors[1]) : colors[1];
|
||||
CRGB prim = gamma32(colors[0]);
|
||||
CRGB sec = gamma32(colors[1]);
|
||||
targetPalette = CRGBPalette16(prim,prim,sec,sec); break;}
|
||||
case 4: {//primary + secondary + tertiary
|
||||
CRGB prim = strip.gammaCorrectCol ? gamma32(colors[0]) : colors[0];
|
||||
CRGB sec = strip.gammaCorrectCol ? gamma32(colors[1]) : colors[1];
|
||||
CRGB ter = strip.gammaCorrectCol ? gamma32(colors[2]) : colors[2];
|
||||
CRGB prim = gamma32(colors[0]);
|
||||
CRGB sec = gamma32(colors[1]);
|
||||
CRGB ter = gamma32(colors[2]);
|
||||
targetPalette = CRGBPalette16(ter,sec,prim); break;}
|
||||
case 5: {//primary + secondary (+tert if not off), more distinct
|
||||
CRGB prim = strip.gammaCorrectCol ? gamma32(colors[0]) : colors[0];
|
||||
CRGB sec = strip.gammaCorrectCol ? gamma32(colors[1]) : colors[1];
|
||||
CRGB prim = gamma32(colors[0]);
|
||||
CRGB sec = gamma32(colors[1]);
|
||||
if (colors[2]) {
|
||||
CRGB ter = strip.gammaCorrectCol ? gamma32(colors[2]) : colors[2];
|
||||
CRGB ter = gamma32(colors[2]);
|
||||
targetPalette = CRGBPalette16(prim,prim,prim,prim,prim,sec,sec,sec,sec,sec,ter,ter,ter,ter,ter,prim);
|
||||
} else {
|
||||
targetPalette = CRGBPalette16(prim,prim,prim,prim,prim,prim,prim,prim,sec,sec,sec,sec,sec,sec,sec,sec);
|
||||
@ -823,7 +825,7 @@ uint32_t Segment::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_
|
||||
// default palette or no RGB support on segment
|
||||
if ((palette == 0 && mcol < NUM_COLORS) || !(_capabilities & 0x01)) {
|
||||
uint32_t color = (transitional && _t) ? _t->_colorT[mcol] : colors[mcol];
|
||||
color = strip.gammaCorrectCol ? gamma32(color) : color;
|
||||
color = gamma32(color);
|
||||
if (pbri == 255) return color;
|
||||
return RGBW32(scale8_video(R(color),pbri), scale8_video(G(color),pbri), scale8_video(B(color),pbri), scale8_video(W(color),pbri));
|
||||
}
|
||||
|
@ -302,10 +302,10 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
|
||||
float light_gc_bri = light["gc"]["bri"];
|
||||
float light_gc_col = light["gc"]["col"]; // 2.8
|
||||
if (light_gc_bri > 1.5) strip.gammaCorrectBri = true;
|
||||
else if (light_gc_bri > 0.5) strip.gammaCorrectBri = false;
|
||||
if (light_gc_col > 1.5) strip.gammaCorrectCol = true;
|
||||
else if (light_gc_col > 0.5) strip.gammaCorrectCol = false;
|
||||
if (light_gc_bri > 1.5) gammaCorrectBri = true;
|
||||
else if (light_gc_bri > 0.5) gammaCorrectBri = false;
|
||||
if (light_gc_col > 1.5) gammaCorrectCol = true;
|
||||
else if (light_gc_col > 0.5) gammaCorrectCol = false;
|
||||
|
||||
JsonObject light_tr = light["tr"];
|
||||
CJSON(fadeTransition, light_tr["mode"]);
|
||||
@ -759,8 +759,8 @@ void serializeConfig() {
|
||||
light[F("aseg")] = autoSegments;
|
||||
|
||||
JsonObject light_gc = light.createNestedObject("gc");
|
||||
light_gc["bri"] = (strip.gammaCorrectBri) ? 2.8 : 1.0;
|
||||
light_gc["col"] = (strip.gammaCorrectCol) ? 2.8 : 1.0;
|
||||
light_gc["bri"] = (gammaCorrectBri) ? 2.8 : 1.0;
|
||||
light_gc["col"] = (gammaCorrectCol) ? 2.8 : 1.0;
|
||||
|
||||
JsonObject light_tr = light.createNestedObject("tr");
|
||||
light_tr["mode"] = fadeTransition;
|
||||
|
@ -358,7 +358,7 @@ uint8_t gamma8(uint8_t b)
|
||||
|
||||
uint32_t gamma32(uint32_t color)
|
||||
{
|
||||
//if (!strip.gammaCorrectCol) return color;
|
||||
if (!gammaCorrectCol) return color;
|
||||
uint8_t w = W(color);
|
||||
uint8_t r = R(color);
|
||||
uint8_t g = G(color);
|
||||
|
@ -611,13 +611,13 @@ function parseInfo(i) {
|
||||
//gId("filter2D").classList.add("hide");
|
||||
hideModes("2D");
|
||||
}
|
||||
if (i.noaudio) {
|
||||
gId("filterVol").classList.add("hide");
|
||||
gId("filterFreq").classList.add("hide");
|
||||
}
|
||||
// if (i.noaudio) {
|
||||
// gId("filterVol").classList.add("hide");
|
||||
// gId("filterFreq").classList.add("hide");
|
||||
// }
|
||||
// if (!i.u || !i.u.AudioReactive) {
|
||||
//gId("filterVol").classList.add("hide"); hideModes(" ♪"); // hide volume reactive effects
|
||||
//gId("filterFreq").classList.add("hide"); hideModes(" ♫"); // hide frequency reactive effects
|
||||
// gId("filterVol").classList.add("hide"); hideModes(" ♪"); // hide volume reactive effects
|
||||
// gId("filterFreq").classList.add("hide"); hideModes(" ♫"); // hide frequency reactive effects
|
||||
// }
|
||||
}
|
||||
|
||||
@ -654,11 +654,11 @@ function populateInfo(i)
|
||||
}
|
||||
var vcn = "Kuuhaku";
|
||||
if (i.ver.startsWith("0.14.")) vcn = "Hoshi";
|
||||
if (i.ver.includes("-bl")) vcn = "Ryujin";
|
||||
if (i.cn) vcn = i.cn;
|
||||
|
||||
cn += `v${i.ver} "${vcn}"<br><br><table>
|
||||
${urows}
|
||||
${urows===""?'':'<tr><td colspan=2><hr style="height:1px;border-width:0;color:gray;background-color:gray"></td></tr>'}
|
||||
${inforow("Build",i.vid)}
|
||||
${inforow("Signal strength",i.wifi.signal +"% ("+ i.wifi.rssi, " dBm)")}
|
||||
${inforow("Uptime",getRuntimeStr(i.uptime))}
|
||||
@ -714,7 +714,7 @@ function populateSegments(s)
|
||||
}
|
||||
let map2D = `<div id="seg${i}map2D" data-map="map2D" class="lbl-s hide">Expand 1D FX<br>
|
||||
<div class="sel-p"><select class="sel-p" id="seg${i}mp12" onchange="setMp12(${i})">
|
||||
<option value="0" ${inst.mp12==0?' selected':''}>Strip</option>
|
||||
<option value="0" ${inst.mp12==0?' selected':''}>Pixels</option>
|
||||
<option value="1" ${inst.mp12==1?' selected':''}>Bar</option>
|
||||
<option value="2" ${inst.mp12==2?' selected':''}>Arc</option>
|
||||
<option value="3" ${inst.mp12==3?' selected':''}>Corner</option>
|
||||
|
@ -506,7 +506,6 @@ function populateInfo(i)
|
||||
}
|
||||
var vcn = "Kuuhaku";
|
||||
if (i.ver.startsWith("0.14.")) vcn = "Hoshi";
|
||||
if (i.ver.includes("-bl")) vcn = "Ryujin";
|
||||
if (i.cn) vcn = i.cn;
|
||||
|
||||
cn += `v${i.ver} "${vcn}"<br><br><table>
|
||||
|
1498
wled00/html_other.h
1498
wled00/html_other.h
File diff suppressed because it is too large
Load Diff
2233
wled00/html_simple.h
2233
wled00/html_simple.h
File diff suppressed because it is too large
Load Diff
3740
wled00/html_ui.h
3740
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -84,8 +84,8 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
|
||||
if ((spc>0 && spc!=seg.spacing) || seg.map1D2D!=map1D2D) seg.fill(BLACK); // clear spacing gaps
|
||||
|
||||
seg.map1D2D = map1D2D & 0x07;
|
||||
seg.soundSim = soundSim & 0x03;
|
||||
seg.map1D2D = constrain(map1D2D, 0, 7);
|
||||
seg.soundSim = constrain(soundSim, 0, 7);
|
||||
|
||||
uint16_t len = 1;
|
||||
if (stop > start) len = stop - start;
|
||||
@ -190,8 +190,8 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
sOpt = extractModeDefaults(fx, "c1"); if (sOpt >= 0) seg.custom1 = sOpt;
|
||||
sOpt = extractModeDefaults(fx, "c2"); if (sOpt >= 0) seg.custom2 = sOpt;
|
||||
sOpt = extractModeDefaults(fx, "c3"); if (sOpt >= 0) seg.custom3 = sOpt;
|
||||
sOpt = extractModeDefaults(fx, "mp12"); if (sOpt >= 0) seg.map1D2D = sOpt & 0x07;
|
||||
sOpt = extractModeDefaults(fx, "ssim"); if (sOpt >= 0) seg.soundSim = sOpt & 0x03;
|
||||
sOpt = extractModeDefaults(fx, "mp12"); if (sOpt >= 0) seg.map1D2D = constrain(sOpt, 0, 7);
|
||||
sOpt = extractModeDefaults(fx, "ssim"); if (sOpt >= 0) seg.soundSim = constrain(sOpt, 0, 7);
|
||||
sOpt = extractModeDefaults(fx, "rev"); if (sOpt >= 0) seg.reverse = (bool)sOpt;
|
||||
sOpt = extractModeDefaults(fx, "mi"); if (sOpt >= 0) seg.mirror = (bool)sOpt; // NOTE: setting this option is a risky business
|
||||
sOpt = extractModeDefaults(fx, "rY"); if (sOpt >= 0) seg.reverse_y = (bool)sOpt;
|
||||
@ -219,7 +219,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
getVal(elem["c2"], &seg.custom2);
|
||||
uint8_t cust3 = seg.custom3;
|
||||
getVal(elem["c3"], &cust3); // we can't pass reference to bifield
|
||||
seg.custom3 = cust3;
|
||||
seg.custom3 = constrain(cust3, 0, 31);
|
||||
|
||||
seg.check1 = elem["o1"] | seg.check1;
|
||||
seg.check2 = elem["o2"] | seg.check2;
|
||||
@ -265,12 +265,9 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
}
|
||||
|
||||
if (set < 2) stop = start + 1;
|
||||
uint32_t c = gamma32(RGBW32(rgbw[0], rgbw[1], rgbw[2], rgbw[3]));
|
||||
for (int i = start; i < stop; i++) {
|
||||
if (strip.gammaCorrectCol) {
|
||||
seg.setPixelColor(i, gamma8(rgbw[0]), gamma8(rgbw[1]), gamma8(rgbw[2]), gamma8(rgbw[3]));
|
||||
} else {
|
||||
seg.setPixelColor(i, rgbw[0], rgbw[1], rgbw[2], rgbw[3]);
|
||||
}
|
||||
seg.setPixelColor(i, c);
|
||||
}
|
||||
if (!set) start++;
|
||||
set = 0;
|
||||
@ -615,10 +612,6 @@ void serializeInfo(JsonObject root)
|
||||
leds[F("wv")] = totalLC & 0x02; // deprecated, true if white slider should be displayed for any segment
|
||||
leds["cct"] = totalLC & 0x04; // deprecated, use info.leds.lc
|
||||
|
||||
#ifdef WLED_DISABLE_AUDIO
|
||||
root[F("noaudio")] = true;
|
||||
#endif
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
JsonArray i2c = root.createNestedArray(F("i2c"));
|
||||
i2c.add(i2c_sda);
|
||||
|
@ -184,8 +184,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
turnOnAtBoot = request->hasArg(F("BO"));
|
||||
t = request->arg(F("BP")).toInt();
|
||||
if (t <= 250) bootPreset = t;
|
||||
strip.gammaCorrectBri = request->hasArg(F("GB"));
|
||||
strip.gammaCorrectCol = request->hasArg(F("GC"));
|
||||
gammaCorrectBri = request->hasArg(F("GB"));
|
||||
gammaCorrectCol = request->hasArg(F("GC"));
|
||||
|
||||
fadeTransition = request->hasArg(F("TF"));
|
||||
t = request->arg(F("TD")).toInt();
|
||||
|
@ -564,7 +564,7 @@ void setRealtimePixel(uint16_t i, byte r, byte g, byte b, byte w)
|
||||
{
|
||||
uint16_t pix = i + arlsOffset;
|
||||
if (pix < strip.getLengthTotal()) {
|
||||
if (!arlsDisableGammaCorrection && strip.gammaCorrectCol) {
|
||||
if (!arlsDisableGammaCorrection && gammaCorrectCol) {
|
||||
r = gamma8(r);
|
||||
g = gamma8(g);
|
||||
b = gamma8(b);
|
||||
|
@ -133,9 +133,6 @@
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_AUDIOREACTIVE
|
||||
#ifdef WLED_DISABLE_AUDIO
|
||||
#error Incompatible options: WLED_DISABLE_AUDIO and USERMOD_AUDIOREACTIVE
|
||||
#endif
|
||||
#include "../usermods/audioreactive/audio_reactive.h"
|
||||
#endif
|
||||
|
||||
@ -260,9 +257,6 @@ void registerUsermods()
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_AUDIOREACTIVE
|
||||
#ifdef WLED_DISABLE_AUDIO
|
||||
#error Incompatible options: WLED_DISABLE_AUDIO and USERMOD_AUDIOREACTIVE
|
||||
#endif
|
||||
usermods.add(new AudioReactive());
|
||||
#endif
|
||||
}
|
||||
|
@ -390,7 +390,6 @@ uint16_t crc16(const unsigned char* data_p, size_t length) {
|
||||
}
|
||||
|
||||
|
||||
#ifndef WLED_DISABLE_AUDIO
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Begin simulateSound (to enable audio enhanced effects to display something)
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -402,7 +401,6 @@ typedef enum UM_SoundSimulations {
|
||||
UMS_14_3
|
||||
} um_soundSimulations_t;
|
||||
|
||||
// this is still work in progress
|
||||
um_data_t* simulateSound(uint8_t simulationId)
|
||||
{
|
||||
static uint8_t samplePeak;
|
||||
@ -507,7 +505,6 @@ um_data_t* simulateSound(uint8_t simulationId)
|
||||
|
||||
return um_data;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void enumerateLedmaps() {
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
// version code in format yymmddb (b = daily build)
|
||||
#define VERSION 2209020
|
||||
#define VERSION 220950
|
||||
|
||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||
//#define WLED_USE_MY_CONFIG
|
||||
@ -288,8 +288,10 @@ WLED_GLOBAL byte bootPreset _INIT(0); // save preset to load
|
||||
//if false, only one segment spanning the total LEDs is created,
|
||||
//but not on LED settings save if there is more than one segment currently
|
||||
WLED_GLOBAL bool autoSegments _INIT(false);
|
||||
WLED_GLOBAL bool correctWB _INIT(false); //CCT color correction of RGB color
|
||||
WLED_GLOBAL bool cctFromRgb _INIT(false); //CCT is calculated from RGB instead of using seg.cct
|
||||
WLED_GLOBAL bool correctWB _INIT(false); // CCT color correction of RGB color
|
||||
WLED_GLOBAL bool cctFromRgb _INIT(false); // CCT is calculated from RGB instead of using seg.cct
|
||||
WLED_GLOBAL bool gammaCorrectCol _INIT(false); // use gamma correction on colors
|
||||
WLED_GLOBAL bool gammaCorrectBri _INIT(false); // use gamma correction on brightness
|
||||
|
||||
WLED_GLOBAL byte col[] _INIT_N(({ 255, 160, 0, 0 })); // current RGB(W) primary color. col[] should be updated if you want to change the color.
|
||||
WLED_GLOBAL byte colSec[] _INIT_N(({ 0, 0, 0, 0 })); // current RGB(W) secondary color
|
||||
|
@ -140,8 +140,8 @@ void loadSettingsFromEEPROM()
|
||||
ntpEnabled = EEPROM.read(327);
|
||||
currentTimezone = EEPROM.read(328);
|
||||
useAMPM = EEPROM.read(329);
|
||||
strip.gammaCorrectBri = EEPROM.read(330);
|
||||
strip.gammaCorrectCol = EEPROM.read(331);
|
||||
gammaCorrectBri = EEPROM.read(330);
|
||||
gammaCorrectCol = EEPROM.read(331);
|
||||
overlayCurrent = EEPROM.read(332);
|
||||
|
||||
alexaEnabled = EEPROM.read(333);
|
||||
|
@ -394,8 +394,8 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('c',SET_F("BO"),turnOnAtBoot);
|
||||
sappend('v',SET_F("BP"),bootPreset);
|
||||
|
||||
sappend('c',SET_F("GB"),strip.gammaCorrectBri);
|
||||
sappend('c',SET_F("GC"),strip.gammaCorrectCol);
|
||||
sappend('c',SET_F("GB"),gammaCorrectBri);
|
||||
sappend('c',SET_F("GC"),gammaCorrectCol);
|
||||
sappend('c',SET_F("TF"),fadeTransition);
|
||||
sappend('v',SET_F("TD"),transitionDelayDefault);
|
||||
sappend('c',SET_F("PF"),strip.paletteFade);
|
||||
|
Loading…
Reference in New Issue
Block a user