Mercurial > hg > audiostuff
comparison spandsp-0.0.3/spandsp-0.0.3/tests/t31_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 * t31_tests.c - Tests for the T.31 modem. | |
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: t31_tests.c,v 1.42 2006/11/19 14:07:27 steveu Exp $ | |
26 */ | |
27 | |
28 /*! \file */ | |
29 | |
30 /*! \page t31_tests_page T.31 tests | |
31 \section t31_tests_page_sec_1 What does it do? | |
32 */ | |
33 | |
34 #ifdef HAVE_CONFIG_H | |
35 #include "config.h" | |
36 #endif | |
37 | |
38 #define _GNU_SOURCE | |
39 | |
40 #include <inttypes.h> | |
41 #include <stdlib.h> | |
42 #include <unistd.h> | |
43 #include <stdio.h> | |
44 #include <fcntl.h> | |
45 #include <string.h> | |
46 #if defined(HAVE_TGMATH_H) | |
47 #include <tgmath.h> | |
48 #endif | |
49 #if defined(HAVE_MATH_H) | |
50 #include <math.h> | |
51 #endif | |
52 #include <assert.h> | |
53 #include <audiofile.h> | |
54 #include <tiffio.h> | |
55 | |
56 #include "spandsp.h" | |
57 #include "spandsp/t30_fcf.h" | |
58 | |
59 #define INPUT_FILE_NAME "../itutests/fax/itu1.tif" | |
60 #define OUTPUT_FILE_NAME "t31.tif" | |
61 #define OUTPUT_WAVE_FILE_NAME "t31_tests.wav" | |
62 | |
63 #define DLE 0x10 | |
64 #define ETX 0x03 | |
65 #define SUB 0x1A | |
66 | |
67 #define MANUFACTURER "www.soft-switch.org" | |
68 | |
69 #define SAMPLES_PER_CHUNK 160 | |
70 | |
71 struct command_response_s | |
72 { | |
73 const char *command; | |
74 int len_command; | |
75 const char *response; | |
76 int len_response; | |
77 }; | |
78 | |
79 #define EXCHANGE(a,b) {a, sizeof(a) - 1, b, sizeof(b) - 1} | |
80 #define RESPONSE(b) {"", 0, b, sizeof(b) - 1} | |
81 #define FAST_RESPONSE(b) {NULL, -1, b, sizeof(b) - 1} | |
82 #define FAST_SEND(b) {(const char *) 1, -2, b, sizeof(b) - 1} | |
83 | |
84 static const struct command_response_s fax_send_test_seq[] = | |
85 { | |
86 EXCHANGE("ATE0\r", "ATE0\r\r\nOK\r\n"), | |
87 EXCHANGE("AT+FCLASS=1\r", "\r\nOK\r\n"), | |
88 EXCHANGE("ATD123456789\r", "\r\nCONNECT\r\n"), | |
89 //<NSF frame> AT+FRH=3 is implied when dialing in the AT+FCLASS=1 state | |
90 //RESPONSE("\xFF\x03\x10\x03"), | |
91 //RESPONSE("\r\nOK\r\n"), | |
92 //EXCHANGE("AT+FRH=3\r", "\r\nCONNECT\r\n"), | |
93 //<CSI frame data> | |
94 RESPONSE("\xFF\x03\x40\x31\x31\x31\x31\x31\x31\x31\x31\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x1e\x46\x10\x03"), | |
95 RESPONSE("\r\nOK\r\n"), | |
96 EXCHANGE("AT+FRH=3\r", "\r\nCONNECT\r\n"), | |
97 //<DIS frame data> | |
98 RESPONSE("\xFF\x13\x80\x00\xCE\xF8\x80\x80\x89\x80\x80\x80\x98\x80\x80\x80\x80\x80\x00\xFA\x72\x10\x03"), | |
99 RESPONSE("\r\nOK\r\n"), | |
100 //EXCHANGE("AT+FRH=3\r", "\r\nNO CARRIER\r\n"), | |
101 EXCHANGE("AT+FTH=3\r", "\r\nCONNECT\r\n"), | |
102 //<TSI frame data> | |
103 EXCHANGE("\xFF\x03\x43\x32\x32\x32\x32\x32\x32\x32\x32\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x10\x03", "\r\nCONNECT\r\n"), | |
104 //<DCS frame data> | |
105 EXCHANGE("\xFF\x13\x83\x01\xC6\x80\x80\x80\x80\x01\xFD\x13\x10\x03", "\r\nOK\r\n"), | |
106 //Do a wait for timed silence at this point, or there won't be one in the tests | |
107 EXCHANGE("AT+FRS=7\r", "\r\nOK\r\n"), | |
108 //EXCHANGE("AT+FTS=8;+FTM=96\r", "\r\nCONNECT\r\n"), | |
109 EXCHANGE("AT+FTS=8\r", "\r\nOK\r\n"), | |
110 EXCHANGE("AT+FTM=96\r", "\r\nCONNECT\r\n"), | |
111 //<TCF data pattern> | |
112 FAST_SEND("\r\nOK\r\n"), | |
113 EXCHANGE("AT+FRH=3\r", "\r\nCONNECT\r\n"), | |
114 //<CFR frame data> | |
115 RESPONSE("\xFF\x13\x84\xEA\x7D\x10\x03"), | |
116 RESPONSE("\r\nOK\r\n"), | |
117 EXCHANGE("AT+FTM=96\r", "\r\nCONNECT\r\n"), | |
118 //<page image data> | |
119 FAST_SEND("\r\nOK\r\n"), | |
120 //EXCHANGE("AT+FTS=8;+FTH=3\r", "\r\nCONNECT\r\n"), | |
121 EXCHANGE("AT+FTS=8\r", "\r\nOK\r\n"), | |
122 EXCHANGE("AT+FTH=3\r", "\r\nCONNECT\r\n"), | |
123 //<EOP frame data> | |
124 EXCHANGE("\xFF\x13\x2E\x10\x03", "\r\nOK\r\n"), | |
125 EXCHANGE("AT+FRH=3\r", "\r\nCONNECT\r\n"), | |
126 //<MCF frame data> | |
127 EXCHANGE("\xFF\x13\x8C\x10\x03", "\r\nOK\r\n"), | |
128 EXCHANGE("AT+FTH=3\r", "\r\nCONNECT\r\n"), | |
129 // <DCN frame data> | |
130 EXCHANGE("\xFF\x13\xFB\x10\x03", "\r\nOK\r\n"), | |
131 EXCHANGE("ATH0\r", "\r\nOK\r\n") | |
132 }; | |
133 | |
134 static const struct command_response_s fax_receive_test_seq[] = | |
135 { | |
136 EXCHANGE("ATE0\r", "ATE0\r\r\nOK\r\n"), | |
137 EXCHANGE("AT+FCLASS=1\r", "\r\nOK\r\n"), | |
138 RESPONSE("\r\nRING\r\n"), | |
139 EXCHANGE("ATA\r", "\r\nCONNECT\r\n"), | |
140 //<CSI frame data> | |
141 EXCHANGE("\xFF\x03\x40\x32\x32\x32\x32\x32\x32\x32\x32\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x10\x03", "\r\nCONNECT\r\n"), | |
142 //<DIS frame data> | |
143 EXCHANGE("\xFF\x13\x80\x01\xCE\xF4\x80\x80\x81\x80\x80\x80\x18\x10\x03", "\r\nOK\r\n"), | |
144 EXCHANGE("AT+FRH=3\r", "\r\nCONNECT\r\n"), | |
145 //<TSI frame data> | |
146 RESPONSE("\xFF\x03\x43\x31\x31\x31\x31\x31\x31\x31\x31\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\xAA\x1F\x10\x03"), | |
147 RESPONSE("\r\nOK\r\n"), | |
148 EXCHANGE("AT+FRH=3\r", "\r\nCONNECT\r\n"), | |
149 //<DCS frame data> | |
150 RESPONSE("\xFF\x13\x83\x00\xC6\xF0\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x00\xE4\x7E\x10\x03"), | |
151 RESPONSE("\r\nOK\r\n"), | |
152 EXCHANGE("AT+FRM=96\r", "\r\nCONNECT\r\n"), | |
153 //<TCF data> | |
154 FAST_RESPONSE(NULL), | |
155 RESPONSE("\r\nNO CARRIER\r\n"), | |
156 EXCHANGE("AT+FTH=3\r", "\r\nCONNECT\r\n"), | |
157 //<CFR frame data> | |
158 EXCHANGE("\xFF\x13\x84\x10\x03", "\r\nOK\r\n"), | |
159 EXCHANGE("AT+FRM=96\r", "\r\nCONNECT\r\n"), | |
160 //<page image data> | |
161 FAST_RESPONSE(NULL), | |
162 RESPONSE("\r\nNO CARRIER\r\n"), | |
163 EXCHANGE("AT+FRH=3\r", "\r\nCONNECT\r\n"), | |
164 //<EOP frame data> | |
165 RESPONSE("\xFF\x13\x2F\x33\x66\x10\x03"), | |
166 RESPONSE("\r\nOK\r\n"), | |
167 EXCHANGE("AT+FTH=3\r", "\r\nCONNECT\r\n"), | |
168 //<MCF frame data> | |
169 EXCHANGE("\xFF\x13\x8C\x10\x03", "\r\nOK\r\n"), | |
170 EXCHANGE("AT+FRH=3\r", "\r\nCONNECT\r\n"), | |
171 //<DCN frame data> | |
172 RESPONSE("\xFF\x13\xfb\x9a\xf6\x10\x03"), | |
173 RESPONSE("\r\nOK\r\n"), | |
174 EXCHANGE("ATH0\r", "\r\nOK\r\n") | |
175 }; | |
176 | |
177 char *decode_test_file = NULL; | |
178 int countdown = 0; | |
179 int command_response_test_step = -1; | |
180 char response_buf[1000]; | |
181 int response_buf_ptr = 0; | |
182 int answered = FALSE; | |
183 int kick = FALSE; | |
184 int dled = FALSE; | |
185 int done = FALSE; | |
186 | |
187 static const struct command_response_s *fax_test_seq; | |
188 | |
189 int test_seq_ptr = 0; | |
190 | |
191 t31_state_t t31_state; | |
192 | |
193 static void phase_b_handler(t30_state_t *s, void *user_data, int result) | |
194 { | |
195 int i; | |
196 | |
197 i = (intptr_t) user_data; | |
198 printf("Phase B handler on channel %d - (0x%X) %s\n", i, result, t30_frametype(result)); | |
199 } | |
200 /*- End of function --------------------------------------------------------*/ | |
201 | |
202 static void phase_d_handler(t30_state_t *s, void *user_data, int result) | |
203 { | |
204 int i; | |
205 t30_stats_t t; | |
206 char ident[21]; | |
207 | |
208 i = (intptr_t) user_data; | |
209 printf("Phase D handler on channel %d - (0x%X) %s\n", i, result, t30_frametype(result)); | |
210 t30_get_transfer_statistics(s, &t); | |
211 printf("Phase D: bit rate %d\n", t.bit_rate); | |
212 printf("Phase D: ECM %s\n", (t.error_correcting_mode) ? "on" : "off"); | |
213 printf("Phase D: pages transferred %d\n", t.pages_transferred); | |
214 printf("Phase D: image size %d x %d\n", t.width, t.length); | |
215 printf("Phase D: image resolution %d x %d\n", t.x_resolution, t.y_resolution); | |
216 printf("Phase D: bad rows %d\n", t.bad_rows); | |
217 printf("Phase D: longest bad row run %d\n", t.longest_bad_row_run); | |
218 printf("Phase D: coding method %d\n", t.encoding); | |
219 printf("Phase D: image size %d\n", t.image_size); | |
220 t30_get_local_ident(s, ident); | |
221 printf("Phase D: local ident '%s'\n", ident); | |
222 t30_get_far_ident(s, ident); | |
223 printf("Phase D: remote ident '%s'\n", ident); | |
224 } | |
225 /*- End of function --------------------------------------------------------*/ | |
226 | |
227 static void phase_e_handler(t30_state_t *s, void *user_data, int result) | |
228 { | |
229 int i; | |
230 | |
231 i = (intptr_t) user_data; | |
232 printf("Phase E handler on channel %d\n", i); | |
233 //exit(0); | |
234 } | |
235 /*- End of function --------------------------------------------------------*/ | |
236 | |
237 static int modem_call_control(t31_state_t *s, void *user_data, int op, const char *num) | |
238 { | |
239 switch (op) | |
240 { | |
241 case AT_MODEM_CONTROL_ANSWER: | |
242 printf("\nModem control - Answering\n"); | |
243 answered = TRUE; | |
244 break; | |
245 case AT_MODEM_CONTROL_CALL: | |
246 printf("\nModem control - Dialing '%s'\n", num); | |
247 t31_call_event(&t31_state, AT_CALL_EVENT_CONNECTED); | |
248 break; | |
249 case AT_MODEM_CONTROL_HANGUP: | |
250 printf("\nModem control - Hanging up\n"); | |
251 done = TRUE; | |
252 break; | |
253 case AT_MODEM_CONTROL_OFFHOOK: | |
254 printf("\nModem control - Going off hook\n"); | |
255 break; | |
256 case AT_MODEM_CONTROL_DTR: | |
257 printf("\nModem control - DTR %d\n", (int) (intptr_t) num); | |
258 break; | |
259 case AT_MODEM_CONTROL_RTS: | |
260 printf("\nModem control - RTS %d\n", (int) (intptr_t) num); | |
261 break; | |
262 case AT_MODEM_CONTROL_CTS: | |
263 printf("\nModem control - CTS %d\n", (int) (intptr_t) num); | |
264 break; | |
265 case AT_MODEM_CONTROL_CAR: | |
266 printf("\nModem control - CAR %d\n", (int) (intptr_t) num); | |
267 break; | |
268 case AT_MODEM_CONTROL_RNG: | |
269 printf("\nModem control - RNG %d\n", (int) (intptr_t) num); | |
270 break; | |
271 case AT_MODEM_CONTROL_DSR: | |
272 printf("\nModem control - DSR %d\n", (int) (intptr_t) num); | |
273 break; | |
274 default: | |
275 printf("\nModem control - operation %d\n", op); | |
276 break; | |
277 } | |
278 /*endswitch*/ | |
279 return 0; | |
280 } | |
281 /*- End of function --------------------------------------------------------*/ | |
282 | |
283 static int at_tx_handler(at_state_t *s, void *user_data, const uint8_t *buf, size_t len) | |
284 { | |
285 size_t i; | |
286 | |
287 i = 0; | |
288 if (fax_test_seq[test_seq_ptr].command == NULL) | |
289 { | |
290 /* TCF or non-ECM image data expected */ | |
291 for ( ; i < len; i++) | |
292 { | |
293 if (dled) | |
294 { | |
295 if (buf[i] == ETX) | |
296 { | |
297 printf("\nFast data ended\n"); | |
298 response_buf_ptr = 0; | |
299 response_buf[response_buf_ptr] = '\0'; | |
300 test_seq_ptr++; | |
301 if (fax_test_seq[test_seq_ptr].command) | |
302 kick = TRUE; | |
303 break; | |
304 } | |
305 dled = FALSE; | |
306 } | |
307 else | |
308 { | |
309 if (buf[i] == DLE) | |
310 dled = TRUE; | |
311 } | |
312 } | |
313 i++; | |
314 if (i >= len) | |
315 return 0; | |
316 } | |
317 for ( ; i < len; i++) | |
318 { | |
319 response_buf[response_buf_ptr++] = buf[i]; | |
320 putchar(buf[i]); | |
321 } | |
322 response_buf[response_buf_ptr] = '\0'; | |
323 printf("Expected "); | |
324 for (i = 0; i < response_buf_ptr; i++) | |
325 printf("%02x ", fax_test_seq[test_seq_ptr].response[i] & 0xFF); | |
326 printf("\n"); | |
327 printf("Response "); | |
328 for (i = 0; i < response_buf_ptr; i++) | |
329 printf("%02x ", response_buf[i] & 0xFF); | |
330 printf("\n"); | |
331 printf("Match %d against %d\n", response_buf_ptr, fax_test_seq[test_seq_ptr].len_response); | |
332 if (response_buf_ptr >= fax_test_seq[test_seq_ptr].len_response | |
333 && | |
334 memcmp(fax_test_seq[test_seq_ptr].response, response_buf, fax_test_seq[test_seq_ptr].len_response) == 0) | |
335 { | |
336 printf("\nMatched\n"); | |
337 test_seq_ptr++; | |
338 response_buf_ptr = 0; | |
339 response_buf[response_buf_ptr] = '\0'; | |
340 if (fax_test_seq[test_seq_ptr].command) | |
341 kick = TRUE; | |
342 else | |
343 dled = FALSE; | |
344 } | |
345 return 0; | |
346 } | |
347 /*- End of function --------------------------------------------------------*/ | |
348 | |
349 int main(int argc, char *argv[]) | |
350 { | |
351 int i; | |
352 int k; | |
353 int outframes; | |
354 fax_state_t fax_state; | |
355 int16_t t30_amp[SAMPLES_PER_CHUNK]; | |
356 int16_t t31_amp[SAMPLES_PER_CHUNK]; | |
357 int16_t silence[SAMPLES_PER_CHUNK]; | |
358 int16_t out_amp[2*SAMPLES_PER_CHUNK]; | |
359 int t30_len; | |
360 int t31_len; | |
361 AFfilesetup filesetup; | |
362 AFfilehandle wave_handle; | |
363 AFfilehandle in_handle; | |
364 int log_audio; | |
365 int test_sending; | |
366 int fast_send; | |
367 int fast_blocks; | |
368 uint8_t fast_buf[1000]; | |
369 | |
370 decode_test_file = NULL; | |
371 log_audio = FALSE; | |
372 test_sending = FALSE; | |
373 for (i = 1; i < argc; i++) | |
374 { | |
375 if (strcmp(argv[i], "-d") == 0) | |
376 { | |
377 decode_test_file = argv[++i]; | |
378 continue; | |
379 } | |
380 if (strcmp(argv[i], "-l") == 0) | |
381 { | |
382 log_audio = TRUE; | |
383 continue; | |
384 } | |
385 if (strcmp(argv[i], "-r") == 0) | |
386 { | |
387 test_sending = FALSE; | |
388 continue; | |
389 } | |
390 if (strcmp(argv[i], "-s") == 0) | |
391 { | |
392 test_sending = TRUE; | |
393 continue; | |
394 } | |
395 } | |
396 | |
397 filesetup = AF_NULL_FILESETUP; | |
398 wave_handle = AF_NULL_FILEHANDLE; | |
399 if (log_audio) | |
400 { | |
401 if ((filesetup = afNewFileSetup()) == AF_NULL_FILESETUP) | |
402 { | |
403 fprintf(stderr, " Failed to create file setup\n"); | |
404 exit(2); | |
405 } | |
406 afInitSampleFormat(filesetup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16); | |
407 afInitRate(filesetup, AF_DEFAULT_TRACK, (float) SAMPLE_RATE); | |
408 afInitFileFormat(filesetup, AF_FILE_WAVE); | |
409 afInitChannels(filesetup, AF_DEFAULT_TRACK, 2); | |
410 if ((wave_handle = afOpenFile(OUTPUT_WAVE_FILE_NAME, "w", filesetup)) == AF_NULL_FILEHANDLE) | |
411 { | |
412 fprintf(stderr, " Cannot create wave file '%s'\n", OUTPUT_WAVE_FILE_NAME); | |
413 exit(2); | |
414 } | |
415 } | |
416 | |
417 memset(silence, 0, sizeof(silence)); | |
418 | |
419 in_handle = NULL; | |
420 if (decode_test_file) | |
421 { | |
422 if ((in_handle = afOpenFile(decode_test_file, "r", NULL)) == AF_NULL_FILEHANDLE) | |
423 { | |
424 fprintf(stderr, " Cannot create wave file '%s'\n", decode_test_file); | |
425 exit(2); | |
426 } | |
427 } | |
428 | |
429 if (test_sending) | |
430 { | |
431 fax_init(&fax_state, FALSE); | |
432 t30_set_rx_file(&fax_state.t30_state, OUTPUT_FILE_NAME, -1); | |
433 fax_test_seq = fax_send_test_seq; | |
434 countdown = 0; | |
435 } | |
436 else | |
437 { | |
438 fax_init(&fax_state, TRUE); | |
439 t30_set_tx_file(&fax_state.t30_state, INPUT_FILE_NAME, -1, -1); | |
440 fax_test_seq = fax_receive_test_seq; | |
441 countdown = 250; | |
442 } | |
443 | |
444 t30_set_local_ident(&fax_state.t30_state, "11111111"); | |
445 t30_set_phase_b_handler(&fax_state.t30_state, phase_b_handler, (void *) 0); | |
446 t30_set_phase_d_handler(&fax_state.t30_state, phase_d_handler, (void *) 0); | |
447 t30_set_phase_e_handler(&fax_state.t30_state, phase_e_handler, (void *) 0); | |
448 memset(t30_amp, 0, sizeof(t30_amp)); | |
449 | |
450 span_log_set_level(&fax_state.t30_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW); | |
451 span_log_set_tag(&fax_state.t30_state.logging, "YYY"); | |
452 span_log_set_level(&fax_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW); | |
453 span_log_set_tag(&fax_state.logging, "YYY"); | |
454 | |
455 if (t31_init(&t31_state, at_tx_handler, NULL, modem_call_control, NULL, NULL, NULL) == NULL) | |
456 { | |
457 fprintf(stderr, " Cannot start the FAX modem\n"); | |
458 exit(2); | |
459 } | |
460 | |
461 span_log_set_level(&t31_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW); | |
462 span_log_set_tag(&t31_state.logging, "XXX"); | |
463 | |
464 fast_send = FALSE; | |
465 fast_blocks = 0; | |
466 kick = TRUE; | |
467 while (!done) | |
468 { | |
469 if (kick) | |
470 { | |
471 kick = FALSE; | |
472 if (fax_test_seq[test_seq_ptr].command > (const char *) 1) | |
473 { | |
474 if (fax_test_seq[test_seq_ptr].command[0]) | |
475 { | |
476 printf("%s\n", fax_test_seq[test_seq_ptr].command); | |
477 t31_at_rx(&t31_state, fax_test_seq[test_seq_ptr].command, fax_test_seq[test_seq_ptr].len_command); | |
478 } | |
479 } | |
480 else | |
481 { | |
482 printf("Fast send\n"); | |
483 fast_send = TRUE; | |
484 fast_blocks = 100; | |
485 } | |
486 } | |
487 if (fast_send) | |
488 { | |
489 /* Send fast modem data */ | |
490 memset(fast_buf, 0, 36); | |
491 if (fast_blocks == 1) | |
492 { | |
493 /* Insert EOLs */ | |
494 fast_buf[35] = ETX; | |
495 fast_buf[34] = DLE; | |
496 fast_buf[31] = | |
497 fast_buf[28] = | |
498 fast_buf[25] = | |
499 fast_buf[22] = | |
500 fast_buf[19] = | |
501 fast_buf[16] = 1; | |
502 } | |
503 t31_at_rx(&t31_state, (char *) fast_buf, 36); | |
504 if (--fast_blocks == 0) | |
505 fast_send = FALSE; | |
506 } | |
507 t30_len = fax_tx(&fax_state, t30_amp, SAMPLES_PER_CHUNK); | |
508 /* The receive side always expects a full block of samples, but the | |
509 transmit side may not be sending any when it doesn't need to. We | |
510 may need to pad with some silence. */ | |
511 if (t30_len < SAMPLES_PER_CHUNK) | |
512 { | |
513 memset(t30_amp + t30_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len)); | |
514 t30_len = SAMPLES_PER_CHUNK; | |
515 } | |
516 if (log_audio) | |
517 { | |
518 for (k = 0; k < t30_len; k++) | |
519 out_amp[2*k] = t30_amp[k]; | |
520 } | |
521 if (t31_rx(&t31_state, t30_amp, t30_len)) | |
522 break; | |
523 if (countdown) | |
524 { | |
525 if (answered) | |
526 { | |
527 countdown = 0; | |
528 t31_call_event(&t31_state, AT_CALL_EVENT_ANSWERED); | |
529 } | |
530 else if (--countdown == 0) | |
531 { | |
532 t31_call_event(&t31_state, AT_CALL_EVENT_ALERTING); | |
533 countdown = 250; | |
534 } | |
535 } | |
536 | |
537 t31_len = t31_tx(&t31_state, t31_amp, SAMPLES_PER_CHUNK); | |
538 if (t31_len < SAMPLES_PER_CHUNK) | |
539 { | |
540 memset(t31_amp + t31_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t31_len)); | |
541 t31_len = SAMPLES_PER_CHUNK; | |
542 } | |
543 if (log_audio) | |
544 { | |
545 for (k = 0; k < t31_len; k++) | |
546 out_amp[2*k + 1] = t31_amp[k]; | |
547 } | |
548 if (fax_rx(&fax_state, t31_amp, SAMPLES_PER_CHUNK)) | |
549 break; | |
550 | |
551 if (log_audio) | |
552 { | |
553 outframes = afWriteFrames(wave_handle, AF_DEFAULT_TRACK, out_amp, SAMPLES_PER_CHUNK); | |
554 if (outframes != SAMPLES_PER_CHUNK) | |
555 break; | |
556 } | |
557 } | |
558 if (decode_test_file) | |
559 { | |
560 if (afCloseFile(in_handle) != 0) | |
561 { | |
562 fprintf(stderr, " Cannot close wave file '%s'\n", decode_test_file); | |
563 exit(2); | |
564 } | |
565 } | |
566 if (log_audio) | |
567 { | |
568 if (afCloseFile(wave_handle) != 0) | |
569 { | |
570 fprintf(stderr, " Cannot close wave file '%s'\n", OUTPUT_WAVE_FILE_NAME); | |
571 exit(2); | |
572 } | |
573 afFreeFileSetup(filesetup); | |
574 } | |
575 if (done) | |
576 { | |
577 printf("Tests passed\n"); | |
578 } | |
579 return 0; | |
580 } | |
581 /*- End of function --------------------------------------------------------*/ | |
582 /*- End of file ------------------------------------------------------------*/ |