# SD 卡音乐播放器 - [English Version](./README.md) - 例程难度:⭐⭐ ## 例程简介 本例程演示一个带触摸屏 UI 的 SD 卡音乐播放器。例程可扫描 microSD 卡中的本地音乐文件,在屏幕上显示播放器界面、歌曲信息和播放控制入口,并通过音频输出设备播放音乐。 ### 典型场景 - 带触摸屏的本地音乐播放器 - SD 卡音频文件扫描与列表播放 - 屏幕播放器界面与音频播放状态联动 ### 运行机制 1. `esp_board_manager` 初始化 SD 卡、音频 DAC、LCD 与触摸 2. `esp_media_db` 扫描 SD 卡挂载点 `/sdcard` 下的 `.mp3`、`.aac`、`.wav` 文件(扫描深度为 1) 3. `esp_playlist` 导入扫描结果并管理播放模式(单曲循环 / 列表循环 / 随机播放) 4. `esp_audio_simple_player` 异步解码,PCM 通过 `esp_codec_dev_write()` 直接写入 codec 输出 5. `esp_lvgl_adapter` 运行 LVGL 任务,显示 `lv_demo_music` 界面并叠加中文歌名与控制按钮 ### 文件结构 ``` music_player/ ├── assets/ font.ttf 可放在此目录,编译时打入 assets 分区 ├── main/ │ ├── app_main.c 例程入口 │ ├── music_player_config.h 默认音量、字体路径等宏 │ ├── music_player_board.c/h 板级设备初始化 │ ├── music_player_display.c/h LVGL adapter 与显示注册 │ ├── music_player_playback.c/h 播放列表与 simple player 控制 │ ├── music_player_ui.c/h LVGL music demo 与触摸控制 │ └── idf_component.yml ├── partitions.csv ├── sdkconfig.defaults ├── sdkconfig.defaults.esp32p4 ├── pytest_music_player.py ├── README.md └── README_CN.md ``` ## 环境配置 ### 硬件要求 - microSD 卡(FAT 文件系统) - 扬声器或耳机(连接到开发板音频输出) - LCD 屏与触摸输入设备 ### 默认 IDF 分支 本例程支持 IDF release/v5.4 (>= v5.4.3) 与 release/v5.5 (>= v5.5.2) 分支。 ### 软件要求 - 在 microSD 卡挂载点 `/sdcard` 下放入 `.mp3`、`.aac` 或 `.wav` 测试文件(支持中文文件名) - 如需使用 FreeType 显示中文,将 `font.ttf` 放入 `assets/` 目录;编译时会打入 Flash 的 assets 分区(须确认字体授权可再分发)。未提供时使用内置 CJK 字体 ## 编译和下载 ### 编译准备 编译本例程前需先确保已配置 ESP-IDF 环境;若已配置可跳过本段,直接进入工程目录。若未配置,请在 ESP-IDF 根目录运行以下脚本完成环境设置,完整步骤请根据目标芯片参阅 [《ESP-IDF 编程指南》](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/)。 ``` ./install.sh . ./export.sh ``` 下面是简略步骤: - 进入本例程工程目录: ``` cd adf_examples/player/music_player ``` 本示例使用 [ESP Board Manager](https://github.com/espressif/esp-board-manager) 管理板级资源。安装辅助工具 [`esp-bmgr-assist`](https://pypi.org/project/esp-bmgr-assist/) 后,可通过下文命令选择开发板。 - 在已激活的 ESP-IDF Python 环境下安装辅助工具(同一环境只需安装一次): ```bash pip install esp-bmgr-assist ``` - 选择开发板。所选板型需要包含 `fs_sdcard`、`audio_dac`、`display_lcd` 与 `lcd_touch` 设备: ```bash idf.py bmgr -b <board_name> # 例如选择本文档验证使用的 ESP32-P4 Function EV idf.py bmgr -b esp32_p4_function_ev ``` > [!NOTE] > 如果切换为其他 `esp_board_manager` 支持的开发板,请按相同步骤执行并替换板型名称。 > 自定义开发板请参考 [自定义开发板指南](https://github.com/espressif/esp-board-manager/blob/main/esp_board_manager/docs/how_to_customize_board_cn.md)。 > `esp_board_manager` 更多信息请参考 [ESP_BOARD_MANAGER 入门指南](https://github.com/espressif/esp-board-manager/blob/main/esp_board_manager/README_CN.md) ### 项目配置 本例程默认行为由 `main/music_player_config.h` 与 `sdkconfig.defaults` 决定,通常无需额外 menuconfig。常用可调项如下: - `MUSIC_PLAYER_DEFAULT_VOLUME`:默认播放音量(当前为 70) - `MUSIC_PLAYER_FONT_PATH` / `MUSIC_PLAYER_FONT_SIZE`:FreeType 字体路径与字号(默认 `F:font.ttf`、24) - `MUSIC_PLAYER_SCAN_DEPTH`:媒体库扫描深度(当前为 1,对应挂载点 `/sdcard`) 如需启用或关闭 FreeType、CJK 内置字体等 LVGL 相关选项,可在 `idf.py menuconfig` 中查看 `Component config` → `ESP LVGL Adapter` 与 `LVGL configuration`。 ### 编译与烧录 - 编译示例程序 ``` idf.py build ``` - 烧录程序并运行 monitor 工具来查看串口输出 (替换 PORT 为端口名称): ``` idf.py -p PORT flash monitor ``` - 退出调试界面使用 `Ctrl-]` ## 如何使用例程 ### 功能和用法 1. 将音乐文件放入 microSD 卡挂载点 `/sdcard` 或其一层子目录(见下文 log 中的 `scan dir: /sdcard`) 2. 上电后例程自动扫描;若找到音乐则播放第一首,否则 UI 显示“未找到音乐” 3. 触摸屏底部控制栏: - 上一首 / 播放或暂停 / 下一首 - 循环模式按钮:依次切换单曲循环、列表循环、随机播放 4. 顶部显示当前歌名(固定宽度省略显示,支持中文)和播放模式 5. 背景使用 LVGL 自带 `lv_demo_music` 界面,进度条为 demo 动效,不绑定真实播放进度 6. 当前曲目播放结束后自动播放下一首(按当前模式) ### 日志输出 以下为 ESP32-P4 Function EV 实机运行时的连续串口 log 片段,包含 `[ 1 ]`~`[ 5 ]` 步骤、`Scanned N tracks` 与 `Play file:` 等关键信息。不同开发板的 LCD、触摸与 codec 初始化日志会随板级设备配置变化。 ```text I (1229) main_task: Calling app_main() I (1229) MUSIC_PLAYER: [ 1 ] Initialize board peripherals I (1229) PERIPH_LDO: LDO initialize success W (1229) ldo: The voltage value 0 is out of the recommended range [500, 2700] I (1229) DEV_FS_FAT_SUB_SDMMC: slot_config: cd=-1, wp=-1, clk=0, cmd=0, d0=0, d1=0, d2=0, d3=0, d4=0, d5=0, d6=0, d7=0, width=4, flags=0x1 Name: SC32G Type: SDHC Speed: 40.00 MHz (limit: 40.00 MHz) Size: 30436MB CSD: ver=2, sector_size=512, capacity=62333952 read_bl_len=9 SSR: bus_width=4 I (1276) DEV_FS_FAT: Filesystem mounted, base path: /sdcard I (1276) BOARD_MANAGER: Device fs_sdcard initialized I (1277) BOARD_DEVICE: Device handle fs_sdcard found, Handle: 0x4ffbb43c TO: 0x4ffbb43c I (1278) PERIPH_I2S: I2S[0] STD, TX, ws: 10, bclk: 12, dout: 9, din: 11 I (1278) PERIPH_I2S: I2S[0] initialize success: 0x4800822c I (1278) DEV_AUDIO_CODEC: DAC is ENABLED I (1278) PERIPH_GPIO: Initialize success, pin: 53, set the default level: 0 I (1279) PERIPH_I2C: I2C master bus initialized successfully I (1284) ES8311: Work in Slave mode I (1287) DEV_AUDIO_CODEC: Successfully initialized codec: audio_dac I (1287) DEV_AUDIO_CODEC: Create esp_codec_dev success, dev:0x4ffbc284, chip:es8311 I (1287) BOARD_MANAGER: Device audio_dac initialized I (1287) BOARD_DEVICE: Device handle audio_dac found, Handle: 0x4ffbb854 TO: 0x4ffbb854 I (1288) I2S_IF: No paired data, current mode: playback I (1288) I2S_IF: STD: TX, data_bit: 16, slot_bit: 16, ws_width: 16, slot_mode: STEREO, slot_mask: 0x3 I (1289) I2S_IF: STD: TX, sample_rate_hz: 48000, mclk_multiple: 256, clk_src: 0 I (1303) Adev_Codec: Open codec device OK I (1303) MUSIC_PLAYER_BOARD: SD card mounted at /sdcard, scan dir: /sdcard I (1304) MUSIC_PLAYER: [ 2 ] Initialize display and LVGL music UI I (1304) DEV_DISPLAY_LCD: Initializing LCD display: display_lcd, chip: ek79007, sub_type: dsi I (1304) DEV_DISPLAY_LCD_SUB_DSI: Initializing DSI LCD display: display_lcd, chip: ek79007 I (1304) BOARD_PERIPH: Reuse periph: ldo_mipi, ref_count=2 I (1306) PERIPH_DSI: MIPI DSI bus initialize success I (1306) ek79007: version: 1.0.4 E (1467) lcd_panel: esp_lcd_panel_swap_xy(50): swap_xy is not supported by this panel W (1467) DEV_DISPLAY_LCD: Failed to swap LCD panel XY: ESP_ERR_NOT_SUPPORTED E (1467) lcd_panel: esp_lcd_panel_disp_on_off(71): disp_on_off is not supported by this panel I (1467) DEV_DISPLAY_LCD: Successfully initialized LCD display: display_lcd (sub_type: dsi), panel: 0x4ffbd65c, io: 0x4ffbd610 I (1468) BOARD_MANAGER: Device display_lcd initialized I (1468) BOARD_PERIPH: Reuse periph: i2c_master, ref_count=2 I (1468) GT911: I2C address initialization procedure skipped - using default GT9xx setup I (1470) GT911: TouchPad_ID:0x39,0x31,0x31 I (1470) GT911: TouchPad_Config_Version:89 I (1470) DEV_LCD_TOUCH_SUB_I2C: Successfully initialized LCD touch: lcd_touch, addr: 0xba, touch:0x48134cd4, io:0x4ffbdab8 I (1470) DEV_LCD_TOUCH: Successfully initialized LCD touch: lcd_touch, chip: gt911, sub_type: i2c I (1471) BOARD_MANAGER: Device lcd_touch initialized I (1471) BOARD_DEVICE: Device handle display_lcd found, Handle: 0x4ffbbe14 TO: 0x4ffbbe14 I (1471) BOARD_DEVICE: Device display_lcd config found: 0x40232fe0 (size: 124) I (1471) BOARD_DEVICE: Device handle lcd_touch found, Handle: 0x4ffbda30 TO: 0x4ffbda30 I (1472) esp_lvgl:adapter: LVGL adapter initialized successfully I (1474) esp_lvgl:bridge_v9: Initializing hardware resources I (1474) esp_lvgl:bridge_v9: Hardware resources initialized successfully W (1475) esp_lvgl:touch: LV_USE_GESTURE_RECOGNITION is disabled; only single-point pointer events are available I (1475) esp_lvgl:touch: Touch input device registered successfully (IRQ mode: disabled) I (1476) mmap_assets: MMAP Assets [assets] mounted successfully. (Lib: v2.0.0, Bin: v1.0.0) I (1476) lv_fs: Drive 'F' successfully created, version: 1.0.1 I (1476) esp_lvgl:adapter: File system mounted successfully I (1476) MUSIC_PLAYER_DISPLAY: LVGL assets FS mounted as F: I (1476) MUSIC_PLAYER_DISPLAY: Display initialized: 1024x600 (dsi) I (1532) MUSIC_PLAYER_UI: Hidden lv_demo_music title box I (1536) MUSIC_PLAYER_UI: Use FreeType font: F:font.ttf I (1540) esp_lvgl:adapter: LVGL task started successfully I (1540) MUSIC_PLAYER: [ 3 ] Scan SD card playlist from /sdcard I (1878) MUSIC_PLAYER_PLAYBACK: Scanned 365 tracks under /sdcard I (1890) MUSIC_PLAYER: [ 4 ] Start playback controller I (1891) ASP_POOL: Dest rate:48000 I (1891) ASP_POOL: Dest channels:2 I (1891) ASP_POOL: Dest bits:16 I (1892) MUSIC_PLAYER: [ 5 ] Music player ready I (1892) MUSIC_PLAYER_PLAYBACK: Play file: /sdcard/test_1.mp3 E (1892) ESP_GMF_PIPELINE: esp_gmf_pipeline.c:536 (esp_gmf_pipeline_stop): Got NULL Pointer I (1892) AUD_SIMP_PLAYER: Use the tag of io from pool, in_str:io_file I (1893) ESP_GMF_FILE: Open, dir:1, uri:/sdcard/test_1.mp3 I (1896) ESP_GMF_FILE: File size: 4784128 byte, file position: 0 I (1897) ESP_ES_PARSER: The version of es_parser is v1.0.1 W (1898) ESP_GMF_ASMP_DEC: Not enough memory for out, need:4608, old: 1024, new: 4608 I (7892) : ┌───────────────────┬──────────┬─────────────┬─────────┬──────────┬───────────┬────────────┬───────┐ I (7893) : │ Task │ Core ID │ Run Time │ CPU │ Priority │ Stack HWM │ State │ Stack │ I (7893) : ├───────────────────┼──────────┼─────────────┼─────────┼──────────┼───────────┼────────────┼───────┤ I (7894) : │ lvgl │ 0 │ 408646 │ 20.43% │ 6 │ 4056 │ Suspended │ Extr │ I (7895) : │ IDLE0 │ 0 │ 304097 │ 15.20% │ 0 │ 1228 │ Ready │ Intr │ I (7895) : │ TSK_0x4ff5bd14 │ 0 │ 271071 │ 13.55% │ 10 │ 3840 │ Blocked │ Intr │ I (7896) : │ esp_timer │ 0 │ 15753 │ 0.79% │ 22 │ 3764 │ Suspended │ Intr │ I (7896) : │ main │ 0 │ 460 │ 0.02% │ 1 │ 1428 │ Running │ Intr │ I (7897) : │ ipc0 │ 0 │ 0 │ 0.00% │ 24 │ 708 │ Suspended │ Intr │ I (7897) : ├───────────────────┼──────────┼─────────────┼─────────┼──────────┼───────────┼────────────┼───────┤ I (7898) : │ IDLE1 │ 1 │ 482368 │ 24.12% │ 0 │ 1220 │ Ready │ Intr │ I (7898) : │ ipc1 │ 1 │ 0 │ 0.00% │ 24 │ 716 │ Suspended │ Intr │ I (7908) : │ music_ctrl │ 1 │ 0 │ 0.00% │ 5 │ 3640 │ Blocked │ Intr │ I (7909) : ├───────────────────┼──────────┼─────────────┼─────────┼──────────┼───────────┼────────────┼───────┤ I (7910) : │ swdraw │ 7fffffff │ 518961 │ 25.95% │ 3 │ 14348 │ Ready │ Intr │ I (7910) : │ Tmr Svc │ 7fffffff │ 0 │ 0.00% │ 1 │ 1724 │ Blocked │ Intr │ I (7911) : └───────────────────┴──────────┴─────────────┴─────────┴──────────┴───────────┴────────────┴───────┘ ``` ## 故障排除 ### 未找到音乐文件 如果日志提示扫描失败或 `No music found`,请确认 microSD 卡已正确挂载,且 `/sdcard` 下存在 `.mp3`、`.aac` 或 `.wav` 文件。 ### 播放失败 如果日志出现 `Failed to run player` 或 `Failed to open on read`,请检查文件是否损坏、格式是否受支持,以及 SD 卡接触是否良好。 ### 中文显示异常 若 assets 分区未包含 `font.ttf`,例程会回退到内置 CJK 字体。如需更好的中文显示,请在编译前将 `font.ttf` 放入 `assets/` 目录后重新编译并烧录。 ## 参考资料 - [ESP Audio Simple Player](https://components.espressif.com/components/espressif/esp_audio_simple_player) - [ESP Board Manager](https://github.com/espressif/esp-board-manager) - [ESP LVGL Adapter](https://components.espressif.com/components/espressif/esp_lvgl_adapter) ## 技术支持 请按照下面的链接获取技术支持: - 技术支持参见 [esp32.com](https://esp32.com/viewforum.php?f=20) 论坛 - 问题反馈与功能需求,请创建 [GitHub issue](https://github.com/espressif/esp-adf/issues) 我们会尽快回复。
To create a project from this example, run:
idf.py create-project-from-example "espressif/adf_examples=0.2.1:music_player"