• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

paulmthompson / WhiskerToolbox / 17270491352

27 Aug 2025 02:57PM UTC coverage: 65.333%. Remained the same
17270491352

push

github

paulmthompson
Merge branch 'main' of https://github.com/paulmthompson/WhiskerToolbox

352 of 628 new or added lines in 92 files covered. (56.05%)

357 existing lines in 24 files now uncovered.

26429 of 40453 relevant lines covered (65.33%)

1119.34 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

59.73
/src/DataManager/utils/filter/FilterImplementations.hpp
1
#ifndef FILTER_IMPLEMENTATIONS_HPP
2
#define FILTER_IMPLEMENTATIONS_HPP
3

4
#include "IFilter.hpp"
5
#include "Iir.h"
6

7
#include <memory>
8
#include <sstream>
9
#include <stdexcept>
10

11
/**
12
 * @brief Butterworth Low-pass filter implementation
13
 * 
14
 * @tparam Order The filter order (must be known at compile time)
15
 */
16
template<int Order>
17
class ButterworthLowpassFilter : public IFilter {
18
private:
19
    Iir::Butterworth::LowPass<Order> filter_;
20
    double cutoff_hz_;
21
    double sampling_rate_hz_;
22
    bool configured_ = false;
23

24
public:
25
    /**
26
     * @brief Construct and configure the filter
27
     * 
28
     * @param cutoff_hz Cutoff frequency in Hz
29
     * @param sampling_rate_hz Sampling rate in Hz
30
     */
31
    ButterworthLowpassFilter(double cutoff_hz, double sampling_rate_hz) 
18✔
32
        : cutoff_hz_(cutoff_hz), sampling_rate_hz_(sampling_rate_hz) {
18✔
33
        try {
34
            filter_.setup(Order, sampling_rate_hz_, cutoff_hz_);
18✔
35
            configured_ = true;
18✔
36
        } catch (std::exception const& e) {
×
37
            throw std::runtime_error("Failed to configure Butterworth lowpass filter: " + std::string(e.what()));
×
38
        }
39
    }
18✔
40

41
    void process(std::span<float> data) override {
16✔
42
        if (!configured_) {
16✔
43
            throw std::runtime_error("Filter not properly configured");
×
44
        }
45

46
        // Process all samples - the tight loop is inside the virtual function
47
        for (float& sample : data) {
17,016✔
48
            sample = filter_.filter(sample);
17,000✔
49
        }
50
    }
16✔
51

52
    void reset() override {
3✔
53
        if (configured_) {
3✔
54
            filter_.reset();
3✔
55
        }
56
    }
3✔
57

58
    std::string getName() const override {
5✔
59
        std::ostringstream oss;
5✔
60
        oss << "Butterworth Lowpass Order " << Order << " (fc=" << cutoff_hz_ << "Hz)";
5✔
61
        return oss.str();
10✔
62
    }
5✔
63
};
64

65
/**
66
 * @brief Butterworth High-pass filter implementation
67
 * 
68
 * @tparam Order The filter order (must be known at compile time)
69
 */
70
template<int Order>
71
class ButterworthHighpassFilter : public IFilter {
72
private:
73
    Iir::Butterworth::HighPass<Order> filter_;
74
    double cutoff_hz_;
75
    double sampling_rate_hz_;
76
    bool configured_ = false;
77

78
public:
79
    ButterworthHighpassFilter(double cutoff_hz, double sampling_rate_hz) 
4✔
80
        : cutoff_hz_(cutoff_hz), sampling_rate_hz_(sampling_rate_hz) {
4✔
81
        try {
82
            filter_.setup(Order, sampling_rate_hz_, cutoff_hz_);
4✔
83
            configured_ = true;
4✔
84
        } catch (std::exception const& e) {
×
85
            throw std::runtime_error("Failed to configure Butterworth highpass filter: " + std::string(e.what()));
×
86
        }
87
    }
4✔
88

89
    void process(std::span<float> data) override {
3✔
90
        if (!configured_) {
3✔
91
            throw std::runtime_error("Filter not properly configured");
×
92
        }
93

94
        for (float& sample : data) {
4,003✔
95
            sample = filter_.filter(sample);
4,000✔
96
        }
97
    }
3✔
98

99
    void reset() override {
×
100
        if (configured_) {
×
101
            filter_.reset();
×
102
        }
103
    }
×
104

105
    std::string getName() const override {
1✔
106
        std::ostringstream oss;
1✔
107
        oss << "Butterworth Highpass Order " << Order << " (fc=" << cutoff_hz_ << "Hz)";
1✔
108
        return oss.str();
2✔
109
    }
1✔
110
};
111

