FERS 1.0.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
interpolation_filter.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-only
2//
3// Copyright (c) 2006-2008 Marc Brooker and Michael Inggs
4// Copyright (c) 2008-present FERS Contributors (see AUTHORS.md).
5//
6// See the GNU GPLv2 LICENSE file in the FERS project root for more information.
7
8/**
9 * @file interpolation_filter.cpp
10 * @brief Implementation of the InterpFilter class.
11 */
12
14
15#include <stdexcept>
16
17#include "core/logging.h"
18#include "core/parameters.h"
19
20using logging::Level;
21
22namespace
23{
24 /**
25 * @brief Computes the modified Bessel function of the first kind for x.
26 *
27 * @param x The input value for which the Bessel function is computed.
28 * @return The computed Bessel function value, or an error message if computation fails.
29 */
30 std::expected<RealType, std::string> besselI0(const RealType x)
31 {
32 // Use the polynomial approximation from section 9.8 of
33 // "Handbook of Mathematical Functions" by Abramowitz and Stegun
34 if (x < 0.0)
35 {
36 return std::unexpected("Modified Bessel approximation only valid for x > 0");
37 }
38 if (RealType t = x / 3.75; t <= 1.0)
39 {
40 t *= t;
41 return 1.0 +
42 t * (3.5156229 + t * (3.0899424 + t * (1.2067492 + t * (0.2659732 + t * (0.0360768 + t * 0.0045813)))));
43 }
44 else
45 {
46 const RealType i0 = 0.39894228 +
47 t *
48 (0.01328592 +
49 t *
50 (0.00225319 +
51 t *
52 (-0.00157565 +
53 t *
54 (0.00916281 +
55 t * (-0.02057706 + t * (0.02635537 + t * (-0.01647633 + t * 0.00392377)))))));
56 return i0 * std::exp(x) / std::sqrt(x);
57 }
58 }
59}
60
61namespace interp
62{
64 {
65 static InterpFilter instance;
66 return instance;
67 }
68
69 std::expected<RealType, std::string> InterpFilter::kaiserWinCompute(const RealType x) const noexcept
70 {
71 if (x < 0 || x > _alpha * 2)
72 {
73 return 0;
74 }
75 if (auto bessel = besselI0(_beta * std::sqrt(1 - std::pow((x - _alpha) / _alpha, 2))); bessel)
76 {
77 return *bessel / _bessel_beta;
78 }
79 else
80 {
81 return std::unexpected(bessel.error());
82 }
83 }
84
85 std::expected<RealType, std::string> InterpFilter::interpFilter(const RealType x) const noexcept
86 {
87 if (auto kaiser = kaiserWinCompute(x + _alpha); kaiser)
88 {
89 return *kaiser * sinc(x);
90 }
91 else
92 {
93 return std::unexpected(kaiser.error());
94 }
95 }
96
97 InterpFilter::InterpFilter()
98 {
99 _length = static_cast<int>(params::renderFilterLength());
100 _table_filters = 1000;
101 _filter_table = std::vector<RealType>(_table_filters * _length);
102
103 _alpha = std::floor(params::renderFilterLength() / 2.0);
104 if (auto bessel = besselI0(_beta); bessel)
105 {
106 _bessel_beta = *bessel;
107 }
108 else
109 {
110 LOG(Level::FATAL, "Bessel function calculation failed: {}", bessel.error());
111 throw std::runtime_error("Bessel function calculation failed");
112 }
113
114 const int hfilt = _table_filters / 2;
115
116 LOG(Level::DEBUG, "Building table of {} filters", _table_filters);
117
118 for (int i = -hfilt; i < hfilt; ++i)
119 {
120 const RealType delay = i / static_cast<RealType>(hfilt);
121 for (int j = static_cast<int>(-_alpha); j < _alpha; ++j)
122 {
123 if (auto interp = interpFilter(j - delay); interp)
124 {
125 _filter_table[(i + hfilt) * _length + j + static_cast<int>(_alpha)] = *interp;
126 }
127 else
128 {
129 LOG(Level::FATAL, "Interpolation filter calculation failed: {}", interp.error());
130 throw std::runtime_error("Interpolation filter calculation failed");
131 }
132 }
133 }
134
135 LOG(Level::DEBUG, "Filter table complete");
136 }
137
138 std::span<const RealType> InterpFilter::getFilter(RealType delay) const
139 {
140 if (delay < -1 || delay > 1)
141 {
142 LOG(Level::FATAL, "Requested delay filter value out of range: {}", delay);
143 throw std::runtime_error("Requested delay filter value out of range");
144 }
145
146 const auto filt = static_cast<unsigned>((delay + 1) * (_table_filters / 2.0));
147 return std::span{&_filter_table[filt * _length], static_cast<size_t>(_length)};
148 }
149}
Provides methods to generate interpolation filters using Kaiser windows.
static InterpFilter & getInstance() noexcept
Retrieves the singleton instance of the InterpFilter class.
std::span< const RealType > getFilter(RealType delay) const
Retrieves a span of precomputed filter values for a given delay.
std::expected< RealType, std::string > kaiserWinCompute(RealType x) const noexcept
Computes the Kaiser window function for a given input.
std::expected< RealType, std::string > interpFilter(RealType x) const noexcept
Computes the interpolation filter value for a given input.
double RealType
Type for real numbers.
Definition config.h:27
Interpolation filter implementation using Kaiser windowing.
Header file for the logging system.
#define LOG(level,...)
Definition logging.h:19
unsigned renderFilterLength() noexcept
Get the render filter length.
Definition parameters.h:127
Defines the Parameters struct and provides methods for managing simulation parameters.