comparison spandsp-0.0.6pre17/src/fax_modems.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 * fax_modems.c - the analogue modem set for fax processing
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2003, 2005, 2006, 2008 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 Lesser General Public License version 2.1,
14 * as 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 Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * $Id: fax_modems.c,v 1.8 2009/11/02 13:25:20 steveu Exp $
26 */
27
28 /*! \file */
29
30 #if defined(HAVE_CONFIG_H)
31 #include "config.h"
32 #endif
33
34 #include <inttypes.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38 #if defined(HAVE_TGMATH_H)
39 #include <tgmath.h>
40 #endif
41 #if defined(HAVE_MATH_H)
42 #include <math.h>
43 #endif
44 #include "floating_fudge.h"
45 #include <assert.h>
46 #include <fcntl.h>
47 #include <time.h>
48 #if defined(LOG_FAX_AUDIO)
49 #include <unistd.h>
50 #endif
51
52 #include "spandsp/telephony.h"
53 #include "spandsp/logging.h"
54 #include "spandsp/bit_operations.h"
55 #include "spandsp/dc_restore.h"
56 #include "spandsp/queue.h"
57 #include "spandsp/power_meter.h"
58 #include "spandsp/complex.h"
59 #include "spandsp/tone_detect.h"
60 #include "spandsp/tone_generate.h"
61 #include "spandsp/async.h"
62 #include "spandsp/crc.h"
63 #include "spandsp/hdlc.h"
64 #include "spandsp/silence_gen.h"
65 #include "spandsp/fsk.h"
66 #include "spandsp/v29tx.h"
67 #include "spandsp/v29rx.h"
68 #include "spandsp/v27ter_tx.h"
69 #include "spandsp/v27ter_rx.h"
70 #include "spandsp/v17tx.h"
71 #include "spandsp/v17rx.h"
72 #include "spandsp/super_tone_rx.h"
73 #include "spandsp/modem_connect_tones.h"
74 #include "spandsp/fax_modems.h"
75
76 #include "spandsp/private/logging.h"
77 #include "spandsp/private/silence_gen.h"
78 #include "spandsp/private/fsk.h"
79 #include "spandsp/private/v17tx.h"
80 #include "spandsp/private/v17rx.h"
81 #include "spandsp/private/v27ter_tx.h"
82 #include "spandsp/private/v27ter_rx.h"
83 #include "spandsp/private/v29tx.h"
84 #include "spandsp/private/v29rx.h"
85 #include "spandsp/private/modem_connect_tones.h"
86 #include "spandsp/private/hdlc.h"
87 #include "spandsp/private/fax_modems.h"
88
89 #define HDLC_FRAMING_OK_THRESHOLD 5
90
91 SPAN_DECLARE(int) fax_modems_v17_v21_rx(void *user_data, const int16_t amp[], int len)
92 {
93 fax_modems_state_t *s;
94
95 s = (fax_modems_state_t *) user_data;
96 v17_rx(&s->v17_rx, amp, len);
97 fsk_rx(&s->v21_rx, amp, len);
98 if (s->rx_frame_received)
99 {
100 /* We have received something, and the fast modem has not trained. We must
101 be receiving valid V.21 */
102 span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
103 s->rx_handler = (span_rx_handler_t *) &fsk_rx;
104 s->rx_fillin_handler = (span_rx_fillin_handler_t *) &fsk_rx_fillin;
105 s->rx_user_data = &s->v21_rx;
106 }
107 return 0;
108 }
109 /*- End of function --------------------------------------------------------*/
110
111 SPAN_DECLARE(int) fax_modems_v17_v21_rx_fillin(void *user_data, int len)
112 {
113 fax_modems_state_t *s;
114
115 s = (fax_modems_state_t *) user_data;
116 v17_rx_fillin(&s->v17_rx, len);
117 fsk_rx_fillin(&s->v21_rx, len);
118 return 0;
119 }
120 /*- End of function --------------------------------------------------------*/
121
122 SPAN_DECLARE(int) fax_modems_v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
123 {
124 fax_modems_state_t *s;
125
126 s = (fax_modems_state_t *) user_data;
127 v27ter_rx(&s->v27ter_rx, amp, len);
128 fsk_rx(&s->v21_rx, amp, len);
129 if (s->rx_frame_received)
130 {
131 /* We have received something, and the fast modem has not trained. We must
132 be receiving valid V.21 */
133 span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
134 s->rx_handler = (span_rx_handler_t *) &fsk_rx;
135 s->rx_fillin_handler = (span_rx_fillin_handler_t *) &fsk_rx_fillin;
136 s->rx_user_data = &s->v21_rx;
137 }
138 return 0;
139 }
140 /*- End of function --------------------------------------------------------*/
141
142 SPAN_DECLARE(int) fax_modems_v27ter_v21_rx_fillin(void *user_data, int len)
143 {
144 fax_modems_state_t *s;
145
146 s = (fax_modems_state_t *) user_data;
147 v27ter_rx_fillin(&s->v27ter_rx, len);
148 fsk_rx_fillin(&s->v21_rx, len);
149 return 0;
150 }
151 /*- End of function --------------------------------------------------------*/
152
153 SPAN_DECLARE(int) fax_modems_v29_v21_rx(void *user_data, const int16_t amp[], int len)
154 {
155 fax_modems_state_t *s;
156
157 s = (fax_modems_state_t *) user_data;
158 v29_rx(&s->v29_rx, amp, len);
159 fsk_rx(&s->v21_rx, amp, len);
160 if (s->rx_frame_received)
161 {
162 /* We have received something, and the fast modem has not trained. We must
163 be receiving valid V.21 */
164 span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
165 s->rx_handler = (span_rx_handler_t *) &fsk_rx;
166 s->rx_fillin_handler = (span_rx_fillin_handler_t *) &fsk_rx_fillin;
167 s->rx_user_data = &s->v21_rx;
168 }
169 return 0;
170 }
171 /*- End of function --------------------------------------------------------*/
172
173 SPAN_DECLARE(int) fax_modems_v29_v21_rx_fillin(void *user_data, int len)
174 {
175 fax_modems_state_t *s;
176
177 s = (fax_modems_state_t *) user_data;
178 v29_rx_fillin(&s->v29_rx, len);
179 fsk_rx_fillin(&s->v21_rx, len);
180 return 0;
181 }
182 /*- End of function --------------------------------------------------------*/
183
184 static void v21_rx_status_handler(void *user_data, int status)
185 {
186 fax_modems_state_t *s;
187
188 s = (fax_modems_state_t *) user_data;
189 }
190 /*- End of function --------------------------------------------------------*/
191
192 static void v17_rx_status_handler(void *user_data, int status)
193 {
194 fax_modems_state_t *s;
195
196 s = (fax_modems_state_t *) user_data;
197 switch (status)
198 {
199 case SIG_STATUS_TRAINING_SUCCEEDED:
200 span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx));
201 s->rx_handler = (span_rx_handler_t *) &v17_rx;
202 s->rx_fillin_handler = (span_rx_fillin_handler_t *) &v17_rx_fillin;
203 s->rx_user_data = &s->v17_rx;
204 break;
205 }
206 }
207 /*- End of function --------------------------------------------------------*/
208
209 static void v27ter_rx_status_handler(void *user_data, int status)
210 {
211 fax_modems_state_t *s;
212
213 s = (fax_modems_state_t *) user_data;
214 switch (status)
215 {
216 case SIG_STATUS_TRAINING_SUCCEEDED:
217 span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx));
218 s->rx_handler = (span_rx_handler_t *) &v27ter_rx;
219 s->rx_fillin_handler = (span_rx_fillin_handler_t *) &v27ter_rx_fillin;
220 s->rx_user_data = &s->v27ter_rx;
221 break;
222 }
223 }
224 /*- End of function --------------------------------------------------------*/
225
226 static void v29_rx_status_handler(void *user_data, int status)
227 {
228 fax_modems_state_t *s;
229
230 s = (fax_modems_state_t *) user_data;
231 switch (status)
232 {
233 case SIG_STATUS_TRAINING_SUCCEEDED:
234 span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx));
235 s->rx_handler = (span_rx_handler_t *) &v29_rx;
236 s->rx_fillin_handler = (span_rx_fillin_handler_t *) &v29_rx_fillin;
237 s->rx_user_data = &s->v29_rx;
238 break;
239 }
240 }
241 /*- End of function --------------------------------------------------------*/
242
243 SPAN_DECLARE(void) fax_modems_start_rx_modem(fax_modems_state_t *s, int which)
244 {
245 switch (which)
246 {
247 case FAX_MODEM_V17_RX:
248 v17_rx_set_modem_status_handler(&s->v17_rx, v17_rx_status_handler, s);
249 break;
250 case FAX_MODEM_V27TER_RX:
251 v27ter_rx_set_modem_status_handler(&s->v27ter_rx, v27ter_rx_status_handler, s);
252 break;
253 case FAX_MODEM_V29_RX:
254 v29_rx_set_modem_status_handler(&s->v29_rx, v29_rx_status_handler, s);
255 break;
256 }
257 fsk_rx_set_modem_status_handler(&s->v21_rx, v21_rx_status_handler, s);
258 }
259 /*- End of function --------------------------------------------------------*/
260
261 SPAN_DECLARE(void) fax_modems_set_tep_mode(fax_modems_state_t *s, int use_tep)
262 {
263 s->use_tep = use_tep;
264 }
265 /*- End of function --------------------------------------------------------*/
266
267 SPAN_DECLARE(fax_modems_state_t *) fax_modems_init(fax_modems_state_t *s,
268 int use_tep,
269 hdlc_frame_handler_t hdlc_accept,
270 hdlc_underflow_handler_t hdlc_tx_underflow,
271 put_bit_func_t non_ecm_put_bit,
272 get_bit_func_t non_ecm_get_bit,
273 tone_report_func_t tone_callback,
274 void *user_data)
275 {
276 if (s == NULL)
277 {
278 if ((s = (fax_modems_state_t *) malloc(sizeof(*s))) == NULL)
279 return NULL;
280 }
281 memset(s, 0, sizeof(*s));
282 s->use_tep = use_tep;
283
284 hdlc_rx_init(&s->hdlc_rx, FALSE, FALSE, HDLC_FRAMING_OK_THRESHOLD, hdlc_accept, user_data);
285 hdlc_tx_init(&s->hdlc_tx, FALSE, 2, FALSE, hdlc_tx_underflow, user_data);
286 fsk_rx_init(&s->v21_rx, &preset_fsk_specs[FSK_V21CH2], FSK_FRAME_MODE_SYNC, (put_bit_func_t) hdlc_rx_put_bit, &s->hdlc_rx);
287 fsk_rx_signal_cutoff(&s->v21_rx, -39.09f);
288 fsk_tx_init(&s->v21_tx, &preset_fsk_specs[FSK_V21CH2], (get_bit_func_t) hdlc_tx_get_bit, &s->hdlc_tx);
289 v17_rx_init(&s->v17_rx, 14400, non_ecm_put_bit, user_data);
290 v17_tx_init(&s->v17_tx, 14400, s->use_tep, non_ecm_get_bit, user_data);
291 v29_rx_init(&s->v29_rx, 9600, non_ecm_put_bit, user_data);
292 v29_rx_signal_cutoff(&s->v29_rx, -45.5f);
293 v29_tx_init(&s->v29_tx, 9600, s->use_tep, non_ecm_get_bit, user_data);
294 v27ter_rx_init(&s->v27ter_rx, 4800, non_ecm_put_bit, user_data);
295 v27ter_tx_init(&s->v27ter_tx, 4800, s->use_tep, non_ecm_get_bit, user_data);
296 silence_gen_init(&s->silence_gen, 0);
297 modem_connect_tones_tx_init(&s->connect_tx, MODEM_CONNECT_TONES_FAX_CNG);
298 if (tone_callback)
299 {
300 modem_connect_tones_rx_init(&s->connect_rx,
301 MODEM_CONNECT_TONES_FAX_CNG,
302 tone_callback,
303 user_data);
304 }
305 dc_restore_init(&s->dc_restore);
306
307 s->rx_signal_present = FALSE;
308 s->rx_handler = (span_rx_handler_t *) &span_dummy_rx;
309 s->rx_fillin_handler = (span_rx_fillin_handler_t *) &span_dummy_rx;
310 s->rx_user_data = NULL;
311 s->tx_handler = (span_tx_handler_t *) &silence_gen;
312 s->tx_user_data = &s->silence_gen;
313 return s;
314 }
315 /*- End of function --------------------------------------------------------*/
316
317 SPAN_DECLARE(int) fax_modems_release(fax_modems_state_t *s)
318 {
319 return 0;
320 }
321 /*- End of function --------------------------------------------------------*/
322
323 SPAN_DECLARE(int) fax_modems_free(fax_modems_state_t *s)
324 {
325 if (s)
326 free(s);
327 return 0;
328 }
329 /*- End of function --------------------------------------------------------*/
330 /*- End of file ------------------------------------------------------------*/

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