comparison spandsp-0.0.6pre17/tests/v22bis_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 * v22bis_tests.c
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2004 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: v22bis_tests.c,v 1.63 2009/07/09 13:52:09 steveu Exp $
26 */
27
28 /*! \page v22bis_tests_page V.22bis modem tests
29 \section v22bis_tests_page_sec_1 What does it do?
30 These tests connect two V.22bis modems back to back, through a telephone line
31 model. BER testing is then used to evaluate performance under various line
32 conditions.
33
34 If the appropriate GUI environment exists, the tests are built such that a visual
35 display of modem status is maintained.
36
37 \section v22bis_tests_page_sec_2 How is it used?
38 */
39
40 #if defined(HAVE_CONFIG_H)
41 #include "config.h"
42 #endif
43
44 #if defined(HAVE_FL_FL_H) && defined(HAVE_FL_FL_CARTESIAN_H) && defined(HAVE_FL_FL_AUDIO_METER_H)
45 #define ENABLE_GUI
46 #endif
47
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <fcntl.h>
51 #include <unistd.h>
52 #include <string.h>
53 #include <sndfile.h>
54
55 #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
56 #include "spandsp.h"
57 #include "spandsp-sim.h"
58
59 #if defined(ENABLE_GUI)
60 #include "modem_monitor.h"
61 #endif
62
63 #define BLOCK_LEN 160
64
65 #define OUT_FILE_NAME "v22bis.wav"
66
67 char *decode_test_file = NULL;
68 int use_gui = FALSE;
69
70 int rx_bits = 0;
71
72 both_ways_line_model_state_t *model;
73
74 typedef struct
75 {
76 v22bis_state_t *v22bis;
77 bert_state_t bert_tx;
78 bert_state_t bert_rx;
79 bert_results_t latest_results;
80 #if defined(ENABLE_GUI)
81 qam_monitor_t *qam_monitor;
82 #endif
83 float smooth_power;
84 int symbol_no;
85 } endpoint_t;
86
87 endpoint_t endpoint[2];
88
89 static void reporter(void *user_data, int reason, bert_results_t *results)
90 {
91 endpoint_t *s;
92
93 s = (endpoint_t *) user_data;
94 switch (reason)
95 {
96 case BERT_REPORT_REGULAR:
97 fprintf(stderr, "V.22bis rx %p BERT report regular - %d bits, %d bad bits, %d resyncs\n",
98 user_data,
99 results->total_bits,
100 results->bad_bits,
101 results->resyncs);
102 memcpy(&s->latest_results, results, sizeof(s->latest_results));
103 break;
104 default:
105 fprintf(stderr,
106 "V.22bis rx %p BERT report %s\n",
107 user_data,
108 bert_event_to_str(reason));
109 break;
110 }
111 }
112 /*- End of function --------------------------------------------------------*/
113
114 static void v22bis_putbit(void *user_data, int bit)
115 {
116 endpoint_t *s;
117 int i;
118 int len;
119 int bit_rate;
120 complexf_t *coeffs;
121
122 s = (endpoint_t *) user_data;
123 if (bit < 0)
124 {
125 /* Special conditions */
126 printf("V.22bis rx %p status is %s (%d)\n", user_data, signal_status_to_str(bit), bit);
127 switch (bit)
128 {
129 case SIG_STATUS_TRAINING_SUCCEEDED:
130 bit_rate = v22bis_current_bit_rate(s->v22bis);
131 printf("Negotiated bit rate: %d\n", bit_rate);
132 len = v22bis_rx_equalizer_state(s->v22bis, &coeffs);
133 printf("Equalizer:\n");
134 for (i = 0; i < len; i++)
135 printf("%3d (%15.5f, %15.5f) -> %15.5f\n", i, coeffs[i].re, coeffs[i].im, powerf(&coeffs[i]));
136 break;
137 }
138 return;
139 }
140
141 if (decode_test_file)
142 printf("Rx bit %p-%d - %d\n", user_data, rx_bits++, bit);
143 else
144 bert_put_bit(&s->bert_rx, bit);
145 }
146 /*- End of function --------------------------------------------------------*/
147
148 static int v22bis_getbit(void *user_data)
149 {
150 endpoint_t *s;
151 int bit;
152
153 s = (endpoint_t *) user_data;
154 bit = bert_get_bit(&s->bert_tx);
155 return bit;
156 }
157 /*- End of function --------------------------------------------------------*/
158
159 static void qam_report(void *user_data, const complexf_t *constel, const complexf_t *target, int symbol)
160 {
161 int i;
162 int len;
163 complexf_t *coeffs;
164 float fpower;
165 endpoint_t *s;
166
167 s = (endpoint_t *) user_data;
168 if (constel)
169 {
170 #if defined(ENABLE_GUI)
171 if (use_gui)
172 {
173 qam_monitor_update_constel(s->qam_monitor, constel);
174 qam_monitor_update_carrier_tracking(s->qam_monitor, v22bis_rx_carrier_frequency(s->v22bis));
175 qam_monitor_update_symbol_tracking(s->qam_monitor, v22bis_rx_symbol_timing_correction(s->v22bis));
176 }
177 #endif
178 fpower = (constel->re - target->re)*(constel->re - target->re)
179 + (constel->im - target->im)*(constel->im - target->im);
180 s->smooth_power = 0.95f*s->smooth_power + 0.05f*fpower;
181
182 printf("%8d [%8.4f, %8.4f] [%8.4f, %8.4f] %2x %8.4f %8.4f %8.4f\n",
183 s->symbol_no,
184 constel->re,
185 constel->im,
186 target->re,
187 target->im,
188 symbol,
189 fpower,
190 s->smooth_power,
191 v22bis_rx_signal_power(s->v22bis));
192 s->symbol_no++;
193 }
194 else
195 {
196 printf("Gardner step %d\n", symbol);
197 len = v22bis_rx_equalizer_state(s->v22bis, &coeffs);
198 printf("Equalizer A:\n");
199 for (i = 0; i < len; i++)
200 printf("%3d (%15.5f, %15.5f) -> %15.5f\n", i, coeffs[i].re, coeffs[i].im, powerf(&coeffs[i]));
201 #if defined(ENABLE_GUI)
202 if (use_gui)
203 qam_monitor_update_equalizer(s->qam_monitor, coeffs, len);
204 #endif
205 }
206 }
207 /*- End of function --------------------------------------------------------*/
208
209 int main(int argc, char *argv[])
210 {
211 int16_t amp[2][BLOCK_LEN];
212 int16_t model_amp[2][BLOCK_LEN];
213 int16_t out_amp[2*BLOCK_LEN];
214 SNDFILE *inhandle;
215 SNDFILE *outhandle;
216 int outframes;
217 int samples;
218 int samples2;
219 int i;
220 int j;
221 int test_bps;
222 int line_model_no;
223 int bits_per_test;
224 int noise_level;
225 int signal_level;
226 int log_audio;
227 int channel_codec;
228 int opt;
229
230 channel_codec = MUNGE_CODEC_NONE;
231 test_bps = 2400;
232 line_model_no = 0;
233 decode_test_file = NULL;
234 noise_level = -70;
235 signal_level = -13;
236 bits_per_test = 50000;
237 log_audio = FALSE;
238 while ((opt = getopt(argc, argv, "b:B:c:d:glm:n:s:")) != -1)
239 {
240 switch (opt)
241 {
242 case 'b':
243 test_bps = atoi(optarg);
244 if (test_bps != 2400 && test_bps != 1200)
245 {
246 fprintf(stderr, "Invalid bit rate specified\n");
247 exit(2);
248 }
249 break;
250 case 'B':
251 bits_per_test = atoi(optarg);
252 break;
253 case 'c':
254 channel_codec = atoi(optarg);
255 break;
256 case 'd':
257 decode_test_file = optarg;
258 break;
259 case 'g':
260 #if defined(ENABLE_GUI)
261 use_gui = TRUE;
262 #else
263 fprintf(stderr, "Graphical monitoring not available\n");
264 exit(2);
265 #endif
266 break;
267 case 'l':
268 log_audio = TRUE;
269 break;
270 case 'm':
271 line_model_no = atoi(optarg);
272 break;
273 case 'n':
274 noise_level = atoi(optarg);
275 break;
276 case 's':
277 signal_level = atoi(optarg);
278 break;
279 default:
280 //usage();
281 exit(2);
282 break;
283 }
284 }
285 inhandle = NULL;
286 if (decode_test_file)
287 {
288 /* We will decode the audio from a file. */
289 if ((inhandle = sf_open_telephony_read(decode_test_file, 1)) == NULL)
290 {
291 fprintf(stderr, " Cannot open audio file '%s'\n", decode_test_file);
292 exit(2);
293 }
294 }
295
296 outhandle = NULL;
297 if (log_audio)
298 {
299 if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME, 2)) == NULL)
300 {
301 fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME);
302 exit(2);
303 }
304 }
305 memset(endpoint, 0, sizeof(endpoint));
306
307 for (i = 0; i < 2; i++)
308 {
309 endpoint[i].v22bis = v22bis_init(NULL, test_bps, V22BIS_GUARD_TONE_1800HZ, (i == 0), v22bis_getbit, &endpoint[i], v22bis_putbit, &endpoint[i]);
310 v22bis_tx_power(endpoint[i].v22bis, signal_level);
311 /* Move the carrier off a bit */
312 endpoint[i].v22bis->tx.carrier_phase_rate = dds_phase_ratef((i == 0) ? 1207.0f : 2407.0f);
313 v22bis_rx_set_qam_report_handler(endpoint[i].v22bis, qam_report, (void *) &endpoint[i]);
314 span_log_set_level(&endpoint[i].v22bis->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
315 span_log_set_tag(&endpoint[i].v22bis->logging, (i == 0) ? "caller" : "answerer");
316 endpoint[i].smooth_power = 0.0f;
317 endpoint[i].symbol_no = 0;
318 bert_init(&endpoint[i].bert_tx, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20);
319 bert_init(&endpoint[i].bert_rx, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20);
320 bert_set_report(&endpoint[i].bert_rx, 10000, reporter, &endpoint[i]);
321 }
322
323
324 #if defined(ENABLE_GUI)
325 if (use_gui)
326 {
327 endpoint[0].qam_monitor = qam_monitor_init(6.0f, "Calling modem");
328 endpoint[1].qam_monitor = qam_monitor_init(6.0f, "Answering modem");
329 }
330 #endif
331 if ((model = both_ways_line_model_init(line_model_no, (float) noise_level, line_model_no, (float) noise_level, channel_codec, 0)) == NULL)
332 {
333 fprintf(stderr, " Failed to create line model\n");
334 exit(2);
335 }
336 samples = 0;
337 for (;;)
338 {
339 for (i = 0; i < 2; i++)
340 {
341 samples = v22bis_tx(endpoint[i].v22bis, amp[i], BLOCK_LEN);
342 #if defined(ENABLE_GUI)
343 if (use_gui)
344 qam_monitor_update_audio_level(endpoint[i].qam_monitor, amp[i], samples);
345 #endif
346 if (samples == 0)
347 {
348 /* Note that we might get a few bad bits as the carrier shuts down. */
349 bert_result(&endpoint[i].bert_rx, &endpoint[i].latest_results);
350
351 bert_init(&endpoint[i].bert_tx, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20);
352 bert_init(&endpoint[i].bert_rx, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20);
353 bert_set_report(&endpoint[i].bert_rx, 10000, reporter, &endpoint[i]);
354
355 printf("Restarting on zero output\n");
356 v22bis_restart(endpoint[i].v22bis, test_bps);
357 }
358 }
359
360 #if 1
361 both_ways_line_model(model,
362 model_amp[0],
363 amp[0],
364 model_amp[1],
365 amp[1],
366 samples);
367 #else
368 vec_copyi16(model_amp[0], amp[0], samples);
369 vec_copyi16(model_amp[1], amp[1], samples);
370 #endif
371 if (decode_test_file)
372 {
373 samples2 = sf_readf_short(inhandle, model_amp[0], samples);
374 if (samples2 != samples)
375 break;
376 }
377 for (i = 0; i < 2; i++)
378 {
379 span_log_bump_samples(&endpoint[i].v22bis->logging, samples);
380 v22bis_rx(endpoint[i ^ 1].v22bis, model_amp[i], samples);
381 for (j = 0; j < samples; j++)
382 out_amp[2*j + i] = model_amp[i][j];
383 for ( ; j < BLOCK_LEN; j++)
384 out_amp[2*j + i] = 0;
385 }
386
387 if (log_audio)
388 {
389 outframes = sf_writef_short(outhandle, out_amp, BLOCK_LEN);
390 if (outframes != BLOCK_LEN)
391 {
392 fprintf(stderr, " Error writing audio file\n");
393 exit(2);
394 }
395 }
396 }
397 #if defined(ENABLE_GUI)
398 if (use_gui)
399 qam_wait_to_end(endpoint[0].qam_monitor);
400 #endif
401 if (decode_test_file)
402 {
403 if (sf_close(inhandle))
404 {
405 fprintf(stderr, " Cannot close audio file '%s'\n", decode_test_file);
406 exit(2);
407 }
408 }
409 if (log_audio)
410 {
411 if (sf_close(outhandle) != 0)
412 {
413 fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
414 exit(2);
415 }
416 }
417 return 0;
418 }
419 /*- End of function --------------------------------------------------------*/
420 /*- End of file ------------------------------------------------------------*/

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