案例3:Ascend 310B DDSP 智能电子琴
案例3:Ascend 310B DDSP 智能电子琴
数字乐器的音色生成既要描述音高、力度、起音和衰减等音乐控制信息,也要在有限计算资源下连续产生具有稳定听感的音频波形。传统采样合成依赖预先录制的声音素材,而直接生成波形的神经网络通常需要在音频采样率上执行高密度计算。可微分数字信号处理(Differentiable Digital Signal Processing,DDSP)将谐波振荡器、滤波噪声和混响等声学结构引入神经网络训练,使模型能够预测具有物理含义的控制量,再由数字信号处理模块完成波形合成。DDSP 论文给出了这一方法的系统论述。
将 DDSP 从研究模型迁移到边缘计算设备,并不只是完成模型格式转换。实时演奏需要维持毫秒级控制周期和连续循环状态,MIDI 文件渲染需要处理完整乐曲的时序上下文,麦克风音色转换还涉及音高估计、噪声门、采样率转换和双工音频路由。这些任务具有不同的时间尺度和资源需求,能够集中体现神经网络推理、数字信号处理、实时调度与人机交互之间的协同关系。
基于上述背景,本案例以 Ascend 310B 为计算平台,选取复音钢琴演奏、MIDI 文件音色渲染和单音音色转换三类任务,构建一套完整的 DDSP 实验系统。该案例既可用于理解 Piano-DDSP、MIDI-DDSP 与 DDSP-VST 的网络结构和控制机制,也可用于研究 NPU 推理与 CPU 音频合成的任务划分,以及模型在交互式数字乐器、自动音乐制作和边缘音频处理中的应用方式。
配套代码位于 samples/case3。
1. 案例目标与学习成果
1.1 系统功能
该 Web 工作站支持以下三类处理流程:
| 工作流 | 输入 | 神经网络 | 输出 | 适用场景 |
|---|---|---|---|---|
| 实时演奏 | 触摸屏钢琴或标准 MIDI 键盘 | Piano-DDSP OM | 实时扬声器声音 | 触控输入与具有力度、踏板和弯音控制的实体演奏 |
| MIDI-DDSP | .mid 或 .midi 文件 | Expression 与 Synthesis OM 组件 | WAV、开发板播放或浏览器播放 | 离线多声部音色渲染 |
| DDSP-VST | 摄像头或独立麦克风的实体音频输入 | Feature OM 与 Control OM | 实时音色转换 | 把单音哼唱或乐器声转换为 11 种音色 |
设备页不参与音乐生成,它负责展示开发板、NPU、模型、音频、MIDI、蓝牙和 Python 环境状态,并提供独占的扬声器与麦克风测试。
1.2 学习成果与边界
读者将理解并复现以下内容:
- DDSP 以可解释控制量连接神经网络与音频合成模块的基本原理。
- Piano-DDSP、MIDI-DDSP 和 DDSP-VST 三套网络在输入、状态、时序和用途上的区别。
- 自训练模型导出与上游 TFLite 模型迁移两类来源,以及 ONNX、OM 和板端推理之间的关系。
- FastAPI、WebSocket、音频线程、MIDI 状态机、资源互斥和文件产物如何协作。
- React 界面如何在触摸屏、桌面和移动视口中保持良好的可读性、可操作性与渲染效率。
本案例关注声音生成与实时音频处理,摄像头仅作为麦克风载体,不涉及图像分析。DDSP-VST Effect 的研究对象限定为基频相对稳定的单音输入,复音分离与复杂声场建模不在讨论范围内。运行指标用于描述计算链路和资源状态;音色质量、声压与声学特性仍需通过独立的听音和测量实验评价。
2. 器件与材料清单
2.1 最小配置
最小配置用于完成触控演奏、浏览器操作和基本声音输出。
| 器件 | 数量 | 接口 | 用途 | 替代要求 |
|---|---|---|---|---|
| Ascend 310B 开发板 | 1 | 以太网、HDMI、USB、音频 | 运行 FastAPI、PyACL、OM 推理和 CPU DSP | 必须具备可用 CANN/PyACL 和对应 SoC 的 OM 支持 |
| 原配电源与启动存储 | 1 套 | 开发板专用 | 启动和稳定供电 | 电压、电流和启动介质必须符合板卡说明 |
| HDMI 触摸显示器 | 1 | HDMI、USB 触控 | 本地显示与触摸演奏 | 应支持浏览器全屏显示和稳定的多点触控 |
| HDMI 线与 USB 触控线 | 各 1 | HDMI、USB | 视频与触控回传 | 线材需支持屏幕分辨率和持续供电 |
| 音频输出 | 1 | USB、板载接口或 Bluetooth A2DP | 播放合成音频 | 支持有线音箱、蓝牙音箱和蓝牙耳机;实时演奏验收推荐使用有线输出 |
| 局域网与开发电脑 | 1 套 | 以太网或 Wi-Fi | 构建、部署和浏览器访问 | 开发电脑与开发板需位于可信局域网 |
本案例支持通过 Bluetooth A2DP 连接蓝牙音箱和蓝牙耳机。蓝牙链路中的音频编码、无线传输和播放缓冲通常会增加端到端延迟,因此实时演奏时可能出现较明显的声音滞后,影响演奏反馈。该部分延迟来自蓝牙音频链路,不应归因于 NPU 推理性能;评价模型推理和实时合成能力时,应优先采用有线输出,或将蓝牙链路延迟作为独立分量测量。
2.2 完整功能配置
以下型号构成本案例的验证配置,但不代表唯一可用品牌。
| 器件 | 数量 | 验证型号 | 接口 | 在实验中的作用 |
|---|---|---|---|---|
| Ascend 310B 开发板 | 1 | Orange Pi AIpro | USB、HDMI、网络 | OM 推理、音频、后端和触摸屏主机 |
| 触摸显示器 | 1 | HDMI 触摸显示器 | HDMI + USB | 四工作区本地操作 |
| USB 音箱 | 1 | EDIFIER M16 Pro | USB Audio | Piano-DDSP、MIDI-DDSP 和 DDSP-VST 的默认输出 |
| 摄像头麦克风 | 1 | UGREEN Camera 1080P | USB Audio Capture | DDSP-VST 输入与麦克风测试;图像数据不参与本案例 |
| MIDI 键盘 | 1 | MIDIPLUS TINY,32 键 | USB MIDI | 物理按键、力度和控制器输入 |
| 路由器 | 1 | 普通局域网路由器 | 以太网或 Wi-Fi | 分配 IPv4 地址并连接开发电脑与开发板 |
| 网线 | 1 | Cat5e 或更高 | RJ45 | 推荐的稳定部署和调试链路 |
| 开发电脑 | 1 | Windows 或 Linux | USB、网络 | Python 测试、Node 前端构建和模型发布下载 |
| USB 线材与供电线 | 若干 | 与设备匹配 | USB-A、USB-C 等 | 音箱、摄像头、MIDI、触控和供电连接 |
2.3 可选扩展
| 扩展 | 用途 | 使用条件 |
|---|---|---|
| 蓝牙 A2DP 音箱 | 无线播放 | 先由开发板系统完成配对,并在 PulseAudio 中出现可用 sink;蓝牙延迟不作为低延迟验收路径 |
| USB DAC 或 USB 声卡 | 提供更稳定的线路输出 | 必须能被开发板枚举并显示为可用输出 |
| 独立单音麦克风 | 改善 DDSP-VST 输入信噪比 | 必须是实体 capture source,不能使用 PulseAudio monitor |
| 延音踏板 | 控制实体 MIDI 的 CC64 | MIDI 控制器需要上报标准控制变化消息 |
3. 系统总体架构与完整流程
3.1 三条业务链

