consider human hearing for "Major Peak" frequency
The "Major Peak" (for double-notes effects) was computed on the raw FFT results. However the human ear is more sensitive to higher frequencies (pink noise profile). This code change considers human ear properties for major peak computations. Effects like "freqmap" will look much more vivid afterwards, as higher frequencies will now have a stronger influence (harmonics are still suppressed properly).
This commit is contained in:
@@ -23,6 +23,12 @@
|
||||
#define FFT_PREFER_EXACT_PEAKS // use different FFT wndowing -> results in "sharper" peaks and less "leaking" into other frequencies
|
||||
//#define SR_STATS
|
||||
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
// this applies "pink noise scaling" to FFT results before computing the major peak for effects.
|
||||
// currently only for ESP32-S3 and classic ESP32, due to increased runtime
|
||||
#define FFT_MAJORPEAK_HUMAN_EAR
|
||||
#endif
|
||||
|
||||
// Comment/Uncomment to toggle usb serial debugging
|
||||
// #define MIC_LOGGER // MIC sampling & sound input debugging (serial plotter)
|
||||
// #define FFT_SAMPLING_LOG // FFT result debugging
|
||||
@@ -289,6 +295,13 @@ static float vImag[samplesFFT] = {0.0f}; // imaginary parts
|
||||
static float windowWeighingFactors[samplesFFT] = {0.0f};
|
||||
#endif
|
||||
|
||||
#ifdef FFT_MAJORPEAK_HUMAN_EAR
|
||||
static float pinkFactors[samplesFFT] = {0.0f}; // "pink noise" correction factors
|
||||
constexpr float pinkcenter = 23.66; // sqrt(560) - center freq for scaling is 560 hz.
|
||||
constexpr float binWidth = SAMPLE_RATE / (float)samplesFFT; // frequency range of each FFT result bin
|
||||
#endif
|
||||
|
||||
|
||||
// Create FFT object
|
||||
#ifdef UM_AUDIOREACTIVE_USE_NEW_FFT
|
||||
// lib_deps += https://github.com/kosme/arduinoFFT#develop @ 1.9.2
|
||||
@@ -376,6 +389,17 @@ void FFTcode(void * parameter)
|
||||
const TickType_t xFrequencyDouble = FFT_MIN_CYCLE * portTICK_PERIOD_MS * 2;
|
||||
static bool isFirstRun = false;
|
||||
|
||||
#ifdef FFT_MAJORPEAK_HUMAN_EAR
|
||||
// pre-compute pink noise scaling table
|
||||
for(uint_fast16_t binInd = 0; binInd < samplesFFT; binInd++) {
|
||||
float binFreq = binInd * binWidth + binWidth/2.0f;
|
||||
if (binFreq > (SAMPLE_RATE * 0.42f))
|
||||
binFreq = (SAMPLE_RATE * 0.42f) - 0.25 * (binFreq - (SAMPLE_RATE * 0.42f)); // supress noise and aliasing
|
||||
pinkFactors[binInd] = sqrtf(binFreq) / pinkcenter;
|
||||
}
|
||||
pinkFactors[0] *= 0.5; // suppress 0-42hz bin
|
||||
#endif
|
||||
|
||||
TickType_t xLastWakeTime = xTaskGetTickCount();
|
||||
for(;;) {
|
||||
delay(1); // DO NOT DELETE THIS LINE! It is needed to give the IDLE(0) task enough time and to keep the watchdog happy.
|
||||
@@ -498,11 +522,28 @@ void FFTcode(void * parameter)
|
||||
FFT.ComplexToMagnitude(); // Compute magnitudes
|
||||
#endif
|
||||
|
||||
#ifdef FFT_MAJORPEAK_HUMAN_EAR
|
||||
// scale FFT results
|
||||
for(uint_fast16_t binInd = 0; binInd < samplesFFT; binInd++)
|
||||
vReal[binInd] *= pinkFactors[binInd];
|
||||
#endif
|
||||
|
||||
#ifdef UM_AUDIOREACTIVE_USE_NEW_FFT
|
||||
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
|
||||
#endif
|
||||
|
||||
#ifdef FFT_MAJORPEAK_HUMAN_EAR
|
||||
// undo scaling - we want unmodified values for FFTResult[] computations
|
||||
for(uint_fast16_t binInd = 0; binInd < samplesFFT; binInd++)
|
||||
vReal[binInd] *= 1.0f/pinkFactors[binInd];
|
||||
//fix peak magnitude
|
||||
if ((FFT_MajorPeak > (binWidth/1.25f)) && (FFT_MajorPeak < (SAMPLE_RATE/2.2f)) && (FFT_Magnitude > 4.0f)) {
|
||||
unsigned peakBin = constrain((int)((FFT_MajorPeak + binWidth/2.0f) / binWidth), 0, samplesFFT -1);
|
||||
FFT_Magnitude *= fmaxf(1.0f/pinkFactors[peakBin], 1.0f);
|
||||
}
|
||||
#endif
|
||||
FFT_MajorPeak = constrain(FFT_MajorPeak, 1.0f, 11025.0f); // restrict value to range expected by effects
|
||||
FFT_MajPeakSmth = FFT_MajPeakSmth + 0.42 * (FFT_MajorPeak - FFT_MajPeakSmth); // I like this "swooping peak" look
|
||||
|
||||
|
||||
Reference in New Issue
Block a user