38 void adcSimulate(std::span<ComplexType> data,
const unsigned bits,
const RealType fullscale)
noexcept
40 const RealType levels = std::pow(2, bits - 1);
42 for (
auto& sample : data)
44 auto [i, q] = std::tuple{std::clamp(std::floor(levels * sample.real() / fullscale) / levels, -1.0, 1.0),
45 std::clamp(std::floor(levels * sample.imag() / fullscale) / levels, -1.0, 1.0)};
60 const RealType start,
const RealType fracDelay,
const unsigned localWindowSize)
64 const auto array = resp->
renderBinary(prate, psize, fracDelay);
65 int start_sample =
static_cast<int>(std::round(rate * (resp->
startTime() - start)));
66 const unsigned roffset = start_sample < 0 ? -start_sample : 0;
72 for (
unsigned i = roffset; i < psize && i + start_sample < localWindowSize; ++i)
74 localWindow[i + start_sample] += array[i];
82 const RealType fracDelay,
const std::span<
const std::unique_ptr<serial::Response>> responses)
85 std::queue<serial::Response*> work_list;
87 for (
const auto& response : responses)
89 if (response->startTime() <= end && response->endTime() >= start)
91 work_list.push(response.get());
96 const auto local_window_size =
static_cast<unsigned>(std::ceil(length * rate));
98 std::vector local_window(local_window_size,
ComplexType{});
100 while (!work_list.empty())
102 const auto* resp = work_list.front();
104 processResponse(resp, local_window, rate, start, fracDelay, local_window_size);
107 for (
unsigned i = 0; i < local_window_size; ++i)
109 window[i] += local_window[i];
115 if (noiseTemperature == 0)
124 const RealType per_channel_power = total_power / 2.0;
125 const RealType stddev = std::sqrt(per_channel_power);
128 for (
auto& sample : window)
137 for (
const auto& sample : window)
139 const RealType real_abs = std::fabs(sample.real());
140 const RealType imag_abs = std::fabs(sample.imag());
142 max_value = std::max({max_value, real_abs, imag_abs});
147 adcSimulate(window, adc_bits, max_value);
149 else if (max_value != 0)
151 for (
auto& sample : window)
Generates white Gaussian noise.
RealType getSample() noexcept override
Generates a sample of white Gaussian noise.
Manages radar signal responses from a transmitter.
RealType startTime() const noexcept
Retrieves the start time of the response.
std::vector< ComplexType > renderBinary(RealType &rate, unsigned &size, RealType fracWinDelay) const
Renders the response in binary format.
double RealType
Type for real numbers.
std::complex< RealType > ComplexType
Type for complex numbers.
RealType rate() noexcept
Get the rendering sample rate.
RealType boltzmannK() noexcept
Get the Boltzmann constant.
unsigned oversampleRatio() noexcept
Get the oversampling ratio.
unsigned adcBits() noexcept
Get the ADC quantization bits.
void applyThermalNoise(std::span< ComplexType > window, const RealType noiseTemperature, std::mt19937 &rngEngine)
Applies thermal (Johnson-Nyquist) noise to a window of I/Q samples.
RealType quantizeAndScaleWindow(std::span< ComplexType > window)
Simulates ADC quantization and scales a window of complex I/Q samples.
void renderWindow(std::vector< ComplexType > &window, const RealType length, const RealType start, const RealType fracDelay, const std::span< const std::unique_ptr< serial::Response > > responses)
Renders a time-window of I/Q data from a collection of raw radar responses.
Header file for noise generator classes.
Defines the Parameters struct and provides methods for managing simulation parameters.
Classes for managing radar signal responses.
Header for receiver-side signal processing and rendering.
A simple thread pool implementation.