m5stack / M5Core2

M5Core2 Arduino Library
MIT License
262 stars 113 forks source link

M5Core2 录音pcm文件格式问题 #150

Closed fssqawj closed 2 months ago

fssqawj commented 4 months ago

问题描述: 使用 M5Core2 录音存储 pcm 文件,然后从 pcm 文件读数据,使用 I2S 可以播放(音量较低,听着也有杂音,但是能正常听清内容)。但是从电脑打开该 pcm 文件,不能正常播放(进而导致 ASR 服务不能正常进行识别)。 怀疑过电脑打开 pcm 设置不对,所以尝试了电脑能正常播放的 WAV(PCM+header),M5Core2 也能正常播放该 WAV 文件。也尝试了电脑换不同的参数打开(虽然很确定录音参数,以防万一^-^!),包括各种采样率,位宽,大小端,声道数 等,也不能正常播放。同时,换了各种采样率/I2S参数进行录音,并不奏效。基本断定是获取的 pcm 文件本身就有问题。 使用该 repo 提供的录音样例 https://github.com/m5stack/M5Core2/blob/master/examples/Basics/record/record.ino ,存储为pcm文件,也有该问题。 所以感觉是 M5Core2 录音存储的 PCM 文件格式问题 或者是 pdm 麦克风的问题。请了解的同学提供下解决问题的思路~

相关文件:

官方提供的录音样例,把 read 数据存储到 pcm 文件

录音语句:“你好,请问你叫什么名字” test_example.zip

打开方式:

image

波形文件: image 可以看到不是正常的波形

录音部分代码:

const int RECORD_BUFFER_SIZE = 4096;
uint8_t microphonedata0[RECORD_BUFFER_SIZE];
            M5.Spk.InitI2SSpeakOrMic(MODE_MIC);
            File audioDataFile = SD.open("/test_audio.pcm", FILE_WRITE);
            // Serial.println(audioDataFile);
            size_t byte_read;
            while (1) {
                i2s_read(Speak_I2S_NUMBER,
                         microphonedata0, RECORD_BUFFER_SIZE,
                         &byte_read, (100 / portTICK_RATE_MS));
                audioDataFile.write(microphonedata0, RECORD_BUFFER_SIZE);
                // Serial.println(byte_read);
                if (M5.Touch.ispressed() != true)
                    break;
            }

M5Core2 SPK 录音/播放 I2S 设置:

https://github.com/m5stack/M5Core2/blob/master/src/Speaker.cpp

icyqwq commented 3 months ago

Please try wav.

#define WAVE_HEADER_SIZE    44
#define EXAMPLE_SAMPLE_RATE     (32000)

inline void generate_wav_header(char* wav_header, uint32_t wav_size, uint32_t sample_rate, uint8_t channels, uint32_t byte_rate){

    // See this for reference: http://soundfile.sapp.org/doc/WaveFormat/
    uint32_t file_size = wav_size + WAVE_HEADER_SIZE - 8;

    const char set_wav_header[] = {
        'R','I','F','F', // ChunkID
        file_size, file_size >> 8, file_size >> 16, file_size >> 24, // ChunkSize
        'W','A','V','E', // Format
        'f','m','t',' ', // Subchunk1ID
        0x10, 0x00, 0x00, 0x00, // Subchunk1Size (16 for PCM)
        0x01, 0x00, // AudioFormat (1 for PCM)
        channels, 0x00, // NumChannels (1 channel)
        sample_rate, sample_rate >> 8, sample_rate >> 16, sample_rate >> 24, // SampleRate
        byte_rate, byte_rate >> 8, byte_rate >> 16, byte_rate >> 24, // ByteRate
        0x02, 0x00, // BlockAlign
        0x10, 0x00, // BitsPerSample (16 bits)
        'd','a','t','a', // Subchunk2ID
        wav_size, wav_size >> 8, wav_size >> 16, wav_size >> 24, // Subchunk2Size
    };

    memcpy(wav_header, set_wav_header, sizeof(set_wav_header));
}

