/* Copyright (c) 2020, Serhat Şevki Dinçer. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package butter // Second order filter type filter2 struct { s2, s1, a1, a2, b0, b1, b2 float64 } func (f *filter2) Next(u float64) float64 { t := u - f.a1*f.s1 - f.a2*f.s2 // Direct Form 2 y := f.b0*t + f.b1*f.s1 + f.b2*f.s2 f.s2, f.s1 = f.s1, t // shift memory return y } func (f *filter2) NextS(u, y []float64) { n := len(u) if n > len(y) { n = len(y) } for i := 0; i < n; i++ { y[i] = f.Next(u[i]) } } func (f *filter2) Reset(u, y float64) { // Internal states will be in arithmetic progression except HP // All divisions are safe hp := f.b1 == -2*f.b0 // HP? if hp { f.s1 = -y / (2 * f.b0) f.s2 = u - f.a1*f.s1 } else { f.s1 = y / (f.b1 + 2*f.b0) f.s2 = u - (f.a1+2)*f.s1 } if f.b2 < 0 || hp { // BP or HP? f.s2 /= 1 + f.a1 + f.a2 f.s1 += f.s2 } else { f.s2 /= f.a2 - 1 } } // NewLowPass2 creates second order Low-Pass filter func NewLowPass2(wc float64) Filter { if !valid(wc) { return nil } var f filter2 wat := prewarp(wc) // wa * dt wat2 := wat * wat wat *= 2.82842712474619 // sqrt(8) a0 := wat2 + 4 + wat f.a1 = 2 * (wat2 - 4) / a0 f.a2 = (wat2 + 4 - wat) / a0 f.b0 = wat2 / a0 f.b2 = f.b0 f.b1 = 2 * f.b0 f.s2, f.s1 = 0, 0 return &f } // NewHighPass2 creates second order High-Pass filter func NewHighPass2(wc float64) Filter { if !valid(wc) { return nil } var f filter2 wat := prewarp(wc) // wa * dt wat2 := wat * wat wat *= 2.82842712474619 // sqrt(8) a0 := wat2 + 4 + wat f.a1 = 2 * (wat2 - 4) / a0 f.a2 = (wat2 + 4 - wat) / a0 f.b0 = 4 / a0 f.b2 = f.b0 f.b1 = -2 * f.b0 f.s2, f.s1 = 0, 0 return &f } // NewBandPass2 creates second order Band-Pass filter func NewBandPass2(wc, wd float64) Filter { if !valid2(wc, wd) { return nil } var f filter2 wat := prewarp(wc) // wa * dt wbt := prewarp(wd) // wb * dt wbwa := wbt * wat // wb * wa * dt^2 wd = 2 * (wbt - wat) a0 := wbwa + 4 + wd f.a1 = 2 * (wbwa - 4) / a0 f.a2 = (wbwa + 4 - wd) / a0 f.b0 = wd / a0 f.b2 = -f.b0 f.b1, f.s2, f.s1 = 0, 0, 0 return &f } // NewBandStop2 creates second order Band-Stop filter func NewBandStop2(wc, wd float64) Filter { if !valid2(wc, wd) { return nil } var f filter2 wat := prewarp(wc) // wa * dt wbt := prewarp(wd) // wb * dt wbwa := wbt * wat // wb * wa * dt^2 wd = 2 * (wbt - wat) a0 := wbwa + 4 + wd f.a1 = 2 * (wbwa - 4) / a0 f.b1 = f.a1 f.a2 = (wbwa + 4 - wd) / a0 f.b0 = (wbwa + 4) / a0 f.b2 = f.b0 f.s2, f.s1 = 0, 0 return &f }