Page 1 of 1

Audio Pipline with MAX98357A issue.

Posted: Fri Jun 14, 2024 9:47 am
by Parth1568
I have custom hardware and I can play sine tone on the speaker using ESP-IDF 5.2.1, But when I try to use ADF for Audio application to play MP3 I can not see any error on log or crash.
Am I missing some thing here I am attaching code and load.

Code: Select all


#include <string.h>
#include <stdio.h>
#include <math.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "esp_heap_caps.h"

#include "audio_element.h"
#include "audio_pipeline.h"
#include "audio_event_iface.h"
#include "audio_common.h"
#include "i2s_stream.h"
#include "mp3_decoder.h"

#define SAMPLE_RATE (44100)
#define PI (3.14159265)

static const char *TAG = "main";

// Define the MP3 file in flash memory
extern const uint8_t mp3_file_start[] asm("_binary_music_mp3_start");
extern const uint8_t mp3_file_end[] asm("_binary_music_mp3_end");

static struct
{
    int pos;
    const uint8_t *start;
    const uint8_t *end;
} file_marker;

int mp3_music_read_cb(audio_element_handle_t el, char *buf, int len, TickType_t wait_time, void *ctx)
{
    int read_size = file_marker.end - file_marker.start - file_marker.pos;
    if (read_size == 0)
    {
        return AEL_IO_DONE;
    }
    else if (len < read_size)
    {
        read_size = len;
    }
    memcpy(buf, file_marker.start + file_marker.pos, read_size);
    file_marker.pos += read_size;
    ESP_LOGD(TAG, "Read %d bytes from MP3 file, total read: %d bytes", read_size, file_marker.pos);
    return read_size;
}


void generate_sine_wave(int16_t *buffer, int sample_count, int frequency)
{
    for (int i = 0; i < sample_count; i++)
    {
        buffer[i] = (int16_t)(sin(2.0 * PI * frequency * ((float)i / SAMPLE_RATE)) * INT16_MAX);
    }
}

void test_sine_wave(audio_element_handle_t i2s_stream_writer)
{
    const int sample_count = 1024;
    int16_t samples[sample_count];
    const int frequency = 440; // A4 note

    generate_sine_wave(samples, sample_count, frequency);

    int bytes_written = audio_element_output(i2s_stream_writer, samples, sample_count * sizeof(int16_t));
    if (bytes_written <= 0)
    {
        ESP_LOGE(TAG, "Failed to write sine wave to I2S stream");
    }
}

