remove beginner/advanced mode, fix D7 detection, history on key lock, stable loop display
This commit is contained in:
+13
-30
@@ -22,9 +22,6 @@ export default function App() {
|
|||||||
// ── Listening state ──────────────────────────────────────────────────────
|
// ── Listening state ──────────────────────────────────────────────────────
|
||||||
const [isListening, setIsListening] = useState(false)
|
const [isListening, setIsListening] = useState(false)
|
||||||
|
|
||||||
// ── App mode ─────────────────────────────────────────────────────────────
|
|
||||||
const [appMode, setAppMode] = useState('beginner') // 'beginner' | 'advanced'
|
|
||||||
|
|
||||||
// ── Key: auto-detected + optional lock ───────────────────────────────────
|
// ── Key: auto-detected + optional lock ───────────────────────────────────
|
||||||
const [keyInfo, setKeyInfo] = useState(null) // auto-detected
|
const [keyInfo, setKeyInfo] = useState(null) // auto-detected
|
||||||
const [lockedKey, setLockedKey] = useState(null) // { root, mode } or null
|
const [lockedKey, setLockedKey] = useState(null) // { root, mode } or null
|
||||||
@@ -33,9 +30,6 @@ export default function App() {
|
|||||||
|
|
||||||
// Effective key used by all components
|
// Effective key used by all components
|
||||||
const effectiveKey = lockedKey ?? keyInfo
|
const effectiveKey = lockedKey ?? keyInfo
|
||||||
// Beginner + locked key = only match the 7 diatonic chords (simpler, fewer false positives)
|
|
||||||
// Advanced + locked key = allow borrowed/chromatic chords like D7 in Am
|
|
||||||
const isStrictMode = appMode === 'beginner' && lockedKey !== null
|
|
||||||
|
|
||||||
// ── Chord state ───────────────────────────────────────────────────────────
|
// ── Chord state ───────────────────────────────────────────────────────────
|
||||||
const [chordHistory, setChordHistory] = useState([])
|
const [chordHistory, setChordHistory] = useState([])
|
||||||
@@ -52,14 +46,22 @@ export default function App() {
|
|||||||
Array.from({ length: CHROMA_SMOOTH }, () => new Float32Array(12))
|
Array.from({ length: CHROMA_SMOOTH }, () => new Float32Array(12))
|
||||||
)
|
)
|
||||||
const chromaIdxRef = useRef(0)
|
const chromaIdxRef = useRef(0)
|
||||||
const chordVotesRef = useRef([])
|
const chordVotesRef = useRef([])
|
||||||
|
const progressionVoteRef = useRef(null) // stabilise loop display
|
||||||
|
|
||||||
// Keep ref in sync
|
// Keep ref in sync
|
||||||
useEffect(() => { effectiveKeyRef.current = effectiveKey }, [effectiveKey])
|
useEffect(() => { effectiveKeyRef.current = effectiveKey }, [effectiveKey])
|
||||||
|
|
||||||
// ── Detect progression whenever chord history changes ─────────────────────
|
// ── Detect progression — require 2 consecutive identical results to commit ─
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setDetectedProgression(detectRepeatingProgression(chordHistory))
|
const detected = detectRepeatingProgression(chordHistory)
|
||||||
|
if (!detected) return
|
||||||
|
const key = detected.join(',')
|
||||||
|
if (progressionVoteRef.current === key) {
|
||||||
|
setDetectedProgression(detected)
|
||||||
|
} else {
|
||||||
|
progressionVoteRef.current = key
|
||||||
|
}
|
||||||
}, [chordHistory])
|
}, [chordHistory])
|
||||||
|
|
||||||
// ── Key lock handlers ─────────────────────────────────────────────────────
|
// ── Key lock handlers ─────────────────────────────────────────────────────
|
||||||
@@ -68,8 +70,6 @@ export default function App() {
|
|||||||
setLockedKey(info)
|
setLockedKey(info)
|
||||||
effectiveKeyRef.current = info
|
effectiveKeyRef.current = info
|
||||||
chordVotesRef.current = []
|
chordVotesRef.current = []
|
||||||
setChordHistory([])
|
|
||||||
setDetectedProgression(null)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function quickLock({ root, mode, confidence }) {
|
function quickLock({ root, mode, confidence }) {
|
||||||
@@ -77,8 +77,6 @@ export default function App() {
|
|||||||
setLockedKey(info)
|
setLockedKey(info)
|
||||||
effectiveKeyRef.current = info
|
effectiveKeyRef.current = info
|
||||||
chordVotesRef.current = []
|
chordVotesRef.current = []
|
||||||
setChordHistory([])
|
|
||||||
setDetectedProgression(null)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeLock() {
|
function removeLock() {
|
||||||
@@ -136,7 +134,7 @@ export default function App() {
|
|||||||
for (const frame of ring) for (let i = 0; i < 12; i++) avg[i] += frame[i]
|
for (const frame of ring) for (let i = 0; i < 12; i++) avg[i] += frame[i]
|
||||||
for (let i = 0; i < 12; i++) avg[i] /= CHROMA_SMOOTH
|
for (let i = 0; i < 12; i++) avg[i] /= CHROMA_SMOOTH
|
||||||
|
|
||||||
const chord = matchChordFromChroma(avg, key, bassPC, isStrictMode)
|
const chord = matchChordFromChroma(avg, key, bassPC, false)
|
||||||
if (!chord) {
|
if (!chord) {
|
||||||
// Ambiguous moment (transition, silence) — reset streak, history is untouched
|
// Ambiguous moment (transition, silence) — reset streak, history is untouched
|
||||||
chordVotesRef.current = []
|
chordVotesRef.current = []
|
||||||
@@ -184,21 +182,6 @@ export default function App() {
|
|||||||
|
|
||||||
{/* ── Controls bar ── */}
|
{/* ── Controls bar ── */}
|
||||||
<div className="mb-4 flex flex-wrap gap-3 items-center p-3 bg-panel border border-border rounded-xl">
|
<div className="mb-4 flex flex-wrap gap-3 items-center p-3 bg-panel border border-border rounded-xl">
|
||||||
{/* Mode toggle */}
|
|
||||||
<div className="flex bg-surface border border-border rounded-full p-0.5 text-sm">
|
|
||||||
{['beginner', 'advanced'].map(m => (
|
|
||||||
<button
|
|
||||||
key={m}
|
|
||||||
onClick={() => setAppMode(m)}
|
|
||||||
className={`px-4 py-1 rounded-full capitalize transition-all ${
|
|
||||||
appMode === m ? 'bg-accent text-white' : 'text-gray-400 hover:text-gray-200'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{m}
|
|
||||||
</button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Key lock */}
|
{/* Key lock */}
|
||||||
{lockedKey ? (
|
{lockedKey ? (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
@@ -276,7 +259,7 @@ export default function App() {
|
|||||||
<Fretboard
|
<Fretboard
|
||||||
keyInfo={effectiveKey}
|
keyInfo={effectiveKey}
|
||||||
currentChord={currentChord}
|
currentChord={currentChord}
|
||||||
pentatonicOnly={appMode === 'beginner'}
|
pentatonicOnly={false}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="md:col-span-2">
|
<div className="md:col-span-2">
|
||||||
|
|||||||
Reference in New Issue
Block a user