From 35b758e9a7254c1916415a6868b6daae0fe9aa6e Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Wed, 1 Nov 2023 00:48:43 +0100 Subject: [PATCH] beginning refactoring of soundevent --- src/classes/SoundEvent.ts | 642 +++++++++++++++----------------------- 1 file changed, 251 insertions(+), 391 deletions(-) diff --git a/src/classes/SoundEvent.ts b/src/classes/SoundEvent.ts index 80ac9f8..ecb67ad 100644 --- a/src/classes/SoundEvent.ts +++ b/src/classes/SoundEvent.ts @@ -20,9 +20,258 @@ export type SoundParams = { export class SoundEvent extends AudibleEvent { nudge: number; + private methodMap = { + volume: ["volume", "vol"], + zrand: ["zrand", "zr"], + curve: ["curve"], + slide: ["slide", "sld"], + deltaSlide: ["deltaSlide", "dslide"], + pitchJump: ["pitchJump", "pj"], + pitchJumpTime: ["pitchJumpTime", "pjt"], + lfo: ["lfo"], + znoise: ["znoise"], + noise: ["noise"], + zmod: ["zmod"], + zcrush: ["zcrush"], + zdelay: ["zdelay"], + sustainVolume: ["sustainVolume"], + tremolo: ["tremolo"], + dur: ["dur"], + zzfx: ["zzfx"], + fmi: ["fmi"], + fmh: ["fmh"], + fmenv: ["fmenv"], + fmattack: ["fmattack", "fmatk"], + fmdecay: ["fmdecay", "fmdec"], + fmsustain: ["fmsustain", "fmsus"], + fmrelease: ["fmrelease", "fmrel"], + fmvelocity: ["fmvelocity", "fmvel"], + fmwave: ["fmwave", "fmw"], + fmadsr: (a: number, d: number, s: number, r: number) => { + this.updateValue("fmattack", a); + this.updateValue("fmdecay", d); + this.updateValue("fmsustain", s); + this.updateValue("fmrelease", r); + return this; + }, + fmad: (a: number, d: number) => { + this.updateValue("fmattack", a); + this.updateValue("fmdecay", d); + }, + ftype: ["ftype"], + fanchor: ["fanchor"], + attack: ["attack", "atk"], + decay: ["decay", "dec"], + sustain: ["sustain", "sus"], + release: ["release", "rel"], + adsr: (a: number, d: number, s: number, r: number) => { + this.updateValue("attack", a); + this.updateValue("decay", d); + this.updateValue("sustain", s); + this.updateValue("release", r); + return this; + }, + ad: (a: number, d: number) => { + this.updateValue("attack", a); + this.updateValue("decay", d); + this.updateValue("sustain", 0.0); + this.updateValue("release", 0.0); + return this; + }, + lpenv: ["lpenv", "lpe"], + lpattack: ["lpattack", "lpa"], + lpdecay: ["lpdecay", "lpd"], + lpsustain: ["lpsustain", "lps"], + lprelease: ["lprelease", "lpr"], + cutoff: (value: number, resonance?: number) => { + this.updateValue("cutoff", value); + if (resonance) { + this.resonance(resonance); + } + return this; + }, + lpf: (value: number, resonance?: number) => { + this.updateValue("cutoff", value); + if (resonance) { + this.resonance(resonance); + } + return this; + }, + resonance: (value: number) => { + if (value >= 0 && value <= 1) { + this.updateValue("resonance", 50 * value); + } + return this; + }, + lpadsr: (depth: number, a: number, d: number, s: number, r: number) => { + this.updateValue("lpenv", depth); + this.updateValue("lpattack", a); + this.updateValue("lpdecay", d); + this.updateValue("lpsustain", s); + this.updateValue("lprelease", r); + return this; + }, + lpad: (depth: number, a: number, d: number) => { + this.updateValue("lpenv", depth); + this.updateValue("lpattack", a); + this.updateValue("lpdecay", d); + this.updateValue("lpsustain", 0); + this.updateValue("lprelease", 0); + return this; + }, + hpenv: ["hpenv", "hpe"], + hpattack: ["hpattack", "hpa"], + hpdecay: ["hpdecay", "hpd"], + hpsustain: ["hpsustain", "hpsus"], + hprelease: ["hprelease", "hpr"], + hcutoff: (value: number, resonance?: number) => { + this.updateValue("hcutoff", value); + if (resonance) { + this.updateValue("hresonance", resonance); + } + return this; + }, + hpq: (value: number) => { + this.updateValue("hresonance", value); + return this; + }, + hpadsr: (depth: number, a: number, d: number, s: number, r: number) => { + this.updateValue("hpenv", depth); + this.updateValue("hpattack", a); + this.updateValue("hpdecay", d); + this.updateValue("hpsustain", s); + this.updateValue("hprelease", r); + return this; + }, + hpad: (depth: number, a: number, d: number) => { + this.updateValue("hpenv", depth); + this.updateValue("hpattack", a); + this.updateValue("hpdecay", d); + this.updateValue("hpsustain", 0); + this.updateValue("hprelease", 0); + return this; + }, + bpenv: ["bpenv", "bpe"], + bpattack: ["bpattack", "bpa"], + bpdecay: ["bpdecay", "bpd"], + bpsustain: ["bpsustain", "bps"], + bprelease: ["bprelease", "bpr"], + bandf: (value: number, resonance?: number) => { + this.updateValue("bandf", value); + if (resonance) { + this.updateValue("bandq", resonance); + } + return this; + }, + bpf: (value: number, resonance?: number) => { + this.updateValue("bandf", value); + if (resonance) { + this.updateValue("bandq", resonance); + } + return this; + }, + bandq: ["bandq", "bpq"], + bpadsr: (depth: number, a: number, d: number, s: number, r: number) => { + this.updateValue("bpenv", depth); + this.updateValue("bpattack", a); + this.updateValue("bpdecay", d); + this.updateValue("bpsustain", s); + this.updateValue("bprelease", r); + return this; + }, + bpad: (depth: number, a: number, d: number) => { + this.updateValue("bpenv", depth); + this.updateValue("bpattack", a); + this.updateValue("bpdecay", d); + this.updateValue("bpsustain", 0); + this.updateValue("bprelease", 0); + return this; + }, + vib: ["vib"], + vibmod: ["vibmod"], + fm: (value: number | string) => { + if (typeof value === "number") { + this.values["fmi"] = value; + } else { + let values = value.split(":"); + this.values["fmi"] = parseFloat(values[0]); + if (values.length > 1) this.values["fmh"] = parseFloat(values[1]); + } + return this; + }, + loop: ["loop"], + loopBegin: ["loopBegin", "loopb"], + loopEnd: ["loopEnd", "loope"], + begin: ["begin"], + end: ["end"], + gain: ["gain"], + dbgain: (value: number) => { + this.updateValue("gain", Math.min(Math.pow(10, value / 20), 10)); + }, + db: (value: number) => { + this.updateValue("gain", Math.min(Math.pow(10, value / 20), 10)); + }, + velocity: ["velocity", "vel"], + pan: ["pan"], + cut: ["cut"], + clip: ["clip"], + n: ["n"], + speed: ["speed", "spd"], + coarse: ["coarse"], + crush: ["crush"], + shape: ["shape"], + vowel: ["vowel", "vow"], + delay: ["delay", "del"], + delayfeedback: ["delayfeedback", "delayfb"], + delaytime: ["delaytime", "delayt"], + orbit: ["orbit", "o"], + room: ["room", "rm"], + roomfade: ["roomfade", "rfade"], + roomlp: ["roomlp", "rlp"], + roomdim: ["roomdim", "rdim"], + size: (value: number) => { + this.updateValue("roomsize", value); + }, + sz: (value: number) => { + this.updateValue("roomsize", value); + }, + comp: ["compressor", "cmp"], + ratio: (value: number) => { + this.updateValue("compressorRatio", value); + }, + knee: (value: number) => { + this.updateValue("compressorKnee", value); + }, + compAttack: (value: number) => { + this.updateValue("compressorAttack", value); + }, + compRelease: (value: number) => { + this.updateValue("compressorRelease", value); + }, + stretch: (beat: number) => { + this.updateValue("unit", "c"); + this.updateValue("speed", 1 / beat); + this.updateValue("cut", beat); + return this; + }, + }; + constructor(sound: string | object, public app: Editor) { super(app); this.nudge = app.dough_nudge / 100; + + for (const [methodName, keys] of Object.entries(this.methodMap)) { + if (Symbol.iterator in Object(keys)) { + for (const key of keys as string[]) { + // @ts-ignore + this[key] = (value: number) => this.updateValue(keys[0], value); + } + } else { + // @ts-ignore + this[methodName] = keys; + } + } + if (typeof sound === "string") { if (sound.includes(":")) { this.values = { @@ -39,401 +288,12 @@ export class SoundEvent extends AudibleEvent { } } - private updateValue(key: string, value: T): this { + private updateValue(key: string, value: T | T[] | null): this { + if (value == null) return this; this.values[key] = value; return this; } - // ================================================================================ - // ZZFX Sound Parameters - // ================================================================================ - - public volume = (value: number) => this.updateValue("volume", value); - public vol = this.volume; - public zrand = (value: number) => this.updateValue("zrand", value); - public curve = (value: number) => this.updateValue("curve", value); - public slide = (value: number) => this.updateValue("slide", value); - public sld = this.slide; - public deltaSlide = (value: number) => this.updateValue("deltaSlide", value); - public dslide = this.deltaSlide; - public pitchJump = (value: number) => this.updateValue("pitchJump", value); - public pj = this.pitchJump; - public pitchJumpTime = (value: number) => - this.updateValue("pitchJumpTime", value); - public pjt = this.pitchJumpTime; - public lfo = (value: number) => this.updateValue("lfo", value); - public znoise = (value: number) => this.updateValue("znoise", value); - public noise = (value: number) => this.updateValue("noise", value); - public zmod = (value: number) => this.updateValue("zmod", value); - public zcrush = (value: number) => this.updateValue("zcrush", value); - public zdelay = (value: number) => this.updateValue("zdelay", value); - public sustainVolume = (value: number) => - this.updateValue("sustainVolume", value); - public tremolo = (value: number) => this.updateValue("tremolo", value); - public dur = (value: number) => this.updateValue("dur", value); - public zzfx = (value: number[]) => this.updateValue("zzfx", value); - - // ================================================================================ - // Basic Audio Engine Parameters - // ================================================================================ - - // FM Synthesis - public fmi = (value: number) => this.updateValue("fmi", value); - public fmh = (value: number) => this.updateValue("fmh", value); - public fmenv = (value: "lin" | "exp") => this.updateValue("fmenv", value); - public fmattack = (value: number) => this.updateValue("fmattack", value); - public fmatk = this.fmattack; - public fmdecay = (value: number) => this.updateValue("fmdecay", value); - public fmdec = this.fmdecay; - public fmsustain = (value: number) => this.updateValue("fmsustain", value); - public fmsus = this.fmsustain; - public fmrelease = (value: number) => this.updateValue("fmrelease", value); - public fmrel = this.fmrelease; - public fmvelocity = (value: number) => this.updateValue("fmvelocity", value); - public fmvel = this.fmvelocity; - public fmwave = (value: "sine" | "triangle" | "sawtooth" | "square") => - this.updateValue("fmwave", value); - public fmw = this.fmwave; - - // Filter type - public ftype = (value: "12db" | "24db") => this.updateValue("ftype", value); - public fanchor = (value: number) => this.updateValue("fanchor", value); - - // Amplitude Envelope - public attack = (value: number) => this.updateValue("attack", value); - public atk = this.attack; - public decay = (value: number) => this.updateValue("decay", value); - public dec = this.decay; - public sustain = (value: number) => this.updateValue("sustain", value); - public sus = this.sustain; - public release = (value: number) => this.updateValue("release", value); - public rel = this.release; - public adsr = (a: number, d: number, s: number, r: number) => { - this.attack(a); - this.decay(d); - this.sustain(s); - this.release(r); - return this; - }; - public ad = (a: number, d: number) => { - this.attack(a); - this.decay(d); - this.sustain(0.0); - this.release(0.0); - return this; - }; - - // Lowpass filter - public lpenv = (value: number) => this.updateValue("lpenv", value); - public lpe = (value: number) => this.updateValue("lpenv", value); - public lpattack = (value: number) => this.updateValue("lpattack", value); - public lpa = this.lpattack; - public lpdecay = (value: number) => this.updateValue("lpdecay", value); - public lpd = this.lpdecay; - public lpsustain = (value: number) => this.updateValue("lpsustain", value); - public lps = this.lpsustain; - public lprelease = (value: number) => this.updateValue("lprelease", value); - public lpr = this.lprelease; - public cutoff = (value: number, resonance?: number) => { - this.updateValue("cutoff", value); - if (resonance) { - this.resonance(resonance) - } - return this; - } - public lpf = this.cutoff; - public resonance = (value: number) => { - if (value >= 0 && value <= 1) { - this.updateValue( - "resonance", - 50 * value - ); - } - return this; - } - public lpq = this.resonance; - public lpadsr = ( - depth: number, - a: number, - d: number, - s: number, - r: number - ) => { - this.lpenv(depth); - this.lpattack(a); - this.lpdecay(d); - this.lpsustain(s); - this.lprelease(r); - return this; - }; - public lpad = ( - depth: number, - a: number, - d: number, - ) => { - this.lpenv(depth); - this.lpattack(a); - this.lpdecay(d); - this.lpsustain(0); - this.lprelease(0); - return this; - }; - - - // Highpass filter - - public hpenv = (value: number) => this.updateValue("hpenv", value); - public hpe = (value: number) => this.updateValue("hpe", value); - public hpattack = (value: number) => this.updateValue("hpattack", value); - public hpa = this.hpattack; - public hpdecay = (value: number) => this.updateValue("hpdecay", value); - public hpd = this.hpdecay; - public hpsustain = (value: number) => this.updateValue("hpsustain", value); - public hpsus = this.hpsustain; - public hprelease = (value: number) => this.updateValue("hprelease", value); - public hpr = this.hprelease; - public hcutoff = (value: number) => this.updateValue("hcutoff", value); - public hpf = this.hcutoff; - public hresonance = (value: number, resonance?: number) => { - this.updateValue("hresonance", value); - if (resonance) { - this.resonance(resonance) - } - return this; - } - public hpq = this.hresonance; - public hpadsr = ( - depth: number, - a: number, - d: number, - s: number, - r: number - ) => { - this.hpenv(depth); - this.hpattack(a); - this.hpdecay(d); - this.hpsustain(s); - this.hprelease(r); - return this; - }; - public hpad = ( - depth: number, - a: number, - d: number, - ) => { - this.hpenv(depth); - this.hpattack(a); - this.hpdecay(d); - this.hpsustain(0); - this.hprelease(0); - return this; - }; - - // Bandpass filter - - public bpenv = (value: number) => this.updateValue("bpenv", value); - public bpe = (value: number) => this.updateValue("bpe", value); - public bpattack = (value: number) => this.updateValue("bpattack", value); - public bpa = this.bpattack; - public bpdecay = (value: number) => this.updateValue("bpdecay", value); - public bpd = this.bpdecay; - public bpsustain = (value: number) => this.updateValue("bpsustain", value); - public bps = this.bpsustain; - public bprelease = (value: number) => this.updateValue("bprelease", value); - public bpr = this.bprelease; - public bandf = (value: number, resonance?: number) => { - this.updateValue("bandf", value); - if (resonance) { - this.resonance(resonance) - } - return this; - } - public bpf = this.bandf; - public bandq = (value: number) => this.updateValue("bandq", value); - public bpq = this.bandq; - public bpadsr = ( - depth: number, - a: number, - d: number, - s: number, - r: number - ) => { - this.bpenv(depth); - this.bpattack(a); - this.bpdecay(d); - this.bpsustain(s); - this.bprelease(r); - return this; - }; - public bpad = ( - depth: number, - a: number, - d: number, - ) => { - this.bpenv(depth); - this.bpattack(a); - this.bpdecay(d); - this.bpsustain(0); - this.bprelease(0); - return this; - }; - - - public freq = (value: number) => this.updateValue("freq", value); - public f = this.freq; - public vib = (value: number) => this.updateValue("vib", value); - public vibmod = (value: number) => this.updateValue("vibmod", value); - public fm = (value: number | string) => { - if (typeof value === "number") { - this.values["fmi"] = value; - } else { - let values = value.split(":"); - this.values["fmi"] = parseFloat(values[0]); - if (values.length > 1) this.values["fmh"] = parseFloat(values[1]); - } - return this; - }; - - // Sampler looping - public loop = (value: number) => this.updateValue("loop", value); - public loopBegin = (value: number) => this.updateValue("loopBegin", value); - public loopEnd = (value: number) => this.updateValue("loopEnd", value); - public begin = (value: number) => this.updateValue("begin", value); - public end = (value: number) => this.updateValue("end", value); - - // Gain management - public gain = (value: number) => this.updateValue("gain", value); - public dbgain = (value: number) => - this.updateValue("gain", Math.min(Math.pow(10, value / 20), 10)); - public db = this.dbgain; - public velocity = (value: number) => this.updateValue("velocity", value); - public vel = this.velocity; - - // Panoramic control (stereo) - public pan = (value: number) => this.updateValue("pan", value); - - // Frequency management - - public sound = (value: string) => this.updateValue("s", value); - public chord = ( - value: string | object[] | number[] | number, - ...kwargs: number[] - ) => { - if (typeof value === "string") { - const chord = parseChord(value); - value = chord.map((note: number) => { - return { note: note, freq: midiToFreq(note) }; - }); - } else if (value instanceof Array && typeof value[0] === "number") { - value = (value as number[]).map((note: number) => { - return { note: note, freq: midiToFreq(note) }; - }); - } else if (typeof value === "number" && kwargs.length > 0) { - value = [value, ...kwargs].map((note: number) => { - return { note: note, freq: midiToFreq(note) }; - }); - } - return this.updateValue("chord", value); - }; - 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 snd = this.sound; - public cut = (value: number) => this.updateValue("cut", value); - public clip = (value: number) => this.updateValue("clip", value); - public n = (value: number) => this.updateValue("n", value); - 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); - } - }; - public speed = (value: number) => this.updateValue("speed", value); - public spd = this.speed; - - // Creative sampler effects - public coarse = (value: number) => this.updateValue("coarse", value); - public crush = (value: number) => this.updateValue("crush", value); - public shape = (value: number) => this.updateValue("shape", value); - public vowel = (value: number) => this.updateValue("vowel", value); - public vow = this.vowel; - - // Delay control - public delay = (value: number) => this.updateValue("delay", value); - public del = this.delay; - public delayfeedback = (value: number) => - this.updateValue("delayfeedback", value); - public delayfb = this.delayfeedback; - public delaytime = (value: number) => this.updateValue("delaytime", value); - public delayt = this.delaytime; - - // Orbit management - public orbit = (value: number) => this.updateValue("orbit", value); - public o = this.orbit; - - // Reverb management - public room = (value: number) => this.updateValue("room", value); - public rm = this.room; - public roomfade = (value: number) => this.updateValue("roomfade", value); - public rfade = this.roomfade; - public roomlp = (value: number) => this.updateValue("roomlp", value); - public rlp = this.roomlp; - public roomdim = (value: number) => this.updateValue("roomdim", value); - public rdim = this.roomdim; - public size = (value: number) => this.updateValue("roomsize", value); - public sz = this.size; - public rev = (room: number, size: number, fade?: number, lp?: number, dim?: number) => { - this.updateValue("room", room) - this.updateValue("roomsize", size) - if (fade) - this.updateValue("roomfade", fade) - if (lp) - this.updateValue("roomlp", lp) - if (dim) - this.updateValue("roomdim", dim) - - return this; - } - - // Compressor - public comp = (value: number) => this.updateValue("compressor", value); - public cmp = this.comp; - public ratio = (value: number) => this.updateValue("compressorRatio", value); - public rt = this.ratio; - public knee = (value: number) => this.updateValue("compressorKnee", value); - public kn = this.knee; - public compAttack = (value: number) => - this.updateValue("compressorAttack", value); - public cmpa = this.compAttack; - public compRelease = (value: number) => - this.updateValue("compressorRelease", value); - public cmpr = this.compRelease; - - // Unit - public stretch = (beat: number) => { - this.updateValue("unit", "c"); - this.updateValue("speed", 1 / beat); - this.updateValue("cut", beat); - return this; - }; - // ================================================================================ // AbstactEvent overrides // ================================================================================