LASP 1.0
Library for Acoustic Signal Processing
Loading...
Searching...
No Matches
lasp_siggen_impl.cpp
Go to the documentation of this file.
1// lasp_siggen_impl.cpp
2//
3// Author: J.A. de Jong -ASCEE
4//
5// Description:
6// Signal generators implementation
8/* #define DEBUGTRACE_ENABLED */
9#include "lasp_siggen_impl.h"
10#include "debugtrace.hpp"
11#include "lasp_mathtypes.h"
12#include <cassert>
13
14using rte = std::runtime_error;
15
17
20#define NITER_NEWTON 20
21
22Noise::Noise(){DEBUGTRACE_ENTER}
23
24vd Noise::genSignalUnscaled(us nframes) {
25 return arma::randn<vd>(nframes);
26}
27void Noise::resetImpl() {}
28
29Sine::Sine(const d freq) : omg(2 * arma::datum::pi * freq) { DEBUGTRACE_ENTER; }
30
32 /* DEBUGTRACE_ENTER; */
33 const d pi = arma::datum::pi;
34 vd phase_vec =
35 arma::linspace(phase, phase + omg * (nframes - 1) / _fs, nframes);
36 phase += omg * nframes / _fs;
37 while (phase > 2 * arma::datum::pi) {
38 phase -= 2 * pi;
39 }
40 return arma::sin(phase_vec);
41}
42
44
45 vd res(nframes);
46 if (_signal.size() == 0) {
47 throw rte("No signal defined while calling");
48 }
49 for (us i = 0; i < nframes; i++) {
50 res(i) = _signal[_cur_pos];
51 _cur_pos++;
52 _cur_pos %= _signal.size();
53 }
54 return res;
55}
56
57Sweep::Sweep(const d fl, const d fu, const d Ts, const d Tq, const us flags)
58 : fl_(fl), fu_(fu), Ts(Ts), Tq(Tq), flags(flags) {
59 if (fl <= 0 || fu < fl || Ts <= 0) {
60 throw rte("Invalid sweep parameters");
61 }
62 if ((flags & ForwardSweep) && (flags & BackwardSweep)) {
63 throw rte(
64 "Both forward and backward sweep flag set. Please only set either one "
65 "or none for a continuous sweep");
66 }
67 if ((flags & LinearSweep) && (flags & LogSweep)) {
68 throw rte(
69 "Both logsweep and linear sweep flag set. Please only set either one.");
70 }
71 if (!((flags & LinearSweep) || (flags & LogSweep))) {
72 throw rte("Either LinearSweep or LogSweep should be given as flag");
73 }
74}
75
76void Sweep::resetImpl() {
77
78 DEBUGTRACE_ENTER;
79
80 _cur_pos = 0;
81
82 bool forward_sweep = flags & ForwardSweep;
83 bool backward_sweep = flags & BackwardSweep;
84
85 const d Dt = 1 / _fs; // Deltat
86
87 // Estimate N, the number of samples in the sweep part (non-quiescent part):
88 const us Ns = (us)(Ts * _fs);
89 const us Nq = (us)(Tq * _fs);
90 const us N = Ns + Nq;
91
92 _signal = vd(N, arma::fill::zeros);
93 index = 0;
94
95 d fl, fu;
96 /* Swap fl and fu for a backward sweep */
97 if (backward_sweep) {
98 fu = fl_;
99 fl = fu_;
100 } else {
101 /* Case of continuous sweep, or forward sweep */
102 fl = fl_;
103 fu = fu_;
104 }
105
106 d phase = 0;
107
108 /* Linear sweep */
109 if (flags & LinearSweep) {
110 if (forward_sweep || backward_sweep) {
111 /* Forward or backward sweep */
112 /* TRACE(15, "Forward or backward sweep"); */
113 us K = (us)(Dt * (fl * Ns + 0.5 * (Ns - 1) * (fu - fl)));
114 d eps_num = ((d)K) / Dt - fl * Ns - 0.5 * (Ns - 1) * (fu - fl);
115 d eps = eps_num / (0.5 * (Ns - 1));
116 /* iVARTRACE(15, K); */
117 /* dVARTRACE(15, eps); */
118
119 for (us n = 0; n < Ns; n++) {
120 _signal(n) = d_sin(phase);
121 d fn = fl + ((d)n) / Ns * (fu + eps - fl);
122 phase += 2 * arma::datum::pi * Dt * fn;
123 }
124 } else {
125 /* Continous sweep */
126 /* TRACE(15, "continuous sweep"); */
127
128 /* iVARTRACE(17, N); */
129 /* dVARTRACE(17, fl); */
130 /* dVARTRACE(17, fu); */
131
132 const us Nf = Ns / 2;
133 const us Nb = Ns - Nf;
134
135 /* Phi halfway */
136 d phih = 2 * number_pi * Dt * (fl * Nf + 0.5 * (Nf - 1) * (fu - fl));
137
138 us K =
139 (us)(phih / (2 * number_pi) + Dt * (fu * Nb - (Nb - 1) * (fu - fl)));
140
141 d eps_num1 = (K - phih / (2 * number_pi)) / Dt;
142 d eps_num2 = -fu * Nb + (Nb - 1) * (fu - fl);
143 d eps = (eps_num1 + eps_num2) / (0.5 * (Nb + 1));
144
145 /* iVARTRACE(15, K); */
146 /* dVARTRACE(15, eps); */
147 d phase = 0;
148
149 for (us n = 0; n <= Ns; n++) {
150 /* iVARTRACE(17, n); */
151 if (n < N) {
152 _signal[n] = d_sin(phase);
153 }
154
155 d fn;
156 if (n <= Nf) {
157 fn = fl + ((d)n) / Nf * (fu - fl);
158 } else {
159 fn = fu - ((d)n - Nf) / Nb * (fu + eps - fl);
160 }
161 /* dbgassert(fn >= 0, "BUG"); */
162
163 phase += 2 * number_pi * Dt * fn;
164 }
165 /* This should be a very small number!! */
166 /* dVARTRACE(15, phase); */
167 }
168 } else if (flags & LogSweep) {
169
170 DEBUGTRACE_PRINT("Log sweep");
171 if (forward_sweep || backward_sweep) {
172 /* Forward or backward sweep */
173 DEBUGTRACE_PRINT("Forward or backward sweep");
174 d k1 = (fu / fl);
175 us K = (us)(Dt * fl * (k1 - 1) / (d_pow(k1, 1.0 / Ns) - 1));
176 d k = k1;
177
178 /* Iterate k to the right solution */
179 d E;
180 for (us iter = 0; iter < 10; iter++) {
181 E = 1 + K / (Dt * fl) * (d_pow(k, 1.0 / Ns) - 1) - k;
182 d dEdk = K / (Dt * fl) * d_pow(k, 1.0 / Ns) / (Ns * k) - 1;
183 k -= E / dEdk;
184 }
185
186 DEBUGTRACE_PRINT(K);
187 DEBUGTRACE_PRINT(k1);
188 DEBUGTRACE_PRINT(k);
189 DEBUGTRACE_PRINT(E);
190
191 for (us n = 0; n < Ns; n++) {
192 _signal[n] = d_sin(phase);
193 d fn = fl * d_pow(k, ((d)n) / Ns);
194 phase += 2 * number_pi * Dt * fn;
195 }
196 } else {
197
198 DEBUGTRACE_PRINT("Continuous sweep");
199
200 const us Nf = Ns / 2;
201 const us Nb = Ns - Nf;
202 const d k1 = (fu / fl);
203 const d phif1 =
204 2 * number_pi * Dt * fl * (k1 - 1) / (d_pow(k1, 1.0 / Nf) - 1);
205 const us K = (us)(phif1 / (2 * number_pi) +
206 Dt * fu * (1 / k1 - 1) / (d_pow(1 / k1, 1.0 / Nb) - 1));
207
208 d E;
209 d k = k1;
210
211 /* Newton iterations to converge k to the value such that the sweep is
212 * continuous */
213 for (us iter = 0; iter < NITER_NEWTON; iter++) {
214 E = (k - 1) / (d_pow(k, 1.0 / Nf) - 1) +
215 (k - 1) / (1 - d_pow(k, -1.0 / Nb)) - K / Dt / fl;
216 DEBUGTRACE_PRINT(E);
217
218 /* All parts of the derivative of above error E to k */
219 d dEdk1 = 1 / (d_pow(k, 1.0 / Nf) - 1);
220 d dEdk2 = (1 / k - 1) / (d_pow(k, -1.0 / Nb) - 1);
221 d dEdk3 = -1 / (k * (d_pow(k, -1.0 / Nb) - 1));
222 d dEdk4 = d_pow(k, -1.0 / Nb) * (1 / k - 1) /
223 (Nb * d_pow(d_pow(k, -1.0 / Nb) - 1, 2));
224 d dEdk5 = -d_pow(k, 1.0 / Nf) * (k - 1) /
225 (Nf * k * d_pow(d_pow(k, 1.0 / Nf) - 1, 2));
226 d dEdk = dEdk1 + dEdk2 + dEdk3 + dEdk4 + dEdk5;
227
228 /* Iterate! */
229 k -= E / dEdk;
230 }
231
232 DEBUGTRACE_PRINT(K);
233 DEBUGTRACE_PRINT(k1);
234 DEBUGTRACE_PRINT(k);
235 DEBUGTRACE_PRINT(E);
236
237 for (us n = 0; n <= Ns; n++) {
238 /* iVARTRACE(17, n); */
239 if (n < Ns) {
240 _signal[n] = d_sin(phase);
241 }
242
243 d fn;
244 if (n <= Nf) {
245 fn = fl * d_pow(k, ((d)n) / Nf);
246 } else {
247 fn = fl * k * d_pow(1 / k, ((d)n - Nf) / Nb);
248 }
249 /* dbgassert(fn >= 0, "BUG"); */
250
251 phase += 2 * number_pi * Dt * fn;
252 while (phase > 2 * number_pi)
253 phase -= 2 * number_pi;
254 /* dVARTRACE(17, phase); */
255 }
256 /* This should be a very small number!! */
257 DEBUGTRACE_PRINT(phase);
258 }
259 } // End of log sweep
260 else {
261 // Either log or linear sweep had to be given as flags.
262 assert(false);
263
264 }
265}
Noise()
Constructs a noise generator. If no filter is used, the output will be white noise....
virtual vd genSignalUnscaled(const us nframes) override final
Sine(const d freq_Hz)
Create a sine wave generator.
virtual vd genSignalUnscaled(const us nframes) override final
static constexpr int BackwardSweep
static constexpr int LogSweep
Sweep(const d fl, const d fu, const d Ts, const d Tq, const us sweep_flags)
static constexpr int LinearSweep
static constexpr int ForwardSweep
std::runtime_error rte
Definition lasp_daq.cpp:16
arma::Col< d > vd
#define d_sin
#define d_pow
const d number_pi
DEBUGTRACE_VARIABLES
#define NITER_NEWTON
size_t us
We often use boolean values.
Definition lasp_types.h:29