ESP32 LyraT音频开发板试玩(二):播放音乐

Stella981
• 阅读 753

我是卓波,很高兴你来看我的博客。

系列文章:

ESP32 LyraT音频开发板试玩(一):搭建开发环境

ESP32 LyraT音频开发板试玩(二):播放音乐

本文延续上一篇博客

将D:\msys32\home\user\esp\esp-adf\examples\get-started目录下的play_mp3工程直接拷贝到esp目录下

 ESP32 LyraT音频开发板试玩(二):播放音乐

看一下代码,代码量也不多,核心是创建一个mp3元素和一个i2s元素,然后将两个元素链接到管道中。

形成了mp3元素拿数据给i2s元素播放的关系。

/* Play mp3 file by audio pipeline

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/

#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "esp_log.h"
#include "audio_element.h"
#include "audio_pipeline.h"
#include "audio_event_iface.h"
#include "audio_mem.h"
#include "audio_common.h"
#include "i2s_stream.h"
#include "mp3_decoder.h"
#include "audio_hal.h"

static const char *TAG = "PLAY_MP3_FLASH";
/*
   To embed it in the app binary, the mp3 file is named
   in the component.mk COMPONENT_EMBED_TXTFILES variable.
*/
extern const uint8_t adf_music_mp3_start[] asm("_binary_adf_music_mp3_start");
extern const uint8_t adf_music_mp3_end[]   asm("_binary_adf_music_mp3_end");

int mp3_music_read_cb(audio_element_handle_t el, char *buf, int len, TickType_t wait_time, void *ctx)
{
    static int mp3_pos;
    int read_size = adf_music_mp3_end - adf_music_mp3_start - mp3_pos;
    if (read_size == 0) {
        return AEL_IO_DONE;
    } else if (len < read_size) {
        read_size = len;
    }
    memcpy(buf, adf_music_mp3_start + mp3_pos, read_size);
    mp3_pos += read_size;
    return read_size;
}

void app_main(void)
{
    audio_pipeline_handle_t pipeline;
    audio_element_handle_t i2s_stream_writer, mp3_decoder;
    esp_log_level_set("*", ESP_LOG_WARN);
    esp_log_level_set(TAG, ESP_LOG_INFO);


    ESP_LOGI(TAG, "[ 1 ] Start audio codec chip");
    audio_hal_codec_config_t audio_hal_codec_cfg =  AUDIO_HAL_ES8388_DEFAULT();
    audio_hal_handle_t hal = audio_hal_init(&audio_hal_codec_cfg, 0);
    audio_hal_ctrl_codec(hal, AUDIO_HAL_CODEC_MODE_DECODE, AUDIO_HAL_CTRL_START);

    ESP_LOGI(TAG, "[ 2 ] Create audio pipeline, add all elements to pipeline, and subscribe pipeline event");
    audio_pipeline_cfg_t pipeline_cfg = DEFAULT_AUDIO_PIPELINE_CONFIG();
    pipeline = audio_pipeline_init(&pipeline_cfg);
    mem_assert(pipeline);

    ESP_LOGI(TAG, "[2.1] Create mp3 decoder to decode mp3 file and set custom read callback");
    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);

    ESP_LOGI(TAG, "[2.2] Create i2s stream to write data to codec chip");
    i2s_stream_cfg_t i2s_cfg = I2S_STREAM_CFG_DEFAULT();
    i2s_cfg.type = AUDIO_STREAM_WRITER;
    i2s_stream_writer = i2s_stream_init(&i2s_cfg);

    ESP_LOGI(TAG, "[2.3] Register all elements to audio pipeline");
    audio_pipeline_register(pipeline, mp3_decoder, "mp3");
    audio_pipeline_register(pipeline, i2s_stream_writer, "i2s");

    ESP_LOGI(TAG, "[2.4] Link it together [mp3_music_read_cb]-->mp3_decoder-->i2s_stream-->[codec_chip]");
    audio_pipeline_link(pipeline, (const char *[]) {"mp3", "i2s"}, 2);

    ESP_LOGI(TAG, "[ 3 ] Setup 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, "[3.1] Listening event from all elements of pipeline");
    audio_pipeline_set_listener(pipeline, evt);

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

    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 mp3 decoder, sample_rates=%d, bits=%d, ch=%d",
                music_info.sample_rates, music_info.bits, music_info.channels);

            audio_element_setinfo(i2s_stream_writer, &music_info);
            i2s_stream_set_clk(i2s_stream_writer, music_info.sample_rates, music_info.bits, music_info.channels);
            continue;
        }
        /* Stop when the last pipeline element (i2s_stream_writer in this case) receives stop event */
        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) {
            break;
        }
    }

    ESP_LOGI(TAG, "[ 5 ] Stop audio_pipeline");
    audio_pipeline_terminate(pipeline);

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

    /* Make sure audio_pipeline_remove_listener is called before destroying event_iface */
    audio_event_iface_destroy(evt);

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

然后根据上一篇介绍的方法编译和下载

 ESP32 LyraT音频开发板试玩(二):播放音乐

ESP32 LyraT音频开发板试玩(二):播放音乐

运行后在串口调试助手输出

ets Jun  8 2016 00:22:57

 

rst:0x1 (POWERON_RESET),boot:0x3f (SPI_FAST_FLASH_BOOT)

flash read err, 1000

ets_main.c 371

ets Jun  8 2016 00:22:57

 

rst:0x10 (RTCWDT_RTC_RESET),boot:0x3f (SPI_FAST_FLASH_BOOT)

configsip: 0, SPIWP:0xee

clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00

mode:DIO, clock div:2

load:0x3fff0018,len:4

