Initial Commit
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
# maschine
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## 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
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
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.
|
||||
Reference in New Issue
Block a user