Line data Source code
1 : /** 2 : * \file SecondOrderFilter.hxx 3 : * @see http://abvolt.com/research/publications2.htm 4 : * @see http://www.music.mcgill.ca/~ich/classes/FiltersChap2.pdf for the allpass filter 5 : */ 6 : 7 : #include "SecondOrderFilter.h" 8 : 9 : #include <boost/math/constants/constants.hpp> 10 : 11 : #include <cassert> 12 : #include <cmath> 13 : 14 : namespace ATK 15 : { 16 : template <typename DataType_> 17 105 : SecondOrderCoreCoefficients<DataType_>::SecondOrderCoreCoefficients(gsl::index nb_channels) 18 105 : :Parent(nb_channels, nb_channels) 19 : { 20 105 : } 21 : 22 : template <typename DataType_> 23 95 : SecondOrderBaseCoefficients<DataType_>::SecondOrderBaseCoefficients(gsl::index nb_channels) 24 95 : : Parent(nb_channels) 25 : { 26 95 : } 27 : 28 : template <typename DataType_> 29 239 : void SecondOrderBaseCoefficients<DataType_>::setup() 30 : { 31 239 : Parent::setup(); 32 : 33 239 : coefficients_in.assign(in_order+1, 0); 34 239 : coefficients_out.assign(out_order, 0); 35 239 : } 36 : 37 : template <typename DataType_> 38 62 : void SecondOrderBaseCoefficients<DataType_>::set_cut_frequency(CoeffDataType cut_frequency) 39 : { 40 62 : if(cut_frequency <= 0) 41 : { 42 1 : throw std::out_of_range("Frequency can't be negative"); 43 : } 44 61 : this->cut_frequency = cut_frequency; 45 61 : setup(); 46 61 : } 47 : 48 : template <typename DataType_> 49 2 : typename SecondOrderBaseCoefficients<DataType_>::CoeffDataType SecondOrderBaseCoefficients<DataType_>::get_cut_frequency() const 50 : { 51 2 : return cut_frequency; 52 : } 53 : 54 : template<typename DataType_> 55 5 : SecondOrderBandPassCoefficients<DataType_>::SecondOrderBandPassCoefficients(gsl::index nb_channels) 56 5 : :Parent(nb_channels) 57 : { 58 5 : } 59 : 60 : template <typename DataType_> 61 13 : void SecondOrderBandPassCoefficients<DataType_>::setup() 62 : { 63 13 : Parent::setup(); 64 : 65 13 : CoeffDataType c = std::tan(boost::math::constants::pi<CoeffDataType>() * cut_frequency / input_sampling_rate); 66 13 : CoeffDataType d = (1 + std::sqrt(static_cast<CoeffDataType>(2.)) * c + c * c); 67 13 : CoeffDataType Q_inv = 1 / Q; 68 : 69 13 : coefficients_in[2] = Q_inv * c / d; 70 13 : coefficients_in[1] = 0; 71 13 : coefficients_in[0] = -Q_inv * c / d; 72 13 : coefficients_out[1] = - 2 * (c * c - 1) / d; 73 13 : coefficients_out[0] = - (1 - std::sqrt(static_cast<CoeffDataType>(2.)) * c + c * c) / d; 74 13 : } 75 : 76 : template <typename DataType_> 77 5 : void SecondOrderBandPassCoefficients<DataType_>::set_Q(CoeffDataType Q) 78 : { 79 5 : if(Q <= 0) 80 : { 81 1 : throw std::out_of_range("Q can't be negative"); 82 : } 83 4 : this->Q = Q; 84 4 : setup(); 85 4 : } 86 : 87 : template <typename DataType_> 88 1 : typename SecondOrderBandPassCoefficients<DataType_>::CoeffDataType SecondOrderBandPassCoefficients<DataType_>::get_Q() const 89 : { 90 1 : return Q; 91 : } 92 : 93 : template<typename DataType_> 94 6 : SecondOrderLowPassCoefficients<DataType_>::SecondOrderLowPassCoefficients(gsl::index nb_channels) 95 6 : :Parent(nb_channels) 96 : { 97 6 : } 98 : 99 : template <typename DataType_> 100 13 : void SecondOrderLowPassCoefficients<DataType_>::setup() 101 : { 102 13 : Parent::setup(); 103 : 104 13 : CoeffDataType c = std::tan(boost::math::constants::pi<CoeffDataType>() * cut_frequency / input_sampling_rate); 105 13 : CoeffDataType d = (1 + std::sqrt(static_cast<CoeffDataType>(2.)) * c + c * c); 106 : 107 13 : coefficients_in[2] = c * c / d; 108 13 : coefficients_in[1] = 2 * c * c / d; 109 13 : coefficients_in[0] = c * c / d; 110 13 : coefficients_out[1] = - 2 * (c * c - 1) / d; 111 13 : coefficients_out[0] = - (1 - std::sqrt(static_cast<CoeffDataType>(2.)) * c + c * c) / d; 112 13 : } 113 : 114 : template<typename DataType_> 115 3 : SecondOrderHighPassCoefficients<DataType_>::SecondOrderHighPassCoefficients(gsl::index nb_channels) 116 3 : :Parent(nb_channels) 117 : { 118 3 : } 119 : 120 : template <typename DataType_> 121 9 : void SecondOrderHighPassCoefficients<DataType_>::setup() 122 : { 123 9 : Parent::setup(); 124 : 125 9 : CoeffDataType c = std::tan(boost::math::constants::pi<CoeffDataType>() * cut_frequency / input_sampling_rate); 126 9 : CoeffDataType d = (1 + std::sqrt(static_cast<CoeffDataType>(2.)) * c + c * c); 127 : 128 9 : coefficients_in[2] = 1; 129 9 : coefficients_in[1] = -2; 130 9 : coefficients_in[0] = 1; 131 9 : coefficients_out[1] = - 2 * (c * c - 1) / d; 132 9 : coefficients_out[0] = - (1 - std::sqrt(static_cast<CoeffDataType>(2.)) * c + c * c) / d; 133 9 : } 134 : 135 : template<typename DataType_> 136 6 : SecondOrderBandPassPeakCoefficients<DataType_>::SecondOrderBandPassPeakCoefficients(gsl::index nb_channels) 137 6 : :Parent(nb_channels) 138 : { 139 6 : } 140 : 141 : template <typename DataType_> 142 17 : void SecondOrderBandPassPeakCoefficients<DataType_>::setup() 143 : { 144 17 : Parent::setup(); 145 : 146 17 : CoeffDataType c = std::tan(boost::math::constants::pi<CoeffDataType>() * cut_frequency / input_sampling_rate); 147 17 : CoeffDataType Q_inv = 1 / Q; 148 17 : if(gain <= 1) 149 : { 150 13 : CoeffDataType V0 = 1 / gain; 151 13 : CoeffDataType d = 1 + V0 * Q_inv * c + c * c; 152 : 153 13 : coefficients_in[2] = (1 + Q_inv * c + c * c) / d; 154 13 : coefficients_in[1] = 2 * (c * c - 1) / d; 155 13 : coefficients_in[0] = (1 - Q_inv * c + c * c) / d; 156 13 : coefficients_out[1] = -2 * (c * c - 1) / d; 157 13 : coefficients_out[0] = -(1 - V0 * Q_inv * c + c * c) / d; 158 : } 159 : else 160 : { 161 4 : CoeffDataType V0 = gain; 162 4 : CoeffDataType d = 1 + Q_inv * c + c * c; 163 : 164 4 : coefficients_in[2] = (1 + V0 * Q_inv * c + c * c) / d; 165 4 : coefficients_in[1] = 2 * (c * c - 1) / d; 166 4 : coefficients_in[0] = (1 - V0 * Q_inv * c + c * c) / d; 167 4 : coefficients_out[1] = -2 * (c * c - 1) / d; 168 4 : coefficients_out[0] = -(1 - Q_inv * c + c * c) / d; 169 : } 170 17 : } 171 : 172 : template <typename DataType_> 173 5 : void SecondOrderBandPassPeakCoefficients<DataType_>::set_Q(CoeffDataType Q) 174 : { 175 5 : if(Q <= 0) 176 : { 177 1 : throw std::out_of_range("Q can't be negative"); 178 : } 179 4 : this->Q = Q; 180 4 : setup(); 181 4 : } 182 : 183 : template <typename DataType_> 184 1 : typename SecondOrderBandPassPeakCoefficients<DataType_>::CoeffDataType SecondOrderBandPassPeakCoefficients<DataType_>::get_Q() const 185 : { 186 1 : return Q; 187 : } 188 : 189 : template <typename DataType_> 190 4 : void SecondOrderBandPassPeakCoefficients<DataType_>::set_gain(CoeffDataType gain) 191 : { 192 4 : this->gain = gain; 193 4 : setup(); 194 4 : } 195 : 196 : template <typename DataType_> 197 1 : typename SecondOrderBandPassPeakCoefficients<DataType_>::CoeffDataType SecondOrderBandPassPeakCoefficients<DataType_>::get_gain() const 198 : { 199 1 : return gain; 200 : } 201 : 202 : template<typename DataType_> 203 5 : SecondOrderAllPassCoefficients<DataType_>::SecondOrderAllPassCoefficients(gsl::index nb_channels) 204 5 : :Parent(nb_channels) 205 : { 206 5 : } 207 : 208 : template <typename DataType_> 209 13 : void SecondOrderAllPassCoefficients<DataType_>::setup() 210 : { 211 13 : Parent::setup(); 212 : 213 13 : CoeffDataType c = std::tan(boost::math::constants::pi<CoeffDataType>() * Q); 214 13 : CoeffDataType d = -std::cos(2 * boost::math::constants::pi<CoeffDataType>() * cut_frequency / input_sampling_rate); 215 : 216 13 : coefficients_in[2] = -c; 217 13 : coefficients_in[1] = d * (1 - c); 218 13 : coefficients_in[0] = 1; 219 13 : coefficients_out[1] = -d * (1 - c); 220 13 : coefficients_out[0] = c; 221 13 : } 222 : 223 : template <typename DataType_> 224 5 : void SecondOrderAllPassCoefficients<DataType_>::set_Q(CoeffDataType Q) 225 : { 226 5 : if(Q <= 0) 227 : { 228 1 : throw std::out_of_range("Q can't be negative"); 229 : } 230 4 : this->Q = Q; 231 4 : setup(); 232 4 : } 233 : 234 : template <typename DataType_> 235 1 : typename SecondOrderAllPassCoefficients<DataType_>::CoeffDataType SecondOrderAllPassCoefficients<DataType_>::get_Q() const 236 : { 237 1 : return Q; 238 : } 239 : 240 : template<typename DataType_> 241 4 : SecondOrderLowShelvingCoefficients<DataType_>::SecondOrderLowShelvingCoefficients(gsl::index nb_channels) 242 4 : :Parent(nb_channels) 243 : { 244 4 : } 245 : 246 : template <typename DataType_> 247 13 : void SecondOrderLowShelvingCoefficients<DataType_>::setup() 248 : { 249 13 : Parent::setup(); 250 : 251 13 : CoeffDataType c = std::tan(boost::math::constants::pi<CoeffDataType>() * cut_frequency / input_sampling_rate); 252 13 : if(gain <= 1) 253 : { 254 12 : CoeffDataType V0 = 1 / gain; 255 12 : CoeffDataType d = (1 + std::sqrt(static_cast<CoeffDataType>(2.) * V0) * c + V0 * c * c); 256 : 257 12 : coefficients_in[2] = (1 + std::sqrt(static_cast<CoeffDataType>(2.)) * c + c * c) / d; 258 12 : coefficients_in[1] = 2 * (c * c - 1) / d; 259 12 : coefficients_in[0] = (1 - std::sqrt(static_cast<CoeffDataType>(2.)) * c + c * c) / d; 260 12 : coefficients_out[1] = - 2 * (V0 * c * c - 1) / d; 261 12 : coefficients_out[0] = - (1 - std::sqrt(static_cast<CoeffDataType>(2.) * V0) * c + V0 * c * c) / d; 262 : } 263 : else 264 : { 265 1 : CoeffDataType d = (1 + std::sqrt(static_cast<CoeffDataType>(2.)) * c + c * c); 266 : 267 1 : coefficients_in[2] = (1 + std::sqrt(static_cast<CoeffDataType>(2.) * gain) * c + gain * c * c) / d; 268 1 : coefficients_in[1] = 2 * (gain * c * c - 1) / d; 269 1 : coefficients_in[0] = (1 - std::sqrt(static_cast<CoeffDataType>(2.) * gain) * c + gain * c * c) / d; 270 1 : coefficients_out[1] = - 2 * (c * c - 1) / d; 271 1 : coefficients_out[0] = - (1 - std::sqrt(static_cast<CoeffDataType>(2.)) * c + c * c) / d; 272 : } 273 13 : } 274 : 275 : template <typename DataType_> 276 4 : void SecondOrderLowShelvingCoefficients<DataType_>::set_gain(CoeffDataType gain) 277 : { 278 4 : this->gain = gain; 279 4 : setup(); 280 4 : } 281 : 282 : template <typename DataType_> 283 1 : typename SecondOrderLowShelvingCoefficients<DataType_>::CoeffDataType SecondOrderLowShelvingCoefficients<DataType_>::get_gain() const 284 : { 285 1 : return gain; 286 : } 287 : 288 : template<typename DataType_> 289 4 : SecondOrderHighShelvingCoefficients<DataType_>::SecondOrderHighShelvingCoefficients(gsl::index nb_channels) 290 4 : :Parent(nb_channels) 291 : { 292 4 : } 293 : 294 : template <typename DataType> 295 13 : void SecondOrderHighShelvingCoefficients<DataType>::setup() 296 : { 297 13 : Parent::setup(); 298 : 299 13 : CoeffDataType c = std::tan(boost::math::constants::pi<CoeffDataType>() * cut_frequency / input_sampling_rate); 300 13 : if(gain <= 1) 301 : { 302 12 : CoeffDataType V0 = 1 / gain; 303 12 : CoeffDataType d = (V0 + std::sqrt(static_cast<CoeffDataType>(2.) * V0) * c + c * c); 304 : 305 12 : coefficients_in[2] = -(1 + std::sqrt(static_cast<CoeffDataType>(2.0)) * c + c * c) / d; 306 12 : coefficients_in[1] = -2 * (c * c - 1) / d; 307 12 : coefficients_in[0] = -(1 - std::sqrt(static_cast<CoeffDataType>(2.0)) * c + c * c) / d; 308 12 : coefficients_out[1] = - 2 * (c * c - V0) / d; 309 12 : coefficients_out[0] = - (V0 - std::sqrt(static_cast<CoeffDataType>(2.0) * V0) * c + c * c) / d; 310 : } 311 : else 312 : { 313 1 : CoeffDataType d = (1 + std::sqrt(static_cast<CoeffDataType>(2.)) * c + c * c); 314 : 315 1 : coefficients_in[2] = -(gain + std::sqrt(static_cast<CoeffDataType>(2.0) * gain) * c + c * c) / d; 316 1 : coefficients_in[1] = -2 * (c * c - gain) / d; 317 1 : coefficients_in[0] = -(gain - std::sqrt(static_cast<CoeffDataType>(2.0) * gain) * c + c * c) / d; 318 1 : coefficients_out[1] = - 2 * (c * c - 1) / d; 319 1 : coefficients_out[0] = - (1 - std::sqrt(static_cast<CoeffDataType>(2.0)) * c + c * c) / d; 320 : } 321 13 : } 322 : 323 : template<typename DataType_> 324 4 : void SecondOrderHighShelvingCoefficients<DataType_>::set_gain(CoeffDataType gain) 325 : { 326 4 : this->gain = gain; 327 4 : setup(); 328 4 : } 329 : 330 : template <typename DataType_> 331 1 : typename SecondOrderHighShelvingCoefficients<DataType_>::CoeffDataType SecondOrderHighShelvingCoefficients<DataType_>::get_gain() const 332 : { 333 1 : return gain; 334 : } 335 : }