Skip to content

Commit

Permalink
Rewrite frontend library with explicit props args
Browse files Browse the repository at this point in the history
  • Loading branch information
nick-thompson committed Oct 21, 2024
1 parent 9f02954 commit fc56661
Show file tree
Hide file tree
Showing 12 changed files with 573 additions and 1,143 deletions.
654 changes: 225 additions & 429 deletions js/packages/core/lib/core.ts

Large diffs are not rendered by default.

74 changes: 30 additions & 44 deletions js/packages/core/lib/dynamics.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
import {
createNode,
isNode,
} from '../nodeUtils';
resolve,
ElemNode,
NodeRepr_t,
} from "../nodeUtils";

import type { ElemNode, NodeRepr_t } from '../nodeUtils';
import * as co from "./core";
import * as ma from "./math";
import * as si from "./signals";

import * as co from './core';
import * as ma from './math';
import * as si from './signals';


type OptionalKeyProps = {
key?: string,
}

// NEED Signals library stuffs for tau2pole and db2gain yayay
const el = {
...co,
...ma,
Expand All @@ -28,12 +23,12 @@ const el = {
* same input both as the input to be compressed and as the sidechain signal itself
* for standard compressor behavior.
*
* @param {Node | number} atkMs – attack time in milliseconds
* @param {Node | number} relMs – release time in millseconds
* @param {Node | number} threshold – decibel value above which the comp kicks in
* @param {Node | number} ratio – ratio by which we squash signal above the threshold
* @param {Node} sidechain – sidechain signal to drive the compressor
* @param {Node} xn – input signal to filter
* @param {ElemNode} atkMs – attack time in milliseconds
* @param {ElemNode} relMs – release time in millseconds
* @param {ElemNode} threshold – decibel value above which the comp kicks in
* @param {ElemNode} ratio – ratio by which we squash signal above the threshold
* @param {ElemNode} sidechain – sidechain signal to drive the compressor
* @param {ElemNode} xn – input signal to filter
*/
export function compress(
attackMs: ElemNode,
Expand All @@ -42,13 +37,10 @@ export function compress(
ratio: ElemNode,
sidechain: ElemNode,
xn: ElemNode,
): NodeRepr_t;

export function compress(atkMs, relMs, threshold, ratio, sidechain, xn) {

): NodeRepr_t {
const env = el.env(
el.tau2pole(el.mul(0.001, atkMs)),
el.tau2pole(el.mul(0.001, relMs)),
el.tau2pole(el.mul(0.001, attackMs)),
el.tau2pole(el.mul(0.001, releaseMs)),
sidechain,
);

Expand All @@ -58,7 +50,7 @@ export function compress(atkMs, relMs, threshold, ratio, sidechain, xn) {
const adjustedRatio = el.sub(1, el.div(1, ratio));

// Calculate gain reduction in dB
const gain = el.mul(adjustedRatio, el.sub(threshold, envDecibels)) // adjustedRatio * (threshold - envDecibels);
const gain = el.mul(adjustedRatio, el.sub(threshold, envDecibels)); // adjustedRatio * (threshold - envDecibels);

// Ensuring gain is not positive
const cleanGain = el.min(0, gain);
Expand All @@ -69,7 +61,6 @@ export function compress(atkMs, relMs, threshold, ratio, sidechain, xn) {
return el.mul(xn, compressedGain);
}


/* A simple softknee compressor with parameterized attack and release times,
* threshold, compression ratio and knee width.
*
Expand All @@ -79,13 +70,13 @@ export function compress(atkMs, relMs, threshold, ratio, sidechain, xn) {
* same input both as the input to be compressed and as the sidechain signal itself
* for standard compressor behavior.
*
* @param {Node | number} atkMs – attack time in milliseconds
* @param {Node | number} relMs – release time in millseconds
* @param {Node | number} threshold – decibel value above which the comp kicks in
* @param {Node | number} ratio – ratio by which we squash signal above the threshold
* @param {Node | number} kneeWidth – width of the knee in decibels, 0 for hard knee
* @param {Node} sidechain – sidechain signal to drive the compressor
* @param {Node} xn – input signal to filter
* @param {ElemNode} atkMs – attack time in milliseconds
* @param {ElemNode} relMs – release time in millseconds
* @param {ElemNode} threshold – decibel value above which the comp kicks in
* @param {ElemNode} ratio – ratio by which we squash signal above the threshold
* @param {ElemNode} kneeWidth – width of the knee in decibels, 0 for hard knee
* @param {ElemNode} sidechain – sidechain signal to drive the compressor
* @param {ElemNode} xn – input signal to filter
*/
export function skcompress(
attackMs: ElemNode,
Expand All @@ -95,12 +86,10 @@ export function skcompress(
kneeWidth: ElemNode,
sidechain: ElemNode,
xn: ElemNode,
): NodeRepr_t;

export function skcompress(atkMs, relMs, threshold, ratio, kneeWidth, sidechain, xn) {
): NodeRepr_t {
const env = el.env(
el.tau2pole(el.mul(0.001, atkMs)),
el.tau2pole(el.mul(0.001, relMs)),
el.tau2pole(el.mul(0.001, attackMs)),
el.tau2pole(el.mul(0.001, releaseMs)),
sidechain,
);

Expand Down Expand Up @@ -131,13 +120,10 @@ export function skcompress(atkMs, relMs, threshold, ratio, kneeWidth, sidechain,
el.div(adjustedRatio, 2),
el.mul(
el.div(el.sub(envDecibels, lowerKneeBound), kneeWidth),
el.sub(lowerKneeBound, envDecibels)
)
el.sub(lowerKneeBound, envDecibels),
),
),
el.mul(
adjustedRatio,
el.sub(threshold, envDecibels)
)
el.mul(adjustedRatio, el.sub(threshold, envDecibels)),
);

// Ensuring gain is not positive
Expand Down
52 changes: 15 additions & 37 deletions js/packages/core/lib/envelopes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,14 @@ import {
createNode,
isNode,
resolve,
} from '../nodeUtils';
ElemNode,
NodeRepr_t,
} from "../nodeUtils";

import type {ElemNode, NodeRepr_t} from '../nodeUtils';

import * as co from './core';
import * as ma from './math';
import * as fi from './filters';
import * as si from './signals';


// Generic
type OptionalKeyProps = {
key?: string,
}
import * as co from "./core";
import * as ma from "./math";
import * as fi from "./filters";
import * as si from "./signals";

const el = {
...co,
Expand All @@ -30,37 +24,21 @@ const el = {
* When the gate is high (1), this generates the ADS phase. When the gate is
* low (0), the R phase.
*
* @param {Object} [props]
* @param {core.Node|number} a - Attack time in seconds
* @param {core.Node|number} d - Decay time in seconds
* @param {core.Node|number} s - Sustain level between 0, 1
* @param {core.Node|number} r - Release time in seconds
* @param {core.Node|number} g - Gate signal
* @returns {core.Node}
* @param {ElemNode} a - Attack time in seconds
* @param {ElemNode} d - Decay time in seconds
* @param {ElemNode} s - Sustain level between 0, 1
* @param {ElemNode} r - Release time in seconds
* @param {ElemNode} g - Gate signal
* @returns {NodeRepr_t}
*/
export function adsr(
attackSec: ElemNode,
decaySec: ElemNode,
sustain: ElemNode,
releaseSec: ElemNode,
gate: ElemNode,
): NodeRepr_t;

export function adsr(
props: OptionalKeyProps,
attackSec: ElemNode,
decaySec: ElemNode,
sustain: ElemNode,
releaseSec: ElemNode,
gate: ElemNode,
): NodeRepr_t;

export function adsr(a_, b_, c_, d_, e_, f_?) {
let children = (typeof a_ === "number" || isNode(a_))
? [a_, b_, c_, d_, e_]
: [b_, c_, d_, e_, f_];

let [a, d, s, r, g] = children;
): NodeRepr_t {
let [a, d, s, r, g] = [attackSec, decaySec, sustain, releaseSec, gate];
let atkSamps = el.mul(a, el.sr());
let atkGate = el.le(el.counter(g), atkSamps);

Expand Down
Loading

0 comments on commit fc56661

Please sign in to comment.