ESP32-S3 + INMP441 on PlatformIO; build/upload OK and model runs, but I2S samples are always zero, ESP32-S3-DevKitC-1-N16R8V, INMP441 wired BCLK=GPI

.ino file

#define I2S_BCK_PIN 17 // Bit clock
#define I2S_WS_PIN 18 // Word select
#define I2S_SD_PIN 16 // Serial data
#define I2S_PORT I2S_NUM_0
this is my hardware config

.cpp file

AudioProcessor::AudioProcessor(int bckPin, int wsPin, int sdPin,

                           float input_scale, int input_zero_point, i2s_port_t port)

: _audio_buffer(nullptr), _i2sPort(port), _sampleRate(0),

  _write_index(0), _samples_collected(0),

  _frame_position(0), _hop_counter(0),

  _input_scale(input_scale), _input_zero_point(input_zero_point)

{

_pinConfig.bck_io_num = bckPin;

_pinConfig.ws_io_num = wsPin;

_pinConfig.data_out_num = I2S_PIN_NO_CHANGE;

_pinConfig.data_in_num = sdPin;



memset(_frame_buffer, 0, sizeof(_frame_buffer));

}

AudioProcessor::~AudioProcessor()

{

i2s_driver_uninstall(_i2sPort);

}

bool AudioProcessor::begin(int sampleRate)

{

_sampleRate = sampleRate;



Serial.println("Initializing Audio Processor...");

Serial.printf("Sample rate: %d Hz\n", _sampleRate);

Serial.printf("Analysis window: %d seconds\n", ANALYSIS_SECONDS);

Serial.printf("Buffer size: %d samples\n", BUFFER_SAMPLES);



// Initialize MFCC extractor

if (!_mfcc_extractor.begin())

{

    Serial.println("Failed to initialize MFCC extractor");

    return false;

}



// Configure I2S

i2s_config_t i2sConfig = {

    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),

    .sample_rate = static_cast<uint32_t>(_sampleRate),

    .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,

    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,

    .communication_format = I2S_COMM_FORMAT_STAND_I2S,

    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,

    .dma_buf_count = 8,

    .dma_buf_len = 256,

    .use_apll = false,

    .tx_desc_auto_clear = false,

    .fixed_mclk = 0};



// Install I2S driver

esp_err_t err = i2s_driver_install(_i2sPort, &i2sConfig, 0, NULL);

if (err != ESP_OK)

{

    Serial.printf("Failed installing I2S driver: %d\n", err);

    return false;

}



// Set I2S pins

err = i2s_set_pin(_i2sPort, &_pinConfig);

if (err != ESP_OK)

{

    Serial.printf("Failed setting I2S pins: %d\n", err);

    i2s_driver_uninstall(_i2sPort);

    return false;

}



// Explicitly set clock for mono 32-bit samples

err = i2s_set_clk(_i2sPort, _sampleRate, I2S_BITS_PER_SAMPLE_32BIT, I2S_CHANNEL_MONO);

if (err != ESP_OK)

{

    Serial.printf("Failed setting I2S clock: %d\n", err);

    i2s_driver_uninstall(_i2sPort);

    return false;

}



// Clear DMA buffer

i2s_zero_dma_buffer(_i2sPort);



Serial.println("Audio Processor initialized successfully");

return true;

}

float AudioProcessor::convertI2SToFloat(int32_t i2s_sample)

{

// INMP441: 24-bit audio in 32-bit container

// Extract 24-bit value (right-shift 8 bits)

int32_t audio_24bit = i2s_sample >> 8;



// Sign extend if negative (24-bit signed to 32-bit signed)

if (audio_24bit & 0x00800000)

{

    audio_24bit |= 0xFF000000;

}



// Convert to float in range [-1.0, 1.0]

// 24-bit signed range: -8388608 to 8388607

return (float)audio_24bit / 8388608.0f;

}

void AudioProcessor::quantizeMFCC(const float *mfcc_float, int8_t *mfcc_int8)

{

// Quantize using model's exact parameters

for (int i = 0; i < NUM_INPUTS; i++)

{

    // Formula: quantized = round(value / scale + zero_point)

    float scaled = mfcc_float[i] / _input_scale;

    int32_t quantized = (int32_t)roundf(scaled + _input_zero_point);



    // Clamp to int8 range (safety)

    if (quantized > 127)

        quantized = 127;

    if (quantized < -128)

        quantized = -128;



    mfcc_int8[i] = (int8_t)quantized;

}

}

int AudioProcessor::read(int32_t *buffer, int bufferLength)

{

size_t bytesRead = 0;



// Read I2S data (blocking)

esp_err_t err = i2s_read(_i2sPort,

                         (void *)buffer,

                         bufferLength * sizeof(int32_t),

                         &bytesRead,

                         portMAX_DELAY);



if (err != ESP_OK)

{

    Serial.printf("I2S read error: %d\n", err);

    return 0;

}



int samplesRead = (int)(bytesRead / sizeof(int32_t));



// Convert and store in circular buffer

for (int i = 0; i < samplesRead; i++)

{

    float sample = convertI2SToFloat(buffer[i]);



    // Store in circular buffer

    _audio_buffer[_write_index] = sample;

    _write_index = (_write_index + 1) % BUFFER_SAMPLES;

    _samples_collected++;



    // Keep track of the most recent samples

    if (_samples_collected > BUFFER_SAMPLES)

    {

        _samples_collected = BUFFER_SAMPLES;

    }

}



return samplesRead;

}