Missing samples in I2S readout

FatherOfElectronics
Posts: 2
Joined: Sun Feb 04, 2024 12:41 am

Missing samples in I2S readout

Postby FatherOfElectronics » Sun Feb 04, 2024 12:50 am

Hello all!

I'm currently trying to read audio data from a PCM4222 ADC using I2S. I managed to get the ESP to read correct data from the ADC, however it seems like the ESP is skipping some samples, see image below.

Screenshot 2024-02-04 012256.png
Screenshot 2024-02-04 012256.png (53.83 KiB) Viewed 682 times

This seems to always happen somewhere between sample number 400 and 500 and I cannot for the life of me figure out what the issue is.

Furthermore, is there a way to ensure seamless consecutive readouts? It seems like there also are a handful of samples missing between individual readouts.

Minimal working example:

Code: Select all

// Include I2S library
#include <driver/i2s.h>

// Define I2S settings
#define I2S_BCK_PIN 14
#define I2S_LRCK_PIN 25
#define I2S_DATA_PIN 26
#define SAMPLE_RATE 48000
#define DMA_BUF_LEN 1024
#define DMA_BUF_COUNT 2

void setup()
{
  // Initialize serial communication
  Serial.begin(115200);

  // Configure I2S
  i2s_config_t i2s_config = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
    .sample_rate = SAMPLE_RATE,
    .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
    .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
    .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_LSB),
    .intr_alloc_flags = 0,
    .dma_buf_count = DMA_BUF_COUNT,
    .dma_buf_len = DMA_BUF_LEN
  };
  
  // Define I2S pins
  i2s_pin_config_t pin_config = {
    .bck_io_num = I2S_BCK_PIN,
    .ws_io_num = I2S_LRCK_PIN,
    .data_out_num = -1,
    .data_in_num = I2S_DATA_PIN
  };

  // Initialize I2S communication
  i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
  i2s_set_pin(I2S_NUM_0, &pin_config);
}

void loop()
{
  // Define variables
  size_t bytesRead;
  int32_t* i2sData = (int32_t*)malloc(2 * DMA_BUF_LEN * sizeof(int32_t));

  // Read data for both left and right channels
  i2s_read(I2S_NUM_0, i2sData, 2 * DMA_BUF_LEN * sizeof(int32_t), &bytesRead, portMAX_DELAY);

  for (uint16_t i = 0; i < DMA_BUF_LEN; ++i)
  {
    // Discard first bit and last 7 bits
    i2sData[2 * i] = (i2sData[2 * i] >> 7) & 0xFFFFFF;
    i2sData[2 * i + 1] = (i2sData[2 * i + 1] >> 7) & 0xFFFFFF;

    // Sign extend
    i2sData[2 * i] <<= 8;
    i2sData[2 * i] >>= 8;
    i2sData[2 * i + 1] <<= 8;
    i2sData[2 * i + 1] >>= 8;

    // Print right channel data for debugging purposes
    Serial.print(i); Serial.print("\t"); Serial.println(i2sData[2 * i + 1]);
  }
  Serial.print("");

  // De-allocate memory used for data samples
  free(i2sData);
}
Thanks a lot in advance!

lbernstone
Posts: 826
Joined: Mon Jul 22, 2019 3:20 pm

Re: Missing samples in I2S readout

Postby lbernstone » Sun Feb 04, 2024 3:12 am

If your processing is taking a lot of time, I'd recommend that you put the i2s functionality into a task at high priority.
Is there any difference if you remark the Serial.print statements? Those take a significant amount of cpu time, and may be slowing things down.

FatherOfElectronics
Posts: 2
Joined: Sun Feb 04, 2024 12:41 am

Re: Missing samples in I2S readout

Postby FatherOfElectronics » Sun Feb 04, 2024 7:45 am

lbernstone wrote:
Sun Feb 04, 2024 3:12 am
If your processing is taking a lot of time, I'd recommend that you put the i2s functionality into a task at high priority.
Is there any difference if you remark the Serial.print statements? Those take a significant amount of cpu time, and may be slowing things down.
As far as I understood, i2s_read waits until the buffer is fully read, so time intensive processing after the fact may explain the problem with consecutive reads but should not cause issues with an already read buffer?

Who is online

Users browsing this forum: Google [Bot] and 61 guests