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.
Files changed (172) hide show
  1. package/.github/workflows/ci.yml +185 -0
  2. package/.vscode/c_cpp_properties.json +17 -0
  3. package/.vscode/settings.json +68 -0
  4. package/.vscode/tasks.json +28 -0
  5. package/DISCLAIMER.md +32 -0
  6. package/LICENSE +21 -0
  7. package/README.md +1803 -0
  8. package/ROADMAP.md +192 -0
  9. package/TECHNICAL_DEBT.md +165 -0
  10. package/binding.gyp +65 -0
  11. package/docs/ADVANCED_LOGGER_FEATURES.md +598 -0
  12. package/docs/AUTHENTICATION_SECURITY.md +396 -0
  13. package/docs/BACKEND_IMPROVEMENTS.md +399 -0
  14. package/docs/CHEBYSHEV_BIQUAD_EQ_IMPLEMENTATION.md +405 -0
  15. package/docs/FFT_IMPLEMENTATION.md +490 -0
  16. package/docs/FFT_IMPROVEMENTS_SUMMARY.md +387 -0
  17. package/docs/FFT_USER_GUIDE.md +494 -0
  18. package/docs/FILTERS_IMPLEMENTATION.md +260 -0
  19. package/docs/FILTER_API_GUIDE.md +418 -0
  20. package/docs/FIR_SIMD_OPTIMIZATION.md +175 -0
  21. package/docs/LOGGER_API_REFERENCE.md +350 -0
  22. package/docs/NOTCH_FILTER_QUICK_REF.md +121 -0
  23. package/docs/PHASE2_TESTS_AND_NOTCH_FILTER.md +341 -0
  24. package/docs/PHASES_5_7_SUMMARY.md +403 -0
  25. package/docs/PIPELINE_FILTER_INTEGRATION.md +446 -0
  26. package/docs/SIMD_OPTIMIZATIONS.md +211 -0
  27. package/docs/TEST_MIGRATION_SUMMARY.md +173 -0
  28. package/docs/TIMESERIES_IMPLEMENTATION_SUMMARY.md +322 -0
  29. package/docs/TIMESERIES_QUICK_REF.md +85 -0
  30. package/docs/advanced.md +559 -0
  31. package/docs/time-series-guide.md +617 -0
  32. package/docs/time-series-migration.md +376 -0
  33. package/jest.config.js +37 -0
  34. package/package.json +42 -0
  35. package/prebuilds/linux-x64/dsp-ts-redis.node +0 -0
  36. package/prebuilds/win32-x64/dsp-ts-redis.node +0 -0
  37. package/scripts/test.js +24 -0
  38. package/src/build/dsp-ts-redis.node +0 -0
  39. package/src/native/DspPipeline.cc +675 -0
  40. package/src/native/DspPipeline.h +44 -0
  41. package/src/native/FftBindings.cc +817 -0
  42. package/src/native/FilterBindings.cc +1001 -0
  43. package/src/native/IDspStage.h +53 -0
  44. package/src/native/adapters/InterpolatorStage.h +201 -0
  45. package/src/native/adapters/MeanAbsoluteValueStage.h +289 -0
  46. package/src/native/adapters/MovingAverageStage.h +306 -0
  47. package/src/native/adapters/RectifyStage.h +88 -0
  48. package/src/native/adapters/ResamplerStage.h +238 -0
  49. package/src/native/adapters/RmsStage.h +299 -0
  50. package/src/native/adapters/SscStage.h +121 -0
  51. package/src/native/adapters/VarianceStage.h +307 -0
  52. package/src/native/adapters/WampStage.h +114 -0
  53. package/src/native/adapters/WaveformLengthStage.h +115 -0
  54. package/src/native/adapters/ZScoreNormalizeStage.h +326 -0
  55. package/src/native/core/FftEngine.cc +441 -0
  56. package/src/native/core/FftEngine.h +224 -0
  57. package/src/native/core/FirFilter.cc +324 -0
  58. package/src/native/core/FirFilter.h +149 -0
  59. package/src/native/core/IirFilter.cc +576 -0
  60. package/src/native/core/IirFilter.h +210 -0
  61. package/src/native/core/MovingAbsoluteValueFilter.cc +17 -0
  62. package/src/native/core/MovingAbsoluteValueFilter.h +135 -0
  63. package/src/native/core/MovingAverageFilter.cc +18 -0
  64. package/src/native/core/MovingAverageFilter.h +135 -0
  65. package/src/native/core/MovingFftFilter.cc +291 -0
  66. package/src/native/core/MovingFftFilter.h +203 -0
  67. package/src/native/core/MovingVarianceFilter.cc +194 -0
  68. package/src/native/core/MovingVarianceFilter.h +114 -0
  69. package/src/native/core/MovingZScoreFilter.cc +215 -0
  70. package/src/native/core/MovingZScoreFilter.h +113 -0
  71. package/src/native/core/Policies.h +352 -0
  72. package/src/native/core/RmsFilter.cc +18 -0
  73. package/src/native/core/RmsFilter.h +131 -0
  74. package/src/native/core/SscFilter.cc +16 -0
  75. package/src/native/core/SscFilter.h +137 -0
  76. package/src/native/core/WampFilter.cc +16 -0
  77. package/src/native/core/WampFilter.h +101 -0
  78. package/src/native/core/WaveformLengthFilter.cc +17 -0
  79. package/src/native/core/WaveformLengthFilter.h +98 -0
  80. package/src/native/utils/CircularBufferArray.cc +336 -0
  81. package/src/native/utils/CircularBufferArray.h +62 -0
  82. package/src/native/utils/CircularBufferVector.cc +145 -0
  83. package/src/native/utils/CircularBufferVector.h +45 -0
  84. package/src/native/utils/NapiUtils.cc +53 -0
  85. package/src/native/utils/NapiUtils.h +21 -0
  86. package/src/native/utils/SimdOps.h +870 -0
  87. package/src/native/utils/SlidingWindowFilter.cc +239 -0
  88. package/src/native/utils/SlidingWindowFilter.h +159 -0
  89. package/src/native/utils/TimeSeriesBuffer.cc +205 -0
  90. package/src/native/utils/TimeSeriesBuffer.h +140 -0
  91. package/src/ts/CircularLogBuffer.ts +87 -0
  92. package/src/ts/DriftDetector.ts +331 -0
  93. package/src/ts/TopicRouter.ts +428 -0
  94. package/src/ts/__tests__/AdvancedDsp.test.ts +585 -0
  95. package/src/ts/__tests__/AuthAndEdgeCases.test.ts +241 -0
  96. package/src/ts/__tests__/Chaining.test.ts +387 -0
  97. package/src/ts/__tests__/ChebyshevBiquad.test.ts +229 -0
  98. package/src/ts/__tests__/CircularLogBuffer.test.ts +158 -0
  99. package/src/ts/__tests__/DriftDetector.test.ts +389 -0
  100. package/src/ts/__tests__/Fft.test.ts +484 -0
  101. package/src/ts/__tests__/ListState.test.ts +153 -0
  102. package/src/ts/__tests__/Logger.test.ts +208 -0
  103. package/src/ts/__tests__/LoggerAdvanced.test.ts +319 -0
  104. package/src/ts/__tests__/LoggerMinor.test.ts +247 -0
  105. package/src/ts/__tests__/MeanAbsoluteValue.test.ts +398 -0
  106. package/src/ts/__tests__/MovingAverage.test.ts +322 -0
  107. package/src/ts/__tests__/RMS.test.ts +315 -0
  108. package/src/ts/__tests__/Rectify.test.ts +272 -0
  109. package/src/ts/__tests__/Redis.test.ts +456 -0
  110. package/src/ts/__tests__/SlopeSignChange.test.ts +166 -0
  111. package/src/ts/__tests__/Tap.test.ts +164 -0
  112. package/src/ts/__tests__/TimeBasedExpiration.test.ts +124 -0
  113. package/src/ts/__tests__/TimeBasedRmsAndMav.test.ts +231 -0
  114. package/src/ts/__tests__/TimeBasedVarianceAndZScore.test.ts +284 -0
  115. package/src/ts/__tests__/TimeSeries.test.ts +254 -0
  116. package/src/ts/__tests__/TopicRouter.test.ts +332 -0
  117. package/src/ts/__tests__/TopicRouterAdvanced.test.ts +483 -0
  118. package/src/ts/__tests__/TopicRouterPriority.test.ts +487 -0
  119. package/src/ts/__tests__/Variance.test.ts +509 -0
  120. package/src/ts/__tests__/WaveformLength.test.ts +147 -0
  121. package/src/ts/__tests__/WillisonAmplitude.test.ts +197 -0
  122. package/src/ts/__tests__/ZScoreNormalize.test.ts +459 -0
  123. package/src/ts/advanced-dsp.ts +566 -0
  124. package/src/ts/backends.ts +1137 -0
  125. package/src/ts/bindings.ts +1225 -0
  126. package/src/ts/easter-egg.ts +42 -0
  127. package/src/ts/examples/MeanAbsoluteValue/test-state.ts +99 -0
  128. package/src/ts/examples/MeanAbsoluteValue/test-streaming.ts +269 -0
  129. package/src/ts/examples/MovingAverage/test-state.ts +85 -0
  130. package/src/ts/examples/MovingAverage/test-streaming.ts +188 -0
  131. package/src/ts/examples/RMS/test-state.ts +97 -0
  132. package/src/ts/examples/RMS/test-streaming.ts +253 -0
  133. package/src/ts/examples/Rectify/test-state.ts +107 -0
  134. package/src/ts/examples/Rectify/test-streaming.ts +242 -0
  135. package/src/ts/examples/Variance/test-state.ts +195 -0
  136. package/src/ts/examples/Variance/test-streaming.ts +260 -0
  137. package/src/ts/examples/ZScoreNormalize/test-state.ts +277 -0
  138. package/src/ts/examples/ZScoreNormalize/test-streaming.ts +306 -0
  139. package/src/ts/examples/advanced-dsp-examples.ts +397 -0
  140. package/src/ts/examples/callbacks/advanced-router-features.ts +326 -0
  141. package/src/ts/examples/callbacks/benchmark-circular-buffer.ts +109 -0
  142. package/src/ts/examples/callbacks/monitoring-example.ts +265 -0
  143. package/src/ts/examples/callbacks/pipeline-callbacks-example.ts +137 -0
  144. package/src/ts/examples/callbacks/pooled-callbacks-example.ts +274 -0
  145. package/src/ts/examples/callbacks/priority-routing-example.ts +277 -0
  146. package/src/ts/examples/callbacks/production-topic-router.ts +214 -0
  147. package/src/ts/examples/callbacks/topic-based-logging.ts +161 -0
  148. package/src/ts/examples/chaining/test-chaining-redis.ts +113 -0
  149. package/src/ts/examples/chaining/test-chaining.ts +52 -0
  150. package/src/ts/examples/emg-features-example.ts +284 -0
  151. package/src/ts/examples/fft-example.ts +309 -0
  152. package/src/ts/examples/fft-examples.ts +349 -0
  153. package/src/ts/examples/filter-examples.ts +320 -0
  154. package/src/ts/examples/list-state-example.ts +131 -0
  155. package/src/ts/examples/logger-example.ts +91 -0
  156. package/src/ts/examples/notch-filter-examples.ts +243 -0
  157. package/src/ts/examples/phase5/drift-detection-example.ts +290 -0
  158. package/src/ts/examples/phase6-7/production-observability.ts +476 -0
  159. package/src/ts/examples/phase6-7/redis-timeseries-integration.ts +446 -0
  160. package/src/ts/examples/redis/redis-example.ts +202 -0
  161. package/src/ts/examples/redis-example.ts +202 -0
  162. package/src/ts/examples/simd-benchmark.ts +126 -0
  163. package/src/ts/examples/tap-debugging.ts +230 -0
  164. package/src/ts/examples/timeseries/comparison-example.ts +290 -0
  165. package/src/ts/examples/timeseries/iot-sensor-example.ts +143 -0
  166. package/src/ts/examples/timeseries/redis-streaming-example.ts +233 -0
  167. package/src/ts/examples/waveform-length-example.ts +139 -0
  168. package/src/ts/fft.ts +722 -0
  169. package/src/ts/filters.ts +1078 -0
  170. package/src/ts/index.ts +120 -0
  171. package/src/ts/types.ts +589 -0
  172. package/tsconfig.json +15 -0
