Spaces:
Running
Running
File size: 2,112 Bytes
f23825d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
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]
}
}
|