From a3ef46033468486b33799eb4b60fae37530fb39b Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Tue, 13 Jan 2026 17:29:02 -0500 Subject: [PATCH] Use common box filter. --- .../Clock Signal/ScanTarget/CSScanTarget.mm | 49 +++++-------------- SignalProcessing/FIRFilter.hpp | 27 ++++++++-- 2 files changed, 35 insertions(+), 41 deletions(-) diff --git a/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm b/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm index 8c449e94f..32ee88e9e 100644 --- a/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm +++ b/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm @@ -151,38 +151,6 @@ constexpr MTLResourceOptions SharedResourceOptionsTexture = } \ } \ } - -/// @returns the proper 1d kernel to apply a box filter around a certain point a pixel density of @c radiansPerPixel and applying an -/// angular limit of @c cutoff. The values returned will be the first eight of a fifteen-point filter that is symmetrical around its centre. -std::array boxCoefficients(float radiansPerPixel, float cutoff) { - std::array filter; - float total = 0.0f; - - for(size_t c = 0; c < 8; ++c) { - // This coefficient occupies the angular window [6.5-c, 7.5-c]*radiansPerPixel. - const float startAngle = (6.5f - float(c)) * radiansPerPixel; - const float endAngle = (7.5f - float(c)) * radiansPerPixel; - - float coefficient = 0.0f; - if(endAngle < cutoff) { - coefficient = 1.0f; - } else if(startAngle >= cutoff) { - coefficient = 0.0f; - } else { - coefficient = (cutoff - startAngle) / radiansPerPixel; - } - total += 2.0f * coefficient; // All but the centre coefficient will be used twice. - filter[c] = coefficient; - } - total = total - filter[7]; // As per above; ensure the centre coefficient is counted only once. - - for(size_t c = 0; c < 8; ++c) { - filter[c] /= total; - } - - return filter; -} - } using BufferingScanTarget = Outputs::Display::BufferingScanTarget; @@ -730,9 +698,11 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget; simd::float3 firCoefficients[8]{}; // Initial seed: a box filter for the chrominance parts and no filter at all for luminance. - const auto chromaCoefficients = boxCoefficients(radiansPerPixel, 3.141592654f); - const auto testBox = SignalProcessing::Box::filter(radiansPerPixel, 3.141592654f * 2.0f); - (void)testBox; + const auto chromaCoefficients = + SignalProcessing::Box::filter( + radiansPerPixel, + 3.141592654f * 2.0f + ).resize(15); _chromaKernelSize = 15; for(size_t c = 0; c < 8; ++c) { @@ -765,10 +735,9 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget; // actual cutoff frequency is going to be a function of the input clock, which is a bit phoney but the // best way to stay safe within the PCM sampling limits. if(!isSVideoOutput) { - const auto sharpenFilter + const auto sharpen = SignalProcessing::KaiserBessel::filter( 15, 1368, 60.0f, 227.5f); - const auto sharpen = sharpenFilter.coefficients(); const size_t offset = (15 - sharpen.size()) / 2; for(size_t c = offset; c < 8; ++c) { @@ -787,7 +756,11 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget; // Generate the luminance separation filter and determine its required size. { simd::float2 lumaCoefficients[8]{}; - const auto coefficients = boxCoefficients(radiansPerPixel, 3.141592654f); + const auto coefficients = + SignalProcessing::Box::filter( + radiansPerPixel, + 3.141592654f * 2.0f + ).resize(15); _lumaKernelSize = 15; for(size_t c = 0; c < 8; ++c) { lumaCoefficients[c].x = coefficients[c];// * 1.15f; diff --git a/SignalProcessing/FIRFilter.hpp b/SignalProcessing/FIRFilter.hpp index faf7b3ce9..8662af4a0 100644 --- a/SignalProcessing/FIRFilter.hpp +++ b/SignalProcessing/FIRFilter.hpp @@ -17,8 +17,9 @@ #endif #include +#include #include -#include +#include #include namespace SignalProcessing { @@ -116,8 +117,28 @@ public: } } - std::span coefficients() const { - return std::span(coefficients_); + CoefficientType operator[](const size_t index) const { + return coefficients_[index]; + } + + size_t size() const { + return coefficients_.size(); + } + + FIRFilter &resize(const size_t size) { + assert(size & 1); + + if(size >= coefficients_.size()) { + // TODO: find a faster solution than this. + const auto half_difference = (size - coefficients_.size()) / 2; + std::vector zeroes(half_difference); + coefficients_.insert(coefficients_.begin(), zeroes.begin(), zeroes.end()); + coefficients_.insert(coefficients_.end(), zeroes.begin(), zeroes.end()); + return *this; + } + +// const auto total = std::accumulate(coefficients_.begin(), coefficients_.end(), CoefficientType{}); + return *this; } private: