FM3 .syx 编辑器
一个脚本完成所有操作:scripts/fm3syx.mjs。它复用了 mcp-midi-control v0.8.0 附带的编解码器,因此请使用该安装目录下的 node 来运行:
N="$LOCALAPPDATA/mcp-midi-control/mcp-midi-control-v0.8.0/node.exe"
"$N" scripts/fm3syx.mjs <command> ...
命令
| 命令 | 说明 |
|---|---|
pull <slot> <out.syx> | 通过 COM7 从 FM3 读取一个已存储的预设(无需 FM3-Edit) |
info <file> | 插槽、名称、场景、网格行数、每通道模块类型、场景通道/旁通、调制器 |
params <file> <Block[#n]> [ch] | 某个模块的每一个参数:名称、原始字、显示值 |
get <file> <Block> <ch> <PARAM> | 获取单个值 |
set <in> <out> <Block> <ch> <PARAM> <val> ... | 值 = FM3 显示的显示值(40 Hz, -12 dB, 3.5)、选项名称(post, "Analog Stereo")或 raw:N |
scenename <in> <out> <1-8> <name> | 场景名称(31 个字符) |
cell <in> <out> <row> <col> [Block|Shunt|empty] [from=1,2|none] | 网格单元格 + 哪些行馈入其中(连线)。行列索引从 1 开始,与 FM3-Edit 一致 |
add <in> <out> <row> <col> <Block[#n]> [from=1,2] | 使用 FM3 自身的默认值添加新模块(defaults/<eid>.bin) |
midi <in> <out> <scene> [pc:ch:val|cc:ch:num:val|-]... | 某个场景的 MIDI 行;使用 add ... MIDI 添加该模块(eid 190,无网格连线)。已验证:重建的预设与 FM3-Edit 保存的文件字节完全一致,并在场景切换和预设加载时进行了测试 |
midishow <file> | 所有场景的 MIDI 行 |
remove <in> <out> <Block[#n]> | 删除一个模块(网格单元格 + 记录) |
scenectl <in> <out> <1-4> <%> [x8] | 每场景的场景控制器 1-4 值(一个值 = 所有 8 个场景) |
mods <file> [all] / mod <in> <out> <1-32> FIELD=val ... | 32 个调制器:CTRLID(源名称)、EFFECTID(模块)、PARAM(参数名)、MIN/MAX/STARTPT/MIDPT/ENDPT(N% 或原始值)、SLOPE、DAMPING、AUTOENGAGE、PCRESET、SCALE、OFFSET… |
type <in> <out> <Block> <ch> <name> / types <Block> | 交换 / 列出类型(Amp, Reverb, Drive, Delay, Chorus, Comp, Filter, Flanger, Phaser, Wah, Tremolo) |
rename <in> <out> <name> | 预设名称 |
slot <in> <out> <N> | 将文件重定向到插槽 N(头部 + 校验和) |
diff <a> <b> | 按名称显示每个参数的差异 |
learn <file> <Block> <ch> <PARAM> <display> | 向 calib.json 添加一个原始值→显示值的校准点 |
node cpu.mjs [preset] | 已加载预设的实时 DSP 负载,与 FM3-Edit 显示一致(如果提供了预设,则先切换)。达到 80% 或以上时退出码为 2 |
push <file> --yes | 将文件存储到其头部指定的插槽中 |
PARAM = 目录名称 (PITCH_FEEDBACK1, 或仅 FEEDBACK1) 或 FM3-Edit 标签 (Feedback 1)。
Block#2 选取同名的第二个模块 (Return#2)。
规则(绝不违反)
- 受保护插槽:在
scripts/fm3-local.json({"protected":[383]}, 已加入 gitignore) 或FM3_PROTECTED环境变量中列出它们;push和harvest.mjs会拒绝操作它们。 push= 在设备上保存:每次都必须先询问用户,并告知是哪个插槽。 首先对目标插槽运行pull,以便备份即将被覆盖的内容。- FM3 端口(COM7,可由 FM3_PORT 覆盖)是独占的:请先关闭 FM3-Edit 或使用设置 > 暂停通信;任何 mcp-midi-control 服务器都不可占用该端口。
- 切勿探测 FC 模块(效果 id 199)。
- DSP 负载:Fractal 规定永远不可超过 80%。 每次执行
add+push后,加载该预设并运行cpu.mjs; 达到 80% 或以上时,在保留当前修改前,请先删除/简化部分模块。逐个添加重型模块(Amp, Cab, Pitch, Reverb)。 - 在副本上操作(
set in out):保持拉取的原始文件不变。
文件构建方式(验证于 2026-11-03)
.syx= 0x77 头部(字节 6-7 为 14 位表示的插槽号,字节 11 为 XOR 校验和)+ 8 个 0x78 块(压缩的补丁数据,带 CRC 校验)+ 0x79 XOR 尾部。每个 FM3 预设 24,680 字节。 编解码器在每次写入时重新压缩并重新计算 CRC 和尾部。- 解压缩后的主体:模块链;每个模块有一个头部(23 个字:场景通道、场景旁通、…)然后是一个每通道参数数组:
rows个通道 ×cols个字。 - 字索引 = FM3 paramId − 6(paramId 来自
fractal-midi/dist/gen3/fm3,从 FM3-Edit 中挖掘而得)。已在 Amp (drive/bass/mid/treble/master/presence/depth)、Pitch (shift/pan/feedback/mix/level/splice) 和 Delay (time) 上验证。ParamIds 0-5 位于头部字 17-22 中(公式相同)。 - 值是原始 uint16 0..65534(与实时连线相同),除了存储为纯整数的整数参数:类型/型号、枚举、节奏分割、半音(有符号:12 = +12, 0 = 0)。
- 在 FM3-Edit(2026-11-03)中校验过的刻度,存储在
calib.json中,与规范脚本相邻:- 线性:百分比、双极性百分比、旋钮 0-10、Pitch 反馈 0..100%、Pitch 失谐 −50..+50 分、电平 −80..+20 dB (52427 = 0 dB)、延时 FEED −100..+100%。
- 对数:Hz = min·(max/min)^(raw/65534) 使用目录的 displayMin/Max(Pitch 高切 200..20000 Hz, 42631 = 4000 Hz)。对于单位
hz,脚本会自动执行此操作。 - 点:Delay TIME 2044 = 500 毫秒;Reverb TIME 2034 = 3.20 秒, 5085 = 7.85 秒。
- 节奏枚举 (DTEMPO/TEMPO): 0 None, 11 1/8, 12 1/8 dot, 13 1/4 trip, 14 1/4, 15 1/4 dot。
- Pitch TYPE (paramId 0): 8 = Crystal Echoes。Delay type = DELAY_MODEL (非 DELAY_TYPE):13 = Ambient Stereo, 2 = Analog Mono, 24 = Wandering Delays (
types Delay)。 - Cab → DynaCab:
CABINET_MODE raw:1+DYNACAB_TYPE1/2 raw:<id>(types DynaCab;FM3-Edit 显示 id+1, 29 = "30: 2x12 Texas Star"),AUTO_ALIGN raw:1。 未知的刻度?设置一个原始猜测值,推送,读取 FM3-Edit,添加校准点 (learn)。
- 模块头部:字 −1 = 场景-1 通道, 字 0..6 = 场景 2-8 通道 (0=A..3=D), 字 7..14 = 场景 1-8 旁通 (1 = 已旁通);
scene命令用于编辑它们。 - FM3 将推送的转储直接存储到其头部指定的插槽中(无需额外保存)。
覆盖范围(2026-11-03)
- 控制模块 = 整个控制器菜单(速度、LFO 1/2、ADSR 1/2、音序器、包络、Manual 1-5、场景控制器):家族 CONTROLLERS, eid 2, 130 个参数 × 4 个通道,位于网格之后(主体 0x1c4)。像任何模块一样编辑它:
set f Control A TEMPO raw:120(速度 = 纯 BPM),params f Control A。编解码器的场景控制器偏移量是错误的(偏移 9 个字);请使用scenectl。 - 在 FM3-Edit 中对 FM3 进行的验证:场景名称、网格单元格/连线、
add/remove、调制器 (mod 2 CTRLID="LFO 1A" EFFECTID=Delay PARAM=MIX MIN=10% MAX=40%使延迟混音值变化),场景控制器,速度。 - 实时输出电平表(子 0x2E
parseGen3LiveMetersoutput_left/right)在没有信号时返回随机值:不可用。场景响度必须通过 USB 重录测量来代替。 - scales.json: 针对 FM3 自身显示文本校准过的 34 个模块家族的 1,390 个参数(
calibrate.mjs实时扫描每个参数并读取回显;calfix.mjs第二轮)。连续参数采用线性/对数拟合或插值;枚举双向映射名称。calib.json(已人工校验)优先级更高。 未覆盖:无文本的参数(部分 MIX/图形参数,73 个条目为空),Plex(FM3 拒绝放置)。 - 主体中的每条记录 = eid 字 + 5 个字 + 23 字头部 + cols×rows 个字。顺序:32 条 MOD 记录 (eid 3..34 = 调制器 1..32),然后是模块,然后是 eid 201 和 eid 200(每预设脚控开关数据,1525 个字:只读知识,切勿实时探测)。编解码器按大小命名模块,部分识别错误(Input/Output 显示为 Vol/Pan/PEQ);fm3syx 会重新标记它们。
- 仅放置在网格中的模块,其所有参数均为 0(电平 −80 dB):务必使用
add,它会插入从 FM3 采集的默认记录(harvest.mjs <scratchSlot> <restore.syx> [eids],每批一个模块,使用BATCH=1:一次放置多个重型模块曾导致 FM3 死机一次)。 - 从未保存的插槽(
<EMPTY>)使用另一种容器,编解码器无法解码:请在存储一次后拉取。
无需 FM3-Edit 即可工作
此处所有操作都直接通过 USB 与 FM3 通信(默认 COM7,如果端口改变,请设置 FM3_PORT):pull, push, switch.mjs, cpu.mjs, fm3ctl.mjs(场景选择、乐句循环按钮)、levels.py(通过 USB 录制测量场景响度)。
不需要 FM3-Edit。无需它即可验证更改:push → 再次 pull → cmp/diff(0 字节 = FM3 完全按发送内容存储)→ switch.mjs <other> 然后 switch.mjs <slot> 加载它 → cpu.mjs (< 80 %)。FM3-Edit 仅在构建本技能时用于目测结果。
全局(设置)设置 — fm3sys.mjs + sendsys.mjs(验证于 2026-11-03)
全局设置不在预设中。它们作为一个完整的系统库(197 kB, 66 帧)传输。使用 node pullsystem.mjs <out.syx> 读取(关闭 FM3-Edit,只读,请求函数 0x43,与 Fractal-Bot 发送的一致,由 USBPcap 于 2026-11-06 捕获;输出与 Fractal-Bot 的 FM3-<date>-system+gb+fc.syx 字节完全一致)。
该库包含两份副本(字 0.. 和 32768..,各有其自己的头部和 CRC)。FM3 写入较旧的副本,并在副本 + 14874 处递增保存计数器,因此最新副本会交替。fm3sys.mjs 和 fm3fc.mjs 将每次编辑写入两个副本。
- 格式:fn 0x51 头部,64 个 fn 0x52 块(2 字节索引 + 1024 个字,每字 3 个 septet),fn 0x53 尾部(所有字的 XOR)。未压缩。字 0 = 0x1008, 字 1 = 0xAA55, 字 2 = CRC-CCITT (多项式 0x1021, 初始值 0xAA55) 作用于字节 8 .. 8 + 字 3, 字 3 = 数据长度 (29760)。 全局目录参数 p = 字 4 + p (IN1_SOURCE 61, MIDI_CHAN 68 (0-based), LINEFREQ 112, DISPLAY_OFFSET 72…)。
fm3sys.mjs get <file> IN1_SOURCE/set <in> <out> IN1_SOURCE 1/diff a b/check file(修复 CRC、尾部和帧校验和;一个未经修改的往返传输是字节完全一致的)。- MIDI/Remote 表格(通过写入、读回和 MC8 测试验证于 2026-11-05):Bypass 字 138 + 模块 id, Channel 字 394 + 模块 id, External n 字 1305 + n; 128 = none。使用
fm3sys.mjs setword <in> <out> <word> <raw>...编辑。调制器源 External 6..16 = ids 19..29。 sendsys.mjs <file> --yes写入整个库(FM3 对每帧回复 fn 0x64 代码 0)。测试:Display Offset 通过文件从 1 改为 0,然后新的备份与发送的文件完全匹配。- 规则:始终从全新的备份开始(它包含所有全局设置 + FC 布局);在发送前询问用户;保留原始备份以便恢复。切勿探测其他请求码。
脚控开关布局 — fm3fc.mjs(存储的文件) + fcset.mjs(实时设置)(验证于 2026-11-08)
8 个布局 + 主布局位于系统库中,因此无需探测 FC 模块。 开关索引 i = layout × 12 + view × 3 + switch(基于 0;layout 8 = 主布局)。在一份副本中的偏移量:
| 字段 | 点击 | 按住 |
|---|---|---|
| 类别 (0 未分配, 1 库, 2 预设, 3 场景, 4 效果, 5 工具, 6 布局, 7 控制开关, 8 乐句循环, 9 每预设, 10 视图, 11 歌单, 12 歌曲, 13 歌曲段落) | 1658 + i | 2630 + i |
| 功能 (FM3-Edit 菜单顺序: Utility 0 Tuner 1 Tap Tempo 2 Amp Level+Save 3 Reveal Hold 4 Scene Level+Save; Effect 0 Bypass 1 Chan Select 2 Chan Toggle 3 Chan Inc/Dec) | 1766 + i | 2738 + i |
| 标签模式 (Scene: 0 名称, 1 编号, 2 自定义; Effect: 0 长名称, 1 短名称, 2 长名称 + 通道, 3 短名称 + 通道, 4 自定义) | 1874 + i | 2846 + i |
| 参数, 6 个字 (preset/scene/layout 编号 基于 1;Effect = [block, channel]; Inc/Dec = [step, wrap, lower, upper], step 65535 = -1) | 1982 + 6i | 2954 + 6i |
| 自定义标签, 10 个字符 + 0 | 3623 + 11i | 4811 + 11i |
| 布局名称位于 1370 + 32 × layout;颜色位于 6000 + i (0 默认, 1 红色, 2 橙色…)。 | ||
效果模块编号遵循一个包含隐藏条目的字母顺序内部列表;表格在 fm3fc.mjs 中(已验证:Amp 1 0, Cab 1 1, Chorus 1 2, Comp 1 4, Delay 1 7, Drive 1 9, Drive 2 10, Enhance 1 11, Filter 1 17, Flanger 1 21, Gate 1 25, GEQ 1 27, In 2 30, MultDly 1 38, Phaser 1 45, Pitch 1 47, Plex 1 48, Reverb 1 51, Rotary 1 53, TremPan 1 57, Vol/Pan 1 59, Vol/Pan 2 60, Wah 1 61)。 |
fm3fc.mjs show <system.syx> [layout]列出每个开关;set <in> <out> <layout> <view> <switch> tap=Effect param="Wah 1" ...编辑两个副本。使用sendsys.mjs发送的文件会被存储,但正在运行的 FM3 将其布局保存在 RAM 中,直到下次断电(此前的任何系统保存都会覆盖此编辑)。- 实时,无需重启: FM3-Edit 使用 fn 0x01 sub 0x09 编辑模块 199 的一个参数:
F0 00 01 74 11 01 09 00 47 01 <pid lo> <pid hi> <float32 编码为 5 个 septet,LSB 在前> 00 00 00 00 <xor> F7。 参数 id = 存储的偏移量 − 1658 (点击类别 i, 点击功能 108 + i, 点击参数 324 + 6i + k, 按住类别 972 + i, 点击标签模式 216 + i);从文本区域看,id 偏移了 +276:点击自定义文本 2241 + 11i (每个字符一个参数,值 = 字符编码,结束后为 0), 颜色 4618 + i。fcset.mjs text <layout> <view> <switch> <TEXT> [mode=N]实时重命名一个开关。fcset.mjs <pid> <value> ...逐字节重建捕获的消息;FM3 立即应用更改并自行保存。通过 USBPcap 从 FM3-Edit 捕获。 - 仅设置已知的参数 id。切勿向模块 199 发送 GET 命令(sub 0x1a/0x1b),用于您未见 FM3-Edit 使用过的 id:读取未知的 FC 参数曾冻结过 FM3。
每预设开关 — fm3syx.mjs pp/ppset(文件操作) + fcset.mjs pp(实时操作)(验证于 2026-11-08)
它们位于预设本身中:记录 eid 200, 数据 = 记录起始 + 23 个字。由此开始的偏移量(j = PP 编号 − 1)也是模块 200 上的实时参数 id:
| 字段 | 点击 | 按住 |
|---|---|---|
| 类别 | j | 216 + j |
| 功能 | 24 + j | 240 + j |
| 标签模式 | 48 + j | 264 + j |
| 参数 (6) | 72 + 6j | 288 + 6j |
| 自定义文本 (11) | 432 + 11j | 696 + 11j |
布局覆盖表位于 960 + i (i = layout × 12 + view × 3 + switch, 值 = PP − 1, 65535 = none);颜色 1069 + j。
代码与布局相同(表格在 fcmap.mjs 中)。
fm3syx.mjs pp <file>列出它们;ppset <in> <out> <PP> key=value ...或ppset ... override L V S PP|none编辑一个文件 (一个脚本化的编辑逐字节复现了 FM3-Edit 的文件)。- `fcset.mjs p