Changeset 1972 for pjproject/trunk
- Timestamp:
- May 30, 2008 11:30:24 AM (16 years ago)
- Location:
- pjproject/trunk/pjmedia
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/include/pjmedia/delaybuf.h
r1833 r1972 69 69 * @param clock_rate Number of samples processed per second. 70 70 * @param samples_per_frame Number of samples per frame. 71 * @param max_frames Maximum number of delay to be accommodated, 72 * in number of frames. 73 * @param delay The delay to be applied, in number of frames. 74 * If the value is -1 or 0, the delay buffer will 75 * learn about the delay automatically. If 76 * the value is greater than zero, then this 77 * value will be used and no learning will be 78 * performed. 71 * @param channel_count Number of channel per frame. 72 * @param max_delay Maximum number of delay to be accommodated, 73 * in ms, if this value is negative or less than 74 * one frame time, default maximum delay used is 75 * 400 ms. 79 76 * @param option Option flags, must be zero for now. 80 77 * @param p_b Pointer to receive the delay buffer instance. … … 88 85 unsigned clock_rate, 89 86 unsigned samples_per_frame, 90 unsigned max_frames,91 intdelay,87 unsigned channel_count, 88 unsigned max_delay, 92 89 unsigned options, 93 90 pjmedia_delay_buf **p_b); … … 128 125 129 126 /** 130 * Reinitiate learning state. This will clear the buffer's content.131 *132 * @param b The delay buffer.133 *134 * @return PJ_SUCCESS on success or the appropriate error.135 */136 PJ_DECL(pj_status_t) pjmedia_delay_buf_learn(pjmedia_delay_buf *b);137 138 /**139 127 * Reset delay buffer. This will clear the buffer's content. But keep 140 128 * the learning result. -
pjproject/trunk/pjmedia/src/pjmedia/conference.c
r1929 r1972 419 419 struct conf_port *conf_port; 420 420 pj_status_t status; 421 unsigned ptime; 421 422 422 423 /* Create port */ … … 426 427 427 428 /* Passive port has delay buf. */ 429 ptime = conf->samples_per_frame * 1000 / conf->clock_rate / 430 conf->channel_count; 428 431 status = pjmedia_delay_buf_create(pool, name->ptr, 429 432 conf->clock_rate, 430 433 conf->samples_per_frame, 431 RX_BUF_COUNT, /* max */432 -1, /*delay */434 conf->channel_count, 435 RX_BUF_COUNT * ptime, /* max delay */ 433 436 0, /* options */ 434 437 &conf_port->delay_buf); -
pjproject/trunk/pjmedia/src/pjmedia/delaybuf.c
r1847 r1972 24 24 #include <pj/lock.h> 25 25 #include <pj/log.h> 26 #include <pj/math.h> 26 27 #include <pj/pool.h> 27 28 … … 33 34 #endif 34 35 35 36 /* Type of states of delay buffer */ 37 enum state 38 { 39 STATE_WAITING, 40 STATE_LEARNING, 41 STATE_RUNNING 36 /* Operation types of delay buffer */ 37 enum OP 38 { 39 OP_PUT, 40 OP_GET 42 41 }; 43 42 44 /* Type of operation of delay buffer */ 45 enum OP 46 { 47 OP_PUT, 48 OP_GET, 49 OP_UNDEFINED 50 }; 51 52 /* The following macros represent cycles of test. Since there are two 53 * operations performed (get & put), these macros minimum value must be 2 54 * and should be even number. 55 */ 56 #define WAITING_COUNT 4 57 #define LEARN_COUNT 16 58 59 /* Number of buffers to add to learnt level for additional stability 60 * Please note that wsola_discard() needs minimum 3 frames, so max buffer 61 * count should be minimally 3, setting SAFE_MARGIN to 2 will guarantees 62 * this. 63 */ 64 #define SAFE_MARGIN 2 65 66 /* 67 * Some experimental data (with SAFE_MARGIN=1): 68 * 69 * System 1: 70 * - XP, WMME, 10ms ptime, 71 * - Sennheiser Headset+USB sound card 72 * - Stable delaybuf level: 6, on WAITING_COUNT=4 and LEARNING_COUNT=48 73 * 74 * System 2: 75 * - XP, WMME, 10ms ptime 76 * - Onboard SoundMAX Digital Audio 77 * - Stable delaybuf level: 6, on WAITING_COUNT=4 and LEARNING_COUNT=48 78 * 79 * System 3: 80 * - MacBook Core 2 Duo, OSX 10.5, 10ms ptime 81 * - Stable delaybuf level: 2, on WAITING_COUNT=4 and LEARNING_COUNT=8 82 */ 83 43 /* Specify time for delaybuf to recalculate effective delay, in ms. 44 */ 45 #define RECALC_TIME 2000 46 47 /* Default value of maximum delay, in ms, this value is used when 48 * maximum delay requested is less than ptime (one frame length). 49 */ 50 #define DEFAULT_MAX_DELAY 400 51 52 /* Number of frames to add to learnt level for additional stability. 53 */ 54 #define SAFE_MARGIN 0 55 56 /* This structure describes internal delaybuf settings and states. 57 */ 84 58 struct pjmedia_delay_buf 85 59 { 60 /* Properties and configuration */ 86 61 char obj_name[PJ_MAX_OBJ_NAME]; 87 88 62 pj_lock_t *lock; /**< Lock object. */ 89 90 63 pj_int16_t *frame_buf; 91 enum state state; /**< State of delay buffer */92 64 unsigned samples_per_frame; /**< Number of samples in one frame */ 93 unsigned max_frames; /**< Buffer allocated, in frames */ 94 65 unsigned ptime; /**< Frame time, in ms */ 66 unsigned channel_count; /**< Channel count, in ms */ 67 unsigned max_cnt; /**< Max buffered samples, in samples*/ 68 69 /* Buffer pointer and counter */ 95 70 unsigned put_pos; /**< Position for put op, in samples */ 96 71 unsigned get_pos; /**< Position for get op, in samples */ 97 72 unsigned buf_cnt; /**< Number of buffered samples */ 98 unsigned max_cnt; /**< Max number of buffered samples */ 99 100 struct { 101 unsigned level; /**< Burst level storage on learning */ 102 } op[2]; 73 unsigned eff_cnt; /**< Effective count of buffered 74 samples to keep the optimum 75 balance between delay and 76 stability. This is calculated 77 based on burst level. */ 78 79 /* Learning vars */ 80 unsigned level; /**< Burst level counter */ 103 81 enum OP last_op; /**< Last op (GET or PUT) of learning*/ 104 unsigned state_count; /**< Counter of op cycles of learning*/105 106 unsigned max_level; /**< Learning result: burst level */ 107 82 int recalc_timer; /**< Timer for recalculating max_level*/ 83 unsigned max_level; /**< Current max burst level */ 84 85 /* Drift handler */ 108 86 pjmedia_wsola *wsola; /**< Drift handler */ 109 87 }; 88 110 89 111 90 PJ_DEF(pj_status_t) pjmedia_delay_buf_create( pj_pool_t *pool, … … 113 92 unsigned clock_rate, 114 93 unsigned samples_per_frame, 115 unsigned max_frames,116 intdelay,94 unsigned channel_count, 95 unsigned max_delay, 117 96 unsigned options, 118 97 pjmedia_delay_buf **p_b) … … 121 100 pj_status_t status; 122 101 123 PJ_ASSERT_RETURN(pool && samples_per_frame && max_frames && p_b, PJ_EINVAL);124 PJ_ASSERT_RETURN((int)max_frames >= delay, PJ_EINVAL);102 PJ_ASSERT_RETURN(pool && samples_per_frame && clock_rate && channel_count && 103 p_b, PJ_EINVAL); 125 104 PJ_ASSERT_RETURN(options==0, PJ_EINVAL); 126 105 … … 134 113 135 114 pj_ansi_strncpy(b->obj_name, name, PJ_MAX_OBJ_NAME-1); 115 136 116 b->samples_per_frame = samples_per_frame; 137 b->max_frames = max_frames; 117 b->channel_count = channel_count; 118 b->ptime = samples_per_frame * 1000 / clock_rate / channel_count; 119 if (max_delay < b->ptime) 120 max_delay = PJ_MAX(DEFAULT_MAX_DELAY, b->ptime); 121 122 b->max_cnt = samples_per_frame * max_delay / b->ptime; 123 b->eff_cnt = b->max_cnt >> 1; 124 b->recalc_timer = RECALC_TIME; 138 125 139 126 status = pj_lock_create_recursive_mutex(pool, b->obj_name, … … 143 130 144 131 b->frame_buf = (pj_int16_t*) 145 pj_pool_zalloc(pool, samples_per_frame * max_frames * 146 sizeof(pj_int16_t)); 147 148 if (delay >= 0) { 149 if (delay == 0) 150 delay = 1; 151 b->max_level = delay; 152 b->max_cnt = delay * samples_per_frame; 153 b->state = STATE_RUNNING; 154 } else { 155 b->max_cnt = max_frames * samples_per_frame; 156 b->last_op = OP_UNDEFINED; 157 b->state = STATE_WAITING; 158 } 132 pj_pool_zalloc(pool, b->max_cnt * sizeof(pj_int16_t)); 159 133 160 134 status = pjmedia_wsola_create(pool, clock_rate, samples_per_frame, 1, … … 183 157 184 158 pj_lock_release(b->lock); 159 185 160 pj_lock_destroy(b->lock); 186 161 b->lock = NULL; … … 263 238 } 264 239 265 static void set_max_cnt(pjmedia_delay_buf *b, unsigned new_max_cnt) 266 { 267 unsigned old_max_cnt = b->max_cnt; 268 269 /* nothing to adjust */ 270 if (old_max_cnt == new_max_cnt) 240 /* Fast increase, slow decrease */ 241 #define AGC_UP(cur, target) cur = (cur + target*3) >> 2 242 #define AGC_DOWN(cur, target) cur = (cur*3 + target) >> 2 243 #define AGC(cur, target) \ 244 if (cur < target) AGC_UP(cur, target); \ 245 else AGC_DOWN(cur, target) 246 247 static void update(pjmedia_delay_buf *b, enum OP op) 248 { 249 /* Sequential operation */ 250 if (op == b->last_op) { 251 ++b->level; 271 252 return; 272 273 /* For now, only support shrinking */ 274 pj_assert(old_max_cnt > new_max_cnt); 275 276 /* Buffer empty, only need to reset pointers then set new max directly */ 277 if (b->buf_cnt == 0) { 278 b->put_pos = b->get_pos = 0; 279 b->max_cnt = new_max_cnt; 280 return; 281 } 282 283 /* If samples number in the buffer > new_max_cnt, reduce samples first */ 284 if (b->buf_cnt > new_max_cnt) 285 shrink_buffer(b, b->buf_cnt - new_max_cnt); 286 287 /* Adjust buffer to accomodate the new max_cnt so the samples is secured. 288 * This is done by make get_pos = 0 289 */ 290 if (b->get_pos <= b->put_pos) { 291 /* sssss .. sssss 292 * ^ ^ 293 * G P 253 } 254 255 /* Switching operation */ 256 if (b->level > b->max_level) 257 b->max_level = b->level; 258 259 b->recalc_timer -= (b->level * b->ptime) >> 1; 260 261 b->last_op = op; 262 b->level = 1; 263 264 /* Recalculate effective count based on max_level */ 265 if (b->recalc_timer <= 0) { 266 unsigned new_eff_cnt = (b->max_level+SAFE_MARGIN)*b->samples_per_frame; 267 268 /* Smoothening effective count transition */ 269 AGC(b->eff_cnt, new_eff_cnt); 270 271 /* Make sure the new effective count is multiplication of 272 * channel_count, so let's round it up. 294 273 */ 295 /* Consistency checking */ 296 pj_assert((b->put_pos - b->get_pos) <= new_max_cnt); 297 pj_assert((b->put_pos - b->get_pos) == b->buf_cnt); 298 299 pjmedia_move_samples(b->frame_buf, &b->frame_buf[b->get_pos], 300 b->get_pos); 301 b->put_pos -= b->get_pos; 302 b->get_pos = 0; 303 } else { 304 /* sssss .. sssss 305 * ^ ^ 306 * P G 307 */ 308 unsigned d = old_max_cnt - b->get_pos; 309 310 /* Consistency checking */ 311 pj_assert((b->get_pos - b->put_pos) >= (old_max_cnt - new_max_cnt)); 312 313 /* Make get_pos = 0, shift right the leftmost block first */ 314 pjmedia_move_samples(&b->frame_buf[d], b->frame_buf, d); 315 pjmedia_copy_samples(b->frame_buf, &b->frame_buf[b->get_pos], d); 316 b->put_pos += d; 317 b->get_pos = 0; 318 } 319 320 b->max_cnt = new_max_cnt; 321 } 322 323 static void update(pjmedia_delay_buf *b, enum OP op) 324 { 325 enum OP other = (enum OP) !op; 326 327 switch (b->state) { 328 case STATE_RUNNING: 329 break; 330 case STATE_WAITING: 331 ++b->op[op].level; 332 if (b->op[other].level != 0) { 333 ++b->state_count; 334 if (b->state_count == WAITING_COUNT) { 335 /* Start learning */ 336 pjmedia_delay_buf_learn(b); 337 } 338 } 339 b->last_op = op; 340 break; 341 case STATE_LEARNING: 342 ++b->op[op].level; 343 if (b->last_op == other) { 344 unsigned last_level = b->op[other].level; 345 if (last_level > b->max_level) 346 b->max_level = last_level; 347 b->op[other].level = 0; 348 b->state_count++; 349 if (b->state_count == LEARN_COUNT) { 350 /* give SAFE_MARGIN compensation for added stability */ 351 b->max_level += SAFE_MARGIN; 352 353 /* buffer not enough! */ 354 if (b->max_level > b->max_frames) { 355 PJ_LOG(4,(b->obj_name,"Delay buffer learning result (%d)" 356 " exceeds the maximum delay allowed (%d)", 357 b->max_level, 358 b->max_frames)); 359 360 b->max_level = b->max_frames; 361 } 362 363 /* we need to set new max_cnt & adjust buffer */ 364 set_max_cnt(b, b->max_level * b->samples_per_frame); 365 366 b->state = STATE_RUNNING; 367 368 PJ_LOG(4,(b->obj_name,"Delay buffer start running, level=%u", 369 b->max_level)); 370 } 371 } 372 b->last_op = op; 373 break; 374 } 375 376 274 if (b->eff_cnt % b->channel_count) 275 b->eff_cnt += b->channel_count - (b->eff_cnt % b->channel_count); 276 277 TRACE__((b->obj_name,"Cur eff_cnt=%d", b->eff_cnt)); 278 279 b->max_level = 0; 280 b->recalc_timer = RECALC_TIME; 281 } 282 283 /* See if we need to shrink the buffer to reduce delay */ 284 if (b->buf_cnt > b->samples_per_frame + b->eff_cnt) { 285 unsigned erase_cnt = b->samples_per_frame >> 1; 286 unsigned old_buf_cnt = b->buf_cnt; 287 288 shrink_buffer(b, erase_cnt); 289 PJ_LOG(5,(b->obj_name,"Buffer size adjusted from %d to %d", 290 old_buf_cnt, b->buf_cnt)); 291 } 377 292 } 378 293 … … 500 415 } 501 416 502 PJ_DEF(pj_status_t) pjmedia_delay_buf_learn(pjmedia_delay_buf *b) 417 418 PJ_DEF(pj_status_t) pjmedia_delay_buf_reset(pjmedia_delay_buf *b) 503 419 { 504 420 PJ_ASSERT_RETURN(b, PJ_EINVAL); … … 506 422 pj_lock_acquire(b->lock); 507 423 508 b->last_op = OP_UNDEFINED; 509 b->op[OP_GET].level = b->op[OP_PUT].level = 0; 510 b->state = STATE_LEARNING; 511 b->state_count = 0; 512 b->max_level = 0; 513 b->max_cnt = b->max_frames * b->samples_per_frame; 514 515 pjmedia_delay_buf_reset(b); 516 517 pj_lock_release(b->lock); 518 519 PJ_LOG(5,(b->obj_name,"Delay buffer start learning")); 520 521 return PJ_SUCCESS; 522 } 523 524 PJ_DEF(pj_status_t) pjmedia_delay_buf_reset(pjmedia_delay_buf *b) 525 { 526 PJ_ASSERT_RETURN(b, PJ_EINVAL); 527 528 pj_lock_acquire(b->lock); 424 b->recalc_timer = RECALC_TIME; 529 425 530 426 /* clean up buffer */ -
pjproject/trunk/pjmedia/src/pjmedia/sound_port.c
r1836 r1972 373 373 pjmedia_snd_port *snd_port; 374 374 pj_status_t status; 375 unsigned ptime; 375 376 376 377 PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); … … 389 390 390 391 #if PJMEDIA_SOUND_USE_DELAYBUF 392 ptime = samples_per_frame * 1000 / (clock_rate * channel_count); 393 391 394 status = pjmedia_delay_buf_create(pool, "snd_buff", 392 clock_rate, samples_per_frame, 393 PJMEDIA_SOUND_BUFFER_COUNT, -1, 395 clock_rate, samples_per_frame, 396 channel_count, 397 PJMEDIA_SOUND_BUFFER_COUNT * ptime, 394 398 0, &snd_port->delay_buf); 395 399 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 396 400 #else 397 401 PJ_UNUSED_ARG(status); 402 PJ_UNUSED_ARG(ptime); 398 403 #endif 399 404 -
pjproject/trunk/pjmedia/src/pjmedia/splitcomb.c
r1866 r1972 308 308 struct splitcomb *sc = (struct splitcomb*) splitcomb; 309 309 struct reverse_port *rport; 310 unsigned buf_cnt ;310 unsigned buf_cnt, ptime; 311 311 pjmedia_port *port; 312 312 pj_status_t status; … … 347 347 buf_cnt = MAX_BUF_CNT; 348 348 349 ptime = port->info.samples_per_frame * 1000 / port->info.clock_rate / 350 port->info.channel_count; 351 349 352 rport->max_burst = MAX_BURST; 350 353 rport->max_null_frames = MAX_NULL_FRAMES; … … 354 357 port->info.clock_rate, 355 358 port->info.samples_per_frame, 356 buf_cnt, -1, 0, 359 port->info.channel_count, 360 buf_cnt * ptime, 0, 357 361 &rport->buf[DIR_DOWNSTREAM].dbuf); 358 362 if (status != PJ_SUCCESS) { … … 364 368 port->info.clock_rate, 365 369 port->info.samples_per_frame, 366 buf_cnt, -1, 0, 370 port->info.channel_count, 371 buf_cnt * ptime, 0, 367 372 &rport->buf[DIR_UPSTREAM].dbuf); 368 373 if (status != PJ_SUCCESS) {
Note: See TracChangeset
for help on using the changeset viewer.