三条链路共享 NPU 和音频设备,但采用不同的时间模型。Piano-DDSP 每 4 ms 更新一次控制量;MIDI-DDSP 利用完整乐曲上下文离线生成 WAV;DDSP-VST 每 20 ms 处理一帧音高和响度控制。因此,三条链路需要分别设计状态管理、调度和缓冲策略。
3.2 硬件连接

应按设备标识选择输入输出。程序不会在摄像头或音箱断开后静默切换到其他设备,也不会把 PulseAudio 输出监听源用作麦克风输入。显式路由可以避免意外回放系统声音、产生反馈或将测试信号发送到错误的音频设备。
3.3 开发电脑与开发板的职责边界

| 操作 | 开发电脑 | Ascend 310B |
|---|---|---|
| 编辑源码、运行普通 Python 单元测试 | 是 | 否 |
npm ci、npm run test、npm run build | 是 | 否 |
| 下载并校验发布模型 | 是 | 可接收已校验资产 |
ATC、PyACL、OM 推理、npu-smi | 否 | 是 |
| PulseAudio 实体路由和真实听音 | 否 | 是 |
4. DDSP 原理
4.1 从采样合成到可微分 DSP
传统采样合成器把大量录音映射到音高和力度区域,音色逼真但资产大,跨音高和连续控制依赖插值。端到端波形神经网络可以直接预测音频,却需要在音频采样率上输出大量数据,实时部署的计算量、状态和可解释性都更困难。
DDSP 将振荡器、滤波器、包络和混响等数字信号处理模块写成可微形式,使这些模块能够参与梯度优化;部署阶段则由神经网络预测低维控制量,再由信号处理模块合成波形。DDSP 论文提出了这一建模框架,官方代码给出了相应实现。
4.2 基频、谐波和相位
设采样率为 ,第 个采样的基频为 。第 个谐波的相位按下式累积:
网络预测总幅度 和未归一化谐波参数 。使用非负映射和归一化得到谐波比例:
谐波信号为:
超过奈奎斯特频率的谐波必须被抑制,即 。Piano-DDSP 还预测 inharmonicity,用于表达钢琴弦的部分音偏离整数倍基频的现象。
4.3 滤波噪声、包络、重采样和混响
噪声支路把白噪声 变换到频域,并用网络预测的频带幅度 构成时变滤波器:
最终干声是谐波和噪声之和:
控制网络工作在 50 Hz 或 250 Hz,远低于 16 kHz 音频采样率,因此幅度、基频和频带系数需要插值到音频时间轴。混响可以是学习到的冲激响应 ,也可以是 FreeVerb 风格反馈延迟网络:

4.4 参数如何改变听感
| 控制量 | 物理或听觉含义 | 常见异常 |
|---|---|---|
f0 | 基频,决定音高和滑音轨迹 | 噪声被误检为基频时会出现无意义的低音或抖动 |
| 幅度或响度 | 控制音符包络和整体强弱 | 过大会削波,过小会让音色模型看不到有效输入 |
| 谐波分布 | 决定明亮度、共鸣和乐器主体音色 | 高频谐波过多会尖锐,归一化错误会改变总能量 |
| 噪声频带 | 表达吹气、摩擦、击弦和瞬态 | 过高会产生嘶声,全部关闭会让音色不自然 |
| 混响 | 表达空间和尾音 | 全湿声会掩盖起音,实时链路中也会增加主观拖尾 |
| 噪声门 | 阻止环境底噪触发模型 | 阈值过低会持续触发,过高会吞掉轻声起音 |
5. 三套神经网络架构
5.1 Piano-DDSP
5.1.1 模型来源
本案例所用的 Piano-DDSP 不是对上游 TensorFlow 权重的格式转换,而是作者在独立的 piano-ddsp-pytorch 训练项目中完成的 PyTorch 实现与训练。网络设计以 DDSP-Piano 的复音钢琴建模方法为基础,发布权重均由该项目在 MAESTRO 数据集上的训练过程产生,并由训练所得 checkpoint 导出为 ONNX。因而,Piano-DDSP 的研究链路是“结构复现与修改、PyTorch 训练、ONNX 导出、OM 转换”,与本章另外两类模型的迁移来源有本质区别。
5.1.2 网络实现
模型以 MIDI 音高、力度、踏板状态和钢琴录音域索引为条件,在 16 kHz 采样率下以 250 Hz 控制率工作,每个控制帧对应 64 个音频采样,并行描述最多 16 个声部。网络由全局上下文分支和共享权重的单声部分支构成。全局分支综合所有活动音符、踏板和钢琴嵌入,通过循环网络形成跨声部的上下文表示;单声部分支则为每个声部分别结合当前音符、延音阶段与全局上下文,预测幅度、谐波分布和噪声频带。音高支路进一步估计基频、弦间微小失谐与非谐性,从而表达钢琴弦的刚度及同音弦拍频。
这一分层结构兼顾了复音耦合与逐声部独立性:全局上下文反映踏板和同时发声音符对整体音色的影响,单声部循环状态保持各音符起音、持续和释放阶段的连续性。神经网络只预测声学控制量,谐波振荡、滤波噪声、相位累积与混响卷积由宿主端 DSP 完成,避免在高采样率上直接生成整段波形。

