The Right Thing to Do (makes GEQ look awesome)
... found that stupid commit messages get more attention ;-) - use 22050 Hz for sampling, as it is a standard frequency. I think this is the best choise. - redesigned the GEQ channels (fftResult[]) for 22Khz, based on channels found on old HiFi equalizer equipment. 1Kzh is now at the center; Bass/Trebble channels are using 1/4 on left/right side respectively - similar to real equalizers. Looks nice :-) - adjusted effects that use FFT_MajorPeak so that the maximum frequency is supported.
This commit is contained in:
parent
b8db47e528
commit
bbc8049832
@ -47,11 +47,12 @@
|
||||
|
||||
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 = 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
|
||||
|
||||
#define FFT_MIN_CYCLE 22 // minimum time before FFT task is repeated. Must be less than time needed to read 512 samples at SAMPLE_RATE -> not the same as I2S time!!
|
||||
//#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
|
||||
|
||||
// globals
|
||||
static uint8_t inputLevel = 128; // UI slider value
|
||||
@ -65,7 +66,7 @@ static bool limiterOn = true; // bool: enable / disable dynamics
|
||||
static uint16_t attackTime = 80; // int: attack time in milliseconds. Default 0.08sec
|
||||
static uint16_t decayTime = 1400; // int: decay time in milliseconds. Default 1.40sec
|
||||
// user settable options for FFTResult scaling
|
||||
static uint8_t FFTScalingMode = 2; // 0 none; 1 optimized logarithmic; 2 optimized linear
|
||||
static uint8_t FFTScalingMode = 3; // 0 none; 1 optimized logarithmic; 2 optimized linear; 3 optimized sqare root
|
||||
|
||||
//
|
||||
// AGC presets
|
||||
@ -121,7 +122,10 @@ static float vReal[samplesFFT] = {0.0f};
|
||||
static float vImag[samplesFFT] = {0.0f};
|
||||
static float fftBin[samplesFFT_2] = {0.0f};
|
||||
|
||||
#define FFT_DOWNSCALE 0.65f // downscaling factor for FFT results - "Flat-Top" window
|
||||
// the following are observed values, supported by a bit of "educated guessing"
|
||||
//#define FFT_DOWNSCALE 0.65f // 20kHz - downscaling factor for FFT results - "Flat-Top" window @20Khz, old freq channels
|
||||
|
||||
#define FFT_DOWNSCALE 0.46f // downscaling factor for FFT results - for "Flat-Top" window @22Khz, new freq channels
|
||||
#define LOG_256 5.54517744
|
||||
|
||||
#ifdef UM_AUDIOREACTIVE_USE_NEW_FFT
|
||||
@ -269,7 +273,7 @@ void FFTcode(void * parameter)
|
||||
* Multiplier = 1.320367784
|
||||
*/
|
||||
if (sampleAvg > 1) { // noise gate open
|
||||
// Range
|
||||
#if 0 // Range
|
||||
fftCalc[ 0] = fftAddAvg(2,4); // 60 - 100
|
||||
fftCalc[ 1] = fftAddAvg(4,5); // 80 - 120
|
||||
fftCalc[ 2] = fftAddAvg(5,7); // 100 - 160
|
||||
@ -286,6 +290,26 @@ void FFTcode(void * parameter)
|
||||
fftCalc[13] = fftAddAvg(111,147); // 2220 - 2960
|
||||
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
|
||||
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
|
||||
fftCalc[ 3] = fftAddAvg(5,7); // 2 216 - 301 bass + midrange
|
||||
fftCalc[ 4] = fftAddAvg(7,10); // 3 301 - 430 midrange
|
||||
fftCalc[ 5] = fftAddAvg(10,13); // 3 430 - 560 midrange
|
||||
fftCalc[ 6] = fftAddAvg(13,19); // 5 560 - 818 midrange
|
||||
fftCalc[ 7] = fftAddAvg(19,26); // 7 818 - 1120 midrange -- 1Khz should always be the center !
|
||||
fftCalc[ 8] = fftAddAvg(26,33); // 7 1120 - 1421 midrange
|
||||
fftCalc[ 9] = fftAddAvg(33,44); // 9 1421 - 1895 midrange
|
||||
fftCalc[10] = fftAddAvg(44,56); // 12 1895 - 2412 midrange + high mid
|
||||
fftCalc[11] = fftAddAvg(56,70); // 14 2412 - 3015 high mid
|
||||
fftCalc[12] = fftAddAvg(70,86); // 16 3015 - 3704 high mid
|
||||
fftCalc[13] = fftAddAvg(86,104); // 18 3704 - 4479 high mid
|
||||
fftCalc[14] = fftAddAvg(104,165) * 0.88f; // 61 4479 - 7106 high mid + high -- with slight damping
|
||||
fftCalc[15] = fftAddAvg(165,215) * 0.70f; // 50 7106 - 9259 high -- with some damping
|
||||
// don't use the last bins from 216 to 255. They are usually contaminated by aliasing (aka noise)
|
||||
#endif
|
||||
|
||||
} else { // noise gate closed
|
||||
for (int i=0; i < 16; i++) {
|
||||
@ -350,7 +374,7 @@ void FFTcode(void * parameter)
|
||||
if (currentResult > 1.0)
|
||||
currentResult = sqrtf(currentResult);
|
||||
else currentResult = 0.0; // special handling, because sqrt(0) = undefined
|
||||
currentResult *= 0.85f + (float(i)/5.0f); // extra up-scaling for high frequencies
|
||||
currentResult *= 0.85f + (float(i)/4.5f); // extra up-scaling for high frequencies
|
||||
currentResult = mapf(currentResult, 0.0, 16.0, 0.0, 255.0); // map [sqrt(1) ... sqrt(256)] to [0 ... 255]
|
||||
break;
|
||||
|
||||
@ -872,7 +896,8 @@ class AudioReactive : public Usermod {
|
||||
|
||||
my_magnitude = fmaxf(receivedPacket->FFT_Magnitude, 0.0f);
|
||||
FFT_Magnitude = my_magnitude;
|
||||
FFT_MajorPeak = fmaxf(receivedPacket->FFT_MajorPeak, 1.0f);
|
||||
FFT_MajorPeak = constrain(receivedPacket->FFT_MajorPeak, 1.0f, 11050.0f); // restrict value to range expected by effects
|
||||
|
||||
//DEBUGSR_PRINTLN("Finished parsing UDP Sync Packet");
|
||||
haveFreshData = true;
|
||||
}
|
||||
|
@ -5938,7 +5938,7 @@ static const char _data_FX_MODE_2DDRIFTROSE[] PROGMEM = "Drift Rose@Fade,Blur;;;
|
||||
|
||||
uint8_t *binNum = (uint8_t*)&SEGENV.aux1, *maxVol = (uint8_t*)(&SEGENV.aux1+1); // just in case assignment
|
||||
bool samplePeak = false;
|
||||
float FFT_MajorPeak = 0.0;
|
||||
float FFT_MajorPeak = 1.0;
|
||||
uint8_t *fftResult = nullptr;
|
||||
float *fftBin = nullptr;
|
||||
um_data_t *um_data;
|
||||
@ -5958,6 +5958,15 @@ 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_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)
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// * Ripple Peak //
|
||||
@ -6724,12 +6733,12 @@ 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/(4.0102f-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/(4.0102f-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.
|
||||
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));
|
||||
@ -6769,7 +6778,7 @@ uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Plesch
|
||||
CRGB color = CRGB::Black;
|
||||
|
||||
//if (FFT_MajorPeak > 5120) FFT_MajorPeak = 0;
|
||||
if (FFT_MajorPeak > 10240) 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
|
||||
// we will treat everything with less than 65Hz as 0
|
||||
@ -6777,8 +6786,8 @@ uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Plesch
|
||||
if (FFT_MajorPeak < 80) {
|
||||
color = CRGB::Black;
|
||||
} else {
|
||||
int upperLimit = 20 * SEGMENT.custom2;
|
||||
int lowerLimit = 2 * SEGMENT.custom1;
|
||||
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;
|
||||
uint16_t b = 255 * intensity;
|
||||
if (b > 255) b = 255;
|
||||
@ -6818,7 +6827,7 @@ 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/(4.0102f-1.78f); // 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.
|
||||
SEGMENT.setPixelColor(locn, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(SEGMENT.intensity+pixCol, false, PALETTE_SOLID_WRAP, 0), (int)my_magnitude));
|
||||
}
|
||||
|
||||
@ -6869,7 +6878,7 @@ uint16_t mode_freqwave(void) { // Freqwave. By Andreas Pleschun
|
||||
CRGB color = 0;
|
||||
|
||||
//if (FFT_MajorPeak > 5120) FFT_MajorPeak = 0.0f;
|
||||
if (FFT_MajorPeak > 10240) 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
|
||||
// we will treat everything with less than 65Hz as 0
|
||||
@ -6877,8 +6886,8 @@ uint16_t mode_freqwave(void) { // Freqwave. By Andreas Pleschun
|
||||
if (FFT_MajorPeak < 80) {
|
||||
color = CRGB::Black;
|
||||
} else {
|
||||
int upperLimit = 20 * SEGMENT.custom2;
|
||||
int lowerLimit = 2 * SEGMENT.custom1;
|
||||
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;
|
||||
uint16_t b = 255.0 * intensity;
|
||||
if (b > 255) b=255;
|
||||
@ -6927,7 +6936,7 @@ uint16_t mode_gravfreq(void) { // Gravfreq. By Andrew Tuline.
|
||||
for (int i=0; i<tempsamp; i++) {
|
||||
|
||||
//uint8_t index = (log10((int)FFT_MajorPeak) - (3.71-1.78)) * 255; //int? shouldn't it be floor() or similar
|
||||
uint8_t index = (log10f(FFT_MajorPeak) - (4.0102f-1.78f)) * 255; //int? shouldn't it be floor() or similar
|
||||
uint8_t index = (log10f(FFT_MajorPeak) - (MAX_FREQ_LOG10 - 1.78f)) * 255; //int? shouldn't it be floor() or similar
|
||||
|
||||
SEGMENT.setPixelColor(i+SEGLEN/2, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0));
|
||||
SEGMENT.setPixelColor(SEGLEN/2-i-1, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0));
|
||||
|
Loading…
Reference in New Issue
Block a user