annotate dsp/signalconditioning/Filter.cpp @ 193:ca658c7215a9

Faster filter implementation with explicit FIR support
author Chris Cannam
date Wed, 07 Oct 2015 10:36:09 +0100
parents e5907ae6de17
children ccd2019190bf
rev   line source
cannam@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@0 2
cannam@0 3 /*
cannam@0 4 QM DSP Library
cannam@0 5
cannam@0 6 Centre for Digital Music, Queen Mary, University of London.
Chris@84 7
Chris@84 8 This program is free software; you can redistribute it and/or
Chris@84 9 modify it under the terms of the GNU General Public License as
Chris@84 10 published by the Free Software Foundation; either version 2 of the
Chris@84 11 License, or (at your option) any later version. See the file
Chris@84 12 COPYING included with this distribution for more information.
cannam@0 13 */
cannam@0 14
cannam@0 15 #include "Filter.h"
cannam@0 16
Chris@193 17 #include <stdexcept>
cannam@0 18
Chris@193 19 using namespace std;
Chris@193 20
Chris@193 21 Filter::Filter(Parameters params)
cannam@0 22 {
Chris@193 23 if (params.a.empty()) {
Chris@193 24 m_fir = true;
Chris@193 25 if (params.b.empty()) {
Chris@193 26 throw logic_error("Filter must have at least one pair of coefficients");
Chris@193 27 }
Chris@193 28 } else {
Chris@193 29 m_fir = false;
Chris@193 30 if (params.a.size() != params.b.size()) {
Chris@193 31 throw logic_error("Inconsistent numbers of filter coefficients");
Chris@193 32 }
Chris@193 33 }
Chris@193 34
Chris@193 35 m_sz = int(params.b.size());
Chris@193 36 m_order = m_sz - 1;
cannam@0 37
Chris@193 38 m_a = params.a;
Chris@193 39 m_b = params.b;
Chris@193 40
Chris@193 41 // We keep some empty space at the start of the buffer, and
Chris@193 42 // encroach gradually into it as we add individual sample
Chris@193 43 // calculations at the start. Then when we run out of space, we
Chris@193 44 // move the buffer back to the end and begin again. This is
Chris@193 45 // significantly faster than moving the whole buffer along in
Chris@193 46 // 1-sample steps every time.
Chris@193 47
Chris@193 48 m_offmax = 20;
Chris@193 49 m_offa = m_offmax;
Chris@193 50 m_offb = m_offmax;
Chris@193 51
Chris@193 52 if (!m_fir) {
Chris@193 53 m_bufa.resize(m_order + m_offmax);
Chris@193 54 }
Chris@193 55
Chris@193 56 m_bufb.resize(m_sz + m_offmax);
cannam@0 57 }
cannam@0 58
cannam@0 59 Filter::~Filter()
cannam@0 60 {
cannam@0 61 }
cannam@0 62
Chris@193 63 void
Chris@193 64 Filter::reset()
cannam@0 65 {
Chris@193 66 m_offb = m_offmax;
Chris@193 67 m_offa = m_offmax;
cannam@0 68
Chris@193 69 if (!m_fir) {
Chris@193 70 m_bufa.assign(m_bufa.size(), 0.0);
Chris@193 71 }
cannam@0 72
Chris@193 73 m_bufb.assign(m_bufb.size(), 0.0);
cannam@0 74 }
cannam@0 75
Chris@193 76 void
Chris@193 77 Filter::process(const double *const __restrict__ in,
Chris@193 78 double *const __restrict__ out,
Chris@193 79 const int n)
cannam@0 80 {
Chris@193 81 for (int s = 0; s < n; ++s) {
Chris@193 82
Chris@193 83 if (m_offb > 0) --m_offb;
Chris@193 84 else {
Chris@193 85 for (int i = m_sz - 2; i >= 0; --i) {
Chris@193 86 m_bufb[i + m_offmax + 1] = m_bufb[i];
Chris@193 87 }
Chris@193 88 m_offb = m_offmax;
Chris@193 89 }
Chris@193 90 m_bufb[m_offb] = in[s];
Chris@193 91
Chris@193 92 double b_sum = 0.0;
Chris@193 93 for (int i = 0; i < m_sz; ++i) {
Chris@193 94 b_sum += m_b[i] * m_bufb[i + m_offb];
Chris@193 95 }
Chris@193 96
Chris@193 97 double outval;
Chris@193 98
Chris@193 99 if (m_fir) {
Chris@193 100
Chris@193 101 outval = b_sum;
Chris@193 102
Chris@193 103 } else {
Chris@193 104
Chris@193 105 double a_sum = 0.0;
Chris@193 106 for (int i = 0; i < m_order; ++i) {
Chris@193 107 a_sum += m_a[i + 1] * m_bufa[i + m_offa];
Chris@193 108 }
Chris@193 109
Chris@193 110 outval = b_sum - a_sum;
Chris@193 111
Chris@193 112 if (m_offa > 0) --m_offa;
Chris@193 113 else {
Chris@193 114 for (int i = m_order - 2; i >= 0; --i) {
Chris@193 115 m_bufa[i + m_offmax + 1] = m_bufa[i];
Chris@193 116 }
Chris@193 117 m_offa = m_offmax;
Chris@193 118 }
Chris@193 119 m_bufa[m_offa] = outval;
Chris@193 120 }
Chris@193 121
Chris@193 122 out[s] = outval;
Chris@193 123 }
cannam@0 124 }
cannam@0 125