first commit
This commit is contained in:
56
docs/media/audio/midi/src/sysex/sysex.md
Normal file
56
docs/media/audio/midi/src/sysex/sysex.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# sysex/sysex
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
`parseSysEx` and `buildSysEx` are the canonical helpers for working with MIDI System Exclusive payloads — the manufacturer-defined byte streams that sit between an `F0` prefix and an `F7` terminator. Every vendor uses SysEx for patch dumps, parameter sysex, MMC (MIDI Machine Control), and identity-request handshakes; standardising the parse / build code in one place prevents off-by-one errors with the one-byte vs three-byte manufacturer-id forms.
|
||||
|
||||
`parseSysEx` expects the *body* of the frame (i.e. everything between `F0` and `F7`, exclusive of both endpoints). `buildSysEx` produces a complete `F0...F7` frame; callers feed the result straight to `MidiPortLike.send`.
|
||||
|
||||
## Features
|
||||
|
||||
- Auto-detects one-byte vs three-byte manufacturer ids (`0x00` prefix signals the extended form).
|
||||
- Looks up the manufacturer name from the registry; returns it on `SysExFrame.manufacturerName` when known.
|
||||
- Validates that every byte in the manufacturer id, device id, and body has bit 7 clear — surfaces wire corruption instead of silently masking.
|
||||
- Rejects short payloads and missing device-id bytes loudly.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { buildSysEx, parseSysEx } from "@suaveplan/midi";
|
||||
|
||||
const frame = buildSysEx([0x43], 0x10, [0x4c, 0x00]);
|
||||
// Uint8Array(6) [0xF0, 0x43, 0x10, 0x4C, 0x00, 0xF7]
|
||||
|
||||
const parsed = parseSysEx(frame.slice(1, -1));
|
||||
// parsed.manufacturer = [0x43], parsed.manufacturerName = "Yamaha"
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import { buildSysEx, MANUFACTURERS, parseSysEx } from "@suaveplan/midi";
|
||||
|
||||
// Build a Native Instruments device-identity request.
|
||||
const ni = MANUFACTURERS.NATIVE_INSTRUMENTS.id;
|
||||
const req = buildSysEx(ni, 0x00, [0x01, 0x00]);
|
||||
await outputPort.send(req);
|
||||
|
||||
// Wait for the device's response and parse it.
|
||||
const responseBytes = await readNextSysEx(outputPort);
|
||||
const response = parseSysEx(responseBytes);
|
||||
console.log(response.manufacturerName, response.body);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `parseSysEx(payload: Uint8Array): SysExFrame` — parses the body between `F0` and `F7`. Throws `MidiError("MIDI.INVALID_SYSEX")` for short, malformed, or extended-id-truncated payloads.
|
||||
- `buildSysEx(manufacturer: ManufacturerId, deviceId: number, body: Uint8Array | readonly number[]): Uint8Array` — produces a full F0/F7-framed byte sequence; throws on high-bit-set inputs.
|
||||
- `SysExFrame { manufacturer; manufacturerName?; deviceId; body }` — the parsed shape.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The build path walks the input three times: once for manufacturer validation, once for body validation, once for the final write. The cost is three pure-numeric loops over typically very short arrays (manufacturer ids are 1 or 3 bytes; bodies are usually <64 bytes for parameter messages), so the constant is negligible compared to the IO that follows. Parse uses `Uint8Array.slice` to detach the body from the input buffer — callers that mutate the source buffer afterwards do not affect already-parsed frames.
|
||||
Reference in New Issue
Block a user