基于炬芯ATS308X 设计的上位机usb 串口音乐EQ调节工具

python music_eq.py

ATS3089P 音乐 EQ 与 USB CDC 曲线调音工具

2026-10-30 无提示音/音乐问题已定位为历史 SDFS_K 与 OTA 临时区重叠;修复和一次性保留 U 盘的恢复步骤见 AUDIO_RECOVERY_README.md(AUDIO_RECOVERY_README.md)。已损坏的板子需要同时恢复分区表和 DSP 资源,不能只更新应用 OTA。

  1. 功能与使用边界

本功能通过 PC 自制上位机,读取开发板当前管理的音乐 PEQ 参数,拖动曲线并实时写入原厂 DSP 音乐后处理器。支持 20 段参数均衡器、每段频率/增益/Q/滤波器类型/处理位置,以及 PEQ 总开关和预衰减。

主要用于经典蓝牙 A2DP 音乐、板上走 DSP 的本地音乐播放。板端没有新增 CPU PCM 滤波循环,也没有新增工作线程;串口命令在已有 Shell 线程处理。通话 EQ、AEC、VAD、录音降噪属于其它处理链,不由本工具调节。绕过 DSP 的直通 PCM 输出也不受此功能控制。

参数修改在本次开机内保留,换曲、停止后重新播放仍可使用;重启恢复固件原有 `alcfg.bin`。PC 可导出、导入 JSON 预设,再写入设备。本版不在拖动过程中写 Flash/NVRAM。不要同时用原厂 ASET 工具修改同一音效块,以免两套控制状态互相覆盖。

  1. 快速启动

2.1 开发板进入 USB 虚拟串口模式

升级本功能对应固件后,可从现有调试 UART 输入:

```text

app usbserial on

```

Windows 设备管理器中应出现 `ATS3089 USB Serial` 对应的 COM 口。若希望保留自动监听插线设置,可执行:

```text

app usbserial auto on

app usbserial boot on

```

USB CDC、USB U 盘、USB 声卡共用一个 USB 控制器,同一时间选择一种模式。进入 CDC 后仍可从板内 NAND 播放音乐,也可由手机通过经典蓝牙向板子播放音乐。使用上位机期间关闭占用同一 COM 口的串口助手、IAP 程序和其它上位机。

2.2 安装并启动 PC 工具

在 PowerShell 中执行:

```powershell

cd D:\Master\6project\ATS3089C_to_ATS3089P\\application\bt_watch\tools\music_eq

python -m pip install -r requirements.txt

python music_eq.py

```

也可双击 `start_eq.cmd`。工具使用 Python Tkinter、Canvas 和 pyserial,不依赖原厂调音 DLL。推荐使用带 Tkinter 的 Python 3.8 或更新版本。

选择开发板 COM 口并连接。连接后自动读取完整参数。先用手机向板子播放一首熟悉的音乐,再选一个频段,轻微上下拖动,观察设备状态和听感变化。

无板时可运行:

```powershell

python music_eq.py --demo

```

演示模式只在电脑内模拟参数和确认,不发送串口数据,不代表实板已经生效。

2.3 曲线操作

  • 拖动控制点:横向改变中心/截止频率,纵向改变增益;频率轴为对数坐标。

  • 按住 Shift 拖动:锁定频率,调节增益。

  • 鼠标滚轮:调节选中频段的 Q。Q 越大,峰值滤波器影响范围越窄。

  • 侧栏:精确输入频率、增益、Q,选择频段、滤波器类型和处理位置。

  • "实时写入":拖动时合并短时间内的修改,约 100 ms 节流;关闭后可先编辑,再手动写入。

  • "读取设备":以开发板返回的完整参数更新界面;需要放弃未写修改时使用。

  • "平直":生成一套平直 PEQ 参数。PEQ 平直仍不等于关闭所有原厂音效。

  • 预设导出/导入:保存或加载 PC JSON 文件。导入后仍需实时写入或手动写入并确认。

20 个原厂频段可能存在同频点重叠,可从侧栏选择具体段。处理位置为"关闭"的段保留参数,但不参与频响。高通、低通滤波器的增益参数不决定其通带增益,界面按实际滤波类型绘制理论曲线。

  1. 参数与当前工程原厂设置

本项目的实际参数范围来自随工程配套的 `configal.bin` 定义,不能套用通用调音工具皮肤中的更大范围。

| 参数 | 范围/含义 | 串口单位 |

| --- | --- | --- |

| 频段索引 | 0~19,共 20 段 | 整数 |

| 频率 | 20~20000 Hz | Hz,步进 1 Hz |

| 增益 | -24.0~+12.0 dB | 0.1 dB |

| Q | 0.3~3.0 | 0.1 |

| 预衰减 | -12.0~0.0 dB,可独立启用 | 0.1 dB |