5.1.3 训练策略
MAESTRO 提供时间对齐的钢琴音频与高精度 MIDI。训练时,MIDI 音符、击键力度和踏板控制构成条件序列,配对音频构成声学监督;录音年份映射为钢琴录音域索引,使模型能够学习不同乐器与录音环境之间的系统差异。训练、验证和测试按照数据集给定的乐曲划分组织,避免同一作品的不同演奏跨越数据子集而造成信息泄漏。
训练过程将音色控制与音高细节分阶段优化。首先关闭失谐支路,学习上下文网络、单声部控制网络、钢琴嵌入和混响,使模型建立稳定的幅度、谐波与噪声表征;随后固定主要音色通路,训练失谐、非谐性及其录音域嵌入;最后在音高支路生效的条件下微调控制网络,使频率结构与音色包络共同收敛。分阶段训练减少了幅度谱重建与细微音高偏差之间的相互干扰,也使不同结构方案能够在一致的数据和控制合同下比较。
训练系统保留干声与混响声两条评价路径。干声约束主要考察振荡器控制和瞬态是否合理,混响声约束则用于评价最终听感及空间响应。对全湿声候选结构,还加入能量、起音和力度相关的感知约束,以抑制仅凭频谱损失获得低数值误差、却削弱击弦瞬态的情况。模型选择因此不能只依据单一损失值,还需要结合未见曲目的渲染结果和听音比较。
5.1.4 面向实时部署的结构修改
为适应流式推理,训练实现将原本隐含在序列计算中的上下文状态和逐声部状态改为显式输入输出,使每次推理只处理一个控制帧,同时保持帧间递归关系。音符释放状态由宿主端维护,谐波相位、噪声重叠缓存和混响历史也位于模型之外;这种边界既缩小了 ONNX 计算图,也使状态复位、声部回收和确定性重放具有明确语义。面向 Ascend 转换时,GRU 进一步等价展开为矩阵乘、门控激活和逐元素运算,以规避循环算子的精度与算子支持限制。展开只改变计算图的表示方式,不改变训练权重和递推方程。
在共同的输入、状态和输出合同下,本案例训练并比较了四类结构:
| 结构方案 | 主要修改 | 研究目的 |
|---|---|---|
| GRU 与学习型冲激响应 | 复现基准上下文网络和单声部 GRU,预测 96 个谐波与 64 个噪声频带 | 建立与 DDSP-Piano 结构相近的因果基线 |
| FiLM 与反馈延迟网络 | 用钢琴嵌入调制全局特征,引入更深的单声部网络、联合非谐性模型和 128/96 维控制 | 考察条件调制、模型容量和参数化混响的作用 |
| GRU 全湿声校准 | 保留基准控制网络,强化混响声、能量、起音和力度约束 | 研究感知目标对击弦瞬态和空间感的影响 |
| FiLM 全湿声校准 | 结合 FiLM、深层单声部网络、联合非谐性和学习型冲激响应 | 比较结构扩展与感知校准的联合效果 |
这些结构名称表示建模假设,而不是预设的音质排序。不同方案在网络容量、谐波分辨率和混响表示上各有侧重,最终选择需要同时考虑闭环数值误差、实时预算和主观听音结果。
5.1.5 ONNX 导出合同
训练后的 PyTorch 控制网络以 FP32、固定批量和单控制帧形式导出为 ONNX。下表以 GRU 与学习型冲激响应结构为例;FiLM 与反馈延迟网络结构保持相同的输入和循环状态语义,但将谐波、噪声及混响输出分别扩展为相应的控制维度。
| 方向 | 张量 | 形状 | 含义 |
|---|---|---|---|
| 输入 | conditioning | [1,1,16,2] | 16 声部的音高与力度条件 |
| 输入 | pedal | [1,1,4] | 踏板与连续控制状态 |
| 输入 | piano_model | [1] | MAESTRO 钢琴年份索引 |
| 输入 | extended_pitch | [1,1,16,1] | 扩展音高条件 |
| 输入 | context_state | [1,1,64] | 全局循环状态 |
| 输入 | monophonic_state | [1,16,192] | 每声部循环状态 |
| 输出 | amplitudes | [1,1,16,1] | 声部总幅度 |
| 输出 | harmonic_distribution | [1,1,16,96] | 96 个谐波比例 |
| 输出 | inharmonicity、f0_hz | [1,1,16,1] | 非谐性和基频 |
| 输出 | noise_magnitudes | [1,1,16,64] | 64 个噪声频带 |
| 输出 | reverb_ir | [1,24000] | 学习到的混响冲激响应 |
| 输出 | next_context_state | [1,1,64] | 下一帧全局状态 |
| 输出 | next_monophonic_state | [1,16,192] | 下一帧声部状态 |
导出验证不仅比较单帧输出,还将上一帧状态连续反馈给下一帧,逐项对照 PyTorch 与 ONNX Runtime 的控制量和循环状态。这样可以发现单帧误差较小、但在长序列中逐步累积的偏差。通过该检验的 ONNX 才进入后续 OM 转换;此处的数值一致性仍不等价于音质评价或端到端音频延迟。
5.2 MIDI-DDSP

MIDI-DDSP 为已知完整乐曲的离线层级模型,不是物理 MIDI 键盘的低延迟模型。Expression Generator 先从最长 32 个 note/rest token 的上下文预测 6 维表情控制:volume、vol_fluc、vibrato、brightness、attack 和 vol_peak_pos。Synthesis Generator 再用 64 帧窗口、250 Hz 控制率生成音频控制量。MIDI-DDSP 论文和官方仓库解释了这种符号控制与音色合成的层级结构。
stateful v2 把原始图拆成八个可独立转换和批处理的组件:
| 组件 | 关键输入输出 |
|---|---|
expression_context_forward | 前向 token 上下文与状态 |
expression_context_backward | 反向 token 上下文与状态 |
expression_decode | 上下文、上一控制与下一自回归状态 |
synthesis_precondition | 帧级音高、表情和乐器条件 |
synthesis_context_forward | 前向帧上下文与状态 |
synthesis_context_backward | 反向帧上下文与状态 |
synthesis_f0_decode | 基频控制与解码状态 |
synthesis_timbre | amplitude[1]、harmonics[60]、noise_amps[65] |
模型为单声部建模。程序先把 MIDI 分成单音声部,再按静态 batch 1/2/4/8 选择最小可容纳 OM,生成每个 stem,最后对齐并混音。双向上下文需要看到完整前后文,因此不能把这条链路直接放到按键后的 4 ms 实时路径中。
5.3 DDSP-VST Feature 与 Control
DDSP-VST Effect 参考上游 DDSP-VST 实现。其计算过程分为 Feature 与 Control 两级:Feature 模型从滑动音频窗口估计基频和响度表征,Control 模型结合循环状态生成谐波、噪声与幅度控制量。两级模型的分离使音频特征提取与乐器音色建模能够采用不同的状态更新方式。

