ESP-ADF Sonic 实战:3 个参数、2 种插值,搞定 WAV 倍速不变调
要做 1.5× 的 WAV 倍速播放还不让人声变尖?ESP-ADF Sonic 就是干这个的音频变速组件:它把 pitch / speed 解调成两个独立倍率,倍率一设,时间轴上的采样点自动重排。核心接口只有一个 sonic_set_pitch_and_speed_info(el, pitch, speed),插值在线性与 FIR 之间二选一。下面按"定参数 → 选插值 → 看调度"三步讲清。
控制面:一张表看懂倍率组合
先说结论:Sonic 全部可调项就三个——speed、pitch、插值类型。前两个是 float 倍率,1.0 为基准,运行时随时可改。
效果 → 参数 速查表
| 想要的效果 | pitch | speed | 备注 |
|---|---|---|---|
| 直通(不处理) | 1.0 | 1.0 | 上电验证链路用 |
| 2× 倍速、音调不变 | 1.0 | 2.0 | ✅ 推荐:核心用法 |
| 半速慢放 | 1.0 | 0.5 | 学习、跟读场景 |
| 只升调、时长不变 | 2.0 | 1.0 | ⚠️ 注意:听感整体变高 |
| 只降调、时长不变 | 0.5 | 1.0 | 变调实验 |
sonic_set_pitch_and_speed_info 调用姿势
参数顺序固定为 el, pitch, speed,最容易踩的坑就是把后两个写反。最常用的两行:
sonic_set_pitch_and_speed_info(el, 1.0, 2.0); // 2 倍速、音调不变
sonic_set_pitch_and_speed_info(el, 1.0, 1.0); // 直通,验证链路
说白了,speed 决定"多久取一个点",pitch 决定"取完点之后音高落在哪",两者互不牵连——这就是"倍速不变调"能成立的原因。
线性插值 vs FIR 插值:CPU 占用和音质怎么取舍
回到开头那个 1.5× 的问题:倍率定了,剩下就是插值选型。它决定"重新取点"时新样本怎么算出来。
- 线性插值:更快、更省 CPU,精度低一些;
- FIR 插值:更慢、精度更高,相当于用更密的采样窗去逼近原始波形。
具体怎么选,连问自己三句就行。
三问决策流
- 实时播放、CPU 余量紧张吗?是 → 线性插值,先把实时性保住;
- 离线批处理、对音质敏感吗?是 → FIR,用算力换波形细节;
- 两个都拿不准?→ 先用线性把整条链路跑通,再切 FIR 做一次 A/B,听感和 CPU 占用都记下来再定。
Sonic 作为 Audio Element 接入 Pipeline 的 3 个要点
接下来看它怎么被框架调度。在 ADF 里,解码器、编码器、滤波器本质都是 audio_element 对象,Sonic 归在滤波器(filter)一类,串进 pipeline 有三个要点:
- 每个 Element 独立跑在自己的任务里,数据走"输入 → 处理 → 输出";Element 定义了 7 类回调(open、seek、process、close、destroy、read、write),滤波器基本只依赖 process;
- Element 之间靠 ringbuffer 串联:上游解码出的 PCM 先进 Sonic 的输入 ringbuffer,处理完再写进下游 ringbuffer。应用只跟整条 pipeline 交互,不用逐个管元素;
- speed / pitch 运行期可热修改——播放中途改倍率,下一块数据即按新参数输出,"边播边调"天然成立。
WAV 输入 ──ringbuffer──> [ Sonic 元素 ] ──ringbuffer──> I2S/Codec 输出
▲
sonic_set_pitch_and_speed_info(运行期热修改)
再横向比一下:Equalizer 动的是频谱(十段均衡),Resample 动的是采样率并做单/双声道转换,Sonic 两者都不碰,只重排时间轴上的采样点——它是 ADF 音频处理家族里少见的"时间域"成员。
想深挖时看这里
官方演示在 audio_processing/pipeline_sonic 示例里(示例源码以官方发布包为准)。组件归属 esp_codec,分两层:codec/audio_sonic.h 是对外 API 声明层,sonic_set_pitch_and_speed_info 就在这里;processing/esp_sonic.h 是变速/变调插值算法层。想看 FIR 或线性插值的具体实现,从后者读起。
动手清单
按顺序走一遍,半天能验证完全部关键点:
- ✅ 搭最小链路:WAV 输入 → Sonic → I2S 输出,能正常出声
- ✅ 调
sonic_set_pitch_and_speed_info(el, 1.0, 1.0):听感与原始文件一致 - ✅ 改为
el, 1.0, 2.0:2 倍速且人声不尖 - ✅ 线性 ↔ FIR 各放一遍:记录听感差异与 CPU 占用
- ✅ 播放中途动态改 speed:过渡平滑、不爆音
下一步:接 ADF 的按键服务(button 组件),把倍率挂到按键上,做成用户可选速率的交互式变速播放。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



