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,260 @@
1
+ # FIR and IIR Filter Implementation Summary
2
+
3
+ ## Overview
4
+
5
+ Successfully implemented comprehensive FIR (Finite Impulse Response) and IIR (Infinite Impulse Response) digital filters with N-API bindings for Node.js.
6
+
7
+ ## Implementation Details
8
+
9
+ ### FIR Filter (`FirFilter.h`, `FirFilter.cc`)
10
+
11
+ **Type**: Non-recursive, always stable
12
+ **Features**:
13
+
14
+ - Windowed sinc filter design method
15
+ - Four filter types: Low-Pass, High-Pass, Band-Pass, Band-Stop
16
+ - Window functions: Hamming, Hann, Blackman, Bartlett
17
+ - Circular buffer state management (O(1) operations)
18
+ - Template support for `float` and `double` precision
19
+ - Stateful (streaming) and stateless (batch) processing modes
20
+
21
+ **Key Methods**:
22
+
23
+ - `processSample(T sample)` - Process single sample with state
24
+ - `process(const T* input, T* output, size_t length, bool stateless)` - Batch processing
25
+ - `reset()` - Clear internal state
26
+ - `getOrder()` - Get filter order (number of taps - 1)
27
+ - `getCoefficients()` - Get impulse response coefficients
28
+ - `setCoefficients(coeffs)` - Update filter coefficients
29
+
30
+ **Static Factory Methods**:
31
+
32
+ ```cpp
33
+ FirFilter<T> createLowPass(T cutoffFreq, size_t numTaps, std::string windowType = "hamming");
34
+ FirFilter<T> createHighPass(T cutoffFreq, size_t numTaps, std::string windowType = "hamming");
35
+ FirFilter<T> createBandPass(T lowCutoff, T highCutoff, size_t numTaps, std::string windowType = "hamming");
36
+ FirFilter<T> createBandStop(T lowCutoff, T highCutoff, size_t numTaps, std::string windowType = "hamming");
37
+ ```
38
+
39
+ ### IIR Filter (`IirFilter.h`, `IirFilter.cc`)
40
+
41
+ **Type**: Recursive, more efficient but requires stability checking
42
+ **Features**:
43
+
44
+ - Direct Form II implementation (numerically stable)
45
+ - Bilinear transform for analog-to-digital conversion
46
+ - Butterworth filter designs (maximally flat passband)
47
+ - First-order and second-order (biquad) sections
48
+ - Template support for `float` and `double` precision
49
+ - Stateful (streaming) and stateless (batch) processing modes
50
+ - Stability checking method
51
+
52
+ **Key Methods**:
53
+
54
+ - `processSample(T sample)` - Process single sample with feedback
55
+ - `process(const T* input, T* output, size_t length, bool stateless)` - Batch processing
56
+ - `reset()` - Clear input/output history
57
+ - `getFeedforwardOrder()` - Get order of feedforward coefficients (b)
58
+ - `getFeedbackOrder()` - Get order of feedback coefficients (a)
59
+ - `getBCoefficients()` - Get feedforward (numerator) coefficients
60
+ - `getACoefficients()` - Get feedback (denominator) coefficients
61
+ - `isStable()` - Basic stability check
62
+
63
+ **Static Factory Methods**:
64
+
65
+ ```cpp
66
+ IirFilter<T> createFirstOrderLowPass(T cutoffFreq);
67
+ IirFilter<T> createFirstOrderHighPass(T cutoffFreq);
68
+ IirFilter<T> createButterworthLowPass(T cutoffFreq, int order);
69
+ IirFilter<T> createButterworthHighPass(T cutoffFreq, int order);
70
+ IirFilter<T> createButterworthBandPass(T lowCutoff, T highCutoff, int order);
71
+ IirFilter<T> createBiquad(T b0, T b1, T b2, T a1, T a2);
72
+ ```
73
+
74
+ ## N-API Bindings (`FilterBindings.cc`)
75
+
76
+ ### FirFilterWrapper
77
+
78
+ Exposes FIR filter to JavaScript with:
79
+
80
+ - Constructor: `new FirFilter(coefficients, stateful?)`
81
+ - All instance methods wrapped
82
+ - Static factory methods: `FirFilter.createLowPass()`, etc.
83
+ - Automatic memory management via `std::unique_ptr`
84
+
85
+ ### IirFilterWrapper
86
+
87
+ Exposes IIR filter to JavaScript with:
88
+
89
+ - Constructor: `new IirFilter(b_coeffs, a_coeffs, stateful?)`
90
+ - All instance methods wrapped
91
+ - Static factory methods: `IirFilter.createButterworthLowPass()`, etc.
92
+ - Automatic memory management via `std::unique_ptr`
93
+
94
+ ## Build Configuration
95
+
96
+ Updated `binding.gyp` to include:
97
+
98
+ - `src/native/core/FirFilter.cc`
99
+ - `src/native/core/IirFilter.cc`
100
+ - `src/native/FilterBindings.cc`
101
+
102
+ Compiled successfully with:
103
+
104
+ - **3012 functions** (up from 2720)
105
+ - AVX2 SIMD optimizations enabled
106
+ - O2/O3 optimization level
107
+ - Fast math enabled (`/fp:fast`)
108
+
109
+ ## Test Results
110
+
111
+ Created `test-filters.cjs` to verify functionality:
112
+
113
+ ### FIR Filter Tests
114
+
115
+ ✅ Create low-pass filter with 51 taps, Hamming window
116
+ ✅ Process single sample (stateful)
117
+ ✅ Process batch of 8 samples
118
+ ✅ Reset filter state
119
+ ✅ Get filter order (50)
120
+ ✅ Is stateful: true
121
+
122
+ **Sample Output**:
123
+
124
+ ```
125
+ Order: 50
126
+ First 5 outputs: [-0.0011, -0.0018, -0.0003, 0.0025, 0.0030]
127
+ ```
128
+
129
+ ### IIR Filter Tests
130
+
131
+ ✅ Create first-order low-pass filter (0.1 normalized frequency)
132
+ ✅ Process single sample (stateful with feedback)
133
+ ✅ Process batch of 8 samples
134
+ ✅ Reset filter state
135
+ ✅ Get feedforward/feedback orders
136
+ ✅ Is stable: true
137
+ ✅ Get B and A coefficients
138
+
139
+ **First-Order Filter Coefficients**:
140
+
141
+ ```
142
+ B coefficients: [0.2452, 0.2452]
143
+ A coefficients: [-0.5095]
144
+ First 5 outputs: [0.6154, 0.6814, 0.4698, 0.1168, -0.3084]
145
+ ```
146
+
147
+ ### Butterworth IIR Filter Tests
148
+
149
+ ✅ Create 2nd-order Butterworth low-pass filter
150
+ ✅ Process batch of 8 samples
151
+ ✅ Validate coefficient structure
152
+
153
+ **Second-Order Butterworth Coefficients**:
154
+
155
+ ```
156
+ B coefficients: [0.2066, 0.4131, 0.2066]
157
+ A coefficients: [-0.3695, 0.1958]
158
+ Outputs: [0.2066, 0.6961, 1.0430, 1.0754, 0.8129, 0.2964, -0.0497, -0.0764]
159
+ ```
160
+
161
+ ## Integration Status
162
+
163
+ ✅ **All 395 existing tests pass** - No regressions
164
+ ✅ **C++ implementation complete**
165
+ ✅ **N-API bindings working**
166
+ ✅ **Factory methods functional**
167
+ ✅ **Stateful and stateless modes operational**
168
+ ✅ **Memory management verified**
169
+
170
+ ## Design Theory
171
+
172
+ ### FIR Filters
173
+
174
+ - **Windowed Sinc Method**: Generates ideal frequency response in time domain, then applies window function to create finite-length filter
175
+ - **Spectral Inversion**: Converts low-pass to high-pass by subtracting from unit impulse
176
+ - **Filter Cascading**: Band-pass/band-stop created by combining low-pass and high-pass designs
177
+ - **Always Stable**: No feedback, output is weighted sum of past inputs only
178
+
179
+ ### IIR Filters
180
+
181
+ - **Bilinear Transform**: Maps analog (s-domain) to digital (z-domain) via `s = 2(1-z⁻¹)/(1+z⁻¹)`
182
+ - **Butterworth Polynomials**: Maximally flat magnitude response in passband
183
+ - **Direct Form II**: Uses single delay line for both feedforward and feedback paths (numerically stable)
184
+ - **Biquad Sections**: Second-order sections can be cascaded for higher-order filters
185
+
186
+ ### Performance Characteristics
187
+
188
+ - **FIR**: Linear phase (symmetric coefficients), higher computational cost (more taps needed)
189
+ - **IIR**: Non-linear phase, lower computational cost (fewer coefficients), requires stability checking
190
+ - **Trade-offs**: FIR for phase-critical applications, IIR for efficiency and sharp roll-off
191
+
192
+ ## Frequency Specifications
193
+
194
+ All cutoff frequencies are **normalized** (0 to 0.5):
195
+
196
+ - `cutoffFreq = desiredFreq / sampleRate`
197
+ - Example: 100 Hz cutoff at 1000 Hz sample rate = 0.1
198
+ - Nyquist frequency (sampleRate/2) = 0.5
199
+
200
+ ## Next Steps (Not Yet Implemented)
201
+
202
+ 1. ⏳ TypeScript wrappers in `src/ts/filters.ts`
203
+ 2. ⏳ Full test suite in `src/ts/__tests__/Filters.test.ts`
204
+ 3. ⏳ Documentation in `docs/FILTERS_IMPLEMENTATION.md`
205
+ 4. ⏳ Export from main `index.ts`
206
+ 5. ⏳ Usage examples in `src/ts/examples/`
207
+
208
+ ## Usage Examples
209
+
210
+ ### JavaScript/Node.js (Direct Native Bindings)
211
+
212
+ ```javascript
213
+ const dsp = require("./build/Release/dspx.node");
214
+
215
+ // FIR low-pass filter: 200 Hz cutoff at 1000 Hz sample rate
216
+ const firLP = dsp.FirFilter.createLowPass(0.2, 51, "hamming");
217
+ const filtered = firLP.process(new Float32Array([1, 0, -1, 0, 1]));
218
+
219
+ // IIR Butterworth low-pass: 150 Hz cutoff at 1000 Hz sample rate, order 2
220
+ const iirLP = dsp.IirFilter.createButterworthLowPass(0.15, 2);
221
+ const result = iirLP.process(new Float32Array([1, 2, 3, 2, 1]));
222
+
223
+ // Streaming mode (stateful)
224
+ for (let sample of signal) {
225
+ const out = firLP.processSample(sample);
226
+ console.log(out);
227
+ }
228
+
229
+ // Batch mode (stateless)
230
+ const batchOut = firLP.process(signalArray, true);
231
+ ```
232
+
233
+ ## File Manifest
234
+
235
+ ```
236
+ src/native/
237
+ ├── core/
238
+ │ ├── FirFilter.h (~150 lines)
239
+ │ ├── FirFilter.cc (~280 lines)
240
+ │ ├── IirFilter.h (~140 lines)
241
+ │ └── IirFilter.cc (~280 lines)
242
+ ├── FilterBindings.cc (~720 lines)
243
+ └── DspPipeline.cc (updated with init calls)
244
+
245
+ binding.gyp (updated with new sources)
246
+ test-filters.cjs (verification script)
247
+ ```
248
+
249
+ ## Compilation Warnings (Harmless)
250
+
251
+ - **C4661**: Explicit template instantiation warnings for `convolve()` and `bilinearTransform()` - These are declared in headers but only defined for explicitly instantiated types (`float` and `double`). No runtime impact.
252
+ - **D9025**: Compiler flags override warnings (`/std:c++17` overriding `/std:c++20`) - Expected behavior from node-gyp configuration.
253
+
254
+ ## Conclusion
255
+
256
+ FIR and IIR digital filters are **fully operational** at the C++ and N-API binding level. All factory methods work correctly, both stateful (streaming) and stateless (batch) modes are functional, and coefficient management is working. The implementation follows industry-standard filter design techniques and maintains numerical stability.
257
+
258
+ **Build Status**: ✅ **3012 functions compiled successfully**
259
+ **Test Status**: ✅ **All 395 existing tests passing**
260
+ **Integration**: ✅ **Ready for TypeScript wrapper layer**
@@ -0,0 +1,418 @@
1
+ # Filter Design API - User Guide
2
+
3
+ ## Quick Start
4
+
5
+ ```typescript
6
+ import { createFilter, FirFilter, IirFilter } from "dspx";
7
+
8
+ // Method 1: Unified API
9
+ const filter = createFilter({
10
+ type: "fir",
11
+ mode: "lowpass",
12
+ cutoffFrequency: 1000, // Hz
13
+ sampleRate: 8000, // Hz
14
+ order: 51,
15
+ windowType: "hamming",
16
+ });
17
+
18
+ // Method 2: Direct class methods
19
+ const fir = FirFilter.createLowPass({
20
+ cutoffFrequency: 1000,
21
+ sampleRate: 8000,
22
+ order: 51,
23
+ windowType: "hamming",
24
+ });
25
+
26
+ const iir = IirFilter.createButterworthLowPass({
27
+ cutoffFrequency: 1000,
28
+ sampleRate: 8000,
29
+ order: 4,
30
+ });
31
+
32
+ // Process signal
33
+ const filtered = await filter.process(signal);
34
+ ```
35
+
36
+ ## Filter Types
37
+
38
+ ### FIR Filters
39
+
40
+ **Pros**: Always stable, linear phase possible, precise frequency response
41
+ **Cons**: More taps = more computation
42
+
43
+ **Available Modes**:
44
+
45
+ - `lowpass` - Pass low frequencies, attenuate high
46
+ - `highpass` - Pass high frequencies, attenuate low
47
+ - `bandpass` - Pass only frequencies in specified band
48
+ - `bandstop` - Reject frequencies in specified band (notch filter)
49
+
50
+ **Window Types**:
51
+
52
+ - `hamming` - Good for general use (default)
53
+ - `hann` - Smooth frequency response
54
+ - `blackman` - Best sidelobe rejection
55
+ - `bartlett` - Simple triangular window
56
+
57
+ ### IIR Butterworth Filters
58
+
59
+ **Pros**: Efficient (fewer coefficients), sharp roll-off
60
+ **Cons**: Non-linear phase, can be unstable if poorly designed
61
+
62
+ **Available Modes**:
63
+
64
+ - `lowpass` - Maximally flat passband
65
+ - `highpass` - Maximally flat passband
66
+ - `bandpass` - Two Butterworth filters cascaded
67
+
68
+ **Orders**: 1-8 (higher order = sharper transition)
69
+
70
+ ### First-Order IIR Filters
71
+
72
+ **Pros**: Very fast, low latency, minimal state
73
+ **Cons**: Gentle rolloff (-20 dB/decade)
74
+
75
+ **Available Modes**:
76
+
77
+ - `lowpass` - Simple RC low-pass
78
+ - `highpass` - Simple RC high-pass
79
+
80
+ ## API Reference
81
+
82
+ ### `createFilter(options)`
83
+
84
+ Unified function to create any filter type.
85
+
86
+ ```typescript
87
+ function createFilter(options: FilterOptions): FirFilter | IirFilter;
88
+
89
+ type FilterOptions = {
90
+ type: "fir" | "butterworth";
91
+ mode: "lowpass" | "highpass" | "bandpass" | "bandstop" | "notch";
92
+
93
+ // For low-pass and high-pass
94
+ cutoffFrequency: number; // Hz
95
+
96
+ // For band-pass and band-stop
97
+ lowCutoffFrequency?: number; // Hz
98
+ highCutoffFrequency?: number; // Hz
99
+
100
+ sampleRate: number; // Hz
101
+ order: number; // Number of taps (FIR) or filter order (IIR)
102
+
103
+ // FIR only
104
+ windowType?: "hamming" | "hann" | "blackman" | "bartlett";
105
+ };
106
+ ```
107
+
108
+ ### `FirFilter` Class
109
+
110
+ ```typescript
111
+ class FirFilter {
112
+ // Factory methods
113
+ static createLowPass(options: {
114
+ cutoffFrequency: number;
115
+ sampleRate: number;
116
+ order: number;
117
+ windowType?: string;
118
+ }): FirFilter;
119
+
120
+ static createHighPass(options: {...}): FirFilter;
121
+ static createBandPass(options: {...}): FirFilter;
122
+ static createBandStop(options: {...}): FirFilter;
123
+
124
+ // Instance methods
125
+ process(input: Float32Array): Promise<Float32Array>;
126
+ processSample(sample: number): Promise<number>;
127
+ reset(): void;
128
+ getOrder(): number;
129
+ getCoefficients(): Float32Array;
130
+ }
131
+ ```
132
+
133
+ ### `IirFilter` Class
134
+
135
+ ```typescript
136
+ class IirFilter {
137
+ // Butterworth factory methods
138
+ static createButterworthLowPass(options: {
139
+ cutoffFrequency: number;
140
+ sampleRate: number;
141
+ order: number;
142
+ }): IirFilter;
143
+
144
+ static createButterworthHighPass(options: {...}): IirFilter;
145
+ static createButterworthBandPass(options: {...}): IirFilter;
146
+
147
+ // First-order factory methods
148
+ static createFirstOrderLowPass(options: {
149
+ cutoffFrequency: number;
150
+ sampleRate: number;
151
+ }): IirFilter;
152
+
153
+ static createFirstOrderHighPass(options: {...}): IirFilter;
154
+
155
+ // Instance methods
156
+ process(input: Float32Array): Promise<Float32Array>;
157
+ processSample(sample: number): Promise<number>;
158
+ reset(): void;
159
+ getOrder(): number;
160
+ getBCoefficients(): Float32Array;
161
+ getACoefficients(): Float32Array;
162
+ isStable(): boolean;
163
+ }
164
+ ```
165
+
166
+ ## Usage Examples
167
+
168
+ ### Example 1: Anti-Aliasing Filter
169
+
170
+ ```typescript
171
+ const antiAlias = createFilter({
172
+ type: "butterworth",
173
+ mode: "lowpass",
174
+ cutoffFrequency: 4000, // Nyquist - 1000 Hz
175
+ sampleRate: 10000,
176
+ order: 4,
177
+ });
178
+
179
+ const filtered = await antiAlias.process(rawSignal);
180
+ ```
181
+
182
+ ### Example 2: DC Offset Removal
183
+
184
+ ```typescript
185
+ const dcBlocker = IirFilter.createFirstOrderHighPass({
186
+ cutoffFrequency: 20, // Remove below 20 Hz
187
+ sampleRate: 8000,
188
+ });
189
+
190
+ const noDC = await dcBlocker.process(signal);
191
+ ```
192
+
193
+ ### Example 3: Voice Band Extraction
194
+
195
+ ```typescript
196
+ const voiceFilter = FirFilter.createBandPass({
197
+ lowCutoffFrequency: 300, // Telephone voice band
198
+ highCutoffFrequency: 3400,
199
+ sampleRate: 8000,
200
+ order: 101,
201
+ windowType: "blackman", // Best frequency selectivity
202
+ });
203
+
204
+ const voiceOnly = await voiceFilter.process(audio);
205
+ ```
206
+
207
+ ### Example 4: 50/60 Hz Notch Filter
208
+
209
+ ```typescript
210
+ // Remove powerline hum
211
+ const notch50Hz = createFilter({
212
+ type: "fir",
213
+ mode: "notch",
214
+ lowCutoffFrequency: 48,
215
+ highCutoffFrequency: 52,
216
+ sampleRate: 8000,
217
+ order: 201, // Higher order = narrower notch
218
+ });
219
+
220
+ const clean = await notch50Hz.process(noisySignal);
221
+ ```
222
+
223
+ ### Example 5: Real-Time Sample-by-Sample
224
+
225
+ ```typescript
226
+ const realtimeFilter = createFilter({
227
+ type: "butterworth",
228
+ mode: "lowpass",
229
+ cutoffFrequency: 1000,
230
+ sampleRate: 8000,
231
+ order: 4,
232
+ });
233
+
234
+ // Stream processing
235
+ for (const sample of incomingData) {
236
+ const filtered = await realtimeFilter.processSample(sample);
237
+ sendToOutput(filtered);
238
+ }
239
+ ```
240
+
241
+ ### Example 6: Batch Processing with State
242
+
243
+ ```typescript
244
+ const filter = FirFilter.createLowPass({
245
+ cutoffFrequency: 1000,
246
+ sampleRate: 8000,
247
+ order: 51,
248
+ });
249
+
250
+ // Process first batch
251
+ const batch1 = await filter.process(chunk1);
252
+
253
+ // Process second batch (state maintained)
254
+ const batch2 = await filter.process(chunk2);
255
+
256
+ // Reset state if needed
257
+ filter.reset();
258
+ ```
259
+
260
+ ## Performance Guide
261
+
262
+ ### Choosing Filter Type
263
+
264
+ | Use Case | Recommended Filter |
265
+ | -------------------- | ----------------------------- |
266
+ | Audio processing | FIR (linear phase) |
267
+ | Real-time control | IIR Butterworth (low latency) |
268
+ | Voice communications | FIR band-pass |
269
+ | Powerline removal | FIR notch (narrow band) |
270
+ | DC removal | First-order IIR high-pass |
271
+ | Anti-aliasing | IIR Butterworth (efficiency) |
272
+
273
+ ### FIR Order Guidelines
274
+
275
+ - **Anti-aliasing**: 51-101 taps
276
+ - **Voice band-pass**: 101-201 taps
277
+ - **Notch filter**: 151-301 taps
278
+ - **General smoothing**: 31-51 taps
279
+
280
+ **Rule of thumb**: Transition width ≈ (4-8) / order
281
+
282
+ ### IIR Order Guidelines
283
+
284
+ - **Order 2**: Basic smoothing, gentle rolloff
285
+ - **Order 4**: Good selectivity, common choice
286
+ - **Order 6-8**: Sharp transition, more latency
287
+
288
+ **Rule of thumb**: Each order adds ~6 dB/octave rolloff
289
+
290
+ ## Validation and Error Handling
291
+
292
+ The API automatically validates:
293
+
294
+ ✅ Cutoff frequency < Nyquist frequency (sampleRate / 2)
295
+ ✅ Order is in valid range (FIR: > 0, IIR: 1-8)
296
+ ✅ Band-pass/stop: low cutoff < high cutoff
297
+ ✅ All parameters are positive numbers
298
+
299
+ Error messages:
300
+
301
+ ```typescript
302
+ // Cutoff > Nyquist
303
+ Error: "Cutoff frequency must be between 0 and 4000 Hz (Nyquist frequency)";
304
+
305
+ // Invalid order
306
+ Error: "Order must be between 1 and 8 for IIR Butterworth filters";
307
+
308
+ // Invalid band
309
+ Error: "Low cutoff must be less than high cutoff";
310
+ ```
311
+
312
+ ## Technical Details
313
+
314
+ ### Frequency Normalization
315
+
316
+ You provide frequencies in **Hz**, the API normalizes internally:
317
+
318
+ ```typescript
319
+ normalizedFreq = cutoffFrequency / (sampleRate / 2); // Range: 0 to 1
320
+ ```
321
+
322
+ ### FIR Implementation
323
+
324
+ - **Method**: Windowed sinc design
325
+ - **Optimization**: SIMD-accelerated convolution (6.7x speedup)
326
+ - **Phase**: Linear (symmetric coefficients)
327
+ - **Stability**: Always stable
328
+
329
+ ### IIR Implementation
330
+
331
+ - **Method**: Bilinear transform (analog → digital)
332
+ - **Structure**: Direct Form II (biquad sections)
333
+ - **Phase**: Non-linear
334
+ - **Stability**: Checked on construction
335
+
336
+ ### State Management
337
+
338
+ Both FIR and IIR filters maintain state:
339
+
340
+ - **FIR**: Circular buffer of past inputs
341
+ - **IIR**: Past inputs and outputs (feedback)
342
+
343
+ Call `reset()` to clear state between independent signals.
344
+
345
+ ## Common Patterns
346
+
347
+ ### Pattern 1: Multi-Stage Filtering
348
+
349
+ ```typescript
350
+ // Anti-alias then downsample
351
+ const antiAlias = createFilter({
352
+ type: "butterworth",
353
+ mode: "lowpass",
354
+ cutoffFrequency: sampleRate / 4,
355
+ sampleRate,
356
+ order: 4,
357
+ });
358
+
359
+ const step1 = await antiAlias.process(signal);
360
+ const downsampled = downsample(step1, 2);
361
+ ```
362
+
363
+ ### Pattern 2: Cascade for Sharp Rolloff
364
+
365
+ ```typescript
366
+ // Two 2nd-order filters = 4th-order response
367
+ const stage1 = IirFilter.createButterworthLowPass({
368
+ cutoffFrequency: 1000,
369
+ sampleRate: 8000,
370
+ order: 2,
371
+ });
372
+
373
+ const stage2 = IirFilter.createButterworthLowPass({
374
+ cutoffFrequency: 1000,
375
+ sampleRate: 8000,
376
+ order: 2,
377
+ });
378
+
379
+ const filtered1 = await stage1.process(signal);
380
+ const filtered2 = await stage2.process(filtered1);
381
+ ```
382
+
383
+ ### Pattern 3: Adaptive Filtering
384
+
385
+ ```typescript
386
+ let cutoff = 1000;
387
+
388
+ function updateFilter() {
389
+ filter = createFilter({
390
+ type: "butterworth",
391
+ mode: "lowpass",
392
+ cutoffFrequency: cutoff,
393
+ sampleRate: 8000,
394
+ order: 4,
395
+ });
396
+ }
397
+
398
+ // Adjust cutoff based on signal characteristics
399
+ if (noiseLevel > threshold) {
400
+ cutoff = 500; // More aggressive filtering
401
+ updateFilter();
402
+ }
403
+ ```
404
+
405
+ ## See Also
406
+
407
+ - **Examples**: `src/ts/examples/filter-examples.ts`
408
+ - **Tests**: Run `npm test`
409
+ - **C++ Implementation**: `docs/FILTERS_IMPLEMENTATION.md`
410
+ - **FFT Guide**: `docs/FFT_USER_GUIDE.md`
411
+
412
+ ## Support
413
+
414
+ For more information:
415
+
416
+ - TypeScript types provide inline documentation
417
+ - Examples demonstrate all filter types
418
+ - Test suite shows validation patterns