code cleanup, few optimizations, and fixing more overflows
- code cleanup in audio_reactive.h - fixing some more under/overflows in fx.cpp
This commit is contained in:
parent
450a0180f8
commit
d053bc562f
@ -23,11 +23,9 @@
|
||||
// Comment/Uncomment to toggle usb serial debugging
|
||||
// #define MIC_LOGGER // MIC sampling & sound input debugging (serial plotter)
|
||||
// #define FFT_SAMPLING_LOG // FFT result debugging
|
||||
// #define SR_DEBUG // generic SR DEBUG messages (including MIC_LOGGER)
|
||||
// #define SR_DEBUG // generic SR DEBUG messages
|
||||
// #define NO_MIC_LOGGER // exclude MIC_LOGGER from SR_DEBUG
|
||||
|
||||
// hackers corner
|
||||
|
||||
#ifdef SR_DEBUG
|
||||
#define DEBUGSR_PRINT(x) Serial.print(x)
|
||||
#define DEBUGSR_PRINTLN(x) Serial.println(x)
|
||||
@ -37,10 +35,6 @@
|
||||
#define DEBUGSR_PRINTLN(x)
|
||||
#define DEBUGSR_PRINTF(x...)
|
||||
#endif
|
||||
// legacy support
|
||||
// #if defined(SR_DEBUG) && !defined(MIC_LOGGER) && !defined(NO_MIC_LOGGER)
|
||||
// #define MIC_LOGGER
|
||||
// #endif
|
||||
|
||||
|
||||
#include "audio_source.h"
|
||||
@ -49,10 +43,11 @@ constexpr i2s_port_t I2S_PORT = I2S_NUM_0;
|
||||
constexpr int BLOCK_SIZE = 128;
|
||||
constexpr int SAMPLE_RATE = 22050; // Base sample rate in Hz - 22Khz is a standard rate. Physical sample time -> 23ms
|
||||
//constexpr int SAMPLE_RATE = 20480; // Base sample rate in Hz - 20Khz is experimental. Physical sample time -> 25ms
|
||||
//constexpr int SAMPLE_RATE = 10240; // Base sample rate in Hz - standard. Physical sample time -> 50ms
|
||||
//constexpr int SAMPLE_RATE = 10240; // Base sample rate in Hz - previous default. Physical sample time -> 50ms
|
||||
|
||||
//#define FFT_MIN_CYCLE 22 // minimum time before FFT task is repeated. Use with 20Khz sampling
|
||||
#define FFT_MIN_CYCLE 18 // minimum time before FFT task is repeated. Use with 22Khz sampling
|
||||
//#define FFT_MIN_CYCLE 22 // minimum time before FFT task is repeated. Use with 20Khz sampling
|
||||
//#define FFT_MIN_CYCLE 44 // minimum time before FFT task is repeated. Use with 10Khz sampling
|
||||
|
||||
// globals
|
||||
static uint8_t inputLevel = 128; // UI slider value
|
||||
@ -204,26 +199,19 @@ void FFTcode(void * parameter)
|
||||
}
|
||||
#endif
|
||||
|
||||
const int halfSamplesFFT = samplesFFT / 2; // samplesFFT divided by 2
|
||||
float maxSample1 = 0.0f; // max sample from first half of FFT batch
|
||||
float maxSample2 = 0.0f; // max sample from second half of FFT batch
|
||||
for (int i=0; i < halfSamplesFFT; i++) {
|
||||
//const int halfSamplesFFT = samplesFFT / 2; // samplesFFT divided by 2
|
||||
float maxSample = 0.0f; // max sample from FFT batch
|
||||
for (int i=0; i < samplesFFT; i++) {
|
||||
// set imaginary parts to 0
|
||||
vImag[i] = 0;
|
||||
// pick our our current mic sample - we take the max value from all samples that go into FFT
|
||||
if ((vReal[i] <= (INT16_MAX - 1024)) && (vReal[i] >= (INT16_MIN + 1024))) //skip extreme values - normally these are artefacts
|
||||
if (fabsf((float)vReal[i]) > maxSample1) maxSample1 = fabsf((float)vReal[i]);
|
||||
if (fabsf((float)vReal[i]) > maxSample) maxSample = fabsf((float)vReal[i]);
|
||||
}
|
||||
for (int i=halfSamplesFFT; i < samplesFFT; i++) {
|
||||
// set imaginary parts to 0
|
||||
vImag[i] = 0;
|
||||
// pick our our current mic sample - we take the max value from all samples that go into FFT
|
||||
if ((vReal[i] <= (INT16_MAX - 1024)) && (vReal[i] >= (INT16_MIN + 1024))) //skip extreme values - normally these are artefacts
|
||||
if (fabsf((float)vReal[i]) > maxSample2) maxSample2 = fabsf((float)vReal[i]);
|
||||
}
|
||||
// release first sample to volume reactive effects
|
||||
micDataReal = maxSample1;
|
||||
// release sample to volume reactive effects
|
||||
micDataReal = maxSample; // doing this early allows filters (getSample() and agcAvg()) to run on latest values - we'll have up-to-date gain and noise gate values when FFT is done
|
||||
|
||||
// run FFT
|
||||
#ifdef UM_AUDIOREACTIVE_USE_NEW_FFT
|
||||
FFT.dcRemoval(); // remove DC offset
|
||||
FFT.windowing( FFTWindow::Flat_top, FFTDirection::Forward); // Weigh data using "Flat Top" function - better amplitude accuracy
|
||||
@ -246,11 +234,11 @@ void FFTcode(void * parameter)
|
||||
//
|
||||
|
||||
#ifdef UM_AUDIOREACTIVE_USE_NEW_FFT
|
||||
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
|
||||
#else
|
||||
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
|
||||
#endif
|
||||
FFT_MajorPeak = constrain(FFT_MajorPeak, 1.0f, 10240.0f);
|
||||
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.
|
||||
float t = fabsf(vReal[i]); // just to be sure - values in fft bins should be positive any way
|
||||
@ -258,18 +246,17 @@ void FFTcode(void * parameter)
|
||||
} // for()
|
||||
|
||||
|
||||
/* 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.
|
||||
*
|
||||
*
|
||||
* Andrew's updated mapping of 256 bins down to the 16 result bins with Sample Freq = 10240, samplesFFT = 512 and some overlap.
|
||||
* Based on testing, the lowest/Start frequency is 60 Hz (with bin 3) and a highest/End frequency of 5120 Hz in bin 255.
|
||||
* Now, Take the 60Hz and multiply by 1.320367784 to get the next frequency and so on until the end. Then detetermine the bins.
|
||||
* End frequency = Start frequency * multiplier ^ 16
|
||||
* Multiplier = (End frequency/ Start frequency) ^ 1/16
|
||||
* Multiplier = 1.320367784
|
||||
*/
|
||||
if (sampleAvg > 1) { // noise gate open
|
||||
#if 0 // Range
|
||||
#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.
|
||||
*
|
||||
* Andrew's updated mapping of 256 bins down to the 16 result bins with Sample Freq = 10240, samplesFFT = 512 and some overlap.
|
||||
* Based on testing, the lowest/Start frequency is 60 Hz (with bin 3) and a highest/End frequency of 5120 Hz in bin 255.
|
||||
* Now, Take the 60Hz and multiply by 1.320367784 to get the next frequency and so on until the end. Then detetermine the bins.
|
||||
* End frequency = Start frequency * multiplier ^ 16
|
||||
* Multiplier = (End frequency/ Start frequency) ^ 1/16
|
||||
* Multiplier = 1.320367784
|
||||
*/ // Range
|
||||
fftCalc[ 0] = fftAddAvg(2,4); // 60 - 100
|
||||
fftCalc[ 1] = fftAddAvg(4,5); // 80 - 120
|
||||
fftCalc[ 2] = fftAddAvg(5,7); // 100 - 160
|
||||
@ -287,7 +274,8 @@ void FFTcode(void * parameter)
|
||||
fftCalc[14] = fftAddAvg(147,194); // 2940 - 3900
|
||||
fftCalc[15] = fftAddAvg(194,250); // 3880 - 5000 // avoid the last 5 bins, which are usually inaccurate
|
||||
#else
|
||||
// optimized for 22050 Hz by softhack007 bins frequency range
|
||||
/* new mapping, optimized for 22050 Hz by softhack007 */
|
||||
// bins frequency range
|
||||
fftCalc[ 0] = fftAddAvg(1,2); // 1 43 - 86 sub-bass
|
||||
fftCalc[ 1] = fftAddAvg(2,3); // 1 86 - 129 bass
|
||||
fftCalc[ 2] = fftAddAvg(3,5); // 2 129 - 216 bass
|
||||
@ -397,10 +385,6 @@ void FFTcode(void * parameter)
|
||||
}
|
||||
#endif
|
||||
|
||||
// release second sample to volume reactive effects.
|
||||
// Releasing a second sample now effectively doubles the "sample rate"
|
||||
micDataReal = maxSample2; // do we really need this? FFT now takes only about 2ms so no need for this
|
||||
|
||||
} // for(;;)
|
||||
} // FFTcode()
|
||||
|
||||
@ -816,9 +800,6 @@ class AudioReactive : public Usermod {
|
||||
|
||||
audioSyncPacket transmitData;
|
||||
strncpy_P(transmitData.header, PSTR(UDP_SYNC_HEADER), 6);
|
||||
|
||||
//transmitData.sampleRaw = volumeRaw;
|
||||
//transmitData.sampleSmth = volumeSmth;
|
||||
// transmit samples that were not modified by limitSampleDynamics()
|
||||
transmitData.sampleRaw = (soundAgc) ? rawSampleAgc: sampleRaw;
|
||||
transmitData.sampleSmth = (soundAgc) ? sampleAgc : sampleAvg;
|
||||
@ -848,7 +829,6 @@ class AudioReactive : public Usermod {
|
||||
bool receiveAudioData() // check & process new data. return TRUE in case that new audio data was received.
|
||||
{
|
||||
if (!udpSyncConnected) return false;
|
||||
//DEBUGSR_PRINTLN("Checking for UDP Microphone Packet");
|
||||
bool haveFreshData = false;
|
||||
size_t packetSize = fftUdp.parsePacket();
|
||||
if (packetSize > 5) {
|
||||
@ -891,7 +871,7 @@ class AudioReactive : public Usermod {
|
||||
|
||||
my_magnitude = fmaxf(receivedPacket->FFT_Magnitude, 0.0f);
|
||||
FFT_Magnitude = my_magnitude;
|
||||
FFT_MajorPeak = constrain(receivedPacket->FFT_MajorPeak, 1.0f, 11050.0f); // restrict value to range expected by effects
|
||||
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;
|
||||
@ -1101,51 +1081,6 @@ class AudioReactive : public Usermod {
|
||||
if (volumeSmth < 1 ) my_magnitude = 0.001f; // noise gate closed - mute
|
||||
|
||||
limitSampleDynamics(); // optional - makes volumeSmth very smooth and fluent
|
||||
|
||||
#if 0
|
||||
/* currently this is _not_ working. Code relies on "musical note" symbol as second char of the effect name */
|
||||
#error I told you its not working right now
|
||||
// update WebServer UI
|
||||
uint8_t knownMode = strip.getFirstSelectedSeg().mode; // 1st selected segment is more appropriate than main segment
|
||||
if (lastMode != knownMode) { // only execute if mode changes
|
||||
char lineBuffer[4];
|
||||
extractModeName(knownMode, JSON_mode_names, lineBuffer, 3); // use of JSON_mode_names is deprecated, use nullptr
|
||||
agcEffect = (lineBuffer[1] == 226 && lineBuffer[2] == 153); // && (lineBuffer[3] == 170 || lineBuffer[3] == 171 ) encoding of ♪ or ♫
|
||||
// agcEffect = (lineBuffer[4] == 240 && lineBuffer[5] == 159 && lineBuffer[6] == 142 && lineBuffer[7] == 154 ); //encoding of 🎚 No clue why as not found here https://www.iemoji.com/view/emoji/918/objects/level-slider
|
||||
lastMode = knownMode;
|
||||
}
|
||||
|
||||
// update inputLevel Slider based on current AGC gain
|
||||
if ((soundAgc>0) && agcEffect) {
|
||||
unsigned long now_time = millis();
|
||||
|
||||
// "user kick" feature - if user has moved the slider by at least 32 units, we "kick" AGC gain by 30% (up or down)
|
||||
// only once in 3.5 seconds
|
||||
if ( (lastMode == knownMode)
|
||||
&& (abs(last_user_inputLevel - inputLevel) > 31)
|
||||
&& (now_time - last_kick_time > 3500)) {
|
||||
if (last_user_inputLevel > inputLevel) multAgc *= 0.60; // down -> reduce gain
|
||||
if (last_user_inputLevel < inputLevel) multAgc *= 1.50; // up -> increase gain
|
||||
last_kick_time = now_time;
|
||||
}
|
||||
|
||||
int new_user_inputLevel = 128.0f * multAgc; // scale AGC multiplier so that "1" is at 128
|
||||
if (multAgc > 1.0f) new_user_inputLevel = 128.0f * (((multAgc - 1.0f) / 4.0f) +1.0f); // compress range so we can show values up to 4
|
||||
new_user_inputLevel = MIN(MAX(new_user_inputLevel, 0),255);
|
||||
|
||||
// update user interfaces - restrict frequency to avoid flooding UI's with small changes
|
||||
if (( ((now_time - last_update_time > 3500) && (abs(new_user_inputLevel - inputLevel) > 2)) // small change - every 3.5 sec (max)
|
||||
||((now_time - last_update_time > 2200) && (abs(new_user_inputLevel - inputLevel) > 15)) // medium change
|
||||
||((now_time - last_update_time > 1200) && (abs(new_user_inputLevel - inputLevel) > 31))) // BIG change - every second
|
||||
&& !strip.isUpdating()) // don't interfere while strip is updating
|
||||
{
|
||||
inputLevel = new_user_inputLevel; // change of least 3 units -> update user variable
|
||||
updateInterfaces(CALL_MODE_WS_SEND); // is this the correct way to notify UIs ? Yes says blazoncek
|
||||
last_update_time = now_time;
|
||||
last_user_inputLevel = new_user_inputLevel;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -5958,14 +5958,20 @@ static const char _data_FX_MODE_2DDRIFTROSE[] PROGMEM = "Drift Rose@Fade,Blur;;;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// a few constants needed for AudioReactive effects
|
||||
|
||||
// for 22Khz sampling
|
||||
#define MAX_FREQUENCY 11025 // sample frequency / 2 (as per Nyquist criterion)
|
||||
#define MAX_FREQUENCY 11025 // sample frequency / 2 (as per Nyquist criterion)
|
||||
#define MAX_FREQ_LOG10 4.04238f // log10(MAX_FREQUENCY)
|
||||
|
||||
// for 20Khz sampling
|
||||
//#define MAX_FREQUENCY 10240 // sample frequency / 2 (as per Nyquist criterion)
|
||||
//#define MAX_FREQ_LOG10 4.0103f // log10(MAX_FREQUENCY)
|
||||
//#define MAX_FREQUENCY 10240
|
||||
//#define MAX_FREQ_LOG10 4.0103f
|
||||
|
||||
// for 10Khz sampling
|
||||
//#define MAX_FREQUENCY 5120
|
||||
//#define MAX_FREQ_LOG10 3.71f
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
@ -6719,7 +6725,7 @@ static const char _data_FX_MODE_DJLIGHT[] PROGMEM = "DJ Light@Speed;;;mp12=2,ssi
|
||||
////////////////////
|
||||
uint16_t mode_freqmap(void) { // Map FFT_MajorPeak to SEGLEN. Would be better if a higher framerate.
|
||||
// Start frequency = 60 Hz and log10(60) = 1.78
|
||||
// End frequency = 5120 Hz and lo10(5120) = 3.71
|
||||
// End frequency = MAX_FREQUENCY in Hz and lo10(MAX_FREQUENCY) = MAX_FREQ_LOG10
|
||||
|
||||
um_data_t *um_data;
|
||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||
@ -6732,13 +6738,13 @@ uint16_t mode_freqmap(void) { // Map FFT_MajorPeak to SEGLEN.
|
||||
|
||||
SEGMENT.fade_out(SEGMENT.speed);
|
||||
|
||||
// int locn = (log10f((float)FFT_MajorPeak) - 1.78f) * (float)SEGLEN/(3.71f-1.78f); // log10 frequency range is from 1.78 to 3.71. Let's scale to SEGLEN.
|
||||
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
|
||||
|
||||
if (locn >=SEGLEN) locn = SEGLEN-1;
|
||||
//uint16_t pixCol = (log10f(FFT_MajorPeak) - 1.78f) * 255.0f/(3.71f-1.78f); // Scale log10 of frequency values to the 255 colour index.
|
||||
uint16_t pixCol = (log10f(FFT_MajorPeak) - 1.78f) * 255.0f/(MAX_FREQ_LOG10 - 1.78f); // Scale log10 of frequency values to the 255 colour index.
|
||||
if (FFT_MajorPeak < 61.0f) pixCol = 0; // handle underflow
|
||||
|
||||
uint16_t bright = (int)my_magnitude;
|
||||
|
||||
SEGMENT.setPixelColor(locn, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(SEGMENT.intensity+pixCol, false, PALETTE_SOLID_WRAP, 0), bright));
|
||||
@ -6777,7 +6783,6 @@ uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Plesch
|
||||
|
||||
CRGB color = CRGB::Black;
|
||||
|
||||
//if (FFT_MajorPeak > 5120) FFT_MajorPeak = 0;
|
||||
if (FFT_MajorPeak > MAX_FREQUENCY) FFT_MajorPeak = 1;
|
||||
// MajorPeak holds the freq. value which is most abundant in the last sample.
|
||||
// With our sampling rate of 10240Hz we have a usable freq range from roughtly 80Hz to 10240/2 Hz
|
||||
@ -6788,7 +6793,7 @@ uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Plesch
|
||||
} else {
|
||||
int upperLimit = 80 + 42 * SEGMENT.custom2;
|
||||
int lowerLimit = 80 + 3 * SEGMENT.custom1;
|
||||
int i = lowerLimit!=upperLimit ? map(FFT_MajorPeak, lowerLimit, upperLimit, 0, 255) : FFT_MajorPeak;
|
||||
uint8_t i = lowerLimit!=upperLimit ? map(FFT_MajorPeak, lowerLimit, upperLimit, 0, 255) : FFT_MajorPeak; // may under/overflow - so we enforce uint8_t
|
||||
uint16_t b = 255 * intensity;
|
||||
if (b > 255) b = 255;
|
||||
color = CHSV(i, 240, (uint8_t)b); // implicit conversion to RGB supplied by FastLED
|
||||
@ -6826,8 +6831,8 @@ uint16_t mode_freqpixels(void) { // Freqpixel. By Andrew Tuline.
|
||||
|
||||
for (int i=0; i < SEGMENT.intensity/32+1; i++) {
|
||||
uint16_t locn = random16(0,SEGLEN);
|
||||
//uint8_t pixCol = (log10f(FFT_MajorPeak) - 1.78) * 255.0/(3.71-1.78); // Scale log10 of frequency values to the 255 colour index.
|
||||
uint8_t pixCol = (log10f(FFT_MajorPeak) - 1.78f) * 255.0f/(MAX_FREQ_LOG10 - 1.78f); // Scale log10 of frequency values to the 255 colour index.
|
||||
if (FFT_MajorPeak < 61.0f) pixCol = 0; // handle underflow
|
||||
SEGMENT.setPixelColor(locn, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(SEGMENT.intensity+pixCol, false, PALETTE_SOLID_WRAP, 0), (int)my_magnitude));
|
||||
}
|
||||
|
||||
@ -6877,7 +6882,6 @@ uint16_t mode_freqwave(void) { // Freqwave. By Andreas Pleschun
|
||||
|
||||
CRGB color = 0;
|
||||
|
||||
//if (FFT_MajorPeak > 5120) FFT_MajorPeak = 0.0f;
|
||||
if (FFT_MajorPeak > MAX_FREQUENCY) FFT_MajorPeak = 1.0f;
|
||||
// MajorPeak holds the freq. value which is most abundant in the last sample.
|
||||
// With our sampling rate of 10240Hz we have a usable freq range from roughtly 80Hz to 10240/2 Hz
|
||||
@ -6888,7 +6892,7 @@ uint16_t mode_freqwave(void) { // Freqwave. By Andreas Pleschun
|
||||
} else {
|
||||
int upperLimit = 80 + 42 * SEGMENT.custom2;
|
||||
int lowerLimit = 80 + 3 * SEGMENT.custom1;
|
||||
int i = lowerLimit!=upperLimit ? map(FFT_MajorPeak, lowerLimit, upperLimit, 0, 255) : FFT_MajorPeak;
|
||||
uint8_t i = lowerLimit!=upperLimit ? map(FFT_MajorPeak, lowerLimit, upperLimit, 0, 255) : FFT_MajorPeak; // may under/overflow - so we enforce uint8_t
|
||||
uint16_t b = 255.0 * intensity;
|
||||
if (b > 255) b=255;
|
||||
color = CHSV(i, 240, (uint8_t)b); // implicit conversion to RGB supplied by FastLED
|
||||
@ -6924,7 +6928,7 @@ uint16_t mode_gravfreq(void) { // Gravfreq. By Andrew Tuline.
|
||||
float volumeSmth = *(float*) um_data->u_data[0];
|
||||
if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception)
|
||||
|
||||
SEGMENT.fade_out(240);
|
||||
SEGMENT.fade_out(250);
|
||||
|
||||
float segmentSampleAvg = volumeSmth * (float)SEGMENT.intensity / 255.0;
|
||||
segmentSampleAvg *= 0.125; // divide by 8, to compensate for later "sensitivty" upscaling
|
||||
@ -7012,6 +7016,7 @@ uint16_t mode_rocktaves(void) { // Rocktaves. Same note from eac
|
||||
frTemp = fabs(frTemp * 2.1); // Fudge factors to compress octave range starting at 0 and going to 255;
|
||||
|
||||
uint16_t i = map(beatsin8(8+octCount*4, 0, 255, 0, octCount*8), 0, 255, 0, SEGLEN-1);
|
||||
i = constrain(i, 0, SEGLEN-1);
|
||||
SEGMENT.addPixelColor(i, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette((uint8_t)frTemp, false, PALETTE_SOLID_WRAP, 0), volTemp));
|
||||
|
||||
return FRAMETIME;
|
||||
@ -7054,7 +7059,9 @@ uint16_t mode_waterfall(void) { // Waterfall. By: Andrew Tulin
|
||||
if (SEGENV.aux0 != secondHand) { // Triggered millis timing.
|
||||
SEGENV.aux0 = secondHand;
|
||||
|
||||
uint8_t pixCol = (log10f((float)FFT_MajorPeak) - 2.26f) * 177; // log10 frequency range is from 2.26 to 3.7. Let's scale accordingly.
|
||||
//uint8_t pixCol = (log10f((float)FFT_MajorPeak) - 2.26f) * 177; // 10Khz sampling - log10 frequency range is from 2.26 (182hz) to 3.7 (5012hz). Let's scale accordingly.
|
||||
uint8_t pixCol = (log10f(FFT_MajorPeak) - 2.26f) * 150; // 22Khz sampling - log10 frequency range is from 2.26 (182hz) to 3.967 (9260hz). Let's scale accordingly.
|
||||
if (FFT_MajorPeak < 182.0f) pixCol = 0; // handle underflow
|
||||
|
||||
if (samplePeak) {
|
||||
SEGMENT.setPixelColor(SEGLEN-1, CHSV(92,92,92));
|
||||
|
Loading…
Reference in New Issue
Block a user