我是卓波,很高兴你来看我的博客。
系列文章:
本文延续上一篇博客
将D:\msys32\home\user\esp\esp-adf\examples\get-started目录下的play_mp3工程直接拷贝到esp目录下

看一下代码,代码量也不多,核心是创建一个mp3元素和一个i2s元素,然后将两个元素链接到管道中。
形成了mp3元素拿数据给i2s元素播放的关系。
1/* Play mp3 file by audio pipeline 2 3 This example code is in the Public Domain (or CC0 licensed, at your option.) 4 5 Unless required by applicable law or agreed to in writing, this 6 software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 7 CONDITIONS OF ANY KIND, either express or implied. 8*/ 9 10#include <string.h> 11#include "freertos/FreeRTOS.h" 12#include "freertos/task.h" 13 14#include "esp_log.h" 15#include "audio_element.h" 16#include "audio_pipeline.h" 17#include "audio_event_iface.h" 18#include "audio_mem.h" 19#include "audio_common.h" 20#include "i2s_stream.h" 21#include "mp3_decoder.h" 22#include "audio_hal.h" 23 24static const char *TAG = "PLAY_MP3_FLASH"; 25/* 26 To embed it in the app binary, the mp3 file is named 27 in the component.mk COMPONENT_EMBED_TXTFILES variable. 28*/ 29extern const uint8_t adf_music_mp3_start[] asm("_binary_adf_music_mp3_start"); 30extern const uint8_t adf_music_mp3_end[] asm("_binary_adf_music_mp3_end"); 31 32int mp3_music_read_cb(audio_element_handle_t el, char *buf, int len, TickType_t wait_time, void *ctx) 33{ 34 static int mp3_pos; 35 int read_size = adf_music_mp3_end - adf_music_mp3_start - mp3_pos; 36 if (read_size == 0) { 37 return AEL_IO_DONE; 38 } else if (len < read_size) { 39 read_size = len; 40 } 41 memcpy(buf, adf_music_mp3_start + mp3_pos, read_size); 42 mp3_pos += read_size; 43 return read_size; 44} 45 46void app_main(void) 47{ 48 audio_pipeline_handle_t pipeline; 49 audio_element_handle_t i2s_stream_writer, mp3_decoder; 50 esp_log_level_set("*", ESP_LOG_WARN); 51 esp_log_level_set(TAG, ESP_LOG_INFO); 52 53 54 ESP_LOGI(TAG, "[ 1 ] Start audio codec chip"); 55 audio_hal_codec_config_t audio_hal_codec_cfg = AUDIO_HAL_ES8388_DEFAULT(); 56 audio_hal_handle_t hal = audio_hal_init(&audio_hal_codec_cfg, 0); 57 audio_hal_ctrl_codec(hal, AUDIO_HAL_CODEC_MODE_DECODE, AUDIO_HAL_CTRL_START); 58 59 ESP_LOGI(TAG, "[ 2 ] Create audio pipeline, add all elements to pipeline, and subscribe pipeline event"); 60 audio_pipeline_cfg_t pipeline_cfg = DEFAULT_AUDIO_PIPELINE_CONFIG(); 61 pipeline = audio_pipeline_init(&pipeline_cfg); 62 mem_assert(pipeline); 63 64 ESP_LOGI(TAG, "[2.1] Create mp3 decoder to decode mp3 file and set custom read callback"); 65 mp3_decoder_cfg_t mp3_cfg = DEFAULT_MP3_DECODER_CONFIG(); 66 mp3_decoder = mp3_decoder_init(&mp3_cfg); 67 audio_element_set_read_cb(mp3_decoder, mp3_music_read_cb, NULL); 68 69 ESP_LOGI(TAG, "[2.2] Create i2s stream to write data to codec chip"); 70 i2s_stream_cfg_t i2s_cfg = I2S_STREAM_CFG_DEFAULT(); 71 i2s_cfg.type = AUDIO_STREAM_WRITER; 72 i2s_stream_writer = i2s_stream_init(&i2s_cfg); 73 74 ESP_LOGI(TAG, "[2.3] Register all elements to audio pipeline"); 75 audio_pipeline_register(pipeline, mp3_decoder, "mp3"); 76 audio_pipeline_register(pipeline, i2s_stream_writer, "i2s"); 77 78 ESP_LOGI(TAG, "[2.4] Link it together [mp3_music_read_cb]-->mp3_decoder-->i2s_stream-->[codec_chip]"); 79 audio_pipeline_link(pipeline, (const char *[]) {"mp3", "i2s"}, 2); 80 81 ESP_LOGI(TAG, "[ 3 ] Setup event listener"); 82 audio_event_iface_cfg_t evt_cfg = AUDIO_EVENT_IFACE_DEFAULT_CFG(); 83 audio_event_iface_handle_t evt = audio_event_iface_init(&evt_cfg); 84 85 ESP_LOGI(TAG, "[3.1] Listening event from all elements of pipeline"); 86 audio_pipeline_set_listener(pipeline, evt); 87 88 ESP_LOGI(TAG, "[ 4 ] Start audio_pipeline"); 89 audio_pipeline_run(pipeline); 90 91 while (1) { 92 audio_event_iface_msg_t msg; 93 esp_err_t ret = audio_event_iface_listen(evt, &msg, portMAX_DELAY); 94 if (ret != ESP_OK) { 95 ESP_LOGE(TAG, "[ * ] Event interface error : %d", ret); 96 continue; 97 } 98 99 if (msg.source_type == AUDIO_ELEMENT_TYPE_ELEMENT && msg.source == (void *) mp3_decoder 100 && msg.cmd == AEL_MSG_CMD_REPORT_MUSIC_INFO) { 101 audio_element_info_t music_info = {0}; 102 audio_element_getinfo(mp3_decoder, &music_info); 103 104 ESP_LOGI(TAG, "[ * ] Receive music info from mp3 decoder, sample_rates=%d, bits=%d, ch=%d", 105 music_info.sample_rates, music_info.bits, music_info.channels); 106 107 audio_element_setinfo(i2s_stream_writer, &music_info); 108 i2s_stream_set_clk(i2s_stream_writer, music_info.sample_rates, music_info.bits, music_info.channels); 109 continue; 110 } 111 /* Stop when the last pipeline element (i2s_stream_writer in this case) receives stop event */ 112 if (msg.source_type == AUDIO_ELEMENT_TYPE_ELEMENT && msg.source == (void *) i2s_stream_writer 113 && msg.cmd == AEL_MSG_CMD_REPORT_STATUS && (int) msg.data == AEL_STATUS_STATE_STOPPED) { 114 break; 115 } 116 } 117 118 ESP_LOGI(TAG, "[ 5 ] Stop audio_pipeline"); 119 audio_pipeline_terminate(pipeline); 120 121 /* Terminate the pipeline before removing the listener */ 122 audio_pipeline_remove_listener(pipeline); 123 124 /* Make sure audio_pipeline_remove_listener is called before destroying event_iface */ 125 audio_event_iface_destroy(evt); 126 127 /* Release all resources */ 128 audio_pipeline_deinit(pipeline); 129 audio_element_deinit(i2s_stream_writer); 130 audio_element_deinit(mp3_decoder); 131}
然后根据上一篇介绍的方法编译和下载