uint32_t bytesread = 0;
uint8_t mic_buffer[2048];
int32_t wrote_cycle = 300;

generate_wav_header((char*)mic_buffer, 2048 * wrote_cycle, EXAMPLE_SAMPLE_RATE*2, 1, EXAMPLE_SAMPLE_RATE*2);

File file = SD.open("/test.wav", FILE_WRITE);
file.write(mic_buffer, WAVE_HEADER_SIZE);
while (wrote_cycle--)
{
        esp_err_t err = i2s_read(I2S_NUM, mic_buffer, sizeof(mic_buffer), &bytesread, 1000);
        file.write(mic_buffer, bytesread);
}
icyqwq commented 2 months ago

Please reopen this issue if you still need it.

fssqawj commented 2 months ago

Please try wav.

#define WAVE_HEADER_SIZE    44
#define EXAMPLE_SAMPLE_RATE     (32000)

inline void generate_wav_header(char* wav_header, uint32_t wav_size, uint32_t sample_rate, uint8_t channels, uint32_t byte_rate){

    // See this for reference: http://soundfile.sapp.org/doc/WaveFormat/
    uint32_t file_size = wav_size + WAVE_HEADER_SIZE - 8;

    const char set_wav_header[] = {
        'R','I','F','F', // ChunkID
        file_size, file_size >> 8, file_size >> 16, file_size >> 24, // ChunkSize
        'W','A','V','E', // Format
        'f','m','t',' ', // Subchunk1ID
        0x10, 0x00, 0x00, 0x00, // Subchunk1Size (16 for PCM)
        0x01, 0x00, // AudioFormat (1 for PCM)
        channels, 0x00, // NumChannels (1 channel)
        sample_rate, sample_rate >> 8, sample_rate >> 16, sample_rate >> 24, // SampleRate
        byte_rate, byte_rate >> 8, byte_rate >> 16, byte_rate >> 24, // ByteRate
        0x02, 0x00, // BlockAlign
        0x10, 0x00, // BitsPerSample (16 bits)
        'd','a','t','a', // Subchunk2ID
        wav_size, wav_size >> 8, wav_size >> 16, wav_size >> 24, // Subchunk2Size
    };

    memcpy(wav_header, set_wav_header, sizeof(set_wav_header));
}

uint32_t bytesread = 0;
uint8_t mic_buffer[2048];
int32_t wrote_cycle = 300;

generate_wav_header((char*)mic_buffer, 2048 * wrote_cycle, EXAMPLE_SAMPLE_RATE*2, 1, EXAMPLE_SAMPLE_RATE*2);

File file = SD.open("/test.wav", FILE_WRITE);
file.write(mic_buffer, WAVE_HEADER_SIZE);
while (wrote_cycle--)
{
        esp_err_t err = i2s_read(I2S_NUM, mic_buffer, sizeof(mic_buffer), &bytesread, 1000);
        file.write(mic_buffer, bytesread);
}

尝试加了 wav header,仍然有问题 audio_0605.zip

            InitI2SSpeakOrMic(MODE_MIC);
            int cnt = 50;
            generate_wav_header((char*)microphonedata0, cnt * RECORD_BUFFER_SIZE, 8000, 1, 8000);
            audioDataFile.write(microphonedata0, WAVE_HEADER_SIZE);
            while (cnt --) {
                Serial.println(cnt);
                i2s_read(Speak_I2S_NUMBER,
                         microphonedata0, RECORD_BUFFER_SIZE,
                         &byte_read, (100 / portTICK_RATE_MS));
                audioDataFile.write(microphonedata0, RECORD_BUFFER_SIZE);
            }

I2S 设置:

