comparison spandsp-0.0.3/spandsp-0.0.3/tests/v22bis_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 * 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.37 2006/11/19 14:07:27 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 #ifdef 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 <inttypes.h>
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <fcntl.h>
52 #include <string.h>
53 #if defined(HAVE_TGMATH_H)
54 #include <tgmath.h>
55 #endif
56 #if defined(HAVE_MATH_H)
57 #include <math.h>
58 #endif
59 #include <assert.h>
60 #include <audiofile.h>
61 #include <tiffio.h>
62
63 #include "spandsp.h"
64 #include "test_utils.h"
65 #include "line_model.h"
66 #if defined(ENABLE_GUI)
67 #include "modem_monitor.h"
68 #endif
69
70 #define BLOCK_LEN 160
71
72 #define IN_FILE_NAME "v22bis_samp.wav"
73 #define OUT_FILE_NAME "v22bis.wav"
74
75 int in_bit = 0;
76 int out_bit = 0;
77
78 int in_bit_no = 0;
79 int out_bit_no = 0;
80
81 uint8_t tx_buf[1000];
82 int rx_ptr = 0;
83 int tx_ptr = 0;
84
85 int rx_bits = 0;
86 int rx_bad_bits = 0;
87
88 int use_gui = FALSE;
89
90 both_ways_line_model_state_t *model;
91
92 v22bis_state_t caller;
93 v22bis_state_t answerer;
94
95 struct qam_report_control_s
96 {
97 v22bis_state_t *s;
98 #if defined(ENABLE_GUI)
99 qam_monitor_t *qam_monitor;
100 #endif
101 float smooth_power;
102 int symbol_no;
103 };
104
105 struct qam_report_control_s qam_caller;
106 struct qam_report_control_s qam_answerer;
107
108 static void v22bis_putbit(void *user_data, int bit)
109 {
110 v22bis_state_t *s;
111 int i;
112 int len;
113 complexf_t *coeffs;
114
115 s = (v22bis_state_t *) user_data;
116 if (bit < 0)
117 {
118 /* Special conditions */
119 switch (bit)
120 {
121 case PUTBIT_TRAINING_FAILED:
122 printf("Training failed\n");
123 break;
124 case PUTBIT_TRAINING_SUCCEEDED:
125 printf("Training succeeded\n");
126 len = v22bis_rx_equalizer_state(s, &coeffs);
127 printf("Equalizer:\n");
128 for (i = 0; i < len; i++)
129 printf("%3d (%15.5f, %15.5f) -> %15.5f\n", i, coeffs[i].re, coeffs[i].im, powerf(&coeffs[i]));
130 break;
131 case PUTBIT_CARRIER_UP:
132 printf("Carrier up\n");
133 break;
134 case PUTBIT_CARRIER_DOWN:
135 printf("Carrier down\n");
136 break;
137 default:
138 printf("Eh!\n");
139 break;
140 }
141 return;
142 }
143
144 if (bit != tx_buf[rx_ptr])
145 {
146 printf("Rx bit %d - %d\n", rx_bits, bit);
147 rx_bad_bits++;
148 }
149 rx_ptr++;
150 if (rx_ptr > 1000)
151 rx_ptr = 0;
152 rx_bits++;
153 if ((rx_bits % 100000) == 0)
154 {
155 printf("%d bits received, %d bad bits\r", rx_bits, rx_bad_bits);
156 fflush(stdout);
157 }
158 }
159 /*- End of function --------------------------------------------------------*/
160
161 static int v22bis_getbit(void *user_data)
162 {
163 int bit;
164 static int tx_bits = 0;
165
166 bit = rand() & 1;
167 tx_buf[tx_ptr++] = bit;
168 if (tx_ptr > 1000)
169 tx_ptr = 0;
170 //printf("Tx bit %d\n", bit);
171 if (++tx_bits > 100000)
172 {
173 tx_bits = 0;
174 bit = 2;
175 }
176 return bit;
177 }
178 /*- End of function --------------------------------------------------------*/
179
180 static void qam_report(void *user_data, const complexf_t *constel, const complexf_t *target, int symbol)
181 {
182 int i;
183 int len;
184 complexf_t *coeffs;
185 float fpower;
186 struct qam_report_control_s *s;
187
188 s = (struct qam_report_control_s *) user_data;
189 if (constel)
190 {
191 #if defined(ENABLE_GUI)
192 if (use_gui)
193 {
194 qam_monitor_update_constel(s->qam_monitor, constel);
195 qam_monitor_update_carrier_tracking(s->qam_monitor, v22bis_rx_carrier_frequency(s->s));
196 qam_monitor_update_symbol_tracking(s->qam_monitor, v22bis_rx_symbol_timing_correction(s->s));
197 }
198 #endif
199 fpower = (constel->re - target->re)*(constel->re - target->re)
200 + (constel->im - target->im)*(constel->im - target->im);
201 s->smooth_power = 0.95*s->smooth_power + 0.05*fpower;
202 printf("%8d [%8.4f, %8.4f] [%8.4f, %8.4f] %8.4f %8.4f\n", s->symbol_no, constel->re, constel->im, target->re, target->im, fpower, s->smooth_power);
203 s->symbol_no++;
204 }
205 else
206 {
207 printf("Gardner step %d\n", symbol);
208 len = v22bis_rx_equalizer_state(s->s, &coeffs);
209 printf("Equalizer A:\n");
210 for (i = 0; i < len; i++)
211 printf("%3d (%15.5f, %15.5f) -> %15.5f\n", i, coeffs[i].re, coeffs[i].im, powerf(&coeffs[i]));
212 #if defined(ENABLE_GUI)
213 if (use_gui)
214 qam_monitor_update_equalizer(s->qam_monitor, coeffs, len);
215 #endif
216 }
217 }
218 /*- End of function --------------------------------------------------------*/
219
220 int main(int argc, char *argv[])
221 {
222 int16_t caller_amp[BLOCK_LEN];
223 int16_t answerer_amp[BLOCK_LEN];
224 int16_t caller_model_amp[BLOCK_LEN];
225 int16_t answerer_model_amp[BLOCK_LEN];
226 int16_t out_amp[2*BLOCK_LEN];
227 AFfilehandle outhandle;
228 AFfilesetup filesetup;
229 int outframes;
230 int samples;
231 int i;
232 int test_bps;
233 int line_model_no;
234 int bits_per_test;
235 int noise_level;
236 int signal_level;
237 int log_audio;
238 int channel_codec;
239
240 channel_codec = MUNGE_CODEC_NONE;
241 test_bps = 2400;
242 line_model_no = 0;
243 noise_level = -70;
244 signal_level = -13;
245 bits_per_test = 50000;
246 log_audio = FALSE;
247 for (i = 1; i < argc; i++)
248 {
249 if (strcmp(argv[i], "-b") == 0)
250 {
251 bits_per_test = atoi(argv[++i]);
252 continue;
253 }
254 if (strcmp(argv[i], "-c") == 0)
255 {
256 channel_codec = atoi(argv[++i]);
257 continue;
258 }
259 if (strcmp(argv[i], "-g") == 0)
260 {
261 use_gui = TRUE;
262 continue;
263 }
264 if (strcmp(argv[i], "-m") == 0)
265 {
266 log_audio = TRUE;
267 continue;
268 }
269 if (strcmp(argv[i], "-m") == 0)
270 {
271 line_model_no = atoi(argv[++i]);
272 continue;
273 }
274 if (strcmp(argv[i], "-n") == 0)
275 {
276 noise_level = atoi(argv[++i]);
277 continue;
278 }
279 if (strcmp(argv[i], "-s") == 0)
280 {
281 signal_level = atoi(argv[++i]);
282 continue;
283 }
284 if (strcmp(argv[i], "2400") == 0)
285 test_bps = 2400;
286 else if (strcmp(argv[i], "1200") == 0)
287 test_bps = 1200;
288 else
289 {
290 fprintf(stderr, "Invalid bit rate\n");
291 exit(2);
292 }
293 }
294 filesetup = AF_NULL_FILESETUP;
295 outhandle = AF_NULL_FILEHANDLE;
296 if (log_audio)
297 {
298 if ((filesetup = afNewFileSetup()) == AF_NULL_FILESETUP)
299 {
300 fprintf(stderr, " Failed to create file setup\n");
301 exit(2);
302 }
303 afInitSampleFormat(filesetup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16);
304 afInitRate(filesetup, AF_DEFAULT_TRACK, (float) SAMPLE_RATE);
305 afInitFileFormat(filesetup, AF_FILE_WAVE);
306 afInitChannels(filesetup, AF_DEFAULT_TRACK, 2);
307
308 if ((outhandle = afOpenFile(OUT_FILE_NAME, "w", filesetup)) == AF_NULL_FILEHANDLE)
309 {
310 fprintf(stderr, " Cannot create wave file '%s'\n", OUT_FILE_NAME);
311 exit(2);
312 }
313 }
314 v22bis_init(&caller, test_bps, 2, TRUE, v22bis_getbit, v22bis_putbit, &caller);
315 v22bis_tx_power(&caller, signal_level);
316 /* Move the carrier off a bit */
317 caller.tx_carrier_phase_rate = dds_phase_ratef(1207.0);
318 v22bis_init(&answerer, test_bps, 2, FALSE, v22bis_getbit, v22bis_putbit, &answerer);
319 v22bis_tx_power(&answerer, signal_level);
320 answerer.tx_carrier_phase_rate = dds_phase_ratef(2407.0);
321 v22bis_rx_set_qam_report_handler(&caller, qam_report, (void *) &qam_caller);
322 v22bis_rx_set_qam_report_handler(&answerer, qam_report, (void *) &qam_answerer);
323 span_log_set_level(&caller.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW);
324 span_log_set_tag(&caller.logging, "caller");
325 span_log_set_level(&answerer.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW);
326 span_log_set_tag(&answerer.logging, "answerer");
327
328 qam_caller.s = &caller;
329 qam_caller.smooth_power = 0.0;
330 qam_caller.symbol_no = 0;
331
332 qam_answerer.s = &answerer;
333 qam_answerer.smooth_power = 0.0;
334 qam_answerer.symbol_no = 0;
335
336 #if defined(ENABLE_GUI)
337 if (use_gui)
338 {
339 qam_caller.qam_monitor = qam_monitor_init(6.0, "Calling modem");
340 qam_answerer.qam_monitor = qam_monitor_init(6.0, "Answering modem");
341 }
342 #endif
343
344 if ((model = both_ways_line_model_init(line_model_no, (float) noise_level, line_model_no, (float) noise_level, channel_codec)) == NULL)
345 {
346 fprintf(stderr, " Failed to create line model\n");
347 exit(2);
348 }
349 for (;;)
350 {
351 samples = v22bis_tx(&caller, caller_amp, BLOCK_LEN);
352 #if defined(ENABLE_GUI)
353 if (use_gui)
354 qam_monitor_update_audio_level(qam_caller.qam_monitor, caller_amp, samples);
355 #endif
356 if (samples == 0)
357 {
358 printf("Restarting on zero output\n");
359 v22bis_restart(&caller, test_bps);
360 rx_ptr = 0;
361 tx_ptr = 0;
362 }
363
364 samples = v22bis_tx(&answerer, answerer_amp, BLOCK_LEN);
365 #if defined(ENABLE_GUI)
366 if (use_gui)
367 qam_monitor_update_audio_level(qam_answerer.qam_monitor, answerer_amp, samples);
368 #endif
369 if (samples == 0)
370 {
371 printf("Restarting on zero output\n");
372 v22bis_restart(&answerer, test_bps);
373 rx_ptr = 0;
374 tx_ptr = 0;
375 }
376
377 both_ways_line_model(model,
378 caller_model_amp,
379 caller_amp,
380 answerer_model_amp,
381 answerer_amp,
382 samples);
383
384 v22bis_rx(&answerer, caller_model_amp, samples);
385 for (i = 0; i < samples; i++)
386 out_amp[2*i] = caller_model_amp[i];
387 for ( ; i < BLOCK_LEN; i++)
388 out_amp[2*i] = 0;
389
390 v22bis_rx(&caller, answerer_model_amp, samples);
391 for (i = 0; i < samples; i++)
392 out_amp[2*i + 1] = answerer_model_amp[i];
393 for ( ; i < BLOCK_LEN; i++)
394 out_amp[2*i + 1] = 0;
395
396 if (log_audio)
397 {
398 outframes = afWriteFrames(outhandle,
399 AF_DEFAULT_TRACK,
400 out_amp,
401 BLOCK_LEN);
402 if (outframes != BLOCK_LEN)
403 {
404 fprintf(stderr, " Error writing wave file\n");
405 exit(2);
406 }
407 }
408 }
409 if (log_audio)
410 {
411 if (afCloseFile(outhandle) != 0)
412 {
413 fprintf(stderr, " Cannot close wave file '%s'\n", OUT_FILE_NAME);
414 exit(2);
415 }
416 afFreeFileSetup(filesetup);
417 }
418 return 0;
419 }
420 /*- End of function --------------------------------------------------------*/
421 /*- End of file ------------------------------------------------------------*/

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