mirror of
https://github.com/9x/sheetmusictrainer.git
synced 2026-11-03 22:03:54 +01:00
Arpeggio sequences + auto-start on first note
- Sequence mode: bars (2/4/6/8) with one chord per bar, chosen by functional rules (I->IV/V/vi...), diatonic cycle, or random (no immediate repeats); deterministic via melody seed. Chord symbols per bar in the score model (chordSymbols) rendered above the staff via setSection. - Rhythm: quarters or eighths (cycling up/down through the pattern). - Single-chord mode unchanged (whole path, overflow bars if needed). - Auto-start: 'Start on first note (no count-in)' — step pace begins the run as soon as the mic detects the first note; no start press needed. - 'New' button re-rolls the progression (new seed). - Tests 174/174.
This commit is contained in:
@@ -34,6 +34,9 @@ export interface PhraseTrainerConfig {
|
||||
readonly clickSound: boolean;
|
||||
readonly inputMode: 'mic' | 'virtual';
|
||||
readonly previewVolume?: number;
|
||||
/** Auto-start: begin without count-in as soon as the mic detects the
|
||||
* first note (step pace only — tempo needs the scheduled clock). */
|
||||
readonly autoStartOnNote?: boolean;
|
||||
}
|
||||
|
||||
export interface PhraseSummary {
|
||||
@@ -282,7 +285,18 @@ export function usePhraseTrainer(
|
||||
const unsubscribe = subscribeRawFrames(frame => {
|
||||
if (configRef.current.inputMode !== 'mic') return;
|
||||
const p = phaseRef.current;
|
||||
if (p !== 'countIn' && p !== 'playing') return;
|
||||
// Auto-start: first detected note begins the run immediately
|
||||
// (no count-in) — only in step pace, only from 'ready', mic only.
|
||||
if (
|
||||
p === 'ready' &&
|
||||
configRef.current.autoStartOnNote &&
|
||||
paceRef.current === 'step'
|
||||
) {
|
||||
startRef.current?.();
|
||||
// Fall through: this frame feeds the fresh run below.
|
||||
}
|
||||
const p2 = phaseRef.current;
|
||||
if (p2 !== 'countIn' && p2 !== 'playing') return;
|
||||
// Pitched speaker output (preview, virtual instruments) must not
|
||||
// be scored; while audible the matcher sees no frames at all.
|
||||
if (audioEngine.isAudible()) return;
|
||||
|
||||
Reference in New Issue
Block a user