npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@billdaddy/dspkit

v0.1.0

Published

Zero-dependency digital signal processing: FFT/IFFT, spectrum analysis, FIR filter design (lowpass/highpass/bandpass/bandstop), window functions, signal utilities.

Readme

dspkit

npm version npm downloads CI License: MIT

Zero-dependency digital signal processing: FFT/IFFT, spectrum analysis, FIR filter design, window functions, and signal utilities — TypeScript-first npm equivalent of Python's scipy.signal, Go's gonum/dsp, Java's JTransforms.

import { fft, magnitudeSpectrum, dominantFrequency, generateSine, lowpassFilter, applyFilter } from "@billdaddy/dspkit";

// Generate a 440 Hz sine wave at 44100 Hz sample rate
const signal = generateSine(440, 1.0, 44100, 4096);

// Compute FFT and find dominant frequency
const spectrum = fft(signal);
const { magnitude, frequencies } = magnitudeSpectrum(spectrum, 44100);
const freq = dominantFrequency(magnitude, frequencies); // ≈ 440

// Design a 1 kHz lowpass FIR filter and apply it
const cutoff = 1000 / 44100; // normalized (0–0.5)
const h = lowpassFilter(cutoff, 128);
const filtered = applyFilter(signal, h);

Why dspkit?

Every major scientific computing ecosystem ships DSP primitives in its standard or near-standard library:

  • Pythonscipy.signal (FFT, IIR/FIR design, spectrogram)
  • Gogonum.org/v1/gonum/dsp (FFT, windowing)
  • JavaJTransforms, Apache Commons Math
  • C#Math.NET Numerics (FFT, filter design)
  • JuliaDSP.jl (comprehensive)

The only npm package attempting this space — dsp.js — was self-declared unmaintained as of 2014, has no TypeScript support, and receives ~38k downloads per week only because no alternative exists. dspkit is its modern, zero-dep, TypeScript-native replacement.

Install

npm install @billdaddy/dspkit

Usage

FFT / IFFT

import { fft, ifft, fftConvolve, nextPow2 } from "@billdaddy/dspkit";

// Real-valued signal → complex spectrum (auto zero-pads to next power of 2)
const spectrum = fft([1, 2, 3, 4, 5, 6, 7, 8]);
spectrum.re; // real parts
spectrum.im; // imaginary parts
spectrum.length; // 8 (already a power of 2)

// Non-power-of-2 inputs are zero-padded automatically
fft([1, 2, 3]).length; // 4

// Inverse FFT → recover original signal
const back = ifft(spectrum);
back.re; // ≈ [1, 2, 3, 4, 5, 6, 7, 8]

// FFT-based convolution: O(N log N) vs direct O(N*M)
const result = fftConvolve([1, 2, 3], [4, 5, 6]); // → Float64Array([4, 13, 28, 27, 18])

Spectrum analysis

import { fft, magnitude, powerSpectrum, phase, magnitudeSpectrum, dominantFrequency, rms, peak, crestFactor } from "@billdaddy/dspkit";

const c = fft(signal);

magnitude(c);      // |X[k]|  — amplitude at each bin
powerSpectrum(c);  // |X[k]|² — power at each bin
phase(c);          // atan2(im, re) — phase at each bin

// One-sided magnitude spectrum with physical frequency labels
const { magnitude: mag, frequencies } = magnitudeSpectrum(c, 44100);
// mag[k] is amplitude at frequencies[k] Hz
dominantFrequency(mag, frequencies); // frequency with highest amplitude

// Time-domain statistics
rms(signal);          // root-mean-square energy
peak(signal);         // maximum absolute value
crestFactor(signal);  // peak / rms

Window functions

Reduce spectral leakage when your signal doesn't contain an integer number of cycles.

import { hannWindow, hammingWindow, blackmanWindow, bartlettWindow,
         nuttallWindow, blackmanHarrisWindow, flatTopWindow, rectangularWindow,
         applyWindow, coherentGain, getWindow } from "@billdaddy/dspkit";

const N = 1024;
const w = hannWindow(N);     // → Float64Array of length N
applyWindow(signal, w);      // element-wise multiply signal × window
coherentGain(w);             // mean of window (≈ 0.5 for Hann)

// Get window by name
getWindow("blackman", N);    // one of: rectangular|hann|hamming|blackman|bartlett|nuttall|blackman-harris|flat-top

| Window | Sidelobe level | Main lobe width | Use case | |--------|---------------|-----------------|----------| | Rectangular | -13 dB | Narrowest | Never leak matters | | Hann | -31 dB | Moderate | General purpose | | Hamming | -41 dB | Moderate | General purpose | | Blackman | -57 dB | Wide | Low sidelobes | | Nuttall | -93 dB | Wide | Very low sidelobes | | Blackman-Harris | -92 dB | Wide | Very low sidelobes | | Flat-Top | -44 dB | Widest | Amplitude accuracy |

FIR filter design (windowed-sinc)

All cutoff frequencies are normalized: cutoff = f_Hz / f_sample. Valid range: (0, 0.5) where 0.5 = Nyquist.

