Files
skills/docs/media/audio/midi/src/sysex/manufacturers.md
2026-05-29 08:20:56 +01:00

3.0 KiB

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

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

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.