Multiple changes:
- change arduinoFFT to float (custom) - update audioreactive to use float - update effects to use float - info slider (usermod) - hide Peek in 2D - minor bugfixes
This commit is contained in:
parent
569138ac80
commit
0a2e01a616
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
constexpr i2s_port_t I2S_PORT = I2S_NUM_0;
|
constexpr i2s_port_t I2S_PORT = I2S_NUM_0;
|
||||||
constexpr int BLOCK_SIZE = 128;
|
constexpr int BLOCK_SIZE = 128;
|
||||||
constexpr int SAMPLE_RATE = 10240; // Base sample rate in Hz
|
constexpr int SAMPLE_RATE = 20480; // Base sample rate in Hz
|
||||||
|
|
||||||
// #define MIC_LOGGER
|
// #define MIC_LOGGER
|
||||||
// #define MIC_SAMPLING_LOG
|
// #define MIC_SAMPLING_LOG
|
||||||
@ -51,18 +51,18 @@ static uint8_t audioSyncEnabled = 0; // bit field: bit 0 - send, bit 1
|
|||||||
// Note: in C++, "const" implies "static" - no need to explicitly declare everything as "static const"
|
// Note: in C++, "const" implies "static" - no need to explicitly declare everything as "static const"
|
||||||
//
|
//
|
||||||
#define AGC_NUM_PRESETS 3 // AGC presets: normal, vivid, lazy
|
#define AGC_NUM_PRESETS 3 // AGC presets: normal, vivid, lazy
|
||||||
const double agcSampleDecay[AGC_NUM_PRESETS] = { 0.9994f, 0.9985f, 0.9997f}; // decay factor for sampleMax, in case the current sample is below sampleMax
|
const float agcSampleDecay[AGC_NUM_PRESETS] = { 0.9994f, 0.9985f, 0.9997f}; // decay factor for sampleMax, in case the current sample is below sampleMax
|
||||||
const float agcZoneLow[AGC_NUM_PRESETS] = { 32, 28, 36}; // low volume emergency zone
|
const float agcZoneLow[AGC_NUM_PRESETS] = { 32, 28, 36}; // low volume emergency zone
|
||||||
const float agcZoneHigh[AGC_NUM_PRESETS] = { 240, 240, 248}; // high volume emergency zone
|
const float agcZoneHigh[AGC_NUM_PRESETS] = { 240, 240, 248}; // high volume emergency zone
|
||||||
const float agcZoneStop[AGC_NUM_PRESETS] = { 336, 448, 304}; // disable AGC integrator if we get above this level
|
const float agcZoneStop[AGC_NUM_PRESETS] = { 336, 448, 304}; // disable AGC integrator if we get above this level
|
||||||
const float agcTarget0[AGC_NUM_PRESETS] = { 112, 144, 164}; // first AGC setPoint -> between 40% and 65%
|
const float agcTarget0[AGC_NUM_PRESETS] = { 112, 144, 164}; // first AGC setPoint -> between 40% and 65%
|
||||||
const float agcTarget0Up[AGC_NUM_PRESETS] = { 88, 64, 116}; // setpoint switching value (a poor man's bang-bang)
|
const float agcTarget0Up[AGC_NUM_PRESETS] = { 88, 64, 116}; // setpoint switching value (a poor man's bang-bang)
|
||||||
const float agcTarget1[AGC_NUM_PRESETS] = { 220, 224, 216}; // second AGC setPoint -> around 85%
|
const float agcTarget1[AGC_NUM_PRESETS] = { 220, 224, 216}; // second AGC setPoint -> around 85%
|
||||||
const double agcFollowFast[AGC_NUM_PRESETS] = { 1/192.f, 1/128.f, 1/256.f}; // quickly follow setpoint - ~0.15 sec
|
const float agcFollowFast[AGC_NUM_PRESETS] = { 1/192.f, 1/128.f, 1/256.f}; // quickly follow setpoint - ~0.15 sec
|
||||||
const double agcFollowSlow[AGC_NUM_PRESETS] = {1/6144.f,1/4096.f,1/8192.f}; // slowly follow setpoint - ~2-15 secs
|
const float agcFollowSlow[AGC_NUM_PRESETS] = {1/6144.f,1/4096.f,1/8192.f}; // slowly follow setpoint - ~2-15 secs
|
||||||
const double agcControlKp[AGC_NUM_PRESETS] = { 0.6f, 1.5f, 0.65f}; // AGC - PI control, proportional gain parameter
|
const float agcControlKp[AGC_NUM_PRESETS] = { 0.6f, 1.5f, 0.65f}; // AGC - PI control, proportional gain parameter
|
||||||
const double agcControlKi[AGC_NUM_PRESETS] = { 1.7f, 1.85f, 1.2f}; // AGC - PI control, integral gain parameter
|
const float agcControlKi[AGC_NUM_PRESETS] = { 1.7f, 1.85f, 1.2f}; // AGC - PI control, integral gain parameter
|
||||||
const float agcSampleSmooth[AGC_NUM_PRESETS] = { 1/12.f, 1/6.f, 1/16.f}; // smoothing factor for sampleAgc (use rawSampleAgc if you want the non-smoothed value)
|
const float agcSampleSmooth[AGC_NUM_PRESETS] = { 1/12.f, 1/6.f, 1/16.f}; // smoothing factor for sampleAgc (use rawSampleAgc if you want the non-smoothed value)
|
||||||
// AGC presets end
|
// AGC presets end
|
||||||
|
|
||||||
static AudioSource *audioSource = nullptr;
|
static AudioSource *audioSource = nullptr;
|
||||||
@ -80,13 +80,13 @@ static float multAgc = 1.0f; // sample * multAgc = sampleAgc.
|
|||||||
// FFT Variables
|
// FFT Variables
|
||||||
constexpr uint16_t samplesFFT = 512; // Samples in an FFT batch - This value MUST ALWAYS be a power of 2
|
constexpr uint16_t samplesFFT = 512; // Samples in an FFT batch - This value MUST ALWAYS be a power of 2
|
||||||
|
|
||||||
static double FFT_MajorPeak = 0;
|
static float FFT_MajorPeak = 0.0f;
|
||||||
static double FFT_Magnitude = 0;
|
static float FFT_Magnitude = 0.0f;
|
||||||
|
|
||||||
// These are the input and output vectors. Input vectors receive computed results from FFT.
|
// These are the input and output vectors. Input vectors receive computed results from FFT.
|
||||||
static double vReal[samplesFFT];
|
static float vReal[samplesFFT];
|
||||||
static double vImag[samplesFFT];
|
static float vImag[samplesFFT];
|
||||||
static float fftBin[samplesFFT];
|
static float fftBin[samplesFFT];
|
||||||
|
|
||||||
// Try and normalize fftBin values to a max of 4096, so that 4096/16 = 256.
|
// 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.
|
// Oh, and bins 0,1,2 are no good, so we'll zero them out.
|
||||||
@ -97,6 +97,11 @@ static float fftResultMax[16]; // A table used for test
|
|||||||
#endif
|
#endif
|
||||||
static float fftAvg[16];
|
static float fftAvg[16];
|
||||||
|
|
||||||
|
#ifdef WLED_DEBUG
|
||||||
|
static unsigned long fftTime = 0;
|
||||||
|
static unsigned long sampleTime = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Table of linearNoise results to be multiplied by soundSquelch in order to reduce squelch across fftResult bins.
|
// Table of linearNoise results to be multiplied by soundSquelch in order to reduce squelch across fftResult bins.
|
||||||
static uint8_t linearNoise[16] = { 34, 28, 26, 25, 20, 12, 9, 6, 4, 4, 3, 2, 2, 2, 2, 2 };
|
static uint8_t linearNoise[16] = { 34, 28, 26, 25, 20, 12, 9, 6, 4, 4, 3, 2, 2, 2, 2, 2 };
|
||||||
|
|
||||||
@ -107,12 +112,12 @@ static float fftResultPink[16] = { 1.70f, 1.71f, 1.73f, 1.78f, 1.68f, 1.56f, 1.5
|
|||||||
static arduinoFFT FFT = arduinoFFT(vReal, vImag, samplesFFT, SAMPLE_RATE);
|
static arduinoFFT FFT = arduinoFFT(vReal, vImag, samplesFFT, SAMPLE_RATE);
|
||||||
static TaskHandle_t FFT_Task;
|
static TaskHandle_t FFT_Task;
|
||||||
|
|
||||||
float fftAdd(int from, int to) {
|
float fftAddAvg(int from, int to) {
|
||||||
float result = 0.0f;
|
float result = 0.0f;
|
||||||
for (int i = from; i <= to; i++) {
|
for (int i = from; i <= to; i++) {
|
||||||
result += fftBin[i];
|
result += fftBin[i];
|
||||||
}
|
}
|
||||||
return result;
|
return result / float(to - from + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FFT main code
|
// FFT main code
|
||||||
@ -120,7 +125,7 @@ void FFTcode(void * parameter)
|
|||||||
{
|
{
|
||||||
DEBUGSR_PRINT("FFT running on core: "); DEBUGSR_PRINTLN(xPortGetCoreID());
|
DEBUGSR_PRINT("FFT running on core: "); DEBUGSR_PRINTLN(xPortGetCoreID());
|
||||||
#ifdef MAJORPEAK_SUPPRESS_NOISE
|
#ifdef MAJORPEAK_SUPPRESS_NOISE
|
||||||
static double xtemp[24] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
static float xtemp[24] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
@ -130,8 +135,16 @@ void FFTcode(void * parameter)
|
|||||||
// Only run the FFT computing code if we're not in Receive mode
|
// Only run the FFT computing code if we're not in Receive mode
|
||||||
if (audioSyncEnabled & 0x02) continue;
|
if (audioSyncEnabled & 0x02) continue;
|
||||||
|
|
||||||
|
#ifdef WLED_DEBUG
|
||||||
|
unsigned long start = millis();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (audioSource) audioSource->getSamples(vReal, samplesFFT);
|
if (audioSource) audioSource->getSamples(vReal, samplesFFT);
|
||||||
|
|
||||||
|
#ifdef WLED_DEBUG
|
||||||
|
sampleTime = ((millis() - start)*3 + sampleTime*7)/10; // smooth
|
||||||
|
#endif
|
||||||
|
|
||||||
// old code - Last sample in vReal is our current mic sample
|
// old code - Last sample in vReal is our current mic sample
|
||||||
//micDataSm = (uint16_t)vReal[samplesFFT - 1]; // will do a this a bit later
|
//micDataSm = (uint16_t)vReal[samplesFFT - 1]; // will do a this a bit later
|
||||||
//micDataSm = ((micData * 3) + micData)/4;
|
//micDataSm = ((micData * 3) + micData)/4;
|
||||||
@ -172,31 +185,31 @@ void FFTcode(void * parameter)
|
|||||||
//
|
//
|
||||||
#ifdef MAJORPEAK_SUPPRESS_NOISE
|
#ifdef MAJORPEAK_SUPPRESS_NOISE
|
||||||
// teporarily reduce signal strength in the highest + lowest bins
|
// teporarily reduce signal strength in the highest + lowest bins
|
||||||
xtemp[0] = vReal[0]; vReal[0] *= 0.005;
|
xtemp[0] = vReal[0]; vReal[0] *= 0.005f;
|
||||||
xtemp[1] = vReal[1]; vReal[1] *= 0.005;
|
xtemp[1] = vReal[1]; vReal[1] *= 0.005f;
|
||||||
xtemp[2] = vReal[2]; vReal[2] *= 0.005;
|
xtemp[2] = vReal[2]; vReal[2] *= 0.005f;
|
||||||
xtemp[3] = vReal[3]; vReal[3] *= 0.02;
|
xtemp[3] = vReal[3]; vReal[3] *= 0.02f;
|
||||||
xtemp[4] = vReal[4]; vReal[4] *= 0.02;
|
xtemp[4] = vReal[4]; vReal[4] *= 0.02f;
|
||||||
xtemp[5] = vReal[5]; vReal[5] *= 0.02;
|
xtemp[5] = vReal[5]; vReal[5] *= 0.02f;
|
||||||
xtemp[6] = vReal[6]; vReal[6] *= 0.05;
|
xtemp[6] = vReal[6]; vReal[6] *= 0.05f;
|
||||||
xtemp[7] = vReal[7]; vReal[7] *= 0.08;
|
xtemp[7] = vReal[7]; vReal[7] *= 0.08f;
|
||||||
xtemp[8] = vReal[8]; vReal[8] *= 0.1;
|
xtemp[8] = vReal[8]; vReal[8] *= 0.1f;
|
||||||
xtemp[9] = vReal[9]; vReal[9] *= 0.2;
|
xtemp[9] = vReal[9]; vReal[9] *= 0.2f;
|
||||||
xtemp[10] = vReal[10]; vReal[10] *= 0.2;
|
xtemp[10] = vReal[10]; vReal[10] *= 0.2f;
|
||||||
xtemp[11] = vReal[11]; vReal[11] *= 0.25;
|
xtemp[11] = vReal[11]; vReal[11] *= 0.25f;
|
||||||
xtemp[12] = vReal[12]; vReal[12] *= 0.3;
|
xtemp[12] = vReal[12]; vReal[12] *= 0.3f;
|
||||||
xtemp[13] = vReal[13]; vReal[13] *= 0.3;
|
xtemp[13] = vReal[13]; vReal[13] *= 0.3f;
|
||||||
xtemp[14] = vReal[14]; vReal[14] *= 0.4;
|
xtemp[14] = vReal[14]; vReal[14] *= 0.4f;
|
||||||
xtemp[15] = vReal[15]; vReal[15] *= 0.4;
|
xtemp[15] = vReal[15]; vReal[15] *= 0.4f;
|
||||||
xtemp[16] = vReal[16]; vReal[16] *= 0.4;
|
xtemp[16] = vReal[16]; vReal[16] *= 0.4f;
|
||||||
xtemp[17] = vReal[17]; vReal[17] *= 0.5;
|
xtemp[17] = vReal[17]; vReal[17] *= 0.5f;
|
||||||
xtemp[18] = vReal[18]; vReal[18] *= 0.5;
|
xtemp[18] = vReal[18]; vReal[18] *= 0.5f;
|
||||||
xtemp[19] = vReal[19]; vReal[19] *= 0.6;
|
xtemp[19] = vReal[19]; vReal[19] *= 0.6f;
|
||||||
xtemp[20] = vReal[20]; vReal[20] *= 0.7;
|
xtemp[20] = vReal[20]; vReal[20] *= 0.7f;
|
||||||
xtemp[21] = vReal[21]; vReal[21] *= 0.8;
|
xtemp[21] = vReal[21]; vReal[21] *= 0.8f;
|
||||||
|
|
||||||
xtemp[22] = vReal[samplesFFT-2]; vReal[samplesFFT-2] =0.0;
|
xtemp[22] = vReal[samplesFFT-2]; vReal[samplesFFT-2] = 0.0f;
|
||||||
xtemp[23] = vReal[samplesFFT-1]; vReal[samplesFFT-1] =0.0;
|
xtemp[23] = vReal[samplesFFT-1]; vReal[samplesFFT-1] = 0.0f;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FFT.MajorPeak(&FFT_MajorPeak, &FFT_Magnitude); // let the effects know which freq was most dominant
|
FFT.MajorPeak(&FFT_MajorPeak, &FFT_Magnitude); // let the effects know which freq was most dominant
|
||||||
@ -233,7 +246,7 @@ void FFTcode(void * parameter)
|
|||||||
|
|
||||||
for (int i = 0; i < samplesFFT; i++) { // Values for bins 0 and 1 are WAY too large. Might as well start at 3.
|
for (int i = 0; i < samplesFFT; i++) { // Values for bins 0 and 1 are WAY too large. Might as well start at 3.
|
||||||
float t = fabs(vReal[i]); // just to be sure - values in fft bins should be positive any way
|
float t = fabs(vReal[i]); // just to be sure - values in fft bins should be positive any way
|
||||||
fftBin[i] = t / 16.0; // Reduce magnitude. Want end result to be linear and ~4096 max.
|
fftBin[i] = t / 16.0f; // Reduce magnitude. Want end result to be linear and ~4096 max.
|
||||||
} // for()
|
} // for()
|
||||||
|
|
||||||
|
|
||||||
@ -247,23 +260,23 @@ void FFTcode(void * parameter)
|
|||||||
* Multiplier = (End frequency/ Start frequency) ^ 1/16
|
* Multiplier = (End frequency/ Start frequency) ^ 1/16
|
||||||
* Multiplier = 1.320367784
|
* Multiplier = 1.320367784
|
||||||
*/
|
*/
|
||||||
// Range
|
// Range
|
||||||
fftCalc[0] = (fftAdd(3,4)) /2; // 60 - 100
|
fftCalc[ 0] = fftAddAvg(3,4); // 60 - 100
|
||||||
fftCalc[1] = (fftAdd(4,5)) /2; // 80 - 120
|
fftCalc[ 1] = fftAddAvg(4,5); // 80 - 120
|
||||||
fftCalc[2] = (fftAdd(5,7)) /3; // 100 - 160
|
fftCalc[ 2] = fftAddAvg(5,7); // 100 - 160
|
||||||
fftCalc[3] = (fftAdd(7,9)) /3; // 140 - 200
|
fftCalc[ 3] = fftAddAvg(7,9); // 140 - 200
|
||||||
fftCalc[4] = (fftAdd(9,12)) /4; // 180 - 260
|
fftCalc[ 4] = fftAddAvg(9,12); // 180 - 260
|
||||||
fftCalc[5] = (fftAdd(12,16)) /5; // 240 - 340
|
fftCalc[ 5] = fftAddAvg(12,16); // 240 - 340
|
||||||
fftCalc[6] = (fftAdd(16,21)) /6; // 320 - 440
|
fftCalc[ 6] = fftAddAvg(16,21); // 320 - 440
|
||||||
fftCalc[7] = (fftAdd(21,28)) /8; // 420 - 600
|
fftCalc[ 7] = fftAddAvg(21,28); // 420 - 600
|
||||||
fftCalc[8] = (fftAdd(29,37)) /10; // 580 - 760
|
fftCalc[ 8] = fftAddAvg(29,37); // 580 - 760
|
||||||
fftCalc[9] = (fftAdd(37,48)) /12; // 740 - 980
|
fftCalc[ 9] = fftAddAvg(37,48); // 740 - 980
|
||||||
fftCalc[10] = (fftAdd(48,64)) /17; // 960 - 1300
|
fftCalc[10] = fftAddAvg(48,64); // 960 - 1300
|
||||||
fftCalc[11] = (fftAdd(64,84)) /21; // 1280 - 1700
|
fftCalc[11] = fftAddAvg(64,84); // 1280 - 1700
|
||||||
fftCalc[12] = (fftAdd(84,111)) /28; // 1680 - 2240
|
fftCalc[12] = fftAddAvg(84,111); // 1680 - 2240
|
||||||
fftCalc[13] = (fftAdd(111,147)) /37; // 2220 - 2960
|
fftCalc[13] = fftAddAvg(111,147); // 2220 - 2960
|
||||||
fftCalc[14] = (fftAdd(147,194)) /48; // 2940 - 3900
|
fftCalc[14] = fftAddAvg(147,194); // 2940 - 3900
|
||||||
fftCalc[15] = (fftAdd(194, 255)) /62; // 3880 - 5120
|
fftCalc[15] = fftAddAvg(194,255); // 3880 - 5120
|
||||||
|
|
||||||
for (int i=0; i < 16; i++) {
|
for (int i=0; i < 16; i++) {
|
||||||
// Noise supression of fftCalc bins using soundSquelch adjustment for different input types.
|
// Noise supression of fftCalc bins using soundSquelch adjustment for different input types.
|
||||||
@ -283,10 +296,14 @@ void FFTcode(void * parameter)
|
|||||||
micDataSm = (uint16_t)maxSample2;
|
micDataSm = (uint16_t)maxSample2;
|
||||||
micDataReal = maxSample2;
|
micDataReal = maxSample2;
|
||||||
|
|
||||||
|
#ifdef WLED_DEBUG
|
||||||
|
fftTime = ((millis() - start)*3 + fftTime*7)/10;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SR_DEBUG
|
#ifdef SR_DEBUG
|
||||||
// Looking for fftResultMax for each bin using Pink Noise
|
// Looking for fftResultMax for each bin using Pink Noise
|
||||||
for (int i=0; i<16; i++) {
|
for (int i=0; i<16; i++) {
|
||||||
fftResultMax[i] = ((fftResultMax[i] * 63.0) + fftResult[i]) / 64.0;
|
fftResultMax[i] = ((fftResultMax[i] * 63.0f) + fftResult[i]) / 64.0f;
|
||||||
DEBUGSR_PRINT(fftResultMax[i]*fftResultPink[i]); DEBUGSR_PRINT("\t");
|
DEBUGSR_PRINT(fftResultMax[i]*fftResultPink[i]); DEBUGSR_PRINT("\t");
|
||||||
}
|
}
|
||||||
DEBUGSR_PRINTLN();
|
DEBUGSR_PRINTLN();
|
||||||
@ -397,6 +414,7 @@ class AudioReactive : public Usermod {
|
|||||||
// strings to reduce flash memory usage (used more than twice)
|
// strings to reduce flash memory usage (used more than twice)
|
||||||
static const char _name[];
|
static const char _name[];
|
||||||
static const char _enabled[];
|
static const char _enabled[];
|
||||||
|
static const char _inputLvl[];
|
||||||
static const char _analogmic[];
|
static const char _analogmic[];
|
||||||
static const char _digitalmic[];
|
static const char _digitalmic[];
|
||||||
static const char UDP_SYNC_HEADER[];
|
static const char UDP_SYNC_HEADER[];
|
||||||
@ -563,16 +581,16 @@ class AudioReactive : public Usermod {
|
|||||||
|
|
||||||
// NOW finally amplify the signal
|
// NOW finally amplify the signal
|
||||||
tmpAgc = sampleReal * multAgcTemp; // apply gain to signal
|
tmpAgc = sampleReal * multAgcTemp; // apply gain to signal
|
||||||
if (fabs(sampleReal) < 2.0f) tmpAgc = 0; // apply squelch threshold
|
if (fabsf(sampleReal) < 2.0f) tmpAgc = 0.0f; // apply squelch threshold
|
||||||
//tmpAgc = constrain(tmpAgc, 0, 255);
|
//tmpAgc = constrain(tmpAgc, 0, 255);
|
||||||
if (tmpAgc > 255) tmpAgc = 255; // limit to 8bit
|
if (tmpAgc > 255) tmpAgc = 255.0f; // limit to 8bit
|
||||||
if (tmpAgc < 1) tmpAgc = 0; // just to be sure
|
if (tmpAgc < 1) tmpAgc = 0.0f; // just to be sure
|
||||||
|
|
||||||
// update global vars ONCE - multAgc, sampleAGC, rawSampleAgc
|
// update global vars ONCE - multAgc, sampleAGC, rawSampleAgc
|
||||||
multAgc = multAgcTemp;
|
multAgc = multAgcTemp;
|
||||||
rawSampleAgc = 0.8f * tmpAgc + 0.2f * (float)rawSampleAgc;
|
rawSampleAgc = 0.8f * tmpAgc + 0.2f * (float)rawSampleAgc;
|
||||||
// update smoothed AGC sample
|
// update smoothed AGC sample
|
||||||
if (fabs(tmpAgc) < 1.0f)
|
if (fabsf(tmpAgc) < 1.0f)
|
||||||
sampleAgc = 0.5f * tmpAgc + 0.5f * sampleAgc; // fast path to zero
|
sampleAgc = 0.5f * tmpAgc + 0.5f * sampleAgc; // fast path to zero
|
||||||
else
|
else
|
||||||
sampleAgc += agcSampleSmooth[AGC_preset] * (tmpAgc - sampleAgc); // smooth path
|
sampleAgc += agcSampleSmooth[AGC_preset] * (tmpAgc - sampleAgc); // smooth path
|
||||||
@ -613,14 +631,14 @@ class AudioReactive : public Usermod {
|
|||||||
expAdjF = (weighting * micInNoDC + (1.0-weighting) * expAdjF);
|
expAdjF = (weighting * micInNoDC + (1.0-weighting) * expAdjF);
|
||||||
expAdjF = (expAdjF <= soundSquelch) ? 0: expAdjF; // simple noise gate
|
expAdjF = (expAdjF <= soundSquelch) ? 0: expAdjF; // simple noise gate
|
||||||
|
|
||||||
expAdjF = fabs(expAdjF); // Now (!) take the absolute value
|
expAdjF = fabsf(expAdjF); // Now (!) take the absolute value
|
||||||
tmpSample = expAdjF;
|
tmpSample = expAdjF;
|
||||||
|
|
||||||
DEBUGSR_PRINT("\t\t"); DEBUGSR_PRINT(tmpSample);
|
DEBUGSR_PRINT("\t\t"); DEBUGSR_PRINT(tmpSample);
|
||||||
|
|
||||||
micIn = abs(micIn); // And get the absolute value of each sample
|
micIn = abs(micIn); // And get the absolute value of each sample
|
||||||
|
|
||||||
sampleAdj = tmpSample * sampleGain / 40 * inputLevel/128 + tmpSample / 16; // Adjust the gain. with inputLevel adjustment
|
sampleAdj = tmpSample * sampleGain / 40.0f * inputLevel/128.0f + tmpSample / 16.0f; // Adjust the gain. with inputLevel adjustment
|
||||||
//sampleReal = sampleAdj;
|
//sampleReal = sampleAdj;
|
||||||
sampleReal = tmpSample;
|
sampleReal = tmpSample;
|
||||||
|
|
||||||
@ -647,8 +665,8 @@ class AudioReactive : public Usermod {
|
|||||||
uint16_t MinShowDelay = strip.getMinShowDelay();
|
uint16_t MinShowDelay = strip.getMinShowDelay();
|
||||||
|
|
||||||
if (millis() - timeOfPeak > MinShowDelay) { // Auto-reset of samplePeak after a complete frame has passed.
|
if (millis() - timeOfPeak > MinShowDelay) { // Auto-reset of samplePeak after a complete frame has passed.
|
||||||
samplePeak = 0;
|
samplePeak = false;
|
||||||
udpSamplePeak = 0;
|
udpSamplePeak = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (userVar1 == 0) samplePeak = 0;
|
//if (userVar1 == 0) samplePeak = 0;
|
||||||
@ -664,9 +682,9 @@ class AudioReactive : public Usermod {
|
|||||||
if ((fftBin[binNum] > maxVol) && (millis() > (timeOfPeak + 100))) { // This goes through ALL of the 255 bins
|
if ((fftBin[binNum] > maxVol) && (millis() > (timeOfPeak + 100))) { // This goes through ALL of the 255 bins
|
||||||
// if (sample > (sampleAvg + maxVol) && millis() > (timeOfPeak + 200)) {
|
// if (sample > (sampleAvg + maxVol) && millis() > (timeOfPeak + 200)) {
|
||||||
// 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.
|
// 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 = 1;
|
samplePeak = true;
|
||||||
timeOfPeak = millis();
|
timeOfPeak = millis();
|
||||||
udpSamplePeak = 1;
|
udpSamplePeak = true;
|
||||||
//userVar1 = samplePeak;
|
//userVar1 = samplePeak;
|
||||||
}
|
}
|
||||||
} // getSample()
|
} // getSample()
|
||||||
@ -776,9 +794,9 @@ class AudioReactive : public Usermod {
|
|||||||
um_data->u_data[ 5] = &samplePeak; //*used (Puddlepeak, Ripplepeak, Waterfall)
|
um_data->u_data[ 5] = &samplePeak; //*used (Puddlepeak, Ripplepeak, Waterfall)
|
||||||
um_data->u_type[ 5] = UMT_BYTE;
|
um_data->u_type[ 5] = UMT_BYTE;
|
||||||
um_data->u_data[ 6] = &FFT_MajorPeak; //*used (Ripplepeak, Freqmap, Freqmatrix, Freqpixels, Freqwave, Gravfreq, Rocktaves, Waterfall)
|
um_data->u_data[ 6] = &FFT_MajorPeak; //*used (Ripplepeak, Freqmap, Freqmatrix, Freqpixels, Freqwave, Gravfreq, Rocktaves, Waterfall)
|
||||||
um_data->u_type[ 6] = UMT_DOUBLE;
|
um_data->u_type[ 6] = UMT_FLOAT;
|
||||||
um_data->u_data[ 7] = &FFT_Magnitude; //*used (Binmap, Freqmap, Freqpixels, Rocktaves, Waterfall)
|
um_data->u_data[ 7] = &FFT_Magnitude; //*used (Binmap, Freqmap, Freqpixels, Rocktaves, Waterfall)
|
||||||
um_data->u_type[ 7] = UMT_DOUBLE;
|
um_data->u_type[ 7] = UMT_FLOAT;
|
||||||
um_data->u_data[ 8] = fftResult; //*used (Blurz, DJ Light, Noisemove, GEQ_base, 2D Funky Plank, Akemi)
|
um_data->u_data[ 8] = fftResult; //*used (Blurz, DJ Light, Noisemove, GEQ_base, 2D Funky Plank, Akemi)
|
||||||
um_data->u_type[ 8] = UMT_BYTE_ARR;
|
um_data->u_type[ 8] = UMT_BYTE_ARR;
|
||||||
um_data->u_data[ 9] = &maxVol; // assigned in effect function from UI element!!! (Puddlepeak, Ripplepeak, Waterfall)
|
um_data->u_data[ 9] = &maxVol; // assigned in effect function from UI element!!! (Puddlepeak, Ripplepeak, Waterfall)
|
||||||
@ -966,6 +984,9 @@ class AudioReactive : public Usermod {
|
|||||||
|
|
||||||
void onUpdateBegin(bool init)
|
void onUpdateBegin(bool init)
|
||||||
{
|
{
|
||||||
|
#ifdef WLED_DEBUG
|
||||||
|
fftTime = sampleTime = 0;
|
||||||
|
#endif
|
||||||
if (init) vTaskDelete(FFT_Task); // update is about to begin, remove task to prevent crash
|
if (init) vTaskDelete(FFT_Task); // update is about to begin, remove task to prevent crash
|
||||||
else { // update has failed or create task requested
|
else { // update has failed or create task requested
|
||||||
// Define the FFT Task and lock it to core 0
|
// Define the FFT Task and lock it to core 0
|
||||||
@ -1021,6 +1042,25 @@ class AudioReactive : public Usermod {
|
|||||||
uiDomString += F("\"></i>");
|
uiDomString += F("\"></i>");
|
||||||
uiDomString += F("</button>");
|
uiDomString += F("</button>");
|
||||||
infoArr.add(uiDomString);
|
infoArr.add(uiDomString);
|
||||||
|
|
||||||
|
infoArr = user.createNestedArray(F("Input level"));
|
||||||
|
uiDomString = F("<div class=\"slider\"><div class=\"sliderwrap il\"><input class=\"noslide\" onchange=\"requestJson({");
|
||||||
|
uiDomString += FPSTR(_name);
|
||||||
|
uiDomString += F(":{");
|
||||||
|
uiDomString += FPSTR(_inputLvl);
|
||||||
|
uiDomString += F(":parseInt(this.value)}});\" oninput=\"updateTrail(this);\" max=255 min=0 type=\"range\" value=");
|
||||||
|
uiDomString += inputLevel;
|
||||||
|
uiDomString += F(" /><div class=\"sliderdisplay\"></div></div></div>"); //<output class=\"sliderbubble\"></output>
|
||||||
|
infoArr.add(uiDomString);
|
||||||
|
|
||||||
|
#ifdef WLED_DEBUG
|
||||||
|
infoArr = user.createNestedArray(F("Sampling time"));
|
||||||
|
infoArr.add(sampleTime);
|
||||||
|
infoArr.add("ms");
|
||||||
|
infoArr = user.createNestedArray(F("FFT time"));
|
||||||
|
infoArr.add(fftTime-sampleTime);
|
||||||
|
infoArr.add("ms");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1050,6 +1090,9 @@ class AudioReactive : public Usermod {
|
|||||||
enabled = usermod[FPSTR(_enabled)].as<bool>();
|
enabled = usermod[FPSTR(_enabled)].as<bool>();
|
||||||
if (prevEnabled != enabled) onUpdateBegin(!enabled);
|
if (prevEnabled != enabled) onUpdateBegin(!enabled);
|
||||||
}
|
}
|
||||||
|
if (usermod[FPSTR(_inputLvl)].is<int>()) {
|
||||||
|
inputLevel = min(255,max(0,usermod[FPSTR(_inputLvl)].as<int>()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1215,6 +1258,7 @@ class AudioReactive : public Usermod {
|
|||||||
// strings to reduce flash memory usage (used more than twice)
|
// strings to reduce flash memory usage (used more than twice)
|
||||||
const char AudioReactive::_name[] PROGMEM = "AudioReactive";
|
const char AudioReactive::_name[] PROGMEM = "AudioReactive";
|
||||||
const char AudioReactive::_enabled[] PROGMEM = "enabled";
|
const char AudioReactive::_enabled[] PROGMEM = "enabled";
|
||||||
|
const char AudioReactive::_inputLvl[] PROGMEM = "inputLevel";
|
||||||
const char AudioReactive::_analogmic[] PROGMEM = "analogmic";
|
const char AudioReactive::_analogmic[] PROGMEM = "analogmic";
|
||||||
const char AudioReactive::_digitalmic[] PROGMEM = "digitalmic";
|
const char AudioReactive::_digitalmic[] PROGMEM = "digitalmic";
|
||||||
const char AudioReactive::UDP_SYNC_HEADER[] PROGMEM = "00001";
|
const char AudioReactive::UDP_SYNC_HEADER[] PROGMEM = "00001";
|
||||||
|
@ -50,7 +50,7 @@ class AudioSource {
|
|||||||
Read num_samples from the microphone, and store them in the provided
|
Read num_samples from the microphone, and store them in the provided
|
||||||
buffer
|
buffer
|
||||||
*/
|
*/
|
||||||
virtual void getSamples(double *buffer, uint16_t num_samples) = 0;
|
virtual void getSamples(float *buffer, uint16_t num_samples) = 0;
|
||||||
|
|
||||||
/* Get an up-to-date sample without DC offset */
|
/* Get an up-to-date sample without DC offset */
|
||||||
virtual int getSampleWithoutDCOffset() { return _sampleNoDCOffset; };
|
virtual int getSampleWithoutDCOffset() { return _sampleNoDCOffset; };
|
||||||
@ -156,7 +156,7 @@ class I2SSource : public AudioSource {
|
|||||||
if (_mclkPin != I2S_PIN_NO_CHANGE) pinManager.deallocatePin(_mclkPin, PinOwner::UM_Audioreactive);
|
if (_mclkPin != I2S_PIN_NO_CHANGE) pinManager.deallocatePin(_mclkPin, PinOwner::UM_Audioreactive);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void getSamples(double *buffer, uint16_t num_samples) {
|
virtual void getSamples(float *buffer, uint16_t num_samples) {
|
||||||
if (_initialized) {
|
if (_initialized) {
|
||||||
esp_err_t err;
|
esp_err_t err;
|
||||||
size_t bytes_read = 0; /* Counter variable to check if we actually got enough data */
|
size_t bytes_read = 0; /* Counter variable to check if we actually got enough data */
|
||||||
@ -184,17 +184,17 @@ class I2SSource : public AudioSource {
|
|||||||
if (_shift != 0)
|
if (_shift != 0)
|
||||||
newSamples[i] >>= 16;
|
newSamples[i] >>= 16;
|
||||||
#endif
|
#endif
|
||||||
double currSample = 0.0;
|
float currSample = 0.0f;
|
||||||
if(_shift > 0)
|
if(_shift > 0)
|
||||||
currSample = (double) (newSamples[i] >> _shift);
|
currSample = (float) (newSamples[i] >> _shift);
|
||||||
else {
|
else {
|
||||||
if(_shift < 0)
|
if(_shift < 0)
|
||||||
currSample = (double) (newSamples[i] << (- _shift)); // need to "pump up" 12bit ADC to full 16bit as delivered by other digital mics
|
currSample = (float) (newSamples[i] << (- _shift)); // need to "pump up" 12bit ADC to full 16bit as delivered by other digital mics
|
||||||
else
|
else
|
||||||
#ifdef I2S_SAMPLE_DOWNSCALE_TO_16BIT
|
#ifdef I2S_SAMPLE_DOWNSCALE_TO_16BIT
|
||||||
currSample = (double) newSamples[i] / 65536.0; // _shift == 0 -> use the chance to keep lower 16bits
|
currSample = (float) newSamples[i] / 65536.0f; // _shift == 0 -> use the chance to keep lower 16bits
|
||||||
#else
|
#else
|
||||||
currSample = (double) newSamples[i];
|
currSample = (float) newSamples[i];
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
buffer[i] = currSample;
|
buffer[i] = currSample;
|
||||||
@ -356,7 +356,7 @@ class I2SAdcSource : public I2SSource {
|
|||||||
_initialized = true;
|
_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void getSamples(double *buffer, uint16_t num_samples) {
|
void getSamples(float *buffer, uint16_t num_samples) {
|
||||||
/* Enable ADC. This has to be enabled and disabled directly before and
|
/* Enable ADC. This has to be enabled and disabled directly before and
|
||||||
* after sampling, otherwise Wifi dies
|
* after sampling, otherwise Wifi dies
|
||||||
*/
|
*/
|
||||||
|
@ -9,9 +9,11 @@ The usermod **does not** provide effects or draws anything to LED strip/matrix.
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Add `-D USERMOD_AUDIOREACTIVE` to your PlatformIO environment as well as `arduinoFFT @ 1.5.6` to your `lib_deps`.
|
Add `-D USERMOD_AUDIOREACTIVE` to your PlatformIO environment as well as `arduinoFFT` to your `lib_deps`.
|
||||||
If you are not using PlatformIO (which you should) try adding `#define USERMOD_AUDIOREACTIVE` to *my_config.h* and make sure you have _arduinoFFT_ library downloaded and installed.
|
If you are not using PlatformIO (which you should) try adding `#define USERMOD_AUDIOREACTIVE` to *my_config.h* and make sure you have _arduinoFFT_ library downloaded and installed.
|
||||||
|
|
||||||
|
Customised _arduinoFFT_ library for use with this usermod can be found at https://github.com/blazoncek/arduinoFFT.git
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
All parameters are runtime configurable though some may require hard boot after change (I2S microphone or selected GPIOs).
|
All parameters are runtime configurable though some may require hard boot after change (I2S microphone or selected GPIOs).
|
||||||
|
@ -5947,7 +5947,7 @@ static const char *_data_FX_MODE_DRIFT_ROSE PROGMEM = "2D Drift Rose@Fade,Blur;;
|
|||||||
uint8_t soundAgc = 0, soundSquelch = 10;
|
uint8_t soundAgc = 0, soundSquelch = 10;
|
||||||
bool samplePeak = false;
|
bool samplePeak = false;
|
||||||
float sampleAgc = 0.0f, sampleAgv = 0.0f, multAgc = 0.0f, sampleReal = 0.0f;
|
float sampleAgc = 0.0f, sampleAgv = 0.0f, multAgc = 0.0f, sampleReal = 0.0f;
|
||||||
double FFT_MajorPeak = 0.0, FFT_Magnitude = 0.0;
|
float FFT_MajorPeak = 0.0, FFT_Magnitude = 0.0;
|
||||||
uint8_t *fftResult = nullptr;
|
uint8_t *fftResult = nullptr;
|
||||||
uint16_t *myVals = nullptr;
|
uint16_t *myVals = nullptr;
|
||||||
float *fftBin = nullptr;
|
float *fftBin = nullptr;
|
||||||
@ -5959,8 +5959,8 @@ static const char *_data_FX_MODE_DRIFT_ROSE PROGMEM = "2D Drift Rose@Fade,Blur;;
|
|||||||
sample = *(uint16_t*)um_data->u_data[ 3];
|
sample = *(uint16_t*)um_data->u_data[ 3];
|
||||||
rawSampleAgc = *(uint16_t*)um_data->u_data[ 4];
|
rawSampleAgc = *(uint16_t*)um_data->u_data[ 4];
|
||||||
samplePeak = *(uint8_t*) um_data->u_data[ 5];
|
samplePeak = *(uint8_t*) um_data->u_data[ 5];
|
||||||
FFT_MajorPeak = *(double*) um_data->u_data[ 6];
|
FFT_MajorPeak = *(float*) um_data->u_data[ 6];
|
||||||
FFT_Magnitude = *(double*) um_data->u_data[ 7];
|
FFT_Magnitude = *(float*) um_data->u_data[ 7];
|
||||||
fftResult = (uint8_t*) um_data->u_data[ 8];
|
fftResult = (uint8_t*) um_data->u_data[ 8];
|
||||||
maxVol = (uint8_t*) um_data->u_data[ 9]; // requires UI element (SEGMENT.customX?), changes source element
|
maxVol = (uint8_t*) um_data->u_data[ 9]; // requires UI element (SEGMENT.customX?), changes source element
|
||||||
binNum = (uint8_t*) um_data->u_data[10]; // requires UI element (SEGMENT.customX?), changes source element
|
binNum = (uint8_t*) um_data->u_data[10]; // requires UI element (SEGMENT.customX?), changes source element
|
||||||
@ -5998,10 +5998,10 @@ uint16_t WS2812FX::mode_ripplepeak(void) { // * Ripple peak. By A
|
|||||||
|
|
||||||
uint8_t *binNum, *maxVol; // just in case assignment
|
uint8_t *binNum, *maxVol; // just in case assignment
|
||||||
uint8_t samplePeak = 0; // actually a bool
|
uint8_t samplePeak = 0; // actually a bool
|
||||||
double FFT_MajorPeak = 0.0;
|
float FFT_MajorPeak = 0.0;
|
||||||
um_data_t *um_data;
|
um_data_t *um_data;
|
||||||
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||||
FFT_MajorPeak = *(double*) um_data->u_data[6];
|
FFT_MajorPeak = *(float*) um_data->u_data[6];
|
||||||
binNum = (uint8_t*)um_data->u_data[10];
|
binNum = (uint8_t*)um_data->u_data[10];
|
||||||
maxVol = (uint8_t*)um_data->u_data[9];
|
maxVol = (uint8_t*)um_data->u_data[9];
|
||||||
samplePeak = *(uint8_t*)um_data->u_data[5];
|
samplePeak = *(uint8_t*)um_data->u_data[5];
|
||||||
@ -6885,7 +6885,7 @@ uint16_t WS2812FX::mode_binmap(void) {
|
|||||||
uint16_t endBin = FIRSTBIN+(i+1)*(LASTBIN-FIRSTBIN)/SEGLEN; // This is the END bin for this particular pixel.
|
uint16_t endBin = FIRSTBIN+(i+1)*(LASTBIN-FIRSTBIN)/SEGLEN; // This is the END bin for this particular pixel.
|
||||||
if (endBin > startBin) endBin --; // avoid overlapping
|
if (endBin > startBin) endBin --; // avoid overlapping
|
||||||
|
|
||||||
double sumBin = 0;
|
float sumBin = 0;
|
||||||
|
|
||||||
for (int j=startBin; j<=endBin; j++) {
|
for (int j=startBin; j<=endBin; j++) {
|
||||||
sumBin += (fftBin[j] < soundSquelch*1.75f) ? 0 : fftBin[j]; // We need some sound temporary squelch for fftBin, because we didn't do it for the raw bins in audio_reactive.h
|
sumBin += (fftBin[j] < soundSquelch*1.75f) ? 0 : fftBin[j]; // We need some sound temporary squelch for fftBin, because we didn't do it for the raw bins in audio_reactive.h
|
||||||
@ -6988,15 +6988,15 @@ uint16_t WS2812FX::mode_freqmap(void) { // Map FFT_MajorPeak t
|
|||||||
// Start frequency = 60 Hz and log10(60) = 1.78
|
// Start frequency = 60 Hz and log10(60) = 1.78
|
||||||
// End frequency = 5120 Hz and lo10(5120) = 3.71
|
// End frequency = 5120 Hz and lo10(5120) = 3.71
|
||||||
|
|
||||||
double FFT_MajorPeak = 0.0;
|
float FFT_MajorPeak = 0.0;
|
||||||
double FFT_Magnitude = 0.0;
|
float FFT_Magnitude = 0.0;
|
||||||
uint8_t soundAgc = 0;
|
uint8_t soundAgc = 0;
|
||||||
float sampleAvg = 0.0f;
|
float sampleAvg = 0.0f;
|
||||||
float multAgc = 0.0f;
|
float multAgc = 0.0f;
|
||||||
um_data_t *um_data;
|
um_data_t *um_data;
|
||||||
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||||
FFT_MajorPeak = *(double*)um_data->u_data[6];
|
FFT_MajorPeak = *(float*)um_data->u_data[6];
|
||||||
FFT_Magnitude = *(double*)um_data->u_data[7];
|
FFT_Magnitude = *(float*)um_data->u_data[7];
|
||||||
sampleAvg = *(float*)um_data->u_data[0];
|
sampleAvg = *(float*)um_data->u_data[0];
|
||||||
soundAgc = *(uint8_t*)um_data->u_data[1];
|
soundAgc = *(uint8_t*)um_data->u_data[1];
|
||||||
multAgc = *(float*)um_data->u_data[11];
|
multAgc = *(float*)um_data->u_data[11];
|
||||||
@ -7027,11 +7027,11 @@ static const char *_data_FX_MODE_FREQMAP PROGMEM = " ♫ Freqmap@Fade rate,Start
|
|||||||
// ** Freqmatrix //
|
// ** Freqmatrix //
|
||||||
///////////////////////
|
///////////////////////
|
||||||
uint16_t WS2812FX::mode_freqmatrix(void) { // Freqmatrix. By Andreas Pleschung.
|
uint16_t WS2812FX::mode_freqmatrix(void) { // Freqmatrix. By Andreas Pleschung.
|
||||||
double FFT_MajorPeak = 0.0;
|
float FFT_MajorPeak = 0.0;
|
||||||
float sampleAgc = 0.0f;
|
float sampleAgc = 0.0f;
|
||||||
um_data_t *um_data;
|
um_data_t *um_data;
|
||||||
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||||
FFT_MajorPeak = *(double*)um_data->u_data[6];
|
FFT_MajorPeak = *(float*)um_data->u_data[6];
|
||||||
sampleAgc = *(float*)um_data->u_data[2];
|
sampleAgc = *(float*)um_data->u_data[2];
|
||||||
} else {
|
} else {
|
||||||
// add support for no audio data
|
// add support for no audio data
|
||||||
@ -7083,15 +7083,15 @@ static const char *_data_FX_MODE_FREQMATRIX PROGMEM = " ♫ Freqmatrix@Time dela
|
|||||||
// SEGMENT.speed select faderate
|
// SEGMENT.speed select faderate
|
||||||
// SEGMENT.intensity select colour index
|
// SEGMENT.intensity select colour index
|
||||||
uint16_t WS2812FX::mode_freqpixels(void) { // Freqpixel. By Andrew Tuline.
|
uint16_t WS2812FX::mode_freqpixels(void) { // Freqpixel. By Andrew Tuline.
|
||||||
double FFT_MajorPeak = 0.0;
|
float FFT_MajorPeak = 0.0;
|
||||||
double FFT_Magnitude = 0.0;
|
float FFT_Magnitude = 0.0;
|
||||||
uint8_t soundAgc = 0;
|
uint8_t soundAgc = 0;
|
||||||
float sampleAvg = 0.0f;
|
float sampleAvg = 0.0f;
|
||||||
float multAgc = 0.0f;
|
float multAgc = 0.0f;
|
||||||
um_data_t *um_data;
|
um_data_t *um_data;
|
||||||
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||||
FFT_MajorPeak = *(double*)um_data->u_data[6];
|
FFT_MajorPeak = *(float*)um_data->u_data[6];
|
||||||
FFT_Magnitude = *(double*)um_data->u_data[7];
|
FFT_Magnitude = *(float*)um_data->u_data[7];
|
||||||
sampleAvg = *(float*)um_data->u_data[0];
|
sampleAvg = *(float*)um_data->u_data[0];
|
||||||
soundAgc = *(uint8_t*)um_data->u_data[1];
|
soundAgc = *(uint8_t*)um_data->u_data[1];
|
||||||
multAgc = *(float*)um_data->u_data[11];
|
multAgc = *(float*)um_data->u_data[11];
|
||||||
@ -7133,12 +7133,12 @@ static const char *_data_FX_MODE_FREQPIXELS PROGMEM = " ♫ Freqpixels@Fade rate
|
|||||||
// As a compromise between speed and accuracy we are currently sampling with 10240Hz, from which we can then determine with a 512bin FFT our max frequency is 5120Hz.
|
// As a compromise between speed and accuracy we are currently sampling with 10240Hz, from which we can then determine with a 512bin FFT our max frequency is 5120Hz.
|
||||||
// Depending on the music stream you have you might find it useful to change the frequency mapping.
|
// Depending on the music stream you have you might find it useful to change the frequency mapping.
|
||||||
uint16_t WS2812FX::mode_freqwave(void) { // Freqwave. By Andreas Pleschung.
|
uint16_t WS2812FX::mode_freqwave(void) { // Freqwave. By Andreas Pleschung.
|
||||||
double FFT_MajorPeak = 0.0;
|
float FFT_MajorPeak = 0.0;
|
||||||
uint8_t soundAgc = 0;
|
uint8_t soundAgc = 0;
|
||||||
float sampleAgc = 0.0f, sampleAvg = 0.0f;
|
float sampleAgc = 0.0f, sampleAvg = 0.0f;
|
||||||
um_data_t *um_data;
|
um_data_t *um_data;
|
||||||
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||||
FFT_MajorPeak = *(double*)um_data->u_data[6];
|
FFT_MajorPeak = *(float*)um_data->u_data[6];
|
||||||
sampleAvg = *(float*)um_data->u_data[0];
|
sampleAvg = *(float*)um_data->u_data[0];
|
||||||
soundAgc = *(uint8_t*)um_data->u_data[1];
|
soundAgc = *(uint8_t*)um_data->u_data[1];
|
||||||
sampleAgc = *(float*)um_data->u_data[2];
|
sampleAgc = *(float*)um_data->u_data[2];
|
||||||
@ -7203,9 +7203,9 @@ uint16_t WS2812FX::mode_gravfreq(void) { // Gravfreq. By Andrew
|
|||||||
um_data_t *um_data;
|
um_data_t *um_data;
|
||||||
uint8_t soundAgc = 0;
|
uint8_t soundAgc = 0;
|
||||||
float sampleAgc = 0.0f, sampleAvg = 0.0f;
|
float sampleAgc = 0.0f, sampleAvg = 0.0f;
|
||||||
double FFT_MajorPeak = 0.0;
|
float FFT_MajorPeak = 0.0;
|
||||||
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||||
FFT_MajorPeak = *(double*)um_data->u_data[6];
|
FFT_MajorPeak = *(float*)um_data->u_data[6];
|
||||||
soundAgc = *(uint8_t*)um_data->u_data[1];
|
soundAgc = *(uint8_t*)um_data->u_data[1];
|
||||||
sampleAgc = *(float*)um_data->u_data[2];
|
sampleAgc = *(float*)um_data->u_data[2];
|
||||||
sampleAvg = *(float*)um_data->u_data[0];
|
sampleAvg = *(float*)um_data->u_data[0];
|
||||||
@ -7279,15 +7279,15 @@ static const char *_data_FX_MODE_NOISEMOVE PROGMEM = " ♫ Noisemove@Speed of pe
|
|||||||
// ** Rocktaves //
|
// ** Rocktaves //
|
||||||
//////////////////////
|
//////////////////////
|
||||||
uint16_t WS2812FX::mode_rocktaves(void) { // Rocktaves. Same note from each octave is same colour. By: Andrew Tuline
|
uint16_t WS2812FX::mode_rocktaves(void) { // Rocktaves. Same note from each octave is same colour. By: Andrew Tuline
|
||||||
double FFT_MajorPeak = 0.0;
|
float FFT_MajorPeak = 0.0;
|
||||||
double FFT_Magnitude = 0.0;
|
float FFT_Magnitude = 0.0;
|
||||||
uint8_t soundAgc = 0;
|
uint8_t soundAgc = 0;
|
||||||
float sampleAvg = 0.0f;
|
float sampleAvg = 0.0f;
|
||||||
float multAgc = 0.0f;
|
float multAgc = 0.0f;
|
||||||
um_data_t *um_data;
|
um_data_t *um_data;
|
||||||
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||||
FFT_MajorPeak = *(double*)um_data->u_data[6];
|
FFT_MajorPeak = *(float*)um_data->u_data[6];
|
||||||
FFT_Magnitude = *(double*)um_data->u_data[7];
|
FFT_Magnitude = *(float*)um_data->u_data[7];
|
||||||
sampleAvg = *(float*)um_data->u_data[0];
|
sampleAvg = *(float*)um_data->u_data[0];
|
||||||
soundAgc = *(uint8_t*)um_data->u_data[1];
|
soundAgc = *(uint8_t*)um_data->u_data[1];
|
||||||
multAgc = *(float*)um_data->u_data[11];
|
multAgc = *(float*)um_data->u_data[11];
|
||||||
@ -7333,8 +7333,8 @@ uint16_t WS2812FX::mode_waterfall(void) { // Waterfall. By: An
|
|||||||
|
|
||||||
uint8_t *binNum, *maxVol;
|
uint8_t *binNum, *maxVol;
|
||||||
uint8_t samplePeak = 0;
|
uint8_t samplePeak = 0;
|
||||||
double FFT_MajorPeak = 0.0;
|
float FFT_MajorPeak = 0.0;
|
||||||
double FFT_Magnitude = 0.0;
|
float FFT_Magnitude = 0.0;
|
||||||
uint8_t soundAgc = 0;
|
uint8_t soundAgc = 0;
|
||||||
float sampleAvg = 0.0f;
|
float sampleAvg = 0.0f;
|
||||||
float multAgc = 0.0f;
|
float multAgc = 0.0f;
|
||||||
@ -7343,8 +7343,8 @@ uint16_t WS2812FX::mode_waterfall(void) { // Waterfall. By: An
|
|||||||
maxVol = (uint8_t*)um_data->u_data[9];
|
maxVol = (uint8_t*)um_data->u_data[9];
|
||||||
samplePeak = *(uint8_t*)um_data->u_data[5];
|
samplePeak = *(uint8_t*)um_data->u_data[5];
|
||||||
binNum = (uint8_t*)um_data->u_data[10];
|
binNum = (uint8_t*)um_data->u_data[10];
|
||||||
FFT_MajorPeak = *(double*)um_data->u_data[6];
|
FFT_MajorPeak = *(float*)um_data->u_data[6];
|
||||||
FFT_Magnitude = *(double*)um_data->u_data[7];
|
FFT_Magnitude = *(float*)um_data->u_data[7];
|
||||||
sampleAvg = *(float*)um_data->u_data[0];
|
sampleAvg = *(float*)um_data->u_data[0];
|
||||||
soundAgc = *(uint8_t*)um_data->u_data[1];
|
soundAgc = *(uint8_t*)um_data->u_data[1];
|
||||||
multAgc = *(float*)um_data->u_data[11];
|
multAgc = *(float*)um_data->u_data[11];
|
||||||
@ -7446,16 +7446,6 @@ uint16_t WS2812FX::mode_2DGEQ(void) { // By Will Tatam. Code reduction by Ewoud
|
|||||||
static const char *_data_FX_MODE_2DGEQ PROGMEM = " ♫ 2D GEQ@Fade speed,Ripple decay,# of bands=255,Color bars=64;!,,Peak Color;!=11";
|
static const char *_data_FX_MODE_2DGEQ PROGMEM = " ♫ 2D GEQ@Fade speed,Ripple decay,# of bands=255,Color bars=64;!,,Peak Color;!=11";
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////
|
|
||||||
// ** 2D CenterBars //
|
|
||||||
/////////////////////////
|
|
||||||
// NOTE: obsolete!
|
|
||||||
uint16_t WS2812FX::mode_2DCenterBars(void) { // Written by Scott Marley Adapted by Spiro-C..
|
|
||||||
return mode_2DGEQ();
|
|
||||||
} // mode_2DCenterBars()
|
|
||||||
static const char *_data_FX_MODE_2DCENTERBARS PROGMEM = " ♫ 2D CenterBars@Bar speed,Ripple decay,# of bands=255,Color bars=64;!,,Peak Color;!=11";
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////
|
/////////////////////////
|
||||||
// ** 2D Funky plank //
|
// ** 2D Funky plank //
|
||||||
/////////////////////////
|
/////////////////////////
|
||||||
@ -7834,7 +7824,7 @@ void WS2812FX::setupEffectData() {
|
|||||||
addEffect(FX_MODE_GRAVFREQ, &WS2812FX::mode_gravfreq, _data_FX_MODE_GRAVFREQ);
|
addEffect(FX_MODE_GRAVFREQ, &WS2812FX::mode_gravfreq, _data_FX_MODE_GRAVFREQ);
|
||||||
addEffect(FX_MODE_DJLIGHT, &WS2812FX::mode_DJLight, _data_FX_MODE_DJLIGHT);
|
addEffect(FX_MODE_DJLIGHT, &WS2812FX::mode_DJLight, _data_FX_MODE_DJLIGHT);
|
||||||
addEffect(FX_MODE_2DFUNKYPLANK, &WS2812FX::mode_2DFunkyPlank, _data_FX_MODE_2DFUNKYPLANK);
|
addEffect(FX_MODE_2DFUNKYPLANK, &WS2812FX::mode_2DFunkyPlank, _data_FX_MODE_2DFUNKYPLANK);
|
||||||
addEffect(FX_MODE_2DCENTERBARS, &WS2812FX::mode_2DCenterBars, _data_FX_MODE_2DCENTERBARS);
|
//addEffect(FX_MODE_2DCENTERBARS, &WS2812FX::mode_2DCenterBars, _data_FX_MODE_2DCENTERBARS);
|
||||||
addEffect(FX_MODE_2DPULSER, &WS2812FX::mode_2DPulser, _data_FX_MODE_2DPULSER);
|
addEffect(FX_MODE_2DPULSER, &WS2812FX::mode_2DPulser, _data_FX_MODE_2DPULSER);
|
||||||
addEffect(FX_MODE_BLURZ, &WS2812FX::mode_blurz, _data_FX_MODE_BLURZ);
|
addEffect(FX_MODE_BLURZ, &WS2812FX::mode_blurz, _data_FX_MODE_BLURZ);
|
||||||
addEffect(FX_MODE_2DSUNRADIATION, &WS2812FX::mode_2DSunradiation, _data_FX_MODE_2DSUNRADIATION);
|
addEffect(FX_MODE_2DSUNRADIATION, &WS2812FX::mode_2DSunradiation, _data_FX_MODE_2DSUNRADIATION);
|
||||||
|
@ -327,7 +327,7 @@
|
|||||||
#define FX_MODE_GRAVFREQ 158
|
#define FX_MODE_GRAVFREQ 158
|
||||||
#define FX_MODE_DJLIGHT 159
|
#define FX_MODE_DJLIGHT 159
|
||||||
#define FX_MODE_2DFUNKYPLANK 160
|
#define FX_MODE_2DFUNKYPLANK 160
|
||||||
#define FX_MODE_2DCENTERBARS 161 // obsolete by X & Y mirroring
|
//#define FX_MODE_2DCENTERBARS 161 // obsolete by X & Y mirroring
|
||||||
#define FX_MODE_2DPULSER 162 // non audio
|
#define FX_MODE_2DPULSER 162 // non audio
|
||||||
#define FX_MODE_BLURZ 163
|
#define FX_MODE_BLURZ 163
|
||||||
#define FX_MODE_2DDRIFT 164 // non audio
|
#define FX_MODE_2DDRIFT 164 // non audio
|
||||||
@ -968,7 +968,6 @@ class WS2812FX {
|
|||||||
mode_2DAkemi(void);
|
mode_2DAkemi(void);
|
||||||
#else
|
#else
|
||||||
uint16_t
|
uint16_t
|
||||||
GEQ_base(bool centered_horizontal, bool centered_vertical, bool color_vertical),
|
|
||||||
mode_pixels(void),
|
mode_pixels(void),
|
||||||
mode_pixelwave(void),
|
mode_pixelwave(void),
|
||||||
mode_juggles(void),
|
mode_juggles(void),
|
||||||
@ -991,7 +990,6 @@ class WS2812FX {
|
|||||||
mode_ripplepeak(void),
|
mode_ripplepeak(void),
|
||||||
mode_2Dfirenoise(void),
|
mode_2Dfirenoise(void),
|
||||||
mode_2Dsquaredswirl(void),
|
mode_2Dsquaredswirl(void),
|
||||||
//mode_2Dfire2012(void),
|
|
||||||
mode_2Ddna(void),
|
mode_2Ddna(void),
|
||||||
mode_2Dmatrix(void),
|
mode_2Dmatrix(void),
|
||||||
mode_2Dmetaballs(void),
|
mode_2Dmetaballs(void),
|
||||||
@ -1001,7 +999,6 @@ class WS2812FX {
|
|||||||
mode_gravfreq(void),
|
mode_gravfreq(void),
|
||||||
mode_DJLight(void),
|
mode_DJLight(void),
|
||||||
mode_2DFunkyPlank(void),
|
mode_2DFunkyPlank(void),
|
||||||
mode_2DCenterBars(void),
|
|
||||||
mode_2DPulser(void),
|
mode_2DPulser(void),
|
||||||
mode_blurz(void),
|
mode_blurz(void),
|
||||||
mode_2Dgameoflife(void),
|
mode_2Dgameoflife(void),
|
||||||
@ -1047,8 +1044,9 @@ class WS2812FX {
|
|||||||
_triggered;
|
_triggered;
|
||||||
|
|
||||||
uint8_t _modeCount = MODE_COUNT;
|
uint8_t _modeCount = MODE_COUNT;
|
||||||
|
// TODO: allocate memory using new or malloc()
|
||||||
mode_ptr _mode[MODE_COUNT]; // SRAM footprint: 4 bytes per element
|
mode_ptr _mode[MODE_COUNT]; // SRAM footprint: 4 bytes per element
|
||||||
const char *_modeData[MODE_COUNT];// mode (effect) name and its slider control data array
|
const char *_modeData[MODE_COUNT]; // mode (effect) name and its slider control data array
|
||||||
|
|
||||||
show_callback _callback = nullptr;
|
show_callback _callback = nullptr;
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ void WS2812FX::service() {
|
|||||||
}
|
}
|
||||||
handle_palette();
|
handle_palette();
|
||||||
|
|
||||||
delay = (this->*_mode[SEGMENT.mode])(); //effect function
|
delay = (this->*_mode[SEGMENT.mode])(); // effect function (NOTE: may add SEGMENT and SEGENV to parameters)
|
||||||
if (SEGMENT.mode != FX_MODE_HALLOWEEN_EYES) SEGENV.call++;
|
if (SEGMENT.mode != FX_MODE_HALLOWEEN_EYES) SEGENV.call++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,6 +531,16 @@ button {
|
|||||||
z-index: -2;
|
z-index: -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#info .slider {
|
||||||
|
max-width: 200px;
|
||||||
|
min-width: 145px;
|
||||||
|
float: right;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
#info .sliderwrap {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
#info table, #nodes table {
|
#info table, #nodes table {
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -1377,7 +1387,7 @@ TD .checkmark, TD .radiomark {
|
|||||||
width: 145px;
|
width: 145px;
|
||||||
}
|
}
|
||||||
#info div, #nodes div {
|
#info div, #nodes div {
|
||||||
width: 320px;
|
max-width: 320px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -605,9 +605,23 @@ function parseInfo(i) {
|
|||||||
mh = i.leds.matrix ? i.leds.matrix.h : 0;
|
mh = i.leds.matrix ? i.leds.matrix.h : 0;
|
||||||
isM = mw>0 && mh>0;
|
isM = mw>0 && mh>0;
|
||||||
if (!isM) hideModes("2D ");
|
if (!isM) hideModes("2D ");
|
||||||
|
else gId('buttonSr').classList.add("hide"); // peek does not work in 2D
|
||||||
if (!i.u || !i.u.AudioReactive) { /*hideModes("♪ ");*/ hideModes("♫ "); } // hide /*audio*/ frequency reactive effects
|
if (!i.u || !i.u.AudioReactive) { /*hideModes("♪ ");*/ hideModes("♫ "); } // hide /*audio*/ frequency reactive effects
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//https://stackoverflow.com/questions/2592092/executing-script-elements-inserted-with-innerhtml
|
||||||
|
//var setInnerHTML = function(elm, html) {
|
||||||
|
// elm.innerHTML = html;
|
||||||
|
// Array.from(elm.querySelectorAll("script")).forEach( oldScript => {
|
||||||
|
// const newScript = document.createElement("script");
|
||||||
|
// Array.from(oldScript.attributes)
|
||||||
|
// .forEach( attr => newScript.setAttribute(attr.name, attr.value) );
|
||||||
|
// newScript.appendChild(document.createTextNode(oldScript.innerHTML));
|
||||||
|
// oldScript.parentNode.replaceChild(newScript, oldScript);
|
||||||
|
// });
|
||||||
|
//}
|
||||||
|
//setInnerHTML(obj, html);
|
||||||
|
|
||||||
function populateInfo(i)
|
function populateInfo(i)
|
||||||
{
|
{
|
||||||
var cn="";
|
var cn="";
|
||||||
@ -645,6 +659,11 @@ ${inforow("Filesystem",i.fs.u + "/" + i.fs.t + " kB (" +Math.round(i.fs.u*100/i.
|
|||||||
${inforow("Environment",i.arch + " " + i.core + " (" + i.lwip + ")")}
|
${inforow("Environment",i.arch + " " + i.core + " (" + i.lwip + ")")}
|
||||||
</table>`;
|
</table>`;
|
||||||
gId('kv').innerHTML = cn;
|
gId('kv').innerHTML = cn;
|
||||||
|
// update all sliders in Info
|
||||||
|
for (let sd of (gId('kv').getElementsByClassName('sliderdisplay')||[])) {
|
||||||
|
let s = sd.previousElementSibling;
|
||||||
|
if (s) updateTrail(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function populateSegments(s)
|
function populateSegments(s)
|
||||||
@ -1346,15 +1365,16 @@ function setSliderAndColorControl(idx, applyDef=false)
|
|||||||
else if (i==1) btn.innerHTML = "Bg";
|
else if (i==1) btn.innerHTML = "Bg";
|
||||||
else btn.innerHTML = "Cs";
|
else btn.innerHTML = "Cs";
|
||||||
hide = false;
|
hide = false;
|
||||||
|
if (!cslCnt) selectSlot(i); // select 1st displayed slot
|
||||||
cslCnt++;
|
cslCnt++;
|
||||||
} else if (!controlDefined /*|| paOnOff.length>0*/) { // if no controls then all buttons should be shown for color 1..3
|
} else if (!controlDefined /*|| paOnOff.length>0*/) { // if no controls then all buttons should be shown for color 1..3
|
||||||
btn.style.display = "inline";
|
btn.style.display = "inline";
|
||||||
btn.innerHTML = `${i+1}`;
|
btn.innerHTML = `${i+1}`;
|
||||||
hide = false;
|
hide = false;
|
||||||
|
if (!cslCnt) selectSlot(i); // select 1st displayed slot
|
||||||
cslCnt++;
|
cslCnt++;
|
||||||
} else {
|
} else {
|
||||||
btn.style.display = "none";
|
btn.style.display = "none";
|
||||||
if (i>0 && csel==i) selectSlot(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gId("cslLabel").innerHTML = cslLabel;
|
gId("cslLabel").innerHTML = cslLabel;
|
||||||
|
3547
wled00/html_ui.h
3547
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2206291
|
#define VERSION 2207031
|
||||||
|
|
||||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||||
//#define WLED_USE_MY_CONFIG
|
//#define WLED_USE_MY_CONFIG
|
||||||
|
Loading…
Reference in New Issue
Block a user