import { lowpassFilter, highpassFilter, bandpassFilter, bandstopFilter, applyFilter } from "@billdaddy/dspkit";

const sampleRate = 44100;

// Lowpass: pass < 2 kHz, attenuate > 2 kHz
const lp = lowpassFilter(2000 / sampleRate, 128);  // order 128 → 129 coefficients

// Highpass: pass > 5 kHz, attenuate < 5 kHz
const hp = highpassFilter(5000 / sampleRate, 128);

// Bandpass: pass 300–3400 Hz (telephone band)
const bp = bandpassFilter(300 / sampleRate, 3400 / sampleRate, 128);

// Bandstop (notch): suppress 50 Hz power-line hum
const bs = bandstopFilter(45 / sampleRate, 55 / sampleRate, 128);

// Apply any FIR filter to a signal (causal, same output length as input)
const filtered = applyFilter(signal, lp);
// Note: group delay = order/2 samples (filter is linear-phase)

Direct convolution

import { convolve } from "@billdaddy/dspkit";

convolve([1, 2, 3], [4, 5, 6]);
// → Float64Array([4, 13, 28, 27, 18])  (length = 3 + 3 - 1 = 5)

Signal generation

import { generateSine, generateCosine, generateSquare, generateNoise, linspace } from "@billdaddy/dspkit";

const sr = 44100, n = 4096;

generateSine(440, 1.0, sr, n);       // A4 at full amplitude
generateCosine(440, 0.5, sr, n);     // half-amplitude cosine
generateSquare(100, 1.0, sr, n, 10); // square wave (10 harmonics)
generateNoise(0.1, n);               // white noise at 10% amplitude

linspace(0, 1, 11); // [0, 0.1, 0.2, ..., 1.0]

Signal utilities

import { zeroPad, mean, removeDC, normalize, toDb, fromDb } from "@billdaddy/dspkit";

zeroPad(signal, 512);    // extend with zeros to length 512
mean(signal);            // arithmetic mean
removeDC(signal);        // subtract mean (remove DC offset)
normalize(signal);       // scale so peak absolute value = 1
toDb(0.5);               // ≈ -6 dB
fromDb(-6);              // ≈ 0.5

API summary

FFT

| Function | Description | |----------|-------------| | fft(signal) | Forward FFT of real signal → ComplexArray | | ifft(complex) | Inverse FFT → ComplexArray | | fftConvolve(a, b) | FFT-based linear convolution | | nextPow2(n) | Smallest power of 2 ≥ n |

Spectrum

| Function | Description | |----------|-------------| | magnitude(c) | |X[k]| for each bin | | powerSpectrum(c) | |X[k]|² for each bin | | phase(c) | atan2(im, re) for each bin | | magnitudeSpectrum(c, sr?) | One-sided spectrum with frequency labels | | dominantFrequency(mag, freqs) | Frequency at spectral peak | | rms(signal) | Root-mean-square | | peak(signal) | Maximum absolute value | | crestFactor(signal) | peak / rms |

Windows

| Function | Description | |----------|-------------| | hannWindow(n) | Hann window | | hammingWindow(n) | Hamming window | | blackmanWindow(n) | Blackman window | | bartlettWindow(n) | Bartlett (triangular) window | | nuttallWindow(n) | Nuttall window | | blackmanHarrisWindow(n) | Blackman-Harris window | | flatTopWindow(n) | Flat-top window | | rectangularWindow(n) | No windowing (boxcar) | | applyWindow(signal, w) | Element-wise multiply | | coherentGain(w) | Mean of window coefficients | | getWindow(name, n) | Get window by name |

Filters (FIR)

| Function | Description | |----------|-------------| | lowpassFilter(cutoff, order, window?) | Lowpass FIR coefficients | | highpassFilter(cutoff, order, window?) | Highpass FIR coefficients | | bandpassFilter(lo, hi, order, window?) | Bandpass FIR coefficients | | bandstopFilter(lo, hi, order, window?) | Bandstop (notch) FIR coefficients | | applyFilter(signal, coeffs) | Apply FIR filter (causal) | | convolve(a, b) | Direct linear convolution |

Signal utilities

| Function | Description | |----------|-------------| | generateSine(f, amp, sr, n, phase?) | Sine wave | | generateCosine(f, amp, sr, n, phase?) | Cosine wave | | generateSquare(f, amp, sr, n, harmonics?) | Square wave | | generateNoise(amp, n) | White noise | | zeroPad(signal, length) | Zero-pad to length | | linspace(start, end, n) | Evenly-spaced values | | mean(signal) | Arithmetic mean | | removeDC(signal) | Subtract mean | | normalize(signal) | Scale peak to 1 | | toDb(linear) | Amplitude → dB | | fromDb(db) | dB → amplitude |

Performance

| Operation | Complexity | |-----------|-----------| | fft(n) | O(n log n) | | ifft(n) | O(n log n) | | fftConvolve(a, b) | O(N log N), N = nextPow2(a+b-1) | | convolve(a, b) | O(a.length × b.length) — fine for FIR taps | | applyFilter(signal, h) | O(signal.length × h.length) | | Window functions | O(n) |

Contributors ✨

License

MIT © trananhtung