Consonance Matrix
consonance-matrixVisualizersA playing aid rather than an analysis: twelve cells, C through B, each shaded by how well that note agrees with the current harmony. Bright means it will land, dim means it will fight. The context has two halves and blending them is what makes it useful — the held chord is fast-moving and knows what your hands are doing, the tonal histogram is slow-moving and knows what key you are in. Either alone is worse: the chord alone relights the whole row on every change and loses the key, the histogram alone never responds to you. Blended, a note belonging to both glows brightest, which is exactly the note that will sound most resolved. One thing to understand before reading it: the shading is min-max normalised across the twelve, not absolute. Raw consonance scores cluster in a narrow band, so an absolute scale would render twelve near-identical grey cells; normalising against the current spread turns that into a visible ranking. So there is always a brightest and a dimmest cell. Read it as a ranking, not a set of verdicts. This is the same maths the reference hardware lights its strum-bar LEDs with.
Slide to 0 and the row is the key alone — the same seven notes stay lit whatever you hold. Slide to 1 and it tracks only the chord. In between, the notes belonging to both glow brightest.
Install
Copies the source into your project. Anything it depends on comes with it.
$ npx shadcn add @syntho-ui/consonance-matrixPulls in
First time? Add the registry to your components.json once:
{
"registries": {
"@syntho-ui": "https://engine.syntho.app/r/{name}.json"
}
}Usage
Controlled or uncontrolled, whichever suits the surrounding state.
import { ConsonanceMatrix } from "@/components/ui/consonance-matrix"
<ConsonanceMatrix
referencePcs={[0, 4, 7]}
histogram={[10, 0, 6, 0, 8, 6, 0, 9, 0, 6, 0, 4]}
chordWeight={0.5}
rootPc={0}
/>Props
| Prop | Type | Default | Description |
|---|---|---|---|
| referencePcs | number[] | — | Pitch classes sounding right now — typically the held chord. Reduced mod 12, so raw MIDI works. |
| histogram | number[] | — | Length-12 pitch-class weights in CHROMATIC order (0 = C … 11 = B): the tonal field the piece has established. Units are arbitrary. |
| chordWeight | number | 0.5 | How much the held chord counts against the histogram. 1 is the chord alone, 0 the histogram alone. |
| rootPc | number | — | Marks this pitch class as the root/tonic with a tick beneath its cell. |
| labels | boolean | true | Draw the note name in each cell. |
| height | number | 44 | Height of the cells in pixels. |
| color | string | — | Cell colour. Defaults to the --uikit-accent token; brightness varies per cell. |
Interaction
- Drag with pointer capture, so the gesture keeps tracking past the edge of the control.
- Shift while dragging for a fine pass; release it mid-gesture and coarse tracking resumes.
- Double-click resets to
defaultValue. - Arrow keys step normally, Shift+arrow steps finely, PageUp/PageDown jump by ten, Home/End go to the extremes.
- Proper
sliderandswitchroles with livearia-valuetext, so a screen reader announces the formatted value rather than the raw number. - The scroll wheel adjusts the value while the pointer is over the control; stepped ranges move at least one declared step per notch by default.