#ifndef FIRREAL_H #define FIRREAL_H #include #include #include #include "../../../Assertions.h" namespace FIR { namespace Real { using Kernel = std::vector; using DataVec = std::vector; class Filter { Kernel kernel; DataVec data; public: /** ctor */ Filter(const Kernel& kernel) : kernel(kernel) { ; } /** empty ctor */ Filter() : kernel() { ; } /** set the filter-kernel */ void setKernel(const Kernel& kernel) { this->kernel = kernel; } /** filter the given incoming real data */ DataVec append(const DataVec& newData) { // append to local buffer (as we need some history) data.insert(data.end(), newData.begin(), newData.end()); return processLocalBuffer(); } /** filter the given incoming real value */ float append(const float val) { data.push_back(val); auto tmp = processLocalBuffer(); if (tmp.size() == 0) {return NAN;} if (tmp.size() == 1) {return tmp[0];} throw Exception("FIR::Real::Filter detected invalid result"); } private: DataVec processLocalBuffer() { // sanity check Assert::isNot0(kernel.size(), "FIRComplex:: kernel not yet configured!"); // number of processable elements (due to filter size) const int processable = data.size() - kernel.size() + 1 - kernel.size()/2; // nothing to-do? if (processable <= 0) {return DataVec();} // result-vector DataVec res; res.resize(processable); // fire convolve(data.data(), res.data(), processable); // drop processed elements from the local buffer data.erase(data.begin(), data.begin() + processable); // done return res; } template void convolve(const float* src, T* dst, const size_t cnt) { const size_t ks = kernel.size(); for (size_t i = 0; i < cnt; ++i) { T t = T(); for (size_t j = 0; j < ks; ++j) { t += src[j+i] * kernel[j]; } if (t != t) {throw std::runtime_error("detected NaN");} dst[i] = t; } } }; } } #endif // FIRREAL_H