bool InitI2SSpeakOrMic(int mode) {  // Init I2S.  初始化I2S
    esp_err_t err = ESP_OK;

    i2s_driver_uninstall(
        Speak_I2S_NUMBER);  // Uninstall the I2S driver.  卸载I2S驱动

    i2s_comm_format_t comm_fmt;
    comm_fmt = (i2s_comm_format_t) (I2S_COMM_FORMAT_STAND_I2S);

    i2s_config_t i2s_config = {
        .mode = (i2s_mode_t)(I2S_MODE_MASTER),  // Set the I2S operating mode.
                                                // 设置I2S工作模式
        .sample_rate = 8000,  // Set the I2S sampling rate.  设置I2S采样率
        .bits_per_sample =
            I2S_BITS_PER_SAMPLE_16BIT,
        .channel_format =
            I2S_CHANNEL_FMT_ONLY_RIGHT,  // Set the channel format. 设置频道格式
        .communication_format = comm_fmt,
        .intr_alloc_flags =
            ESP_INTR_FLAG_LEVEL1,  // Set the interrupt flag.  设置中断的标志
        .dma_buf_count      = 8,    // DMA buffer count.  DMA缓冲区计数
        .dma_buf_len        = 128,  // DMA buffer length.  DMA缓冲区长度
        .use_apll           = false,
        .tx_desc_auto_clear = true,
        .fixed_mclk         = -1,
        .mclk_multiple      = I2S_MCLK_MULTIPLE_DEFAULT,
        .bits_per_chan      = I2S_BITS_PER_CHAN_DEFAULT,
    };
    if (mode == MODE_MIC) {
        i2s_config.mode =
            (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM);
    } else {
        i2s_config.mode     = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX);
        i2s_config.use_apll = false;  // I2S clock setup.  I2S时钟设置
        i2s_config.tx_desc_auto_clear =
            true;  // Enables auto-cleanup descriptors for understreams.
                   // 开启欠流自动清除描述符
    }
    // Install and drive I2S.  安装并驱动I2S
    err += i2s_driver_install(Speak_I2S_NUMBER, &i2s_config, 0, NULL);

    i2s_pin_config_t tx_pin_config;

#if (ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(4, 3, 0))
    tx_pin_config.mck_io_num = I2S_PIN_NO_CHANGE;
#endif
    tx_pin_config.bck_io_num =
        CONFIG_I2S_BCK_PIN;  // Link the BCK to the CONFIG_I2S_BCK_PIN pin.
                             // 将BCK链接至CONFIG_I2S_BCK_PIN引脚
    tx_pin_config.ws_io_num    = CONFIG_I2S_LRCK_PIN;     //          ...
    tx_pin_config.data_out_num = CONFIG_I2S_DATA_PIN;     //       ...
    tx_pin_config.data_in_num  = CONFIG_I2S_DATA_IN_PIN;  //      ...
    err +=
        i2s_set_pin(Speak_I2S_NUMBER,
                    &tx_pin_config);  // Set the I2S pin number. 设置I2S引脚编号
    err += i2s_set_clk(
        Speak_I2S_NUMBER, 8000, I2S_BITS_PER_SAMPLE_16BIT,
        I2S_CHANNEL_MONO);  // Set the clock and bitwidth used by I2S Rx and Tx.
                            // 设置I2S RX、Tx使用的时钟和位宽
    return true;
}
fssqawj commented 2 months ago

I can't reopen this issue.

icyqwq commented 2 months ago
#include <M5Unified.h>
#include <Arduino.h>

#include <driver/gpio.h>
#include "driver/i2s.h"
#include <math.h>

#include <SPI.h>
#include <SD.h>

#define TAG "Main"

#define UTILS_WAVE_HEADER_SIZE    44

static uint8_t audio_buffer[2048];

