espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.71k stars 7.3k forks source link

samples are duplicated when read from a stereo mic via I2S DMA (IDFGH-5090) #6874

Open aguaviva opened 3 years ago

aguaviva commented 3 years ago

Environment

Problem Description

Values read using the DMA from the IS2 port are duplicated, see the picture below:

image

    i2s_config_t i2s_config = {
      .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
      .sample_rate = sampleRate,
      .bits_per_sample = i2s_bits_per_sample_t(I2S_SAMPLE_BITS),
      .channel_format = (channels==2)?I2S_CHANNEL_FMT_RIGHT_LEFT:I2S_CHANNEL_FMT_ONLY_LEFT,
      .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
      .intr_alloc_flags = 0,
      .dma_buf_count = 32,
      .dma_buf_len = 1024,
      .use_apll = true
    };

    err = i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);

This happens regardless of the sample rate or channels I use

Expected Behavior

samples to not be duplicated

Steps to reproduce

Reading from 2 MSM26S4030H0 microphones via i2s

Code to reproduce this issue

// the code should be wrapped in the ```cpp tag so that it will be displayed better.
#include "esp_log.h"

void app_main()
{
#define I2S_PORT          I2S_NUM_0
#define I2S_CHANNELS      (2)
#define I2S_SAMPLE_RATE   (44100)
#define I2S_SAMPLE_BITS   (16)
#define I2S_READ_LEN      (8*1024)

  esp_err_t err = ESP_OK;
  int sampleRate = I2S_SAMPLE_RATE;
  int secondsToRecord = 10;
  int bitsPerChannel = I2S_SAMPLE_BITS;
  int channels = I2S_CHANNELS;

 int i2s_read_len = I2S_READ_LEN;
  size_t bytes_read;
  char* i2s_read_buff = (char*) calloc(i2s_read_len, sizeof(char));

  // init i2s
  {
    i2s_config_t i2s_config = {
      .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
      .sample_rate = sampleRate,
      .bits_per_sample = i2s_bits_per_sample_t(I2S_SAMPLE_BITS),
      .channel_format = (channels==2)?I2S_CHANNEL_FMT_RIGHT_LEFT:I2S_CHANNEL_FMT_ONLY_LEFT,
      .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
      .intr_alloc_flags = 0,
      .dma_buf_count = 32,
      .dma_buf_len = 1024,
      .use_apll = true
    };

    err = i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
    if (err!=ESP_OK)
    {
      Serial.print("i2s_driver_install: ");
      Serial.println(err);
      httpd_resp_send_500(req);
      return ESP_FAIL;
    }

    const i2s_pin_config_t pin_config = {
      .bck_io_num = I2S_SCK,
      .ws_io_num = I2S_WS,
      .data_out_num = -1,
      .data_in_num = I2S_SD
    };

    i2s_set_pin(I2S_PORT, &pin_config);

    i2s_read(I2S_PORT, (void*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
    i2s_read(I2S_PORT, (void*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
  }

// send data
    for(;;)
    {
      i2s_read(I2S_PORT, (void*) i2s_read_buff, min(i2s_read_len, bytesToRead) , &bytes_read, portMAX_DELAY);

      //fix endiannes
      if (channels==1)
      {
          int16_t *temp_buf = (int16_t *)i2s_read_buff;
          int16_t temp_box;
          int k = bytes_read >> 1;
          for (int i = 0; i < k; i += 2) {
              temp_box = temp_buf[i];
              temp_buf[i] = temp_buf[i + 1];
              temp_buf[i + 1] = temp_box;
          }      
      }

      saveData();

      bytesToRead -= bytes_read; 
      if (bytesToRead==0)
        break;
    }

}

// If your code is longer than 30 lines, GIST is preferred.

Debug Logs

nothing to report

aguaviva commented 3 years ago

setting the bitsPerChannel to 32 solved the issue

aguaviva commented 3 years ago

Reopening the bug to make sure this gets documented

Alvin1Zhang commented 3 years ago

Thanks for reporting and sharing the fix, we will look into.

therealergo commented 1 year ago

Has there been any movement on this issue? I've re-tested with ESP-IDF 5.0.1, and I'm seeing the same behavior: When 16-bit mono RX is requested, every sample is duplicated twice in each 32-bit word.

anthonymayfield commented 11 months ago

@aguaviva Did you have to do anything else other than set '.bits_per_chan = i2s_bits_per_chan_t(32)', this isn't working for me :(

@Alvin1Zhang Did you guys manage to look into this? I'm having the same issue and I can't find any documentation to help me get it working :(