fix(voicings): correct movable-shape base-fret indexing in getGuitarVoicings (task L-23)

strIdx = rootStr-1 read OPEN [s6..s1] backwards: every rootStr-5 shape
sat 2 frets low, every rootStr-4 shape 5 frets low (A-shape C major
labeled fret 1 instead of 3) in ChordDetailModal/ExplorePanel/
CurrentJamPanel; rootStr-6 was accidentally correct (same pc both ends).
Now uses the shared 6-rootStr convention. Also: playChord docstring
octave example corrected. Critic PASS (6 independent fret checks +
252-entry pre/post sweep, structure unchanged).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
vadimwit
2026-07-08 22:54:18 +01:00
parent 3c903ad1d9
commit f4e0ac67e0
2 changed files with 6 additions and 3 deletions
+1 -1
View File
@@ -264,7 +264,7 @@ export function guitarShapeToNotes(shape, opts = {}) {
* Simple fallback when all you have is a bare pitch-class set (e.g. a detected
* chord's tones, no voicing). Stacks the pcs ASCENDING from the first pc, which
* is treated as the bass: each subsequent pc lands in the nearest position
* above the previous note — so [7, 11, 5] plays G3-B3-F4, a real shell, not a
* above the previous note — so [7, 11, 5] plays G4-B4-F5, a real shell, not a
* scrambled cluster. `octave` places the bass (4 = the octave starting at
* C4 = middle C; default 4; piano.js note = (octave 3) * 12 + pc).
*
+5 -2
View File
@@ -504,8 +504,11 @@ export function getGuitarVoicings(chordName) {
continue
}
// barre shape: compute rootFret on rootStr
const strIdx = shape.rootStr - 1 // 0=s6 … 5=s1
// barre shape: compute rootFret on rootStr.
// OPEN is ordered [s6 … s1] and rootStr is 1-indexed with 6 = low E,
// so string N lives at index 6 - N (same convention as ChordDiagram.jsx
// and chordAudio.guitarShapeToNotes).
const strIdx = 6 - shape.rootStr // 0=s6 … 5=s1
const openPc = OPEN[strIdx]
let rootFret = (rootPc - openPc + 12) % 12