Esp32 How to do Mono channel I2S DMA ADC?

I'm trying to use ESP32 I2S DMA to record audio from a single mic and save it to mp3 or other usual audio formats.

Here is my code:

#include <driver/i2s.h>

#define I2S_SAMPLE_RATE 44000
#define ADC_INPUT ADC1_CHANNEL_4 //pin 32
#define OUTPUT_PIN 27
#define OUTPUT_VALUE 3800
#define READ_DELAY 9000 //microseconds

void i2sInit()
{
  i2s_config_t i2s_config = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN),
    .sample_rate =  I2S_SAMPLE_RATE,              // The format of the signal using ADC_BUILT_IN
    .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // is fixed at 12bit, stereo, MSB
    //.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
    .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
    .communication_format = I2S_COMM_FORMAT_I2S_MSB,
    //.communication_format = I2S_COMM_FORMAT_PCM,
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
    .dma_buf_count = 4,
    .dma_buf_len = 8,
    .use_apll = false,
    .tx_desc_auto_clear = false,
    .fixed_mclk = 0
  };
  i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
  i2s_set_clk(I2S_NUM_0,I2S_SAMPLE_RATE,I2S_BITS_PER_SAMPLE_16BIT,I2S_CHANNEL_MONO);
  i2s_set_adc_mode(ADC_UNIT_1, ADC_INPUT);
  i2s_adc_enable(I2S_NUM_0);
}

void reader(void *pvParameters) {
  uint64_t read_sum = 0;
  // The 4 high bits are the channel, and the data is inverted
  uint16_t offset = (int)ADC_INPUT * 0x1000 + 0xFFF;
  size_t bytes_read;
  while (1) {
    uint16_t buffer[3] = {0};
    i2s_read(I2S_NUM_0, &buffer, sizeof(buffer), &bytes_read, 15);
    Serial.printf("%d  %d  %d\n", offset - buffer[0], offset - buffer[1],offset - buffer[2]);
    if (bytes_read == sizeof(buffer)) {
      read_sum += offset - buffer[0];
      read_sum += offset - buffer[1];
      //Serial.printf("%d\n",read_sum);
    } else {
      Serial.println("buffer empty");
    }
  }
}

void setup() {
  Serial.begin(115200);
  // Initialize the I2S peripheral
  i2sInit();
  // Create a task that will read the data
  xTaskCreatePinnedToCore(reader, "ADC_reader", 2048, NULL, 1, NULL, 1);
}

void loop() {
}

There are 2 issues confused me at this point.

  1. What's the right way to make it record mono channel? I tried i2s_set_clk(,,,I2S_CHANNEL_MONO) with .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, the output buffer[0] and buffer[1] both give similar valid values. And .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT will only give valid value to buffer[1] and 0 to buffer[0], which is expected.
    I might be thinking this in a very wrong way, but does the ONLY_RIGHT config still makes the chip to think there is a stereo source but it just ignores half of the data from the mic which it interprets as "from the left channel of a stereo mic"? since the "I2S_CHANNEL_FMT_RIGHT_LEFT" setting produces 2 different but similar values (it shouldn't, the source is a mono), if this is the case, how to tell the chip that there is only one mono channel audio source?

  2. If I need to save the output data to a mp3 or other common audio formats, Should I use .communication_format = I2S_COMM_FORMAT_PCM or MSB/LSB? Is the difference between PCM and MSB/LSB just about quantisation, which PCM is using A Law or mu Law and the later one is just linear?

I don't have too much experience in this area, if I have some very wrong understanding, please tell me. And any ideas will be appreciated, thanks.

I2S DACs and ADCs are inherently two-channel, there isn't a mono mode, everything is driven on a left-right clock (LRCLK is the pin name).

ONLY_RIGHT is the thing to use for reduced memory usage. If you route the mic to both ADC channels you won't have to worry if its read in stereo or with right-only.