Docs/Skills and code/skill video-visual-production
.claude/skills/video-visual-production/scripts/lib/dsp.js
What the file says about itself
Dependency-free DSP: seeded noise, biquad band-pass, WAV read/write. All sounds are deterministic from their parameters.
// Dependency-free DSP: seeded noise, biquad band-pass, WAV read/write. All sounds are deterministic from their parameters.
const fs = require('fs');
const SR = 48000;
function rng(seed) { // mulberry32
let a = seed >>> 0;
return () => { a |= 0; a = (a + 0x6D2B79F5) | 0; let t = Math.imul(a ^ (a >>> 15), 1 | a); t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t; return ((t ^ (t >>> 14)) >>> 0) / 4294967296; };
}
// RBJ band-pass (constant 0 dB peak gain); returns a stateful sample processor whose centre frequency may change per call
function bandpass(Q = 1) {
let x1 = 0, x2 = 0, y1 = 0, y2 = 0;
return (x, f0) => {
const w = (2 * Math.PI * Math.min(f0, SR * 0.45)) / SR, al = Math.sin(w) / (2 * Q), cs = Math.cos(w);
const b0 = al, b2 = -al, a0 = 1 + al, a1 = -2 * cs, a2 = 1 - al;
const y = (b0 * x + b2 * x2 - a1 * y1 - a2 * y2) / a0;
x2 = x1; x1 = x; y2 = y1; y1 = y;
return y;
};
}
function onePoleLP(fc) {
const a = Math.exp((-2 * Math.PI * fc) / SR);
let y = 0;
return (x) => (y = (1 - a) * x + a * y);
}
function peak(a) { let p = 0; for (let i = 0; i < a.length; i++) { const v = Math.abs(a[i]); if (v > p) p = v; } return p; }
function rms(a, from = 0, to = a.length) { let s = 0; for (let i = from; i < to; i++) s += a[i] * a[i]; return Math.sqrt(s / Math.max(1, to - from)); }
function normalizePeak(a, target = 1) { const p = peak(a) || 1; for (let i = 0; i < a.length; i++) a[i] = (a[i] / p) * target; return a; }
const db = (x) => Math.pow(10, x / 20);
// 32-bit float or 16-bit PCM mono/stereo WAV
function writeWav(file, data, sr = SR, bits = 32) {
const n = data.length, bytes = bits === 32 ? 4 : 2;
const buf = Buffer.alloc(44 + n * bytes);
buf.write('RIFF', 0); buf.writeUInt32LE(36 + n * bytes, 4); buf.write('WAVE', 8); buf.write('fmt ', 12);
buf.writeUInt32LE(16, 16); buf.writeUInt16LE(bits === 32 ? 3 : 1, 20); buf.writeUInt16LE(1, 22);
buf.writeUInt32LE(sr, 24); buf.writeUInt32LE(sr * bytes, 28); buf.writeUInt16LE(bytes, 32); buf.writeUInt16LE(bits, 34);
buf.write('data', 36); buf.writeUInt32LE(n * bytes, 40);
for (let i = 0; i < n; i++) { if (bits === 32) buf.writeFloatLE(data[i], 44 + i * 4); else buf.writeInt16LE(Math.max(-32768, Math.min(32767, Math.round(data[i] * 32767))), 44 + i * 2); }
fs.writeFileSync(file, buf);
}
// Raw f32le (from ffmpeg) to an aligned Float32Array
function f32FromBuffer(b) { const out = new Float32Array(b.length / 4); for (let i = 0; i < out.length; i++) out[i] = b.readFloatLE(i * 4); return out; }
function f32ToBuffer(a) { const b = Buffer.alloc(a.length * 4); for (let i = 0; i < a.length; i++) b.writeFloatLE(a[i], i * 4); return b; }
module.exports = { SR, rng, bandpass, onePoleLP, peak, rms, normalizePeak, db, writeWav, f32FromBuffer, f32ToBuffer };
Shown as it is in the repository at build time (2026-11-03); the home directory appears as <home>. If this page and the file differ, the file is right. Back to the catalogue.