112
/**
113
 * @brief Butterworth Band-pass filter implementation
114
 * 
115
 * @tparam Order The filter order (must be known at compile time)
116
 */
117
template<int Order>
118
class ButterworthBandpassFilter : public IFilter {
119
private:
120
    Iir::Butterworth::BandPass<Order> filter_;
121
    double low_cutoff_hz_;
122
    double high_cutoff_hz_;
123
    double sampling_rate_hz_;
124
    bool configured_ = false;
125

126
public:
127
    ButterworthBandpassFilter(double low_cutoff_hz, double high_cutoff_hz, double sampling_rate_hz) 
4✔
128
        : low_cutoff_hz_(low_cutoff_hz), high_cutoff_hz_(high_cutoff_hz), sampling_rate_hz_(sampling_rate_hz) {
4✔
129
        try {
130
            double center_freq = (low_cutoff_hz_ + high_cutoff_hz_) / 2.0;
4✔
131
            double bandwidth = high_cutoff_hz_ - low_cutoff_hz_;
4✔
132
            filter_.setup(Order, sampling_rate_hz_, center_freq, bandwidth);
4✔
133
            configured_ = true;
4✔
134
        } catch (std::exception const& e) {
×
135
            throw std::runtime_error("Failed to configure Butterworth bandpass filter: " + std::string(e.what()));
×
136
        }
137
    }
4✔
138

139
    void process(std::span<float> data) override {
3✔
140
        if (!configured_) {
3✔
141
            throw std::runtime_error("Filter not properly configured");
×
142
        }
143

144
        for (float& sample : data) {
4,003✔
145
            sample = filter_.filter(sample);
4,000✔
146
        }
147
    }
3✔
148

149
    void reset() override {
×
150
        if (configured_) {
×
151
            filter_.reset();
×
152
        }
153
    }
×
154

155
    std::string getName() const override {
1✔
156
        std::ostringstream oss;
1✔
157
        oss << "Butterworth Bandpass Order " << Order << " (fc=" << low_cutoff_hz_ << "-" << high_cutoff_hz_ << "Hz)";
1✔
158
        return oss.str();
2✔
159
    }
1✔
160
};
161

162
/**
163
 * @brief Butterworth Band-stop filter implementation
164
 * 
165
 * @tparam Order The filter order (must be known at compile time)
166
 */
167
template<int Order>
168
class ButterworthBandstopFilter : public IFilter {
169
private:
170
    Iir::Butterworth::BandStop<Order> filter_;
171
    double low_cutoff_hz_;
172
    double high_cutoff_hz_;
173
    double sampling_rate_hz_;
174
    bool configured_ = false;
175

176
public:
177
    ButterworthBandstopFilter(double low_cutoff_hz, double high_cutoff_hz, double sampling_rate_hz) 
1✔
178
        : low_cutoff_hz_(low_cutoff_hz), high_cutoff_hz_(high_cutoff_hz), sampling_rate_hz_(sampling_rate_hz) {
1✔
179
        try {
180
            double center_freq = (low_cutoff_hz_ + high_cutoff_hz_) / 2.0;
1✔
181
            double bandwidth = high_cutoff_hz_ - low_cutoff_hz_;
1✔
182
            filter_.setup(sampling_rate_hz_, center_freq, bandwidth);
1✔
183
            configured_ = true;
1✔
184
        } catch (std::exception const& e) {
×
185
            throw std::runtime_error("Failed to configure Butterworth bandstop filter: " + std::string(e.what()));
×
186
        }
187
    }
1✔
188

189
    void process(std::span<float> data) override {
1✔
190
        if (!configured_) {
1✔
191
            throw std::runtime_error("Filter not properly configured");
×
192
        }
193

194
        for (float& sample : data) {
1,001✔
195
            sample = filter_.filter(sample);
1,000✔
196
        }
197
    }
1✔
198

199
    void reset() override {
×
200
        if (configured_) {
×
201
            filter_.reset();
×
202
        }
203
    }
×
204

205
    std::string getName() const override {
×
206
        std::ostringstream oss;
×
207
        oss << "Butterworth Bandstop Order " << Order << " (fc=" << low_cutoff_hz_ << "-" << high_cutoff_hz_ << "Hz)";
×
208
        return oss.str();
×
209
    }
×
210
};
211

