Changeset 323
- Timestamp:
- Mar 17, 2006 12:16:01 AM (19 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/include/pjmedia/conference.h
r322 r323 59 59 PJMEDIA_CONF_NO_MIC = 1, /**< Disable audio streams from the 60 60 microphone device. */ 61 PJMEDIA_CONF_NO_DEVICE = 2, /**< Do not create sound device. */ 61 62 }; 62 63 63 64 64 65 /** 65 * Create conference bridge. This normally will also create instances of 66 * sound device to be attached to the port zero of the bridge. 66 * Create conference bridge with the specified parameters. The sampling rate, 67 * samples per frame, and bits per sample will be used for the internal 68 * operation of the bridge (e.g. when mixing audio frames). However, ports 69 * with different configuration may be connected to the bridge. In this case, 70 * the bridge is able to perform sampling rate conversion, and buffering in 71 * case the samples per frame is different. 72 * 73 * For this version of PJMEDIA, only 16bits per sample is supported. 74 * 75 * For this version of PJMEDIA, the channel count of the ports MUST match 76 * the channel count of the bridge. 77 * 78 * Under normal operation (i.e. when PJMEDIA_CONF_NO_DEVICE option is NOT 79 * specified), the bridge internally create an instance of sound device 80 * and connect the sound device to port zero of the bridge. 81 * 82 * If PJMEDIA_CONF_NO_DEVICE options is specified, no sound device will 83 * be created in the conference bridge. Application MUST acquire the port 84 * interface of the bridge by calling #pjmedia_conf_get_master_port(), and 85 * connect this port interface to a sound device port by calling 86 * #pjmedia_snd_port_connect(). 87 * 88 * The sound device is crucial for the bridge's operation, because it provides 89 * the bridge with necessary clock to process the audio frames periodically. 90 * Internally, the bridge runs when get_frame() to port zero is called. 67 91 * 68 92 * @param pool Pool to use to allocate the bridge and … … 114 138 115 139 /** 140 * Get the master port interface of the conference bridge. The master port 141 * corresponds to the port zero of the bridge. This is only usefull when 142 * application wants to manage the sound device by itself, instead of 143 * allowing the bridge to automatically create a sound device implicitly. 144 * 145 * This function will only return a port interface if PJMEDIA_CONF_NO_DEVICE 146 * option was specified when the bridge was created. 147 * 148 * Application can connect the port returned by this function to a 149 * sound device by calling #pjmedia_snd_port_connect(). 150 * 151 * @param conf The conference bridge. 152 * 153 * @return The port interface of port zero of the bridge, 154 * only when PJMEDIA_CONF_NO_DEVICE options was 155 * specified when the bridge was created. 156 */ 157 PJ_DECL(pjmedia_port*) pjmedia_conf_get_master_port(pjmedia_conf *conf); 158 159 160 /** 116 161 * Add stream port to the conference bridge. By default, the new conference 117 162 * port will have both TX and RX enabled, but it is not connected to any … … 161 206 * @param src_slot Source slot. 162 207 * @param sink_slot Sink slot. 208 * @param level This argument is reserved for future improvements 209 * where it is possible to adjust the level of signal 210 * transmitted in a specific connection. For now, 211 * this argument MUST be zero. 163 212 * 164 213 * @return PJ_SUCCES on success. … … 166 215 PJ_DECL(pj_status_t) pjmedia_conf_connect_port( pjmedia_conf *conf, 167 216 unsigned src_slot, 168 unsigned sink_slot ); 217 unsigned sink_slot, 218 int level ); 169 219 170 220 … … 224 274 PJ_DECL(pj_status_t) pjmedia_conf_get_ports_info(pjmedia_conf *conf, 225 275 unsigned *size, 226 pjmedia_conf_port_info info[]); 276 pjmedia_conf_port_info info[] 277 ); 278 279 280 /** 281 * Get last signal level transmitted to or received from the specified port. 282 * The signal level is an integer value in zero to 255, with zero indicates 283 * no signal, and 255 indicates the loudest signal level. 284 * 285 * @param conf The conference bridge. 286 * @param slot Slot number. 287 * @param tx_level Optional argument to receive the level of signal 288 * transmitted to the specified port (i.e. the direction 289 * is from the bridge to the port). 290 * @param rx_level Optional argument to receive the level of signal 291 * received from the port (i.e. the direction is from the 292 * port to the bridge). 293 * 294 * @return PJ_SUCCESS on success. 295 */ 296 PJ_DECL(pj_status_t) pjmedia_conf_get_signal_level(pjmedia_conf *conf, 297 unsigned slot, 298 unsigned *tx_level, 299 unsigned *rx_level); 300 301 302 /** 303 * Adjust the level of signal received from the specified port. 304 * Application may adjust the level to make the signal received from the port 305 * either louder or more quiet, by giving the value from +127 to -128. The 306 * value zero indicates no adjustment, the value -128 will mute the signal, 307 * and the value of +127 will make the signal twice as loud. 308 * 309 * @param conf The conference bridge. 310 * @param slot Slot number. 311 * @param adj_level Adjustment level, with valid values are from -128 312 * to +127. A value of zero means there is no level 313 * adjustment to be made, the value -128 will mute the 314 * signal, and the value of +127 will make the signal 315 * twice as loud. 316 * 317 * @return PJ_SUCCESS on success. 318 */ 319 PJ_DECL(pj_status_t) pjmedia_conf_adjust_rx_level( pjmedia_conf *conf, 320 unsigned slot, 321 int adj_level ); 322 323 324 /** 325 * Adjust the level of signal to be transmitted to the specified port. 326 * Application may adjust the level to make the signal transmitted to the port 327 * either louder or more quiet, by giving the value from +127 to -128. The 328 * value zero indicates no adjustment, the value -128 will mute the signal, 329 * and the value of +127 will make the signal twice as loud. 330 * 331 * @param conf The conference bridge. 332 * @param slot Slot number. 333 * @param adj_level Adjustment level, with valid values are from -128 334 * to +127. A value of zero means there is no level 335 * adjustment to be made, the value -128 will mute the 336 * signal, and the value of +127 will make the signal 337 * twice as loud. 338 * 339 * @return PJ_SUCCESS on success. 340 */ 341 PJ_DECL(pj_status_t) pjmedia_conf_adjust_tx_level( pjmedia_conf *conf, 342 unsigned slot, 343 int adj_level ); 344 227 345 228 346 -
pjproject/trunk/pjmedia/src/pjmedia/conference.c
r322 r323 22 22 #include <pjmedia/resample.h> 23 23 #include <pjmedia/silencedet.h> 24 #include <pjmedia/sound .h>24 #include <pjmedia/sound_port.h> 25 25 #include <pjmedia/stream.h> 26 26 #include <pj/assert.h> … … 47 47 * 48 48 * TX and RX directions are always viewed from the conference bridge's point 49 * of view, and NOT from the port's point of view. 49 * of view, and NOT from the port's point of view. So TX means the bridge 50 * is transmitting to the port, RX means the bridge is receiving from the 51 * port. 50 52 */ 51 53 … … 68 70 unsigned samples_per_frame; /**< Port's samples per frame. */ 69 71 72 /* Calculated signal levels: */ 73 pj_bool_t need_tx_level; /**< Need to calculate tx level? */ 74 unsigned tx_level; /**< Last tx level to this port. */ 75 unsigned rx_level; /**< Last rx level from this port. */ 76 77 /* The normalized signal level adjustment. 78 * A value of 128 means there's no adjustment. 79 */ 80 unsigned tx_adj_level; /**< Adjustment for TX. */ 81 unsigned rx_adj_level; /**< Adjustment for RX. */ 82 70 83 /* Resample, for converting clock rate, if they're different. */ 71 84 pjmedia_resample *rx_resample; … … 74 87 /* RX buffer is temporary buffer to be used when there is mismatch 75 88 * between port's sample rate or ptime with conference's sample rate 76 * or ptime. When both sample rate and ptime of the port match the 77 * conference settings, this buffer will not be used. 89 * or ptime. The buffer is used for sampling rate conversion AND/OR to 90 * buffer the samples until there are enough samples to fulfill a 91 * complete frame to be processed by the bridge. 92 * 93 * When both sample rate AND ptime of the port match the conference 94 * settings, this buffer will not be created. 78 95 * 79 96 * This buffer contains samples at port's clock rate. … … 86 103 87 104 /* Mix buf is a temporary buffer used to calculate the average signal 88 * received by this port from all other ports. 105 * received by this port from all other ports. Samples from all ports 106 * that are transmitting to this port will be accumulated here, then 107 * they will be divided by the sources count before the samples are put 108 * to the TX buffer of this port. 89 109 * 90 110 * This buffer contains samples at bridge's clock rate. … … 98 118 /* Tx buffer is a temporary buffer to be used when there's mismatch 99 119 * between port's clock rate or ptime with conference's sample rate 100 * or ptime. When both sample rate and ptime of the port match the 101 * conference's settings, this buffer will not be used. 120 * or ptime. This buffer is used as the source of the sampling rate 121 * conversion AND/OR to buffer the samples until there are enough 122 * samples to fulfill a complete frame to be transmitted to the port. 123 * 124 * When both sample rate and ptime of the port match the bridge's 125 * settings, this buffer will not be created. 102 126 * 103 127 * This buffer contains samples at port's clock rate. … … 109 133 unsigned tx_buf_count; /**< # of samples in the buffer. */ 110 134 111 /* Snd buffers is a special buffer for sound device port (port 0 ).112 * It's not used by other ports.135 /* Snd buffers is a special buffer for sound device port (port 0, master 136 * port). It's not used by other ports. 113 137 * 114 138 * There are multiple numbers of this buffer, because we can not expect … … 132 156 unsigned port_cnt; /**< Current number of ports. */ 133 157 unsigned connect_cnt; /**< Total number of connections */ 134 pjmedia_snd_stream *snd_rec; /**< Sound recorder stream. */ 135 pjmedia_snd_stream *snd_player; /**< Sound player stream. */ 158 pjmedia_snd_port *snd_rec; /**< Sound recorder stream. */ 159 pjmedia_snd_port *snd_player; /**< Sound player stream. */ 160 pjmedia_port *master_port; /**< Port zero's port. */ 136 161 pj_mutex_t *mutex; /**< Conference mutex. */ 137 162 struct conf_port **ports; /**< Array of ports. */ … … 148 173 149 174 /* Prototypes */ 150 static pj_status_t play_cb( /* in */ void *user_data, 151 /* in */ pj_uint32_t timestamp, 152 /* out */ void *output, 153 /* out */ unsigned size); 154 static pj_status_t rec_cb( /* in */ void *user_data, 155 /* in */ pj_uint32_t timestamp, 156 /* in */ const void *input, 157 /* in*/ unsigned size); 175 static pj_status_t put_frame(pjmedia_port *this_port, 176 const pjmedia_frame *frame); 177 static pj_status_t get_frame(pjmedia_port *this_port, 178 pjmedia_frame *frame); 179 158 180 159 181 /* … … 179 201 conf_port->rx_setting = PJMEDIA_PORT_ENABLE; 180 202 conf_port->tx_setting = PJMEDIA_PORT_ENABLE; 203 204 /* Default level adjustment is 128 (which means no adjustment) */ 205 conf_port->tx_adj_level = 128; 206 conf_port->rx_adj_level = 128; 181 207 182 208 /* Create transmit flag array */ … … 310 336 conf->port_cnt++; 311 337 338 339 /* Create sound devices: */ 340 341 /* Create recorder only if mic is not disabled. */ 342 if ((conf->options & PJMEDIA_CONF_NO_DEVICE) == 0 && 343 (conf->options & PJMEDIA_CONF_NO_MIC) == 0) 344 { 345 status = pjmedia_snd_port_create_rec( pool, -1, conf->clock_rate, 346 conf->channel_count, 347 conf->samples_per_frame, 348 conf->bits_per_sample, 349 0, /* Options */ 350 &conf->snd_rec); 351 if (status != PJ_SUCCESS) { 352 conf->snd_rec = NULL; 353 return status; 354 } 355 } 356 357 /* Create player device */ 358 if ((conf->options & PJMEDIA_CONF_NO_DEVICE) == 0) { 359 status = pjmedia_snd_port_create_player(pool, -1, conf->clock_rate, 360 conf->channel_count, 361 conf->samples_per_frame, 362 conf->bits_per_sample, 363 0, /* options */ 364 &conf->snd_player); 365 if (status != PJ_SUCCESS) { 366 if (conf->snd_rec) { 367 pjmedia_snd_port_destroy(conf->snd_rec); 368 conf->snd_rec = NULL; 369 } 370 conf->snd_player = NULL; 371 return status; 372 } 373 } 374 375 312 376 PJ_LOG(5,(THIS_FILE, "Sound device successfully created for port 0")); 313 377 return PJ_SUCCESS; … … 349 413 conf->max_ports = max_ports; 350 414 conf->clock_rate = clock_rate; 415 conf->channel_count = channel_count; 351 416 conf->samples_per_frame = samples_per_frame; 352 417 conf->bits_per_sample = bits_per_sample; 418 419 420 /* Create and initialize the master port interface. */ 421 conf->master_port = pj_pool_zalloc(pool, sizeof(pjmedia_port)); 422 PJ_ASSERT_RETURN(conf->master_port, PJ_ENOMEM); 423 424 conf->master_port->info.bits_per_sample = bits_per_sample; 425 conf->master_port->info.bytes_per_frame = samples_per_frame * 426 bits_per_sample / 8; 427 conf->master_port->info.channel_count = channel_count; 428 conf->master_port->info.encoding_name = pj_str("pcm"); 429 conf->master_port->info.has_info = 1; 430 conf->master_port->info.name = pj_str("master port"); 431 conf->master_port->info.need_info = 0; 432 conf->master_port->info.pt = 0xFF; 433 conf->master_port->info.sample_rate = clock_rate; 434 conf->master_port->info.samples_per_frame = samples_per_frame; 435 conf->master_port->info.signature = 0; 436 conf->master_port->info.type = PJMEDIA_TYPE_AUDIO; 437 438 conf->master_port->get_frame = &get_frame; 439 conf->master_port->put_frame = &put_frame; 440 441 conf->master_port->user_data = conf; 353 442 354 443 … … 367 456 return status; 368 457 458 /* If sound device was created, connect sound device to the 459 * master port. 460 */ 461 if (conf->snd_player) { 462 status = pjmedia_snd_port_connect( conf->snd_player, 463 conf->master_port ); 464 if (status != PJ_SUCCESS) { 465 pjmedia_conf_destroy(conf); 466 return status; 467 } 468 } 469 470 if (conf->snd_rec) { 471 status = pjmedia_snd_port_connect( conf->snd_rec, 472 conf->master_port); 473 if (status != PJ_SUCCESS) { 474 pjmedia_conf_destroy(conf); 475 return status; 476 } 477 } 478 369 479 370 480 /* Done */ … … 377 487 378 488 /* 379 * Create sound device 380 */ 381 static pj_status_t create_sound( pjmedia_conf *conf ) 382 { 383 pj_status_t status; 384 385 /* Open recorder only if mic is not disabled. */ 386 if ((conf->options & PJMEDIA_CONF_NO_MIC) == 0) { 387 status = pjmedia_snd_open_recorder(-1, conf->clock_rate, 1, 388 conf->samples_per_frame, 389 conf->bits_per_sample, 390 &rec_cb, conf, &conf->snd_rec); 391 if (status != PJ_SUCCESS) { 392 conf->snd_rec = NULL; 393 return status; 394 } 395 } 396 397 /* Open player */ 398 status = pjmedia_snd_open_player(-1, conf->clock_rate, 1, 399 conf->samples_per_frame, 400 conf->bits_per_sample, 401 &play_cb, conf, &conf->snd_player); 402 if (status != PJ_SUCCESS) { 403 if (conf->snd_rec) { 404 pjmedia_snd_stream_close(conf->snd_rec); 405 conf->snd_rec = NULL; 406 } 407 conf->snd_player = NULL; 408 return status; 409 } 410 411 return PJ_SUCCESS; 412 } 413 414 /* 415 * Destroy sound device 416 */ 417 static pj_status_t destroy_sound( pjmedia_conf *conf ) 418 { 419 if (conf->snd_rec) { 420 pjmedia_snd_stream_close(conf->snd_rec); 421 conf->snd_rec = NULL; 422 } 423 if (conf->snd_player) { 424 pjmedia_snd_stream_close(conf->snd_player); 425 conf->snd_player = NULL; 426 } 427 return PJ_SUCCESS; 428 } 429 430 /* 431 * Activate sound device. 489 * Pause sound device. 490 */ 491 static pj_status_t pause_sound( pjmedia_conf *conf ) 492 { 493 /* Do nothing. */ 494 PJ_UNUSED_ARG(conf); 495 return PJ_SUCCESS; 496 } 497 498 /* 499 * Resume sound device. 432 500 */ 433 501 static pj_status_t resume_sound( pjmedia_conf *conf ) 434 502 { 435 char errmsg[PJ_ERR_MSG_SIZE]; 436 pj_status_t status; 437 438 if (conf->snd_player == NULL) { 439 status = create_sound(conf); 440 if (status != PJ_SUCCESS) 441 return status; 442 } 443 444 /* Start recorder. */ 445 if (conf->snd_rec) { 446 status = pjmedia_snd_stream_start(conf->snd_rec); 447 if (status != PJ_SUCCESS) 448 goto on_error; 449 } 450 451 /* Start player. */ 452 if (conf->snd_player) { 453 status = pjmedia_snd_stream_start(conf->snd_player); 454 if (status != PJ_SUCCESS) 455 goto on_error; 456 } 457 458 return PJ_SUCCESS; 459 460 on_error: 461 pj_strerror(status, errmsg, sizeof(errmsg)); 462 PJ_LOG(4,(THIS_FILE, "Error starting sound player/recorder: %s", 463 errmsg)); 464 return status; 503 /* Do nothing. */ 504 PJ_UNUSED_ARG(conf); 505 return PJ_SUCCESS; 465 506 } 466 507 … … 473 514 PJ_ASSERT_RETURN(conf != NULL, PJ_EINVAL); 474 515 475 //suspend_sound(conf); 476 destroy_sound(conf); 516 /* Destroy sound devices. */ 517 if (conf->snd_rec) { 518 pjmedia_snd_port_destroy(conf->snd_rec); 519 conf->snd_rec = NULL; 520 } 521 if (conf->snd_player) { 522 pjmedia_snd_port_destroy(conf->snd_player); 523 conf->snd_player = NULL; 524 } 525 526 /* Destroy mutex */ 477 527 pj_mutex_destroy(conf->mutex); 478 528 479 529 return PJ_SUCCESS; 530 } 531 532 533 /* 534 * Get port zero interface. 535 */ 536 PJ_DEF(pjmedia_port*) pjmedia_conf_get_master_port(pjmedia_conf *conf) 537 { 538 /* Sanity check. */ 539 PJ_ASSERT_RETURN(conf != NULL, NULL); 540 541 /* Can only return port interface when PJMEDIA_CONF_NO_DEVICE was 542 * present in the option. 543 */ 544 PJ_ASSERT_RETURN((conf->options & PJMEDIA_CONF_NO_DEVICE) != 0, NULL); 545 546 return conf->master_port; 480 547 } 481 548 … … 520 587 pj_assert(index != conf->max_ports); 521 588 522 /* Create port structure. */589 /* Create conf port structure. */ 523 590 status = create_conf_port(pool, conf, strm_port, port_name, &conf_port); 524 591 if (status != PJ_SUCCESS) { … … 575 642 PJ_DEF(pj_status_t) pjmedia_conf_connect_port( pjmedia_conf *conf, 576 643 unsigned src_slot, 577 unsigned sink_slot ) 644 unsigned sink_slot, 645 int level ) 578 646 { 579 647 struct conf_port *src_port, *dst_port; … … 587 655 PJ_ASSERT_RETURN(conf->ports[src_slot] != NULL, PJ_EINVAL); 588 656 PJ_ASSERT_RETURN(conf->ports[sink_slot] != NULL, PJ_EINVAL); 657 658 /* For now, level MUST be zero. */ 659 PJ_ASSERT_RETURN(level == 0, PJ_EINVAL); 589 660 590 661 pj_mutex_lock(conf->mutex); … … 659 730 660 731 if (conf->connect_cnt == 0) { 661 destroy_sound(conf);732 pause_sound(conf); 662 733 } 663 734 … … 724 795 /* Stop sound if there's no connection. */ 725 796 if (conf->connect_cnt == 0) { 726 destroy_sound(conf);797 pause_sound(conf); 727 798 } 728 799 … … 780 851 781 852 853 /* 854 * Get signal level. 855 */ 856 PJ_DEF(pj_status_t) pjmedia_conf_get_signal_level( pjmedia_conf *conf, 857 unsigned slot, 858 unsigned *tx_level, 859 unsigned *rx_level) 860 { 861 struct conf_port *conf_port; 862 863 /* Check arguments */ 864 PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL); 865 866 /* Port must be valid. */ 867 PJ_ASSERT_RETURN(conf->ports[slot] != NULL, PJ_EINVAL); 868 869 conf_port = conf->ports[slot]; 870 871 if (tx_level != NULL) { 872 conf_port->need_tx_level = 1; 873 *tx_level = conf_port->tx_level; 874 } 875 876 if (rx_level != NULL) 877 *rx_level = conf_port->rx_level; 878 879 return PJ_SUCCESS; 880 } 881 882 883 /* 884 * Adjust RX level of individual port. 885 */ 886 PJ_DEF(pj_status_t) pjmedia_conf_adjust_rx_level( pjmedia_conf *conf, 887 unsigned slot, 888 int adj_level ) 889 { 890 struct conf_port *conf_port; 891 892 /* Check arguments */ 893 PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL); 894 895 /* Port must be valid. */ 896 PJ_ASSERT_RETURN(conf->ports[slot] != NULL, PJ_EINVAL); 897 898 /* Value must be from -128 to +127 */ 899 PJ_ASSERT_RETURN(adj_level >= -128 && adj_level <= 127, PJ_EINVAL); 900 901 conf_port = conf->ports[slot]; 902 903 /* Set normalized adjustment level. */ 904 conf_port->rx_adj_level = adj_level + 128; 905 906 return PJ_SUCCESS; 907 } 908 909 910 /* 911 * Adjust TX level of individual port. 912 */ 913 PJ_DEF(pj_status_t) pjmedia_conf_adjust_tx_level( pjmedia_conf *conf, 914 unsigned slot, 915 int adj_level ) 916 { 917 struct conf_port *conf_port; 918 919 /* Check arguments */ 920 PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL); 921 922 /* Port must be valid. */ 923 PJ_ASSERT_RETURN(conf->ports[slot] != NULL, PJ_EINVAL); 924 925 /* Value must be from -128 to +127 */ 926 PJ_ASSERT_RETURN(adj_level >= -128 && adj_level <= 127, PJ_EINVAL); 927 928 conf_port = conf->ports[slot]; 929 930 /* Set normalized adjustment level. */ 931 conf_port->tx_adj_level = adj_level + 128; 932 933 return PJ_SUCCESS; 934 } 935 936 782 937 /* Convert signed 16bit pcm sample to unsigned 16bit sample */ 783 938 static pj_uint16_t pcm2unsigned(pj_int32_t pcm) … … 925 1080 pjmedia_port_put_frame(cport->port, &frame); 926 1081 1082 cport->tx_level = 0; 927 1083 return PJ_SUCCESS; 928 1084 929 1085 } else if (cport->tx_setting != PJMEDIA_PORT_ENABLE) { 1086 cport->tx_level = 0; 930 1087 return PJ_SUCCESS; 931 1088 } … … 934 1091 * to the mixed samples itself. This is possible because mixed sample 935 1092 * is 32bit. 1093 * 1094 * In addition to this process, if we need to change the level of 1095 * TX signal, we adjust is here too. 936 1096 */ 937 1097 buf = (pj_int16_t*)cport->mix_buf; 938 for (j=0; j<conf->samples_per_frame; ++j) { 939 buf[j] = unsigned2pcm(cport->mix_buf[j] / cport->sources); 1098 1099 if (cport->tx_adj_level != 128) { 1100 1101 unsigned adj_level = cport->tx_adj_level; 1102 1103 /* We need to adjust signal level. */ 1104 for (j=0; j<conf->samples_per_frame; ++j) { 1105 pj_int32_t itemp; 1106 1107 /* Calculate average level, and convert the sample to 1108 * 16bit signed integer. 1109 */ 1110 itemp = unsigned2pcm(cport->mix_buf[j] / cport->sources); 1111 1112 /* Adjust the level */ 1113 itemp = itemp * adj_level / 128; 1114 1115 /* Clip the signal if it's too loud */ 1116 if (itemp > 32767) itemp = 32767; 1117 else if (itemp < -32768) itemp = -32768; 1118 1119 /* Put back in the buffer. */ 1120 buf[j] = (pj_int16_t) itemp; 1121 } 1122 1123 } else { 1124 /* No need to adjust signal level. */ 1125 for (j=0; j<conf->samples_per_frame; ++j) { 1126 buf[j] = unsigned2pcm(cport->mix_buf[j] / cport->sources); 1127 } 1128 } 1129 1130 /* Calculate TX level if we need to do so. 1131 * This actually is not the most correct place to calculate TX signal 1132 * level of the port; it should calculate the level of the actual 1133 * frame just before put_frame() is called. 1134 * But doing so would make the code more complicated than it is 1135 * necessary, since the purpose of level calculation mostly is just 1136 * for VU meter display. By doing it here, it should give the acceptable 1137 * indication of the signal level of the port. 1138 */ 1139 if (cport->need_tx_level) { 1140 pj_uint32_t level; 1141 1142 /* Get the signal level. */ 1143 level = pjmedia_calc_avg_signal(buf, conf->samples_per_frame); 1144 1145 /* Convert level to 8bit complement ulaw */ 1146 cport->tx_level = linear2ulaw(level) ^ 0xff; 1147 1148 } else { 1149 cport->tx_level = 0; 940 1150 } 941 1151 … … 1013 1223 * Player callback. 1014 1224 */ 1015 static pj_status_t play_cb( /* in */ void *user_data, 1016 /* in */ pj_uint32_t timestamp, 1017 /* out */ void *output, 1018 /* out */ unsigned size) 1019 { 1020 pjmedia_conf *conf = user_data; 1225 static pj_status_t get_frame(pjmedia_port *this_port, 1226 pjmedia_frame *frame) 1227 { 1228 pjmedia_conf *conf = this_port->user_data; 1021 1229 unsigned ci, cj, i, j; 1022 1230 1023 PJ_UNUSED_ARG(timestamp); 1024 PJ_UNUSED_ARG(size); 1025 1231 /* Check that correct size is specified. */ 1232 pj_assert(frame->size == conf->samples_per_frame * 1233 conf->bits_per_sample / 8); 1234 1235 /* Must lock mutex (must we??) */ 1026 1236 pj_mutex_lock(conf->mutex); 1027 1237 … … 1057 1267 continue; 1058 1268 1269 /* Var "ci" is to count how many ports have been visited so far. */ 1059 1270 ++ci; 1060 1271 1061 1272 /* Skip if we're not allowed to receive from this port. */ 1062 1273 if (conf_port->rx_setting == PJMEDIA_PORT_DISABLE) { 1274 conf_port->rx_level = 0; 1063 1275 continue; 1064 1276 } 1065 1277 1066 1278 /* Also skip if this port doesn't have listeners. */ 1067 if (conf_port->listener_cnt == 0) 1279 if (conf_port->listener_cnt == 0) { 1280 conf_port->rx_level = 0; 1068 1281 continue; 1282 } 1069 1283 1070 1284 /* Get frame from this port. … … 1083 1297 /* Skip if this port is muted/disabled. */ 1084 1298 if (conf_port->rx_setting != PJMEDIA_PORT_ENABLE) { 1299 conf_port->rx_level = 0; 1085 1300 continue; 1086 1301 } 1087 1302 1088 1089 /* Skip if no port is listening to the microphone */1090 if (conf_port->listener_cnt == 0) {1091 continue;1092 }1093 1094 1303 snd_buf = conf_port->snd_buf[conf_port->snd_read_pos]; 1095 1304 for (j=0; j<conf->samples_per_frame; ++j) { 1096 ((pj_int16_t*) output)[j] = snd_buf[j];1305 ((pj_int16_t*)frame->buf)[j] = snd_buf[j]; 1097 1306 } 1098 1307 conf_port->snd_read_pos = (conf_port->snd_read_pos+1) % RX_BUF_COUNT; … … 1103 1312 pjmedia_frame_type frame_type; 1104 1313 1105 status = read_port(conf, conf_port, output,1314 status = read_port(conf, conf_port, frame->buf, 1106 1315 conf->samples_per_frame, &frame_type); 1107 1316 … … 1117 1326 } 1118 1327 1119 /* Get the signal level. */ 1120 level = pjmedia_calc_avg_signal(output, conf->samples_per_frame); 1328 /* If we need to adjust the RX level from this port, adjust the level 1329 * and calculate the average level at the same time. 1330 * Otherwise just calculate the averate level. 1331 */ 1332 if (conf_port->rx_adj_level != 128) { 1333 pj_int16_t *input = frame->buf; 1334 pj_int32_t adj = conf_port->rx_adj_level; 1335 1336 level = 0; 1337 for (j=0; j<conf->samples_per_frame; ++j) { 1338 pj_int32_t itemp; 1339 1340 /* For the level adjustment, we need to store the sample to 1341 * a temporary 32bit integer value to avoid overflowing the 1342 * 16bit sample storage. 1343 */ 1344 itemp = input[j]; 1345 itemp = itemp * adj / 128; 1346 1347 /* Clip the signal if it's too loud */ 1348 if (itemp > 32767) itemp = 32767; 1349 else if (itemp < -32768) itemp = -32768; 1350 1351 input[j] = (pj_int16_t) itemp; 1352 level += itemp; 1353 } 1354 1355 level /= conf->samples_per_frame; 1356 1357 } else { 1358 level = pjmedia_calc_avg_signal(frame->buf, 1359 conf->samples_per_frame); 1360 } 1121 1361 1122 1362 /* Convert level to 8bit complement ulaw */ 1123 1363 level = linear2ulaw(level) ^ 0xff; 1124 1364 1365 /* Put this level to port's last RX level. */ 1366 conf_port->rx_level = level; 1367 1125 1368 /* Convert the buffer to unsigned 16bit value */ 1126 1369 for (j=0; j<conf->samples_per_frame; ++j) 1127 conf->uns_buf[j] = pcm2unsigned(((pj_int16_t*) output)[j]);1370 conf->uns_buf[j] = pcm2unsigned(((pj_int16_t*)frame->buf)[j]); 1128 1371 1129 1372 /* Add the signal to all listeners. */ … … 1143 1386 continue; 1144 1387 1388 /* Var "cj" is the number of listeners we have visited so far */ 1145 1389 ++cj; 1146 1390 … … 1158 1402 } 1159 1403 1160 /* For all ports, calculate avg signal. */ 1404 /* Time for all ports to transmit whetever they have in their 1405 * buffer. 1406 */ 1161 1407 for (i=0, ci=0; i<conf->max_ports && ci<conf->port_cnt; ++i) { 1162 1408 struct conf_port *conf_port = conf->ports[i]; … … 1166 1412 continue; 1167 1413 1414 /* Var "ci" is to count how many ports have been visited. */ 1168 1415 ++ci; 1169 1416 1170 status = write_port( conf, conf_port, timestamp);1417 status = write_port( conf, conf_port, frame->timestamp.u32.lo); 1171 1418 if (status != PJ_SUCCESS) { 1172 1419 PJ_LOG(4,(THIS_FILE, "Port %.*s put_frame() returned %d. " … … 1182 1429 /* Return sound playback frame. */ 1183 1430 if (conf->ports[0]->sources) { 1184 copy_samples( output, (pj_int16_t*)conf->ports[0]->mix_buf,1431 copy_samples( frame->buf, (pj_int16_t*)conf->ports[0]->mix_buf, 1185 1432 conf->samples_per_frame); 1186 1433 } else { 1187 zero_samples( output, conf->samples_per_frame );1434 zero_samples( frame->buf, conf->samples_per_frame ); 1188 1435 } 1189 1436 … … 1197 1444 * Recorder callback. 1198 1445 */ 1199 static pj_status_t rec_cb( /* in */ void *user_data, 1200 /* in */ pj_uint32_t timestamp, 1201 /* in */ const void *input, 1202 /* in */ unsigned size) 1203 { 1204 pjmedia_conf *conf = user_data; 1446 static pj_status_t put_frame(pjmedia_port *this_port, 1447 const pjmedia_frame *frame) 1448 { 1449 pjmedia_conf *conf = this_port->user_data; 1205 1450 struct conf_port *snd_port = conf->ports[0]; 1451 const pj_int16_t *input = frame->buf; 1206 1452 pj_int16_t *target_snd_buf; 1207 1453 unsigned i; 1208 1454 1209 PJ_UNUSED_ARG(timestamp);1210 1211 1455 TRACE_(("r")); 1212 1456 1213 if (size != conf->samples_per_frame*2) { 1214 TRACE_(("rxerr ")); 1215 } 1457 /* Check for correct size. */ 1458 PJ_ASSERT_RETURN( frame->size == conf->samples_per_frame * 1459 conf->bits_per_sample / 8, 1460 PJMEDIA_ENCSAMPLESPFRAME); 1216 1461 1217 1462 /* Skip if this port is muted/disabled. */ -
pjproject/trunk/pjmedia/src/pjmedia/resample.c
r299 r323 20 20 /* 21 21 * Based on: 22 * resample-1.2.tar.Z (from ftp://ccrma-ftp.stanford.edu/pub/NeXT) 22 * resample-1.8.tar.gz from the 23 * Digital Audio Resampling Home Page located at 24 * http://www-ccrma.stanford.edu/~jos/resample/. 25 * 23 26 * SOFTWARE FOR SAMPLING-RATE CONVERSION AND FIR DIGITAL FILTER DESIGN 24 27 * 25 * COPYING 26 * 27 * This software package is Copyright 1994 by Julius O. Smith 28 * (jos@ccrma.stanford.edu), all rights reserved. Permission to use and copy 29 * is granted subject to the terms of the "GNU Software General Public 30 * License" (see ftp://prep.ai.mit.edu/pub/gnu/COPYING). In addition, we 31 * request that a copy of any modified files be sent by email to 32 * jos@ccrma.stanford.edu so that we may incorporate them in the CCRMA 33 * version. 28 * Snippet from the resample.1 man page: 29 * 30 * HISTORY 31 * 32 * The first version of this software was written by Julius O. Smith III 33 * <jos@ccrma.stanford.edu> at CCRMA <http://www-ccrma.stanford.edu> in 34 * 1981. It was called SRCONV and was written in SAIL for PDP-10 35 * compatible machines. The algorithm was first published in 36 * 37 * Smith, Julius O. and Phil Gossett. ``A Flexible Sampling-Rate 38 * Conversion Method,'' Proceedings (2): 19.4.1-19.4.4, IEEE Conference 39 * on Acoustics, Speech, and Signal Processing, San Diego, March 1984. 40 * 41 * An expanded tutorial based on this paper is available at the Digital 42 * Audio Resampling Home Page given above. 43 * 44 * Circa 1988, the SRCONV program was translated from SAIL to C by 45 * Christopher Lee Fraley working with Roger Dannenberg at CMU. 46 * 47 * Since then, the C version has been maintained by jos. 48 * 49 * Sndlib support was added 6/99 by John Gibson <jgg9c@virginia.edu>. 50 * 51 * The resample program is free software distributed in accordance 52 * with the Lesser GNU Public License (LGPL). There is NO warranty; not 53 * even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 34 54 */ 35 55 -
pjproject/trunk/pjsip-apps/src/pjsua/main.c
r315 r323 813 813 status = pjmedia_conf_connect_port(pjsua.mconf, 814 814 atoi(src_port), 815 atoi(dst_port)); 815 atoi(dst_port), 816 0); 816 817 } else { 817 818 status = pjmedia_conf_disconnect_port(pjsua.mconf, -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
r305 r323 962 962 963 963 pjmedia_conf_connect_port( pjsua.mconf, pjsua.wav_slot, 964 call->conf_slot );964 call->conf_slot, 0); 965 965 966 966 } else if (pjsua.auto_loop && call->inv->role == PJSIP_ROLE_UAS) { 967 967 968 968 pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot, 969 call->conf_slot );969 call->conf_slot, 0); 970 970 971 971 } else if (pjsua.auto_conf) { … … 973 973 int i; 974 974 975 pjmedia_conf_connect_port( pjsua.mconf, 0, call->conf_slot );976 pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot, 0 );975 pjmedia_conf_connect_port( pjsua.mconf, 0, call->conf_slot, 0); 976 pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot, 0, 0); 977 977 978 978 for (i=0; i < pjsua.max_calls; ++i) { … … 982 982 983 983 pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot, 984 pjsua.calls[i].conf_slot );984 pjsua.calls[i].conf_slot, 0); 985 985 pjmedia_conf_connect_port( pjsua.mconf, pjsua.calls[i].conf_slot, 986 call->conf_slot );986 call->conf_slot, 0); 987 987 } 988 988 … … 992 992 * main conference bridge. 993 993 */ 994 pjmedia_conf_connect_port( pjsua.mconf, 0, call->conf_slot );995 pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot, 0 );994 pjmedia_conf_connect_port( pjsua.mconf, 0, call->conf_slot, 0); 995 pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot, 0, 0); 996 996 } 997 997
Note: See TracChangeset
for help on using the changeset viewer.