Help needed: Compiler errors using complex numbers in FFT

I'd like some help with this issue.

I'm using Arduino IDE 2.3.4 on Windows 10 and a ESP32 board. The original author used an older Arduino verson. I tried using that and got similar compiler errors. I also used his latest versions as shown on his web page and get similar compiler errors

This is his web link: https://www.instructables.com/Portable-Sound-Analyzer-on-ESP32/

Here's the code that I'm unable to compile:

SoundAnalyzer_ESP32_TTGO.ino

/* Sound analyzer
Several display modes (spectrum, sound amplitude, envelope)
(by) Lesept October 2020

TFT_eSPI:
In the file TFT_eSPI/User_Setup_Select.h
comment this line: #include <User_Setup.h>
and uncomment this line: #include <User_Setups/Setup25_TTGO_T_Display.h>

*/
#include <Arduino.h>
#include <driver/adc.h>
#include <complex.h>
#define FREQ2IND (SAMPLES * 1.0 / MAX_FREQ)
#include "params.h"
#include <TFT_eSPI.h>
#include <SPI.h>
#define MIC 32

//Display parameters
#ifndef TFT_DISPOFF
#define TFT_DISPOFF 0x28
#endif

#ifndef TFT_SLPIN
#define TFT_SLPIN 0x10
#endif

#define TFT_MOSI 19
#define TFT_SCLK 18
#define TFT_CS 5
#define TFT_DC 16
#define TFT_RST 23

#define TFT_BL 4 // Display backlight control pin
#define ADC_EN 14 // ADC_EN is the ADC detection enable port
#define ADC_PIN 34
#define BUTTON_1 35
#define BUTTON_2 0

TFT_eSPI display = TFT_eSPI(135, 240); // Invoke custom library

unsigned long chrono, chrono1;
unsigned long sampling_period_us;
byte peak[SAMPLES] = {0};
float _Complex data[SAMPLES];
const int nTimes = 54; // number of acquisitions in a row (700 ms total)
uint16_t data2D[SAMPLES][nTimes];
int sound[SAMPLES];
float MULT = MAX_FREQ * 1000.0 / SAMPLES;
unsigned int P2P = 0;
const int LOG2SAMPLE = log(SAMPLES) / log(2);
int32_t backgroundSound = 0;
#include "functions.h"
#define MODE 19
#define MAXMODES 7

void setup() {
Serial.begin(115200);
pinMode(BUTTON_1, INPUT_PULLUP);
pinMode(BUTTON_2, INPUT_PULLUP);
adc1_config_width(ADC_WIDTH_BIT_12);
// ADC1 Channel 4 is GPIO 32 (microphone)
// https://microcontrollerslab.com/wp-content/uploads/2019/03/ESP32-ADC-channels-pinout.jpg
adc1_config_channel_atten(ADC1_CHANNEL_4, ADC_ATTEN_DB_11);
calibrate();
display.init();
display.fillScreen(TFT_BLACK);
display.setRotation(3);
display.setTextColor(TFT_BLUE);
display.drawString("on ESP32", 20, 110, 4); // Splash screen
display.setTextSize(2);
display.drawString("SONO", 0, 10, 4);
display.drawString("METER", 68, 60, 4);
display.setTextSize(1);
display.setTextColor(TFT_RED);
display.drawString("[by Lesept]", 165, 120, 2);
Serial.println("SonoMeter on ESP32");
delay(2000);
sampling_period_us = round(1000ul * (1.0 / MAX_FREQ));
chrono1 = millis();
}

void loop() {
static int modes = 0;
bool changeMode = false;
// Push the button to change modes
if (millis() - chrono1 > 1000ul) {
if (digitalRead(BUTTON_1) == LOW) { // Modes up
delay(30);
modes = (modes + 1) % MAXMODES;
changeMode = true;
chrono1 = millis();
} else if (digitalRead(BUTTON_2) == LOW) { // Modes down
delay(30);
modes = (modes - 1 + MAXMODES) % MAXMODES;
changeMode = true;
chrono1 = millis();
}
}
switch (modes) {
case 0: // Display spectrum
acquireSound();
displaySpectrum();
break;
case 1: // Display spectrum
acquireSound();
displaySpectrum2();
break;
case 2: // Display amplitude with bars
displayAmplitudeBars();
break;
case 3: // Display envelope
displayEnvelope(changeMode);
break;
case 4: // Display running amplitude
displayRunningEnvelope(changeMode);
break;
case 5: // Display Spectrogram
displaySpectrogram (changeMode, false);
break;
case 6: // Display Spectrogram with maxima in circles
displaySpectrogram (changeMode, true);
break;
default:
break;
}
// Touch GPIO 15 to stop the display
const int touchPin = 15;
const int threshold = 90;
if (touchRead(touchPin) < threshold) while (touchRead(touchPin) < threshold);
}

typedef enum fft_dir {
FFT_FORWARD, /* kernel uses "-1" sign /
FFT_INVERSE /
kernel uses "+1" sign */
} fft_dir;

void window (float _Complex *data, unsigned int log2_N, byte windowType, fft_dir direction) {
unsigned int N = 1 << log2_N;
unsigned int Nd2 = N >> 1;
for (int i = 0; i < Nd2; i++) {
double indexMinusOne = double(i);
double ratio = (indexMinusOne / (N - 1));
double weighingFactor = 1.0;
// Compute and record weighting factor
switch (windowType) {
case RECTANGLE: // rectangle (box car)
weighingFactor = 1.0;
break;
case HAMMING: // hamming
weighingFactor = 0.54 - (0.46 * cos(2 * PI * ratio));
break;
case HANN: // hann
weighingFactor = 0.54 * (1.0 - cos(2 * PI * ratio));
break;
case TRIANGLE: // triangle (Bartlett)
weighingFactor = 1.0 - ((2.0 * abs(indexMinusOne - ((N - 1) / 2.0))) / (N - 1));
break;
case NUTTALL: // nuttall
weighingFactor = 0.355768 - (0.487396 * (cos(2 * PI * ratio))) + (0.144232 * (cos(4 * PI * ratio))) - (0.012604 * (cos(6 * PI * ratio)));
break;
case BLACKMAN: // blackman
weighingFactor = 0.42323 - (0.49755 * (cos(2 * PI * ratio))) + (0.07922 * (cos(4 * PI * ratio)));
break;
case BLACKMAN_NUTTALL: // blackman nuttall
weighingFactor = 0.3635819 - (0.4891775 * (cos(2 * PI * ratio))) + (0.1365995 * (cos(4 * PI * ratio))) - (0.0106411 * (cos(6 * PI * ratio)));
break;
case BLACKMAN_HARRIS: // blackman harris
weighingFactor = 0.35875 - (0.48829 * (cos(2 * PI * ratio))) + (0.14128 * (cos(4 * PI * ratio))) - (0.01168 * (cos(6 * PI * ratio)));
break;
case FLT_TOP: // flat top
weighingFactor = 0.2810639 - (0.5208972 * cos(2 * PI * ratio)) + (0.1980399 * cos(4 * PI * ratio));
break;
case WELCH: // welch
weighingFactor = 1.0 - sq((indexMinusOne - (N - 1) / 2.0) / ((N - 1) / 2.0));
break;
}
if (direction == FFT_FORWARD) {
data[i] *= weighingFactor;
data[N - (i + 1)] *= weighingFactor;
}
else {
data[i] /= weighingFactor;
data[N - (i + 1)] /= weighingFactor;
}
}
}

functions.h

