first commit
This commit is contained in:
63
docs/media/audio/midi/src/sysex/manufacturers.md
Normal file
63
docs/media/audio/midi/src/sysex/manufacturers.md
Normal 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.
|
||||
Reference in New Issue
Block a user