- Timestamp:
- Jul 10, 2008 3:04:27 PM (16 years ago)
- Location:
- pjproject/trunk/pjmedia
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/include/pjmedia/delaybuf.h
r2039 r2116 151 151 PJ_END_DECL 152 152 153 /** 154 * @} 155 */ 153 156 154 157 #endif /* __PJMEDIA_DELAYBUF_H__ */ -
pjproject/trunk/pjmedia/src/pjmedia/delaybuf.c
r2039 r2116 19 19 20 20 #include <pjmedia/delaybuf.h> 21 #include <pjmedia/circbuf.h> 21 22 #include <pjmedia/errno.h> 22 23 #include <pjmedia/wsola.h> … … 61 62 char obj_name[PJ_MAX_OBJ_NAME]; 62 63 pj_lock_t *lock; /**< Lock object. */ 63 pj_int16_t *frame_buf;64 64 unsigned samples_per_frame; /**< Number of samples in one frame */ 65 65 unsigned ptime; /**< Frame time, in ms */ 66 66 unsigned channel_count; /**< Channel count, in ms */ 67 unsigned max_cnt; /**< Max buffered samples, in samples*/ 68 69 /* Buffer pointer and counter */ 70 unsigned put_pos; /**< Position for put op, in samples */ 71 unsigned get_pos; /**< Position for get op, in samples */ 72 unsigned buf_cnt; /**< Number of buffered samples */ 67 pjmedia_circ_buf *circ_buf; /**< Circular buffer to store audio 68 samples */ 69 unsigned max_cnt; /**< Maximum samples to be buffered */ 73 70 unsigned eff_cnt; /**< Effective count of buffered 74 71 samples to keep the optimum … … 129 126 return status; 130 127 131 b->frame_buf = (pj_int16_t*) 132 pj_pool_zalloc(pool, b->max_cnt * sizeof(pj_int16_t)); 128 status = pjmedia_circ_buf_create(pool, b->max_cnt, &b->circ_buf); 129 if (status != PJ_SUCCESS) 130 return status; 133 131 134 132 status = pjmedia_wsola_create(pool, clock_rate, samples_per_frame, 1, 135 PJMEDIA_WSOLA_NO_PLC, &b->wsola);133 0, &b->wsola); 136 134 if (status != PJ_SUCCESS) 137 135 return status; … … 169 167 static void shrink_buffer(pjmedia_delay_buf *b, unsigned erase_cnt) 170 168 { 169 pj_int16_t *buf1, *buf2; 171 170 unsigned buf1len; 172 171 unsigned buf2len; 173 172 pj_status_t status; 174 173 175 pj_assert(b && erase_cnt && b->buf_cnt); 176 177 if (b->get_pos < b->put_pos) { 178 /* sssss .. sssss 179 * ^ ^ 180 * G P 174 pj_assert(b && erase_cnt && pjmedia_circ_buf_get_len(b->circ_buf)); 175 176 pjmedia_circ_buf_get_read_regions(b->circ_buf, &buf1, &buf1len, 177 &buf2, &buf2len); 178 status = pjmedia_wsola_discard(b->wsola, buf1, buf1len, buf2, buf2len, 179 &erase_cnt); 180 181 if ((status == PJ_SUCCESS) && (erase_cnt > 0)) { 182 /* WSOLA discard will manage the first buffer to be full, unless 183 * erase_cnt is greater than second buffer length. So it is safe 184 * to just set the circular buffer length. 181 185 */ 182 buf1len = b->put_pos - b->get_pos; 183 buf2len = 0; 184 } else { 185 /* sssss .. sssss 186 * ^ ^ 187 * P G 188 */ 189 buf1len = b->max_cnt - b->get_pos; 190 buf2len = b->put_pos; 191 } 192 193 /* Consistency checking */ 194 pj_assert((buf1len + buf2len) == b->buf_cnt); 195 196 if (buf1len != 0) 197 status = pjmedia_wsola_discard(b->wsola, 198 &b->frame_buf[b->get_pos], buf1len, 199 b->frame_buf, buf2len, 200 &erase_cnt); 201 else 202 status = pjmedia_wsola_discard(b->wsola, 203 b->frame_buf, buf2len, 204 NULL, 0, 205 &erase_cnt); 206 207 if ((status == PJ_SUCCESS) && (erase_cnt > 0)) { 208 /* WSOLA discard will shrink only the second buffer, but it may 209 * also shrink first buffer if second buffer is 'destroyed', so 210 * it is safe to just set the new put_pos. 211 */ 212 if (b->put_pos >= erase_cnt) 213 b->put_pos -= erase_cnt; 214 else 215 b->put_pos = b->max_cnt - (erase_cnt - b->put_pos); 216 217 b->buf_cnt -= erase_cnt; 186 187 pjmedia_circ_buf_set_len(b->circ_buf, 188 pjmedia_circ_buf_get_len(b->circ_buf) - 189 erase_cnt); 218 190 219 191 PJ_LOG(5,(b->obj_name,"%d samples reduced, buf_cnt=%d", 220 erase_cnt, b->buf_cnt));192 erase_cnt, pjmedia_circ_buf_get_len(b->circ_buf))); 221 193 } 222 194 } … … 266 238 267 239 /* See if we need to shrink the buffer to reduce delay */ 268 if (b->buf_cnt > b->samples_per_frame + b->eff_cnt) { 240 if (pjmedia_circ_buf_get_len(b->circ_buf) > 241 b->samples_per_frame + b->eff_cnt) 242 { 269 243 unsigned erase_cnt = b->samples_per_frame >> 1; 270 unsigned old_buf_cnt = b->buf_cnt;244 unsigned old_buf_cnt = pjmedia_circ_buf_get_len(b->circ_buf); 271 245 272 246 shrink_buffer(b, erase_cnt); 273 247 PJ_LOG(4,(b->obj_name,"Buffer size adjusted from %d to %d (eff_cnt=%d)", 274 old_buf_cnt, b->buf_cnt, b->eff_cnt)); 248 old_buf_cnt, 249 pjmedia_circ_buf_get_len(b->circ_buf), 250 b->eff_cnt)); 275 251 } 276 252 } … … 294 270 295 271 /* Overflow checking */ 296 if (b->buf_cnt + b->samples_per_frame > b->max_cnt) 272 if (pjmedia_circ_buf_get_len(b->circ_buf) + b->samples_per_frame > 273 b->max_cnt) 297 274 { 298 275 unsigned erase_cnt; … … 300 277 /* shrink one frame or just the diff? */ 301 278 //erase_cnt = b->samples_per_frame; 302 erase_cnt = b->buf_cnt + b->samples_per_frame - b->max_cnt; 279 erase_cnt = pjmedia_circ_buf_get_len(b->circ_buf) + 280 b->samples_per_frame - b->max_cnt; 303 281 304 282 shrink_buffer(b, erase_cnt); … … 308 286 * samples get rough transition which may produce tick noise. 309 287 */ 310 if ( b->buf_cnt + b->samples_per_frame > b->max_cnt) {311 erase_cnt = b->buf_cnt + b->samples_per_frame - b->max_cnt;312 313 b->buf_cnt -= erase_cnt;314 315 /* Shift get_pos forward */ 316 b->get_pos = (b->get_pos + erase_cnt) % b->max_cnt;288 if (pjmedia_circ_buf_get_len(b->circ_buf) + b->samples_per_frame > 289 b->max_cnt) 290 { 291 erase_cnt = pjmedia_circ_buf_get_len(b->circ_buf) + 292 b->samples_per_frame - b->max_cnt; 293 294 pjmedia_circ_buf_adv_read_ptr(b->circ_buf, erase_cnt); 317 295 318 296 PJ_LOG(4,(b->obj_name,"Shrinking failed or insufficient, dropping" 319 " %d eldest samples, buf_cnt=%d", erase_cnt, b->buf_cnt)); 297 " %d eldest samples, buf_cnt=%d", erase_cnt, 298 pjmedia_circ_buf_get_len(b->circ_buf))); 320 299 } 321 300 } 322 301 323 /* put the frame on put_pos */ 324 if (b->put_pos + b->samples_per_frame <= b->max_cnt) { 325 pjmedia_copy_samples(&b->frame_buf[b->put_pos], frame, 326 b->samples_per_frame); 327 } else { 328 int remainder = b->put_pos + b->samples_per_frame - b->max_cnt; 329 330 pjmedia_copy_samples(&b->frame_buf[b->put_pos], frame, 331 b->samples_per_frame - remainder); 332 pjmedia_copy_samples(&b->frame_buf[0], 333 &frame[b->samples_per_frame - remainder], 334 remainder); 335 } 336 337 /* Update put_pos & buf_cnt */ 338 b->put_pos = (b->put_pos + b->samples_per_frame) % b->max_cnt; 339 b->buf_cnt += b->samples_per_frame; 302 pjmedia_circ_buf_write(b->circ_buf, frame, b->samples_per_frame); 340 303 341 304 pj_lock_release(b->lock); … … 355 318 356 319 /* Starvation checking */ 357 if ( b->buf_cnt< b->samples_per_frame) {320 if (pjmedia_circ_buf_get_len(b->circ_buf) < b->samples_per_frame) { 358 321 359 322 PJ_LOG(4,(b->obj_name,"Underflow, buf_cnt=%d, will generate 1 frame", 360 b->buf_cnt));323 pjmedia_circ_buf_get_len(b->circ_buf))); 361 324 362 325 status = pjmedia_wsola_generate(b->wsola, frame); … … 364 327 if (status == PJ_SUCCESS) { 365 328 TRACE__((b->obj_name,"Successfully generate 1 frame")); 366 if ( b->buf_cnt== 0) {329 if (pjmedia_circ_buf_get_len(b->circ_buf) == 0) { 367 330 pj_lock_release(b->lock); 368 331 return PJ_SUCCESS; … … 370 333 371 334 /* Put generated frame into buffer */ 372 if (b->put_pos + b->samples_per_frame <= b->max_cnt) { 373 pjmedia_copy_samples(&b->frame_buf[b->put_pos], frame, 374 b->samples_per_frame); 375 } else { 376 int remainder = b->put_pos + b->samples_per_frame - b->max_cnt; 377 378 pjmedia_copy_samples(&b->frame_buf[b->put_pos], &frame[0], 379 b->samples_per_frame - remainder); 380 pjmedia_copy_samples(&b->frame_buf[0], 381 &frame[b->samples_per_frame - remainder], 382 remainder); 383 } 384 385 b->put_pos = (b->put_pos + b->samples_per_frame) % b->max_cnt; 386 b->buf_cnt += b->samples_per_frame; 335 pjmedia_circ_buf_write(b->circ_buf, frame, b->samples_per_frame); 387 336 388 337 } else { 338 unsigned buf_len = pjmedia_circ_buf_get_len(b->circ_buf); 339 389 340 /* Give all what delay buffer has, then pad with zeroes */ 390 341 PJ_LOG(4,(b->obj_name,"Error generating frame, status=%d", 391 342 status)); 392 343 393 if (b->get_pos + b->buf_cnt <= b->max_cnt) { 394 pjmedia_copy_samples(frame, &b->frame_buf[b->get_pos], b->buf_cnt); 395 } else { 396 int remainder = b->get_pos + b->buf_cnt - b->max_cnt; 397 398 pjmedia_copy_samples(frame, &b->frame_buf[b->get_pos], 399 b->buf_cnt - remainder); 400 pjmedia_copy_samples(&frame[b->buf_cnt - remainder], 401 &b->frame_buf[0], remainder); 402 } 403 404 pjmedia_zero_samples(&frame[b->buf_cnt], 405 b->samples_per_frame - b->buf_cnt); 406 407 /* Delay buf is empty */ 408 b->get_pos = b->put_pos = 0; 409 b->buf_cnt = 0; 344 pjmedia_circ_buf_read(b->circ_buf, frame, buf_len); 345 pjmedia_zero_samples(&frame[buf_len], 346 b->samples_per_frame - buf_len); 347 348 /* The buffer is empty now, reset it */ 349 pjmedia_circ_buf_reset(b->circ_buf); 410 350 411 351 pj_lock_release(b->lock); … … 415 355 } 416 356 417 if (b->get_pos + b->samples_per_frame <= b->max_cnt) { 418 pjmedia_copy_samples(frame, &b->frame_buf[b->get_pos], 419 b->samples_per_frame); 420 } else { 421 int remainder = b->get_pos + b->samples_per_frame - b->max_cnt; 422 423 pjmedia_copy_samples(frame, &b->frame_buf[b->get_pos], 424 b->samples_per_frame - remainder); 425 pjmedia_copy_samples(&frame[b->samples_per_frame - remainder], 426 &b->frame_buf[0], 427 remainder); 428 } 429 430 b->get_pos = (b->get_pos + b->samples_per_frame) % b->max_cnt; 431 b->buf_cnt -= b->samples_per_frame; 357 pjmedia_circ_buf_read(b->circ_buf, frame, b->samples_per_frame); 432 358 433 359 pj_lock_release(b->lock); … … 445 371 b->recalc_timer = RECALC_TIME; 446 372 447 /* clean up buffer */ 448 b->buf_cnt = 0; 449 b->put_pos = b->get_pos = 0; 373 /* Reset buffer */ 374 pjmedia_circ_buf_reset(b->circ_buf); 375 376 /* Reset WSOLA */ 450 377 pjmedia_wsola_reset(b->wsola, 0); 451 378
Note: See TracChangeset
for help on using the changeset viewer.