135 lines
4.0 KiB
TypeScript
135 lines
4.0 KiB
TypeScript
import { Event } from './Event';
|
|
import { type Editor } from './main';
|
|
import { MidiConnection } from "./IO/MidiConnection";
|
|
import { freqToMidi, midiToFreq, resolvePitchBend, noteFromPc, getScale, isScale, parseScala } from 'zifferjs';
|
|
|
|
export class Note extends Event {
|
|
midiConnection: MidiConnection;
|
|
|
|
constructor(input: number|object, public app: Editor) {
|
|
super(app);
|
|
if(typeof input === 'number') this.values['note'] = input;
|
|
else this.values = input;
|
|
this.midiConnection = app.api.MidiConnection
|
|
}
|
|
|
|
note = (value: number): this => {
|
|
this.values['note'] = value;
|
|
return this;
|
|
}
|
|
|
|
duration = (value: number): this => {
|
|
this.values['duration'] = value;
|
|
return this;
|
|
}
|
|
|
|
sustain = (value: number): this => {
|
|
this.values['sustain'] = value;
|
|
return this;
|
|
}
|
|
|
|
channel = (value: number): this => {
|
|
this.values['channel'] = value;
|
|
return this;
|
|
}
|
|
|
|
port = (value: number|string): this => {
|
|
this.values['port'] = this.midiConnection.getMidiOutputIndex(value);
|
|
return this;
|
|
}
|
|
|
|
add = (value: number): this => {
|
|
this.values.note += value;
|
|
return this;
|
|
}
|
|
|
|
modify = (func: Function): this => {
|
|
const funcResult = func(this);
|
|
if(funcResult instanceof Object) {
|
|
return funcResult;
|
|
|
|
}
|
|
else {
|
|
func(this.values);
|
|
return this;
|
|
}
|
|
}
|
|
|
|
freq = (value: number): this => {
|
|
this.values['freq'] = value;
|
|
const midiNote = freqToMidi(value);
|
|
if(midiNote % 1 !== 0) {
|
|
this.values['note'] = Math.floor(midiNote);
|
|
this.values['bend'] = resolvePitchBend(midiNote)[1];
|
|
} else {
|
|
this.values['note'] = midiNote;
|
|
}
|
|
return this;
|
|
}
|
|
|
|
bend = (value: number): this => {
|
|
this.values['bend'] = value;
|
|
return this;
|
|
}
|
|
|
|
random = (min: number = 0, max: number = 127): this => {
|
|
min = Math.min(Math.max(min, 0), 127);
|
|
max = Math.min(Math.max(max, 0), 127);
|
|
this.values['note'] = Math.floor(this.randomGen() * (max - min + 1)) + min;
|
|
return this;
|
|
}
|
|
|
|
update = (): void => {
|
|
// TODO: Figure out why _ is sometimes added?
|
|
if(this.values.type === 'Pitch' || this.values.type === '_Pitch') {
|
|
const [note,bend] = noteFromPc(this.values.key!, this.values.pitch!, this.values.parsedScale!, this.values.octave!);
|
|
this.values.note = note;
|
|
this.values.freq = midiToFreq(note);
|
|
if(bend) {
|
|
this.values.bend = bend;
|
|
}
|
|
}
|
|
}
|
|
|
|
octave = (value: number): this => {
|
|
this.values['octave'] = value;
|
|
this.update();
|
|
return this;
|
|
}
|
|
|
|
key = (value: string): this => {
|
|
this.values['key'] = value;
|
|
this.update();
|
|
return this;
|
|
}
|
|
|
|
scale = (value: string): this => {
|
|
if(!isScale(value)) {
|
|
this.values.parsedScale = parseScala(value) as number[];
|
|
} else {
|
|
this.values.scaleName = value;
|
|
this.values.parsedScale = getScale(value) as number[];
|
|
}
|
|
this.update();
|
|
return this;
|
|
}
|
|
|
|
out = (): void => {
|
|
const note = this.values.note ? this.values.note : 60;
|
|
const channel = this.values.channel ? this.values.channel : 0;
|
|
const velocity = this.values.velocity ? this.values.velocity : 100;
|
|
|
|
const sustain = this.values.sustain ?
|
|
this.values.sustain * this.app.clock.pulse_duration * this.app.api.ppqn() :
|
|
this.app.clock.pulse_duration * this.app.api.ppqn();
|
|
|
|
const bend = this.values.bend ? this.values.bend : undefined;
|
|
|
|
const port = this.values.port ?
|
|
this.midiConnection.getMidiOutputIndex(this.values.port) :
|
|
this.midiConnection.getCurrentMidiPortIndex();
|
|
|
|
this.midiConnection.sendMidiNote(note, channel, velocity, sustain, port, bend);
|
|
}
|
|
|
|
} |