| PEQ 开关 | 0 关闭、1 启用 | 整数 |

| 滤波器 type | 0 关闭、1 峰值、2 高通、3 低通、4 低架、5 高架 | 整数 |

| 处理位置 route | 0 关闭、1 speaker EQ、2 post EQ | 整数 |

首次读回的是固件当前原厂曲线,并非工具预设的"全平直"。本工程原始预衰减为 -6.0 dB 且启用,频段 0 的 route 为关闭,频段 1 为 speaker,频段 2 为 post,其余主频段为 speaker。以实际读回为准。

多个提升频段叠加后,峰值可能超过单段的 +12 dB。调音时先维持适当预衰减,再逐步调整;预衰减只改变余量,不能保证任意曲线都不失真。限幅器、动态 EQ、音量、扬声器和声腔均会影响最终听感。曲线显示的是 PEQ 理论电响应,不是麦克风实测声学响应。

  1. 同步状态与失败恢复

PC 仅允许一个串口请求在途,使用序号区分回复与其它日志。写入流程为:比较差异 → 发送各项修改 → 接收每条 OK → 完整 GET 回读 → 确认参数。未收到确认、回复不完整或参数不一致时,不能把本地拖动曲线显示为设备已同步。

`active=1` 表示受管理的 DSP 音乐播放器已由媒体服务接受本工具提交的参数;这不是对 DAC 波形的实测。首次 GET 原厂参数不会主动提交,因此即使音乐已经播放也可能返回 `active=0`;可点击"写入设备",没有参数差异时工具也会提交一次总开关再回读。无音乐播放时修改仍可在本次运行中保留,下一次打开支持的音乐链路时加载。暂停、切换音源或播放器关闭时,状态可能改变。

如果当前业务关闭或旁路了 DSP DAE(例如部分 AAC 蓝牙转发路径),本功能拒绝冒充应用成功。需要退出该业务并重新打开正常音乐播放器,再写入 EQ;本功能不强行覆盖转发业务的音效策略。

若写入后拔线、超时或出现错误,设备可能已经接收了其中一部分参数。重新连接后先"读取设备",核对当前真实参数,再继续编辑;工具不盲目重试写入。单次多段预设下发采用逐项更新,不承诺整套参数同时切换。

二进制 IAP 升级期间拒绝 EQ 命令;日志导出等独占 CDC 流占用时也不允许抢占写入。完成升级/导出后重新连接工具并读取。

  1. UART/USB CDC 手动调试指令

UART 和 CDC 使用同一 `app eq` 命令。`seq` 是由请求方指定的 32 位无符号序号,上位机使用非零序号。

```text

app eq get 1

app eq set 2 4 1000 30 10 1 1

app eq preamp 3 -60 1

app eq enable 4 0

app eq enable 5 1

```

第二条将索引 4(界面第 5 段)设为:1000 Hz、+3.0 dB、Q=1.0、峰值滤波、speaker EQ。`preamp` 最后一项为预衰减启用标志;`enable` 是 PEQ 总开关,不是所有原厂音效的总旁通。

参数只接受完整十进制整数;不接受小数、正号、尾随字符或溢出数值。比如 +3.0 dB 必须发送 `30`,Q=0.7 必须发送 `7`。错误参数不改变设备配置。

5.1 协议版本 1

所有协议行均为 ASCII,以 LF 结束;PC 兼容 CRLF,并过滤 Shell 回显、ANSI 控制序列和普通日志。

GET 回复:

```text

EQ,1,1,BEGIN,revision,enabled,preamp_x10,preamp_enabled,20,active,sample_rate_hz

EQ,1,1,CAPS,20,20000,-240,120,3,30,-120,0

EQ,1,1,BAND,0,frequency_hz,gain_x10,q_x10,type,route

...

EQ,1,1,BAND,19,frequency_hz,gain_x10,q_x10,type,route

EQ,1,1,END,revision

```

BEGIN 与 END 的 revision 必须一致;必须收到 20 个不重复的频段索引。CAPS 依次给出频率、增益、Q、预衰减的最小值/最大值。`sample_rate_hz=0` 表示当前无法确认采样率,PC 使用明确标注的 48 kHz 假设绘制理论响应。

写成功和错误回复:

```text

EQ,1,2,OK,revision,active

EQ,1,2,ERR,-34,out_of_range

```

错误原因使用固定 ASCII 标识,如 `bad_args`、`bad_number`、`out_of_range`、`backend`。CDC 无法预约或 IAP 期间可能无法返回协议行,此时 PC 按超时处理。OK 表示该次操作被后端接受,PC 最后仍通过完整 GET 确认。

  1. 板端实现原理

6.1 音频路径

