资讯动态

esp-adf codec_dev_test 测试应用:用模拟 Codec 与真实硬件双维度验证 esp_codec_dev 播放录音接口

发布时间:2026/10/14 16:17:19 来源:尧图企业网站定制
音视频音频处理嵌入式物联网语音【免费下载链接】esp-adfEspressif Advanced Development Framework for Multimedia Applications项目地址https://gitcode.com/gh_mirrors/es/esp-adf点击查看免费下载本文基于 esp-adf 仓库中的 codec_dev_test 测试应用系统讲解esp_codec_dev组件配套的单元测试是如何组织的一套基于完全自定义模拟codec 接口对全部上层 API 做纯软件验证另一套基于 ESP32-S3 KORVO2_V3 等真实开发板验证 ES8311/ES7210 等 codec 芯片的播放、录音、混响镜像、TDM 多通道与重叠场景。读完本文你可以掌握该测试应用的两类用例结构、换板适配方法修改 test_board.h 与 test_board.c以及构建、交互运行与 CI 批量执行的方式。1. 应用定位与支持的芯片codec_dev_test是 esp_codec_dev 组件的测试应用位于 test_apps 目录官方 README 明确了应用内包含两组测试Using customized codec to test all related API使用一套完全自定义的 codec 实现仓库中的 my_codec.c / my_codec.h驱动esp_codec_dev的全部相关 API属于纯软件层面的单元测试Test codec device on special board在特定开发板上测试真实 codec 设备。默认测试板是ESP32S3_KORVO2_V3板上 ES8311 播放 ES7210 录音如果使用其他开发板需要修改 test_board.h 中的引脚定义以及 test_board.c 中的实现代码。README 给出的支持目标为Supported TargetsESP32ESP32-C2ESP32-C3ESP32-C6ESP32-S2ESP32-S3ESP32-P4codec_dev_testYYYYYYY需要注意虽然目标表覆盖了多系列芯片但真实硬件用例如 S3 板用例、TDM 用例依赖具体板子与芯片外设能力SOC_I2S_SUPPORTS_TDM、SOC_I2S_SUPPORTS_XTAL等编译宏CI 中实际仅对 ESP32-S3 执行见 pytest_esp_codec_dev_test.py。2. 测试框架入口与内存泄漏检查应用入口非常薄见 test_app_main.c#define TEST_MEMORY_LEAK_THRESHOLD (400) void setUp(void) { unity_utils_record_free_mem(); } void tearDown(void) { unity_utils_evaluate_leaks_direct(TEST_MEMORY_LEAK_THRESHOLD); } void app_main(void) { unity_run_menu(); }这里使用 ESP-IDFunity组件的交互式菜单模式unity_run_menu()设备启动后进入菜单按下对应数字键即可单独运行某个TEST_CASE。每个用例执行前后通过unity_utils_record_free_mem()/unity_utils_evaluate_leaks_direct()记录并校验空闲内存泄漏阈值设为400 字节——对驱动类代码而言这要求esp_codec_dev_new/delete、各audio_codec_*_if的创建/删除必须严格配对。main/CMakeLists.txt 声明了依赖组件unity、driver、esp_driver_i2c、esp_driver_i2s、esp_pm、esp_codec_dev并启用WHOLE_ARCHIVE TRUE保证 Unity 用例符号不被裁剪。main/idf_component.yml 中将esp_codec_dev依赖版本约束为1.1并用override_path: ../../../指向仓库内本组件源码确保测试的正是当前仓库代码而非组件注册表版本。3. 第一组测试自定义 codecmy_codec驱动全部 API3.1 模拟接口的设计my_codec.c 按esp_codec_dev的分层架构实现了四套接口全部用内存模拟不依赖任何真实外设接口实现内容作用my_codec_ctrl_new()一个uint8_t reg[MY_CODEC_REG_MAX]数组模拟寄存器验证read_reg/write_reg控制通路my_codec_data_new()read输出递增字节序列、write累计write_idx验证数据通路读/写行为可断言my_codec_new()GPIO 复位时序RESET 拉低 10ms 再拉高、enable中“先恢复 suspend 再开 PA / 先 mute 再关 PA 再 suspend”的防破音时序验证 codec 接口 open/enable/set_fs/mute/set_vol/set_mic_gain 等my_codec_vol_new()按db / 6.0206换算位移量对 16bit 数据做移位验证软件音量 handleraudio_codec_vol_if_t其中my_codec_set_vol()体现了硬件增益补偿逻辑static int my_codec_set_vol(const audio_codec_if_t *h, float db) { my_codec_t *codec (my_codec_t *) h; // Need minus hw_gain to avoid hardware saturation db - codec-hw_gain; if (db 0) { db 0; } uint8_t data esp_codec_dev_vol_calc_reg(vol_range, db); return codec-ctrl_if-write_reg(codec-ctrl_if, MY_CODEC_REG_VOL, 1, data, 1); }hw_gain由esp_codec_dev_col_calc_hw_gain(codec_cfg-hw_gain)根据 PA 电压、codec DAC 电压和 PA 增益计算测试中配置pa_voltage3.3, codec_dac_voltage3.3, pa_gain10.0见 test_my_codec.c这与 esp_codec_dev README 中“硬件增益会影响模拟放大效率需配置esp_codec_dev_hw_gain_t保证不同平台响度一致”的说明一一对应。3.2 API 全覆盖用例esp codec dev API testtest_my_codec.c#L25-L182覆盖了核心 API 矩阵设备生命周期esp_codec_dev_new→esp_codec_dev_open48kHz / 2ch / 16bit→esp_codec_dev_close→esp_codec_dev_delete并验证 close 之后 read/write 必须失败ret ! ESP_CODEC_DEV_OK音量曲线通过esp_codec_dev_set_vol_curve注入自定义曲线static esp_codec_dev_vol_map_t volume_maps[] { {.vol 1, .db_value -49.5}, {.vol 33, .db_value -33.5}, {.vol 66, .db_value -17.0}, {.vol 100, .db_value 0.0}, };然后断言esp_codec_dev_set_out_vol(dev, 33.0)后模拟寄存器reg[MY_CODEC_REG_VOL] 43、设 66 时寄存器为 27即验证了“线性插值换算 dB → 再经esp_codec_dev_vol_calc_reg映射到寄存器值”的完整计算链mute / mic gain / mic mute分别对esp_codec_dev_set_out_mute、esp_codec_dev_set_in_gain20dB/40dB 直接映射到模拟寄存器、esp_codec_dev_set_in_mute做逐值断言读写数据esp_codec_dev_read两次 256 字节后逐字节断言递增序列验证 fake data_if 的透传esp_codec_dev_write后断言write_idx 512软件音量 handler通过esp_codec_dev_set_vol_handler(dev, vol_if)挂入my_codec_vol_new()验证esp_codec_dev_set_out_vol(dev, 40.0)时 handler 收到曲线插值出的-30.0 dBopen/close时 handler 的is_open状态翻转且write 512字节后process_len 512。3.3 错误路径与能力边界用例esp codec dev wrong argument testL271-L354验证esp_codec_dev_new(NULL)、data_ifNULL、open(dev, NULL)、缺vol_map的曲线、set_out_vol(NULL, 50)、read/write 传 NULL 指针等所有非法输入均返回失败esp codec dev feature should not supportL356-L442验证能力边界——ESP_CODEC_DEV_TYPE_IN设备调用set_vol_curve/set_out_vol/write失败ESP_CODEC_DEV_TYPE_OUT设备调用set_in_gain/set_in_mute/read失败且对纯输出设备调用esp_codec_dev_mirror_cfg/mirror_read精确返回ESP_CODEC_DEV_NOT_SUPPORT。3.4 输入镜像mirror用例input mirror - fake input keeps latest dataL184-L269专门验证esp_codec_dev_mirror_cfg()/esp_codec_dev_mirror_read()的语义未读入数据时mirror_read超时返回ESP_CODEC_DEV_TIMEOUT且bytes_read 0esp_codec_dev_mirror_cfg(dev, 0)返回ESP_CODEC_DEV_INVALID_ARG重复配置同尺寸幂等mirror_read的 NULL 指针、0 长度、NULLbytes_read均返回ESP_CODEC_DEV_INVALID_ARG读入 600 字节后再mirror_read(dev, cache_data, 512, 0, bytes_read)应拿到最近512 字节即read_data[88..]体现“保留最新数据”的环形缓存语义close之后mirror_read返回ESP_CODEC_DEV_WRONG_STATE。该 API 在真实板用例中被用于“边录边播”的镜像回听链路见下文 4.3 节。4. 第二组测试真实开发板上的 codec 验证4.1 默认板引脚定义与换板方法默认板ESP32-S3 KORVO2_V3的全部引脚在 test_board.h 中集中定义宏GPIO说明TEST_BOARD_I2C_SDA_PIN17I2C 数据脚codec 控制总线TEST_BOARD_I2C_SCL_PIN18I2C 时钟脚TEST_BOARD_I2S_BCK_PIN9I2S BCLKTEST_BOARD_I2S_MCK_PIN16I2S MCLKTEST_BOARD_I2S_DATA_IN_PIN10I2S DIN录音数据TEST_BOARD_I2S_DATA_OUT_PIN8I2S DOUT播放数据TEST_BOARD_I2S_DATA_WS_PIN45I2S WS/LRCLKTEST_BOARD_PA_PIN48功放PA控制脚换板时需要同时修改两处test_board.h的引脚宏以及test_board.c中与板级强相关的初始化实现I2C/I2S 安装、codec 型号与 I2C 地址等。test_board.c 中的ut_i2c_init()/ut_i2s_init()都支持传入自定义引脚结构体codec_i2c_pin_t/codec_i2s_pin_t不传则回落到test_board.h默认宏因此“多 codec 实例”用例可以直接传不同引脚复用同一安装函数见 L1044-L1060。4.2 硬件用例的通用初始化链以esp codec dev test using S3 boardtest_board.c#L394-L539为例初始化链与 esp_codec_dev README 的 Usage 步骤完全一致安装底层驱动ut_i2c_init(0)、ut_i2s_init(0)。I2S 使用 IDF 5.x 通道 API默认I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(16, I2S_SLOT_MODE_STEREO)、16kHz 时钟TDM 模式则配置 4 slot 的i2s_tdm_config_tI2C 在CONFIG_CODEC_I2C_BACKWARD_COMPATIBLEn时走新的i2c_new_master_bus内部上拉、glitch_ignore_cnt7创建默认接口const audio_codec_data_if_t *data_if audio_codec_new_i2s_data(i2s_cfg); const audio_codec_ctrl_if_t *out_ctrl_if audio_codec_new_i2c_ctrl(i2c_cfg); /* addr ES8311_CODEC_DEFAULT_ADDR, 400kHz */ i2c_cfg.addr ES7210_CODEC_DEFAULT_ADDR; const audio_codec_ctrl_if_t *in_ctrl_if audio_codec_new_i2c_ctrl(i2c_cfg); const audio_codec_gpio_if_t *gpio_if audio_codec_new_gpio();创建芯片级 codec 接口ES8311 配codec_mode ESP_CODEC_DEV_WORK_MODE_DAC、pa_pin TEST_BOARD_PA_PIN、use_mclk true后经es8311_codec_new()创建ES7210 配mic_selected ES7210_SEL_MIC1|MIC2|MIC3后经es7210_codec_new()创建分别创建ESP_CODEC_DEV_TYPE_OUT的play_dev与ESP_CODEC_DEV_TYPE_IN的record_dev设置esp_codec_dev_set_out_vol(play_dev, 60.0)、esp_codec_dev_set_in_gain(record_dev, 30.0)以 48kHz / 2ch / 16bit 打开双设备后持续读录 10 秒数据limit_size 10 * sample_rate * channel * (bits3)每 512 字节用codec_max_sample()检查max min确认录音数据“非常量”即麦克风确实有信号进来结束后按esp_codec_dev_close→esp_codec_dev_delete→ 各audio_codec_delete_*_if→ut_i2c_deinit/ut_i2s_deinit的严格逆序释放。该链中用到的接口配置结构体定义可参考 esp_codec_dev_defaults.haudio_codec_i2c_cfg_t的clock_speed_hz为 0 时默认 100kHz、audio_codec_i2s_cfg_t的clk_src为 0 时使用默认时钟源等默认值注释。4.3 板级用例总览用例名Unity tag:[esp_codec_dev]验证重点默认板/条件esp codec dev test using S3 board基础播放 录音 镜像回听esp_codec_dev_mirror_cfg512B独立任务mirror_task以esp_codec_dev_mirror_read循环读取并回写播放校验total_read 0且出现过活跃数据KORVO2_V3esp codec dev test using S3 board with XTALI2S 时钟源切到 XTAL 且esp_pm_configure({40MHz, 40MHz})限制 CPU 频率验证低主频下音频时钟稳定SOC_I2S_SUPPORTS_XTAL CONFIG_PM_ENABLERecord play overlap test双向重叠①播放持续、录音 5 轮 open/close 打断②录音持续、播放 5 轮 open/close 打断验证设备状态机在交叉开关下不崩溃KORVO2_V3Multiple es8311 codec test use ESP32_S3_KORVO_2L/... reuse data_if test双 ES8311 实例全部接口独立 vs 共享data_if两种拓扑执行“只录 → 回放中关录 → 回放中开录 → 录关中播”的交叉开关序列KORVO_2LPlaying while recording use TDM modeRX 走 TDM 4 通道ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0) | MASK(3)选通道 0/3TX 走 STD实现边录 4ch 边播 2chSOC_I2S_SUPPORTS_TDMPlay and record use separate data_if with 2ch 32bitsES7210 以 2ch 32bit mclk_multiple256channel_maskBIT(0)录 4ch 16bit顺序 ch3 ch1 ch2 ch4ES8311 用独立 data_if 以 16bit 播放回放时跳过 2 字节对齐IDF ≥ 5.0esp codec dev ADC MIC record and PDM speaker play test (default use ESP32_C3_LYRA)无外部 codec 芯片的板型audio_codec_new_adc_dataADC_UNIT_112bit16kHz录 ADC 麦克风 I2S PDM TX 驱动喇叭 dummy_codec_new绑定pa_pin1循环 300 轮 read 校验数据非常量后 writeESP32-C3-LyraCONFIG_CODEC_DATA_ADC_SUPPORT SOC_ADC_SUPPORTED SOC_I2S_SUPPORTS_PDM_TX其中镜像回听任务test_board.c#L345-L381的错误处理值得注意ESP_CODEC_DEV_TIMEOUT时继续循环、ESP_CODEC_DEV_WRONG_STATE且已收到 stop 时正常退出、其余错误码写入ctx-ret由主线程断言展示了mirror_read超时语义在真实场景中的正确用法。TDM 用例中 TDM 配置细节见 L1169-L1289ut_set_i2s_mode(I2S_COMM_MODE_STD, I2S_COMM_MODE_TDM)先切换 RX 模式再ut_i2s_init录音侧.channel 4并配channel_mask测试结束后ut_clr_i2s_mode()复位模式。5. 构建、运行与 CI 执行5.1 默认配置sdkconfig.defaults 中的关键项# Enable FreeRTOS trace CONFIG_FREERTOS_HZ1000 # Use new I2C master CONFIG_CODEC_I2C_BACKWARD_COMPATIBLEn CONFIG_ESP_TASK_WDT_ENn CONFIG_ESP_INT_WDTn CONFIG_PM_ENABLEyCONFIG_CODEC_I2C_BACKWARD_COMPATIBLEn强制使用 IDF 5.3 的新 I2C master 总线 API对应test_board.c中USE_IDF_I2C_MASTER分支控制接口以 400kHz 运行CONFIG_PM_ENABLEy使能功耗管理配合SOC_I2S_SUPPORTS_XTAL编译出 XTAL 时钟源用例关闭任务/中断 WDT 是因为录音回放为长时间忙等待测试。5.2 本地构建与交互式运行# 在测试应用目录下构建默认目标按 CI 使用 esp32s3 idf.py -D IDF_TARGETesp32s3 build flash monitor烧录进入 monitor 后unity_run_menu()会打印用例菜单按数字键即可逐个运行每个用例结束都会执行 400 字节阈值的泄漏检查。真实板用例需要在对应硬件上执行纯my_codec用例API test、mirror、wrong argument、feature should not support在任意支持目标上都能跑通。5.3 CI 批量执行pytest_esp_codec_dev_test.py 通过pytest-embedded在esp32s3目标上运行以下固定清单超时 3600 秒case_list [esp codec dev test using S3 board, Record play overlap test, Playing while recording use TDM mode, Play and record use separate data_if with 2ch 32bits, esp codec dev test using S3 board with XTAL, esp codec dev API test, esp codec dev wrong argument test, esp codec dev feature should not support, input mirror - fake input keeps latest data] dut.run_all_single_board_cases(namecase_list, timeout3600)可见 CI 清单覆盖了 8 个 S3 板用例 4 个模拟接口用例而依赖 ESP32-C3-LyraADC MIC PDM和 ESP32-S3-KORVO_2L双 ES8311的用例不在通用 CI 清单内属于特定硬件条件下的补充验证这与各用例源码中的编译条件宏一致。在仓库根目录可用以下命令复现 CI 行为需安装pytest-embedded-idf环境pytest components/esp_codec_dev/test_apps/codec_dev_test/pytest_esp_codec_dev_test.py6. 小结从该测试应用能获得什么API 契约参考test_my_codec.c 对返回值ESP_CODEC_DEV_OK/INVALID_ARG/WRONG_STATE/NOT_SUPPORT/TIMEOUT、能力边界IN/OUT 设备不可互换调用、关闭后行为均有明确断言是调用esp_codec_dev时的行为契约手册自定义 codec 模板my_codec.c 给出了实现audio_codec_ctrl_if_t/audio_codec_data_if_t/audio_codec_if_t/audio_codec_vol_if_t四类接口、防破音 enable 时序与硬件增益补偿的完整骨架移植新 codec 芯片时可作为起点真实板适配模板test_board.c 展示了 I2C/I2S 双驱动安装、多 codec 实例共享/独立接口、TDM 通道选择、XTAL 时钟源与低主频 PM 配置等场景的完整初始化/释放序列可复制的 CI 模式sdkconfig.defaults Unity 菜单 pytest-embedded用例清单的组合可作为其他 ADF 组件测试应用的参考结构。赞分享音视频音频处理嵌入式物联网语音【免费下载链接】esp-adfEspressif Advanced Development Framework for Multimedia Applications项目地址https://gitcode.com/gh_mirrors/es/esp-adf点击查看免费下载相关推荐ESP-ADF TCP客户端音频流播放实例详解ESP ADF TCP客户端音频流播放实例详解 概述 本文将详细介绍ESP ADFEspressif Audio Development Framework音视频音频处理嵌入式物联网语音ESP IoT Solution PWM 音频方案用 LEDC 外设实现免 Codec 的音频播放ESP IoT Solution PWM 音频方案用 LEDC 外设实现免 Codec 的音频播放 本篇技术指南基于 esp iot solution 仓库中物联网嵌入式驱动开发硬件开发RIOT 中使用 FatFsVFS 接口测试与实践指南native 模拟与真实 SD 卡双路径RIOT 中使用 FatFsVFS 接口测试与实践指南native 模拟与真实 SD 卡双路径 本指南以 RIOT 官方测试应用 tests/pkg/fa物联网嵌入式操作系统实时系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