- Timestamp:
- Mar 19, 2006 12:09:53 PM (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip-apps/src/samples/confsample.c
r336 r337 40 40 * DESCRIPTION: 41 41 * 42 * Here we create a conference bridge, with at least two ports: 43 * - port zero is for the sound device (capture and play), 44 * - port one is to play a generated sine wave. 42 * Here we create a conference bridge, with at least one port (port zero 43 * is always created for the sound device). 45 44 * 46 45 * If WAV files are specified, the WAV file player ports will be connected 47 * to slot starting from number twoin the bridge. The WAV files can have48 * arbitrary sampling rate; the bridge will convert the samples to its clock49 * rate.However, the files MUST have a single audio channel only (i.e. mono).46 * to slot starting from number one in the bridge. The WAV files can have 47 * arbitrary sampling rate; the bridge will convert it to its clock rate. 48 * However, the files MUST have a single audio channel only (i.e. mono). 50 49 */ 51 50 … … 81 80 printf("%s: %s [code=%d]\n", title, errmsg, status); 82 81 return 1; 83 }84 85 86 /* Struct attached to sine generator */87 typedef struct88 {89 pj_int16_t *samples; /* Sine samples. */90 } port_data;91 92 93 /* This callback is called to feed sine wave samples from the sine94 * generator.95 */96 static pj_status_t sine_get_frame( pjmedia_port *port,97 pjmedia_frame *frame)98 {99 port_data *sine = port->user_data;100 pj_int16_t *samples = frame->buf;101 unsigned i, count, left, right;102 103 /* Get number of samples */104 count = frame->size / 2 / port->info.channel_count;105 106 left = 0;107 right = 0;108 109 for (i=0; i<count; ++i) {110 *samples++ = sine->samples[left];111 ++left;112 113 if (port->info.channel_count == 2) {114 *samples++ = sine->samples[right];115 right += 2; /* higher pitch so we can distinguish left and right. */116 if (right >= count)117 right = 0;118 }119 }120 121 /* Must set frame->type correctly, otherwise the sound device122 * will refuse to play.123 */124 frame->type = PJMEDIA_FRAME_TYPE_AUDIO;125 126 return PJ_SUCCESS;127 }128 129 #ifndef M_PI130 #define M_PI (3.14159265)131 #endif132 133 /*134 * Create a media port to generate sine wave samples.135 */136 static pj_status_t create_sine_port(pj_pool_t *pool,137 unsigned sampling_rate,138 unsigned channel_count,139 pjmedia_port **p_port)140 {141 pjmedia_port *port;142 unsigned i;143 unsigned count;144 port_data *sine;145 146 PJ_ASSERT_RETURN(pool && channel_count > 0 && channel_count <= 2,147 PJ_EINVAL);148 149 port = pj_pool_zalloc(pool, sizeof(pjmedia_port));150 PJ_ASSERT_RETURN(port != NULL, PJ_ENOMEM);151 152 /* Fill in port info. */153 port->info.bits_per_sample = 16;154 port->info.channel_count = channel_count;155 port->info.encoding_name = pj_str("pcm");156 port->info.has_info = 1;157 port->info.name = pj_str("sine generator");158 port->info.need_info = 0;159 port->info.pt = 0xFF;160 port->info.sample_rate = sampling_rate;161 port->info.samples_per_frame = sampling_rate * 20 / 1000 * channel_count;162 port->info.bytes_per_frame = port->info.samples_per_frame * 2;163 port->info.type = PJMEDIA_TYPE_AUDIO;164 165 /* Set the function to feed frame */166 port->get_frame = &sine_get_frame;167 168 /* Create sine port data */169 port->user_data = sine = pj_pool_zalloc(pool, sizeof(port_data));170 171 /* Create samples */172 count = port->info.samples_per_frame / channel_count;173 sine->samples = pj_pool_alloc(pool, count * sizeof(pj_int16_t));174 PJ_ASSERT_RETURN(sine->samples != NULL, PJ_ENOMEM);175 176 /* initialise sinusoidal wavetable */177 for( i=0; i<count; i++ )178 {179 sine->samples[i] = (pj_int16_t) (8000.0 *180 sin(((double)i/(double)count) * M_PI * 8.) );181 }182 183 *p_port = port;184 185 return PJ_SUCCESS;186 82 } 187 83 … … 202 98 203 99 /* Input simple string */ 204 static pj_bool_t simple_input(const char *title, char *buf, pj_size_t len)100 static pj_bool_t input(const char *title, char *buf, pj_size_t len) 205 101 { 206 102 char *p; … … 231 127 pj_pool_t *pool; 232 128 pjmedia_conf *conf; 233 pjmedia_port *sine_port; 234 235 int i, file_count; 129 130 int i, port_count, file_count; 236 131 pjmedia_port **file_port; /* Array of file ports */ 237 132 … … 270 165 271 166 167 file_count = argc-1; 168 port_count = file_count + 1; 169 272 170 /* Create the conference bridge. 273 171 * With default options (zero), the bridge will create an instance of … … 275 173 */ 276 174 status = pjmedia_conf_create( pool, /* pool to use */ 277 2+argc-1,/* number of ports */175 port_count,/* number of ports */ 278 176 16000, /* sampling rate */ 279 177 1, /* # of channels. */ … … 289 187 290 188 291 /* Create a media port to generate sine wave samples. */292 status = create_sine_port( pool, /* memory pool */293 11025, /* sampling rate */294 1, /* # of channels */295 &sine_port /* returned port */296 );297 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);298 299 300 /* Add the sine generator port to the conference bridge. */301 status = pjmedia_conf_add_port(conf, /* the conference bridge */302 pool, /* pool */303 sine_port, /* the sine generator */304 NULL, /* use port's name */305 NULL /* ptr to receive slot # */306 );307 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);308 309 310 311 189 /* Create file ports. */ 312 file_count = argc-1;313 190 file_port = pj_pool_alloc(pool, file_count * sizeof(pjmedia_port*)); 314 191 … … 391 268 puts(""); 392 269 puts("Connect source port to destination port"); 393 if (! simple_input("Enter source port number", tmp1, sizeof(tmp1)) )270 if (!input("Enter source port number", tmp1, sizeof(tmp1)) ) 394 271 continue; 395 272 src = strtol(tmp1, &err, 10); 396 if (*err || src < 0 || src > file_count+2) {397 puts("Invalid slot number"); 398 continue; 399 } 400 401 if (! simple_input("Enter destination port number", tmp2, sizeof(tmp2)) )273 if (*err || src < 0 || src >= port_count) { 274 puts("Invalid slot number"); 275 continue; 276 } 277 278 if (!input("Enter destination port number", tmp2, sizeof(tmp2)) ) 402 279 continue; 403 280 dst = strtol(tmp2, &err, 10); 404 if (*err || dst < 0 || dst >= file_count+2) {281 if (*err || dst < 0 || dst >= port_count) { 405 282 puts("Invalid slot number"); 406 283 continue; … … 416 293 puts(""); 417 294 puts("Disconnect port connection"); 418 if (! simple_input("Enter source port number", tmp1, sizeof(tmp1)) )295 if (!input("Enter source port number", tmp1, sizeof(tmp1)) ) 419 296 continue; 420 297 src = strtol(tmp1, &err, 10); 421 if (*err || src < 0 || src > file_count+2) {422 puts("Invalid slot number"); 423 continue; 424 } 425 426 if (! simple_input("Enter destination port number", tmp2, sizeof(tmp2)) )298 if (*err || src < 0 || src >= port_count) { 299 puts("Invalid slot number"); 300 continue; 301 } 302 303 if (!input("Enter destination port number", tmp2, sizeof(tmp2)) ) 427 304 continue; 428 305 dst = strtol(tmp2, &err, 10); 429 if (*err || dst < 0 || dst >= file_count+2) {306 if (*err || dst < 0 || dst >= port_count) { 430 307 puts("Invalid slot number"); 431 308 continue; … … 442 319 puts(""); 443 320 puts("Adjust transmit level of a port"); 444 if (! simple_input("Enter port number", tmp1, sizeof(tmp1)) )321 if (!input("Enter port number", tmp1, sizeof(tmp1)) ) 445 322 continue; 446 323 src = strtol(tmp1, &err, 10); 447 if (*err || src < 0 || src > file_count+2) {448 puts("Invalid slot number"); 449 continue; 450 } 451 452 if (! simple_input("Enter level (-128 to +127, 0 for normal)",324 if (*err || src < 0 || src >= port_count) { 325 puts("Invalid slot number"); 326 continue; 327 } 328 329 if (!input("Enter level (-128 to +127, 0 for normal)", 453 330 tmp2, sizeof(tmp2)) ) 454 331 continue; … … 468 345 puts(""); 469 346 puts("Adjust receive level of a port"); 470 if (! simple_input("Enter port number", tmp1, sizeof(tmp1)) )347 if (!input("Enter port number", tmp1, sizeof(tmp1)) ) 471 348 continue; 472 349 src = strtol(tmp1, &err, 10); 473 if (*err || src < 0 || src > file_count+2) {474 puts("Invalid slot number"); 475 continue; 476 } 477 478 if (! simple_input("Enter level (-128 to +127, 0 for normal)",350 if (*err || src < 0 || src >= port_count) { 351 puts("Invalid slot number"); 352 continue; 353 } 354 355 if (!input("Enter level (-128 to +127, 0 for normal)", 479 356 tmp2, sizeof(tmp2)) ) 480 357 continue; … … 493 370 puts(""); 494 371 puts("Display VU meter"); 495 if (! simple_input("Enter port number to monitor", tmp1, sizeof(tmp1)) )372 if (!input("Enter port number to monitor", tmp1, sizeof(tmp1)) ) 496 373 continue; 497 374 src = strtol(tmp1, &err, 10); 498 if (*err || src < 0 || src > file_count+2) {499 puts("Invalid slot number"); 500 continue; 501 } 502 503 if (! simple_input("Enter r for rx level or t for tx level", tmp2, sizeof(tmp2)))375 if (*err || src < 0 || src >= port_count) { 376 puts("Invalid slot number"); 377 continue; 378 } 379 380 if (!input("Enter r for rx level or t for tx level", tmp2, sizeof(tmp2))) 504 381 continue; 505 382 if (tmp2[0] != 'r' && tmp2[0] != 't') { … … 508 385 } 509 386 510 if (! simple_input("Duration to monitor (in seconds)", tmp1, sizeof(tmp1)) )387 if (!input("Duration to monitor (in seconds)", tmp1, sizeof(tmp1)) ) 511 388 continue; 512 389 strtol(tmp1, &err, 10); … … 542 419 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 543 420 } 544 545 /* Destroy sine generator port */546 status = pjmedia_port_destroy( sine_port );547 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);548 421 549 422 /* Release application pool */ … … 636 509 static void monitor_level(pjmedia_conf *conf, int slot, int dir, int dur) 637 510 { 638 enum { SLEEP = 100};511 enum { SLEEP = 20, SAMP_CNT = 2}; 639 512 pj_status_t status; 640 int i, count; 513 int i, total_count; 514 unsigned level, samp_cnt; 515 641 516 642 517 puts(""); … … 644 519 slot, dur); 645 520 646 count = dur * 1000 / SLEEP; 647 648 for (i=0; i<count; ++i) { 521 total_count = dur * 1000 / SLEEP; 522 523 level = 0; 524 samp_cnt = 0; 525 526 for (i=0; i<total_count; ++i) { 649 527 unsigned tx_level, rx_level; 650 int j, le vel;528 int j, length; 651 529 char meter[21]; 652 530 531 /* Poll the volume every 20 msec */ 653 532 status = pjmedia_conf_get_signal_level(conf, slot, 654 533 &tx_level, &rx_level); … … 658 537 } 659 538 660 level = 20 * (dir=='r'?rx_level:tx_level) / 255; 661 for (j=0; j<level; ++j) 539 level += (dir=='r' ? rx_level : tx_level); 540 ++samp_cnt; 541 542 /* Accumulate until we have enough samples */ 543 if (samp_cnt < SAMP_CNT) { 544 pj_thread_sleep(SLEEP); 545 continue; 546 } 547 548 /* Get average */ 549 level = level / samp_cnt; 550 551 /* Draw bar */ 552 length = 20 * level / 255; 553 for (j=0; j<length; ++j) 662 554 meter[j] = '#'; 663 555 for (; j<20; ++j) … … 665 557 meter[20] = '\0'; 666 558 667 printf("Port #%02d %cx level: [%s]\r", 668 slot, dir, meter); 559 printf("Port #%02d %cx level: [%s] %d \r", 560 slot, dir, meter, level); 561 562 /* Next.. */ 563 samp_cnt = 0; 564 level = 0; 669 565 670 566 pj_thread_sleep(SLEEP);
Note: See TracChangeset
for help on using the changeset viewer.