```text

手机 A2DP / 本地音乐

→ 媒体服务解码

→ 原厂 DSP 音乐后处理(PEQ、限幅/其它已配置音效)

→ DAC / 扬声器

PC 曲线界面 → USB CDC → 现有 Shell

→ 参数与范围检查 → 完整音效容器候选副本

→ 媒体生命周期锁 → DSP UPDATE_PARAM

→ 回复 OK → PC GET 回读确认

```

原厂实时更新入口为 `media_player_update_effect_param()`,音乐块大小必须为 1024 字节。后续起播加载的 `alcfg.bin` 则是完整配置容器,不能把纯 1024 字节音乐块误当作完整文件。

当前工程 `alcfg.bin` 长 1860 字节:16 字节头、12 字节条目表,音乐块从偏移 28 开始,长度 1024;之后是通话与语音处理参数。后端保留完整容器,更新时仅改指定 PEQ 字段,向正在播放的 DSP 发送其中 1024 字节音乐块。原有其它音效和通话数据保持原值。

媒体更新在 `media_player.c` 内使用与 open/close 相同的互斥锁,避免 Shell 拿到一个随后被关闭释放的裸播放器指针。候选参数在媒体服务同步消费完成前保持有效;失败时不将候选配置发布为成功状态。后续起播也使用完整、稳定的已提交配置。

6.2 原厂字段布局

以下偏移相对于音乐块起点,采用 little-endian 16 位字段:

| 偏移 | 内容 |

| --- | --- |

| 16 | PEQ 总开关 |

| 18 | 预衰减,0.1 dB |

| 20 | 预衰减启用 |

| 32 + 8×i | 第 i 段频率 |

| 34 + 8×i | 第 i 段 Q×10 |

| 36 + 8×i | 第 i 段增益×10 |

| 38 + 8×i | 第 i 段滤波器类型 |

| 192 + 2×i | 第 i 段处理位置/启用类型 |

`i=0..19`。额外 12 段扩展区及其它音效区本版不开放编辑,按原容器保留。本工程的扩展段处理位置均为关闭。

6.3 PC 曲线计算

峰值 EQ 使用 RBJ 二阶 IIR 公式。令 `A=10^(gain/40)`、`w0=2πf0/Fs`、`alpha=sin(w0)/(2Q)`:

```text

b0 = 1 + alpha*A a0 = 1 + alpha/A

b1 = -2*cos(w0) a1 = -2*cos(w0)

b2 = 1 - alpha*A a2 = 1 - alpha/A

H(z) = (b0+b1*z^-1+b2*z^-2)/(a0+a1*z^-1+a2*z^-2)

```

每段归一化 a0,在对数频率采样点求复数频响,级联后的 dB 响应相加,再叠加启用的预衰减。高/低通、高/低架使用对应的 RBJ 二阶形式;关闭的段不计入。它用于解释和操作参数,未复刻原厂 DSP 的全部定点量化、内部系数生成及非线性动态处理。因此图上曲线与原厂工具、板上实测可能存在差别。

  1. 源码结构与配置

| 路径 | 作用 |

| --- | --- |

| `src/main/music_eq.c/.h` | 容器校验、20 段状态、候选提交与读取 |

| `src/main/music_eq_shell.c/.h` | 命令解析、序号、可靠 CDC 回复、IAP/占用拒绝 |

| `src/main/system_app_shell.c` | 注册 `app eq` |

| `framework/media/media_player.c` | 受生命周期锁保护的音乐 EQ 更新/起播接入 |

| `tools/music_eq/music_eq.py` | Tkinter 上位机与 Canvas 曲线 |

| `tools/music_eq/eq_model.py` | 状态校验、预设、理论响应 |

| `tools/music_eq/eq_protocol.py` | pyserial 请求、快照解析、确认与回读 |

| `tools/music_eq/eq_worker.py` | 独立 PC 串口线程与界面事件 |

板端配置为 `CONFIG_APP_MUSIC_EQ=y`,依赖本板、Shell、USB CDC、媒体播放器/服务、DSP 和 `MUSIC_EFFECT`。关闭此项可去掉新 EQ 功能。重要修改遵守工程 `//zk+` / `//zk+-` 中文标记约定。

  1. 验证、固件与实板验收

软件验证包括:真实原厂容器字段/边界及非 EQ 字节保留,失败不提交,Shell 非法参数无副作用、CDC 独占与 IAP 拒绝,以及 PC 分片串口回复、序号、错误、超时和完整回读。记录放在工程忽略目录 `out/music_eq_261030/`。

已通过的软件验证:

| 验证项 | 结果 | 报告 |

| --- | --- | --- |

| PC 协议、分片/异常回复、严格写后回读、滤波及预设 | 38 项通过 | `out/music_eq_261030/pc_tests_v2/report.json` |

