# 从 Flash 中播放 MP3 文件例程

## 例程简介

本例程源自 ADF 例程：[pipeline_flash_tone](https://github.com/espressif/esp-adf/tree/master/examples/player/pipeline_flash_tone)，需在 [ADF](https://github.com/espressif/esp-adf/tree/master) 环境下开发

通过触摸事件，触发音频管道 API 播放存储在 flash 中的 MP3 文件，同时驱动 WS2812 灯环。

## 预备知识

本例程在 `/tools/audio_tone.bin` 和 `/components/audio_flash_tone/` 目录下已经帮助用户生成了例程所需的 bin 文件和音频文件在 flash 中地址的源代码文件。

如果用户需要生成自己的 `audio_tone.bin`，则需要执行 `mk_audio_bin.py` 脚本（位于 $ADF_PATH/tools/audio_tone/mk_audio_tone.py），并且指定相关文件的路径。

 源 MP3 文件在 `tone_mp3_folder` 文件夹中，生成的 C 文件、H 文件以及二进制 bin 文件都存放在此目录下。

```
python3 $ADF_PATH/tools/audio_tone/mk_audio_tone.py -f ./ -r tone_mp3_folder
```

请使用 *python3 $ADF_PATH/tools/audio_tone/mk_audio_tone.py --help* 查看更多脚本信息。

本例程默认的 `audio_tone.bin` 包含如下音频文件：

```c
   "flash://tone/0_belly_1.mp3",
   "flash://tone/1_belly_2.mp3",
   "flash://tone/2_belly_3.mp3",
   "flash://tone/3_belly_4.mp3",
   "flash://tone/4_bread_1.mp3",
   "flash://tone/5_bread_2.mp3",
   "flash://tone/6_capybara_song_1.mp3",
   "flash://tone/7_hat_1.mp3",
   "flash://tone/8_neck_1.mp3",
   "flash://tone/9_neck_2.mp3",
   "flash://tone/10_reverse.mp3",
   "flash://tone/11_screaming.mp3",
   "flash://tone/12_shake.mp3",
   "flash://tone/13_touch_nose.mp3",
   "flash://tone/14_woohoo.mp3",
```

## 环境配置

### IDF 默认分支

本例程支持 IDF release/v5.0 及以后的分支，例程默认使用 ADF 的內建分支 `$ADF_PATH/esp-idf`。

## 配置说明

1. 开发板
   - 默认使用搭载 ESP32-S3 模组的 ``ESP-SPOT`` 开发板。该模组集成触摸传感器功能，技术细节请参考：：[ESP32-S3 数据手册](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_cn.pdf)

2. LED 灯环
   - 控制灯环的 IO 默认为 `GPIO45`，可通过 `idf.py menuconfig` 修改 `CONFIG_LED_GPIO_INPUT` 控制灯环的 IO，配置 `CONFIG_LED_COUNT` 修改 LED 数量，默认为 16 个

3. 音频文件
   - **如果 MP3 音频总数量大于 `9`，则需要修改 `$ADF_PATH/components/audio_stream` 文件夹中的 `tone_stream.c` 文件**
   - 将 `_tone_open(audio_element_handle_t self)` 函数中 `char find_num[2]` 数组的长度修改为 `char find_num[3]`。这样可以确保函数在解析双位数的音频文件名（例如 10.mp3、11.mp3）时不会发生字符串截断错误，正确识别全部音频文件

4. 音频储存地址
   - 此例程的 `flashTone` 在 `partition_flash_tone.csv` 中地址配置如下，用户可以根据自己的项目 flash 分区灵活配置地址

      ```
      flashTone,data,  0x04,  0x110000 , 500K,
      ```


### 编译和下载

请先编译版本并烧录到开发板上，然后运行 monitor 工具来查看串口输出（替换 PORT 为端口名称）：

```
idf.py -p PORT flash monitor
```

**此外，本例程还需烧录 `/tools/audio_tone.bin` 到 `partition_flash_tone.csv` 的 `flashTone` 分区，请使用如下命令:**

```
esptool.py --chip esp32s3 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x110000 ./tools/audio_tone.bin
```

有关配置和使用 ESP-IDF 生成项目的完整步骤，请参阅 [《ESP-IDF 编程指南》](https://docs.espressif.com/projects/esp-idf/zh_CN/release-v5.3/esp32/index.html)。


## 如何使用

### 功能和用法

- 例程开始运行后，如果事前没有烧录 `/tools/audio_tone.bin` 到 `partition_flash_tone.csv ` 的 `flashTone` 分区，例程将会报错，请参考 [编译和下载](#编译和下载) 的说明进行烧录

## 故障排除

```c
E (481) TONE_PARTITION: Not flash tone partition
E (481) AUDIO_ELEMENT: [tone] AEL_STATUS_ERROR_OPEN,-1
W (491) AUDIO_ELEMENT: [tone] audio_element_on_cmd_error,7
E (501) TONE_PARTITION: /repo/adfs/bugfix/esp-adf-internal/components/tone_partition/tone_partition.c:204 (tone_partition_deinit): Got NULL Pointer
W (511) AUDIO_ELEMENT: IN-[mp3] AEL_IO_ABORT
E (511) MP3_DECODER: failed to read audio data (line 119)
W (521) AUDIO_ELEMENT: [mp3] AEL_IO_ABORT, -3
W (531) AUDIO_ELEMENT: IN-[i2s] AEL_IO_ABORT
```

如果遇到上述的错误，请把按照 [编译和下载](#编译和下载) 的说明烧录 `/tools/audio_tone.bin` 到 `partition_flash_tone.csv ` 的 `flashTone` 分区。


## 技术支持
请按照下面的链接获取技术支持：

- 技术支持参见 [esp32.com](https://esp32.com/viewforum.php?f=20) 论坛
- 故障和新功能需求，请创建 [GitHub issue](https://github.com/espressif/esp-adf/issues)

我们会尽快回复。
