comparison spandsp-0.0.6pre17/tests/modem_connect_tones_tests.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 * modem_connect_tones_tests.c
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2006 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2, as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * $Id: modem_connect_tones_tests.c,v 1.32 2009/11/02 15:04:15 steveu Exp $
26 */
27
28 /*! \page modem_connect_tones_tests_page Modem connect tones tests
29 \section modem_connect_tones_rx_tests_page_sec_1 What does it do?
30 These tests...
31 */
32
33 /* Enable the following definition to enable direct probing into the FAX structures */
34 //#define WITH_SPANDSP_INTERNALS
35
36 #if defined(HAVE_CONFIG_H)
37 #include "config.h"
38 #endif
39
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <fcntl.h>
43 #include <unistd.h>
44 #include <string.h>
45 #include <sndfile.h>
46
47 //#if defined(WITH_SPANDSP_INTERNALS)
48 #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
49 //#endif
50
51 #include "spandsp.h"
52 #include "spandsp-sim.h"
53
54 #define SAMPLES_PER_CHUNK 160
55
56 #define OUTPUT_FILE_NAME "modem_connect_tones.wav"
57
58 #define MITEL_DIR "../test-data/mitel/"
59 #define BELLCORE_DIR "../test-data/bellcore/"
60
61 #define FALSE 0
62 #define TRUE (!FALSE)
63
64 #define LEVEL_MAX -5
65 #define LEVEL_MIN -48
66 #define LEVEL_MIN_ACCEPT -43
67 #define LEVEL_MIN_REJECT -44
68
69 /* The 1100Hz tone is supposed to be within 38Hz, according to T.30. Allow another 8Hz for FDM, even though
70 you rarely see that used today. */
71 #define CED_FREQ_TOLERANCE (38 + 8)
72 #define CED_FREQ_BLACKOUT (80)
73 /* The 2100Hz tone is supposed to be within 15Hz, according to T.30. Allow another 8Hz for FDM, even though
74 you rarely see that used today. */
75 #define CNG_FREQ_TOLERANCE (15 + 8)
76 #define CNG_FREQ_BLACKOUT (80)
77 #define AM_FREQ_TOLERANCE (1)
78
79 const char *bellcore_files[] =
80 {
81 MITEL_DIR "mitel-cm7291-talkoff.wav",
82 BELLCORE_DIR "tr-tsy-00763-1.wav",
83 BELLCORE_DIR "tr-tsy-00763-2.wav",
84 BELLCORE_DIR "tr-tsy-00763-3.wav",
85 BELLCORE_DIR "tr-tsy-00763-4.wav",
86 BELLCORE_DIR "tr-tsy-00763-5.wav",
87 BELLCORE_DIR "tr-tsy-00763-6.wav",
88 ""
89 };
90
91 enum
92 {
93 PERFORM_TEST_1A = (1 << 1),
94 PERFORM_TEST_1B = (1 << 2),
95 PERFORM_TEST_1C = (1 << 3),
96 PERFORM_TEST_1D = (1 << 4),
97 PERFORM_TEST_1E = (1 << 5),
98 PERFORM_TEST_2A = (1 << 6),
99 PERFORM_TEST_2B = (1 << 7),
100 PERFORM_TEST_2C = (1 << 8),
101 PERFORM_TEST_2D = (1 << 9),
102 PERFORM_TEST_2E = (1 << 10),
103 PERFORM_TEST_3A = (1 << 11),
104 PERFORM_TEST_3B = (1 << 12),
105 PERFORM_TEST_3C = (1 << 13),
106 PERFORM_TEST_3D = (1 << 14),
107 PERFORM_TEST_3E = (1 << 15),
108 PERFORM_TEST_4 = (1 << 16),
109 PERFORM_TEST_5A = (1 << 17),
110 PERFORM_TEST_5B = (1 << 18),
111 PERFORM_TEST_6A = (1 << 19),
112 PERFORM_TEST_6B = (1 << 20),
113 PERFORM_TEST_7A = (1 << 21),
114 PERFORM_TEST_7B = (1 << 22),
115 PERFORM_TEST_8 = (1 << 23)
116 };
117
118 int preamble_count = 0;
119 int preamble_on_at = -1;
120 int preamble_off_at = -1;
121 int hits = 0;
122 int when = 0;
123
124 static int preamble_get_bit(void *user_data)
125 {
126 static int bit_no = 0;
127 int bit;
128
129 /* Generate a section of HDLC flag octet preamble. Then generate some random
130 bits, which should not look like preamble. */
131 if (++preamble_count < 255)
132 {
133 bit = (bit_no < 2) ? 0 : 1;
134 if (++bit_no >= 8)
135 bit_no = 0;
136 #if 0
137 /* Inject some bad bits */
138 if (rand()%15 == 0)
139 return bit ^ 1;
140 #endif
141 }
142 else
143 {
144 bit = rand() & 1;
145 }
146 return bit;
147 }
148 /*- End of function --------------------------------------------------------*/
149
150 static void cng_detected(void *user_data, int tone, int level, int delay)
151 {
152 printf("%s (%d) declared at %fs, delay %d (%ddBm0)\n", modem_connect_tone_to_str(tone), tone, (float) when/SAMPLE_RATE, delay, level);
153 if (tone == MODEM_CONNECT_TONES_FAX_CNG)
154 hits++;
155 }
156 /*- End of function --------------------------------------------------------*/
157
158 static void preamble_detected(void *user_data, int tone, int level, int delay)
159 {
160 printf("%s (%d) declared at bit %d (%ddBm0)\n", modem_connect_tone_to_str(tone), tone, preamble_count, level);
161 if (tone == MODEM_CONNECT_TONES_FAX_PREAMBLE)
162 preamble_on_at = preamble_count;
163 else
164 preamble_off_at = preamble_count;
165 /*endif*/
166 }
167 /*- End of function --------------------------------------------------------*/
168
169 static void ced_detected(void *user_data, int tone, int level, int delay)
170 {
171 printf("%s (%d) declared at %fs, delay %d (%ddBm0)\n", modem_connect_tone_to_str(tone), tone, (float) when/SAMPLE_RATE, delay, level);
172 if (tone == MODEM_CONNECT_TONES_FAX_PREAMBLE
173 ||
174 tone == MODEM_CONNECT_TONES_ANS)
175 {
176 hits++;
177 }
178 }
179 /*- End of function --------------------------------------------------------*/
180
181 static void ans_pr_detected(void *user_data, int tone, int level, int delay)
182 {
183 printf("%s (%d) declared at %fs, delay %d (%ddBm0)\n", modem_connect_tone_to_str(tone), tone, (float) when/SAMPLE_RATE, delay, level);
184 if (tone == MODEM_CONNECT_TONES_ANS_PR)
185 hits++;
186 }
187 /*- End of function --------------------------------------------------------*/
188
189 int main(int argc, char *argv[])
190 {
191 int i;
192 int j;
193 int pitch;
194 int depth;
195 int level;
196 int interval;
197 int cycle;
198 int16_t amp[8000];
199 modem_connect_tones_rx_state_t cng_rx;
200 modem_connect_tones_rx_state_t ced_rx;
201 modem_connect_tones_rx_state_t ans_pr_rx;
202 modem_connect_tones_tx_state_t modem_tone_tx;
203 awgn_state_t chan_noise_source;
204 SNDFILE *inhandle;
205 SNDFILE *outhandle;
206 int outframes;
207 int frames;
208 int samples;
209 int hit;
210 int false_hit;
211 int false_miss;
212 power_meter_t power_state;
213 int power;
214 int max_power;
215 int level2;
216 int max_level2;
217 int tone_type;
218 int test_list;
219 int opt;
220 char *decode_test_file;
221 fsk_tx_state_t preamble_tx;
222
223 test_list = 0;
224 decode_test_file = NULL;
225 while ((opt = getopt(argc, argv, "d:")) != -1)
226 {
227 switch (opt)
228 {
229 case 'd':
230 decode_test_file = optarg;
231 break;
232 default:
233 //usage();
234 exit(2);
235 break;
236 }
237 }
238 argc -= optind;
239 argv += optind;
240 for (i = 0; i < argc; i++)
241 {
242 if (strcasecmp(argv[i], "1a") == 0)
243 test_list |= PERFORM_TEST_1A;
244 else if (strcasecmp(argv[i], "1b") == 0)
245 test_list |= PERFORM_TEST_1B;
246 else if (strcasecmp(argv[i], "1c") == 0)
247 test_list |= PERFORM_TEST_1C;
248 else if (strcasecmp(argv[i], "1d") == 0)
249 test_list |= PERFORM_TEST_1D;
250 else if (strcasecmp(argv[i], "1e") == 0)
251 test_list |= PERFORM_TEST_1E;
252 else if (strcasecmp(argv[i], "2a") == 0)
253 test_list |= PERFORM_TEST_2A;
254 else if (strcasecmp(argv[i], "2b") == 0)
255 test_list |= PERFORM_TEST_2B;
256 else if (strcasecmp(argv[i], "2c") == 0)
257 test_list |= PERFORM_TEST_2C;
258 else if (strcasecmp(argv[i], "2d") == 0)
259 test_list |= PERFORM_TEST_2D;
260 else if (strcasecmp(argv[i], "2e") == 0)
261 test_list |= PERFORM_TEST_2E;
262 else if (strcasecmp(argv[i], "3a") == 0)
263 test_list |= PERFORM_TEST_3A;
264 else if (strcasecmp(argv[i], "3b") == 0)
265 test_list |= PERFORM_TEST_3B;
266 else if (strcasecmp(argv[i], "3c") == 0)
267 test_list |= PERFORM_TEST_3C;
268 else if (strcasecmp(argv[i], "3d") == 0)
269 test_list |= PERFORM_TEST_3D;
270 else if (strcasecmp(argv[i], "3e") == 0)
271 test_list |= PERFORM_TEST_3E;
272 else if (strcasecmp(argv[i], "4") == 0)
273 test_list |= PERFORM_TEST_4;
274 else if (strcasecmp(argv[i], "5a") == 0)
275 test_list |= PERFORM_TEST_5A;
276 else if (strcasecmp(argv[i], "5b") == 0)
277 test_list |= PERFORM_TEST_5B;
278 else if (strcasecmp(argv[i], "6a") == 0)
279 test_list |= PERFORM_TEST_6A;
280 else if (strcasecmp(argv[i], "6b") == 0)
281 test_list |= PERFORM_TEST_6B;
282 else if (strcasecmp(argv[i], "7a") == 0)
283 test_list |= PERFORM_TEST_7A;
284 else if (strcasecmp(argv[i], "7b") == 0)
285 test_list |= PERFORM_TEST_7B;
286 else if (strcasecmp(argv[i], "8") == 0)
287 test_list |= PERFORM_TEST_8;
288 else
289 {
290 fprintf(stderr, "Unknown test '%s' specified\n", argv[i]);
291 exit(2);
292 }
293 }
294 if (decode_test_file == NULL && test_list == 0)
295 test_list = 0xFFFFFFFF;
296
297 if ((outhandle = sf_open_telephony_write(OUTPUT_FILE_NAME, 1)) == NULL)
298 {
299 fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_FILE_NAME);
300 exit(2);
301 }
302
303 if ((test_list & PERFORM_TEST_1A))
304 {
305 printf("Test 1a: CNG generation to a file\n");
306 modem_connect_tones_tx_init(&modem_tone_tx, MODEM_CONNECT_TONES_FAX_CNG);
307 for (i = 0; i < 20*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
308 {
309 samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
310 outframes = sf_writef_short(outhandle, amp, samples);
311 if (outframes != samples)
312 {
313 fprintf(stderr, " Error writing audio file\n");
314 exit(2);
315 }
316 /*endif*/
317 }
318 /*endfor*/
319 }
320 /*endif*/
321
322 if ((test_list & PERFORM_TEST_1B))
323 {
324 printf("Test 1b: CED/ANS generation to a file\n");
325 modem_connect_tones_tx_init(&modem_tone_tx, MODEM_CONNECT_TONES_FAX_CED);
326 for (i = 0; i < 20*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
327 {
328 samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
329 outframes = sf_writef_short(outhandle, amp, samples);
330 if (outframes != samples)
331 {
332 fprintf(stderr, " Error writing audio file\n");
333 exit(2);
334 }
335 /*endif*/
336 }
337 /*endfor*/
338 }
339 /*endif*/
340
341 if ((test_list & PERFORM_TEST_1C))
342 {
343 printf("Test 1c: ANSam (Modulated ANS) generation to a file\n");
344 /* Some with modulation */
345 modem_connect_tones_tx_init(&modem_tone_tx, MODEM_CONNECT_TONES_ANSAM);
346 for (i = 0; i < 20*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
347 {
348 samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
349 outframes = sf_writef_short(outhandle, amp, samples);
350 if (outframes != samples)
351 {
352 fprintf(stderr, " Error writing audio file\n");
353 exit(2);
354 }
355 /*endif*/
356 }
357 /*endfor*/
358 }
359 /*endif*/
360
361 if ((test_list & PERFORM_TEST_1D))
362 {
363 printf("Test 1d: ANS/ (EC-disable) generation to a file\n");
364 /* Some without modulation, but with phase reversals */
365 modem_connect_tones_tx_init(&modem_tone_tx, MODEM_CONNECT_TONES_ANS_PR);
366 for (i = 0; i < 20*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
367 {
368 samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
369 outframes = sf_writef_short(outhandle, amp, samples);
370 if (outframes != samples)
371 {
372 fprintf(stderr, " Error writing audio file\n");
373 exit(2);
374 }
375 /*endif*/
376 }
377 /*endfor*/
378 }
379 /*endif*/
380
381 if ((test_list & PERFORM_TEST_1E))
382 {
383 printf("Test 1e: ANSam/ (Modulated EC-disable) generation to a file\n");
384 /* Some with modulation and phase reversals */
385 modem_connect_tones_tx_init(&modem_tone_tx, MODEM_CONNECT_TONES_ANSAM_PR);
386 for (i = 0; i < 20*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
387 {
388 samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
389 outframes = sf_writef_short(outhandle, amp, samples);
390 if (outframes != samples)
391 {
392 fprintf(stderr, " Error writing audio file\n");
393 exit(2);
394 }
395 /*endif*/
396 }
397 /*endfor*/
398 }
399 /*endif*/
400
401 if (sf_close(outhandle) != 0)
402 {
403 printf(" Cannot close audio file '%s'\n", OUTPUT_FILE_NAME);
404 exit(2);
405 }
406 /*endif*/
407
408 if ((test_list & PERFORM_TEST_2A))
409 {
410 printf("Test 2a: CNG detection with frequency\n");
411 tone_type = MODEM_CONNECT_TONES_FAX_CNG;
412 awgn_init_dbm0(&chan_noise_source, 7162534, -50.0f);
413 false_hit = FALSE;
414 false_miss = FALSE;
415 for (pitch = 600; pitch <= 1600; pitch++)
416 {
417 /* Use the transmitter to test the receiver */
418 modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
419 /* Fudge things for the test */
420 modem_tone_tx.tone_phase_rate = dds_phase_rate(pitch);
421 modem_connect_tones_rx_init(&cng_rx, tone_type, NULL, NULL);
422 power_meter_init(&power_state, 5);
423 power = 0;
424 max_power = 0;
425 level2 = 0;
426 max_level2 = 0;
427 for (i = 0; i < 10*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
428 {
429 samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
430 for (j = 0; j < samples; j++)
431 {
432 amp[j] += awgn(&chan_noise_source);
433 power = power_meter_update(&power_state, amp[j]);
434 if (power > max_power)
435 max_power = power;
436 /*endif*/
437 level2 += ((abs(amp[j]) - level2) >> 5);
438 if (level2 > max_level2)
439 max_level2 = level2;
440 }
441 /*endfor*/
442 modem_connect_tones_rx(&cng_rx, amp, samples);
443 }
444 /*endfor*/
445 hit = modem_connect_tones_rx_get(&cng_rx);
446 if (pitch < (1100 - CED_FREQ_BLACKOUT) || pitch > (1100 + CED_FREQ_BLACKOUT))
447 {
448 if (hit != MODEM_CONNECT_TONES_NONE)
449 false_hit = TRUE;
450 /*endif*/
451 }
452 else if (pitch > (1100 - CED_FREQ_TOLERANCE) && pitch < (1100 + CED_FREQ_TOLERANCE))
453 {
454 if (hit != tone_type)
455 false_miss = TRUE;
456 /*endif*/
457 }
458 /*endif*/
459 if (hit != MODEM_CONNECT_TONES_NONE)
460 printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %d\n", pitch, cng_rx.channel_level, cng_rx.notch_level, hit);
461 /*endif*/
462 }
463 /*endfor*/
464 if (false_hit || false_miss)
465 {
466 printf("Test failed.\n");
467 exit(2);
468 }
469 /*endif*/
470 printf("Test passed.\n");
471 }
472 /*endif*/
473
474 if ((test_list & PERFORM_TEST_2B))
475 {
476 printf("Test 2b: CED/ANS detection with frequency\n");
477 awgn_init_dbm0(&chan_noise_source, 7162534, -50.0f);
478 false_hit = FALSE;
479 false_miss = FALSE;
480 for (pitch = 1600; pitch < 2600; pitch++)
481 {
482 /* Use the transmitter to test the receiver */
483 modem_connect_tones_tx_init(&modem_tone_tx, MODEM_CONNECT_TONES_ANS);
484 /* Fudge things for the test */
485 modem_tone_tx.tone_phase_rate = dds_phase_rate(pitch);
486 modem_connect_tones_rx_init(&ced_rx, MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE, NULL, NULL);
487 for (i = 0; i < 10*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
488 {
489 samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
490 for (j = 0; j < samples; j++)
491 amp[j] += awgn(&chan_noise_source);
492 /*endfor*/
493 modem_connect_tones_rx(&ced_rx, amp, samples);
494 }
495 /*endfor*/
496 hit = modem_connect_tones_rx_get(&ced_rx);
497 if (pitch < (2100 - CNG_FREQ_BLACKOUT) || pitch > (2100 + CNG_FREQ_BLACKOUT))
498 {
499 if (hit != MODEM_CONNECT_TONES_NONE)
500 false_hit = TRUE;
501 /*endif*/
502 }
503 else if (pitch > (2100 - CNG_FREQ_TOLERANCE) && pitch < (2100 + CNG_FREQ_TOLERANCE))
504 {
505 if (hit != MODEM_CONNECT_TONES_FAX_CED)
506 false_miss = TRUE;
507 /*endif*/
508 }
509 /*endif*/
510 if (hit != MODEM_CONNECT_TONES_NONE)
511 printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %d\n", pitch, ced_rx.channel_level, ced_rx.notch_level, hit);
512 /*endif*/
513 }
514 if (false_hit || false_miss)
515 {
516 printf("Test failed.\n");
517 exit(2);
518 }
519 /*endif*/
520 printf("Test passed.\n");
521 }
522 /*endif*/
523
524 if ((test_list & PERFORM_TEST_2C))
525 {
526 printf("Test 2c: ANSam detection with frequency\n");
527 tone_type = MODEM_CONNECT_TONES_ANSAM;
528 awgn_init_dbm0(&chan_noise_source, 7162534, -50.0f);
529 false_hit = FALSE;
530 false_miss = FALSE;
531 for (pitch = 2000; pitch <= 2200; pitch++)
532 {
533 /* Use the transmitter to test the receiver */
534 modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
535 /* Fudge things for the test */
536 modem_tone_tx.tone_phase_rate = dds_phase_rate(pitch);
537 modem_connect_tones_rx_init(&ans_pr_rx, tone_type, NULL, NULL);
538 for (i = 0; i < 10*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
539 {
540 samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
541 for (j = 0; j < samples; j++)
542 amp[j] += awgn(&chan_noise_source);
543 /*endfor*/
544 modem_connect_tones_rx(&ans_pr_rx, amp, samples);
545 }
546 /*endfor*/
547 hit = modem_connect_tones_rx_get(&ans_pr_rx);
548 if (pitch < (2100 - CNG_FREQ_BLACKOUT) || pitch > (2100 + CNG_FREQ_BLACKOUT))
549 {
550 if (hit != MODEM_CONNECT_TONES_NONE)
551 false_hit = TRUE;
552 /*endif*/
553 }
554 else if (pitch > (2100 - CNG_FREQ_TOLERANCE) && pitch < (2100 + CNG_FREQ_TOLERANCE))
555 {
556 if (hit != tone_type)
557 false_miss = TRUE;
558 /*endif*/
559 }
560 /*endif*/
561 if (hit != MODEM_CONNECT_TONES_NONE)
562 printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %d\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
563 /*endif*/
564 }
565 /*endfor*/
566 if (false_hit || false_miss)
567 {
568 printf("Test failed.\n");
569 exit(2);
570 }
571 /*endif*/
572 printf("Test passed.\n");
573 }
574 /*endif*/
575
576 if ((test_list & PERFORM_TEST_2D))
577 {
578 printf("Test 2d: ANS/ (EC-disable) detection with frequency\n");
579 tone_type = MODEM_CONNECT_TONES_ANS_PR;
580 awgn_init_dbm0(&chan_noise_source, 7162534, -50.0f);
581 false_hit = FALSE;
582 false_miss = FALSE;
583 for (pitch = 2000; pitch <= 2200; pitch++)
584 {
585 /* Use the transmitter to test the receiver */
586 modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
587 /* Fudge things for the test */
588 modem_tone_tx.tone_phase_rate = dds_phase_rate(pitch);
589 modem_connect_tones_rx_init(&ans_pr_rx, tone_type, NULL, NULL);
590 for (i = 0; i < 10*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
591 {
592 samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
593 for (j = 0; j < samples; j++)
594 amp[j] += awgn(&chan_noise_source);
595 /*endfor*/
596 modem_connect_tones_rx(&ans_pr_rx, amp, samples);
597 }
598 /*endfor*/
599 hit = modem_connect_tones_rx_get(&ans_pr_rx);
600 if (pitch < (2100 - CNG_FREQ_BLACKOUT) || pitch > (2100 + CNG_FREQ_BLACKOUT))
601 {
602 if (hit != MODEM_CONNECT_TONES_NONE)
603 false_hit = TRUE;
604 /*endif*/
605 }
606 else if (pitch > (2100 - CNG_FREQ_TOLERANCE) && pitch < (2100 + CNG_FREQ_TOLERANCE))
607 {
608 if (hit != tone_type)
609 false_miss = TRUE;
610 /*endif*/
611 }
612 /*endif*/
613 if (hit != MODEM_CONNECT_TONES_NONE)
614 printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %d\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
615 /*endif*/
616 }
617 /*endfor*/
618 if (false_hit || false_miss)
619 {
620 printf("Test failed.\n");
621 exit(2);
622 }
623 /*endif*/
624 printf("Test passed.\n");
625 }
626 /*endif*/
627
628 if ((test_list & PERFORM_TEST_2E))
629 {
630 printf("Test 2e: ANSam/ (Modulated EC-disable) detection with frequency\n");
631 tone_type = MODEM_CONNECT_TONES_ANSAM_PR;
632 awgn_init_dbm0(&chan_noise_source, 7162534, -50.0f);
633 false_hit = FALSE;
634 false_miss = FALSE;
635 for (pitch = 2000; pitch <= 2200; pitch++)
636 {
637 /* Use the transmitter to test the receiver */
638 modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
639 /* Fudge things for the test */
640 modem_tone_tx.tone_phase_rate = dds_phase_rate(pitch);
641 modem_connect_tones_rx_init(&ans_pr_rx, tone_type, NULL, NULL);
642 for (i = 0; i < 10*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
643 {
644 samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
645 for (j = 0; j < samples; j++)
646 amp[j] += awgn(&chan_noise_source);
647 /*endfor*/
648 modem_connect_tones_rx(&ans_pr_rx, amp, samples);
649 }
650 /*endfor*/
651 hit = modem_connect_tones_rx_get(&ans_pr_rx);
652 if (pitch < (2100 - CNG_FREQ_BLACKOUT) || pitch > (2100 + CNG_FREQ_BLACKOUT))
653 {
654 if (hit != MODEM_CONNECT_TONES_NONE)
655 false_hit = TRUE;
656 /*endif*/
657 }
658 else if (pitch > (2100 - CNG_FREQ_TOLERANCE) && pitch < (2100 + CNG_FREQ_TOLERANCE))
659 {
660 if (hit != tone_type)
661 false_miss = TRUE;
662 /*endif*/
663 }
664 /*endif*/
665 if (hit != MODEM_CONNECT_TONES_NONE)
666 printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %d\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
667 /*endif*/
668 }
669 /*endfor*/
670 if (false_hit || false_miss)
671 {
672 printf("Test failed.\n");
673 exit(2);
674 }
675 /*endif*/
676 printf("Test passed.\n");
677 }
678 /*endif*/
679
680 if ((test_list & PERFORM_TEST_3A))
681 {
682 printf("Test 3a: CNG detection with level\n");
683 tone_type = MODEM_CONNECT_TONES_FAX_CNG;
684 awgn_init_dbm0(&chan_noise_source, 7162534, -60.0f);
685 false_hit = FALSE;
686 false_miss = FALSE;
687 for (pitch = 1100 - CED_FREQ_TOLERANCE; pitch <= 1100 + CED_FREQ_TOLERANCE; pitch += 2*CED_FREQ_TOLERANCE)
688 {
689 for (level = LEVEL_MAX; level >= LEVEL_MIN; level--)
690 {
691 /* Use the transmitter to test the receiver */
692 modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
693 /* Fudge things for the test */
694 modem_tone_tx.tone_phase_rate = dds_phase_rate(pitch);
695 modem_tone_tx.level = dds_scaling_dbm0(level);
696 modem_connect_tones_rx_init(&cng_rx, tone_type, NULL, NULL);
697 for (i = 0; i < 10*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
698 {
699 samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
700 for (j = 0; j < samples; j++)
701 amp[j] += awgn(&chan_noise_source);
702 /*endfor*/
703 modem_connect_tones_rx(&cng_rx, amp, samples);
704 }
705 /*endfor*/
706 hit = modem_connect_tones_rx_get(&cng_rx);
707 if (level < LEVEL_MIN_REJECT)
708 {
709 if (hit != MODEM_CONNECT_TONES_NONE)
710 false_hit = TRUE;
711 /*endif*/
712 }
713 else if (level > LEVEL_MIN_ACCEPT)
714 {
715 if (hit != tone_type)
716 false_miss = TRUE;
717 /*endif*/
718 }
719 /*endif*/
720 if (hit != MODEM_CONNECT_TONES_NONE)
721 printf("Detected at %5dHz %4ddB %12" PRId32 " %12" PRId32 " %d\n", pitch, level, cng_rx.channel_level, cng_rx.notch_level, hit);
722 /*endif*/
723 }
724 /*endfor*/
725 }
726 /*endfor*/
727 if (false_hit || false_miss)
728 {
729 printf("Test failed.\n");
730 exit(2);
731 }
732 /*endif*/
733 printf("Test passed.\n");
734 }
735 /*endif*/
736
737 if ((test_list & PERFORM_TEST_3B))
738 {
739 printf("Test 3b: CED/ANS detection with level\n");
740 tone_type = MODEM_CONNECT_TONES_ANS;
741 awgn_init_dbm0(&chan_noise_source, 7162534, -60.0f);
742 false_hit = FALSE;
743 false_miss = FALSE;
744 for (pitch = 2100 - CNG_FREQ_TOLERANCE; pitch <= 2100 + CNG_FREQ_TOLERANCE; pitch += 2*CNG_FREQ_TOLERANCE)
745 {
746 for (level = LEVEL_MAX; level >= LEVEL_MIN; level--)
747 {
748 /* Use the transmitter to test the receiver */
749 modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
750 /* Fudge things for the test */
751 modem_tone_tx.tone_phase_rate = dds_phase_rate(pitch);
752 modem_tone_tx.level = dds_scaling_dbm0(level);
753 modem_connect_tones_rx_init(&ced_rx, MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE, NULL, NULL);
754 for (i = 0; i < 10*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
755 {
756 samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
757 for (j = 0; j < samples; j++)
758 amp[j] += awgn(&chan_noise_source);
759 /*endfor*/
760 modem_connect_tones_rx(&ced_rx, amp, samples);
761 }
762 /*endfor*/
763 hit = modem_connect_tones_rx_get(&ced_rx);
764 if (level < LEVEL_MIN_REJECT)
765 {
766 if (hit != MODEM_CONNECT_TONES_NONE)
767 false_hit = TRUE;
768 /*endif*/
769 }
770 else if (level > LEVEL_MIN_ACCEPT)
771 {
772 if (hit != tone_type)
773 false_miss = TRUE;
774 /*endif*/
775 }
776 /*endif*/
777 if (hit != MODEM_CONNECT_TONES_NONE)
778 printf("Detected at %5dHz %4ddB %12" PRId32 " %12" PRId32 " %d\n", pitch, level, ced_rx.channel_level, ced_rx.notch_level, hit);
779 /*endif*/
780 }
781 /*endfor*/
782 }
783 /*endfor*/
784 if (false_hit || false_miss)
785 {
786 printf("Test failed.\n");
787 exit(2);
788 }
789 /*endif*/
790 printf("Test passed.\n");
791 }
792 /*endif*/
793
794 if ((test_list & PERFORM_TEST_3C))
795 {
796 printf("Test 3c: ANSam detection with level\n");
797 tone_type = MODEM_CONNECT_TONES_ANSAM;
798 awgn_init_dbm0(&chan_noise_source, 7162534, -60.0f);
799 false_hit = FALSE;
800 false_miss = FALSE;
801 for (pitch = 2100 - CNG_FREQ_TOLERANCE; pitch <= 2100 + CNG_FREQ_TOLERANCE; pitch += 2*CNG_FREQ_TOLERANCE)
802 {
803 //for (level = LEVEL_MAX; level >= LEVEL_MIN; level--)
804 for (level = -26; level >= -26; level--)
805 {
806 /* Use the transmitter to test the receiver */
807 modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
808 /* Fudge things for the test */
809 modem_tone_tx.tone_phase_rate = dds_phase_rate(pitch);
810 modem_tone_tx.level = dds_scaling_dbm0(level);
811 modem_tone_tx.mod_level = modem_tone_tx.level*20/100;
812 modem_connect_tones_rx_init(&ans_pr_rx, tone_type, NULL, NULL);
813 for (i = 0; i < 10*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
814 {
815 samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
816 for (j = 0; j < samples; j++)
817 amp[j] += awgn(&chan_noise_source);
818 /*endfor*/
819 modem_connect_tones_rx(&ans_pr_rx, amp, samples);
820 }
821 /*endfor*/
822 hit = modem_connect_tones_rx_get(&ans_pr_rx);
823 if (level < LEVEL_MIN_REJECT)
824 {
825 if (hit != MODEM_CONNECT_TONES_NONE)
826 false_hit = TRUE;
827 /*endif*/
828 }
829 else if (level > LEVEL_MIN_ACCEPT)
830 {
831 if (hit != tone_type)
832 false_miss = TRUE;
833 /*endif*/
834 }
835 /*endif*/
836 //if (hit != MODEM_CONNECT_TONES_NONE)
837 printf("Detected at %5dHz %4ddB %12" PRId32 " %12" PRId32 " %d\n", pitch, level, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
838 /*endif*/
839 }
840 /*endfor*/
841 }
842 /*endfor*/
843 if (false_hit || false_miss)
844 {
845 printf("Test failed.\n");
846 exit(2);
847 }
848 /*endif*/
849 printf("Test passed.\n");
850 }
851 /*endif*/
852
853 if ((test_list & PERFORM_TEST_3D))
854 {
855 printf("Test 3d: ANS/ (EC-disable) detection with level\n");
856 tone_type = MODEM_CONNECT_TONES_ANS_PR;
857 awgn_init_dbm0(&chan_noise_source, 7162534, -60.0f);
858 false_hit = FALSE;
859 false_miss = FALSE;
860 for (pitch = 2100 - CNG_FREQ_TOLERANCE; pitch <= 2100 + CNG_FREQ_TOLERANCE; pitch += 2*CNG_FREQ_TOLERANCE)
861 {
862 for (level = LEVEL_MAX; level >= LEVEL_MIN; level--)
863 {
864 /* Use the transmitter to test the receiver */
865 modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
866 /* Fudge things for the test */
867 modem_tone_tx.tone_phase_rate = dds_phase_rate(pitch);
868 modem_tone_tx.level = dds_scaling_dbm0(level);
869 modem_connect_tones_rx_init(&ans_pr_rx, tone_type, NULL, NULL);
870 for (i = 0; i < 10*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
871 {
872 samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
873 for (j = 0; j < samples; j++)
874 amp[j] += awgn(&chan_noise_source);
875 /*endfor*/
876 modem_connect_tones_rx(&ans_pr_rx, amp, samples);
877 }
878 /*endfor*/
879 hit = modem_connect_tones_rx_get(&ans_pr_rx);
880 if (level < LEVEL_MIN_REJECT)
881 {
882 if (hit != MODEM_CONNECT_TONES_NONE)
883 false_hit = TRUE;
884 /*endif*/
885 }
886 else if (level > LEVEL_MIN_ACCEPT)
887 {
888 if (hit != tone_type)
889 false_miss = TRUE;
890 /*endif*/
891 }
892 /*endif*/
893 if (hit != MODEM_CONNECT_TONES_NONE)
894 printf("Detected at %5dHz %4ddB %12" PRId32 " %12" PRId32 " %d\n", pitch, level, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
895 /*endif*/
896 }
897 /*endfor*/
898 }
899 /*endfor*/
900 if (false_hit || false_miss)
901 {
902 printf("Test failed.\n");
903 exit(2);
904 }
905 /*endif*/
906 printf("Test passed.\n");
907 }
908 /*endif*/
909
910 if ((test_list & PERFORM_TEST_3E))
911 {
912 printf("Test 3e: ANSam/ (Modulated EC-disable) detection with level\n");
913 tone_type = MODEM_CONNECT_TONES_ANSAM_PR;
914 awgn_init_dbm0(&chan_noise_source, 7162534, -60.0f);
915 false_hit = FALSE;
916 false_miss = FALSE;
917 for (pitch = 2100 - CNG_FREQ_TOLERANCE; pitch <= 2100 + CNG_FREQ_TOLERANCE; pitch += 2*CNG_FREQ_TOLERANCE)
918 {
919 for (level = LEVEL_MAX; level >= LEVEL_MIN; level--)
920 {
921 /* Use the transmitter to test the receiver */
922 modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
923 /* Fudge things for the test */
924 modem_tone_tx.tone_phase_rate = dds_phase_rate(pitch);
925 modem_tone_tx.level = dds_scaling_dbm0(level);
926 modem_tone_tx.mod_level = modem_tone_tx.level*20/100;
927 modem_connect_tones_rx_init(&ans_pr_rx, tone_type, NULL, NULL);
928 for (i = 0; i < 10*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
929 {
930 samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
931 for (j = 0; j < samples; j++)
932 amp[j] += awgn(&chan_noise_source);
933 /*endfor*/
934 modem_connect_tones_rx(&ans_pr_rx, amp, samples);
935 }
936 /*endfor*/
937 hit = modem_connect_tones_rx_get(&ans_pr_rx);
938 if (level < LEVEL_MIN_REJECT)
939 {
940 if (hit != MODEM_CONNECT_TONES_NONE)
941 false_hit = TRUE;
942 /*endif*/
943 }
944 else if (level > LEVEL_MIN_ACCEPT)
945 {
946 if (hit != tone_type)
947 false_miss = TRUE;
948 /*endif*/
949 }
950 /*endif*/
951 if (hit != MODEM_CONNECT_TONES_NONE)
952 printf("Detected at %5dHz %4ddB %12" PRId32 " %12" PRId32 " %d\n", pitch, level, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
953 /*endif*/
954 }
955 /*endfor*/
956 }
957 /*endfor*/
958 if (false_hit || false_miss)
959 {
960 printf("Test failed.\n");
961 exit(2);
962 }
963 /*endif*/
964 printf("Test passed.\n");
965 }
966 /*endif*/
967
968 if ((test_list & PERFORM_TEST_4))
969 {
970 printf("Test 4: CED detection, when stimulated with V.21 preamble\n");
971 false_hit = FALSE;
972 false_miss = FALSE;
973
974 /* Send 255 bits of preamble (0.85s, the minimum specified preamble for T.30), and then
975 some random bits. Check the preamble detector comes on, and goes off at reasonable times. */
976 fsk_tx_init(&preamble_tx, &preset_fsk_specs[FSK_V21CH2], preamble_get_bit, NULL);
977 modem_connect_tones_rx_init(&ced_rx, MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE, preamble_detected, NULL);
978 for (i = 0; i < 2*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
979 {
980 samples = fsk_tx(&preamble_tx, amp, SAMPLES_PER_CHUNK);
981 modem_connect_tones_rx(&ced_rx, amp, samples);
982 }
983 /*endfor*/
984 for (i = 0; i < SAMPLE_RATE/10; i += SAMPLES_PER_CHUNK)
985 {
986 memset(amp, 0, sizeof(int16_t)*SAMPLES_PER_CHUNK);
987 modem_connect_tones_rx(&ced_rx, amp, SAMPLES_PER_CHUNK);
988 }
989 /*endfor*/
990 if (preamble_on_at < 40 || preamble_on_at > 50
991 ||
992 preamble_off_at < 580 || preamble_off_at > 620)
993 {
994 printf("Test failed.\n");
995 exit(2);
996 }
997 /*endif*/
998 printf("Test passed.\n");
999 }
1000 /*endif*/
1001
1002 if ((test_list & PERFORM_TEST_5A))
1003 {
1004 printf("Test 5A: ANS and ANS/ detection with reversal interval\n");
1005 tone_type = MODEM_CONNECT_TONES_ANS_PR;
1006 awgn_init_dbm0(&chan_noise_source, 7162534, -60.0f);
1007 false_hit = FALSE;
1008 false_miss = FALSE;
1009 for (interval = 400; interval < 800; interval++)
1010 {
1011 printf("Reversal interval = %d\n", interval);
1012 /* Use the transmitter to test the receiver */
1013 modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
1014 modem_connect_tones_rx_init(&ans_pr_rx, tone_type, ans_pr_detected, NULL);
1015 hits = 0;
1016 for (i = 0; i < 10*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
1017 {
1018 when = i;
1019 samples = SAMPLES_PER_CHUNK;
1020 for (j = 0; j < samples; j++)
1021 {
1022 if (--modem_tone_tx.hop_timer <= 0)
1023 {
1024 modem_tone_tx.hop_timer = ms_to_samples(interval);
1025 modem_tone_tx.tone_phase += 0x80000000;
1026 }
1027 /*endif*/
1028 amp[j] = dds_mod(&modem_tone_tx.tone_phase, modem_tone_tx.tone_phase_rate, modem_tone_tx.level, 0);
1029 }
1030 for (j = 0; j < samples; j++)
1031 amp[j] += awgn(&chan_noise_source);
1032 /*endfor*/
1033 modem_connect_tones_rx(&ans_pr_rx, amp, samples);
1034 }
1035 /*endfor*/
1036 if (interval < (450 - 25) || interval > (450 + 25))
1037 {
1038 if (hits != 0)
1039 false_hit = TRUE;
1040 /*endif*/
1041 }
1042 else if (interval > (450 - 25) && interval < (450 + 25))
1043 {
1044 if (hits == 0)
1045 false_miss = TRUE;
1046 /*endif*/
1047 }
1048 /*endif*/
1049 if (hits)
1050 printf("Detected at %5dHz %4ddB %dms %12" PRId32 " %12" PRId32 " %d\n", 2100, -11, interval, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hits);
1051 /*endif*/
1052 }
1053 /*endfor*/
1054 if (false_hit || false_miss)
1055 {
1056 printf("Test failed.\n");
1057 exit(2);
1058 }
1059 /*endif*/
1060 printf("Test passed.\n");
1061 }
1062 /*endif*/
1063
1064 if ((test_list & PERFORM_TEST_5B))
1065 {
1066 printf("Test 5B: ANS and ANS/ detection with mixed reversal intervals\n");
1067 awgn_init_dbm0(&chan_noise_source, 7162534, -60.0f);
1068 tone_type = MODEM_CONNECT_TONES_ANS_PR;
1069 false_hit = FALSE;
1070 false_miss = FALSE;
1071 interval = 450;
1072 printf("Reversal interval = %d\n", interval);
1073 /* Use the transmitter to test the receiver */
1074 modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
1075 modem_connect_tones_rx_init(&ans_pr_rx, tone_type, ans_pr_detected, NULL);
1076 cycle = 0;
1077 hits = 0;
1078 for (i = 0; i < 60*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
1079 {
1080 when = i;
1081 samples = SAMPLES_PER_CHUNK;
1082 for (j = 0; j < samples; j++)
1083 {
1084 if (--modem_tone_tx.hop_timer <= 0)
1085 {
1086 if (++cycle == 10)
1087 interval = 1000;
1088 if (cycle == 20)
1089 interval = 450;
1090 modem_tone_tx.hop_timer = ms_to_samples(interval);
1091 modem_tone_tx.tone_phase += 0x80000000;
1092 }
1093 amp[j] = dds_mod(&modem_tone_tx.tone_phase, modem_tone_tx.tone_phase_rate, modem_tone_tx.level, 0);
1094 }
1095 /*endfor*/
1096 for (j = 0; j < samples; j++)
1097 amp[j] += awgn(&chan_noise_source);
1098 /*endfor*/
1099 modem_connect_tones_rx(&ans_pr_rx, amp, samples);
1100 /* TODO: Add test result detection logic. */
1101 }
1102 /*endfor*/
1103 if (false_hit || false_miss)
1104 {
1105 printf("Test failed.\n");
1106 exit(2);
1107 }
1108 /*endif*/
1109 printf("Test passed.\n");
1110 }
1111 /*endif*/
1112
1113 if ((test_list & PERFORM_TEST_6A))
1114 {
1115 printf("Test 6a: ANSam detection with AM pitch\n");
1116 tone_type = MODEM_CONNECT_TONES_ANSAM;
1117 awgn_init_dbm0(&chan_noise_source, 7162534, -50.0f);
1118 false_hit = FALSE;
1119 false_miss = FALSE;
1120 for (pitch = 5; pitch < 25; pitch++)
1121 {
1122 /* Use the transmitter to test the receiver */
1123 modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
1124 /* Fudge things for the test */
1125 modem_tone_tx.mod_phase_rate = dds_phase_rate(pitch);
1126 modem_connect_tones_rx_init(&ans_pr_rx, tone_type, NULL, NULL);
1127 for (i = 0; i < 10*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
1128 {
1129 samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
1130 for (j = 0; j < samples; j++)
1131 amp[j] += awgn(&chan_noise_source);
1132 /*endfor*/
1133 modem_connect_tones_rx(&ans_pr_rx, amp, samples);
1134 }
1135 /*endfor*/
1136 hit = modem_connect_tones_rx_get(&ans_pr_rx);
1137 if (pitch < (15 - 10) || pitch > (15 + 10))
1138 {
1139 if (hit == tone_type)
1140 false_hit = TRUE;
1141 /*endif*/
1142 }
1143 else if (pitch > (15 - AM_FREQ_TOLERANCE) && pitch < (15 + AM_FREQ_TOLERANCE))
1144 {
1145 if (hit != tone_type)
1146 false_miss = TRUE;
1147 /*endif*/
1148 }
1149 /*endif*/
1150 if (hit != MODEM_CONNECT_TONES_NONE)
1151 printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %d\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
1152 /*endif*/
1153 }
1154 /*endfor*/
1155 if (false_hit || false_miss)
1156 {
1157 printf("Test failed.\n");
1158 exit(2);
1159 }
1160 /*endif*/
1161 printf("Test passed.\n");
1162 }
1163 /*endif*/
1164
1165 if ((test_list & PERFORM_TEST_6B))
1166 {
1167 printf("Test 6b: ANSam/ (Modulated EC-disable) detection with AM pitch\n");
1168 tone_type = MODEM_CONNECT_TONES_ANSAM_PR;
1169 awgn_init_dbm0(&chan_noise_source, 7162534, -50.0f);
1170 false_hit = FALSE;
1171 false_miss = FALSE;
1172 for (pitch = 5; pitch < 25; pitch++)
1173 {
1174 /* Use the transmitter to test the receiver */
1175 modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
1176 /* Fudge things for the test */
1177 modem_tone_tx.mod_phase_rate = dds_phase_rate(pitch);
1178 modem_connect_tones_rx_init(&ans_pr_rx, tone_type, NULL, NULL);
1179 for (i = 0; i < 10*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
1180 {
1181 samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
1182 for (j = 0; j < samples; j++)
1183 amp[j] += awgn(&chan_noise_source);
1184 /*endfor*/
1185 modem_connect_tones_rx(&ans_pr_rx, amp, samples);
1186 }
1187 /*endfor*/
1188 hit = modem_connect_tones_rx_get(&ans_pr_rx);
1189 if (pitch < (15 - 10) || pitch > (15 + 10))
1190 {
1191 if (hit == tone_type)
1192 false_hit = TRUE;
1193 /*endif*/
1194 }
1195 else if (pitch > (15 - AM_FREQ_TOLERANCE) && pitch < (15 + AM_FREQ_TOLERANCE))
1196 {
1197 if (hit != tone_type)
1198 false_miss = TRUE;
1199 /*endif*/
1200 }
1201 /*endif*/
1202 if (hit != MODEM_CONNECT_TONES_NONE)
1203 printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %d\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
1204 /*endif*/
1205 }
1206 /*endfor*/
1207 if (false_hit || false_miss)
1208 {
1209 printf("Test failed.\n");
1210 exit(2);
1211 }
1212 /*endif*/
1213 printf("Test passed.\n");
1214 }
1215 /*endif*/
1216
1217 if ((test_list & PERFORM_TEST_7A))
1218 {
1219 printf("Test 7a: ANSam detection with AM depth\n");
1220 tone_type = MODEM_CONNECT_TONES_ANSAM;
1221 pitch = 2100;
1222 awgn_init_dbm0(&chan_noise_source, 7162534, -50.0f);
1223 false_hit = FALSE;
1224 false_miss = FALSE;
1225 for (depth = 0; depth < 40; depth++)
1226 {
1227 /* Use the transmitter to test the receiver */
1228 modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
1229 /* Fudge things for the test */
1230 modem_tone_tx.mod_level = modem_tone_tx.level*depth/100;
1231 modem_connect_tones_rx_init(&ans_pr_rx, tone_type, NULL, NULL);
1232 for (i = 0; i < 10*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
1233 {
1234 samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
1235 for (j = 0; j < samples; j++)
1236 amp[j] += awgn(&chan_noise_source);
1237 /*endfor*/
1238 modem_connect_tones_rx(&ans_pr_rx, amp, samples);
1239 }
1240 /*endfor*/
1241 hit = modem_connect_tones_rx_get(&ans_pr_rx);
1242 if (depth < 10)
1243 {
1244 if (hit == tone_type)
1245 false_hit = TRUE;
1246 /*endif*/
1247 }
1248 else if (depth > 15)
1249 {
1250 if (hit != tone_type)
1251 false_miss = TRUE;
1252 /*endif*/
1253 }
1254 /*endif*/
1255 if (hit != MODEM_CONNECT_TONES_NONE)
1256 printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %d\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
1257 /*endif*/
1258 }
1259 /*endfor*/
1260 if (false_hit || false_miss)
1261 {
1262 printf("Test failed.\n");
1263 exit(2);
1264 }
1265 /*endif*/
1266 printf("Test passed.\n");
1267 }
1268 /*endif*/
1269
1270 if ((test_list & PERFORM_TEST_7B))
1271 {
1272 printf("Test 7b: ANSam/ (Modulated EC-disable) detection with AM depth\n");
1273 tone_type = MODEM_CONNECT_TONES_ANSAM_PR;
1274 pitch = 2100;
1275 awgn_init_dbm0(&chan_noise_source, 7162534, -50.0f);
1276 false_hit = FALSE;
1277 false_miss = FALSE;
1278 for (depth = 0; depth < 40; depth++)
1279 {
1280 /* Use the transmitter to test the receiver */
1281 modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
1282 /* Fudge things for the test */
1283 modem_tone_tx.mod_level = modem_tone_tx.level*depth/100;
1284 modem_connect_tones_rx_init(&ans_pr_rx, tone_type, NULL, NULL);
1285 for (i = 0; i < 10*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
1286 {
1287 samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
1288 for (j = 0; j < samples; j++)
1289 amp[j] += awgn(&chan_noise_source);
1290 /*endfor*/
1291 modem_connect_tones_rx(&ans_pr_rx, amp, samples);
1292 }
1293 /*endfor*/
1294 hit = modem_connect_tones_rx_get(&ans_pr_rx);
1295 if (depth < 10)
1296 {
1297 if (hit == tone_type)
1298 false_hit = TRUE;
1299 /*endif*/
1300 }
1301 else if (depth > 15)
1302 {
1303 if (hit != tone_type)
1304 false_miss = TRUE;
1305 /*endif*/
1306 }
1307 /*endif*/
1308 if (hit != MODEM_CONNECT_TONES_NONE)
1309 printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %d\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
1310 /*endif*/
1311 }
1312 /*endfor*/
1313 if (false_hit || false_miss)
1314 {
1315 printf("Test failed.\n");
1316 exit(2);
1317 }
1318 /*endif*/
1319 printf("Test passed.\n");
1320 }
1321 /*endif*/
1322
1323 if ((test_list & PERFORM_TEST_8))
1324 {
1325 /* Talk-off test */
1326 /* Here we use the BellCore and Mitel talk off test tapes, intended for DTMF
1327 detector testing. Presumably they should also have value here, but I am not
1328 sure. If those voice snippets were chosen to be tough on DTMF detectors, they
1329 might go easy on detectors looking for different pitches. However, the
1330 Mitel DTMF test tape is known (the hard way) to exercise 2280Hz tone
1331 detectors quite well. */
1332 printf("Test 8: Talk-off test\n");
1333 modem_connect_tones_rx_init(&cng_rx, MODEM_CONNECT_TONES_FAX_CNG, NULL, NULL);
1334 modem_connect_tones_rx_init(&ced_rx, MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE, NULL, NULL);
1335 modem_connect_tones_rx_init(&ans_pr_rx, MODEM_CONNECT_TONES_ANS_PR, NULL, NULL);
1336 for (j = 0; bellcore_files[j][0]; j++)
1337 {
1338 if ((inhandle = sf_open_telephony_read(bellcore_files[j], 1)) == NULL)
1339 {
1340 fprintf(stderr, " Cannot open speech file '%s'\n", bellcore_files[j]);
1341 exit (2);
1342 }
1343 /*endif*/
1344
1345 when = 0;
1346 hits = 0;
1347 while ((frames = sf_readf_short(inhandle, amp, 8000)))
1348 {
1349 when++;
1350 modem_connect_tones_rx(&cng_rx, amp, frames);
1351 modem_connect_tones_rx(&ced_rx, amp, frames);
1352 modem_connect_tones_rx(&ans_pr_rx, amp, frames);
1353 if (modem_connect_tones_rx_get(&cng_rx) != MODEM_CONNECT_TONES_NONE)
1354 {
1355 /* This is not a true measure of hits, as there might be more
1356 than one in a block of data. However, since the only good
1357 result is no hits, this approximation is OK. */
1358 printf("Hit CNG at %ds\n", when);
1359 hits++;
1360 modem_connect_tones_rx_init(&cng_rx, MODEM_CONNECT_TONES_FAX_CNG, NULL, NULL);
1361 }
1362 /*endif*/
1363 if (modem_connect_tones_rx_get(&ced_rx) != MODEM_CONNECT_TONES_NONE)
1364 {
1365 printf("Hit CED at %ds\n", when);
1366 hits++;
1367 modem_connect_tones_rx_init(&ced_rx, MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE, NULL, NULL);
1368 }
1369 /*endif*/
1370 if (modem_connect_tones_rx_get(&ans_pr_rx) != MODEM_CONNECT_TONES_NONE)
1371 {
1372 printf("Hit EC disable at %ds\n", when);
1373 hits++;
1374 modem_connect_tones_rx_init(&ans_pr_rx, MODEM_CONNECT_TONES_ANS_PR, NULL, NULL);
1375 }
1376 /*endif*/
1377 }
1378 /*endwhile*/
1379 if (sf_close(inhandle) != 0)
1380 {
1381 fprintf(stderr, " Cannot close speech file '%s'\n", bellcore_files[j]);
1382 exit(2);
1383 }
1384 /*endif*/
1385 printf(" File %d gave %d false hits.\n", j + 1, hits);
1386 }
1387 /*endfor*/
1388 if (hits > 0)
1389 {
1390 printf("Test failed.\n");
1391 exit(2);
1392 }
1393 /*endif*/
1394 printf("Test passed.\n");
1395 }
1396 /*endif*/
1397
1398 if (decode_test_file)
1399 {
1400 printf("Decode file '%s'\n", decode_test_file);
1401 modem_connect_tones_rx_init(&cng_rx, MODEM_CONNECT_TONES_FAX_CNG, cng_detected, NULL);
1402 modem_connect_tones_rx_init(&ced_rx, MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE, ced_detected, NULL);
1403 modem_connect_tones_rx_init(&ans_pr_rx, MODEM_CONNECT_TONES_ANS_PR, ans_pr_detected, NULL);
1404 hits = 0;
1405 if ((inhandle = sf_open_telephony_read(decode_test_file, 1)) == NULL)
1406 {
1407 fprintf(stderr, " Cannot open speech file '%s'\n", decode_test_file);
1408 exit (2);
1409 }
1410 /*endif*/
1411
1412 when = 0;
1413 hits = 0;
1414 while ((frames = sf_readf_short(inhandle, amp, 8000)))
1415 {
1416 when++;
1417 modem_connect_tones_rx(&cng_rx, amp, frames);
1418 modem_connect_tones_rx(&ced_rx, amp, frames);
1419 modem_connect_tones_rx(&ans_pr_rx, amp, frames);
1420 }
1421 /*endwhile*/
1422 if (sf_close(inhandle) != 0)
1423 {
1424 fprintf(stderr, " Cannot close speech file '%s'\n", decode_test_file);
1425 exit(2);
1426 }
1427 /*endif*/
1428 printf(" File gave %d hits.\n", hits);
1429 }
1430 printf("Tests passed.\n");
1431 return 0;
1432 }
1433 /*- End of function --------------------------------------------------------*/
1434 /*- End of file ------------------------------------------------------------*/

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