| 生产 Shell、参数边界、IAP、CDC 独占和输出失败 | 77 案例、228 断言通过;Cortex-M33 对象编译通过 | `out/music_eq_261030/shell_final/report.json` |

| 生产 C 后端、真实原厂容器、回滚、媒体锁、旁路和 AAC 转发禁用 | 3996 断言通过 | `out/music_eq/backend/report.json` |

后端测试可从工程根目录执行:

```powershell

python application/bt_watch/tests/music_eq/run_backend_tests.py --out out/music_eq_261030/backend_local

python application/bt_watch/tests/music_eq/run_shell_tests.py --out out/music_eq_261030/shell_local

```

本机 C 测试使用已安装在工程 `out/offline_translate/board_paged_pretrained_route/pwb1_tools/ziglang/zig.exe` 的 Zig C 编译器,Shell 另用 SDK Cortex-M33 编译器生成对象。移到其它电脑时可修改测试脚本中的编译器路径。PC 测试不依赖 C 编译器,命令见工具目录 README。

完整构建已通过,包含分区修复的当前版本 **1.00_2610301752**,构建期间生产源码未变化。固件沿用统一目录 `outdir/ats3089p_dev_watch/_firmware/`:

  • `ats3089p_dev_watch_261030.fw`:正常完整固件。

  • `ats3089p_dev_watch_261030_debug.fw`:对应调试固件。

  • `ota_firmware.bin` / `ota_firmware_261030.bin`:本轮 OTA 镜像。

  • `music_eq_261030_manifest.json`:最终版本、产物/源码 SHA-256 和验证证据。

  • `music_eq_261030_SHA256SUMS.txt`:对应校验清单。

原已验收 `1.00_2610301548` 固件先归档为同目录下的 `ats3089p_dev_watch_2610301548_archive.zip`。最终链接占用 SRAM 932608/932864 B、PSRAM 16766624/16777216 B,均在原有分区内;新增 EQ 容器 4096 B 放在 PSRAM,没有扩大 SRAM 或音频共享区。

旧 EQ 版本 `1.00_2610301656` 另存为 `ats3089p_dev_watch_2610301656_archive.zip`,用于复现 OTA 覆盖 DSP 资源。当前修复包及验证记录见 `audio_restore_261030_manifest.json`。旧 OTA 布局的板子先按 AUDIO_RECOVERY_README 完成一次分区表和资源恢复,再使用新 OTA。

软件模拟、理论曲线和编译通过不能代替实板听音、DSP 动态更新与 USB 驱动测试。未自动烧录,需升级本轮固件后完成下面的实板验收。

建议实板按以下顺序验收:

  1. 连接 COM 后读取,确认原厂 -6 dB 预衰减、20 段与处理位置显示正确。

  2. 手机 A2DP 播放音乐,将一个启用的峰值段设为 1000 Hz/+3 dB/Q1.0,观察确认状态并听差别。

  3. 再读回,确认频率/增益/Q/type/route 与设备一致;测试总开关和预衰减。

  4. 停止/换曲/重连 A2DP 后复读,确认本次开机内仍保留参数;重启后确认恢复原厂配置。

  5. 调整中拔线,确认 PC 不显示成功;重连先读取,再继续编辑。

  6. 导出 JSON,平直后重新导入并写入,核对恢复;对照原厂工具或音频测量验证实际滤波响应。

相关推荐
三佛科技-134163842124 小时前
过认证72W碳化硅方案(12V6A)主控HN1562+HN36228V 典型应用电路、变压器参数分享
单片机·嵌入式硬件·物联网·智能家居·pcb工艺
Zwawa6 小时前
串口为什么会丢字节:从轮询到中断和环形缓冲区
c语言·单片机·嵌入式
Brilliantwxx6 小时前
【STM32】 内部 Flash 详解:寄存器逐位拆解 + 工作流程顺序全讲 + EEPROM再实现
stm32·单片机·嵌入式硬件·1024程序员节
木子单片机6 小时前
基于单片机的DS18B20温度传感器测温系统设计
单片机·嵌入式硬件·51单片机·keil
华清远见IT开放实验室6 小时前
实验室建设案例 | 安徽三联学院物联网实验室
stm32·单片机·嵌入式硬件·物联网·华清远见
Zw-awa7 小时前
串口为什么会丢字节:从轮询到中断和环形缓冲区
stm32
深圳光特通信豆子8 小时前
TTL 光模块在工业控制与串口通信中的应用指南(10M BIDI 单模系列)
单片机·嵌入式硬件
桀人8 小时前
SPI概念引入
stm32·单片机·嵌入式硬件
离凌寒9 小时前
一、基于stm32+freertos下LD2410D和R60ADB1两款雷达的使用效果
stm32·单片机·嵌入式硬件