212
/**
213
 * @brief Chebyshev Type I Low-pass filter implementation
214
 * 
215
 * @tparam Order The filter order (must be known at compile time)
216
 */
217
template<int Order>
218
class ChebyshevILowpassFilter : public IFilter {
219
private:
220
    Iir::ChebyshevI::LowPass<Order> filter_;
221
    double cutoff_hz_;
222
    double sampling_rate_hz_;
223
    double passband_ripple_db_;
224
    bool configured_ = false;
225

226
public:
227
    /**
228
     * @brief Construct and configure the filter
229
     * 
230
     * @param cutoff_hz Cutoff frequency in Hz
231
     * @param sampling_rate_hz Sampling rate in Hz
232
     * @param passband_ripple_db Passband ripple in dB
233
     */
234
    ChebyshevILowpassFilter(double cutoff_hz, double sampling_rate_hz, double passband_ripple_db = 1.0) 
7✔
235
        : cutoff_hz_(cutoff_hz), sampling_rate_hz_(sampling_rate_hz), passband_ripple_db_(passband_ripple_db) {
7✔
236
        try {
237
            filter_.setup(Order, sampling_rate_hz_, cutoff_hz_, passband_ripple_db_);
7✔
238
            configured_ = true;
7✔
239
        } catch (std::exception const& e) {
×
240
            throw std::runtime_error("Failed to configure Chebyshev I lowpass filter: " + std::string(e.what()));
×
241
        }
242
    }
7✔
243

244
    void process(std::span<float> data) override {
5✔
245
        if (!configured_) {
5✔
246
            throw std::runtime_error("Filter not properly configured");
×
247
        }
248

249
        for (float& sample : data) {
5,005✔
250
            sample = filter_.filter(sample);
5,000✔
251
        }
252
    }
5✔
253

254
    void reset() override {
2✔
255
        if (configured_) {
2✔
256
            filter_.reset();
2✔
257
        }
258
    }
2✔
259

260
    std::string getName() const override {
7✔
261
        std::ostringstream oss;
7✔
262
        oss << "Chebyshev I Lowpass Order " << Order << " (fc=" << cutoff_hz_ << "Hz, ripple=" << passband_ripple_db_ << "dB)";
7✔
263
        return oss.str();
14✔
264
    }
7✔
265
};
266

267
/**
268
 * @brief Chebyshev Type I High-pass filter implementation
269
 * 
270
 * @tparam Order The filter order (must be known at compile time)
271
 */
272
template<int Order>
273
class ChebyshevIHighpassFilter : public IFilter {
274
private:
275
    Iir::ChebyshevI::HighPass<Order> filter_;
276
    double cutoff_hz_;
277
    double sampling_rate_hz_;
278
    double passband_ripple_db_;
279
    bool configured_ = false;
280

281
public:
282
    ChebyshevIHighpassFilter(double cutoff_hz, double sampling_rate_hz, double passband_ripple_db = 1.0) 
2✔
283
        : cutoff_hz_(cutoff_hz), sampling_rate_hz_(sampling_rate_hz), passband_ripple_db_(passband_ripple_db) {
2✔
284
        try {
285
            filter_.setup(Order, sampling_rate_hz_, cutoff_hz_, passband_ripple_db_);
2✔
286
            configured_ = true;
2✔
287
        } catch (std::exception const& e) {
×
288
            throw std::runtime_error("Failed to configure Chebyshev I highpass filter: " + std::string(e.what()));
×
289
        }
290
    }
2✔
291

292
    void process(std::span<float> data) override {
×
293
        if (!configured_) {
×
294
            throw std::runtime_error("Filter not properly configured");
×
295
        }
296

297
        for (float& sample : data) {
×
NEW
298
            sample = filter_.filter(sample);
×
299
        }
300
    }
×
301

302
    void reset() override {
×
303
        if (configured_) {
×
304
            filter_.reset();
×
305
        }
306
    }
×
307

308
    std::string getName() const override {
3✔
309
        std::ostringstream oss;
3✔
310
        oss << "Chebyshev I Highpass Order " << Order << " (fc=" << cutoff_hz_ << "Hz, ripple=" << passband_ripple_db_ << "dB)";
3✔
311
        return oss.str();
6✔
312
    }
3✔
313
};
314

