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,195 @@
1
+ import { createDspPipeline } from "../../index.js";
2
+
3
+ console.log("Variance Filter - State Management Examples\n");
4
+
5
+ // Example 1: Batch variance (stateless)
6
+ console.log("1. Batch Variance (Stateless)");
7
+ {
8
+ const pipeline = createDspPipeline().Variance({ mode: "batch" });
9
+
10
+ const input = new Float32Array([1, 2, 3, 4, 5]);
11
+ const output = await pipeline.process(input, {
12
+ sampleRate: 1000,
13
+ channels: 1,
14
+ });
15
+
16
+ console.log(` Input: [${Array.from(input).join(", ")}]`);
17
+ console.log(` Output (all same): ${output[0].toFixed(3)}`);
18
+ console.log(` Expected variance: 2.0 (spread around mean of 3)`);
19
+ }
20
+
21
+ // Example 2: Moving variance (stateful)
22
+ console.log("\n2. Moving Variance (Stateful)");
23
+ {
24
+ const pipeline = createDspPipeline().Variance({
25
+ mode: "moving",
26
+ windowSize: 3,
27
+ });
28
+
29
+ const input = new Float32Array([1, 2, 3, 4, 5]);
30
+ const output = await pipeline.process(input, {
31
+ sampleRate: 1000,
32
+ channels: 1,
33
+ });
34
+
35
+ console.log(` Input: [${Array.from(input).join(", ")}]`);
36
+ console.log(` Output (sliding window):`);
37
+ console.log(` [1] -> variance: ${output[0].toFixed(3)}`);
38
+ console.log(` [1,2] -> variance: ${output[1].toFixed(3)}`);
39
+ console.log(` [1,2,3] -> variance: ${output[2].toFixed(3)}`);
40
+ console.log(` [2,3,4] -> variance: ${output[3].toFixed(3)}`);
41
+ console.log(` [3,4,5] -> variance: ${output[4].toFixed(3)}`);
42
+ }
43
+
44
+ // Example 3: Save and restore state
45
+ console.log("\n3. Save and Restore State");
46
+ {
47
+ const pipeline = createDspPipeline().Variance({
48
+ mode: "moving",
49
+ windowSize: 5,
50
+ });
51
+
52
+ // Process first batch
53
+ const input1 = new Float32Array([1, 2, 3, 4, 5]);
54
+ await pipeline.process(input1, { sampleRate: 1000, channels: 1 });
55
+
56
+ // Save state
57
+ const stateJson = await pipeline.saveState();
58
+ const state = JSON.parse(stateJson);
59
+
60
+ console.log(" Saved state:");
61
+ console.log(` Mode: ${state.stages[0].state.mode}`);
62
+ console.log(` Window size: ${state.stages[0].state.windowSize}`);
63
+ console.log(
64
+ ` Buffer: [${state.stages[0].state.channels[0].buffer.join(", ")}]`
65
+ );
66
+ console.log(
67
+ ` Running sum: ${state.stages[0].state.channels[0].runningSum}`
68
+ );
69
+
70
+ // Create new pipeline and restore
71
+ const pipeline2 = createDspPipeline().Variance({
72
+ mode: "moving",
73
+ windowSize: 5,
74
+ });
75
+ await pipeline2.loadState(stateJson);
76
+
77
+ console.log(" State restored!");
78
+
79
+ // Continue processing
80
+ const input2 = new Float32Array([6, 7, 8]);
81
+ const output = await pipeline2.process(input2, {
82
+ sampleRate: 1000,
83
+ channels: 1,
84
+ });
85
+
86
+ console.log(` Continued with [6, 7, 8]`);
87
+ console.log(
88
+ ` Output: [${Array.from(output)
89
+ .map((v) => v.toFixed(3))
90
+ .join(", ")}]`
91
+ );
92
+ }
93
+
94
+ // Example 4: Clear state
95
+ console.log("\n4. Clear State (Reset)");
96
+ {
97
+ const pipeline = createDspPipeline().Variance({
98
+ mode: "moving",
99
+ windowSize: 3,
100
+ });
101
+
102
+ // Build up state
103
+ await pipeline.process(new Float32Array([10, 20, 30, 40, 50]), {
104
+ sampleRate: 1000,
105
+ channels: 1,
106
+ });
107
+
108
+ // Clear state
109
+ pipeline.clearState();
110
+ console.log(" State cleared!");
111
+
112
+ // Process new data - should start fresh
113
+ const input = new Float32Array([1, 2, 3]);
114
+ const output = await pipeline.process(input, {
115
+ sampleRate: 1000,
116
+ channels: 1,
117
+ });
118
+
119
+ console.log(` After reset, input [1, 2, 3]:`);
120
+ console.log(
121
+ ` Output: [${Array.from(output)
122
+ .map((v) => v.toFixed(3))
123
+ .join(", ")}]`
124
+ );
125
+ console.log(` (Same as if processing first time)`);
126
+ }
127
+
128
+ // Example 5: Batch vs Moving comparison
129
+ console.log("\n5. Batch vs Moving Comparison");
130
+ {
131
+ const batchPipeline = createDspPipeline().Variance({ mode: "batch" });
132
+ const movingPipeline = createDspPipeline().Variance({
133
+ mode: "moving",
134
+ windowSize: 5,
135
+ });
136
+
137
+ const data = new Float32Array([1, 2, 3, 4, 5]);
138
+
139
+ const batchOutput = await batchPipeline.process(data.slice(), {
140
+ sampleRate: 1000,
141
+ channels: 1,
142
+ });
143
+ const movingOutput = await movingPipeline.process(data.slice(), {
144
+ sampleRate: 1000,
145
+ channels: 1,
146
+ });
147
+
148
+ console.log(` Input: [${Array.from(data).join(", ")}]`);
149
+ console.log(` Batch (all same): ${batchOutput[0].toFixed(3)}`);
150
+ console.log(
151
+ ` Moving (evolving): [${Array.from(movingOutput)
152
+ .map((v) => v.toFixed(3))
153
+ .join(", ")}]`
154
+ );
155
+ console.log("\n Batch: Single variance for entire dataset");
156
+ console.log(" Moving: Variance evolves as window slides");
157
+ }
158
+
159
+ // Example 6: Multi-channel state
160
+ console.log("\n6. Multi-Channel State Management");
161
+ {
162
+ const pipeline = createDspPipeline().Variance({
163
+ mode: "moving",
164
+ windowSize: 3,
165
+ });
166
+
167
+ // 2-channel interleaved data
168
+ const input = new Float32Array([1, 10, 2, 20, 3, 30, 4, 40, 5, 50]);
169
+ await pipeline.process(input, { sampleRate: 1000, channels: 2 });
170
+
171
+ const state = JSON.parse(await pipeline.saveState());
172
+
173
+ console.log(" 2-channel processing:");
174
+ console.log(
175
+ ` Channel 0 buffer: [${state.stages[0].state.channels[0].buffer.join(
176
+ ", "
177
+ )}]`
178
+ );
179
+ console.log(
180
+ ` Channel 1 buffer: [${state.stages[0].state.channels[1].buffer.join(
181
+ ", "
182
+ )}]`
183
+ );
184
+ console.log(" (Each channel maintains independent state)");
185
+ }
186
+
187
+ console.log("\nKey Takeaways:");
188
+ console.log(" - Batch mode: Stateless, computes variance over entire batch");
189
+ console.log(" - Moving mode: Stateful, maintains sliding window");
190
+ console.log(
191
+ " - State includes: circular buffer, running sum, running sum of squares"
192
+ );
193
+ console.log(
194
+ " - Each channel has independent state for multi-channel processing"
195
+ );
@@ -0,0 +1,260 @@
1
+ import { createDspPipeline } from "../../index.js";
2
+
3
+ console.log("Variance Filter - Streaming Examples\n");
4
+
5
+ // Example 1: Batch variance for signal quality monitoring
6
+ console.log("1. Batch Variance for Signal Quality Monitoring");
7
+ {
8
+ const pipeline = createDspPipeline().Variance({ mode: "batch" });
9
+
10
+ console.log(" Monitoring signal stability across chunks:");
11
+
12
+ const chunks = [
13
+ new Float32Array([1, 1.1, 0.9, 1.05, 0.95]), // Stable signal
14
+ new Float32Array([5, 15, 25, 35, 45]), // Increasing signal
15
+ new Float32Array([50, 10, 60, 5, 55]), // Noisy signal
16
+ ];
17
+
18
+ for (let i = 0; i < chunks.length; i++) {
19
+ const output = await pipeline.process(chunks[i].slice(), {
20
+ sampleRate: 1000,
21
+ channels: 1,
22
+ });
23
+
24
+ const variance = output[0];
25
+ const quality =
26
+ variance < 1 ? "STABLE" : variance < 100 ? "MODERATE" : "NOISY";
27
+
28
+ console.log(
29
+ ` Chunk ${i + 1}: variance = ${variance.toFixed(2)} -> ${quality}`
30
+ );
31
+ }
32
+ }
33
+
34
+ // Example 2: Moving variance for real-time variability detection
35
+ console.log("\n2. Moving Variance for Real-Time Variability Detection");
36
+ {
37
+ const pipeline = createDspPipeline().Variance({
38
+ mode: "moving",
39
+ windowSize: 10,
40
+ });
41
+
42
+ console.log(" Detecting variability changes in streaming data:");
43
+
44
+ // Simulate streaming sensor data with changing variability
45
+ const chunk1 = new Float32Array(20).map(
46
+ (_, i) => 100 + Math.sin(i * 0.1) * 2
47
+ ); // Low variance
48
+ const chunk2 = new Float32Array(20).map(
49
+ (_, i) => 100 + Math.sin(i * 0.1) * 20
50
+ ); // High variance
51
+ const chunk3 = new Float32Array(20).map(
52
+ (_, i) => 100 + Math.sin(i * 0.1) * 2
53
+ ); // Back to low
54
+
55
+ const output1 = await pipeline.process(chunk1, {
56
+ sampleRate: 1000,
57
+ channels: 1,
58
+ });
59
+ const output2 = await pipeline.process(chunk2, {
60
+ sampleRate: 1000,
61
+ channels: 1,
62
+ });
63
+ const output3 = await pipeline.process(chunk3, {
64
+ sampleRate: 1000,
65
+ channels: 1,
66
+ });
67
+
68
+ console.log(
69
+ ` Chunk 1 avg variance: ${(
70
+ output1.reduce((a, b) => a + b) / output1.length
71
+ ).toFixed(2)}`
72
+ );
73
+ console.log(
74
+ ` Chunk 2 avg variance: ${(
75
+ output2.reduce((a, b) => a + b) / output2.length
76
+ ).toFixed(2)}`
77
+ );
78
+ console.log(
79
+ ` Chunk 3 avg variance: ${(
80
+ output3.reduce((a, b) => a + b) / output3.length
81
+ ).toFixed(2)}`
82
+ );
83
+ console.log(" (Variance adapts to signal characteristics)");
84
+ }
85
+
86
+ // Example 3: Multi-channel EMG processing with variance
87
+ console.log("\n3. Multi-Channel EMG Variance Monitoring");
88
+ {
89
+ const pipeline = createDspPipeline().Variance({
90
+ mode: "moving",
91
+ windowSize: 50,
92
+ });
93
+
94
+ // Simulate 4-channel EMG data
95
+ const generateEMG = (amplitude: number, length: number) => {
96
+ return new Float32Array(length).map(
97
+ () => (Math.random() - 0.5) * 2 * amplitude
98
+ );
99
+ };
100
+
101
+ // Channel 1: High activity, Channel 2: Low activity, etc.
102
+ const ch1 = generateEMG(100, 100);
103
+ const ch2 = generateEMG(20, 100);
104
+ const ch3 = generateEMG(60, 100);
105
+ const ch4 = generateEMG(30, 100);
106
+
107
+ // Interleave channels
108
+ const interleaved = new Float32Array(400);
109
+ for (let i = 0; i < 100; i++) {
110
+ interleaved[i * 4] = ch1[i];
111
+ interleaved[i * 4 + 1] = ch2[i];
112
+ interleaved[i * 4 + 2] = ch3[i];
113
+ interleaved[i * 4 + 3] = ch4[i];
114
+ }
115
+
116
+ const output = await pipeline.process(interleaved, {
117
+ sampleRate: 2000,
118
+ channels: 4,
119
+ });
120
+
121
+ // Calculate average variance per channel
122
+ const avgVariances = [0, 0, 0, 0];
123
+ for (let i = 0; i < output.length; i++) {
124
+ avgVariances[i % 4] += output[i];
125
+ }
126
+ avgVariances.forEach((sum, ch) => {
127
+ avgVariances[ch] = sum / (output.length / 4);
128
+ });
129
+
130
+ console.log(" Average variance per muscle channel:");
131
+ avgVariances.forEach((var_, ch) => {
132
+ const activity = var_ > 5000 ? "HIGH" : var_ > 2000 ? "MODERATE" : "LOW";
133
+ console.log(
134
+ ` Channel ${ch}: ${var_.toFixed(0)} -> ${activity} activity`
135
+ );
136
+ });
137
+ }
138
+
139
+ // Example 4: Interrupted processing with state recovery
140
+ console.log("\n4. Interrupted Processing with State Recovery");
141
+ {
142
+ const pipeline = createDspPipeline().Variance({
143
+ mode: "moving",
144
+ windowSize: 20,
145
+ });
146
+
147
+ // Simulate streaming with interruption
148
+ console.log(" Processing stream...");
149
+
150
+ // Process first chunk
151
+ const chunk1 = new Float32Array(30).map((_, i) => Math.sin(i * 0.1) * 50);
152
+ await pipeline.process(chunk1, { sampleRate: 1000, channels: 1 });
153
+
154
+ // Save state before interruption
155
+ const savedState = await pipeline.saveState();
156
+ console.log(" State saved (simulating service restart)");
157
+
158
+ // Simulate restart - create new pipeline
159
+ const pipeline2 = createDspPipeline().Variance({
160
+ mode: "moving",
161
+ windowSize: 20,
162
+ });
163
+ await pipeline2.loadState(savedState);
164
+ console.log(" State restored!");
165
+
166
+ // Continue processing
167
+ const chunk2 = new Float32Array(30).map(
168
+ (_, i) => Math.sin((i + 30) * 0.1) * 50
169
+ );
170
+ const output = await pipeline2.process(chunk2, {
171
+ sampleRate: 1000,
172
+ channels: 1,
173
+ });
174
+
175
+ console.log(` Resumed processing: ${output.length} samples processed`);
176
+ console.log(" (Seamless continuation from saved state)");
177
+ }
178
+
179
+ // Example 5: Combining with other filters for feature extraction
180
+ console.log("\n5. Feature Extraction Pipeline (Rectify → Variance)");
181
+ {
182
+ const pipeline = createDspPipeline()
183
+ .Rectify({ mode: "full" })
184
+ .Variance({ mode: "moving", windowSize: 100 });
185
+
186
+ // Simulate biosignal with varying amplitude
187
+ const signal = new Float32Array(200).map((_, i) => {
188
+ const base = Math.sin(i * 0.05) * 100;
189
+ const noise = (Math.random() - 0.5) * 20;
190
+ return base + noise;
191
+ });
192
+
193
+ const output = await pipeline.process(signal, {
194
+ sampleRate: 1000,
195
+ channels: 1,
196
+ });
197
+
198
+ // Get last 10 variance values
199
+ const recentVariance = Array.from(output.slice(-10));
200
+ const avgVariance =
201
+ recentVariance.reduce((a, b) => a + b) / recentVariance.length;
202
+
203
+ console.log(` Input signal: 200 samples (bipolar with noise)`);
204
+ console.log(` After Rectify: All positive values`);
205
+ console.log(` After Variance: Variability measure`);
206
+ console.log(` Recent avg variance: ${avgVariance.toFixed(2)}`);
207
+ console.log(" (Can detect changes in signal amplitude variability)");
208
+ }
209
+
210
+ // Example 6: Threshold-based alerts
211
+ console.log("\n6. Variance-Based Alerting");
212
+ {
213
+ const pipeline = createDspPipeline().Variance({
214
+ mode: "moving",
215
+ windowSize: 50,
216
+ });
217
+
218
+ const VARIANCE_THRESHOLD = 100;
219
+ let alertCount = 0;
220
+
221
+ console.log(` Monitoring for variance > ${VARIANCE_THRESHOLD}:`);
222
+
223
+ // Simulate multiple data chunks
224
+ const chunks = [
225
+ new Float32Array(100).map((_, i) => 50 + Math.sin(i * 0.1) * 5), // Low variance
226
+ new Float32Array(100).map((_, i) => 50 + Math.sin(i * 0.1) * 50), // High variance
227
+ new Float32Array(100).map((_, i) => 50 + Math.sin(i * 0.1) * 10), // Moderate variance
228
+ ];
229
+
230
+ for (let chunkIdx = 0; chunkIdx < chunks.length; chunkIdx++) {
231
+ const output = await pipeline.process(chunks[chunkIdx], {
232
+ sampleRate: 1000,
233
+ channels: 1,
234
+ });
235
+
236
+ // Check for threshold crossings
237
+ const exceedances = output.filter((v) => v > VARIANCE_THRESHOLD).length;
238
+
239
+ if (exceedances > 0) {
240
+ alertCount++;
241
+ console.log(
242
+ ` Chunk ${
243
+ chunkIdx + 1
244
+ }: ALERT - ${exceedances} samples exceeded threshold`
245
+ );
246
+ } else {
247
+ console.log(` Chunk ${chunkIdx + 1}: OK - variance within limits`);
248
+ }
249
+ }
250
+
251
+ console.log(` Total alerts: ${alertCount}`);
252
+ }
253
+
254
+ console.log("\nStreaming Use Cases:");
255
+ console.log(" - Signal quality monitoring (batch variance per chunk)");
256
+ console.log(" - Real-time variability detection (moving window)");
257
+ console.log(" - Multi-channel muscle activity monitoring (EMG)");
258
+ console.log(" - Crash recovery with state persistence");
259
+ console.log(" - Feature extraction pipelines (combine with other filters)");
260
+ console.log(" - Threshold-based alerting for anomaly detection");