Bug Summary

File:sig_tone.c
Warning:line 429, column 15
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name sig_tone.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fno-trapping-math -ffp-contract=fast -ffast-math -ffinite-math-only -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -target-feature +sse2 -dwarf-column-info -debugger-tuning=gdb -resource-dir /usr/lib/llvm-7/lib/clang/7.0.1 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/libxml2 -D NDEBUG -D HAVE_VISIBILITY=1 -D PIC -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.1/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -std=gnu99 -fconst-strings -fdebug-compilation-dir /drone/src/src -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -fobjc-runtime=gcc -fdiagnostics-show-option -analyzer-output=html -o /drone/src/scan-build/2021-05-27-190700-749-1 -x c sig_tone.c -faddrsig
1/*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * sig_tone.c - Signalling tone processing for the 2280Hz, 2400Hz, 2600Hz
5 * and similar signalling tones used in older protocols.
6 *
7 * Written by Steve Underwood <steveu@coppice.org>
8 *
9 * Copyright (C) 2004 Steve Underwood
10 *
11 * All rights reserved.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU Lesser General Public License version 2.1,
15 * as published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Lesser General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27/*! \file */
28
29#if defined(HAVE_CONFIG_H1)
30#include "config.h"
31#endif
32
33#include <stdlib.h>
34#include <inttypes.h>
35#if defined(HAVE_TGMATH_H1)
36#include <tgmath.h>
37#endif
38#if defined(HAVE_MATH_H1)
39#include <math.h>
40#endif
41#if defined(HAVE_STDBOOL_H1)
42#include <stdbool.h>
43#else
44#include "spandsp/stdbool.h"
45#endif
46#include "floating_fudge.h"
47#include <memory.h>
48#include <string.h>
49#include <limits.h>
50
51#include "spandsp/telephony.h"
52#include "spandsp/alloc.h"
53#include "spandsp/fast_convert.h"
54#include "spandsp/saturated.h"
55#include "spandsp/vector_int.h"
56#include "spandsp/complex.h"
57#include "spandsp/power_meter.h"
58#include "spandsp/dds.h"
59#include "spandsp/super_tone_rx.h"
60#include "spandsp/sig_tone.h"
61
62#include "spandsp/private/power_meter.h"
63#include "spandsp/private/sig_tone.h"
64
65/*! PI */
66#define PI3.14159265358979323 3.14159265358979323
67
68enum
69{
70 NOTCH_COEFF_SET_2280HZ = 0,
71 NOTCH_COEFF_SET_2400HZ,
72 NOTCH_COEFF_SET_2600HZ
73};
74
75/* The coefficients for the data notch filters. These filters are also the
76 guard filters for tone detection. */
77static const sig_tone_notch_coeffs_t notch_coeffs[3] =
78{
79 { /* 2280 Hz */
80#if defined(SPANDSP_USE_FIXED_POINT)
81 { 3600, 14397, 32767},
82 { 0, -9425, -28954},
83 { 0, 14196, 32767},
84 { 0, -17393, -28954},
85 12,
86#else
87 {0.878906f, 0.439362f, 1.0f},
88 {0.0f, -0.287627f, -0.883605f},
89 {0.0f, 0.433228f, 1.0f},
90 {0.0f, -0.530792f, -0.883605f},
91#endif
92 },
93 { /* 2400Hz */
94#if defined(SPANDSP_USE_FIXED_POINT)
95 { 3530, 20055, 32767},
96 { 0, -14950, -28341},
97 { 0, 20349, 32767},
98 { 0, -22633, -28341},
99 12,
100#else
101 {0.862000f, 0.612055f, 1.0f},
102 {0.0f, -0.456264f, -0.864899f},
103 {0.0f, 0.621021f, 1.0f},
104 {0.0f, -0.690738f, -0.864899f},
105#endif
106 },
107 { /* 2600Hz */
108#if defined(SPANDSP_USE_FIXED_POINT)
109 { 3530, 29569, 32767},
110 { 0, -24010, -28341},
111 { 0, 29844, 32767},
112 { 0, -31208, -28341},
113 12,
114#else
115 {0.862000f, 0.902374f, 1.0f},
116 {0.0f, -0.732727f, -0.864899f},
117 {0.0f, 0.910766f, 1.0f},
118 {0.0f, -0.952393f, -0.864899f},
119#endif
120 }
121};
122
123static const sig_tone_flat_coeffs_t flat_coeffs[1] =
124{
125 {
126#if defined(SPANDSP_USE_FIXED_POINT)
127 { 12900, -16384, -16384},
128 { 0, -8578, -11796},
129 15,
130#else
131 {0.393676f, -0.5f, -0.5f},
132 {0.0f, -0.261778f, -0.359985f},
133#endif
134 }
135};
136
137static const sig_tone_descriptor_t sig_tones[3] =
138{
139 {
140 /* 2280Hz (e.g. AC15, and many other European protocols) */
141 {2280, 0},
142 {{-10, -20}, {0, 0}}, /* -10+-1 dBm0 and -20+-1 dBm0 */
143 ms_to_samples(400)((400)*(8000/1000)), /* High to low timout - 300ms to 550ms */
144 ms_to_samples(225)((225)*(8000/1000)), /* Sharp to flat timeout */
145 ms_to_samples(225)((225)*(8000/1000)), /* Notch insertion timeout */
146
147 ms_to_samples(3)((3)*(8000/1000)), /* Tone on persistence check */
148 ms_to_samples(8)((8)*(8000/1000)), /* Tone off persistence check */
149
150 1,
151 {
152 &notch_coeffs[NOTCH_COEFF_SET_2280HZ],
153 NULL((void*)0),
154 },
155 &flat_coeffs[NOTCH_COEFF_SET_2280HZ],
156
157#if defined(SPANDSP_USE_FIXED_POINT)
158 13,
159 -30,
160 -30
161#else
162 13.0f,
163 -30.0f,
164 -30.0f
165#endif
166 },
167 {
168 /* 2600Hz (e.g. many US protocols) */
169 {2600, 0},
170 {{-8, -8}, {0, 0}},
171 ms_to_samples(0)((0)*(8000/1000)),
172 ms_to_samples(0)((0)*(8000/1000)),
173 ms_to_samples(225)((225)*(8000/1000)),
174
175 ms_to_samples(3)((3)*(8000/1000)),
176 ms_to_samples(8)((8)*(8000/1000)),
177
178 1,
179 {
180 &notch_coeffs[NOTCH_COEFF_SET_2600HZ],
181 NULL((void*)0),
182 },
183 NULL((void*)0),
184
185#if defined(SPANDSP_USE_FIXED_POINT)
186 16,
187 -30,
188 -30
189#else
190 15.6f,
191 -30.0f,
192 -30.0f
193#endif
194 },
195 {
196 /* 2400Hz/2600Hz (e.g. SS5 and SS5bis) */
197 {2400, 2600},
198 {{-8, -8}, {-8, -8}},
199 ms_to_samples(0)((0)*(8000/1000)),
200 ms_to_samples(0)((0)*(8000/1000)),
201 ms_to_samples(225)((225)*(8000/1000)),
202
203 ms_to_samples(3)((3)*(8000/1000)),
204 ms_to_samples(8)((8)*(8000/1000)),
205
206 2,
207 {
208 &notch_coeffs[NOTCH_COEFF_SET_2400HZ],
209 &notch_coeffs[NOTCH_COEFF_SET_2600HZ]
210 },
211 NULL((void*)0),
212
213#if defined(SPANDSP_USE_FIXED_POINT)
214 16,
215 -30,
216 -30
217#else
218 15.6f,
219 -30.0f,
220 -30.0f
221#endif
222 }
223};
224
225static const int tone_present_bits[3] =
226{
227 SIG_TONE_1_PRESENT,
228 SIG_TONE_2_PRESENT,
229 SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT
230};
231
232static const int tone_change_bits[3] =
233{
234 SIG_TONE_1_CHANGE,
235 SIG_TONE_2_CHANGE,
236 SIG_TONE_1_CHANGE | SIG_TONE_2_CHANGE
237};
238
239static const int coeff_sets[3] =
240{
241 0,
242 1,
243 0
244};
245
246SPAN_DECLARE(int)__attribute__((visibility("default"))) int sig_tone_tx(sig_tone_tx_state_t *s, int16_t amp[], int len)
247{
248 int i;
249 int j;
250 int k;
251 int n;
252 int16_t tone;
253 bool_Bool need_update;
254 int high_low;
255
256 for (i = 0; i < len; i += n)
257 {
258 if (s->current_tx_timeout)
259 {
260 if (s->current_tx_timeout <= len - i)
261 {
262 n = s->current_tx_timeout;
263 need_update = true1;
264 }
265 else
266 {
267 n = len - i;
268 need_update = false0;
269 }
270 s->current_tx_timeout -= n;
271 }
272 else
273 {
274 n = len - i;
275 need_update = false0;
276 }
277 if (!(s->current_tx_tone & SIG_TONE_TX_PASSTHROUGH))
278 vec_zeroi16(&amp[i], n);
279 /*endif*/
280 if ((s->current_tx_tone & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT)))
281 {
282 /* Are we in the early phase (high tone energy level), or the sustaining
283 phase (low tone energy level) of tone generation? */
284 /* This doesn't try to get the high/low timing precise, as there is no
285 value in doing so. It works block by block, and the blocks are normally
286 quite short. */
287 if (s->high_low_timer > 0)
288 {
289 if (n > s->high_low_timer)
290 n = s->high_low_timer;
291 s->high_low_timer -= n;
292 high_low = 0;
293 }
294 else
295 {
296 high_low = 1;
297 }
298 /*endif*/
299 for (k = 0; k < s->desc->tones; k++)
300 {
301 if ((s->current_tx_tone & tone_present_bits[k]) && s->phase_rate[k])
302 {
303 for (j = i; j < i + n; j++)
304 {
305 tone = dds_mod(&s->phase_acc[k], s->phase_rate[k], s->tone_scaling[k][high_low], 0);
306 amp[j] = sat_add16(amp[j], tone);
307 }
308 /*endfor*/
309 }
310 /*endif*/
311 }
312 }
313 /*endif*/
314 if (need_update && s->sig_update)
315 s->sig_update(s->user_data, SIG_TONE_TX_UPDATE_REQUEST, 0, 0);
316 /*endif*/
317 }
318 /*endfor*/
319 return len;
320}
321/*- End of function --------------------------------------------------------*/
322
323SPAN_DECLARE(void)__attribute__((visibility("default"))) void sig_tone_tx_set_mode(sig_tone_tx_state_t *s, int mode, int duration)
324{
325 int old_tones;
326 int new_tones;
327
328 old_tones = s->current_tx_tone & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT);
329 new_tones = mode & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT);
330 if (new_tones && old_tones != new_tones)
331 s->high_low_timer = s->desc->high_low_timeout;
332 /*endif*/
333 /* If a tone is being turned on, let's start the phase from zero */
334 if ((mode & SIG_TONE_1_PRESENT) && !(s->current_tx_tone & SIG_TONE_1_PRESENT))
335 s->phase_acc[0] = 0;
336 if ((mode & SIG_TONE_2_PRESENT) && !(s->current_tx_tone & SIG_TONE_2_PRESENT))
337 s->phase_acc[1] = 0;
338 s->current_tx_tone = mode;
339 s->current_tx_timeout = duration;
340}
341/*- End of function --------------------------------------------------------*/
342
343SPAN_DECLARE(sig_tone_tx_state_t *)__attribute__((visibility("default"))) sig_tone_tx_state_t * sig_tone_tx_init(sig_tone_tx_state_t *s, int tone_type, tone_report_func_t sig_update, void *user_data)
344{
345 int i;
346
347 if (sig_update == NULL((void*)0) || tone_type < 1 || tone_type > 3)
348 return NULL((void*)0);
349 /*endif*/
350
351 if (s == NULL((void*)0))
352 {
353 if ((s = (sig_tone_tx_state_t *) span_alloc(sizeof(*s))) == NULL((void*)0))
354 return NULL((void*)0);
355 }
356 memset(s, 0, sizeof(*s));
357
358 s->sig_update = sig_update;
359 s->user_data = user_data;
360
361 s->desc = &sig_tones[tone_type - 1];
362
363 for (i = 0; i < 2; i++)
364 {
365 if (s->desc->tone_freq[i])
366 s->phase_rate[i] = dds_phase_rate((float) s->desc->tone_freq[i]);
367 else
368 s->phase_rate[i] = 0;
369 s->tone_scaling[i][0] = dds_scaling_dbm0((float) s->desc->tone_amp[i][0]);
370 s->tone_scaling[i][1] = dds_scaling_dbm0((float) s->desc->tone_amp[i][1]);
371 }
372 return s;
373}
374/*- End of function --------------------------------------------------------*/
375
376SPAN_DECLARE(int)__attribute__((visibility("default"))) int sig_tone_tx_release(sig_tone_tx_state_t *s)
377{
378 return 0;
379}
380/*- End of function --------------------------------------------------------*/
381
382SPAN_DECLARE(int)__attribute__((visibility("default"))) int sig_tone_tx_free(sig_tone_tx_state_t *s)
383{
384 if (s)
385 span_free(s);
386 return 0;
387}
388/*- End of function --------------------------------------------------------*/
389
390int nnn = 0;
391
392SPAN_DECLARE(int)__attribute__((visibility("default"))) int sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len)
393{
394#if defined(SPANDSP_USE_FIXED_POINT)
395 int16_t x;
396 int32_t v;
397 int16_t notched_signal[3] = {0};
398 int16_t bandpass_signal;
399 int16_t signal;
400#else
401 float x;
402 float v;
403 float notched_signal[3] = {0};
404 float bandpass_signal;
405 float signal;
406#endif
407 int i;
408 int j;
409 int k;
410 int l;
411 int m;
412 int32_t notch_power[3] = {0};
413 int32_t flat_power;
414 int immediate;
415
416 l = s->desc->tones;
417 if (l == 2)
1
Assuming 'l' is not equal to 2
2
Taking false branch
418 l = 3;
419 notch_power[1] =
420 notch_power[2] = INT32_MAX(2147483647);
421 for (i = 0; i < len; i++)
3
Assuming 'i' is < 'len'
4
Loop condition is true. Entering loop body
422 {
423 if (s->signalling_state_duration < INT_MAX2147483647)
5
Assuming the condition is false
6
Taking false branch
424 s->signalling_state_duration++;
425 /*endif*/
426 signal = amp[i];
427 for (j = 0; j < l; j++)
7
Assuming 'j' is < 'l'
8
Loop condition is true. Entering loop body
10
Assuming 'j' is < 'l'
11
Loop condition is true. Entering loop body
13
Loop condition is true. Entering loop body
15
Assuming 'j' is < 'l'
16
Loop condition is true. Entering loop body
428 {
429 k = coeff_sets[j];
17
Assigned value is garbage or undefined
430 /* The notch filter is two cascaded biquads. */
431#if defined(SPANDSP_USE_FIXED_POINT)
432 v = ((int32_t) signal*s->desc->notch[k]->a1[0])
433 + ((int32_t) s->tone[j].notch_z1[0]*s->desc->notch[k]->b1[1])
434 + ((int32_t) s->tone[j].notch_z1[1]*s->desc->notch[k]->b1[2]);
435 x = v >> 15;
436 v += ((int32_t) s->tone[j].notch_z1[0]*s->desc->notch[k]->a1[1])
437 + ((int32_t) s->tone[j].notch_z1[1]*s->desc->notch[k]->a1[2]);
438 s->tone[j].notch_z1[1] = s->tone[j].notch_z1[0];
439 s->tone[j].notch_z1[0] = x;
440 v += ((int32_t) s->tone[j].notch_z2[0]*s->desc->notch[k]->b2[1])
441 + ((int32_t) s->tone[j].notch_z2[1]*s->desc->notch[k]->b2[2]);
442 x = v >> 15;
443 v += ((int32_t) s->tone[j].notch_z2[0]*s->desc->notch[k]->a2[1])
444 + ((int32_t) s->tone[j].notch_z2[1]*s->desc->notch[k]->a2[2]);
445 s->tone[j].notch_z2[1] = s->tone[j].notch_z2[0];
446 s->tone[j].notch_z2[0] = x;
447 notched_signal[j] = v >> s->desc->notch[k]->postscale;
448#else
449 v = signal*s->desc->notch[k]->a1[0]
450 + s->tone[j].notch_z1[0]*s->desc->notch[k]->b1[1]
451 + s->tone[j].notch_z1[1]*s->desc->notch[k]->b1[2];
452 x = v;
453 v += s->tone[j].notch_z1[0]*s->desc->notch[k]->a1[1]
454 + s->tone[j].notch_z1[1]*s->desc->notch[k]->a1[2];
455 s->tone[j].notch_z1[1] = s->tone[j].notch_z1[0];
456 s->tone[j].notch_z1[0] = x;
457 v += s->tone[j].notch_z2[0]*s->desc->notch[k]->b2[1]
458 + s->tone[j].notch_z2[1]*s->desc->notch[k]->b2[2];
459 x = v;
460 v += s->tone[j].notch_z2[0]*s->desc->notch[k]->a2[1]
461 + s->tone[j].notch_z2[1]*s->desc->notch[k]->a2[2];
462 s->tone[j].notch_z2[1] = s->tone[j].notch_z2[0];
463 s->tone[j].notch_z2[0] = x;
464 notched_signal[j] = v;
465#endif
466 /* Modulus and leaky integrate the notched data. The result of
467 this isn't used in low tone detect mode, but we must keep the
468 power measurement rolling along. */
469 notch_power[j] = power_meter_update(&s->tone[j].power, notched_signal[j]);
470 if (j == 1)
9
Taking false branch
12
Taking true branch
14
Taking false branch
471 signal = notched_signal[j];
472 }
473 if ((s->signalling_state & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT)))
474 {
475 if (s->flat_mode_timeout && --s->flat_mode_timeout == 0)
476 s->flat_mode = true1;
477 /*endif*/
478 }
479 else
480 {
481 s->flat_mode_timeout = s->desc->sharp_flat_timeout;
482 s->flat_mode = false0;
483 }
484 /*endif*/
485
486 immediate = -1;
487 if (s->flat_mode)
488 {
489 //printf("Flat mode %d %d\n", s->flat_mode_timeout, s->desc->sharp_flat_timeout);
490 /* Flat mode */
491 bandpass_signal = amp[i];
492 if (s->desc->flat)
493 {
494 /* The bandpass filter is a single bi-quad stage */
495#if defined(SPANDSP_USE_FIXED_POINT)
496 v = ((int32_t) amp[i]*s->desc->flat->a[0])
497 + ((int32_t) s->flat_z[0]*s->desc->flat->b[1])
498 + ((int32_t) s->flat_z[1]*s->desc->flat->b[2]);
499 x = v >> 15;
500 v += ((int32_t) s->flat_z[0]*s->desc->flat->a[1])
501 + ((int32_t) s->flat_z[1]*s->desc->flat->a[2]);
502 s->flat_z[1] = s->flat_z[0];
503 s->flat_z[0] = x;
504 bandpass_signal = v >> s->desc->flat->postscale;
505#else
506 v = amp[i]*s->desc->flat->a[0]
507 + s->flat_z[0]*s->desc->flat->b[1]
508 + s->flat_z[1]*s->desc->flat->b[2];
509 x = v;
510 v += s->flat_z[0]*s->desc->flat->a[1]
511 + s->flat_z[1]*s->desc->flat->a[2];
512 s->flat_z[1] = s->flat_z[0];
513 s->flat_z[0] = x;
514 bandpass_signal = v;
515#endif
516 }
517 flat_power = power_meter_update(&s->flat_power, bandpass_signal);
518
519 /* For the flat receiver we use a simple power threshold! */
520 if ((s->signalling_state & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT)))
521 {
522 if (flat_power < s->flat_detection_threshold)
523 {
524 s->signalling_state &= ~tone_present_bits[0];
525 s->signalling_state |= tone_change_bits[0];
526 }
527 /*endif*/
528 }
529 else
530 {
531 if (flat_power > s->flat_detection_threshold)
532 s->signalling_state |= (tone_present_bits[0] | tone_change_bits[0]);
533 /*endif*/
534 }
535 /*endif*/
536
537 /* Notch insertion logic */
538 /* tone_present and tone_on are equivalent in flat mode */
539 if ((s->signalling_state & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT)))
540 {
541 s->notch_insertion_timeout = s->desc->notch_lag_time;
542 }
543 else
544 {
545 if (s->notch_insertion_timeout)
546 s->notch_insertion_timeout--;
547 /*endif*/
548 }
549 /*endif*/
550 }
551 else
552 {
553 /* Sharp mode */
554 flat_power = power_meter_update(&s->flat_power, amp[i]);
555
556 /* Persistence checking and notch insertion logic */
557 if (flat_power >= s->sharp_detection_threshold)
558 {
559 /* Which is the better of the single tone responses? */
560 m = (notch_power[0] < notch_power[1]) ? 0 : 1;
561 /* Single tone has precedence. If the better one fails to detect, try
562 for a dual tone signal. */
563 if ((notch_power[m] >> 6)*s->detection_ratio < (flat_power >> 6))
564 immediate = m;
565 else if ((notch_power[2] >> 6)*s->detection_ratio < (flat_power >> 7))
566 immediate = 2;
567 }
568 //printf("Immediate = %d %d %d\n", immediate, s->signalling_state, s->tone_persistence_timeout);
569 if ((s->signalling_state & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT)))
570 {
571 if (immediate != s->current_notch_filter)
572 {
573 /* No tone is detected this sample */
574 if (--s->tone_persistence_timeout == 0)
575 {
576 /* Tone off is confirmed */
577 s->tone_persistence_timeout = s->desc->tone_on_check_time;
578 s->signalling_state |= ((s->signalling_state & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT)) << 1);
579 s->signalling_state &= ~(SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT);
580 }
581 /*endif*/
582 }
583 else
584 {
585 s->tone_persistence_timeout = s->desc->tone_off_check_time;
586 }
587 /*endif*/
588 }
589 else
590 {
591 if (s->notch_insertion_timeout)
592 s->notch_insertion_timeout--;
593 /*endif*/
594 if (immediate >= 0 && immediate == s->last_sample_tone_present)
595 {
596 /* Consistent tone detected this sample */
597 if (--s->tone_persistence_timeout == 0)
598 {
599 /* Tone on is confirmed */
600 s->tone_persistence_timeout = s->desc->tone_off_check_time;
601 s->notch_insertion_timeout = s->desc->notch_lag_time;
602 s->signalling_state |= (tone_present_bits[immediate] | tone_change_bits[immediate]);
603 s->current_notch_filter = immediate;
604 }
605 /*endif*/
606 }
607 else
608 {
609 s->tone_persistence_timeout = s->desc->tone_on_check_time;
610 }
611 /*endif*/
612 }
613 /*endif*/
614 //printf("XXX %d %d %d %d %d %d\n", nnn++, notch_power[0], notch_power[1], notch_power[2], flat_power, immediate*10000000);
615 }
616 /*endif*/
617 if ((s->signalling_state & (SIG_TONE_1_CHANGE | SIG_TONE_2_CHANGE)))
618 {
619 if (s->sig_update)
620 s->sig_update(s->user_data, s->signalling_state, 0, s->signalling_state_duration);
621 /*endif*/
622 s->signalling_state &= ~(SIG_TONE_1_CHANGE | SIG_TONE_2_CHANGE);
623 s->signalling_state_duration = 0;
624 }
625 /*endif*/
626
627 if ((s->current_rx_tone & SIG_TONE_RX_PASSTHROUGH))
628 {
629 if ((s->current_rx_tone & SIG_TONE_RX_FILTER_TONE) || s->notch_insertion_timeout)
630#if defined(SPANDSP_USE_FIXED_POINT)
631 amp[i] = saturate16(notched_signal[s->current_notch_filter]);
632#else
633 amp[i] = fsaturatef(notched_signal[s->current_notch_filter]);
634#endif
635 /*endif*/
636 }
637 else
638 {
639 /* Simply mute the media path */
640 amp[i] = 0;
641 }
642 /*endif*/
643 s->last_sample_tone_present = immediate;
644 }
645 /*endfor*/
646 return len;
647}
648/*- End of function --------------------------------------------------------*/
649
650SPAN_DECLARE(void)__attribute__((visibility("default"))) void sig_tone_rx_set_mode(sig_tone_rx_state_t *s, int mode, int duration)
651{
652 s->current_rx_tone = mode;
653}
654/*- End of function --------------------------------------------------------*/
655
656SPAN_DECLARE(sig_tone_rx_state_t *)__attribute__((visibility("default"))) sig_tone_rx_state_t * sig_tone_rx_init(sig_tone_rx_state_t *s, int tone_type, tone_report_func_t sig_update, void *user_data)
657{
658 int i;
659#if !defined(SPANDSP_USE_FIXED_POINT)
660 int j;
661#endif
662
663 if (sig_update == NULL((void*)0) || tone_type < 1 || tone_type > 3)
664 return NULL((void*)0);
665 /*endif*/
666
667 if (s == NULL((void*)0))
668 {
669 if ((s = (sig_tone_rx_state_t *) span_alloc(sizeof(*s))) == NULL((void*)0))
670 return NULL((void*)0);
671 }
672 memset(s, 0, sizeof(*s));
673#if !defined(SPANDSP_USE_FIXED_POINT)
674 for (j = 0; j < 3; j++)
675 {
676 for (i = 0; i < 2; i++)
677 {
678 s->tone[j].notch_z1[i] = 0.0f;
679 s->tone[j].notch_z2[i] = 0.0f;
680 }
681 }
682 for (i = 0; i < 2; i++)
683 s->flat_z[i] = 0.0f;
684#endif
685 s->last_sample_tone_present = -1;
686
687 s->sig_update = sig_update;
688 s->user_data = user_data;
689
690 s->desc = &sig_tones[tone_type - 1];
691
692 for (i = 0; i < 3; i++)
693 power_meter_init(&s->tone[i].power, 5);
694 power_meter_init(&s->flat_power, 5);
695
696 s->flat_detection_threshold = power_meter_level_dbm0(s->desc->flat_detection_threshold);
697 s->sharp_detection_threshold = power_meter_level_dbm0(s->desc->sharp_detection_threshold);
698 s->detection_ratio = powf(10.0f, s->desc->detection_ratio/10.0f) + 1.0f;
699
700 return s;
701}
702/*- End of function --------------------------------------------------------*/
703
704SPAN_DECLARE(int)__attribute__((visibility("default"))) int sig_tone_rx_release(sig_tone_rx_state_t *s)
705{
706 return 0;
707}
708/*- End of function --------------------------------------------------------*/
709
710SPAN_DECLARE(int)__attribute__((visibility("default"))) int sig_tone_rx_free(sig_tone_rx_state_t *s)
711{
712 if (s)
713 span_free(s);
714 return 0;
715}
716/*- End of function --------------------------------------------------------*/
717/*- End of file ------------------------------------------------------------*/