315
/**
316
 * @brief Chebyshev Type I Band-pass filter implementation
317
 * 
318
 * @tparam Order The filter order (must be known at compile time)
319
 */
320
template<int Order>
321
class ChebyshevIBandpassFilter : public IFilter {
322
private:
323
    Iir::ChebyshevI::BandPass<Order> filter_;
324
    double low_cutoff_hz_;
325
    double high_cutoff_hz_;
326
    double sampling_rate_hz_;
327
    double ripple_db_;
328
    bool configured_ = false;
329

330
public:
331
    ChebyshevIBandpassFilter(double low_cutoff_hz, double high_cutoff_hz, double sampling_rate_hz, double ripple_db) 
1✔
332
        : low_cutoff_hz_(low_cutoff_hz), high_cutoff_hz_(high_cutoff_hz), sampling_rate_hz_(sampling_rate_hz), ripple_db_(ripple_db) {
1✔
333
        try {
334
            double center_freq = (low_cutoff_hz_ + high_cutoff_hz_) / 2.0;
1✔
335
            double bandwidth = high_cutoff_hz_ - low_cutoff_hz_;
1✔
336
            filter_.setup(Order, sampling_rate_hz_, center_freq, bandwidth, ripple_db_);
1✔
337
            configured_ = true;
1✔
338
        } catch (std::exception const& e) {
×
339
            throw std::runtime_error("Failed to configure Chebyshev I bandpass filter: " + std::string(e.what()));
×
340
        }
341
    }
1✔
342

343
    void process(std::span<float> data) override {
×
344
        if (!configured_) {
×
345
            throw std::runtime_error("Filter not properly configured");
×
346
        }
347

348
        for (float& sample : data) {
×
NEW
349
            sample = filter_.filter(sample);
×
350
        }
351
    }
×
352

353
    void reset() override {
×
354
        if (configured_) {
×
355
            filter_.reset();
×
356
        }
357
    }
×
358

359
    std::string getName() const override {
1✔
360
        std::ostringstream oss;
1✔
361
        oss << "Chebyshev I Bandpass Order " << Order << " (fc=" << low_cutoff_hz_ << "-" << high_cutoff_hz_ << "Hz, ripple=" << ripple_db_ << "dB)";
1✔
362
        return oss.str();
2✔
363
    }
1✔
364
};
365

366
/**
367
 * @brief Chebyshev Type I Band-stop filter implementation
368
 * 
369
 * @tparam Order The filter order (must be known at compile time)
370
 */
371
template<int Order>
372
class ChebyshevIBandstopFilter : public IFilter {
373
private:
374
    Iir::ChebyshevI::BandStop<Order> filter_;
375
    double low_cutoff_hz_;
376
    double high_cutoff_hz_;
377
    double sampling_rate_hz_;
378
    double ripple_db_;
379
    bool configured_ = false;
380

381
public:
382
    ChebyshevIBandstopFilter(double low_cutoff_hz, double high_cutoff_hz, double sampling_rate_hz, double ripple_db) 
1✔
383
        : low_cutoff_hz_(low_cutoff_hz), high_cutoff_hz_(high_cutoff_hz), sampling_rate_hz_(sampling_rate_hz), ripple_db_(ripple_db) {
1✔
384
        try {
385
            double center_freq = (low_cutoff_hz_ + high_cutoff_hz_) / 2.0;
1✔
386
            double bandwidth = high_cutoff_hz_ - low_cutoff_hz_;
1✔
387
            filter_.setup(Order, sampling_rate_hz_, center_freq, bandwidth, ripple_db_);
1✔
388
            configured_ = true;
1✔
389
        } catch (std::exception const& e) {
×
390
            throw std::runtime_error("Failed to configure Chebyshev I bandstop filter: " + std::string(e.what()));
×
391
        }
392
    }
1✔
393

394
    void process(std::span<float> data) override {
×
395
        if (!configured_) {
×
396
            throw std::runtime_error("Filter not properly configured");
×
397
        }
398

399
        for (float& sample : data) {
×
NEW
400
            sample = filter_.filter(sample);
×
401
        }
402
    }
×
403

404
    void reset() override {
×
405
        if (configured_) {
×
406
            filter_.reset();
×
407
        }
408
    }
×
409

410
    std::string getName() const override {
1✔
411
        std::ostringstream oss;
1✔
412
        oss << "Chebyshev I Bandstop Order " << Order << " (fc=" << low_cutoff_hz_ << "-" << high_cutoff_hz_ << "Hz, ripple=" << ripple_db_ << "dB)";
1✔
413
        return oss.str();
2✔
414
    }
1✔
415
};
416

