Merge branch 'audioreactive-prototype' of https://github.com/blazoncek/WLED into audio-fix
This commit is contained in:
commit
ca891b0e70
@ -197,6 +197,7 @@ void FFTcode(void * parameter)
|
|||||||
|
|
||||||
#if defined(WLED_DEBUG) || defined(SR_DEBUG)
|
#if defined(WLED_DEBUG) || defined(SR_DEBUG)
|
||||||
uint64_t start = esp_timer_get_time();
|
uint64_t start = esp_timer_get_time();
|
||||||
|
bool haveDoneFFT = false; // indicates if second measurement (FFT time) is valid
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// get a fresh batch of samples from I2S
|
// get a fresh batch of samples from I2S
|
||||||
@ -204,9 +205,10 @@ void FFTcode(void * parameter)
|
|||||||
|
|
||||||
#if defined(WLED_DEBUG) || defined(SR_DEBUG)
|
#if defined(WLED_DEBUG) || defined(SR_DEBUG)
|
||||||
if (start < esp_timer_get_time()) { // filter out overflows
|
if (start < esp_timer_get_time()) { // filter out overflows
|
||||||
unsigned long sampleTimeInMillis = (esp_timer_get_time() - start +5ULL) / 10ULL; // "+5" to ensure proper rounding
|
uint64_t sampleTimeInMillis = (esp_timer_get_time() - start +5ULL) / 10ULL; // "+5" to ensure proper rounding
|
||||||
sampleTime = (sampleTimeInMillis*3 + sampleTime*7)/10; // smooth
|
sampleTime = (sampleTimeInMillis*3 + sampleTime*7)/10; // smooth
|
||||||
}
|
}
|
||||||
|
start = esp_timer_get_time(); // start measuring FFT time
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
xLastWakeTime = xTaskGetTickCount(); // update "last unblocked time" for vTaskDelay
|
xLastWakeTime = xTaskGetTickCount(); // update "last unblocked time" for vTaskDelay
|
||||||
@ -221,13 +223,13 @@ void FFTcode(void * parameter)
|
|||||||
if (fabsf((float)vReal[i]) > maxSample) maxSample = fabsf((float)vReal[i]);
|
if (fabsf((float)vReal[i]) > maxSample) maxSample = fabsf((float)vReal[i]);
|
||||||
}
|
}
|
||||||
// release highest sample to volume reactive effects early - not strictly necessary here - could also be done at the end of the function
|
// release highest sample to volume reactive effects early - not strictly necessary here - could also be done at the end of the function
|
||||||
// early release allows the filters (getSample() and agcAvg()) to work with fresh values - we will have matching gain and noise gate values when we want to process the FFT results. micDataReal = maxSample;
|
// early release allows the filters (getSample() and agcAvg()) to work with fresh values - we will have matching gain and noise gate values when we want to process the FFT results.
|
||||||
micDataReal = maxSample;
|
micDataReal = maxSample;
|
||||||
|
|
||||||
#ifdef SR_DEBUG
|
#ifdef SR_DEBUG
|
||||||
if (true) { // this allows measure FFT runtimes, as it disables the "only when needed" optimization
|
if (true) { // this allows measure FFT runtimes, as it disables the "only when needed" optimization
|
||||||
#else
|
#else
|
||||||
if (sampleAvg > 1) { // noise gate open means that FFT results will be used. Don't run FFT if results are not needed.
|
if (sampleAvg > 0.5f) { // noise gate open means that FFT results will be used. Don't run FFT if results are not needed.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// run FFT (takes 3-5ms on ESP32, ~12ms on ESP32-S2)
|
// run FFT (takes 3-5ms on ESP32, ~12ms on ESP32-S2)
|
||||||
@ -255,6 +257,10 @@ void FFTcode(void * parameter)
|
|||||||
#endif
|
#endif
|
||||||
FFT_MajorPeak = constrain(FFT_MajorPeak, 1.0f, 11025.0f); // restrict value to range expected by effects
|
FFT_MajorPeak = constrain(FFT_MajorPeak, 1.0f, 11025.0f); // restrict value to range expected by effects
|
||||||
|
|
||||||
|
#if defined(WLED_DEBUG) || defined(SR_DEBUG)
|
||||||
|
haveDoneFFT = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
} else { // noise gate closed - only clear results as FFT was skipped. MIC samples are still valid when we do this.
|
} else { // noise gate closed - only clear results as FFT was skipped. MIC samples are still valid when we do this.
|
||||||
memset(vReal, 0, sizeof(vReal));
|
memset(vReal, 0, sizeof(vReal));
|
||||||
FFT_MajorPeak = 1;
|
FFT_MajorPeak = 1;
|
||||||
@ -267,7 +273,7 @@ void FFTcode(void * parameter)
|
|||||||
} // for()
|
} // for()
|
||||||
|
|
||||||
// mapping of FFT result bins to frequency channels
|
// mapping of FFT result bins to frequency channels
|
||||||
if (sampleAvg > 1) { // noise gate open
|
if (sampleAvg > 0.5f) { // noise gate open
|
||||||
#if 0
|
#if 0
|
||||||
/* This FFT post processing is a DIY endeavour. What we really need is someone with sound engineering expertise to do a great job here AND most importantly, that the animations look GREAT as a result.
|
/* This FFT post processing is a DIY endeavour. What we really need is someone with sound engineering expertise to do a great job here AND most importantly, that the animations look GREAT as a result.
|
||||||
*
|
*
|
||||||
@ -325,7 +331,7 @@ void FFTcode(void * parameter)
|
|||||||
// post-processing of frequency channels (pink noise adjustment, AGC, smooting, scaling)
|
// post-processing of frequency channels (pink noise adjustment, AGC, smooting, scaling)
|
||||||
for (int i=0; i < NUM_GEQ_CHANNELS; i++) {
|
for (int i=0; i < NUM_GEQ_CHANNELS; i++) {
|
||||||
|
|
||||||
if (sampleAvg > 1) { // noise gate open
|
if (sampleAvg > 0.5f) { // noise gate open
|
||||||
// Adjustment for frequency curves.
|
// Adjustment for frequency curves.
|
||||||
fftCalc[i] *= fftResultPink[i];
|
fftCalc[i] *= fftResultPink[i];
|
||||||
if (FFTScalingMode > 0) fftCalc[i] *= FFT_DOWNSCALE; // adjustment related to FFT windowing function
|
if (FFTScalingMode > 0) fftCalc[i] *= FFT_DOWNSCALE; // adjustment related to FFT windowing function
|
||||||
@ -397,16 +403,19 @@ void FFTcode(void * parameter)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(WLED_DEBUG) || defined(SR_DEBUG)
|
#if defined(WLED_DEBUG) || defined(SR_DEBUG)
|
||||||
if (start < esp_timer_get_time()) { // filter out overflows
|
if (haveDoneFFT && (start < esp_timer_get_time())) { // filter out overflows
|
||||||
unsigned long fftTimeInMillis = ((esp_timer_get_time() - start) +5ULL) / 10ULL; // "+5" to ensure proper rounding
|
uint64_t fftTimeInMillis = ((esp_timer_get_time() - start) +5ULL) / 10ULL; // "+5" to ensure proper rounding
|
||||||
fftTime = (fftTimeInMillis*3 + fftTime*7)/10; // smooth
|
fftTime = (fftTimeInMillis*3 + fftTime*7)/10; // smooth
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// run peak detection
|
// run peak detection
|
||||||
autoResetPeak();
|
autoResetPeak();
|
||||||
detectSamplePeak();
|
detectSamplePeak();
|
||||||
|
|
||||||
vTaskDelayUntil( &xLastWakeTime, xFrequency); // release CPU, and let I2S fill its buffers
|
#if !defined(I2S_GRAB_ADC1_COMPLETELY)
|
||||||
|
if ((audioSource == nullptr) || (audioSource->getType() != AudioSource::Type_I2SAdc)) // the "delay trick" does not help for analog ADC
|
||||||
|
#endif
|
||||||
|
vTaskDelayUntil( &xLastWakeTime, xFrequency); // release CPU, and let I2S fill its buffers
|
||||||
|
|
||||||
} // for(;;)ever
|
} // for(;;)ever
|
||||||
} // FFTcode() task end
|
} // FFTcode() task end
|
||||||
@ -543,6 +552,7 @@ class AudioReactive : public Usermod {
|
|||||||
|
|
||||||
// used to feed "Info" Page
|
// used to feed "Info" Page
|
||||||
unsigned long last_UDPTime = 0; // time of last valid UDP sound sync datapacket
|
unsigned long last_UDPTime = 0; // time of last valid UDP sound sync datapacket
|
||||||
|
int receivedFormat = 0; // last received UDP sound sync format - 0=none, 1=v1 (0.13.x), 2=v2 (0.14.x)
|
||||||
float maxSample5sec = 0.0f; // max sample (after AGC) in last 5 seconds
|
float maxSample5sec = 0.0f; // max sample (after AGC) in last 5 seconds
|
||||||
unsigned long sampleMaxTimer = 0; // last time maxSample5sec was reset
|
unsigned long sampleMaxTimer = 0; // last time maxSample5sec was reset
|
||||||
#define CYCLE_SAMPLEMAX 3500 // time window for merasuring
|
#define CYCLE_SAMPLEMAX 3500 // time window for merasuring
|
||||||
@ -563,21 +573,21 @@ class AudioReactive : public Usermod {
|
|||||||
////////////////////
|
////////////////////
|
||||||
void logAudio()
|
void logAudio()
|
||||||
{
|
{
|
||||||
|
if (disableSoundProcessing && (!udpSyncConnected || ((audioSyncEnabled & 0x02) == 0))) return; // no audio availeable
|
||||||
#ifdef MIC_LOGGER
|
#ifdef MIC_LOGGER
|
||||||
// Debugging functions for audio input and sound processing. Comment out the values you want to see
|
// Debugging functions for audio input and sound processing. Comment out the values you want to see
|
||||||
Serial.print("micReal:"); Serial.print(micDataReal); Serial.print("\t");
|
Serial.print("micReal:"); Serial.print(micDataReal); Serial.print("\t");
|
||||||
//Serial.print("micIn:"); Serial.print(micIn); Serial.print("\t");
|
Serial.print("volumeSmth:"); Serial.print(volumeSmth); Serial.print("\t");
|
||||||
//Serial.print("micLev:"); Serial.print(micLev); Serial.print("\t");
|
//Serial.print("volumeRaw:"); Serial.print(volumeRaw); Serial.print("\t");
|
||||||
//Serial.print("sampleReal:"); Serial.print(sampleReal); Serial.print("\t");
|
//Serial.print("DC_Level:"); Serial.print(micLev); Serial.print("\t");
|
||||||
//Serial.print("sample:"); Serial.print(sample); Serial.print("\t");
|
//Serial.print("sampleAgc:"); Serial.print(sampleAgc); Serial.print("\t");
|
||||||
//Serial.print("sampleAvg:"); Serial.print(sampleAvg); Serial.print("\t");
|
//Serial.print("sampleAvg:"); Serial.print(sampleAvg); Serial.print("\t");
|
||||||
|
//Serial.print("sampleReal:"); Serial.print(sampleReal); Serial.print("\t");
|
||||||
|
//Serial.print("micIn:"); Serial.print(micIn); Serial.print("\t");
|
||||||
|
//Serial.print("sample:"); Serial.print(sample); Serial.print("\t");
|
||||||
//Serial.print("sampleMax:"); Serial.print(sampleMax); Serial.print("\t");
|
//Serial.print("sampleMax:"); Serial.print(sampleMax); Serial.print("\t");
|
||||||
//Serial.print("samplePeak:"); Serial.print((samplePeak!=0) ? 128:0); Serial.print("\t");
|
//Serial.print("samplePeak:"); Serial.print((samplePeak!=0) ? 128:0); Serial.print("\t");
|
||||||
//Serial.print("multAgc:"); Serial.print(multAgc, 4); Serial.print("\t");
|
//Serial.print("multAgc:"); Serial.print(multAgc, 4); Serial.print("\t");
|
||||||
Serial.print("sampleAgc:"); Serial.print(sampleAgc); Serial.print("\t");
|
|
||||||
//Serial.print("volumeRaw:"); Serial.print(volumeRaw); Serial.print("\t");
|
|
||||||
//Serial.print("volumeSmth:"); Serial.print(volumeSmth); Serial.print("\t");
|
|
||||||
|
|
||||||
Serial.println();
|
Serial.println();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -669,7 +679,7 @@ class AudioReactive : public Usermod {
|
|||||||
if (time_now - last_time > 2) {
|
if (time_now - last_time > 2) {
|
||||||
last_time = time_now;
|
last_time = time_now;
|
||||||
|
|
||||||
if((fabs(sampleReal) < 2.0f) || (sampleMax < 1.0f)) {
|
if((fabsf(sampleReal) < 2.0f) || (sampleMax < 1.0f)) {
|
||||||
// MIC signal is "squelched" - deliver silence
|
// MIC signal is "squelched" - deliver silence
|
||||||
tmpAgc = 0;
|
tmpAgc = 0;
|
||||||
// we need to "spin down" the intgrated error buffer
|
// we need to "spin down" the intgrated error buffer
|
||||||
@ -727,6 +737,7 @@ class AudioReactive : public Usermod {
|
|||||||
else
|
else
|
||||||
sampleAgc += agcSampleSmooth[AGC_preset] * (tmpAgc - sampleAgc); // smooth path
|
sampleAgc += agcSampleSmooth[AGC_preset] * (tmpAgc - sampleAgc); // smooth path
|
||||||
|
|
||||||
|
sampleAgc = fabsf(sampleAgc); // // make sure we have a positive value
|
||||||
last_soundAgc = soundAgc;
|
last_soundAgc = soundAgc;
|
||||||
} // agcAvg()
|
} // agcAvg()
|
||||||
|
|
||||||
@ -764,12 +775,13 @@ class AudioReactive : public Usermod {
|
|||||||
|
|
||||||
micIn -= micLev; // Let's center it to 0 now
|
micIn -= micLev; // Let's center it to 0 now
|
||||||
// Using an exponential filter to smooth out the signal. We'll add controls for this in a future release.
|
// Using an exponential filter to smooth out the signal. We'll add controls for this in a future release.
|
||||||
float micInNoDC = fabs(micDataReal - micLev);
|
float micInNoDC = fabsf(micDataReal - micLev);
|
||||||
expAdjF = (weighting * micInNoDC + (1.0-weighting) * expAdjF);
|
expAdjF = (weighting * micInNoDC + (1.0-weighting) * expAdjF);
|
||||||
|
expAdjF = fabsf(expAdjF); // Now (!) take the absolute value
|
||||||
|
|
||||||
expAdjF = (expAdjF <= soundSquelch) ? 0: expAdjF; // simple noise gate
|
expAdjF = (expAdjF <= soundSquelch) ? 0: expAdjF; // simple noise gate
|
||||||
if ((soundSquelch == 0) && (expAdjF < 0.25f)) expAdjF = 0; // do something meaningfull when "squelch = 0"
|
if ((soundSquelch == 0) && (expAdjF < 0.25f)) expAdjF = 0; // do something meaningfull when "squelch = 0"
|
||||||
|
|
||||||
expAdjF = fabsf(expAdjF); // Now (!) take the absolute value
|
|
||||||
tmpSample = expAdjF;
|
tmpSample = expAdjF;
|
||||||
micIn = abs(micIn); // And get the absolute value of each sample
|
micIn = abs(micIn); // And get the absolute value of each sample
|
||||||
|
|
||||||
@ -791,6 +803,7 @@ class AudioReactive : public Usermod {
|
|||||||
if (sampleMax < 0.5f) sampleMax = 0.0f;
|
if (sampleMax < 0.5f) sampleMax = 0.0f;
|
||||||
|
|
||||||
sampleAvg = ((sampleAvg * 15.0f) + sampleAdj) / 16.0f; // Smooth it out over the last 16 samples.
|
sampleAvg = ((sampleAvg * 15.0f) + sampleAdj) / 16.0f; // Smooth it out over the last 16 samples.
|
||||||
|
sampleAvg = fabsf(sampleAvg); // make sure we have a positive value
|
||||||
} // getSample()
|
} // getSample()
|
||||||
|
|
||||||
|
|
||||||
@ -875,11 +888,67 @@ class AudioReactive : public Usermod {
|
|||||||
static bool isValidUdpSyncVersion(const char *header) {
|
static bool isValidUdpSyncVersion(const char *header) {
|
||||||
return strncmp_P(header, PSTR(UDP_SYNC_HEADER), 6) == 0;
|
return strncmp_P(header, PSTR(UDP_SYNC_HEADER), 6) == 0;
|
||||||
}
|
}
|
||||||
|
static bool isValidUdpSyncVersion_v1(const char *header) {
|
||||||
|
return strncmp_P(header, PSTR(UDP_SYNC_HEADER_v1), 6) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void decodeAudioData(int packetSize, uint8_t *fftBuff) {
|
||||||
|
audioSyncPacket *receivedPacket = reinterpret_cast<audioSyncPacket*>(fftBuff);
|
||||||
|
// update samples for effects
|
||||||
|
volumeSmth = fmaxf(receivedPacket->sampleSmth, 0.0f);
|
||||||
|
volumeRaw = fmaxf(receivedPacket->sampleRaw, 0.0f);
|
||||||
|
// update internal samples
|
||||||
|
sampleRaw = volumeRaw;
|
||||||
|
sampleAvg = volumeSmth;
|
||||||
|
rawSampleAgc = volumeRaw;
|
||||||
|
sampleAgc = volumeSmth;
|
||||||
|
multAgc = 1.0f;
|
||||||
|
// Only change samplePeak IF it's currently false.
|
||||||
|
// If it's true already, then the animation still needs to respond.
|
||||||
|
autoResetPeak();
|
||||||
|
if (!samplePeak) {
|
||||||
|
samplePeak = receivedPacket->samplePeak >0 ? true:false;
|
||||||
|
if (samplePeak) timeOfPeak = millis();
|
||||||
|
//userVar1 = samplePeak;
|
||||||
|
}
|
||||||
|
//These values are only available on the ESP32
|
||||||
|
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;
|
||||||
|
FFT_MajorPeak = constrain(receivedPacket->FFT_MajorPeak, 1.0f, 11025.0f); // restrict value to range expected by effects
|
||||||
|
}
|
||||||
|
|
||||||
|
void decodeAudioData_v1(int packetSize, uint8_t *fftBuff) {
|
||||||
|
audioSyncPacket_v1 *receivedPacket = reinterpret_cast<audioSyncPacket_v1*>(fftBuff);
|
||||||
|
// update samples for effects
|
||||||
|
volumeSmth = fmaxf(receivedPacket->sampleAgc, 0.0f);
|
||||||
|
volumeRaw = volumeSmth; // V1 format does not have "raw" AGC sample
|
||||||
|
// update internal samples
|
||||||
|
sampleRaw = fmaxf(receivedPacket->sampleRaw, 0.0f);
|
||||||
|
sampleAvg = fmaxf(receivedPacket->sampleAvg, 0.0f);;
|
||||||
|
sampleAgc = volumeSmth;
|
||||||
|
rawSampleAgc = volumeRaw;
|
||||||
|
multAgc = 1.0f;
|
||||||
|
// Only change samplePeak IF it's currently false.
|
||||||
|
// If it's true already, then the animation still needs to respond.
|
||||||
|
autoResetPeak();
|
||||||
|
if (!samplePeak) {
|
||||||
|
samplePeak = receivedPacket->samplePeak >0 ? true:false;
|
||||||
|
if (samplePeak) timeOfPeak = millis();
|
||||||
|
//userVar1 = samplePeak;
|
||||||
|
}
|
||||||
|
//These values are only available on the ESP32
|
||||||
|
for (int i = 0; i < NUM_GEQ_CHANNELS; i++) fftResult[i] = receivedPacket->fftResult[i];
|
||||||
|
my_magnitude = fmaxf(receivedPacket->FFT_Magnitude, 0.0);
|
||||||
|
FFT_Magnitude = my_magnitude;
|
||||||
|
FFT_MajorPeak = constrain(receivedPacket->FFT_MajorPeak, 1.0, 11025.0); // restrict value to range expected by effects
|
||||||
|
}
|
||||||
|
|
||||||
bool receiveAudioData() // check & process new data. return TRUE in case that new audio data was received.
|
bool receiveAudioData() // check & process new data. return TRUE in case that new audio data was received.
|
||||||
{
|
{
|
||||||
if (!udpSyncConnected) return false;
|
if (!udpSyncConnected) return false;
|
||||||
bool haveFreshData = false;
|
bool haveFreshData = false;
|
||||||
|
|
||||||
size_t packetSize = fftUdp.parsePacket();
|
size_t packetSize = fftUdp.parsePacket();
|
||||||
if (packetSize > 5) {
|
if (packetSize > 5) {
|
||||||
//DEBUGSR_PRINTLN("Received UDP Sync Packet");
|
//DEBUGSR_PRINTLN("Received UDP Sync Packet");
|
||||||
@ -888,37 +957,17 @@ class AudioReactive : public Usermod {
|
|||||||
|
|
||||||
// VERIFY THAT THIS IS A COMPATIBLE PACKET
|
// VERIFY THAT THIS IS A COMPATIBLE PACKET
|
||||||
if (packetSize == sizeof(audioSyncPacket) && (isValidUdpSyncVersion((const char *)fftBuff))) {
|
if (packetSize == sizeof(audioSyncPacket) && (isValidUdpSyncVersion((const char *)fftBuff))) {
|
||||||
audioSyncPacket *receivedPacket = reinterpret_cast<audioSyncPacket*>(fftBuff);
|
decodeAudioData(packetSize, fftBuff);
|
||||||
|
//DEBUGSR_PRINTLN("Finished parsing UDP Sync Packet v2");
|
||||||
// update samples for effects
|
|
||||||
volumeSmth = fmaxf(receivedPacket->sampleSmth, 0.0f);
|
|
||||||
volumeRaw = fmaxf(receivedPacket->sampleRaw, 0.0f);
|
|
||||||
|
|
||||||
// update internal samples
|
|
||||||
sampleRaw = volumeRaw;
|
|
||||||
sampleAvg = volumeSmth;
|
|
||||||
rawSampleAgc = volumeRaw;
|
|
||||||
sampleAgc = volumeSmth;
|
|
||||||
multAgc = 1.0f;
|
|
||||||
|
|
||||||
autoResetPeak();
|
|
||||||
// Only change samplePeak IF it's currently false.
|
|
||||||
// If it's true already, then the animation still needs to respond.
|
|
||||||
if (!samplePeak) {
|
|
||||||
samplePeak = receivedPacket->samplePeak >0 ? true:false;
|
|
||||||
if (samplePeak) timeOfPeak = millis();
|
|
||||||
//userVar1 = samplePeak;
|
|
||||||
}
|
|
||||||
|
|
||||||
//These values are only available on the ESP32
|
|
||||||
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;
|
|
||||||
FFT_MajorPeak = constrain(receivedPacket->FFT_MajorPeak, 1.0f, 11025.0f); // restrict value to range expected by effects
|
|
||||||
|
|
||||||
//DEBUGSR_PRINTLN("Finished parsing UDP Sync Packet");
|
|
||||||
haveFreshData = true;
|
haveFreshData = true;
|
||||||
|
receivedFormat = 2;
|
||||||
|
} else {
|
||||||
|
if (packetSize == sizeof(audioSyncPacket_v1) && (isValidUdpSyncVersion_v1((const char *)fftBuff))) {
|
||||||
|
decodeAudioData_v1(packetSize, fftBuff);
|
||||||
|
//DEBUGSR_PRINTLN("Finished parsing UDP Sync Packet v1");
|
||||||
|
haveFreshData = true;
|
||||||
|
receivedFormat = 1;
|
||||||
|
} else receivedFormat = 0; // unknown format
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return haveFreshData;
|
return haveFreshData;
|
||||||
@ -1170,9 +1219,11 @@ class AudioReactive : public Usermod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(MIC_LOGGER) || defined(MIC_SAMPLING_LOG) || defined(FFT_SAMPLING_LOG)
|
#if defined(MIC_LOGGER) || defined(MIC_SAMPLING_LOG) || defined(FFT_SAMPLING_LOG)
|
||||||
EVERY_N_MILLIS(20) {
|
static unsigned long lastMicLoggerTime = 0;
|
||||||
logAudio();
|
if (millis()-lastMicLoggerTime > 20) {
|
||||||
}
|
lastMicLoggerTime = millis();
|
||||||
|
logAudio();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Info Page: keep max sample from last 5 seconds
|
// Info Page: keep max sample from last 5 seconds
|
||||||
@ -1381,22 +1432,34 @@ class AudioReactive : public Usermod {
|
|||||||
if (audioSyncEnabled) {
|
if (audioSyncEnabled) {
|
||||||
if (audioSyncEnabled & 0x01) {
|
if (audioSyncEnabled & 0x01) {
|
||||||
infoArr.add(F("send mode"));
|
infoArr.add(F("send mode"));
|
||||||
|
if ((udpSyncConnected) && (millis() - lastTime < 2500)) infoArr.add(F(" v2"));
|
||||||
} else if (audioSyncEnabled & 0x02) {
|
} else if (audioSyncEnabled & 0x02) {
|
||||||
infoArr.add(F("receive mode"));
|
infoArr.add(F("receive mode"));
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
infoArr.add("off");
|
infoArr.add("off");
|
||||||
if (audioSyncEnabled && !udpSyncConnected) infoArr.add(" <i>(unconnected)</i>");
|
if (audioSyncEnabled && !udpSyncConnected) infoArr.add(" <i>(unconnected)</i>");
|
||||||
|
if (audioSyncEnabled && udpSyncConnected && (millis() - last_UDPTime < 2500)) {
|
||||||
|
if (receivedFormat == 1) infoArr.add(F(" v1"));
|
||||||
|
if (receivedFormat == 2) infoArr.add(F(" v2"));
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(WLED_DEBUG) || defined(SR_DEBUG)
|
#if defined(WLED_DEBUG) || defined(SR_DEBUG)
|
||||||
infoArr = user.createNestedArray(F("Sampling time"));
|
infoArr = user.createNestedArray(F("Sampling time"));
|
||||||
infoArr.add(float(sampleTime)/100.0f);
|
infoArr.add(float(sampleTime)/100.0f);
|
||||||
infoArr.add(" ms");
|
infoArr.add(" ms");
|
||||||
|
|
||||||
infoArr = user.createNestedArray(F("FFT time"));
|
infoArr = user.createNestedArray(F("FFT time"));
|
||||||
infoArr.add(float(fftTime-sampleTime)/100.0f);
|
infoArr.add(float(fftTime)/100.0f);
|
||||||
infoArr.add(" ms");
|
if ((fftTime/100) >= FFT_MIN_CYCLE) // FFT time over budget -> I2S buffer will overflow
|
||||||
|
infoArr.add("<b style=\"color:red;\">! ms</b>");
|
||||||
|
else if ((fftTime/80 + sampleTime/80) >= FFT_MIN_CYCLE) // FFT time >75% of budget -> risk of instability
|
||||||
|
infoArr.add("<b style=\"color:orange;\"> ms!</b>");
|
||||||
|
else
|
||||||
|
infoArr.add(" ms");
|
||||||
|
|
||||||
DEBUGSR_PRINTF("AR Sampling time: %5.2f ms\n", float(sampleTime)/100.0f);
|
DEBUGSR_PRINTF("AR Sampling time: %5.2f ms\n", float(sampleTime)/100.0f);
|
||||||
DEBUGSR_PRINTF("AR FFT time : %5.2f ms\n", float(fftTime-sampleTime)/100.0f);
|
DEBUGSR_PRINTF("AR FFT time : %5.2f ms\n", float(fftTime)/100.0f);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,9 +204,11 @@ void WLED::loop()
|
|||||||
DEBUG_PRINT(F("State time: ")); DEBUG_PRINTLN(wifiStateChangedTime);
|
DEBUG_PRINT(F("State time: ")); DEBUG_PRINTLN(wifiStateChangedTime);
|
||||||
DEBUG_PRINT(F("NTP last sync: ")); DEBUG_PRINTLN(ntpLastSyncTime);
|
DEBUG_PRINT(F("NTP last sync: ")); DEBUG_PRINTLN(ntpLastSyncTime);
|
||||||
DEBUG_PRINT(F("Client IP: ")); DEBUG_PRINTLN(Network.localIP());
|
DEBUG_PRINT(F("Client IP: ")); DEBUG_PRINTLN(Network.localIP());
|
||||||
DEBUG_PRINT(F("Loops/sec: ")); DEBUG_PRINTLN(loops / 30);
|
if (loops > 0) { // avoid division by zero
|
||||||
DEBUG_PRINT(F("UM time[ms]: ")); DEBUG_PRINT(avgUsermodMillis/loops); DEBUG_PRINT("/");DEBUG_PRINTLN(maxUsermodMillis);
|
DEBUG_PRINT(F("Loops/sec: ")); DEBUG_PRINTLN(loops / 30);
|
||||||
DEBUG_PRINT(F("Strip time[ms]: ")); DEBUG_PRINT(avgStripMillis/loops); DEBUG_PRINT("/"); DEBUG_PRINTLN(maxStripMillis);
|
DEBUG_PRINT(F("UM time[ms]: ")); DEBUG_PRINT(avgUsermodMillis/loops); DEBUG_PRINT("/");DEBUG_PRINTLN(maxUsermodMillis);
|
||||||
|
DEBUG_PRINT(F("Strip time[ms]: ")); DEBUG_PRINT(avgStripMillis/loops); DEBUG_PRINT("/"); DEBUG_PRINTLN(maxStripMillis);
|
||||||
|
}
|
||||||
strip.printSize();
|
strip.printSize();
|
||||||
loops = 0;
|
loops = 0;
|
||||||
maxUsermodMillis = 0;
|
maxUsermodMillis = 0;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2210200
|
#define VERSION 2210220
|
||||||
|
|
||||||
//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