Refactor object mangling and add midi support

This commit is contained in:
2023-11-03 16:07:39 +02:00
parent 269df3f899
commit a09e3a76be
7 changed files with 242 additions and 161 deletions

View File

@ -1,7 +1,8 @@
import { AudibleEvent } from "./AbstractEvents";
import { type Editor } from "../main";
import { MidiConnection } from "../IO/MidiConnection";
import { midiToFreq, noteFromPc } from "zifferjs";
import { noteFromPc, chord as parseChord } from "zifferjs";
import { filterObject, arrayOfObjectsToObjectWithArrays, objectWithArraysToArrayOfObjects } from "../Utils/Generic";
export type MidiParams = {
note: number;
@ -9,40 +10,49 @@ export type MidiParams = {
channel?: number;
port?: number;
sustain?: number;
velocity?: number;
}
export class MidiEvent extends AudibleEvent {
midiConnection: MidiConnection;
constructor(input: number | object, public app: Editor) {
constructor(input: MidiParams, public app: Editor) {
super(app);
if (typeof input === "number") this.values["note"] = input;
else this.values = input;
this.values = input;
this.midiConnection = app.api.MidiConnection;
}
chord = (value: MidiParams[]): this => {
this.values["chord"] = value;
return this;
public chord = (value: string) => {
this.values.note = parseChord(value);
return this;
};
note = (value: number): this => {
note = (value: number | number[]): this => {
this.values["note"] = value;
return this;
};
sustain = (value: number): this => {
sustain = (value: number | number[]): this => {
this.values["sustain"] = value;
return this;
};
channel = (value: number): this => {
velocity = (value: number | number[]): this => {
this.values["velocity"] = value;
return this;
}
channel = (value: number | number[]): this => {
this.values["channel"] = value;
return this;
};
port = (value: number | string): this => {
this.values["port"] = this.midiConnection.getMidiOutputIndex(value);
port = (value: number | string | number[] | string[]): this => {
if(typeof value === "string"){
this.values["port"] = this.midiConnection.getMidiOutputIndex(value);
} else if(Array.isArray(value)){
this.values["port"] = value.map((v) => typeof v === "string" ? this.midiConnection.getMidiOutputIndex(v) : v);
}
return this;
};
@ -75,37 +85,46 @@ export class MidiEvent extends AudibleEvent {
};
update = (): void => {
const [note, bend] = noteFromPc(
this.values.key || "C4",
this.values.pitch || 0,
this.values.parsedScale || "MAJOR",
this.values.octave || 0
);
this.values.note = note;
this.values.freq = midiToFreq(note);
if (bend) this.values.bend = bend;
// Get key, pitch, parsedScale and octave from this.values object
const filteredValues = filterObject(this.values, ["key", "pitch", "parsedScale", "octave"]);
const events = objectWithArraysToArrayOfObjects(filteredValues,["parsedScale"]);
events.forEach((event) => {
const [note, bend] = noteFromPc(
event.key as number || "C4",
event.pitch as number || 0,
event.parsedScale as number[] || event.scale || "MAJOR",
event.octave as number || 0
);
event.note = note;
if(bend) event.bend = bend;
});
const newArrays = arrayOfObjectsToObjectWithArrays(events) as MidiParams;
this.values.note = newArrays.note;
if(newArrays.bend) this.values.bend = newArrays.bend;
};
out = (): void => {
function play(event: MidiEvent, params?: MidiParams): void {
const paramChannel = params && params.channel ? params.channel : 0;
const channel = event.values.channel ? event.values.channel : paramChannel;
const velocity = event.values.velocity ? event.values.velocity : 100;
const paramNote = params && params.note ? params.note : 60;
const note = event.values.note ? event.values.note : paramNote;
function play(event: MidiEvent, params: MidiParams): void {
const channel = params.channel ? params.channel : 0;
const velocity = params.velocity ? params.velocity : 100;
const note = params.note ? params.note : 60;
const sustain = event.values.sustain
? event.values.sustain *
const sustain = params.sustain
? params.sustain *
event.app.clock.pulse_duration *
event.app.api.ppqn()
: event.app.clock.pulse_duration * event.app.api.ppqn();
const bend = event.values.bend ? event.values.bend : undefined;
const port = event.values.port
? event.midiConnection.getMidiOutputIndex(event.values.port)
: event.midiConnection.getCurrentMidiPortIndex();
const bend = params.bend ? params.bend : undefined;
const port = params.port
? event.midiConnection.getMidiOutputIndex(params.port)
: event.midiConnection.getCurrentMidiPortIndex() || 0;
event.midiConnection.sendMidiNote(
note,
channel,
@ -116,13 +135,11 @@ export class MidiEvent extends AudibleEvent {
);
}
if(this.values.chord) {
this.values.chord.forEach((p: MidiParams) => {
play(this, p);
});
} else {
play(this);
}
const events = objectWithArraysToArrayOfObjects(this.values,["parsedScale"]) as MidiParams[];
events.forEach((p: MidiParams) => {
play(this,p);
});
};
}