Using ringbuffer with PSRAM

hubert3x3
Posts: 3
Joined: Sun May 30, 2021 9:27 pm

Using ringbuffer with PSRAM

Postby hubert3x3 » Mon Aug 16, 2021 8:14 pm

I'm using ESP32 with PSRAM onboard to collect audio (44.1kHz@16b) from I2S and send it to PC using http_stream. As long as there is no problem with Wifi received audio is smooth but as I am moving further away from router some artifacts starts to occur. It seems that I lose some data. I've chosen ESP32 with PSRAM because I read that it can be used for ringbuffer to buffer audio data. After some trying, I still can't figure out how to use that PSRAM to fix the problem with skipped data. Can you point me to any example of using ringbuffer in PSRAM. Or maybe my problem is not caused by to small data buffers?

Here is my initialization code for audio pipeline

Code: Select all

void RECORDER_init(void)
{
    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");

    //init streamu http
    http_stream_cfg_t http_cfg = HTTP_STREAM_CFG_DEFAULT();
    http_cfg.task_prio = 22;
    http_cfg.task_core = 0;
    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");
    //init streamu i2s
    i2s_stream_cfg_t i2s_cfg = I2S_STREAM_CFG_DEFAULT();

    i2s_cfg.type = AUDIO_STREAM_READER;
    i2s_cfg.i2s_port = 0;
    i2s_cfg.task_core = 1;
    i2s_cfg.i2s_config = (i2s_config_t)
    {
        .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
        .sample_rate = 44100,
        .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
        .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
        .communication_format = 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 = 1
    };
    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, 44100, 16, 2);
    
    //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");

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

And here is part of my sdkconfig regarding SPIRAM:

Code: Select all

# SPI RAM config
#
CONFIG_SPIRAM_TYPE_AUTO=y
# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set
# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set
CONFIG_SPIRAM_SIZE=-1
CONFIG_SPIRAM_SPEED_40M=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_BOOT_INIT=y
# CONFIG_SPIRAM_USE_MEMMAP is not set
# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set
CONFIG_SPIRAM_USE_MALLOC=y
CONFIG_SPIRAM_MEMTEST=y
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384
CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
CONFIG_SPIRAM_CACHE_WORKAROUND=y

#
# SPIRAM cache workaround debugging
#
CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_MEMW=y
# CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_DUPLDST is not set
# CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_NOPS is not set
# end of SPIRAM cache workaround debugging

CONFIG_SPIRAM_BANKSWITCH_ENABLE=y
CONFIG_SPIRAM_BANKSWITCH_RESERVE=8
# CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY is not set

hubert3x3
Posts: 3
Joined: Sun May 30, 2021 9:27 pm

Re: Using ringbuffer with PSRAM

Postby hubert3x3 » Mon Aug 16, 2021 9:54 pm

Update on my issue. I added log that shows how much of i2s_stream output buffer is filles and its size. Testing with that logs confirmed that from time to time buffer is completely filled. Also I noticed that its size was set to 8192 bytes by default.
After adding this to init issue seems to be resolved

Code: Select all

    i2s_cfg.out_rb_size = 1000*1024;
Before that I experimented with creating ringbuffer and adding it to manually to pipeline but above code seems to do the trick just fine.

Who is online

Users browsing this forum: No registered users and 26 guests