运行后在串口调试助手输出
1ets Jun 8 2016 00:22:57 2 3 4 5rst:0x1 (POWERON_RESET),boot:0x3f (SPI_FAST_FLASH_BOOT) 6 7flash read err, 1000 8 9ets_main.c 371 10 11ets Jun 8 2016 00:22:57 12 13 14 15rst:0x10 (RTCWDT_RTC_RESET),boot:0x3f (SPI_FAST_FLASH_BOOT) 16 17configsip: 0, SPIWP:0xee 18 19clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 20 21mode:DIO, clock div:2 22 23load:0x3fff0018,len:4 24 25load:0x3fff001c,len:5576 26 27load:0x40078000,len:0 28 29ho 12 tail 0 room 4 30 31load:0x40078000,len:13756 32 33entry 0x40078fb4 34 35[0;32mI (31) boot: ESP-IDF v3.0.1 2nd stage bootloader[0m 36 37[0;32mI (31) boot: compile time 11:50:00[0m 38 39[0;32mI (33) boot: Enabling RNG early entropy source...[0m 40 41[0;32mI (35) boot: SPI Speed : 40MHz[0m 42 43[0;32mI (39) boot: SPI Mode : DIO[0m 44 45[0;32mI (43) boot: SPI Flash Size : 4MB[0m 46 47[0;32mI (47) boot: Partition Table:[0m 48 49[0;32mI (51) boot: ## Label Usage Type ST Offset Length[0m 50 51[0;32mI (58) boot: 0 nvs WiFi data 01 02 00009000 00006000[0m 52 53[0;32mI (66) boot: 1 phy_init RF data 01 01 0000f000 00001000[0m 54 55[0;32mI (73) boot: 2 factory factory app 00 00 00010000 00100000[0m 56 57[0;32mI (81) boot: End of partition table[0m 58 59[0;32mI (85) esp_image: segment 0: paddr=0x00010020 vaddr=0x3f400020 size=0x1f468 (128104) map[0m 60 61[0;32mI (139) esp_image: segment 1: paddr=0x0002f490 vaddr=0x3ffb0000 size=0x00b80 ( 2944) load[0m 62 63[0;32mI (140) esp_image: segment 2: paddr=0x00030018 vaddr=0x400d0018 size=0x21604 (136708) map[0m 64 65[0;32mI (193) esp_image: segment 3: paddr=0x00051624 vaddr=0x3ffb0b80 size=0x0169c ( 5788) load[0m 66 67[0;32mI (196) esp_image: segment 4: paddr=0x00052cc8 vaddr=0x40080000 size=0x00400 ( 1024) load[0m 68 69[0;32mI (200) esp_image: segment 5: paddr=0x000530d0 vaddr=0x40080400 size=0x09e80 ( 40576) load[0m 70 71[0;32mI (226) esp_image: segment 6: paddr=0x0005cf58 vaddr=0x400c0000 size=0x00000 ( 0) load[0m 72 73[0;32mI (232) boot: Loaded app from partition at offset 0x10000[0m 74 75[0;32mI (232) boot: Disabling RNG early entropy source...[0m 76 77[0;32mI (235) cpu_start: Pro cpu up.[0m 78 79[0;32mI (239) cpu_start: Starting app cpu, entry point is 0x40080ee4[0m 80 81[0;32mI (0) cpu_start: App cpu up.[0m 82 83[0;32mI (249) heap_init: Initializing. RAM available for dynamic allocation:[0m 84 85[0;32mI (256) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM[0m 86 87[0;32mI (262) heap_init: At 3FFB2A48 len 0002D5B8 (181 KiB): DRAM[0m 88 89[0;32mI (268) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM[0m 90 91[0;32mI (275) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM[0m 92 93[0;32mI (281) heap_init: At 4008A280 len 00015D80 (87 KiB): IRAM[0m 94 95[0;32mI (287) cpu_start: Pro cpu start user code[0m 96 97[0;32mI (305) cpu_start: Starting scheduler on PRO CPU.[0m 98 99[0;32mI (0) cpu_start: Starting scheduler on APP CPU.[0m 100 101[0;32mI (307) PLAY_MP3_FLASH: [ 1 ] Start audio codec chip[0m 102 103[0;32mI (327) PLAY_MP3_FLASH: [ 2 ] Create audio pipeline, add all elements to pipeline, and subscribe pipeline event[0m 104 105[0;32mI (327) PLAY_MP3_FLASH: [2.1] Create mp3 decoder to decode mp3 file and set custom read callback[0m 106 107[0;32mI (337) PLAY_MP3_FLASH: [2.2] Create i2s stream to write data to codec chip[0m 108 109[0;32mI (347) PLAY_MP3_FLASH: [2.3] Register all elements to audio pipeline[0m 110 111[0;32mI (357) PLAY_MP3_FLASH: [2.4] Link it together [mp3_music_read_cb]-->mp3_decoder-->i2s_stream-->[codec_chip][0m 112 113[0;32mI (367) PLAY_MP3_FLASH: [ 3 ] Setup event listener[0m 114 115[0;32mI (367) PLAY_MP3_FLASH: [3.1] Listening event from all elements of pipeline[0m 116 117[0;32mI (377) PLAY_MP3_FLASH: [ 4 ] Start audio_pipeline[0m 118 119[0;32mI (397) PLAY_MP3_FLASH: [ * ] Receive music info from mp3 decoder, sample_rates=44100, bits=16, ch=2[0m 120 121[0;32mI (7177) PLAY_MP3_FLASH: [ 5 ] Stop audio_pipeline[0m 122 123[0;33mW (7177) AUDIO_PIPELINE: There are no listener registered[0m
接上喇叭,就可以听到音乐

关于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文件夹下还有很多例子,亲们可以去研究研究。
版权所有,转载请打赏哟
如果你喜欢我的文章,可以通过微信扫一扫给我打赏哟
