How to decode MP3 on ESP32 ?

ThomasESP32
Posts: 229
Joined: Thu Jul 14, 2022 5:15 am

How to decode MP3 on ESP32 ?

Postby ThomasESP32 » Wed Feb 15, 2023 6:52 am

Good Morning,

I need to read a MP3 file from a SD Card, to decode it using firmware and to send it via I2S to an amplifier.
Using some Espressif librairies, I managed to initialise the SDCard and to read an MP3 file on it.
Moreover, I managed to initialise I2S and to send datas manually.
Now I need to find a MP3 decoder to decode the MP3 file.

Do you know if there is some librairies that I can use in order to do it ??

I have seen some examples using ADF (Pipes, Elements, Streams and so on...) that do the job.
Unfortunately, I managed to implement it but the datas at the output of the I2S pins where not correct.
The LR_CLK and the BIT_CLK where not at the good frequency and I did not find how to correct it...
When I configured a 16KHz sample rate, the LR_CLK frequency was 1,35Khz only...

So now, I try to do it manually, and I am looking for a MP3 decoder.

Could you please help me on the subject ?

Best regards,

Thomas TRUILHE

tempo.tian
Posts: 40
Joined: Wed Jun 22, 2022 12:10 pm

Re: How to decode MP3 on ESP32 ?

Postby tempo.tian » Wed Mar 15, 2023 10:50 am

Suppose your test file is "/sdcard/test.mp3" you can use follow code directly to play mp3.

Code: Select all

#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "sdkconfig.h"
#include "audio_element.h"
#include "audio_pipeline.h"
#include "audio_event_iface.h"
#include "audio_common.h"
#include "fatfs_stream.h"
#include "i2s_stream.h"
#include "mp3_decoder.h"
#include "wav_encoder.h"
#include "esp_peripherals.h"
#include "periph_sdcard.h"
#include "board.h"

static const char *TAG = "MP3_EXAMPLE";

void app_main(void)
{
    audio_pipeline_handle_t pipeline;
    audio_element_handle_t fatfs_stream_reader, i2s_stream_writer, mp3_decoder;
    esp_log_level_set("*", ESP_LOG_WARN);
    esp_log_level_set(TAG, ESP_LOG_INFO);
    ESP_LOGI(TAG, "[1.0] Mount sdcard");
    // Initialize peripherals management
    esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();
    esp_periph_set_handle_t set = esp_periph_set_init(&periph_cfg);
    // Initialize SD Card peripheral
    audio_board_sdcard_init(set, SD_MODE_1_LINE);

    ESP_LOGI(TAG, "[2.0] Start codec chip");
    audio_board_handle_t board_handle = audio_board_init();
    audio_hal_ctrl_codec(board_handle->audio_hal, AUDIO_HAL_CODEC_MODE_BOTH, AUDIO_HAL_CTRL_START);

    ESP_LOGI(TAG, "[3.0] Create audio pipeline");
    audio_pipeline_cfg_t pipeline_cfg = DEFAULT_AUDIO_PIPELINE_CONFIG();
    pipeline = audio_pipeline_init(&pipeline_cfg);
    mem_assert(pipeline);

    fatfs_stream_cfg_t fatfs_cfg = FATFS_STREAM_CFG_DEFAULT();
    fatfs_cfg.type = AUDIO_STREAM_READER;
    fatfs_stream_reader = fatfs_stream_init(&fatfs_cfg);

    i2s_stream_cfg_t i2s_cfg = I2S_STREAM_CFG_DEFAULT();
    i2s_cfg.type = AUDIO_STREAM_WRITER;
    i2s_stream_writer = i2s_stream_init(&i2s_cfg);

    mp3_decoder_cfg_t mp3_dec_cfg = DEFAULT_MP3_DECODER_CONFIG();
    mp3_decoder = mp3_decoder_init(&mp3_dec_cfg);

    ESP_LOGI(TAG, "[3.1] Register all elements to audio pipeline");
    audio_pipeline_register(pipeline, fatfs_stream_reader, "file_read");
    audio_pipeline_register(pipeline, mp3_decoder, "mp3_decoder");
    audio_pipeline_register(pipeline, i2s_stream_writer, "i2s");

    ESP_LOGI(TAG, "[3.2] Link it together [sdcard]-->fatfs_stream-->mp3_decoder-->i2s_stream");
    audio_pipeline_link(pipeline, (const char *[]) {
        "file_read", "mp3_decoder",  "i2s"
    }, 3);

    ESP_LOGI(TAG, "[3.3] Set up  uri (file as fatfs_stream, wav as wav decoder, and default output is i2s)");
    audio_element_set_uri(fatfs_stream_reader, "/sdcard/test.mp3"); // change your test file name here

    ESP_LOGI(TAG, "[4.0] 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);

    ESP_LOGI(TAG, "[4.1] Listening event from all elements of pipeline");
    audio_pipeline_set_listener(pipeline, evt);

    ESP_LOGI(TAG, "[4.2] Listening event from peripherals");
    audio_event_iface_set_listener(esp_periph_set_get_event_iface(set), evt);

    ESP_LOGI(TAG, "[5.0] Start audio_pipeline");
    audio_pipeline_run(pipeline);

    ESP_LOGI(TAG, "[6.0] Listen for all pipeline events");
    while (1) {
        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 wav 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.cmd == AEL_MSG_CMD_REPORT_STATUS
            && (((int)msg.data == AEL_STATUS_STATE_STOPPED) || ((int)msg.data == AEL_STATUS_STATE_FINISHED))) {
            ESP_LOGW(TAG, "[ * ] Stop event received");
            break;
        }
    }

    ESP_LOGI(TAG, "[7.0] Stop audio_pipeline and release all resources");
    audio_pipeline_stop(pipeline);
    audio_pipeline_wait_for_stop(pipeline);
    audio_pipeline_terminate(pipeline);
    audio_pipeline_unregister(pipeline, fatfs_stream_reader);
    audio_pipeline_unregister(pipeline, mp3_decoder);
    audio_pipeline_unregister(pipeline, i2s_stream_writer);

    /* Terminate the pipeline before removing the listener */
    audio_pipeline_remove_listener(pipeline);

    /* Stop all peripheral before removing the listener */
    esp_periph_set_stop_all(set);
    audio_event_iface_remove_listener(esp_periph_set_get_event_iface(set), evt);

    /* Make sure audio_pipeline_remove_listener & audio_event_iface_remove_listener are called before destroying event_iface */
    audio_event_iface_destroy(evt);

    /* Release all resources */
    audio_pipeline_deinit(pipeline);
    audio_element_deinit(fatfs_stream_reader);
    audio_element_deinit(mp3_decoder);
    audio_element_deinit(i2s_stream_writer);
    esp_periph_set_destroy(set);
}

CobaltEcho
Posts: 7
Joined: Sun Aug 13, 2023 10:35 pm

Re: How to decode MP3 on ESP32 ?

Postby CobaltEcho » Sun Aug 13, 2023 11:54 pm

Did you ever figure this out? I've been trying to do the exact same thing!

dauhen
Posts: 2
Joined: Sat Sep 16, 2023 5:08 pm

Re: How to decode MP3 on ESP32 ?

Postby dauhen » Sat Sep 16, 2023 5:14 pm

Try the esp-adf player example called pipeline_play_sdcard_music. It works perfectly for me on mp3 files on an SD card using the ESP32-LryaT-Mini v1.2.

Who is online

Users browsing this forum: No registered users and 13 guests