Spaces:
Running
Running
import { SynthEvent } from "@ryohey/wavelet" | |
import Song from "../song" | |
const tickToMillisec = (tick: number, bpm: number, timebase: number) => | |
(tick / (timebase / 60) / bpm) * 1000 | |
interface Keyframe { | |
tick: number | |
bpm: number | |
timestamp: number | |
} | |
export const songToSynthEvents = ( | |
song: Song, | |
sampleRate: number, | |
): SynthEvent[] => { | |
const events = [...song.allEvents].sort((a, b) => a.tick - b.tick) | |
let keyframe: Keyframe = { | |
tick: 0, | |
bpm: 120, | |
timestamp: 0, | |
} | |
const synthEvents: SynthEvent[] = [] | |
// channel γ€γγ³γγ MIDI Output γ«ιδΏ‘ | |
// Send Channel Event to MIDI OUTPUT | |
for (const e of events) { | |
const timestamp = | |
tickToMillisec(e.tick - keyframe.tick, keyframe.bpm, song.timebase) + | |
keyframe.timestamp | |
const delayTime = (timestamp / 1000) * sampleRate | |
switch (e.type) { | |
case "channel": | |
synthEvents.push({ | |
type: "midi", | |
midi: e, | |
delayTime, | |
}) | |
case "meta": | |
switch (e.subtype) { | |
case "setTempo": | |
keyframe = { | |
tick: e.tick, | |
bpm: (60 * 1000000) / e.microsecondsPerBeat, | |
timestamp, | |
} | |
break | |
} | |
} | |
} | |
return synthEvents | |
} | |