Community编程与开发github.com

FM3 .syx 预设编辑器

无需 FM3-Edit,即可读取、分析和编辑 Fractal FM3 预设保存文件 (.syx):通过 USB 拉取已存储的预设,列出其网格/模块/通道/场景/调制器及每个模块参数,修改数值,交换模块类型,重命名,重新定位到另一个插槽,对比两个保存文件,并将文件推回插槽。

FM3 .syx 预设编辑器 是什么?

该技能为 Fractal Audio FM3 用户提供了一套完整的命令行工具集,用于直接操作 .syx 预设文件,完全摆脱对 FM3-Edit 图形界面的依赖。其核心脚本 `fm3syx.mjs` 能够通过 USB 通信从 FM3 硬件拉取预设、解析预设内部的模块链(包括模块头、通道参数、场景旁通、网格连接等所有结构)、修改任意参数(支持显示值、原始值或枚举名称)、交换模块类型、管理场景控制器和调制器,甚至支持在两个预设文件之间进行精确的参数级差异对比。同时,它还提供了独立的脚本来处理全局系统设置 (`fm3sys.mjs`)、脚控开关布局 (`fm3fc.mjs` 和 `fcset.mjs`) 以及实时 DSP 负载监控 (`cpu.mjs`)。技能文档中包含了关于文件格式、编解码器实现、参数校准以及安全操作规则(如保护插槽、CPU 负载限制、工作流程)的详尽技术说明,确保用户能安全、精确地在文件层面操控 FM3 的所有可编辑状态。该技能适用于任何支持 Node.js 和 USB 串口的开发环境,无需 FM3-Edit 即可实现高效、可脚本化的预设管理。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/TheCoolHippo/fm3-syx-editor/tree/HEAD

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

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 parseGen3LiveMeters output_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 + i2630 + 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 + i2738 + i
标签模式 (Scene: 0 名称, 1 编号, 2 自定义; Effect: 0 长名称, 1 短名称, 2 长名称 + 通道, 3 短名称 + 通道, 4 自定义)1874 + i2846 + i
参数, 6 个字 (preset/scene/layout 编号 基于 1;Effect = [block, channel]; Inc/Dec = [step, wrap, lower, upper], step 65535 = -1)1982 + 6i2954 + 6i
自定义标签, 10 个字符 + 03623 + 11i4811 + 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:

字段点击按住
类别j216 + j
功能24 + j240 + j
标签模式48 + j264 + j
参数 (6)72 + 6j288 + 6j
自定义文本 (11)432 + 11j696 + 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

相关技能