# gm/gs ## Purpose Roland's GS dialect predates GM2 and uses Bank-Select LSB (CC 32) to select instrument variations on top of the GM1 base programs. The variation values differ from GM2 (Roland's "Capital Tones" sit at LSB 8, 16, 24, ...; GM2 uses 1, 2, 3, ...), so a separate dialect-specific table is necessary — sharing a table would mis-name patches on the wrong dialect. This module exposes `GS_VARIATIONS` covering the most commonly supported Capital Tones plus a handful of frequently-quoted variations from the GS bank-select map. Engines aiming at full GS compatibility layer additional entries via the frozen-object idiom. ## Features - `GS_VARIATIONS` frozen map keyed by `program * 256 + bankLsb`. - Covers Roland's Capital Tones and the most commonly cited GS variation banks. - Designed to compose with the `gm2Key` helper from `./level2.ts`. - Strict `Object.freeze` for safe extension via spread. ## Usage: Basic ```ts import { GS_VARIATIONS, gm2Key } from "@suaveplan/midi"; console.log(GS_VARIATIONS[gm2Key(0, 8)]); // "Piano 1w" console.log(GS_VARIATIONS[gm2Key(40, 0)]); // undefined → fall back to GM1 ``` ## Usage: Advanced ```ts import { GM_LEVEL1_PATCHES, GS_VARIATIONS, gm2Key, } from "@suaveplan/midi"; function gsPatchName(program: number, bankLsb: number): string { return ( GS_VARIATIONS[gm2Key(program, bankLsb)] ?? GM_LEVEL1_PATCHES[program] ?? `Program ${program}` ); } ``` ## API Reference - `GS_VARIATIONS: Readonly>` — frozen map; same key encoding as `GM_LEVEL2_VARIATIONS`. ## Implementation Notes GS uses Bank LSB (CC 32) for variation selection — the opposite of XG which uses Bank MSB. Mixing the two on the same instance leads to silent mis-naming; consumers picking a dialect should choose at engine-construction time, not per-message. The table is intentionally a curated subset; full GS coverage (~480 entries) lives in downstream SoundFont rendering packages that map their own GS-format banks to display names.