Skip to content

Commit 9aa2e0f

Browse files
k-l-lambdaclaude
andcommitted
fix: Add default tempo for MIDI playback
- Parse MIDI data through MusicNotation.Notation.parseMidi - Add default tempo (120 BPM) if Verovio MIDI doesn't include tempo events - Fixes "invalid notation, tempos is empty" error Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 949fb06 commit 9aa2e0f

File tree

1 file changed

+15
-9
lines changed

1 file changed

+15
-9
lines changed

src/lib/components/Player.svelte

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
import { onMount, onDestroy } from 'svelte';
33
import { editorStore } from '$lib/stores/editor';
44
import { getToolkit } from '$lib/verovio/toolkit';
5-
import { MIDI, MusicNotation, MidiPlayer } from '@k-l-lambda/music-widgets';
5+
import { MIDI, MidiPlayer, MusicNotation } from '@k-l-lambda/music-widgets';
66
import { MidiAudio } from '@k-l-lambda/music-widgets/dist/musicWidgetsBrowser.es.js';
77
88
let isPlaying = false;
99
let currentTime = 0;
1010
let duration = 0;
1111
let midiPlayer: any = null;
12-
let midiNotation: any = null;
12+
let midiData: any = null;
1313
let isAudioLoaded = false;
1414
1515
onMount(async () => {
@@ -39,22 +39,28 @@
3939
bytes[i] = binaryString.charCodeAt(i);
4040
}
4141
42-
const midiData = MIDI.parseMidiData(bytes.buffer);
43-
midiNotation = MusicNotation.Notation.parseMidi(midiData);
44-
42+
const rawMidiData = MIDI.parseMidiData(bytes.buffer);
43+
// Parse to notation and add default tempo if missing
44+
const notation = MusicNotation.Notation.parseMidi(rawMidiData);
45+
if (!notation.tempos || notation.tempos.length === 0) {
46+
// Add default tempo (120 BPM = 500000 microseconds per beat)
47+
notation.tempos = [{ tempo: 500000, tick: 0, time: 0 }];
48+
}
49+
midiData = notation;
50+
4551
if (midiPlayer) {
4652
midiPlayer.dispose();
4753
}
4854
49-
midiPlayer = new MidiPlayer(midiNotation, {
55+
midiPlayer = new MidiPlayer(midiData, {
5056
cacheSpan: 400,
5157
onMidi: (data: any, timestamp: number) => {
5258
switch (data.subtype) {
5359
case 'noteOn':
54-
MidiAudio.noteOn(data.channel, data.noteNumber, data.velocity, timestamp / 1000);
60+
MidiAudio.noteOn(data.channel, data.noteNumber, data.velocity, timestamp);
5561
break;
5662
case 'noteOff':
57-
MidiAudio.noteOff(data.channel, data.noteNumber, timestamp / 1000);
63+
MidiAudio.noteOff(data.channel, data.noteNumber, timestamp);
5864
break;
5965
case 'programChange':
6066
MidiAudio.programChange(data.channel, data.programNumber);
@@ -75,7 +81,7 @@
7581
}
7682
});
7783
78-
duration = midiNotation.endTime;
84+
duration = midiData.endTime;
7985
} catch (error) {
8086
console.error('Failed to initialize player:', error);
8187
}

0 commit comments

Comments
 (0)