Mercurial > hg > audiostuff
comparison intercom/intercomd.cpp @ 2:13be24d74cd2
import intercom-0.4.1
| author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
|---|---|
| date | Fri, 25 Jun 2010 09:57:52 +0200 |
| parents | |
| children | c6c5a16ce2f2 |
comparison
equal
deleted
inserted
replaced
| 1:9cadc470e3da | 2:13be24d74cd2 |
|---|---|
| 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 } |