417
/**
418
 * @brief Chebyshev II Low-pass filter implementation
419
 * 
420
 * @tparam Order The filter order (must be known at compile time)
421
 */
422
template<int Order>
423
class ChebyshevIILowpassFilter : public IFilter {
424
private:
425
    Iir::ChebyshevII::LowPass<Order> filter_;
426
    double cutoff_hz_;
427
    double sampling_rate_hz_;
428
    double stopband_ripple_db_;
429
    bool configured_ = false;
430

431
public:
432
    ChebyshevIILowpassFilter(double cutoff_hz, double sampling_rate_hz, double stopband_ripple_db) 
2✔
433
        : cutoff_hz_(cutoff_hz), sampling_rate_hz_(sampling_rate_hz), stopband_ripple_db_(stopband_ripple_db) {
2✔
434
        try {
435
            filter_.setup(Order, sampling_rate_hz_, cutoff_hz_, stopband_ripple_db_);
2✔
436
            configured_ = true;
2✔
437
        } catch (std::exception const& e) {
×
438
            throw std::runtime_error("Failed to configure Chebyshev II lowpass filter: " + std::string(e.what()));
×
439
        }
440
    }
2✔
441

442
    void process(std::span<float> data) override {
1✔
443
        if (!configured_) {
1✔
444
            throw std::runtime_error("Filter not properly configured");
×
445
        }
446

447
        for (float& sample : data) {
1,001✔
448
            sample = filter_.filter(sample);
1,000✔
449
        }
450
    }
1✔
451

452
    void reset() override {
×
453
        if (configured_) {
×
454
            filter_.reset();
×
455
        }
456
    }
×
457

458
    std::string getName() const override {
1✔
459
        std::ostringstream oss;
1✔
460
        oss << "Chebyshev II Lowpass Order " << Order << " (fc=" << cutoff_hz_ << "Hz, stopband=" << stopband_ripple_db_ << "dB)";
1✔
461
        return oss.str();
2✔
462
    }
1✔
463
};
464

465
/**
466
 * @brief Chebyshev II High-pass filter implementation
467
 * 
468
 * @tparam Order The filter order (must be known at compile time)
469
 */
470
template<int Order>
471
class ChebyshevIIHighpassFilter : public IFilter {
472
private:
473
    Iir::ChebyshevII::HighPass<Order> filter_;
474
    double cutoff_hz_;
475
    double sampling_rate_hz_;
476
    double stopband_ripple_db_;
477
    bool configured_ = false;
478

479
public:
480
    ChebyshevIIHighpassFilter(double cutoff_hz, double sampling_rate_hz, double stopband_ripple_db) 
1✔
481
        : cutoff_hz_(cutoff_hz), sampling_rate_hz_(sampling_rate_hz), stopband_ripple_db_(stopband_ripple_db) {
1✔
482
        try {
483
            filter_.setup(Order, sampling_rate_hz_, cutoff_hz_, stopband_ripple_db_);
1✔
484
            configured_ = true;
1✔
485
        } catch (std::exception const& e) {
×
486
            throw std::runtime_error("Failed to configure Chebyshev II highpass filter: " + std::string(e.what()));
×
487
        }
488
    }
1✔
489

490
    void process(std::span<float> data) override {
×
491
        if (!configured_) {
×
492
            throw std::runtime_error("Filter not properly configured");
×
493
        }
494

495
        for (float& sample : data) {
×
NEW
496
            sample = filter_.filter(sample);
×
497
        }
498
    }
×
499

500
    void reset() override {
×
501
        if (configured_) {
×
502
            filter_.reset();
×
503
        }
504
    }
×
505

506
    std::string getName() const override {
1✔
507
        std::ostringstream oss;
1✔
508
        oss << "Chebyshev II Highpass Order " << Order << " (fc=" << cutoff_hz_ << "Hz, stopband=" << stopband_ripple_db_ << "dB)";
1✔
509
        return oss.str();
2✔
510
    }
1✔
511
};
512

