From 278dce0196f74244192e9bf31585c584386b0876 Mon Sep 17 00:00:00 2001 From: Miika Alonen Date: Tue, 28 Nov 2023 07:50:03 +0200 Subject: [PATCH] Fix chord & note issues --- src/classes/AbstractEvents.ts | 46 +++++++++++++++++++++++++++++- src/classes/MidiEvent.ts | 12 +------- src/classes/SoundEvent.ts | 43 ---------------------------- src/extensions/NumberExtensions.ts | 7 +++-- 4 files changed, 50 insertions(+), 58 deletions(-) diff --git a/src/classes/AbstractEvents.ts b/src/classes/AbstractEvents.ts index 1be343d..72aa7e6 100644 --- a/src/classes/AbstractEvents.ts +++ b/src/classes/AbstractEvents.ts @@ -1,5 +1,6 @@ import { type Editor } from "../main"; -import { freqToMidi, resolvePitchBend, safeScale } from "zifferjs"; +import { freqToMidi, chord as parseChord, noteNameToMidi, resolvePitchBend, safeScale } from "zifferjs"; +import { SkipEvent } from "./SkipEvent"; export type EventOperation = (instance: T, ...args: any[]) => void; @@ -310,6 +311,49 @@ export abstract class AudibleEvent extends AbstractEvent { return this; }; + protected updateValue( + key: string, + value: T | T[] | null + ): this { + if (value == null) return this; + this.values[key] = value; + return this; + } + + public note = (value: number | string | null, ...kwargs: number[]|string[]) => { + if (typeof value === "string") { + const parsedNote = noteNameToMidi(value); + return this.updateValue("note", [parsedNote, ...kwargs].flat(Infinity)); + } else if (typeof value == null || value == undefined) { + return new SkipEvent(); + } else { + return this.updateValue("note", [value, ...kwargs].flat(Infinity)); + } + }; + + public chord = (value: number|string, ...kwargs: number[]) => { + if(typeof value === "string") { + const chord = parseChord(value); + return this.updateValue("note", chord); + } else { + const chord = [value, ...kwargs].flat(Infinity); + return this.updateValue("note", chord); + } + }; + + public invert = (howMany: number = 0) => { + if (this.values.note) { + let notes = [...this.values.note]; + notes = howMany < 0 ? [...notes].reverse() : notes; + for (let i = 0; i < Math.abs(howMany); i++) { + notes[i % notes.length] += howMany <= 0 ? -12 : 12; + } + return this.updateValue("note", notes); + } else { + return this; + } + }; + freq = (value: number | number[], ...kwargs: number[]): this => { /* * This function is used to set the frequency of the Event. diff --git a/src/classes/MidiEvent.ts b/src/classes/MidiEvent.ts index e0076f6..df8fa37 100644 --- a/src/classes/MidiEvent.ts +++ b/src/classes/MidiEvent.ts @@ -1,7 +1,7 @@ import { AudibleEvent } from "./AbstractEvents"; import { type Editor } from "../main"; import { MidiConnection } from "../IO/MidiConnection"; -import { noteFromPc, chord as parseChord } from "zifferjs"; +import { noteFromPc } from "zifferjs"; import { filterObject, arrayOfObjectsToObjectWithArrays, @@ -29,16 +29,6 @@ export class MidiEvent extends AudibleEvent { this.midiConnection = app.api.MidiConnection; } - public chord = (value: string) => { - this.values.note = parseChord(value); - return this; - }; - - note = (value: number | number[]): this => { - this.values["note"] = value; - return this; - }; - sustain = (value: number | number[]): this => { this.values["sustain"] = value; return this; diff --git a/src/classes/SoundEvent.ts b/src/classes/SoundEvent.ts index 7aef672..3051f25 100644 --- a/src/classes/SoundEvent.ts +++ b/src/classes/SoundEvent.ts @@ -6,10 +6,8 @@ import { objectWithArraysToArrayOfObjects, } from "../Utils/Generic"; import { - chord as parseChord, midiToFreq, noteFromPc, - noteNameToMidi, } from "zifferjs"; import { @@ -36,15 +34,6 @@ export class SoundEvent extends AudibleEvent { nudge: number; sound: any; - public updateValue( - key: string, - value: T | T[] | SoundParams[] | null, - ): this { - if (value == null) return this; - this.values[key] = value; - return this; - } - private static methodMap = { volume: ["volume", "vol"], zrand: ["zrand", "zr"], @@ -453,38 +442,6 @@ export class SoundEvent extends AudibleEvent { this.values.freq = newArrays.freq; }; - public chord = (value: string) => { - const chord = parseChord(value); - return this.updateValue("note", chord); - }; - - public invert = (howMany: number = 0) => { - if (this.values.chord) { - let notes = this.values.chord.map( - (obj: { [key: string]: number }) => obj.note, - ); - notes = howMany < 0 ? [...notes].reverse() : notes; - for (let i = 0; i < Math.abs(howMany); i++) { - notes[i % notes.length] += howMany <= 0 ? -12 : 12; - } - const chord = notes.map((note: number) => { - return { note: note, freq: midiToFreq(note) }; - }); - return this.updateValue("chord", chord); - } else { - return this; - } - }; - public note = (value: number | string | null) => { - if (typeof value === "string") { - return this.updateValue("note", noteNameToMidi(value)); - } else if (typeof value == null || value == undefined) { - return this.updateValue("note", 0).updateValue("gain", 0); - } else { - return this.updateValue("note", value); - } - }; - out = (orbit?: number | number[]): void => { if (orbit) this.values["orbit"] = orbit; const events = objectWithArraysToArrayOfObjects(this.values, [ diff --git a/src/extensions/NumberExtensions.ts b/src/extensions/NumberExtensions.ts index 76fdc9e..84a781b 100644 --- a/src/extensions/NumberExtensions.ts +++ b/src/extensions/NumberExtensions.ts @@ -2,6 +2,7 @@ import { type UserAPI } from "../API"; import { MidiEvent } from "../classes/MidiEvent"; import { Player } from "../classes/ZPlayer"; import { SoundEvent } from "../classes/SoundEvent"; +import { SkipEvent } from "../classes/SkipEvent"; declare global { interface Number { @@ -24,7 +25,7 @@ declare global { z15(): Player; z16(): Player; midi(): MidiEvent; - sound(name: string): SoundEvent; + sound(name: string): SoundEvent|SkipEvent; } } @@ -101,11 +102,11 @@ export const makeNumberExtensions = (api: UserAPI) => { return api.midi(this.valueOf(), ...kwargs); }; - Number.prototype.sound = function (name: string) { + Number.prototype.sound = function (name: string): SoundEvent|SkipEvent { if (Number.isInteger(this.valueOf())) { return (api.sound(name) as SoundEvent).note(this.valueOf()); } else { return (api.sound(name) as SoundEvent).freq(this.valueOf()); - } + } }; };