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,277 @@
1
+ import { createDspPipeline } from "../../bindings.js";
2
+
3
+ console.log("Z-Score Normalize Filter - State Management Examples\n");
4
+
5
+ // =============================================================================
6
+ // Example 1: Batch Z-Score Normalization (Stateless)
7
+ // =============================================================================
8
+ console.log("1. Batch Z-Score Normalization (Stateless)");
9
+
10
+ const pipeline1 = createDspPipeline();
11
+ pipeline1.ZScoreNormalize({ mode: "batch" });
12
+
13
+ const input1 = new Float32Array([10, 20, 30, 40, 50]);
14
+ const output1 = await pipeline1.process(input1, {
15
+ sampleRate: 1000,
16
+ channels: 1,
17
+ });
18
+
19
+ console.log(` Input: [${input1.join(", ")}]`);
20
+ console.log(` Mean: 30, Std Dev: ~14.14`);
21
+ console.log(
22
+ ` Output (normalized): [${Array.from(output1)
23
+ .map((v) => v.toFixed(3))
24
+ .join(", ")}]`
25
+ );
26
+ console.log(
27
+ ` Mean after normalization: ${(
28
+ output1.reduce((s, v) => s + v, 0) / output1.length
29
+ ).toFixed(6)}`
30
+ );
31
+ console.log(
32
+ ` Variance after normalization: ${(
33
+ output1.reduce((s, v) => s + v * v, 0) / output1.length
34
+ ).toFixed(6)}`
35
+ );
36
+ console.log("");
37
+
38
+ // =============================================================================
39
+ // Example 2: Moving Z-Score Normalization (Stateful)
40
+ // =============================================================================
41
+ console.log("2. Moving Z-Score Normalization (Stateful)");
42
+
43
+ const pipeline2 = createDspPipeline();
44
+ pipeline2.ZScoreNormalize({ mode: "moving", windowSize: 3 });
45
+
46
+ const input2 = new Float32Array([1, 2, 3, 4, 5]);
47
+ const output2 = await pipeline2.process(input2, {
48
+ sampleRate: 1000,
49
+ channels: 1,
50
+ });
51
+
52
+ console.log(` Input: [${input2.join(", ")}]`);
53
+ console.log(` Output (sliding window):`);
54
+ console.log(` [1] -> z-score: ${output2[0].toFixed(3)} (mean=1, stddev=0)`);
55
+ console.log(
56
+ ` [1,2] -> z-score: ${output2[1].toFixed(3)} (mean=1.5, stddev=0.5)`
57
+ );
58
+ console.log(
59
+ ` [1,2,3] -> z-score: ${output2[2].toFixed(3)} (mean=2, stddev≈0.816)`
60
+ );
61
+ console.log(
62
+ ` [2,3,4] -> z-score: ${output2[3].toFixed(3)} (mean=3, stddev≈0.816)`
63
+ );
64
+ console.log(
65
+ ` [3,4,5] -> z-score: ${output2[4].toFixed(3)} (mean=4, stddev≈0.816)`
66
+ );
67
+ console.log("");
68
+
69
+ // =============================================================================
70
+ // Example 3: Save and Restore State
71
+ // =============================================================================
72
+ console.log("3. Save and Restore State");
73
+
74
+ const pipeline3 = createDspPipeline();
75
+ pipeline3.ZScoreNormalize({ mode: "moving", windowSize: 5 });
76
+
77
+ // Build up state
78
+ const initialData = new Float32Array([10, 15, 20, 25, 30]);
79
+ await pipeline3.process(initialData, { sampleRate: 1000, channels: 1 });
80
+
81
+ // Save state
82
+ const stateJson = await pipeline3.saveState();
83
+ const state = JSON.parse(stateJson);
84
+
85
+ console.log(` Saved state:`);
86
+ console.log(` Mode: ${state.stages[0].state.mode}`);
87
+ console.log(` Window size: ${state.stages[0].state.windowSize}`);
88
+ console.log(
89
+ ` Buffer: [${state.stages[0].state.channels[0].buffer.join(", ")}]`
90
+ );
91
+ console.log(` Running sum: ${state.stages[0].state.channels[0].runningSum}`);
92
+ console.log(
93
+ ` Running sum of squares: ${state.stages[0].state.channels[0].runningSumOfSquares}`
94
+ );
95
+
96
+ // Restore state in a new pipeline
97
+ const pipeline3b = createDspPipeline();
98
+ pipeline3b.ZScoreNormalize({ mode: "moving", windowSize: 5 });
99
+ await pipeline3b.loadState(stateJson);
100
+
101
+ console.log(` State restored!`);
102
+
103
+ // Continue processing with restored state
104
+ const continuedData = new Float32Array([35, 40, 45]);
105
+ const continuedOutput = await pipeline3b.process(continuedData, {
106
+ sampleRate: 1000,
107
+ channels: 1,
108
+ });
109
+
110
+ console.log(` Continued with [${continuedData.join(", ")}]`);
111
+ console.log(
112
+ ` Output: [${Array.from(continuedOutput)
113
+ .map((v) => v.toFixed(3))
114
+ .join(", ")}]`
115
+ );
116
+ console.log("");
117
+
118
+ // =============================================================================
119
+ // Example 4: Clear State (Reset)
120
+ // =============================================================================
121
+ console.log("4. Clear State (Reset)");
122
+
123
+ const pipeline4 = createDspPipeline();
124
+ pipeline4.ZScoreNormalize({ mode: "moving", windowSize: 3 });
125
+
126
+ // Process some data
127
+ await pipeline4.process(new Float32Array([100, 200, 300]), {
128
+ sampleRate: 1000,
129
+ channels: 1,
130
+ });
131
+
132
+ // Clear state
133
+ pipeline4.clearState();
134
+ console.log(` State cleared!`);
135
+
136
+ // Process new data (should start fresh)
137
+ const resetInput = new Float32Array([1, 2, 3]);
138
+ const resetOutput = await pipeline4.process(resetInput, {
139
+ sampleRate: 1000,
140
+ channels: 1,
141
+ });
142
+
143
+ console.log(` After reset, input [${resetInput.join(", ")}]:`);
144
+ console.log(
145
+ ` Output: [${Array.from(resetOutput)
146
+ .map((v) => v.toFixed(3))
147
+ .join(", ")}]`
148
+ );
149
+ console.log(` (Same as if processing first time)`);
150
+ console.log("");
151
+
152
+ // =============================================================================
153
+ // Example 5: Batch vs Moving Comparison
154
+ // =============================================================================
155
+ console.log("5. Batch vs Moving Comparison");
156
+
157
+ const inputData = new Float32Array([10, 20, 30, 40, 50]);
158
+
159
+ // Batch mode
160
+ const batchPipeline = createDspPipeline();
161
+ batchPipeline.ZScoreNormalize({ mode: "batch" });
162
+ const batchOutput = await batchPipeline.process(inputData.slice(), {
163
+ sampleRate: 1000,
164
+ channels: 1,
165
+ });
166
+
167
+ // Moving mode
168
+ const movingPipeline = createDspPipeline();
169
+ movingPipeline.ZScoreNormalize({ mode: "moving", windowSize: 5 });
170
+ const movingOutput = await movingPipeline.process(inputData.slice(), {
171
+ sampleRate: 1000,
172
+ channels: 1,
173
+ });
174
+
175
+ console.log(` Input: [${inputData.join(", ")}]`);
176
+ console.log(
177
+ ` Batch (global normalization): [${Array.from(batchOutput)
178
+ .map((v) => v.toFixed(3))
179
+ .join(", ")}]`
180
+ );
181
+ console.log(
182
+ ` Moving (evolving window): [${Array.from(movingOutput)
183
+ .map((v) => v.toFixed(3))
184
+ .join(", ")}]`
185
+ );
186
+ console.log("");
187
+ console.log(` Batch: All samples normalized using entire dataset statistics`);
188
+ console.log(` Moving: Each sample normalized using local window statistics`);
189
+ console.log("");
190
+
191
+ // =============================================================================
192
+ // Example 6: Multi-Channel State Management
193
+ // =============================================================================
194
+ console.log("6. Multi-Channel State Management");
195
+
196
+ const pipeline6 = createDspPipeline();
197
+ pipeline6.ZScoreNormalize({ mode: "moving", windowSize: 3 });
198
+
199
+ // 2 channels, 5 samples per channel (interleaved)
200
+ // Channel 0: [1, 2, 3, 4, 5]
201
+ // Channel 1: [100, 200, 300, 400, 500]
202
+ const multiChannelInput = new Float32Array([
203
+ 1, 100, 2, 200, 3, 300, 4, 400, 5, 500,
204
+ ]);
205
+
206
+ await pipeline6.process(multiChannelInput, {
207
+ sampleRate: 1000,
208
+ channels: 2,
209
+ });
210
+
211
+ const state6 = JSON.parse(await pipeline6.saveState());
212
+
213
+ console.log(` 2-channel processing:`);
214
+ console.log(
215
+ ` Channel 0 buffer: [${state6.stages[0].state.channels[0].buffer.join(
216
+ ", "
217
+ )}]`
218
+ );
219
+ console.log(
220
+ ` Channel 1 buffer: [${state6.stages[0].state.channels[1].buffer.join(
221
+ ", "
222
+ )}]`
223
+ );
224
+ console.log(` (Each channel maintains independent state)`);
225
+ console.log("");
226
+
227
+ // =============================================================================
228
+ // Example 7: Custom Epsilon for Near-Constant Signals
229
+ // =============================================================================
230
+ console.log("7. Custom Epsilon for Near-Constant Signals");
231
+
232
+ const pipeline7a = createDspPipeline();
233
+ pipeline7a.ZScoreNormalize({ mode: "batch", epsilon: 1e-6 }); // Default
234
+
235
+ const pipeline7b = createDspPipeline();
236
+ pipeline7b.ZScoreNormalize({ mode: "batch", epsilon: 0.1 }); // Larger epsilon
237
+
238
+ // Nearly constant signal
239
+ const nearConstant = new Float32Array([5.0, 5.001, 4.999, 5.0, 5.001]);
240
+
241
+ const output7a = await pipeline7a.process(nearConstant.slice(), {
242
+ sampleRate: 1000,
243
+ channels: 1,
244
+ });
245
+
246
+ const output7b = await pipeline7b.process(nearConstant.slice(), {
247
+ sampleRate: 1000,
248
+ channels: 1,
249
+ });
250
+
251
+ console.log(` Input (nearly constant): [${nearConstant.join(", ")}]`);
252
+ console.log(
253
+ ` Default epsilon (1e-6): [${Array.from(output7a)
254
+ .map((v) => v.toFixed(3))
255
+ .join(", ")}]`
256
+ );
257
+ console.log(
258
+ ` Large epsilon (0.1): [${Array.from(output7b)
259
+ .map((v) => v.toFixed(3))
260
+ .join(", ")}]`
261
+ );
262
+ console.log("");
263
+
264
+ console.log("Key Takeaways:");
265
+ console.log(
266
+ " - Batch mode: Stateless, normalizes using global statistics (mean=0, stddev=1)"
267
+ );
268
+ console.log(
269
+ " - Moving mode: Stateful, normalizes using local window statistics"
270
+ );
271
+ console.log(
272
+ " - State includes: circular buffer, running sum, running sum of squares"
273
+ );
274
+ console.log(
275
+ " - Each channel has independent state for multi-channel processing"
276
+ );
277
+ console.log(" - Epsilon prevents division by zero when stddev is near 0");
@@ -0,0 +1,306 @@
1
+ import { createDspPipeline } from "../../bindings.js";
2
+
3
+ console.log("Z-Score Normalize Filter - Streaming Examples\n");
4
+
5
+ // =============================================================================
6
+ // Example 1: Batch Normalization for Data Preprocessing
7
+ // =============================================================================
8
+ console.log("1. Batch Normalization for Data Preprocessing");
9
+
10
+ const pipeline1 = createDspPipeline();
11
+ pipeline1.ZScoreNormalize({ mode: "batch" });
12
+
13
+ // Simulate processing chunks of sensor data before machine learning
14
+ const chunks = [
15
+ new Float32Array([23.5, 24.1, 23.8, 24.3, 23.9]), // Temperature readings (°C)
16
+ new Float32Array([100, 102, 98, 101, 99]), // Pressure readings (kPa)
17
+ new Float32Array([5.2, 5.5, 5.1, 5.4, 5.3]), // Flow rate (L/min)
18
+ ];
19
+
20
+ console.log(" Normalizing sensor data chunks for ML preprocessing:");
21
+ for (let i = 0; i < chunks.length; i++) {
22
+ const output = await pipeline1.process(chunks[i].slice(), {
23
+ sampleRate: 100,
24
+ channels: 1,
25
+ });
26
+ const mean = output.reduce((s, v) => s + v, 0) / output.length;
27
+ const variance = output.reduce((s, v) => s + v * v, 0) / output.length;
28
+ console.log(
29
+ ` Chunk ${i + 1}: mean=${mean.toFixed(6)}, variance=${variance.toFixed(
30
+ 6
31
+ )} → NORMALIZED`
32
+ );
33
+ }
34
+ console.log("");
35
+
36
+ // =============================================================================
37
+ // Example 2: Real-Time Anomaly Detection with Moving Z-Score
38
+ // =============================================================================
39
+ console.log("2. Real-Time Anomaly Detection with Moving Z-Score");
40
+
41
+ const pipeline2 = createDspPipeline();
42
+ pipeline2.ZScoreNormalize({ mode: "moving", windowSize: 50 });
43
+
44
+ // Simulate streaming temperature data with an anomaly
45
+ const normalData = new Float32Array(40)
46
+ .fill(0)
47
+ .map(() => 20 + Math.random() * 2); // Normal: 20-22°C
48
+ const anomalyData = new Float32Array(10).fill(0).map(() => 30 + Math.random()); // Anomaly: 30-31°C
49
+ const recoveryData = new Float32Array(20)
50
+ .fill(0)
51
+ .map(() => 20 + Math.random() * 2); // Back to normal
52
+
53
+ const streamData = new Float32Array([
54
+ ...normalData,
55
+ ...anomalyData,
56
+ ...recoveryData,
57
+ ]);
58
+
59
+ const zScores = await pipeline2.process(streamData, {
60
+ sampleRate: 10,
61
+ channels: 1,
62
+ });
63
+
64
+ let anomalyCount = 0;
65
+ const anomalyThreshold = 3.0; // Standard threshold for outlier detection
66
+
67
+ console.log(" Monitoring temperature stream for anomalies (z-score > 3.0):");
68
+ for (let i = 0; i < zScores.length; i++) {
69
+ if (Math.abs(zScores[i]) > anomalyThreshold) {
70
+ if (anomalyCount === 0) {
71
+ console.log(
72
+ ` 🚨 ANOMALY DETECTED at sample ${i}: z-score = ${zScores[i].toFixed(
73
+ 2
74
+ )}`
75
+ );
76
+ }
77
+ anomalyCount++;
78
+ }
79
+ }
80
+ console.log(` Total anomalies detected: ${anomalyCount}`);
81
+ console.log("");
82
+
83
+ // =============================================================================
84
+ // Example 3: Multi-Channel EEG Signal Normalization
85
+ // =============================================================================
86
+ console.log("3. Multi-Channel EEG Signal Normalization");
87
+
88
+ const pipeline3 = createDspPipeline();
89
+ pipeline3.ZScoreNormalize({ mode: "moving", windowSize: 100 });
90
+
91
+ // Simulate 4 EEG channels with different amplitudes
92
+ const numSamples = 200;
93
+ const numChannels = 4;
94
+ const eegData = new Float32Array(numSamples * numChannels);
95
+
96
+ for (let i = 0; i < numSamples; i++) {
97
+ eegData[i * numChannels + 0] = Math.sin(i * 0.1) * 50; // Channel 0: 50µV amplitude
98
+ eegData[i * numChannels + 1] = Math.sin(i * 0.15) * 100; // Channel 1: 100µV amplitude
99
+ eegData[i * numChannels + 2] = Math.sin(i * 0.2) * 25; // Channel 2: 25µV amplitude
100
+ eegData[i * numChannels + 3] = Math.sin(i * 0.25) * 75; // Channel 3: 75µV amplitude
101
+ }
102
+
103
+ const normalizedEEG = await pipeline3.process(eegData, {
104
+ sampleRate: 256,
105
+ channels: numChannels,
106
+ });
107
+
108
+ // Extract last 20 samples of each channel to check normalization
109
+ const extractChannel = (data: Float32Array, ch: number, numCh: number) => {
110
+ const result = [];
111
+ for (let i = ch; i < data.length; i += numCh) {
112
+ result.push(data[i]);
113
+ }
114
+ return result.slice(-20);
115
+ };
116
+
117
+ console.log(" Normalized EEG channels (last 20 samples):");
118
+ for (let ch = 0; ch < numChannels; ch++) {
119
+ const samples = extractChannel(normalizedEEG, ch, numChannels);
120
+ const mean = samples.reduce((s, v) => s + v, 0) / samples.length;
121
+ const variance = samples.reduce((s, v) => s + v * v, 0) / samples.length;
122
+ console.log(
123
+ ` Channel ${ch}: mean=${mean.toFixed(3)}, variance=${variance.toFixed(
124
+ 3
125
+ )}`
126
+ );
127
+ }
128
+ console.log("");
129
+
130
+ // =============================================================================
131
+ // Example 4: Interrupted Processing with State Recovery
132
+ // =============================================================================
133
+ console.log("4. Interrupted Processing with State Recovery");
134
+
135
+ const pipeline4 = createDspPipeline();
136
+ pipeline4.ZScoreNormalize({ mode: "moving", windowSize: 30 });
137
+
138
+ // Process first chunk
139
+ const chunk1 = new Float32Array(50).fill(0).map(() => 100 + Math.random() * 20);
140
+ await pipeline4.process(chunk1, { sampleRate: 1000, channels: 1 });
141
+
142
+ console.log(" Processing stream...");
143
+
144
+ // Save state (simulating service restart or crash recovery)
145
+ const savedState = await pipeline4.saveState();
146
+ console.log(" State saved (simulating service restart)");
147
+
148
+ // Create new pipeline and restore state
149
+ const pipeline4b = createDspPipeline();
150
+ pipeline4b.ZScoreNormalize({ mode: "moving", windowSize: 30 });
151
+ await pipeline4b.loadState(savedState);
152
+
153
+ console.log(" State restored!");
154
+
155
+ // Continue processing
156
+ const chunk2 = new Float32Array(30).fill(0).map(() => 100 + Math.random() * 20);
157
+ const output = await pipeline4b.process(chunk2, {
158
+ sampleRate: 1000,
159
+ channels: 1,
160
+ });
161
+
162
+ console.log(` Resumed processing: ${output.length} samples processed`);
163
+ console.log(` (Seamless continuation from saved state)`);
164
+ console.log("");
165
+
166
+ // =============================================================================
167
+ // Example 5: Feature Extraction Pipeline (Rectify → Z-Score)
168
+ // =============================================================================
169
+ console.log("5. Feature Extraction Pipeline (Rectify → Z-Score)");
170
+
171
+ const pipeline5 = createDspPipeline();
172
+ pipeline5.Rectify({ mode: "full" }).ZScoreNormalize({
173
+ mode: "moving",
174
+ windowSize: 50,
175
+ });
176
+
177
+ // Generate bipolar signal with noise
178
+ const signalLength = 200;
179
+ const rawSignal = new Float32Array(signalLength);
180
+ for (let i = 0; i < signalLength; i++) {
181
+ rawSignal[i] = Math.sin(i * 0.1) * 10 + (Math.random() - 0.5) * 5;
182
+ }
183
+
184
+ const features = await pipeline5.process(rawSignal, {
185
+ sampleRate: 100,
186
+ channels: 1,
187
+ });
188
+
189
+ // Calculate feature statistics
190
+ const mean = features.reduce((s, v) => s + v, 0) / features.length;
191
+ const variance = features.reduce((s, v) => s + v * v, 0) / features.length;
192
+ const recentMean = features.slice(-20).reduce((s, v) => s + v, 0) / 20;
193
+
194
+ console.log(` Input signal: ${signalLength} samples (bipolar with noise)`);
195
+ console.log(` After Rectify: All positive values`);
196
+ console.log(` After Z-Score: Normalized features`);
197
+ console.log(` Overall mean: ${mean.toFixed(3)}`);
198
+ console.log(` Overall variance: ${variance.toFixed(3)}`);
199
+ console.log(` Recent avg z-score: ${recentMean.toFixed(3)}`);
200
+ console.log(` (Ready for ML feature extraction)`);
201
+ console.log("");
202
+
203
+ // =============================================================================
204
+ // Example 6: Adaptive Threshold Alerting
205
+ // =============================================================================
206
+ console.log("6. Adaptive Threshold Alerting");
207
+
208
+ const pipeline6 = createDspPipeline();
209
+ pipeline6.ZScoreNormalize({ mode: "moving", windowSize: 50 });
210
+
211
+ // Simulate streaming data with gradual drift
212
+ const generateChunk = (baseline: number, drift: number) => {
213
+ return new Float32Array(100)
214
+ .fill(0)
215
+ .map(() => baseline + drift + (Math.random() - 0.5) * 5);
216
+ };
217
+
218
+ const chunks6 = [
219
+ generateChunk(100, 0), // Baseline
220
+ generateChunk(100, 5), // Small drift
221
+ generateChunk(100, 20), // Significant drift
222
+ ];
223
+
224
+ const alertThreshold = 2.5;
225
+
226
+ console.log(` Monitoring for z-score > ${alertThreshold}:`);
227
+ for (let i = 0; i < chunks6.length; i++) {
228
+ const zScores = await pipeline6.process(chunks6[i], {
229
+ sampleRate: 100,
230
+ channels: 1,
231
+ });
232
+
233
+ const alertCount = zScores.filter((z) => Math.abs(z) > alertThreshold).length;
234
+
235
+ if (alertCount > 10) {
236
+ console.log(
237
+ ` Chunk ${i + 1}: 🚨 ALERT - ${alertCount} samples exceeded threshold`
238
+ );
239
+ } else {
240
+ console.log(` Chunk ${i + 1}: ✓ OK - drift within normal range`);
241
+ }
242
+ }
243
+ console.log("");
244
+
245
+ // =============================================================================
246
+ // Example 7: Streaming Data Standardization for Neural Network
247
+ // =============================================================================
248
+ console.log("7. Streaming Data Standardization for Neural Network");
249
+
250
+ const pipeline7 = createDspPipeline();
251
+ pipeline7.ZScoreNormalize({ mode: "moving", windowSize: 100 });
252
+
253
+ // Simulate streaming accelerometer data (3 axes, interleaved)
254
+ const streamLength = 300; // 100 samples per axis
255
+ const accelData = new Float32Array(streamLength);
256
+
257
+ for (let i = 0; i < streamLength / 3; i++) {
258
+ accelData[i * 3 + 0] = Math.sin(i * 0.1) * 2 + 9.8; // X-axis (with gravity)
259
+ accelData[i * 3 + 1] = Math.cos(i * 0.1) * 1.5; // Y-axis
260
+ accelData[i * 3 + 2] = Math.sin(i * 0.15) * 1.0; // Z-axis
261
+ }
262
+
263
+ const normalizedAccel = await pipeline7.process(accelData, {
264
+ sampleRate: 50,
265
+ channels: 3,
266
+ });
267
+
268
+ // Verify normalization for each axis
269
+ const axes = ["X", "Y", "Z"];
270
+ console.log(" Accelerometer data normalized for neural network:");
271
+ for (let axis = 0; axis < 3; axis++) {
272
+ const axisData = [];
273
+ for (let i = axis; i < normalizedAccel.length; i += 3) {
274
+ axisData.push(normalizedAccel[i]);
275
+ }
276
+ const mean = axisData.reduce((s, v) => s + v, 0) / axisData.length;
277
+ const variance = axisData.reduce((s, v) => s + v * v, 0) / axisData.length;
278
+
279
+ console.log(
280
+ ` ${axes[axis]}-axis: mean=${mean.toFixed(
281
+ 4
282
+ )}, variance=${variance.toFixed(4)} → READY`
283
+ );
284
+ }
285
+ console.log("");
286
+
287
+ console.log("Streaming Use Cases:");
288
+ console.log(
289
+ " - Data preprocessing: Normalize features before machine learning"
290
+ );
291
+ console.log(
292
+ " - Anomaly detection: Identify outliers using z-score thresholds (±3σ)"
293
+ );
294
+ console.log(
295
+ " - Multi-channel normalization: EEG, EMG, accelerometer standardization"
296
+ );
297
+ console.log(" - Crash recovery: Maintain state across service restarts");
298
+ console.log(
299
+ " - Feature extraction: Combine with other filters (Rectify, RMS, etc.)"
300
+ );
301
+ console.log(
302
+ " - Adaptive alerting: Detect drift and anomalies in streaming data"
303
+ );
304
+ console.log(
305
+ " - Neural network preprocessing: Standardize input features for deep learning"
306
+ );