3 ms·
Show HN: dspx — Serverless-friendly DSP for Node.js (native C++ + Redis state)
- deleted 11mo ago[deleted]
- deleted 11mo ago[deleted]
- deleted 11mo ago[deleted]
- deleted 11mo ago[deleted]
- deleted 11mo ago[deleted]
- deleted 11mo ago[deleted]
- deleted 11mo ago[deleted]
- deleted 11mo ago[deleted]
- deleted 11mo ago[deleted]
- a-kgeorge 11mo agoI built dspx after hitting a wall with real-time EMG processing in Node.js. Problem: 2 kHz × 8 channels → filters → decimation → FFT. JS is too slow; the Python sidecar is complex; WASM lacks native threading. Solution: Native C++ DSP with Redis-persisted state. Workers process a chunk, save state in ~1–2ms, die, and resume elsewhere. Serverless DSP without losing filter history. Repo: https://github.com/a-kgeorge/dspx https://github.com/a-kgeorge/dspx Benchmarks: https://github.com/a-kgeorge/dspx-benchmark https://github.com/a-kgeorge/dspx-benchmark npm: https://www.npmjs.com/package/dspx https://www.npmjs.com/package/dspx
- a-kgeorge 11mo agoDSP Primitives: • STFT, Mel-spectrogram, MFCC • FIR/IIR (Butterworth, Chebyshev, Parks-McClellan) • Time + FFT convolution • Decimation, resampling, rectification • Hilbert transform, wavelet decomposition Infrastructure • Multi-channel streaming (audio, biosignals, IoT) • Redis-backed persistence • TypeScript-first API w/ full type safety • SIMD: AVX2 / SSE2 / NEON Performance (i5-12600T • Node 22.21.1 • 16GB RAM): • 1 pipeline → ~34M samples/s • 32 pipelines → ~101M samples/s • Small inputs → sub-ms p50 • With Redis → ~31ms p50 / ~39ms p99 • Zero leaks over 10k+ save/restore cycles Benchmark repo: https://github.com/a-kgeorge/dspx-benchmark https://github.com/a-kgeorge/dspx-benchmark
- a-kgeorge 11mo agoCode Example: const pipeline = await createDspPipeline({ redisHost: "localhost", redisPort: 6379, stateKey: "dsp:user:ch1", }); pipeline .filter({type:"butterworth",mode:"bandpass",lowCutoffFrequency:20,highCutoffFrequency:450}) .stft({windowSize:512,hopSize:160}) .melSpectrogram({numMelBands:26}) .mfcc({numCoefficients:13}); await pipeline.process(audioData, {sampleRate:16000}); const state = await pipeline.saveState(); // worker dies → new worker await pipeline.loadState(state); Platform • x64 + ARM • Tested on Pixel 9 Pro XL (stable; NEON tuning pending) • Node 18/20/22 • N-API v8 • Prebuilds for x64 (Linux/macOS/Win) • ARM compiles once → works like normal Why not WASM? • Native threading • AVX2/SSE2/NEON • Zero-copy buffers to/from Redis • Clean integration w/ Node streams
- a-kgeorge 11mo agoWho It’s For • Node backends running streaming DSP • Systems needing stateful pipelines + fault tolerance • Teams avoiding separate Python/C++ services • IoT gateways w/ intermittent workloads Not ideal: • Browser-only DSP (use WebAudio) • Hard realtime (<1ms) embedded audio Help Wanted • Portable NEON optimization (FFT + convolution) • Kafka integration (batching / backpressure / checkpoints) • Production war stories Status STFT / Mel / MFCC Convolution + FFT (native C/C++) Redis persistence stable ARM functional (not optimized) 891 tests passing Kafka integration (seeking input) Repos: https://github.com/a-kgeorge/dspx https://github.com/a-kgeorge/dspx https://github.com/a-kgeorge/dspx-benchmark https://github.com/a-kgeorge/dspx-benchmark