comparison spandsp-0.0.3/spandsp-0.0.3/tests/modem_connect_tones_tests.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 * 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.5 2006/11/19 14:07:27 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 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #include <stdlib.h>
38 #include <inttypes.h>
39 #include <stdio.h>
40 #if defined(HAVE_TGMATH_H)
41 #include <tgmath.h>
42 #endif
43 #if defined(HAVE_MATH_H)
44 #include <math.h>
45 #endif
46 #include <fcntl.h>
47 #include <string.h>
48 #include <audiofile.h>
49 #include <tiffio.h>
50
51 #include "spandsp.h"
52
53 #define OUTPUT_FILE_NAME "modem_connect_tones.wav"
54
55 #define BELLCORE_DIR "../itutests/bellcore/"
56
57 #define FALSE 0
58 #define TRUE (!FALSE)
59
60 const char *bellcore_files[] =
61 {
62 BELLCORE_DIR "tr-tsy-00763-1.wav",
63 BELLCORE_DIR "tr-tsy-00763-2.wav",
64 BELLCORE_DIR "tr-tsy-00763-3.wav",
65 BELLCORE_DIR "tr-tsy-00763-4.wav",
66 BELLCORE_DIR "tr-tsy-00763-5.wav",
67 BELLCORE_DIR "tr-tsy-00763-6.wav",
68 ""
69 };
70
71 int main(int argc, char *argv[])
72 {
73 int i;
74 int j;
75 int pitch;
76 int level;
77 int16_t amp[8000];
78 modem_connect_tones_rx_state_t cng_rx;
79 modem_connect_tones_rx_state_t ced_rx;
80 modem_connect_tones_rx_state_t ec_dis_rx;
81 modem_connect_tones_tx_state_t ec_dis_tx;
82 awgn_state_t chan_noise_source;
83 int hits;
84 AFfilehandle inhandle;
85 AFfilehandle outhandle;
86 AFfilesetup filesetup;
87 int outframes;
88 int frames;
89 int samples;
90 int hit;
91 int false_hit;
92 int false_miss;
93 float x;
94 tone_gen_descriptor_t tone_desc;
95 tone_gen_state_t tone_tx;
96
97 if ((filesetup = afNewFileSetup()) == AF_NULL_FILESETUP)
98 {
99 fprintf(stderr, " Failed to create file setup\n");
100 exit(2);
101 }
102 afInitSampleFormat(filesetup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16);
103 afInitRate(filesetup, AF_DEFAULT_TRACK, (float) SAMPLE_RATE);
104 afInitFileFormat(filesetup, AF_FILE_WAVE);
105 afInitChannels(filesetup, AF_DEFAULT_TRACK, 1);
106
107 if ((outhandle = afOpenFile(OUTPUT_FILE_NAME, "w", filesetup)) == AF_NULL_FILEHANDLE)
108 {
109 fprintf(stderr, " Cannot create wave file '%s'\n", OUTPUT_FILE_NAME);
110 exit(2);
111 }
112
113 printf("Test 1a: CNG generation to a file\n");
114 modem_connect_tones_tx_init(&ec_dis_tx, MODEM_CONNECT_TONES_FAX_CNG);
115 for (i = 0; i < 1000; i++)
116 {
117 samples = modem_connect_tones_tx(&ec_dis_tx, amp, 160);
118 outframes = afWriteFrames(outhandle,
119 AF_DEFAULT_TRACK,
120 amp,
121 samples);
122 if (outframes != samples)
123 {
124 fprintf(stderr, " Error writing wave file\n");
125 exit(2);
126 }
127 }
128
129 printf("Test 1b: CED generation to a file\n");
130 modem_connect_tones_tx_init(&ec_dis_tx, MODEM_CONNECT_TONES_FAX_CED);
131 for (i = 0; i < 1000; i++)
132 {
133 samples = modem_connect_tones_tx(&ec_dis_tx, amp, 160);
134 outframes = afWriteFrames(outhandle,
135 AF_DEFAULT_TRACK,
136 amp,
137 samples);
138 if (outframes != samples)
139 {
140 fprintf(stderr, " Error writing wave file\n");
141 exit(2);
142 }
143 }
144
145 printf("Test 1c: Modulated EC-disable generation to a file\n");
146 /* Some with modulation */
147 modem_connect_tones_tx_init(&ec_dis_tx, MODEM_CONNECT_TONES_EC_DISABLE_MOD);
148 for (i = 0; i < 1000; i++)
149 {
150 samples = modem_connect_tones_tx(&ec_dis_tx, amp, 160);
151 outframes = afWriteFrames(outhandle,
152 AF_DEFAULT_TRACK,
153 amp,
154 samples);
155 if (outframes != samples)
156 {
157 fprintf(stderr, " Error writing wave file\n");
158 exit(2);
159 }
160 }
161
162 printf("Test 1d: EC-disable generation to a file\n");
163 /* Some without modulation */
164 modem_connect_tones_tx_init(&ec_dis_tx, MODEM_CONNECT_TONES_EC_DISABLE);
165 for (i = 0; i < 1000; i++)
166 {
167 samples = modem_connect_tones_tx(&ec_dis_tx, amp, 160);
168 outframes = afWriteFrames(outhandle,
169 AF_DEFAULT_TRACK,
170 amp,
171 samples);
172 if (outframes != samples)
173 {
174 fprintf(stderr, " Error writing wave file\n");
175 exit(2);
176 }
177 }
178 if (afCloseFile(outhandle) != 0)
179 {
180 printf(" Cannot close wave file '%s'\n", OUTPUT_FILE_NAME);
181 exit(2);
182 }
183
184 printf("Test 2a: CNG detection with frequency\n");
185 awgn_init_dbm0(&chan_noise_source, 7162534, -50.0f);
186 false_hit = FALSE;
187 false_miss = FALSE;
188 for (pitch = 600; pitch < 1600; pitch++)
189 {
190 make_tone_gen_descriptor(&tone_desc,
191 pitch,
192 -11,
193 0,
194 0,
195 425,
196 3000,
197 0,
198 0,
199 TRUE);
200 tone_gen_init(&tone_tx, &tone_desc);
201
202 modem_connect_tones_rx_init(&cng_rx, MODEM_CONNECT_TONES_FAX_CNG, NULL, NULL);
203 for (i = 0; i < 500; i++)
204 {
205 samples = tone_gen(&tone_tx, amp, 160);
206 for (j = 0; j < samples; j++)
207 amp[j] += awgn(&chan_noise_source);
208 /*endfor*/
209 modem_connect_tones_rx(&cng_rx, amp, samples);
210 }
211 hit = modem_connect_tones_rx_get(&cng_rx);
212 if (pitch < (1100 - 70) || pitch > (1100 + 70))
213 {
214 if (hit)
215 false_hit = TRUE;
216 }
217 else if (pitch > (1100 - 50) && pitch < (1100 + 50))
218 {
219 if (!hit)
220 false_miss = TRUE;
221 }
222 if (hit)
223 printf("Detected at %5dHz %12d %12d %d\n", pitch, cng_rx.channel_level, cng_rx.notch_level, hit);
224 }
225 if (false_hit || false_miss)
226 {
227 printf("Test failed.\n");
228 exit(2);
229 }
230
231 printf("Test 2b: CED detection with frequency\n");
232 awgn_init_dbm0(&chan_noise_source, 7162534, -50.0f);
233 false_hit = FALSE;
234 false_miss = FALSE;
235 for (pitch = 1600; pitch < 2600; pitch++)
236 {
237 make_tone_gen_descriptor(&tone_desc,
238 pitch,
239 -11,
240 0,
241 0,
242 2600,
243 0,
244 0,
245 0,
246 FALSE);
247 tone_gen_init(&tone_tx, &tone_desc);
248
249 modem_connect_tones_rx_init(&ced_rx, MODEM_CONNECT_TONES_FAX_CED, NULL, NULL);
250 for (i = 0; i < 500; i++)
251 {
252 samples = tone_gen(&tone_tx, amp, 160);
253 for (j = 0; j < samples; j++)
254 amp[j] += awgn(&chan_noise_source);
255 /*endfor*/
256 modem_connect_tones_rx(&ced_rx, amp, samples);
257 }
258 hit = modem_connect_tones_rx_get(&ced_rx);
259 if (pitch < (2100 - 70) || pitch > (2100 + 70))
260 {
261 if (hit)
262 false_hit = TRUE;
263 }
264 else if (pitch > (2100 - 50) && pitch < (2100 + 50))
265 {
266 if (!hit)
267 false_miss = TRUE;
268 }
269 if (hit)
270 printf("Detected at %5dHz %12d %12d %d\n", pitch, ced_rx.channel_level, ced_rx.notch_level, hit);
271 }
272 if (false_hit || false_miss)
273 {
274 printf("Test failed.\n");
275 exit(2);
276 }
277
278 printf("Test 2c: EC disable detection with frequency\n");
279 awgn_init_dbm0(&chan_noise_source, 7162534, -50.0f);
280 false_hit = FALSE;
281 false_miss = FALSE;
282 for (pitch = 2000; pitch < 2200; pitch++)
283 {
284 /* Use the transmitter to test the receiver */
285 modem_connect_tones_tx_init(&ec_dis_tx, MODEM_CONNECT_TONES_EC_DISABLE);
286 /* Fudge things for the test */
287 ec_dis_tx.tone_phase_rate = dds_phase_rate(pitch);
288 ec_dis_tx.level = dds_scaling_dbm0(-25);
289 modem_connect_tones_rx_init(&ec_dis_rx, MODEM_CONNECT_TONES_EC_DISABLE, NULL, NULL);
290 for (i = 0; i < 500; i++)
291 {
292 samples = modem_connect_tones_tx(&ec_dis_tx, amp, 160);
293 for (j = 0; j < samples; j++)
294 amp[j] += awgn(&chan_noise_source);
295 /*endfor*/
296 modem_connect_tones_rx(&ec_dis_rx, amp, samples);
297 }
298 hit = modem_connect_tones_rx_get(&ec_dis_rx);
299 if (pitch < (2100 - 70) || pitch > (2100 + 70))
300 {
301 if (hit)
302 false_hit = TRUE;
303 }
304 else if (pitch > (2100 - 50) && pitch < (2100 + 50))
305 {
306 if (!hit)
307 false_miss = TRUE;
308 }
309 if (hit)
310 printf("Detected at %5dHz %12d %12d %d\n", pitch, ec_dis_rx.channel_level, ec_dis_rx.notch_level, hit);
311 }
312 if (false_hit || false_miss)
313 {
314 printf("Test failed.\n");
315 exit(2);
316 }
317
318 printf("Test 3a: CNG detection with level\n");
319 awgn_init_dbm0(&chan_noise_source, 7162534, -60.0f);
320 false_hit = FALSE;
321 false_miss = FALSE;
322 for (pitch = 1062; pitch <= 1138; pitch += 2*38)
323 {
324 for (level = 0; level >= -43; level--)
325 {
326 make_tone_gen_descriptor(&tone_desc,
327 pitch,
328 level,
329 0,
330 0,
331 500,
332 3000,
333 0,
334 0,
335 TRUE);
336 tone_gen_init(&tone_tx, &tone_desc);
337
338 modem_connect_tones_rx_init(&cng_rx, MODEM_CONNECT_TONES_FAX_CNG, NULL, NULL);
339 for (i = 0; i < 500; i++)
340 {
341 samples = tone_gen(&tone_tx, amp, 160);
342 for (j = 0; j < samples; j++)
343 amp[j] += awgn(&chan_noise_source);
344 /*endfor*/
345 modem_connect_tones_rx(&cng_rx, amp, samples);
346 }
347 hit = modem_connect_tones_rx_get(&cng_rx);
348 if (level < -43)
349 {
350 if (hit)
351 false_hit = TRUE;
352 }
353 else if (level > -43)
354 {
355 if (!hit)
356 false_miss = TRUE;
357 }
358 if (hit)
359 printf("Detected at %5dHz %ddB %12d %12d %d\n", pitch, level, cng_rx.channel_level, cng_rx.notch_level, hit);
360 }
361 }
362 if (false_hit || false_miss)
363 {
364 printf("Test failed.\n");
365 exit(2);
366 }
367
368 printf("Test 3b: CED detection with level\n");
369 awgn_init_dbm0(&chan_noise_source, 7162534, -60.0f);
370 false_hit = FALSE;
371 false_miss = FALSE;
372 for (pitch = 2062; pitch <= 2138; pitch += 2*38)
373 {
374 for (level = 0; level >= -43; level--)
375 {
376 make_tone_gen_descriptor(&tone_desc,
377 pitch,
378 level,
379 0,
380 0,
381 2600,
382 0,
383 0,
384 0,
385 FALSE);
386 tone_gen_init(&tone_tx, &tone_desc);
387
388 modem_connect_tones_rx_init(&ced_rx, MODEM_CONNECT_TONES_FAX_CED, NULL, NULL);
389 for (i = 0; i < 500; i++)
390 {
391 samples = tone_gen(&tone_tx, amp, 160);
392 for (j = 0; j < samples; j++)
393 amp[j] += awgn(&chan_noise_source);
394 /*endfor*/
395 modem_connect_tones_rx(&ced_rx, amp, samples);
396 }
397 hit = modem_connect_tones_rx_get(&ced_rx);
398 if (level < -43)
399 {
400 if (hit)
401 false_hit = TRUE;
402 }
403 else if (level > -43)
404 {
405 if (!hit)
406 false_miss = TRUE;
407 }
408 if (hit)
409 printf("Detected at %5dHz %ddB %12d %12d %d\n", pitch, level, ced_rx.channel_level, ced_rx.notch_level, hit);
410 }
411 }
412 if (false_hit || false_miss)
413 {
414 printf("Test failed.\n");
415 exit(2);
416 }
417
418 /* Talk-off test */
419 /* Here we use the BellCore talk off test tapes, intended for DTMF detector
420 testing. Presumably they should also have value here, but I am not sure.
421 If those voice snippets were chosen to be tough on DTMF detectors, they
422 might go easy on detectors looking for different pitches. However, the
423 Mitel DTMF test tape is known (the hard way) to exercise 2280Hz tone
424 detectors quite well. */
425 printf("Test 2: Talk-off test\n");
426 modem_connect_tones_rx_init(&cng_rx, MODEM_CONNECT_TONES_FAX_CNG, NULL, NULL);
427 modem_connect_tones_rx_init(&ced_rx, MODEM_CONNECT_TONES_FAX_CED, NULL, NULL);
428 modem_connect_tones_rx_init(&ec_dis_rx, MODEM_CONNECT_TONES_EC_DISABLE, NULL, NULL);
429 hits = 0;
430 for (j = 0; bellcore_files[j][0]; j++)
431 {
432 if ((inhandle = afOpenFile(bellcore_files[j], "r", 0)) == AF_NULL_FILEHANDLE)
433 {
434 printf (" Cannot open speech file '%s'\n", bellcore_files[j]);
435 exit (2);
436 }
437 if ((x = afGetFrameSize(inhandle, AF_DEFAULT_TRACK, 1)) != 2.0)
438 {
439 printf (" Unexpected frame size in speech file '%s'\n", bellcore_files[j]);
440 exit (2);
441 }
442 if ((x = afGetRate(inhandle, AF_DEFAULT_TRACK)) != (float) SAMPLE_RATE)
443 {
444 printf(" Unexpected sample rate in speech file '%s'\n", bellcore_files[j]);
445 exit(2);
446 }
447 if ((x = afGetChannels(inhandle, AF_DEFAULT_TRACK)) != 1.0)
448 {
449 printf(" Unexpected number of channels in speech file '%s'\n", bellcore_files[j]);
450 exit(2);
451 }
452
453 hits = 0;
454 while ((frames = afReadFrames(inhandle, AF_DEFAULT_TRACK, amp, 8000)))
455 {
456 modem_connect_tones_rx(&cng_rx, amp, frames);
457 modem_connect_tones_rx(&ced_rx, amp, frames);
458 modem_connect_tones_rx(&ec_dis_rx, amp, frames);
459 if (modem_connect_tones_rx_get(&cng_rx))
460 {
461 /* This is not a true measure of hits, as there might be more
462 than one in a block of data. However, since the only good
463 result is no hits, this approximation is OK. */
464 hits++;
465 modem_connect_tones_rx_init(&cng_rx, MODEM_CONNECT_TONES_FAX_CNG, NULL, NULL);
466 }
467 if (modem_connect_tones_rx_get(&ced_rx))
468 {
469 hits++;
470 modem_connect_tones_rx_init(&ced_rx, MODEM_CONNECT_TONES_FAX_CED, NULL, NULL);
471 }
472 if (modem_connect_tones_rx_get(&ec_dis_rx))
473 {
474 hits++;
475 modem_connect_tones_rx_init(&ec_dis_rx, MODEM_CONNECT_TONES_EC_DISABLE, NULL, NULL);
476 }
477 }
478 if (afCloseFile(inhandle) != 0)
479 {
480 printf(" Cannot close speech file '%s'\n", bellcore_files[j]);
481 exit(2);
482 }
483 printf(" File %d gave %d false hits.\n", j + 1, hits);
484 }
485 if (hits)
486 {
487 printf("Test failed.\n");
488 exit(2);
489 }
490
491 printf("Tests passed.\n");
492 return 0;
493 }
494 /*- End of function --------------------------------------------------------*/
495 /*- End of file ------------------------------------------------------------*/

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