2
|
1 /* intercomd.cpp
|
|
2 *
|
|
3 * Copyright (C) DFS Deutsche Flugsicherung (2004, 2005).
|
|
4 * All Rights Reserved.
|
|
5 * Author: Andre Adrian
|
|
6 *
|
|
7 * Voice over IP Intercom with Telephone conference and Acoustic Echo
|
|
8 * Cancellation using unicast RTP messages (RFC3550, RFC3551)
|
|
9 *
|
|
10 * Attention. This source code is for Linux only! You need:
|
|
11 * same endian for CPU and soundcard for 16bit PCM audio sample
|
|
12 * Open Source Sound (OSS) support
|
|
13 * ALSA Sound support for hardware (2-channel) AEC
|
|
14 *
|
|
15 * Format Sourcecode:
|
|
16 indent -kr -i2 -nlp -ci2 -l72 -lc72 -nut intercomd.cpp
|
|
17 *
|
|
18 * global Replace (one replace per line only!)
|
|
19 sed -i "s/PIT_MIN/G729_PIT_MIN/" *.h *.cpp
|
|
20 *
|
|
21 */
|
|
22
|
|
23 const char VERSION[] = "0.4.1";
|
|
24
|
|
25 #include <stdio.h>
|
|
26 #include <stdlib.h>
|
|
27 #include <string.h>
|
|
28 #include <math.h>
|
|
29 #include <stdarg.h>
|
|
30 #include <syslog.h>
|
|
31
|
|
32 /* Error handling */
|
|
33 #include <assert.h>
|
|
34 #include <errno.h>
|
|
35 extern int errno;
|
|
36
|
|
37 /* low level io */
|
|
38 #include <sys/types.h>
|
|
39 #include <sys/stat.h>
|
|
40 #include <fcntl.h>
|
|
41 #include <sys/ioctl.h>
|
|
42 #include <unistd.h>
|
|
43 #include <sys/select.h>
|
|
44 #include <sys/time.h>
|
|
45
|
|
46 /* Socket io */
|
|
47 #include <sys/types.h>
|
|
48 #include <sys/socket.h>
|
|
49 #include <netinet/in.h>
|
|
50
|
|
51 /* IETF iLBC codec */
|
|
52 extern "C" {
|
|
53 #include "ilbc/iLBC_define.h"
|
|
54 #include "ilbc/iLBC_encode.h"
|
|
55 #include "ilbc/iLBC_decode.h"
|
|
56 }
|
|
57
|
|
58 /* ITU-T G.711 codec */
|
|
59 extern "C" {
|
|
60 #include "g711/g711.h"
|
|
61 }
|
|
62
|
|
63 /* 3GPP GSM codec */
|
|
64 extern "C" {
|
|
65 #include "gsm/private.h"
|
|
66 #include "gsm/gsm.h"
|
|
67 #include "gsm/rpeltp.h"
|
|
68 }
|
|
69
|
|
70 /* ITU-T G.726 codec */
|
|
71 extern "C" {
|
|
72 #include "g726/g726.h"
|
|
73 #include "g726/g726_rfc3551.h"
|
|
74 }
|
|
75
|
|
76 /* Speex codec */
|
|
77 extern "C" {
|
|
78 #include <speex/speex.h>
|
|
79 /* Note: if you use the RPM speex-devel on SuSE 9.1 change the
|
|
80 * header file above from <speex/speex.h> to <speex.h> */
|
|
81 }
|
|
82
|
|
83 #include "sinuston.h"
|
|
84
|
|
85 typedef unsigned char Byte;
|
|
86 typedef short Word16;
|
|
87
|
|
88 #ifdef EFRSTUB
|
|
89 /* EFR stubs - because of function name conflict in EFR and G.729 */
|
|
90 class EFR {
|
|
91 public:
|
|
92 int EFR::initEncode(int dtx_mode_) {
|
|
93 return 0;
|
|
94 };
|
|
95 int EFR::encode( /* (o) len in byte of encoded_data */
|
|
96 Byte * encoded_data, /* (o) The encoded bytes */
|
|
97 Word16 * data /* (i) The signal block to encode */
|
|
98 ) {
|
|
99 return 0;
|
|
100 };
|
|
101 int EFR::initDecode() {
|
|
102 return 0;
|
|
103 };
|
|
104 int EFR::decode( /* (o) Number of decoded samples or 0 for error */
|
|
105 Word16 * decoded_data, /* (o) Decoded signal block */
|
|
106 Byte * encoded_data, /* (i) Encoded bytes */
|
|
107 Word16 mode /* (i) 0=PL, 1=Normal */
|
|
108 ) {
|
|
109 return 0;
|
|
110 };
|
|
111 };
|
|
112 #else
|
|
113 /* 3GPP GSM-EFR codec */
|
|
114 #include "efr/typedef.h"
|
|
115 #include "efr/efr.h"
|
|
116 #endif
|
|
117
|
|
118 #ifdef G729STUB
|
|
119 /* G.729 stubs - because of function name conflict in EFR and G.729 */
|
|
120 class G729 {
|
|
121 public:
|
|
122 int G729::initEncode(int dummy) {
|
|
123 return 0;
|
|
124 };
|
|
125
|
|
126 int G729::encode( /* len in byte of encoded_data */
|
|
127 Byte * encoded_data, /* (o) The encoded bytes */
|
|
128 Word16 * data /* (i) The signal block to encode */
|
|
129 ) {
|
|
130 return 0;
|
|
131 };
|
|
132 int G729::initDecode() {
|
|
133 return 0;
|
|
134 };
|
|
135
|
|
136 int G729::decode( /* (o) Number of decoded samples */
|
|
137 Word16 * decoded_data, /* (o) Decoded signal block */
|
|
138 Byte * encoded_data, /* (i) Encoded bytes */
|
|
139 Word16 mode /* (i) 0=PL, 1=Normal */
|
|
140 ) {
|
|
141 return 0;
|
|
142 };
|
|
143 };
|
|
144 #else
|
|
145 /* ITU-T G.729 codec */
|
|
146 #include "g729/typedef.h"
|
|
147 #include "g729/ld8k.h"
|
|
148 #include "g729/g729.h"
|
|
149 #endif
|
|
150
|
|
151
|
|
152 /* intercom */
|
|
153 #include "rtp.h"
|
|
154 #include "udp.h"
|
|
155 #include "tcp.h"
|
|
156 #include "aec.h"
|
|
157 #include "oss.h"
|
|
158 #include "cirbuf.h"
|
|
159 #include "intercomd.h"
|
|
160
|
|
161 /* Design Constants */
|
|
162 #define PARTNERS 5 /* maximum telephony partners */
|
|
163
|
|
164 /* End of Design Constants */
|
|
165 #define MAXPACKSIZE 160 /* maximum size of 20ms encoded audio */
|
|
166 #define ILBC_MODE 20
|
|
167 #define FRAMESIZE (20*8*WIDEB*2) /* compression frame size */
|
|
168 #define MTU 1460 /* max. MTU size without Headers */
|
|
169
|
|
170 /* Globals */
|
|
171 int wdisplay = NO; /* export aec.cpp */
|
|
172
|
|
173
|
|
174 /* audio */
|
|
175 static CIRBUF mic_cirbuf;
|
|
176 static CIRBUF spk_cirbuf;
|
|
177 static AEC aec;
|
|
178 static int channels = 1;
|
|
179 static int audio_wr_fd = -1; // Audio Output (speaker)
|
|
180 static int packetlc = NO;
|
|
181 static SINUSTON sinuston; // Erweiterung Christian Dorge
|
|
182 static int sinuson = 0; // Sinustonaktivierung
|
|
183
|
|
184 /* network transmitting to partners */
|
|
185 static in_addr_t to_ip[PARTNERS];
|
|
186 static RTP to_rtp[PARTNERS];
|
|
187 static UDP to_udp[PARTNERS];
|
|
188 static iLBC_Enc_Inst_t enc_ilbc[PARTNERS];
|
|
189 static G726_state enc_g726[PARTNERS];
|
|
190 static EFR enc_efr[PARTNERS];
|
|
191 static G729 enc_g729[PARTNERS];
|
|
192 static gsm enc_gsm[PARTNERS];
|
|
193 static SpeexBits enc_spxbits[PARTNERS];
|
|
194 static void *enc_spx[PARTNERS];
|
|
195 static CIRBUF conf_cirbuf[PARTNERS];
|
|
196 static char tx_buf[PARTNERS][MTU];
|
|
197 static char *tx_pbuf[PARTNERS];
|
|
198 static int tx_frame[PARTNERS];
|
|
199 static int to_partners = 0;
|
|
200 static int telephone_conference = NO;
|
|
201 static int tx_frames = 4;
|
|
202 static int tx_payloadt = PT_iLBC; /* default Codec */
|
|
203 static int tx_packsize = NO_OF_BYTES_20MS;
|
|
204 static unsigned long to_ssrc = 0;
|
|
205
|
|
206 /* network receiving from partners */
|
|
207 static in_addr_t from_ip[PARTNERS];
|
|
208 static unsigned long from_ssrc[PARTNERS];
|
|
209 static int from_cnt[PARTNERS];
|
|
210 static CIRBUF from_cirbuf[PARTNERS];
|
|
211 static iLBC_Dec_Inst_t dec_ilbc[PARTNERS];
|
|
212 static G726_state dec_g726[PARTNERS];
|
|
213 static EFR dec_efr[PARTNERS];
|
|
214 static G729 dec_g729[PARTNERS];
|
|
215 static gsm dec_gsm[PARTNERS];
|
|
216 static SpeexBits dec_spxbits[PARTNERS];
|
|
217 static void *dec_spx[PARTNERS];
|
|
218 static int from_partners = 0;
|
|
219 static int from_rx_pt[PARTNERS];
|
|
220 static RTP from_rtp[PARTNERS];
|
|
221
|
|
222 /*----------------------------------------------------------------*
|
|
223 * iLBC Encoder interface function
|
|
224 *---------------------------------------------------------------*/
|
|
225
|
|
226 short encode( /* (o) Number of bytes encoded */
|
|
227 iLBC_Enc_Inst_t * iLBCenc_inst, /* (i/o) Encoder instance */
|
|
228 unsigned char *encoded_data, /* (o) The encoded bytes */
|
|
229 short *data /* (i) The signal block to encode */
|
|
230 )
|
|
231 {
|
|
232 float block[BLOCKL_MAX];
|
|
233 int k;
|
|
234
|
|
235 /* convert signal to float */
|
|
236
|
|
237 for (k = 0; k < iLBCenc_inst->blockl; k++)
|
|
238 block[k] = (float) data[k];
|
|
239
|
|
240 /* do the actual encoding */
|
|
241
|
|
242 iLBC_encode(encoded_data, block, iLBCenc_inst);
|
|
243
|
|
244 return (iLBCenc_inst->no_of_bytes);
|
|
245 }
|
|
246
|
|
247 short spx_encode( /* (o) Number of bytes encoded */
|
|
248 SpeexBits *bits,
|
|
249 void *enc_state,
|
|
250 unsigned char *encoded_data, /* (o) The encoded bytes */
|
|
251 short *data /* (i) The signal block to encode */
|
|
252 )
|
|
253 {
|
|
254 float block[20*WIDEB*8];
|
|
255 unsigned int k;
|
|
256
|
|
257 /* convert signal to float */
|
|
258
|
|
259 for (k = 0; k < sizeof(block) / sizeof(float); k++)
|
|
260 block[k] = (float) data[k];
|
|
261
|
|
262 /* do the actual encoding */
|
|
263
|
|
264 speex_bits_reset(bits);
|
|
265 speex_encode(enc_state, block, bits);
|
|
266 int bytes = speex_bits_write(bits, (char *)encoded_data, 200);
|
|
267
|
|
268 // RPM speex-devel 1.0.3 has different size then Speex 1.1.7
|
|
269 if (bytes != SZ_SPX) {
|
|
270 static int errcnt = 0;
|
|
271 if (++errcnt > 0) {
|
|
272 errcnt = -250;
|
|
273 syslog(LOG_WARNING, "%s:%d: %s: Error bytes = %d, Update Speex lib to 1.1\n", \
|
|
274 __FILE__, __LINE__, __PRETTY_FUNCTION__, bytes); \
|
|
275 }
|
|
276 }
|
|
277 return SZ_SPX;
|
|
278 }
|
|
279
|
|
280 void tx_buf_init(int i)
|
|
281 {
|
|
282 tx_pbuf[i] = tx_buf[i];
|
|
283 tx_frame[i] = 0;
|
|
284 }
|
|
285
|
|
286 int encode_any(int i, Byte * encoded_data, short *buf)
|
|
287 {
|
|
288 static int once = 0;
|
|
289 int len = 0;
|
|
290 switch (tx_payloadt) {
|
|
291 case PT_PCMA:
|
|
292 len = 160;
|
|
293 alaw_compress(len, buf, encoded_data);
|
|
294 break;
|
|
295 case PT_PCMU:
|
|
296 len = 160;
|
|
297 ulaw_compress(len, buf, encoded_data);
|
|
298 break;
|
|
299 case PT_GSM:
|
|
300 gsm_encode(enc_gsm[i], buf, encoded_data);
|
|
301 len = 33;
|
|
302 break;
|
|
303 case PT_EFR:
|
|
304 len = enc_efr[i].encode(encoded_data, buf);
|
|
305 break;
|
|
306 case PT_G729:
|
|
307 /* G.729 is a 10ms per frame codec */
|
|
308 enc_g729[i].encode(encoded_data, buf);
|
|
309 len = 2 * enc_g729[i].encode(encoded_data + 10, buf + 80);
|
|
310 break;
|
|
311 case PT_iLBC:
|
|
312 len = encode(&enc_ilbc[i], encoded_data, buf);
|
|
313 break;
|
|
314 case PT_SPX:
|
|
315 len = spx_encode(&enc_spxbits[i], enc_spx[i], encoded_data, buf);
|
|
316 if (!once) {
|
|
317 printf("speex encode len = %d\n", len);
|
|
318 once = 1;
|
|
319 }
|
|
320 break;
|
|
321 case PT_G726:
|
|
322 len = g726_encode(&enc_g726[i], encoded_data, buf);
|
|
323 break;
|
|
324 }
|
|
325 return len;
|
|
326 }
|
|
327
|
|
328 static int packet_loss = 0;
|
|
329
|
|
330 int audio_read(int audio_rd_fd)
|
|
331 {
|
|
332 /* fat software interrupt routine: read audio, send UDP packets */
|
|
333
|
|
334 short mic_buf[FRAGSIZE / 2];
|
|
335 if (1 == channels) {
|
|
336 size_t len = read(audio_rd_fd, mic_buf, FRAGSIZE);
|
|
337 return_if(len != FRAGSIZE, ERROR);
|
|
338
|
|
339 if (0 == to_partners) {
|
|
340 /* start assembling send packets only if we have a target */
|
|
341 return OKAY;
|
|
342 }
|
|
343
|
|
344 short spk_buf[FRAGSIZE / 2];
|
|
345 spk_cirbuf.pop((char *) spk_buf, FRAGSIZE);
|
|
346
|
|
347 /* Acoustic Echo Cancellation - using software buffers */
|
|
348 int i;
|
|
349 for (i = 0; i < FRAGSIZE / 2; ++i) {
|
|
350 mic_buf[i] = aec.doAEC(mic_buf[i], spk_buf[i]);
|
|
351 }
|
|
352 } else {
|
|
353 short mic2_buf[FRAGSIZE];
|
|
354 size_t len = read(audio_rd_fd, mic2_buf, 2 * FRAGSIZE);
|
|
355 return_if(len != 2 * FRAGSIZE, ERROR);
|
|
356
|
|
357 if (0 == to_partners) {
|
|
358 /* start assembling send packets only if we have a target */
|
|
359 return OKAY;
|
|
360 }
|
|
361
|
|
362 /* Acoustic Echo Cancellation - using hardware audio mixer */
|
|
363 int i;
|
|
364 for (i = 0; i < FRAGSIZE / 2; ++i) {
|
|
365 mic_buf[i] = aec.doAEC(mic2_buf[2 * i], mic2_buf[2 * i + 1]);
|
|
366 }
|
|
367 }
|
|
368
|
|
369 int ret = mic_cirbuf.push((char *) mic_buf, FRAGSIZE);
|
|
370 if (ret < 0) {
|
|
371 syslog(LOG_WARNING, "mic_cirbuf.push overrun\n");
|
|
372 }
|
|
373
|
|
374 if (mic_cirbuf.getlen() >= FRAMESIZE) {
|
|
375 /* My RFC3551 interpretation: Only one RTP Header for packets
|
|
376 * with a number of frames */
|
|
377 int i;
|
|
378 for (i = 0; i < PARTNERS; ++i) {
|
|
379 if (to_ip[i] && 0 == tx_frame[i]) {
|
|
380 to_rtp[i].reset_csrc();
|
|
381
|
|
382 /* add ssrc from partners in csrc field */
|
|
383 if (telephone_conference) {
|
|
384 int j;
|
|
385 for (j = 0; j < PARTNERS; ++j) {
|
|
386 /* do not mix in origin */
|
|
387 if (from_ssrc[j] && (to_ip[i] != from_ip[j])) {
|
|
388 to_rtp[i].add_csrc(from_ssrc[j]);
|
|
389 }
|
|
390 }
|
|
391 }
|
|
392 /* put RTP header */
|
|
393 tx_pbuf[i] = RTP_network_copy(tx_pbuf[i], &to_rtp[i]);
|
|
394 }
|
|
395 }
|
|
396
|
|
397 /* put payload (audio) */
|
|
398 short micbuf[FRAMESIZE / 2];
|
|
399 mic_cirbuf.pop((char *) micbuf, FRAMESIZE);
|
|
400
|
|
401 if (telephone_conference) {
|
|
402 /* telephone conference mix - everybody from/to everybody else */
|
|
403 short from_buf[PARTNERS][FRAMESIZE / sizeof(short)];
|
|
404 short sum_buf[FRAMESIZE / sizeof(short)];
|
|
405 int i, k;
|
|
406 unsigned int j;
|
|
407
|
|
408 /* get audio from other partners */
|
|
409 for (i = 0; i < PARTNERS; ++i) {
|
|
410 conf_cirbuf[i].pop((char *) from_buf[i], FRAMESIZE);
|
|
411 }
|
|
412
|
|
413 for (i = 0; i < PARTNERS; ++i) {
|
|
414 if (to_ip[i]) {
|
|
415 for (j = 0; j < FRAMESIZE / sizeof(short); ++j) {
|
|
416 /* mix */
|
|
417 long sum = micbuf[j];
|
|
418 for (k = 0; k < PARTNERS; ++k) {
|
|
419 if (to_ip[i] != from_ip[k]) { /* do not mix in origin */
|
|
420 sum += from_buf[k][j];
|
|
421 }
|
|
422 }
|
|
423 /* clip */
|
|
424 if (sum > 32767) {
|
|
425 sum_buf[j] = 32767;
|
|
426 } else if (sum < -32767) {
|
|
427 sum_buf[j] = -32767;
|
|
428 } else {
|
|
429 sum_buf[j] = sum;
|
|
430 }
|
|
431 }
|
|
432 /* do encoding (audio compression) */
|
|
433 Byte encoded_data[MAXPACKSIZE];
|
|
434 int len = encode_any(i, encoded_data, sum_buf);
|
|
435
|
|
436 /* distribute to transmit buffers */
|
|
437 memcpy(tx_pbuf[i], encoded_data, len);
|
|
438 tx_pbuf[i] += len;
|
|
439 assert(tx_pbuf[i] - tx_buf[i] <= MTU);
|
|
440 }
|
|
441 }
|
|
442 } else {
|
|
443 /* intercom conference mixing - central node from/to other nodes */
|
|
444 /* do encoding (audio compression) */
|
|
445 Byte encoded_data[MAXPACKSIZE];
|
|
446 int len = encode_any(0, encoded_data, micbuf);
|
|
447
|
|
448 /* distribute to transmit buffers */
|
|
449 int i;
|
|
450 for (i = 0; i < PARTNERS; ++i) {
|
|
451 if (to_ip[i]) {
|
|
452 memcpy(tx_pbuf[i], encoded_data, len);
|
|
453 tx_pbuf[i] += len;
|
|
454 assert(tx_pbuf[i] - tx_buf[i] <= MTU);
|
|
455 }
|
|
456 }
|
|
457 }
|
|
458
|
|
459 /* transmit data packet(s) */
|
|
460 for (i = 0; i < PARTNERS; ++i) {
|
|
461 if (to_ip[i] && ++tx_frame[i] >= tx_frames) {
|
|
462
|
|
463 if (random() >= packet_loss) { // simulate packet loss
|
|
464 to_udp[i].send(tx_buf[i], tx_pbuf[i] - tx_buf[i]);
|
|
465 }
|
|
466
|
|
467 /* prepare next go */
|
|
468 tx_buf_init(i);
|
|
469 to_rtp[i].next(tx_frames * 20 * 8);
|
|
470 }
|
|
471 }
|
|
472 }
|
|
473 return OKAY;
|
|
474 }
|
|
475
|
|
476 void partner_timeout()
|
|
477 {
|
|
478 /* Delete old from_ssrc[] entries - this is not very quick! */
|
|
479 int i;
|
|
480 for (i = 0; i < PARTNERS; ++i) {
|
|
481 if (from_ssrc[i] && from_cnt[i] == 0) {
|
|
482 char s[20];
|
|
483 print_gui("d %s\n", iptoa(s, from_ip[i]));
|
|
484 from_ssrc[i] = 0;
|
|
485 from_ip[i] = 0;
|
|
486 from_rx_pt[i] = -1;
|
|
487 from_rtp[i].reset_csrc();
|
|
488 --from_partners;
|
|
489 if (0 == from_partners) {
|
|
490 /* no more demand for PCM out */
|
|
491 close(audio_wr_fd);
|
|
492 audio_wr_fd = -1;
|
|
493 }
|
|
494 }
|
|
495 from_cnt[i] = 0;
|
|
496 }
|
|
497 }
|
|
498
|
|
499
|
|
500 int partner_lookup(unsigned long ssrc, in_addr_t ip)
|
|
501 {
|
|
502 /* search */
|
|
503 int i;
|
|
504 for (i = 0; i < PARTNERS; ++i) {
|
|
505 if (from_ssrc[i] == ssrc) {
|
|
506 ++from_cnt[i];
|
|
507 return i; /* old entry */
|
|
508 }
|
|
509 }
|
|
510 /* add new entry */
|
|
511 for (i = 0; i < PARTNERS; ++i) {
|
|
512 if (0 == from_ssrc[i]) {
|
|
513 if (0 == from_partners) {
|
|
514 spk_cirbuf.init();
|
|
515 }
|
|
516 from_ssrc[i] = ssrc;
|
|
517 from_ip[i] = ip;
|
|
518 from_cnt[i] = 1;
|
|
519
|
|
520 initDecode(dec_ilbc + i, ILBC_MODE, 1);
|
|
521 enc_efr[i].initDecode();
|
|
522 enc_g729[i].initDecode();
|
|
523 rpeltp_delete(dec_gsm[i]);
|
|
524 dec_gsm[i] = rpeltp_init();
|
|
525 speex_bits_destroy(dec_spxbits + i);
|
|
526 speex_decoder_destroy(dec_spx[i]);
|
|
527 speex_bits_init(dec_spxbits + i);
|
|
528 dec_spx[i] = speex_decoder_init(&speex_wb_mode);
|
|
529 int value = SPX_ENH;
|
|
530 speex_decoder_ctl(dec_spx[i], SPEEX_SET_ENH, &value);
|
|
531
|
|
532 from_cirbuf[i].init();
|
|
533 conf_cirbuf[i].init();
|
|
534 ++from_partners;
|
|
535 char s[20];
|
|
536 print_gui("r %s\n", iptoa(s, ip));
|
|
537
|
|
538 printf("from_ssrc[%d] = %08lx\n", i, from_ssrc[i]);
|
|
539 return i;
|
|
540 }
|
|
541 }
|
|
542 return ERROR;
|
|
543 }
|
|
544
|
|
545 /*----------------------------------------------------------------*
|
|
546 * iLBC Decoder interface function
|
|
547 *---------------------------------------------------------------*/
|
|
548
|
|
549 short decode( /* (o) Number of decoded samples */
|
|
550 iLBC_Dec_Inst_t * iLBCdec_inst, /* (i/o) Decoder instance */
|
|
551 short *decoded_data, /* (o) Decoded signal block */
|
|
552 unsigned char *encoded_data, /* (i) Encoded bytes */
|
|
553 short mode /* (i) 0=PL, 1=Normal */
|
|
554 )
|
|
555 {
|
|
556 int k;
|
|
557 float decblock[BLOCKL_MAX], dtmp;
|
|
558
|
|
559 /* check if mode is valid */
|
|
560
|
|
561 if (mode < 0 || mode > 1) {
|
|
562 printf("\nERROR - Wrong mode - 0, 1 allowed\n");
|
|
563 exit(3);
|
|
564 }
|
|
565
|
|
566 /* do actual decoding of block */
|
|
567 iLBC_decode(decblock, encoded_data, iLBCdec_inst, mode);
|
|
568
|
|
569 /* convert to short */
|
|
570
|
|
571 for (k = 0; k < iLBCdec_inst->blockl; k++) {
|
|
572 dtmp = decblock[k];
|
|
573
|
|
574 if (dtmp < MIN_SAMPLE)
|
|
575 dtmp = MIN_SAMPLE;
|
|
576 else if (dtmp > MAX_SAMPLE)
|
|
577 dtmp = MAX_SAMPLE;
|
|
578 decoded_data[k] = (short) dtmp;
|
|
579 }
|
|
580
|
|
581 return (iLBCdec_inst->blockl);
|
|
582 }
|
|
583
|
|
584 short spx_decode( /* (o) Number of decoded samples */
|
|
585 SpeexBits *bits,
|
|
586 void *dec_state,
|
|
587 short *decoded_data, /* (o) Decoded signal block */
|
|
588 unsigned char *encoded_data, /* (i) Encoded bytes */
|
|
589 short mode /* (i) 0=PL, 1=Normal */
|
|
590 )
|
|
591 {
|
|
592 unsigned int k;
|
|
593 float decblock[20*WIDEB*8];
|
|
594
|
|
595 /* do actual decoding of block */
|
|
596 if (bits)
|
|
597 speex_bits_read_from(bits, (char *)encoded_data, SZ_SPX);
|
|
598 speex_decode(dec_state, bits, decblock);
|
|
599
|
|
600 /* convert to short */
|
|
601
|
|
602 for (k = 0; k < sizeof(decblock) / sizeof(float); k++) {
|
|
603 decoded_data[k] = (short)decblock[k];
|
|
604 }
|
|
605
|
|
606 return 20*WIDEB*8;
|
|
607 }
|
|
608
|
|
609 void audio_write()
|
|
610 {
|
|
611 int i;
|
|
612 unsigned int j;
|
|
613 short from_buf[PARTNERS][FRAGSIZE / sizeof(short)];
|
|
614 short sum_buf[FRAGSIZE / sizeof(short)];
|
|
615 int playout = 0; // is 1 if we have audio, not silence
|
|
616
|
|
617 /* get audio */
|
|
618 for (i = 0; i < PARTNERS; ++i) {
|
|
619 int ret = from_cirbuf[i].pop((char *) from_buf[i], FRAGSIZE);
|
|
620 if (OKAY == ret) playout = 1;
|
|
621 if (packetlc && ERROR == ret && from_ssrc[i] && audio_wr_fd >= 0) {
|
|
622 // printf("audio_write() PLC ch=%d ret=%d \n", i, ret);
|
|
623
|
|
624 /* do Packet Loss Concealment */
|
|
625 short decoded_data[FRAMESIZE / 2];
|
|
626 int len;
|
|
627 switch (from_rx_pt[i]) {
|
|
628 case PT_iLBC:
|
|
629 len = decode(dec_ilbc + i, decoded_data, NULL, 0);
|
|
630 from_cirbuf[i].push((char *) decoded_data, 2 * len);
|
|
631 from_cirbuf[i].pop((char *) from_buf[i], FRAGSIZE);
|
|
632 playout = 1;
|
|
633 break;
|
|
634 case PT_SPX:
|
|
635 Byte spx_dummy[SZ_SPX];
|
|
636 memset(spx_dummy, 0, SZ_SPX);
|
|
637 len = spx_decode(NULL, dec_spx[i],
|
|
638 decoded_data, spx_dummy, 1);
|
|
639 from_cirbuf[i].push((char *) decoded_data, 2 * len);
|
|
640 from_cirbuf[i].pop((char *) from_buf[i], FRAGSIZE);
|
|
641 playout = 1;
|
|
642 break;
|
|
643 case PT_EFR:
|
|
644 Byte efr_dummy[31];
|
|
645 memset(efr_dummy, 0, 31);
|
|
646 efr_dummy[0] = 0xC0;
|
|
647 len = dec_efr[i].decode(decoded_data, efr_dummy, 0);
|
|
648 from_cirbuf[i].push((char *) decoded_data, 2 * len);
|
|
649 from_cirbuf[i].pop((char *) from_buf[i], FRAGSIZE);
|
|
650 playout = 1;
|
|
651 break;
|
|
652 case PT_G729:
|
|
653 Byte g729_dummy[20];
|
|
654 memset(g729_dummy, 0, 20);
|
|
655 len = dec_g729[i].decode(decoded_data, g729_dummy, 0);
|
|
656 len +=
|
|
657 dec_g729[i].decode(decoded_data + 80, g729_dummy + 10, 0);
|
|
658 from_cirbuf[i].push((char *) decoded_data, 2 * len);
|
|
659 from_cirbuf[i].pop((char *) from_buf[i], FRAGSIZE);
|
|
660 playout = 1;
|
|
661 break;
|
|
662 }
|
|
663 }
|
|
664 }
|
|
665
|
|
666 // if (!playout) return; // knistern with AD1985
|
|
667
|
|
668 // audio mixing with sinuston
|
|
669 for (j = 0; j < FRAGSIZE / sizeof(short); ++j) {
|
|
670 /* mix */
|
|
671 long sum = 0;
|
|
672 for (i = 0; i < PARTNERS; ++i) {
|
|
673 sum += from_buf[i][j];
|
|
674 }
|
|
675 /* clip */
|
|
676 if (sum > 32767) {
|
|
677 sum = 32767;
|
|
678 } else if (sum < -32767) {
|
|
679 sum = -32767;
|
|
680 }
|
|
681 if (sinuson && playout) {
|
|
682 // Sinuston dazumischen 11jul2005 adrian
|
|
683 sum = sinuston.mischen(sum);
|
|
684 }
|
|
685 sum_buf[j] = sum;
|
|
686 }
|
|
687
|
|
688 if (1 == channels) {
|
|
689 if (from_partners > 0) {
|
|
690 /* save for 1-channel AEC */
|
|
691 int ret = spk_cirbuf.push((char *) sum_buf, FRAGSIZE);
|
|
692 if (ret < 0) {
|
|
693 /* syslog(LOG_WARNING, "spk_cirbuf.push overrun\n"); */
|
|
694 }
|
|
695 }
|
|
696 if (audio_wr_fd < 0) {
|
|
697 /* late audio write open */
|
|
698 audio_wr_fd = audio_init("/dev/dsp", channels, O_WRONLY);
|
|
699 }
|
|
700 if (audio_wr_fd >= 0) {
|
|
701 write(audio_wr_fd, sum_buf, FRAGSIZE);
|
|
702 }
|
|
703 } else {
|
|
704 short sum2_buf[FRAGSIZE];
|
|
705 int i;
|
|
706 for (i = 0; i < FRAGSIZE / 2; ++i) {
|
|
707 sum2_buf[2 * i] = 0; /* left channel nothing */
|
|
708 sum2_buf[2 * i + 1] = sum_buf[i]; /* right channel spk */
|
|
709 }
|
|
710 if (audio_wr_fd < 0) {
|
|
711 /* late audio write open */
|
|
712 audio_wr_fd = audio_init("/dev/dsp", channels, O_WRONLY);
|
|
713 }
|
|
714 if (audio_wr_fd >= 0) {
|
|
715 write(audio_wr_fd, sum2_buf, 2 * FRAGSIZE);
|
|
716 }
|
|
717 }
|
|
718 }
|
|
719
|
|
720 static unsigned short rtp_port = 5004; /* see RFC3551 */
|
|
721
|
|
722 int udp_read(int udp_fd)
|
|
723 {
|
|
724 /* software interrupt routine */
|
|
725 char buf[MTU];
|
|
726 struct sockaddr_in from_sock;
|
|
727 socklen_t from_socklen = sizeof(sockaddr_in);
|
|
728 RTP rtp_in;
|
|
729
|
|
730 int len = recvfrom(udp_fd, buf, MTU, 0,
|
|
731 (struct sockaddr *) &from_sock, &from_socklen);
|
|
732
|
|
733 /* check Port number */
|
|
734 in_addr_t from_ip = ntohl(from_sock.sin_addr.s_addr);
|
|
735 in_port_t from_port = ntohs(from_sock.sin_port);
|
|
736 return_if(from_port != rtp_port, ERROR);
|
|
737
|
|
738 char *pbuf = RTP_host_copy(&rtp_in, buf);
|
|
739 len -= (pbuf - buf);
|
|
740 return_if(len < 0, ERROR);
|
|
741 int rc = rtp_in.check();
|
|
742 return_if(rc, ERROR);
|
|
743
|
|
744 int partner = partner_lookup(rtp_in.getssrc(), from_ip);
|
|
745 return_if(partner < 0, ERROR);
|
|
746
|
|
747 /* Avoid Megaphone (station with itself) audio loop */
|
|
748 if (to_ssrc == rtp_in.getssrc()) {
|
|
749 // return ERROR;
|
|
750 }
|
|
751
|
|
752 /* Avoid telephone conference style audio loop (multipath) */
|
|
753 int i;
|
|
754 for (i = 0; i < PARTNERS; ++i) {
|
|
755 /* drop packets with SSRC the same as an known CSRC */
|
|
756 if (i != partner && from_rtp[i].find_csrc(rtp_in.getssrc())) {
|
|
757 return ERROR;
|
|
758 }
|
|
759 }
|
|
760 /* to avoid silence with audio loops: Only if above test passed
|
|
761 * copy rtp_in */
|
|
762 from_rtp[partner] = rtp_in; /* die CSRC */
|
|
763
|
|
764 int rx_frames = 0;
|
|
765 int rx_pt = rtp_in.get_pt();
|
|
766 /* detect number of frames and dynamic payload type from length */
|
|
767 switch (len) {
|
|
768 case 1 * 20:
|
|
769 rx_frames = 1;
|
|
770 break; /* G729 */
|
|
771 case 1 * 33:
|
|
772 rx_frames = 1;
|
|
773 break; /* GSM */
|
|
774 case 1 * 31:
|
|
775 rx_frames = 1;
|
|
776 rx_pt = PT_EFR;
|
|
777 break;
|
|
778 case 1 * 38:
|
|
779 rx_frames = 1;
|
|
780 rx_pt = PT_iLBC;
|
|
781 break;
|
|
782 case 1 * SZ_SPX:
|
|
783 rx_frames = 1;
|
|
784 rx_pt = PT_SPX;
|
|
785 break;
|
|
786 case 1 * 80: /* or 4*20 */
|
|
787 switch (rx_pt) {
|
|
788 case PT_G729:
|
|
789 rx_frames = 4;
|
|
790 break;
|
|
791 default:
|
|
792 rx_frames = 1;
|
|
793 rx_pt = PT_G726;
|
|
794 break;
|
|
795 }
|
|
796 break;
|
|
797 case 1 * 160: /* or 2*80 */
|
|
798 switch (rx_pt) {
|
|
799 case PT_PCMA:
|
|
800 case PT_PCMU:
|
|
801 rx_frames = 1; /* G711 */
|
|
802 break;
|
|
803 default:
|
|
804 rx_frames = 2; /* G726 32kbps */
|
|
805 rx_pt = PT_G726;
|
|
806 break;
|
|
807 }
|
|
808 break;
|
|
809
|
|
810 case 2 * 20:
|
|
811 rx_frames = 2;
|
|
812 break;
|
|
813 case 2 * 33:
|
|
814 rx_frames = 2;
|
|
815 break;
|
|
816 case 2 * 31:
|
|
817 rx_frames = 2;
|
|
818 rx_pt = PT_EFR;
|
|
819 break;
|
|
820 case 2 * 38:
|
|
821 rx_frames = 2;
|
|
822 rx_pt = PT_iLBC;
|
|
823 break;
|
|
824 case 2 * SZ_SPX:
|
|
825 rx_frames = 2;
|
|
826 rx_pt = PT_SPX;
|
|
827 break;
|
|
828 case 2 * 160: /* or 4*80 */
|
|
829 switch (rx_pt) {
|
|
830 case PT_PCMA:
|
|
831 case PT_PCMU:
|
|
832 rx_frames = 2; /* G711 */
|
|
833 break;
|
|
834 default:
|
|
835 rx_frames = 4; /* G726 32kbps */
|
|
836 rx_pt = PT_G726;
|
|
837 break;
|
|
838 }
|
|
839 break;
|
|
840
|
|
841 case 3 * 20:
|
|
842 rx_frames = 3;
|
|
843 break;
|
|
844 case 3 * 33:
|
|
845 rx_frames = 3;
|
|
846 break;
|
|
847 case 3 * 31:
|
|
848 rx_frames = 3;
|
|
849 rx_pt = PT_EFR;
|
|
850 break;
|
|
851 case 3 * 38:
|
|
852 rx_frames = 3;
|
|
853 rx_pt = PT_iLBC;
|
|
854 break;
|
|
855 case 3 * SZ_SPX:
|
|
856 rx_frames = 3;
|
|
857 rx_pt = PT_SPX;
|
|
858 break;
|
|
859 case 3 * 80:
|
|
860 rx_frames = 3;
|
|
861 rx_pt = PT_G726;
|
|
862 break;
|
|
863 case 3 * 160:
|
|
864 rx_frames = 3;
|
|
865 break;
|
|
866
|
|
867 case 4 * 33:
|
|
868 rx_frames = 4;
|
|
869 break;
|
|
870 case 4 * 31:
|
|
871 rx_frames = 4;
|
|
872 rx_pt = PT_EFR;
|
|
873 break;
|
|
874 case 4 * 38:
|
|
875 rx_frames = 4;
|
|
876 rx_pt = PT_iLBC;
|
|
877 break;
|
|
878 case 4 * SZ_SPX:
|
|
879 rx_frames = 4;
|
|
880 rx_pt = PT_SPX;
|
|
881 break;
|
|
882 case 4 * 160:
|
|
883 rx_frames = 4;
|
|
884 break;
|
|
885 };
|
|
886 return_if(0 == rx_frames, ERROR);
|
|
887
|
|
888 from_rx_pt[partner] = rx_pt;
|
|
889 for (i = 0; i < rx_frames; ++i) {
|
|
890 /* do decoding (audio decompression) */
|
|
891 short decoded_data[FRAMESIZE / 2];
|
|
892 switch (rx_pt) {
|
|
893 case PT_PCMA:
|
|
894 len = 160;
|
|
895 alaw_expand(len, (Byte *) pbuf, decoded_data);
|
|
896 pbuf += 160;
|
|
897 break;
|
|
898 case PT_PCMU:
|
|
899 len = 160;
|
|
900 ulaw_expand(len, (Byte *) pbuf, decoded_data);
|
|
901 pbuf += 160;
|
|
902 break;
|
|
903 case PT_GSM:
|
|
904 len = 160;
|
|
905 gsm_decode(dec_gsm[partner], (Byte *) pbuf, decoded_data);
|
|
906 pbuf += 33;
|
|
907 break;
|
|
908 case PT_EFR:
|
|
909 len = dec_efr[partner].decode(decoded_data, (Byte *) pbuf, 1);
|
|
910 pbuf += 31;
|
|
911 break;
|
|
912 case PT_G729:
|
|
913 len = dec_g729[partner].decode(decoded_data, (Byte *) pbuf, 1);
|
|
914 len +=
|
|
915 dec_g729[partner].decode(decoded_data + 80,
|
|
916 (Byte *) (pbuf + 10), 1);
|
|
917 pbuf += 20;
|
|
918 break;
|
|
919 case PT_iLBC:
|
|
920 len = decode(dec_ilbc + partner, decoded_data, (Byte *) pbuf, 1);
|
|
921 pbuf += 38;
|
|
922 break;
|
|
923 case PT_SPX:
|
|
924 len = spx_decode(dec_spxbits + partner, dec_spx[partner],
|
|
925 decoded_data, (Byte *) pbuf, 1);
|
|
926 pbuf += SZ_SPX;
|
|
927 break;
|
|
928 case PT_G726:
|
|
929 len =
|
|
930 g726_decode(dec_g726 + partner, decoded_data, (Byte *) pbuf, 1);
|
|
931 pbuf += 80;
|
|
932 break;
|
|
933 }
|
|
934 return_if(len != FRAMESIZE / 2, ERROR);
|
|
935
|
|
936 int ret = from_cirbuf[partner].push((char *) decoded_data, 2 * len);
|
|
937 if (ret < 0) {
|
|
938 syslog(LOG_WARNING, "from_cirbuf[%d].push overrun=%d\n", partner,
|
|
939 ret / FRAGSIZE);
|
|
940 }
|
|
941 if (telephone_conference) {
|
|
942 ret = conf_cirbuf[partner].push((char *) decoded_data, 2 * len);
|
|
943 if (ret < 0) {
|
|
944 /* syslog(LOG_WARNING, "conf_cirbuf[%d].push overrun=%d\n",
|
|
945 partner, ret/FRAGSIZE); */
|
|
946 }
|
|
947 }
|
|
948 }
|
|
949 return OKAY;
|
|
950 }
|
|
951
|
|
952 void spx_encoder_init(int i)
|
|
953 {
|
|
954 speex_bits_init(enc_spxbits + i);
|
|
955 enc_spx[i] = speex_encoder_init(&speex_wb_mode);
|
|
956 int value = SPX_QUALITY;
|
|
957 speex_encoder_ctl(enc_spx[i], SPEEX_SET_QUALITY, &value);
|
|
958 value = SPX_BITRATE;
|
|
959 speex_encoder_ctl(enc_spx[i], SPEEX_SET_BITRATE, &value);
|
|
960 value = SPX_COMPLEXITY;
|
|
961 speex_encoder_ctl(enc_spx[i], SPEEX_SET_COMPLEXITY, &value);
|
|
962 }
|
|
963
|
|
964 // user command
|
|
965 void command(char *cmd, int udp_fd)
|
|
966 {
|
|
967 /* delete special characters like \r, \n */
|
|
968 unsigned int i;
|
|
969 for (i = 0; i < strlen(cmd); ++i) {
|
|
970 if (cmd[i] < ' ') { /* hack: assume ASCII coding */
|
|
971 cmd[i] = 0;
|
|
972 break;
|
|
973 }
|
|
974 }
|
|
975 in_addr_t ip;
|
|
976 switch (cmd[0]) {
|
|
977 default:
|
|
978 printf("voipconf commands:\n"
|
|
979 "c IP-Adress - connect to IP-Adress\n"
|
|
980 "h IP-Adress - hang-up IP-Adress\n\n");
|
|
981 fflush(stdout);
|
|
982 break;
|
|
983 case 'p':
|
|
984 /* do nothing */
|
|
985 break;
|
|
986 case 'c':
|
|
987 ip = atoip(cmd + 2);
|
|
988 for (i = 0; i < PARTNERS; ++i) {
|
|
989 if (0 == to_ip[i]) {
|
|
990 if (0 == to_partners) {
|
|
991 mic_cirbuf.init();
|
|
992 }
|
|
993 tx_buf_init(i);
|
|
994 to_ip[i] = ip;
|
|
995 to_rtp[i].init(tx_payloadt, to_ssrc);
|
|
996 to_udp[i].send_init(cmd + 2, rtp_port, udp_fd);
|
|
997 switch (tx_payloadt) {
|
|
998 case PT_EFR:
|
|
999 enc_efr[i].initEncode(0);
|
|
1000 break;
|
|
1001 case PT_G729:
|
|
1002 enc_g729[i].initEncode(0);
|
|
1003 break;
|
|
1004 case PT_iLBC:
|
|
1005 initEncode(enc_ilbc + i, ILBC_MODE);
|
|
1006 break;
|
|
1007 case PT_GSM:
|
|
1008 rpeltp_delete(enc_gsm[i]);
|
|
1009 enc_gsm[i] = rpeltp_init();
|
|
1010 break;
|
|
1011 case PT_SPX:
|
|
1012 speex_bits_destroy(enc_spxbits + i);
|
|
1013 speex_encoder_destroy(enc_spx[i]);
|
|
1014 spx_encoder_init(i);
|
|
1015 break;
|
|
1016 }
|
|
1017 ++to_partners;
|
|
1018 break;
|
|
1019 }
|
|
1020 }
|
|
1021 break;
|
|
1022 case 'h':
|
|
1023 ip = atoip(cmd + 2);
|
|
1024 for (i = 0; i < PARTNERS; ++i) {
|
|
1025 if (ip == to_ip[i]) {
|
|
1026 to_ip[i] = 0;
|
|
1027 to_udp[i].send_close();
|
|
1028 --to_partners;
|
|
1029
|
|
1030 print_gui("%s\n", cmd); /* Tcl/Tk needs \n */
|
|
1031 break;
|
|
1032 }
|
|
1033 }
|
|
1034 break;
|
|
1035 }
|
|
1036
|
|
1037 /* syslog(LOG_WARNING, "cmd=%s to_partners=%d\n", cmd, to_partners); */
|
|
1038 }
|
|
1039
|
|
1040 #define CMDLEN 80
|
|
1041
|
|
1042 // local signalling from intercom.tcl
|
|
1043 int gui_read(int gui_fd, int udp_fd)
|
|
1044 {
|
|
1045 char cmd[CMDLEN];
|
|
1046
|
|
1047 int len = read(gui_fd, cmd, CMDLEN);
|
|
1048
|
|
1049 if (len <= 0) {
|
|
1050 syslog(LOG_WARNING, "gui_read() close\n");
|
|
1051 int ret = shutdown(gui_fd, SHUT_RDWR);
|
|
1052 assert_errno(ret >= 0);
|
|
1053
|
|
1054 return -1;
|
|
1055 }
|
|
1056
|
|
1057 command(cmd, udp_fd);
|
|
1058
|
|
1059 return gui_fd;
|
|
1060 }
|
|
1061
|
|
1062 static int gui_fd = -1;
|
|
1063
|
|
1064 int print_gui(const char *fmt, ...)
|
|
1065 {
|
|
1066 /* in fmt: Formatstring as printf */
|
|
1067 /* in ...: Parameter(s) as printf */
|
|
1068
|
|
1069 if (gui_fd >= 0) {
|
|
1070 char s[MTU];
|
|
1071 va_list ap;
|
|
1072 va_start(ap, fmt);
|
|
1073 (void) vsnprintf(s, MTU, fmt, ap);
|
|
1074 va_end(ap);
|
|
1075
|
|
1076 int len = strlen(s);
|
|
1077
|
|
1078 return write(gui_fd, s, len);
|
|
1079 } else {
|
|
1080 return ERROR;
|
|
1081 }
|
|
1082 }
|
|
1083
|
|
1084 struct timeval difftimeval(struct timeval time1, struct timeval time2)
|
|
1085 {
|
|
1086 struct timeval diff;
|
|
1087
|
|
1088 diff.tv_usec = time1.tv_usec - time2.tv_usec;
|
|
1089 if (diff.tv_usec < 0) {
|
|
1090 diff.tv_usec += 1000000;
|
|
1091 time2.tv_usec += 1;
|
|
1092 }
|
|
1093 diff.tv_sec = time1.tv_sec - time2.tv_sec;
|
|
1094
|
|
1095 return diff;
|
|
1096 }
|
|
1097
|
|
1098 float dB2q(float dB)
|
|
1099 {
|
|
1100 /* Dezibel to Ratio */
|
|
1101 return powf(10.0f, dB / 20.0f);
|
|
1102 }
|
|
1103 float q2dB(float q)
|
|
1104 {
|
|
1105 /* Ratio to Dezibel */
|
|
1106 return 20.0f * log10f(q);
|
|
1107 }
|
|
1108
|
|
1109 /* program main loop. OS Event handler */
|
|
1110 int loop(int audio_rd_fd, int udp_fd, int gui_listen_fd)
|
|
1111 {
|
|
1112
|
|
1113 struct timeval timeout;
|
|
1114 fd_set read_fds;
|
|
1115 int max_fd = 64; /* should be max(fd, ..) + 1 */
|
|
1116 static struct timeval last_partner_timeout;
|
|
1117 static struct timeval last_getambient;
|
|
1118 static struct timeval last_spkout;
|
|
1119 static long remainder_spkout = 0;
|
|
1120 struct timezone tz;
|
|
1121 static int mic_int, spk_int, time_int;
|
|
1122
|
|
1123 openlog(NULL, LOG_PERROR, LOG_WARNING);
|
|
1124
|
|
1125 gettimeofday(&last_partner_timeout, &tz);
|
|
1126 gettimeofday(&last_getambient, &tz);
|
|
1127 gettimeofday(&last_spkout, &tz);
|
|
1128 for (;;) {
|
|
1129 timeout.tv_sec = 0;
|
|
1130 timeout.tv_usec = FRAGTIME * 1000;
|
|
1131 FD_ZERO(&read_fds);
|
|
1132 FD_SET(audio_rd_fd, &read_fds);
|
|
1133 FD_SET(udp_fd, &read_fds);
|
|
1134 FD_SET(gui_listen_fd, &read_fds);
|
|
1135 if (gui_fd >= 0) {
|
|
1136 FD_SET(gui_fd, &read_fds);
|
|
1137 }
|
|
1138 // int ret = select(max_fd, &read_fds, NULL, NULL, &timeout);
|
|
1139 int ret = select(max_fd, &read_fds, NULL, NULL, NULL);
|
|
1140 assert_errno(ret >= 0);
|
|
1141
|
|
1142 if (FD_ISSET(audio_rd_fd, &read_fds)) {
|
|
1143 audio_read(audio_rd_fd);
|
|
1144 ++mic_int;
|
|
1145 }
|
|
1146 if (FD_ISSET(udp_fd, &read_fds)) {
|
|
1147 udp_read(udp_fd);
|
|
1148 }
|
|
1149 if (FD_ISSET(gui_listen_fd, &read_fds)) {
|
|
1150 gui_fd = tcp_server_init2(gui_listen_fd);
|
|
1151 }
|
|
1152 if (gui_fd >= 0) {
|
|
1153 if (FD_ISSET(gui_fd, &read_fds)) {
|
|
1154 gui_fd = gui_read(gui_fd, udp_fd);
|
|
1155 }
|
|
1156 }
|
|
1157 #if 0
|
|
1158 if ((mic_int % (5000 / FRAGTIME)) == 0) {
|
|
1159 printf("int: mic %d spk %d time %d\n", mic_int, spk_int,
|
|
1160 time_int);
|
|
1161 }
|
|
1162 #endif
|
|
1163
|
|
1164 struct timeval now, diff;
|
|
1165 if (packetlc) {
|
|
1166 gettimeofday(&now, &tz);
|
|
1167 diff = difftimeval(now, last_spkout);
|
|
1168 if (diff.tv_usec + remainder_spkout >= FRAGTIME * 1000) {
|
|
1169 ++time_int;
|
|
1170 last_spkout = now;
|
|
1171 /* Linux time resolution is more coarse (15ms) then mic
|
|
1172 * time interval (4ms), therefore remainder calculation */
|
|
1173 remainder_spkout =
|
|
1174 diff.tv_usec + remainder_spkout - FRAGTIME * 1000;
|
|
1175 if (audio_wr_fd < 0) {
|
|
1176 /* new output: fill up Open Sound System (OSS) buffer
|
|
1177 * to compensate Operation System Jitter */
|
|
1178 // audio_write();
|
|
1179 }
|
|
1180 audio_write();
|
|
1181 ++spk_int;
|
|
1182 }
|
|
1183 } else {
|
|
1184 /* because of problems with Intel ICH5/Analog Devices AD1985
|
|
1185 * not together with audio_read() */
|
|
1186 audio_write();
|
|
1187 }
|
|
1188
|
|
1189 gettimeofday(&now, &tz);
|
|
1190 diff = difftimeval(now, last_partner_timeout);
|
|
1191 if (diff.tv_usec >= 160000) { /* 2*PACKETDURATION in usec */
|
|
1192 last_partner_timeout = now;
|
|
1193 partner_timeout();
|
|
1194 }
|
|
1195 #if 0
|
|
1196 gettimeofday(&now, &tz);
|
|
1197 diff = difftimeval(now, last_getambient);
|
|
1198 if (diff.tv_sec >= 2) {
|
|
1199 last_getambient = now;
|
|
1200 // if (to_partners > 0) {
|
|
1201 // float ambient = aec.getambient();
|
|
1202 // float ambientdB = q2dB(ambient / 32767.0f);
|
|
1203 // syslog(LOG_WARNING, "Ambient = %2.0f dB\n", ambientdB);
|
|
1204 float xfastdB = q2dB(aec.xfast / 32767.0f);
|
|
1205 float dfastdB = q2dB(aec.dfast / 32767.0f);
|
|
1206 float efastdB = q2dB(aec.efast / 32767.0f);
|
|
1207 float xslowdB = q2dB(aec.xslow / 32767.0f);
|
|
1208 float dslowdB = q2dB(aec.dslow / 32767.0f);
|
|
1209 syslog(LOG_WARNING, "ratio= %2.0f / %2.0f / %2.0f / %2.0f e= %2.0f\n",
|
|
1210 dfastdB, xfastdB, dslowdB, xslowdB, efastdB);
|
|
1211 // }
|
|
1212 }
|
|
1213 #endif
|
|
1214 }
|
|
1215 return ERROR;
|
|
1216 }
|
|
1217
|
|
1218 int main(int argc, char *argv[])
|
|
1219 {
|
|
1220 int i;
|
|
1221 float ambient = 0.0f;
|
|
1222 float dB;
|
|
1223
|
|
1224 #if WIDEB==1
|
|
1225 tx_payloadt = PT_iLBC;
|
|
1226 tx_packsize = SZ_iLBC;
|
|
1227 printf("Narrowband DFS VoIP Intercom %s\n", VERSION);
|
|
1228 #else
|
|
1229 tx_payloadt = PT_SPX;
|
|
1230 tx_packsize = SZ_SPX;
|
|
1231 printf("Wideband DFS VoIP Intercom %s\n", VERSION);
|
|
1232 #endif
|
|
1233 for (i = 1; i < argc && '-' == argv[i][0]; ++i) {
|
|
1234 switch (argv[i][1]) {
|
|
1235 case 'a': /* set Ambient (No Talking) Noise level */
|
|
1236 ambient = atof(argv[++i]);
|
|
1237 break;
|
|
1238 case 'b': /* No AES */
|
|
1239 dB = atof(argv[++i]);
|
|
1240 if (dB < 0.0f) {
|
|
1241 aec.setaes(dB2q(dB));
|
|
1242 } else {
|
|
1243 aec.setaes(0.0f); // 0 is no AES
|
|
1244 }
|
|
1245 break;
|
|
1246 case 'e':
|
|
1247 sinuson = 1; /* Sinuston 2040Hz zumischen */
|
|
1248 break;
|
|
1249 case 'k': /* packet loss concealment */
|
|
1250 packetlc = YES;
|
|
1251 break;
|
|
1252 case 'f': /* Frames */
|
|
1253 tx_frames = atoi(argv[++i]);
|
|
1254 if (tx_frames < 1)
|
|
1255 tx_frames = 1;
|
|
1256 if (tx_frames > 4)
|
|
1257 tx_frames = 4;
|
|
1258 break;
|
|
1259 case 'l': /* use hardware AEC and Line-in for microphone */
|
|
1260 channels = 2;
|
|
1261 break;
|
|
1262 case 'm': /* use hardware AEC and Mic-in for microphone */
|
|
1263 channels = 2;
|
|
1264 break;
|
|
1265 case 'p': /* RTP Portnumber */
|
|
1266 rtp_port = atoi(argv[++i]);
|
|
1267 rtp_port &= 0xFFFE; /* RFC3551: RTP port has even port number */
|
|
1268 break;
|
|
1269 case 's': /* simulated Packet loss */
|
|
1270 packet_loss = (RAND_MAX / 100) * atoi(argv[++i]);
|
|
1271 break;
|
|
1272 case 't': /* Telephone conference call (true conference) */
|
|
1273 telephone_conference = YES;
|
|
1274 break;
|
|
1275 case 'w': /* visualize vector w */
|
|
1276 aec.openwdisplay();
|
|
1277 break;
|
|
1278 #if WIDEB==1
|
|
1279 case 'A': /* set G.711 A-law */
|
|
1280 tx_payloadt = PT_PCMA;
|
|
1281 tx_packsize = 160; /* see RFC3551 */
|
|
1282 break;
|
|
1283 case 'U': /* set G.711 u-law */
|
|
1284 tx_payloadt = PT_PCMU;
|
|
1285 tx_packsize = 160; /* see RFC3551 */
|
|
1286 break;
|
|
1287 case '6': /* set G.726 codec */
|
|
1288 tx_payloadt = PT_G726;
|
|
1289 tx_packsize = 80; /* see RFC3551 */
|
|
1290 break;
|
|
1291 case 'G': /* set GSM codec */
|
|
1292 tx_payloadt = PT_GSM;
|
|
1293 tx_packsize = 33; /* see RFC3551 */
|
|
1294 break;
|
|
1295 case 'E': /* set GSM-EFR codec */
|
|
1296 tx_payloadt = PT_EFR;
|
|
1297 tx_packsize = 31; /* see RFC3551 */
|
|
1298 break;
|
|
1299 case '9': /* set G.729 codec */
|
|
1300 tx_payloadt = PT_G729;
|
|
1301 tx_packsize = 20; /* see RFC3551 */
|
|
1302 break;
|
|
1303 #else
|
|
1304 case 'S': /* set Speex codec */
|
|
1305 tx_payloadt = PT_SPX;
|
|
1306 tx_packsize = SZ_SPX; /* 16.8kBit/s Wideband */
|
|
1307 break;
|
|
1308 #endif
|
|
1309 }
|
|
1310 }
|
|
1311
|
|
1312 /* do -a option even if codec options follows */
|
|
1313 if (ambient != 0.0f) {
|
|
1314 aec.setambient(MAXPCM * dB2q(ambient));
|
|
1315 }
|
|
1316
|
|
1317 /* init Sinuston fuer Transmitter */
|
|
1318 sinuston.frequenz(2040, WIDEB*8000, -24.0f);
|
|
1319
|
|
1320 /* open Audio Receive */
|
|
1321 int audio_rd_fd = audio_init("/dev/dsp", channels, O_RDONLY);
|
|
1322 assert(audio_rd_fd >= 0);
|
|
1323
|
|
1324 /* open Network Receive */
|
|
1325 int udp_fd = UDP_recv_init(rtp_port);
|
|
1326 assert(udp_fd >= 0);
|
|
1327
|
|
1328 /* open Graphical User Interface as TCP server */
|
|
1329 int gui_listen_fd = tcp_server_init(4999);
|
|
1330
|
|
1331 /* codec Initialization */
|
|
1332 int j;
|
|
1333 for (j = 0; j < PARTNERS; ++j) {
|
|
1334 /* iLBC */
|
|
1335 initEncode(enc_ilbc + j, ILBC_MODE);
|
|
1336 initDecode(dec_ilbc + j, ILBC_MODE, 1);
|
|
1337
|
|
1338 /* GSM-EFR */
|
|
1339 enc_efr[j].initEncode(0);
|
|
1340 dec_efr[j].initDecode();
|
|
1341
|
|
1342 /* G.729 */
|
|
1343 enc_g729[j].initEncode(0);
|
|
1344 dec_g729[j].initDecode();
|
|
1345
|
|
1346 /* GSM */
|
|
1347 enc_gsm[i] = rpeltp_init();
|
|
1348 dec_gsm[i] = rpeltp_init();
|
|
1349
|
|
1350 /* Speex */
|
|
1351 spx_encoder_init(j);
|
|
1352
|
|
1353 speex_bits_init(dec_spxbits + j);
|
|
1354 dec_spx[j] = speex_decoder_init(&speex_wb_mode); // Wideband
|
|
1355 int value = SPX_ENH;
|
|
1356 speex_decoder_ctl(dec_spx[j], SPEEX_SET_ENH, &value);
|
|
1357 }
|
|
1358
|
|
1359 /* open Network Transmit Partner (Connections) */
|
|
1360 to_ssrc = random32(tx_payloadt);
|
|
1361 printf("to_ssrc = %08lx\n", to_ssrc);
|
|
1362 for (; i < argc; ++i) {
|
|
1363 if (0 == to_partners) {
|
|
1364 mic_cirbuf.init();
|
|
1365 }
|
|
1366 tx_buf_init(to_partners);
|
|
1367 to_ip[to_partners] = atoip(argv[i]);
|
|
1368 to_rtp[to_partners].init(tx_payloadt, to_ssrc);
|
|
1369 to_udp[to_partners].send_init(argv[i], rtp_port, udp_fd);
|
|
1370 ++to_partners;
|
|
1371 }
|
|
1372
|
|
1373 loop(audio_rd_fd, udp_fd, gui_listen_fd);
|
|
1374
|
|
1375 return OKAY;
|
|
1376 }
|