From 281b18b6ca924acdc417f04ef21655af4788bdcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?BENEDEK=20L=C3=A1szl=C3=B3?= Date: Fri, 14 Mar 2025 12:14:39 +0100 Subject: [PATCH] fix filter generation --- include/filter/filter/filter.hpp | 3 +++ include/filter/filter/low_pass_filter.hpp | 2 +- include/filter/window/hamming_window.hpp | 4 ++- include/filter/window/window.hpp | 5 +++- src/filter/filter/filter.cpp | 30 ++++++++++++++++------- src/filter/filter/low_pass_filter.cpp | 17 ++++++++----- src/filter/main.cpp | 14 +++++++---- src/filter/window/hamming_window.cpp | 14 ++++++++--- 8 files changed, 63 insertions(+), 26 deletions(-) diff --git a/include/filter/filter/filter.hpp b/include/filter/filter/filter.hpp index 50fa37b..9507c85 100644 --- a/include/filter/filter/filter.hpp +++ b/include/filter/filter/filter.hpp @@ -2,6 +2,7 @@ #define FILTER_IFILTER_H #include +#include #include namespace Filter { @@ -14,6 +15,8 @@ class IFilter { IFilter(std::size_t size); virtual ~IFilter(){}; + void Dump(const std::string& path) const; + void ConvolveIQ(const std::vector& input, std::vector& output); }; } // namespace Filter diff --git a/include/filter/filter/low_pass_filter.hpp b/include/filter/filter/low_pass_filter.hpp index 37c588b..86cd704 100644 --- a/include/filter/filter/low_pass_filter.hpp +++ b/include/filter/filter/low_pass_filter.hpp @@ -10,7 +10,7 @@ namespace Filter { class LowPassFilter : public IFilter { public: - LowPassFilter(std::size_t size, std::size_t cutoffHz, std::size_t sampleRateHz, const std::vector& window); + LowPassFilter(std::int32_t size, std::size_t cutoffHz, std::size_t sampleRateHz, const std::vector& window); ~LowPassFilter() override{}; }; } // namespace Filter diff --git a/include/filter/window/hamming_window.hpp b/include/filter/window/hamming_window.hpp index c40767e..aa2ee62 100644 --- a/include/filter/window/hamming_window.hpp +++ b/include/filter/window/hamming_window.hpp @@ -14,7 +14,9 @@ class HammingWindow : public IWindow { HammingWindow(std::size_t width); ~HammingWindow() override {} - const std::vector& getWindow() override { return window; } + + void Dump(const std::string& path) const override; + const std::vector& getWindow() const override { return window; } }; } // namespace Filter diff --git a/include/filter/window/window.hpp b/include/filter/window/window.hpp index e451688..3077ed5 100644 --- a/include/filter/window/window.hpp +++ b/include/filter/window/window.hpp @@ -1,13 +1,16 @@ #ifndef FILTER_IWINDOW_H #define FILTER_IWINDOW_H +#include #include namespace Filter { class IWindow { public: virtual ~IWindow() {} - virtual const std::vector& getWindow() = 0; + + virtual void Dump(const std::string& path) const = 0; + virtual const std::vector& getWindow() const = 0; }; } // namespace Filter diff --git a/src/filter/filter/filter.cpp b/src/filter/filter/filter.cpp index 0c9668d..28bea4b 100644 --- a/src/filter/filter/filter.cpp +++ b/src/filter/filter/filter.cpp @@ -1,31 +1,43 @@ -#include +#include #include #include +#include + namespace Filter { -IFilter::IFilter(std::size_t size) { - impulseResponse.reserve(size); +IFilter::IFilter(std::size_t size) : impulseResponse(size) {} + +void IFilter::Dump(const std::string& path) const { + std::ofstream output; + output.open(path, std::ios::out | std::ios::binary); + output.write(reinterpret_cast(impulseResponse.data()), sizeof(float) * impulseResponse.size()); + output.close(); } void IFilter::ConvolveIQ(const std::vector& input, std::vector& output) { // TODO: SIMD + output.clear(); + auto itIn = input.begin(); auto itOut = output.begin(); while (itIn != input.end()) { + float I = 0, Q = 0; for (float h : impulseResponse) { // I - *itOut += *itIn * h; - itIn++; - itOut++; + I += *itIn * h; // Q - *itOut += *itIn * h; - itIn++; - itOut++; + Q += *itIn * h; } + + *(itOut + 0) = I; + *(itOut + 1) = Q; + + itIn += 2; + itOut += 2; } } } // namespace Filter \ No newline at end of file diff --git a/src/filter/filter/low_pass_filter.cpp b/src/filter/filter/low_pass_filter.cpp index e0f4de4..624f2fd 100644 --- a/src/filter/filter/low_pass_filter.cpp +++ b/src/filter/filter/low_pass_filter.cpp @@ -1,21 +1,26 @@ #include +#include +#include #include #include #include +using std::numbers::pi; + namespace Filter { -LowPassFilter::LowPassFilter(std::size_t size, std::size_t cutoffHz, std::size_t sampleRateHz, const std::vector& window) : IFilter(size) { - for (std::size_t i = 0; i < size; i++) { - std::size_t shift = std::round(size / 2); - float sampleTime = 1.0f / sampleRateHz; +LowPassFilter::LowPassFilter(std::int32_t size, std::size_t cutoffHz, std::size_t sampleRateHz, const std::vector& window) : IFilter(size) { + for (std::int32_t i = 0; i < size; i++) { + int shift = size / 2.0f; + float sampleTimeS = 1.0f / sampleRateHz; + if (shift != i) { - IFilter::impulseResponse[i] = std::sin(2.0f * std::numbers::pi * sampleTime * (i - shift)) / (std::numbers::pi * sampleTime * (i - shift)); + IFilter::impulseResponse[i] = std::sin(2.0f * pi * cutoffHz * sampleTimeS * (i - shift)) / (pi * sampleTimeS * (i - shift)); } else { IFilter::impulseResponse[i] = 2.0f * cutoffHz; } - IFilter::impulseResponse[i] *= sampleTime * window[i]; + IFilter::impulseResponse[i] *= sampleTimeS * window[i]; } } diff --git a/src/filter/main.cpp b/src/filter/main.cpp index e5e5bfa..ad91763 100644 --- a/src/filter/main.cpp +++ b/src/filter/main.cpp @@ -9,6 +9,7 @@ #include const std::size_t BUFFER_SIZE = 256; +const std::size_t FILTER_SIZE = 64; using namespace Filter; @@ -45,14 +46,15 @@ int main(int argc, char** argv) { } // create low pass filter - LowPassFilter lpf(BUFFER_SIZE, result["cutoff"].as(), result["sample_rate"].as(), HammingWindow(BUFFER_SIZE).getWindow()); + LowPassFilter lpf(FILTER_SIZE, result["cutoff"].as(), result["sample_rate"].as(), HammingWindow(FILTER_SIZE).getWindow()); + + lpf.Dump("filter.dmp"); + HammingWindow(FILTER_SIZE).Dump("window.dmp"); // read data - std::vector inputBuffer; - inputBuffer.reserve(BUFFER_SIZE); + std::vector inputBuffer(BUFFER_SIZE); - std::vector outputBuffer; - outputBuffer.reserve(BUFFER_SIZE); + std::vector outputBuffer(BUFFER_SIZE); std::size_t len; @@ -63,6 +65,8 @@ int main(int argc, char** argv) { } lpf.ConvolveIQ(inputBuffer, outputBuffer); + + std::fwrite(outputBuffer.data(), sizeof(float), BUFFER_SIZE, stdout); } return 0; diff --git a/src/filter/window/hamming_window.cpp b/src/filter/window/hamming_window.cpp index 51ce13a..16e272c 100644 --- a/src/filter/window/hamming_window.cpp +++ b/src/filter/window/hamming_window.cpp @@ -1,13 +1,21 @@ #include +#include +#include #include #include namespace Filter { -HammingWindow::HammingWindow(std::size_t width) { - window.reserve(width); +HammingWindow::HammingWindow(std::size_t width) : window(width) { for (std::size_t i = 0; i < width; i++) { - window[i] = (25 / 46.0) - (21 / 46.0) * std::cos(2 * std::numbers::pi * i / width); + window[i] = (25 / 46.0f) - (21 / 46.0f) * std::cos(2.0f * std::numbers::pi * i / (float)width); } } + +void HammingWindow::Dump(const std::string& path) const { + std::ofstream output; + output.open(path, std::ios::out | std::ios::binary); + output.write(reinterpret_cast(getWindow().data()), sizeof(float) * getWindow().size()); + output.close(); +} } // namespace Filter \ No newline at end of file