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,63 @@
# sysex/manufacturers
## Purpose
The manufacturer-id registry maps the bytes that follow `F0` in a SysEx frame to a human-readable name. The MIDI Manufacturers Association assigns each vendor either a one-byte id (legacy, range 0x01..0x7D) or a three-byte id starting with `0x00` (modern allocations, the bulk of post-1995 vendors). This module owns the canonical mapping plus a `lookupManufacturer` helper that handles both forms.
The registry is intentionally a representative subset of the well-known assignments — synth makers, DAW makers, accessory makers — not the complete MMA database. Downstream packages that need additional ids can layer them via `Object.assign({}, MANUFACTURERS, { CUSTOM: { name, id } })` since the base object is frozen.
## Features
- One-byte ids for legacy vendors (Roland 0x41, Korg 0x42, Yamaha 0x43, etc.).
- Three-byte ids for modern vendors (Native Instruments `00 21 09`, Ableton `00 21 1D`).
- `SYSEX_UNIVERSAL_NON_REALTIME = 0x7E` and `SYSEX_UNIVERSAL_REALTIME = 0x7F` constants.
- `lookupManufacturer(idBytes)` for runtime resolution from arbitrary byte arrays.
## Usage: Basic
```ts
import { lookupManufacturer } from "@suaveplan/midi";
console.log(lookupManufacturer([0x41])); // "Roland"
console.log(lookupManufacturer([0x00, 0x21, 0x09])); // "Native Instruments"
console.log(lookupManufacturer([0x6F])); // undefined
```
## Usage: Advanced
```ts
import { MANUFACTURERS, lookupManufacturer, SYSEX_UNIVERSAL_REALTIME } from "@suaveplan/midi";
// Filter sysex messages by manufacturer.
function isUniversalRealtime(idBytes: readonly number[]): boolean {
return idBytes.length === 1 && idBytes[0] === SYSEX_UNIVERSAL_REALTIME;
}
// Extend the registry for a private vendor id.
const EXTENDED = Object.freeze({
...MANUFACTURERS,
MY_BRAND: { name: "My Brand", id: [0x00, 0x7F, 0x01] as const },
});
function nameOf(idBytes: readonly number[]): string | undefined {
for (const entry of Object.values(EXTENDED)) {
if (
entry.id.length === idBytes.length &&
entry.id.every((b, i) => b === idBytes[i])
) return entry.name;
}
return lookupManufacturer(idBytes);
}
```
## API Reference
- `MANUFACTURERS: Readonly<Record<string, ManufacturerEntry>>` — frozen registry keyed by friendly constant.
- `ManufacturerEntry { name: string; id: ManufacturerId }`.
- `ManufacturerId = readonly [number] | readonly [0x00, number, number]`.
- `lookupManufacturer(idBytes: readonly number[]): string | undefined`.
- `SYSEX_UNIVERSAL_NON_REALTIME: 0x7E`, `SYSEX_UNIVERSAL_REALTIME: 0x7F`.
## Implementation Notes
`lookupManufacturer` walks `Object.values(MANUFACTURERS)` linearly because the registry is small (under 100 entries) and the cost of building / maintaining a `Map<string, string>` keyed by stringified bytes would dwarf the lookup itself. The function uses `continue` to skip length mismatches and a labelled `match` boolean to track byte equality — avoiding a nested `every` call keeps the function within the strict-mode statement budget and produces no garbage objects per lookup.