first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
# gm/level1
## Purpose
The General MIDI Level 1 patch and percussion tables — the canonical instrument-name lookups every GM-compliant playback engine, score editor, and patch-browser needs. Without a shared source of truth, every consumer ends up hand-typing the same 128-entry table with the same handful of typos ("Honky-Tonk Piano" vs "Honky-tonk Piano" being a perennial favourite).
This module exposes three immutable, exhaustive tables: the 128-entry patch map (`GM_LEVEL1_PATCHES`, program 0..127), the 47-entry percussion map (`GM_LEVEL1_PERCUSSION`, notes 35..81), and the 16-entry family list (`GM_LEVEL1_FAMILIES`, grouped in eight-program blocks). Spelling and capitalisation follow the official MMA specification.
## Features
- Frozen `GM_LEVEL1_PATCHES` covering every program 0..127 with the spec-canonical name.
- Frozen `GM_LEVEL1_PERCUSSION` covering channel-10 drum notes 35..81.
- Frozen `GM_LEVEL1_FAMILIES` for UI grouping (program ÷ 8).
- All tables use the MMA canonical capitalisation — diff-compatible with other specs.
## Usage: Basic
```ts
import { GM_LEVEL1_PATCHES, GM_LEVEL1_PERCUSSION } from "@suaveplan/midi";
console.log(GM_LEVEL1_PATCHES[0]); // "Acoustic Grand Piano"
console.log(GM_LEVEL1_PERCUSSION[36]); // "Bass Drum 1"
```
## Usage: Advanced
```ts
import { GM_LEVEL1_FAMILIES, GM_LEVEL1_PATCHES } from "@suaveplan/midi";
// Build a hierarchical patch browser for a UI tree component.
function buildPatchTree() {
const tree = GM_LEVEL1_FAMILIES.map((family, i) => ({
name: family,
patches: Array.from({ length: 8 }, (_, j) => {
const program = i * 8 + j;
return { program, name: GM_LEVEL1_PATCHES[program]! };
}),
}));
return tree;
}
```
## API Reference
- `GM_LEVEL1_PATCHES: Readonly<Record<number, string>>` — frozen map, 128 entries (programs 0..127).
- `GM_LEVEL1_PERCUSSION: Readonly<Record<number, string>>` — frozen map, 47 entries (notes 35..81 on channel 10).
- `GM_LEVEL1_FAMILIES: readonly string[]` — 16 instrument-family names, indexed by `Math.floor(program / 8)`.
## Implementation Notes
Both maps are declared as `Object.freeze({ ... })` rather than via numeric arrays because programs and percussion notes are sparse from the consumer's perspective — looking up `PERCUSSION[36]` directly is clearer than `PERCUSSION[36 - 35]`. The freeze guarantees downstream compose patterns (`{ ...GM_LEVEL1_PATCHES, 0: 'Custom Piano' }`) produce a new object rather than mutating the canonical table.