Files
2026-05-27 23:47:53 +01:00

2.4 KiB
Raw Permalink Blame History

maschine

(no submodules)

Purpose

MaschinePlugin is the concrete MidiControllerPlugin subclass for Native Instruments Maschine: a 16-pad grid with per-pad velocity, a 16-step sequencer row per pad, and slot-based sample loading. It inherits the universal MIDI lifecycle from the base and adds the device-specific surface declared by the spec: setPadVelocity, setStep, and loadSample. Sample loading is delegated to an injectable SampleLoader so the package stays universal and side-effect-free.

Features

  • 16 pads × 16 steps internal grid.
  • Per-pad velocity table (0–127) with MIDIOutput echo.
  • loadSample(slot, id, { signal }) honours AbortSignal both before and after the loader resolves.
  • Range-checked pad index, step index, velocity, and slot index.
  • Sample registry exposed via getSample(slotIndex).

Usage: Basic

const maschine = new MaschinePlugin({ adapter, transport });
await maschine.initialize();
maschine.setPadVelocity(3, 96);
maschine.setStep(3, 0, true);
await maschine.loadSample(3, "kick-808");

Usage: Advanced

const ctl = new AbortController();
const maschine = new MaschinePlugin({
  adapter,
  transport,
  sampleLoader: async (id, signal) => loadFromDrive(id, signal),
});
await maschine.initialize({ signal: ctl.signal });
maschine.setPadVelocity(0, 127);
maschine.setStep(0, 0, true);
maschine.setStep(0, 4, true);
maschine.setStep(0, 8, true);
maschine.setStep(0, 12, true);
await maschine.loadSample(0, "kick-808", { signal: ctl.signal });

API Reference

  • new MaschinePlugin({ adapter, transport, sampleLoader? }).
  • setPadVelocity(padIndex, velocity) / getPadVelocity(padIndex).
  • setStep(padIndex, stepIndex, active) / getStep(padIndex, stepIndex).
  • loadSample(slotIndex, sampleId, { signal? }) → Promise<void>.
  • getSample(slotIndex) → string | undefined.

Implementation Notes

loadSample performs a pre-await abort check, awaits the loader, then re-checks the signal at the next await boundary — the spec's "mid-operation abort" guarantee. Any failure inside the loader is re-thrown as AUDIO_CONTROLLERS.DEVICE_ERROR carrying the original error as cause, so consumers can introspect transport-layer failures without re-implementing error mapping. The default loader is a no-op suitable for unit-test scenarios; production callers wire in their own.