Page 1 of 1

24bit ADC -> 16bit I2S

Posted: Sun May 30, 2021 9:44 pm
by hubert3x3
I'm using PCM1808 (24bit audio ADC) + ESP32 to sample audio and send it over http_stream. My problem is that PCM1808 is outputting 24bits per sample and I have to set I2S for 32bits for my code to work. With 32bits per sample I can only go as high as 32kHz sample rate. Above that the received audio is not recognizable. At 32bps@32kHz everything works fine, but I need to provide 16bps/44.1kHz http_stream. In theory I2S I should be able to configure I2S for 16bps in slave mode and hardware module in ESP should ignore last 8bits of data sent by ADC (24bps). In practice in such configuration i cannot read anything from i2s. When I change bitwidth to 24bits I can read data. Can anyone confirm that ESP can truncate excessive bits when operating in slave mode? I2S specification describes such behavior as standard.
Below is my init code but http_stream was changed to raw_stream so I could read from it and print data to console.

Code: Select all

    esp_log_level_set(TAG, ESP_LOG_INFO);
    ESP_LOGI(TAG, "Create audio pipeline for recording");
    audio_pipeline_cfg_t pipeline_cfg = DEFAULT_AUDIO_PIPELINE_CONFIG();
    pipeline = audio_pipeline_init(&pipeline_cfg);
    mem_assert(pipeline);

    ESP_LOGI(TAG, "Create http stream to post data to server");

    http_stream_cfg_t http_cfg = HTTP_STREAM_CFG_DEFAULT();
    http_cfg.type = AUDIO_STREAM_WRITER;
    http_cfg.event_handle = _http_stream_event_handle;
    http_stream_writer = http_stream_init(&http_cfg);

    ESP_LOGI(TAG, "Create i2s stream to read audio data from codec chip");

    i2s_stream_cfg_t i2s_cfg = I2S_STREAM_CFG_DEFAULT();
    i2s_cfg.type = AUDIO_STREAM_READER;
    i2s_cfg.i2s_port = 0;
    i2s_cfg.i2s_config = (i2s_config_t)
    {
        .mode = (i2s_mode_t)(I2S_MODE_SLAVE | I2S_MODE_RX),
        .sample_rate = 32000,
        .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
        .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
        .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
        .dma_buf_count = 8,
        .dma_buf_len = 1024,
        .use_apll = true,
        .tx_desc_auto_clear = false,
        .fixed_mclk = 0
    };

    static const i2s_pin_config_t pin_config =
    {
        .bck_io_num = GPIO_NUM_26,
        .ws_io_num = GPIO_NUM_25,
        .data_out_num = I2S_PIN_NO_CHANGE,
        .data_in_num = GPIO_NUM_33
    };

    i2s_stream_reader = i2s_stream_init(&i2s_cfg);

    i2s_set_pin(0, &pin_config);
    i2s_stream_set_clk(i2s_stream_reader, 32000, 16, 2);
    raw_stream_cfg_t raw_stream_cfg = {.type = AUDIO_STREAM_READER,
                                       .out_rb_size = 1024};
    raw_stream = raw_stream_init(&raw_stream_cfg);
    
    ESP_LOGI(TAG, "[3.3] Create a ringbuffer and insert it between mp3 decoder and i2s writer");
    ringbuf = rb_create(1024*2000, 1);

    //audio_element_set_output_ringbuf(i2s_stream_reader, ringbuf);
    //audio_element_set_input_ringbuf(http_stream_writer, ringbuf);

    ESP_LOGI(TAG, "Register all elements to audio pipeline");
    audio_pipeline_register(pipeline, i2s_stream_reader, "i2s");
    audio_pipeline_register(pipeline, http_stream_writer, "http");
    audio_pipeline_register(pipeline, raw_stream, "raw");

    ESP_LOGI(TAG, "Link it together [codec_chip]-->i2s_stream->http_stream-->[http_server]");
    const char *link_tag[2] = {"i2s", "raw"};
    audio_pipeline_link(pipeline, &link_tag[0], 2);