Add piano fingering generation and display via pianoplayer, fix silent audio on first load

This commit is contained in:
Fabricio Giglio
2026-05-10 23:50:20 +02:00
parent 5c0ad9afd1
commit c6a0c7f676
8 changed files with 542 additions and 162 deletions
+21 -1
View File
@@ -44,7 +44,9 @@ export function PracticeView() {
isLoadingDocument,
} = useAppStore();
// Pre-warm audio so piano keys respond with minimal latency.
// Pre-warm sample loading so piano keys respond with minimal latency.
// Sample fetch (CDN) does NOT need a user gesture - just creates an
// AudioContext (suspended) and downloads samples in the background.
useEffect(() => {
syncEngine.audio.load().catch(() => {});
const preWarm = () => syncEngine.audio.load().catch(() => {});
@@ -52,6 +54,24 @@ export function PracticeView() {
return () => document.removeEventListener("pointermove", preWarm);
}, []);
// Wake both audio contexts (Tone.js + smplr) on the FIRST real user gesture.
// The pre-warm above creates contexts before any gesture, so browser autoplay
// policy keeps them suspended. Without this, no sound ever plays.
useEffect(() => {
let woken = false;
const wake = () => {
if (woken) return;
woken = true;
syncEngine.wakeAudio();
};
window.addEventListener("pointerdown", wake);
window.addEventListener("keydown", wake);
return () => {
window.removeEventListener("pointerdown", wake);
window.removeEventListener("keydown", wake);
};
}, []);
// Apply theme to <html> element
useEffect(() => {
document.documentElement.dataset.theme = settings.theme;