Refactor object mangling and add midi support
This commit is contained in:
@ -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);
|
||||
});
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user