firfilter.hh
#ifndef __SDR_FIRFILTER_HH__
#define __SDR_FIRFILTER_HH__
#include "config.hh"
#include "node.hh"
#include "logger.hh"
namespace sdr {
class FIRLowPassCoeffs
{
public:
static inline void coeffs(std::vector<double> &alpha, double Fl, double Fu, double Fs)
{
size_t N = alpha.size();
double w = 2*M_PI*Fu/Fs;
double M = double(N)/2;
double norm = 0;
for (size_t i=0; i<N; i++) {
if (N == 2*i) { alpha[i] = 4*w/M_PI; }
else { alpha[i] = std::sin(w*(i-M))/(w*(i-M)); }
// apply window function
alpha[i] *= (0.42 - 0.5*cos((2*M_PI*i)/N) + 0.08*cos((4*M_PI*i)/N));
// Calc norm
norm += std::abs(alpha[i]);
}
// Normalize filter coeffs:
for (size_t i=0; i<N; i++) { alpha[i] /= norm; }
}
};
class FIRHighPassCoeffs
{
public:
static inline void coeffs(std::vector<double> &alpha, double Fl, double Fu, double Fs)
{
size_t N = alpha.size();
double w = 2*M_PI*Fl/Fs;
double M = double(N)/2;
double norm = 0;
for (size_t i=0; i<N; i++) {
if (N == 2*i) { alpha[i] = -std::sin(w*(i-M))/(w*(i-N)); }
else { alpha[i] = 1-4*w/M_PI; }
// apply window function
alpha[i] *= (0.42 - 0.5*cos((2*M_PI*i)/N) + 0.08*cos((4*M_PI*i)/N));
norm += std::abs(alpha[i]);
}
// Normalize filter coeffs:
for (size_t i=0; i<N; i++) { alpha[i] /= norm; }
}
};
class FIRBandPassCoeffs
{
public:
static inline void coeffs(std::vector<double> &alpha, double Fl, double Fu, double Fs)
{
size_t N = alpha.size();
double wl = 2*M_PI*Fl/Fs;
double wu = 2*M_PI*Fu/Fs;
double M = double(N)/2;
double norm = 0;
for (size_t i=0; i<N; i++) {
if (N == 2*i) { alpha[i] = 4*(wl-wu)/M_PI; }
else { alpha[i] = std::sin(wl*(i-M)/(wl*(i-M))) - std::sin(wu*(i-M)/(wu*(i-M))); }
// apply window function
alpha[i] *= (0.42 - 0.5*cos((2*M_PI*i)/N) + 0.08*cos((4*M_PI*i)/N));
norm += std::abs(alpha[i]);
}
// Normalize filter coeffs:
for (size_t i=0; i<N; i++) { alpha[i] /= norm; }
}
};
class FIRBandStopCoeffs
{
public:
static inline void coeffs(std::vector<double> &alpha, double Fl, double Fu, double Fs)
{
size_t N = alpha.size();
double wl = 2*M_PI*Fl/Fs;
double wu = 2*M_PI*Fl/Fs;
double M = double(N)/2;
double norm = 0;
for (size_t i=0; i<N; i++) {
if (N == 2*i) { alpha[i] = 1-4*(wl-wu)/M_PI; }
else { alpha[i] = std::sin(wu*(i-M)/(wu*(i-M))) - std::sin(wl*(i-M)/(wl*(i-M))); }
// apply window function
alpha[i] *= (0.42 - 0.5*cos((2*M_PI*i)/N) + 0.08*cos((4*M_PI*i)/N));
norm += std::abs(alpha[i]);
}
// Normalize filter coeffs:
for (size_t i=0; i<N; i++) { alpha[i] /= norm; }
}
};
template <class Scalar, class FilterCoeffs>
class FIRFilter: public Sink<Scalar>, public Source
{
public:
FIRFilter(size_t order, double Fl, double Fu)
: Sink<Scalar>(), Source(), _enabled(true), _order(std::max(size_t(1), order)), _Fl(Fl), _Fu(Fu),
_Fs(0), _alpha(_order, 0), _ring(_order), _ring_offset(0)
{
// pass...
}
virtual ~FIRFilter() {
_ring.unref();
_buffer.unref();
}
inline bool enabled() const { return _enabled; }
inline void enable(bool enable) { _enabled = enable; }
inline size_t order() const { return _order; }
virtual void setOrder(size_t order) {
// Ensure order is larger 0:
order = std::max(size_t(1), order);
if (order == _order) { return; }
_order = order;
// Resize past and coeffs
_alpha.resize(_order);
_ring = Buffer<Scalar>(_order);
_ring_offset = 0;
// Update coeffs:
FilterCoeffs::coeffs(_alpha, _Fl, _Fu, _Fs);
}
inline double lowerFreq() const { return _Fl; }
inline void setLowerFreq(double Fl) {
_Fl = Fl;
FilterCoeffs::coeffs(_alpha, _Fl, _Fu, _Fs);
}
inline double uppertFreq() const { return _Fl; }
inline void setUpperFreq(double Fu) {
_Fu = Fu;
FilterCoeffs::coeffs(_alpha, _Fl, _Fu, _Fs);
}
virtual void config(const Config &src_cfg) {
// Requires type, sample-rate and buffer-size
if (!src_cfg.hasType() || !src_cfg.hasSampleRate() || !src_cfg.hasBufferSize()) { return; }
// check type
if (Config::typeId<Scalar>() != src_cfg.type()) {
ConfigError err;
err << "Can not configure FIRLowPass: Invalid type " << src_cfg.type()
<< ", expected " << Config::typeId<Scalar>();
throw err;
}
// Calc coeff
_Fs = src_cfg.sampleRate();
FilterCoeffs::coeffs(_alpha, _Fl, _Fu, _Fs);
// unref buffer if non-empty
if (!_buffer.isEmpty()) { _buffer.unref(); }
// allocate buffer
_buffer = Buffer<Scalar>(src_cfg.bufferSize());
// Clear ring buffer
for (size_t i=0; i<_order; i++) { _ring[i] = 0; }
_ring_offset = 0;
LogMessage msg(LOG_DEBUG);
msg << "Configured FIRFilter:" << std::endl
<< " type " << src_cfg.type() << std::endl
<< " sample rate " << _Fs << std::endl
<< " buffer size " << src_cfg.bufferSize() << std::endl
<< " order " << _order;
Logger::get().log(msg);
// Propergate config
this->setConfig(Config(src_cfg.type(), src_cfg.sampleRate(), src_cfg.bufferSize(), 1));
}
virtual void process(const Buffer<Scalar> &buffer, bool allow_overwrite) {
// If emtpy
if (0 == buffer.size()) { /* drop buffer */ }
// If disabled -> pass
if (!_enabled) { this->send(buffer, allow_overwrite); return; }
// Perform filtering in-place or out-of-place filtering
if (allow_overwrite) { _process(buffer, buffer); }
else if (_buffer.isUnused()) { _process(buffer, _buffer); }
else {
#ifdef SDR_DEBUG
LogMessage msg(LOG_WARNING);
msg << "FIR Filter: Drop buffer, output buffer still in use.";
Logger::get().log(msg);
#endif
}
}
protected:
inline void _process(const Buffer<Scalar> &in, const Buffer<Scalar> &out)
{
for (size_t i=0; i<in.size(); i++) {
// Store input value into ring buffer
_ring[_ring_offset] = in[i]; _ring_offset++;
if (_ring_offset == _order) { _ring_offset=0; }
out[i] = 0;
// Apply filter on ring buffer
size_t idx = _ring_offset;
for (size_t j=0; j<_order; j++, idx++) {
if (idx == _order) { idx = 0; }
out[i] += _alpha[j]*_ring[idx];
}
}
// Done.
this->send(out.head(in.size()), true);
}
protected:
bool _enabled;
size_t _order;
double _Fl;
double _Fu;
double _Fs;
std::vector<double> _alpha;
Buffer<Scalar> _ring;
size_t _ring_offset;
Buffer<Scalar> _buffer;
};
template <class Scalar>
class FIRLowPass: public FIRFilter<Scalar, FIRLowPassCoeffs>
{
public:
FIRLowPass(size_t order, double Fc)
: FIRFilter<Scalar, FIRLowPassCoeffs>(order, 0, Fc) { }
virtual ~FIRLowPass() { }
inline double freq() const { return FIRFilter<Scalar, FIRLowPassCoeffs>::_Fu; }
inline void setFreq(double freq) { FIRFilter<Scalar, FIRLowPassCoeffs>::setUpperFreq(freq); }
};
template <class Scalar>
class FIRHighPass: public FIRFilter<Scalar, FIRHighPassCoeffs>
{
public:
FIRHighPass(size_t order, double Fc)
: FIRFilter<Scalar, FIRHighPassCoeffs>(order, Fc, 0) { }
virtual ~FIRHighPass() { }
inline double freq() const { return FIRFilter<Scalar, FIRLowPassCoeffs>::_Fl; }
inline void setFreq(double freq) { FIRFilter<Scalar, FIRLowPassCoeffs>::setLowerFreq(freq); }
};
template <class Scalar>
class FIRBandPass: public FIRFilter<Scalar, FIRBandPassCoeffs>
{
public:
FIRBandPass(size_t order, double Fl, double Fu)
: FIRFilter<Scalar, FIRBandPassCoeffs>(order, Fl, Fu) { }
virtual ~FIRBandPass() { }
};
template <class Scalar>
class FIRBandStop: public FIRFilter<Scalar, FIRBandStopCoeffs>
{
public:
FIRBandStop(size_t order, double Fl, double Fu)
: FIRFilter<Scalar, FIRBandStopCoeffs>(order, Fl, Fu) { }
virtual ~FIRBandStop() { }
};
}
#endif // FIRFILTER_HH
sdr::FIRBandStop
Band-stop FIR filter specialization.
Definition: firfilter.hh:324
sdr::FIRBandStop::~FIRBandStop
virtual ~FIRBandStop()
Destructor.
Definition: firfilter.hh:331
sdr::Config
A collection of configuration information that is send by a source to all connected sinks to properga...
Definition: node.hh:35
sdr::FIRFilter::~FIRFilter
virtual ~FIRFilter()
Destructor.
Definition: firfilter.hh:129
sdr::FIRBandPass
Band-pass FIR filter specialization.
Definition: firfilter.hh:311
sdr::FIRBandStopCoeffs::coeffs
static void coeffs(std::vector< double > &alpha, double Fl, double Fu, double Fs)
Calculates the filter coefficients.
Definition: firfilter.hh:93
sdr::FIRFilter::_Fu
double _Fu
The upper edge frequency.
Definition: firfilter.hh:259
sdr::FIRBandPassCoeffs::coeffs
static void coeffs(std::vector< double > &alpha, double Fl, double Fu, double Fs)
Calculates the filter coefficients.
Definition: firfilter.hh:67
sdr::FIRLowPassCoeffs
Implements the calculation of the filter coefficients for the use in the FIRFilter template class...
Definition: firfilter.hh:12
sdr::FIRFilter::_Fs
double _Fs
Current sample rate.
Definition: firfilter.hh:261
sdr::Source::send
virtual void send(const RawBuffer &buffer, bool allow_overwrite=false)
Sends the given buffer to all connected sinks.
Definition: node.cc:67
sdr::FIRFilter::_process
void _process(const Buffer< Scalar > &in, const Buffer< Scalar > &out)
performs the actual computation
Definition: firfilter.hh:231
sdr::Sink
Typed sink.
Definition: node.hh:192
sdr::FIRHighPass::freq
double freq() const
Returns the filter frequency.
Definition: firfilter.hh:302
sdr
Definition: autocast.hh:8
sdr::RawBuffer::isEmpty
bool isEmpty() const
Returns true if the buffer is invalid/empty.
Definition: buffer.hh:77
std
Definition: operators.hh:9
sdr::FIRHighPass::FIRHighPass
FIRHighPass(size_t order, double Fc)
Constructor.
Definition: firfilter.hh:297
sdr::Config::hasSampleRate
bool hasSampleRate() const
If true, the configuration has a sample rate.
Definition: node.hh:75
sdr::Source
Generic source class.
Definition: node.hh:213
sdr::FIRBandStopCoeffs
Implements the calculation of the filter coefficients for the use in the FIRFilter template class...
Definition: firfilter.hh:89
sdr::FIRLowPass::~FIRLowPass
virtual ~FIRLowPass()
Destructor.
Definition: firfilter.hh:283
sdr::FIRHighPass::~FIRHighPass
virtual ~FIRHighPass()
Destructor.
Definition: firfilter.hh:300
sdr::FIRLowPassCoeffs::coeffs
static void coeffs(std::vector< double > &alpha, double Fl, double Fu, double Fs)
Calculates the filter coefficients.
Definition: firfilter.hh:16
sdr::Buffer::size
size_t size() const
Returns the number of elements of type T in this buffer.
Definition: buffer.hh:166
sdr::Config::hasType
bool hasType() const
If true, the configuration has a type.
Definition: node.hh:69
sdr::FIRFilter::lowerFreq
double lowerFreq() const
Returns the lower edge frequency.
Definition: firfilter.hh:156
sdr::Source::setConfig
virtual void setConfig(const Config &config)
Stores the configuration and propergates it if the configuration has been changed.
Definition: node.cc:98
sdr::FIRFilter::_ring
Buffer< Scalar > _ring
A "ring-buffer" used to perform the filtering.
Definition: firfilter.hh:265
sdr::Buffer::head
Buffer< T > head(size_t n) const
Returns a new view on this buffer.
Definition: buffer.hh:237
sdr::FIRLowPass::FIRLowPass
FIRLowPass(size_t order, double Fc)
Constructor.
Definition: firfilter.hh:280
sdr::FIRBandPassCoeffs
Implements the calculation of the filter coefficients for the use in the FIRFilter template class...
Definition: firfilter.hh:63
sdr::FIRHighPassCoeffs
Implements the calculation of the filter coefficients for the use in the FIRFilter template class...
Definition: firfilter.hh:38
sdr::FIRFilter::_enabled
bool _enabled
If true, the filtering is enabled.
Definition: firfilter.hh:253
sdr::FIRFilter
Generic FIR filter class.
Definition: firfilter.hh:117
sdr::FIRFilter::enable
void enable(bool enable)
Enable/Disable the filter.
Definition: firfilter.hh:137
sdr::FIRBandStop::FIRBandStop
FIRBandStop(size_t order, double Fl, double Fu)
Constructor.
Definition: firfilter.hh:328
sdr::FIRBandPass::~FIRBandPass
virtual ~FIRBandPass()
Destructor.
Definition: firfilter.hh:318
sdr::Logger::log
void log(const LogMessage &message)
Logs a message.
Definition: logger.cc:100
sdr::Config::type
Type type() const
Returns the type.
Definition: node.hh:71
sdr::FIRLowPass::freq
double freq() const
Returns the filter frequency.
Definition: firfilter.hh:285
sdr::FIRBandPass::FIRBandPass
FIRBandPass(size_t order, double Fl, double Fu)
Constructor.
Definition: firfilter.hh:315
sdr::FIRHighPassCoeffs::coeffs
static void coeffs(std::vector< double > &alpha, double Fl, double Fu, double Fs)
Calculates the filter coefficients.
Definition: firfilter.hh:42
sdr::Logger::get
static Logger & get()
Returns the singleton instance of the logger.
Definition: logger.cc:89
sdr::ConfigError
The configuration error class.
Definition: exception.hh:24
sdr::LogMessage
A log message.
Definition: logger.hh:22
sdr::Config::bufferSize
size_t bufferSize() const
Returns the max.
Definition: node.hh:83
sdr::FIRFilter::_ring_offset
size_t _ring_offset
Offset of the "ring-buffer".
Definition: firfilter.hh:267
sdr::FIRFilter::setOrder
virtual void setOrder(size_t order)
Sets the order of the filter and updates the filter coefficients.
Definition: firfilter.hh:142
sdr::FIRFilter::order
size_t order() const
Returns the order of the filter.
Definition: firfilter.hh:140
sdr::FIRFilter::uppertFreq
double uppertFreq() const
Returns the upper edge frequency.
Definition: firfilter.hh:164
sdr::FIRFilter::_buffer
Buffer< Scalar > _buffer
The output buffer, unused if filtering is performed in-place.
Definition: firfilter.hh:269
sdr::FIRFilter::_order
size_t _order
The order of the filter.
Definition: firfilter.hh:255
sdr::FIRFilter::config
virtual void config(const Config &src_cfg)
Configures the filter.
Definition: firfilter.hh:172
sdr::FIRFilter::enabled
bool enabled() const
Returns true if the filter is enabled.
Definition: firfilter.hh:135
sdr::FIRHighPass::setFreq
void setFreq(double freq)
Sets the filter frequency.
Definition: firfilter.hh:304
sdr::FIRFilter::_alpha
std::vector< double > _alpha
The current filter coefficients.
Definition: firfilter.hh:263
sdr::RawBuffer::unref
void unref()
Dereferences the buffer.
Definition: buffer.cc:63
sdr::FIRHighPass
High-pass FIR filter specialization.
Definition: firfilter.hh:293
sdr::RawBuffer::isUnused
bool isUnused() const
We assume here that buffers are owned by one object: A buffer is therefore "unused" if the owner hold...
Definition: buffer.hh:87
sdr::FIRLowPass::setFreq
void setFreq(double freq)
Sets the filter frequency.
Definition: firfilter.hh:287
sdr::FIRFilter::setLowerFreq
void setLowerFreq(double Fl)
Sets the lower edge frequency.
Definition: firfilter.hh:158
sdr::FIRFilter::_Fl
double _Fl
The lower edge frequency.
Definition: firfilter.hh:257
sdr::FIRFilter::setUpperFreq
void setUpperFreq(double Fu)
Sets the upper edge frequency.
Definition: firfilter.hh:166
sdr::FIRLowPass
Low-pass FIR filter specialization.
Definition: firfilter.hh:276
sdr::Buffer< Scalar >
sdr::Config::hasBufferSize
bool hasBufferSize() const
If true, the configuration has a buffer size.
Definition: node.hh:81
sdr::Config::sampleRate
double sampleRate() const
Returns the sample rate.
Definition: node.hh:77
sdr::FIRFilter::process
virtual void process(const Buffer< Scalar > &buffer, bool allow_overwrite)
Performs the filtering.
Definition: firfilter.hh:211
sdr::FIRFilter::FIRFilter
FIRFilter(size_t order, double Fl, double Fu)
Constructor.
Definition: firfilter.hh:121