@muse-player/core
Core React hooks and components for MXL/MusicXML score rendering and playback.
pnpm add @muse-player/core
Peer dependencies: react >=18, react-dom >=18
Warning
This package does not include Verovio or any MXL parsing capability. It only consumes pre-rendered static artifacts (manifest.json, data.json, SVG pages) produced by @muse-player/server or the muse-render CLI. You must pre-render your MXL files before using these hooks.
Hooks
useScore
Loads pre-rendered score data from a manifest URL. The URL must point to a manifest.json produced by @muse-player/server or muse-render. There is no way to load raw MXL/MusicXML files through this hook.
function useScore(): ScoreState
Parameters: None
Returns:
usePlayback
Full MIDI playback engine. Parses base64 MIDI, schedules notes via Tone.js, tracks time and measure, and supports real-time tempo changes.
function usePlayback(
midiBase64: string,
timeMap: TimeMapEntry[],
onTimeUpdate?: (time: number) => void,
onNotesUpdate?: (noteIds: string[]) => void,
instrument?: { sampler: any } | null,
): PlaybackControls
Parameters:
Returns:
Warning
The first play() call triggers Tone.start() which is required by browser audio policy. This must be called from a user gesture handler.
usePianoSampler
Loads realistic piano samples via Tone.Sampler with a compressor and reverb effects chain.
function usePianoSampler(options?: UsePianoSamplerOptions): PianoSamplerState
Parameters:
Returns:
The audio chain is: Sampler -> Compressor -> Reverb -> Destination
Automatically scrolls the score container during playback to keep the current measure visible.
function useAutoScroll(
containerRef: React.RefObject<HTMLDivElement | null>,
currentMeasure: number,
isPlaying: boolean,
): AutoScrollState
Parameters:
Returns:
Manual scrolling disables auto-scroll for 5 seconds. It re-enables immediately when playback starts.
useNoteHighlight
Draws colored overlay rectangles around actively playing notes on the score. Blue for right hand (staff 1), red for left hand (staff 2).
function useNoteHighlight(
containerRef: React.RefObject<HTMLDivElement | null>,
activeNoteIds: string[],
getElementAttribute: (xmlId: string) => Record<string, string>,
): void
Parameters:
This hook is purely side-effectful — it returns nothing.
Component
ScoreRenderer
Renders a single SVG page inside a scrollable container.
<ScoreRenderer containerRef={containerRef} svg={svg} />
Types
TimeMapEntry
interface TimeMapEntry {
off?: string[]; // XML IDs of notes ending at this time
on?: string[]; // XML IDs of notes starting at this time
qstamp: number; // Quarter-note stamp (position in score)
tempo?: number; // Tempo at this entry (BPM)
tstamp: number; // Absolute timestamp in milliseconds
}
ScoreData
interface ScoreData {
title: string;
totalPages: number;
}
ScoreManifest
interface ScoreManifest {
data: string; // Relative path to data.json
pages: string[]; // Relative paths to SVG page files
scoreData: { title: string; totalPages: number };
}
ScoreRenderResult
interface ScoreRenderResult {
elementAttributes: ElementAttributes;
midiBase64: string;
scoreData: { title: string; totalPages: number };
svgPages: string[];
timemap: TimeMapEntry[];
}
ElementAttributes
interface ElementAttributes {
[xmlId: string]: Record<string, string>;
}
NoteEvent
interface NoteEvent {
duration: number; // Note duration in seconds
midi: number; // MIDI note number (0-127)
pitch: string; // Note name (e.g., "C4", "F#5")
time: number; // Start time in seconds
}