513
/**
514
 * @brief Chebyshev II Band-pass filter implementation
515
 * 
516
 * @tparam Order The filter order (must be known at compile time)
517
 */
518
template<int Order>
519
class ChebyshevIIBandpassFilter : public IFilter {
520
private:
521
    Iir::ChebyshevII::BandPass<Order> filter_;
522
    double low_cutoff_hz_;
523
    double high_cutoff_hz_;
524
    double sampling_rate_hz_;
525
    double stopband_ripple_db_;
526
    bool configured_ = false;
527

528
public:
529
    ChebyshevIIBandpassFilter(double low_cutoff_hz, double high_cutoff_hz, double sampling_rate_hz, double stopband_ripple_db) 
1✔
530
        : low_cutoff_hz_(low_cutoff_hz), high_cutoff_hz_(high_cutoff_hz), sampling_rate_hz_(sampling_rate_hz), stopband_ripple_db_(stopband_ripple_db) {
1✔
531
        try {
532
            double center_freq = (low_cutoff_hz_ + high_cutoff_hz_) / 2.0;
1✔
533
            double bandwidth = high_cutoff_hz_ - low_cutoff_hz_;
1✔
534
            filter_.setup(Order, sampling_rate_hz_, center_freq, bandwidth, stopband_ripple_db_);
1✔
535
            configured_ = true;
1✔
536
        } catch (std::exception const& e) {
×
537
            throw std::runtime_error("Failed to configure Chebyshev II bandpass filter: " + std::string(e.what()));
×
538
        }
539
    }
1✔
540

541
    void process(std::span<float> data) override {
×
542
        if (!configured_) {
×
543
            throw std::runtime_error("Filter not properly configured");
×
544
        }
545

546
        for (float& sample : data) {
×
NEW
547
            sample = filter_.filter(sample);
×
548
        }
549
    }
×
550

551
    void reset() override {
×
552
        if (configured_) {
×
553
            filter_.reset();
×
554
        }
555
    }
×
556

557
    std::string getName() const override {
1✔
558
        std::ostringstream oss;
1✔
559
        oss << "Chebyshev II Bandpass Order " << Order << " (fc=" << low_cutoff_hz_ << "-" << high_cutoff_hz_ << "Hz, stopband=" << stopband_ripple_db_ << "dB)";
1✔
560
        return oss.str();
2✔
561
    }
1✔
562
};
563

564
/**
565
 * @brief Chebyshev II Band-stop filter implementation
566
 * 
567
 * @tparam Order The filter order (must be known at compile time)
568
 */
569
template<int Order>
570
class ChebyshevIIBandstopFilter : public IFilter {
571
private:
572
    Iir::ChebyshevII::BandStop<Order> filter_;
573
    double low_cutoff_hz_;
574
    double high_cutoff_hz_;
575
    double sampling_rate_hz_;
576
    double stopband_ripple_db_;
577
    bool configured_ = false;
578

579
public:
580
    ChebyshevIIBandstopFilter(double low_cutoff_hz, double high_cutoff_hz, double sampling_rate_hz, double stopband_ripple_db) 
1✔
581
        : low_cutoff_hz_(low_cutoff_hz), high_cutoff_hz_(high_cutoff_hz), sampling_rate_hz_(sampling_rate_hz), stopband_ripple_db_(stopband_ripple_db) {
1✔
582
        try {
583
            double center_freq = (low_cutoff_hz_ + high_cutoff_hz_) / 2.0;
1✔
584
            double bandwidth = high_cutoff_hz_ - low_cutoff_hz_;
1✔
585
            filter_.setup(Order, sampling_rate_hz_, center_freq, bandwidth, stopband_ripple_db_);
1✔
586
            configured_ = true;
1✔
587
        } catch (std::exception const& e) {
×
588
            throw std::runtime_error("Failed to configure Chebyshev II bandstop filter: " + std::string(e.what()));
×
589
        }
590
    }
1✔
591

592
    void process(std::span<float> data) override {
×
593
        if (!configured_) {
×
594
            throw std::runtime_error("Filter not properly configured");
×
595
        }
596

597
        for (float& sample : data) {
×
NEW
598
            sample = filter_.filter(sample);
×
599
        }
600
    }
×
601

602
    void reset() override {
×
603
        if (configured_) {
×
604
            filter_.reset();
×
605
        }
606
    }
×
607

608
    std::string getName() const override {
1✔
609
        std::ostringstream oss;
1✔
610
        oss << "Chebyshev II Bandstop Order " << Order << " (fc=" << low_cutoff_hz_ << "-" << high_cutoff_hz_ << "Hz, stopband=" << stopband_ripple_db_ << "dB)";
1✔
611
        return oss.str();
2✔
612
    }
1✔
613
};
614

