-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathPathSimProcessor.cpp
95 lines (83 loc) · 3.18 KB
/
PathSimProcessor.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include "PathSimProcessor.h"
namespace PathSim {
// RMS amplitude out of 32768
// pick so that worst case Gaussian noise
// plus signals will not overflow soundcard
static constexpr double RMS_MAXAMPLITUDE = 0.122; // 4000. / 32768.;
static constexpr double RMSAVE = 20.;
PathSimProcessor::~PathSimProcessor()
{
#ifdef PATHSIM_TESTMODE
EndTest();
#endif
}
void PathSimProcessor::init(const PathSimParams& params)
{
m_params = params;
int numpaths = int(m_params.paths.size());
m_direct_path = numpaths == 0;
m_paths.assign(numpaths, { {}, {BUF_SIZE, cmplx{}} });
m_noise_gen.init(true);
if (! m_direct_path) {
m_hilbert.init();
m_delay.init();
for (const PathParams& p : params.paths) {
int i = int(&p - params.paths.data());
m_paths[i].path.init_path(p.spread, p.offset, BUF_SIZE, numpaths);
if (i > 0)
m_delay.add_delay(p.delay);
}
}
m_SNR = pow(10., params.noise.snr / 20.0);
m_SigRMS = RMS_MAXAMPLITUDE;
}
void PathSimProcessor::process_buffer(double *buffer)
{
{
// Calculate sum of squares for RMS calculations
double acc = 0.;
for (int i = 0; i < BUF_SIZE; ++ i)
acc += buffer[i] * buffer[i];
// Simple IIR LP filter the rms averages
m_SigRMS = (1.0 / RMSAVE) * sqrt(acc / BUF_SIZE) + (1.0 - 1.0 / RMSAVE) * m_SigRMS;
}
if (! m_params.noise.has_awgn) {
m_SignalGain = 1.0;
m_NoiseRMS = 0.0;
}
m_state.m_SigRMS = m_SigRMS;
if (! m_direct_path) {
// Bandpass filter into I and Q and get delayed versions of the input data
static_assert(m_hilbert.BLOCKSIZE == this->BUF_SIZE, "Buffer length has to be satisfied");
m_hilbert.filter_block(buffer, m_paths.front().buffer.data());
static_assert(m_delay.BLOCKSIZE == this->BUF_SIZE, "Buffer length has to be satisfied");
std::vector<std::vector<cmplx>*> buffers;
buffers.reserve(m_paths.size() - 1);
for (size_t i = 1; i < m_paths.size(); ++ i)
buffers.emplace_back(&m_paths[i].buffer);
m_delay.delay_block(m_paths.front().buffer, buffers);
// Calculate each path.
for (PathWithBuffer& path : m_paths)
path.path.calc_path(path.buffer.data(), path.buffer.data());
// Sum and Copy just the real part back into the real buffer for output
for (int i = 0; i < BUF_SIZE; ++ i) {
double acc = 0;
for (PathWithBuffer& path : m_paths)
acc += path.buffer[i].r;
buffer[i] = acc;
}
}
if (m_params.noise.has_awgn) {
// if AWGN is used, figure out gains for SNR
if (m_SNR >= 1.0) {
m_SignalGain = RMS_MAXAMPLITUDE / m_SigRMS;
m_NoiseRMS = m_SignalGain * m_SigRMS / m_SNR;
} else {
m_SignalGain = RMS_MAXAMPLITUDE * m_SNR / m_SigRMS;
m_NoiseRMS = RMS_MAXAMPLITUDE;
}
m_noise_gen.add_band_limited_noise(BUF_SIZE, buffer, m_SignalGain, m_NoiseRMS);
}
m_state.m_NoiseRMS = m_NoiseRMS;
}
} // namespace PathSim