UNPKG

@thi.ng/dsp

Version:

Composable signal generators, oscillators, filters, FFT, spectrum, windowing & related DSP utils

107 lines (106 loc) 2.65 kB
import { isFunction } from "@thi.ng/checks/is-function"; import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; import { wrap } from "@thi.ng/math/interval"; import { AProc } from "./aproc.js"; const delay = (n) => new Delay(n, 0); const delayT = (n, off) => new Delay(n, off); class Delay extends AProc { /** * Constructs new delay line of size `n` and initializes all * elements to `empty`. If the latter is a function, the buffer will * be initialized with the results of that function (called for each * element). * * @param n - * @param _empty - */ constructor(n, _empty) { super(isFunction(_empty) ? _empty() : _empty); this._empty = _empty; if (n < 1) illegalArgs("delay size must be >= 1"); n >>>= 0; this._wpos = n - 1; this._rpos = 0; this._buf = new Array(n); this.clear(); } _buf; _rpos; _wpos; get length() { return this._buf.length; } clear() { const { _buf, _empty } = this; if (isFunction(_empty)) { for (let i = _buf.length; i-- > 0; ) { this._buf[i] = _empty(); } } else { this._buf.fill(_empty); } } copy() { return new Delay(this._buf.length, this._empty); } /** * Alias for {@link Delay.clear} */ reset() { this.clear(); return this; } /** * Returns the delayed value at current read position (i.e. `n` * samples behind current write pos, where `n` is the length of this * delay line). */ deref() { return this._buf[this._rpos]; } /** * Reads value at `t` relative to current write position. `t` should * be in `(-∞..0)` interval. E.g. `tap(-1)` returns the second * most recent value written. * * @param t - */ tap(t) { return this._buf[wrap((t | 0) + this._wpos, 0, this._buf.length - 1)]; } /** * Takes an array of offsets relative to current write position, * calls {@link Delay.tap} for each, writes results to `out` and * returns it. */ multiTap(t, out = []) { for (let i = t.length; i-- > 0; ) { out[i] = this.tap(t[i]); } return out; } /** * Progresses read & write pos, stores new value and returns delayed value. * * @param x - */ next(x) { this.step(); this._buf[this._wpos] = x; return this._val = this._buf[this._rpos]; } /** * Moves read & write cursors one step forward. Useful for skipping * elements and/or to create gaps in the delay line. */ step() { const n = this._buf.length; ++this._wpos >= n && (this._wpos -= n); ++this._rpos >= n && (this._rpos -= n); } } export { Delay, delay, delayT };