1.8 KiB
gm/xg
Purpose
Yamaha's XG dialect uses Bank-Select MSB (CC 0) to select instrument variations on top of the GM1 base programs — the inverse of GS, which uses Bank LSB. The XG specification covers hundreds of variations across the full program range; this module exposes a curated set of the canonical XG patches every XG-aware engine should at least be able to label.
The table key encoding intentionally matches gm2Key(program, bankMsb) so consumers can write a single resolver function that handles all three dialects by branching on which CC carried the bank select.
Features
XG_VARIATIONSfrozen map keyed byprogram * 256 + bankMsb.- Mandatory XG variation set; vendor-specific extensions layer on top.
- Same key encoding as
GS_VARIATIONSandGM_LEVEL2_VARIATIONS— uniform composition. - Frozen object to safeguard against accidental mutation.
Usage: Basic
import { XG_VARIATIONS, gm2Key } from "@suaveplan/midi";
console.log(XG_VARIATIONS[gm2Key(56, 16)]); // "Trumpet 2"
Usage: Advanced
import {
GM_LEVEL1_PATCHES,
XG_VARIATIONS,
gm2Key,
} from "@suaveplan/midi";
function xgPatchName(program: number, bankMsb: number): string {
return (
XG_VARIATIONS[gm2Key(program, bankMsb)] ??
GM_LEVEL1_PATCHES[program] ??
`Program ${program}`
);
}
API Reference
XG_VARIATIONS: Readonly<Record<number, string>>— frozen map; key encoding isprogram * 256 + bankMsb.
Implementation Notes
Because XG selects on Bank MSB rather than LSB, an engine running multiple dialects in parallel must track both CCs separately and dispatch on the dialect chosen for the channel. The frozen-object idiom keeps the runtime contract immutable: composing { ...XG_VARIATIONS, [gm2Key(80, 64)]: 'Custom Lead' } produces a fresh object without touching the canonical export.