void utils_generate_wav_header(char* wav_header, uint32_t wav_size, uint32_t sample_rate, uint8_t channels, uint32_t byte_rate){

    // See this for reference: http://soundfile.sapp.org/doc/WaveFormat/
    uint32_t file_size = wav_size + UTILS_WAVE_HEADER_SIZE - 8;

    const char set_wav_header[] = {
        'R','I','F','F', // ChunkID
        file_size, file_size >> 8, file_size >> 16, file_size >> 24, // ChunkSize
        'W','A','V','E', // Format
        'f','m','t',' ', // Subchunk1ID
        0x10, 0x00, 0x00, 0x00, // Subchunk1Size (16 for PCM)
        0x01, 0x00, // AudioFormat (1 for PCM)
        channels, 0x00, // NumChannels (1 channel)
        sample_rate, sample_rate >> 8, sample_rate >> 16, sample_rate >> 24, // SampleRate
        byte_rate, byte_rate >> 8, byte_rate >> 16, byte_rate >> 24, // ByteRate
        0x02, 0x00, // BlockAlign
        0x10, 0x00, // BitsPerSample (16 bits)
        'd','a','t','a', // Subchunk2ID
        wav_size, wav_size >> 8, wav_size >> 16, wav_size >> 24, // Subchunk2Size
    };

    memcpy(wav_header, set_wav_header, sizeof(set_wav_header));
}

static void mic_test()
{
    int n = 100;
    auto file = SD.open("/test.wav", FILE_WRITE);
    if (!file) {
        ESP_LOGE(TAG, "Failed to open file for writing");
        return;
    }
    utils_generate_wav_header((char*)audio_buffer, n * sizeof(audio_buffer), 16000, 1, 16000 * 2);
    file.write(audio_buffer, UTILS_WAVE_HEADER_SIZE);

    while (n--)
    {
        size_t bytes_read;
        esp_err_t err = i2s_read(I2S_NUM_0, audio_buffer, sizeof(audio_buffer), &bytes_read, 1000);
        file.write(audio_buffer, bytes_read);
        if (err != ESP_OK) {
            ESP_LOGE(TAG, "I2S Read failed, errno = %d", err);
            break;
        }
    }

    file.close();

    i2s_stop(I2S_NUM_0);
    i2s_zero_dma_buffer(I2S_NUM_0);
    i2s_driver_uninstall(I2S_NUM_0);

    printf("Done\n");
}

static esp_err_t _pdm_mic_init(uint32_t sample_rate, int8_t pin_ws, int8_t pin_data)
{
    esp_err_t err = ESP_OK;

    i2s_config_t i2s_config = {
        .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM),
        .sample_rate = sample_rate,
        .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
        .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
        .communication_format = I2S_COMM_FORMAT_I2S,
        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL2,
        .dma_buf_count = 4,
        .dma_buf_len = 256,
        .use_apll = 0,
    };

    i2s_pin_config_t i2s_mic_pins = {
        .bck_io_num = I2S_PIN_NO_CHANGE,
        .ws_io_num = pin_ws,
        .data_out_num = I2S_PIN_NO_CHANGE,
        .data_in_num = pin_data,
    };

    err = i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); // PDM mode only supported in I2S_NUM_0
    if (err != ESP_OK) {
        return err;
    }

    err = i2s_set_pin(I2S_NUM_0, &i2s_mic_pins);
    if (err != ESP_OK) {
        return err;
    }

    err = i2s_start(I2S_NUM_0);
    if (err != ESP_OK) {
        return err;
    }

    return err;
}

extern "C" void app_main()
{

    auto config = M5.config();
    config.internal_spk = false;
    config.internal_mic = false;
    config.internal_imu = false;
    config.internal_rtc = false;
    M5.begin(config);
    M5.Power.Axp192.setGPIO2(1);
    M5.Lcd.fillScreen(GREEN);
    M5.Lcd.setTextColor(WHITE);
    M5.Lcd.setTextSize(2);

    SPI.begin(18, 38, 23);
    SD.begin(4, SPI, 20000000);

    printf("SD Card Size: %llu\n", SD.cardSize() / 1024 / 1024);

    _pdm_mic_init(16000, 0, 34);
    mic_test();

    while (1)
    {   
        delay(10);
    }
}

