comparison spandsp-0.0.3/spandsp-0.0.3/src/sig_tone.c @ 5:f762bf195c4b

import spandsp-0.0.3
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 16:00:21 +0200
parents
children
comparison
equal deleted inserted replaced
4:26cd8f1ef0b1 5:f762bf195c4b
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 General Public License version 2, as
15 * 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 General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * 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.15 2006/11/19 14:07:25 steveu Exp $
27 */
28
29 /*! \file */
30
31 #ifdef 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 <memory.h>
45 #include <string.h>
46
47 #include "spandsp/telephony.h"
48 #include "spandsp/dc_restore.h"
49 #include "spandsp/dds.h"
50 #include "spandsp/sig_tone.h"
51
52 #define PI 3.14159265358979323
53
54 /* The coefficients for the data notch filter. This filter is also the
55 guard filter for tone detection. */
56
57 sig_tone_descriptor_t sig_tones[4] =
58 {
59 {
60 /* 2280Hz (e.g. AC15, and many other European protocols) */
61 {2280, 0},
62 {-10, -20},
63 400*8,
64
65 225*8,
66
67 225*8,
68 TRUE,
69
70 24,
71 64,
72
73 { 3600, 14397, 32767},
74 { 0, -9425, -28954},
75 { 0, 14196, 32767},
76 { 0, -17393, -28954},
77 12,
78 /*
79 0.1098633, 0.4393615, 1.0,
80 0, -0.2876274, -0.8836059,
81 0, 0.4332275, 1.0,
82 0, -0.5307922, -0.8836059,
83 */
84 { 12900, -16384, -16384},
85 { 0, -8578, -11796},
86 15,
87
88 31744,
89 1024,
90
91 31744,
92 187,
93
94 31744,
95 187,
96
97 -1,
98 -32,
99
100 57
101 },
102 {
103 /* 2600Hz (e.g. many US protocols) */
104 {2600, 0},
105 {-8, -8},
106 400*8,
107
108 225*8,
109
110 225*8,
111 FALSE,
112
113 24,
114 64,
115
116 { 3539, 29569, 32767},
117 { 0, -24010, -28341},
118 { 0, 29844, 32767},
119 { 0, -31208, -28341},
120 12,
121 /*
122 0.1080017, 0.9023743, 1.0,
123 0, -0.7327271, -0.86489868,
124 0, 0.9107666, 1.0,
125 0, -0.9523925, -0.86489868,
126 */
127 { 32768, 0, 0},
128 { 0, 0, 0},
129 15,
130
131 31744,
132 1024,
133
134 31744,
135 170,
136
137 31744,
138 170,
139
140 -1,
141 -32,
142
143 52
144 },
145 {
146 /* 2400Hz / 2600Hz (e.g. SS5 and SS5bis) */
147 {2400, 2600},
148 {-8, -8},
149 400*8,
150
151 225*8,
152
153 225*8,
154 FALSE,
155
156 24,
157 64,
158
159 { 3539, 20349, 32767},
160 { 0, -22075, -31856},
161 { 0, 20174, 32767},
162 { 0, -17832, -31836},
163 12,
164 /*
165 0.1080017, 0.6210065, 1.0,
166 0, -0.6736673, -0.9721678,
167 0, 0.6156693, 1.0,
168 0, -0.5441804, -0.9715460,
169 */
170
171 { 32768, 0, 0},
172 { 0, 0, 0},
173 15,
174
175 31744,
176 1024,
177
178 31744,
179 170,
180
181 31744,
182 170,
183
184 -1,
185 -32,
186
187 52
188 }
189 };
190
191 int sig_tone_rx(sig_tone_state_t *s, int16_t amp[], int len)
192 {
193 int32_t x;
194 int32_t notched_signal;
195 int32_t bandpass_signal;
196 int i;
197
198 for (i = 0; i < len; i++)
199 {
200 if (s->signaling_state_duration < 0xFFFF)
201 s->signaling_state_duration++;
202 /*endif*/
203 /* The notch filter is two cascaded biquads. */
204 notched_signal = amp[i];
205
206 notched_signal *= s->desc->notch_a1[0];
207 notched_signal += s->notch_z1[1]*s->desc->notch_b1[1];
208 notched_signal += s->notch_z1[2]*s->desc->notch_b1[2];
209 x = notched_signal;
210 notched_signal += s->notch_z1[1]*s->desc->notch_a1[1];
211 notched_signal += s->notch_z1[2]*s->desc->notch_a1[2];
212 s->notch_z1[2] = s->notch_z1[1];
213 s->notch_z1[1] = x >> 15;
214
215 notched_signal += s->notch_z2[1]*s->desc->notch_b2[1];
216 notched_signal += s->notch_z2[2]*s->desc->notch_b2[2];
217 x = notched_signal;
218 notched_signal += s->notch_z2[1]*s->desc->notch_a2[1];
219 notched_signal += s->notch_z2[2]*s->desc->notch_a2[2];
220 s->notch_z2[2] = s->notch_z2[1];
221 s->notch_z2[1] = x >> 15;
222
223 notched_signal >>= s->desc->notch_postscale;
224
225 /* Modulus and leaky integrate the notched data. The result of
226 this isn't used in low tone detect mode, but we must keep notch_zl
227 rolling along. */
228 s->notch_zl = ((s->notch_zl*s->desc->notch_slugi) >> 15)
229 + ((abs(notched_signal)*s->desc->notch_slugp) >> 15);
230
231 /* Mow the grass to weed out the noise! */
232 s->mown_notch = s->notch_zl & s->desc->notch_threshold;
233
234 if (s->tone_present)
235 {
236 if (s->flat_mode_timeout <= 0)
237 s->flat_mode = TRUE;
238 else
239 s->flat_mode_timeout--;
240 /*endif*/
241 }
242 else
243 {
244 s->flat_mode_timeout = s->desc->sharp_flat_timeout;
245 s->flat_mode = FALSE;
246 }
247 /*endif*/
248
249 if (s->flat_mode)
250 {
251 /* Flat mode */
252
253 /* The bandpass filter is a single bi-quad stage */
254 bandpass_signal = amp[i];
255 bandpass_signal *= s->desc->broad_a[0];
256 bandpass_signal += s->broad_z[1]*s->desc->broad_b[1];
257 bandpass_signal += s->broad_z[2]*s->desc->broad_b[2];
258 x = bandpass_signal;
259 bandpass_signal += s->broad_z[1]*s->desc->broad_a[1];
260 bandpass_signal += s->broad_z[2]*s->desc->broad_a[2];
261 s->broad_z[2] = s->broad_z[1];
262 s->broad_z[1] = x >> 15;
263 bandpass_signal >>= s->desc->broad_postscale;
264
265 /* Leaky integrate the bandpassed data */
266 s->broad_zl = ((s->broad_zl*s->desc->broad_slugi) >> 15)
267 + ((abs(bandpass_signal)*s->desc->broad_slugp) >> 15);
268
269 /* For the broad band receiver we use a simple linear threshold! */
270 if (s->tone_present)
271 {
272 s->tone_present = (s->broad_zl > s->desc->broad_threshold);
273 if (!s->tone_present)
274 {
275 if (s->sig_update)
276 s->sig_update(s->user_data, SIG_TONE_1_CHANGE | (s->signaling_state_duration << 16));
277 /*endif*/
278 s->signaling_state_duration = 0;
279 }
280 /*endif*/
281 }
282 else
283 {
284 s->tone_present = (s->broad_zl > s->desc->broad_threshold);
285 if (s->tone_present)
286 {
287 if (s->sig_update)
288 s->sig_update(s->user_data, SIG_TONE_1_CHANGE | SIG_TONE_1_PRESENT | (s->signaling_state_duration << 16));
289 /*endif*/
290 s->signaling_state_duration = 0;
291 }
292 /*endif*/
293 }
294 /*endif*/
295 /* Notch insertion logic */
296
297 /* tone_present and tone_on are equivalent in flat mode */
298 if (s->tone_present)
299 {
300 s->notch_enabled = s->desc->notch_allowed;
301 s->notch_insertion_timeout = s->desc->notch_lag_time;
302 }
303 else
304 {
305 if (s->notch_insertion_timeout > 0)
306 s->notch_insertion_timeout--;
307 else
308 s->notch_enabled = FALSE;
309 /*endif*/
310 }
311 /*endif*/
312 }
313 else
314 {
315 /* Sharp mode */
316
317 /* Modulus and leaky integrate the data */
318 s->broad_zl = ((s->broad_zl*s->desc->unfiltered_slugi) >> 15)
319 + ((abs(amp[i])*s->desc->unfiltered_slugp) >> 15);
320
321 /* Mow the grass to weed out the noise! */
322 s->mown_bandpass = s->broad_zl & s->desc->unfiltered_threshold;
323
324 /* Persistence checking and notch insertion logic */
325 if (!s->tone_present)
326 {
327 if (s->mown_notch < s->mown_bandpass)
328 {
329 /* Tone is detected this sample */
330 if (s->tone_persistence_timeout <= 0)
331 {
332 s->tone_present = TRUE;
333 s->notch_enabled = s->desc->notch_allowed;
334 s->tone_persistence_timeout = s->desc->tone_off_check_time;
335 s->notch_insertion_timeout = s->desc->notch_lag_time;
336 if (s->sig_update)
337 s->sig_update(s->user_data, SIG_TONE_1_CHANGE | SIG_TONE_1_PRESENT | (s->signaling_state_duration << 16));
338 /*endif*/
339 s->signaling_state_duration = 0;
340 }
341 else
342 {
343 s->tone_persistence_timeout--;
344 if (s->notch_insertion_timeout > 0)
345 s->notch_insertion_timeout--;
346 else
347 s->notch_enabled = FALSE;
348 /*endif*/
349 }
350 /*endif*/
351 }
352 else
353 {
354 s->tone_persistence_timeout = s->desc->tone_on_check_time;
355 if (s->notch_insertion_timeout > 0)
356 s->notch_insertion_timeout--;
357 else
358 s->notch_enabled = FALSE;
359 /*endif*/
360 }
361 /*endif*/
362 }
363 else
364 {
365 if (s->mown_notch > s->mown_bandpass)
366 {
367 /* Tone is not detected this sample */
368 if (s->tone_persistence_timeout <= 0)
369 {
370 s->tone_present = FALSE;
371 s->tone_persistence_timeout = s->desc->tone_on_check_time;
372 if (s->sig_update)
373 s->sig_update(s->user_data, SIG_TONE_1_CHANGE | (s->signaling_state_duration << 16));
374 /*endif*/
375 s->signaling_state_duration = 0;
376 }
377 else
378 {
379 s->tone_persistence_timeout--;
380 }
381 /*endif*/
382 }
383 else
384 {
385 s->tone_persistence_timeout = s->desc->tone_off_check_time;
386 }
387 /*endif*/
388 }
389 /*endif*/
390 }
391 /*endif*/
392
393 if ((s->current_tx_tone & SIG_TONE_RX_PASSTHROUGH))
394 {
395 //if (s->notch_enabled)
396 amp[i] = (int16_t) notched_signal;
397 /*endif*/
398 }
399 else
400 {
401 amp[i] = 0;
402 }
403 /*endif*/
404 }
405 /*endfor*/
406 return len;
407 }
408 /*- End of function --------------------------------------------------------*/
409
410 int sig_tone_tx(sig_tone_state_t *s, int16_t amp[], int len)
411 {
412 int i;
413 int16_t tone;
414 int update;
415 int high_low;
416
417 if (s->current_tx_tone & SIG_TONE_1_PRESENT)
418 {
419 for (i = 0; i < len; i++)
420 {
421 if (s->high_low_timer > 0 && --s->high_low_timer > 0)
422 high_low = 1;
423 else
424 high_low = 0;
425 /*endif*/
426 tone = dds_mod(&(s->phase_acc[0]), s->phase_rate[0], s->tone_scaling[high_low], 0);
427 if (s->current_tx_tone & SIG_TONE_TX_PASSTHROUGH)
428 amp[i] = saturate(amp[i] + tone);
429 else
430 amp[i] = tone;
431 /*endif*/
432 if (--s->current_tx_timeout <= 0)
433 {
434 if (s->sig_update)
435 {
436 update = s->sig_update(s->user_data, SIG_TONE_UPDATE_REQUEST);
437 if ((update & 0x03) == 0x03 && !(s->current_tx_tone & SIG_TONE_1_PRESENT))
438 s->high_low_timer = s->desc->high_low_timeout;
439 /*endif*/
440 s->current_tx_tone = update & 0xFFFF;
441 s->current_tx_timeout = (update >> 16) & 0xFFFF;
442 }
443 /*endif*/
444 }
445 /*endif*/
446 }
447 /*endfor*/
448 }
449 else
450 {
451 for (i = 0; i < len; )
452 {
453 if (s->current_tx_timeout < len - i)
454 {
455 if (!(s->current_tx_tone & SIG_TONE_TX_PASSTHROUGH))
456 {
457 /* Zap any audio in the buffer */
458 memset(amp + i, 0, sizeof(int16_t)*s->current_tx_timeout);
459 }
460 /*endif*/
461 i += s->current_tx_timeout;
462 if (s->sig_update)
463 {
464 update = s->sig_update(s->user_data, SIG_TONE_UPDATE_REQUEST);
465 if ((update & 0x03) == 0x03)
466 s->high_low_timer = s->desc->high_low_timeout;
467 /*endif*/
468 s->current_tx_tone = update & 0xFFFF;
469 s->current_tx_timeout = (update >> 16) & 0xFFFF;
470 }
471 /*endif*/
472 }
473 else
474 {
475 s->current_tx_timeout -= (len - i);
476 if (!(s->current_tx_tone & SIG_TONE_TX_PASSTHROUGH))
477 {
478 /* Zap any audio in the buffer */
479 memset(amp + i, 0, sizeof(int16_t)*(len - i));
480 i = len;
481 }
482 /*endif*/
483 }
484 /*endif*/
485 }
486 /*endfor*/
487 }
488 /*endif*/
489 return len;
490 }
491 /*- End of function --------------------------------------------------------*/
492
493 sig_tone_state_t *sig_tone_init(sig_tone_state_t *s, int tone_type, sig_tone_func_t sig_update, void *user_data)
494 {
495 if (tone_type <= 0 || tone_type > 3)
496 return NULL;
497 /*endif*/
498
499 memset(s, 0, sizeof(*s));
500
501 s->sig_update = sig_update;
502 s->user_data = user_data;
503
504 s->desc = &sig_tones[tone_type - 1];
505
506 /* Set up the transmit side */
507 s->phase_rate[0] = dds_phase_rate((float) s->desc->tone_freq[0]);
508 if (s->desc->tone_freq[1])
509 s->phase_rate[1] = dds_phase_rate((float) s->desc->tone_freq[1]);
510 else
511 s->phase_rate[1] = 0;
512 /*endif*/
513 s->tone_scaling[0] = dds_scaling_dbm0((float) s->desc->tone_amp[0]);
514 s->tone_scaling[1] = dds_scaling_dbm0((float) s->desc->tone_amp[1]);
515
516 /* Set up the receive side */
517 s->flat_mode_timeout = 0;
518 s->notch_insertion_timeout = 0;
519 s->tone_persistence_timeout = 0;
520 s->signaling_state_duration = 0;
521 return s;
522 }
523 /*- End of function --------------------------------------------------------*/
524 /*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.