615
/**
616
 * @brief RBJ Low-pass filter implementation (always 2nd order)
617
 */
618
class RBJLowpassFilter : public IFilter {
619
private:
620
    Iir::RBJ::LowPass filter_;
621
    double cutoff_hz_;
622
    double sampling_rate_hz_;
623
    double q_factor_;
624
    bool configured_ = false;
625

626
public:
627
    RBJLowpassFilter(double cutoff_hz, double sampling_rate_hz, double q_factor) 
2✔
628
        : cutoff_hz_(cutoff_hz), sampling_rate_hz_(sampling_rate_hz), q_factor_(q_factor) {
2✔
629
        try {
630
            filter_.setup(sampling_rate_hz_, cutoff_hz_, q_factor_);
2✔
631
            configured_ = true;
2✔
632
        } catch (std::exception const& e) {
×
633
            throw std::runtime_error("Failed to configure RBJ lowpass filter: " + std::string(e.what()));
×
634
        }
×
635
    }
2✔
636

637
    void process(std::span<float> data) override {
1✔
638
        if (!configured_) {
1✔
639
            throw std::runtime_error("Filter not properly configured");
×
640
        }
641

642
        for (float& sample : data) {
1,001✔
643
            sample = filter_.filter(sample);
1,000✔
644
        }
645
    }
1✔
646

647
    void reset() override {
×
648
        if (configured_) {
×
649
            filter_.reset();
×
650
        }
651
    }
×
652

653
    std::string getName() const override {
1✔
654
        std::ostringstream oss;
1✔
655
        oss << "RBJ Lowpass (fc=" << cutoff_hz_ << "Hz, Q=" << q_factor_ << ")";
1✔
656
        return oss.str();
2✔
657
    }
1✔
658
};
659

660
/**
661
 * @brief RBJ High-pass filter implementation (always 2nd order)
662
 */
663
class RBJHighpassFilter : public IFilter {
664
private:
665
    Iir::RBJ::HighPass filter_;
666
    double cutoff_hz_;
667
    double sampling_rate_hz_;
668
    double q_factor_;
669
    bool configured_ = false;
670

671
public:
672
    RBJHighpassFilter(double cutoff_hz, double sampling_rate_hz, double q_factor) 
1✔
673
        : cutoff_hz_(cutoff_hz), sampling_rate_hz_(sampling_rate_hz), q_factor_(q_factor) {
1✔
674
        try {
675
            filter_.setup(sampling_rate_hz_, cutoff_hz_, q_factor_);
1✔
676
            configured_ = true;
1✔
677
        } catch (std::exception const& e) {
×
678
            throw std::runtime_error("Failed to configure RBJ highpass filter: " + std::string(e.what()));
×
679
        }
×
680
    }
1✔
681

682
    void process(std::span<float> data) override {
×
683
        if (!configured_) {
×
684
            throw std::runtime_error("Filter not properly configured");
×
685
        }
686

687
        for (float& sample : data) {
×
NEW
688
            sample = filter_.filter(sample);
×
689
        }
690
    }
×
691

692
    void reset() override {
×
693
        if (configured_) {
×
694
            filter_.reset();
×
695
        }
696
    }
×
697

698
    std::string getName() const override {
1✔
699
        std::ostringstream oss;
1✔
700
        oss << "RBJ Highpass (fc=" << cutoff_hz_ << "Hz, Q=" << q_factor_ << ")";
1✔
701
        return oss.str();
2✔
702
    }
1✔
703
};
704