void ffti_shuffle_f(float _Complex data, unsigned int log2_N)
{
/

Basic Bit-Reversal Scheme:

 The incrementing pattern operations used here correspond
 to the logic operations of a synchronous counter.

 Incrementing a binary number simply flips a sequence of
 least-significant bits, for example from 0111 to 1000.
 So in order to compute the next bit-reversed index, we
 have to flip a sequence of most-significant bits.

*/

unsigned int N = 1 << log2_N; /* N /
unsigned int Nd2 = N >> 1; /
N/2 = number range midpoint /
unsigned int Nm1 = N - 1; /
N-1 = digit mask /
unsigned int i; /
index for array elements /
unsigned int j; /
index for next element swap location */

for (i = 0, j = 0; i < N; i++) {
if (j > i) {
float _Complex tmp = data[i];
data[i] = data[j];
data[j] = tmp;
}

/*
   Find least significant zero bit
*/

unsigned int lszb = ~i & (i + 1);

/*
   Use division to bit-reverse the single bit so that we now have
   the most significant zero bit

   N = 2^r = 2^(m+1)
   Nd2 = N/2 = 2^m
   if lszb = 2^k, where k is within the range of 0...m, then
       mszb = Nd2 / lszb
            = 2^m / 2^k
            = 2^(m-k)
            = bit-reversed value of lszb
*/

unsigned int mszb = Nd2 / lszb;

/*
   Toggle bits with bit-reverse mask
*/

unsigned int bits = Nm1 & ~(mszb - 1);
j ^= bits;

}
}

void ffti_evaluate_f(float _Complex data, unsigned int log2_N, fft_dir direction)
{
/

In-place FFT butterfly algorithm

 input:
     A[] = array of N shuffled complex values where N is a power of 2
 output:
     A[] = the DFT of input A[]

 for r = 1 to log2(N)
     m = 2^r
     Wm = exp(−j2π/m)
     for n = 0 to N-1 by m
         Wmk = 1
         for k = 0 to m/2 - 1
             u = A[n + k]
             t = Wmk * A[n + k + m/2]
             A[n + k]       = u + t
             A[n + k + m/2] = u - t
             Wmk = Wmk * Wm

 For inverse FFT, use Wm = exp(+j2π/m)

*/

unsigned int N = 1 << log2_N;
double theta_2pi = (direction == FFT_FORWARD) ? -PI : PI;
theta_2pi *= 2;

for (unsigned int r = 1; r <= log2_N; r++)
{
unsigned int m = 1 << r;
unsigned int md2 = m >> 1;
double theta = theta_2pi / m;
double re = cos(theta);
double im = sin(theta);
double _Complex Wm = re + I * im;
for (unsigned int n = 0; n < N; n += m) {
double _Complex Wmk = 1.0f; /* Use double for precision */
for (unsigned int k = 0; k < md2; k++) {
unsigned int i_e = n + k;
unsigned int i_o = i_e + md2;
double _Complex t = Wmk * data[i_o];
data[i_o] = data[i_e] - t;
data[i_e] = data[i_e] + t;
t = Wmk * Wm;
Wmk = t;
}
}
}
}

void ffti_f(float _Complex data[], unsigned int log2_N, fft_dir direction)
{
ffti_shuffle_f(data, log2_N);
ffti_evaluate_f(data, log2_N, direction);
}

void acquireSound () {
for (int i = 0; i < SAMPLES; i++) {
unsigned long chrono = micros();
data[i] = analogRead(MIC);
while (micros() - chrono < sampling_period_us); // do nothing
} // 12.8 ms
}

void displaySpectrum () {
window (data, LOG2SAMPLE, HAMMING, FFT_FORWARD);
ffti_f(data, LOG2SAMPLE, FFT_FORWARD);
// window + FFT last 10ms
int nFreq = SAMPLES / 2;
int hauteur = display.height();
display.fillScreen(TFT_BLACK);
display.setTextColor(TFT_WHITE);
display.setTextSize(1);
const float freqs[7] = {.5, 1, 2, 3, 4, 6, 8};
for (int i = 0; i < 7; i++) {
int pos = FREQ2IND * freqs[i] * 1.9 ;
if (i == 0) display.drawString(".5", pos - 5, hauteur - 13, 2);
else display.drawString(String(freqs[i], 0), pos, hauteur - 13, 2);
}
display.drawString("kHz", display.width() - 22, hauteur - 13, 2);

const int decal = 15;
// Affichage du spectre
int ampmax = 0;
int imax = 0;
for (int i = 2; i < nFreq; i++) {
int amplitude = (int)creal(data[i]) / COEF;
if (amplitude > ampmax) {
ampmax = amplitude;
imax = i;
}
amplitude = min(amplitude, hauteur - decal);
display.drawFastVLine (i * 2, hauteur - amplitude - decal, amplitude, TFT_GREEN);
}

// Affichage fréquence de plus forte amplitude
if (ampmax > 20) {
display.setTextSize(2);
display.setTextColor(TFT_BLUE);
int freqmax = 985.0 * imax * MAX_FREQ / SAMPLES;
char texte[14];
sprintf(texte, "%4d Hz: %3d", freqmax, ampmax);
display.drawString(texte, display.width() - 145, 0, 1);
}

// Affichage et décroissance des valeurs peak
for (int i = 2; i < nFreq - 4; i = i + 4) {
int amplitude = (int)creal(data[i]);
amplitude = max(amplitude, (int)creal(data[i + 1]));
amplitude = max(amplitude, (int)creal(data[i + 2]));
amplitude = max(amplitude, (int)creal(data[i + 3]));
amplitude /= COEF;
if (amplitude > peak[i]) peak[i] = amplitude;
if (peak[i] > hauteur - decal) peak[i] = hauteur - decal;
if (peak[i] > 8) {
peak[i] -= 2; // Decay the peak
display.drawFastHLine(i * 2, hauteur - peak[i] - decal, 4, TFT_RED);
}
}
}

void rectangleGR (int x0, int w, int h) {
const uint16_t colors[8] = {TFT_DARKGREEN, TFT_GREEN, TFT_GREENYELLOW, TFT_YELLOW,
TFT_GOLD, TFT_ORANGE, TFT_RED, TFT_BROWN
};
const int decal = 15;
int x = x0 * (w + 2);
int dh = (display.height() - decal) / 8;
for (int i = 1; i < 8; i++) {
if (h > i * dh) {
int y = display.height() - decal - i * dh;
display.fillRect(x, y, w, dh, colors[i - 1]);
} else {
int y = display.height() - decal - h;
display.fillRect(x, y, w, h - (i - 1) * dh, colors[i - 1]);
break;
}
}
}

void displaySpectrum2 () {
window (data, LOG2SAMPLE, HAMMING, FFT_FORWARD);
ffti_f(data, LOG2SAMPLE, FFT_FORWARD);
int nFreq = SAMPLES / 2;
int hauteur = display.height();
display.fillScreen(TFT_BLACK);
display.setTextColor(TFT_WHITE);
display.setTextSize(1);
const float freqs[6] = {.5, 1, 1.5, 2, 3, 4};
for (int i = 0; i < 6; i++) {
int pos = FREQ2IND * freqs[i] * 3.5 ;
if (i == 0) display.drawString(".5", pos - 5, hauteur - 13, 2);
else if (i == 1) display.drawString("1", pos - 10, hauteur - 13, 2);
else if (i == 2) display.drawString("1.5", pos - 5, hauteur - 13, 2);
else display.drawString(String(freqs[i], 0), pos, hauteur - 13, 2);
}
display.drawString("kHz", display.width() - 22, hauteur - 13, 2);

const int decal = 15;
// Affichage du spectre
for (int i = 0; i < 16; i++) {
int amplitude = 0;
for (int j = 0; j < 4; j++) amplitude += abs((int)creal(data[i * 4 + j + 2]) / COEF);
amplitude = min(amplitude, hauteur - decal);
rectangleGR (i, 13, amplitude);
}
}

