2017-12-26 04:59:51 -05:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
2023-11-19 00:43:20 -05:00
|
|
|
// Copyright (C) 2017, 2019-2020 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
|
2017-12-26 04:59:51 -05:00
|
|
|
// //
|
|
|
|
// 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 as version 3 of the License, or //
|
2019-04-11 08:32:15 -04:00
|
|
|
// (at your option) any later version. //
|
2017-12-26 04:59:51 -05:00
|
|
|
// //
|
|
|
|
// 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 V3 for more details. //
|
|
|
|
// //
|
|
|
|
// You should have received a copy of the GNU General Public License //
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2017-12-26 14:29:23 -05:00
|
|
|
/**
|
|
|
|
* IIR filter
|
|
|
|
* See: https://cdn.mikroe.com/ebooks/img/8/2016/02/digital-filter-design-chapter-03-image-2-9.gif
|
|
|
|
*/
|
|
|
|
|
2017-12-26 04:59:51 -05:00
|
|
|
#ifndef SDRBASE_DSP_IIRFILTER_H_
|
|
|
|
#define SDRBASE_DSP_IIRFILTER_H_
|
|
|
|
|
|
|
|
#include <stdint.h>
|
2017-12-26 14:29:23 -05:00
|
|
|
#include <string.h>
|
2017-12-26 04:59:51 -05:00
|
|
|
|
|
|
|
template <typename Type, uint32_t Order> class IIRFilter
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
IIRFilter(const Type *a, const Type *b);
|
|
|
|
~IIRFilter();
|
2017-12-26 14:29:23 -05:00
|
|
|
void setCoeffs(const Type *a, const Type *b);
|
|
|
|
Type run(const Type& sample);
|
2017-12-26 04:59:51 -05:00
|
|
|
|
|
|
|
private:
|
|
|
|
Type *m_a;
|
|
|
|
Type *m_b;
|
|
|
|
Type *m_x;
|
|
|
|
Type *m_y;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename Type> class IIRFilter<Type, 2>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
IIRFilter(const Type *a, const Type *b);
|
|
|
|
~IIRFilter();
|
2017-12-26 14:29:23 -05:00
|
|
|
void setCoeffs(const Type *a, const Type *b);
|
|
|
|
Type run(const Type& sample);
|
2017-12-26 04:59:51 -05:00
|
|
|
|
|
|
|
private:
|
|
|
|
Type m_a[3];
|
|
|
|
Type m_b[3];
|
|
|
|
Type m_x[2];
|
|
|
|
Type m_y[2];
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename Type, uint32_t Order>
|
|
|
|
IIRFilter<Type, Order>::IIRFilter(const Type *a, const Type *b)
|
|
|
|
{
|
|
|
|
m_a = new Type[Order+1];
|
|
|
|
m_b = new Type[Order+1];
|
|
|
|
m_x = new Type[Order];
|
|
|
|
m_y = new Type[Order];
|
|
|
|
|
2017-12-26 14:29:23 -05:00
|
|
|
setCoeffs(a, b);
|
2017-12-26 04:59:51 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Type, uint32_t Order>
|
|
|
|
IIRFilter<Type, Order>::~IIRFilter()
|
|
|
|
{
|
|
|
|
delete[] m_y;
|
|
|
|
delete[] m_x;
|
|
|
|
delete[] m_b;
|
|
|
|
delete[] m_a;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Type, uint32_t Order>
|
2017-12-26 14:29:23 -05:00
|
|
|
void IIRFilter<Type, Order>::setCoeffs(const Type *a, const Type *b)
|
2017-12-26 04:59:51 -05:00
|
|
|
{
|
2017-12-26 14:29:23 -05:00
|
|
|
memcpy(m_a, b, (Order+1)*sizeof(Type));
|
|
|
|
memcpy(m_b, a, (Order+1)*sizeof(Type));
|
2017-12-26 04:59:51 -05:00
|
|
|
|
2017-12-26 14:29:23 -05:00
|
|
|
for (uint32_t i = 0; i < Order; i++)
|
2017-12-26 04:59:51 -05:00
|
|
|
{
|
2017-12-26 14:29:23 -05:00
|
|
|
m_x[i] = 0;
|
|
|
|
m_y[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename Type, uint32_t Order>
|
|
|
|
Type IIRFilter<Type, Order>::run(const Type& sample)
|
|
|
|
{
|
|
|
|
Type y = m_b[0] * sample;
|
|
|
|
|
|
|
|
for (uint32_t i = Order; i > 0; i--)
|
|
|
|
{
|
|
|
|
y += m_b[i] * m_x[i-1] + m_a[i] * m_y[i-1];
|
|
|
|
|
|
|
|
if (i > 1) // shift
|
|
|
|
{
|
|
|
|
m_x[i-1] = m_x[i-2];
|
|
|
|
m_y[i-1] = m_y[i-2];
|
|
|
|
}
|
2017-12-26 04:59:51 -05:00
|
|
|
}
|
|
|
|
|
2017-12-26 14:29:23 -05:00
|
|
|
// last shift
|
2017-12-26 04:59:51 -05:00
|
|
|
m_x[0] = sample;
|
|
|
|
m_y[0] = y;
|
|
|
|
|
2017-12-26 14:29:23 -05:00
|
|
|
return y;
|
2017-12-26 04:59:51 -05:00
|
|
|
}
|
|
|
|
|
2017-12-26 14:29:23 -05:00
|
|
|
|
2017-12-26 04:59:51 -05:00
|
|
|
template <typename Type>
|
|
|
|
IIRFilter<Type, 2>::IIRFilter(const Type *a, const Type *b)
|
2017-12-26 14:29:23 -05:00
|
|
|
{
|
|
|
|
setCoeffs(a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Type>
|
|
|
|
IIRFilter<Type, 2>::~IIRFilter()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Type>
|
|
|
|
void IIRFilter<Type, 2>::setCoeffs(const Type *a, const Type *b)
|
2017-12-26 04:59:51 -05:00
|
|
|
{
|
|
|
|
m_a[0] = a[0];
|
|
|
|
m_a[1] = a[1];
|
|
|
|
m_a[2] = a[2];
|
|
|
|
m_b[0] = b[0];
|
|
|
|
m_b[1] = b[1];
|
|
|
|
m_b[2] = b[2];
|
2017-12-26 14:29:23 -05:00
|
|
|
m_x[0] = 0;
|
|
|
|
m_x[1] = 0;
|
|
|
|
m_y[0] = 0;
|
|
|
|
m_y[1] = 0;
|
2017-12-26 04:59:51 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Type>
|
2017-12-26 14:29:23 -05:00
|
|
|
Type IIRFilter<Type, 2>::run(const Type& sample)
|
2017-12-26 04:59:51 -05:00
|
|
|
{
|
2017-12-26 14:29:23 -05:00
|
|
|
Type y = m_b[0]*sample + m_b[1]*m_x[0] + m_b[2]*m_x[1] + m_a[1]*m_y[0] + m_a[2]*m_y[1]; // this is y[n]
|
2017-12-26 04:59:51 -05:00
|
|
|
|
|
|
|
m_x[1] = m_x[0];
|
|
|
|
m_x[0] = sample;
|
|
|
|
|
|
|
|
m_y[1] = m_y[0];
|
|
|
|
m_y[0] = y;
|
|
|
|
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* SDRBASE_DSP_IIRFILTER_H_ */
|