diff --git a/google-tests/CMakeLists.txt b/google-tests/CMakeLists.txt index 6a7f103..2119c13 100644 --- a/google-tests/CMakeLists.txt +++ b/google-tests/CMakeLists.txt @@ -11,6 +11,10 @@ include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR} libnpy/inclu add_executable(Google_Tests_run test1.cpp) file(COPY test1/data1.npy DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/test1) +file(COPY test1/iir_t1_a.npy DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/test1) +file(COPY test1/iir_t1_b.npy DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/test1) +file(COPY test1/iir_t1_x.npy DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/test1) +file(COPY test1/iir_t1_y.npy DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/test1) target_link_libraries(Google_Tests_run pasada) #target_include_directories(Google_Tests_run PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/pasada-lib/include") diff --git a/google-tests/test1.cpp b/google-tests/test1.cpp index f576e76..c9fd64d 100644 --- a/google-tests/test1.cpp +++ b/google-tests/test1.cpp @@ -3,6 +3,7 @@ // #include #include "library.h" +#include "iir_filter.h" #include "npy.hpp" #include #include @@ -51,76 +52,6 @@ TEST(HelloTest, Save_npy_matrix) { npy::write_npy(path, d); } -/** Shift register implemented as a circular buffer. */ -class Buf { -protected: - std::vector data; - size_t size; - size_t n; -public: - Buf(size_t N): size(N), n(0) { - data.resize(N); - data.assign(N, 0.0); - } - void push(double val) { - data[n] = val; - n = (n+1) % size; - } -}; - -/** Running filter base. */ -class Filt : Buf { -protected: - std::vector taps; - size_t shift; - size_t offset; -public: - Filt(size_t N, size_t shift, size_t offset, std::vector taps): Buf(N), shift(shift), offset(offset), taps(taps) { - if (taps.size() != N) throw std::invalid_argument("taps.size() != N"); - } - double filter(double val) { - this->push(val); - return this->peek(); - } - double peek() { - double sum = 0; - for (size_t i = offset; i < this->size; i++) { - //size_t n = (this->n - i + shift - 1) % this->size; // unsigned % size ... bad if u is negative - size_t n = (this->size + this->n - i + shift - 1) % this->size; - //std::cout << " t[" << i << "] * v[" << n << "]" << std::endl; - sum += this->data[n] * this->taps[i]; - } - return sum; - } - void push(double val) { - Buf::push(val); - } -}; - -class IirFilter { -protected: - Filt y; - Filt x; -public: - IirFilter(std::vector b, std::vector a) : x(b.size(), 0, 0, b), y(a.size(), 1, 1, a) { - if (b.size() != a.size()) throw std::invalid_argument("b.size() != a.size()"); - } - double filter(double val) { - //std::cout << "x.filter(" << val << ")" << std::endl; - double xv = x.filter(val); - //std::cout << "xv=" << xv << std::endl; - //std::cout << "y.peek()" << std::endl; - double yv = y.peek(); - //std::cout << "yv=" << yv << std::endl; - //std::cout << "---" << std::endl; - double yo = xv - yv; - y.push(yo); - return yo; - } -}; - -// TODO: copy npy files from CMake output folder -// TODO: add npy files to CMakeLists.txt so they are copied into output folder TEST(HelloTest, Test_IIR_1_Apply_IIR) { npy::npy_data x = npy::read_npy("test1/iir_t1_x.npy"); npy::npy_data y_e = npy::read_npy("test1/iir_t1_y.npy"); diff --git a/google-tests/test1/iir_t1_a.npy b/google-tests/test1/iir_t1_a.npy new file mode 100644 index 0000000..63e37c1 Binary files /dev/null and b/google-tests/test1/iir_t1_a.npy differ diff --git a/google-tests/test1/iir_t1_b.npy b/google-tests/test1/iir_t1_b.npy new file mode 100644 index 0000000..9d18c84 Binary files /dev/null and b/google-tests/test1/iir_t1_b.npy differ diff --git a/google-tests/test1/iir_t1_x.npy b/google-tests/test1/iir_t1_x.npy new file mode 100644 index 0000000..d6351a5 Binary files /dev/null and b/google-tests/test1/iir_t1_x.npy differ diff --git a/google-tests/test1/iir_t1_y.npy b/google-tests/test1/iir_t1_y.npy new file mode 100644 index 0000000..9a4d017 Binary files /dev/null and b/google-tests/test1/iir_t1_y.npy differ diff --git a/pasada-lib/CMakeLists.txt b/pasada-lib/CMakeLists.txt index 22a82a8..64f1494 100644 --- a/pasada-lib/CMakeLists.txt +++ b/pasada-lib/CMakeLists.txt @@ -2,6 +2,7 @@ project(Pasada_Lib) SET(PASADA_SRC library.cpp + iir_filter.cpp ) if(PASADA_BUILD_TESTS) diff --git a/pasada-lib/iir_filter.cpp b/pasada-lib/iir_filter.cpp new file mode 100644 index 0000000..6c308b5 --- /dev/null +++ b/pasada-lib/iir_filter.cpp @@ -0,0 +1,51 @@ +// +// Created by david on 02.03.2026. +// + +#include "iir_filter.h" + +Buf::Buf(size_t N): size(N), n(0) { + data.resize(N); + data.assign(N, 0.0); +} +void Buf::push(double val) { + data[n] = val; + n = (n+1) % size; +} + +Filt::Filt(size_t N, size_t shift, size_t offset, std::vector taps): Buf(N), shift(shift), offset(offset), taps(taps) { + if (taps.size() != N) throw std::invalid_argument("taps.size() != N"); +} +double Filt::filter(double val) { + this->push(val); + return this->peek(); +} +double Filt::peek() { + double sum = 0; + for (size_t i = offset; i < this->size; i++) { + //size_t n = (this->n - i + shift - 1) % this->size; // unsigned % size ... bad if u is negative + size_t n = (this->size + this->n - i + shift - 1) % this->size; + //std::cout << " t[" << i << "] * v[" << n << "]" << std::endl; + sum += this->data[n] * this->taps[i]; + } + return sum; +} +void Filt::push(double val) { + Buf::push(val); +} + +IirFilter::IirFilter(std::vector b, std::vector a) : x(b.size(), 0, 0, b), y(a.size(), 1, 1, a) { + if (b.size() != a.size()) throw std::invalid_argument("b.size() != a.size()"); +} +double IirFilter::filter(double val) { + //std::cout << "x.filter(" << val << ")" << std::endl; + double xv = x.filter(val); + //std::cout << "xv=" << xv << std::endl; + //std::cout << "y.peek()" << std::endl; + double yv = y.peek(); + //std::cout << "yv=" << yv << std::endl; + //std::cout << "---" << std::endl; + double yo = xv - yv; + y.push(yo); + return yo; +} diff --git a/pasada-lib/include/iir_filter.h b/pasada-lib/include/iir_filter.h new file mode 100644 index 0000000..b3fca5f --- /dev/null +++ b/pasada-lib/include/iir_filter.h @@ -0,0 +1,46 @@ +// +// Created by david on 02.03.2026. +// + +#ifndef PASADASUPERPROJECT_IIR_FILTER_H +#define PASADASUPERPROJECT_IIR_FILTER_H + +#include +#include +#include + +/** Shift register implemented as a circular buffer. */ +class Buf { +protected: + std::vector data; + size_t size; + size_t n; +public: + Buf(size_t N); + void push(double val); +}; + +/** Running filter base. */ +class Filt : Buf { +protected: + std::vector taps; + size_t shift; + size_t offset; +public: + Filt(size_t N, size_t shift, size_t offset, std::vector taps); + double filter(double val); + double peek(); + void push(double val); +}; + +/** Running IIR filter. */ +class IirFilter { +protected: + Filt y; + Filt x; +public: + IirFilter(std::vector b, std::vector a); + double filter(double val); +}; + +#endif //PASADASUPERPROJECT_IIR_FILTER_H \ No newline at end of file