load:0x3fff001c,len:5576

load:0x40078000,len:0

ho 12 tail 0 room 4

load:0x40078000,len:13756

entry 0x40078fb4

[0;32mI (31) boot: ESP-IDF v3.0.1 2nd stage bootloader[0m

[0;32mI (31) boot: compile time 11:50:00[0m

[0;32mI (33) boot: Enabling RNG early entropy source...[0m

[0;32mI (35) boot: SPI Speed      : 40MHz[0m

[0;32mI (39) boot: SPI Mode       : DIO[0m

[0;32mI (43) boot: SPI Flash Size : 4MB[0m

[0;32mI (47) boot: Partition Table:[0m

[0;32mI (51) boot: ## Label            Usage          Type ST Offset   Length[0m

[0;32mI (58) boot:  0 nvs              WiFi data        01 02 00009000 00006000[0m

[0;32mI (66) boot:  1 phy_init         RF data          01 01 0000f000 00001000[0m

[0;32mI (73) boot:  2 factory          factory app      00 00 00010000 00100000[0m

[0;32mI (81) boot: End of partition table[0m

[0;32mI (85) esp_image: segment 0: paddr=0x00010020 vaddr=0x3f400020 size=0x1f468 (128104) map[0m

[0;32mI (139) esp_image: segment 1: paddr=0x0002f490 vaddr=0x3ffb0000 size=0x00b80 (  2944) load[0m

[0;32mI (140) esp_image: segment 2: paddr=0x00030018 vaddr=0x400d0018 size=0x21604 (136708) map[0m

[0;32mI (193) esp_image: segment 3: paddr=0x00051624 vaddr=0x3ffb0b80 size=0x0169c (  5788) load[0m

[0;32mI (196) esp_image: segment 4: paddr=0x00052cc8 vaddr=0x40080000 size=0x00400 (  1024) load[0m

[0;32mI (200) esp_image: segment 5: paddr=0x000530d0 vaddr=0x40080400 size=0x09e80 ( 40576) load[0m

[0;32mI (226) esp_image: segment 6: paddr=0x0005cf58 vaddr=0x400c0000 size=0x00000 (     0) load[0m

[0;32mI (232) boot: Loaded app from partition at offset 0x10000[0m

[0;32mI (232) boot: Disabling RNG early entropy source...[0m

[0;32mI (235) cpu_start: Pro cpu up.[0m

[0;32mI (239) cpu_start: Starting app cpu, entry point is 0x40080ee4[0m

[0;32mI (0) cpu_start: App cpu up.[0m

[0;32mI (249) heap_init: Initializing. RAM available for dynamic allocation:[0m

[0;32mI (256) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM[0m

[0;32mI (262) heap_init: At 3FFB2A48 len 0002D5B8 (181 KiB): DRAM[0m

[0;32mI (268) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM[0m

[0;32mI (275) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM[0m

[0;32mI (281) heap_init: At 4008A280 len 00015D80 (87 KiB): IRAM[0m

[0;32mI (287) cpu_start: Pro cpu start user code[0m

[0;32mI (305) cpu_start: Starting scheduler on PRO CPU.[0m

[0;32mI (0) cpu_start: Starting scheduler on APP CPU.[0m

[0;32mI (307) PLAY_MP3_FLASH: [ 1 ] Start audio codec chip[0m

[0;32mI (327) PLAY_MP3_FLASH: [ 2 ] Create audio pipeline, add all elements to pipeline, and subscribe pipeline event[0m

[0;32mI (327) PLAY_MP3_FLASH: [2.1] Create mp3 decoder to decode mp3 file and set custom read callback[0m

[0;32mI (337) PLAY_MP3_FLASH: [2.2] Create i2s stream to write data to codec chip[0m

[0;32mI (347) PLAY_MP3_FLASH: [2.3] Register all elements to audio pipeline[0m

[0;32mI (357) PLAY_MP3_FLASH: [2.4] Link it together [mp3_music_read_cb]-->mp3_decoder-->i2s_stream-->[codec_chip][0m

[0;32mI (367) PLAY_MP3_FLASH: [ 3 ] Setup event listener[0m

[0;32mI (367) PLAY_MP3_FLASH: [3.1] Listening event from all elements of pipeline[0m

[0;32mI (377) PLAY_MP3_FLASH: [ 4 ] Start audio_pipeline[0m

[0;32mI (397) PLAY_MP3_FLASH: [ * ] Receive music info from mp3 decoder, sample_rates=44100, bits=16, ch=2[0m

[0;32mI (7177) PLAY_MP3_FLASH: [ 5 ] Stop audio_pipeline[0m

[0;33mW (7177) AUDIO_PIPELINE: There are no listener registered[0m

接上喇叭,就可以听到音乐

ESP32 LyraT音频开发板试玩(二):播放音乐

关于idf和adf的api用法,官方有相关教程链接:

IDF: https://docs.espressif.com/projects/esp-idf/en/latest/

ADF: https://docs.espressif.com/projects/esp-adf/en/latest/

最后

本文主要介绍了运行adf的mp3播放例子的方法,在adf的examples文件夹下还有很多例子,亲们可以去研究研究。

版权所有,转载请打赏哟

如果你喜欢我的文章,可以通过微信扫一扫给我打赏哟

ESP32 LyraT音频开发板试玩(二):播放音乐

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
3年前
Google地球出现“无法连接到登录服务器(错误代码:c00a0194)”解决方法
Google地球出现“无法连接到登录服务器(错误代码:c00a0194)”解决方法参考文章:(1)Google地球出现“无法连接到登录服务器(错误代码:c00a0194)”解决方法(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fwww.codeprj.com%2Fblo
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这