PlatformIO Community

Reading from INMP441 with ESP32 results in loud noise

I am currently desperatly trying to get a NMP441 microphone properly working with a ESP32.
The code I am using seems to work but when I send the data off to my server hosted on a rpi the audio sounds broken and is just a very loud noise. My guess is that I am parsing the data from the microphone wrong. To setup the code and trying to understand what using the I2S interface means I used this doku and this github repo
This is the code for setting up the mic:

// i2s config
const i2s_config_t i2s_config = {
    .mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX), // receive
    .sample_rate = SAMPLE_RATE,
    .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT, // 32 bits per sample
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,  // use right channel
    .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // interrupt level 1
    .dma_buf_count = 64,                      // number of buffers
    .dma_buf_len = SAMPLES_PER_BUFFER};

// pin config
const i2s_pin_config_t pin_config = {
    .bck_io_num = gpio_sck,            // serial clock, sck
    .ws_io_num = gpio_ws,              // word select, ws
    .data_out_num = I2S_PIN_NO_CHANGE, // only used for speakers
    .data_in_num = gpio_sd             // serial data, sd

Serial.println("-----Mic Controller-----");

// config i2s driver and pins
// fct must be called before any read/write
esp_err_t err = i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
if (err != ESP_OK)
    Serial.printf("Failed installing the driver: %d\n", err);

err = i2s_set_pin(I2S_PORT, &pin_config);
if (err != ESP_OK)
    Serial.printf("Failed setting pin: %d\n", err);

Serial.println("I2S driver installed! :-)");


This the code for reading from the i2s peripheral:

// 44KHz (SAMPLE_RATE) * Byte per sample * time in seconds = total size in bytes
const size_t recordSize = (SAMPLE_RATE * I2S_BITS_PER_SAMPLE_32BIT / 8) * recordTime; //recordTime = 2s

// size in bytes
size_t totalReadSize = 0;

// 32 bits per sample set in config * 1024 samples per buffers = total bits per buffer
char *samples = (char *)calloc(totalBitsPerBuffer, sizeof(char));

// number of bytes read
size_t bytesRead;

Serial.println("Start recording...");
// read until wanted size is reached
while (totalReadSize < recordSize)
    // read to buffer
    esp_err_t err = i2s_read(I2S_PORT, (void *)samples, totalBitsPerBuffer, &bytesRead, portMAX_DELAY);

    // check if error occurd, if so stop recording
    if (err != ESP_OK)
        Serial.println("Error while recording!");

    // check if bytes read works → yes
    for (int i = 0; i < bytesRead; i++)
        uint8_t sample = (uint8_t) samples[i];
    } */

    // add read size to total read size
    totalReadSize += bytesRead;

HttpController httpController("");
httpController.postRequest("/esp/audio", "application/octet-stream", "", (uint8_t *)samples, totalReadSize);

The httpController just sends a simple request to my node server.
The node server saves the send data in the following way:'/esp/audio', (req, res) => {
    console.log(`Got ${req.body.length} I2S bytes`);
    fs.appendFile('audio.raw', req.body, () => {

After that I transform the audio to a .wav file.
I am probably not in the correct forum but I am pretty desperate atm to be honest.
Thanks in advance for any help!
Have a great weekend!

Per ESP32 | INMP441 | Tutorial - [Part.4] Capturing audio from i2s mic to save WAV file (I2S interface) - YouTube and ThatProject/ESP32_INMP441_RECORDING.ino at master · 0015/ThatProject · GitHub that’s supposed to be 16-bit, not 32-bit. Try the reference sketch first.

First of all, thanks for your answer. But unfortunatly this does not change anything. Still a broken wav at the end. Converting from .raw to .wav is done with the proper params so this should not be the problem either.
My guess is that something with the bytes read into the buffer is not correct. Do you recognize any flaw in my code?

This is a part of the buffer content:

ec ff ef ff e7 ff ec ff 
e3 ff e7 ff df ff e3 ff 
db ff df ff d7 ff db ff 
d4 ff d7 ff d0 ff d4 ff 
cb ff d0 ff c8 ff cb ff 
c4 ff c8 ff bf ff c4 ff

Is there maybe a problem passing the buffer as an arg to my custom http controller?
This is the called function of the controller:

void HttpController::postRequest(const char *route, const char *contentType, const char *data, uint8_t *bytes, size_t payloadSize)
    Serial.println("-----Http Controller-----");

    // set request stuff
    // ip with route
    String url(serverIp);

    httpClient.begin(wifiClient, url);
    httpClient.addHeader("Content-Type", contentType);

    // log request
    Serial.printf("Route: %s\n", route);
    strcmp(data, "") ? Serial.printf("Data: %s\n", data) : Serial.printf("Bytes: %d\n", bytes);

    // send request, switch between data in form of characters or bytes
        int httpResponseCode = strcmp(data, "") ? httpClient.POST(data) : httpClient.POST(bytes, payloadSize);
        Serial.printf("Http response code: %d\n", httpResponseCode);
    catch (const std::exception &e)

    // end request

This is the output of the received buffer on my server which seems still fine I guess:

<Buffer ef ff ef ff ef ff ef ff f0 ff f0 ff f0 ff f0 ff f3 ff f3 ff f3 ff f3 ff f3 ff f3 ff f3 ff f3 ff f4 ff f4 ff f4 ff f4 ff f0 ff f0 ff f0 ff f0 ff f0 ff ... 360398 more bytes>