| 模型 | 输入 | 输出 | 时率与作用 |
|---|---|---|---|
| Feature OM | float32[1024] 音频 | f0_scaled[1]、pw_scaled[1]、f0_hz[1]、pw_db[1] | 16 kHz,步长 320,即 50 Hz |
| Control OM | state[512]、f0_scaled[1]、pw_scaled[1] | amplitude[1]、harmonics[60]、noise_amps[65]、state_out[512] | 每 20 ms 更新音色控制与 GRU 状态 |
Control 模型覆盖巴松、单簧管、长笛、口风琴、萨克斯、西塔琴、长号、小号、大号、小提琴和人声音色,共 11 类。不同音色共享相同的输入与状态合同,但通过各自的模型参数形成不同的谐波和噪声分布。
5.4 三套网络对比
| 特性 | Piano-DDSP | MIDI-DDSP | DDSP-VST Effect |
|---|---|---|---|
| 输入 | MIDI 帧、踏板、钢琴索引 | 完整 MIDI 文件与乐器分配 | 实体麦克风音频 |
| 主要用途 | 实时复音钢琴 | 离线高质量 MIDI 渲染 | 实时单音音色转换 |
| 复音能力 | 固定 16 声部 | 分离后逐单音声部渲染并混音 | 单音输入 |
| 控制率 | 250 Hz | 250 Hz | 50 Hz |
| 时序状态 | 显式全局与逐声部状态 | 八组件双向和自回归状态 | 512 维 Control GRU 状态 |
| 前后文 | 只依赖过去和当前帧 | 使用完整乐曲的双向上下文 | 滑动音频窗口与过去状态 |
| NPU 输出 | 96 谐波、64 噪声等控制 | 60 谐波、65 噪声等控制 | Feature 特征和 60/65 控制 |
| DSP 边界 | CPU 合成、重采样和 IR/FDN | CPU 合成、混响、stem 混音和 WAV | CPU 合成、重采样、增益和 FreeVerb |
6. 模型转换与 Ascend 部署
6.1 两类模型来源
三套网络进入 Ascend 部署链之前具有两种不同来源,不能将其笼统表述为同一种“模型下载”过程。
| 模型族 | 原始来源 | ONNX 的形成方式 | 本案例中的作用 |
|---|---|---|---|
| Piano-DDSP | 作者基于 DDSP-Piano 结构完成的 PyTorch 训练模型 | 从本地训练 checkpoint 导出因果、显式状态的 ONNX | 实时复音钢琴控制 |
| MIDI-DDSP | Google MIDI-DDSP 项目的 TFLite 模型 | 按层级生成过程重构静态 ONNX 组件,并显式化双向与自回归状态 | 完整 MIDI 的表情与音色渲染 |
| DDSP-VST | Google DDSP-VST 项目的 TFLite 模型 | 将 Feature 与 Control 分别转换为流式 ONNX,并显式化 Control 的循环状态 | 实时单音特征提取与音色转换 |
Piano-DDSP 的训练代码与模型修改见 piano-ddsp-pytorch,导出的 ONNX 模型发布在 Piano-DDSP 模型仓库。MIDI-DDSP 与 DDSP-VST 的网络语义分别以 Google MIDI-DDSP 和 Google DDSP-VST 为依据。固定模型来源的意义在于使后续差异可以归因于图变换、精度配置或硬件执行,而不是上游权重的变化。
6.2 从 TFLite 到 ONNX 的图语义重构
TFLite 到 ONNX 的迁移不能只追求算子逐项替换,还必须保持原模型的时序语义。DDSP-VST 的 Control 模型原本包含循环控制流;转换时将其改写为单步计算图,把上一帧 GRU 状态作为输入、下一帧状态作为输出,并将幅度非线性、谐波归一化和奈奎斯特频率屏蔽纳入同一图中。Feature 模型则保持滑动音频窗口与固定步长,使基频和响度估计与上游实时处理的时间尺度一致。验证时需要连续输入多帧信号,因为循环状态的误差不会在孤立单帧测试中充分显现。
MIDI-DDSP 的转换更为复杂。Expression Generator 与 Synthesis Generator 同时包含双向上下文和自回归解码,若简单按窗口截断,会破坏完整乐曲的前后文。本案例将其分解为上下文编码、条件预处理、自回归解码、基频解码和音色控制等八类组件,显式传递各级状态,并通过有效帧掩码保持填充区域不参与统计。该设计既满足 ONNX 静态形状约束,又保留完整 MIDI 序列上的双向语义和逐帧递推关系。
具体转换遵循以下方法:
- 以 TFLite 模型和一组连续参考输入为起点,记录初始状态、逐帧输出及状态演化,而非只保存孤立样本。
- 识别 TFLite 子图中的常量权重、张量布局、门控顺序和后处理操作,建立与上游模型一致的逻辑张量合同。
- 将动态循环和张量列表改写为固定形状的单步或分段 ONNX 图,把所有跨调用信息显式表示为状态输入输出。
- 对广播、归一化、填充掩码和非线性后处理逐项对齐,避免框架默认语义差异改变声学控制量。
- 使用相同输入连续运行 TFLite 与 ONNX,比较控制量、离散采样结果和循环状态;通过闭环对照后再执行 ONNX 结构检查。
两类转换均以 TFLite 输出为参考,比较连续控制量、离散采样结果和状态演化;只有当 ONNX 在相同输入下保持规定误差范围内的一致性,才能进入硬件编译阶段。这种做法把“模型可以被转换”与“转换后仍实现同一算法”区分开来。
6.3 ONNX 到 OM 的转换与验证

ONNX 首先按照 ONNX 官方规范检查计算图、张量名称、形状和数据类型,再由与开发板匹配的 CANN 工具链转换为 OM;ATC 参数及目标芯片配置应以 Ascend CANN 官方文档为准。精度模式不是孤立的编译选项,而会改变循环状态和声学控制量的数值行为,因此不同网络应依据参考误差与实时预算分别确定,不能仅以转换成功或模型文件大小作为选择标准。
验证分为四个相互衔接的层次:
| 验证层次 | 核心问题 | 主要判据 |
|---|---|---|
| 结构一致性 | OM 是否实现预期的输入输出接口 | 张量名称、形状、类型和状态维度完全对应 |
| 数值一致性 | 图变换和精度选择是否改变模型行为 | ONNX 与 OM 在固定输入及连续状态回路上的误差受控,无 NaN 或 Inf |
| 时间可行性 | 推理是否能在控制周期内稳定完成 | 预热后统计延迟分布,并以高百分位而非单次最小值判断 |
| 系统一致性 | 神经控制量能否形成连续可听的音频 | 检查非静音输入输出、音频缓冲、削波、设备路由与长时间状态增长 |
其中,Piano-DDSP 尤其需要考察全局状态与逐声部状态的长期累积误差;MIDI-DDSP 需要保持双向上下文、自回归采样和整曲统计;DDSP-VST 则需要联合验证 Feature 与 Control 的控制周期。详细转换命令、张量夹具和报告格式见模型与 OM 部署文档。
6.4 运行时模型边界
实验系统在板端以 OM 作为统一的神经网络执行形式,使三套模型共享相同的 NPU 调用和资源管理边界。若模型合同、循环状态或音频设备条件不满足,运行会话应显式终止并释放资源,避免不同推理后端或隐式设备切换混入同一次实验。ONNX 与 TFLite 在这里承担来源对照和数值参考的角色,性能评价则以真实 OM 推理和完整音频链路为对象。
7. 后端设计
7.1 服务分层与作业模型
后端以 FastAPI 为服务框架,将静态界面、请求响应、事件推送、文件产物和硬件控制组织在同一应用边界内。查询类请求用于获得模型、设备和会话快照,命令类请求负责启动或停止具有副作用的操作,WebSocket 则传递音符边沿、作业进度和实时指标。三类通信承担不同的时间语义,可避免用高频轮询近似短暂事件,也能防止将耗时渲染阻塞在一次 HTTP 请求中。

MIDI-DDSP 渲染采用异步作业模型。输入 MIDI、声部分配、模型选择与合成参数共同确定一次渲染上下文,输出 WAV 与任务元数据构成可追溯的结果版本。关系数据库只承担索引和检索功能,原始 MIDI、音频产物及其元数据仍是实验记录的主体;这种安排既支持同一乐曲的多方案比较,也避免界面状态成为唯一的数据来源。
7.2 资源互斥与实时钢琴
资源协调层对以下会占用 NPU 或物理音频设备的流程实行互斥:
- Piano-DDSP 触控与实体 MIDI 共享实时会话;
- DDSP-VST Effect 双工链路;
- MIDI-DDSP 板端 WAV 播放;
- 麦克风输入测试;
- 扬声器左右声道测试。
冲突请求会被显式拒绝,而不是让多个任务同时打开同一硬件。会话在正常停止、异常退出或设备断开时均需释放资源;设备和模型的实际路径由后端管理,浏览器只表达选择意图。由此可以把一次实验的输入、模型与输出路由固定在明确的资源组合上。
实时钢琴在独立常驻进程中维持神经状态和音频状态。MIDI 按下事件立即进入状态机,过早到达的释放事件只延长合成内部的最小发声门限,从而避免一次浏览器刷新周期内的快速点按退化为零长度声音。重复音符、延音踏板、声部替换和异常断开都在同一状态机中处理,以保证有限声部槽位能够被确定地占用和回收。
合成结果先写入有界队列,再依据交互延迟与抗抖动需求组合为不同长度的音频块。较短的缓冲提高按键响应,但对推理抖动和设备调度更敏感;较长的缓冲能够提高连续性,却增加演奏反馈延迟。合成增益、系统混音器音量和音箱硬件音量属于三个独立控制层,评价时应分别记录,避免把音量变化误判为模型幅度变化。
7.3 DDSP-VST 音频线程与安全控制
Effect 的固定链路为:48 kHz 双声道摄像头输入 -> 单声道 -> 16 kHz -> 1024 窗/320 步长 -> Feature OM -> Control OM -> DDSP 合成 -> 48 kHz 双声道输出。输入和输出使用 parec、paplay 对应的 PulseAudio source/sink,不使用 monitor,也不在设备丢失后自动改路。
噪声门先校准环境底噪,再用开启阈值、迟滞、保持、开启和关闭时间平滑门增益。默认只输出转换后的声音,输出增益为 -18 dB。持续过载会进入明确的安全静音,并在状态和 WebSocket 中报告;不会继续输出可能削波的声音。

