Lab

piano

The piano's controller from @audio-ui/core: which keys sound, played by pointer, glide or keyboard, one note per pointer, and where each key sits on a keyboard or a piano roll's rows.

pnpm add @audio-ui/core
import { createPianoController, KEYBOARD_VELOCITY, MIN_VELOCITY, BLACK_KEY_DEPTH, keyAt, /* … */ } from "@audio-ui/core/piano";
Adapters@audio-ui/react/piano, @audio-ui/elements/piano
ExportKindWhat it is
createPianoControllerfunctionA keyboard's behavior with no view attached: which keys sound, by pointer, glide or keyboard, how hard, and where the keyboard's one tab stop is.
KEYBOARD_VELOCITYconstWhat a key played from the keyboard sounds at.
MIN_VELOCITYconstThe softest a pointer press plays: the very top of a key, not silence.
PianoControllerinterfaceWhat createPianoController returns: the snapshot to draw from, and the presses, keys and focus moves of the keyboard.
PianoNoteOffEventDetailstypeWhat onNoteOff receives when a key stops: the reason ("press", "glide" or "keyboard") and the event.
PianoNoteOnEventDetailstypeWhat onNoteOn receives when a key sounds: its velocity, from 0 to 1, the reason ("press", "glide" or "keyboard"), the event, and cancel() to refuse it.
PianoOptionsinterfaceThe options of createPianoController: the pitches, their layout and orientation, the notes lit from elsewhere, and the callbacks.
PianoSnapshotinterfaceWhat a view draws the keyboard from: the pitches and where each key sits, the ones sounding, and the tab stop.
BLACK_KEY_DEPTHconstHow far across the keyboard a black key reaches; past it, a press lands on a white key.
KeyLayouttypeHow the keys share the keyboard's length: "keyboard" like a piano, white keys side by side with the black ones between them, or "even", one equal share each, the way a piano roll's rows are.
KeyPlacementinterfaceWhere a key sits along the keyboard, how much of it it takes, and whether it is black.
keyAtfunctionThe key under a point, given as shares of the keyboard: along its length from the low end, across its depth from the back, where black keys are.
placeKeysfunctionWhere each of pitches (lowest first) sits along the keyboard.

Usage

The controller follows the contract every controller shares, with notes in place of a value:

import { createPianoController } from "@audio-ui/core/piano";

const piano = createPianoController({
  layout: "keyboard",
  minPitch: 48,
  maxPitch: 72,
  orientation: "horizontal",
  onNoteOn: (pitch) => synth.noteOn(pitch),
  onNoteOff: (pitch) => synth.noteOff(pitch),
});

The piano reports a note on when a key is pressed and a note off when it is released, one per pointer, so two fingers can hold two keys. keyOn(pitch, event) and keyOff(pitch, event) do the same for the keyboard, and navigate(pitch, event) moves focus between keys with the arrows. getSnapshot() gives each key's placements and the active set, which an element draws.

A pointer press sounds harder toward the near end of a key, from MIN_VELOCITY at its very top; a key played from the keyboard sounds at KEYBOARD_VELOCITY.

Layout

placeKeys(pitches, layout) says where each key sits along the keyboard, from 0 to 1: "keyboard" lays white keys side by side with the black ones between them, as on a piano, and "even" gives each key an equal share, as a piano roll's rows are. keyAt(placements, along, across, layout) is the key under a point: past BLACK_KEY_DEPTH across the keyboard, a press lands on a white key.

The Piano draws this controller in React.

Built by Ouest Labs, the source code is available on GitHub.
RSS