annotate dsp/signalconditioning/Filter.cpp @ 417:fa851e147e3f

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