2.3 KiB
gm/level2
Purpose
General MIDI Level 2 added a bank-select-driven variation layer on top of GM1. Each GM1 program (0..127) gains optional variation banks selected by Bank-Select LSB (CC 32). Bank 0 is always the GM1 default; banks 1..127 are reserved for GM2 variations. This module exposes the variation-name lookup so engines can render (program, bankLsb) pairs into a user-visible patch name.
The table here mirrors the GM2 v1.2 mandatory variation set. Full-coverage engines (hundreds of additional variations) layer their own tables on top via Object.assign({}, GM_LEVEL2_VARIATIONS, …) — keeping the base set small means importing this module costs negligible bundle size for consumers that only need the GM1 fallback path.
Features
GM_LEVEL2_VARIATIONSfrozen map keyed byprogram * 256 + bankLsb.gm2Key(program, bankLsb)helper for composing the lookup key.- Bank 0 entries are deliberately omitted; consumers fall back to
GM_LEVEL1_PATCHES. - Composable with downstream extension tables via the frozen-object idiom.
Usage: Basic
import { GM_LEVEL2_VARIATIONS, gm2Key } from "@suaveplan/midi";
const name = GM_LEVEL2_VARIATIONS[gm2Key(4, 1)];
// "Detuned Electric Piano 1"
Usage: Advanced
import {
GM_LEVEL1_PATCHES,
GM_LEVEL2_VARIATIONS,
gm2Key,
} from "@suaveplan/midi";
function resolvePatchName(program: number, bankLsb: number): string {
if (bankLsb === 0) return GM_LEVEL1_PATCHES[program] ?? `Program ${program}`;
return (
GM_LEVEL2_VARIATIONS[gm2Key(program, bankLsb)] ??
GM_LEVEL1_PATCHES[program] ??
`Program ${program}`
);
}
API Reference
GM_LEVEL2_VARIATIONS: Readonly<Record<number, string>>— frozen map keyed byprogram * 256 + bankLsb.gm2Key(program: number, bankLsb: number): number— pure function returning the composite lookup key.
Implementation Notes
The composite key encoding (program * 256 + bankLsb) is preferred over a nested Record<number, Record<number, string>> because a flat key has constant-time lookup with no intermediate object allocation, and because both forms have the same Object.freeze cost. Variations are added selectively — full GM2 / GS / XG coverage is huge and varies by vendor, so consumers can choose which dialect tables to spread on top.