Mercurial > hg > audiostuff
comparison spandsp-0.0.6pre17/src/sig_tone.c @ 4:26cd8f1ef0b1
import spandsp-0.0.6pre17
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 15:50:58 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
3:c6c5a16ce2f2 | 4:26cd8f1ef0b1 |
---|---|
1 /* | |
2 * SpanDSP - a series of DSP components for telephony | |
3 * | |
4 * sig_tone.c - Signalling tone processing for the 2280Hz, 2600Hz and similar | |
5 * signalling tone 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 * $Id: sig_tone.c,v 1.33 2009/09/04 14:38:46 steveu Exp $ | |
27 */ | |
28 | |
29 /*! \file */ | |
30 | |
31 #if defined(HAVE_CONFIG_H) | |
32 #include "config.h" | |
33 #endif | |
34 | |
35 #include <stdlib.h> | |
36 #include <stdio.h> | |
37 #include <inttypes.h> | |
38 #if defined(HAVE_TGMATH_H) | |
39 #include <tgmath.h> | |
40 #endif | |
41 #if defined(HAVE_MATH_H) | |
42 #include <math.h> | |
43 #endif | |
44 #include "floating_fudge.h" | |
45 #include <memory.h> | |
46 #include <string.h> | |
47 #include <limits.h> | |
48 | |
49 #undef SPANDSP_USE_FIXED_POINT | |
50 #include "spandsp/telephony.h" | |
51 #include "spandsp/fast_convert.h" | |
52 #include "spandsp/dc_restore.h" | |
53 #include "spandsp/saturated.h" | |
54 #include "spandsp/vector_int.h" | |
55 #include "spandsp/complex.h" | |
56 #include "spandsp/dds.h" | |
57 #include "spandsp/super_tone_rx.h" | |
58 #include "spandsp/sig_tone.h" | |
59 | |
60 #include "spandsp/private/sig_tone.h" | |
61 | |
62 /*! PI */ | |
63 #define PI 3.14159265358979323 | |
64 | |
65 /* The coefficients for the data notch filter. This filter is also the | |
66 guard filter for tone detection. */ | |
67 | |
68 sig_tone_descriptor_t sig_tones[4] = | |
69 { | |
70 { | |
71 /* 2280Hz (e.g. AC15, and many other European protocols) */ | |
72 {2280, 0}, | |
73 {{-10, -20}, {0, 0}}, /* -10+-1 dBmO and -20+-1 dBm0 */ | |
74 ms_to_samples(400), /* 300ms to 550ms */ | |
75 | |
76 ms_to_samples(225), | |
77 | |
78 ms_to_samples(225), | |
79 TRUE, | |
80 | |
81 24, | |
82 64, | |
83 | |
84 1, | |
85 { | |
86 { | |
87 #if defined(SPANDSP_USE_FIXED_POINT) | |
88 { 3600, 14397, 32767}, | |
89 { 0, -9425, -28954}, | |
90 { 0, 14196, 32767}, | |
91 { 0, -17393, -28954}, | |
92 12, | |
93 #else | |
94 {0.878906f, 0.439362f, 1.0f}, | |
95 {0.0f, -0.287627f, -0.883605f}, | |
96 {0.0f, 0.433228f, 1.0f}, | |
97 {0.0f, -0.530792f, -0.883605f}, | |
98 #endif | |
99 }, | |
100 { | |
101 #if defined(SPANDSP_USE_FIXED_POINT) | |
102 { 0, 0, 0}, | |
103 { 0, 0, 0}, | |
104 { 0, 0, 0}, | |
105 { 0, 0, 0}, | |
106 0, | |
107 #else | |
108 {0.0f, 0.0f, 0.0f}, | |
109 {0.0f, 0.0f, 0.0f}, | |
110 {0.0f, 0.0f, 0.0f}, | |
111 {0.0f, 0.0f, 0.0f}, | |
112 #endif | |
113 } | |
114 }, | |
115 #if defined(SPANDSP_USE_FIXED_POINT) | |
116 { 12900, -16384, -16384}, | |
117 { 0, -8578, -11796}, | |
118 15, | |
119 #else | |
120 {0.393676f, -0.5f, -0.5f}, | |
121 {0.0f, -0.261778f, -0.359985f}, | |
122 #endif | |
123 | |
124 31744, | |
125 1024, | |
126 | |
127 31744, | |
128 187, | |
129 | |
130 31744, | |
131 187, | |
132 | |
133 -1, | |
134 -32, | |
135 | |
136 57 | |
137 }, | |
138 { | |
139 /* 2600Hz (e.g. many US protocols) */ | |
140 {2600, 0}, | |
141 {{-8, -8}, {0, 0}}, | |
142 ms_to_samples(400), | |
143 | |
144 ms_to_samples(225), | |
145 | |
146 ms_to_samples(225), | |
147 FALSE, | |
148 | |
149 24, | |
150 64, | |
151 | |
152 1, | |
153 { | |
154 { | |
155 #if defined(SPANDSP_USE_FIXED_POINT) | |
156 { 3539, 29569, 32767}, | |
157 { 0, -24010, -28341}, | |
158 { 0, 29844, 32767}, | |
159 { 0, -31208, -28341}, | |
160 12, | |
161 #else | |
162 {0.864014f, 0.902374f, 1.0f}, | |
163 {0.0f, -0.732727f, -0.864899f}, | |
164 {0.0f, 0.910766f, 1.0f}, | |
165 {0.0f, -0.952393f, -0.864899f}, | |
166 #endif | |
167 }, | |
168 { | |
169 #if defined(SPANDSP_USE_FIXED_POINT) | |
170 { 0, 0, 0}, | |
171 { 0, 0, 0}, | |
172 { 0, 0, 0}, | |
173 { 0, 0, 0}, | |
174 0, | |
175 #else | |
176 {0.0f, 0.0f, 0.0f}, | |
177 {0.0f, 0.0f, 0.0f}, | |
178 {0.0f, 0.0f, 0.0f}, | |
179 {0.0f, 0.0f, 0.0f}, | |
180 #endif | |
181 } | |
182 }, | |
183 #if defined(SPANDSP_USE_FIXED_POINT) | |
184 { 32768, 0, 0}, | |
185 { 0, 0, 0}, | |
186 15, | |
187 #else | |
188 {1.0f, 0.0f, 0.0f}, | |
189 {0.0f, 0.0f, 0.0f}, | |
190 #endif | |
191 | |
192 31744, | |
193 1024, | |
194 | |
195 31744, | |
196 170, | |
197 | |
198 31744, | |
199 170, | |
200 | |
201 -1, | |
202 -32, | |
203 | |
204 52 | |
205 }, | |
206 { | |
207 /* 2400Hz/2600Hz (e.g. SS5 and SS5bis) */ | |
208 {2600, 2400}, | |
209 {{-8, -8}, {-8, -8}}, | |
210 ms_to_samples(400), | |
211 | |
212 ms_to_samples(225), | |
213 | |
214 ms_to_samples(225), | |
215 FALSE, | |
216 | |
217 24, | |
218 64, | |
219 | |
220 2, | |
221 { | |
222 { | |
223 #if defined(SPANDSP_USE_FIXED_POINT) | |
224 { 3539, 29569, 32767}, | |
225 { 0, -24010, -28341}, | |
226 { 0, 29844, 32767}, | |
227 { 0, -31208, -28341}, | |
228 12, | |
229 #else | |
230 {0.864014f, 0.902374f, 1.0f}, | |
231 {0.0f, -0.732727f, -0.864899f}, | |
232 {0.0f, 0.910766f, 1.0f}, | |
233 {0.0f, -0.952393f, -0.864899f}, | |
234 #endif | |
235 }, | |
236 { | |
237 #if defined(SPANDSP_USE_FIXED_POINT) | |
238 { 3539, 20349, 32767}, | |
239 { 0, -22075, -31856}, | |
240 { 0, 20174, 32767}, | |
241 { 0, -17832, -31836}, | |
242 12, | |
243 #else | |
244 {0.864014f, 0.621007f, 1.0f}, | |
245 {0.0f, -0.673667f, -0.972167f}, | |
246 {0.0f, 0.615669f, 1.0f}, | |
247 {0.0f, -0.544180f, -0.971546f}, | |
248 #endif | |
249 } | |
250 }, | |
251 #if defined(SPANDSP_USE_FIXED_POINT) | |
252 { 32768, 0, 0}, | |
253 { 0, 0, 0}, | |
254 15, | |
255 #else | |
256 {1.0f, 0.0f, 0.0f}, | |
257 {0.0f, 0.0f, 0.0f}, | |
258 #endif | |
259 | |
260 31744, | |
261 1024, | |
262 | |
263 31744, | |
264 170, | |
265 | |
266 31744, | |
267 170, | |
268 | |
269 -1, | |
270 -32, | |
271 | |
272 52 | |
273 } | |
274 }; | |
275 | |
276 SPAN_DECLARE(int) sig_tone_tx(sig_tone_tx_state_t *s, int16_t amp[], int len) | |
277 { | |
278 int i; | |
279 int j; | |
280 int n; | |
281 int16_t tone; | |
282 int need_update; | |
283 int high_low; | |
284 | |
285 for (i = 0; i < len; i += n) | |
286 { | |
287 if (s->current_tx_timeout) | |
288 { | |
289 if (s->current_tx_timeout <= len - i) | |
290 { | |
291 n = s->current_tx_timeout; | |
292 need_update = TRUE; | |
293 } | |
294 else | |
295 { | |
296 n = len - i; | |
297 need_update = FALSE; | |
298 } | |
299 s->current_tx_timeout -= n; | |
300 } | |
301 else | |
302 { | |
303 n = len - i; | |
304 need_update = FALSE; | |
305 } | |
306 if (!(s->current_tx_tone & SIG_TONE_TX_PASSTHROUGH)) | |
307 vec_zeroi16(&[i], n); | |
308 /*endif*/ | |
309 if ((s->current_tx_tone & (SIG_TONE_1_PRESENT || SIG_TONE_2_PRESENT))) | |
310 { | |
311 /* Are we in the early phase (high tone energy level), or the sustaining | |
312 phase (low tone energy level) of tone generation? */ | |
313 /* This doesn't try to get the high/low timing precise, as there is no | |
314 value in doing so. It works block by block, and the blocks are normally | |
315 quite short. */ | |
316 if (s->high_low_timer > 0) | |
317 { | |
318 if (n > s->high_low_timer) | |
319 n = s->high_low_timer; | |
320 s->high_low_timer -= n; | |
321 high_low = 0; | |
322 } | |
323 else | |
324 { | |
325 high_low = 1; | |
326 } | |
327 /*endif*/ | |
328 if ((s->current_tx_tone & SIG_TONE_1_PRESENT) && s->phase_rate[0]) | |
329 { | |
330 for (j = i; j < i + n; j++) | |
331 { | |
332 tone = dds_mod(&(s->phase_acc[0]), s->phase_rate[0], s->tone_scaling[0][high_low], 0); | |
333 amp[j] = saturate(amp[j] + tone); | |
334 } | |
335 /*endfor*/ | |
336 } | |
337 /*endif*/ | |
338 if ((s->current_tx_tone & SIG_TONE_2_PRESENT) && s->phase_rate[1]) | |
339 { | |
340 for (j = i; j < i + n; j++) | |
341 { | |
342 tone = dds_mod(&(s->phase_acc[1]), s->phase_rate[1], s->tone_scaling[1][high_low], 0); | |
343 amp[j] = saturate(amp[j] + tone); | |
344 } | |
345 /*endfor*/ | |
346 } | |
347 /*endif*/ | |
348 } | |
349 /*endif*/ | |
350 if (need_update && s->sig_update) | |
351 s->sig_update(s->user_data, SIG_TONE_TX_UPDATE_REQUEST, 0, 0); | |
352 /*endif*/ | |
353 } | |
354 /*endfor*/ | |
355 return len; | |
356 } | |
357 /*- End of function --------------------------------------------------------*/ | |
358 | |
359 SPAN_DECLARE(void) sig_tone_tx_set_mode(sig_tone_tx_state_t *s, int mode, int duration) | |
360 { | |
361 int old_tones; | |
362 int new_tones; | |
363 | |
364 old_tones = s->current_tx_tone & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT); | |
365 new_tones = mode & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT); | |
366 if (new_tones && old_tones != new_tones) | |
367 s->high_low_timer = s->desc->high_low_timeout; | |
368 /*endif*/ | |
369 s->current_tx_tone = mode; | |
370 s->current_tx_timeout = duration; | |
371 } | |
372 /*- End of function --------------------------------------------------------*/ | |
373 | |
374 SPAN_DECLARE(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) | |
375 { | |
376 int i; | |
377 | |
378 if (sig_update == NULL || tone_type < 1 || tone_type > 3) | |
379 return NULL; | |
380 /*endif*/ | |
381 | |
382 if (s == NULL) | |
383 { | |
384 if ((s = (sig_tone_tx_state_t *) malloc(sizeof(*s))) == NULL) | |
385 return NULL; | |
386 } | |
387 memset(s, 0, sizeof(*s)); | |
388 | |
389 s->sig_update = sig_update; | |
390 s->user_data = user_data; | |
391 | |
392 s->desc = &sig_tones[tone_type - 1]; | |
393 | |
394 for (i = 0; i < 2; i++) | |
395 { | |
396 if (s->desc->tone_freq[i]) | |
397 s->phase_rate[i] = dds_phase_rate((float) s->desc->tone_freq[i]); | |
398 else | |
399 s->phase_rate[i] = 0; | |
400 s->tone_scaling[i][0] = dds_scaling_dbm0((float) s->desc->tone_amp[i][0]); | |
401 s->tone_scaling[i][1] = dds_scaling_dbm0((float) s->desc->tone_amp[i][1]); | |
402 } | |
403 return s; | |
404 } | |
405 /*- End of function --------------------------------------------------------*/ | |
406 | |
407 SPAN_DECLARE(int) sig_tone_tx_release(sig_tone_tx_state_t *s) | |
408 { | |
409 return 0; | |
410 } | |
411 /*- End of function --------------------------------------------------------*/ | |
412 | |
413 SPAN_DECLARE(int) sig_tone_tx_free(sig_tone_tx_state_t *s) | |
414 { | |
415 if (s) | |
416 free(s); | |
417 return 0; | |
418 } | |
419 /*- End of function --------------------------------------------------------*/ | |
420 | |
421 SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len) | |
422 { | |
423 #if defined(SPANDSP_USE_FIXED_POINT) | |
424 int32_t x; | |
425 int32_t notched_signal; | |
426 int32_t bandpass_signal; | |
427 #else | |
428 float x; | |
429 float notched_signal; | |
430 float bandpass_signal; | |
431 #endif | |
432 int i; | |
433 int j; | |
434 int32_t mown_notch[2]; | |
435 int32_t mown_bandpass; | |
436 | |
437 for (i = 0; i < len; i++) | |
438 { | |
439 if (s->signaling_state_duration < INT_MAX) | |
440 s->signaling_state_duration++; | |
441 /*endif*/ | |
442 notched_signal = 0; | |
443 for (j = 0; j < s->desc->tones; j++) | |
444 { | |
445 /* The notch filter is two cascaded biquads. */ | |
446 notched_signal = amp[i]; | |
447 | |
448 #if defined(SPANDSP_USE_FIXED_POINT) | |
449 notched_signal *= s->desc->tone[j].notch_a1[0]; | |
450 notched_signal += s->tone[j].notch_z1[1]*s->desc->tone[j].notch_b1[1]; | |
451 notched_signal += s->tone[j].notch_z1[2]*s->desc->tone[j].notch_b1[2]; | |
452 x = notched_signal; | |
453 notched_signal += s->tone[j].notch_z1[1]*s->desc->tone[j].notch_a1[1]; | |
454 notched_signal += s->tone[j].notch_z1[2]*s->desc->tone[j].notch_a1[2]; | |
455 s->tone[j].notch_z1[2] = s->tone[j].notch_z1[1]; | |
456 s->tone[j].notch_z1[1] = x >> 15; | |
457 | |
458 notched_signal += s->tone[j].notch_z2[1]*s->desc->tone[j].notch_b2[1]; | |
459 notched_signal += s->tone[j].notch_z2[2]*s->desc->tone[j].notch_b2[2]; | |
460 x = notched_signal; | |
461 notched_signal += s->tone[j].notch_z2[1]*s->desc->tone[j].notch_a2[1]; | |
462 notched_signal += s->tone[j].notch_z2[2]*s->desc->tone[j].notch_a2[2]; | |
463 s->tone[j].notch_z2[2] = s->tone[j].notch_z2[1]; | |
464 s->tone[j].notch_z2[1] = x >> 15; | |
465 | |
466 notched_signal >>= s->desc->notch_postscale; | |
467 #else | |
468 notched_signal *= s->desc->tone[j].notch_a1[0]; | |
469 notched_signal += s->tone[j].notch_z1[1]*s->desc->tone[j].notch_b1[1]; | |
470 notched_signal += s->tone[j].notch_z1[2]*s->desc->tone[j].notch_b1[2]; | |
471 x = notched_signal; | |
472 notched_signal += s->tone[j].notch_z1[1]*s->desc->tone[j].notch_a1[1]; | |
473 notched_signal += s->tone[j].notch_z1[2]*s->desc->tone[j].notch_a1[2]; | |
474 s->tone[j].notch_z1[2] = s->tone[j].notch_z1[1]; | |
475 s->tone[j].notch_z1[1] = x; | |
476 | |
477 notched_signal += s->tone[j].notch_z2[1]*s->desc->tone[j].notch_b2[1]; | |
478 notched_signal += s->tone[j].notch_z2[2]*s->desc->tone[j].notch_b2[2]; | |
479 x = notched_signal; | |
480 notched_signal += s->tone[j].notch_z2[1]*s->desc->tone[j].notch_a2[1]; | |
481 notched_signal += s->tone[j].notch_z2[2]*s->desc->tone[j].notch_a2[2]; | |
482 s->tone[j].notch_z2[2] = s->tone[j].notch_z2[1]; | |
483 s->tone[j].notch_z2[1] = x; | |
484 #endif | |
485 /* Modulus and leaky integrate the notched data. The result of | |
486 this isn't used in low tone detect mode, but we must keep notch_zl | |
487 rolling along. */ | |
488 s->tone[j].notch_zl = ((s->tone[j].notch_zl*s->desc->notch_slugi) >> 15) | |
489 + ((abs((int) notched_signal)*s->desc->notch_slugp) >> 15); | |
490 /* Mow the grass to weed out the noise! */ | |
491 mown_notch[j] = s->tone[0].notch_zl & s->desc->notch_threshold; | |
492 } | |
493 | |
494 if (s->tone_present) | |
495 { | |
496 if (s->flat_mode_timeout <= 0) | |
497 s->flat_mode = TRUE; | |
498 else | |
499 s->flat_mode_timeout--; | |
500 /*endif*/ | |
501 } | |
502 else | |
503 { | |
504 s->flat_mode_timeout = s->desc->sharp_flat_timeout; | |
505 s->flat_mode = FALSE; | |
506 } | |
507 /*endif*/ | |
508 | |
509 if (s->flat_mode) | |
510 { | |
511 /* Flat mode */ | |
512 | |
513 /* The bandpass filter is a single bi-quad stage */ | |
514 bandpass_signal = amp[i]; | |
515 #if defined(SPANDSP_USE_FIXED_POINT) | |
516 bandpass_signal *= s->desc->broad_a[0]; | |
517 bandpass_signal += s->broad_z[1]*s->desc->broad_b[1]; | |
518 bandpass_signal += s->broad_z[2]*s->desc->broad_b[2]; | |
519 x = bandpass_signal; | |
520 bandpass_signal += s->broad_z[1]*s->desc->broad_a[1]; | |
521 bandpass_signal += s->broad_z[2]*s->desc->broad_a[2]; | |
522 s->broad_z[2] = s->broad_z[1]; | |
523 s->broad_z[1] = x >> 15; | |
524 bandpass_signal >>= s->desc->broad_postscale; | |
525 #else | |
526 bandpass_signal *= s->desc->broad_a[0]; | |
527 bandpass_signal += s->broad_z[1]*s->desc->broad_b[1]; | |
528 bandpass_signal += s->broad_z[2]*s->desc->broad_b[2]; | |
529 x = bandpass_signal; | |
530 bandpass_signal += s->broad_z[1]*s->desc->broad_a[1]; | |
531 bandpass_signal += s->broad_z[2]*s->desc->broad_a[2]; | |
532 s->broad_z[2] = s->broad_z[1]; | |
533 s->broad_z[1] = x; | |
534 #endif | |
535 /* Leaky integrate the bandpassed data */ | |
536 s->broad_zl = ((s->broad_zl*s->desc->broad_slugi) >> 15) | |
537 + ((abs((int) bandpass_signal)*s->desc->broad_slugp) >> 15); | |
538 | |
539 /* For the broad band receiver we use a simple linear threshold! */ | |
540 if (s->tone_present) | |
541 { | |
542 s->tone_present = (s->broad_zl > s->desc->broad_threshold); | |
543 if (!s->tone_present) | |
544 { | |
545 if (s->sig_update) | |
546 s->sig_update(s->user_data, SIG_TONE_1_CHANGE, 0, s->signaling_state_duration); | |
547 /*endif*/ | |
548 s->signaling_state_duration = 0; | |
549 } | |
550 /*endif*/ | |
551 } | |
552 else | |
553 { | |
554 s->tone_present = (s->broad_zl > s->desc->broad_threshold); | |
555 if (s->tone_present) | |
556 { | |
557 if (s->sig_update) | |
558 s->sig_update(s->user_data, SIG_TONE_1_CHANGE | SIG_TONE_1_PRESENT, 0, s->signaling_state_duration); | |
559 /*endif*/ | |
560 s->signaling_state_duration = 0; | |
561 } | |
562 /*endif*/ | |
563 } | |
564 /*endif*/ | |
565 | |
566 /* Notch insertion logic */ | |
567 /* tone_present and tone_on are equivalent in flat mode */ | |
568 if (s->tone_present) | |
569 { | |
570 s->notch_enabled = s->desc->notch_allowed; | |
571 s->notch_insertion_timeout = s->desc->notch_lag_time; | |
572 } | |
573 else | |
574 { | |
575 if (s->notch_insertion_timeout > 0) | |
576 s->notch_insertion_timeout--; | |
577 else | |
578 s->notch_enabled = FALSE; | |
579 /*endif*/ | |
580 } | |
581 /*endif*/ | |
582 } | |
583 else | |
584 { | |
585 /* Sharp mode */ | |
586 | |
587 /* Modulus and leaky integrate the data */ | |
588 s->broad_zl = ((s->broad_zl*s->desc->unfiltered_slugi) >> 15) | |
589 + ((abs((int) amp[i])*s->desc->unfiltered_slugp) >> 15); | |
590 | |
591 /* Mow the grass to weed out the noise! */ | |
592 mown_bandpass = s->broad_zl & s->desc->unfiltered_threshold; | |
593 | |
594 /* Persistence checking and notch insertion logic */ | |
595 if (!s->tone_present) | |
596 { | |
597 if (mown_notch[0] < mown_bandpass) | |
598 { | |
599 /* Tone is detected this sample */ | |
600 if (s->tone_persistence_timeout <= 0) | |
601 { | |
602 s->tone_present = TRUE; | |
603 s->notch_enabled = s->desc->notch_allowed; | |
604 s->tone_persistence_timeout = s->desc->tone_off_check_time; | |
605 s->notch_insertion_timeout = s->desc->notch_lag_time; | |
606 if (s->sig_update) | |
607 s->sig_update(s->user_data, SIG_TONE_1_CHANGE | SIG_TONE_1_PRESENT, 0, s->signaling_state_duration); | |
608 /*endif*/ | |
609 s->signaling_state_duration = 0; | |
610 } | |
611 else | |
612 { | |
613 s->tone_persistence_timeout--; | |
614 if (s->notch_insertion_timeout > 0) | |
615 s->notch_insertion_timeout--; | |
616 else | |
617 s->notch_enabled = FALSE; | |
618 /*endif*/ | |
619 } | |
620 /*endif*/ | |
621 } | |
622 else | |
623 { | |
624 s->tone_persistence_timeout = s->desc->tone_on_check_time; | |
625 if (s->notch_insertion_timeout > 0) | |
626 s->notch_insertion_timeout--; | |
627 else | |
628 s->notch_enabled = FALSE; | |
629 /*endif*/ | |
630 } | |
631 /*endif*/ | |
632 } | |
633 else | |
634 { | |
635 if (mown_notch[0] > mown_bandpass) | |
636 { | |
637 /* Tone is not detected this sample */ | |
638 if (s->tone_persistence_timeout <= 0) | |
639 { | |
640 s->tone_present = FALSE; | |
641 s->tone_persistence_timeout = s->desc->tone_on_check_time; | |
642 if (s->sig_update) | |
643 s->sig_update(s->user_data, SIG_TONE_1_CHANGE, 0, s->signaling_state_duration); | |
644 /*endif*/ | |
645 s->signaling_state_duration = 0; | |
646 } | |
647 else | |
648 { | |
649 s->tone_persistence_timeout--; | |
650 } | |
651 /*endif*/ | |
652 } | |
653 else | |
654 { | |
655 s->tone_persistence_timeout = s->desc->tone_off_check_time; | |
656 } | |
657 /*endif*/ | |
658 } | |
659 /*endif*/ | |
660 } | |
661 /*endif*/ | |
662 | |
663 if ((s->current_rx_tone & SIG_TONE_RX_PASSTHROUGH)) | |
664 { | |
665 if ((s->current_rx_tone & SIG_TONE_RX_FILTER_TONE) || s->notch_enabled) | |
666 amp[i] = (int16_t) notched_signal; | |
667 /*endif*/ | |
668 } | |
669 else | |
670 { | |
671 amp[i] = 0; | |
672 } | |
673 /*endif*/ | |
674 } | |
675 /*endfor*/ | |
676 return len; | |
677 } | |
678 /*- End of function --------------------------------------------------------*/ | |
679 | |
680 SPAN_DECLARE(void) sig_tone_rx_set_mode(sig_tone_rx_state_t *s, int mode, int duration) | |
681 { | |
682 s->current_rx_tone = mode; | |
683 } | |
684 /*- End of function --------------------------------------------------------*/ | |
685 | |
686 SPAN_DECLARE(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) | |
687 { | |
688 if (sig_update == NULL || tone_type < 1 || tone_type > 3) | |
689 return NULL; | |
690 /*endif*/ | |
691 | |
692 if (s == NULL) | |
693 { | |
694 if ((s = (sig_tone_rx_state_t *) malloc(sizeof(*s))) == NULL) | |
695 return NULL; | |
696 } | |
697 memset(s, 0, sizeof(*s)); | |
698 | |
699 s->sig_update = sig_update; | |
700 s->user_data = user_data; | |
701 | |
702 s->desc = &sig_tones[tone_type - 1]; | |
703 | |
704 s->flat_mode_timeout = 0; | |
705 s->notch_insertion_timeout = 0; | |
706 s->tone_persistence_timeout = 0; | |
707 s->signaling_state_duration = 0; | |
708 return s; | |
709 } | |
710 /*- End of function --------------------------------------------------------*/ | |
711 | |
712 SPAN_DECLARE(int) sig_tone_rx_release(sig_tone_rx_state_t *s) | |
713 { | |
714 return 0; | |
715 } | |
716 /*- End of function --------------------------------------------------------*/ | |
717 | |
718 SPAN_DECLARE(int) sig_tone_rx_free(sig_tone_rx_state_t *s) | |
719 { | |
720 if (s) | |
721 free(s); | |
722 return 0; | |
723 } | |
724 /*- End of function --------------------------------------------------------*/ | |
725 /*- End of file ------------------------------------------------------------*/ |