為何樂譜標示的節拍單位與播放 BPM 必須分開處理
Why a score's printed beat and playback BPM need separate units
Pianory 將樂譜標示的節拍單位用於顯示,並轉換為以四分音符為基準的速度,供播放時間軸計算,避免把兩種 BPM 數值當成相同速度而令播放快一倍。以每分鐘 120 拍的八分音符標記為例,會換算成每分鐘 60 個四分音符;測試確認時間軸換算結果,但未驗證真實瀏覽器的播放準確度或所有 MusicXML 檔案的表現。
A printed tempo mark can say eighth note = 120, while a playback timeline measures speed in quarter notes per minute. Treating both numbers as the same BPM would double the intended playback rate. Pianory keeps the score's beat unit for display and converts to a canonical quarter-note rate for timeline math.
In tempo.ts, a TempoMark stores the printed unit, whether it is dotted, the printed per-minute value, and quarterBpm. beatQuarters maps half, quarter and eighth notes to 2, 1 and 0.5 quarter notes respectively, then multiplies by 1.5 for one dot. So an eighth-note mark at 120 beats per minute becomes 60 quarter notes per minute. The label function reverses that conversion for the player UI, leaving the score's printed ♪ = 120 intact.
readTempoMark deliberately accepts only the first simple MusicXML <metronome> mark. Unsupported beat units, more than one dot, note-to-note relations and non-positive rates return no mark. The OSMD iterator supplies tempo points; buildTimeline scales those points against the parsed mark's quarter-note rate and retains the printed beat for display. A focused test checks that eighth note = 120 produces 60 quarter BPM at the start and converts a later point of 60 to 30 quarter BPM. The UI also uses the preserved beat when displaying the tempo slider's accessible value.
This design keeps arithmetic in one unit while showing musicians the beat the score actually printed. The focused conversion and timeline tests passed locally, but they do not measure playback accuracy in a real browser or establish how every MusicXML file behaves. I make Pianory; this example comes from its score player. AI assisted with drafting this article, and I checked the claims against the source and focused tests.
來源:DEV Community · dev.to