Add a durable, committed source of truth for external MIDI synth control:
- synth-midi-cc.json: verified CC maps + provenance/sources (8 devices researched)
- schemas/midi_device.schema.json + schemas/midi_devices/*.json: 6 CC-controllable
device templates (Moog Sub 37/Sub Phatty, Creamware Pro-12 ASB, Elektron Analog
Keys, ASM Hydrasynth, Roland JD-800), params keyed {id, cc, label, min, max,
default, group}.
- codegen/generate-midi-devices.ts (isolated from the mode golden test) emits both
nisps/midi/generated/midi_devices.hpp (no-heap constexpr, firmware+WASM) and
manifold/src/midi-devices/generated/ (typed catalogue for the browser).
- codegen/seed-midi-devices.ts: reproducible seed from the research artifact.
Lets a performer pick a device and address its parameters by name (not CC number)
on both the firmware and the Manifold browser engine.
60 lines
3 KiB
JSON
60 lines
3 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": "https://memlnaut/schemas/midi_device.schema.json",
|
|
"title": "MEMLNaut MIDI Device Template Schema",
|
|
"description": "Describes one external MIDI synth/device as a template of named, CC-addressable parameters. Used by NISPS to let a performer pick a device, see its parameters by name, and select which ones the ML drives via MIDI CC. Codegen (codegen/generate-midi-devices.ts) consumes these to emit a no-heap C++ header (nisps/midi/generated/midi_devices.hpp) and a typed TS module (manifold/src/midi-devices/generated/). Provenance + sources for the CC numbers live in synth-midi-cc.json.",
|
|
"type": "object",
|
|
"required": ["device_id", "name", "manufacturer", "midi", "params"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"$schema": { "type": "string" },
|
|
"_note": { "type": "string", "description": "Free-text author note." },
|
|
"device_id": {
|
|
"type": "string",
|
|
"pattern": "^[a-z][a-z0-9_]*$",
|
|
"description": "snake_case unique identifier for the device."
|
|
},
|
|
"name": { "type": "string", "description": "Human-readable device name shown in the picker." },
|
|
"manufacturer": { "type": "string" },
|
|
"year": { "type": "integer" },
|
|
"midi": {
|
|
"type": "object",
|
|
"required": ["default_channel", "value_range"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"default_channel": { "type": "integer", "minimum": 1, "maximum": 16, "description": "Default MIDI channel (1-16)." },
|
|
"value_range": {
|
|
"type": "array",
|
|
"items": { "type": "integer", "minimum": 0, "maximum": 127 },
|
|
"minItems": 2,
|
|
"maxItems": 2,
|
|
"description": "[min, max] CC value range; almost always [0, 127]."
|
|
},
|
|
"notes": { "type": "string", "description": "How to enable CC on this device, channel quirks, etc." }
|
|
}
|
|
},
|
|
"params": {
|
|
"type": "array",
|
|
"minItems": 1,
|
|
"items": {
|
|
"type": "object",
|
|
"required": ["id", "cc", "label", "min", "max", "default", "group"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"id": {
|
|
"type": "string",
|
|
"pattern": "^[a-z][a-z0-9_]*$",
|
|
"description": "snake_case unique-within-device identifier, derived from the label."
|
|
},
|
|
"cc": { "type": "integer", "minimum": 0, "maximum": 127, "description": "MIDI Control Change number." },
|
|
"label": { "type": "string", "description": "Human-readable parameter name shown in the UI." },
|
|
"min": { "type": "integer", "minimum": 0, "maximum": 127 },
|
|
"max": { "type": "integer", "minimum": 0, "maximum": 127 },
|
|
"default": { "type": "integer", "minimum": 0, "maximum": 127, "description": "Value sent when the param is fixed (not ML-driven)." },
|
|
"group": { "type": "string", "description": "Coarse section for UI grouping (osc, filter, env, lfo, mod, fx, arp, mix, global)." },
|
|
"notes": { "type": "string" }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|