Tryout this complete arduino code, this is working fine with builtin M5StackCore2 microphone (which on the base board). If issue still present, try another mic.

icyqwq commented 2 months ago

Please try wav.

#define WAVE_HEADER_SIZE    44
#define EXAMPLE_SAMPLE_RATE     (32000)

inline void generate_wav_header(char* wav_header, uint32_t wav_size, uint32_t sample_rate, uint8_t channels, uint32_t byte_rate){

    // See this for reference: http://soundfile.sapp.org/doc/WaveFormat/
    uint32_t file_size = wav_size + WAVE_HEADER_SIZE - 8;

    const char set_wav_header[] = {
        'R','I','F','F', // ChunkID
        file_size, file_size >> 8, file_size >> 16, file_size >> 24, // ChunkSize
        'W','A','V','E', // Format
        'f','m','t',' ', // Subchunk1ID
        0x10, 0x00, 0x00, 0x00, // Subchunk1Size (16 for PCM)
        0x01, 0x00, // AudioFormat (1 for PCM)
        channels, 0x00, // NumChannels (1 channel)
        sample_rate, sample_rate >> 8, sample_rate >> 16, sample_rate >> 24, // SampleRate
        byte_rate, byte_rate >> 8, byte_rate >> 16, byte_rate >> 24, // ByteRate
        0x02, 0x00, // BlockAlign
        0x10, 0x00, // BitsPerSample (16 bits)
        'd','a','t','a', // Subchunk2ID
        wav_size, wav_size >> 8, wav_size >> 16, wav_size >> 24, // Subchunk2Size
    };

    memcpy(wav_header, set_wav_header, sizeof(set_wav_header));
}

uint32_t bytesread = 0;
uint8_t mic_buffer[2048];
int32_t wrote_cycle = 300;

generate_wav_header((char*)mic_buffer, 2048 * wrote_cycle, EXAMPLE_SAMPLE_RATE*2, 1, EXAMPLE_SAMPLE_RATE*2);

File file = SD.open("/test.wav", FILE_WRITE);
file.write(mic_buffer, WAVE_HEADER_SIZE);
while (wrote_cycle--)
{
        esp_err_t err = i2s_read(I2S_NUM, mic_buffer, sizeof(mic_buffer), &bytesread, 1000);
        file.write(mic_buffer, bytesread);
}

尝试加了 wav header,仍然有问题 audio_0605.zip

            InitI2SSpeakOrMic(MODE_MIC);
            int cnt = 50;
            generate_wav_header((char*)microphonedata0, cnt * RECORD_BUFFER_SIZE, 8000, 1, 8000);
            audioDataFile.write(microphonedata0, WAVE_HEADER_SIZE);
            while (cnt --) {
                Serial.println(cnt);
                i2s_read(Speak_I2S_NUMBER,
                         microphonedata0, RECORD_BUFFER_SIZE,
                         &byte_read, (100 / portTICK_RATE_MS));
                audioDataFile.write(microphonedata0, RECORD_BUFFER_SIZE);
            }

I2S 设置:

