@@ -0,0 +1,91 @@
|
||||
import {
|
||||
constantTempoMidi,
|
||||
cropMidi,
|
||||
deleteNote,
|
||||
editNote,
|
||||
dropChannel,
|
||||
encodeMidi,
|
||||
exportMidiCsv,
|
||||
exportMidiJson,
|
||||
parseMidi,
|
||||
quantizeMidi,
|
||||
remapChannel,
|
||||
transposeMidi,
|
||||
type MidiDocument,
|
||||
} from "./midi";
|
||||
|
||||
export type MidiOperation =
|
||||
| { kind: "transpose"; semitones: number }
|
||||
| { kind: "quantize"; grid: number }
|
||||
| { kind: "tempo"; bpm: number }
|
||||
| { kind: "crop"; start: number; end: number }
|
||||
| { kind: "remap-channel"; from: number; to: number }
|
||||
| { kind: "drop-channel"; channel: number }
|
||||
| {
|
||||
kind: "edit-note";
|
||||
onOrder: number;
|
||||
note: number;
|
||||
velocity: number;
|
||||
startTick: number;
|
||||
endTick: number;
|
||||
}
|
||||
| { kind: "delete-note"; onOrder: number };
|
||||
|
||||
export type MidiTask =
|
||||
| { kind: "parse"; name: string; bytes: ArrayBuffer }
|
||||
| { kind: "operation"; document: MidiDocument; operation: MidiOperation }
|
||||
| {
|
||||
kind: "export";
|
||||
document: MidiDocument;
|
||||
format: "midi" | "csv" | "json";
|
||||
};
|
||||
|
||||
export type MidiTaskResult =
|
||||
| { kind: "document"; document: MidiDocument }
|
||||
| { kind: "bytes"; bytes: ArrayBuffer; mimeType: string }
|
||||
| { kind: "text"; text: string; mimeType: string };
|
||||
|
||||
/** Pure task entry point shared by the module worker and test fallback. */
|
||||
export function executeMidiTask(task: MidiTask): MidiTaskResult {
|
||||
if (task.kind === "parse")
|
||||
return {
|
||||
kind: "document",
|
||||
document: parseMidi(task.name, new Uint8Array(task.bytes)),
|
||||
};
|
||||
if (task.kind === "operation") {
|
||||
const { document, operation } = task;
|
||||
const next =
|
||||
operation.kind === "transpose"
|
||||
? transposeMidi(document, operation.semitones)
|
||||
: operation.kind === "quantize"
|
||||
? quantizeMidi(document, operation.grid)
|
||||
: operation.kind === "tempo"
|
||||
? constantTempoMidi(document, operation.bpm)
|
||||
: operation.kind === "crop"
|
||||
? cropMidi(document, operation.start, operation.end)
|
||||
: operation.kind === "remap-channel"
|
||||
? remapChannel(document, operation.from, operation.to)
|
||||
: operation.kind === "drop-channel"
|
||||
? dropChannel(document, operation.channel)
|
||||
: operation.kind === "edit-note"
|
||||
? editNote(document, operation.onOrder, operation)
|
||||
: deleteNote(document, operation.onOrder);
|
||||
return { kind: "document", document: next };
|
||||
}
|
||||
if (task.format === "midi") {
|
||||
const bytes = encodeMidi(task.document);
|
||||
return {
|
||||
kind: "bytes",
|
||||
bytes: Uint8Array.from(bytes).buffer,
|
||||
mimeType: "audio/midi",
|
||||
};
|
||||
}
|
||||
return {
|
||||
kind: "text",
|
||||
text:
|
||||
task.format === "csv"
|
||||
? exportMidiCsv(task.document)
|
||||
: exportMidiJson(task.document),
|
||||
mimeType: task.format === "csv" ? "text/csv" : "application/json",
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user