{"_id":"@billdaddy/dspkit","name":"@billdaddy/dspkit","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@billdaddy/dspkit","version":"0.1.0","description":"Zero-dependency digital signal processing: FFT/IFFT, spectrum analysis, FIR filter design (lowpass/highpass/bandpass/bandstop), window functions, signal utilities.","type":"module","exports":{".":{"import":"./dist/index.js","require":"./dist/index.cjs","types":"./dist/index.d.ts"}},"main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","scripts":{"build":"tsup","typecheck":"tsc --noEmit","test":"node --experimental-vm-modules node_modules/.bin/jest","prepublishOnly":"npm run typecheck && npm test && npm run build"},"keywords":["dsp","fft","ifft","digital-signal-processing","signal","filter","lowpass","highpass","bandpass","fir","windowed-sinc","window","hann","hamming","blackman","spectrum","magnitude","frequency","audio","typescript","zero-dependency"],"author":{"name":"trananhtung"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/trananhtung/dspkit.git"},"homepage":"https://github.com/trananhtung/dspkit#readme","bugs":{"url":"https://github.com/trananhtung/dspkit/issues"},"devDependencies":{"@types/jest":"^29.5.14","@types/node":"^22.10.0","jest":"^29.7.0","ts-jest":"^29.2.5","tsup":"^8.3.5","typescript":"^5.7.2"},"_id":"@billdaddy/dspkit@0.1.0","gitHead":"985cc61aff242cead6de5485ecaa7641a002a72b","_nodeVersion":"20.18.2","_npmVersion":"11.5.2","dist":{"integrity":"sha512-HZlc5Krn0AYeP95ZbUWHaXb/FYmWB+90gnMX2BLnUtkDsKS9D7galCmVzkdjTfG8I0HLLyCsdYOV4Br4T0yDUQ==","shasum":"4ec7209cbe9ca02f81d0ce97dca96d4db9acccd7","tarball":"https://registry.npmjs.org/@billdaddy/dspkit/-/dspkit-0.1.0.tgz","fileCount":7,"unpackedSize":54269,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDikbuwLMI6HZb8WbkToDIO6fShQafvJ8wwWVU90hN3iwIgVh8NQ5gFlBIjnnk4r8n9X3yeA9ib8qjH56sX6tD3A7M="}]},"_npmUser":{"name":"billdaddy","email":"tunganhtran94@gmail.com"},"directories":{},"maintainers":[{"name":"billdaddy","email":"tunganhtran94@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/dspkit_0.1.0_1782270280943_0.02830759354045065"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-24T03:04:40.710Z","0.1.0":"2026-06-24T03:04:41.083Z","modified":"2026-06-24T03:04:41.346Z"},"maintainers":[{"name":"billdaddy","email":"tunganhtran94@gmail.com"}],"description":"Zero-dependency digital signal processing: FFT/IFFT, spectrum analysis, FIR filter design (lowpass/highpass/bandpass/bandstop), window functions, signal utilities.","homepage":"https://github.com/trananhtung/dspkit#readme","keywords":["dsp","fft","ifft","digital-signal-processing","signal","filter","lowpass","highpass","bandpass","fir","windowed-sinc","window","hann","hamming","blackman","spectrum","magnitude","frequency","audio","typescript","zero-dependency"],"repository":{"type":"git","url":"git+https://github.com/trananhtung/dspkit.git"},"author":{"name":"trananhtung"},"bugs":{"url":"https://github.com/trananhtung/dspkit/issues"},"license":"MIT","readme":"# dspkit\n\n<!-- ALL-CONTRIBUTORS-BADGE:START --><!-- ALL-CONTRIBUTORS-BADGE:END -->\n[![npm version](https://img.shields.io/npm/v/@billdaddy/dspkit.svg)](https://www.npmjs.com/package/@billdaddy/dspkit)\n[![npm downloads](https://img.shields.io/npm/dm/@billdaddy/dspkit.svg)](https://www.npmjs.com/package/@billdaddy/dspkit)\n[![CI](https://img.shields.io/github/actions/workflow/status/trananhtung/dspkit/ci.yml?branch=main)](https://github.com/trananhtung/dspkit/actions)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n**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`.**\n\n```ts\nimport { fft, magnitudeSpectrum, dominantFrequency, generateSine, lowpassFilter, applyFilter } from \"@billdaddy/dspkit\";\n\n// Generate a 440 Hz sine wave at 44100 Hz sample rate\nconst signal = generateSine(440, 1.0, 44100, 4096);\n\n// Compute FFT and find dominant frequency\nconst spectrum = fft(signal);\nconst { magnitude, frequencies } = magnitudeSpectrum(spectrum, 44100);\nconst freq = dominantFrequency(magnitude, frequencies); // ≈ 440\n\n// Design a 1 kHz lowpass FIR filter and apply it\nconst cutoff = 1000 / 44100; // normalized (0–0.5)\nconst h = lowpassFilter(cutoff, 128);\nconst filtered = applyFilter(signal, h);\n```\n\n## Why dspkit?\n\nEvery major scientific computing ecosystem ships DSP primitives in its standard or near-standard library:\n- **Python** — `scipy.signal` (FFT, IIR/FIR design, spectrogram)\n- **Go** — `gonum.org/v1/gonum/dsp` (FFT, windowing)\n- **Java** — `JTransforms`, `Apache Commons Math`\n- **C#** — `Math.NET Numerics` (FFT, filter design)\n- **Julia** — `DSP.jl` (comprehensive)\n\nThe 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.\n\n## Install\n\n```bash\nnpm install @billdaddy/dspkit\n```\n\n## Usage\n\n### FFT / IFFT\n\n```ts\nimport { fft, ifft, fftConvolve, nextPow2 } from \"@billdaddy/dspkit\";\n\n// Real-valued signal → complex spectrum (auto zero-pads to next power of 2)\nconst spectrum = fft([1, 2, 3, 4, 5, 6, 7, 8]);\nspectrum.re; // real parts\nspectrum.im; // imaginary parts\nspectrum.length; // 8 (already a power of 2)\n\n// Non-power-of-2 inputs are zero-padded automatically\nfft([1, 2, 3]).length; // 4\n\n// Inverse FFT → recover original signal\nconst back = ifft(spectrum);\nback.re; // ≈ [1, 2, 3, 4, 5, 6, 7, 8]\n\n// FFT-based convolution: O(N log N) vs direct O(N*M)\nconst result = fftConvolve([1, 2, 3], [4, 5, 6]); // → Float64Array([4, 13, 28, 27, 18])\n```\n\n### Spectrum analysis\n\n```ts\nimport { fft, magnitude, powerSpectrum, phase, magnitudeSpectrum, dominantFrequency, rms, peak, crestFactor } from \"@billdaddy/dspkit\";\n\nconst c = fft(signal);\n\nmagnitude(c);      // |X[k]|  — amplitude at each bin\npowerSpectrum(c);  // |X[k]|² — power at each bin\nphase(c);          // atan2(im, re) — phase at each bin\n\n// One-sided magnitude spectrum with physical frequency labels\nconst { magnitude: mag, frequencies } = magnitudeSpectrum(c, 44100);\n// mag[k] is amplitude at frequencies[k] Hz\ndominantFrequency(mag, frequencies); // frequency with highest amplitude\n\n// Time-domain statistics\nrms(signal);          // root-mean-square energy\npeak(signal);         // maximum absolute value\ncrestFactor(signal);  // peak / rms\n```\n\n### Window functions\n\nReduce spectral leakage when your signal doesn't contain an integer number of cycles.\n\n```ts\nimport { hannWindow, hammingWindow, blackmanWindow, bartlettWindow,\n         nuttallWindow, blackmanHarrisWindow, flatTopWindow, rectangularWindow,\n         applyWindow, coherentGain, getWindow } from \"@billdaddy/dspkit\";\n\nconst N = 1024;\nconst w = hannWindow(N);     // → Float64Array of length N\napplyWindow(signal, w);      // element-wise multiply signal × window\ncoherentGain(w);             // mean of window (≈ 0.5 for Hann)\n\n// Get window by name\ngetWindow(\"blackman\", N);    // one of: rectangular|hann|hamming|blackman|bartlett|nuttall|blackman-harris|flat-top\n```\n\n| Window | Sidelobe level | Main lobe width | Use case |\n|--------|---------------|-----------------|----------|\n| Rectangular | -13 dB | Narrowest | Never leak matters |\n| Hann | -31 dB | Moderate | General purpose |\n| Hamming | -41 dB | Moderate | General purpose |\n| Blackman | -57 dB | Wide | Low sidelobes |\n| Nuttall | -93 dB | Wide | Very low sidelobes |\n| Blackman-Harris | -92 dB | Wide | Very low sidelobes |\n| Flat-Top | -44 dB | Widest | Amplitude accuracy |\n\n### FIR filter design (windowed-sinc)\n\nAll cutoff frequencies are **normalized**: `cutoff = f_Hz / f_sample`. Valid range: (0, 0.5) where 0.5 = Nyquist.\n\n```ts\nimport { lowpassFilter, highpassFilter, bandpassFilter, bandstopFilter, applyFilter } from \"@billdaddy/dspkit\";\n\nconst sampleRate = 44100;\n\n// Lowpass: pass < 2 kHz, attenuate > 2 kHz\nconst lp = lowpassFilter(2000 / sampleRate, 128);  // order 128 → 129 coefficients\n\n// Highpass: pass > 5 kHz, attenuate < 5 kHz\nconst hp = highpassFilter(5000 / sampleRate, 128);\n\n// Bandpass: pass 300–3400 Hz (telephone band)\nconst bp = bandpassFilter(300 / sampleRate, 3400 / sampleRate, 128);\n\n// Bandstop (notch): suppress 50 Hz power-line hum\nconst bs = bandstopFilter(45 / sampleRate, 55 / sampleRate, 128);\n\n// Apply any FIR filter to a signal (causal, same output length as input)\nconst filtered = applyFilter(signal, lp);\n// Note: group delay = order/2 samples (filter is linear-phase)\n```\n\n### Direct convolution\n\n```ts\nimport { convolve } from \"@billdaddy/dspkit\";\n\nconvolve([1, 2, 3], [4, 5, 6]);\n// → Float64Array([4, 13, 28, 27, 18])  (length = 3 + 3 - 1 = 5)\n```\n\n### Signal generation\n\n```ts\nimport { generateSine, generateCosine, generateSquare, generateNoise, linspace } from \"@billdaddy/dspkit\";\n\nconst sr = 44100, n = 4096;\n\ngenerateSine(440, 1.0, sr, n);       // A4 at full amplitude\ngenerateCosine(440, 0.5, sr, n);     // half-amplitude cosine\ngenerateSquare(100, 1.0, sr, n, 10); // square wave (10 harmonics)\ngenerateNoise(0.1, n);               // white noise at 10% amplitude\n\nlinspace(0, 1, 11); // [0, 0.1, 0.2, ..., 1.0]\n```\n\n### Signal utilities\n\n```ts\nimport { zeroPad, mean, removeDC, normalize, toDb, fromDb } from \"@billdaddy/dspkit\";\n\nzeroPad(signal, 512);    // extend with zeros to length 512\nmean(signal);            // arithmetic mean\nremoveDC(signal);        // subtract mean (remove DC offset)\nnormalize(signal);       // scale so peak absolute value = 1\ntoDb(0.5);               // ≈ -6 dB\nfromDb(-6);              // ≈ 0.5\n```\n\n## API summary\n\n### FFT\n| Function | Description |\n|----------|-------------|\n| `fft(signal)` | Forward FFT of real signal → `ComplexArray` |\n| `ifft(complex)` | Inverse FFT → `ComplexArray` |\n| `fftConvolve(a, b)` | FFT-based linear convolution |\n| `nextPow2(n)` | Smallest power of 2 ≥ n |\n\n### Spectrum\n| Function | Description |\n|----------|-------------|\n| `magnitude(c)` | \\|X[k]\\| for each bin |\n| `powerSpectrum(c)` | \\|X[k]\\|² for each bin |\n| `phase(c)` | atan2(im, re) for each bin |\n| `magnitudeSpectrum(c, sr?)` | One-sided spectrum with frequency labels |\n| `dominantFrequency(mag, freqs)` | Frequency at spectral peak |\n| `rms(signal)` | Root-mean-square |\n| `peak(signal)` | Maximum absolute value |\n| `crestFactor(signal)` | peak / rms |\n\n### Windows\n| Function | Description |\n|----------|-------------|\n| `hannWindow(n)` | Hann window |\n| `hammingWindow(n)` | Hamming window |\n| `blackmanWindow(n)` | Blackman window |\n| `bartlettWindow(n)` | Bartlett (triangular) window |\n| `nuttallWindow(n)` | Nuttall window |\n| `blackmanHarrisWindow(n)` | Blackman-Harris window |\n| `flatTopWindow(n)` | Flat-top window |\n| `rectangularWindow(n)` | No windowing (boxcar) |\n| `applyWindow(signal, w)` | Element-wise multiply |\n| `coherentGain(w)` | Mean of window coefficients |\n| `getWindow(name, n)` | Get window by name |\n\n### Filters (FIR)\n| Function | Description |\n|----------|-------------|\n| `lowpassFilter(cutoff, order, window?)` | Lowpass FIR coefficients |\n| `highpassFilter(cutoff, order, window?)` | Highpass FIR coefficients |\n| `bandpassFilter(lo, hi, order, window?)` | Bandpass FIR coefficients |\n| `bandstopFilter(lo, hi, order, window?)` | Bandstop (notch) FIR coefficients |\n| `applyFilter(signal, coeffs)` | Apply FIR filter (causal) |\n| `convolve(a, b)` | Direct linear convolution |\n\n### Signal utilities\n| Function | Description |\n|----------|-------------|\n| `generateSine(f, amp, sr, n, phase?)` | Sine wave |\n| `generateCosine(f, amp, sr, n, phase?)` | Cosine wave |\n| `generateSquare(f, amp, sr, n, harmonics?)` | Square wave |\n| `generateNoise(amp, n)` | White noise |\n| `zeroPad(signal, length)` | Zero-pad to length |\n| `linspace(start, end, n)` | Evenly-spaced values |\n| `mean(signal)` | Arithmetic mean |\n| `removeDC(signal)` | Subtract mean |\n| `normalize(signal)` | Scale peak to 1 |\n| `toDb(linear)` | Amplitude → dB |\n| `fromDb(db)` | dB → amplitude |\n\n## Performance\n\n| Operation | Complexity |\n|-----------|-----------|\n| `fft(n)` | O(n log n) |\n| `ifft(n)` | O(n log n) |\n| `fftConvolve(a, b)` | O(N log N), N = nextPow2(a+b-1) |\n| `convolve(a, b)` | O(a.length × b.length) — fine for FIR taps |\n| `applyFilter(signal, h)` | O(signal.length × h.length) |\n| Window functions | O(n) |\n\n## Contributors ✨\n\n<!-- ALL-CONTRIBUTORS-LIST:START --><!-- ALL-CONTRIBUTORS-LIST:END -->\n\n## License\n\nMIT © [trananhtung](https://github.com/trananhtung)\n","readmeFilename":"README.md","_rev":"1-36a79a3ebf6c9da1c0495d4930c263bd"}