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 <algorithm>
16#include <cstddef>
17#include <stdexcept>
18
19#include "core/logging.h"
20#include "core/parameters.h"
21
22using logging::Level;
23
24namespace
25{
26 /**
27 * @brief Computes the modified Bessel function of the first kind for x.
28 *
29 * @param x The input value for which the Bessel function is computed.
30 * @return The computed Bessel function value, or an error message if computation fails.
31 */
32 std::expected<RealType, std::string> besselI0(const RealType x)
33 {
34 // Use the polynomial approximation from section 9.8 of
35 // "Handbook of Mathematical Functions" by Abramowitz and Stegun
36 if (x < 0.0)
37 {
38 return std::unexpected("Modified Bessel approximation only valid for x > 0");
39 }
40 RealType t = x / 3.75;
41 if (t <= 1.0)
42 {
43 t *= t;
44 return 1.0 +
45 t * (3.5156229 + t * (3.0899424 + t * (1.2067492 + t * (0.2659732 + t * (0.0360768 + t * 0.0045813)))));
46 }
47
48 const RealType i0 = 0.39894228 +
49 t *
50 (0.01328592 +
51 t *
52 (0.00225319 +
53 t *
54 (-0.00157565 +
55 t *
56 (0.00916281 +
57 t * (-0.02057706 + t * (0.02635537 + t * (-0.01647633 + t * 0.00392377)))))));
58 return i0 * std::exp(x) / std::sqrt(x);
59 }
60}
61
62namespace interp
63{
65 {
66 static InterpFilter instance;
67 return instance;
68 }
69
70 std::expected<RealType, std::string> InterpFilter::kaiserWinCompute(const RealType x) const noexcept
71 {
72 if (x < 0 || x > _alpha * 2)
73 {
74 return 0;
75 }
76 auto bessel = besselI0(_beta * std::sqrt(1 - std::pow((x - _alpha) / _alpha, 2)));
77 if (bessel)
78 {
79 return *bessel / _bessel_beta;
80 }
81
82 return std::unexpected(bessel.error());
83 }
84
85 std::expected<RealType, std::string> InterpFilter::interpFilter(const RealType x) const noexcept
86 {
87 auto kaiser = kaiserWinCompute(x + _alpha);
88 if (kaiser)
89 {
90 return *kaiser * sinc(x);
91 }
92
93 return std::unexpected(kaiser.error());
94 }
95
96 InterpFilter::InterpFilter()
97 {
99 _table_filters = 1000;
100 _filter_table = std::vector<RealType>(_table_filters * _length);
101
102 _alpha = std::floor(static_cast<RealType>(_length) / 2.0);
103 if (auto bessel = besselI0(_beta); bessel)
104 {
105 _bessel_beta = *bessel;
106 }
107 else
108 {
109 LOG(Level::FATAL, "Bessel function calculation failed: {}", bessel.error());
110 throw std::runtime_error("Bessel function calculation failed");
111 }
112
113 const auto hfilt = static_cast<std::ptrdiff_t>(_table_filters / 2);
114 const auto alpha_offset = static_cast<std::ptrdiff_t>(_alpha);
115
116 LOG(Level::DEBUG, "Building table of {} filters", _table_filters);
117
118 for (std::ptrdiff_t i = -hfilt; i < hfilt; ++i)
119 {
120 const RealType delay = static_cast<RealType>(i) / static_cast<RealType>(hfilt);
121 for (std::ptrdiff_t j = -alpha_offset; j < alpha_offset; ++j)
122 {
123 if (auto interp = interpFilter(static_cast<RealType>(j) - delay); interp)
124 {
125 const auto filter_index =
126 static_cast<std::size_t>(i + hfilt) * _length + static_cast<std::size_t>(j + alpha_offset);
127 _filter_table[filter_index] = *interp;
128 }
129 else
130 {
131 LOG(Level::FATAL, "Interpolation filter calculation failed: {}", interp.error());
132 throw std::runtime_error("Interpolation filter calculation failed");
133 }
134 }
135 }
136
137 LOG(Level::DEBUG, "Filter table complete");
138 }
139
140 std::span<const RealType> InterpFilter::getFilter(RealType delay) const
141 {
142 if (delay < -1 || delay > 1)
143 {
144 LOG(Level::FATAL, "Requested delay filter value out of range: {}", delay);
145 throw std::runtime_error("Requested delay filter value out of range");
146 }
147
148 const auto filt =
149 std::min(static_cast<std::size_t>((delay + 1.0) * (static_cast<RealType>(_table_filters) / 2.0)),
150 _table_filters - 1);
151 return std::span{_filter_table.data() + filt * _length, _length};
152 }
153}
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:139
Defines the Parameters struct and provides methods for managing simulation parameters.