705
/**
706
 * @brief RBJ Band-pass filter implementation (always 2nd order)
707
 */
708
class RBJBandpassFilter : public IFilter {
709
private:
710
    Iir::RBJ::BandPass2 filter_;
711
    double center_freq_hz_;
712
    double sampling_rate_hz_;
713
    double q_factor_;
714
    bool configured_ = false;
715

716
public:
717
    // Constructor for Q-factor based design (standard approach for RBJ)
718
    RBJBandpassFilter(double center_freq_hz, double sampling_rate_hz, double q_factor) 
1✔
719
        : center_freq_hz_(center_freq_hz), sampling_rate_hz_(sampling_rate_hz), q_factor_(q_factor) {
1✔
720
        try {
721
            // Convert Q factor to bandwidth in octaves: BW ≈ 1.44 / Q
722
            double bandwidth_octaves = 1.44 / q_factor_;
1✔
723
            filter_.setup(sampling_rate_hz_, center_freq_hz_, bandwidth_octaves);
1✔
724
            configured_ = true;
1✔
725
        } catch (std::exception const& e) {
×
726
            throw std::runtime_error("Failed to configure RBJ bandpass filter: " + std::string(e.what()));
×
727
        }
×
728
    }
1✔
729

730
    void process(std::span<float> data) override {
×
731
        if (!configured_) {
×
732
            throw std::runtime_error("Filter not properly configured");
×
733
        }
734

735
        for (float& sample : data) {
×
NEW
736
            sample = filter_.filter(sample);
×
737
        }
738
    }
×
739

740
    void reset() override {
×
741
        if (configured_) {
×
742
            filter_.reset();
×
743
        }
744
    }
×
745

746
    std::string getName() const override {
1✔
747
        std::ostringstream oss;
1✔
748
        oss << "RBJ Bandpass (fc=" << center_freq_hz_ << "Hz, Q=" << q_factor_ << ")";
1✔
749
        return oss.str();
2✔
750
    }
1✔
751
};
752

753
/**
754
 * @brief RBJ Band-stop/Notch filter implementation (always 2nd order)
755
 */
756
class RBJBandstopFilter : public IFilter {
757
private:
758
    Iir::RBJ::BandStop filter_;
759
    double center_freq_hz_;
760
    double sampling_rate_hz_;
761
    double q_factor_;
762
    bool configured_ = false;
763

764
public:
765
    // Constructor for Q-factor based notch filter design (standard approach for RBJ)
766
    RBJBandstopFilter(double center_freq_hz, double sampling_rate_hz, double q_factor) 
2✔
767
        : center_freq_hz_(center_freq_hz), sampling_rate_hz_(sampling_rate_hz), q_factor_(q_factor) {
2✔
768
        try {
769
            // Convert Q factor to bandwidth in octaves: BW ≈ 1.44 / Q
770
            double bandwidth_octaves = 1.44 / q_factor_;
2✔
771
            filter_.setup(sampling_rate_hz_, center_freq_hz_, bandwidth_octaves);
2✔
772
            configured_ = true;
2✔
773
        } catch (std::exception const& e) {
×
774
            throw std::runtime_error("Failed to configure RBJ bandstop filter: " + std::string(e.what()));
×
775
        }
×
776
    }
2✔
777

778
    void process(std::span<float> data) override {
2✔
779
        if (!configured_) {
2✔
780
            throw std::runtime_error("Filter not properly configured");
×
781
        }
782

783
        for (float& sample : data) {
4,002✔
784
            sample = filter_.filter(sample);
4,000✔
785
        }
786
    }
2✔
787

788
    void reset() override {
2✔
789
        if (configured_) {
2✔
790
            filter_.reset();
2✔
791
        }
792
    }
2✔
793

794
    std::string getName() const override {
1✔
795
        std::ostringstream oss;
1✔
796
        oss << "RBJ Bandstop/Notch (fc=" << center_freq_hz_ << "Hz, Q=" << q_factor_ << ")";
1✔
797
        return oss.str();
2✔
798
    }
1✔
799
};
800
#endif // FILTER_IMPLEMENTATIONS_HPP
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc