nospi/dm3-tools
GitHub: nospi/dm3-tools
解析和写入 Yamaha DM3 数字调音台文件格式的命令行工具,支持场景、预设和演出文件的读写、比对与批量编辑。
Stars: 0 | Forks: 0
# dm3-tools
用于解析和写入 **Yamaha DM3** 数字调音台文件(包括场景、预设和完整的演出文件)的 CLI 工具,同时适用于控制台的 USB 保存/加载以及 DM3 Editor。已完成端到端验证:由 `dm3 set` 写入的文件可以在 Yamaha 的 DM3 Editor 中完美加载。
## 文件类型
| 扩展名 | 内容 | 状态 |
|-----------|----------|--------|
| `.dm3s` | 单个场景 (SceneInfo + Mixing + Processing + FX) | 读/写 |
| `.dm3p` | 单个库预设 (范围限定子树:CH/MX/ST/FXBS) | 读/写 |
| `.dm3f` | 所有调音台设置(“演出文件”,USB ↔ 控制台 ↔ 编辑器) | 读/写 |
## 用法
```
dm3 info scene.dm3s # header + field summary
dm3 dump scene.dm3s -f Mixing # decode to JSON
dm3 get scene.dm3s SceneInfo.Info.Title
dm3 set scene.dm3s "SceneInfo.Info.Title=FSC Town Hall" -o out.dm3s
dm3 set scene.dm3s "Mixing.InputChannel[0].Label.Name=Kick"
dm3 diff before.dm3s after.dm3s # what changed between saves
# .dm3f show files: --entry addresses embedded files
# (默认 entry 是 console 的当前 memory)
dm3 info show.dm3f # list embedded files
dm3 set show.dm3f "Mixing.InputChannel[0].Label.Name=KICK IN" -o out.dm3f
dm3 dump show.dm3f -e 88112F6B….dm3s # decode a stored scene
dm3 extract show.dm3f -d out/ # unpack all embedded files
```
仅您设置的值所占用的字节会被修改;文件中的其他所有内容都将按字节原样保留。
## 工作原理
DM3 文件是 `#YAMAHA MBDF` 容器:包含一个头部 + UUID,随后是 `#MMS FIELD` 部分。每个字段都带有一个 `MMSXLIT` schema 块(函数名 + 锁定 schema 版本的摘要)、一个用于描述参数树的 `COL0`(集合)和 `PR`(参数)记录表,以及一个完全按照树声明进行布局的紧凑型小端序数据块。
权威的 schema 以 Yamaha 自己的 DM3 Editor 随附的 `Descriptor/mms_*.xml` 形式发布(包含名称、C 类型、范围、默认值、结构体大小)。`dm3tools` 会解析这些 XML 文件,并由它们驱动所有的解码/编码过程 —— 无需进行逐个参数的逆向工程。已通过往返测试验证了编辑器附带的全部 278 个出厂预设/场景(845/845 个字段)。
### 获取 descriptors 与 fixtures
Yamaha 的 descriptor XML 文件和出厂预设受版权保护,因此未提交至此仓库。请从 Yamaha 公开的 DM3 Editor 安装程序中获取它们:
```
scripts/fetch_fixtures.sh # downloads editor, extracts via msiextract
```
或者让 CLI 指向已安装的 DM3 Editor:
```
export DM3_DESCRIPTOR_DIR="/path/to/Yamaha/DM3/Descriptor"
```
## 在 Linux 上运行 DM3 Editor
Windows 版本的编辑器可以在 Wine 下运行(已测试 wine 6.0.3,prefix 设置为 win10)。启动时必须将其安装目录设置为工作目录,否则会在启动时崩溃(因为它会加载相对于 cwd 的 `Descriptor/mms_*.xml`):
```
scripts/dm3-editor.sh
```
### .dm3f 演出文件
`.dm3f` 是一个类型为 `ProjectFile` 的 MBDF 文件:包含一个 ProjectInfo 字段,随后是一系列 `#FILE` 条目 —— 槽位名(`Current`、`Scene:A`、`SceneList`)、大端序的大小、文件名,以及一个可解压为另一个 MBDF 文件的 **zlib** 负载(即控制台的当前内存、每个已存储的场景、场景列表索引,以及 `.old` 日志副本)。具体的字节布局请参见 `src/dm3tools/dm3f.py`。
## 先前技术与鸣谢
[netik/decode_dm3](https://github.com/netik/decode_dm3) (Apache-2.0) 首次公开探索了这些格式,并正确识别了 MBDF 容器标记。dm3-tools 与其没有共享任何代码,但正是他们的工作让人明确了这些格式是易于处理的。他们留下的悬而未决的问题 —— `.dm3f` 内嵌文件的压缩方式 —— 最终被证实为普通的 zlib。
## 法律声明
dm3-tools 是一个独立的互操作性项目,不附属于 Yamaha,也未获得 Yamaha 的认可。它是通过观察 DM3 控制台和 DM3 Editor 生成的文件而构建的;未对任何 Yamaha 软件进行反编译或反汇编,本仓库也不分发任何受 Yamaha 版权保护的材料(descriptor XML、出厂预设、二进制文件)—— `scripts/fetch_fixtures.sh` 会从 Yamaha 自己的公开安装程序中获取这些内容。Yamaha、DM3 及相关标志归 Yamaha Corporation 所有。
## 注意事项 / 已知问题
- 物理控制台的 USB 加载测试待完成(编辑器加载测试已通过)。
- 一个出厂文件(`PresetDante` 类型,Status/DNTP 字段)在解码时比其 descriptor 少了 148 个字节 —— 疑似是不同的 schema 版本所致。暂且搁置。
- 出厂文件中的字符串字段在 NUL 终止符之后包含垃圾数据(Yamaha 没有将缓冲区清零)。这在语义上无关紧要;我们会为未修改的字段保留原样,并对我们写入的字段进行零填充。
- 重写后的 `.dm3f` 文件比编辑器写入的文件稍大(我们的 zlib 压缩级别 1 不如 Yamaha 的紧凑);这并无大碍,因为容器中已明确指定了大小。
## 开发
```
pip install -e .
PYTHONPATH=src python3 -m dm3tools.cli ... # without installing
python3 scripts/verify_layout.py # structural invariants sweep
```
标签:Homebrew安装, Yamaha DM3, 二进制数据处理, 数字调音台, 文件解析, 文档结构分析, 逆向工具