void app_main(void)
{
    audio_pipeline_handle_t pipeline;
    audio_element_handle_t i2s_stream_writer, mp3_decoder;

    esp_log_level_set("*", ESP_LOG_VERBOSE);
    esp_log_level_set(TAG, ESP_LOG_INFO);

    ESP_LOGI(TAG, "[1] Initialize audio pipeline");

    audio_pipeline_cfg_t pipeline_cfg = DEFAULT_AUDIO_PIPELINE_CONFIG();
    pipeline = audio_pipeline_init(&pipeline_cfg);
    mem_assert(pipeline);

    ESP_LOGI(TAG, "[2] Create audio elements and set up callbacks");

    mp3_decoder_cfg_t mp3_cfg = DEFAULT_MP3_DECODER_CONFIG();

    mp3_decoder = mp3_decoder_init(&mp3_cfg);
    audio_element_set_read_cb(mp3_decoder, mp3_music_read_cb, NULL);

    //     // Create I2S stream writer with detailed configuration

    i2s_std_config_t std_cfg = {
        .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(SAMPLE_RATE), // Example sample rate
        .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
        .gpio_cfg = {
            .mclk = I2S_GPIO_UNUSED,
            .bclk = 26, // BCLK pin number
            .ws = 25,   // LRCLK pin number
            .dout = 22, // Data Out pin number
            .din = I2S_GPIO_UNUSED,
            .invert_flags = {
                .mclk_inv = false,
                .bclk_inv = false,
                .ws_inv = false,
            },
        },
    };
    i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER);

    i2s_stream_cfg_t i2s_cfg = I2S_STREAM_CFG_DEFAULT();
    i2s_cfg.type = AUDIO_STREAM_WRITER;
    i2s_cfg.chan_cfg = chan_cfg;
    i2s_cfg.std_cfg = std_cfg;

    i2s_stream_writer = i2s_stream_init(&i2s_cfg);
    if (!i2s_stream_writer)
    {
        ESP_LOGE(TAG, "Failed to create I2S stream writer");
        return;
    }
    AUDIO_NULL_CHECK(TAG, i2s_stream_writer, return); // Check if initialization was successful

    ESP_LOGI(TAG, "[3] Register elements to audio pipeline");

    audio_pipeline_register(pipeline, mp3_decoder, "mp3");
    audio_pipeline_register(pipeline, i2s_stream_writer, "i2s");

    ESP_LOGI(TAG, "[4] Link elements together");

    const char *link_tag[2] = {"mp3", "i2s"};
    audio_pipeline_link(pipeline, &link_tag[0], 2);

    ESP_LOGI(TAG, "[5] Set up event listener");

    audio_event_iface_cfg_t evt_cfg = AUDIO_EVENT_IFACE_DEFAULT_CFG();
    audio_event_iface_handle_t evt = audio_event_iface_init(&evt_cfg);
    audio_pipeline_set_listener(pipeline, evt);

    ESP_LOGI(TAG, "[6] Start audio_pipeline");

    file_marker.start = mp3_file_start;
    file_marker.end = mp3_file_end;
    file_marker.pos = 0;
    audio_pipeline_run(pipeline);

    ESP_LOGI(TAG, "[7] Test I2S stream with sine wave");

    // Add a small delay to ensure the pipeline is running
    vTaskDelay(pdMS_TO_TICKS(100));

    test_sine_wave(i2s_stream_writer);


    ESP_LOGI(TAG, "[7] Listen for events");

    while (true)
    {
        audio_event_iface_msg_t msg;
        esp_err_t ret = audio_event_iface_listen(evt, &msg, portMAX_DELAY);
        if (ret != ESP_OK)
        {
            ESP_LOGE(TAG, "[ * ] Event interface error : %d", ret);
            continue;
        }

        if (msg.source_type == AUDIO_ELEMENT_TYPE_ELEMENT && msg.source == (void *)mp3_decoder && msg.cmd == AEL_MSG_CMD_REPORT_MUSIC_INFO)
        {
            audio_element_info_t music_info = {0};
            audio_element_getinfo(mp3_decoder, &music_info);

            ESP_LOGI(TAG, "[ * ] Receive music info from mp3 decoder, sample_rates=%d, bits=%d, ch=%d",
                     music_info.sample_rates, music_info.bits, music_info.channels);
            i2s_stream_set_clk(i2s_stream_writer, music_info.sample_rates, music_info.bits, music_info.channels);
            continue;
        }

        if (msg.source_type == AUDIO_ELEMENT_TYPE_ELEMENT && msg.source == (void *)i2s_stream_writer && msg.cmd == AEL_MSG_CMD_REPORT_STATUS && (int)msg.data == AEL_STATUS_STATE_STOPPED)
        {
            ESP_LOGW(TAG, "[ * ] Stop event received");
            break;
        }

        vTaskDelay(100 / portTICK_PERIOD_MS);
    }

    ESP_LOGI(TAG, "[8] Stop and clean up");

    audio_pipeline_stop(pipeline);
    audio_pipeline_wait_for_stop(pipeline);
    audio_pipeline_terminate(pipeline);
    audio_pipeline_unregister(pipeline, mp3_decoder);
    audio_pipeline_unregister(pipeline, i2s_stream_writer);
    audio_pipeline_remove_listener(pipeline);
    audio_event_iface_destroy(evt);
    audio_pipeline_deinit(pipeline);
    audio_element_deinit(mp3_decoder);
    audio_element_deinit(i2s_stream_writer);
}
Log is as per below

I (866) esp_psram: Adding pool of 4096K of PSRAM memory to heap allocator
I (874) spi_flash: detected chip: winbond
I (878) spi_flash: flash io: dio
I (882) main_task: Started on CPU0
I (892) esp_psram: Reserving pool of 32K of internal memory for DMA/internal allocations
I (892) main_task: Calling app_main()
I (892) main: [1] Initialize audio pipeline
I (902) main: [2] Create audio elements and set up callbacks
I (902) MP3_DECODER: MP3 init
I (912) main: [3] Register elements to audio pipeline
I (912) main: [4] Link elements together
I (922) AUDIO_PIPELINE: link el->rb, el:0x3f800a8c, tag:mp3, rb:0x3f801028
I (922) main: [5] Set up event listener
I (932) main: [6] Start audio_pipeline
I (932) AUDIO_THREAD: The mp3 task allocate stack on external memory
I (942) AUDIO_ELEMENT: [mp3-0x3f800a8c] Element task created
I (952) AUDIO_THREAD: The i2s task allocate stack on internal memory
I (952) AUDIO_ELEMENT: [i2s-0x3f800cd4] Element task created
I (962) AUDIO_PIPELINE: Func:audio_pipeline_run, Line:359, MEM Total:4439252 Bytes, Inter:340135 Bytes, Dram:286151 Bytes

I (972) AUDIO_ELEMENT: [mp3] AEL_MSG_CMD_RESUME,state:1
I (982) MP3_DECODER: MP3 opened
I (982) CODEC_ELEMENT_HELPER: The element is 0x3f800a8c. The reserve data 2 is 0x0.
I (1002) AUDIO_ELEMENT: [i2s] AEL_MSG_CMD_RESUME,state:1
I (1022) AUDIO_PIPELINE: Pipeline started
I (1022) main: [7] Test I2S stream with sine wave
I (18902) AUDIO_ELEMENT: IN-[mp3] AEL_IO_DONE,-2
I (19062) MP3_DECODER: Closed
I (19082) AUDIO_ELEMENT: IN-[i2s] AEL_IO_DONE,-2
I (19092) main: [7] Listen for events
I (19192) main: [ * ] Receive music info from mp3 decoder, sample_rates=44100, bits=16, ch=2