7.4 通信语义
| 通信形式 | 适用信息 | 设计依据 |
|---|---|---|
| REST 查询 | 模型目录、设备目录、系统状态和历史作业 | 信息具有快照语义,可重复读取且不改变运行状态 |
| REST 命令 | 会话启停、参数修改、渲染创建和设备测试 | 操作具有明确副作用,需要校验资源条件并返回执行结果 |
| WebSocket 事件 | 音符边沿、踏板变化、作业进度、设备变化和实时指标 | 信息短暂且连续,轮询可能遗漏事件或引入额外延迟 |
| 文件访问 | MIDI、WAV、录音与评价报告 | 大型产物采用独立传输,避免混入控制消息 |
通信接口的核心约束是:客户端提交目录标识和有界参数,服务端解析实际模型与设备;实时事件负责同步变化,状态快照负责断线后的重新对齐。具体端点和字段属于实现合同,见WebUI 与 API 指南。由于服务直接控制音频与模型资源,部署范围应限定在可信网络中。
8. 前端设计
8.1 信息架构与状态同步
前端以 React、TypeScript 和 Canvas 构成交互层,按照实时演奏、MIDI 文件渲染、麦克风音色转换和设备管理四类任务组织顶层信息。触摸琴键与实体 MIDI 键盘共享同一实时演奏工作区和后端会话,只在输入方式上切换,避免把同一模型和参数拆成两套彼此漂移的界面。
界面状态分为三类:用户偏好、服务端快照和实时事件。音色显示方式、键盘范围等偏好可以保存在浏览器中;模型可用性、设备选择和会话生命周期以服务端为准;音符、作业进度和音频指标则由事件流更新。恢复页面时先读取快照,再接续事件,能够在刷新或短暂断线后重新建立一致状态。会话运行期间锁定会改变模型或设备归属的选项,以免界面选择与实际音频链路脱节。
低频状态采用周期性查询,短暂变化采用 WebSocket 推送。工作区按需加载,包含连续动画的视图在不可见时暂停绘制,使界面更新不会与音频线程争夺不必要的 CPU 时间。运行、不可用、故障、输入门和安全静音等状态同时使用文字、图标和颜色表达,保证信息不依赖单一视觉通道。
8.2 两个钢琴卷帘的时间模型
实时演奏和 MIDI 文件浏览都使用钢琴卷帘,但二者具有不同的时间模型:
| 卷帘类型 | 时间来源 | 绘制策略 | 性能边界 |
|---|---|---|---|
| 实时卷帘 | WebSocket 的音符边沿 | 缓存键位与网格,仅更新新增轨迹和当前按键 | 限制刷新率、像素密度与历史长度,空闲时停止绘制 |
| 文件卷帘 | 完整 MIDI 时间轴与播放位置 | 分离静态网格、音符层和动态光标 | 以分层 Canvas 承载长序列,避免为每个音符创建界面节点 |
实时卷帘保留短音符的最小可见高度;状态快照只用于重新同步当前按键,不能反推已错过的短音符。文件卷帘支持声部颜色、拍号网格、缩放、拖动、进度光标和活动音符,但不是 MIDI 编辑器。
8.3 触摸屏、桌面和手机布局
响应式设计不以某一种屏幕尺寸作为成立条件,而以内容优先级、可用空间和输入方式决定布局。宽视口并排显示控制面板与主要可视化区域,空间收窄时依次换行或折叠次要信息;钢琴键盘和卷帘保持自身比例并在容器内缩放。触控目标应留有足够间距,连续滑块与离散命令采用不同控件,文本标签不得因缩放而被截断。
移动布局将高频工作流保留在可达位置,并处理浏览器安全区;桌面布局则强调横向比较和键盘焦点。所有布局都应避免文档级横向滚动、控件重叠和状态跳动,同时保留页签语义、可访问名称与清晰的焦点顺序。由此,界面可以适应不同显示设备,而不把案例能力绑定到某一分辨率或物理尺寸。
9. 逐页界面与操作说明
本节截图采集自 Ascend 310B 开发板实际运行的服务,用于说明界面结构、交互关系和典型状态,不作为性能测量证据。界面中的 NPU 诊断警告应与设备可见性、模型加载状态和 OM 推理结果联合解释,不能由单一提示直接推断推理失败。
9.1 实时演奏 / 触摸屏

| 区域 | 控件 | 作用 | 正常状态 | 注意事项 |
|---|---|---|---|---|
| 统一会话栏 | 输入方式、当前音色、音频输出、延时档、开始/停止、Panic | 管理共享 Piano-DDSP 会话 | 截图为已连接、待机 | 会话运行、录音或切换时不能更换输入方式;Panic 用于释放悬挂音符 |
| 参数带 | 输出增益、混响、触控力度、移调、力度曲线、钢琴年份 | 实时改变当前钢琴音色参数 | 数值稳定,不改变布局 | 输出增益不是系统音量,参数值受服务端目录约束 |
| 卷帘工具栏 | 按键 P95、NPU P95、欠载、监听丢弃、削波、录音、监听、2/4/8 秒 | 查看会话指标和实时 note edge | 待机指标为空或为 0,运行后更新 | 短音符保留最小可见轨迹,监听和录音只在会话运行时可用 |
| 触控命令栏 | 13/25 键、小/中/大、八度、弯音、延音 | 调整屏幕琴键范围并演奏 | 截图为 25 键与大键盘 | 无缓存时键盘大小默认为“中”;弯音松开自动回中,88 键只属于 MIDI 键盘模式 |
| 底部钢琴 | 触控白键和黑键 | 手指直接发送 note_on/note_off | 待机可查看音域,开始后发声 | 快速松开仍由后端保证 16 ms 门长;失焦、取消触摸或停止会全部停音 |
9.2 实时演奏 / MIDI 键盘

| 区域 | 控件 | 作用 | 正常状态 | 注意事项 |
|---|---|---|---|---|
| 统一会话栏与参数带 | 当前钢琴音色、音频输出、延时档、输出增益、混响、移调和力度曲线 | 与触摸屏模式共享 Piano-DDSP 会话 | 截图为已连接、待机 | 本页没有第二套音色参数,也不加载 DDSP-VST Synth 或 MIDI 文件抽屉 |
| 键盘范围 | 常见键数与八度 | 匹配实体控制器与可视范围 | 键数与已连接键盘一致 | 非全音域键盘可逐八度移动;全音域范围固定为 A0-C8 |
| 实体 MIDI 输入 | 服务端端口下拉框 | 绑定板端枚举的输入端口 | 已连接键盘被选中 | 浏览器 Web MIDI 不是输入来源;运行中不能换端口,断开时释放该来源音符 |
| 卷帘工具栏 | 会话指标、录音、监听、2/4/8 秒 | 观察真实 WebSocket 音符边沿和运行状态 | 短音符仍有可见标记 | 不用轮询替代边沿事件;录音、监听和指标与触摸屏模式共享 |
| 可视键盘 | 只读键位高亮 | 对照实体 MIDI 的当前音符和音域 | 32 键范围为 F2-C5 | 只用于反馈,不在此处提供鼠标或触控演奏 |
9.3 MIDI-DDSP 音频库

