/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "NotchFilter.h" /* initialise filter */ template void NotchFilter::init(float sample_freq_hz, float center_freq_hz, float bandwidth_hz, float attenuation_dB) { float omega = 2.0 * M_PI * center_freq_hz / sample_freq_hz; float octaves = log2f(center_freq_hz / (center_freq_hz - bandwidth_hz/2)) * 2; float A = powf(10, -attenuation_dB/40); float Q = sqrtf(powf(2, octaves)) / (powf(2,octaves) - 1); float alpha = sinf(omega) / (2 * Q/A); b0 = 1.0 + alpha*A; b1 = -2.0 * cosf(omega); b2 = 1.0 - alpha*A; a0_inv = 1.0/(1.0 + alpha/A); a1 = -2.0 * cosf(omega); a2 = 1.0 - alpha/A; initialised = true; } /* apply a new input sample, returning new output */ template T NotchFilter::apply(const T &sample) { if (!initialised) { // if we have not been initialised when return the input // sample as output return sample; } ntchsig2 = ntchsig1; ntchsig1 = ntchsig; ntchsig = sample; T output = (ntchsig*b0 + ntchsig1*b1 + ntchsig2*b2 - signal1*a1 - signal2*a2) * a0_inv; signal2 = signal1; signal1 = output; return output; } // table of user settable parameters const AP_Param::GroupInfo NotchFilterVector3fParam::var_info[] = { // @Param: ENABLE // @DisplayName: Enable // @Description: Enable notch filter // @Values: 0:Disabled,1:Enabled // @User: Advanced AP_GROUPINFO_FLAGS("ENABLE", 1, NotchFilterVector3fParam, enable, 0, AP_PARAM_FLAG_ENABLE), // @Param: FREQ // @DisplayName: Frequency // @Description: Notch center frequency in Hz // @Range: 10 200 // @Units: Hz // @User: Advanced AP_GROUPINFO("FREQ", 2, NotchFilterVector3fParam, center_freq_hz, 80), // @Param: BW // @DisplayName: Bandwidth // @Description: Notch bandwidth in Hz // @Range: 5 50 // @Units: Hz // @User: Advanced AP_GROUPINFO("BW", 3, NotchFilterVector3fParam, bandwidth_hz, 20), // @Param: ATT // @DisplayName: Attenuation // @Description: Notch attenuation in dB // @Range: 5 30 // @Units: dB // @User: Advanced AP_GROUPINFO("ATT", 4, NotchFilterVector3fParam, attenuation_dB, 15), AP_GROUPEND }; /* a notch filter with enable and filter parameters - constructor */ NotchFilterVector3fParam::NotchFilterVector3fParam(void) { AP_Param::setup_object_defaults(this, var_info); } /* initialise filter */ void NotchFilterVector3fParam::init(float _sample_freq_hz) { filter.init(_sample_freq_hz, center_freq_hz, bandwidth_hz, attenuation_dB); sample_freq_hz = _sample_freq_hz; last_center_freq = center_freq_hz; last_bandwidth = bandwidth_hz; last_attenuation = attenuation_dB; } /* apply a filter sample */ Vector3f NotchFilterVector3fParam::apply(const Vector3f &sample) { if (!enable) { // when not enabled it is a simple pass-through return sample; } // check for changed parameters if (!is_equal(center_freq_hz.get(), last_center_freq) || !is_equal(bandwidth_hz.get(), last_bandwidth) || !is_equal(attenuation_dB.get(), last_attenuation)) { if (!is_zero(sample_freq_hz)) { init(sample_freq_hz); } } return filter.apply(sample); } /* instantiate template classes */ template class NotchFilter; template class NotchFilter;