void displayAmplitudeBars() {
const uint16_t colors[8] = {TFT_DARKGREEN, TFT_GREEN, TFT_GREENYELLOW, TFT_YELLOW,
TFT_GOLD, TFT_ORANGE, TFT_RED, TFT_BROWN
};
int ampmax = -5000;
int ampmin = 5000;
int N = display.width();
int decal = 15;
int hauteur = display.height() - decal;
for (int i = 0; i < N; i++) {
sound[i] = analogRead(MIC);
delayMicroseconds(50);
}
display.fillScreen(TFT_BLACK);
int prevamp = 1;
for (int i = 0; i < N; i++) {
uint16_t colour;
// colour = TFT_GREEN;
// colour = colors[(i / 10) % 8];
uint16_t red = 0b11111;
uint16_t red2 = 0b00001;
if (i < N / 2) colour = (red - i * (red - red2) * 2 / N) << 11;
else colour = (i + N / 2) * 32 / N;
int amplitude = (sound[i] - SILENCE) / COEF2;
constrain(amplitude, -hauteur / 2, hauteur / 2);
if (amplitude > ampmax) ampmax = amplitude;
if (amplitude < ampmin) ampmin = amplitude;
display.drawFastVLine (i, hauteur / 2 - amplitude + decal, abs(amplitude), colour);
if (amplitude * prevamp < 0 && i > 0)
display.drawLine(i - 1, hauteur / 2 - prevamp + decal, i, hauteur / 2 - amplitude + decal, colour);
}
// Affichage plus forte amplitude
display.setTextColor(TFT_BLUE);
display.setTextSize(2);
char texte[25];
sprintf(texte, "Min: %3d, Max: %3d", ampmin, ampmax);
display.drawString(texte, 10, 0, 1);
delay(50);
}

void displayEnvelope(bool erase) {
static int i = 0;
if (i == 1 || erase) display.fillScreen(TFT_BLACK);
const int decal = 15;
const int hauteur = display.height();
const int N = display.width();
static unsigned int maxP2P = 0;
static unsigned int minP2P = 5000;
static unsigned int maxP2Pold = 0;
static unsigned int minP2Pold = 5000;
static int amplitudeold = 0;

if (i >= N || erase) {
i = 0;
maxP2P = 0;
minP2P = 5000;
maxP2Pold = 0;
minP2Pold = 5000;
}

unsigned int signalMax = 0;
unsigned int signalMin = 4096;
unsigned long chrono = micros(); // Sample window 10ms
while (micros() - chrono < 10000ul) {
int sample = analogRead(MIC) / COEF3;
if (sample > signalMax) signalMax = sample;
else if (sample < signalMin) signalMin = sample;
}
unsigned int peakToPeak = signalMax - signalMin;
int amplitude = peakToPeak - SENSITIVITY;
if (amplitude < 0) amplitude = 0;
else if (amplitude > 500) amplitude = 500;
int ampPrev = map(amplitudeold, 0, 500, hauteur - 1, decal);
int amp = map(amplitude, 0, 500, hauteur - 1, decal);
if (amplitude > maxP2P) maxP2P = amplitude;
if (amplitude < minP2P) minP2P = amplitude;
if (i > 0) display.drawLine (i - 1, ampPrev, i, amp, TFT_GREEN);
amplitudeold = amplitude;
// Affichage plus forte amplitude
if ((maxP2Pold != maxP2P) || (minP2Pold != minP2P) || (i == 0)) {
display.fillRect(0, 0, N, 15, TFT_BLACK);
display.setTextColor(TFT_BLUE);
char texte[25];
sprintf(texte, "Min : %3d, Max: %3d", minP2P, maxP2P);
display.drawString(texte, 0, 0, 1);
}
maxP2Pold = maxP2P;
minP2Pold = minP2P;
++i;
}

void displayRunningEnvelope(bool erase) {
if (erase) display.fillScreen(TFT_BLACK);
static int ampMaxOld = 0;
static int ampMinOld = 1024;
const int decal = 15;
const int hauteur = display.height();
const int N = display.width();
static int sound[240] = {0};
int save = sound[0];
for (int i = 0; i < N - 1 ; i++) sound[i] = sound[i + 1];

unsigned int signalMax = 0;
unsigned int signalMin = 4096;
unsigned long chrono = micros(); // Sample window 10ms
while (micros() - chrono < 10000ul) {
int sample = analogRead(MIC) / COEF3;
if (sample > signalMax) signalMax = sample;
else if (sample < signalMin) signalMin = sample;
}
unsigned int peakToPeak = signalMax - signalMin;
int x = peakToPeak - SENSITIVITY;
if (x < 0) x = 0;
if (x > 500) x = 500;
sound[N - 1] = map(x, 0, 500, 1, hauteur - decal);

int ampMin = 500;
int ampMax = 0;
display.drawLine (0, hauteur - save, 1, hauteur - sound[0], TFT_BLACK);
for (int j = 1; j < N; j++) {
if (sound[j] > ampMax) ampMax = sound[j];
if (sound[j] < ampMin) ampMin = sound[j];
if (ampMin == 1) ampMin = 0;
display.drawLine (j, hauteur - sound[j - 1], j + 1, hauteur - sound[j], TFT_BLACK);
display.drawLine (j - 1, hauteur - sound[j - 1], j, hauteur - sound[j], TFT_GREEN);
}
// Affichage bornes d'amplitude
if ((ampMaxOld != ampMax) || (ampMinOld != ampMin) || erase) {
display.fillRect(0, 0, N, 15, TFT_BLACK);
char texte[25];
sprintf(texte, "Min : %3d, Max: %3d", ampMin, ampMax);
display.drawString(texte, 0, 0, 1);
ampMaxOld = ampMax;
ampMinOld = ampMin;
}
}

/*
Get "ambient" volume
*/
void calibrate() {
for (int i = 0; i < 200; i++) backgroundSound += analogRead(MIC);
backgroundSound /= 200;
// Serial.print("Threshold set at ");
// Serial.println(backgroundSound);
}

bool soundDetected() {
return abs(analogRead(MIC) - backgroundSound) >= SOUND_THRESHOLD;
}

