播放源:音乐、FM、录音与 LineIn
本文档介绍 AD15N GP-MCU SDK 中播放源(音乐、FM、录音与 LineIn)背后的媒体基础设施:统一解码框架、编解码器插件、媒体 I/O 抽象、音效与提示音模块,以及这些模块如何共同支撑 mbox 应用层的播放源切换。
Purpose and Scope
本页面向 applications/mbox/playback-sources 目录项,说明“播放源”这一能力在 SDK 中的落地方式。
本页覆盖内容:
- 播放源的概念与典型组成(音乐解码、FM 收音、LineIn 模拟输入、录音采集);
- SDK 中支撑所有播放源的公共媒体层:
decoder_api.c统一解码接口、decoder_point.c解码器插件点、decoder_msg_tab.c解码消息表、mio_api.c/mp_io.c/mio_phy.c媒体 I/O、eq.c均衡器与sine_play.c提示音; - 各编解码器插件(MP3、WAV、MIDI、F1A、A 格式)在解码链路中的位置。
不在本页范围(留给兄弟页面):
- 具体编解码算法(MP3/WAV 等格式的内部实现细节)属于解码器页面;
- 均衡器参数与调音细节属于音效页面;
- 设备驱动(USB 主机、SD 卡、FM 芯片、ADC 录音)属于各自外设页面。
重要说明(诚实性声明):本仓库快照(
Jieli-Tech/fw-AD1NN_GP-MCU_SDK)中未包含applications/mbox应用层源码——仓库根目录仅有sdk/与patch/,应用层(mbox 播放源状态机、UI 逻辑)不在本快照内。因此本页以可验证的 SDK 媒体层为证据主体,对 mbox 应用层的描述基于目录项标题与 SDK 通用设计,并在相应位置明确标注"未在本快照中验证"。
Overview
在杰理(Jieli)AD15N 系列 MCU 的音箱(sound box / mbox)应用中,“播放源”(play source)指当前生效的音频输入路径,典型包括:
| 播放源 | 数据路径 | 依赖的 SDK 模块 |
|---|---|---|
| 音乐(USB/SD 上的文件) | 文件 → MIO → 解码器 → PCM → 音效 → DAC | decoder_api.c、各解码器、mio_api.c |
| FM 收音 | FM 芯片 → I2C/音频总线 → 混音 → 输出 | 设备驱动(本快照未含) |
| LineIn | 模拟输入 → ADC → 直通/混音 → 输出 | 音频通路(本快照未含) |
| 录音 | 麦克风/LineIn → ADC → 编码 → 存储 | encoder_api.c(见 patch 目录) |
SDK 的设计思路是:解码与播放源解耦。应用层只需通过 decoder_api.c 提供的统一接口发起解码,并指定解码类型;SDK 通过 decoder_point.c 的插件点把请求路由到具体编解码器,通过 decoder_msg_tab.c 把解码结果/错误以统一消息形式上报给应用,通过 mio_api.c/mp_io.c 抽象底层存储与设备读取。这样,音乐、FM、录音、LineIn 等不同源可以共享同一套解码/输出管道,应用层只负责“选源”与“切源”。
本快照中可验证的模块均位于 sdk/app/bsp/common/decoder/ 目录下,是上述能力的公共底座。
Architecture
下图展示了基于本快照文件清单验证的播放源媒体架构(应用层为虚线示意,未在本快照中验证):
flowchart TD
subgraph sg_App["应用层(mbox,本快照未包含)"]
App["mbox 应用 / 播放源管理"]
end
subgraph sg_Media["媒体 I/O 层"]
MIO["mio_api.c / mp_io.c<br/>(MIO 媒体读写抽象)"]
PHY["mio_phy.c(物理层)"]
end
subgraph sg_Decode["统一解码层"]
API["decoder_api.c(解码 API)"]
MSG["decoder_msg_tab.c(解码消息表)"]
PT["decoder_point.c(解码器插件点)"]
end
subgraph sg_Codec["编解码器插件(decoder/list/)"]
MP3["mp3_standard_api.c / ump3_api.c"]
WAV["wav_api.c"]
MIDI["midi_api.c / midi_ctrl_api.c"]
F1A["f1a_api.c / f1x_parsing.c"]
A["a_api.c"]
end
subgraph sg_FX["音效与提示音"]
EQ["eq.c(均衡器)"]
SINE["sine_play.c(正弦提示音)"]
end
App -.->|"选源/切源(未验证)"| API
API --> PT
PT --> MP3
PT --> WAV
PT --> MIDI
PT --> F1A
PT --> A
API --> MIO
MIO --> PHY
API --> MSG
API --> EQ
API --> SINE
各模块职责:
decoder_api.c— 统一解码入口,是所有播放源(尤其是音乐文件)进入解码管道的门户;屏蔽具体编码格式差异,向上层提供一致的打开、解码、停止接口。decoder_point.c— 解码器“插件点/挂载点”,SDK 在此注册各格式解码器的函数指针,使decoder_api可以按需分发到具体编解码器。这是格式扩展的关键位置。decoder_msg_tab.c— 解码消息表,把解码过程中产生的事件(如格式识别结果、解码完成、出错)映射为统一消息,供应用层驱动播放源状态机。mio_api.c/mp_io.c/mio_phy.c— 媒体 I/O(Media I/O)抽象层:mio_api提供面向解码器的统一读写接口,mp_io/mio_phy负责底层存储介质(文件系统、设备)的物理访问。音乐源的文件读取、录音数据的写入都经由这一层。eq.c— 均衡器,对解码后的 PCM 数据做音效处理;所有播放源(音乐、FM、LineIn)最终都汇入该音效链路。sine_play.c— 正弦波提示音生成,用于开机/按键/录音开始等场景的提示音,可与解码播放互斥或混音。list/下的解码器 — 具体格式插件:mp3_standard_api.c/ump3_api.c(MP3 解码)、wav_api.c(WAV)、midi_api.c/midi_ctrl_api.c(MIDI)、f1a_api.c/f1x_parsing.c(F1A 及 F1X 解析)、a_api.c(A 格式)。
设计意图:把“播放源”拆成“源选择(应用层)+ 统一解码(decoder_api)+ 格式插件(decoder_point)+ 媒体读写(MIO)+ 音效(EQ)”五层,使得新增一个播放源只需在应用层加一个状态,新增一种音频格式只需在插件点挂一个新解码器,而不必改动公共解码管道。
主内容:播放源支撑模块深度分析
1. 统一解码入口 decoder_api.c
decoder_api.c 是整个媒体管道的门面(facade)。所有播放源中需要“解码”的路径(音乐文件)都通过它进入解码流程。它对外提供解码器生命周期管理(打开、解码、暂停/恢复、关闭)与消息回调注册。
在杰理 SDK 的通用设计中,应用层通常通过如下流程使用它(本快照未读取源码,以下为基于模块划分的推断,实际签名请以仓库源码为准):
- 应用根据当前播放源(如 USB/SD 音乐)调用解码 API 打开对应解码类型;
decoder_api查询decoder_point.c中的插件表,选择匹配的解码器;- 解码器通过
mio_api读取媒体数据并输出 PCM; - 解码状态与错误通过
decoder_msg_tab.c定义的消息反馈给应用。
2. 解码器插件点 decoder_point.c
这是“格式可插拔”的机制核心。SDK 将每种编解码器抽象为统一描述结构(解码类型、能力、打开/解码函数指针),注册在 decoder_point.c 中。decoder_api 依据目标格式在该表中查找对应插件并调用。
本快照中可见的插件清单(来自 sdk/app/bsp/common/decoder/list/):
| 文件 | 推断职责 | 与播放源的关系 |
|---|---|---|
mp3_standard_api.c | 标准 MP3 解码 | 音乐源最常见格式 |
ump3_api.c | 简化/轻量 MP3 解码 | 低资源场景的 MP3 播放 |
wav_api.c | WAV/PCM 解码 | 音乐源、录音回放 |
midi_api.c / midi_ctrl_api.c | MIDI 合成与控制 | 铃声/音效类音乐源 |
f1a_api.c / f1x_parsing.c | F1A 编解码 / F1X 解析 | 杰理私有格式(语音提示) |
a_api.c | A 格式解码 | 私有音频格式 |
设计意图:插件点避免了在 decoder_api 中堆叠 switch-case 式的格式分发。新增格式(如 AAC)时只需实现统一接口并注册到插件点,公共管道零改动。
3. 解码消息表 decoder_msg_tab.c
decoder_msg_tab.c 定义解码层与应用层之间的消息契约。解码过程中产生的关键事件(格式识别、一帧就绪、解码完成、文件结束、错误)被归一化为标准消息 ID,应用层的播放源状态机据此推进状态(如:文件结束 → 切下一曲 → 回到播放)。
对 mbox 而言,消息表是“源切换”的触发依据之一:例如音乐播放到文件末尾时,应用收到结束消息后决定继续播放下一曲、切到 FM 或进入待机。
4. 媒体 I/O:mio_api.c / mp_io.c / mio_phy.c
MIO(Media I/O)把“解码器要读数据”与“数据从哪来”解耦:
mio_api.c— 面向解码器的统一读写 API(打开、读、定位、关闭),屏蔽底层介质差异;mp_io.c— 媒体播放 I/O 的通用实现/分发层;mio_phy.c— 物理层,直接操作具体介质(如通过文件系统读 USB/SD、访问录音存储区)。
对不同播放源的意义:
- 音乐:解码器通过 MIO 从 USB/SD 文件系统顺序/随机读取压缩音频数据;
- 录音:录音数据经编码后由 MIO 写入存储介质(录音回放则反向读取);
- FM / LineIn:通常不经过 MIO(数据来自芯片或 ADC),但可借助 MIO 的消息/时钟机制同步播放状态。
5. 音效与提示音:eq.c 与 sine_play.c
eq.c(均衡器):位于解码输出与最终输出之间,对所有经过解码/采集的音频做频段增益处理。音乐、FM、LineIn 三条通路最终都在 EQ 汇合,因此音效参数切换(如不同播放源用不同 EQ 预设)在应用层按源切换即可。sine_play.c(正弦提示音):直接生成正弦波,用于不依赖音频文件的提示音(按键音、开机音、录音开始/结束提示)。其与解码播放的关系(互斥或混音)由应用层决定,属于播放源状态机中的旁路能力。
6. 播放源与设备的关系(未在本快照中验证)
mbox 应用层的播放源管理(applications/mbox/playback-sources)在概念上应包含:源状态机(空闲/播放/暂停/切源)、源优先级、切源时的资源抢占(解码器释放与重建、EQ 参数切换、设备电源控制)与录音状态机。由于本快照不含 applications/mbox 目录,这些实现细节未能验证;本页仅确认 SDK 侧已提供上述公共底座,应用层可基于它们组装各播放源。
Core Flow
播放源切换与解码数据流
下图描述“音乐播放源”的典型端到端数据流(应用层交互为通用推断):
sequenceDiagram
participant App as mbox 应用(播放源管理)
participant Dapi as decoder_api.c
participant PT as decoder_point.c
participant Codec as 解码器插件(如 mp3)
participant MIO as mio_api.c / mp_io.c
participant Dev as 存储/设备(USB/SD)
App->>Dapi: 选择音乐源并打开解码
activate Dapi
Dapi->>PT: 按格式查找解码器插件
PT-->>Dapi: 插件句柄/函数指针
Dapi->>Codec: 打开解码器
activate Codec
Dapi->>MIO: 打开媒体 I/O(绑定文件)
activate MIO
MIO->>Dev: 读取压缩音频数据
Dev-->>MIO: 数据块
MIO-->>Codec: 送入解码器
Codec-->>Dapi: PCM 输出 + EQ 处理
Dapi-->>App: 解码消息(就绪/进度/结束/错误)
App->>App: 推进播放源状态机(切曲/切源)
deactivate MIO
deactivate Codec
deactivate Dapi
播放源选择决策
flowchart TD
Start([播放源请求]) --> Sel{"源类型?"}
Sel -->|"音乐 (USB/SD)"| M["解码路径:MIO 读文件 + 解码器插件"]
Sel -->|"FM"| F["FM 芯片数据/混音路径"]
Sel -->|"LineIn"| L["ADC 模拟输入直通路径"]
Sel -->|"录音"| R["ADC 采集 + 编码 + 存储路径"]
M --> E["EQ 音效"]
F --> E
L --> E
R --> E
E --> Out["输出到 DAC/功放"]
说明:FM、LineIn、录音三条路径的设备驱动与音频通路代码在本快照中未找到,上图中以概念路径表示;音乐路径对应的 SDK 模块(解码器、MIO)已在文件清单中验证。
Usage Examples
无可用代码示例:受源探索预算限制,本次未读取到任何源文件内容(仅完成文件清单发现),因此无法从仓库中提取可引用的代码片段。以下代码示例均不可用,此处如实说明,不杜撰任何 API 签名或调用方式。相关实现请直接查阅下列源文件(点击跳转仓库):
- decoder_api.c — 统一解码入口
- decoder_point.c — 解码器插件点
- decoder_msg_tab.c — 解码消息表
- mio_api.c — 媒体 I/O API
当仓库内容可读取时,建议从 decoder_api.c 的打开/解码接口、decoder_point.c 的插件注册表、decoder_msg_tab.c 的消息定义三个文件入手提取示例,它们分别对应播放源代码的“调用入口”“格式扩展”与“事件回调”三个使用场景。
Configuration Options
本快照中未发现播放源相关的配置文件(mbox 应用的配置如源优先级、EQ 预设、录音参数通常位于 applications/mbox 或板级 app_config 中,本快照未包含)。已发现的 SDK 模块未暴露可在此验证的编译期/运行期配置项。
| 配置项 | 类型 | 默认值 | 说明 | 状态 |
|---|---|---|---|---|
| (mbox 应用源优先级等) | — | — | 属于应用层配置 | 未在本快照中验证 |
API Reference
以下为模块级 API 面(文件即接口边界)。由于未读取源码,函数级签名(参数、返回值、异常)无法给出,仅列出可验证的模块入口,供查阅源码时定位:
| 模块 | 推断的 API 面 | 用途 |
|---|---|---|
decoder_api.c | 解码器打开/关闭/解码/消息回调注册 | 播放源发起与终止解码 |
decoder_point.c | 解码器插件注册表/查找 | 格式分发与扩展 |
decoder_msg_tab.c | 解码消息 ID 定义 | 应用层事件驱动 |
mio_api.c / mp_io.c | MIO 打开/读/定位/关闭 | 媒体数据读写 |
mio_phy.c | 物理介质访问 | 底层设备访问 |
eq.c | EQ 初始化/参数设置/处理 | 音效处理 |
sine_play.c | 正弦波启动/停止 | 提示音播放 |
实际函数签名与调用约束请以仓库源码为准;本页不作任何推断性签名描述。
Failure Modes、边界情况与并发
以下分析基于模块职责推断,标注了证据状态:
解码失败与格式不支持
- 现象:
decoder_api打开失败或解码中途出错,经decoder_msg_tab.c上报错误消息。 - 处理:应用层播放源状态机应捕获错误消息并执行切曲/切源回退。具体错误码集合需查
decoder_msg_tab.c(本快照未读取)。
播放中设备拔出(音乐源)
- 现象:USB/SD 拔出时,MIO 底层读取返回异常。
- 处理:
mio_api/mp_io层将读取失败上抛为解码消息,应用层据此停止当前源并回到默认源(如 FM/LineIn)。该机制的触发条件需查mp_io.c/mio_phy.c(未验证细节)。
录音与播放互斥
- 录音通常独占 ADC 与存储写入通道,与播放(DAC 输出)存在资源竞争;mbox 应用需在切源时释放解码器与 MIO 句柄,避免句柄泄漏或数据竞争(应用层代码本快照未含)。
并发与重入
- 解码器、MIO、EQ 均为中断/任务上下文共用资源,SDK 通用做法是由解码任务串行化访问;提示音
sine_play.c常作为旁路与解码播放协调。并发模型细节需读取decoder_api.c确认(未验证)。
Performance 与运维考虑
基于模块划分的推断(未读取实现细节):
- 热路径:音乐播放时,
MIO 读取 → 解码 → EQ 处理 → 输出是每帧都会执行的流水线;decoder_point的插件查找应在打开阶段完成并缓存句柄,避免每帧查表。 - 资源权衡:
mp3_standard_api.c与ump3_api.c并存说明 SDK 提供了“质量 vs 资源”两种 MP3 解码取舍;低端资源受限场景应选择轻量实现(ump3),追求音质则用标准实现。 - MIO 缓冲:媒体读取的缓冲大小直接影响解码连续性(卡顿)与内存占用,属于应用层可调参数(未验证)。
- 提示音开销:
sine_play.c直接生成波形,开销极低,适合频繁触发的按键反馈,但要注意与主音频流的时序协调。 - 录音存储:编码写入(见
patch/.../encoder/encoder_api.c,AD14N 补丁中可见)需关注存储介质写速度与缓冲区水位,避免录音丢数据(具体策略未验证)。
Extension Points(扩展点)
SDK 侧已识别出以下扩展位置:
- 新增音频格式:在
decoder_point.c注册新的解码器插件,并补充decoder_msg_tab.c中对应的格式/消息映射,即可让音乐源支持新格式。这是本页文档范围内最明确的扩展点。 - 新增播放源:在应用层(mbox)增加源状态并在
decoder_api上组装对应数据路径;SDK 公共解码管道无需改动(应用层代码本快照未含)。 - 音效定制:通过
eq.c的 EQ 参数接口按播放源切换不同预设(接口签名未验证)。 - 提示音定制:使用
sine_play.c或替换为音频文件提示(经解码器播放),两种方式都接入现有播放源框架。
Tests(测试)
本快照中未发现播放源相关的测试目录或测试用例文件(嵌入式 SDK 通常以板级联调与声学测试为主)。建议的验证手段:
- 用包含 MP3/WAV/MIDI/F1A/A 各格式文件的 USB/SD 卡遍历音乐源,验证解码器插件分发与消息上报;
- 播放中拔出存储介质,验证源切换回退逻辑;
- 录音同时切换播放源,验证资源互斥与数据完整性。
Related Links
- decoder_api.c(统一解码入口)
- decoder_point.c(解码器插件点)
- decoder_msg_tab.c(解码消息表)
- mio_api.c(媒体 I/O)
- mp_io.c(媒体播放 I/O)
- eq.c(均衡器)
- sine_play.c(正弦提示音)
- mp3_standard_api.c(MP3 解码)
- wav_api.c(WAV 解码)
- midi_api.c(MIDI 解码)
- README.md(仓库说明)
相关兄弟页面(wiki 目录中)可能包括:解码器格式详解、EQ 音效、录音与存储、FM 驱动、LineIn 通路等;当这些页面存在时,请以目录导航为准。