bool InitI2SSpeakOrMic(int mode) {  // Init I2S.  初始化I2S
    esp_err_t err = ESP_OK;

    i2s_driver_uninstall(
        Speak_I2S_NUMBER);  // Uninstall the I2S driver.  卸载I2S驱动

    i2s_comm_format_t comm_fmt;
    comm_fmt = (i2s_comm_format_t) (I2S_COMM_FORMAT_STAND_I2S);

    i2s_config_t i2s_config = {
        .mode = (i2s_mode_t)(I2S_MODE_MASTER),  // Set the I2S operating mode.
                                                // 设置I2S工作模式
        .sample_rate = 8000,  // Set the I2S sampling rate.  设置I2S采样率
        .bits_per_sample =
            I2S_BITS_PER_SAMPLE_16BIT,
        .channel_format =
            I2S_CHANNEL_FMT_ONLY_RIGHT,  // Set the channel format. 设置频道格式
        .communication_format = comm_fmt,
        .intr_alloc_flags =
            ESP_INTR_FLAG_LEVEL1,  // Set the interrupt flag.  设置中断的标志
        .dma_buf_count      = 8,    // DMA buffer count.  DMA缓冲区计数
        .dma_buf_len        = 128,  // DMA buffer length.  DMA缓冲区长度
        .use_apll           = false,
        .tx_desc_auto_clear = true,
        .fixed_mclk         = -1,
        .mclk_multiple      = I2S_MCLK_MULTIPLE_DEFAULT,
        .bits_per_chan      = I2S_BITS_PER_CHAN_DEFAULT,
    };
    if (mode == MODE_MIC) {
        i2s_config.mode =
            (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM);
    } else {
        i2s_config.mode     = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX);
        i2s_config.use_apll = false;  // I2S clock setup.  I2S时钟设置
        i2s_config.tx_desc_auto_clear =
            true;  // Enables auto-cleanup descriptors for understreams.
                   // 开启欠流自动清除描述符
    }
    // Install and drive I2S.  安装并驱动I2S
    err += i2s_driver_install(Speak_I2S_NUMBER, &i2s_config, 0, NULL);

    i2s_pin_config_t tx_pin_config;

#if (ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(4, 3, 0))
    tx_pin_config.mck_io_num = I2S_PIN_NO_CHANGE;
#endif
    tx_pin_config.bck_io_num =
        CONFIG_I2S_BCK_PIN;  // Link the BCK to the CONFIG_I2S_BCK_PIN pin.
                             // 将BCK链接至CONFIG_I2S_BCK_PIN引脚
    tx_pin_config.ws_io_num    = CONFIG_I2S_LRCK_PIN;     //          ...
    tx_pin_config.data_out_num = CONFIG_I2S_DATA_PIN;     //       ...
    tx_pin_config.data_in_num  = CONFIG_I2S_DATA_IN_PIN;  //      ...
    err +=
        i2s_set_pin(Speak_I2S_NUMBER,
                    &tx_pin_config);  // Set the I2S pin number. 设置I2S引脚编号
    err += i2s_set_clk(
        Speak_I2S_NUMBER, 8000, I2S_BITS_PER_SAMPLE_16BIT,
        I2S_CHANNEL_MONO);  // Set the clock and bitwidth used by I2S Rx and Tx.
                            // 设置I2S RX、Tx使用的时钟和位宽
    return true;
}

The byterate shoulde be sample rate * 2, since one sample contains two byte :)

fssqawj commented 2 months ago
#include <M5Unified.h>
#include <Arduino.h>

#include <driver/gpio.h>
#include "driver/i2s.h"
#include <math.h>

#include <SPI.h>
#include <SD.h>

#define TAG "Main"

#define UTILS_WAVE_HEADER_SIZE    44

static uint8_t audio_buffer[2048];

void utils_generate_wav_header(char* wav_header, uint32_t wav_size, uint32_t sample_rate, uint8_t channels, uint32_t byte_rate){

    // See this for reference: http://soundfile.sapp.org/doc/WaveFormat/
    uint32_t file_size = wav_size + UTILS_WAVE_HEADER_SIZE - 8;

    const char set_wav_header[] = {
        'R','I','F','F', // ChunkID
        file_size, file_size >> 8, file_size >> 16, file_size >> 24, // ChunkSize
        'W','A','V','E', // Format
        'f','m','t',' ', // Subchunk1ID
        0x10, 0x00, 0x00, 0x00, // Subchunk1Size (16 for PCM)
        0x01, 0x00, // AudioFormat (1 for PCM)
        channels, 0x00, // NumChannels (1 channel)
        sample_rate, sample_rate >> 8, sample_rate >> 16, sample_rate >> 24, // SampleRate
        byte_rate, byte_rate >> 8, byte_rate >> 16, byte_rate >> 24, // ByteRate
        0x02, 0x00, // BlockAlign
        0x10, 0x00, // BitsPerSample (16 bits)
        'd','a','t','a', // Subchunk2ID
        wav_size, wav_size >> 8, wav_size >> 16, wav_size >> 24, // Subchunk2Size
    };

    memcpy(wav_header, set_wav_header, sizeof(set_wav_header));
}

