audio_beat_detection

Example of the component zhanghongze/beat_detection v1.0.0
# Beat Detection 示例

## 概述

本示例展示了如何使用 Beat Detection 组件进行音频鼓点检测。示例通过生成模拟音频数据(250Hz 正弦波)来演示 Beat Detection 的功能,检测到鼓点时会通过串口输出 "audio detected!"。

## 功能特性

- **Beat Detection 初始化**:配置并初始化 Beat Detection 组件
- **模拟音频输入**:生成 250Hz 正弦波作为测试音频(在低音频率范围内)
- **实时检测**:持续处理音频数据并检测鼓点
- **回调通知**:检测到鼓点时通过回调函数打印 "audio detected!"
- **静音测试**:交替发送有信号和静音数据,验证检测逻辑

## 硬件要求

- ESP32 系列开发板(ESP32、ESP32-S2、ESP32-S3 等)
- USB 串口线用于查看输出

**注意**:本示例使用模拟音频数据,不需要实际的 I2S 音频输入设备。如需使用真实 I2S 输入,请参考主项目的实现。

## 配置说明

### 音频参数配置

在 `main.c` 中可以修改以下参数:

```c
#define I2S_SAMPLE_RATE         16000    // 采样率(Hz)
#define I2S_BITS_PER_SAMPLE     16       // 每样本位数
#define I2S_CHANNELS            1        // 声道数(1=单声道,2=双声道)
#define I2S_BUFFER_SIZE         2048     // 缓冲区大小(样本数)
#define FFT_SIZE                512      // FFT 大小
```

### Beat Detection 配置

Beat Detection 的配置在 `beat_detection_init_example()` 函数中:

```c
beat_detection_cfg_t cfg = BEAT_DETECTION_DEFAULT_CFG();
cfg.sample_rate = I2S_SAMPLE_RATE;      // 采样率,必须与音频数据一致
cfg.channel = I2S_CHANNELS;              // 声道数,必须与音频数据一致
cfg.fft_size = FFT_SIZE;                // FFT 大小(建议 512 或 1024)
cfg.bass_freq_start = 200;               // 低音频率起始(Hz)
cfg.bass_freq_end = 300;                 // 低音频率结束(Hz)
cfg.bass_surge_threshold = 6.0f;         // 能量突变阈值(默认 6.0)
cfg.task_priority = 5;                   // 处理任务优先级
cfg.task_stack_size = 8192;              // 任务栈大小(字节)
cfg.task_core_id = 0;                    // 任务运行的 CPU 核心
cfg.result_callback = callback;          // 结果回调函数
cfg.flags.enable_psram = false;         // 是否使用 PSRAM
```

### 参数调优建议

- **FFT 大小**:
  - `512`:默认值,平衡精度和性能
  - `256`:更快处理,但频率分辨率较低
  - `1024`:更高精度,但需要更多内存

- **低音频率范围**:
  - `200-300 Hz`:默认值,适合大多数鼓点
  - `150-250 Hz`:更低的频率,适合低音鼓
  - `250-350 Hz`:稍高的频率,适合某些类型的鼓

- **能量突变阈值**:
  - `6.0`:默认值,适合大多数音乐
  - `4.0-5.0`:更敏感,可能产生更多误检
  - `7.0-8.0`:更保守,可能漏检弱鼓点

## 使用方法

### 1. 编译和烧录

```bash
# 进入示例目录
cd components/beat_detection/examples/audio_beat_detection

# 编译项目
idf.py build

# 烧录到设备
idf.py flash

# 查看串口输出
idf.py monitor
```

或者使用一条命令完成编译、烧录和监控:

```bash
idf.py build flash monitor
```

### 2. 运行示例

示例启动后会:

1. 初始化 Beat Detection 组件
2. 分配音频缓冲区(4096 字节,2048 个样本)
3. 进入主循环:
   - 生成 250Hz 正弦波音频数据
   - 将数据输入到 Beat Detection
   - 等待 500ms
   - 发送静音数据
   - 等待 500ms
   - 重复

### 3. 查看输出

在串口监视器中,你会看到类似以下的输出:

```
I (xxx) BEAT_DETECTION_I2S_EXAMPLE: Beat Detection initialized successfully
I (xxx) BEAT_DETECTION_I2S_EXAMPLE: Audio buffer allocated: 4096 bytes (2048 samples)
I (xxx) BEAT_DETECTION_I2S_EXAMPLE: audio detected!
I (xxx) BEAT_DETECTION_I2S_EXAMPLE: audio not detected!
```

## 代码结构

```
main.c
├── beat_detection_result_callback()    # 检测结果回调函数
│   ├── BEAT_DETECTED: 打印 "audio detected!"
│   └── BEAT_NOT_DETECTED: 打印 "audio not detected!"
├── beat_detection_init_example()       # 初始化 Beat Detection
│   └── 配置并初始化 Beat Detection 组件
└── app_main()                          # 主函数
    ├── 初始化 Beat Detection
    ├── 分配音频缓冲区
    └── 主循环
        ├── 生成 250Hz 正弦波
        ├── 输入到 Beat Detection
        ├── 发送静音数据
        └── 重复
```

