Repository navigation
Where a pattern stops being programmed and starts being played.
This release was meant to be about feel — velocity, swing, macros that move real
DSP, a keyboard you can play. It became that, and it also became a bug hunt,
because building an instrument you play meant listening to the app properly for
the first time. Three things had been wrong since v1.0 and nobody had heard them.
Play it live
K opens a 73-key keyboard, C1 to C7. A MIDI keyboard plays it, and when there
is no MIDI keyboard the computer keyboard does — two rows, z s x d c v g b h n j m , and q 2 w 3 e r 5 t 6 y 7 u i, each a complete octave. Every white key
is named and the letter is printed on every key the typing rows reach; the rest
is dimmed, so you can see where your hands are rather than having to be told.
The keyboard never moves. Shifting the octave slides the lit block along a
fixed board, exactly one octave a step, the way transpose works on real
hardware. Three earlier versions moved the keys instead and all three felt
broken.
The live voice is built by the same resolver the scheduler uses, so what you
play is what the clip plays back — custom instruments included — and it runs
through that track's effects, fader and pan. Notes land in a MIDI clip while a
track is armed, held chords included.
On a drum track the keys are labelled with drums rather than notes — BD2, SN1,
CHH, on the black keys too, since that is where General MIDI puts the hats.
The key a piano calls C3 is a tom on a kit.
The MIDI hardware path was built against the specification. No keyboard was
available to test it on, so reports from anyone with one are very welcome.
The drums had been playing the wrong sounds since v1.0
Tone reads a sampler's note-name keys as scientific pitch, so C1 is MIDI 24.
General MIDI puts the kick at 36. All six kits were keyed by note name, so no
slot ever resolved to the sample it named — and Tone.Sampler does not error on
a pitch it lacks, it repitches the nearest buffer it has.
| You wrote | You heard |
|---|---|
| Kick | an open hi-hat, two semitones sharp |
| Snare, both hats, ride, cowbell | the same 2.7 KB shaker, at different speeds |
Seven of the nine samples in each kit were downloaded on every visit and never
heard once. In practice the demo beats — the first thing a visitor hears — had
no kick drum at all: 7.9% of that sound's energy below 150 Hz, against 94.0%
now, and 32 dB quieter. Claps were unmapped too, so the five templates that
layer a clap on the backbeat repitched it off the snare.
The shaker has also moved off the ride cymbal, where it had been standing in.
Because the sampler walks outward from the pitch you ask for, that one sample in
the wrong slot was being handed to every cymbal, tom and latin sound above it.
Your patterns were always right. The kits were reading them wrongly.
Every note was named an octave too high
Math.floor(pitch / 12) is not the octave — MIDI 0 is C**-1** — and both the
piano roll's key column and the live keyboard used it, so middle C was drawn as
C5. The piano roll's own noteName, two hundred lines from its key column in the
same file, got it right. The two disagreed with each other and nothing threw.
Not cosmetic: the lowest octave the keyboard offered was labelled "C1" and was
really 16.35 Hz — below human hearing, below a piano's lowest note, below what
any laptop reproduces. The playable range is now C1–B7, which drops the
octave nothing could play and gains the one a piano has on top.
Your notes have not moved or changed pitch — only what they are called.
A muted track could still be heard
Clicking a note in the piano roll, or a drum in the step sequencer, played
straight to your speakers: past the track's effects, its fader, its pan, and its
mute and solo buttons. Measured with every track muted, clicking a drum put
−34.8 dB on the output while the mixer's own meter sat silent.
It also wasn't the track's instrument. Every melodic track auditioned through
one generic synth, so clicking a note on a Rhodes played something that was not
a Rhodes — true since v1.0. Previews now run through the track they belong to.
Also new
- You can change a track's instrument. Until now the only way was to drag one
from the browser, which also created a clip and filled it with demo notes — so
there was no way to change what a track sounded like without changing what
was on it. The Inspector has an Instrument field on the track and on the
clip, and it is a search box rather than a 64-item menu. - Grand Piano. The low half of the keyboard used to be a bare sine wave,
which a laptop speaker cannot reproduce below middle C. The new FM piano
carries those notes on their harmonics: at C2 and C3, 57% and 75% of the
note now lands where a laptop can play it, against 0% before. - Custom instruments (#21) — start from any of 58 built-ins, move four
controls, hear it as you go. Save, duplicate, and share as a file. Drum kits
too, with Pitch, Decay and Snap. - Clip macros that do something — Energy, Groove, Brightness and Space
applied inside the scheduler, so playback and export cannot disagree. - A velocity lane, a default-velocity control, and velocity drawn into the
clip preview, so a flat part looks flat. - Swing, a real snap grid with triplets, a vibe-based key and scale picker,
and stretch-to-BPM for audio clips. - Recording looks like recording — a count-in overlay you can set and cancel,
an ARMED badge, a pulsing region where the take is landing. Every track type
can be armed now, and arming a MIDI track raises no microphone prompt. - Screen readers can tell whether mute, solo, Loop and the Metronome are on.
They changed colour and said nothing. R,L,Mand?had been printed in tooltips and bound to nothing since
v1.0. All four work, and the build now fails on any key hint nothing binds.
For contributors
npm run check grew build gates for keyboard hints naming unbound keys, reduced
motion, i18n coverage, locale placeholder parity, and the exhaustiveness of the
three hand-maintained lists of Project fields that had each already cost a bug.
656 tests.
Two rules came out of this release worth knowing before touching audio: Tone
cannot be constructed under vitest, so no unit test can prove a synth sounds
right — anything about sound has to be measured in a browser; and a kit or preset
written as a factory is a sound nothing can check, which is why they are data now.
The shaker fix survived a deliberate revert with every test green before that
changed.
Nothing in this release has been assessed by ear. Every audio claim above is
a measurement.
Full changelog: https://github.com/AppsYogi-com/ComposeYogi/blob/main/CHANGELOG.md