@@ -0,0 +1,290 @@
1
+ /**
2
+ * Phase 5: Drift Detection Example
3
+ *
4
+ * Demonstrates how to monitor timing drift in real-time data streams.
5
+ * Essential for production EMG/biosignal applications where timing accuracy matters.
6
+ */
7
+
8
+ import {
9
+ createDspPipeline,
10
+ DriftDetector,
11
+ detectGaps,
12
+ validateMonotonicity,
13
+ estimateSampleRate,
14
+ type DriftStatistics,
15
+ } from "../../index.js";
16
+
17
+ console.log("=== Phase 5: Drift Detection Example ===\n");
18
+
19
+ // Simulate realistic EMG data with timing issues
20
+ function generateEMGDataWithDrift() {
21
+ const samples: number[] = [];
22
+ const timestamps: number[] = [];
23
+
24
+ const nominalRate = 1000; // 1000 Hz target
25
+ const nominalInterval = 1000 / nominalRate; // 1ms
26
+
27
+ let currentTime = Date.now();
28
+
29
+ for (let i = 0; i < 1000; i++) {
30
+ // Simulate EMG signal (muscle activation)
31
+ const signal = Math.sin(i * 0.05) * 100 + Math.random() * 20;
32
+ samples.push(signal);
33
+ timestamps.push(currentTime);
34
+
35
+ // Simulate various timing issues
36
+ if (i % 100 === 0) {
37
+ // Every 100 samples: larger drift (BLE packet delay)
38
+ currentTime += nominalInterval + Math.random() * 5; // +0-5ms drift
39
+ } else if (i % 50 === 0) {
40
+ // Every 50 samples: minor jitter
41
+ currentTime += nominalInterval + (Math.random() - 0.5) * 2; // ±1ms jitter
42
+ } else {
43
+ // Normal sampling
44
+ currentTime += nominalInterval;
45
+ }
46
+ }
47
+
48
+ return {
49
+ samples: new Float32Array(samples),
50
+ timestamps: new Float32Array(timestamps),
51
+ };
52
+ }
53
+
54
+ // Example 1: Basic Drift Detection
55
+ async function example1_BasicDriftDetection() {
56
+ console.log("\n--- Example 1: Basic Drift Detection ---\n");
57
+
58
+ const { samples, timestamps } = generateEMGDataWithDrift();
59
+
60
+ let driftCount = 0;
61
+
62
+ const pipeline = createDspPipeline();
63
+ pipeline.MovingAverage({ mode: "moving", windowDuration: 100 }); // 100ms window
64
+
65
+ await pipeline.process(samples, timestamps, {
66
+ channels: 1,
67
+ sampleRate: 1000,
68
+ enableDriftDetection: true,
69
+ driftThreshold: 5, // 5% threshold
70
+ onDriftDetected: (stats) => {
71
+ driftCount++;
72
+ if (driftCount <= 5) {
73
+ // Only show first 5
74
+ console.log(`āš ļø Drift detected at sample ${stats.sampleIndex}:`);
75
+ console.log(` Expected interval: ${stats.expectedMs.toFixed(3)}ms`);
76
+ console.log(` Actual interval: ${stats.deltaMs.toFixed(3)}ms`);
77
+ console.log(
78
+ ` Drift: ${stats.absoluteDrift.toFixed(
79
+ 3
80
+ )}ms (${stats.relativeDrift.toFixed(1)}%)\n`
81
+ );
82
+ }
83
+ },
84
+ });
85
+
86
+ console.log(`Total drift events detected: ${driftCount}\n`);
87
+ }
88
+
89
+ // Example 2: Comprehensive Timing Analysis
90
+ async function example2_ComprehensiveAnalysis() {
91
+ console.log("\n--- Example 2: Comprehensive Timing Analysis ---\n");
92
+
93
+ const { samples, timestamps } = generateEMGDataWithDrift();
94
+
95
+ // 1. Estimate sample rate
96
+ const rateEstimate = estimateSampleRate(timestamps);
97
+ console.log("šŸ“Š Sample Rate Estimation:");
98
+ console.log(
99
+ ` Estimated rate: ${rateEstimate.estimatedRate.toFixed(2)} Hz`
100
+ );
101
+ console.log(
102
+ ` Average interval: ${rateEstimate.averageInterval.toFixed(3)} ms`
103
+ );
104
+ console.log(
105
+ ` Std deviation: ${rateEstimate.stdDevInterval.toFixed(3)} ms`
106
+ );
107
+ console.log(
108
+ ` Coefficient of var: ${(
109
+ rateEstimate.coefficientOfVariation * 100
110
+ ).toFixed(2)}%`
111
+ );
112
+ console.log(` Regularity: ${rateEstimate.regularity}\n`);
113
+
114
+ // 2. Detect gaps (missing samples)
115
+ const gaps = detectGaps(timestamps, 1000, 2.0); // 2x expected interval
116
+ console.log(`šŸ•³ļø Gap Detection:`);
117
+ console.log(` Gaps found: ${gaps.length}`);
118
+ if (gaps.length > 0) {
119
+ gaps.slice(0, 3).forEach((gap, idx) => {
120
+ console.log(
121
+ ` Gap ${idx + 1}: ${gap.durationMs.toFixed(1)}ms (${
122
+ gap.expectedSamples
123
+ } samples missing)`
124
+ );
125
+ });
126
+ }
127
+ console.log();
128
+
129
+ // 3. Validate monotonicity
130
+ const violations = validateMonotonicity(timestamps);
131
+ console.log(`āœ“ Monotonicity Check:`);
132
+ if (violations.length === 0) {
133
+ console.log(` āœ… All timestamps are monotonically increasing`);
134
+ } else {
135
+ console.log(` āŒ ${violations.length} violations found:`);
136
+ violations.slice(0, 3).forEach((v) => {
137
+ console.log(
138
+ ` - Sample ${v.index}: ${v.violation} (${v.currentTimestamp} vs ${v.previousTimestamp})`
139
+ );
140
+ });
141
+ }
142
+ console.log();
143
+
144
+ // 4. Track metrics over time
145
+ const detector = new DriftDetector({
146
+ expectedSampleRate: 1000,
147
+ driftThreshold: 5,
148
+ });
149
+
150
+ detector.processBatch(timestamps);
151
+ const metrics = detector.getMetrics();
152
+
153
+ console.log(`šŸ“ˆ Timing Metrics (${metrics.samplesProcessed} samples):`);
154
+ console.log(` Min interval: ${metrics.minDelta.toFixed(3)} ms`);
155
+ console.log(` Max interval: ${metrics.maxDelta.toFixed(3)} ms`);
156
+ console.log(` Average interval: ${metrics.averageDelta.toFixed(3)} ms`);
157
+ console.log(` Std deviation: ${metrics.stdDevDelta.toFixed(3)} ms`);
158
+ console.log(` Drift events: ${metrics.driftEventsCount}`);
159
+ console.log(
160
+ ` Max drift observed: ${metrics.maxDriftObserved.toFixed(3)} ms\n`
161
+ );
162
+ }
163
+
164
+ // Example 3: Production Monitoring Setup
165
+ async function example3_ProductionMonitoring() {
166
+ console.log("\n--- Example 3: Production Monitoring Setup ---\n");
167
+
168
+ const { samples, timestamps } = generateEMGDataWithDrift();
169
+
170
+ // Simulated metrics backend (Prometheus, Datadog, etc.)
171
+ const metrics = {
172
+ driftEvents: 0,
173
+ maxDrift: 0,
174
+ avgInterval: 0,
175
+ violations: [] as string[],
176
+ };
177
+
178
+ const pipeline = createDspPipeline();
179
+ pipeline
180
+ .MovingAverage({ mode: "moving", windowDuration: 100 })
181
+ .Rms({ mode: "moving", windowDuration: 50 });
182
+
183
+ await pipeline.process(samples, timestamps, {
184
+ channels: 1,
185
+ sampleRate: 1000,
186
+ enableDriftDetection: true,
187
+ driftThreshold: 10, // 10% for alerting
188
+ onDriftDetected: (stats) => {
189
+ metrics.driftEvents++;
190
+ metrics.maxDrift = Math.max(metrics.maxDrift, stats.absoluteDrift);
191
+
192
+ // Alert if drift is severe (>20%)
193
+ if (stats.relativeDrift > 20) {
194
+ metrics.violations.push(
195
+ `CRITICAL: ${stats.relativeDrift.toFixed(1)}% drift at sample ${
196
+ stats.sampleIndex
197
+ }`
198
+ );
199
+
200
+ // In production, send to PagerDuty/Slack/etc.
201
+ console.log(`🚨 ALERT: Severe timing drift detected!`);
202
+ console.log(` Drift: ${stats.relativeDrift.toFixed(1)}%`);
203
+ console.log(` Sample: ${stats.sampleIndex}`);
204
+ console.log(` Consider checking BLE connection or sensor battery\n`);
205
+ }
206
+ },
207
+ });
208
+
209
+ // Report metrics
210
+ console.log("šŸ“Š Production Metrics:");
211
+ console.log(` Total drift events: ${metrics.driftEvents}`);
212
+ console.log(` Max drift observed: ${metrics.maxDrift.toFixed(3)} ms`);
213
+ console.log(` Critical violations: ${metrics.violations.length}`);
214
+
215
+ if (metrics.violations.length > 0) {
216
+ console.log("\n Critical violations:");
217
+ metrics.violations.forEach((v) => console.log(` - ${v}`));
218
+ }
219
+ console.log();
220
+ }
221
+
222
+ // Example 4: Real-Time Drift Dashboard
223
+ async function example4_RealTimeDashboard() {
224
+ console.log("\n--- Example 4: Real-Time Drift Dashboard ---\n");
225
+
226
+ const { samples, timestamps } = generateEMGDataWithDrift();
227
+
228
+ // Simulate streaming data in chunks
229
+ const chunkSize = 100;
230
+ const detector = new DriftDetector({
231
+ expectedSampleRate: 1000,
232
+ driftThreshold: 5,
233
+ });
234
+
235
+ console.log("Streaming EMG data (simulated)...\n");
236
+ console.log("Chunk | Samples | Drift Events | Avg Interval | Status");
237
+ console.log("------|---------|--------------|--------------|--------");
238
+
239
+ for (let i = 0; i < samples.length; i += chunkSize) {
240
+ const chunkEnd = Math.min(i + chunkSize, samples.length);
241
+ const chunkTimestamps = timestamps.slice(i, chunkEnd);
242
+
243
+ const beforeMetrics = detector.getMetrics();
244
+ detector.processBatch(chunkTimestamps);
245
+ const afterMetrics = detector.getMetrics();
246
+
247
+ const chunkDriftEvents =
248
+ afterMetrics.driftEventsCount - beforeMetrics.driftEventsCount;
249
+ const avgInterval = afterMetrics.averageDelta;
250
+ const status = chunkDriftEvents > 5 ? "āš ļø HIGH" : "āœ… OK";
251
+
252
+ console.log(
253
+ ` ${Math.floor(i / chunkSize)
254
+ .toString()
255
+ .padStart(3)} | ` +
256
+ `${chunkSize.toString().padStart(7)} | ` +
257
+ `${chunkDriftEvents.toString().padStart(12)} | ` +
258
+ `${avgInterval.toFixed(3).padStart(12)} ms | ` +
259
+ `${status}`
260
+ );
261
+ }
262
+
263
+ const finalMetrics = detector.getMetrics();
264
+ console.log("\nšŸ“Š Final Statistics:");
265
+ console.log(` Total samples: ${finalMetrics.samplesProcessed}`);
266
+ console.log(` Total drift events: ${finalMetrics.driftEventsCount}`);
267
+ console.log(
268
+ ` Drift rate: ${(
269
+ (finalMetrics.driftEventsCount / finalMetrics.samplesProcessed) *
270
+ 100
271
+ ).toFixed(2)}%\n`
272
+ );
273
+ }
274
+
275
+ // Run all examples
276
+ async function main() {
277
+ await example1_BasicDriftDetection();
278
+ await example2_ComprehensiveAnalysis();
279
+ await example3_ProductionMonitoring();
280
+ await example4_RealTimeDashboard();
281
+
282
+ console.log("=== Phase 5 Complete ===\n");
283
+ console.log("āœ… Drift detection helps you:");
284
+ console.log(" • Debug BLE/IoT timing issues");
285
+ console.log(" • Monitor data quality in production");
286
+ console.log(" • Detect hardware problems early");
287
+ console.log(" • Ensure accurate EMG/biosignal processing\n");
288
+ }
289
+
290
+ main().catch(console.error);