## 工作流程

1. **初始化阶段**
   - 配置 Beat Detection 参数(采样率、声道数、FFT 大小等)
   - 初始化 Beat Detection 组件
   - 分配音频缓冲区内存

2. **运行阶段**
   - 生成测试音频数据(250Hz 正弦波)
   - 通过 `feed_audio()` 将数据输入到 Beat Detection
   - Beat Detection 在后台任务中处理音频数据:
     - 应用窗函数
     - 执行 FFT 变换
     - 计算低音频率范围内的能量
     - 检测能量突变
   - 检测到鼓点时调用回调函数

3. **数据处理**
   - Beat Detection 需要至少 `channel * fft_size * sizeof(int16_t)` 字节的数据
   - 对于单声道和 512 的 FFT 大小,需要 1024 字节
   - 本示例使用 4096 字节缓冲区,满足要求

## 集成真实 I2S 输入

如需使用真实的 I2S 音频输入,可以参考以下步骤:

1. **添加 I2S 初始化代码**:
   ```c
   #include "driver/i2s_std.h"
   
   i2s_chan_handle_t i2s_rx_handle;
   // 配置并初始化 I2S...
   ```

2. **读取 I2S 数据**:
   ```c
   size_t bytes_read = 0;
   esp_err_t ret = i2s_channel_read(i2s_rx_handle, 
                                     audio_buffer, 
                                     buffer_size_bytes, 
                                     &bytes_read, 
                                     portMAX_DELAY);
   ```

3. **输入到 Beat Detection**:
   ```c
   beat_detection_audio_buffer_t buffer = {
       .audio_buffer = (uint8_t *)audio_buffer,
       .bytes_size = bytes_read,
   };
   g_beat_detection_handle->feed_audio(buffer, g_beat_detection_handle);
   ```

## 注意事项

1. **内存管理**
   - 确保有足够的内存用于音频缓冲区和 FFT 计算
   - 如果内存不足,可以启用 PSRAM(`cfg.flags.enable_psram = true`)
   - 缓冲区大小应至少为 `channel * fft_size * sizeof(int16_t)` 字节

2. **数据格式**
   - 音频数据必须是 16 位 PCM 格式(int16_t)
   - 采样率必须与配置的 `sample_rate` 一致
   - 声道数必须与配置的 `channel` 一致

3. **性能考虑**
   - FFT 计算需要一定的 CPU 资源
   - 建议在专用的 CPU 核心上运行处理任务
   - 如果处理速度跟不上,可以增加任务优先级或减少 FFT 大小

4. **回调函数**
   - 回调函数在 Beat Detection 的处理任务中执行
   - 回调函数应尽量简短,避免阻塞
   - 不要在回调中执行耗时操作

## 故障排除

### 问题:没有检测到鼓点

- **检查音频数据**:确保音频数据包含低音频率(200-300Hz)的能量
- **调整阈值**:降低 `bass_surge_threshold` 值(例如 4.0 或 5.0)
- **检查配置**:确认采样率和声道数配置正确
- **检查数据大小**:确保输入的数据量满足最小要求

### 问题:内存分配失败

- **启用 PSRAM**:设置 `cfg.flags.enable_psram = true`
- **减小缓冲区**:减小 `I2S_BUFFER_SIZE`
- **减小 FFT 大小**:使用 256 而不是 512

### 问题:编译错误

- **检查组件依赖**:确保 `beat_detection` 组件已正确添加到 `CMakeLists.txt`
- **检查路径**:确认 `EXTRA_COMPONENT_DIRS` 路径正确
- **清理重建**:运行 `idf.py fullclean` 后重新编译

### 问题:StoreProhibited 错误

- **检查缓冲区大小**:确保分配的内存足够大
- **检查数据类型**:确保音频数据是 `int16_t` 格式
- **检查指针**:确保所有指针在使用前已正确初始化

## 扩展功能

可以在此基础上添加以下功能:

- **LED 指示**:检测到鼓点时控制 LED 闪烁
- **UART 输出**:通过 UART 发送检测结果到其他设备
- **数据记录**:记录检测到的鼓点时间戳
- **统计分析**:统计单位时间内的鼓点数量(BPM)
- **多阈值检测**:使用不同的阈值检测不同类型的鼓点
- **可视化**:通过串口输出能量值,用于调试和可视化

## 示例输出说明

- `audio detected!`:检测到鼓点(能量突变满足阈值条件)
- `audio not detected!`:未检测到鼓点(能量变化不满足阈值)

## 相关文档

- [Beat Detection 组件文档](../../README.md)
- [ESP-IDF I2S 驱动文档](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/i2s.html)
- [ESP-IDF FreeRTOS 文档](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/system/freertos.html)

## 许可证

Apache-2.0

To create a project from this example, run:

idf.py create-project-from-example "zhanghongze/beat_detection=1.0.0:audio_beat_detection"

or download archive (~6.25 KB)