comparison spandsp-0.0.3/spandsp-0.0.3/tests/echo_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 * echo_tests.c
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2001 Steve Underwood
9 *
10 * Based on a bit from here, a bit from there, eye of toad,
11 * ear of bat, etc - plus, of course, my own 2 cents.
12 *
13 * All rights reserved.
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License version 2, as
17 * published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 *
28 * $Id: echo_tests.c,v 1.27 2006/11/19 14:07:27 steveu Exp $
29 */
30
31 /*! \page echo_can_tests_page Line echo cancellation for voice tests
32
33 \section echo_can_tests_page_sec_1 What does it do?
34 The echo cancellation tests test the echo cancellor against the G.168 spec. Not
35 all the tests in G.168 are fully implemented at this time.
36
37 \section echo_can_tests_page_sec_2 How does it work?
38
39 \section echo_can_tests_page_sec_2 How do I use it?
40
41 */
42
43 #ifdef HAVE_CONFIG_H
44 #include "config.h"
45 #endif
46
47 #if defined(HAVE_FL_FL_H) && defined(HAVE_FL_FL_CARTESIAN_H) && defined(HAVE_FL_FL_AUDIO_METER_H)
48 #define ENABLE_GUI
49 #endif
50
51 #define _GNU_SOURCE
52
53 #include <unistd.h>
54 #include <inttypes.h>
55 #include <stdlib.h>
56 #include <stdio.h>
57 #include <string.h>
58 #include <strings.h>
59 #if defined(HAVE_TGMATH_H)
60 #include <tgmath.h>
61 #endif
62 #if defined(HAVE_MATH_H)
63 #include <math.h>
64 #endif
65 #include <assert.h>
66 #include <audiofile.h>
67 #include <tiffio.h>
68
69 #define GEN_CONST
70 #include <math.h>
71
72 #include "spandsp.h"
73 #include "spandsp/g168models.h"
74 #if defined(ENABLE_GUI)
75 #include "echo_monitor.h"
76 #endif
77
78 #define TEST_EC_TAPS 256
79
80 #if !defined(NULL)
81 #define NULL (void *) 0
82 #endif
83
84 typedef struct
85 {
86 const char *name;
87 int max;
88 int cur;
89 AFfilehandle handle;
90 int16_t signal[SAMPLE_RATE];
91 } signal_source_t;
92
93 typedef struct
94 {
95 int type;
96 fir_float_state_t *fir;
97 float history[35*8];
98 int pos;
99 float factor;
100 float power;
101 } level_measurement_device_t;
102
103 signal_source_t local_css;
104 signal_source_t far_css;
105
106 fir32_state_t line_model;
107 float model_ki, erl;
108
109 AFfilehandle residuehandle;
110 int16_t residue_sound[SAMPLE_RATE];
111 int residue_cur = 0;
112 int munge;
113
114 FILE *fdump;
115
116 float clip(float x);
117 float clip(float x) {
118 if (x > 32767.0) x = 32767.0;
119 if (x < -32767.0) x = -32767.0;
120
121 return x;
122 }
123 /*- End of function --------------------------------------------------------*/
124
125 static inline void put_residue(int16_t amp)
126 {
127 int outframes;
128
129 residue_sound[residue_cur++] = amp;
130 if (residue_cur >= SAMPLE_RATE) {
131 outframes = afWriteFrames(residuehandle,
132 AF_DEFAULT_TRACK,
133 residue_sound,
134 residue_cur);
135 if (outframes != residue_cur)
136 {
137 fprintf(stderr, " Error writing residue sound\n");
138 exit(2);
139 }
140 residue_cur = 0;
141 }
142 }
143 /*- End of function --------------------------------------------------------*/
144
145 static void signal_load(signal_source_t *sig, const char *name)
146 {
147 float x;
148
149 sig->name = name;
150 if ((sig->handle = afOpenFile(sig->name, "r", 0)) == AF_NULL_FILEHANDLE)
151 {
152 fprintf(stderr, " Cannot open wave file '%s'\n", sig->name);
153 exit(2);
154 }
155 if ((x = afGetFrameSize(sig->handle, AF_DEFAULT_TRACK, 1)) != 2.0)
156 {
157 fprintf(stderr, " Unexpected frame size in wave file '%s'\n", sig->name);
158 exit(2);
159 }
160 if ((x = afGetRate(sig->handle, AF_DEFAULT_TRACK)) != (float) SAMPLE_RATE)
161 {
162 printf(" Unexpected sample rate in wave file '%s'\n", sig->name);
163 exit(2);
164 }
165 if ((x = afGetChannels(sig->handle, AF_DEFAULT_TRACK)) != 1.0)
166 {
167 printf(" Unexpected number of channels in wave file '%s'\n", sig->name);
168 exit(2);
169 }
170 sig->max = afReadFrames(sig->handle, AF_DEFAULT_TRACK, sig->signal, SAMPLE_RATE);
171 if (sig->max < 0)
172 {
173 fprintf(stderr, " Error reading sound file '%s'\n", sig->name);
174 exit(2);
175 }
176 }
177 /*- End of function --------------------------------------------------------*/
178
179 static AFfilehandle af_file_open_for_read(const char *name)
180 {
181 float x;
182 AFfilehandle handle;
183
184 if ((handle = afOpenFile(name, "r", 0)) == AF_NULL_FILEHANDLE)
185 {
186 fprintf(stderr, " Cannot open wave file '%s'\n", name);
187 exit(2);
188 }
189 if ((x = afGetFrameSize(handle, AF_DEFAULT_TRACK, 1)) != 2.0)
190 {
191 fprintf(stderr, " Unexpected frame size in wave file '%s'\n", name);
192 exit(2);
193 }
194 if ((x = afGetRate(handle, AF_DEFAULT_TRACK)) != (float) SAMPLE_RATE)
195 {
196 printf(" Unexpected sample rate in wave file '%s'\n", name);
197 exit(2);
198 }
199 if ((x = afGetChannels(handle, AF_DEFAULT_TRACK)) != 1.0)
200 {
201 printf(" Unexpected number of channels in wave file '%s'\n", name);
202 exit(2);
203 }
204
205 return handle;
206 }
207 /*- End of function --------------------------------------------------------*/
208
209 static AFfilehandle af_file_open_for_write(const char *name)
210 {
211 AFfilesetup setup;
212 AFfilehandle handle;
213
214 setup = afNewFileSetup();
215 if (setup == AF_NULL_FILESETUP)
216 {
217 fprintf(stderr, " %s: Failed to create file setup\n", name);
218 exit(2);
219 }
220 afInitSampleFormat(setup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16);
221 afInitRate(setup, AF_DEFAULT_TRACK, (float) SAMPLE_RATE);
222 afInitFileFormat(setup, AF_FILE_WAVE);
223 afInitChannels(setup, AF_DEFAULT_TRACK, 1);
224 handle = afOpenFile(name, "w", setup);
225
226 if (handle == AF_NULL_FILEHANDLE)
227 {
228 fprintf(stderr, " Failed to open result file\n");
229 exit(2);
230 }
231 afFreeFileSetup(setup);
232
233 return handle;
234 }
235 /*- End of function --------------------------------------------------------*/
236
237 static void signal_restart(signal_source_t *sig)
238 {
239 sig->cur = 0;
240 }
241 /*- End of function --------------------------------------------------------*/
242
243 static int16_t signal_amp(signal_source_t *sig)
244 {
245 int16_t tx;
246
247 tx = sig->signal[sig->cur++];
248 if (sig->cur >= sig->max)
249 sig->cur = 0;
250 return tx;
251 }
252 /*- End of function --------------------------------------------------------*/
253
254 /* note mu-law used, alaw has big DC Offsets that causes probs with G168
255 tests, due to alaw idle values being passed thru when NLP opens for
256 very low level signals. Probably need a DC blocking filter in e/c
257 */
258 static inline int16_t codec_munge(int16_t amp)
259 {
260 return ulaw_to_linear(linear_to_ulaw(amp));
261 }
262 /*- End of function --------------------------------------------------------*/
263
264 static int channel_model_create(int model)
265 {
266 static const int32_t *line_models[] =
267 {
268 line_model_d2_coeffs,
269 line_model_d3_coeffs,
270 line_model_d4_coeffs,
271 line_model_d5_coeffs,
272 line_model_d6_coeffs,
273 line_model_d7_coeffs,
274 line_model_d8_coeffs,
275 line_model_d9_coeffs
276 };
277
278 static int line_model_sizes[] =
279 {
280 sizeof(line_model_d2_coeffs)/sizeof(int32_t),
281 sizeof(line_model_d3_coeffs)/sizeof(int32_t),
282 sizeof(line_model_d4_coeffs)/sizeof(int32_t),
283 sizeof(line_model_d5_coeffs)/sizeof(int32_t),
284 sizeof(line_model_d6_coeffs)/sizeof(int32_t),
285 sizeof(line_model_d7_coeffs)/sizeof(int32_t),
286 sizeof(line_model_d8_coeffs)/sizeof(int32_t),
287 sizeof(line_model_d9_coeffs)/sizeof(int32_t)
288 };
289
290 static float ki[] =
291 {
292 1.39E-5, 1.44E-5, 1.52E-5, 1.77E-5, 9.33E-6, 1.51E-5, 2.33E-5, 1.33E-5
293 };
294
295 if (model < 1 || model > (int) (sizeof(line_model_sizes)/sizeof(line_model_sizes[0])))
296 return -1;
297 fir32_create(&line_model, line_models[model-1], line_model_sizes[model-1]);
298
299 model_ki = ki[model-1];
300
301 return 0;
302 }
303 /*- End of function --------------------------------------------------------*/
304
305 static int16_t channel_model(int16_t *new_local, int16_t *new_far, int16_t local, int16_t far)
306 {
307 int16_t echo;
308 int16_t rx;
309
310 /* Channel modelling is merely simulating the effects of A-law or u-law distortion
311 and using one of the echo models from G.168. Simulating the codec is very important,
312 as this is usually the limiting factor in how much echo reduction is achieved. */
313
314 /* The local tx signal will usually have gone through an A-law munging before
315 it reached the line's analogue area, where the echo occurs. */
316 if (munge == TRUE)
317 local = codec_munge(local);
318 /* Now we need to model the echo. We only model a single analogue segment, as per
319 the G.168 spec. However, there will generally be near end and far end analogue/echoey
320 segments in the real world, unless an end is purely digital. */
321 echo = fir32(&line_model, local*erl*(32768.0*model_ki));
322 /* The far end signal will have been through an A-law munging, although
323 this should not affect things. */
324 if (munge == TRUE)
325 rx = clip(echo + codec_munge(far));
326 else
327 rx = clip(echo + far);
328
329 /* This mixed echo and far end signal will have been through an A-law munging
330 when it came back into the digital network. */
331 if (munge == TRUE)
332 rx = codec_munge(rx);
333 if (new_far)
334 *new_far = rx;
335 if (new_local)
336 *new_local = local;
337 return rx;
338 }
339 /*- End of function --------------------------------------------------------*/
340
341 /*
342 250Hz HP filter, designed using this excellent site:
343
344 http://www-users.cs.york.ac.uk/~fisher/mkfilter/
345
346 Included as preliminary test to see if this sort of filter will help
347 hum removal from low cost X100P type cards. Unfortunately I couldn't
348 get thios to work well in fixed point, so had to leave it out of
349 treh core echo canceller.
350 */
351
352 #define NZEROS 4
353 #define NPOLES 4
354
355 #define FIXED
356 #ifdef FIXED
357 #define GAIN 1.293080949e+00
358 #define QCONST32(x,bits) ((int)((x)*(1<<(bits))))
359
360 static int hp_filter(int xv[], int yv[], int x)
361 {
362 xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4];
363 xv[4] = x * (int)((1<<5)/GAIN);
364 yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = yv[4];
365 yv[4] = (xv[0] + xv[4]) - 4 * (xv[1] + xv[3]) + 6 * xv[2];
366 yv[4] += (QCONST32(-0.5980652616f, 10) * yv[0]) >> 10;
367 yv[4] += (QCONST32( 2.6988843913f, 10) * yv[1]) >> 10;
368 yv[4] += (QCONST32(-4.5892912321f, 10) * yv[2]) >> 10;
369 yv[4] += (QCONST32( 3.4873077415f, 10) * yv[3]) >> 10;
370
371 return yv[4] >> 5;
372 }
373
374 #else
375 #define GAIN 1.293080949e+00
376
377 static float hp_filter(float xv[], float yv[], float x)
378 {
379 xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4];
380 xv[4] = x / GAIN;
381 yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = yv[4];
382 yv[4] = (xv[0] + xv[4]) - 4 * (xv[1] + xv[3]) + 6 * xv[2]
383 + ( -0.5980652616 * yv[0]) + ( 2.6988843913 * yv[1])
384 + ( -4.5892912321 * yv[2]) + ( 3.4873077415 * yv[3]);
385 return yv[4];
386 }
387 #endif
388
389 static level_measurement_device_t *level_measurement_device_create(int type)
390 {
391 level_measurement_device_t *dev;
392 int i;
393
394 dev = (level_measurement_device_t *) malloc(sizeof(level_measurement_device_t));
395 dev->fir = (fir_float_state_t *) malloc(sizeof(fir_float_state_t));
396 fir_float_create(dev->fir,
397 level_measurement_bp_coeffs,
398 sizeof(level_measurement_bp_coeffs)/sizeof(float));
399 for (i = 0; i < 35*8; i++)
400 dev->history[i] = 0.0;
401 dev->pos = 0;
402 dev->factor = exp(-1.0/((float) SAMPLE_RATE*0.035));
403 dev->power = 0;
404 dev->type = type;
405 return dev;
406 }
407 /*- End of function --------------------------------------------------------*/
408
409 static void level_measurement_device_reset(level_measurement_device_t *dev)
410 {
411 int i;
412
413 for (i = 0; i < 35*8; i++)
414 dev->history[i] = 0.0;
415 dev->pos = 0;
416 dev->power = 0;
417 }
418 /*- End of function --------------------------------------------------------*/
419
420 static int level_measurement_device_release(level_measurement_device_t *s)
421 {
422 fir_float_free(s->fir);
423 free(s->fir);
424 free(s);
425 return 0;
426 }
427 /*- End of function --------------------------------------------------------*/
428
429 static float level_measurement_device(level_measurement_device_t *dev, int16_t amp)
430 {
431 float signal;
432
433 signal = fir_float(dev->fir, amp);
434 signal *= signal;
435 if (dev->type == 0)
436 {
437 dev->power = dev->power*dev->factor + signal*(1.0 - dev->factor);
438 signal = sqrt(dev->power);
439 }
440 else
441 {
442 dev->power -= dev->history[dev->pos];
443 dev->power += signal;
444 dev->history[dev->pos++] = signal;
445 signal = sqrt(dev->power/(35.8*8.0));
446 }
447 if (signal > 0.0)
448 return DBM0_MAX_POWER + 20.0*log10(signal/32767.0);
449 else
450 return -1000.0;
451 }
452 /*- End of function --------------------------------------------------------*/
453
454 /* Globals used for performing tests */
455
456 echo_can_state_t *ctx;
457 awgn_state_t sgen_noise_source;
458 awgn_state_t rin_noise_source;
459
460 level_measurement_device_t *Rin_power_meter;
461 level_measurement_device_t *Sgen_power_meter;
462 level_measurement_device_t *Sin_power_meter;
463 level_measurement_device_t *Sout_power_meter;
464
465 float LRin, maxLRin;
466 float LSgen, maxLSgen;
467 float LSin, maxLSin;
468 float LSout, maxLSout;
469 float Lres, maxLres;
470 float test_clock;
471 float maxHoth;
472
473 float Rin_level, Sgen_level;
474 FILE *flevel;
475 int Rin_type, Sgen_type;
476 int failed;
477 int verbose, quiet;
478 float threshold;
479 int model_number;
480 char test_name[80];
481
482 tone_gen_state_t rin_tone_state;
483 tone_gen_state_t sgen_tone_state;
484
485 /*
486 Test callback functions are called one for every processed sample
487 during run_test(). They are user supplied, and return TRUE if the
488 test is passing or FALSE if a combination of variables mean that
489 the test has failed (for example Lres exceeding some threshold).
490
491 Different test callback functions are required for each G168 test.
492 */
493 int (*test_callback)(void);
494
495 /* macros to convert units for run_test */
496
497 #define MSEC (SAMPLE_RATE/1000)
498 #define SEC SAMPLE_RATE
499
500 /* Sgen signal generator types */
501
502 #define NONE 0
503 #define CSS 1
504 #define HOTH 2
505 #define TONE 3
506
507 /* Experimentally generated constants to normalise levels to dBm0 */
508
509 #define HOTH_SCALE 2.40
510 #define CSS_SCALE 5.60
511
512 static void reset_all(void) {
513 echo_can_flush(ctx);
514 maxLRin = maxLSgen = maxLSin = maxLSout = maxLres = -100.0;
515 signal_restart(&local_css);
516 signal_restart(&far_css);
517 test_callback = NULL;
518 Rin_type = CSS;
519 Sgen_type = NONE;
520 failed = FALSE;
521 test_clock = 0.0;
522 }
523
524 static void reset_meter_peaks(void) {
525 maxLRin = maxLSgen = maxLSin = maxLSout = maxLres = -100.0;
526 }
527
528 static void install_test_callback(int (*f)(void)) {
529 test_callback = f;
530 }
531
532 /* note: maybe we should use absolute levels rather than gain? Need to
533 normalise levels from various signal types to do this */
534
535 static void set_Sgen(int source_type, float gain) {
536 Sgen_type = source_type;
537 Sgen_level = pow(10.0, gain/20.0);
538 }
539
540 static void set_Rin(int source_type, float gain) {
541 Rin_type = source_type;
542 Rin_level = pow(10.0, gain/20.0);
543 }
544
545 static void mute_Rin(void) {
546 Rin_type = NONE;
547 }
548
549 static void unmute_Rin(void) {
550 Rin_type = CSS;
551 }
552
553 static void update_levels(int16_t rin, int16_t sin, int16_t sout, int16_t sgen)
554 {
555 LRin = level_measurement_device(Rin_power_meter, rin);
556 LSin = level_measurement_device(Sin_power_meter, sin);
557 LSout = level_measurement_device(Sout_power_meter, sout);
558 LSgen = level_measurement_device(Sgen_power_meter, sgen);
559 if (LRin > maxLRin) maxLRin = LRin;
560 if (LSin > maxLSin) maxLSin = LSin;
561 if (LSout > maxLSout) maxLSout = LSout;
562 if (LSgen > maxLSgen) maxLSgen = LSgen;
563 }
564
565 static void write_log_files(int16_t rout, int16_t sin)
566 {
567 fprintf(flevel, "%f\t%f\t%f\t%f\n",LRin, LSin, LSout, LSgen);
568 fprintf(fdump, "%d %d %d", ctx->tx, ctx->rx, ctx->clean);
569 fprintf(fdump, " %d %d %d %d %d %d %d %d %d %d\n", ctx->clean_nlp, ctx->Ltx,
570 ctx->Lrx, ctx->Lclean,
571 (ctx->nonupdate_dwell > 0), ctx->adapt, ctx->Lclean_bg, ctx->Pstates,
572 ctx->Lbgn_upper, ctx->Lbgn);
573 }
574
575 static void run_test(float time, float units) {
576 int i;
577 int samples;
578 int16_t rout, rin=0, sin;
579 int16_t sgen=0, sout;
580 float rin_hoth_noise = 0;
581 float sgen_hoth_noise = 0;
582
583 samples = time * units;
584
585 for (i = 0; i < samples; i++) {
586
587 switch(Rin_type) {
588 case NONE:
589 rin = 0;
590 break;
591 case CSS:
592 rin = clip(Rin_level*signal_amp(&local_css)*CSS_SCALE);
593 break;
594 case HOTH:
595 rin_hoth_noise = rin_hoth_noise*0.625 + awgn(&rin_noise_source)*0.375;
596 rin = clip(Rin_level*rin_hoth_noise*HOTH_SCALE);
597 break;
598 case TONE:
599 tone_gen(&rin_tone_state, &rin, 1);
600 break;
601 }
602
603 switch(Sgen_type) {
604 case NONE:
605 sgen = 0;
606 break;
607 case CSS:
608 sgen = clip(Sgen_level*signal_amp(&far_css)*CSS_SCALE);
609 break;
610 case HOTH:
611 sgen_hoth_noise = sgen_hoth_noise*0.625 + awgn(&sgen_noise_source)*0.375;
612 sgen = clip(Sgen_level*sgen_hoth_noise*HOTH_SCALE);
613 break;
614 case TONE:
615 tone_gen(&sgen_tone_state, &sgen, 1);
616 break;
617 }
618
619 rout = echo_can_hpf_tx(ctx, rin);
620 channel_model(&rout, &sin, rin, sgen);
621 sout = echo_can_update(ctx, rout, sin);
622 update_levels(rin, sin, sout, sgen);
623 write_log_files(rout, sin);
624
625 /* now test for fail condition */
626 if (test_callback != NULL) {
627 if ( (failed == FALSE) && (test_callback() == FALSE)) {
628 /* test has failed */
629 failed = TRUE;
630 }
631 }
632
633 /* stop clock on fail - points to time of failure in test */
634
635 if (failed == FALSE)
636 test_clock += (float)1/SAMPLE_RATE;
637 }
638 }
639
640 static void print_title(const char *title) {
641 if (quiet == FALSE)
642 printf(title);
643 }
644
645 static void print_results(void) {
646
647 if (quiet == FALSE)
648 printf("test model ERL time Max Rin Max Sin Max Sgen Max Sout Result\n");
649 printf("%-4s %-1d %-5.1f%6.2fs%9.2f%9.2f%10.2f%10.2f ",
650 test_name, model_number, 20.0*log10(erl),
651 test_clock, maxLRin, maxLSin, maxLSgen, maxLSout);
652 if (failed == TRUE)
653 printf("FAIL\n");
654 else
655 printf("PASS\n");
656 }
657
658 static int test_2a(void) {
659 if (LSout > -65.0)
660 return FALSE;
661 else
662 return TRUE;
663 }
664
665 static int test_2c(void) {
666 if (LSout > maxHoth)
667 return FALSE;
668 else
669 return TRUE;
670 }
671
672 static int test_3a(void) {
673 if (LSout > maxLSgen)
674 return FALSE;
675 else
676 return TRUE;
677 }
678
679 static int test_3b(void) {
680 if (LSout > threshold)
681 return FALSE;
682 else
683 return TRUE;
684 }
685
686 static int test_3c_t2(void) {
687 if (LSout > maxLSgen)
688 return FALSE;
689 else
690 return TRUE;
691 }
692
693 static int test_3c_t4t5(void) {
694 if (LSout > (maxLSgen+6.0))
695 return FALSE;
696 else
697 return TRUE;
698 }
699
700 static int test_9(void) {
701 if (fabs(LSout - LSgen) > 2.0)
702 return FALSE;
703 else
704 return TRUE;
705 }
706
707 #define N_TESTS 9
708 static const char *supported_tests[] = {"ut1", "2aa", "2ca", "3a", "3ba",
709 "3bb", "3c", "6", "9"};
710
711 static int is_test_supported(char *test) {
712 int i;
713 for(i=0; i<N_TESTS; i++) {
714 if (!strcasecmp(test, supported_tests[i]))
715 return TRUE;
716 }
717
718 return FALSE;
719 }
720
721 /* dump estimate echo response */
722 static void dump_h(void) {
723 int i;
724 FILE *f = fopen("h.txt","wt");
725 for(i=0; i<TEST_EC_TAPS; i++) {
726 fprintf(f, "%f\n", (float)ctx->fir_taps16[0][i]/(1<<15));
727 }
728 fclose(f);
729 }
730
731 int main(int argc, char *argv[])
732 {
733 //awgn_state_t local_noise_source;
734 int i;
735 //int j;
736 //int k;
737 //tone_gen_descriptor_t tone_desc;
738 //tone_gen_state_t tone_state;
739 //int16_t local_sound[40000];
740 //int local_max;
741 //int local_cur;
742 int far_cur;
743 int result_cur;
744 AFfilehandle txfile, rxfile, ecfile;
745 time_t now;
746 int tone_burst_step;
747 float X_level, Sgen_leveldB;
748 #ifdef FIXED
749 int xvrx[NZEROS+1], yvrx[NPOLES+1];
750 int xvtx[NZEROS+1], yvtx[NPOLES+1];
751 #else
752 float xvrx[NZEROS+1], yvrx[NPOLES+1];
753 float xvtx[NZEROS+1], yvtx[NPOLES+1];
754 #endif
755
756 int file_mode;
757 float tmp;
758 int cng;
759 int hpf;
760
761 /* default config ------------------------------------------------*/
762
763 model_number = 1;
764 erl = pow(10.0, -10.0/20.0);
765 verbose = quiet = FALSE;
766 file_mode = FALSE;
767 Rin_level = pow(10.0, -15.0/20.0);
768 Sgen_leveldB = -15.0;
769 Sgen_level = pow(10.0, Sgen_leveldB/20.0);
770 X_level = pow(10.0, 6.0/20.0);
771 tone_burst_step = 0;
772 txfile = rxfile = ecfile = NULL;
773 munge = TRUE;
774 cng = FALSE;
775 hpf = TRUE;
776 for(i=0; i<NPOLES+1; i++) {
777 xvtx[i] = yvtx[i] = xvrx[i] = yvrx[i] = 0.0;
778 }
779
780 /* Check which tests we should run ----------------------------------------*/
781
782 if (argc < 2) {
783 fprintf(stderr, "Usage: echo [2aa] [2ca] [3a] [3ba] [3bb] [3c] [6] [9]\n"
784 "[-m ChannelModelNumber]\n"
785 "[-erl ERL_in_dB\n"
786 "[-file RinInputFile.wav SinInputFile.wav SoutOutputFile.wav\n"
787 "[-r RinLeveldBm0] [-s SgenLeveldBm0] [-x XLeveldB]\n"
788 "[-nomunge]\n"
789 "[-cng]\n"
790 "[-nohpf] Disable DC block HPF (-file mode)\n");
791
792 exit(1);
793 }
794
795 for (i = 1; i < argc; i++)
796 {
797 if (is_test_supported(argv[i])) {
798 }
799 else if (strcmp(argv[i], "-m") == 0)
800 {
801 if (++i < argc)
802 model_number = atoi(argv[i]);
803 }
804 else if (strcmp(argv[i], "-r") == 0)
805 {
806 if (++i < argc)
807 Rin_level = pow(10.0, atof(argv[i])/20.0);
808 }
809 else if (strcmp(argv[i], "-s") == 0)
810 {
811 if (++i < argc) {
812 Sgen_leveldB = atof(argv[i]);
813 Sgen_level = pow(10.0, Sgen_leveldB/20.0);
814 }
815 }
816 else if (strcmp(argv[i], "-x") == 0)
817 {
818 if (++i < argc)
819 X_level = pow(10.0, atof(argv[i])/20.0);
820 }
821 else if (strcmp(argv[i], "-erl") == 0)
822 {
823 if (++i < argc) {
824 erl = atof(argv[i]);
825 if (erl < 0.0) {
826 printf("ERL must be >= 0.0 dB\n");
827 exit(1);
828 }
829 erl = pow(10.0, -erl/20.0);
830 }
831 }
832 else if (strcmp(argv[i], "-v") == 0)
833 {
834 verbose = TRUE;
835 }
836 else if (strcmp(argv[i], "-q") == 0)
837 {
838 quiet = TRUE;
839 }
840 else if (strcmp(argv[i], "-file") == 0)
841 {
842 file_mode = TRUE;
843 if (argc < (i+3)) {
844 printf("not enough arguments for --file\n");
845 exit(2);
846 }
847 txfile = af_file_open_for_read(argv[i+1]);
848 rxfile = af_file_open_for_read(argv[i+2]);
849 ecfile = af_file_open_for_write(argv[i+3]);
850 i += 3;
851 }
852 else if (strcmp(argv[i], "-nomunge") == 0)
853 {
854 munge = FALSE;
855 }
856 else if (strcmp(argv[i], "-cng") == 0)
857 {
858 cng = TRUE;
859 }
860 else if (strcmp(argv[i], "-nohpf") == 0)
861 {
862 hpf = FALSE;
863 }
864 else
865 {
866 fprintf(stderr, "Unknown test/option '%s' specified\n", argv[i]);
867 exit(2);
868 }
869 }
870
871 /* initialise a bunch of modules we need ------------------------------*/
872
873 time(&now);
874
875 ctx = echo_can_create(TEST_EC_TAPS, 0);
876 awgn_init_dbm0(&rin_noise_source, 7162534, 0.0f);
877 awgn_init_dbm0(&sgen_noise_source, 7162534, 0.0f);
878 Rin_power_meter = level_measurement_device_create(0);
879 Sgen_power_meter = level_measurement_device_create(0);
880 Sin_power_meter = level_measurement_device_create(0);
881 Sout_power_meter = level_measurement_device_create(0);
882 if (channel_model_create(model_number))
883 {
884 fprintf(stderr, " Failed to create line model\n");
885 exit(2);
886 }
887
888 far_cur = 0;
889 result_cur = 0;
890
891 if (verbose == TRUE) {
892 printf("ERL (linear)......: %6.2f (%5.2f)\n"
893 "Rin level (linear).: %6.2f (%5.2f)\n"
894 "Sgen level (linear): %6.2f (%5.2f)\n",
895 20.0*log10(erl), erl,
896 20.0*log10(Rin_level), Rin_level,
897 20.0*log10(Sgen_level), Sgen_level);
898 }
899
900 fdump = fopen("dump.txt","wt");
901 assert(fdump != NULL);
902 flevel = fopen("level.txt","wt");
903 assert(flevel != NULL);
904
905 if (file_mode == TRUE) {
906 /* process wave files instead of running tests, useful for
907 testing real world signals */
908 int ntx, nrx, nec;
909 int16_t rin, rout, sin, sout;
910 int mode;
911
912 mode = ECHO_CAN_USE_ADAPTION | ECHO_CAN_USE_NLP;
913 if (cng)
914 mode |= ECHO_CAN_USE_CNG;
915 else
916 mode |= ECHO_CAN_USE_CLIP;
917 if (hpf) {
918 mode |= ECHO_CAN_USE_TX_HPF;
919 mode |= ECHO_CAN_USE_RX_HPF;
920 }
921 echo_can_adaption_mode(ctx, mode);
922 do {
923 ntx = afReadFrames(txfile, AF_DEFAULT_TRACK, &rin, 1);
924 if (ntx < 0) {
925 fprintf(stderr, " Error reading tx sound file\n");
926 exit(2);
927 }
928 nrx = afReadFrames(rxfile, AF_DEFAULT_TRACK, &sin, 1);
929 if (nrx < 0) {
930 fprintf(stderr, " Error reading rx sound file\n");
931 exit(2);
932 }
933
934 rout = echo_can_hpf_tx(ctx, rin);
935 sout = echo_can_update(ctx, rout, sin);
936
937 nec = afWriteFrames(ecfile, AF_DEFAULT_TRACK, &sout, 1);
938 if (nec != 1) {
939 fprintf(stderr, " Error writing ec sound file\n");
940 exit(2);
941 }
942
943 update_levels(rin, sin, sout, 0);
944 write_log_files(rin, sin);
945
946 } while (ntx && nrx);
947
948 dump_h();
949
950 afCloseFile(txfile);
951 afCloseFile(rxfile);
952 afCloseFile(ecfile);
953 exit(0);
954 }
955
956 signal_load(&local_css, "sound_c1_8k.wav");
957 signal_load(&far_css, "sound_c3_8k.wav");
958
959 strcpy(test_name, argv[1]);
960
961 /* basic unit test used in e/c dvelopment */
962
963 if (!strcasecmp(argv[1], "ut1")) {
964 int16_t rin, sin, rout, sout, sgen;
965
966 print_title("Performing Unit Test 1 - DC inputs\n");
967 reset_all();
968 echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
969
970 rout = rin = 2000;
971 sin = 1000;
972 sgen = 0;
973 for(i=0; i<10; i++) {
974 rout = 2000+2*i;
975 sout = echo_can_update(ctx, rout, sin);
976 update_levels(rin, sin, sout, sgen);
977 write_log_files(rout, sin);
978 }
979 dump_h();
980 }
981
982 /* Test 1 - Steady state residual and returned echo level test */
983 /* This functionality has been merged with test 2 in newer versions of G.168,
984 so test 1 no longer exists. */
985
986 /* Test 2 - Convergence and steady state residual and returned echo level test */
987
988 /*
989 NOTE: This test is only partially implemented, only the conidtion after
990 1s is tested and I am still not sure if LSout == Lres in the part
991 of the test after 1s.
992 */
993
994 if (!strcasecmp(argv[1], "2aa")) {
995
996 print_title("Performing test 2A(a) - Convergence with NLP enabled\n");
997 reset_all();
998 echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION | ECHO_CAN_USE_NLP);
999
1000 /* initial zero input as reqd by G168 */
1001
1002 mute_Rin();
1003 run_test(200, MSEC);
1004 unmute_Rin();
1005
1006 /* Now test convergence */
1007
1008 run_test(1, SEC);
1009 reset_meter_peaks();
1010 install_test_callback(test_2a);
1011 run_test(10, SEC);
1012
1013 print_results();
1014 }
1015
1016 #ifdef OTHER_TESTS
1017 if ((test_list & PERFORM_TEST_2B))
1018 {
1019 printf("Performing test 2B - Re-convergence with NLP disabled\n");
1020
1021 /* Test 2B - Re-convergence with NLP disabled */
1022
1023 echo_can_flush(ctx);
1024 echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
1025
1026 /* Converge a canceller */
1027
1028 signal_restart(&local_css);
1029 for (i = 0; i < 800*2; i++)
1030 {
1031 clean = echo_can_update(ctx, 0, 0);
1032 put_residue(clean);
1033 }
1034
1035 for (i = 0; i < SAMPLE_RATE*5; i++)
1036 {
1037 tx = signal_amp(&local_css);
1038 channel_model(&tx, &rx, tx, 0);
1039 clean = echo_can_update(ctx, tx, rx);
1040 put_residue(clean);
1041 #if defined(ENABLE_GUI)
1042 if (use_gui)
1043 echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
1044 #endif
1045 }
1046 #if defined(ENABLE_GUI)
1047 if (use_gui)
1048 echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
1049 #endif
1050 }
1051 #endif
1052
1053 if (!strcasecmp(argv[1], "2ca")) {
1054 float SgenLeveldB;
1055
1056 print_title("Performing test 2C(a) - Convergence with background noise present\n");
1057 reset_all();
1058 echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION | ECHO_CAN_USE_NLP);
1059
1060 /* Converge canceller with background noise */
1061
1062 mute_Rin();
1063 run_test(200, MSEC);
1064 unmute_Rin();
1065
1066 SgenLeveldB = 20.0*log10(Rin_level) - 15.0;
1067 if (SgenLeveldB > -30.0) SgenLeveldB = -30.0;
1068 set_Sgen(HOTH, SgenLeveldB);
1069 run_test(1, SEC);
1070 maxHoth = maxLSgen;
1071
1072 /* After 1 second freeze adaption, switch off noise. */
1073
1074 mute_Rin();
1075 run_test(150, MSEC);
1076
1077 echo_can_adaption_mode(ctx, ECHO_CAN_USE_NLP);
1078 run_test(1, SEC);
1079
1080 unmute_Rin();
1081 set_Sgen(NONE, 0.0);
1082 run_test(500, MSEC);
1083
1084 /* now measure the echo */
1085
1086 reset_meter_peaks();
1087 maxLSgen = maxHoth; /* keep this peak for print out but reset the rest */
1088 install_test_callback(test_2c);
1089 set_Sgen(NONE, 0.0);
1090 run_test(5, SEC);
1091
1092 print_results();
1093 }
1094
1095 /* Test 3 - Performance under double talk conditions */
1096
1097 if (!strcasecmp(argv[1], "3a")) {
1098 print_title("Performing test 3A - Double talk test with low cancelled-end levels\n");
1099 reset_all();
1100
1101 echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
1102 set_Sgen(CSS, -15.0 + 20.0*log10(Rin_level));
1103 run_test(5, SEC);
1104 tmp = maxLSgen;
1105
1106 /* now freeze adaption */
1107
1108 echo_can_adaption_mode(ctx, 0);
1109 set_Sgen(NONE, 0.0);
1110 run_test(500, MSEC);
1111
1112 /* Now measure the echo */
1113
1114 reset_meter_peaks();
1115 maxLSgen = tmp;
1116 install_test_callback(test_3a);
1117 run_test(5, SEC);
1118
1119 print_results();
1120 }
1121
1122 if (!strcasecmp(argv[1], "3ba")) {
1123 float fig11;
1124
1125 print_title("Performing test 3B(a) - Double talk stability test with high cancelled-end levels\n");
1126 reset_all();
1127
1128 echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
1129 run_test(5, SEC);
1130
1131 /* Apply double talk */
1132
1133 set_Sgen(CSS, 20.0*log10(Sgen_level));
1134 run_test(5, SEC);
1135 tmp = maxLSgen;
1136
1137 /* freeze adaption and measure echo */
1138
1139 mute_Rin();
1140 run_test(150, MSEC);
1141
1142 echo_can_adaption_mode(ctx, 0);
1143 run_test(1, SEC);
1144
1145 unmute_Rin();
1146 set_Sgen(NONE, 0.0);
1147 run_test(500, MSEC);
1148
1149 /* Now measure the echo */
1150
1151 fig11 = (25.0/30.0)*maxLRin - 30.0; /* pass/fail based on clean level @ tx peak */
1152 threshold = fig11 + 10.0;
1153 reset_meter_peaks();
1154 maxLSgen = tmp;
1155 install_test_callback(test_3b);
1156 run_test(5, SEC);
1157
1158 print_results();
1159 }
1160
1161 if (!strcasecmp(argv[1], "3bb")) {
1162 float fig11;
1163
1164 print_title("Performing test 3B(b) - Double talk stability test with low cancelled-end levels\n");
1165 reset_all();
1166
1167 echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
1168 run_test(5, SEC);
1169
1170 /* Apply double talk */
1171
1172 set_Sgen(CSS, 20.0*log10(Rin_level) - 20.0*log10(X_level));
1173 run_test(5, SEC);
1174 tmp = maxLSgen;
1175
1176 /* freeze adaption and measure echo */
1177
1178 mute_Rin();
1179 run_test(150, MSEC);
1180
1181 echo_can_adaption_mode(ctx, 0);
1182 run_test(1, SEC);
1183
1184 unmute_Rin();
1185 set_Sgen(NONE, 0.0);
1186 run_test(500, MSEC);
1187
1188 /* Now measure the echo */
1189
1190 fig11 = (25.0/30.0)*maxLRin - 30.0; /* pass/fail based on clean level @ tx peak */
1191 threshold = fig11 + 3.0;
1192 reset_meter_peaks();
1193 maxLSgen = tmp;
1194 install_test_callback(test_3b);
1195 run_test(5, SEC);
1196
1197 print_results();
1198 }
1199
1200 if (!strcasecmp(argv[1], "3c")) {
1201 print_title("Performing test 3C - Double talk test under simulated conversation\n");
1202 reset_all();
1203
1204 /* t1 (5.6s) - double talk */
1205
1206 echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION | ECHO_CAN_USE_NLP);
1207 set_Sgen(CSS, Sgen_leveldB);
1208 run_test(5600, MSEC);
1209
1210 /* t2 (1.4s) - to pass Sout <= Sgen */
1211
1212 set_Sgen(NONE, 0.0);
1213 install_test_callback(test_3c_t2);
1214 run_test(1400, MSEC);
1215
1216 /* t3 - (5s) - single talk to converge e/c */
1217
1218 run_test(5000, MSEC);
1219
1220 /* t4 - (5.6s) - double talk again */
1221
1222 install_test_callback(test_3c_t4t5);
1223 set_Sgen(CSS, Sgen_leveldB);
1224 run_test(5600, MSEC);
1225
1226 /* t5 - (5.6s) - near end single talk */
1227
1228 mute_Rin();
1229 run_test(5600, MSEC);
1230
1231 print_results();
1232 }
1233
1234 #ifdef OTHER_TESTS
1235 if ((test_list & PERFORM_TEST_4))
1236 {
1237 printf("Performing test 4 - Leak rate test\n");
1238 /* Test 4 - Leak rate test */
1239 echo_can_flush(ctx);
1240 echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
1241 /* Converge a canceller */
1242 signal_restart(&local_css);
1243 for (i = 0; i < SAMPLE_RATE*5; i++)
1244 {
1245 tx = signal_amp(&local_css);
1246 channel_model(&tx, &rx, tx, 0);
1247 clean = echo_can_update(ctx, tx, rx);
1248 put_residue(clean);
1249 }
1250 /* Put 2 minutes of silence through it */
1251 for (i = 0; i < SAMPLE_RATE*120; i++)
1252 {
1253 clean = echo_can_update(ctx, 0, 0);
1254 put_residue(clean);
1255 }
1256 /* Now freeze it, and check if it is still well adapted. */
1257 echo_can_adaption_mode(ctx, 0);
1258 for (i = 0; i < SAMPLE_RATE*5; i++)
1259 {
1260 tx = signal_amp(&local_css);
1261 channel_model(&tx, &rx, tx, 0);
1262 clean = echo_can_update(ctx, tx, rx);
1263 put_residue(clean);
1264 }
1265 echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
1266 #if defined(ENABLE_GUI)
1267 if (use_gui)
1268 echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
1269 #endif
1270 }
1271
1272 if ((test_list & PERFORM_TEST_5))
1273 {
1274 printf("Performing test 5 - Infinite return loss convergence test\n");
1275 /* Test 5 - Infinite return loss convergence test */
1276 echo_can_flush(ctx);
1277 echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
1278 /* Converge the canceller */
1279 signal_restart(&local_css);
1280 for (i = 0; i < SAMPLE_RATE*5; i++)
1281 {
1282 tx = signal_amp(&local_css);
1283 channel_model(&tx, &rx, tx, 0);
1284 clean = echo_can_update(ctx, tx, rx);
1285 put_residue(clean);
1286 }
1287 /* Now stop echoing, and see we don't do anything unpleasant as the
1288 echo path is open looped. */
1289 for (i = 0; i < SAMPLE_RATE*5; i++)
1290 {
1291 tx = signal_amp(&local_css);
1292 rx = 0;
1293 tx = codec_munge(tx);
1294 clean = echo_can_update(ctx, tx, rx);
1295 put_residue(clean);
1296 }
1297 #if defined(ENABLE_GUI)
1298 if (use_gui)
1299 echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
1300 #endif
1301 }
1302
1303 #endif
1304
1305 if (!strcasecmp(argv[1], "6"))
1306 {
1307 int k;
1308 float fig11;
1309
1310 printf("Performing test 6 - Non-divergence on narrow-band signals\n");
1311
1312 reset_all();
1313 echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
1314 run_test(5, SEC);
1315
1316 /* Now put 5s bursts of a list of tones through the converged canceller, and check
1317 that nothing unpleasant happens. */
1318
1319 for (k = 0; tones_6_4_2_7[k][0]; k++)
1320 {
1321 tone_gen_descriptor_t tone_desc;
1322
1323 /* 5 secs of each tone */
1324
1325 echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
1326 set_Rin(TONE, 20.0*log10(Rin_level)); /* level actually set by next func */
1327 make_tone_gen_descriptor(&tone_desc,
1328 tones_6_4_2_7[k][0],
1329 -11,
1330 tones_6_4_2_7[k][1],
1331 -9,
1332 1,
1333 0,
1334 0,
1335 0,
1336 1);
1337 tone_gen_init(&rin_tone_state, &tone_desc);
1338 run_test(5, SEC);
1339 }
1340
1341 /* disable adaption, back to speech */
1342
1343 echo_can_adaption_mode(ctx, 0);
1344 set_Rin(CSS, 20.0*log10(Rin_level));
1345 run_test(1, SEC);
1346
1347 /* now test convergence as per test 2 fig 11 */
1348
1349 fig11 = (25.0/30.0)*maxLRin - 30.0; /* pass/fail based on clean level @ tx peak */
1350 threshold = fig11 + 10.0;
1351 reset_meter_peaks();
1352 install_test_callback(test_3b);
1353 run_test(5, SEC);
1354
1355 print_results();
1356 }
1357
1358 #ifdef OTHER_TESTS
1359
1360 if ((test_list & PERFORM_TEST_7))
1361 {
1362 printf("Performing test 7 - Stability\n");
1363 /* Test 7 - Stability */
1364 /* Put tones through an unconverged canceller, and check nothing unpleasant
1365 happens. */
1366 echo_can_flush(ctx);
1367 echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
1368 make_tone_gen_descriptor(&tone_desc,
1369 tones_6_4_2_7[0][0],
1370 -11,
1371 tones_6_4_2_7[0][1],
1372 -9,
1373 1,
1374 0,
1375 0,
1376 0,
1377 1);
1378 tone_gen_init(&tone_state, &tone_desc);
1379 j = 0;
1380 for (i = 0; i < 120; i++)
1381 {
1382 local_max = tone_gen(&tone_state, local_sound, SAMPLE_RATE);
1383 for (j = 0; j < SAMPLE_RATE; j++)
1384 {
1385 tx = local_sound[j];
1386 channel_model(&tx, &rx, tx, 0);
1387 clean = echo_can_update(ctx, tx, rx);
1388 put_residue(clean);
1389 }
1390 #if defined(ENABLE_GUI)
1391 if (use_gui)
1392 {
1393 echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
1394 echo_can_monitor_update_display();
1395 usleep(100000);
1396 }
1397 #endif
1398 }
1399 #if defined(ENABLE_GUI)
1400 if (use_gui)
1401 echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
1402 #endif
1403 }
1404
1405 if ((test_list & PERFORM_TEST_8))
1406 {
1407 printf("Performing test 8 - Non-convergence on No 5, 6, and 7 in-band signalling\n");
1408 /* Test 8 - Non-convergence on No 5, 6, and 7 in-band signalling */
1409 fprintf(stderr, "Test 8 not yet implemented\n");
1410 }
1411 #endif
1412
1413 if (!strcasecmp(argv[1], "9"))
1414 {
1415 printf("Performing test 9 - Comfort noise test\n");
1416
1417 echo_can_flush(ctx);
1418 echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION
1419 | ECHO_CAN_USE_NLP
1420 | ECHO_CAN_USE_CNG);
1421
1422 /* Test 9 Part 1 - matching */
1423
1424 set_Sgen(HOTH, -45.0);
1425 mute_Rin();
1426 run_test(5, SEC); /* should be 30s but I wanted to speed up sim */
1427 set_Rin(HOTH, -10.0);
1428 run_test(2, SEC);
1429
1430 reset_meter_peaks();
1431 install_test_callback(test_9);
1432 run_test(700, MSEC);
1433
1434 /* Test 9 Part 2 - adjustment down */
1435
1436 install_test_callback(NULL);
1437 set_Sgen(HOTH, -55.0);
1438 mute_Rin();
1439 run_test(5, SEC); /* should be 10s but I wanted to speed up sim */
1440 set_Rin(HOTH, -10.0);
1441 run_test(2, SEC);
1442
1443 reset_meter_peaks();
1444 install_test_callback(test_9);
1445 run_test(700, MSEC);
1446
1447 /* Test 9 Part 3 - adjustment up */
1448
1449 install_test_callback(NULL);
1450 set_Sgen(HOTH, -45.0);
1451 mute_Rin();
1452 run_test(5, SEC); /* should be 10s but I wanted to speed up sim */
1453 set_Rin(HOTH, -10.0);
1454 run_test(2, SEC);
1455
1456 reset_meter_peaks();
1457 install_test_callback(test_9);
1458 run_test(700, MSEC);
1459
1460 print_results();
1461 }
1462
1463 #ifdef OTHER_TESTS
1464 /* Test 10 - FAX test during call establishment phase */
1465 if ((test_list & PERFORM_TEST_10A))
1466 {
1467 printf("Performing test 10A - Canceller operation on the calling station side\n");
1468 /* Test 10A - Canceller operation on the calling station side */
1469 fprintf(stderr, "Test 10A not yet implemented\n");
1470 }
1471
1472 if ((test_list & PERFORM_TEST_10B))
1473 {
1474 printf("Performing test 10B - Canceller operation on the called station side\n");
1475 /* Test 10B - Canceller operation on the called station side */
1476 fprintf(stderr, "Test 10B not yet implemented\n");
1477 }
1478
1479 if ((test_list & PERFORM_TEST_10C))
1480 {
1481 printf("Performing test 10C - Canceller operation on the calling station side during page\n"
1482 "transmission and page breaks (for further study)\n");
1483 /* Test 10C - Canceller operation on the calling station side during page
1484 transmission and page breaks (for further study) */
1485 fprintf(stderr, "Test 10C not yet implemented\n");
1486 }
1487
1488 if ((test_list & PERFORM_TEST_11))
1489 {
1490 printf("Performing test 11 - Tandem echo canceller test (for further study)\n");
1491 /* Test 11 - Tandem echo canceller test (for further study) */
1492 fprintf(stderr, "Test 11 not yet implemented\n");
1493 }
1494
1495 if ((test_list & PERFORM_TEST_12))
1496 {
1497 printf("Performing test 12 - Residual acoustic echo test (for further study)\n");
1498 /* Test 12 - Residual acoustic echo test (for further study) */
1499 fprintf(stderr, "Test 12 not yet implemented\n");
1500 }
1501
1502 if ((test_list & PERFORM_TEST_13))
1503 {
1504 printf("Performing test 13 - Performance with ITU-T low-bit rate coders in echo path (Optional, under study)\n");
1505 /* Test 13 - Performance with ITU-T low-bit rate coders in echo path
1506 (Optional, under study) */
1507 fprintf(stderr, "Test 13 not yet implemented\n");
1508 }
1509
1510 if ((test_list & PERFORM_TEST_14))
1511 {
1512 printf("Performing test 14 - Performance with V-series low-speed data modems\n");
1513 /* Test 14 - Performance with V-series low-speed data modems */
1514 fprintf(stderr, "Test 14 not yet implemented\n");
1515 }
1516
1517 if ((test_list & PERFORM_TEST_15))
1518 {
1519 printf("Performing test 15 - PCM offset test (Optional)\n");
1520 /* Test 15 - PCM offset test (Optional) */
1521 fprintf(stderr, "Test 15 not yet implemented\n");
1522 }
1523
1524 echo_can_free(ctx);
1525
1526 signal_free(&local_css);
1527 signal_free(&far_css);
1528
1529 if (afCloseFile(resulthandle) != 0)
1530 {
1531 fprintf(stderr, " Cannot close speech file '%s'\n", "result_sound.wav");
1532 exit(2);
1533 }
1534 if (afCloseFile(residuehandle) != 0)
1535 {
1536 fprintf(stderr, " Cannot close speech file '%s'\n", "residue_sound.wav");
1537 exit(2);
1538 }
1539 afFreeFileSetup(filesetup);
1540 afFreeFileSetup(filesetup2);
1541
1542 #if defined(XYZZY)
1543 for (j = 0; j < ctx->taps; j++)
1544 {
1545 for (i = 0; i < coeff_index; i++)
1546 fprintf(stderr, "%d ", coeffs[i][j]);
1547 fprintf(stderr, "\n");
1548 }
1549 #endif
1550 #endif
1551 if (verbose == TRUE)
1552 printf("Run time %lds\n", time(NULL) - now);
1553
1554 #if defined(ENABLE_GUI)
1555 if (use_gui)
1556 echo_can_monitor_wait_to_end();
1557 #endif
1558
1559
1560 fclose(fdump);
1561 fclose(flevel);
1562
1563 return 0;
1564 }
1565 /*- End of function --------------------------------------------------------*/
1566 /*- End of file ------------------------------------------------------------*/

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