diff --git a/src/App.tsx b/src/App.tsx index 6c80290..459cafd 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -69,6 +69,14 @@ function App() { const currentTuning = TUNINGS[settings.tuningId]; const currentInstrumentDef = INSTRUMENT_DEFINITIONS[settings.instrument]; + // Resolve overrides + const currentRangeDef = useMemo(() => { + return currentInstrumentDef.ranges.find(r => r.id === settings.difficulty); + }, [currentInstrumentDef, settings.difficulty]); + + const activeClef = currentRangeDef?.clef ?? currentInstrumentDef.clefMode; + const activeTranspose = currentRangeDef?.transpose ?? currentInstrumentDef.transpose; + // Generate valid notes based on difficulty const validNotes = useMemo(() => { // Find range config @@ -423,10 +431,10 @@ function App() { targetMidi={targetMidi} playedMidi={virtualNote ?? pitchData?.midi} keySignature={settings.keySignature} - clef={currentInstrumentDef.clefMode} - transpose={currentInstrumentDef.transpose} + clef={activeClef} + transpose={activeTranspose} width={Math.min(window.innerWidth - 40, 500)} - height={currentInstrumentDef.clefMode === 'grand' ? 260 : 180} + height={activeClef === 'grand' ? 260 : 180} hideTargetNote={settings.gameMode === 'ear_training' && !revealed} /> @@ -458,7 +466,7 @@ function App() {
{settings.showHint && (
- {getNoteDetails(targetMidi + currentInstrumentDef.transpose).scientific} + {getNoteDetails(targetMidi + activeTranspose).scientific}
)} {currentInstrumentDef.showTuning && currentTuning && ( diff --git a/src/music/InstrumentConfigs.ts b/src/music/InstrumentConfigs.ts index 4ee31c7..2563320 100644 --- a/src/music/InstrumentConfigs.ts +++ b/src/music/InstrumentConfigs.ts @@ -14,6 +14,8 @@ export interface NoteSetConfig { defaultMinFret?: number; defaultMaxFret?: number; stringIndex?: number; // 0-based index from lowest string (0) to highest + transpose?: number; // Override instrument default + clef?: ClefMode; // Override instrument default } export interface InstrumentDefinition { @@ -98,17 +100,27 @@ export const INSTRUMENT_DEFINITIONS: Record = { voice: { id: 'voice', displayName: 'Voice', - clefMode: 'treble', // Dynamic? Usually vocal music is specific clef OR treble w/ 8va. Let's stick to Treble/Bass per range? - // Actually, let's keep simple static clef or make App logic handle it. - // For now, Voice is usually Treble unless Bass/Baritone. - // Let's use Treble by default and maybe switch if range is low. + clefMode: 'treble', // Default transpose: 0, showTuning: false, ranges: [ { id: 'soprano', label: 'Soprano (C4-A5)', type: 'static', min: 60, max: 81 }, { id: 'alto', label: 'Alto (G3-E5)', type: 'static', min: 55, max: 76 }, - { id: 'tenor', label: 'Tenor (C3-A4)', type: 'static', min: 48, max: 69 }, - { id: 'bass_voice', label: 'Bass (E2-E4)', type: 'static', min: 40, max: 64 } + { + id: 'tenor', + label: 'Tenor (C3-A4) [8vb]', + type: 'static', + min: 48, max: 69, + transpose: 12 // Reads Treble, Sounds octave lower. + }, + { + id: 'bass_voice', + label: 'Bass (E2-E4)', + type: 'static', + min: 40, max: 64, + clef: 'bass', // Override to Bass Clef + transpose: 0 // Reads actual pitch on Bass Clef + } ] }, whistle: {