| 区域 | 控件 | 作用 | 正常状态 | 注意事项 |
|---|---|---|---|---|
| 主标题 | 音频库/新建渲染 | 切换浏览与创建流程 | 音频库选中 | 两种流程不混在一个长页面 |
| 曲目与版本 | 版本下拉、设为默认 | 一首 MIDI 管理多次渲染 | 版本、音色和 WAV 同步变化 | 缺失文件会标记不可用,不删除历史 |
| 文件卷帘 | 缩放、跟随、全屏 | 查看完整 MIDI 和播放光标 | 仅一个可见卷帘 | 页面不恢复第二个波形动画 |
| 播放区 | 开发板/浏览器、设备、增益 | 选择实际播放目标 | 默认开发板喇叭 | 浏览器播放不改变系统 mixer |
| 右侧曲目列表 | 曲目、版本数、时长 | 快速切换音频库来源 | 选中项有文字和底色 | 选择不可用版本时返回错误 |
9.4 MIDI-DDSP 新建渲染

| 区域 | 控件 | 作用 | 正常状态 | 注意事项 |
|---|---|---|---|---|
| 曲目栏 | MIDI 选择和上传 | 选择现有文件或上传受限格式 | 显示时长、音符、轨道和声部 | 只接受 .mid/.midi 和大小限制 |
| 文件卷帘 | 声部颜色与视图控制 | 检查声部分离结果 | 声部数与表格一致 | 和弦轨需先拆成单音声部 |
| 分配表 | 每声部合成音色 | 修改自动建议 | 每个声部都有有效目录 ID | 浏览器不提交模型文件路径 |
| 右侧设置 | 模型包、方案、随机种子、增益、尾音 | 固定可复现的渲染配置 | OM 已验证、声部已就绪 | 相同配置再次渲染仍创建新版本 |
| 底部操作 | 开始渲染、状态、产物 | 创建异步任务并显示进度 | 成功后可下载 | 运行时保留取消、心跳、预计完成时间和报告 |
9.5 DDSP-VST 音色

| 区域 | 控件 | 作用 | 正常状态 | 注意事项 |
|---|---|---|---|---|
| 顶部链路 | 输入、输出、运行/停止 | 明确真实设备路径 | 实体输入到所选音频输出,运行中 | 运行时不允许静默换设备 |
| 轨迹 Canvas | 音高和响度点 | 观察单音输入与门限 | Canvas 非空,异常为 0 | 环境噪声也可能有音高估计,不等于已输出 |
| 模型区 | 11 种中文音色 | 选择 Control OM | 已选择小提琴音色 | 后端使用稳定的模型 ID |
| 音色参数 | 移调、音高校准、力度、谐波、噪声 | 调整转换控制 | 有边界值即时更新 | 谐波和噪声全关会失去主要声源 |
| 指标 | Feature、Control、总延迟、后端 | 检查 OM 链路和线程状态 | ACL/OM 且异常 0 | 指标不能代替听感评价 |
9.6 DDSP-VST 输入门

| 区域 | 控件 | 作用 | 正常状态 | 注意事项 |
|---|---|---|---|---|
| 校准 | 重新校准 | 采集环境底噪并给出建议门限 | 显示底噪和门限 | 校准时应保持安静,不要讲话或播放声音 |
| 开启门限 | dBFS 滑块 | 达到阈值后允许音频进入 | 底噪低于开启门限 | 太低会被噪声触发,太高会吞轻声 |
| 迟滞 | dB 滑块 | 让关闭阈值低于开启阈值 | 开关不频繁抖动 | 迟滞不是额外增益 |
| 保持/开启/关闭 | 毫秒滑块 | 平滑门状态 | 输入门状态稳定 | 关闭过慢会拖尾,过快会切断音头 |
| 状态条 | 输入门已关闭/打开 | 明确当前是否输出 | 静音环境显示关闭 | 有音高点但门关闭时不会送入合成输出 |
9.7 DDSP-VST 效果

| 区域 | 控件 | 作用 | 正常状态 | 注意事项 |
|---|---|---|---|---|
| 输出增益 | dB 滑块 | 控制转换后 PCM | 默认 -18 dB | 与系统音量分离,避免同时放大两处 |
| 混响空间 | 0 到 1 | 调整房间反馈感 | 默认 0.40 | 更大空间会增加主观尾音 |
| 混响阻尼 | 0 到 1 | 衰减高频反馈 | 默认 0.10 | 不是低通滤波器的精确截止频率 |
| 混响 | 0 到 1 | 控制湿声比例 | 默认 0 | 本实现没有原声 Dry/Wet 直通 |
| 安全状态 | 异常和安全静音 | 防止持续过载 | 异常 0、安全静音关闭 | 触发后应停止并排查输入和增益 |
9.8 设备概览

| 区域 | 正常状态 | 验收要点 |
|---|---|---|
| 开发板状态 | 板端在线、IP 可见、NPU 状态显示 | Health Alarm 是警告,真实推理结果优先 |
| 触控与 MIDI | 输出可选、会话无错误 | 概览只提示准备度,不重复提供跳转按钮 |
| DDSP-VST | 至少一个 capture、错误为 0 | monitor 数量不代表麦克风数量 |
| MIDI-DDSP | bundle 和组件已索引 | 发现资产不等同于已听音验收 |
| 运行环境 | Python、依赖、任务状态可见 | 详细内容放在运行环境页 |
9.9 音频输出与扬声器测试

| 区域 | 控件 | 作用 | 正常状态 | 注意事项 |
|---|---|---|---|---|
| 蓝牙音频 | 刷新、扫描、连接 | 管理板端已有蓝牙能力 | 控制器开启、设备可见 | 不在板端安装缺失的 bluetoothctl |
| 接口状态 | 输出/输入/MIDI | 切换设备清单 | 系统音频输出和直接 ALSA 设备可见 | “检测到”不等于已听见 |
| 声道表 | Left、Right 和电平 | 展示测试声道和状态 | 空闲时电平归零 | 测试会独占输出资源 |
| 输出设置 | 音频输出、系统音量 | 选择输出并显示系统音量 | 已选择有线输出且未静音 | 音箱硬件按键应通过设备事件更新显示 |
| 测试设置 | 左/双/右声道、频率、增益、时长 | 播放受控正弦测试 | 状态从 IDLE 进入运行 | 从低增益开始,避免突然高声压 |
9.10 音频输入与麦克风测试

| 区域 | 控件 | 作用 | 正常状态 | 注意事项 |
|---|---|---|---|---|
| 输入清单 | capture 与 monitor | 区分实体采集和回放监视 | 实体输入标为 CAPTURE | Effect 和输入测试都拒绝 monitor |
| 实时电平 | dBFS 表和峰值 | 观察麦克风输入 | 讲话时电平变化、无溢出 | -96 dBFS 表示空闲或未开始测试 |
| 输入选择 | capture 下拉 | 固定真实麦克风 ID | 实体输入被选中 | 设备断开后不会自动替换 |
| 检测阈值 | dBFS 滑块 | 控制输入测试是否判为有效 | 高于底噪、低于说话峰值 | 与 DDSP-VST 噪声门是两个不同设置 |
| 时长与开始 | 步进器、开始输入测试 | 运行独占采集检查 | IDLE 或完成结果 | 测试期间不能启动 Effect |
9.11 MIDI 设备