void displaySpectrogram (bool erase, bool displayMax) {
#define nCoul 20
if (erase) {
display.fillScreen(TFT_BLACK);
display.setTextColor(TFT_BLUE);
display.setTextSize(1);
display.drawString("WAITING", 65, 40, 4);
display.drawString("FOR SOUND", 40, 70, 4);
}
const int rectW = display.width() / nTimes;
const int nbFreqD = 60;
const int decal = 15;
const int rectH = (display.height() - decal) / nbFreqD;
const uint16_t colors[nCoul] = {TFT_BLACK, TFT_BLACK, TFT_BLACK, TFT_BLACK,
TFT_BLACK, TFT_BLACK, TFT_BLACK, TFT_BLACK,
TFT_BLACK, TFT_BLACK, TFT_DARKGREEN, TFT_VIOLET,
TFT_BLUE, TFT_SKYBLUE, TFT_GREEN, TFT_GREENYELLOW,
TFT_YELLOW, TFT_GOLD, TFT_ORANGE, TFT_RED //, TFT_BROWN
};
// Wait until a sound arrives
if (erase) delay(300); // to avoid the sound of the button
if (!soundDetected()) return;
// Acquire samples over the 700ms range
for (int j = 0; j < nTimes; j++) {
for (int i = 0; i < SAMPLES; i++) {
unsigned long chrono = micros();
data2D[i][j] = analogRead(MIC);
//Serial.printf("%d %d %d\n",j,i,data2D[i][j]);
while (micros() - chrono < sampling_period_us); // do nothing
} // 12.8 ms
}
// Fourier transform and display each sound
display.fillScreen(TFT_BLACK);
for (int k = 1; k < 5; k++) display.drawString(String(k), 0, display.height() - k * 25 - decal - 8, 2);
for (int k = 0; k < 8; k++) // '8' is for 700ms
display.drawString(String((float)(k / 10.0), 1), k * 30, display.height() - 13, 2);
display.drawString("s", display.width() - 7, display.height() - 13, 2);

//Histogram
// int nb[22] = {0};

int indMax0[nTimes] = {0}; int thresh0 = 400;
int indMax1[nTimes] = {0}; int thresh1 = 800;
int indMax2[nTimes] = {0}; int thresh2 = 2000;
int indMax3[nTimes] = {0}; int thresh3 = 4000;

for (int j = 0; j < nTimes; j++) {
for (int i = 0; i < SAMPLES; i++) data[i] = (float)data2D[i][j] + I * 0.0f;
window (data, LOG2SAMPLE, HAMMING, FFT_FORWARD);
ffti_f(data, LOG2SAMPLE, FFT_FORWARD);

int amplitude[nbFreqD] = {0};
for (int i = 3; i < nbFreqD; i++) {
  amplitude[i] = abs((int)creal(data[i]));
  if (!displayMax) {
    // draw spectrogram
    int iCoul = map(amplitude[i], 0, 160, 0, nCoul - 1);
    if (iCoul < 0) iCoul = 0;
    if (iCoul > nCoul - 1) iCoul = nCoul - 1;
    //    ++nb[iCoul];
    int y = display.height() - decal - i * rectH;
    display.fillRect((j + 2) * rectW + 3, y, rectW, rectH, colors[iCoul]);
  }
}

// Search the envelopes in time - frequency
if (displayMax) {
  for (int i = nbFreqD; i > 2; i--) {
    if (amplitude[i] > thresh0 && indMax0[j] == 0) indMax0[j] = i;
    if (amplitude[i] > thresh1 && indMax1[j] == 0) indMax1[j] = i;
    if (amplitude[i] > thresh2 && indMax2[j] == 0) indMax2[j] = i;
    if (amplitude[i] > thresh3 && indMax3[j] == 0) indMax3[j] = i;
  }
}

}
// Print histogram
// for (int h = 0; h < nCoul; h++) Serial.printf("Colour %2d : %d\n", h, nb[h]);
// Serial.println();
display.drawString("kHz", 15, 0, 2);

if (!displayMax) {
// Display scale
int dx = 13;
int dy = (display.height() - 2 * decal) / 11;
for (int i = 9; i < nCoul; i++) {
int y = display.height() - (i - 9) * dy - decal * 2 - 3;
display.fillRect(display.width() - dx, y, dx, dy - 3, colors[i]);
display.drawRect(display.width() - dx, y, dx, dy - 3, TFT_WHITE);
}
} else {
// Display envelopes
int xp = 2 * rectW + 3;
int yp = display.height() - decal - indMax0[0] * rectH;
for (int j = 1; j < nTimes; j++) {
int x = (j + 2) * rectW + 3;
int y = display.height() - decal - indMax0[j] * rectH;
display.drawLine(xp, yp, x, y, TFT_RED);
xp = x;
yp = y;
}
xp = 2 * rectW + 3;
yp = display.height() - decal - indMax1[0] * rectH;
for (int j = 1; j < nTimes; j++) {
int x = (j + 2) * rectW + 3;
int y = display.height() - decal - indMax1[j] * rectH;
display.drawLine(xp, yp, x, y, TFT_CYAN);
xp = x;
yp = y;
}
xp = 2 * rectW + 3;
yp = display.height() - decal - indMax2[0] * rectH;
for (int j = 1; j < nTimes; j++) {
int x = (j + 2) * rectW + 3;
int y = display.height() - decal - indMax2[j] * rectH;
display.drawLine(xp, yp, x, y, TFT_BLUE);
xp = x;
yp = y;
}
xp = 2 * rectW + 3;
yp = display.height() - decal - indMax3[0] * rectH;
for (int j = 1; j < nTimes; j++) {
int x = (j + 2) * rectW + 3;
int y = display.height() - decal - indMax3[j] * rectH;
display.drawLine(xp, yp, x, y, TFT_GREEN);
xp = x;
yp = y;
}
}

}

params.h

/* Windowing type /
#define RECTANGLE 0x00 /
rectangle (Box car) /
#define HAMMING 0x01 /
hamming /
#define HANN 0x02 /
hann /
#define TRIANGLE 0x03 /
triangle (Bartlett) /
#define NUTTALL 0x04 /
nuttall /
#define BLACKMAN 0x05 /
blackman /
#define BLACKMAN_NUTTALL 0x06 /
blackman nuttall /
#define BLACKMAN_HARRIS 0x07 /
blackman harris*/
#define FLT_TOP 0x08 /* flat top /
#define WELCH 0x09 /
welch */

// FFT parameters
#define SAMPLES 256
#define MAX_FREQ 20 // kHz
// Attenuation for display
#define COEF 60
#define COEF2 5
#define COEF3 3
#define SILENCE 1426
#define SENSITIVITY 30 // decrease for better sensitivity
#define SOUND_THRESHOLD 150

