Yann
test
f23825d
raw
history blame
2.11 kB
import { NoteOffEvent, NoteOnEvent } from "midifile-ts"
import { noteOffMidiEvent, noteOnMidiEvent } from "../midi/MidiEvent"
import { NoteEvent, TickProvider } from "../track"
/**
assemble noteOn and noteOff to single note event to append duration
*/
export function assemble<T extends {}>(
events: (T | TickNoteOffEvent | TickNoteOnEvent)[],
): (T | NoteEvent)[] {
const noteOnEvents: TickNoteOnEvent[] = []
function findNoteOn(noteOff: TickNoteOffEvent): TickNoteOnEvent | null {
const i = noteOnEvents.findIndex((e) => {
return e.noteNumber === noteOff.noteNumber
})
if (i < 0) {
return null
}
const e = noteOnEvents[i]
noteOnEvents.splice(i, 1)
return e
}
const result: (T | NoteEvent)[] = []
events.forEach((e) => {
if ("subtype" in e) {
switch (e.subtype) {
case "noteOn":
noteOnEvents.push(e)
break
case "noteOff": {
const noteOn = findNoteOn(e)
if (noteOn != null) {
const note: NoteEvent = {
...noteOn,
subtype: "note",
id: -1,
tick: noteOn.tick,
duration: e.tick - noteOn.tick,
}
result.push(note)
}
break
}
default:
result.push(e)
break
}
} else {
result.push(e)
}
})
return result
}
export type TickNoteOnEvent = Omit<NoteOnEvent, "channel" | "deltaTime"> &
TickProvider
export type TickNoteOffEvent = Omit<NoteOffEvent, "channel" | "deltaTime"> &
TickProvider
// separate note to noteOn + noteOff
export function deassemble<T extends {}>(
e: T | NoteEvent,
): (T | TickNoteOnEvent | TickNoteOffEvent)[] {
if ("subtype" in e && e.subtype === "note") {
const channel = (e as any)["channel"] ?? -1
const noteOn = noteOnMidiEvent(0, channel, e.noteNumber, e.velocity)
const noteOff = noteOffMidiEvent(0, channel, e.noteNumber)
return [
{ ...noteOn, tick: e.tick },
{ ...noteOff, tick: e.tick + e.duration },
]
} else {
return [e as T]
}
}