| 区域 | 控件 | 作用 | 正常状态 | 注意事项 |
|---|---|---|---|---|
| MIDI 清单 | MIDI 页签 | 枚举服务端输入端口 | 键数与可用状态可见 | 浏览器 Web MIDI 不是板端输入来源 |
| 设备与端口 | 型号、输入端口 | 识别正确设备 | 端口状态正常 | 重新插拔后设备 ID 可能变化,应刷新 |
| MIDI 输入状态 | 全宽设备状态卡 | 显示键数、型号、输入端口和可用状态 | 实体键盘已连接 | 切换到 MIDI 后不显示音频输入输出测试;MIDI 枚举本身不会产生声音 |
| 蓝牙区 | 已配对音频设备 | 展示另一类外设状态 | 与 MIDI 清单分开 | 蓝牙音频不能替代 USB MIDI |
9.12 运行环境

| 区域 | 控件 | 作用 | 正常状态 | 注意事项 |
|---|---|---|---|---|
| 摘要 | Python、依赖、模型、NPU | 一屏判断服务准备度 | 版本号与依赖状态均可见 | 版本应与部署清单和板端环境一致 |
| NPU 警告 | Health Alarm 文本 | 如实展示硬件诊断 | 警告可见 | 不直接粘贴整个终端输出 |
| 运行依赖 | 包名与找到状态 | 定位 Python 启动缺包 | 全部找到 | 板端只允许唯一 requirements 的 pip 安装例外 |
| 模型资产 | 类型、精度、大小 | 检查目录索引结果 | OM 数量和精度可见 | 资产存在仍需清单和真实推理验证 |
| Python 环境 | 解释器与环境名称 | 核对服务使用的板端运行环境 | 环境与依赖合同一致 | 不在运行中隐式切换解释器 |
9.13 布局验收场景
| 使用场景 | 导航与布局策略 | 重点验收 |
|---|---|---|
| 横向触摸显示器 | 完整导航,主控制与可视化并排 | 实际点按、琴键可达、无裁切和滚动冲突 |
| 桌面浏览器 | 完整导航,强调信息对照 | 参数区紧凑但不重叠,Canvas 与表格无横向溢出 |
| 平板或窄窗口 | 控制组换行,次要信息折叠 | 页签语义、触控间距和文本完整性 |
| 移动浏览器 | 采用易触达导航并处理安全区 | 核心命令可达,无文档级横向滚动 |
10. 从零复现实验
10.1 接线与启动检查
- 断电状态连接开发板电源、启动存储、HDMI 屏幕和 USB 触控线。
- 连接音频输出、摄像头或独立麦克风以及 MIDI 键盘;高功耗 USB 设备较多时使用合规的独立供电 Hub。
- 连接网线或 Wi-Fi,启动开发板,确认触摸和桌面正常。
- 在开发板查看 IPv4、USB、ALSA/PulseAudio 和 MIDI;这些是板端只读诊断,不在开发电脑执行。
ip -4 address
lsusb
pactl list short sinks
pactl list short sources
cat /proc/asound/cards
cat /proc/asound/seq/clients在 pactl list short sources 中,麦克风应显示为实体 capture source。名称以 .monitor 结尾的条目是输出回放监视源,不能用于 DDSP-VST 或麦克风输入测试。
10.2 开发电脑准备与本地测试
# 从 Ascend310 仓库根目录执行
cd samples\case3
python -m pip install -r requirements.txt
python -m pytest -q
cd webui
npm ci
npm run test
npm run build
npm run test:e2e各 npm 命令的职责不同:
| 命令 | 作用 | 何时必须执行 |
|---|---|---|
npm ci | 严格按 package-lock.json 安装前端依赖 | 第一次准备环境、删除过 node_modules 或锁文件变化后 |
npm run test | 用 Vitest 检查组件、状态和交互回归 | 前端逻辑、组件或相关样式改变后;纯低风险文字修改可酌情跳过 |
npm run build | TypeScript 检查并生成部署所需 webui/dist | 任何前端源码变化后必须执行 |
npm run test:e2e | 用 Playwright 检查生产页面布局和交互 | 发布前或影响工作流、响应式、Canvas 时 |
开发板不安装 Node 或 npm,也不运行 Vite 生产服务器。它只接收开发电脑生成的 webui/dist/。
10.3 模型准备与转换边界
模型准备应遵循第 6 节给出的两类来源:Piano-DDSP 使用作者训练并验证的 ONNX,MIDI-DDSP 与 DDSP-VST 使用由上游 TFLite 语义重构并完成对照的 ONNX。进入 ATC 之前,应确认来源、输入输出合同和参考结果彼此对应,避免把不同结构或音色的模型混入同一次转换。
ONNX 到 OM 的转换和 PyACL 验证必须在真实 Ascend 开发板上完成,开发电脑不安装或模拟 CANN。各模型族的输入形状、循环状态和精度判据不同,应依据模型与 OM 部署文档与Piano-DDSP 合同执行,并保留足以复核图变换和数值对照的实验记录。
10.4 部署、原子切换和启动
在开发电脑上执行仓库提供的部署脚本:
# 从 Ascend310 仓库根目录执行
cd samples\case3
powershell -ExecutionPolicy Bypass -File tools/deploy_midi_ddsp_webui.ps1部署过程先在暂存位置完成程序、前端资源和模型元数据的一致性检查,再原子切换运行版本。该策略使正在运行的服务不会读取到半同步状态,并将程序升级与实验产生的 MIDI、WAV 和评价记录分离。
在板端已有 conda base 中,仅允许安装本仓库唯一 requirements 并确认 pytest:
cd /home/HwHiAiUser/Documents/case3
/usr/local/miniconda3/bin/python -m pip install -r requirements.txt
/usr/local/miniconda3/bin/python -m pytest -q
/usr/local/miniconda3/bin/python scripts/check_webui_env.py
/usr/local/miniconda3/bin/python scripts/run_webui.py服务启动后检查本机页面和状态接口:
curl -fsS http://127.0.0.1:8765/
curl -fsS http://127.0.0.1:8765/api/v1/status还应核对进程状态、事件连接、生产静态资源和触摸操作。由于服务能够直接控制模型和音频设备,不应将其暴露到不可信网络。
10.5 功能验收顺序
- 设备:确认网络、NPU、Python 环境、实体音频输入输出和 MIDI 键盘均可用。
- 触控演奏:先以低音量测试单音,再测试快速点按、多指、延音、移调和 panic。
- MIDI 键盘:测试力度、重复音、快速音阶、CC64、断开重连和无悬挂音符。
- MIDI-DDSP:选择 MIDI,检查声部分离和分配,渲染 WAV,切换版本并测试开发板/浏览器播放。
- DDSP-VST:停止钢琴会话,选择实体输入与输出,安静校准噪声门,再以独立单音声源测试各类音色。
真实音频验收至少记录推理耗时、队列延迟、总延迟、PCM 非零、削波、capture overflow 和 playback underrun。仅有 HTTP 200 不能证明发声正确。
11. 性能评价与故障排查
11.1 DDSP-VST 板端长稳评价方法
为避免把接口连通性、单模型推理或短时运行误写成实时音频性能,本案例采用长时间双工测试评价 DDSP-VST Effect。评价协议包括:
- 固定实体音频输入、待测 Control OM 和实体音频输出;
- 使用独立单音声源,禁止把扬声器到麦克风的声学反馈当作输入;
- 持续至少
600 s,状态每10 s采样一次,处理帧数持续增长; - 存在非静音输入、非静音输出和有效 F0;
- Feature 与 Control 的合计 p95 小于
20 ms,软件总延迟小于150 ms; - capture overflow、playback underrun、clipped samples 均为
0,且 safety mute 未触发。
其中,p95 表示采样期间耗时分布的第 95 百分位数,时间单位均为毫秒。20 ms 和 150 ms 是本案例的验收阈值,不是未执行测试时的性能结论。
只有同时满足上述条件的报告,才能作为板端性能结论的证据。接口响应、单独的 OM 冒烟测试或页面截图均不能替代双工长稳评价;未通过的实验也应保留原始指标,以免在事后选择性呈现结果。
11.2 常见问题
| 现象 | 优先检查 | 处理原则 |
|---|---|---|
| 页面正常但没有声音 | 会话状态、输出 ID、系统静音、合成增益、PCM 非零、underrun | 先用扬声器测试确认路由,再检查模型和 MIDI;不要同时提高系统音量和合成增益 |
| 环境噪声触发 DDSP-VST | capture 是否正确、底噪、开启门限、迟滞和校准环境 | 安静时重新校准;提高开启门限,保留合理迟滞和保持时间 |
| DDSP-VST 始终没有输出 | 输入门、pw_db、安全静音、Feature/Control 后端 | 确认讲话峰值高于门限且两个后端都是 acl/om |
| 快速 MIDI 声音抖动 | 重复 note edge、声部复用、FIFO、设备 underrun | 不增加前端 hold delay;检查后端 16 ms 最小门、WebSocket 边沿和 MIDI 来源释放 |
| 触摸键抖动或多指缺失 | 浏览器 pointer 事件、触控硬件、多指取消 | 确保 pointerdown/up/cancel 成对,禁用浏览器手势冲突,保留 panic 回收 |
| 悬挂音符或踏板 | note_off、CC64、release_source、断线清理 | 执行 panic;修复事件边界,不能靠高频轮询重建短音符 |
| 开发板没有 IPv4 | 路由器 DHCP、网线、接口状态、地址冲突 | 先恢复网络基础设施;不要修改应用代码来掩盖路由器故障 |
| NPU 显示 Health Alarm | NPU 是否可见、真实 OM 是否能加载和推理、CANN 日志 | 保留警告;真实推理成功时不自动阻断,失败时保存诊断 |
| 模型资产验证失败 | 发布版本、模型清单、暂存文件和同步完整性 | 重新下载损坏的暂存文件;不能跳过校验或修改清单以迎合错误文件 |
| 摄像头或音箱中途断开 | 固定设备 ID、PulseAudio source/sink、线程退出和资源锁 | 立即停止并释放资源;重新枚举后由用户显式选择,禁止静默改路 |
| 蓝牙设备可见但不可播放 | bluetoothctl、PulseAudio A2DP sink、连接 profile | 使用板端已有设施;缺少系统组件时报告,不在部署中安装 |
更多板端日志、ATC/OOM、音频和兼容性案例见测试故障排查记录与音频输出说明。
11.3 测试矩阵
| 层级 | 工具 | 主要覆盖 |
|---|---|---|
| Python 单元与 API | pytest | MIDI 状态边沿、最小门长、资源冲突、索引重建、模型后端边界、监视源拒绝、参数边界和线程清理 |
| React 组件 | Vitest | 加载、不可用、运行、故障、安全静音、触摸事件和音色中文显示 |
| 页面回归 | Playwright | 多类视口、顶层导航、实时演奏双输入模式、Canvas 非空、无溢出、快速触摸和 MIDI-DDSP 单卷帘 |
| 板端模型 | PyACL 与参考 NPZ | 张量合同、1,000/10,000 帧精度、p95/p99 和 NaN/Inf |
| 板端音频 | 真实双工与听音 | PCM 非零、路由、总延迟、overflow、underrun、clipping 和设备断开 |
本地测试不得运行 PyACL、ATC、OM 推理或 npu-smi;这些结果必须来自真实 Ascend 310B。
12. 系统分层、总结与参考资料
12.1 软件分层
| 层次 | 核心职责 | 与相邻层的边界 |
|---|---|---|
| 交互层 | 呈现演奏、渲染、音色转换和设备状态 | 只提交用户意图,不持有模型文件或物理设备路径 |
| 服务与协调层 | 校验请求、管理作业、同步事件并仲裁共享资源 | 不直接实现神经网络或音频合成算法 |
| 神经推理层 | 维护模型输入输出和循环状态,调用 OM 产生控制量 | 不承担高采样率波形生成 |
| 信号处理层 | 完成谐波、噪声、混响、重采样、缓冲与设备输出 | 不决定模型或界面状态 |
| 实验记录层 | 关联输入、配置、音频产物和评价结果 | 不参与实时控制路径 |
这种分层对应不同的时间尺度:交互事件要求及时响应,神经控制按固定帧率递推,音频设备持续消费采样块,离线作业则以完整乐曲为单位。将这些时间尺度分离,是在同一设备上维持实时性与可复现性的基础。
12.2 数据与控制边界
系统的数据流遵循单向责任关系:浏览器表达操作意图,后端确定模型与设备资源,OM 预测低维声学控制量,CPU DSP 将控制量转换为波形,实验记录层保存可复核的输入与结果。状态流则沿相反方向返回:音频线程和模型运行时产生指标,服务端汇总为快照与事件,界面据此更新显示。
这一边界有两个方法论意义。其一,模型推理耗时与端到端音频延迟可以分别测量,避免把缓冲或无线传输延迟归因于 NPU;其二,界面刷新、设备切换和文件索引不会直接改变正在执行的神经状态,从而降低交互层扰动实时链路的风险。
12.3 继续阅读
- Case3 代码总览
- 系统分层设计
- WebUI、操作与 API
- Piano-DDSP 模型与实时合同
- MIDI-DDSP 与 DDSP-VST 对比
- MIDI-DDSP 实时与离线边界
- 模型与 OM 部署
- 音频输出与设备边界
- 测试故障排查
12.4 总结
本案例展示了三类 DDSP 模型在边缘设备上的不同研究路径。Piano-DDSP 由作者基于 PyTorch 实现并在 MAESTRO 数据上训练,通过显式循环状态支持低延迟复音演奏;MIDI-DDSP 与 DDSP-VST 则从 Google 项目的 TFLite 模型出发,在保持层级上下文和流式状态语义的前提下迁移到 ONNX 与 OM。三者共享“神经网络预测控制量、宿主 DSP 生成波形”的基本范式,却分别对应因果复音控制、完整乐曲建模和实时单音转换三种时间问题。
案例的普遍意义不在于把若干模型集中到同一界面,而在于建立清晰的模型来源、状态边界和评价层次。只有将图语义一致性、NPU 推理预算、CPU 音频处理、设备路由与人机交互分别建模并联合验证,才能对实时数字乐器的性能与局限作出可靠判断。
