FERS 0.1.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
falpha_branch.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 falpha_branch.cpp
10 * @brief Implementation of the FAlphaBranch class for noise generation.
11 */
12
13#include "falpha_branch.h"
14
15#include <array>
16#include <cmath>
17#include <span>
18#include <stdexcept>
19#include <utility>
20
21#include "core/logging.h"
22#include "signal/dsp_filters.h"
23
26using logging::Level;
27
28namespace noise
29{
31 std::unique_ptr<FAlphaBranch> pre, const bool last) :
32 _rng_engine_ref(rngEngine), _normal_dist{0.0, 1.0}, _pre(std::move(pre)),
33 _upsample_scale(std::pow(10, ffrac + fint + 0.5)), _buffer(10), _ffrac(ffrac), _fint(fint), _last(last)
34 {
35 LOG(Level::TRACE, "Creating FAlphaBranch: ffrac={} fint={}", ffrac, fint);
36 init();
37
38 if (!_last)
39 {
40 refill();
41 }
42 }
43
44 void FAlphaBranch::init()
45 {
46 _upsampler = std::make_unique<DecadeUpsampler>();
47
48 if (_pre)
49 {
50 constexpr std::array hp_num = {3.817871081981451e-01, -4.093384095523618e+00, 2.005300512623078e+01,
51 -5.924672881811163e+01, 1.172948159891025e+02, -1.633810410083022e+02,
52 1.633810410083034e+02, -1.172948159891052e+02, 5.924672881811390e+01,
53 -2.005300512623186e+01, 4.093384095523903e+00, -3.817871081981776e-01};
54 constexpr std::array hp_den = {1.000000000000000e+00, -8.829695665523831e+00, 3.583068809011030e+01,
55 -8.811479652970442e+01, 1.457874067329429e+02, -1.702715637111961e+02,
56 1.431504350055831e+02, -8.656925883534657e+01, 3.687395592491803e+01,
57 -1.052413841411803e+01, 1.808292123637038e+00, -1.412932578340511e-01};
58 _highpass = std::make_unique<IirFilter>(hp_den.data(), hp_num.data(), hp_num.size());
59 }
60
61 if (_ffrac == 0.5)
62 {
63 constexpr std::array sf_num = {
64 5.210373977738306e-03, -7.694671394585578e-03, 1.635979377907092e-03, 9.852449140857658e-05,
65 -2.080553126780113e-03, 4.088764157029523e-03, -1.549082440084623e-03, 9.054734252370680e-04,
66 -3.467369912368729e-04, 4.516383087838856e-04, -1.063356106118517e-03, 1.330008998057684e-04,
67 6.556909567323943e-04, -4.839476350293955e-04, 6.664936170526832e-05, 1.528520559763056e-05};
68 constexpr std::array sf_den = {
69 1.000000000000000e+00, -2.065565041154101e+00, 1.130909190864681e+00, -1.671244644503288e-01,
70 -3.331474931013877e-01, 9.952625337612708e-01, -7.123036343635182e-01, 3.297062696290504e-01,
71 -1.925691520710595e-01, 1.301247006176314e-01, -2.702016290409912e-01, 1.455380885858886e-01,
72 1.091921868353888e-01, -1.524953111510459e-01, 5.667716332023935e-02, -2.890314873767405e-03};
73 _shape_gain = 5.210373977738306e-03;
74 _shape_filter = std::make_unique<IirFilter>(sf_den.data(), sf_num.data(), sf_num.size());
75 }
76 else if (_ffrac != 0.0)
77 {
78 LOG(Level::FATAL, "Fractional noise generation values other than 0.5 or 0 are not supported. ffrac={}",
79 _ffrac);
80 throw std::runtime_error("Fractional integrator values other than 0.5 or 0 are not supported");
81 }
82
83 if (_fint > 0)
84 {
85 _integ_gain = 1.0f;
86
87 if (_fint == 1)
88 {
89 constexpr std::array<RealType, 2> i_den = {1.0f, -1.0f};
90 constexpr std::array<RealType, 2> i_num = {1.0f, 0.0f};
91 _integ_filter = std::make_unique<IirFilter>(i_den.data(), i_num.data(), i_num.size());
92 }
93 else if (_fint == 2)
94 {
95 constexpr std::array<RealType, 3> i_den = {1.0f, -2.0f, 1.0f};
96 constexpr std::array<RealType, 3> i_num = {1.0f, 0.0f, 0.0f};
97 _integ_filter = std::make_unique<IirFilter>(i_den.data(), i_num.data(), i_num.size());
98 }
99 else
100 {
101 throw std::runtime_error("Only alpha values between 2 and -2 are supported for noise generation");
102 }
103 }
104 _offset_sample = 0.0f;
105 _got_offset = false;
106 }
107
109 {
110 if (!_last)
111 {
112 const RealType ret = _buffer[_buffer_samples++];
113 if (_buffer_samples == 10)
114 {
115 refill();
116 }
117 return ret;
118 }
119 return calcSample() + _offset_sample * _upsample_scale;
120 }
121
122 RealType FAlphaBranch::calcSample() noexcept
123 {
124 RealType sample = _normal_dist(_rng_engine_ref.get());
125
126 if (_shape_filter)
127 {
128 sample = _shape_filter->filter(sample) / _shape_gain;
129 }
130
131 if (_integ_filter)
132 {
133 sample = _integ_filter->filter(sample) / _integ_gain;
134 }
135
136 if (_pre)
137 {
138 sample = _highpass->filter(sample);
139 if (_got_offset)
140 {
141 sample += _pre->getSample() * _pre_scale - _offset_sample;
142 }
143 else
144 {
145 _got_offset = true;
146 _offset_sample = _pre->getSample() * _pre_scale;
147 }
148 }
149
150 return sample;
151 }
152
153 void FAlphaBranch::refill() noexcept
154 {
155 const RealType sample = calcSample();
156 _upsampler->upsample(sample, _buffer);
157
158 for (auto& value : _buffer)
159 {
160 value *= _upsample_scale;
161 value += _offset_sample;
162 }
163
164 _buffer_samples = 0;
165 }
166
168 {
169 init();
170 _pre_scale = scale;
171 }
172}
Implements a specialized upsampler with a fixed upsampling factor of 10.
Implements an Infinite Impulse Response (IIR) filter.
FAlphaBranch(std::mt19937 &rngEngine, RealType ffrac, unsigned fint, std::unique_ptr< FAlphaBranch > pre, bool last)
Constructor for FAlphaBranch.
void flush(RealType scale)
Flushes the branch with a new scaling factor.
RealType getSample() noexcept
Retrieves the current noise sample.
double RealType
Type for real numbers.
Definition config.h:27
Header file for Digital Signal Processing (DSP) filters and upsampling/downsampling functionality.
Implementation of the FAlphaBranch class for noise generation.
Header file for the logging system.
#define LOG(level,...)
Definition logging.h:19
math::Vec3 max