NotchFilter.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. */
  13. #include "NotchFilter.h"
  14. /*
  15. calculate the attenuation and quality factors of the filter
  16. */
  17. template <class T>
  18. void NotchFilter<T>::calculate_A_and_Q(float center_freq_hz, float bandwidth_hz, float attenuation_dB, float& A, float& Q) {
  19. A = powf(10, -attenuation_dB / 40.0f);
  20. if (center_freq_hz > 0.5 * bandwidth_hz) {
  21. const float octaves = log2f(center_freq_hz / (center_freq_hz - bandwidth_hz / 2.0f)) * 2.0f;
  22. Q = sqrtf(powf(2, octaves)) / (powf(2, octaves) - 1.0f);
  23. } else {
  24. Q = 0.0;
  25. }
  26. }
  27. /*
  28. initialise filter
  29. */
  30. template <class T>
  31. void NotchFilter<T>::init(float sample_freq_hz, float center_freq_hz, float bandwidth_hz, float attenuation_dB)
  32. {
  33. // check center frequency is in the allowable range
  34. if ((center_freq_hz > 0.5 * bandwidth_hz) && (center_freq_hz < 0.5 * sample_freq_hz)) {
  35. float A, Q;
  36. calculate_A_and_Q(center_freq_hz, bandwidth_hz, attenuation_dB, A, Q);
  37. init_with_A_and_Q(sample_freq_hz, center_freq_hz, A, Q);
  38. } else {
  39. initialised = false;
  40. }
  41. }
  42. template <class T>
  43. void NotchFilter<T>::init_with_A_and_Q(float sample_freq_hz, float center_freq_hz, float A, float Q)
  44. {
  45. if ((center_freq_hz > 0.0) && (center_freq_hz < 0.5 * sample_freq_hz) && (Q > 0.0)) {
  46. float omega = 2.0 * M_PI * center_freq_hz / sample_freq_hz;
  47. float alpha = sinf(omega) / (2 * Q);
  48. b0 = 1.0 + alpha*sq(A);
  49. b1 = -2.0 * cosf(omega);
  50. b2 = 1.0 - alpha*sq(A);
  51. a0_inv = 1.0/(1.0 + alpha);
  52. a1 = b1;
  53. a2 = 1.0 - alpha;
  54. initialised = true;
  55. } else {
  56. initialised = false;
  57. }
  58. }
  59. /*
  60. apply a new input sample, returning new output
  61. */
  62. template <class T>
  63. T NotchFilter<T>::apply(const T &sample)
  64. {
  65. if (!initialised) {
  66. // if we have not been initialised when return the input
  67. // sample as output and update delayed samples
  68. ntchsig2 = ntchsig1;
  69. ntchsig1 = ntchsig;
  70. ntchsig = sample;
  71. signal2 = signal1;
  72. signal1 = sample;
  73. return sample;
  74. }
  75. ntchsig2 = ntchsig1;
  76. ntchsig1 = ntchsig;
  77. ntchsig = sample;
  78. T output = (ntchsig*b0 + ntchsig1*b1 + ntchsig2*b2 - signal1*a1 - signal2*a2) * a0_inv;
  79. signal2 = signal1;
  80. signal1 = output;
  81. return output;
  82. }
  83. template <class T>
  84. void NotchFilter<T>::reset()
  85. {
  86. ntchsig2 = ntchsig1 = T();
  87. signal2 = signal1 = T();
  88. }
  89. // table of user settable parameters
  90. const AP_Param::GroupInfo NotchFilterParams::var_info[] = {
  91. // @Param: ENABLE
  92. // @DisplayName: Enable
  93. // @Description: Enable notch filter
  94. // @Values: 0:Disabled,1:Enabled
  95. // @User: Advanced
  96. AP_GROUPINFO_FLAGS("ENABLE", 1, NotchFilterParams, _enable, 0, AP_PARAM_FLAG_ENABLE),
  97. // Slots 2 and 3 are reserved - they were integer versions of FREQ and BW which have since been converted to float
  98. // @Param: ATT
  99. // @DisplayName: Attenuation
  100. // @Description: Notch attenuation in dB
  101. // @Range: 5 30
  102. // @Units: dB
  103. // @User: Advanced
  104. AP_GROUPINFO("ATT", 4, NotchFilterParams, _attenuation_dB, 15),
  105. // @Param: FREQ
  106. // @DisplayName: Frequency
  107. // @Description: Notch center frequency in Hz
  108. // @Range: 10 400
  109. // @Units: Hz
  110. // @User: Advanced
  111. AP_GROUPINFO("FREQ", 5, NotchFilterParams, _center_freq_hz, 80),
  112. // @Param: BW
  113. // @DisplayName: Bandwidth
  114. // @Description: Notch bandwidth in Hz
  115. // @Range: 5 100
  116. // @Units: Hz
  117. // @User: Advanced
  118. AP_GROUPINFO("BW", 6, NotchFilterParams, _bandwidth_hz, 20),
  119. AP_GROUPEND
  120. };
  121. /*
  122. a notch filter with enable and filter parameters - constructor
  123. */
  124. NotchFilterParams::NotchFilterParams(void)
  125. {
  126. AP_Param::setup_object_defaults(this, var_info);
  127. }
  128. /*
  129. instantiate template classes
  130. */
  131. template class NotchFilter<float>;
  132. template class NotchFilter<Vector3f>;