Since you didn't put your code in a <CODE/> block so that it could be easily copied out and tried, or even include the error(s) you're seeing, about the only thing you've given us to go on is: old code on an ESP32. So I'm going to guess (and it's just a guess) is that you've run into the proverbial breaking changes caused by the introduction of the ESP32 v3 core.

If that is indeed what is happening, a thorough read through of Migration from 2.x to 3.0 might be helpful.

Please edit your post to add code tags ( <code> icon in post editor).

Also post the full error messages, using code or quote tags.

If you do come back for help, when you put your code in tags it helps if you apply the IDE Autoformat tool first.

It will put your code into a one of the commonly used formats and make the code easier to read as well as making some errors more obvious.

TIA

a7

a7, I will do so. Thanks.

In the IDE click on Edit, then Copy for Forum. That will copy your code for this forum. Then just come back to the forum and do a paste.

As Jim P suggested, here's the copy paste from the IDE:

/*  Sound analyzer
    Several display modes (spectrum, sound amplitude, envelope)
    (by) Lesept October 2020

    TFT_eSPI:
    In the file TFT_eSPI/User_Setup_Select.h
    comment this line: #include <User_Setup.h>
    and uncomment this line: #include <User_Setups/Setup25_TTGO_T_Display.h>
*/
#include <Arduino.h>
#include <driver/adc.h>
#include <complex.h>
#define FREQ2IND (SAMPLES * 1.0 / MAX_FREQ)
#include "params.h"
#include <TFT_eSPI.h>
#include <SPI.h>
#define MIC 32

//Display parameters
#ifndef TFT_DISPOFF
#define TFT_DISPOFF 0x28
#endif

#ifndef TFT_SLPIN
#define TFT_SLPIN   0x10
#endif

#define TFT_MOSI            19
#define TFT_SCLK            18
#define TFT_CS              5
#define TFT_DC              16
#define TFT_RST             23

#define TFT_BL              4   // Display backlight control pin
#define ADC_EN              14  // ADC_EN is the ADC detection enable port
#define ADC_PIN             34
#define BUTTON_1            35
#define BUTTON_2            0

TFT_eSPI display = TFT_eSPI(135, 240); // Invoke custom library

unsigned long chrono, chrono1;
unsigned long sampling_period_us;
byte peak[SAMPLES] = {0};
float _Complex data[SAMPLES];
const int nTimes = 54; // number of acquisitions in a row (700 ms total)
uint16_t data2D[SAMPLES][nTimes];
int sound[SAMPLES];
float MULT = MAX_FREQ * 1000.0 / SAMPLES;
unsigned int P2P = 0;
const int LOG2SAMPLE = log(SAMPLES) / log(2);
int32_t backgroundSound = 0;
#include "functions.h"
#define MODE 19
#define MAXMODES 7

void setup() {
  Serial.begin(115200);
  pinMode(BUTTON_1, INPUT_PULLUP);
  pinMode(BUTTON_2, INPUT_PULLUP);
  adc1_config_width(ADC_WIDTH_BIT_12);
  // ADC1 Channel 4 is GPIO 32 (microphone)
  // https://microcontrollerslab.com/wp-content/uploads/2019/03/ESP32-ADC-channels-pinout.jpg
  adc1_config_channel_atten(ADC1_CHANNEL_4, ADC_ATTEN_DB_11);
  calibrate();
  display.init();
  display.fillScreen(TFT_BLACK);
  display.setRotation(3);
  display.setTextColor(TFT_BLUE);
  display.drawString("on ESP32", 20, 110, 4); // Splash screen
  display.setTextSize(2);
  display.drawString("SONO", 0, 10, 4);
  display.drawString("METER", 68, 60, 4);
  display.setTextSize(1);
  display.setTextColor(TFT_RED);
  display.drawString("[by Lesept]", 165, 120, 2);
  Serial.println("SonoMeter on ESP32");
  delay(2000);
  sampling_period_us = round(1000ul * (1.0 / MAX_FREQ));
  chrono1 = millis();
}

void loop() {
  static int modes = 0;
  bool changeMode = false;
  // Push the button to change modes
  if (millis() - chrono1 > 1000ul) {
    if (digitalRead(BUTTON_1) == LOW) { // Modes up
      delay(30);
      modes = (modes + 1) % MAXMODES;
      changeMode = true;
      chrono1 = millis();
    } else if (digitalRead(BUTTON_2) == LOW) { // Modes down
      delay(30);
      modes = (modes - 1 + MAXMODES) % MAXMODES;
      changeMode = true;
      chrono1 = millis();
    }
  }
  switch (modes) {
    case 0: // Display spectrum
      acquireSound();
      displaySpectrum();
      break;
    case 1: // Display spectrum
      acquireSound();
      displaySpectrum2();
      break;
    case 2: // Display amplitude with bars
      displayAmplitudeBars();
      break;
    case 3: // Display envelope
      displayEnvelope(changeMode);
      break;
    case 4: // Display running amplitude
      displayRunningEnvelope(changeMode);
      break;
    case 5: // Display Spectrogram
      displaySpectrogram (changeMode, false);
      break;
    case 6: // Display Spectrogram with maxima in circles
      displaySpectrogram (changeMode, true);
      break;
     default:
      break;
  }
  // Touch GPIO 15 to stop the display
  const int touchPin = 15;
  const int threshold = 90;
  if (touchRead(touchPin) < threshold) while (touchRead(touchPin) < threshold);
}

And the rest of it:

typedef enum fft_dir {
  FFT_FORWARD,    /* kernel uses "-1" sign */
  FFT_INVERSE     /* kernel uses "+1" sign */
} fft_dir;

void window (float _Complex *data, unsigned int log2_N, byte windowType, fft_dir direction) {
  unsigned int N = 1 << log2_N;
  unsigned int Nd2 = N >> 1;
  for (int i = 0; i < Nd2; i++) {
    double indexMinusOne = double(i);
    double ratio = (indexMinusOne / (N - 1));
    double weighingFactor = 1.0;
    // Compute and record weighting factor
    switch (windowType) {
      case RECTANGLE: // rectangle (box car)
        weighingFactor = 1.0;
        break;
      case HAMMING: // hamming
        weighingFactor = 0.54 - (0.46 * cos(2 * PI * ratio));
        break;
      case HANN: // hann
        weighingFactor = 0.54 * (1.0 - cos(2 * PI * ratio));
        break;
      case TRIANGLE: // triangle (Bartlett)
        weighingFactor = 1.0 - ((2.0 * abs(indexMinusOne - ((N - 1) / 2.0))) / (N - 1));
        break;
      case NUTTALL: // nuttall
        weighingFactor = 0.355768 - (0.487396 * (cos(2 * PI * ratio))) + (0.144232 * (cos(4 * PI * ratio))) - (0.012604 * (cos(6 * PI * ratio)));
        break;
      case BLACKMAN: // blackman
        weighingFactor = 0.42323 - (0.49755 * (cos(2 * PI * ratio))) + (0.07922 * (cos(4 * PI * ratio)));
        break;
      case BLACKMAN_NUTTALL: // blackman nuttall
        weighingFactor = 0.3635819 - (0.4891775 * (cos(2 * PI * ratio))) + (0.1365995 * (cos(4 * PI * ratio))) - (0.0106411 * (cos(6 * PI * ratio)));
        break;
      case BLACKMAN_HARRIS: // blackman harris
        weighingFactor = 0.35875 - (0.48829 * (cos(2 * PI * ratio))) + (0.14128 * (cos(4 * PI * ratio))) - (0.01168 * (cos(6 * PI * ratio)));
        break;
      case FLT_TOP: // flat top
        weighingFactor = 0.2810639 - (0.5208972 * cos(2 * PI * ratio)) + (0.1980399 * cos(4 * PI * ratio));
        break;
      case WELCH: // welch
        weighingFactor = 1.0 - sq((indexMinusOne - (N - 1) / 2.0) / ((N - 1) / 2.0));
        break;
    }
    if (direction == FFT_FORWARD) {
      data[i] *= weighingFactor;
      data[N - (i + 1)] *= weighingFactor;
    }
    else {
      data[i] /= weighingFactor;
      data[N - (i + 1)] /= weighingFactor;
    }
  }
}

void ffti_shuffle_f(float _Complex *data, unsigned int log2_N)
{
  /*
     Basic Bit-Reversal Scheme:

     The incrementing pattern operations used here correspond
     to the logic operations of a synchronous counter.

     Incrementing a binary number simply flips a sequence of
     least-significant bits, for example from 0111 to 1000.
     So in order to compute the next bit-reversed index, we
     have to flip a sequence of most-significant bits.
  */

  unsigned int N = 1 << log2_N;   /* N */
  unsigned int Nd2 = N >> 1;      /* N/2 = number range midpoint */
  unsigned int Nm1 = N - 1;       /* N-1 = digit mask */
  unsigned int i;                 /* index for array elements */
  unsigned int j;                 /* index for next element swap location */

  for (i = 0, j = 0; i < N; i++) {
    if (j > i) {
      float _Complex tmp = data[i];
      data[i] = data[j];
      data[j] = tmp;
    }

    /*
       Find least significant zero bit
    */

    unsigned int lszb = ~i & (i + 1);

    /*
       Use division to bit-reverse the single bit so that we now have
       the most significant zero bit

       N = 2^r = 2^(m+1)
       Nd2 = N/2 = 2^m
       if lszb = 2^k, where k is within the range of 0...m, then
           mszb = Nd2 / lszb
                = 2^m / 2^k
                = 2^(m-k)
                = bit-reversed value of lszb
    */

    unsigned int mszb = Nd2 / lszb;

    /*
       Toggle bits with bit-reverse mask
    */

    unsigned int bits = Nm1 & ~(mszb - 1);
    j ^= bits;
  }
}



void ffti_evaluate_f(float _Complex *data, unsigned int log2_N, fft_dir direction)
{
  /*
     In-place FFT butterfly algorithm

     input:
         A[] = array of N shuffled complex values where N is a power of 2
     output:
         A[] = the DFT of input A[]

     for r = 1 to log2(N)
         m = 2^r
         Wm = exp(−j2π/m)
         for n = 0 to N-1 by m
             Wmk = 1
             for k = 0 to m/2 - 1
                 u = A[n + k]
                 t = Wmk * A[n + k + m/2]
                 A[n + k]       = u + t
                 A[n + k + m/2] = u - t
                 Wmk = Wmk * Wm

     For inverse FFT, use Wm = exp(+j2π/m)
  */

  unsigned int N = 1 << log2_N;
  double theta_2pi = (direction == FFT_FORWARD) ? -PI : PI;
  theta_2pi *= 2;

  for (unsigned int r = 1; r <= log2_N; r++)
  {
    unsigned int m = 1 << r;
    unsigned int md2 = m >> 1;
    double theta = theta_2pi / m;
    double re = cos(theta);
    double im = sin(theta);
    double complex Wm = re + I * im;
    for (unsigned int n = 0; n < N; n += m) {
      double complex Wmk = 1.0f;   /* Use double for precision */
      for (unsigned int k = 0; k < md2; k++) {
        unsigned int i_e = n + k;
        unsigned int i_o = i_e + md2;
        double complex t = Wmk * data[i_o];
        data[i_o] = data[i_e] - t;
        data[i_e] = data[i_e] + t;
        t = Wmk * Wm;
        Wmk = t;
      }
    }
  }
}

void ffti_f(float complex data[], unsigned int log2_N, fft_dir direction)
{
  ffti_shuffle_f(data, log2_N);
  ffti_evaluate_f(data, log2_N, direction);
}

void acquireSound () {
  for (int i = 0; i < SAMPLES; i++) {
    unsigned long chrono = micros();
    data[i] = analogRead(MIC);
    while (micros() - chrono < sampling_period_us); // do nothing
  } // 12.8 ms
}

void displaySpectrum () {
  window (data, LOG2SAMPLE, HAMMING, FFT_FORWARD);
  ffti_f(data, LOG2SAMPLE, FFT_FORWARD);
  // window + FFT last 10ms
  int nFreq = SAMPLES / 2;
  int hauteur = display.height();
  display.fillScreen(TFT_BLACK);
  display.setTextColor(TFT_WHITE);
  display.setTextSize(1);
  const float freqs[7] = {.5, 1, 2, 3, 4, 6, 8};
  for (int i = 0; i < 7; i++) {
    int pos =  FREQ2IND * freqs[i] * 1.9 ;
    if (i == 0) display.drawString(".5", pos - 5, hauteur - 13, 2);
    else display.drawString(String(freqs[i], 0), pos, hauteur - 13, 2);
  }
  display.drawString("kHz", display.width() - 22, hauteur - 13, 2);

  const int decal = 15;
  // Affichage du spectre
  int ampmax = 0;
  int imax = 0;
  for (int i = 2; i < nFreq; i++) {
    int amplitude = (int)creal(data[i]) / COEF;
    if (amplitude > ampmax) {
      ampmax = amplitude;
      imax = i;
    }
    amplitude = min(amplitude, hauteur - decal);
    display.drawFastVLine (i * 2, hauteur - amplitude - decal, amplitude, TFT_GREEN);
  }

  // Affichage fréquence de plus forte amplitude
  if (ampmax > 20) {
    display.setTextSize(2);
    display.setTextColor(TFT_BLUE);
    int freqmax = 985.0 * imax * MAX_FREQ / SAMPLES;
    char texte[14];
    sprintf(texte, "%4d Hz: %3d", freqmax, ampmax);
    display.drawString(texte, display.width() - 145, 0, 1);
  }

  // Affichage et décroissance des valeurs peak
  for (int i = 2; i < nFreq - 4; i = i + 4) {
    int amplitude = (int)creal(data[i]);
    amplitude = max(amplitude, (int)creal(data[i + 1]));
    amplitude = max(amplitude, (int)creal(data[i + 2]));
    amplitude = max(amplitude, (int)creal(data[i + 3]));
    amplitude /= COEF;
    if (amplitude > peak[i]) peak[i] = amplitude;
    if (peak[i] > hauteur - decal) peak[i] = hauteur - decal;
    if (peak[i] > 8) {
      peak[i] -= 2; // Decay the peak
      display.drawFastHLine(i * 2, hauteur - peak[i] - decal, 4, TFT_RED);
    }
  }
}

void rectangleGR (int x0, int w, int h) {
  const uint16_t colors[8] = {TFT_DARKGREEN, TFT_GREEN, TFT_GREENYELLOW, TFT_YELLOW,
                              TFT_GOLD, TFT_ORANGE, TFT_RED, TFT_BROWN
                             };
  const int decal = 15;
  int x = x0 * (w + 2);
  int dh = (display.height() - decal) / 8;
  for (int i = 1; i < 8; i++) {
    if (h > i * dh) {
      int y = display.height() - decal - i * dh;
      display.fillRect(x, y, w, dh, colors[i - 1]);
    } else {
      int y = display.height() - decal - h;
      display.fillRect(x, y, w, h - (i - 1) * dh, colors[i - 1]);
      break;
    }
  }
}

void displaySpectrum2 () {
  window (data, LOG2SAMPLE, HAMMING, FFT_FORWARD);
  ffti_f(data, LOG2SAMPLE, FFT_FORWARD);
  int nFreq = SAMPLES / 2;
  int hauteur = display.height();
  display.fillScreen(TFT_BLACK);
  display.setTextColor(TFT_WHITE);
  display.setTextSize(1);
  const float freqs[6] = {.5, 1, 1.5, 2, 3, 4};
  for (int i = 0; i < 6; i++) {
    int pos =  FREQ2IND * freqs[i] * 3.5 ;
    if (i == 0) display.drawString(".5", pos - 5, hauteur - 13, 2);
    else if (i == 1) display.drawString("1", pos - 10, hauteur - 13, 2);
    else if (i == 2) display.drawString("1.5", pos - 5, hauteur - 13, 2);
    else display.drawString(String(freqs[i], 0), pos, hauteur - 13, 2);
  }
  display.drawString("kHz", display.width() - 22, hauteur - 13, 2);

  const int decal = 15;
  // Affichage du spectre
  for (int i = 0; i < 16; i++) {
    int amplitude = 0;
    for (int j = 0; j < 4; j++) amplitude += abs((int)creal(data[i * 4 + j + 2]) / COEF);
    amplitude = min(amplitude, hauteur - decal);
    rectangleGR (i, 13, amplitude);
  }
}

void displayAmplitudeBars() {
  const uint16_t colors[8] = {TFT_DARKGREEN, TFT_GREEN, TFT_GREENYELLOW, TFT_YELLOW,
                              TFT_GOLD, TFT_ORANGE, TFT_RED, TFT_BROWN
                             };
  int ampmax = -5000;
  int ampmin =  5000;
  int N = display.width();
  int decal = 15;
  int hauteur = display.height() - decal;
  for (int i = 0; i < N; i++) {
    sound[i] = analogRead(MIC);
    delayMicroseconds(50);
  }
  display.fillScreen(TFT_BLACK);
  int prevamp = 1;
  for (int i = 0; i < N; i++) {
    uint16_t colour;
    //    colour = TFT_GREEN;
    //    colour = colors[(i / 10) % 8];
    uint16_t red  = 0b11111;
    uint16_t red2 = 0b00001;
    if (i < N / 2) colour = (red - i * (red - red2) * 2 / N) << 11;
    else colour = (i + N / 2) * 32 / N;
    int amplitude = (sound[i] - SILENCE) / COEF2;
    constrain(amplitude, -hauteur / 2, hauteur / 2);
    if (amplitude > ampmax) ampmax = amplitude;
    if (amplitude < ampmin) ampmin = amplitude;
    display.drawFastVLine (i, hauteur / 2 - amplitude + decal, abs(amplitude), colour);
    if (amplitude * prevamp < 0 && i > 0)
      display.drawLine(i - 1, hauteur / 2 - prevamp + decal, i, hauteur / 2 - amplitude + decal, colour);
  }
  // Affichage plus forte amplitude
  display.setTextColor(TFT_BLUE);
  display.setTextSize(2);
  char texte[25];
  sprintf(texte, "Min: %3d, Max: %3d", ampmin, ampmax);
  display.drawString(texte, 10, 0, 1);
  delay(50);
}

void displayEnvelope(bool erase) {
  static int i = 0;
  if (i == 1 || erase) display.fillScreen(TFT_BLACK);
  const int decal = 15;
  const int hauteur = display.height();
  const int N = display.width();
  static unsigned int maxP2P = 0;
  static unsigned int minP2P = 5000;
  static unsigned int maxP2Pold = 0;
  static unsigned int minP2Pold = 5000;
  static int amplitudeold = 0;

  if (i >= N || erase) {
    i = 0;
    maxP2P = 0;
    minP2P = 5000;
    maxP2Pold = 0;
    minP2Pold = 5000;
  }

  unsigned int signalMax = 0;
  unsigned int signalMin = 4096;
  unsigned long chrono = micros(); // Sample window 10ms
  while (micros() - chrono < 10000ul) {
    int sample = analogRead(MIC) / COEF3;
    if (sample > signalMax) signalMax = sample;
    else if (sample < signalMin) signalMin = sample;
  }
  unsigned int peakToPeak = signalMax - signalMin;
  int amplitude = peakToPeak - SENSITIVITY;
  if (amplitude < 0) amplitude = 0;
  else if (amplitude > 500) amplitude = 500;
  int ampPrev = map(amplitudeold, 0, 500, hauteur - 1, decal);
  int amp     = map(amplitude,    0, 500, hauteur - 1, decal);
  if (amplitude > maxP2P) maxP2P = amplitude;
  if (amplitude < minP2P) minP2P = amplitude;
  if (i > 0) display.drawLine (i - 1, ampPrev, i, amp, TFT_GREEN);
  amplitudeold = amplitude;
  // Affichage plus forte amplitude
  if ((maxP2Pold != maxP2P) || (minP2Pold != minP2P) || (i == 0)) {
    display.fillRect(0, 0, N, 15, TFT_BLACK);
    display.setTextColor(TFT_BLUE);
    char texte[25];
    sprintf(texte, "Min : %3d, Max: %3d", minP2P, maxP2P);
    display.drawString(texte, 0, 0, 1);
  }
  maxP2Pold = maxP2P;
  minP2Pold = minP2P;
  ++i;
}

void displayRunningEnvelope(bool erase) {
  if (erase) display.fillScreen(TFT_BLACK);
  static int ampMaxOld = 0;
  static int ampMinOld = 1024;
  const int decal = 15;
  const int hauteur = display.height();
  const int N = display.width();
  static int sound[240] = {0};
  int save = sound[0];
  for (int i = 0; i < N - 1 ; i++) sound[i] = sound[i + 1];

  unsigned int signalMax = 0;
  unsigned int signalMin = 4096;
  unsigned long chrono = micros(); // Sample window 10ms
  while (micros() - chrono < 10000ul) {
    int sample = analogRead(MIC) / COEF3;
    if (sample > signalMax) signalMax = sample;
    else if (sample < signalMin) signalMin = sample;
  }
  unsigned int peakToPeak = signalMax - signalMin;
  int x = peakToPeak - SENSITIVITY;
  if (x < 0)   x = 0;
  if (x > 500) x = 500;
  sound[N - 1] = map(x, 0, 500, 1, hauteur - decal);

  int ampMin = 500;
  int ampMax = 0;
  display.drawLine (0, hauteur - save, 1, hauteur - sound[0], TFT_BLACK);
  for (int j = 1; j < N; j++) {
    if (sound[j] > ampMax) ampMax = sound[j];
    if (sound[j] < ampMin) ampMin = sound[j];
    if (ampMin == 1) ampMin = 0;
    display.drawLine (j, hauteur - sound[j - 1], j + 1, hauteur - sound[j], TFT_BLACK);
    display.drawLine (j - 1, hauteur - sound[j - 1], j, hauteur - sound[j], TFT_GREEN);
  }
  // Affichage bornes d'amplitude
  if ((ampMaxOld != ampMax) || (ampMinOld != ampMin) || erase) {
    display.fillRect(0, 0, N, 15, TFT_BLACK);
    char texte[25];
    sprintf(texte, "Min : %3d, Max: %3d", ampMin, ampMax);
    display.drawString(texte, 0, 0, 1);
    ampMaxOld = ampMax;
    ampMinOld = ampMin;
  }
}

/*
    Get "ambient" volume
*/
void calibrate() {
  for (int i = 0; i < 200; i++) backgroundSound += analogRead(MIC);
  backgroundSound /= 200;
  //  Serial.print("Threshold set at ");
  //  Serial.println(backgroundSound);
}

bool soundDetected() {
  return abs(analogRead(MIC) - backgroundSound) >= SOUND_THRESHOLD;
}

void displaySpectrogram (bool erase, bool displayMax) {
#define nCoul 20
  if (erase) {
    display.fillScreen(TFT_BLACK);
    display.setTextColor(TFT_BLUE);
    display.setTextSize(1);
    display.drawString("WAITING", 65, 40, 4);
    display.drawString("FOR SOUND", 40, 70, 4);
  }
  const int rectW = display.width() / nTimes;
  const int nbFreqD = 60;
  const int decal = 15;
  const int rectH = (display.height() - decal) / nbFreqD;
  const uint16_t colors[nCoul] = {TFT_BLACK, TFT_BLACK, TFT_BLACK, TFT_BLACK,
                                  TFT_BLACK, TFT_BLACK, TFT_BLACK, TFT_BLACK,
                                  TFT_BLACK, TFT_BLACK, TFT_DARKGREEN, TFT_VIOLET,
                                  TFT_BLUE, TFT_SKYBLUE, TFT_GREEN, TFT_GREENYELLOW,
                                  TFT_YELLOW, TFT_GOLD, TFT_ORANGE, TFT_RED //, TFT_BROWN
                                 };
  // Wait until a sound arrives
  if (erase) delay(300); // to avoid the sound of the button
  if (!soundDetected()) return;
  // Acquire samples over the 700ms range
  for (int j = 0; j < nTimes; j++) {
    for (int i = 0; i < SAMPLES; i++) {
      unsigned long chrono = micros();
      data2D[i][j] = analogRead(MIC);
      //Serial.printf("%d %d %d\n",j,i,data2D[i][j]);
      while (micros() - chrono < sampling_period_us); // do nothing
    } // 12.8 ms
  }
  // Fourier transform and display each sound
  display.fillScreen(TFT_BLACK);
  for (int k = 1; k < 5; k++) display.drawString(String(k), 0, display.height() - k * 25 - decal - 8, 2);
  for (int k = 0; k < 8; k++) // '8' is for 700ms
    display.drawString(String((float)(k / 10.0), 1), k * 30, display.height() - 13, 2);
  display.drawString("s", display.width() - 7, display.height() - 13, 2);

  //Histogram
  // int nb[22] = {0};

  int indMax0[nTimes] = {0}; int thresh0 =  400;
  int indMax1[nTimes] = {0}; int thresh1 =  800;
  int indMax2[nTimes] = {0}; int thresh2 = 2000;
  int indMax3[nTimes] = {0}; int thresh3 = 4000;

  for (int j = 0; j < nTimes; j++) {
    for (int i = 0; i < SAMPLES; i++) data[i] = (float)data2D[i][j] + I * 0.0f;
    window (data, LOG2SAMPLE, HAMMING, FFT_FORWARD);
    ffti_f(data, LOG2SAMPLE, FFT_FORWARD);

    int amplitude[nbFreqD] = {0};
    for (int i = 3; i < nbFreqD; i++) {
      amplitude[i] = abs((int)creal(data[i]));
      if (!displayMax) {
        // draw spectrogram
        int iCoul = map(amplitude[i], 0, 160, 0, nCoul - 1);
        if (iCoul < 0) iCoul = 0;
        if (iCoul > nCoul - 1) iCoul = nCoul - 1;
        //    ++nb[iCoul];
        int y = display.height() - decal - i * rectH;
        display.fillRect((j + 2) * rectW + 3, y, rectW, rectH, colors[iCoul]);
      }
    }

    // Search the envelopes in time - frequency
    if (displayMax) {
      for (int i = nbFreqD; i > 2; i--) {
        if (amplitude[i] > thresh0 && indMax0[j] == 0) indMax0[j] = i;
        if (amplitude[i] > thresh1 && indMax1[j] == 0) indMax1[j] = i;
        if (amplitude[i] > thresh2 && indMax2[j] == 0) indMax2[j] = i;
        if (amplitude[i] > thresh3 && indMax3[j] == 0) indMax3[j] = i;
      }
    }

  }
  // Print histogram
  //  for (int h = 0; h < nCoul; h++) Serial.printf("Colour %2d : %d\n", h, nb[h]);
  //  Serial.println();
  display.drawString("kHz", 15, 0, 2);

  if (!displayMax) {
    // Display scale
    int dx = 13;
    int dy = (display.height() - 2 * decal) / 11;
    for (int i = 9; i < nCoul; i++) {
      int y = display.height() - (i - 9) * dy - decal * 2 - 3;
      display.fillRect(display.width() - dx, y, dx, dy - 3, colors[i]);
      display.drawRect(display.width() - dx, y, dx, dy - 3, TFT_WHITE);
    }    
  } else {
    // Display envelopes
    int xp = 2 * rectW + 3;
    int yp = display.height() - decal - indMax0[0] * rectH;
    for (int j = 1; j < nTimes; j++) {
      int x = (j + 2) * rectW + 3;
      int y = display.height() - decal - indMax0[j] * rectH;
      display.drawLine(xp, yp, x, y, TFT_RED);
      xp = x;
      yp = y;
    }
    xp = 2 * rectW + 3;
    yp = display.height() - decal - indMax1[0] * rectH;
    for (int j = 1; j < nTimes; j++) {
      int x = (j + 2) * rectW + 3;
      int y = display.height() - decal - indMax1[j] * rectH;
      display.drawLine(xp, yp, x, y, TFT_CYAN);
      xp = x;
      yp = y;
    }
    xp = 2 * rectW + 3;
    yp = display.height() - decal - indMax2[0] * rectH;
    for (int j = 1; j < nTimes; j++) {
      int x = (j + 2) * rectW + 3;
      int y = display.height() - decal - indMax2[j] * rectH;
      display.drawLine(xp, yp, x, y, TFT_BLUE);
      xp = x;
      yp = y;
    }
    xp = 2 * rectW + 3;
    yp = display.height() - decal - indMax3[0] * rectH;
    for (int j = 1; j < nTimes; j++) {
      int x = (j + 2) * rectW + 3;
      int y = display.height() - decal - indMax3[j] * rectH;
      display.drawLine(xp, yp, x, y, TFT_GREEN);
      xp = x;
      yp = y;
    }
  }

}

/* Windowing type */
#define RECTANGLE 0x00 /* rectangle (Box car) */
#define HAMMING 0x01 /* hamming */
#define HANN 0x02 /* hann */
#define TRIANGLE 0x03 /* triangle (Bartlett) */
#define NUTTALL 0x04 /* nuttall */
#define BLACKMAN 0x05 /* blackman */
#define BLACKMAN_NUTTALL 0x06 /* blackman nuttall */
#define BLACKMAN_HARRIS 0x07 /* blackman harris*/
#define FLT_TOP 0x08 /* flat top */
#define WELCH 0x09 /* welch */

// FFT parameters
#define SAMPLES 256
#define MAX_FREQ 20 // kHz
// Attenuation for display
#define COEF 60
#define COEF2 5
#define COEF3 3
#define SILENCE 1426
#define SENSITIVITY 30 // decrease for better sensitivity
#define SOUND_THRESHOLD 150

I'm newish to the forum and I appreciate your patience!

Done.

Post the complete error message(s).

In file included from C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\SoundAnalyzer_ESP32_TTGO.ino:53:
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h: In function 'void ffti_evaluate_f(__complex__ float*, unsigned int, fft_dir)':
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:152:20: error: expected initializer before 'Wm'
  152 |     double complex Wm = re + I * im;
      |                    ^~
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:154:22: error: expected initializer before 'Wmk'
  154 |       double complex Wmk = 1.0f;   /* Use double for precision */
      |                      ^~~
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:158:24: error: expected initializer before 't'
  158 |         double complex t = Wmk * data[i_o];
      |                        ^
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:159:33: error: 't' was not declared in this scope
  159 |         data[i_o] = data[i_e] - t;
      |                                 ^
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:161:13: error: 'Wmk' was not declared in this scope
  161 |         t = Wmk * Wm;
      |             ^~~
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:161:19: error: 'Wm' was not declared in this scope; did you mean 'im'?
  161 |         t = Wmk * Wm;
      |                   ^~
      |                   im
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h: At global scope:
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:168:27: error: expected ',' or '...' before 'data'
  168 | void ffti_f(float complex data[], unsigned int log2_N, fft_dir direction)
      |                           ^~~~
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h: In function 'void ffti_f(float)':
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:170:24: error: 'log2_N' was not declared in this scope; did you mean 'log_n'?
  170 |   ffti_shuffle_f(data, log2_N);
      |                        ^~~~~~
      |                        log_n
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:171:33: error: 'direction' was not declared in this scope; did you mean 'sigaction'?
  171 |   ffti_evaluate_f(data, log2_N, direction);
      |                                 ^~~~~~~~~
      |                                 sigaction
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h: In function 'void displaySpectrum()':
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:184:10: error: cannot convert '__complex__ float*' to 'float'
  184 |   ffti_f(data, LOG2SAMPLE, FFT_FORWARD);
      |          ^~~~
      |          |
      |          __complex__ float*
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:168:19: note:   initializing argument 1 of 'void ffti_f(float)'
  168 | void ffti_f(float complex data[], unsigned int log2_N, fft_dir direction)
      |             ~~~~~~^~~~~~~
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:204:26: error: 'creal' was not declared in this scope; did you mean 'creat'?
  204 |     int amplitude = (int)creal(data[i]) / COEF;
      |                          ^~~~~
      |                          creat
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:225:26: error: 'creal' was not declared in this scope; did you mean 'creat'?
  225 |     int amplitude = (int)creal(data[i]);
      |                          ^~~~~
      |                          creat
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h: In function 'void displaySpectrum2()':
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:260:10: error: cannot convert '__complex__ float*' to 'float'
  260 |   ffti_f(data, LOG2SAMPLE, FFT_FORWARD);
      |          ^~~~
      |          |
      |          __complex__ float*
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:168:19: note:   initializing argument 1 of 'void ffti_f(float)'
  168 | void ffti_f(float complex data[], unsigned int log2_N, fft_dir direction)
      |             ~~~~~~^~~~~~~
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:280:55: error: 'creal' was not declared in this scope; did you mean 'creat'?
  280 |     for (int j = 0; j < 4; j++) amplitude += abs((int)creal(data[i * 4 + j + 2]) / COEF);
      |                                                       ^~~~~
      |                                                       creat
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h: In function 'void displaySpectrogram(bool, bool)':
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:484:71: error: 'I' was not declared in this scope
  484 |     for (int i = 0; i < SAMPLES; i++) data[i] = (float)data2D[i][j] + I * 0.0f;
      |                                                                       ^
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:486:12: error: cannot convert '__complex__ float*' to 'float'
  486 |     ffti_f(data, LOG2SAMPLE, FFT_FORWARD);
      |            ^~~~
      |            |
      |            __complex__ float*
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:168:19: note:   initializing argument 1 of 'void ffti_f(float)'
  168 | void ffti_f(float complex data[], unsigned int log2_N, fft_dir direction)
      |             ~~~~~~^~~~~~~
C:\Users\propg\Desktop\arduino-ide_2.3.4\Arduino IDE\SoundAnalyzer_ESP32_TTGO\functions.h:490:31: error: 'creal' was not declared in this scope; did you mean 'creat'?
  490 |       amplitude[i] = abs((int)creal(data[i]));
      |                               ^~~~~
      |                               creat

exit status 1

Compilation error: expected initializer before 'Wm'

Many of those errors are typical of copy/paste problems. Take a close look at the code associated with each message, especially the preceding code, and try to determine why the compiler is complaining (extra or missing characters, etc.).

Some error messages are self explanatory, for example error: 'log2_N' was not declared in this scope;

Perhaps you are trying to compile parts of the code independently, which won't work without the proper declarations and definitions.

Naturally, you need to use the same ESP32 board, board definition, display and libraries that the author used, or make suitable modifications to match what you actually have.

Anyone else have an opinion on my issues?

Your declaration of complex variables is inconsistent; sometimes "complex", sometimes "_Complex", plus the mix of float and double.

I'm not familiar enough with the complex library to say whether that's intentional but subtly wrong, or just wrong...

Hmm. But "...packages/esp32/tools/esp-x32/2302/xtensa-esp32-elf/include/complex.h" has aliases:

#define complex _Complex
#define _Complex_I 1.0fi
#define I _Complex_I

Which leads me to think that you are not getting the "complex.h" that you think you're getting! (It also doesn't like I or creal()...)

Cut&pasting the compile command and changing -c to -E, I see:

# 17 "...packages/esp32/tools/esp32-arduino-libs/idf-release_v5.1-b6b4727c58/esp32/include/espressif__esp-tflite-micro/signal/src/complex.h"

which is, sure enough, a very different and very minimal version.

I don't know offhand how to fix that. Perhaps you can just delete the tflite-micro directory...

Thanks for that westfw. Makes sense. I'll take a look.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.