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