From 9a9b66c5ee513fc504b16d16ac838ca2ce9dc12c Mon Sep 17 00:00:00 2001 From: monkey-w1n5t0n Date: Sun, 28 Jun 2026 20:03:17 +0200 Subject: [PATCH] feat(midi-devices): canonical external-synth CC templates + dual codegen 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. --- MAP.md | 8 + codegen/generate-midi-devices.ts | 324 +++++ codegen/seed-midi-devices.ts | 121 ++ .../src/midi-devices/generated/devices.ts | 539 +++++++++ manifold/src/midi-devices/generated/index.ts | 4 + manifold/src/midi-devices/generated/types.ts | 23 + nisps/midi/generated/midi_devices.hpp | 572 +++++++++ schemas/midi_device.schema.json | 60 + schemas/midi_devices/asm_hydrasynth.json | 1069 +++++++++++++++++ schemas/midi_devices/creamware_pro12_asb.json | 736 ++++++++++++ .../midi_devices/elektron_analog_keys.json | 781 ++++++++++++ schemas/midi_devices/moog_sub37.json | 745 ++++++++++++ schemas/midi_devices/moog_sub_phatty.json | 655 ++++++++++ schemas/midi_devices/roland_jd800.json | 133 ++ synth-midi-cc.json | 617 ++++++++++ 15 files changed, 6387 insertions(+) create mode 100644 codegen/generate-midi-devices.ts create mode 100644 codegen/seed-midi-devices.ts create mode 100644 manifold/src/midi-devices/generated/devices.ts create mode 100644 manifold/src/midi-devices/generated/index.ts create mode 100644 manifold/src/midi-devices/generated/types.ts create mode 100644 nisps/midi/generated/midi_devices.hpp create mode 100644 schemas/midi_device.schema.json create mode 100644 schemas/midi_devices/asm_hydrasynth.json create mode 100644 schemas/midi_devices/creamware_pro12_asb.json create mode 100644 schemas/midi_devices/elektron_analog_keys.json create mode 100644 schemas/midi_devices/moog_sub37.json create mode 100644 schemas/midi_devices/moog_sub_phatty.json create mode 100644 schemas/midi_devices/roland_jd800.json create mode 100644 synth-midi-cc.json diff --git a/MAP.md b/MAP.md index 73f5a65..ef70ad7 100644 --- a/MAP.md +++ b/MAP.md @@ -11,6 +11,7 @@ MEMLNaut-NISPS — Neural Interactive Shaping of Parameter Spaces. One C++20 cod - `nisps/engines/` — eight audio engines, each satisfying `AudioEngine`: `paf_synth.hpp`, `channel_strip.hpp`, `xiasri.hpp`, `verb_fx.hpp`, `memlcelium.hpp`, `breakor.hpp` (sequencer, NoOp audio), `elysiamorf.hpp` (sequencer, NoOp audio), `analysis.hpp` (input-side spectral features). Plus `base.hpp` (`NoOpEngine`, engine_id "thru"). - `nisps/modes/` — eight platform-agnostic modes binding `{ML config, engine, voice space lambdas, abstract I/O channels}`. Files: `paf_synth.hpp`, `channel_strip.hpp`, `xiasri.hpp`, `verb_fx.hpp`, `memlcelium.hpp`, `breakor.hpp`, `elysiamorf.hpp`, `sound_analysis_midi.hpp`. `base.hpp` provides a CRTP scaffold eliminating the duplication that previously plagued firmware modes. `voice_space.hpp` holds engine-side voice space dispatch helpers. `generated/` contains codegen output (do not edit by hand). - `nisps/wasm/bindings.cpp` — flat C API exported to WASM (Emscripten target only). +- `nisps/midi/generated/midi_devices.hpp` — codegen output: no-heap `constexpr` external-MIDI-synth templates (`nisps::midi::generated`; `MidiParam`/`MidiDevice` + `kMidiDevices` registry). Source = `schemas/midi_devices/`; do not edit by hand. - `nisps/CMakeLists.txt` + `nisps/build/` — host-target builds + ctest. ### `firmware/` — Arduino sketch + hardware glue @@ -62,6 +63,9 @@ anchor + locked decisions) and the `docs/redesign/*-spec.md` set. `OutputsBackendConfig.tsx` (per-backend specialised Outputs panel), `BackendAdvanced.tsx`. - `manifold/src/backends/` — `OutputBackend` adapter + `BackendManager` (spine consumer); `midi-backend.ts` (WebMIDI), `osc-backend.ts`+`osc-client.ts` (OSC-over-WS), `presets.ts` (named presets), `manager.ts`. +- `manifold/src/midi-devices/` — external-synth device templates. `generated/` is codegen output from + `schemas/midi_devices/` (`MIDI_DEVICES` catalogue + `MIDI_DEVICES_BY_ID`, params by name+CC). The MIDI Outputs + config (`dock/OutputsBackendConfig.tsx`) reads it for the device picker + param-select that fills the CC table. - `manifold/src/feedback/` — `controller.ts` (Explore-and-place scratchpad + geometric-dislike + solo, TS prototype), `rng.ts` (seeded). - `manifold/src/settings/` — `settings-store.ts` (monochrome icons, input-map shape, corner radius). @@ -80,9 +84,13 @@ the "BUILD DELTAS" block at the top of `vcv/SPEC.md`). `src/MEMLNaut.cpp` (modul - `schemas/schema.json` — Draft 2020-12 meta-schema validating mode files. - `schemas/modes/.json` (×8) — each mode's params, ranges, defaults, curves, voice spaces, ML config. - `schemas/modes/params_notes.md` — provenance notes and judgement calls per mode. +- `schemas/midi_device.schema.json` — Draft 2020-12 meta-schema for external-MIDI-synth templates. +- `schemas/midi_devices/.json` (×6) — CC-controllable external synths (Moog Sub 37 / Sub Phatty, Creamware Pro-12 ASB, Elektron Analog Keys, ASM Hydrasynth, Roland JD-800). Each param: `{id, cc, label, min, max, default, group}`. Canonical source for both firmware + browser device pickers. Verified-CC provenance + sources live in `synth-midi-cc.json` (repo root). ### `codegen/` — schema → C++/TS code - `codegen/generate.ts` — Bun script: validates schemas via ajv, emits per-mode `nisps/modes/generated/_schema.hpp` (`constexpr`, `nisps::modes::generated`) and `playground/src/modes/generated/_schema.ts`. Idempotent. +- `codegen/generate-midi-devices.ts` — separate Bun script (isolated from the mode golden test): validates `schemas/midi_devices/` via ajv, emits `nisps/midi/generated/midi_devices.hpp` (no-heap `constexpr`) and `manifold/src/midi-devices/generated/{types,devices,index}.ts`. Idempotent. +- `codegen/seed-midi-devices.ts` — one-time/idempotent seed deriving `schemas/midi_devices/*.json` from the `synth-midi-cc.json` research artifact (slugifies labels → ids, heuristic groups). - `codegen/templates/`, `codegen/tests/golden/` — reference templates + golden snapshot for paf_synth. ### `tests/cpp/` — host C++ tests diff --git a/codegen/generate-midi-devices.ts b/codegen/generate-midi-devices.ts new file mode 100644 index 0000000..a404a19 --- /dev/null +++ b/codegen/generate-midi-devices.ts @@ -0,0 +1,324 @@ +#!/usr/bin/env bun +/** + * MEMLNaut MIDI device-template codegen. + * + * Reads: schemas/midi_device.schema.json (Draft 2020-12 meta-schema) + * schemas/midi_devices/*.json (one file per external MIDI device) + * + * Writes: nisps/midi/generated/midi_devices.hpp (no-heap constexpr, firmware + WASM) + * manifold/src/midi-devices/generated/types.ts (shared TS types) + * manifold/src/midi-devices/generated/devices.ts (device catalogue) + * manifold/src/midi-devices/generated/index.ts (re-exports) + * + * One source of truth -> both surfaces. The performer picks a device, sees its params + * by name, and selects which the ML drives over MIDI CC. Idempotent: regenerating the + * same schemas yields byte-identical output. Exits non-zero on validation failure. + * + * Deliberately separate from codegen/generate.ts (the mode-schema pipeline) so it cannot + * disturb the mode golden test. + */ + +import { readFileSync, writeFileSync, readdirSync, mkdirSync, existsSync } from "node:fs"; +import { join, dirname, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import Ajv2020, { type AnySchemaObject } from "ajv/dist/2020.js"; + +// ----- Types ---------------------------------------------------------------- + +interface DeviceParam { + id: string; + cc: number; + label: string; + min: number; + max: number; + default: number; + group: string; + notes?: string; +} + +interface DeviceSchema { + $schema?: string; + _note?: string; + device_id: string; + name: string; + manufacturer: string; + year?: number; + midi: { + default_channel: number; + value_range: [number, number]; + notes?: string; + }; + params: DeviceParam[]; +} + +// ----- Paths ---------------------------------------------------------------- + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const REPO_ROOT = resolve(__dirname, ".."); +const SCHEMAS_DIR = join(REPO_ROOT, "schemas"); +const DEVICES_DIR = join(SCHEMAS_DIR, "midi_devices"); +const META_SCHEMA_PATH = join(SCHEMAS_DIR, "midi_device.schema.json"); +const CPP_OUT_DIR = join(REPO_ROOT, "nisps", "midi", "generated"); +const TS_OUT_DIR = join(REPO_ROOT, "manifold", "src", "midi-devices", "generated"); + +// ----- Helpers -------------------------------------------------------------- + +function ensureDir(d: string): void { + if (!existsSync(d)) mkdirSync(d, { recursive: true }); +} +function readJSON(path: string): T { + return JSON.parse(readFileSync(path, "utf8")) as T; +} +function toPascalCase(snake: string): string { + return snake.split("_").map(s => (s.length === 0 ? s : s[0].toUpperCase() + s.slice(1))).join(""); +} +function cppStringLit(s: string): string { + return '"' + s.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + '"'; +} +function tsStringLit(s: string): string { + return "'" + s.replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "'"; +} + +const BANNER = "// AUTOGENERATED — do not edit. Source: schemas/midi_devices/*.json. " + + "Run `bun run codegen/generate-midi-devices.ts` to regenerate."; + +// ----- C++ emission --------------------------------------------------------- + +function emitCppHeader(devices: DeviceSchema[]): string { + const L: string[] = []; + L.push(BANNER); + L.push("//"); + L.push("// No-heap, constexpr MIDI device templates for the RP2350 firmware (and WASM)."); + L.push("// Names are std::string_view into flash; CC/value fields are uint8_t."); + L.push("#ifndef NISPS_MIDI_GENERATED_MIDI_DEVICES_HPP"); + L.push("#define NISPS_MIDI_GENERATED_MIDI_DEVICES_HPP"); + L.push(""); + L.push("#include "); + L.push("#include "); + L.push("#include "); + L.push("#include "); + L.push(""); + L.push("namespace nisps::midi::generated {"); + L.push(""); + L.push("struct MidiParam {"); + L.push(" std::string_view id;"); + L.push(" std::string_view label;"); + L.push(" std::uint8_t cc;"); + L.push(" std::uint8_t min;"); + L.push(" std::uint8_t max;"); + L.push(" std::uint8_t default_value;"); + L.push(" std::string_view group;"); + L.push("};"); + L.push(""); + L.push("struct MidiDevice {"); + L.push(" std::string_view device_id;"); + L.push(" std::string_view name;"); + L.push(" std::string_view manufacturer;"); + L.push(" std::uint8_t default_channel; // 1-16"); + L.push(" std::uint8_t value_min;"); + L.push(" std::uint8_t value_max;"); + L.push(" std::span params;"); + L.push("};"); + L.push(""); + + for (const d of devices) { + const pn = `k${toPascalCase(d.device_id)}Params`; + L.push(`inline constexpr std::array ${pn} = {{`); + for (const p of d.params) { + L.push(` MidiParam{${cppStringLit(p.id)}, ${cppStringLit(p.label)}, ${p.cc}, ${p.min}, ${p.max}, ${p.default}, ${cppStringLit(p.group)}},`); + } + L.push("}};"); + L.push(""); + } + + for (const d of devices) { + const cn = `k${toPascalCase(d.device_id)}`; + const pn = `${cn}Params`; + L.push(`inline constexpr MidiDevice ${cn} = {`); + L.push(` ${cppStringLit(d.device_id)},`); + L.push(` ${cppStringLit(d.name)},`); + L.push(` ${cppStringLit(d.manufacturer)},`); + L.push(` ${d.midi.default_channel},`); + L.push(` ${d.midi.value_range[0]},`); + L.push(` ${d.midi.value_range[1]},`); + L.push(` std::span{${pn}},`); + L.push("};"); + L.push(""); + } + + L.push(`inline constexpr std::size_t kMidiDeviceCount = ${devices.length}u;`); + L.push(`inline constexpr std::array kMidiDevices = {{`); + for (const d of devices) { + L.push(` k${toPascalCase(d.device_id)},`); + } + L.push("}};"); + L.push(""); + L.push("} // namespace nisps::midi::generated"); + L.push(""); + L.push("#endif // NISPS_MIDI_GENERATED_MIDI_DEVICES_HPP"); + L.push(""); + return L.join("\n"); +} + +// ----- TS emission ---------------------------------------------------------- + +function emitTsTypes(): string { + return [ + BANNER, + "// Shared TypeScript types for generated MIDI device templates.", + "", + "export interface MidiDeviceParam {", + " readonly id: string;", + " readonly cc: number;", + " readonly label: string;", + " readonly min: number;", + " readonly max: number;", + " readonly default: number;", + " readonly group: string;", + "}", + "", + "export interface MidiDeviceTemplate {", + " readonly device_id: string;", + " readonly name: string;", + " readonly manufacturer: string;", + " readonly year?: number;", + " readonly default_channel: number;", + " readonly value_min: number;", + " readonly value_max: number;", + " readonly params: readonly MidiDeviceParam[];", + "}", + "", + ].join("\n"); +} + +function emitTsDevices(devices: DeviceSchema[]): string { + const L: string[] = []; + L.push(BANNER); + L.push("import type { MidiDeviceTemplate } from './types';"); + L.push(""); + for (const d of devices) { + const cn = `${toPascalCase(d.device_id)}Device`; + L.push(`export const ${cn}: MidiDeviceTemplate = {`); + L.push(` device_id: ${tsStringLit(d.device_id)},`); + L.push(` name: ${tsStringLit(d.name)},`); + L.push(` manufacturer: ${tsStringLit(d.manufacturer)},`); + if (d.year) L.push(` year: ${d.year},`); + L.push(` default_channel: ${d.midi.default_channel},`); + L.push(` value_min: ${d.midi.value_range[0]},`); + L.push(` value_max: ${d.midi.value_range[1]},`); + L.push(" params: ["); + for (const p of d.params) { + L.push(` { id: ${tsStringLit(p.id)}, cc: ${p.cc}, label: ${tsStringLit(p.label)}, min: ${p.min}, max: ${p.max}, default: ${p.default}, group: ${tsStringLit(p.group)} },`); + } + L.push(" ],"); + L.push("};"); + L.push(""); + } + L.push("export const MIDI_DEVICES: readonly MidiDeviceTemplate[] = ["); + for (const d of devices) { + L.push(` ${toPascalCase(d.device_id)}Device,`); + } + L.push("];"); + L.push(""); + L.push("export const MIDI_DEVICES_BY_ID: Readonly> = {"); + for (const d of devices) { + L.push(` ${tsStringLit(d.device_id)}: ${toPascalCase(d.device_id)}Device,`); + } + L.push("};"); + L.push(""); + return L.join("\n"); +} + +function emitTsIndex(): string { + return [BANNER, "", "export * from './types';", "export * from './devices';", ""].join("\n"); +} + +// ----- Driver --------------------------------------------------------------- + +function main(): number { + if (!existsSync(META_SCHEMA_PATH)) { + console.error(`error: meta-schema not found at ${META_SCHEMA_PATH}`); + return 1; + } + const metaSchema = readJSON(META_SCHEMA_PATH); + const ajv = new Ajv2020({ strict: false, allErrors: true, allowUnionTypes: true }); + const validate = ajv.compile(metaSchema); + + if (!existsSync(DEVICES_DIR)) { + console.error(`error: devices directory not found at ${DEVICES_DIR}`); + return 1; + } + const files = readdirSync(DEVICES_DIR).filter(f => f.endsWith(".json")).sort(); + if (files.length === 0) { + console.error(`error: no device schemas in ${DEVICES_DIR}`); + return 1; + } + + const devices: DeviceSchema[] = []; + let errors = 0; + for (const f of files) { + const path = join(DEVICES_DIR, f); + let raw: unknown; + try { + raw = readJSON(path); + } catch (e) { + console.error(`error: ${f}: parse: ${(e as Error).message}`); + errors++; + continue; + } + if (!validate(raw)) { + console.error(`error: ${f}: schema validation failed:`); + for (const err of validate.errors ?? []) { + console.error(` ${err.instancePath || ""} ${err.message}`); + } + errors++; + continue; + } + const d = raw as DeviceSchema; + // uniqueness checks + const ids = new Set(); + for (const p of d.params) { + if (ids.has(p.id)) { + console.error(`error: ${f}: duplicate param id '${p.id}'`); + errors++; + } + ids.add(p.id); + if (p.min > p.max) { + console.error(`error: ${f}: param '${p.id}' min>max`); + errors++; + } + } + devices.push(d); + } + if (errors > 0) { + console.error(`\n${errors} error(s); aborting codegen.`); + return 1; + } + devices.sort((a, b) => a.device_id.localeCompare(b.device_id)); + + ensureDir(CPP_OUT_DIR); + writeFileSync(join(CPP_OUT_DIR, "midi_devices.hpp"), emitCppHeader(devices)); + + ensureDir(TS_OUT_DIR); + writeFileSync(join(TS_OUT_DIR, "types.ts"), emitTsTypes()); + writeFileSync(join(TS_OUT_DIR, "devices.ts"), emitTsDevices(devices)); + writeFileSync(join(TS_OUT_DIR, "index.ts"), emitTsIndex()); + + console.log(`OK ${devices.length} MIDI device template(s) processed.`); + console.log(` C++ -> ${join(CPP_OUT_DIR, "midi_devices.hpp")}`); + console.log(` TS -> ${TS_OUT_DIR}`); + for (const d of devices) { + console.log(` - ${d.device_id}: ${d.params.length} params, default ch ${d.midi.default_channel}`); + } + return 0; +} + +const isMain = (() => { + if (typeof process === "undefined") return false; + const argv1 = process.argv[1]; + if (!argv1) return false; + return resolve(argv1) === fileURLToPath(import.meta.url); +})(); +if (isMain) process.exit(main()); + +export { main }; diff --git a/codegen/seed-midi-devices.ts b/codegen/seed-midi-devices.ts new file mode 100644 index 0000000..df7b5c0 --- /dev/null +++ b/codegen/seed-midi-devices.ts @@ -0,0 +1,121 @@ +#!/usr/bin/env bun +/** + * One-time seed: derive canonical MIDI device templates (schemas/midi_devices/*.json) + * from the verified research artifact synth-midi-cc.json. + * + * Only the CC-controllable devices are emitted (has_midi_cc === true). For each, + * every {cc, name} becomes a param with a stable snake_case `id` (slugified from the + * label, de-duplicated by appending _cc), min/max from the device value range, + * a neutral default, and a coarse `group` assigned by keyword heuristic. + * + * Re-runnable and idempotent. Edit the emitted schemas/midi_devices/*.json afterwards + * if you want to hand-tune labels, groups, ranges, or defaults — they are the canonical + * source consumed by codegen/generate-midi-devices.ts. synth-midi-cc.json stays as the + * human-readable provenance/sources document. + */ + +import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs"; +import { join, dirname, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const REPO_ROOT = resolve(__dirname, ".."); +const RESEARCH_PATH = join(REPO_ROOT, "synth-midi-cc.json"); +const OUT_DIR = join(REPO_ROOT, "schemas", "midi_devices"); + +const DEFAULT_VALUE = 64; // neutral midpoint; only used when a param is "fixed", not ML-driven + +// Map research `name` -> canonical device_id + default channel. Only these are seeded. +const DEVICE_MAP: Record = { + "Moog Sub 37": { device_id: "moog_sub37", channel: 1 }, + "Creamware Pro-12 ASB": { device_id: "creamware_pro12_asb", channel: 1 }, + "Elektron Analog Keys": { device_id: "elektron_analog_keys", channel: 1 }, + "ASM Hydrasynth": { device_id: "asm_hydrasynth", channel: 1 }, + "Roland JD-800": { device_id: "roland_jd800", channel: 1 }, + "Moog Sub Phatty": { device_id: "moog_sub_phatty", channel: 1 }, +}; + +function slugify(label: string): string { + // Drop parenthetical notes, lowercase, non-alnum -> _, collapse, trim. + let s = label.replace(/\([^)]*\)/g, " ").toLowerCase(); + s = s.replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "").replace(/_+/g, "_"); + if (s.length === 0) s = "param"; + if (!/^[a-z]/.test(s)) s = "p_" + s; + return s; +} + +function groupFor(label: string): string { + const l = label.toLowerCase(); + const has = (...ks: string[]) => ks.some(k => l.includes(k)); + if (has("arp", "arpeggiat")) return "arp"; + if (has("env", "attack", "decay", "sustain", "release", " adsr", "adr", "hold", "delay time")) return "env"; + if (has("lfo")) return "lfo"; + if (has("filter", "cutoff", "resonance", "res ", " res", "multidrive", "poles", "keytrack", "kb track")) return "filter"; + if (has("delay", "reverb", "chorus", "flanger", "fx", "wet", "dry")) return "fx"; + if (has("macro", "mod ", "mutator", "ring mod", " mod", "modulation", "wheel", "aftertouch")) return "mod"; + if (has("osc", "vco", "wave", "pitch", "tune", "freq", "sub", "noise", "detune", "sync", "cent", "octave", "glide", "portamento")) return "osc"; + if (has("vol", "level", "pan", "mix", "amp", "output")) return "mix"; + return "global"; +} + +interface ResearchParam { cc: number; name: string } +interface ResearchSynth { + name: string; + manufacturer: string; + year?: number; + has_midi_cc: boolean; + cc_parameters: ResearchParam[]; +} +interface Research { synths: ResearchSynth[] } + +function main(): number { + const research = JSON.parse(readFileSync(RESEARCH_PATH, "utf8")) as Research; + if (!existsSync(OUT_DIR)) mkdirSync(OUT_DIR, { recursive: true }); + + let count = 0; + for (const synth of research.synths) { + const map = DEVICE_MAP[synth.name]; + if (!map) continue; // skip non-CC / out-of-scope devices + if (!synth.has_midi_cc || synth.cc_parameters.length === 0) continue; + + const seenIds = new Set(); + const params = synth.cc_parameters.map(p => { + let id = slugify(p.name); + if (seenIds.has(id)) id = `${id}_cc${p.cc}`; + while (seenIds.has(id)) id = `${id}_x`; + seenIds.add(id); + return { + id, + cc: p.cc, + label: p.name, + min: 0, + max: 127, + default: DEFAULT_VALUE, + group: groupFor(p.name), + }; + }); + + const device = { + $schema: "../midi_device.schema.json", + device_id: map.device_id, + name: synth.name, + manufacturer: synth.manufacturer, + ...(synth.year ? { year: synth.year } : {}), + midi: { + default_channel: map.channel, + value_range: [0, 127], + }, + params, + }; + + const out = join(OUT_DIR, `${map.device_id}.json`); + writeFileSync(out, JSON.stringify(device, null, 2) + "\n"); + count++; + console.log(` ${map.device_id}: ${params.length} params`); + } + + console.log(`OK seeded ${count} device template(s) -> ${OUT_DIR}`); + return 0; +} + +process.exit(main()); diff --git a/manifold/src/midi-devices/generated/devices.ts b/manifold/src/midi-devices/generated/devices.ts new file mode 100644 index 0000000..ed00cad --- /dev/null +++ b/manifold/src/midi-devices/generated/devices.ts @@ -0,0 +1,539 @@ +// AUTOGENERATED — do not edit. Source: schemas/midi_devices/*.json. Run `bun run codegen/generate-midi-devices.ts` to regenerate. +import type { MidiDeviceTemplate } from './types'; + +export const AsmHydrasynthDevice: MidiDeviceTemplate = { + device_id: 'asm_hydrasynth', + name: 'ASM Hydrasynth', + manufacturer: 'Ashun Sound Machines (ASM)', + year: 2019, + default_channel: 1, + value_min: 0, + value_max: 127, + params: [ + { id: 'bank_select_msb', cc: 0, label: 'Bank Select MSB', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'mod_wheel', cc: 1, label: 'Mod Wheel', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'noise_vol', cc: 3, label: 'Noise Vol', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'glide_time', cc: 5, label: 'Glide Time', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'master_volume', cc: 7, label: 'Master Volume', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'noise_pan', cc: 8, label: 'Noise Pan', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'ring_mod_vol', cc: 9, label: 'Ring Mod Vol', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'ring_mod_pan', cc: 10, label: 'Ring Mod Pan', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'expression_pedal', cc: 11, label: 'Expression Pedal', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'pre_fx_param1', cc: 12, label: 'PRE-FX Param1', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'pre_fx_param2', cc: 13, label: 'PRE-FX Param2', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'delay_feedback', cc: 14, label: 'Delay Feedback', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'delay_time', cc: 15, label: 'Delay Time', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'macro_1', cc: 16, label: 'Macro 1', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'macro_2', cc: 17, label: 'Macro 2', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'macro_3', cc: 18, label: 'Macro 3', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'macro_4', cc: 19, label: 'Macro 4', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'macro_5', cc: 20, label: 'Macro 5', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'macro_6', cc: 21, label: 'Macro 6', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'macro_7', cc: 22, label: 'Macro 7', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'macro_8', cc: 23, label: 'Macro 8', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'osc1_wavscan', cc: 24, label: 'OSC1 WavScan', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'env4_attack', cc: 25, label: 'ENV4 Attack', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'osc2_wavscan', cc: 26, label: 'OSC2 WavScan', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'env4_decay', cc: 27, label: 'ENV4 Decay', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'lfo2_gain', cc: 28, label: 'LFO2 Gain', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'mutator1_ratio', cc: 29, label: 'Mutator1 Ratio', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'mutator1_depth', cc: 30, label: 'Mutator1 Depth', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'mutator1_dry_wet', cc: 31, label: 'Mutator1 Dry/Wet', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'bank_select_lsb', cc: 32, label: 'Bank Select LSB', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'mutator2_ratio', cc: 33, label: 'Mutator2 Ratio', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'mutator2_depth', cc: 34, label: 'Mutator2 Depth', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'mutator2_dry_wet', cc: 35, label: 'Mutator2 Dry/Wet', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'mutator3_ratio', cc: 36, label: 'Mutator3 Ratio', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'mutator3_depth', cc: 37, label: 'Mutator3 Depth', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'mutator3_dry_wet', cc: 39, label: 'Mutator3 Dry/Wet', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'mutator4_ratio', cc: 40, label: 'Mutator4 Ratio', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'mutator4_depth', cc: 41, label: 'Mutator4 Depth', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'mutator4_dry_wet', cc: 42, label: 'Mutator4 Dry/Wet', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'rm12_depth', cc: 43, label: 'RM12 Depth (Ring Mod Depth)', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'osc1_vol', cc: 44, label: 'OSC1 Vol', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc1_pan', cc: 45, label: 'OSC1 Pan', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc2_vol', cc: 46, label: 'OSC2 Vol', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc2_pan', cc: 47, label: 'OSC2 Pan', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc3_vol', cc: 48, label: 'OSC3 Vol', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc3_pan', cc: 49, label: 'OSC3 Pan', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'filter1_drive', cc: 50, label: 'Filter1 Drive', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter1_keytrack', cc: 51, label: 'Filter1 Keytrack', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter1_lfo1_amt', cc: 52, label: 'Filter1 LFO1 Amt', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'filter1_vel_env', cc: 53, label: 'Filter1 Vel Env', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter1_env1_amt', cc: 54, label: 'Filter1 ENV1 Amt', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter2_cutoff', cc: 55, label: 'Filter2 Cutoff', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter2_res', cc: 56, label: 'Filter2 Res', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter2_type_morph', cc: 57, label: 'Filter2 Type/Morph', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter2_keytrack', cc: 58, label: 'Filter2 Keytrack', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter2_lfo1_amt', cc: 59, label: 'Filter2 LFO1 Amt', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'filter2_vel_env', cc: 60, label: 'Filter2 Vel Env', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter2_env1_amt', cc: 61, label: 'Filter2 ENV1 Amt', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'amp_lfo2_amt', cc: 62, label: 'Amp LFO2 Amt', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'delay_wet_tone', cc: 63, label: 'Delay Wet Tone', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'sustain_pedal', cc: 64, label: 'Sustain Pedal', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'reverb_time', cc: 65, label: 'Reverb Time', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'glide_on_off', cc: 66, label: 'Glide On/Off', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'reverb_tone', cc: 67, label: 'Reverb Tone', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'post_fx_param1', cc: 68, label: 'POST-FX Param1', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'post_fx_param2', cc: 69, label: 'POST-FX Param2', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'lfo1_gain', cc: 70, label: 'LFO1 Gain', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'filter1_res', cc: 71, label: 'Filter1 Res', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'lfo1_rate', cc: 72, label: 'LFO1 Rate', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'lfo2_rate', cc: 73, label: 'LFO2 Rate', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'filter1_cutoff', cc: 74, label: 'Filter1 Cutoff', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'lfo3_gain', cc: 75, label: 'LFO3 Gain', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'lfo3_rate', cc: 76, label: 'LFO3 Rate', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'lfo4_gain', cc: 77, label: 'LFO4 Gain', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'lfo4_rate', cc: 78, label: 'LFO4 Rate', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'lfo5_gain', cc: 79, label: 'LFO5 Gain', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'lfo5_rate', cc: 80, label: 'LFO5 Rate', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'env1_attack', cc: 81, label: 'ENV1 Attack', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'env1_decay', cc: 82, label: 'ENV1 Decay', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'env1_sustain', cc: 83, label: 'ENV1 Sustain', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'env1_release', cc: 84, label: 'ENV1 Release', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'env2_attack', cc: 85, label: 'ENV2 Attack', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'env2_decay', cc: 86, label: 'ENV2 Decay', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'env2_sustain', cc: 87, label: 'ENV2 Sustain', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'env2_release', cc: 88, label: 'ENV2 Release', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'env3_attack', cc: 89, label: 'ENV3 Attack', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'env3_decay', cc: 90, label: 'ENV3 Decay', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'reverb_dry_wet', cc: 91, label: 'Reverb Dry/Wet', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'delay_dry_wet', cc: 92, label: 'Delay Dry/Wet', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'pre_fx_mix', cc: 93, label: 'PRE-FX Mix', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'post_fx_mix', cc: 94, label: 'POST-FX Mix', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'detune', cc: 95, label: 'Detune', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'env3_sustain', cc: 96, label: 'ENV3 Sustain', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'env3_release', cc: 97, label: 'ENV3 Release', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'env5_attack', cc: 102, label: 'ENV5 Attack', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'env5_decay', cc: 103, label: 'ENV5 Decay', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'env5_sustain', cc: 104, label: 'ENV5 Sustain', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'env5_release', cc: 105, label: 'ENV5 Release', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'arp_division', cc: 106, label: 'ARP Division', min: 0, max: 127, default: 64, group: 'arp' }, + { id: 'arp_gate', cc: 107, label: 'ARP Gate', min: 0, max: 127, default: 64, group: 'arp' }, + { id: 'arp_mode', cc: 108, label: 'ARP Mode', min: 0, max: 127, default: 64, group: 'arp' }, + { id: 'arp_ratchet', cc: 109, label: 'ARP Ratchet', min: 0, max: 127, default: 64, group: 'arp' }, + { id: 'arp_chance', cc: 110, label: 'ARP Chance', min: 0, max: 127, default: 64, group: 'arp' }, + { id: 'osc1_cent', cc: 111, label: 'OSC1 Cent', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc2_cent', cc: 112, label: 'OSC2 Cent', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc3_cent', cc: 113, label: 'OSC3 Cent', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc3_f_rate', cc: 114, label: 'OSC3 F Rate', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'noise_f_rate', cc: 115, label: 'Noise F Rate', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'ring_mod_f_rate', cc: 116, label: 'Ring Mod F Rate', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'stereo_width', cc: 117, label: 'Stereo Width', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'osc1_f_rate', cc: 118, label: 'OSC1 F Rate', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc2_f_rate', cc: 119, label: 'OSC2 F Rate', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'arp_octave', cc: 120, label: 'ARP Octave (repurposed from standard \'All Sounds Off\')', min: 0, max: 127, default: 64, group: 'arp' }, + { id: 'arp_length', cc: 122, label: 'ARP Length', min: 0, max: 127, default: 64, group: 'arp' }, + { id: 'all_notes_off', cc: 123, label: 'All Notes Off', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'env4_release', cc: 124, label: 'ENV4 Release', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'env4_sustain', cc: 125, label: 'ENV4 Sustain', min: 0, max: 127, default: 64, group: 'env' }, + ], +}; + +export const CreamwarePro12AsbDevice: MidiDeviceTemplate = { + device_id: 'creamware_pro12_asb', + name: 'Creamware Pro-12 ASB', + manufacturer: 'Creamware / Sonic Core', + year: 2005, + default_channel: 1, + value_min: 0, + value_max: 127, + params: [ + { id: 'bank_select', cc: 0, label: 'Bank Select', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'modulation', cc: 1, label: 'Modulation', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'unison_voices', cc: 2, label: 'Unison Voices', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'unison_detune', cc: 3, label: 'Unison Detune', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'glide_time', cc: 5, label: 'Glide Time', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'data_entry', cc: 6, label: 'Data Entry', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'device_volume', cc: 7, label: 'Device Volume', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'lfo_settings_retrig', cc: 8, label: 'LFO Settings Retrig', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'lfo_settings_phase', cc: 9, label: 'LFO Settings Phase', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'volume', cc: 11, label: 'Volume', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'osc_a_frequency', cc: 12, label: 'Osc A Frequency', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_a_shape_saw', cc: 13, label: 'Osc A Shape Saw', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_a_shape_pulse', cc: 14, label: 'Osc A Shape Pulse', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_a_pulse_width', cc: 15, label: 'Osc A Pulse Width', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_a_sync', cc: 16, label: 'Osc A Sync', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_b_frequency', cc: 17, label: 'Osc B Frequency', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_b_fine', cc: 18, label: 'Osc B Fine', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_b_shape_saw', cc: 19, label: 'Osc B Shape Saw', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_b_shape_triangle', cc: 20, label: 'Osc B Shape Triangle', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'master_tune', cc: 21, label: 'Master Tune', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_b_shape_pulse', cc: 22, label: 'Osc B Shape Pulse', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'aftertouch_pitch', cc: 23, label: 'Aftertouch Pitch', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'bend_range', cc: 24, label: 'Bend Range', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'osc_a_volume', cc: 25, label: 'Osc A Volume', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_b_volume', cc: 26, label: 'Osc B Volume', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_b_pulse_width', cc: 27, label: 'Osc B Pulse Width', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_b_lo_freq', cc: 28, label: 'Osc B Lo Freq', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_b_keyboard', cc: 29, label: 'Osc B Keyboard', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'aftertouch_dest_freq_a', cc: 30, label: 'Aftertouch Dest Freq A', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'aftertouch_dest_freq_b', cc: 31, label: 'Aftertouch Dest Freq B', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'bank_select_cc32', cc: 32, label: 'Bank Select', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'noise_volume', cc: 33, label: 'Noise Volume', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'aftertouch_pw', cc: 34, label: 'Aftertouch PW', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'aftertouch_mw', cc: 35, label: 'Aftertouch MW', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'external_volume', cc: 36, label: 'External Volume', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'aftertouch_dest_pw', cc: 37, label: 'Aftertouch Dest PW', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'aftertouch_dest_pw_cc38', cc: 38, label: 'Aftertouch Dest PW', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'keyboard_amount', cc: 39, label: 'Keyboard Amount', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'cutoff', cc: 40, label: 'Cutoff', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'resonance', cc: 41, label: 'Resonance', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'envelope_amount', cc: 42, label: 'Envelope Amount', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_env_attack', cc: 43, label: 'Filter Env Attack', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_env_decay', cc: 44, label: 'Filter Env Decay', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_env_sustain', cc: 45, label: 'Filter Env Sustain', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_env_velocity', cc: 46, label: 'Filter Env Velocity', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_release', cc: 47, label: 'Filter Release', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'aftertouch_lfo_freq', cc: 48, label: 'Aftertouch LFO Freq', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'release', cc: 49, label: 'Release', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'aftertouch_filter', cc: 50, label: 'Aftertouch Filter', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'aftertouch_amp', cc: 51, label: 'Aftertouch Amp', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'amp_env_attack', cc: 52, label: 'Amp Env Attack', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'amp_env_decay', cc: 53, label: 'Amp Env Decay', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'amp_env_sustain', cc: 54, label: 'Amp Env Sustain', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'amp_env_velocity', cc: 55, label: 'Amp Env Velocity', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'mw_intensity', cc: 56, label: 'MW Intensity', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'mw_offset', cc: 57, label: 'MW Offset', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'poly_mod_osc_b', cc: 58, label: 'Poly Mod OSC B', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'adr', cc: 59, label: 'ADR', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'keyb_mode_retrig', cc: 60, label: 'Keyb Mode Retrig', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'low_note', cc: 61, label: 'Low Note', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'amp_env_release', cc: 62, label: 'Amp Env Release', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'poly_mod_filter_env', cc: 63, label: 'Poly Mod Filter Env', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'poly_mod_destination_freq_a', cc: 75, label: 'Poly Mod Destination Freq A', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'poly_mod_destination_freq_b', cc: 76, label: 'Poly Mod Destination Freq B', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'poly_mod_destination_pw', cc: 77, label: 'Poly Mod Destination PW', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'poly_mod_destination_pw_cc78', cc: 78, label: 'Poly Mod Destination PW', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'poly_mod_destination_filter', cc: 79, label: 'Poly Mod Destination Filter', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'amt', cc: 98, label: 'Amt', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'wheel_mod_source_mix', cc: 108, label: 'Wheel Mod Source Mix', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'time_velocity_attack_filter_env', cc: 113, label: 'Time Velocity Attack Filter Env', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'time_velocity_dec_rel_filter_env', cc: 114, label: 'Time Velocity Dec/Rel Filter Env', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'time_velocity_dec_rel_amp_env', cc: 116, label: 'Time Velocity Dec/Rel Amp Env', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'time_velocity_attack_amp_env', cc: 117, label: 'Time Velocity Attack Amp Env', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'all_sounds_off', cc: 120, label: 'All Sounds Off', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'local_control_off', cc: 121, label: 'Local Control Off', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'all_notes_off', cc: 122, label: 'All Notes Off', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'omni_off', cc: 124, label: 'Omni Off', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'omni_on', cc: 125, label: 'Omni On', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'mono_on', cc: 126, label: 'Mono On', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'poly_on', cc: 127, label: 'Poly On', min: 0, max: 127, default: 64, group: 'global' }, + ], +}; + +export const ElektronAnalogKeysDevice: MidiDeviceTemplate = { + device_id: 'elektron_analog_keys', + name: 'Elektron Analog Keys', + manufacturer: 'Elektron', + year: 2014, + default_channel: 1, + value_min: 0, + value_max: 127, + params: [ + { id: 'modulation_modwheel', cc: 1, label: 'Modulation: Modwheel (MSB, 14-bit pair with CC 33)', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'modulation_breath', cc: 2, label: 'Modulation: Breath (MSB, 14-bit pair with CC 34)', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'performance_parameter_a', cc: 3, label: 'Performance: Parameter A', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'performance_parameter_b', cc: 4, label: 'Performance: Parameter B', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'osc_slide_time', cc: 5, label: 'OSC: Slide Time', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'amp_volume', cc: 7, label: 'Amp: Volume', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'performance_parameter_c', cc: 8, label: 'Performance: Parameter C', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'performance_parameter_d', cc: 9, label: 'Performance: Parameter D', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'amp_pan', cc: 10, label: 'Amp: Pan', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'performance_parameter_e', cc: 11, label: 'Performance: Parameter E', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'osc1_pitch', cc: 16, label: 'OSC1: Pitch (MSB, 14-bit pair with CC 48)', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc2_pitch', cc: 17, label: 'OSC2: Pitch (MSB, 14-bit pair with CC 49)', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'filter_1_frequency', cc: 18, label: 'Filter 1: Frequency (MSB, 14-bit pair with CC 50)', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter_2_frequency', cc: 19, label: 'Filter 2: Frequency (MSB, 14-bit pair with CC 51)', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter_env_depth_a', cc: 20, label: 'Filter Env: Depth A (MSB, 14-bit pair with CC 52)', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_env_depth_b', cc: 21, label: 'Filter Env: Depth B (MSB, 14-bit pair with CC 53)', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'aux_env_depth_a', cc: 22, label: 'AUX Env: Depth A (MSB, 14-bit pair with CC 54)', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'aux_env_depth_b', cc: 23, label: 'AUX Env: Depth B (MSB, 14-bit pair with CC 55)', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'lfo1_depth_a', cc: 24, label: 'LFO1: Depth A (MSB, 14-bit pair with CC 56)', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'lfo1_depth_b', cc: 25, label: 'LFO1: Depth B (MSB, 14-bit pair with CC 57)', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'lfo2_depth_a', cc: 26, label: 'LFO2: Depth A (MSB, 14-bit pair with CC 58)', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'lfo2_depth_b', cc: 27, label: 'LFO2: Depth B (MSB, 14-bit pair with CC 59)', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'modulation_modwheel_cc33', cc: 33, label: 'Modulation: Modwheel (LSB)', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'modulation_breath_cc34', cc: 34, label: 'Modulation: Breath (LSB)', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'osc1_pitch_cc48', cc: 48, label: 'OSC1: Pitch (LSB)', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc2_pitch_cc49', cc: 49, label: 'OSC2: Pitch (LSB)', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'filter_1_frequency_cc50', cc: 50, label: 'Filter 1: Frequency (LSB)', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter_2_frequency_cc51', cc: 51, label: 'Filter 2: Frequency (LSB)', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter_env_depth_a_cc52', cc: 52, label: 'Filter Env: Depth A (LSB; MkI: \'EnvF Gate Length\')', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_env_depth_b_cc53', cc: 53, label: 'Filter Env: Depth B (LSB)', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'aux_env_depth_a_cc54', cc: 54, label: 'AUX Env: Depth A (LSB)', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'aux_env_depth_b_cc55', cc: 55, label: 'AUX Env: Depth B (LSB)', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'lfo1_depth_a_cc56', cc: 56, label: 'LFO1: Depth A (LSB)', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'lfo1_depth_b_cc57', cc: 57, label: 'LFO1: Depth B (LSB)', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'lfo2_depth_a_cc58', cc: 58, label: 'LFO2: Depth A (LSB)', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'lfo2_depth_b_cc59', cc: 59, label: 'LFO2: Depth B (LSB)', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'performance_parameter_f', cc: 64, label: 'Performance: Parameter F', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'performance_parameter_g', cc: 65, label: 'Performance: Parameter G', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'performance_parameter_h', cc: 66, label: 'Performance: Parameter H', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'performance_parameter_i', cc: 67, label: 'Performance: Parameter I', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'performance_parameter_j', cc: 68, label: 'Performance: Parameter J', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'osc1_level', cc: 69, label: 'OSC1: Level', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc1_waveform', cc: 70, label: 'OSC1: Waveform', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc1_sub_oscillator', cc: 71, label: 'OSC1: Sub Oscillator', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc1_pulsewidth', cc: 72, label: 'OSC1: Pulsewidth', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc1_pwm_speed', cc: 73, label: 'OSC1: PWM Speed', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc1_pwm_depth', cc: 74, label: 'OSC1: PWM Depth', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'noise_s_h', cc: 75, label: 'Noise: S&H', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'noise_fade', cc: 76, label: 'Noise: Fade', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'noise_level', cc: 77, label: 'Noise: Level', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc2_level', cc: 78, label: 'OSC2: Level', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc2_waveform', cc: 79, label: 'OSC2: Waveform', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc2_sub_oscillator', cc: 80, label: 'OSC2: Sub Oscillator', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc2_pulsewidth', cc: 81, label: 'OSC2: Pulsewidth', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc2_pwm_speed', cc: 82, label: 'OSC2: PWM Speed', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc2_pwm_depth', cc: 83, label: 'OSC2: PWM Depth', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_sync_amount', cc: 84, label: 'OSC: Sync Amount', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_bend_amount', cc: 85, label: 'OSC: Bend Amount', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'filter_1_overdrive', cc: 86, label: 'Filter 1: Overdrive', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'osc_vibrato_speed', cc: 88, label: 'OSC: Vibrato Speed (Analog Keys/MkI)', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'filter_1_resonance', cc: 89, label: 'Filter 1: Resonance', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter_2_resonance', cc: 90, label: 'Filter 2: Resonance', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'amp_chorus_send', cc: 91, label: 'Amp: Chorus Send', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'amp_delay_send', cc: 92, label: 'Amp: Delay Send', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'amp_reverb_send', cc: 93, label: 'Amp: Reverb Send', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'track_mute', cc: 94, label: 'Track: Mute', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'track_level', cc: 95, label: 'Track: Level', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'filter_1_envelope_depth', cc: 102, label: 'Filter 1: Envelope Depth', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_2_envelope_depth', cc: 103, label: 'Filter 2: Envelope Depth', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'amp_env_attack', cc: 104, label: 'Amp Env: Attack', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'amp_env_decay', cc: 105, label: 'Amp Env: Decay', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'amp_env_sustain', cc: 106, label: 'Amp Env: Sustain', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'amp_env_release', cc: 107, label: 'Amp Env: Release', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_env_attack', cc: 108, label: 'Filter Env: Attack', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_env_decay', cc: 109, label: 'Filter Env: Decay', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_env_sustain', cc: 110, label: 'Filter Env: Sustain', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_env_release', cc: 111, label: 'Filter Env: Release', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'aux_env_attack', cc: 112, label: 'AUX Env: Attack', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'aux_env_decay', cc: 113, label: 'AUX Env: Decay', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'aux_env_sustain', cc: 114, label: 'AUX Env: Sustain', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'aux_env_release', cc: 115, label: 'AUX Env: Release', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'lfo1_speed', cc: 116, label: 'LFO1: Speed', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'lfo1_multiplier', cc: 117, label: 'LFO1: Multiplier', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'lfo2_speed', cc: 118, label: 'LFO2: Speed', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'lfo2_multiplier', cc: 119, label: 'LFO2: Multiplier', min: 0, max: 127, default: 64, group: 'lfo' }, + ], +}; + +export const MoogSubPhattyDevice: MidiDeviceTemplate = { + device_id: 'moog_sub_phatty', + name: 'Moog Sub Phatty', + manufacturer: 'Moog', + year: 2013, + default_channel: 1, + value_min: 0, + value_max: 127, + params: [ + { id: 'modulation_wheel', cc: 1, label: 'Modulation Wheel', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'filter_mod_amount', cc: 2, label: 'Filter Mod Amount', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'lfo_rate', cc: 3, label: 'LFO Rate', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'pitch_mod_amount', cc: 4, label: 'Pitch Mod Amount', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'glide_rate', cc: 5, label: 'Glide Rate', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'output_level', cc: 7, label: 'Output Level (Volume)', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'noise_level', cc: 8, label: 'Noise Level', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'vco_1_wave', cc: 9, label: 'VCO 1 Wave', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'vco_2_frequency', cc: 12, label: 'VCO 2 Frequency', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'vco_2_beat_frequency', cc: 13, label: 'VCO 2 Beat Frequency', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'vco_2_wave', cc: 14, label: 'VCO 2 Wave', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'vco_1_level', cc: 15, label: 'VCO 1 Level', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'vco_2_level', cc: 16, label: 'VCO 2 Level', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'vco_1_sub_level', cc: 17, label: 'VCO 1 Sub Level', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'multidrive_amount', cc: 18, label: 'Multidrive Amount', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter_cutoff_frequency', cc: 19, label: 'Filter Cutoff Frequency', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'wave_mod_amount', cc: 20, label: 'Wave Mod Amount', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'filter_resonance', cc: 21, label: 'Filter Resonance', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter_eg_amount', cc: 22, label: 'Filter EG Amount', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter_eg_attack', cc: 23, label: 'Filter EG Attack', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_eg_decay', cc: 24, label: 'Filter EG Decay', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_eg_sustain', cc: 25, label: 'Filter EG Sustain', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_eg_release', cc: 26, label: 'Filter EG Release', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_kb_tracking_amount', cc: 27, label: 'Filter KB Tracking Amount', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'amplifier_eg_attack', cc: 28, label: 'Amplifier EG Attack', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'amplifier_eg_decay', cc: 29, label: 'Amplifier EG Decay', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'amplifier_eg_sustain', cc: 30, label: 'Amplifier EG Sustain', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'amplifier_eg_release', cc: 31, label: 'Amplifier EG Release', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'glide_on_off', cc: 65, label: 'Glide On/Off', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'legato', cc: 68, label: 'Legato', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'pitch_mod_osc_2_only', cc: 70, label: 'Pitch Mod OSC 2 Only', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'modulation_source', cc: 71, label: 'Modulation Source', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'wave_mod_destination', cc: 72, label: 'Wave Mod Destination', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'gated_glide', cc: 73, label: 'Gated Glide', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'vco_1_octave', cc: 74, label: 'VCO 1 Octave', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'vco_2_octave', cc: 75, label: 'VCO 2 Octave', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'lfo_range', cc: 76, label: 'LFO Range', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'vco_hard_sync', cc: 77, label: 'VCO Hard Sync', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'lfo_kb_tracking_amount', cc: 78, label: 'LFO KB Tracking Amount', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'filter_eg_velocity_to_time', cc: 79, label: 'Filter EG Velocity to Time', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'amplifier_eg_velocity_to_time', cc: 80, label: 'Amplifier EG Velocity to Time', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'vco_gate_reset', cc: 81, label: 'VCO Gate Reset', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter_eg_reset', cc: 82, label: 'Filter EG Reset', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'amplifier_eg_reset', cc: 83, label: 'Amplifier EG Reset', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'glide_type', cc: 85, label: 'Glide Type', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'filter_eg_repeat', cc: 86, label: 'Filter EG Repeat', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'amplifier_eg_repeat', cc: 87, label: 'Amplifier EG Repeat', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'release_on_off', cc: 88, label: 'Release On/Off', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'keyboard_octave', cc: 89, label: 'Keyboard Octave', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'filter_eg_kb_amount', cc: 90, label: 'Filter EG KB Amount', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'amplifier_eg_kb_amount', cc: 91, label: 'Amplifier EG KB Amount', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'amplifier_eg_velocity_to_amplitude', cc: 92, label: 'Amplifier EG Velocity to Amplitude', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'lfo_gate_reset', cc: 93, label: 'LFO Gate Reset', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'glide_legato', cc: 94, label: 'Glide Legato', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'lfo_midi_sync', cc: 102, label: 'LFO MIDI Sync', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'filter_eg_delay', cc: 103, label: 'Filter EG Delay', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'amplifier_eg_delay', cc: 104, label: 'Amplifier EG Delay', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'filter_eg_hold', cc: 105, label: 'Filter EG Hold', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'amplifier_eg_hold', cc: 106, label: 'Amplifier EG Hold', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'pitch_bend_up', cc: 107, label: 'Pitch Bend Up', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'pitch_bend_down', cc: 108, label: 'Pitch Bend Down', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'filter_poles', cc: 109, label: 'Filter Poles', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter_eg_velocity_to_amplitude', cc: 110, label: 'Filter EG Velocity to Amplitude', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'note_priority', cc: 111, label: 'Note Priority', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'filter_eg_gate_source', cc: 113, label: 'Filter EG Gate Source', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'volume_eg_gate_source', cc: 114, label: 'Volume (Amplifier) EG Gate Source', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'filter_eg_trigger_mode', cc: 115, label: 'Filter EG Trigger Mode', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'external_input_level', cc: 116, label: 'External Input Level', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'filter_eg_fast_decay', cc: 117, label: 'Filter EG Fast Decay', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'amplifier_eg_fast_decay', cc: 118, label: 'Amplifier EG Fast Decay', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'keyboard_transpose', cc: 119, label: 'Keyboard Transpose', min: 0, max: 127, default: 64, group: 'global' }, + ], +}; + +export const MoogSub37Device: MidiDeviceTemplate = { + device_id: 'moog_sub37', + name: 'Moog Sub 37', + manufacturer: 'Moog', + year: 2014, + default_channel: 1, + value_min: 0, + value_max: 127, + params: [ + { id: 'bank_select', cc: 0, label: 'Bank Select', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'mod_wheel', cc: 1, label: 'Mod Wheel', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'reserved_midi_breath_control', cc: 2, label: 'Reserved - MIDI Breath Control', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'lfo_1_rate', cc: 3, label: 'LFO 1 Rate (also LFO 1 Clock Divider)', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'mod_1_pitch_amount', cc: 4, label: 'Mod 1 Pitch Amount', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'glide_time', cc: 5, label: 'Glide Time', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'reserved_data_entry', cc: 6, label: 'Reserved - Data Entry', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'master_volume', cc: 7, label: 'Master Volume', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'lfo_2_rate', cc: 8, label: 'LFO 2 Rate (also LFO 2 Clock Divider)', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'osc_1_wave', cc: 9, label: 'Osc 1 Wave', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'reserved_midi_pan', cc: 10, label: 'Reserved - MIDI Pan', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'mod_1_filter_amount', cc: 11, label: 'Mod 1 Filter Amount', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'osc_2_frequency', cc: 12, label: 'Osc 2 Frequency', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_2_beat_frequency', cc: 13, label: 'Osc 2 Beat Frequency', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_2_wave', cc: 14, label: 'Osc 2 Wave', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'mod_2_pitch_amount', cc: 15, label: 'Mod 2 Pitch Amount', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'mod_2_filter_amount', cc: 16, label: 'Mod 2 Filter Amount', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'mod_2_pgm_dest_amount', cc: 17, label: 'Mod 2 Pgm Dest Amount', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'filter_multidrive', cc: 18, label: 'Filter Multidrive', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter_cutoff', cc: 19, label: 'Filter Cutoff', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'mod_1_pgm_dest_amount', cc: 20, label: 'Mod 1 Pgm Dest Amount', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'filter_resonance', cc: 21, label: 'Filter Resonance', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter_kb_amount', cc: 22, label: 'Filter KB Amount', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter_eg_attack_time', cc: 23, label: 'Filter EG Attack Time', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_eg_decay_time', cc: 24, label: 'Filter EG Decay Time', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_eg_sustain_time', cc: 25, label: 'Filter EG Sustain Time', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_eg_release_time', cc: 26, label: 'Filter EG Release Time', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'filter_eg_amount', cc: 27, label: 'Filter EG Amount', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'amp_eg_attack_time', cc: 28, label: 'Amp EG Attack Time', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'amp_eg_decay_time', cc: 29, label: 'Amp EG Decay Time', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'amp_eg_sustain_time', cc: 30, label: 'Amp EG Sustain Time', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'amp_eg_release_time', cc: 31, label: 'Amp EG Release Time', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'bank_select_cc32', cc: 32, label: 'Bank Select (LSB)', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'mod_wheel_cc33', cc: 33, label: 'Mod Wheel (LSB)', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'hold_pedal_sustain', cc: 64, label: 'Hold Pedal/Sustain', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'glide_on', cc: 65, label: 'Glide On', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'arpeggiator_latch', cc: 69, label: 'Arpeggiator Latch', min: 0, max: 127, default: 64, group: 'arp' }, + { id: 'mod_1_osc_1_2_select', cc: 70, label: 'Mod 1 Osc 1/2 Select', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'mod_1_source', cc: 71, label: 'Mod 1 Source', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'mod_2_source', cc: 72, label: 'Mod 2 Source', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'arp_on_off', cc: 73, label: 'Arp On/Off', min: 0, max: 127, default: 64, group: 'arp' }, + { id: 'osc_1_octave', cc: 74, label: 'Osc 1 Octave', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_2_octave', cc: 75, label: 'Osc 2 Octave', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'lfo_1_range', cc: 76, label: 'LFO 1 Range', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'osc_2_hard_sync_on_off', cc: 77, label: 'Osc 2 Hard Sync On/Off', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'lfo_2_range', cc: 78, label: 'LFO 2 Range', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'filter_eg_kb_amount', cc: 79, label: 'Filter EG KB Amount', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'amp_eg_kb_amount', cc: 80, label: 'Amp EG KB Amount', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'osc_kb_reset_on_off', cc: 81, label: 'Osc KB Reset On/Off', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'filter_eg_reset', cc: 82, label: 'Filter EG Reset', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'amp_eg_reset', cc: 83, label: 'Amp EG Reset', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'reserved_portamento_control', cc: 84, label: 'Reserved - Portamento Control', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'glide_type', cc: 85, label: 'Glide Type', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'filter_eg_velocity_amount', cc: 86, label: 'Filter EG Velocity Amount', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'amp_eg_velocity_amount', cc: 87, label: 'Amp EG Velocity Amount', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'mod_2_osc_1_2_select', cc: 88, label: 'Mod 2 Osc 1/2 Select', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'kb_octave', cc: 89, label: 'KB Octave', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'mod_1_destination', cc: 91, label: 'Mod 1 Destination', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'mod_2_destination', cc: 92, label: 'Mod 2 Destination', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'lfo_1_kb_reset', cc: 93, label: 'LFO 1 KB Reset', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'glide_legato', cc: 94, label: 'Glide Legato', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'lfo_2_kb_reset', cc: 95, label: 'LFO 2 KB Reset', min: 0, max: 127, default: 64, group: 'lfo' }, + { id: 'glide_dest_osc_1_2_both', cc: 102, label: 'Glide Dest Osc 1/2/Both', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'filter_eg_delay', cc: 103, label: 'Filter EG Delay', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'amp_eg_delay', cc: 104, label: 'Amp EG Delay', min: 0, max: 127, default: 64, group: 'fx' }, + { id: 'filter_eg_hold', cc: 105, label: 'Filter EG Hold', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'amp_eg_hold', cc: 106, label: 'Amp EG Hold', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'pitch_bend_up_amount', cc: 107, label: 'Pitch Bend Up Amount', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'pitch_bend_down_amount', cc: 108, label: 'Pitch Bend Down Amount', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'filter_slopes', cc: 109, label: 'Filter Slopes (Poles)', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'osc_duo_mode_on_off', cc: 110, label: 'Osc Duo Mode On/Off', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'kb_ctrl_lo_hi', cc: 111, label: 'KB Ctrl Lo/Hi', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'filter_eg_multi_trig', cc: 112, label: 'Filter EG Multi Trig', min: 0, max: 127, default: 64, group: 'filter' }, + { id: 'amp_eg_multi_trig', cc: 113, label: 'Amp EG Multi Trig', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'osc_1_level', cc: 114, label: 'Osc 1 Level', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_1_sub_level', cc: 115, label: 'Osc 1 Sub Level', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'osc_2_level', cc: 116, label: 'Osc 2 Level', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'noise_level', cc: 117, label: 'Noise Level', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'feedback_ext_level', cc: 118, label: 'Feedback/Ext Level', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'kb_transpose', cc: 119, label: 'KB Transpose (receive only)', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'local_control_on_off', cc: 122, label: 'Local Control On/Off', min: 0, max: 127, default: 64, group: 'global' }, + ], +}; + +export const RolandJd800Device: MidiDeviceTemplate = { + device_id: 'roland_jd800', + name: 'Roland JD-800', + manufacturer: 'Roland', + year: 1991, + default_channel: 1, + value_min: 0, + value_max: 127, + params: [ + { id: 'modulation', cc: 1, label: 'Modulation', min: 0, max: 127, default: 64, group: 'mod' }, + { id: 'breath_controller', cc: 2, label: 'Breath Controller', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'portamento_time', cc: 5, label: 'Portamento Time', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'data_entry_msb', cc: 6, label: 'Data Entry MSB (RPN; receive only)', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'volume_part_level', cc: 7, label: 'Volume / Part Level', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'pan', cc: 10, label: 'Pan', min: 0, max: 127, default: 64, group: 'mix' }, + { id: 'expression', cc: 11, label: 'Expression', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'hold_sustain_pedal', cc: 64, label: 'Hold / Sustain Pedal', min: 0, max: 127, default: 64, group: 'env' }, + { id: 'portamento_on_off', cc: 65, label: 'Portamento On/Off', min: 0, max: 127, default: 64, group: 'osc' }, + { id: 'rpn_lsb', cc: 100, label: 'RPN LSB (receive only)', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'rpn_msb', cc: 101, label: 'RPN MSB (receive only)', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'reset_all_controllers', cc: 121, label: 'Reset All Controllers (receive only)', min: 0, max: 127, default: 64, group: 'global' }, + { id: 'all_notes_off', cc: 123, label: 'All Notes Off (receive only)', min: 0, max: 127, default: 64, group: 'global' }, + ], +}; + +export const MIDI_DEVICES: readonly MidiDeviceTemplate[] = [ + AsmHydrasynthDevice, + CreamwarePro12AsbDevice, + ElektronAnalogKeysDevice, + MoogSubPhattyDevice, + MoogSub37Device, + RolandJd800Device, +]; + +export const MIDI_DEVICES_BY_ID: Readonly> = { + 'asm_hydrasynth': AsmHydrasynthDevice, + 'creamware_pro12_asb': CreamwarePro12AsbDevice, + 'elektron_analog_keys': ElektronAnalogKeysDevice, + 'moog_sub_phatty': MoogSubPhattyDevice, + 'moog_sub37': MoogSub37Device, + 'roland_jd800': RolandJd800Device, +}; diff --git a/manifold/src/midi-devices/generated/index.ts b/manifold/src/midi-devices/generated/index.ts new file mode 100644 index 0000000..2a55536 --- /dev/null +++ b/manifold/src/midi-devices/generated/index.ts @@ -0,0 +1,4 @@ +// AUTOGENERATED — do not edit. Source: schemas/midi_devices/*.json. Run `bun run codegen/generate-midi-devices.ts` to regenerate. + +export * from './types'; +export * from './devices'; diff --git a/manifold/src/midi-devices/generated/types.ts b/manifold/src/midi-devices/generated/types.ts new file mode 100644 index 0000000..23171ef --- /dev/null +++ b/manifold/src/midi-devices/generated/types.ts @@ -0,0 +1,23 @@ +// AUTOGENERATED — do not edit. Source: schemas/midi_devices/*.json. Run `bun run codegen/generate-midi-devices.ts` to regenerate. +// Shared TypeScript types for generated MIDI device templates. + +export interface MidiDeviceParam { + readonly id: string; + readonly cc: number; + readonly label: string; + readonly min: number; + readonly max: number; + readonly default: number; + readonly group: string; +} + +export interface MidiDeviceTemplate { + readonly device_id: string; + readonly name: string; + readonly manufacturer: string; + readonly year?: number; + readonly default_channel: number; + readonly value_min: number; + readonly value_max: number; + readonly params: readonly MidiDeviceParam[]; +} diff --git a/nisps/midi/generated/midi_devices.hpp b/nisps/midi/generated/midi_devices.hpp new file mode 100644 index 0000000..8599a93 --- /dev/null +++ b/nisps/midi/generated/midi_devices.hpp @@ -0,0 +1,572 @@ +// AUTOGENERATED — do not edit. Source: schemas/midi_devices/*.json. Run `bun run codegen/generate-midi-devices.ts` to regenerate. +// +// No-heap, constexpr MIDI device templates for the RP2350 firmware (and WASM). +// Names are std::string_view into flash; CC/value fields are uint8_t. +#ifndef NISPS_MIDI_GENERATED_MIDI_DEVICES_HPP +#define NISPS_MIDI_GENERATED_MIDI_DEVICES_HPP + +#include +#include +#include +#include + +namespace nisps::midi::generated { + +struct MidiParam { + std::string_view id; + std::string_view label; + std::uint8_t cc; + std::uint8_t min; + std::uint8_t max; + std::uint8_t default_value; + std::string_view group; +}; + +struct MidiDevice { + std::string_view device_id; + std::string_view name; + std::string_view manufacturer; + std::uint8_t default_channel; // 1-16 + std::uint8_t value_min; + std::uint8_t value_max; + std::span params; +}; + +inline constexpr std::array kAsmHydrasynthParams = {{ + MidiParam{"bank_select_msb", "Bank Select MSB", 0, 0, 127, 64, "global"}, + MidiParam{"mod_wheel", "Mod Wheel", 1, 0, 127, 64, "mod"}, + MidiParam{"noise_vol", "Noise Vol", 3, 0, 127, 64, "osc"}, + MidiParam{"glide_time", "Glide Time", 5, 0, 127, 64, "osc"}, + MidiParam{"master_volume", "Master Volume", 7, 0, 127, 64, "mix"}, + MidiParam{"noise_pan", "Noise Pan", 8, 0, 127, 64, "osc"}, + MidiParam{"ring_mod_vol", "Ring Mod Vol", 9, 0, 127, 64, "mod"}, + MidiParam{"ring_mod_pan", "Ring Mod Pan", 10, 0, 127, 64, "mod"}, + MidiParam{"expression_pedal", "Expression Pedal", 11, 0, 127, 64, "global"}, + MidiParam{"pre_fx_param1", "PRE-FX Param1", 12, 0, 127, 64, "fx"}, + MidiParam{"pre_fx_param2", "PRE-FX Param2", 13, 0, 127, 64, "fx"}, + MidiParam{"delay_feedback", "Delay Feedback", 14, 0, 127, 64, "fx"}, + MidiParam{"delay_time", "Delay Time", 15, 0, 127, 64, "env"}, + MidiParam{"macro_1", "Macro 1", 16, 0, 127, 64, "mod"}, + MidiParam{"macro_2", "Macro 2", 17, 0, 127, 64, "mod"}, + MidiParam{"macro_3", "Macro 3", 18, 0, 127, 64, "mod"}, + MidiParam{"macro_4", "Macro 4", 19, 0, 127, 64, "mod"}, + MidiParam{"macro_5", "Macro 5", 20, 0, 127, 64, "mod"}, + MidiParam{"macro_6", "Macro 6", 21, 0, 127, 64, "mod"}, + MidiParam{"macro_7", "Macro 7", 22, 0, 127, 64, "mod"}, + MidiParam{"macro_8", "Macro 8", 23, 0, 127, 64, "mod"}, + MidiParam{"osc1_wavscan", "OSC1 WavScan", 24, 0, 127, 64, "osc"}, + MidiParam{"env4_attack", "ENV4 Attack", 25, 0, 127, 64, "env"}, + MidiParam{"osc2_wavscan", "OSC2 WavScan", 26, 0, 127, 64, "osc"}, + MidiParam{"env4_decay", "ENV4 Decay", 27, 0, 127, 64, "env"}, + MidiParam{"lfo2_gain", "LFO2 Gain", 28, 0, 127, 64, "lfo"}, + MidiParam{"mutator1_ratio", "Mutator1 Ratio", 29, 0, 127, 64, "mod"}, + MidiParam{"mutator1_depth", "Mutator1 Depth", 30, 0, 127, 64, "mod"}, + MidiParam{"mutator1_dry_wet", "Mutator1 Dry/Wet", 31, 0, 127, 64, "fx"}, + MidiParam{"bank_select_lsb", "Bank Select LSB", 32, 0, 127, 64, "global"}, + MidiParam{"mutator2_ratio", "Mutator2 Ratio", 33, 0, 127, 64, "mod"}, + MidiParam{"mutator2_depth", "Mutator2 Depth", 34, 0, 127, 64, "mod"}, + MidiParam{"mutator2_dry_wet", "Mutator2 Dry/Wet", 35, 0, 127, 64, "fx"}, + MidiParam{"mutator3_ratio", "Mutator3 Ratio", 36, 0, 127, 64, "mod"}, + MidiParam{"mutator3_depth", "Mutator3 Depth", 37, 0, 127, 64, "mod"}, + MidiParam{"mutator3_dry_wet", "Mutator3 Dry/Wet", 39, 0, 127, 64, "fx"}, + MidiParam{"mutator4_ratio", "Mutator4 Ratio", 40, 0, 127, 64, "mod"}, + MidiParam{"mutator4_depth", "Mutator4 Depth", 41, 0, 127, 64, "mod"}, + MidiParam{"mutator4_dry_wet", "Mutator4 Dry/Wet", 42, 0, 127, 64, "fx"}, + MidiParam{"rm12_depth", "RM12 Depth (Ring Mod Depth)", 43, 0, 127, 64, "mod"}, + MidiParam{"osc1_vol", "OSC1 Vol", 44, 0, 127, 64, "osc"}, + MidiParam{"osc1_pan", "OSC1 Pan", 45, 0, 127, 64, "osc"}, + MidiParam{"osc2_vol", "OSC2 Vol", 46, 0, 127, 64, "osc"}, + MidiParam{"osc2_pan", "OSC2 Pan", 47, 0, 127, 64, "osc"}, + MidiParam{"osc3_vol", "OSC3 Vol", 48, 0, 127, 64, "osc"}, + MidiParam{"osc3_pan", "OSC3 Pan", 49, 0, 127, 64, "osc"}, + MidiParam{"filter1_drive", "Filter1 Drive", 50, 0, 127, 64, "filter"}, + MidiParam{"filter1_keytrack", "Filter1 Keytrack", 51, 0, 127, 64, "filter"}, + MidiParam{"filter1_lfo1_amt", "Filter1 LFO1 Amt", 52, 0, 127, 64, "lfo"}, + MidiParam{"filter1_vel_env", "Filter1 Vel Env", 53, 0, 127, 64, "env"}, + MidiParam{"filter1_env1_amt", "Filter1 ENV1 Amt", 54, 0, 127, 64, "env"}, + MidiParam{"filter2_cutoff", "Filter2 Cutoff", 55, 0, 127, 64, "filter"}, + MidiParam{"filter2_res", "Filter2 Res", 56, 0, 127, 64, "filter"}, + MidiParam{"filter2_type_morph", "Filter2 Type/Morph", 57, 0, 127, 64, "filter"}, + MidiParam{"filter2_keytrack", "Filter2 Keytrack", 58, 0, 127, 64, "filter"}, + MidiParam{"filter2_lfo1_amt", "Filter2 LFO1 Amt", 59, 0, 127, 64, "lfo"}, + MidiParam{"filter2_vel_env", "Filter2 Vel Env", 60, 0, 127, 64, "env"}, + MidiParam{"filter2_env1_amt", "Filter2 ENV1 Amt", 61, 0, 127, 64, "env"}, + MidiParam{"amp_lfo2_amt", "Amp LFO2 Amt", 62, 0, 127, 64, "lfo"}, + MidiParam{"delay_wet_tone", "Delay Wet Tone", 63, 0, 127, 64, "fx"}, + MidiParam{"sustain_pedal", "Sustain Pedal", 64, 0, 127, 64, "env"}, + MidiParam{"reverb_time", "Reverb Time", 65, 0, 127, 64, "fx"}, + MidiParam{"glide_on_off", "Glide On/Off", 66, 0, 127, 64, "osc"}, + MidiParam{"reverb_tone", "Reverb Tone", 67, 0, 127, 64, "fx"}, + MidiParam{"post_fx_param1", "POST-FX Param1", 68, 0, 127, 64, "fx"}, + MidiParam{"post_fx_param2", "POST-FX Param2", 69, 0, 127, 64, "fx"}, + MidiParam{"lfo1_gain", "LFO1 Gain", 70, 0, 127, 64, "lfo"}, + MidiParam{"filter1_res", "Filter1 Res", 71, 0, 127, 64, "filter"}, + MidiParam{"lfo1_rate", "LFO1 Rate", 72, 0, 127, 64, "lfo"}, + MidiParam{"lfo2_rate", "LFO2 Rate", 73, 0, 127, 64, "lfo"}, + MidiParam{"filter1_cutoff", "Filter1 Cutoff", 74, 0, 127, 64, "filter"}, + MidiParam{"lfo3_gain", "LFO3 Gain", 75, 0, 127, 64, "lfo"}, + MidiParam{"lfo3_rate", "LFO3 Rate", 76, 0, 127, 64, "lfo"}, + MidiParam{"lfo4_gain", "LFO4 Gain", 77, 0, 127, 64, "lfo"}, + MidiParam{"lfo4_rate", "LFO4 Rate", 78, 0, 127, 64, "lfo"}, + MidiParam{"lfo5_gain", "LFO5 Gain", 79, 0, 127, 64, "lfo"}, + MidiParam{"lfo5_rate", "LFO5 Rate", 80, 0, 127, 64, "lfo"}, + MidiParam{"env1_attack", "ENV1 Attack", 81, 0, 127, 64, "env"}, + MidiParam{"env1_decay", "ENV1 Decay", 82, 0, 127, 64, "env"}, + MidiParam{"env1_sustain", "ENV1 Sustain", 83, 0, 127, 64, "env"}, + MidiParam{"env1_release", "ENV1 Release", 84, 0, 127, 64, "env"}, + MidiParam{"env2_attack", "ENV2 Attack", 85, 0, 127, 64, "env"}, + MidiParam{"env2_decay", "ENV2 Decay", 86, 0, 127, 64, "env"}, + MidiParam{"env2_sustain", "ENV2 Sustain", 87, 0, 127, 64, "env"}, + MidiParam{"env2_release", "ENV2 Release", 88, 0, 127, 64, "env"}, + MidiParam{"env3_attack", "ENV3 Attack", 89, 0, 127, 64, "env"}, + MidiParam{"env3_decay", "ENV3 Decay", 90, 0, 127, 64, "env"}, + MidiParam{"reverb_dry_wet", "Reverb Dry/Wet", 91, 0, 127, 64, "fx"}, + MidiParam{"delay_dry_wet", "Delay Dry/Wet", 92, 0, 127, 64, "fx"}, + MidiParam{"pre_fx_mix", "PRE-FX Mix", 93, 0, 127, 64, "fx"}, + MidiParam{"post_fx_mix", "POST-FX Mix", 94, 0, 127, 64, "fx"}, + MidiParam{"detune", "Detune", 95, 0, 127, 64, "osc"}, + MidiParam{"env3_sustain", "ENV3 Sustain", 96, 0, 127, 64, "env"}, + MidiParam{"env3_release", "ENV3 Release", 97, 0, 127, 64, "env"}, + MidiParam{"env5_attack", "ENV5 Attack", 102, 0, 127, 64, "env"}, + MidiParam{"env5_decay", "ENV5 Decay", 103, 0, 127, 64, "env"}, + MidiParam{"env5_sustain", "ENV5 Sustain", 104, 0, 127, 64, "env"}, + MidiParam{"env5_release", "ENV5 Release", 105, 0, 127, 64, "env"}, + MidiParam{"arp_division", "ARP Division", 106, 0, 127, 64, "arp"}, + MidiParam{"arp_gate", "ARP Gate", 107, 0, 127, 64, "arp"}, + MidiParam{"arp_mode", "ARP Mode", 108, 0, 127, 64, "arp"}, + MidiParam{"arp_ratchet", "ARP Ratchet", 109, 0, 127, 64, "arp"}, + MidiParam{"arp_chance", "ARP Chance", 110, 0, 127, 64, "arp"}, + MidiParam{"osc1_cent", "OSC1 Cent", 111, 0, 127, 64, "osc"}, + MidiParam{"osc2_cent", "OSC2 Cent", 112, 0, 127, 64, "osc"}, + MidiParam{"osc3_cent", "OSC3 Cent", 113, 0, 127, 64, "osc"}, + MidiParam{"osc3_f_rate", "OSC3 F Rate", 114, 0, 127, 64, "osc"}, + MidiParam{"noise_f_rate", "Noise F Rate", 115, 0, 127, 64, "osc"}, + MidiParam{"ring_mod_f_rate", "Ring Mod F Rate", 116, 0, 127, 64, "mod"}, + MidiParam{"stereo_width", "Stereo Width", 117, 0, 127, 64, "global"}, + MidiParam{"osc1_f_rate", "OSC1 F Rate", 118, 0, 127, 64, "osc"}, + MidiParam{"osc2_f_rate", "OSC2 F Rate", 119, 0, 127, 64, "osc"}, + MidiParam{"arp_octave", "ARP Octave (repurposed from standard 'All Sounds Off')", 120, 0, 127, 64, "arp"}, + MidiParam{"arp_length", "ARP Length", 122, 0, 127, 64, "arp"}, + MidiParam{"all_notes_off", "All Notes Off", 123, 0, 127, 64, "global"}, + MidiParam{"env4_release", "ENV4 Release", 124, 0, 127, 64, "env"}, + MidiParam{"env4_sustain", "ENV4 Sustain", 125, 0, 127, 64, "env"}, +}}; + +inline constexpr std::array kCreamwarePro12AsbParams = {{ + MidiParam{"bank_select", "Bank Select", 0, 0, 127, 64, "global"}, + MidiParam{"modulation", "Modulation", 1, 0, 127, 64, "mod"}, + MidiParam{"unison_voices", "Unison Voices", 2, 0, 127, 64, "global"}, + MidiParam{"unison_detune", "Unison Detune", 3, 0, 127, 64, "osc"}, + MidiParam{"glide_time", "Glide Time", 5, 0, 127, 64, "osc"}, + MidiParam{"data_entry", "Data Entry", 6, 0, 127, 64, "global"}, + MidiParam{"device_volume", "Device Volume", 7, 0, 127, 64, "mix"}, + MidiParam{"lfo_settings_retrig", "LFO Settings Retrig", 8, 0, 127, 64, "lfo"}, + MidiParam{"lfo_settings_phase", "LFO Settings Phase", 9, 0, 127, 64, "lfo"}, + MidiParam{"volume", "Volume", 11, 0, 127, 64, "mix"}, + MidiParam{"osc_a_frequency", "Osc A Frequency", 12, 0, 127, 64, "osc"}, + MidiParam{"osc_a_shape_saw", "Osc A Shape Saw", 13, 0, 127, 64, "osc"}, + MidiParam{"osc_a_shape_pulse", "Osc A Shape Pulse", 14, 0, 127, 64, "osc"}, + MidiParam{"osc_a_pulse_width", "Osc A Pulse Width", 15, 0, 127, 64, "osc"}, + MidiParam{"osc_a_sync", "Osc A Sync", 16, 0, 127, 64, "osc"}, + MidiParam{"osc_b_frequency", "Osc B Frequency", 17, 0, 127, 64, "osc"}, + MidiParam{"osc_b_fine", "Osc B Fine", 18, 0, 127, 64, "osc"}, + MidiParam{"osc_b_shape_saw", "Osc B Shape Saw", 19, 0, 127, 64, "osc"}, + MidiParam{"osc_b_shape_triangle", "Osc B Shape Triangle", 20, 0, 127, 64, "osc"}, + MidiParam{"master_tune", "Master Tune", 21, 0, 127, 64, "osc"}, + MidiParam{"osc_b_shape_pulse", "Osc B Shape Pulse", 22, 0, 127, 64, "osc"}, + MidiParam{"aftertouch_pitch", "Aftertouch Pitch", 23, 0, 127, 64, "mod"}, + MidiParam{"bend_range", "Bend Range", 24, 0, 127, 64, "global"}, + MidiParam{"osc_a_volume", "Osc A Volume", 25, 0, 127, 64, "osc"}, + MidiParam{"osc_b_volume", "Osc B Volume", 26, 0, 127, 64, "osc"}, + MidiParam{"osc_b_pulse_width", "Osc B Pulse Width", 27, 0, 127, 64, "osc"}, + MidiParam{"osc_b_lo_freq", "Osc B Lo Freq", 28, 0, 127, 64, "osc"}, + MidiParam{"osc_b_keyboard", "Osc B Keyboard", 29, 0, 127, 64, "osc"}, + MidiParam{"aftertouch_dest_freq_a", "Aftertouch Dest Freq A", 30, 0, 127, 64, "mod"}, + MidiParam{"aftertouch_dest_freq_b", "Aftertouch Dest Freq B", 31, 0, 127, 64, "mod"}, + MidiParam{"bank_select_cc32", "Bank Select", 32, 0, 127, 64, "global"}, + MidiParam{"noise_volume", "Noise Volume", 33, 0, 127, 64, "osc"}, + MidiParam{"aftertouch_pw", "Aftertouch PW", 34, 0, 127, 64, "mod"}, + MidiParam{"aftertouch_mw", "Aftertouch MW", 35, 0, 127, 64, "mod"}, + MidiParam{"external_volume", "External Volume", 36, 0, 127, 64, "mix"}, + MidiParam{"aftertouch_dest_pw", "Aftertouch Dest PW", 37, 0, 127, 64, "mod"}, + MidiParam{"aftertouch_dest_pw_cc38", "Aftertouch Dest PW", 38, 0, 127, 64, "mod"}, + MidiParam{"keyboard_amount", "Keyboard Amount", 39, 0, 127, 64, "global"}, + MidiParam{"cutoff", "Cutoff", 40, 0, 127, 64, "filter"}, + MidiParam{"resonance", "Resonance", 41, 0, 127, 64, "filter"}, + MidiParam{"envelope_amount", "Envelope Amount", 42, 0, 127, 64, "env"}, + MidiParam{"filter_env_attack", "Filter Env Attack", 43, 0, 127, 64, "env"}, + MidiParam{"filter_env_decay", "Filter Env Decay", 44, 0, 127, 64, "env"}, + MidiParam{"filter_env_sustain", "Filter Env Sustain", 45, 0, 127, 64, "env"}, + MidiParam{"filter_env_velocity", "Filter Env Velocity", 46, 0, 127, 64, "env"}, + MidiParam{"filter_release", "Filter Release", 47, 0, 127, 64, "env"}, + MidiParam{"aftertouch_lfo_freq", "Aftertouch LFO Freq", 48, 0, 127, 64, "lfo"}, + MidiParam{"release", "Release", 49, 0, 127, 64, "env"}, + MidiParam{"aftertouch_filter", "Aftertouch Filter", 50, 0, 127, 64, "filter"}, + MidiParam{"aftertouch_amp", "Aftertouch Amp", 51, 0, 127, 64, "mod"}, + MidiParam{"amp_env_attack", "Amp Env Attack", 52, 0, 127, 64, "env"}, + MidiParam{"amp_env_decay", "Amp Env Decay", 53, 0, 127, 64, "env"}, + MidiParam{"amp_env_sustain", "Amp Env Sustain", 54, 0, 127, 64, "env"}, + MidiParam{"amp_env_velocity", "Amp Env Velocity", 55, 0, 127, 64, "env"}, + MidiParam{"mw_intensity", "MW Intensity", 56, 0, 127, 64, "global"}, + MidiParam{"mw_offset", "MW Offset", 57, 0, 127, 64, "global"}, + MidiParam{"poly_mod_osc_b", "Poly Mod OSC B", 58, 0, 127, 64, "mod"}, + MidiParam{"adr", "ADR", 59, 0, 127, 64, "env"}, + MidiParam{"keyb_mode_retrig", "Keyb Mode Retrig", 60, 0, 127, 64, "mod"}, + MidiParam{"low_note", "Low Note", 61, 0, 127, 64, "global"}, + MidiParam{"amp_env_release", "Amp Env Release", 62, 0, 127, 64, "env"}, + MidiParam{"poly_mod_filter_env", "Poly Mod Filter Env", 63, 0, 127, 64, "env"}, + MidiParam{"poly_mod_destination_freq_a", "Poly Mod Destination Freq A", 75, 0, 127, 64, "mod"}, + MidiParam{"poly_mod_destination_freq_b", "Poly Mod Destination Freq B", 76, 0, 127, 64, "mod"}, + MidiParam{"poly_mod_destination_pw", "Poly Mod Destination PW", 77, 0, 127, 64, "mod"}, + MidiParam{"poly_mod_destination_pw_cc78", "Poly Mod Destination PW", 78, 0, 127, 64, "mod"}, + MidiParam{"poly_mod_destination_filter", "Poly Mod Destination Filter", 79, 0, 127, 64, "filter"}, + MidiParam{"amt", "Amt", 98, 0, 127, 64, "global"}, + MidiParam{"wheel_mod_source_mix", "Wheel Mod Source Mix", 108, 0, 127, 64, "mod"}, + MidiParam{"time_velocity_attack_filter_env", "Time Velocity Attack Filter Env", 113, 0, 127, 64, "env"}, + MidiParam{"time_velocity_dec_rel_filter_env", "Time Velocity Dec/Rel Filter Env", 114, 0, 127, 64, "env"}, + MidiParam{"time_velocity_dec_rel_amp_env", "Time Velocity Dec/Rel Amp Env", 116, 0, 127, 64, "env"}, + MidiParam{"time_velocity_attack_amp_env", "Time Velocity Attack Amp Env", 117, 0, 127, 64, "env"}, + MidiParam{"all_sounds_off", "All Sounds Off", 120, 0, 127, 64, "global"}, + MidiParam{"local_control_off", "Local Control Off", 121, 0, 127, 64, "global"}, + MidiParam{"all_notes_off", "All Notes Off", 122, 0, 127, 64, "global"}, + MidiParam{"omni_off", "Omni Off", 124, 0, 127, 64, "global"}, + MidiParam{"omni_on", "Omni On", 125, 0, 127, 64, "global"}, + MidiParam{"mono_on", "Mono On", 126, 0, 127, 64, "global"}, + MidiParam{"poly_on", "Poly On", 127, 0, 127, 64, "global"}, +}}; + +inline constexpr std::array kElektronAnalogKeysParams = {{ + MidiParam{"modulation_modwheel", "Modulation: Modwheel (MSB, 14-bit pair with CC 33)", 1, 0, 127, 64, "mod"}, + MidiParam{"modulation_breath", "Modulation: Breath (MSB, 14-bit pair with CC 34)", 2, 0, 127, 64, "mod"}, + MidiParam{"performance_parameter_a", "Performance: Parameter A", 3, 0, 127, 64, "global"}, + MidiParam{"performance_parameter_b", "Performance: Parameter B", 4, 0, 127, 64, "global"}, + MidiParam{"osc_slide_time", "OSC: Slide Time", 5, 0, 127, 64, "osc"}, + MidiParam{"amp_volume", "Amp: Volume", 7, 0, 127, 64, "mix"}, + MidiParam{"performance_parameter_c", "Performance: Parameter C", 8, 0, 127, 64, "global"}, + MidiParam{"performance_parameter_d", "Performance: Parameter D", 9, 0, 127, 64, "global"}, + MidiParam{"amp_pan", "Amp: Pan", 10, 0, 127, 64, "mix"}, + MidiParam{"performance_parameter_e", "Performance: Parameter E", 11, 0, 127, 64, "global"}, + MidiParam{"osc1_pitch", "OSC1: Pitch (MSB, 14-bit pair with CC 48)", 16, 0, 127, 64, "osc"}, + MidiParam{"osc2_pitch", "OSC2: Pitch (MSB, 14-bit pair with CC 49)", 17, 0, 127, 64, "osc"}, + MidiParam{"filter_1_frequency", "Filter 1: Frequency (MSB, 14-bit pair with CC 50)", 18, 0, 127, 64, "filter"}, + MidiParam{"filter_2_frequency", "Filter 2: Frequency (MSB, 14-bit pair with CC 51)", 19, 0, 127, 64, "filter"}, + MidiParam{"filter_env_depth_a", "Filter Env: Depth A (MSB, 14-bit pair with CC 52)", 20, 0, 127, 64, "env"}, + MidiParam{"filter_env_depth_b", "Filter Env: Depth B (MSB, 14-bit pair with CC 53)", 21, 0, 127, 64, "env"}, + MidiParam{"aux_env_depth_a", "AUX Env: Depth A (MSB, 14-bit pair with CC 54)", 22, 0, 127, 64, "env"}, + MidiParam{"aux_env_depth_b", "AUX Env: Depth B (MSB, 14-bit pair with CC 55)", 23, 0, 127, 64, "env"}, + MidiParam{"lfo1_depth_a", "LFO1: Depth A (MSB, 14-bit pair with CC 56)", 24, 0, 127, 64, "lfo"}, + MidiParam{"lfo1_depth_b", "LFO1: Depth B (MSB, 14-bit pair with CC 57)", 25, 0, 127, 64, "lfo"}, + MidiParam{"lfo2_depth_a", "LFO2: Depth A (MSB, 14-bit pair with CC 58)", 26, 0, 127, 64, "lfo"}, + MidiParam{"lfo2_depth_b", "LFO2: Depth B (MSB, 14-bit pair with CC 59)", 27, 0, 127, 64, "lfo"}, + MidiParam{"modulation_modwheel_cc33", "Modulation: Modwheel (LSB)", 33, 0, 127, 64, "mod"}, + MidiParam{"modulation_breath_cc34", "Modulation: Breath (LSB)", 34, 0, 127, 64, "mod"}, + MidiParam{"osc1_pitch_cc48", "OSC1: Pitch (LSB)", 48, 0, 127, 64, "osc"}, + MidiParam{"osc2_pitch_cc49", "OSC2: Pitch (LSB)", 49, 0, 127, 64, "osc"}, + MidiParam{"filter_1_frequency_cc50", "Filter 1: Frequency (LSB)", 50, 0, 127, 64, "filter"}, + MidiParam{"filter_2_frequency_cc51", "Filter 2: Frequency (LSB)", 51, 0, 127, 64, "filter"}, + MidiParam{"filter_env_depth_a_cc52", "Filter Env: Depth A (LSB; MkI: 'EnvF Gate Length')", 52, 0, 127, 64, "env"}, + MidiParam{"filter_env_depth_b_cc53", "Filter Env: Depth B (LSB)", 53, 0, 127, 64, "env"}, + MidiParam{"aux_env_depth_a_cc54", "AUX Env: Depth A (LSB)", 54, 0, 127, 64, "env"}, + MidiParam{"aux_env_depth_b_cc55", "AUX Env: Depth B (LSB)", 55, 0, 127, 64, "env"}, + MidiParam{"lfo1_depth_a_cc56", "LFO1: Depth A (LSB)", 56, 0, 127, 64, "lfo"}, + MidiParam{"lfo1_depth_b_cc57", "LFO1: Depth B (LSB)", 57, 0, 127, 64, "lfo"}, + MidiParam{"lfo2_depth_a_cc58", "LFO2: Depth A (LSB)", 58, 0, 127, 64, "lfo"}, + MidiParam{"lfo2_depth_b_cc59", "LFO2: Depth B (LSB)", 59, 0, 127, 64, "lfo"}, + MidiParam{"performance_parameter_f", "Performance: Parameter F", 64, 0, 127, 64, "global"}, + MidiParam{"performance_parameter_g", "Performance: Parameter G", 65, 0, 127, 64, "global"}, + MidiParam{"performance_parameter_h", "Performance: Parameter H", 66, 0, 127, 64, "global"}, + MidiParam{"performance_parameter_i", "Performance: Parameter I", 67, 0, 127, 64, "global"}, + MidiParam{"performance_parameter_j", "Performance: Parameter J", 68, 0, 127, 64, "global"}, + MidiParam{"osc1_level", "OSC1: Level", 69, 0, 127, 64, "osc"}, + MidiParam{"osc1_waveform", "OSC1: Waveform", 70, 0, 127, 64, "osc"}, + MidiParam{"osc1_sub_oscillator", "OSC1: Sub Oscillator", 71, 0, 127, 64, "osc"}, + MidiParam{"osc1_pulsewidth", "OSC1: Pulsewidth", 72, 0, 127, 64, "osc"}, + MidiParam{"osc1_pwm_speed", "OSC1: PWM Speed", 73, 0, 127, 64, "osc"}, + MidiParam{"osc1_pwm_depth", "OSC1: PWM Depth", 74, 0, 127, 64, "osc"}, + MidiParam{"noise_s_h", "Noise: S&H", 75, 0, 127, 64, "osc"}, + MidiParam{"noise_fade", "Noise: Fade", 76, 0, 127, 64, "osc"}, + MidiParam{"noise_level", "Noise: Level", 77, 0, 127, 64, "osc"}, + MidiParam{"osc2_level", "OSC2: Level", 78, 0, 127, 64, "osc"}, + MidiParam{"osc2_waveform", "OSC2: Waveform", 79, 0, 127, 64, "osc"}, + MidiParam{"osc2_sub_oscillator", "OSC2: Sub Oscillator", 80, 0, 127, 64, "osc"}, + MidiParam{"osc2_pulsewidth", "OSC2: Pulsewidth", 81, 0, 127, 64, "osc"}, + MidiParam{"osc2_pwm_speed", "OSC2: PWM Speed", 82, 0, 127, 64, "osc"}, + MidiParam{"osc2_pwm_depth", "OSC2: PWM Depth", 83, 0, 127, 64, "osc"}, + MidiParam{"osc_sync_amount", "OSC: Sync Amount", 84, 0, 127, 64, "osc"}, + MidiParam{"osc_bend_amount", "OSC: Bend Amount", 85, 0, 127, 64, "osc"}, + MidiParam{"filter_1_overdrive", "Filter 1: Overdrive", 86, 0, 127, 64, "filter"}, + MidiParam{"osc_vibrato_speed", "OSC: Vibrato Speed (Analog Keys/MkI)", 88, 0, 127, 64, "osc"}, + MidiParam{"filter_1_resonance", "Filter 1: Resonance", 89, 0, 127, 64, "filter"}, + MidiParam{"filter_2_resonance", "Filter 2: Resonance", 90, 0, 127, 64, "filter"}, + MidiParam{"amp_chorus_send", "Amp: Chorus Send", 91, 0, 127, 64, "fx"}, + MidiParam{"amp_delay_send", "Amp: Delay Send", 92, 0, 127, 64, "fx"}, + MidiParam{"amp_reverb_send", "Amp: Reverb Send", 93, 0, 127, 64, "fx"}, + MidiParam{"track_mute", "Track: Mute", 94, 0, 127, 64, "global"}, + MidiParam{"track_level", "Track: Level", 95, 0, 127, 64, "mix"}, + MidiParam{"filter_1_envelope_depth", "Filter 1: Envelope Depth", 102, 0, 127, 64, "env"}, + MidiParam{"filter_2_envelope_depth", "Filter 2: Envelope Depth", 103, 0, 127, 64, "env"}, + MidiParam{"amp_env_attack", "Amp Env: Attack", 104, 0, 127, 64, "env"}, + MidiParam{"amp_env_decay", "Amp Env: Decay", 105, 0, 127, 64, "env"}, + MidiParam{"amp_env_sustain", "Amp Env: Sustain", 106, 0, 127, 64, "env"}, + MidiParam{"amp_env_release", "Amp Env: Release", 107, 0, 127, 64, "env"}, + MidiParam{"filter_env_attack", "Filter Env: Attack", 108, 0, 127, 64, "env"}, + MidiParam{"filter_env_decay", "Filter Env: Decay", 109, 0, 127, 64, "env"}, + MidiParam{"filter_env_sustain", "Filter Env: Sustain", 110, 0, 127, 64, "env"}, + MidiParam{"filter_env_release", "Filter Env: Release", 111, 0, 127, 64, "env"}, + MidiParam{"aux_env_attack", "AUX Env: Attack", 112, 0, 127, 64, "env"}, + MidiParam{"aux_env_decay", "AUX Env: Decay", 113, 0, 127, 64, "env"}, + MidiParam{"aux_env_sustain", "AUX Env: Sustain", 114, 0, 127, 64, "env"}, + MidiParam{"aux_env_release", "AUX Env: Release", 115, 0, 127, 64, "env"}, + MidiParam{"lfo1_speed", "LFO1: Speed", 116, 0, 127, 64, "lfo"}, + MidiParam{"lfo1_multiplier", "LFO1: Multiplier", 117, 0, 127, 64, "lfo"}, + MidiParam{"lfo2_speed", "LFO2: Speed", 118, 0, 127, 64, "lfo"}, + MidiParam{"lfo2_multiplier", "LFO2: Multiplier", 119, 0, 127, 64, "lfo"}, +}}; + +inline constexpr std::array kMoogSubPhattyParams = {{ + MidiParam{"modulation_wheel", "Modulation Wheel", 1, 0, 127, 64, "mod"}, + MidiParam{"filter_mod_amount", "Filter Mod Amount", 2, 0, 127, 64, "filter"}, + MidiParam{"lfo_rate", "LFO Rate", 3, 0, 127, 64, "lfo"}, + MidiParam{"pitch_mod_amount", "Pitch Mod Amount", 4, 0, 127, 64, "mod"}, + MidiParam{"glide_rate", "Glide Rate", 5, 0, 127, 64, "osc"}, + MidiParam{"output_level", "Output Level (Volume)", 7, 0, 127, 64, "mix"}, + MidiParam{"noise_level", "Noise Level", 8, 0, 127, 64, "osc"}, + MidiParam{"vco_1_wave", "VCO 1 Wave", 9, 0, 127, 64, "osc"}, + MidiParam{"vco_2_frequency", "VCO 2 Frequency", 12, 0, 127, 64, "osc"}, + MidiParam{"vco_2_beat_frequency", "VCO 2 Beat Frequency", 13, 0, 127, 64, "osc"}, + MidiParam{"vco_2_wave", "VCO 2 Wave", 14, 0, 127, 64, "osc"}, + MidiParam{"vco_1_level", "VCO 1 Level", 15, 0, 127, 64, "osc"}, + MidiParam{"vco_2_level", "VCO 2 Level", 16, 0, 127, 64, "osc"}, + MidiParam{"vco_1_sub_level", "VCO 1 Sub Level", 17, 0, 127, 64, "osc"}, + MidiParam{"multidrive_amount", "Multidrive Amount", 18, 0, 127, 64, "filter"}, + MidiParam{"filter_cutoff_frequency", "Filter Cutoff Frequency", 19, 0, 127, 64, "filter"}, + MidiParam{"wave_mod_amount", "Wave Mod Amount", 20, 0, 127, 64, "mod"}, + MidiParam{"filter_resonance", "Filter Resonance", 21, 0, 127, 64, "filter"}, + MidiParam{"filter_eg_amount", "Filter EG Amount", 22, 0, 127, 64, "filter"}, + MidiParam{"filter_eg_attack", "Filter EG Attack", 23, 0, 127, 64, "env"}, + MidiParam{"filter_eg_decay", "Filter EG Decay", 24, 0, 127, 64, "env"}, + MidiParam{"filter_eg_sustain", "Filter EG Sustain", 25, 0, 127, 64, "env"}, + MidiParam{"filter_eg_release", "Filter EG Release", 26, 0, 127, 64, "env"}, + MidiParam{"filter_kb_tracking_amount", "Filter KB Tracking Amount", 27, 0, 127, 64, "filter"}, + MidiParam{"amplifier_eg_attack", "Amplifier EG Attack", 28, 0, 127, 64, "env"}, + MidiParam{"amplifier_eg_decay", "Amplifier EG Decay", 29, 0, 127, 64, "env"}, + MidiParam{"amplifier_eg_sustain", "Amplifier EG Sustain", 30, 0, 127, 64, "env"}, + MidiParam{"amplifier_eg_release", "Amplifier EG Release", 31, 0, 127, 64, "env"}, + MidiParam{"glide_on_off", "Glide On/Off", 65, 0, 127, 64, "osc"}, + MidiParam{"legato", "Legato", 68, 0, 127, 64, "global"}, + MidiParam{"pitch_mod_osc_2_only", "Pitch Mod OSC 2 Only", 70, 0, 127, 64, "mod"}, + MidiParam{"modulation_source", "Modulation Source", 71, 0, 127, 64, "mod"}, + MidiParam{"wave_mod_destination", "Wave Mod Destination", 72, 0, 127, 64, "mod"}, + MidiParam{"gated_glide", "Gated Glide", 73, 0, 127, 64, "osc"}, + MidiParam{"vco_1_octave", "VCO 1 Octave", 74, 0, 127, 64, "osc"}, + MidiParam{"vco_2_octave", "VCO 2 Octave", 75, 0, 127, 64, "osc"}, + MidiParam{"lfo_range", "LFO Range", 76, 0, 127, 64, "lfo"}, + MidiParam{"vco_hard_sync", "VCO Hard Sync", 77, 0, 127, 64, "osc"}, + MidiParam{"lfo_kb_tracking_amount", "LFO KB Tracking Amount", 78, 0, 127, 64, "lfo"}, + MidiParam{"filter_eg_velocity_to_time", "Filter EG Velocity to Time", 79, 0, 127, 64, "filter"}, + MidiParam{"amplifier_eg_velocity_to_time", "Amplifier EG Velocity to Time", 80, 0, 127, 64, "mix"}, + MidiParam{"vco_gate_reset", "VCO Gate Reset", 81, 0, 127, 64, "filter"}, + MidiParam{"filter_eg_reset", "Filter EG Reset", 82, 0, 127, 64, "filter"}, + MidiParam{"amplifier_eg_reset", "Amplifier EG Reset", 83, 0, 127, 64, "filter"}, + MidiParam{"glide_type", "Glide Type", 85, 0, 127, 64, "osc"}, + MidiParam{"filter_eg_repeat", "Filter EG Repeat", 86, 0, 127, 64, "filter"}, + MidiParam{"amplifier_eg_repeat", "Amplifier EG Repeat", 87, 0, 127, 64, "mix"}, + MidiParam{"release_on_off", "Release On/Off", 88, 0, 127, 64, "env"}, + MidiParam{"keyboard_octave", "Keyboard Octave", 89, 0, 127, 64, "osc"}, + MidiParam{"filter_eg_kb_amount", "Filter EG KB Amount", 90, 0, 127, 64, "filter"}, + MidiParam{"amplifier_eg_kb_amount", "Amplifier EG KB Amount", 91, 0, 127, 64, "mix"}, + MidiParam{"amplifier_eg_velocity_to_amplitude", "Amplifier EG Velocity to Amplitude", 92, 0, 127, 64, "mix"}, + MidiParam{"lfo_gate_reset", "LFO Gate Reset", 93, 0, 127, 64, "lfo"}, + MidiParam{"glide_legato", "Glide Legato", 94, 0, 127, 64, "osc"}, + MidiParam{"lfo_midi_sync", "LFO MIDI Sync", 102, 0, 127, 64, "lfo"}, + MidiParam{"filter_eg_delay", "Filter EG Delay", 103, 0, 127, 64, "filter"}, + MidiParam{"amplifier_eg_delay", "Amplifier EG Delay", 104, 0, 127, 64, "fx"}, + MidiParam{"filter_eg_hold", "Filter EG Hold", 105, 0, 127, 64, "env"}, + MidiParam{"amplifier_eg_hold", "Amplifier EG Hold", 106, 0, 127, 64, "env"}, + MidiParam{"pitch_bend_up", "Pitch Bend Up", 107, 0, 127, 64, "osc"}, + MidiParam{"pitch_bend_down", "Pitch Bend Down", 108, 0, 127, 64, "osc"}, + MidiParam{"filter_poles", "Filter Poles", 109, 0, 127, 64, "filter"}, + MidiParam{"filter_eg_velocity_to_amplitude", "Filter EG Velocity to Amplitude", 110, 0, 127, 64, "filter"}, + MidiParam{"note_priority", "Note Priority", 111, 0, 127, 64, "global"}, + MidiParam{"filter_eg_gate_source", "Filter EG Gate Source", 113, 0, 127, 64, "filter"}, + MidiParam{"volume_eg_gate_source", "Volume (Amplifier) EG Gate Source", 114, 0, 127, 64, "mix"}, + MidiParam{"filter_eg_trigger_mode", "Filter EG Trigger Mode", 115, 0, 127, 64, "filter"}, + MidiParam{"external_input_level", "External Input Level", 116, 0, 127, 64, "mix"}, + MidiParam{"filter_eg_fast_decay", "Filter EG Fast Decay", 117, 0, 127, 64, "env"}, + MidiParam{"amplifier_eg_fast_decay", "Amplifier EG Fast Decay", 118, 0, 127, 64, "env"}, + MidiParam{"keyboard_transpose", "Keyboard Transpose", 119, 0, 127, 64, "global"}, +}}; + +inline constexpr std::array kMoogSub37Params = {{ + MidiParam{"bank_select", "Bank Select", 0, 0, 127, 64, "global"}, + MidiParam{"mod_wheel", "Mod Wheel", 1, 0, 127, 64, "mod"}, + MidiParam{"reserved_midi_breath_control", "Reserved - MIDI Breath Control", 2, 0, 127, 64, "global"}, + MidiParam{"lfo_1_rate", "LFO 1 Rate (also LFO 1 Clock Divider)", 3, 0, 127, 64, "lfo"}, + MidiParam{"mod_1_pitch_amount", "Mod 1 Pitch Amount", 4, 0, 127, 64, "mod"}, + MidiParam{"glide_time", "Glide Time", 5, 0, 127, 64, "osc"}, + MidiParam{"reserved_data_entry", "Reserved - Data Entry", 6, 0, 127, 64, "global"}, + MidiParam{"master_volume", "Master Volume", 7, 0, 127, 64, "mix"}, + MidiParam{"lfo_2_rate", "LFO 2 Rate (also LFO 2 Clock Divider)", 8, 0, 127, 64, "lfo"}, + MidiParam{"osc_1_wave", "Osc 1 Wave", 9, 0, 127, 64, "osc"}, + MidiParam{"reserved_midi_pan", "Reserved - MIDI Pan", 10, 0, 127, 64, "mix"}, + MidiParam{"mod_1_filter_amount", "Mod 1 Filter Amount", 11, 0, 127, 64, "filter"}, + MidiParam{"osc_2_frequency", "Osc 2 Frequency", 12, 0, 127, 64, "osc"}, + MidiParam{"osc_2_beat_frequency", "Osc 2 Beat Frequency", 13, 0, 127, 64, "osc"}, + MidiParam{"osc_2_wave", "Osc 2 Wave", 14, 0, 127, 64, "osc"}, + MidiParam{"mod_2_pitch_amount", "Mod 2 Pitch Amount", 15, 0, 127, 64, "mod"}, + MidiParam{"mod_2_filter_amount", "Mod 2 Filter Amount", 16, 0, 127, 64, "filter"}, + MidiParam{"mod_2_pgm_dest_amount", "Mod 2 Pgm Dest Amount", 17, 0, 127, 64, "mod"}, + MidiParam{"filter_multidrive", "Filter Multidrive", 18, 0, 127, 64, "filter"}, + MidiParam{"filter_cutoff", "Filter Cutoff", 19, 0, 127, 64, "filter"}, + MidiParam{"mod_1_pgm_dest_amount", "Mod 1 Pgm Dest Amount", 20, 0, 127, 64, "mod"}, + MidiParam{"filter_resonance", "Filter Resonance", 21, 0, 127, 64, "filter"}, + MidiParam{"filter_kb_amount", "Filter KB Amount", 22, 0, 127, 64, "filter"}, + MidiParam{"filter_eg_attack_time", "Filter EG Attack Time", 23, 0, 127, 64, "env"}, + MidiParam{"filter_eg_decay_time", "Filter EG Decay Time", 24, 0, 127, 64, "env"}, + MidiParam{"filter_eg_sustain_time", "Filter EG Sustain Time", 25, 0, 127, 64, "env"}, + MidiParam{"filter_eg_release_time", "Filter EG Release Time", 26, 0, 127, 64, "env"}, + MidiParam{"filter_eg_amount", "Filter EG Amount", 27, 0, 127, 64, "filter"}, + MidiParam{"amp_eg_attack_time", "Amp EG Attack Time", 28, 0, 127, 64, "env"}, + MidiParam{"amp_eg_decay_time", "Amp EG Decay Time", 29, 0, 127, 64, "env"}, + MidiParam{"amp_eg_sustain_time", "Amp EG Sustain Time", 30, 0, 127, 64, "env"}, + MidiParam{"amp_eg_release_time", "Amp EG Release Time", 31, 0, 127, 64, "env"}, + MidiParam{"bank_select_cc32", "Bank Select (LSB)", 32, 0, 127, 64, "global"}, + MidiParam{"mod_wheel_cc33", "Mod Wheel (LSB)", 33, 0, 127, 64, "mod"}, + MidiParam{"hold_pedal_sustain", "Hold Pedal/Sustain", 64, 0, 127, 64, "env"}, + MidiParam{"glide_on", "Glide On", 65, 0, 127, 64, "osc"}, + MidiParam{"arpeggiator_latch", "Arpeggiator Latch", 69, 0, 127, 64, "arp"}, + MidiParam{"mod_1_osc_1_2_select", "Mod 1 Osc 1/2 Select", 70, 0, 127, 64, "mod"}, + MidiParam{"mod_1_source", "Mod 1 Source", 71, 0, 127, 64, "mod"}, + MidiParam{"mod_2_source", "Mod 2 Source", 72, 0, 127, 64, "mod"}, + MidiParam{"arp_on_off", "Arp On/Off", 73, 0, 127, 64, "arp"}, + MidiParam{"osc_1_octave", "Osc 1 Octave", 74, 0, 127, 64, "osc"}, + MidiParam{"osc_2_octave", "Osc 2 Octave", 75, 0, 127, 64, "osc"}, + MidiParam{"lfo_1_range", "LFO 1 Range", 76, 0, 127, 64, "lfo"}, + MidiParam{"osc_2_hard_sync_on_off", "Osc 2 Hard Sync On/Off", 77, 0, 127, 64, "osc"}, + MidiParam{"lfo_2_range", "LFO 2 Range", 78, 0, 127, 64, "lfo"}, + MidiParam{"filter_eg_kb_amount", "Filter EG KB Amount", 79, 0, 127, 64, "filter"}, + MidiParam{"amp_eg_kb_amount", "Amp EG KB Amount", 80, 0, 127, 64, "mix"}, + MidiParam{"osc_kb_reset_on_off", "Osc KB Reset On/Off", 81, 0, 127, 64, "filter"}, + MidiParam{"filter_eg_reset", "Filter EG Reset", 82, 0, 127, 64, "filter"}, + MidiParam{"amp_eg_reset", "Amp EG Reset", 83, 0, 127, 64, "filter"}, + MidiParam{"reserved_portamento_control", "Reserved - Portamento Control", 84, 0, 127, 64, "osc"}, + MidiParam{"glide_type", "Glide Type", 85, 0, 127, 64, "osc"}, + MidiParam{"filter_eg_velocity_amount", "Filter EG Velocity Amount", 86, 0, 127, 64, "filter"}, + MidiParam{"amp_eg_velocity_amount", "Amp EG Velocity Amount", 87, 0, 127, 64, "mix"}, + MidiParam{"mod_2_osc_1_2_select", "Mod 2 Osc 1/2 Select", 88, 0, 127, 64, "mod"}, + MidiParam{"kb_octave", "KB Octave", 89, 0, 127, 64, "osc"}, + MidiParam{"mod_1_destination", "Mod 1 Destination", 91, 0, 127, 64, "mod"}, + MidiParam{"mod_2_destination", "Mod 2 Destination", 92, 0, 127, 64, "mod"}, + MidiParam{"lfo_1_kb_reset", "LFO 1 KB Reset", 93, 0, 127, 64, "lfo"}, + MidiParam{"glide_legato", "Glide Legato", 94, 0, 127, 64, "osc"}, + MidiParam{"lfo_2_kb_reset", "LFO 2 KB Reset", 95, 0, 127, 64, "lfo"}, + MidiParam{"glide_dest_osc_1_2_both", "Glide Dest Osc 1/2/Both", 102, 0, 127, 64, "osc"}, + MidiParam{"filter_eg_delay", "Filter EG Delay", 103, 0, 127, 64, "filter"}, + MidiParam{"amp_eg_delay", "Amp EG Delay", 104, 0, 127, 64, "fx"}, + MidiParam{"filter_eg_hold", "Filter EG Hold", 105, 0, 127, 64, "env"}, + MidiParam{"amp_eg_hold", "Amp EG Hold", 106, 0, 127, 64, "env"}, + MidiParam{"pitch_bend_up_amount", "Pitch Bend Up Amount", 107, 0, 127, 64, "osc"}, + MidiParam{"pitch_bend_down_amount", "Pitch Bend Down Amount", 108, 0, 127, 64, "osc"}, + MidiParam{"filter_slopes", "Filter Slopes (Poles)", 109, 0, 127, 64, "filter"}, + MidiParam{"osc_duo_mode_on_off", "Osc Duo Mode On/Off", 110, 0, 127, 64, "mod"}, + MidiParam{"kb_ctrl_lo_hi", "KB Ctrl Lo/Hi", 111, 0, 127, 64, "global"}, + MidiParam{"filter_eg_multi_trig", "Filter EG Multi Trig", 112, 0, 127, 64, "filter"}, + MidiParam{"amp_eg_multi_trig", "Amp EG Multi Trig", 113, 0, 127, 64, "mix"}, + MidiParam{"osc_1_level", "Osc 1 Level", 114, 0, 127, 64, "osc"}, + MidiParam{"osc_1_sub_level", "Osc 1 Sub Level", 115, 0, 127, 64, "osc"}, + MidiParam{"osc_2_level", "Osc 2 Level", 116, 0, 127, 64, "osc"}, + MidiParam{"noise_level", "Noise Level", 117, 0, 127, 64, "osc"}, + MidiParam{"feedback_ext_level", "Feedback/Ext Level", 118, 0, 127, 64, "mix"}, + MidiParam{"kb_transpose", "KB Transpose (receive only)", 119, 0, 127, 64, "global"}, + MidiParam{"local_control_on_off", "Local Control On/Off", 122, 0, 127, 64, "global"}, +}}; + +inline constexpr std::array kRolandJd800Params = {{ + MidiParam{"modulation", "Modulation", 1, 0, 127, 64, "mod"}, + MidiParam{"breath_controller", "Breath Controller", 2, 0, 127, 64, "global"}, + MidiParam{"portamento_time", "Portamento Time", 5, 0, 127, 64, "osc"}, + MidiParam{"data_entry_msb", "Data Entry MSB (RPN; receive only)", 6, 0, 127, 64, "global"}, + MidiParam{"volume_part_level", "Volume / Part Level", 7, 0, 127, 64, "mix"}, + MidiParam{"pan", "Pan", 10, 0, 127, 64, "mix"}, + MidiParam{"expression", "Expression", 11, 0, 127, 64, "global"}, + MidiParam{"hold_sustain_pedal", "Hold / Sustain Pedal", 64, 0, 127, 64, "env"}, + MidiParam{"portamento_on_off", "Portamento On/Off", 65, 0, 127, 64, "osc"}, + MidiParam{"rpn_lsb", "RPN LSB (receive only)", 100, 0, 127, 64, "global"}, + MidiParam{"rpn_msb", "RPN MSB (receive only)", 101, 0, 127, 64, "global"}, + MidiParam{"reset_all_controllers", "Reset All Controllers (receive only)", 121, 0, 127, 64, "global"}, + MidiParam{"all_notes_off", "All Notes Off (receive only)", 123, 0, 127, 64, "global"}, +}}; + +inline constexpr MidiDevice kAsmHydrasynth = { + "asm_hydrasynth", + "ASM Hydrasynth", + "Ashun Sound Machines (ASM)", + 1, + 0, + 127, + std::span{kAsmHydrasynthParams}, +}; + +inline constexpr MidiDevice kCreamwarePro12Asb = { + "creamware_pro12_asb", + "Creamware Pro-12 ASB", + "Creamware / Sonic Core", + 1, + 0, + 127, + std::span{kCreamwarePro12AsbParams}, +}; + +inline constexpr MidiDevice kElektronAnalogKeys = { + "elektron_analog_keys", + "Elektron Analog Keys", + "Elektron", + 1, + 0, + 127, + std::span{kElektronAnalogKeysParams}, +}; + +inline constexpr MidiDevice kMoogSubPhatty = { + "moog_sub_phatty", + "Moog Sub Phatty", + "Moog", + 1, + 0, + 127, + std::span{kMoogSubPhattyParams}, +}; + +inline constexpr MidiDevice kMoogSub37 = { + "moog_sub37", + "Moog Sub 37", + "Moog", + 1, + 0, + 127, + std::span{kMoogSub37Params}, +}; + +inline constexpr MidiDevice kRolandJd800 = { + "roland_jd800", + "Roland JD-800", + "Roland", + 1, + 0, + 127, + std::span{kRolandJd800Params}, +}; + +inline constexpr std::size_t kMidiDeviceCount = 6u; +inline constexpr std::array kMidiDevices = {{ + kAsmHydrasynth, + kCreamwarePro12Asb, + kElektronAnalogKeys, + kMoogSubPhatty, + kMoogSub37, + kRolandJd800, +}}; + +} // namespace nisps::midi::generated + +#endif // NISPS_MIDI_GENERATED_MIDI_DEVICES_HPP diff --git a/schemas/midi_device.schema.json b/schemas/midi_device.schema.json new file mode 100644 index 0000000..45a0e8a --- /dev/null +++ b/schemas/midi_device.schema.json @@ -0,0 +1,60 @@ +{ + "$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" } + } + } + } + } +} diff --git a/schemas/midi_devices/asm_hydrasynth.json b/schemas/midi_devices/asm_hydrasynth.json new file mode 100644 index 0000000..d350e2e --- /dev/null +++ b/schemas/midi_devices/asm_hydrasynth.json @@ -0,0 +1,1069 @@ +{ + "$schema": "../midi_device.schema.json", + "device_id": "asm_hydrasynth", + "name": "ASM Hydrasynth", + "manufacturer": "Ashun Sound Machines (ASM)", + "year": 2019, + "midi": { + "default_channel": 1, + "value_range": [ + 0, + 127 + ] + }, + "params": [ + { + "id": "bank_select_msb", + "cc": 0, + "label": "Bank Select MSB", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "mod_wheel", + "cc": 1, + "label": "Mod Wheel", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "noise_vol", + "cc": 3, + "label": "Noise Vol", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "glide_time", + "cc": 5, + "label": "Glide Time", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "master_volume", + "cc": 7, + "label": "Master Volume", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "noise_pan", + "cc": 8, + "label": "Noise Pan", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "ring_mod_vol", + "cc": 9, + "label": "Ring Mod Vol", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "ring_mod_pan", + "cc": 10, + "label": "Ring Mod Pan", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "expression_pedal", + "cc": 11, + "label": "Expression Pedal", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "pre_fx_param1", + "cc": 12, + "label": "PRE-FX Param1", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "pre_fx_param2", + "cc": 13, + "label": "PRE-FX Param2", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "delay_feedback", + "cc": 14, + "label": "Delay Feedback", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "delay_time", + "cc": 15, + "label": "Delay Time", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "macro_1", + "cc": 16, + "label": "Macro 1", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "macro_2", + "cc": 17, + "label": "Macro 2", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "macro_3", + "cc": 18, + "label": "Macro 3", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "macro_4", + "cc": 19, + "label": "Macro 4", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "macro_5", + "cc": 20, + "label": "Macro 5", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "macro_6", + "cc": 21, + "label": "Macro 6", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "macro_7", + "cc": 22, + "label": "Macro 7", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "macro_8", + "cc": 23, + "label": "Macro 8", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "osc1_wavscan", + "cc": 24, + "label": "OSC1 WavScan", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "env4_attack", + "cc": 25, + "label": "ENV4 Attack", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "osc2_wavscan", + "cc": 26, + "label": "OSC2 WavScan", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "env4_decay", + "cc": 27, + "label": "ENV4 Decay", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "lfo2_gain", + "cc": 28, + "label": "LFO2 Gain", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "mutator1_ratio", + "cc": 29, + "label": "Mutator1 Ratio", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "mutator1_depth", + "cc": 30, + "label": "Mutator1 Depth", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "mutator1_dry_wet", + "cc": 31, + "label": "Mutator1 Dry/Wet", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "bank_select_lsb", + "cc": 32, + "label": "Bank Select LSB", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "mutator2_ratio", + "cc": 33, + "label": "Mutator2 Ratio", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "mutator2_depth", + "cc": 34, + "label": "Mutator2 Depth", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "mutator2_dry_wet", + "cc": 35, + "label": "Mutator2 Dry/Wet", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "mutator3_ratio", + "cc": 36, + "label": "Mutator3 Ratio", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "mutator3_depth", + "cc": 37, + "label": "Mutator3 Depth", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "mutator3_dry_wet", + "cc": 39, + "label": "Mutator3 Dry/Wet", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "mutator4_ratio", + "cc": 40, + "label": "Mutator4 Ratio", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "mutator4_depth", + "cc": 41, + "label": "Mutator4 Depth", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "mutator4_dry_wet", + "cc": 42, + "label": "Mutator4 Dry/Wet", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "rm12_depth", + "cc": 43, + "label": "RM12 Depth (Ring Mod Depth)", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "osc1_vol", + "cc": 44, + "label": "OSC1 Vol", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc1_pan", + "cc": 45, + "label": "OSC1 Pan", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc2_vol", + "cc": 46, + "label": "OSC2 Vol", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc2_pan", + "cc": 47, + "label": "OSC2 Pan", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc3_vol", + "cc": 48, + "label": "OSC3 Vol", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc3_pan", + "cc": 49, + "label": "OSC3 Pan", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "filter1_drive", + "cc": 50, + "label": "Filter1 Drive", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter1_keytrack", + "cc": 51, + "label": "Filter1 Keytrack", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter1_lfo1_amt", + "cc": 52, + "label": "Filter1 LFO1 Amt", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "filter1_vel_env", + "cc": 53, + "label": "Filter1 Vel Env", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter1_env1_amt", + "cc": 54, + "label": "Filter1 ENV1 Amt", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter2_cutoff", + "cc": 55, + "label": "Filter2 Cutoff", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter2_res", + "cc": 56, + "label": "Filter2 Res", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter2_type_morph", + "cc": 57, + "label": "Filter2 Type/Morph", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter2_keytrack", + "cc": 58, + "label": "Filter2 Keytrack", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter2_lfo1_amt", + "cc": 59, + "label": "Filter2 LFO1 Amt", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "filter2_vel_env", + "cc": 60, + "label": "Filter2 Vel Env", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter2_env1_amt", + "cc": 61, + "label": "Filter2 ENV1 Amt", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "amp_lfo2_amt", + "cc": 62, + "label": "Amp LFO2 Amt", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "delay_wet_tone", + "cc": 63, + "label": "Delay Wet Tone", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "sustain_pedal", + "cc": 64, + "label": "Sustain Pedal", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "reverb_time", + "cc": 65, + "label": "Reverb Time", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "glide_on_off", + "cc": 66, + "label": "Glide On/Off", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "reverb_tone", + "cc": 67, + "label": "Reverb Tone", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "post_fx_param1", + "cc": 68, + "label": "POST-FX Param1", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "post_fx_param2", + "cc": 69, + "label": "POST-FX Param2", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "lfo1_gain", + "cc": 70, + "label": "LFO1 Gain", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "filter1_res", + "cc": 71, + "label": "Filter1 Res", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "lfo1_rate", + "cc": 72, + "label": "LFO1 Rate", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "lfo2_rate", + "cc": 73, + "label": "LFO2 Rate", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "filter1_cutoff", + "cc": 74, + "label": "Filter1 Cutoff", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "lfo3_gain", + "cc": 75, + "label": "LFO3 Gain", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "lfo3_rate", + "cc": 76, + "label": "LFO3 Rate", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "lfo4_gain", + "cc": 77, + "label": "LFO4 Gain", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "lfo4_rate", + "cc": 78, + "label": "LFO4 Rate", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "lfo5_gain", + "cc": 79, + "label": "LFO5 Gain", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "lfo5_rate", + "cc": 80, + "label": "LFO5 Rate", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "env1_attack", + "cc": 81, + "label": "ENV1 Attack", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "env1_decay", + "cc": 82, + "label": "ENV1 Decay", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "env1_sustain", + "cc": 83, + "label": "ENV1 Sustain", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "env1_release", + "cc": 84, + "label": "ENV1 Release", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "env2_attack", + "cc": 85, + "label": "ENV2 Attack", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "env2_decay", + "cc": 86, + "label": "ENV2 Decay", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "env2_sustain", + "cc": 87, + "label": "ENV2 Sustain", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "env2_release", + "cc": 88, + "label": "ENV2 Release", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "env3_attack", + "cc": 89, + "label": "ENV3 Attack", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "env3_decay", + "cc": 90, + "label": "ENV3 Decay", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "reverb_dry_wet", + "cc": 91, + "label": "Reverb Dry/Wet", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "delay_dry_wet", + "cc": 92, + "label": "Delay Dry/Wet", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "pre_fx_mix", + "cc": 93, + "label": "PRE-FX Mix", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "post_fx_mix", + "cc": 94, + "label": "POST-FX Mix", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "detune", + "cc": 95, + "label": "Detune", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "env3_sustain", + "cc": 96, + "label": "ENV3 Sustain", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "env3_release", + "cc": 97, + "label": "ENV3 Release", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "env5_attack", + "cc": 102, + "label": "ENV5 Attack", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "env5_decay", + "cc": 103, + "label": "ENV5 Decay", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "env5_sustain", + "cc": 104, + "label": "ENV5 Sustain", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "env5_release", + "cc": 105, + "label": "ENV5 Release", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "arp_division", + "cc": 106, + "label": "ARP Division", + "min": 0, + "max": 127, + "default": 64, + "group": "arp" + }, + { + "id": "arp_gate", + "cc": 107, + "label": "ARP Gate", + "min": 0, + "max": 127, + "default": 64, + "group": "arp" + }, + { + "id": "arp_mode", + "cc": 108, + "label": "ARP Mode", + "min": 0, + "max": 127, + "default": 64, + "group": "arp" + }, + { + "id": "arp_ratchet", + "cc": 109, + "label": "ARP Ratchet", + "min": 0, + "max": 127, + "default": 64, + "group": "arp" + }, + { + "id": "arp_chance", + "cc": 110, + "label": "ARP Chance", + "min": 0, + "max": 127, + "default": 64, + "group": "arp" + }, + { + "id": "osc1_cent", + "cc": 111, + "label": "OSC1 Cent", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc2_cent", + "cc": 112, + "label": "OSC2 Cent", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc3_cent", + "cc": 113, + "label": "OSC3 Cent", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc3_f_rate", + "cc": 114, + "label": "OSC3 F Rate", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "noise_f_rate", + "cc": 115, + "label": "Noise F Rate", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "ring_mod_f_rate", + "cc": 116, + "label": "Ring Mod F Rate", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "stereo_width", + "cc": 117, + "label": "Stereo Width", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "osc1_f_rate", + "cc": 118, + "label": "OSC1 F Rate", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc2_f_rate", + "cc": 119, + "label": "OSC2 F Rate", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "arp_octave", + "cc": 120, + "label": "ARP Octave (repurposed from standard 'All Sounds Off')", + "min": 0, + "max": 127, + "default": 64, + "group": "arp" + }, + { + "id": "arp_length", + "cc": 122, + "label": "ARP Length", + "min": 0, + "max": 127, + "default": 64, + "group": "arp" + }, + { + "id": "all_notes_off", + "cc": 123, + "label": "All Notes Off", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "env4_release", + "cc": 124, + "label": "ENV4 Release", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "env4_sustain", + "cc": 125, + "label": "ENV4 Sustain", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + } + ] +} diff --git a/schemas/midi_devices/creamware_pro12_asb.json b/schemas/midi_devices/creamware_pro12_asb.json new file mode 100644 index 0000000..f2c7913 --- /dev/null +++ b/schemas/midi_devices/creamware_pro12_asb.json @@ -0,0 +1,736 @@ +{ + "$schema": "../midi_device.schema.json", + "device_id": "creamware_pro12_asb", + "name": "Creamware Pro-12 ASB", + "manufacturer": "Creamware / Sonic Core", + "year": 2005, + "midi": { + "default_channel": 1, + "value_range": [ + 0, + 127 + ] + }, + "params": [ + { + "id": "bank_select", + "cc": 0, + "label": "Bank Select", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "modulation", + "cc": 1, + "label": "Modulation", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "unison_voices", + "cc": 2, + "label": "Unison Voices", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "unison_detune", + "cc": 3, + "label": "Unison Detune", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "glide_time", + "cc": 5, + "label": "Glide Time", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "data_entry", + "cc": 6, + "label": "Data Entry", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "device_volume", + "cc": 7, + "label": "Device Volume", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "lfo_settings_retrig", + "cc": 8, + "label": "LFO Settings Retrig", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "lfo_settings_phase", + "cc": 9, + "label": "LFO Settings Phase", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "volume", + "cc": 11, + "label": "Volume", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "osc_a_frequency", + "cc": 12, + "label": "Osc A Frequency", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_a_shape_saw", + "cc": 13, + "label": "Osc A Shape Saw", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_a_shape_pulse", + "cc": 14, + "label": "Osc A Shape Pulse", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_a_pulse_width", + "cc": 15, + "label": "Osc A Pulse Width", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_a_sync", + "cc": 16, + "label": "Osc A Sync", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_b_frequency", + "cc": 17, + "label": "Osc B Frequency", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_b_fine", + "cc": 18, + "label": "Osc B Fine", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_b_shape_saw", + "cc": 19, + "label": "Osc B Shape Saw", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_b_shape_triangle", + "cc": 20, + "label": "Osc B Shape Triangle", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "master_tune", + "cc": 21, + "label": "Master Tune", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_b_shape_pulse", + "cc": 22, + "label": "Osc B Shape Pulse", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "aftertouch_pitch", + "cc": 23, + "label": "Aftertouch Pitch", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "bend_range", + "cc": 24, + "label": "Bend Range", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "osc_a_volume", + "cc": 25, + "label": "Osc A Volume", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_b_volume", + "cc": 26, + "label": "Osc B Volume", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_b_pulse_width", + "cc": 27, + "label": "Osc B Pulse Width", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_b_lo_freq", + "cc": 28, + "label": "Osc B Lo Freq", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_b_keyboard", + "cc": 29, + "label": "Osc B Keyboard", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "aftertouch_dest_freq_a", + "cc": 30, + "label": "Aftertouch Dest Freq A", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "aftertouch_dest_freq_b", + "cc": 31, + "label": "Aftertouch Dest Freq B", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "bank_select_cc32", + "cc": 32, + "label": "Bank Select", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "noise_volume", + "cc": 33, + "label": "Noise Volume", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "aftertouch_pw", + "cc": 34, + "label": "Aftertouch PW", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "aftertouch_mw", + "cc": 35, + "label": "Aftertouch MW", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "external_volume", + "cc": 36, + "label": "External Volume", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "aftertouch_dest_pw", + "cc": 37, + "label": "Aftertouch Dest PW", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "aftertouch_dest_pw_cc38", + "cc": 38, + "label": "Aftertouch Dest PW", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "keyboard_amount", + "cc": 39, + "label": "Keyboard Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "cutoff", + "cc": 40, + "label": "Cutoff", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "resonance", + "cc": 41, + "label": "Resonance", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "envelope_amount", + "cc": 42, + "label": "Envelope Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_env_attack", + "cc": 43, + "label": "Filter Env Attack", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_env_decay", + "cc": 44, + "label": "Filter Env Decay", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_env_sustain", + "cc": 45, + "label": "Filter Env Sustain", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_env_velocity", + "cc": 46, + "label": "Filter Env Velocity", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_release", + "cc": 47, + "label": "Filter Release", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "aftertouch_lfo_freq", + "cc": 48, + "label": "Aftertouch LFO Freq", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "release", + "cc": 49, + "label": "Release", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "aftertouch_filter", + "cc": 50, + "label": "Aftertouch Filter", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "aftertouch_amp", + "cc": 51, + "label": "Aftertouch Amp", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "amp_env_attack", + "cc": 52, + "label": "Amp Env Attack", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "amp_env_decay", + "cc": 53, + "label": "Amp Env Decay", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "amp_env_sustain", + "cc": 54, + "label": "Amp Env Sustain", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "amp_env_velocity", + "cc": 55, + "label": "Amp Env Velocity", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "mw_intensity", + "cc": 56, + "label": "MW Intensity", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "mw_offset", + "cc": 57, + "label": "MW Offset", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "poly_mod_osc_b", + "cc": 58, + "label": "Poly Mod OSC B", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "adr", + "cc": 59, + "label": "ADR", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "keyb_mode_retrig", + "cc": 60, + "label": "Keyb Mode Retrig", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "low_note", + "cc": 61, + "label": "Low Note", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "amp_env_release", + "cc": 62, + "label": "Amp Env Release", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "poly_mod_filter_env", + "cc": 63, + "label": "Poly Mod Filter Env", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "poly_mod_destination_freq_a", + "cc": 75, + "label": "Poly Mod Destination Freq A", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "poly_mod_destination_freq_b", + "cc": 76, + "label": "Poly Mod Destination Freq B", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "poly_mod_destination_pw", + "cc": 77, + "label": "Poly Mod Destination PW", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "poly_mod_destination_pw_cc78", + "cc": 78, + "label": "Poly Mod Destination PW", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "poly_mod_destination_filter", + "cc": 79, + "label": "Poly Mod Destination Filter", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "amt", + "cc": 98, + "label": "Amt", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "wheel_mod_source_mix", + "cc": 108, + "label": "Wheel Mod Source Mix", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "time_velocity_attack_filter_env", + "cc": 113, + "label": "Time Velocity Attack Filter Env", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "time_velocity_dec_rel_filter_env", + "cc": 114, + "label": "Time Velocity Dec/Rel Filter Env", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "time_velocity_dec_rel_amp_env", + "cc": 116, + "label": "Time Velocity Dec/Rel Amp Env", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "time_velocity_attack_amp_env", + "cc": 117, + "label": "Time Velocity Attack Amp Env", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "all_sounds_off", + "cc": 120, + "label": "All Sounds Off", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "local_control_off", + "cc": 121, + "label": "Local Control Off", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "all_notes_off", + "cc": 122, + "label": "All Notes Off", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "omni_off", + "cc": 124, + "label": "Omni Off", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "omni_on", + "cc": 125, + "label": "Omni On", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "mono_on", + "cc": 126, + "label": "Mono On", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "poly_on", + "cc": 127, + "label": "Poly On", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + } + ] +} diff --git a/schemas/midi_devices/elektron_analog_keys.json b/schemas/midi_devices/elektron_analog_keys.json new file mode 100644 index 0000000..5f6aa22 --- /dev/null +++ b/schemas/midi_devices/elektron_analog_keys.json @@ -0,0 +1,781 @@ +{ + "$schema": "../midi_device.schema.json", + "device_id": "elektron_analog_keys", + "name": "Elektron Analog Keys", + "manufacturer": "Elektron", + "year": 2014, + "midi": { + "default_channel": 1, + "value_range": [ + 0, + 127 + ] + }, + "params": [ + { + "id": "modulation_modwheel", + "cc": 1, + "label": "Modulation: Modwheel (MSB, 14-bit pair with CC 33)", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "modulation_breath", + "cc": 2, + "label": "Modulation: Breath (MSB, 14-bit pair with CC 34)", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "performance_parameter_a", + "cc": 3, + "label": "Performance: Parameter A", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "performance_parameter_b", + "cc": 4, + "label": "Performance: Parameter B", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "osc_slide_time", + "cc": 5, + "label": "OSC: Slide Time", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "amp_volume", + "cc": 7, + "label": "Amp: Volume", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "performance_parameter_c", + "cc": 8, + "label": "Performance: Parameter C", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "performance_parameter_d", + "cc": 9, + "label": "Performance: Parameter D", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "amp_pan", + "cc": 10, + "label": "Amp: Pan", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "performance_parameter_e", + "cc": 11, + "label": "Performance: Parameter E", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "osc1_pitch", + "cc": 16, + "label": "OSC1: Pitch (MSB, 14-bit pair with CC 48)", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc2_pitch", + "cc": 17, + "label": "OSC2: Pitch (MSB, 14-bit pair with CC 49)", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "filter_1_frequency", + "cc": 18, + "label": "Filter 1: Frequency (MSB, 14-bit pair with CC 50)", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter_2_frequency", + "cc": 19, + "label": "Filter 2: Frequency (MSB, 14-bit pair with CC 51)", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter_env_depth_a", + "cc": 20, + "label": "Filter Env: Depth A (MSB, 14-bit pair with CC 52)", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_env_depth_b", + "cc": 21, + "label": "Filter Env: Depth B (MSB, 14-bit pair with CC 53)", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "aux_env_depth_a", + "cc": 22, + "label": "AUX Env: Depth A (MSB, 14-bit pair with CC 54)", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "aux_env_depth_b", + "cc": 23, + "label": "AUX Env: Depth B (MSB, 14-bit pair with CC 55)", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "lfo1_depth_a", + "cc": 24, + "label": "LFO1: Depth A (MSB, 14-bit pair with CC 56)", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "lfo1_depth_b", + "cc": 25, + "label": "LFO1: Depth B (MSB, 14-bit pair with CC 57)", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "lfo2_depth_a", + "cc": 26, + "label": "LFO2: Depth A (MSB, 14-bit pair with CC 58)", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "lfo2_depth_b", + "cc": 27, + "label": "LFO2: Depth B (MSB, 14-bit pair with CC 59)", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "modulation_modwheel_cc33", + "cc": 33, + "label": "Modulation: Modwheel (LSB)", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "modulation_breath_cc34", + "cc": 34, + "label": "Modulation: Breath (LSB)", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "osc1_pitch_cc48", + "cc": 48, + "label": "OSC1: Pitch (LSB)", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc2_pitch_cc49", + "cc": 49, + "label": "OSC2: Pitch (LSB)", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "filter_1_frequency_cc50", + "cc": 50, + "label": "Filter 1: Frequency (LSB)", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter_2_frequency_cc51", + "cc": 51, + "label": "Filter 2: Frequency (LSB)", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter_env_depth_a_cc52", + "cc": 52, + "label": "Filter Env: Depth A (LSB; MkI: 'EnvF Gate Length')", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_env_depth_b_cc53", + "cc": 53, + "label": "Filter Env: Depth B (LSB)", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "aux_env_depth_a_cc54", + "cc": 54, + "label": "AUX Env: Depth A (LSB)", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "aux_env_depth_b_cc55", + "cc": 55, + "label": "AUX Env: Depth B (LSB)", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "lfo1_depth_a_cc56", + "cc": 56, + "label": "LFO1: Depth A (LSB)", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "lfo1_depth_b_cc57", + "cc": 57, + "label": "LFO1: Depth B (LSB)", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "lfo2_depth_a_cc58", + "cc": 58, + "label": "LFO2: Depth A (LSB)", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "lfo2_depth_b_cc59", + "cc": 59, + "label": "LFO2: Depth B (LSB)", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "performance_parameter_f", + "cc": 64, + "label": "Performance: Parameter F", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "performance_parameter_g", + "cc": 65, + "label": "Performance: Parameter G", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "performance_parameter_h", + "cc": 66, + "label": "Performance: Parameter H", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "performance_parameter_i", + "cc": 67, + "label": "Performance: Parameter I", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "performance_parameter_j", + "cc": 68, + "label": "Performance: Parameter J", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "osc1_level", + "cc": 69, + "label": "OSC1: Level", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc1_waveform", + "cc": 70, + "label": "OSC1: Waveform", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc1_sub_oscillator", + "cc": 71, + "label": "OSC1: Sub Oscillator", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc1_pulsewidth", + "cc": 72, + "label": "OSC1: Pulsewidth", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc1_pwm_speed", + "cc": 73, + "label": "OSC1: PWM Speed", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc1_pwm_depth", + "cc": 74, + "label": "OSC1: PWM Depth", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "noise_s_h", + "cc": 75, + "label": "Noise: S&H", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "noise_fade", + "cc": 76, + "label": "Noise: Fade", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "noise_level", + "cc": 77, + "label": "Noise: Level", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc2_level", + "cc": 78, + "label": "OSC2: Level", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc2_waveform", + "cc": 79, + "label": "OSC2: Waveform", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc2_sub_oscillator", + "cc": 80, + "label": "OSC2: Sub Oscillator", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc2_pulsewidth", + "cc": 81, + "label": "OSC2: Pulsewidth", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc2_pwm_speed", + "cc": 82, + "label": "OSC2: PWM Speed", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc2_pwm_depth", + "cc": 83, + "label": "OSC2: PWM Depth", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_sync_amount", + "cc": 84, + "label": "OSC: Sync Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_bend_amount", + "cc": 85, + "label": "OSC: Bend Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "filter_1_overdrive", + "cc": 86, + "label": "Filter 1: Overdrive", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "osc_vibrato_speed", + "cc": 88, + "label": "OSC: Vibrato Speed (Analog Keys/MkI)", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "filter_1_resonance", + "cc": 89, + "label": "Filter 1: Resonance", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter_2_resonance", + "cc": 90, + "label": "Filter 2: Resonance", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "amp_chorus_send", + "cc": 91, + "label": "Amp: Chorus Send", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "amp_delay_send", + "cc": 92, + "label": "Amp: Delay Send", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "amp_reverb_send", + "cc": 93, + "label": "Amp: Reverb Send", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "track_mute", + "cc": 94, + "label": "Track: Mute", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "track_level", + "cc": 95, + "label": "Track: Level", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "filter_1_envelope_depth", + "cc": 102, + "label": "Filter 1: Envelope Depth", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_2_envelope_depth", + "cc": 103, + "label": "Filter 2: Envelope Depth", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "amp_env_attack", + "cc": 104, + "label": "Amp Env: Attack", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "amp_env_decay", + "cc": 105, + "label": "Amp Env: Decay", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "amp_env_sustain", + "cc": 106, + "label": "Amp Env: Sustain", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "amp_env_release", + "cc": 107, + "label": "Amp Env: Release", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_env_attack", + "cc": 108, + "label": "Filter Env: Attack", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_env_decay", + "cc": 109, + "label": "Filter Env: Decay", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_env_sustain", + "cc": 110, + "label": "Filter Env: Sustain", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_env_release", + "cc": 111, + "label": "Filter Env: Release", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "aux_env_attack", + "cc": 112, + "label": "AUX Env: Attack", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "aux_env_decay", + "cc": 113, + "label": "AUX Env: Decay", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "aux_env_sustain", + "cc": 114, + "label": "AUX Env: Sustain", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "aux_env_release", + "cc": 115, + "label": "AUX Env: Release", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "lfo1_speed", + "cc": 116, + "label": "LFO1: Speed", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "lfo1_multiplier", + "cc": 117, + "label": "LFO1: Multiplier", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "lfo2_speed", + "cc": 118, + "label": "LFO2: Speed", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "lfo2_multiplier", + "cc": 119, + "label": "LFO2: Multiplier", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + } + ] +} diff --git a/schemas/midi_devices/moog_sub37.json b/schemas/midi_devices/moog_sub37.json new file mode 100644 index 0000000..bf57171 --- /dev/null +++ b/schemas/midi_devices/moog_sub37.json @@ -0,0 +1,745 @@ +{ + "$schema": "../midi_device.schema.json", + "device_id": "moog_sub37", + "name": "Moog Sub 37", + "manufacturer": "Moog", + "year": 2014, + "midi": { + "default_channel": 1, + "value_range": [ + 0, + 127 + ] + }, + "params": [ + { + "id": "bank_select", + "cc": 0, + "label": "Bank Select", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "mod_wheel", + "cc": 1, + "label": "Mod Wheel", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "reserved_midi_breath_control", + "cc": 2, + "label": "Reserved - MIDI Breath Control", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "lfo_1_rate", + "cc": 3, + "label": "LFO 1 Rate (also LFO 1 Clock Divider)", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "mod_1_pitch_amount", + "cc": 4, + "label": "Mod 1 Pitch Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "glide_time", + "cc": 5, + "label": "Glide Time", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "reserved_data_entry", + "cc": 6, + "label": "Reserved - Data Entry", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "master_volume", + "cc": 7, + "label": "Master Volume", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "lfo_2_rate", + "cc": 8, + "label": "LFO 2 Rate (also LFO 2 Clock Divider)", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "osc_1_wave", + "cc": 9, + "label": "Osc 1 Wave", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "reserved_midi_pan", + "cc": 10, + "label": "Reserved - MIDI Pan", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "mod_1_filter_amount", + "cc": 11, + "label": "Mod 1 Filter Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "osc_2_frequency", + "cc": 12, + "label": "Osc 2 Frequency", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_2_beat_frequency", + "cc": 13, + "label": "Osc 2 Beat Frequency", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_2_wave", + "cc": 14, + "label": "Osc 2 Wave", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "mod_2_pitch_amount", + "cc": 15, + "label": "Mod 2 Pitch Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "mod_2_filter_amount", + "cc": 16, + "label": "Mod 2 Filter Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "mod_2_pgm_dest_amount", + "cc": 17, + "label": "Mod 2 Pgm Dest Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "filter_multidrive", + "cc": 18, + "label": "Filter Multidrive", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter_cutoff", + "cc": 19, + "label": "Filter Cutoff", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "mod_1_pgm_dest_amount", + "cc": 20, + "label": "Mod 1 Pgm Dest Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "filter_resonance", + "cc": 21, + "label": "Filter Resonance", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter_kb_amount", + "cc": 22, + "label": "Filter KB Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter_eg_attack_time", + "cc": 23, + "label": "Filter EG Attack Time", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_eg_decay_time", + "cc": 24, + "label": "Filter EG Decay Time", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_eg_sustain_time", + "cc": 25, + "label": "Filter EG Sustain Time", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_eg_release_time", + "cc": 26, + "label": "Filter EG Release Time", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_eg_amount", + "cc": 27, + "label": "Filter EG Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "amp_eg_attack_time", + "cc": 28, + "label": "Amp EG Attack Time", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "amp_eg_decay_time", + "cc": 29, + "label": "Amp EG Decay Time", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "amp_eg_sustain_time", + "cc": 30, + "label": "Amp EG Sustain Time", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "amp_eg_release_time", + "cc": 31, + "label": "Amp EG Release Time", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "bank_select_cc32", + "cc": 32, + "label": "Bank Select (LSB)", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "mod_wheel_cc33", + "cc": 33, + "label": "Mod Wheel (LSB)", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "hold_pedal_sustain", + "cc": 64, + "label": "Hold Pedal/Sustain", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "glide_on", + "cc": 65, + "label": "Glide On", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "arpeggiator_latch", + "cc": 69, + "label": "Arpeggiator Latch", + "min": 0, + "max": 127, + "default": 64, + "group": "arp" + }, + { + "id": "mod_1_osc_1_2_select", + "cc": 70, + "label": "Mod 1 Osc 1/2 Select", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "mod_1_source", + "cc": 71, + "label": "Mod 1 Source", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "mod_2_source", + "cc": 72, + "label": "Mod 2 Source", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "arp_on_off", + "cc": 73, + "label": "Arp On/Off", + "min": 0, + "max": 127, + "default": 64, + "group": "arp" + }, + { + "id": "osc_1_octave", + "cc": 74, + "label": "Osc 1 Octave", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_2_octave", + "cc": 75, + "label": "Osc 2 Octave", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "lfo_1_range", + "cc": 76, + "label": "LFO 1 Range", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "osc_2_hard_sync_on_off", + "cc": 77, + "label": "Osc 2 Hard Sync On/Off", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "lfo_2_range", + "cc": 78, + "label": "LFO 2 Range", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "filter_eg_kb_amount", + "cc": 79, + "label": "Filter EG KB Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "amp_eg_kb_amount", + "cc": 80, + "label": "Amp EG KB Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "osc_kb_reset_on_off", + "cc": 81, + "label": "Osc KB Reset On/Off", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter_eg_reset", + "cc": 82, + "label": "Filter EG Reset", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "amp_eg_reset", + "cc": 83, + "label": "Amp EG Reset", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "reserved_portamento_control", + "cc": 84, + "label": "Reserved - Portamento Control", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "glide_type", + "cc": 85, + "label": "Glide Type", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "filter_eg_velocity_amount", + "cc": 86, + "label": "Filter EG Velocity Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "amp_eg_velocity_amount", + "cc": 87, + "label": "Amp EG Velocity Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "mod_2_osc_1_2_select", + "cc": 88, + "label": "Mod 2 Osc 1/2 Select", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "kb_octave", + "cc": 89, + "label": "KB Octave", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "mod_1_destination", + "cc": 91, + "label": "Mod 1 Destination", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "mod_2_destination", + "cc": 92, + "label": "Mod 2 Destination", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "lfo_1_kb_reset", + "cc": 93, + "label": "LFO 1 KB Reset", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "glide_legato", + "cc": 94, + "label": "Glide Legato", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "lfo_2_kb_reset", + "cc": 95, + "label": "LFO 2 KB Reset", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "glide_dest_osc_1_2_both", + "cc": 102, + "label": "Glide Dest Osc 1/2/Both", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "filter_eg_delay", + "cc": 103, + "label": "Filter EG Delay", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "amp_eg_delay", + "cc": 104, + "label": "Amp EG Delay", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "filter_eg_hold", + "cc": 105, + "label": "Filter EG Hold", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "amp_eg_hold", + "cc": 106, + "label": "Amp EG Hold", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "pitch_bend_up_amount", + "cc": 107, + "label": "Pitch Bend Up Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "pitch_bend_down_amount", + "cc": 108, + "label": "Pitch Bend Down Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "filter_slopes", + "cc": 109, + "label": "Filter Slopes (Poles)", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "osc_duo_mode_on_off", + "cc": 110, + "label": "Osc Duo Mode On/Off", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "kb_ctrl_lo_hi", + "cc": 111, + "label": "KB Ctrl Lo/Hi", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "filter_eg_multi_trig", + "cc": 112, + "label": "Filter EG Multi Trig", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "amp_eg_multi_trig", + "cc": 113, + "label": "Amp EG Multi Trig", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "osc_1_level", + "cc": 114, + "label": "Osc 1 Level", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_1_sub_level", + "cc": 115, + "label": "Osc 1 Sub Level", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "osc_2_level", + "cc": 116, + "label": "Osc 2 Level", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "noise_level", + "cc": 117, + "label": "Noise Level", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "feedback_ext_level", + "cc": 118, + "label": "Feedback/Ext Level", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "kb_transpose", + "cc": 119, + "label": "KB Transpose (receive only)", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "local_control_on_off", + "cc": 122, + "label": "Local Control On/Off", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + } + ] +} diff --git a/schemas/midi_devices/moog_sub_phatty.json b/schemas/midi_devices/moog_sub_phatty.json new file mode 100644 index 0000000..cc6a069 --- /dev/null +++ b/schemas/midi_devices/moog_sub_phatty.json @@ -0,0 +1,655 @@ +{ + "$schema": "../midi_device.schema.json", + "device_id": "moog_sub_phatty", + "name": "Moog Sub Phatty", + "manufacturer": "Moog", + "year": 2013, + "midi": { + "default_channel": 1, + "value_range": [ + 0, + 127 + ] + }, + "params": [ + { + "id": "modulation_wheel", + "cc": 1, + "label": "Modulation Wheel", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "filter_mod_amount", + "cc": 2, + "label": "Filter Mod Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "lfo_rate", + "cc": 3, + "label": "LFO Rate", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "pitch_mod_amount", + "cc": 4, + "label": "Pitch Mod Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "glide_rate", + "cc": 5, + "label": "Glide Rate", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "output_level", + "cc": 7, + "label": "Output Level (Volume)", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "noise_level", + "cc": 8, + "label": "Noise Level", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "vco_1_wave", + "cc": 9, + "label": "VCO 1 Wave", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "vco_2_frequency", + "cc": 12, + "label": "VCO 2 Frequency", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "vco_2_beat_frequency", + "cc": 13, + "label": "VCO 2 Beat Frequency", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "vco_2_wave", + "cc": 14, + "label": "VCO 2 Wave", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "vco_1_level", + "cc": 15, + "label": "VCO 1 Level", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "vco_2_level", + "cc": 16, + "label": "VCO 2 Level", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "vco_1_sub_level", + "cc": 17, + "label": "VCO 1 Sub Level", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "multidrive_amount", + "cc": 18, + "label": "Multidrive Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter_cutoff_frequency", + "cc": 19, + "label": "Filter Cutoff Frequency", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "wave_mod_amount", + "cc": 20, + "label": "Wave Mod Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "filter_resonance", + "cc": 21, + "label": "Filter Resonance", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter_eg_amount", + "cc": 22, + "label": "Filter EG Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter_eg_attack", + "cc": 23, + "label": "Filter EG Attack", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_eg_decay", + "cc": 24, + "label": "Filter EG Decay", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_eg_sustain", + "cc": 25, + "label": "Filter EG Sustain", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_eg_release", + "cc": 26, + "label": "Filter EG Release", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "filter_kb_tracking_amount", + "cc": 27, + "label": "Filter KB Tracking Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "amplifier_eg_attack", + "cc": 28, + "label": "Amplifier EG Attack", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "amplifier_eg_decay", + "cc": 29, + "label": "Amplifier EG Decay", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "amplifier_eg_sustain", + "cc": 30, + "label": "Amplifier EG Sustain", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "amplifier_eg_release", + "cc": 31, + "label": "Amplifier EG Release", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "glide_on_off", + "cc": 65, + "label": "Glide On/Off", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "legato", + "cc": 68, + "label": "Legato", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "pitch_mod_osc_2_only", + "cc": 70, + "label": "Pitch Mod OSC 2 Only", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "modulation_source", + "cc": 71, + "label": "Modulation Source", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "wave_mod_destination", + "cc": 72, + "label": "Wave Mod Destination", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "gated_glide", + "cc": 73, + "label": "Gated Glide", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "vco_1_octave", + "cc": 74, + "label": "VCO 1 Octave", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "vco_2_octave", + "cc": 75, + "label": "VCO 2 Octave", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "lfo_range", + "cc": 76, + "label": "LFO Range", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "vco_hard_sync", + "cc": 77, + "label": "VCO Hard Sync", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "lfo_kb_tracking_amount", + "cc": 78, + "label": "LFO KB Tracking Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "filter_eg_velocity_to_time", + "cc": 79, + "label": "Filter EG Velocity to Time", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "amplifier_eg_velocity_to_time", + "cc": 80, + "label": "Amplifier EG Velocity to Time", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "vco_gate_reset", + "cc": 81, + "label": "VCO Gate Reset", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter_eg_reset", + "cc": 82, + "label": "Filter EG Reset", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "amplifier_eg_reset", + "cc": 83, + "label": "Amplifier EG Reset", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "glide_type", + "cc": 85, + "label": "Glide Type", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "filter_eg_repeat", + "cc": 86, + "label": "Filter EG Repeat", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "amplifier_eg_repeat", + "cc": 87, + "label": "Amplifier EG Repeat", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "release_on_off", + "cc": 88, + "label": "Release On/Off", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "keyboard_octave", + "cc": 89, + "label": "Keyboard Octave", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "filter_eg_kb_amount", + "cc": 90, + "label": "Filter EG KB Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "amplifier_eg_kb_amount", + "cc": 91, + "label": "Amplifier EG KB Amount", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "amplifier_eg_velocity_to_amplitude", + "cc": 92, + "label": "Amplifier EG Velocity to Amplitude", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "lfo_gate_reset", + "cc": 93, + "label": "LFO Gate Reset", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "glide_legato", + "cc": 94, + "label": "Glide Legato", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "lfo_midi_sync", + "cc": 102, + "label": "LFO MIDI Sync", + "min": 0, + "max": 127, + "default": 64, + "group": "lfo" + }, + { + "id": "filter_eg_delay", + "cc": 103, + "label": "Filter EG Delay", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "amplifier_eg_delay", + "cc": 104, + "label": "Amplifier EG Delay", + "min": 0, + "max": 127, + "default": 64, + "group": "fx" + }, + { + "id": "filter_eg_hold", + "cc": 105, + "label": "Filter EG Hold", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "amplifier_eg_hold", + "cc": 106, + "label": "Amplifier EG Hold", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "pitch_bend_up", + "cc": 107, + "label": "Pitch Bend Up", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "pitch_bend_down", + "cc": 108, + "label": "Pitch Bend Down", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "filter_poles", + "cc": 109, + "label": "Filter Poles", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "filter_eg_velocity_to_amplitude", + "cc": 110, + "label": "Filter EG Velocity to Amplitude", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "note_priority", + "cc": 111, + "label": "Note Priority", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "filter_eg_gate_source", + "cc": 113, + "label": "Filter EG Gate Source", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "volume_eg_gate_source", + "cc": 114, + "label": "Volume (Amplifier) EG Gate Source", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "filter_eg_trigger_mode", + "cc": 115, + "label": "Filter EG Trigger Mode", + "min": 0, + "max": 127, + "default": 64, + "group": "filter" + }, + { + "id": "external_input_level", + "cc": 116, + "label": "External Input Level", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "filter_eg_fast_decay", + "cc": 117, + "label": "Filter EG Fast Decay", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "amplifier_eg_fast_decay", + "cc": 118, + "label": "Amplifier EG Fast Decay", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "keyboard_transpose", + "cc": 119, + "label": "Keyboard Transpose", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + } + ] +} diff --git a/schemas/midi_devices/roland_jd800.json b/schemas/midi_devices/roland_jd800.json new file mode 100644 index 0000000..ed4d6d4 --- /dev/null +++ b/schemas/midi_devices/roland_jd800.json @@ -0,0 +1,133 @@ +{ + "$schema": "../midi_device.schema.json", + "device_id": "roland_jd800", + "name": "Roland JD-800", + "manufacturer": "Roland", + "year": 1991, + "midi": { + "default_channel": 1, + "value_range": [ + 0, + 127 + ] + }, + "params": [ + { + "id": "modulation", + "cc": 1, + "label": "Modulation", + "min": 0, + "max": 127, + "default": 64, + "group": "mod" + }, + { + "id": "breath_controller", + "cc": 2, + "label": "Breath Controller", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "portamento_time", + "cc": 5, + "label": "Portamento Time", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "data_entry_msb", + "cc": 6, + "label": "Data Entry MSB (RPN; receive only)", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "volume_part_level", + "cc": 7, + "label": "Volume / Part Level", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "pan", + "cc": 10, + "label": "Pan", + "min": 0, + "max": 127, + "default": 64, + "group": "mix" + }, + { + "id": "expression", + "cc": 11, + "label": "Expression", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "hold_sustain_pedal", + "cc": 64, + "label": "Hold / Sustain Pedal", + "min": 0, + "max": 127, + "default": 64, + "group": "env" + }, + { + "id": "portamento_on_off", + "cc": 65, + "label": "Portamento On/Off", + "min": 0, + "max": 127, + "default": 64, + "group": "osc" + }, + { + "id": "rpn_lsb", + "cc": 100, + "label": "RPN LSB (receive only)", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "rpn_msb", + "cc": 101, + "label": "RPN MSB (receive only)", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "reset_all_controllers", + "cc": 121, + "label": "Reset All Controllers (receive only)", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + }, + { + "id": "all_notes_off", + "cc": 123, + "label": "All Notes Off (receive only)", + "min": 0, + "max": 127, + "default": 64, + "group": "global" + } + ] +} diff --git a/synth-midi-cc.json b/synth-midi-cc.json new file mode 100644 index 0000000..8abc3e3 --- /dev/null +++ b/synth-midi-cc.json @@ -0,0 +1,617 @@ +{ + "$comment": "Compiled MIDI Continuous Controller (CC) maps for a set of hardware synths/drum machines. Researched and double-verified against official manuals + independent community sources by parallel Sonnet research agents on 2026-06-28. Each entry records confidence and verification_notes; read those before trusting an individual CC. NRPN-only parameters are NOT listed here (CC only). Where a device's panel transmits SysEx/NRPN rather than CC, that is noted.", + "generated": "2026-06-28", + "global_notes": [ + "CC numbers are MSB / primary numbers. Several Moog and Creamware params support 14-bit CC where the LSB = MSB + 32 (active only in 14-bit mode).", + "Two requested names were corrected during research: the 'Creamware Pro-12 ASB' emulates the Sequential Prophet-5 (Rev 3), NOT a Prophet-12; and there is NO 'Roland RD-9' -- the RD-9 Rhythm Designer is a Behringer TR-909 clone (Roland's RD series are stage pianos; Roland's 909 reissue is the TR-09).", + "The original 1981 Korg Polysix predates MIDI entirely and has no CC support; only third-party retrofits and the Korg Legacy software emulation add MIDI." + ], + "synths": [ + { + "name": "Moog Sub 37", + "manufacturer": "Moog", + "year": 2014, + "midi_channel_notes": "Default MIDI In/Out channel 1 (configurable 1-16; In supports ALL/Omni). Panel controls transmit when the 'PANEL' out-filter is ON. 'KNB NRPN/CC' menu selects CC (default) or NRPN; NRPN required for full coverage of 150+ params. 'CC FORMAT' selects 7-bit (default) or 14-bit; most continuous CCs have a 14-bit form (LSB = MSB + 32, e.g. Filter Cutoff CC19 MSB / CC51 LSB). Numbers below are MSB/primary CCs.", + "has_midi_cc": true, + "cc_parameters": [ + {"cc": 0, "name": "Bank Select"}, + {"cc": 1, "name": "Mod Wheel"}, + {"cc": 2, "name": "Reserved - MIDI Breath Control"}, + {"cc": 3, "name": "LFO 1 Rate (also LFO 1 Clock Divider)"}, + {"cc": 4, "name": "Mod 1 Pitch Amount"}, + {"cc": 5, "name": "Glide Time"}, + {"cc": 6, "name": "Reserved - Data Entry"}, + {"cc": 7, "name": "Master Volume"}, + {"cc": 8, "name": "LFO 2 Rate (also LFO 2 Clock Divider)"}, + {"cc": 9, "name": "Osc 1 Wave"}, + {"cc": 10, "name": "Reserved - MIDI Pan"}, + {"cc": 11, "name": "Mod 1 Filter Amount"}, + {"cc": 12, "name": "Osc 2 Frequency"}, + {"cc": 13, "name": "Osc 2 Beat Frequency"}, + {"cc": 14, "name": "Osc 2 Wave"}, + {"cc": 15, "name": "Mod 2 Pitch Amount"}, + {"cc": 16, "name": "Mod 2 Filter Amount"}, + {"cc": 17, "name": "Mod 2 Pgm Dest Amount"}, + {"cc": 18, "name": "Filter Multidrive"}, + {"cc": 19, "name": "Filter Cutoff"}, + {"cc": 20, "name": "Mod 1 Pgm Dest Amount"}, + {"cc": 21, "name": "Filter Resonance"}, + {"cc": 22, "name": "Filter KB Amount"}, + {"cc": 23, "name": "Filter EG Attack Time"}, + {"cc": 24, "name": "Filter EG Decay Time"}, + {"cc": 25, "name": "Filter EG Sustain Time"}, + {"cc": 26, "name": "Filter EG Release Time"}, + {"cc": 27, "name": "Filter EG Amount"}, + {"cc": 28, "name": "Amp EG Attack Time"}, + {"cc": 29, "name": "Amp EG Decay Time"}, + {"cc": 30, "name": "Amp EG Sustain Time"}, + {"cc": 31, "name": "Amp EG Release Time"}, + {"cc": 32, "name": "Bank Select (LSB)"}, + {"cc": 33, "name": "Mod Wheel (LSB)"}, + {"cc": 64, "name": "Hold Pedal/Sustain"}, + {"cc": 65, "name": "Glide On"}, + {"cc": 69, "name": "Arpeggiator Latch"}, + {"cc": 70, "name": "Mod 1 Osc 1/2 Select"}, + {"cc": 71, "name": "Mod 1 Source"}, + {"cc": 72, "name": "Mod 2 Source"}, + {"cc": 73, "name": "Arp On/Off"}, + {"cc": 74, "name": "Osc 1 Octave"}, + {"cc": 75, "name": "Osc 2 Octave"}, + {"cc": 76, "name": "LFO 1 Range"}, + {"cc": 77, "name": "Osc 2 Hard Sync On/Off"}, + {"cc": 78, "name": "LFO 2 Range"}, + {"cc": 79, "name": "Filter EG KB Amount"}, + {"cc": 80, "name": "Amp EG KB Amount"}, + {"cc": 81, "name": "Osc KB Reset On/Off"}, + {"cc": 82, "name": "Filter EG Reset"}, + {"cc": 83, "name": "Amp EG Reset"}, + {"cc": 84, "name": "Reserved - Portamento Control"}, + {"cc": 85, "name": "Glide Type"}, + {"cc": 86, "name": "Filter EG Velocity Amount"}, + {"cc": 87, "name": "Amp EG Velocity Amount"}, + {"cc": 88, "name": "Mod 2 Osc 1/2 Select"}, + {"cc": 89, "name": "KB Octave"}, + {"cc": 91, "name": "Mod 1 Destination"}, + {"cc": 92, "name": "Mod 2 Destination"}, + {"cc": 93, "name": "LFO 1 KB Reset"}, + {"cc": 94, "name": "Glide Legato"}, + {"cc": 95, "name": "LFO 2 KB Reset"}, + {"cc": 102, "name": "Glide Dest Osc 1/2/Both"}, + {"cc": 103, "name": "Filter EG Delay"}, + {"cc": 104, "name": "Amp EG Delay"}, + {"cc": 105, "name": "Filter EG Hold"}, + {"cc": 106, "name": "Amp EG Hold"}, + {"cc": 107, "name": "Pitch Bend Up Amount"}, + {"cc": 108, "name": "Pitch Bend Down Amount"}, + {"cc": 109, "name": "Filter Slopes (Poles)"}, + {"cc": 110, "name": "Osc Duo Mode On/Off"}, + {"cc": 111, "name": "KB Ctrl Lo/Hi"}, + {"cc": 112, "name": "Filter EG Multi Trig"}, + {"cc": 113, "name": "Amp EG Multi Trig"}, + {"cc": 114, "name": "Osc 1 Level"}, + {"cc": 115, "name": "Osc 1 Sub Level"}, + {"cc": 116, "name": "Osc 2 Level"}, + {"cc": 117, "name": "Noise Level"}, + {"cc": 118, "name": "Feedback/Ext Level"}, + {"cc": 119, "name": "KB Transpose (receive only)"}, + {"cc": 122, "name": "Local Control On/Off"} + ], + "sources": [ + "Official Moog Sub 37 User Manual v1.1 (SUB_37_MANUAL_v1.1_0.pdf), 'MIDI Control Change (CC) Messages' tables pp. 52-55", + "midi.guide - Moog Subsequent 37 (shares CC map with Sub 37): https://midi.guide/d/moog/subsequent-37/", + "ManualsLib - Moog Sub 37 User Manual: https://www.manualslib.com/manual/923162/Moog-Sub-37.html", + "Gearspace 'Sub37 MIDI CC MSB LSB' thread (corroborates 14-bit cutoff CC19/CC51)" + ], + "confidence": "high", + "verification_notes": "Read directly from the official Moog manual PDF and cross-checked against midi.guide and ManualsLib. A real conflict was resolved: an OCR read of ManualsLib returned a +1 shift (CC20=Cutoff, CC22=Resonance); both the official manual and midi.guide confirm CC19=Cutoff, CC21=Resonance, CC18=Multidrive. Manual treated as authoritative. CC123 (All Notes Off) is standard MIDI and not in the manual's param table, so omitted. Sub 37 (2014) and Subsequent 37 (2017) share this CC map." + }, + { + "name": "Creamware Pro-12 ASB", + "manufacturer": "Creamware / Sonic Core", + "year": 2005, + "midi_channel_notes": "MIDI In/Out/Thru (DIN-5) plus USB MIDI; receive channel set in PREFS. Every front-panel parameter has a dedicated CC and is transmitted when a patch is selected. External MIDI Clock can drive LFO speed. Standard Channel Mode messages (CC 120-127) implemented.", + "has_midi_cc": true, + "cc_parameters": [ + {"cc": 0, "name": "Bank Select"}, + {"cc": 1, "name": "Modulation"}, + {"cc": 2, "name": "Unison Voices"}, + {"cc": 3, "name": "Unison Detune"}, + {"cc": 5, "name": "Glide Time"}, + {"cc": 6, "name": "Data Entry"}, + {"cc": 7, "name": "Device Volume"}, + {"cc": 8, "name": "LFO Settings Retrig"}, + {"cc": 9, "name": "LFO Settings Phase"}, + {"cc": 11, "name": "Volume"}, + {"cc": 12, "name": "Osc A Frequency"}, + {"cc": 13, "name": "Osc A Shape Saw"}, + {"cc": 14, "name": "Osc A Shape Pulse"}, + {"cc": 15, "name": "Osc A Pulse Width"}, + {"cc": 16, "name": "Osc A Sync"}, + {"cc": 17, "name": "Osc B Frequency"}, + {"cc": 18, "name": "Osc B Fine"}, + {"cc": 19, "name": "Osc B Shape Saw"}, + {"cc": 20, "name": "Osc B Shape Triangle"}, + {"cc": 21, "name": "Master Tune"}, + {"cc": 22, "name": "Osc B Shape Pulse"}, + {"cc": 23, "name": "Aftertouch Pitch"}, + {"cc": 24, "name": "Bend Range"}, + {"cc": 25, "name": "Osc A Volume"}, + {"cc": 26, "name": "Osc B Volume"}, + {"cc": 27, "name": "Osc B Pulse Width"}, + {"cc": 28, "name": "Osc B Lo Freq"}, + {"cc": 29, "name": "Osc B Keyboard"}, + {"cc": 30, "name": "Aftertouch Dest Freq A"}, + {"cc": 31, "name": "Aftertouch Dest Freq B"}, + {"cc": 32, "name": "Bank Select"}, + {"cc": 33, "name": "Noise Volume"}, + {"cc": 34, "name": "Aftertouch PW"}, + {"cc": 35, "name": "Aftertouch MW"}, + {"cc": 36, "name": "External Volume"}, + {"cc": 37, "name": "Aftertouch Dest PW"}, + {"cc": 38, "name": "Aftertouch Dest PW"}, + {"cc": 39, "name": "Keyboard Amount"}, + {"cc": 40, "name": "Cutoff"}, + {"cc": 41, "name": "Resonance"}, + {"cc": 42, "name": "Envelope Amount"}, + {"cc": 43, "name": "Filter Env Attack"}, + {"cc": 44, "name": "Filter Env Decay"}, + {"cc": 45, "name": "Filter Env Sustain"}, + {"cc": 46, "name": "Filter Env Velocity"}, + {"cc": 47, "name": "Filter Release"}, + {"cc": 48, "name": "Aftertouch LFO Freq"}, + {"cc": 49, "name": "Release"}, + {"cc": 50, "name": "Aftertouch Filter"}, + {"cc": 51, "name": "Aftertouch Amp"}, + {"cc": 52, "name": "Amp Env Attack"}, + {"cc": 53, "name": "Amp Env Decay"}, + {"cc": 54, "name": "Amp Env Sustain"}, + {"cc": 55, "name": "Amp Env Velocity"}, + {"cc": 56, "name": "MW Intensity"}, + {"cc": 57, "name": "MW Offset"}, + {"cc": 58, "name": "Poly Mod OSC B"}, + {"cc": 59, "name": "ADR"}, + {"cc": 60, "name": "Keyb Mode Retrig"}, + {"cc": 61, "name": "Low Note"}, + {"cc": 62, "name": "Amp Env Release"}, + {"cc": 63, "name": "Poly Mod Filter Env"}, + {"cc": 75, "name": "Poly Mod Destination Freq A"}, + {"cc": 76, "name": "Poly Mod Destination Freq B"}, + {"cc": 77, "name": "Poly Mod Destination PW"}, + {"cc": 78, "name": "Poly Mod Destination PW"}, + {"cc": 79, "name": "Poly Mod Destination Filter"}, + {"cc": 98, "name": "Amt"}, + {"cc": 108, "name": "Wheel Mod Source Mix"}, + {"cc": 113, "name": "Time Velocity Attack Filter Env"}, + {"cc": 114, "name": "Time Velocity Dec/Rel Filter Env"}, + {"cc": 116, "name": "Time Velocity Dec/Rel Amp Env"}, + {"cc": 117, "name": "Time Velocity Attack Amp Env"}, + {"cc": 120, "name": "All Sounds Off"}, + {"cc": 121, "name": "Local Control Off"}, + {"cc": 122, "name": "All Notes Off"}, + {"cc": 124, "name": "Omni Off"}, + {"cc": 125, "name": "Omni On"}, + {"cc": 126, "name": "Mono On"}, + {"cc": 127, "name": "Poly On"} + ], + "sources": [ + "Creamware PRO-12 ASB Owner's Manual (Rev. 1.1), MIDI implementation table p.36", + "https://www.manualslib.com/manual/949793/Creamware-Pro-12-Asb.html", + "https://www.manualslib.com/manual/744066/Creamware-Pro-12-Asb.html", + "https://www.strumentimusicali.net/manuali/CREAMWARE_Pro12_en.pdf", + "https://www.soundonsound.com/reviews/creamware-pro-12-asb" + ], + "confidence": "high", + "verification_notes": "Emulation CONFIRMED as the Sequential Circuits Prophet-5 (Rev 3), NOT the Prophet-12 (ASB = 'Authentic Sound Box'). Creamware was rebranded Sonic Core c.2007-2008. CC 0-117 synth block extracted from three independent ManualsLib renderings of the official manual and agree byte-for-byte. Two duplicate labels (CC 37/38 'Aftertouch Dest PW'; CC 77/78 'Poly Mod Destination PW') are reproduced verbatim from the manual. Coverage gap: an effects/delay/reverb CC block in the 64-112 range appeared in only one extraction and was left out to avoid OCR error (only the consistently-seen CC 98 and CC 108 were kept from it)." + }, + { + "name": "Elektron Analog Keys", + "manufacturer": "Elektron", + "year": 2014, + "midi_channel_notes": "CCs are per-track. Default channels (all configurable): Synth Track 1-4 = Ch 1-4, FX = Ch 5, CV = Ch 6, Performance = Ch 8, Auto Channel = Ch 9 (routes to the currently-selected synth track). Shares its CC map with the Analog Four.", + "has_midi_cc": true, + "cc_parameters": [ + {"cc": 1, "name": "Modulation: Modwheel (MSB, 14-bit pair with CC 33)"}, + {"cc": 2, "name": "Modulation: Breath (MSB, 14-bit pair with CC 34)"}, + {"cc": 3, "name": "Performance: Parameter A"}, + {"cc": 4, "name": "Performance: Parameter B"}, + {"cc": 5, "name": "OSC: Slide Time"}, + {"cc": 7, "name": "Amp: Volume"}, + {"cc": 8, "name": "Performance: Parameter C"}, + {"cc": 9, "name": "Performance: Parameter D"}, + {"cc": 10, "name": "Amp: Pan"}, + {"cc": 11, "name": "Performance: Parameter E"}, + {"cc": 16, "name": "OSC1: Pitch (MSB, 14-bit pair with CC 48)"}, + {"cc": 17, "name": "OSC2: Pitch (MSB, 14-bit pair with CC 49)"}, + {"cc": 18, "name": "Filter 1: Frequency (MSB, 14-bit pair with CC 50)"}, + {"cc": 19, "name": "Filter 2: Frequency (MSB, 14-bit pair with CC 51)"}, + {"cc": 20, "name": "Filter Env: Depth A (MSB, 14-bit pair with CC 52)"}, + {"cc": 21, "name": "Filter Env: Depth B (MSB, 14-bit pair with CC 53)"}, + {"cc": 22, "name": "AUX Env: Depth A (MSB, 14-bit pair with CC 54)"}, + {"cc": 23, "name": "AUX Env: Depth B (MSB, 14-bit pair with CC 55)"}, + {"cc": 24, "name": "LFO1: Depth A (MSB, 14-bit pair with CC 56)"}, + {"cc": 25, "name": "LFO1: Depth B (MSB, 14-bit pair with CC 57)"}, + {"cc": 26, "name": "LFO2: Depth A (MSB, 14-bit pair with CC 58)"}, + {"cc": 27, "name": "LFO2: Depth B (MSB, 14-bit pair with CC 59)"}, + {"cc": 33, "name": "Modulation: Modwheel (LSB)"}, + {"cc": 34, "name": "Modulation: Breath (LSB)"}, + {"cc": 48, "name": "OSC1: Pitch (LSB)"}, + {"cc": 49, "name": "OSC2: Pitch (LSB)"}, + {"cc": 50, "name": "Filter 1: Frequency (LSB)"}, + {"cc": 51, "name": "Filter 2: Frequency (LSB)"}, + {"cc": 52, "name": "Filter Env: Depth A (LSB; MkI: 'EnvF Gate Length')"}, + {"cc": 53, "name": "Filter Env: Depth B (LSB)"}, + {"cc": 54, "name": "AUX Env: Depth A (LSB)"}, + {"cc": 55, "name": "AUX Env: Depth B (LSB)"}, + {"cc": 56, "name": "LFO1: Depth A (LSB)"}, + {"cc": 57, "name": "LFO1: Depth B (LSB)"}, + {"cc": 58, "name": "LFO2: Depth A (LSB)"}, + {"cc": 59, "name": "LFO2: Depth B (LSB)"}, + {"cc": 64, "name": "Performance: Parameter F"}, + {"cc": 65, "name": "Performance: Parameter G"}, + {"cc": 66, "name": "Performance: Parameter H"}, + {"cc": 67, "name": "Performance: Parameter I"}, + {"cc": 68, "name": "Performance: Parameter J"}, + {"cc": 69, "name": "OSC1: Level"}, + {"cc": 70, "name": "OSC1: Waveform"}, + {"cc": 71, "name": "OSC1: Sub Oscillator"}, + {"cc": 72, "name": "OSC1: Pulsewidth"}, + {"cc": 73, "name": "OSC1: PWM Speed"}, + {"cc": 74, "name": "OSC1: PWM Depth"}, + {"cc": 75, "name": "Noise: S&H"}, + {"cc": 76, "name": "Noise: Fade"}, + {"cc": 77, "name": "Noise: Level"}, + {"cc": 78, "name": "OSC2: Level"}, + {"cc": 79, "name": "OSC2: Waveform"}, + {"cc": 80, "name": "OSC2: Sub Oscillator"}, + {"cc": 81, "name": "OSC2: Pulsewidth"}, + {"cc": 82, "name": "OSC2: PWM Speed"}, + {"cc": 83, "name": "OSC2: PWM Depth"}, + {"cc": 84, "name": "OSC: Sync Amount"}, + {"cc": 85, "name": "OSC: Bend Amount"}, + {"cc": 86, "name": "Filter 1: Overdrive"}, + {"cc": 88, "name": "OSC: Vibrato Speed (Analog Keys/MkI)"}, + {"cc": 89, "name": "Filter 1: Resonance"}, + {"cc": 90, "name": "Filter 2: Resonance"}, + {"cc": 91, "name": "Amp: Chorus Send"}, + {"cc": 92, "name": "Amp: Delay Send"}, + {"cc": 93, "name": "Amp: Reverb Send"}, + {"cc": 94, "name": "Track: Mute"}, + {"cc": 95, "name": "Track: Level"}, + {"cc": 102, "name": "Filter 1: Envelope Depth"}, + {"cc": 103, "name": "Filter 2: Envelope Depth"}, + {"cc": 104, "name": "Amp Env: Attack"}, + {"cc": 105, "name": "Amp Env: Decay"}, + {"cc": 106, "name": "Amp Env: Sustain"}, + {"cc": 107, "name": "Amp Env: Release"}, + {"cc": 108, "name": "Filter Env: Attack"}, + {"cc": 109, "name": "Filter Env: Decay"}, + {"cc": 110, "name": "Filter Env: Sustain"}, + {"cc": 111, "name": "Filter Env: Release"}, + {"cc": 112, "name": "AUX Env: Attack"}, + {"cc": 113, "name": "AUX Env: Decay"}, + {"cc": 114, "name": "AUX Env: Sustain"}, + {"cc": 115, "name": "AUX Env: Release"}, + {"cc": 116, "name": "LFO1: Speed"}, + {"cc": 117, "name": "LFO1: Multiplier"}, + {"cc": 118, "name": "LFO2: Speed"}, + {"cc": 119, "name": "LFO2: Multiplier"} + ], + "sources": [ + "Elektron Analog Keys User Manual, Appendix D (MIDI spec, OS 1.40B) via ManualsLib", + "pencilresearch/midi GitHub: Analog Four.csv / Analog Four MKII.csv (CC BY-SA 4.0)", + "midi.guide - Elektron Analog Four / Analog Four MkII", + "Elektronauts forum MIDI implementation threads" + ], + "confidence": "medium", + "verification_notes": "Cross-checked against 4 sources. The core ~32-CC set is confirmed for Analog Keys hardware. Two MkI-vs-MkII conflicts exist: (1) Vibrato Speed is CC 88 on Analog Keys/MkI (no Vibrato Depth CC); the Four MkII moved it to CC 87 and added CC 88 = Vibrato Depth. (2) The 14-bit MSB/LSB pairs (CC 16-27 MSB, 48-59 LSB) are MkII-era additions; the original Analog Keys manual lists CC 52 as 'EnvF Gate Length' and CC 53 as a standalone 7-bit param. The 14-bit pairs above reflect the later/Four MkII convention. NRPN covers params not reachable by CC (env shapes/curves, filter types, LFO waveforms/dests, FX/CV tracks, arp)." + }, + { + "name": "ASM Hydrasynth", + "manufacturer": "Ashun Sound Machines (ASM)", + "year": 2019, + "midi_channel_notes": "Transmits/receives 1-16. CC mode must be enabled in System Setup (Param TX/RX = CC); DEFAULT is NRPN. CC mode was introduced in firmware v1.5 (Aug 2020); v1.0 had no CC. When in CC mode, CC 6/38/98/99 serve as NRPN infrastructure. The large majority of engine params (osc/filter types, LFO shapes, mod matrix, macro targets) are NRPN-only; the ~115 CCs below are the continuous/performance subset. CC map is identical across Keyboard/Desktop/Explorer/Deluxe.", + "has_midi_cc": true, + "cc_parameters": [ + {"cc": 0, "name": "Bank Select MSB"}, + {"cc": 1, "name": "Mod Wheel"}, + {"cc": 3, "name": "Noise Vol"}, + {"cc": 5, "name": "Glide Time"}, + {"cc": 7, "name": "Master Volume"}, + {"cc": 8, "name": "Noise Pan"}, + {"cc": 9, "name": "Ring Mod Vol"}, + {"cc": 10, "name": "Ring Mod Pan"}, + {"cc": 11, "name": "Expression Pedal"}, + {"cc": 12, "name": "PRE-FX Param1"}, + {"cc": 13, "name": "PRE-FX Param2"}, + {"cc": 14, "name": "Delay Feedback"}, + {"cc": 15, "name": "Delay Time"}, + {"cc": 16, "name": "Macro 1"}, + {"cc": 17, "name": "Macro 2"}, + {"cc": 18, "name": "Macro 3"}, + {"cc": 19, "name": "Macro 4"}, + {"cc": 20, "name": "Macro 5"}, + {"cc": 21, "name": "Macro 6"}, + {"cc": 22, "name": "Macro 7"}, + {"cc": 23, "name": "Macro 8"}, + {"cc": 24, "name": "OSC1 WavScan"}, + {"cc": 25, "name": "ENV4 Attack"}, + {"cc": 26, "name": "OSC2 WavScan"}, + {"cc": 27, "name": "ENV4 Decay"}, + {"cc": 28, "name": "LFO2 Gain"}, + {"cc": 29, "name": "Mutator1 Ratio"}, + {"cc": 30, "name": "Mutator1 Depth"}, + {"cc": 31, "name": "Mutator1 Dry/Wet"}, + {"cc": 32, "name": "Bank Select LSB"}, + {"cc": 33, "name": "Mutator2 Ratio"}, + {"cc": 34, "name": "Mutator2 Depth"}, + {"cc": 35, "name": "Mutator2 Dry/Wet"}, + {"cc": 36, "name": "Mutator3 Ratio"}, + {"cc": 37, "name": "Mutator3 Depth"}, + {"cc": 39, "name": "Mutator3 Dry/Wet"}, + {"cc": 40, "name": "Mutator4 Ratio"}, + {"cc": 41, "name": "Mutator4 Depth"}, + {"cc": 42, "name": "Mutator4 Dry/Wet"}, + {"cc": 43, "name": "RM12 Depth (Ring Mod Depth)"}, + {"cc": 44, "name": "OSC1 Vol"}, + {"cc": 45, "name": "OSC1 Pan"}, + {"cc": 46, "name": "OSC2 Vol"}, + {"cc": 47, "name": "OSC2 Pan"}, + {"cc": 48, "name": "OSC3 Vol"}, + {"cc": 49, "name": "OSC3 Pan"}, + {"cc": 50, "name": "Filter1 Drive"}, + {"cc": 51, "name": "Filter1 Keytrack"}, + {"cc": 52, "name": "Filter1 LFO1 Amt"}, + {"cc": 53, "name": "Filter1 Vel Env"}, + {"cc": 54, "name": "Filter1 ENV1 Amt"}, + {"cc": 55, "name": "Filter2 Cutoff"}, + {"cc": 56, "name": "Filter2 Res"}, + {"cc": 57, "name": "Filter2 Type/Morph"}, + {"cc": 58, "name": "Filter2 Keytrack"}, + {"cc": 59, "name": "Filter2 LFO1 Amt"}, + {"cc": 60, "name": "Filter2 Vel Env"}, + {"cc": 61, "name": "Filter2 ENV1 Amt"}, + {"cc": 62, "name": "Amp LFO2 Amt"}, + {"cc": 63, "name": "Delay Wet Tone"}, + {"cc": 64, "name": "Sustain Pedal"}, + {"cc": 65, "name": "Reverb Time"}, + {"cc": 66, "name": "Glide On/Off"}, + {"cc": 67, "name": "Reverb Tone"}, + {"cc": 68, "name": "POST-FX Param1"}, + {"cc": 69, "name": "POST-FX Param2"}, + {"cc": 70, "name": "LFO1 Gain"}, + {"cc": 71, "name": "Filter1 Res"}, + {"cc": 72, "name": "LFO1 Rate"}, + {"cc": 73, "name": "LFO2 Rate"}, + {"cc": 74, "name": "Filter1 Cutoff"}, + {"cc": 75, "name": "LFO3 Gain"}, + {"cc": 76, "name": "LFO3 Rate"}, + {"cc": 77, "name": "LFO4 Gain"}, + {"cc": 78, "name": "LFO4 Rate"}, + {"cc": 79, "name": "LFO5 Gain"}, + {"cc": 80, "name": "LFO5 Rate"}, + {"cc": 81, "name": "ENV1 Attack"}, + {"cc": 82, "name": "ENV1 Decay"}, + {"cc": 83, "name": "ENV1 Sustain"}, + {"cc": 84, "name": "ENV1 Release"}, + {"cc": 85, "name": "ENV2 Attack"}, + {"cc": 86, "name": "ENV2 Decay"}, + {"cc": 87, "name": "ENV2 Sustain"}, + {"cc": 88, "name": "ENV2 Release"}, + {"cc": 89, "name": "ENV3 Attack"}, + {"cc": 90, "name": "ENV3 Decay"}, + {"cc": 91, "name": "Reverb Dry/Wet"}, + {"cc": 92, "name": "Delay Dry/Wet"}, + {"cc": 93, "name": "PRE-FX Mix"}, + {"cc": 94, "name": "POST-FX Mix"}, + {"cc": 95, "name": "Detune"}, + {"cc": 96, "name": "ENV3 Sustain"}, + {"cc": 97, "name": "ENV3 Release"}, + {"cc": 102, "name": "ENV5 Attack"}, + {"cc": 103, "name": "ENV5 Decay"}, + {"cc": 104, "name": "ENV5 Sustain"}, + {"cc": 105, "name": "ENV5 Release"}, + {"cc": 106, "name": "ARP Division"}, + {"cc": 107, "name": "ARP Gate"}, + {"cc": 108, "name": "ARP Mode"}, + {"cc": 109, "name": "ARP Ratchet"}, + {"cc": 110, "name": "ARP Chance"}, + {"cc": 111, "name": "OSC1 Cent"}, + {"cc": 112, "name": "OSC2 Cent"}, + {"cc": 113, "name": "OSC3 Cent"}, + {"cc": 114, "name": "OSC3 F Rate"}, + {"cc": 115, "name": "Noise F Rate"}, + {"cc": 116, "name": "Ring Mod F Rate"}, + {"cc": 117, "name": "Stereo Width"}, + {"cc": 118, "name": "OSC1 F Rate"}, + {"cc": 119, "name": "OSC2 F Rate"}, + {"cc": 120, "name": "ARP Octave (repurposed from standard 'All Sounds Off')"}, + {"cc": 122, "name": "ARP Length"}, + {"cc": 123, "name": "All Notes Off"}, + {"cc": 124, "name": "ENV4 Release"}, + {"cc": 125, "name": "ENV4 Sustain"} + ], + "sources": [ + "Official ASM MIDI NRPN & CC Spec v1.5: https://www.mecldata.com/download/asm/legacy/Hydrasynth_KB_DR_MIDI_Spec_1.5.0.pdf", + "Hydrasynth Owner's Manuals v2.2.0 (KB/DR pp.116-119, Explorer pp.94-97, Deluxe pp.124-126)", + "midi.guide - ASM Hydrasynth (115 params, updated Sep 2024): https://midi.guide/d/asm/hydrasynth/", + "pencilresearch/midi GitHub: ASM/Hydrasynth.csv", + "eclab/edisyn reverse-engineered nrpn.csv (notes the official PDF has errors)" + ], + "confidence": "high", + "verification_notes": "115 CC assignments cross-verified across the official ASM spec, current owner's manuals, midi.guide and the pencilresearch CSV - all consistent. CC 120 is repurposed for ARP Octave (standard 'All Sounds Off' will move ARP Octave instead). Gaps: CC 2,4,6,38,98-101,121,126-127 unused. ENV4 (Amp env) ADSR is non-contiguous: A=25, D=27, S=125, R=124. An older Explorer-manual page showed a divergent layout (likely a render artifact); the v2.2.0 manuals + spec values above are authoritative. Hundreds of additional params are NRPN-only." + }, + { + "name": "Roland JD-800", + "manufacturer": "Roland", + "year": 1991, + "midi_channel_notes": "Transmits/receives on a configurable channel (1-16); SysEx Device ID defaults to 17. IMPORTANT: the front-panel sliders do NOT transmit CC -- they emit Roland SysEx (F0 41 dev 3D 12 ... F7), and 'TX Edit Data' must be enabled. The synth RECEIVES a small set of standard CCs. There is no NRPN. (The 2021 JD-08 Boutique reissue is a different architecture that maps ~80 CCs.)", + "has_midi_cc": true, + "cc_parameters": [ + {"cc": 1, "name": "Modulation"}, + {"cc": 2, "name": "Breath Controller"}, + {"cc": 5, "name": "Portamento Time"}, + {"cc": 6, "name": "Data Entry MSB (RPN; receive only)"}, + {"cc": 7, "name": "Volume / Part Level"}, + {"cc": 10, "name": "Pan"}, + {"cc": 11, "name": "Expression"}, + {"cc": 64, "name": "Hold / Sustain Pedal"}, + {"cc": 65, "name": "Portamento On/Off"}, + {"cc": 100, "name": "RPN LSB (receive only)"}, + {"cc": 101, "name": "RPN MSB (receive only)"}, + {"cc": 121, "name": "Reset All Controllers (receive only)"}, + {"cc": 123, "name": "All Notes Off (receive only)"} + ], + "sources": [ + "Roland JD-800 Owner's Manual / MIDI Implementation (Owner's Manual II, pp. V-53 to V-65): https://cdn.roland.com/assets/media/pdf/JD-800_OM.pdf", + "Roland JD-800 MIDI Annex (deepsonic archive): https://www.deepsonic.ch/deep/docs_manuals/roland_jd-800_midi_anleitung.pdf", + "Roland Support: 'Transmitting the JD-800's Slider Information to a Sequencer'", + "Vintage Synth Explorer forum (confirms SysEx-only slider transmission): https://forum.vintagesynth.com/viewtopic.php?t=52284", + "Gearspace 'JD800 MIDI automation' thread" + ], + "confidence": "medium", + "verification_notes": "The core received CCs (1, 5, 7, 10, 64, 65) are confirmed across the official manual proxy, Roland support, and forum sources. The defining JD-800 fact: every synthesis parameter (cutoff, resonance, envelopes, LFO, FX) is transmitted/edited via Roland SysEx, NOT CC -- the famous sliders emit SysEx only, so DAW automation needs a SysEx<->CC translator (e.g. Bome). The original manual's MIDI chart pages are image-scanned and not machine-extractable, so the extended receive list (CC 2, 6, 100/101, 121, 123) carries slightly lower confidence than the core set. Do not confuse with the JD-08 reissue." + }, + { + "name": "Korg Polysix", + "manufacturer": "Korg", + "year": 1981, + "midi_channel_notes": "The original 1981 Polysix has no MIDI port and no MIDI channel concept -- it predates the MIDI standard (1983). MIDI/CC exist only on aftermarket retrofits (channel-selectable 1-16) and the Korg Legacy software emulation (follows host channel).", + "has_midi_cc": false, + "cc_parameters": [], + "sources": [ + "https://en.wikipedia.org/wiki/Korg_Polysix", + "https://www.vintagesynth.com/korg/polysix", + "https://www.soundonsound.com/reviews/korg-legacy-collection-part-3", + "CHD Elektroservis Polysix MIDI interface manuals (P6-KBD, PS-6M): https://www.chd-el.cz/products/korg-polysix-midi-interface/", + "Kiwitechnics KiwiSix: http://www.kiwitechnics.com/kiwisix.htm", + "Kenton Polysix MIDI kit: https://kentonuk.com/product/polysix/", + "Tubbutec ModyPoly: https://tubbutec.de/modypoly/" + ], + "confidence": "high", + "verification_notes": "GOTCHA CONFIRMED: the original 1981 Korg Polysix (PS-6) is a PRE-MIDI analog polysynth with NO native MIDI (MIDI standardized 1983). It has only CV/arpeggiator-sync-era connectivity. Therefore has_midi_cc=false and cc_parameters=[] for the original hardware. CC/MIDI exist only on (1) third-party retrofits -- CHD P6-KBD (receive-only; documented CCs incl. CC64 Hold and custom CC16-19) and the fuller CHD PS-6M (CC1 Modulation, CC7 Volume, CC64 Hold, CC70 Chord Memory, CC71 Arpeggiator, CC98/99 NRPN, CC122 Local, CC123 All Notes Off), plus Kenton, Tubbutec ModyPoly and Kiwitechnics KiwiSix mainboard (advertises full CC/NRPN but no public per-CC chart); and (2) the Korg Legacy Collection software emulation (only documented mapping: CC1 -> Vibrato Intensity, rest via MIDI-learn). Any 'Polysix' CC numbers belong to those, not the 1981 unit. No CC numbers were invented." + }, + { + "name": "Roland RD-9 Rhythm Designer", + "manufacturer": "Behringer (NOT Roland -- see notes)", + "year": 2021, + "midi_channel_notes": "Settable per device on SETTINGS > MIDI: MIDI IN channel 1-16/All/Out, separate MIDI OUT channel 1-16, plus independent USB MIDI channels and a SysEx Device ID (1-16). Voices are triggered by MIDI NOTES (note map below), not CC. The official manual documents no CC implementation. Accent is sent via high note velocity.", + "has_midi_cc": false, + "cc_parameters": [], + "community_reported_cc_unofficial": [ + {"cc": 75, "name": "Hi-Hat / Crash Pitch (receive-only; could glitch Kick pre-fw 1.1.4)"}, + {"cc": 76, "name": "Hi-Hat / Crash Pitch (second of pair)"}, + {"cc": 77, "name": "Ride Pitch"} + ], + "note_map": { + "Bass Drum": 36, + "Snare Drum": 40, + "Low Tom / Low Conga": 45, + "Mid Tom / Mid Conga": 47, + "Hi Tom / Hi Conga": 50, + "Rim Shot / Claves": 37, + "Clap / Maracas": 39, + "Cowbell": 56, + "Cymbal": 51, + "Open Hat": 46, + "Closed Hat": 42 + }, + "sources": [ + "Behringer RD-9 User Manual (note map p.17): https://www.manualslib.com/manual/2367155/Behringer-Rd-9.html", + "Behringer RD-9 manual PDF: https://mediadl.musictribe.com/media/PLM/data/docs/P0DG6/P0DG6_RD-9_M_EN.pdf", + "Gearspace 'Behringer RD9 sending midi' thread (CC 75/76/77, community-sourced)", + "Behringer product page: https://www.behringer.com/en/products/0704-AAB", + "For a true Roland 909 with a published CC chart: Roland TR-09 MIDI Implementation: https://static.roland.com/assets/media/pdf/TR-09_MIDI_Imple_e01_W.pdf" + ], + "confidence": "high (that NO official CC chart exists); low (for the community CC values)", + "verification_notes": "NAME CORRECTION: there is NO 'Roland RD-9'. The RD-9 'Rhythm Designer' is a BEHRINGER product (Music Tribe, 2021), an analog/digital TR-909 clone. Roland's RD-x models are stage pianos; Roland's official 909 reissue is the TR-09 and the fuller TR-8S (both publish per-instrument CC charts). The full 38-page official Behringer RD-9 manual was downloaded and exhaustively text-searched: it contains ZERO Control Change / NRPN / RPN mappings -- only the MIDI NOTE trigger map (above) plus SysEx dumps and clock. So has_midi_cc=false and cc_parameters=[] (per-instrument Tune/Decay/Level knobs are physical controls, not CC-addressable). The 'community_reported_cc_unofficial' CC 75/76/77 (cymbal pitch) are forum-sourced, receive-only, firmware-dependent, and NOT in any official documentation. One earlier research pass reported CC 62/63/64 as manual-sourced, but the full-manual read found no such chart, so those are rejected. The TR-909/TR-8S charts were deliberately NOT substituted and no CC numbers were invented. For a documented per-voice CC map, use the Roland TR-8S (e.g. BD Tune CC20, BD Decay CC23) or TR-09." + }, + { + "name": "Moog Sub Phatty", + "manufacturer": "Moog", + "year": 2013, + "midi_channel_notes": "MIDI In channel set by holding SHIFT + a keyboard key (low C to D# = Ch 1-16). Nearly every panel knob/switch transmits and receives CC. CC3 (LFO Rate) doubles as an LFO clock-divider selector when LFO MIDI Sync is on. Continuous params support optional 14-bit CC (LSB = MSB + 32). Distinct CC map from the Sub 37 / Subsequent 37.", + "has_midi_cc": true, + "cc_parameters": [ + {"cc": 1, "name": "Modulation Wheel"}, + {"cc": 2, "name": "Filter Mod Amount"}, + {"cc": 3, "name": "LFO Rate"}, + {"cc": 4, "name": "Pitch Mod Amount"}, + {"cc": 5, "name": "Glide Rate"}, + {"cc": 7, "name": "Output Level (Volume)"}, + {"cc": 8, "name": "Noise Level"}, + {"cc": 9, "name": "VCO 1 Wave"}, + {"cc": 12, "name": "VCO 2 Frequency"}, + {"cc": 13, "name": "VCO 2 Beat Frequency"}, + {"cc": 14, "name": "VCO 2 Wave"}, + {"cc": 15, "name": "VCO 1 Level"}, + {"cc": 16, "name": "VCO 2 Level"}, + {"cc": 17, "name": "VCO 1 Sub Level"}, + {"cc": 18, "name": "Multidrive Amount"}, + {"cc": 19, "name": "Filter Cutoff Frequency"}, + {"cc": 20, "name": "Wave Mod Amount"}, + {"cc": 21, "name": "Filter Resonance"}, + {"cc": 22, "name": "Filter EG Amount"}, + {"cc": 23, "name": "Filter EG Attack"}, + {"cc": 24, "name": "Filter EG Decay"}, + {"cc": 25, "name": "Filter EG Sustain"}, + {"cc": 26, "name": "Filter EG Release"}, + {"cc": 27, "name": "Filter KB Tracking Amount"}, + {"cc": 28, "name": "Amplifier EG Attack"}, + {"cc": 29, "name": "Amplifier EG Decay"}, + {"cc": 30, "name": "Amplifier EG Sustain"}, + {"cc": 31, "name": "Amplifier EG Release"}, + {"cc": 65, "name": "Glide On/Off"}, + {"cc": 68, "name": "Legato"}, + {"cc": 70, "name": "Pitch Mod OSC 2 Only"}, + {"cc": 71, "name": "Modulation Source"}, + {"cc": 72, "name": "Wave Mod Destination"}, + {"cc": 73, "name": "Gated Glide"}, + {"cc": 74, "name": "VCO 1 Octave"}, + {"cc": 75, "name": "VCO 2 Octave"}, + {"cc": 76, "name": "LFO Range"}, + {"cc": 77, "name": "VCO Hard Sync"}, + {"cc": 78, "name": "LFO KB Tracking Amount"}, + {"cc": 79, "name": "Filter EG Velocity to Time"}, + {"cc": 80, "name": "Amplifier EG Velocity to Time"}, + {"cc": 81, "name": "VCO Gate Reset"}, + {"cc": 82, "name": "Filter EG Reset"}, + {"cc": 83, "name": "Amplifier EG Reset"}, + {"cc": 85, "name": "Glide Type"}, + {"cc": 86, "name": "Filter EG Repeat"}, + {"cc": 87, "name": "Amplifier EG Repeat"}, + {"cc": 88, "name": "Release On/Off"}, + {"cc": 89, "name": "Keyboard Octave"}, + {"cc": 90, "name": "Filter EG KB Amount"}, + {"cc": 91, "name": "Amplifier EG KB Amount"}, + {"cc": 92, "name": "Amplifier EG Velocity to Amplitude"}, + {"cc": 93, "name": "LFO Gate Reset"}, + {"cc": 94, "name": "Glide Legato"}, + {"cc": 102, "name": "LFO MIDI Sync"}, + {"cc": 103, "name": "Filter EG Delay"}, + {"cc": 104, "name": "Amplifier EG Delay"}, + {"cc": 105, "name": "Filter EG Hold"}, + {"cc": 106, "name": "Amplifier EG Hold"}, + {"cc": 107, "name": "Pitch Bend Up"}, + {"cc": 108, "name": "Pitch Bend Down"}, + {"cc": 109, "name": "Filter Poles"}, + {"cc": 110, "name": "Filter EG Velocity to Amplitude"}, + {"cc": 111, "name": "Note Priority"}, + {"cc": 113, "name": "Filter EG Gate Source"}, + {"cc": 114, "name": "Volume (Amplifier) EG Gate Source"}, + {"cc": 115, "name": "Filter EG Trigger Mode"}, + {"cc": 116, "name": "External Input Level"}, + {"cc": 117, "name": "Filter EG Fast Decay"}, + {"cc": 118, "name": "Amplifier EG Fast Decay"}, + {"cc": 119, "name": "Keyboard Transpose"} + ], + "sources": [ + "Official Moog Sub Phatty User Manual (Sub_Phatty_Manual.pdf), MIDI parameter tables pp. 38-41", + "https://www.manualslib.com/manual/564539/Moog-Sub-Phatty.html", + "midi.guide - Moog Sub Phatty: https://midi.guide/d/moog/sub-phatty/", + "Moog forum Sub Phatty MIDI CC threads" + ], + "confidence": "high", + "verification_notes": "Built from the official Moog manual MIDI tables (pp. 39-41 via ManualsLib) cross-checked against midi.guide and two Moog forum threads. Conflicts resolved: (1) manual OCR was internally inconsistent for CC 18/22/27 -- used the cleaner midi.guide mapping (CC18=Multidrive, CC22=Filter EG Amount, CC27=Filter KB Tracking); (2) CC65=Glide On/Off, CC107/108=Pitch Bend Up/Down (midi.guide + forum over an OCR shift); (3) CC94=Glide Legato. The forum notes a few documented CCs (CC7, CC68, CC88) reportedly did nothing in fw 2.2.0. Confirmed distinct from the Sub 37 CC map, not copied." + } + ] +}