static void mic_test()
{
  int n = 100;
  auto file = SD.open("/test.wav", FILE_WRITE);
  if (!file) {
      ESP_LOGE(TAG, "Failed to open file for writing");
      return;
  }
  utils_generate_wav_header((char*)audio_buffer, n * sizeof(audio_buffer), 16000, 1, 16000 * 2);
  file.write(audio_buffer, UTILS_WAVE_HEADER_SIZE);

  while (n--)
  {
      size_t bytes_read;
      esp_err_t err = i2s_read(I2S_NUM_0, audio_buffer, sizeof(audio_buffer), &bytes_read, 1000);
      file.write(audio_buffer, bytes_read);
      if (err != ESP_OK) {
          ESP_LOGE(TAG, "I2S Read failed, errno = %d", err);
          break;
      }
  }

  file.close();

  i2s_stop(I2S_NUM_0);
  i2s_zero_dma_buffer(I2S_NUM_0);
  i2s_driver_uninstall(I2S_NUM_0);

  printf("Done\n");
}

static esp_err_t _pdm_mic_init(uint32_t sample_rate, int8_t pin_ws, int8_t pin_data)
{
  esp_err_t err = ESP_OK;

  i2s_config_t i2s_config = {
      .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM),
      .sample_rate = sample_rate,
      .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
      .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
      .communication_format = I2S_COMM_FORMAT_I2S,
      .intr_alloc_flags = ESP_INTR_FLAG_LEVEL2,
      .dma_buf_count = 4,
      .dma_buf_len = 256,
      .use_apll = 0,
  };

  i2s_pin_config_t i2s_mic_pins = {
      .bck_io_num = I2S_PIN_NO_CHANGE,
      .ws_io_num = pin_ws,
      .data_out_num = I2S_PIN_NO_CHANGE,
      .data_in_num = pin_data,
  };

  err = i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); // PDM mode only supported in I2S_NUM_0
  if (err != ESP_OK) {
      return err;
  }

  err = i2s_set_pin(I2S_NUM_0, &i2s_mic_pins);
  if (err != ESP_OK) {
      return err;
  }

  err = i2s_start(I2S_NUM_0);
  if (err != ESP_OK) {
      return err;
  }

  return err;
}

extern "C" void app_main()
{

  auto config = M5.config();
  config.internal_spk = false;
  config.internal_mic = false;
  config.internal_imu = false;
  config.internal_rtc = false;
  M5.begin(config);
  M5.Power.Axp192.setGPIO2(1);
  M5.Lcd.fillScreen(GREEN);
  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.setTextSize(2);

  SPI.begin(18, 38, 23);
  SD.begin(4, SPI, 20000000);

  printf("SD Card Size: %llu\n", SD.cardSize() / 1024 / 1024);

  _pdm_mic_init(16000, 0, 34);
  mic_test();

  while (1)
  {   
      delay(10);
  }
}

Tryout this complete arduino code, this is working fine with builtin M5StackCore2 microphone (which on the base board). If issue still present, try another mic.

Thanks for your code~

I have find the problem, i'm using a lib named ESP8266_multipart for uploading the local sd wav file to the server. The problem is that the transmitted data is incorrect(I thought there was not much difference between esp32 and esp8266), I'm trying to fix this...

Sorry again for misleading you.