dspx 0.1.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +185 -0
- package/.vscode/c_cpp_properties.json +17 -0
- package/.vscode/settings.json +68 -0
- package/.vscode/tasks.json +28 -0
- package/DISCLAIMER.md +32 -0
- package/LICENSE +21 -0
- package/README.md +1803 -0
- package/ROADMAP.md +192 -0
- package/TECHNICAL_DEBT.md +165 -0
- package/binding.gyp +65 -0
- package/docs/ADVANCED_LOGGER_FEATURES.md +598 -0
- package/docs/AUTHENTICATION_SECURITY.md +396 -0
- package/docs/BACKEND_IMPROVEMENTS.md +399 -0
- package/docs/CHEBYSHEV_BIQUAD_EQ_IMPLEMENTATION.md +405 -0
- package/docs/FFT_IMPLEMENTATION.md +490 -0
- package/docs/FFT_IMPROVEMENTS_SUMMARY.md +387 -0
- package/docs/FFT_USER_GUIDE.md +494 -0
- package/docs/FILTERS_IMPLEMENTATION.md +260 -0
- package/docs/FILTER_API_GUIDE.md +418 -0
- package/docs/FIR_SIMD_OPTIMIZATION.md +175 -0
- package/docs/LOGGER_API_REFERENCE.md +350 -0
- package/docs/NOTCH_FILTER_QUICK_REF.md +121 -0
- package/docs/PHASE2_TESTS_AND_NOTCH_FILTER.md +341 -0
- package/docs/PHASES_5_7_SUMMARY.md +403 -0
- package/docs/PIPELINE_FILTER_INTEGRATION.md +446 -0
- package/docs/SIMD_OPTIMIZATIONS.md +211 -0
- package/docs/TEST_MIGRATION_SUMMARY.md +173 -0
- package/docs/TIMESERIES_IMPLEMENTATION_SUMMARY.md +322 -0
- package/docs/TIMESERIES_QUICK_REF.md +85 -0
- package/docs/advanced.md +559 -0
- package/docs/time-series-guide.md +617 -0
- package/docs/time-series-migration.md +376 -0
- package/jest.config.js +37 -0
- package/package.json +42 -0
- package/prebuilds/linux-x64/dsp-ts-redis.node +0 -0
- package/prebuilds/win32-x64/dsp-ts-redis.node +0 -0
- package/scripts/test.js +24 -0
- package/src/build/dsp-ts-redis.node +0 -0
- package/src/native/DspPipeline.cc +675 -0
- package/src/native/DspPipeline.h +44 -0
- package/src/native/FftBindings.cc +817 -0
- package/src/native/FilterBindings.cc +1001 -0
- package/src/native/IDspStage.h +53 -0
- package/src/native/adapters/InterpolatorStage.h +201 -0
- package/src/native/adapters/MeanAbsoluteValueStage.h +289 -0
- package/src/native/adapters/MovingAverageStage.h +306 -0
- package/src/native/adapters/RectifyStage.h +88 -0
- package/src/native/adapters/ResamplerStage.h +238 -0
- package/src/native/adapters/RmsStage.h +299 -0
- package/src/native/adapters/SscStage.h +121 -0
- package/src/native/adapters/VarianceStage.h +307 -0
- package/src/native/adapters/WampStage.h +114 -0
- package/src/native/adapters/WaveformLengthStage.h +115 -0
- package/src/native/adapters/ZScoreNormalizeStage.h +326 -0
- package/src/native/core/FftEngine.cc +441 -0
- package/src/native/core/FftEngine.h +224 -0
- package/src/native/core/FirFilter.cc +324 -0
- package/src/native/core/FirFilter.h +149 -0
- package/src/native/core/IirFilter.cc +576 -0
- package/src/native/core/IirFilter.h +210 -0
- package/src/native/core/MovingAbsoluteValueFilter.cc +17 -0
- package/src/native/core/MovingAbsoluteValueFilter.h +135 -0
- package/src/native/core/MovingAverageFilter.cc +18 -0
- package/src/native/core/MovingAverageFilter.h +135 -0
- package/src/native/core/MovingFftFilter.cc +291 -0
- package/src/native/core/MovingFftFilter.h +203 -0
- package/src/native/core/MovingVarianceFilter.cc +194 -0
- package/src/native/core/MovingVarianceFilter.h +114 -0
- package/src/native/core/MovingZScoreFilter.cc +215 -0
- package/src/native/core/MovingZScoreFilter.h +113 -0
- package/src/native/core/Policies.h +352 -0
- package/src/native/core/RmsFilter.cc +18 -0
- package/src/native/core/RmsFilter.h +131 -0
- package/src/native/core/SscFilter.cc +16 -0
- package/src/native/core/SscFilter.h +137 -0
- package/src/native/core/WampFilter.cc +16 -0
- package/src/native/core/WampFilter.h +101 -0
- package/src/native/core/WaveformLengthFilter.cc +17 -0
- package/src/native/core/WaveformLengthFilter.h +98 -0
- package/src/native/utils/CircularBufferArray.cc +336 -0
- package/src/native/utils/CircularBufferArray.h +62 -0
- package/src/native/utils/CircularBufferVector.cc +145 -0
- package/src/native/utils/CircularBufferVector.h +45 -0
- package/src/native/utils/NapiUtils.cc +53 -0
- package/src/native/utils/NapiUtils.h +21 -0
- package/src/native/utils/SimdOps.h +870 -0
- package/src/native/utils/SlidingWindowFilter.cc +239 -0
- package/src/native/utils/SlidingWindowFilter.h +159 -0
- package/src/native/utils/TimeSeriesBuffer.cc +205 -0
- package/src/native/utils/TimeSeriesBuffer.h +140 -0
- package/src/ts/CircularLogBuffer.ts +87 -0
- package/src/ts/DriftDetector.ts +331 -0
- package/src/ts/TopicRouter.ts +428 -0
- package/src/ts/__tests__/AdvancedDsp.test.ts +585 -0
- package/src/ts/__tests__/AuthAndEdgeCases.test.ts +241 -0
- package/src/ts/__tests__/Chaining.test.ts +387 -0
- package/src/ts/__tests__/ChebyshevBiquad.test.ts +229 -0
- package/src/ts/__tests__/CircularLogBuffer.test.ts +158 -0
- package/src/ts/__tests__/DriftDetector.test.ts +389 -0
- package/src/ts/__tests__/Fft.test.ts +484 -0
- package/src/ts/__tests__/ListState.test.ts +153 -0
- package/src/ts/__tests__/Logger.test.ts +208 -0
- package/src/ts/__tests__/LoggerAdvanced.test.ts +319 -0
- package/src/ts/__tests__/LoggerMinor.test.ts +247 -0
- package/src/ts/__tests__/MeanAbsoluteValue.test.ts +398 -0
- package/src/ts/__tests__/MovingAverage.test.ts +322 -0
- package/src/ts/__tests__/RMS.test.ts +315 -0
- package/src/ts/__tests__/Rectify.test.ts +272 -0
- package/src/ts/__tests__/Redis.test.ts +456 -0
- package/src/ts/__tests__/SlopeSignChange.test.ts +166 -0
- package/src/ts/__tests__/Tap.test.ts +164 -0
- package/src/ts/__tests__/TimeBasedExpiration.test.ts +124 -0
- package/src/ts/__tests__/TimeBasedRmsAndMav.test.ts +231 -0
- package/src/ts/__tests__/TimeBasedVarianceAndZScore.test.ts +284 -0
- package/src/ts/__tests__/TimeSeries.test.ts +254 -0
- package/src/ts/__tests__/TopicRouter.test.ts +332 -0
- package/src/ts/__tests__/TopicRouterAdvanced.test.ts +483 -0
- package/src/ts/__tests__/TopicRouterPriority.test.ts +487 -0
- package/src/ts/__tests__/Variance.test.ts +509 -0
- package/src/ts/__tests__/WaveformLength.test.ts +147 -0
- package/src/ts/__tests__/WillisonAmplitude.test.ts +197 -0
- package/src/ts/__tests__/ZScoreNormalize.test.ts +459 -0
- package/src/ts/advanced-dsp.ts +566 -0
- package/src/ts/backends.ts +1137 -0
- package/src/ts/bindings.ts +1225 -0
- package/src/ts/easter-egg.ts +42 -0
- package/src/ts/examples/MeanAbsoluteValue/test-state.ts +99 -0
- package/src/ts/examples/MeanAbsoluteValue/test-streaming.ts +269 -0
- package/src/ts/examples/MovingAverage/test-state.ts +85 -0
- package/src/ts/examples/MovingAverage/test-streaming.ts +188 -0
- package/src/ts/examples/RMS/test-state.ts +97 -0
- package/src/ts/examples/RMS/test-streaming.ts +253 -0
- package/src/ts/examples/Rectify/test-state.ts +107 -0
- package/src/ts/examples/Rectify/test-streaming.ts +242 -0
- package/src/ts/examples/Variance/test-state.ts +195 -0
- package/src/ts/examples/Variance/test-streaming.ts +260 -0
- package/src/ts/examples/ZScoreNormalize/test-state.ts +277 -0
- package/src/ts/examples/ZScoreNormalize/test-streaming.ts +306 -0
- package/src/ts/examples/advanced-dsp-examples.ts +397 -0
- package/src/ts/examples/callbacks/advanced-router-features.ts +326 -0
- package/src/ts/examples/callbacks/benchmark-circular-buffer.ts +109 -0
- package/src/ts/examples/callbacks/monitoring-example.ts +265 -0
- package/src/ts/examples/callbacks/pipeline-callbacks-example.ts +137 -0
- package/src/ts/examples/callbacks/pooled-callbacks-example.ts +274 -0
- package/src/ts/examples/callbacks/priority-routing-example.ts +277 -0
- package/src/ts/examples/callbacks/production-topic-router.ts +214 -0
- package/src/ts/examples/callbacks/topic-based-logging.ts +161 -0
- package/src/ts/examples/chaining/test-chaining-redis.ts +113 -0
- package/src/ts/examples/chaining/test-chaining.ts +52 -0
- package/src/ts/examples/emg-features-example.ts +284 -0
- package/src/ts/examples/fft-example.ts +309 -0
- package/src/ts/examples/fft-examples.ts +349 -0
- package/src/ts/examples/filter-examples.ts +320 -0
- package/src/ts/examples/list-state-example.ts +131 -0
- package/src/ts/examples/logger-example.ts +91 -0
- package/src/ts/examples/notch-filter-examples.ts +243 -0
- package/src/ts/examples/phase5/drift-detection-example.ts +290 -0
- package/src/ts/examples/phase6-7/production-observability.ts +476 -0
- package/src/ts/examples/phase6-7/redis-timeseries-integration.ts +446 -0
- package/src/ts/examples/redis/redis-example.ts +202 -0
- package/src/ts/examples/redis-example.ts +202 -0
- package/src/ts/examples/simd-benchmark.ts +126 -0
- package/src/ts/examples/tap-debugging.ts +230 -0
- package/src/ts/examples/timeseries/comparison-example.ts +290 -0
- package/src/ts/examples/timeseries/iot-sensor-example.ts +143 -0
- package/src/ts/examples/timeseries/redis-streaming-example.ts +233 -0
- package/src/ts/examples/waveform-length-example.ts +139 -0
- package/src/ts/fft.ts +722 -0
- package/src/ts/filters.ts +1078 -0
- package/src/ts/index.ts +120 -0
- package/src/ts/types.ts +589 -0
- package/tsconfig.json +15 -0
package/ROADMAP.md
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# 🧭 dspx Roadmap
|
|
2
|
+
|
|
3
|
+
This roadmap outlines the planned evolution of **dspx** — a native **C++ + TypeScript DSP** framework featuring **Redis-based state persistence** and **low-overhead logging**.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🚀 Immediate Next Steps
|
|
8
|
+
|
|
9
|
+
**Resampling Operations** (Expected in next few days):
|
|
10
|
+
|
|
11
|
+
- `Decimate`: Downsample by integer factor M with anti-aliasing filter
|
|
12
|
+
- `Interpolate`: Upsample by integer factor L with anti-imaging filter
|
|
13
|
+
- `Resample`: Rational resampling (L/M) for arbitrary sample rate conversion
|
|
14
|
+
|
|
15
|
+
All three will use efficient polyphase FIR filtering implemented in C++ for maximum performance, with full TypeScript wrappers and comprehensive test coverage.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## ✅ Current Progress
|
|
20
|
+
|
|
21
|
+
- [x] **Redis Integration (Serialization / Deserialization)**
|
|
22
|
+
- [x] **Advanced Logging (Circular Buffer, Topic Routing, Concurrency)**
|
|
23
|
+
- [x] **Core DSP Filters:** `movingAverage`, `rms`, `rectify`, `variance`, `zScoreNormalize`, `mav`, `waveformLength`, `willisonAmplitude`, `slopeSignChange`
|
|
24
|
+
- [x] **FFT Implementation:** Forward/inverse FFT, RFFT, windowing, magnitude/phase extraction
|
|
25
|
+
- [x] **Filter Design:** FIR (low/high/band-pass/band-stop), IIR (Butterworth, Chebyshev), Biquad EQ (peaking, low-shelf, high-shelf)
|
|
26
|
+
- [x] **Advanced Signal Analysis:** Hjorth parameters, spectral features (centroid, rolloff, flux), entropy measures (Shannon, SampEn, ApEn)
|
|
27
|
+
- [x] **Utility:** `listState`, `clearState`, `getState`, `saveState`
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 🧩 1. Consolidated Feature Table
|
|
32
|
+
|
|
33
|
+
| **Category** | **Methods** | **Description / Use Case** | **Redis Usage** | **Implementation Difficulty** |
|
|
34
|
+
| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | -------------------------------- | ----------------------------- |
|
|
35
|
+
| 🧩 **Core Time-Domain Filters** | ✅ `movingAverage`, ✅ `rms`, ✅ `rectify`, ✅ `variance`, ✅ `zScoreNormalize`, ✅ `mav`, ✅ `waveformLength`, ✅ `willisonAmplitude`, ✅ `slopeSignChange` | Core smoothing and EMG amplitude estimation | Buffer persistence (per channel) | 🟢 Easy |
|
|
36
|
+
| 🧠 **Statistical / Entropy Features** | ✅ `hjorthParameters`, ✅ `entropy`, ✅ `sampleEntropy`, ✅ `approximateEntropy`, ☐ `kurtosis`, ☐ `skewness` | Shape and complexity features | Aggregates per window | 🟡 Medium |
|
|
37
|
+
| 🔉 **Spectral / Transform Domain** | ✅ `fft`, ✅ `rfft`, ✅ `ifft`, ✅ `irfft`, ✅ `spectralCentroid`, ✅ `spectralRolloff`, ✅ `spectralFlux`, ☐ `hilbertTransform`, ☐ `waveletTransform`, ☐ `stft`, ☐ `melSpectrogram`, ☐ `mfcc` | Frequency and time-frequency analysis | Optional (RedisJSON possible) | 🔴 Hard |
|
|
38
|
+
| 🎛 **Filtering (Classic + Modern)** | ✅ `firFilter`, ✅ `iirFilter`, ✅ `butterworthLowpass/Highpass/Bandpass`, ✅ `chebyshevLowpass/Highpass/Bandpass`, ✅ `peakingEQ`, ✅ `lowShelf`, ✅ `highShelf`, ☐ `kalmanFilter`, ☐ `wienerFilter` | Filtering for sensor / audio data | Coefficients / state storage | 🔴 Hard |
|
|
39
|
+
| ⏱ **Resampling / Rate Control** | 🚀 `polyphaseDecimate`, 🚀 `interpolate`, 🚀 `resample` | Resampling and alias mitigation | Redis phase/delay tracking | 🟡 Medium |
|
|
40
|
+
| 🔊 **Fundamental Frequency** | ☐ `yin`, ☐ `cepstrumPitch` | Pitch / F₀ estimation for audio or tremor detection | Difference function buffers | 🔴 Hard |
|
|
41
|
+
| 🪞 **Feature Extraction (Spectral)** | ✅ `spectralCentroid`, ✅ `spectralRolloff`, ✅ `spectralFlux`, ☐ `spectralFlatness`, ☐ `mfcc` | Audio / signal features for ML | Aggregates + filterbank storage | 🟡 Medium |
|
|
42
|
+
| 🧬 **Adaptive Filters** | ☐ `lmsFilter`, ☐ `nlmsFilter`, ☐ `rls`, ☐ `wienerFilter`, ☐ `pca`, ☐ `ica`, ☐ `whiten` | Adaptive denoising + decorrelation | Redis holds coefficients | 🔴 Hard |
|
|
43
|
+
| ⚡ **Signal Analysis Utilities** | ☐ `autocorrelation`, ☐ `crossCorrelation`, ☐ `detrend`, ☐ `integrator`, ☐ `differentiator`, ☐ `snr`, ☐ `clipDetection`, ☐ `peakDetection` | Pre/post-processing utilities | Minimal (buffer only) | 🟢 Easy |
|
|
44
|
+
| 🧍♂️ **EMG / Biosignal Specific** | ☐ `muscleActivationThreshold`, ☐ `fatigue`, ☐ `autoregression`, ☐ `arCoefficients` | Biomedical signal interpretation | Redis calibration + baseline | 🟡 Medium |
|
|
45
|
+
| 📡 **Amplitude / Modulation** | ☐ `amDemod`, ☐ `amMod`, ☐ `envelopeDetect`, ☐ `instantaneousPhase` | Modulation and envelope features | Low-pass filter state | 🟡 Medium |
|
|
46
|
+
| 🧠 **Multi-Channel Spatial Ops** | ☐ `channelSelect`, ☐ `channelMerge`, ☐ `spatialFilter`, ☐ `beamformer` | Multi-channel EEG/EMG processing | Multi-channel buffers | 🔴 Hard |
|
|
47
|
+
| 🔧 **Utilities** | ✅ `clearState`, ✅ `getState`, ✅ `listState` | Redis state management + debugging | Full Redis integration | 🟢 Easy |
|
|
48
|
+
| 🌀 **Wavelet Filters (Daubechies)** | ☐ `haar`, ☐ `db2`–`db10` | Multi-resolution analysis | Redis stores transform levels | 🟡 Medium |
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 🧱 2. Implementation Phases
|
|
53
|
+
|
|
54
|
+
### 🟩 **Stage 1 — MVP / Easy**
|
|
55
|
+
|
|
56
|
+
| Priority | Category | Status | Notes |
|
|
57
|
+
| -------- | -------------------------------------------------------- | ------ | ------------------------------------- |
|
|
58
|
+
| 1️⃣ | `movingAverage`, `rms`, `rectify`, `variance` | [X] | Baseline DSP primitives (C++ + N-API) |
|
|
59
|
+
| 2️⃣ | `waveformLength`, `willisonAmplitude`, `slopeSignChange` | [X] | Next EMG feature set |
|
|
60
|
+
| 3️⃣ | `clearState`, `getState`, `listState`, `saveState` | [X] | Complete Redis debug utilities |
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
### 🟨 **Stage 2 — Intermediate (Math + Buffer Dependent)**
|
|
65
|
+
|
|
66
|
+
| Priority | Category | Status | Notes |
|
|
67
|
+
| -------- | ----------------------------------------------------- | --------------- | ------------------------------------ |
|
|
68
|
+
| 4️⃣ | `zScoreNormalize`, `mav`, `hjorthParameters` | [X] | Window math & standard deviation ops |
|
|
69
|
+
| 5️⃣ | `polyphaseDecimate`, `interpolate`, `resample` | [🚀 Coming Now] | **Expected in next few days** |
|
|
70
|
+
| 6️⃣ | `spectralCentroid`, `spectralRolloff`, `spectralFlux` | [X] | Derived FFT metrics |
|
|
71
|
+
| 7️⃣ | `entropy`, `sampleEntropy`, `approximateEntropy` | [X] | Complexity metrics per window |
|
|
72
|
+
|
|
73
|
+
**🚀 Resampling Implementation Plan:**
|
|
74
|
+
|
|
75
|
+
- C++ polyphase FIR decimator with anti-aliasing
|
|
76
|
+
- C++ polyphase FIR interpolator with anti-imaging
|
|
77
|
+
- C++ rational resampler (L/M) combining both
|
|
78
|
+
- Full N-API bindings and TypeScript wrappers
|
|
79
|
+
- Comprehensive test coverage for correctness and edge cases
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
### 🔴 **Stage 3 — Advanced DSP / FFT / Wavelets**
|
|
84
|
+
|
|
85
|
+
| Priority | Category | Status | Notes |
|
|
86
|
+
| -------- | ------------------------------------------------------------ | ------------- | ------------------------------ |
|
|
87
|
+
| 8️⃣ | `fft`, `hilbertTransform`, `hilbertEnvelope` | [X] (partial) | Transform foundation |
|
|
88
|
+
| 9️⃣ | `firFilter`, `butterworthFilter`, `notchFilter`, `iirFilter` | [X] | Real-world filter validation |
|
|
89
|
+
| 🔟 | `waveletTransform`, `haar`, `db2–db10` | [ ] | Decomposition + reconstruction |
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### 🧠 **Stage 4 — Adaptive / Statistical / Multichannel**
|
|
94
|
+
|
|
95
|
+
| Category | Status | Notes |
|
|
96
|
+
| -------------------------------- | ------ | ----------------------------------- |
|
|
97
|
+
| `lmsFilter`, `nlmsFilter`, `rls` | [ ] | Adaptive learning filters |
|
|
98
|
+
| `pca`, `ica`, `whiten` | [ ] | Statistical transformations |
|
|
99
|
+
| `beamformer`, `spatialFilter` | [ ] | Vectorized multi-channel processing |
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
### 📊 **Stage 5 — Visualization & Monitoring**
|
|
104
|
+
|
|
105
|
+
| Priority | Category | Status | Notes |
|
|
106
|
+
| -------- | -------------------------------------------------- | ------ | -------------------------------------------- |
|
|
107
|
+
| 🎨 | **Server-Side Plotting** (Matplotlib/Seaborn-like) | [ ] | Generate PNG/SVG plots for debugging/reports |
|
|
108
|
+
| 📈 | **Real-Time Dashboard** (D3.js + uWS) | [ ] | Live signal visualization with WebSockets |
|
|
109
|
+
| 🔍 | **Signal Inspector** (Interactive Analysis) | [ ] | Zoom, pan, measure time-domain features |
|
|
110
|
+
| 📉 | **Spectrogram Viewer** | [ ] | Time-frequency visualization |
|
|
111
|
+
|
|
112
|
+
**Server-Side Plotting Use Cases:**
|
|
113
|
+
|
|
114
|
+
- **Debugging**: Save PNG of signal before/after filtering
|
|
115
|
+
- **Analysis**: Generate histograms of DriftDetector values
|
|
116
|
+
- **Reporting**: Nightly jobs with emailed plot attachments
|
|
117
|
+
- **CI/CD**: Automated test reports with visual validation
|
|
118
|
+
|
|
119
|
+
**Real-Time Dashboard Features:**
|
|
120
|
+
|
|
121
|
+
- **WebSocket Streaming**: uWebSockets for low-latency data push
|
|
122
|
+
- **D3.js Visualizations**: Interactive charts, spectrograms, waterfalls
|
|
123
|
+
- **Multi-Channel Display**: Synchronized views across channels
|
|
124
|
+
- **State Monitoring**: Redis state visualization (like Kafka/Redis admin panels)
|
|
125
|
+
- **Performance Metrics**: Latency histograms, throughput graphs
|
|
126
|
+
|
|
127
|
+
**Potential Libraries:**
|
|
128
|
+
|
|
129
|
+
- Server-Side: `node-canvas`, `sharp`, `svg.js` for plot generation
|
|
130
|
+
- Real-Time: `uWebSockets.js` for streaming, `D3.js` for client rendering
|
|
131
|
+
- Inspiration: Grafana-like dashboard for DSP pipelines
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## 📁 3. Suggested Project Structure
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
dspx/
|
|
139
|
+
├── src/
|
|
140
|
+
│ ├── native/
|
|
141
|
+
│ │ ├── core/
|
|
142
|
+
│ │ │ ├── MovingAverage.cc
|
|
143
|
+
│ │ │ ├── RMS.cc
|
|
144
|
+
│ │ │ ├── Variance.cc
|
|
145
|
+
│ │ │ └── Rectify.cc
|
|
146
|
+
│ │ ├── filters/
|
|
147
|
+
│ │ │ ├── FIRFilter.cc
|
|
148
|
+
│ │ │ ├── Butterworth.cc
|
|
149
|
+
│ │ │ └── NotchFilter.cc
|
|
150
|
+
│ │ ├── transforms/
|
|
151
|
+
│ │ │ ├── FFT.cc
|
|
152
|
+
│ │ │ ├── Hilbert.cc
|
|
153
|
+
│ │ │ └── Wavelet.cc
|
|
154
|
+
│ │ ├── features/
|
|
155
|
+
│ │ │ ├── MAV.cc
|
|
156
|
+
│ │ │ ├── Hjorth.cc
|
|
157
|
+
│ │ │ └── Entropy.cc
|
|
158
|
+
│ │ ├── emg/
|
|
159
|
+
│ │ │ ├── Willison.cc
|
|
160
|
+
│ │ │ ├── SlopeSignChange.cc
|
|
161
|
+
│ │ │ └── WaveformLength.cc
|
|
162
|
+
│ │ ├── utils/
|
|
163
|
+
│ │ │ ├── DSPMath.h
|
|
164
|
+
│ │ │ └── CircularBuffer.h
|
|
165
|
+
│ │ ├── DSPSystem.cc
|
|
166
|
+
│ │ └── DSPSystem.h
|
|
167
|
+
│ ├── ts/
|
|
168
|
+
│ │ ├── index.ts
|
|
169
|
+
│ │ ├── pipeline/
|
|
170
|
+
│ │ │ ├── Pipeline.ts
|
|
171
|
+
│ │ │ ├── Stage.ts
|
|
172
|
+
│ │ │ └── Store.ts
|
|
173
|
+
│ │ └── bindings.ts
|
|
174
|
+
│ └── build/
|
|
175
|
+
├── CMakeLists.txt
|
|
176
|
+
├── package.json
|
|
177
|
+
├── tsconfig.json
|
|
178
|
+
└── README.md
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## 🚀 **Next Goals**
|
|
184
|
+
|
|
185
|
+
- [x] Add time-domain EMG features (`waveformLength`, `willisonAmplitude`, `slopeSignChange`)
|
|
186
|
+
- [x] Implement true time-based filtering with sample expiration by age
|
|
187
|
+
- [x] Introduce FFT and Hilbert transform pipeline (partial)
|
|
188
|
+
- [x] Begin filter design (Butterworth + Notch)
|
|
189
|
+
- [ ] Add server-side plotting (matplotlib-like) for debugging and reports
|
|
190
|
+
- [ ] Build real-time dashboard with D3.js + uWebSockets for live visualization
|
|
191
|
+
- [ ] Benchmark native C++ vs pure JS performance
|
|
192
|
+
- [ ] Expand unit tests for new stages and Redis states
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# Technical Debt & Improvement Opportunities
|
|
2
|
+
|
|
3
|
+
This document tracks known issues, architectural concerns, and improvement opportunities identified through static analysis. Items are prioritized by severity and impact.
|
|
4
|
+
|
|
5
|
+
## 🔴 High Priority Issues
|
|
6
|
+
|
|
7
|
+
**All high priority issues have been resolved! 🎉**
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 🟡 Medium Priority Issues
|
|
12
|
+
|
|
13
|
+
### 1. Custom Module Loader vs node-gyp-build
|
|
14
|
+
|
|
15
|
+
**Status**: Not Fixed (Technical Debt)
|
|
16
|
+
**Location**: `src/ts/bindings.ts` (lines 28-49)
|
|
17
|
+
|
|
18
|
+
**Issue**: Manual module loading loop checking multiple paths:
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
const possiblePaths = [
|
|
22
|
+
join(__dirname, "../build/dspx.node"),
|
|
23
|
+
join(__dirname, "../../build/Release/dspx.node"),
|
|
24
|
+
join(process.cwd(), "build/Release/dspx.node"),
|
|
25
|
+
join(process.cwd(), "src/build/dspx.node"),
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
for (const path of possiblePaths) {
|
|
29
|
+
try {
|
|
30
|
+
DspAddon = require(path);
|
|
31
|
+
break;
|
|
32
|
+
} catch (err: any) {
|
|
33
|
+
errors.push({ path, error: err.message });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Problem**: `node-gyp-build` package (already in dependencies) is designed to solve this exact problem more robustly.
|
|
39
|
+
|
|
40
|
+
**Recommendation**: Replace custom loader with:
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { createRequire } from "node:module";
|
|
44
|
+
const require = createRequire(import.meta.url);
|
|
45
|
+
const DspAddon = require("node-gyp-build")(join(__dirname, "../.."));
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Benefits**:
|
|
49
|
+
|
|
50
|
+
- Standard solution used by thousands of native modules
|
|
51
|
+
- Handles prebuild binaries
|
|
52
|
+
- Better error messages
|
|
53
|
+
- Less maintenance
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
### 2. Dead Code in DspPipeline::ProcessAsync
|
|
58
|
+
|
|
59
|
+
**Status**: Not Fixed (Code Cleanup)
|
|
60
|
+
**Location**: `src/native/DspPipeline.cc`
|
|
61
|
+
|
|
62
|
+
**Issue**: The legacy `(buffer, options)` overload is never called because TypeScript wrapper always provides timestamps:
|
|
63
|
+
|
|
64
|
+
```cpp
|
|
65
|
+
// This else block is dead code:
|
|
66
|
+
else
|
|
67
|
+
{
|
|
68
|
+
// Legacy mode: no timestamps
|
|
69
|
+
timestamps = nullptr;
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**TypeScript always generates timestamps**:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
if (!timestamps) {
|
|
77
|
+
// Auto-generate timestamps from sample rate or indices
|
|
78
|
+
timestamps = new Float32Array(numSamples);
|
|
79
|
+
for (let i = 0; i < numSamples; i++) {
|
|
80
|
+
timestamps[i] = options.sampleRate ? i / options.sampleRate : i;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Recommendation**:
|
|
86
|
+
|
|
87
|
+
1. Remove the dead code path
|
|
88
|
+
2. Simplify C++ signature to always require timestamps
|
|
89
|
+
3. Or add runtime assertion to catch if TypeScript behavior changes
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## 🟢 Low Priority / Future Improvements
|
|
94
|
+
|
|
95
|
+
### 3. Brittle State Validation in LoadState
|
|
96
|
+
|
|
97
|
+
**Status**: Not Fixed (Design Decision)
|
|
98
|
+
**Location**: `src/native/DspPipeline.cc` - `LoadState` method
|
|
99
|
+
|
|
100
|
+
**Issue**: Rigid validation `if (stageCount != m_stages.size())` makes all saved states invalid if pipeline structure changes.
|
|
101
|
+
|
|
102
|
+
**Impact**:
|
|
103
|
+
|
|
104
|
+
- Pipeline evolution is difficult
|
|
105
|
+
- All Redis states become invalid after stage changes
|
|
106
|
+
- No backward compatibility
|
|
107
|
+
|
|
108
|
+
**Possible Solutions** (Future):
|
|
109
|
+
|
|
110
|
+
1. **Semantic Versioning for States**: Add version field to state, support migrations
|
|
111
|
+
2. **Partial State Loading**: Load only compatible stages, skip others
|
|
112
|
+
3. **Stage Identification**: Use stage IDs/names instead of count
|
|
113
|
+
4. **State Migration Functions**: Define upgrade paths between versions
|
|
114
|
+
|
|
115
|
+
**Note**: This is a design trade-off. Current behavior is strict but predictable. Any change requires careful consideration of backward compatibility.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## ✅ Fixed Issues
|
|
120
|
+
|
|
121
|
+
### ~~1. Manual Memory Management in CircularBufferArray~~
|
|
122
|
+
|
|
123
|
+
**Status**: ✅ FIXED (October 2025)
|
|
124
|
+
**Fix**: Replaced raw `T* buffer` with `std::unique_ptr<T[]>`, eliminated manual destructor and move operations (now use compiler-generated defaults per Rule of Zero)
|
|
125
|
+
|
|
126
|
+
### ~~2. Precision Loss in NapiArrayToVector<double>~~
|
|
127
|
+
|
|
128
|
+
**Status**: ✅ FIXED (October 2025)
|
|
129
|
+
**Fix**: Now uses `DoubleValue()` for double types
|
|
130
|
+
|
|
131
|
+
### ~~3. DriftDetector Sample Rate Bug~~
|
|
132
|
+
|
|
133
|
+
**Status**: ✅ FIXED (October 2025)
|
|
134
|
+
**Fix**: Now checks if sample rate changed and recreates detector
|
|
135
|
+
|
|
136
|
+
### ~~4. Missing <numeric> Header~~
|
|
137
|
+
|
|
138
|
+
**Status**: ✅ FIXED (October 2025)
|
|
139
|
+
**Fix**: Added `#include <numeric>` to Policies.h
|
|
140
|
+
|
|
141
|
+
### ~~5. Fragile Build Configuration~~
|
|
142
|
+
|
|
143
|
+
**Status**: ✅ FIXED (October 2025)
|
|
144
|
+
**Fix**: Explicitly listed all source files in binding.gyp
|
|
145
|
+
|
|
146
|
+
### ~~6. Dual Build Systems (node-gyp + cmake-js)~~
|
|
147
|
+
|
|
148
|
+
**Status**: ✅ FIXED (October 2025)
|
|
149
|
+
**Fix**: Removed cmake-js build system
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Contributing
|
|
154
|
+
|
|
155
|
+
If you'd like to tackle any of these issues:
|
|
156
|
+
|
|
157
|
+
1. Open an issue to discuss the approach
|
|
158
|
+
2. Reference this document in your PR
|
|
159
|
+
3. Update this file to mark items as "In Progress" or "Fixed"
|
|
160
|
+
|
|
161
|
+
## Prioritization Guide
|
|
162
|
+
|
|
163
|
+
- 🔴 **High**: Security, data corruption, or crash risks
|
|
164
|
+
- 🟡 **Medium**: Maintainability, confusion, or tech debt
|
|
165
|
+
- 🟢 **Low**: Nice-to-have improvements or future enhancements
|
package/binding.gyp
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"targets": [
|
|
3
|
+
{
|
|
4
|
+
"target_name": "dspx",
|
|
5
|
+
"sources": [
|
|
6
|
+
"src/native/DspPipeline.cc",
|
|
7
|
+
"src/native/core/MovingAbsoluteValueFilter.cc",
|
|
8
|
+
"src/native/core/MovingAverageFilter.cc",
|
|
9
|
+
"src/native/core/MovingVarianceFilter.cc",
|
|
10
|
+
"src/native/core/MovingZScoreFilter.cc",
|
|
11
|
+
"src/native/core/RmsFilter.cc",
|
|
12
|
+
"src/native/core/SscFilter.cc",
|
|
13
|
+
"src/native/core/WampFilter.cc",
|
|
14
|
+
"src/native/core/WaveformLengthFilter.cc",
|
|
15
|
+
"src/native/core/FftEngine.cc",
|
|
16
|
+
"src/native/core/MovingFftFilter.cc",
|
|
17
|
+
"src/native/core/FirFilter.cc",
|
|
18
|
+
"src/native/core/IirFilter.cc",
|
|
19
|
+
"src/native/FftBindings.cc",
|
|
20
|
+
"src/native/FilterBindings.cc",
|
|
21
|
+
"src/native/utils/CircularBufferArray.cc",
|
|
22
|
+
"src/native/utils/CircularBufferVector.cc",
|
|
23
|
+
"src/native/utils/NapiUtils.cc",
|
|
24
|
+
"src/native/utils/SlidingWindowFilter.cc",
|
|
25
|
+
"src/native/utils/TimeSeriesBuffer.cc"
|
|
26
|
+
],
|
|
27
|
+
"include_dirs": [
|
|
28
|
+
"<!@(node -p \"require('node-addon-api').include\")",
|
|
29
|
+
"src/native",
|
|
30
|
+
"src/native/core",
|
|
31
|
+
"src/native/utils",
|
|
32
|
+
"src/native/adapters",
|
|
33
|
+
"src/native/emg"
|
|
34
|
+
],
|
|
35
|
+
"defines": [
|
|
36
|
+
"NAPI_VERSION=8"
|
|
37
|
+
],
|
|
38
|
+
"cflags!": [ "-fno-exceptions" ],
|
|
39
|
+
"cflags_cc!": [ "-fno-exceptions" ],
|
|
40
|
+
"cflags": [ "-O3", "-ffast-math" ],
|
|
41
|
+
"cflags_cc": [ "-std=c++17", "-O3", "-ffast-math" ],
|
|
42
|
+
"msvs_settings": {
|
|
43
|
+
"VCCLCompilerTool": {
|
|
44
|
+
"ExceptionHandling": 1,
|
|
45
|
+
"AdditionalOptions": [ "/std:c++17", "/O2", "/fp:fast", "/arch:AVX2" ],
|
|
46
|
+
"Optimization": 3,
|
|
47
|
+
"FavorSizeOrSpeed": 1,
|
|
48
|
+
"InlineFunctionExpansion": 2
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"xcode_settings": {
|
|
52
|
+
"GCC_ENABLE_CPP_EXCEPTIONS": "YES",
|
|
53
|
+
"CLANG_CXX_LIBRARY": "libc++",
|
|
54
|
+
"MACOSX_DEPLOYMENT_TARGET": "10.15",
|
|
55
|
+
"OTHER_CPLUSPLUSFLAGS": [ "-std=c++17", "-stdlib=libc++", "-O3", "-ffast-math" ],
|
|
56
|
+
"GCC_OPTIMIZATION_LEVEL": "3"
|
|
57
|
+
},
|
|
58
|
+
"conditions": [
|
|
59
|
+
["OS=='win'", {
|
|
60
|
+
"defines": [ "_HAS_EXCEPTIONS=1" ]
|
|
61
|
+
}]
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
}
|