a-kgeorge 2 days ago

I 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 Benchmarks: https://github.com/a-kgeorge/dspx-benchmark npm: https://www.npmjs.com/package/dspx

  • a-kgeorge 2 days ago

    DSP 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

    • a-kgeorge 2 days ago

      Code 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 2 days ago

        Who 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-benchmark