- Timestamp:
- Jul 10, 2008 2:59:57 PM (16 years ago)
- Location:
- pjproject/trunk/pjmedia
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/include/pjmedia/wsola.h
r2039 r2115 137 137 */ 138 138 PJ_DECL(pj_status_t) pjmedia_wsola_save(pjmedia_wsola *wsola, 139 short frm[],139 pj_int16_t frm[], 140 140 pj_bool_t prev_lost); 141 141 … … 149 149 */ 150 150 PJ_DECL(pj_status_t) pjmedia_wsola_generate(pjmedia_wsola *wsola, 151 short frm[]);151 pj_int16_t frm[]); 152 152 153 153 … … 175 175 */ 176 176 PJ_DECL(pj_status_t) pjmedia_wsola_discard(pjmedia_wsola *wsola, 177 short buf1[],177 pj_int16_t buf1[], 178 178 unsigned buf1_cnt, 179 short buf2[],179 pj_int16_t buf2[], 180 180 unsigned buf2_cnt, 181 181 unsigned *erase_cnt); -
pjproject/trunk/pjmedia/src/pjmedia/wsola.c
r2039 r2115 18 18 */ 19 19 #include <pjmedia/wsola.h> 20 #include <pjmedia/circbuf.h> 20 21 #include <pjmedia/errno.h> 21 22 #include <pj/assert.h> 22 23 #include <pj/log.h> 24 #include <pj/math.h> 23 25 #include <pj/pool.h> 24 26 … … 29 31 #define THIS_FILE "wsola.c" 30 32 33 31 34 #if (PJMEDIA_WSOLA_IMP==PJMEDIA_WSOLA_IMP_WSOLA) || \ 32 35 (PJMEDIA_WSOLA_IMP==PJMEDIA_WSOLA_IMP_WSOLA_LITE) … … 36 39 */ 37 40 38 /* History size, in percentage of samples_per_frame*/39 #define HISTSZ (1.5)40 41 /* Number of frames in buffer (excluding history)*/42 #define FRAME_CNT 443 44 /* Template size in msec */45 #define TEMPLATE_PTIME (5)46 47 /* Generate extra samples, in msec */48 #define GEN_EXTRA_PTIME (1)41 /* Buffer size including history, in frames */ 42 #define FRAME_CNT 5 43 44 /* Number of history frames in buffer */ 45 #define HIST_CNT 1.5 46 47 /* Template size, in msec */ 48 #define TEMPLATE_PTIME 5 49 50 /* Hanning window size, in msec */ 51 #define HANNING_PTIME 5 49 52 50 53 /* Number of frames in erase buffer */ 51 54 #define ERASE_CNT ((unsigned)3) 52 55 53 54 #ifndef M_PI55 # define M_PI 3.1415926535897932384656 #endif57 56 58 57 #if 0 … … 62 61 #endif 63 62 63 #if 0 64 # define CHECK_(x) pj_assert(x) 65 #else 66 # define CHECK_(x) 67 #endif 64 68 65 69 /* Buffer content: 66 70 * 67 * t0 time tn 68 * ----------------> 71 * +---------+-----------+--------------------+ 72 * | history | min_extra | more extra / empty | 73 * +---------+-----------+--------------------+ 74 * ^ ^ ^ ^ 75 * buf hist_size min_extra buf_size 76 * 77 * History size (hist_size) is a constant value, initialized upon creation. 69 78 * 70 * +---------+-------+-------+--- --+ 71 * | history | frame | extra | ...empty... | 72 * +---------+-------+-------+---- ---+ 73 * ^ ^ ^ ^ 74 * buf hist_cnt cur_cnt buf_cnt 75 * or 76 * frm pointer 79 * min_extra size is equal to HANNING_PTIME, this samples is useful for 80 * smoothening samples transition between generated frame & history 81 * (when PLC is invoked), or between generated samples & normal frame 82 * (after lost/PLC). Since min_extra samples need to be available at 83 * any time, this will introduce delay of HANNING_PTIME ms. 77 84 * 78 * History count (hist_cnt) is a constant value, initialized upon79 * creation.85 * More extra is excess samples produced by PLC (PLC frame generation may 86 * produce more than exact one frame). 80 87 * 81 * At any particular time, the buffer will contain at least 82 * (hist_cnt+samples_per_frame) samples.88 * At any particular time, the buffer will contain at least (hist_size + 89 * min_extra) samples. 83 90 * 84 * A "save" operation will append the frame to the end of the 85 * buffer, return the samples right after history (the frm pointer), 86 * and shift the buffer by one frame. 91 * A "save" operation will append the new frame to the end of the buffer, 92 * return the frame from samples right after history and shift the buffer 93 * by one frame. 94 * 87 95 */ 88 96 … … 90 98 struct pjmedia_wsola 91 99 { 92 unsigned clock_rate; /* Sampling rate. */ 93 pj_uint16_t samples_per_frame;/* Samples per frame (const) */ 94 pj_uint16_t channel_count; /* Samples per frame (const) */ 95 pj_uint16_t options; /* Options. */ 96 pj_uint16_t hist_cnt; /* # of history samples (const) */ 97 pj_uint16_t buf_cnt; /* Total buffer capacity (const) */ 98 pj_uint16_t cur_cnt; /* Cur # of samples, inc. history */ 99 pj_uint16_t template_size; /* Template size (const) */ 100 pj_uint16_t min_extra; /* Min extra samples for merging (const)*/ 101 pj_uint16_t gen_extra; /* Generate extra samples (const) */ 102 pj_uint16_t expand_cnt; /* Number of expansion currently done */ 103 104 short *buf; /* The buffer. */ 105 short *frm; /* Pointer to next frame to play in buf */ 106 short *mergebuf; /* Temporary merge buffer. */ 107 short *erasebuf; /* Temporary erase buffer. */ 100 unsigned clock_rate; /* Sampling rate. */ 101 pj_uint16_t samples_per_frame; /* Samples per frame (const) */ 102 pj_uint16_t channel_count; /* Channel countt (const) */ 103 pj_uint16_t options; /* Options. */ 104 105 pjmedia_circ_buf *buf; /* The buffer. */ 106 pj_int16_t *erase_buf; /* Temporary erase buffer. */ 107 pj_int16_t *merge_buf; /* Temporary merge buffer. */ 108 109 pj_uint16_t buf_size; /* Total buffer size (const) */ 110 pj_uint16_t hanning_size; /* Hanning window size (const) */ 111 pj_uint16_t templ_size; /* Template size (const) */ 112 pj_uint16_t hist_size; /* History size (const) */ 113 114 pj_uint16_t min_extra; /* Minimum extra (const) */ 115 pj_uint16_t expand_cnt; /* Consecutive expansion count */ 116 108 117 #if defined(PJ_HAS_FLOATING_POINT) && PJ_HAS_FLOATING_POINT!=0 109 float *hanning; /* Hanning window.*/118 float *hanning; /* Hanning window. */ 110 119 #else 111 pj_uint16_t *hanning; /* Hanning window.*/120 pj_uint16_t *hanning; /* Hanning window. */ 112 121 #endif 113 122 114 pj_timestamp ts; /* Running timestamp.*/123 pj_timestamp ts; /* Running timestamp. */ 115 124 }; 116 125 … … 125 134 * diff level = (template[1]+..+template[n]) - (target[1]+..+target[n]) 126 135 */ 127 static short *find_pitch(short *frm, short *beg, short *end,136 static pj_int16_t *find_pitch(pj_int16_t *frm, pj_int16_t *beg, pj_int16_t *end, 128 137 unsigned template_cnt, int first) 129 138 { 130 short *sr, *best=beg;139 pj_int16_t *sr, *best=beg; 131 140 int best_corr = 0x7FFFFFFF; 132 141 int frm_sum = 0; … … 186 195 * Floating point version. 187 196 */ 188 #include <math.h>189 197 190 198 #if (PJMEDIA_WSOLA_IMP==PJMEDIA_WSOLA_IMP_WSOLA) 191 199 192 static short *find_pitch(short *frm, short *beg, short *end,200 static pj_int16_t *find_pitch(pj_int16_t *frm, pj_int16_t *beg, pj_int16_t *end, 193 201 unsigned template_cnt, int first) 194 202 { 195 short *sr, *best=beg;203 pj_int16_t *sr, *best=beg; 196 204 double best_corr = 0; 197 205 … … 241 249 #endif 242 250 243 static void overlapp_add( short dst[], unsigned count,244 short l[], short r[],251 static void overlapp_add(pj_int16_t dst[], unsigned count, 252 pj_int16_t l[], pj_int16_t r[], 245 253 float w[]) 246 254 { … … 248 256 249 257 for (i=0; i<count; ++i) { 250 dst[i] = ( short)(l[i] * w[count-1-i] + r[i] * w[i]);251 } 252 } 253 254 static void overlapp_add_simple( short dst[], unsigned count,255 short l[], short r[])258 dst[i] = (pj_int16_t)(l[i] * w[count-1-i] + r[i] * w[i]); 259 } 260 } 261 262 static void overlapp_add_simple(pj_int16_t dst[], unsigned count, 263 pj_int16_t l[], pj_int16_t r[]) 256 264 { 257 265 float step = (float)(1.0 / count), stepdown = 1.0; … … 259 267 260 268 for (i=0; i<count; ++i) { 261 dst[i] = ( short)(l[i] * stepdown + r[i] * (1-stepdown));269 dst[i] = (pj_int16_t)(l[i] * stepdown + r[i] * (1-stepdown)); 262 270 stepdown -= step; 263 271 } … … 272 280 273 281 for (i=0;i<count; i++) { 274 w[i] = (float)(0.5 - 0.5 * cos(2.0 * M_PI * i / (count*2-1)) );282 w[i] = (float)(0.5 - 0.5 * cos(2.0 * PJ_PI * i / (count*2-1)) ); 275 283 } 276 284 } … … 285 293 #if (PJMEDIA_WSOLA_IMP==PJMEDIA_WSOLA_IMP_WSOLA) 286 294 287 static short *find_pitch(short *frm, short *beg, short *end,295 static pj_int16_t *find_pitch(pj_int16_t *frm, pj_int16_t *beg, pj_int16_t *end, 288 296 unsigned template_cnt, int first) 289 297 { 290 short *sr, *best=beg;298 pj_int16_t *sr, *best=beg; 291 299 pj_int64_t best_corr = 0; 292 300 … … 338 346 339 347 340 static void overlapp_add( short dst[], unsigned count,341 short l[], short r[],348 static void overlapp_add(pj_int16_t dst[], unsigned count, 349 pj_int16_t l[], pj_int16_t r[], 342 350 pj_uint16_t w[]) 343 351 { … … 345 353 346 354 for (i=0; i<count; ++i) { 347 dst[i] = ( short)(((int)(l[i]) * (int)(w[count-1-i]) +355 dst[i] = (pj_int16_t)(((int)(l[i]) * (int)(w[count-1-i]) + 348 356 (int)(r[i]) * (int)(w[i])) >> WINDOW_BITS); 349 357 } 350 358 } 351 359 352 static void overlapp_add_simple( short dst[], unsigned count,353 short l[], short r[])360 static void overlapp_add_simple(pj_int16_t dst[], unsigned count, 361 pj_int16_t l[], pj_int16_t r[]) 354 362 { 355 363 int step = ((WINDOW_MAX_VAL+1) / count), … … 358 366 359 367 for (i=0; i<count; ++i) { 360 dst[i]=( short)((l[i] * stepdown + r[i] * (1-stepdown)) >> WINDOW_BITS);368 dst[i]=(pj_int16_t)((l[i] * stepdown + r[i] * (1-stepdown)) >> WINDOW_BITS); 361 369 stepdown -= step; 362 370 } … … 399 407 pj_uint64_t cos_val; 400 408 401 /* w[i] = (float)(0.5 - 0.5 * cos(2.0 * M_PI * i / (count*2-1)) ); */409 /* w[i] = (float)(0.5 - 0.5 * cos(2.0 * PJ_PI * i / (count*2-1)) ); */ 402 410 403 411 phase = (pj_uint32_t)(PJ_INT64(0xFFFFFFFF) * i / (count*2-1)); … … 424 432 { 425 433 pjmedia_wsola *wsola; 434 pj_status_t status; 426 435 427 436 PJ_ASSERT_RETURN(pool && clock_rate && samples_per_frame && p_wsola, … … 431 440 PJ_ASSERT_RETURN(channel_count > 0, PJ_EINVAL); 432 441 442 /* Allocate wsola and initialize vars */ 433 443 wsola = PJ_POOL_ZALLOC_T(pool, pjmedia_wsola); 434 435 444 wsola->clock_rate= (pj_uint16_t) clock_rate; 436 445 wsola->samples_per_frame = (pj_uint16_t) samples_per_frame; 437 446 wsola->channel_count = (pj_uint16_t) channel_count; 438 wsola->options = (pj_uint16_t) options; 439 wsola->hist_cnt = (pj_uint16_t)(samples_per_frame * HISTSZ); 440 wsola->buf_cnt = (pj_uint16_t)(wsola->hist_cnt + 441 (samples_per_frame * FRAME_CNT)); 442 443 wsola->cur_cnt = (pj_uint16_t)(wsola->hist_cnt + 444 wsola->samples_per_frame); 445 wsola->min_extra = 0; 446 447 if ((options & PJMEDIA_WSOLA_NO_PLC) == 0) 448 wsola->gen_extra = (pj_uint16_t)(GEN_EXTRA_PTIME * clock_rate / 1000); 449 450 wsola->template_size = (pj_uint16_t) (clock_rate * TEMPLATE_PTIME / 1000); 451 if (wsola->template_size > samples_per_frame) 452 wsola->template_size = wsola->samples_per_frame; 453 454 /* Make sure minimal template size is 8, this is required by waveform 455 * similarity calculation (find_pitch()). Moreover, smaller template size 456 * will reduce accuracy. 457 */ 458 if (wsola->template_size < 8) 459 wsola->template_size = 8; 460 461 wsola->buf = (short*)pj_pool_calloc(pool, wsola->buf_cnt, 462 sizeof(short)); 463 wsola->frm = wsola->buf + wsola->hist_cnt; 464 465 wsola->mergebuf = (short*)pj_pool_calloc(pool, samples_per_frame, 466 sizeof(short)); 467 447 wsola->options = (pj_uint16_t) options; 448 449 /* Create circular buffer */ 450 wsola->buf_size = (pj_uint16_t) (samples_per_frame * FRAME_CNT); 451 status = pjmedia_circ_buf_create(pool, wsola->buf_size, &wsola->buf); 452 if (status != PJ_SUCCESS) { 453 PJ_LOG(3, (THIS_FILE, "Failed to create circular buf")); 454 return status; 455 } 456 457 /* Calculate history size */ 458 wsola->hist_size = (pj_uint16_t)(HIST_CNT * samples_per_frame); 459 460 /* Calculate template size */ 461 wsola->templ_size = (pj_uint16_t)(TEMPLATE_PTIME * clock_rate * 462 channel_count / 1000); 463 if (wsola->templ_size > samples_per_frame) 464 wsola->templ_size = wsola->samples_per_frame; 465 466 /* Calculate hanning window size */ 467 wsola->hanning_size = (pj_uint16_t)(HANNING_PTIME * clock_rate * 468 channel_count / 1000); 469 if (wsola->hanning_size > wsola->samples_per_frame) 470 wsola->hanning_size = wsola->samples_per_frame; 471 472 pj_assert(wsola->templ_size <= wsola->hanning_size); 473 474 /* Create merge buffer */ 475 wsola->merge_buf = (pj_int16_t*) pj_pool_calloc(pool, 476 wsola->hanning_size, 477 sizeof(pj_int16_t)); 478 479 /* Setup with PLC */ 480 if ((options & PJMEDIA_WSOLA_NO_PLC) == 0) { 481 wsola->min_extra = wsola->hanning_size; 482 } 483 484 /* Setup with hanning */ 468 485 if ((options & PJMEDIA_WSOLA_NO_HANNING) == 0) { 469 create_win(pool, &wsola->hanning, wsola->samples_per_frame); 470 } 471 486 create_win(pool, &wsola->hanning, wsola->hanning_size); 487 } 488 489 /* Setup with discard */ 472 490 if ((options & PJMEDIA_WSOLA_NO_DISCARD) == 0) { 473 wsola->erase buf = (short*)pj_pool_calloc(pool, samples_per_frame *491 wsola->erase_buf = (pj_int16_t*)pj_pool_calloc(pool, samples_per_frame * 474 492 ERASE_CNT, 475 sizeof(short)); 476 } 493 sizeof(pj_int16_t)); 494 } 495 496 /* Generate dummy extra */ 497 pjmedia_circ_buf_set_len(wsola->buf, wsola->hist_size + wsola->min_extra); 477 498 478 499 *p_wsola = wsola; … … 496 517 PJ_UNUSED_ARG(options); 497 518 498 wsola->cur_cnt = (pj_uint16_t)(wsola->hist_cnt +499 wsola->samples_per_frame);500 pjmedia_zero_samples(wsola->buf, wsola->cur_cnt); 519 pjmedia_circ_buf_reset(wsola->buf); 520 pjmedia_circ_buf_set_len(wsola->buf, wsola->hist_size + wsola->min_extra); 521 501 522 return PJ_SUCCESS; 502 523 } … … 506 527 { 507 528 unsigned generated = 0; 508 unsigned frmsz = wsola->samples_per_frame;509 529 unsigned rep; 510 530 531 pj_int16_t *reg1, *reg2; 532 unsigned reg1_len, reg2_len; 533 534 pjmedia_circ_buf_pack_buffer(wsola->buf); 535 pjmedia_circ_buf_get_read_regions(wsola->buf, ®1, ®1_len, 536 ®2, ®2_len); 537 CHECK_(reg2_len == 0); 538 511 539 for (rep=1;; ++rep) { 512 short *start, *frm;540 pj_int16_t *start, *templ; 513 541 unsigned min_dist, max_dist, dist; 514 542 515 frm = wsola->buf + wsola->cur_cnt - frmsz;516 pj_assert(frm - wsola->buf >= wsola->hist_cnt);517 518 max_dist = wsola->hist_ cnt;519 min_dist = frmsz>> 1;520 521 start = find_pitch( frm, frm - max_dist, frm- min_dist,522 wsola->templ ate_size, 1);543 templ = reg1 + reg1_len - wsola->hanning_size; 544 CHECK_(templ - reg1 >= wsola->hist_size); 545 546 max_dist = wsola->hist_size; 547 min_dist = wsola->hanning_size >> 1; 548 549 start = find_pitch(templ, templ - max_dist, templ - min_dist, 550 wsola->templ_size, 1); 523 551 524 552 /* Should we make sure that "start" is really aligned to … … 528 556 529 557 if (wsola->options & PJMEDIA_WSOLA_NO_HANNING) { 530 overlapp_add_simple(wsola->mergebuf, frmsz,frm, start); 558 overlapp_add_simple(wsola->merge_buf, wsola->hanning_size, 559 templ, start); 531 560 } else { 532 overlapp_add(wsola->mergebuf, frmsz, frm, start, wsola->hanning); 561 overlapp_add(wsola->merge_buf, wsola->hanning_size, templ, 562 start, wsola->hanning); 533 563 } 534 564 535 565 /* How many new samples do we have */ 536 dist = frm - start; 566 dist = templ - start; 567 568 /* Not enough buffer to hold the result */ 569 if (reg1_len + dist > wsola->buf_size) 570 break; 537 571 538 572 /* Copy the "tail" (excess frame) to the end */ 539 pjmedia_move_samples(frm + frmsz, start + frmsz, 540 wsola->buf+wsola->cur_cnt - (start+frmsz)); 573 pjmedia_move_samples(templ + wsola->hanning_size, 574 start + wsola->hanning_size, 575 dist); 541 576 542 577 /* Copy the merged frame */ 543 pjmedia_copy_samples( frm, wsola->mergebuf, frmsz);578 pjmedia_copy_samples(templ, wsola->merge_buf, wsola->hanning_size); 544 579 545 580 /* We have new samples */ 546 wsola->cur_cnt = (pj_uint16_t)(wsola->cur_cnt + dist); 547 548 pj_assert(wsola->cur_cnt <= wsola->buf_cnt); 581 reg1_len += dist; 582 pjmedia_circ_buf_set_len(wsola->buf, reg1_len); 549 583 550 584 generated += dist; … … 559 593 560 594 561 static unsigned compress(pjmedia_wsola *wsola, short *buf, unsigned count,595 static unsigned compress(pjmedia_wsola *wsola, pj_int16_t *buf, unsigned count, 562 596 unsigned del_cnt) 563 597 { … … 565 599 566 600 for (rep=1; ; ++rep) { 567 short *start, *end; 568 unsigned frmsz = wsola->samples_per_frame; 601 pj_int16_t *start, *end; 569 602 unsigned dist; 570 603 571 if ((count - del_cnt) <= frmsz) { 572 //if (count <= (del_cnt << 1)) { 604 if (count <= wsola->hanning_size + del_cnt) { 573 605 TRACE_((THIS_FILE, "Not enough samples to compress!")); 574 606 return samples_del; 575 607 } 576 608 609 // Make start distance to del_cnt, so discard will be performed in 610 // only one iteration. 577 611 //start = buf + (frmsz >> 1); 578 612 start = buf + del_cnt - samples_del; 579 end = start + frmsz; 580 581 if (end + frmsz > buf + count) 582 end = buf+count-frmsz; 583 584 pj_assert(start < end); 585 586 start = find_pitch(buf, start, end, wsola->template_size, 0); 613 end = start + wsola->samples_per_frame; 614 615 if (end + wsola->hanning_size > buf + count) { 616 end = buf+count-wsola->hanning_size; 617 } 618 619 CHECK_(start < end); 620 621 start = find_pitch(buf, start, end, wsola->templ_size, 0); 587 622 dist = start - buf; 588 623 589 624 if (wsola->options & PJMEDIA_WSOLA_NO_HANNING) { 590 overlapp_add_simple(buf, wsola-> samples_per_frame, buf, start);625 overlapp_add_simple(buf, wsola->hanning_size, buf, start); 591 626 } else { 592 overlapp_add(buf, wsola-> samples_per_frame, buf, start,593 wsola->hanning);594 } 595 596 pjmedia_move_samples(buf + frmsz, buf + frmsz+ dist,597 count - frmsz- dist);627 overlapp_add(buf, wsola->hanning_size, buf, start, wsola->hanning); 628 } 629 630 pjmedia_move_samples(buf + wsola->hanning_size, 631 buf + wsola->hanning_size + dist, 632 count - wsola->hanning_size - dist); 598 633 599 634 count -= dist; … … 614 649 615 650 PJ_DEF(pj_status_t) pjmedia_wsola_save( pjmedia_wsola *wsola, 616 short frm[],651 pj_int16_t frm[], 617 652 pj_bool_t prev_lost) 618 653 { 619 unsigned extra; 620 621 extra = wsola->cur_cnt - wsola->hist_cnt - wsola->samples_per_frame; 622 pj_assert(extra >= 0); 623 624 if (prev_lost && extra != 0 && extra >= wsola->min_extra) { 625 short *dst = wsola->buf + wsola->hist_cnt + wsola->samples_per_frame; 626 627 if (extra > wsola->samples_per_frame) 628 extra = wsola->samples_per_frame; 629 630 /* Smoothen the transition. This will also erase the excess 631 * samples 632 */ 633 overlapp_add_simple(dst, extra, dst, frm); 634 635 /* Copy remaining samples from the frame */ 636 pjmedia_copy_samples(dst+extra, frm+extra, 637 wsola->samples_per_frame-extra); 638 639 /* Retrieve frame */ 640 pjmedia_copy_samples(frm, wsola->frm, wsola->samples_per_frame); 641 642 /* Remove excess samples */ 643 wsola->cur_cnt = (pj_uint16_t)(wsola->hist_cnt + 644 wsola->samples_per_frame); 645 646 /* Shift buffer */ 647 pjmedia_move_samples(wsola->buf, wsola->buf+wsola->samples_per_frame, 648 wsola->cur_cnt); 649 650 } else { 651 /* Just append to end of buffer */ 652 if (prev_lost) { 653 TRACE_((THIS_FILE, 654 "Appending new frame without interpolation")); 655 } 656 657 /* Append frame */ 658 pjmedia_copy_samples(wsola->buf + wsola->cur_cnt, frm, 659 wsola->samples_per_frame); 660 661 /* Retrieve frame */ 662 pjmedia_copy_samples(frm, wsola->frm, 663 wsola->samples_per_frame); 664 665 /* Shift buffer */ 666 pjmedia_move_samples(wsola->buf, wsola->buf+wsola->samples_per_frame, 667 wsola->cur_cnt); 668 } 669 654 unsigned buf_len; 655 pj_status_t status; 656 657 buf_len = pjmedia_circ_buf_get_len(wsola->buf); 658 CHECK_(buf_len >= (unsigned)(wsola->hist_size + wsola->min_extra)); 659 660 /* Update vars */ 670 661 wsola->expand_cnt = 0; 671 662 wsola->ts.u64 += wsola->samples_per_frame; 672 663 673 return PJ_SUCCESS; 664 /* If previous frame was lost, smoothen this frame with the generated one */ 665 if (prev_lost) { 666 pj_int16_t *reg1, *reg2; 667 unsigned reg1_len, reg2_len; 668 pj_int16_t *ola_left; 669 670 pjmedia_circ_buf_get_read_regions(wsola->buf, ®1, ®1_len, 671 ®2, ®2_len); 672 673 if (reg2_len == 0) { 674 ola_left = reg1; 675 } else if (reg2_len >= wsola->min_extra) { 676 ola_left = reg2 + reg2_len - wsola->min_extra; 677 } else { 678 unsigned tmp; 679 680 tmp = wsola->min_extra - reg2_len; 681 pjmedia_copy_samples(wsola->merge_buf, reg1 + reg1_len - tmp, tmp); 682 pjmedia_copy_samples(wsola->merge_buf + tmp, reg2, reg2_len); 683 ola_left = wsola->merge_buf; 684 } 685 686 overlapp_add_simple(frm, wsola->min_extra, ola_left, frm); 687 688 buf_len -= wsola->min_extra; 689 pjmedia_circ_buf_set_len(wsola->buf, buf_len); 690 } 691 692 status = pjmedia_circ_buf_write(wsola->buf, frm, wsola->samples_per_frame); 693 if (status != PJ_SUCCESS) { 694 TRACE_((THIS_FILE, "Failed writing to circbuf [err=%d]", status)); 695 return status; 696 } 697 698 status = pjmedia_circ_buf_copy(wsola->buf, wsola->hist_size, frm, 699 wsola->samples_per_frame); 700 if (status != PJ_SUCCESS) { 701 TRACE_((THIS_FILE, "Failed copying from circbuf [err=%d]", status)); 702 return status; 703 } 704 705 return pjmedia_circ_buf_adv_read_ptr(wsola->buf, wsola->samples_per_frame); 674 706 } 675 707 676 708 677 709 PJ_DEF(pj_status_t) pjmedia_wsola_generate( pjmedia_wsola *wsola, 678 short frm[]) 679 { 680 unsigned extra; 681 682 extra = wsola->cur_cnt - wsola->hist_cnt - wsola->samples_per_frame; 683 684 if (extra >= wsola->samples_per_frame) { 685 686 /* We have one extra frame in the buffer, just return this frame 687 * rather than generating a new one. 688 */ 689 pjmedia_copy_samples(frm, wsola->frm, wsola->samples_per_frame); 690 pjmedia_move_samples(wsola->buf, wsola->buf+wsola->samples_per_frame, 691 wsola->cur_cnt - wsola->samples_per_frame); 692 693 pj_assert(wsola->cur_cnt >= 694 wsola->hist_cnt + (wsola->samples_per_frame << 1)); 695 wsola->cur_cnt = (pj_uint16_t)(wsola->cur_cnt - 696 wsola->samples_per_frame); 697 698 } else { 710 pj_int16_t frm[]) 711 { 712 unsigned samples_len; 713 pj_status_t status = PJ_SUCCESS; 714 715 samples_len = pjmedia_circ_buf_get_len(wsola->buf) - wsola->hist_size; 716 wsola->ts.u64 += wsola->samples_per_frame; 717 718 if (samples_len < (unsigned)wsola->samples_per_frame + 719 (unsigned)wsola->min_extra) 720 { 699 721 unsigned new_samples; 700 722 701 /* Calculate how many samples are need for a new frame */ 702 new_samples = ((wsola->samples_per_frame << 1) + wsola->gen_extra - 703 (wsola->cur_cnt - wsola->hist_cnt)); 723 /* Calculate how many samples are needed for a new frame */ 724 new_samples = wsola->samples_per_frame + wsola->min_extra - 725 samples_len; 726 if (wsola->expand_cnt == 0) 727 new_samples += wsola->min_extra; 704 728 705 729 /* Expand buffer */ 706 730 expand(wsola, new_samples); 707 708 pjmedia_copy_samples(frm, wsola->frm, wsola->samples_per_frame); 709 pjmedia_move_samples(wsola->buf, wsola->buf+wsola->samples_per_frame, 710 wsola->cur_cnt - wsola->samples_per_frame); 711 712 pj_assert(wsola->cur_cnt >= 713 wsola->hist_cnt + (wsola->samples_per_frame << 1)); 714 715 wsola->cur_cnt = (pj_uint16_t)(wsola->cur_cnt - 716 wsola->samples_per_frame); 731 TRACE_((THIS_FILE, "Buf size after expanded = %d", 732 pjmedia_circ_buf_get_len(wsola->buf))); 717 733 wsola->expand_cnt++; 718 734 } 719 735 720 wsola->ts.u64 += wsola->samples_per_frame; 736 status = pjmedia_circ_buf_copy(wsola->buf, wsola->hist_size, frm, 737 wsola->samples_per_frame); 738 if (status != PJ_SUCCESS) { 739 TRACE_((THIS_FILE, "Failed copying from circbuf [err=%d]", status)); 740 return status; 741 } 742 743 pjmedia_circ_buf_adv_read_ptr(wsola->buf, wsola->samples_per_frame); 721 744 722 745 return PJ_SUCCESS; … … 725 748 726 749 PJ_DEF(pj_status_t) pjmedia_wsola_discard( pjmedia_wsola *wsola, 727 short buf1[],750 pj_int16_t buf1[], 728 751 unsigned buf1_cnt, 729 short buf2[],752 pj_int16_t buf2[], 730 753 unsigned buf2_cnt, 731 754 unsigned *del_cnt) … … 735 758 736 759 if (buf2_cnt == 0) { 737 /* Buffer is contiguous space, no need to use temporary 738 * buffer. 739 */ 760 /* The whole buffer is contiguous space, straight away. */ 740 761 *del_cnt = compress(wsola, buf1, buf1_cnt, *del_cnt); 741 742 762 } else { 743 763 PJ_ASSERT_RETURN(buf2, PJ_EINVAL); … … 745 765 if (buf1_cnt < ERASE_CNT * wsola->samples_per_frame && 746 766 buf2_cnt < ERASE_CNT * wsola->samples_per_frame && 747 wsola->erase buf == NULL)767 wsola->erase_buf == NULL) 748 768 { 749 /* We need erase buf but WSOLA was created with769 /* We need erase_buf but WSOLA was created with 750 770 * PJMEDIA_WSOLA_NO_DISCARD flag. 751 771 */ … … 755 775 756 776 if (buf2_cnt >= ERASE_CNT * wsola->samples_per_frame) { 777 /* Enough space to perform compress in the second buffer. */ 757 778 *del_cnt = compress(wsola, buf2, buf2_cnt, *del_cnt); 758 779 } else if (buf1_cnt >= ERASE_CNT * wsola->samples_per_frame) { 780 /* Enough space to perform compress in the first buffer, but then 781 * we need to re-arrange the buffers so there is no gap between 782 * buffers. 783 */ 759 784 unsigned max; 760 785 … … 765 790 max = buf2_cnt; 766 791 767 pjmedia_move_samples(buf1 +buf1_cnt-(*del_cnt), buf2,768 max); 792 pjmedia_move_samples(buf1 + buf1_cnt - (*del_cnt), buf2, max); 793 769 794 if (max < buf2_cnt) { 770 795 pjmedia_move_samples(buf2, buf2+(*del_cnt), 771 796 buf2_cnt-max); 772 797 } 773 774 798 } else { 775 unsigned buf_cnt = buf1_cnt + buf2_cnt; 776 short *rem; /* remainder */ 799 /* Not enough samples in either buffers to perform compress. 800 * Need to combine the buffers in a contiguous space, the erase_buf. 801 */ 802 unsigned buf_size = buf1_cnt + buf2_cnt; 803 pj_int16_t *rem; /* remainder */ 777 804 unsigned rem_cnt; 778 805 779 if (buf_ cnt> ERASE_CNT * wsola->samples_per_frame) {780 buf_ cnt= ERASE_CNT * wsola->samples_per_frame;806 if (buf_size > ERASE_CNT * wsola->samples_per_frame) { 807 buf_size = ERASE_CNT * wsola->samples_per_frame; 781 808 782 rem_cnt = buf1_cnt + buf2_cnt - buf_ cnt;809 rem_cnt = buf1_cnt + buf2_cnt - buf_size; 783 810 rem = buf2 + buf2_cnt - rem_cnt; 784 811 … … 788 815 } 789 816 790 pjmedia_copy_samples(wsola->erase buf, buf1, buf1_cnt);791 pjmedia_copy_samples(wsola->erase buf+buf1_cnt, buf2,792 buf_ cnt-buf1_cnt);793 794 *del_cnt = compress(wsola, wsola->erase buf, buf_cnt, *del_cnt);795 796 buf_ cnt-= (*del_cnt);817 pjmedia_copy_samples(wsola->erase_buf, buf1, buf1_cnt); 818 pjmedia_copy_samples(wsola->erase_buf+buf1_cnt, buf2, 819 buf_size-buf1_cnt); 820 821 *del_cnt = compress(wsola, wsola->erase_buf, buf_size, *del_cnt); 822 823 buf_size -= (*del_cnt); 797 824 798 825 /* Copy back to buffers */ 799 if (buf_ cnt== buf1_cnt) {800 pjmedia_copy_samples(buf1, wsola->erase buf, buf_cnt);826 if (buf_size == buf1_cnt) { 827 pjmedia_copy_samples(buf1, wsola->erase_buf, buf_size); 801 828 if (rem_cnt) { 802 829 pjmedia_move_samples(buf2, rem, rem_cnt); 803 830 } 804 } else if (buf_ cnt< buf1_cnt) {805 pjmedia_copy_samples(buf1, wsola->erase buf, buf_cnt);831 } else if (buf_size < buf1_cnt) { 832 pjmedia_copy_samples(buf1, wsola->erase_buf, buf_size); 806 833 if (rem_cnt) { 807 834 unsigned c = rem_cnt; 808 if (c > buf1_cnt-buf_ cnt) {809 c = buf1_cnt-buf_ cnt;835 if (c > buf1_cnt-buf_size) { 836 c = buf1_cnt-buf_size; 810 837 } 811 pjmedia_copy_samples(buf1+buf_ cnt, rem, c);838 pjmedia_copy_samples(buf1+buf_size, rem, c); 812 839 rem += c; 813 840 rem_cnt -= c; … … 816 843 } 817 844 } else { 818 pjmedia_copy_samples(buf1, wsola->erase buf, buf1_cnt);819 pjmedia_copy_samples(buf2, wsola->erase buf+buf1_cnt,820 buf_ cnt-buf1_cnt);845 pjmedia_copy_samples(buf1, wsola->erase_buf, buf1_cnt); 846 pjmedia_copy_samples(buf2, wsola->erase_buf+buf1_cnt, 847 buf_size-buf1_cnt); 821 848 if (rem_cnt) { 822 pjmedia_move_samples(buf2+buf_ cnt-buf1_cnt, rem,849 pjmedia_move_samples(buf2+buf_size-buf1_cnt, rem, 823 850 rem_cnt); 824 851 } 825 852 } 826 853 827 854 } 828 855 } … … 883 910 884 911 PJ_DEF(pj_status_t) pjmedia_wsola_save( pjmedia_wsola *wsola, 885 short frm[],912 pj_int16_t frm[], 886 913 pj_bool_t prev_lost) 887 914 { … … 895 922 896 923 PJ_DEF(pj_status_t) pjmedia_wsola_generate( pjmedia_wsola *wsola, 897 short frm[])924 pj_int16_t frm[]) 898 925 { 899 926 pjmedia_zero_samples(frm, wsola->samples_per_frame); … … 903 930 904 931 PJ_DEF(pj_status_t) pjmedia_wsola_discard( pjmedia_wsola *wsola, 905 short buf1[],932 pj_int16_t buf1[], 906 933 unsigned buf1_cnt, 907 short buf2[],934 pj_int16_t buf2[], 908 935 unsigned buf2_cnt, 909 936 unsigned *del_cnt) 910 937 { 911 pj_assert(buf1_cnt + buf2_cnt >= wsola->samples_per_frame);938 CHECK_(buf1_cnt + buf2_cnt >= wsola->samples_per_frame); 912 939 913 940 PJ_UNUSED_ARG(buf1);
Note: See TracChangeset
for help on using the changeset viewer.