From 3bfc9d6abfe681e610f4e1eb3cb01f008f3bfbbf Mon Sep 17 00:00:00 2001 From: Tellicious Date: Sat, 1 Jun 2024 00:01:33 +0200 Subject: [PATCH] Added band-pass and band-stop filter coefficients calculation to IIRFilters.c --- .github/releaseBody.md | 7 +++++-- Changelog.md | 9 ++++++++- inc/IIRFilters.h | 22 +++++++++++++++++++++- src/IIRFilters.c | 25 ++++++++++++++++++++++++- 4 files changed, 58 insertions(+), 5 deletions(-) diff --git a/.github/releaseBody.md b/.github/releaseBody.md index 5815b4a..63a5572 100644 --- a/.github/releaseBody.md +++ b/.github/releaseBody.md @@ -1,6 +1,9 @@ -## Added assertions to verify correctness of parameters +## Added band-pass and band-stop filter coefficients calculation to IIRFilters.c **Improvements:** -- Added assertions to `matrix.c` and `numMethods.c` +- Added band-pass and band-stop filter coefficients calculation to `IIRFilters.c` to simplify initialization + +**Bugfix:** +- Fixed minor bug in `IIRFilters.c` See [Changelog](Changelog.md) \ No newline at end of file diff --git a/Changelog.md b/Changelog.md index 5c846c8..fae7c95 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,13 @@ # Changelog +## v1.12.0 + +**Improvements:** +- Added band-pass and band-stop filter coefficients calculation to `IIRFilters.c` to simplify initialization + +**Bugfix:** +- Fixed minor bug in `IIRFilters.c` + ## v1.11.1 **Improvements:** @@ -100,7 +108,6 @@ - Fixed snippets - Renamed a few variables inside PID object - ## v1.2.0 **Improvements:** diff --git a/inc/IIRFilters.h b/inc/IIRFilters.h index 2ea3085..bfd59dd 100644 --- a/inc/IIRFilters.h +++ b/inc/IIRFilters.h @@ -98,11 +98,31 @@ void IIRFilterInitLP(IIRFilterGeneric_t* filter, float lpFreq, float dT_ms); * \brief Initialize second-order Butterworth high-pass IIR filter * * \param[in] filter: pointer to IIR filter structure - * \param[in] hpFreq: low-pass cutoff frequency in Hz + * \param[in] hpFreq: high-pass cutoff frequency in Hz * \param[in] dT_ms: sampling time in ms */ void IIRFilterInitHP(IIRFilterGeneric_t* filter, float hpFreq, float dT_ms); +/** + * \brief Initialize second-order Butterworth band-pass IIR filter + * + * \param[in] filter: pointer to IIR filter structure + * \param[in] centerFreq: center frequency of pass-band in Hz + * \param[in] bandwidth: bandwidth of pass-band in Hz. Response will be symmetrical around centerFreq on a logarithmic scale + * \param[in] dT_ms: sampling time in ms + */ +void IIRFilterInitBP(IIRFilterGeneric_t* filter, float centerFreq, float bandwidth, float dT_ms); + +/** + * \brief Initialize second-order Butterworth band-stop IIR filter + * + * \param[in] filter: pointer to IIR filter structure + * \param[in] centerFreq: center frequency of stop-band in Hz + * \param[in] bandwidth: bandwidth of stop-band in Hz. Response will be symmetrical around centerFreq on a logarithmic scale + * \param[in] dT_ms: sampling time in ms + */ +void IIRFilterInitBS(IIRFilterGeneric_t* filter, float centerFreq, float bandwidth, float dT_ms); + /** * \brief Apply generic IIR filter to provided sample * diff --git a/src/IIRFilters.c b/src/IIRFilters.c index 67750c7..8856275 100644 --- a/src/IIRFilters.c +++ b/src/IIRFilters.c @@ -64,7 +64,7 @@ void IIRFilterInitLP(IIRFilterGeneric_t* filter, float lpFreq, float dT_ms) { } void IIRFilterInitHP(IIRFilterGeneric_t* filter, float hpFreq, float dT_ms) { - const float lambda = 1.f / TAN(3.141592653f * (hpFreq * dT_ms * 1e-3f)); + const float lambda = 1.f / TAN(constPI * (hpFreq * dT_ms * 1e-3f)); const float q = SQRT(2.f); float n0 = 1.f / (1.f + q * lambda + lambda * lambda); float n1 = -2.f * n0 * lambda * lambda; @@ -74,6 +74,29 @@ void IIRFilterInitHP(IIRFilterGeneric_t* filter, float hpFreq, float dT_ms) { IIRFilterInit(filter, n0, n1, n0, 0, d1, d2, 0); } +void IIRFilterInitBP(IIRFilterGeneric_t* filter, float centerFreq, float bandwidth, float dT_ms) { + const float Q = centerFreq / bandwidth; // Q factor + const float C = TAN(constPI * (centerFreq * dT_ms * 1e-3f)); + const float D = 1.f / (1.f + C / Q + C * C); + float n0 = C / Q * D; + float n2 = -n0; + float d1 = 2.f * (C * C - 1.f) * D; + float d2 = (1.f - C / Q + C * C) * D; + IIRFilterInit(filter, n0, 0, n2, 0, d1, d2, 0); +} + +void IIRFilterInitBS(IIRFilterGeneric_t* filter, float centerFreq, float bandwidth, float dT_ms) { + const float Q = centerFreq / bandwidth; // Q factor + const float C = TAN(constPI * (centerFreq * dT_ms * 1e-3f)); + const float D = 1.f / (1.f + C / Q + C * C); + float n0 = (1.f + C * C) * D; + float n1 = 2.f * (C * C - 1.f) * D; + float n2 = n0; + float d1 = 2.f * (C * C - 1.f) * D; + float d2 = (1.f - C / Q + C * C) * D; + IIRFilterInit(filter, n0, n1, n2, 0, d1, d2, 0); +} + float IIRFilterProcess(IIRFilterGeneric_t* filter, float input) { /* Apply the IIR filter equation */ float output;