Spaces:
Sleeping
Sleeping
| 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] | |
| } | |
| } | |