+
Piano · {name}
-
playPiano(selectedPiano.voicing)}
- />
+ {/* pianoVoicing() output carries no rootPc, and without it VoicingPiano
+ falls back to the LOWEST voice for its "R" badge — wrong for rootless
+ voicings, whose bass is the 3rd (A) or 7th (B). Supply the chord root. */}
{pianoOptions.map(({ style, voicing }) => (
- {
- stopCurrent()
- setPianoStyle(style)
- }}
+ label={voicing.label}
+ playLabel={`Play ${name} — ${voicing.label} piano voicing`}
+ onPlay={() => playPiano(voicing)}
>
- {voicing.label}
-
+
+
))}
-
- {/* MiniPiano's SVG has a fixed pixel width (up to ~390px for 3 octaves);
- scroll it on narrow columns rather than letting it break the layout.
- pianoVoicing() output carries no rootPc, and without it VoicingPiano
- falls back to the LOWEST voice for its "R" badge — wrong for rootless
- voicings, whose bass is the 3rd (A) or 7th (B). Supply the chord root. */}
-
-
-
)}
{/* Mic-feedback caveat, per the L-20 header + D-20 §3 (microcopy tier).
- At least one row always renders (see the gating above), so this stays. */}
+ At least one section always renders (see the gating above), so this stays. */}
Previews play through your speakers — while the mic is live, detection may
hear them.