Changeset 2115


Ignore:
Timestamp:
Jul 10, 2008 2:59:57 PM (16 years ago)
Author:
nanang
Message:

Updated WSOLA to use circular buffer and configurable hanning window size (which affecting number of delay produced by WSOLA)

Location:
pjproject/trunk/pjmedia
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia/wsola.h

    r2039 r2115  
    137137 */ 
    138138PJ_DECL(pj_status_t) pjmedia_wsola_save(pjmedia_wsola *wsola,  
    139                                         short frm[],  
     139                                        pj_int16_t frm[],  
    140140                                        pj_bool_t prev_lost); 
    141141 
     
    149149 */ 
    150150PJ_DECL(pj_status_t) pjmedia_wsola_generate(pjmedia_wsola *wsola,  
    151                                             short frm[]); 
     151                                            pj_int16_t frm[]); 
    152152 
    153153 
     
    175175 */ 
    176176PJ_DECL(pj_status_t) pjmedia_wsola_discard(pjmedia_wsola *wsola,  
    177                                            short buf1[], 
     177                                           pj_int16_t buf1[], 
    178178                                           unsigned buf1_cnt,  
    179                                            short buf2[], 
     179                                           pj_int16_t buf2[], 
    180180                                           unsigned buf2_cnt, 
    181181                                           unsigned *erase_cnt); 
  • pjproject/trunk/pjmedia/src/pjmedia/wsola.c

    r2039 r2115  
    1818 */ 
    1919#include <pjmedia/wsola.h> 
     20#include <pjmedia/circbuf.h> 
    2021#include <pjmedia/errno.h> 
    2122#include <pj/assert.h> 
    2223#include <pj/log.h> 
     24#include <pj/math.h> 
    2325#include <pj/pool.h> 
    2426 
     
    2931#define THIS_FILE   "wsola.c" 
    3032 
     33 
    3134#if (PJMEDIA_WSOLA_IMP==PJMEDIA_WSOLA_IMP_WSOLA) || \ 
    3235    (PJMEDIA_WSOLA_IMP==PJMEDIA_WSOLA_IMP_WSOLA_LITE) 
     
    3639 */ 
    3740 
    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       4 
    43  
    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 
    4952 
    5053/* Number of frames in erase buffer */ 
    5154#define ERASE_CNT       ((unsigned)3) 
    5255 
    53  
    54 #ifndef M_PI 
    55 #   define  M_PI        3.14159265358979323846 
    56 #endif 
    5756 
    5857#if 0 
     
    6261#endif 
    6362 
     63#if 0 
     64#   define CHECK_(x)    pj_assert(x) 
     65#else 
     66#   define CHECK_(x) 
     67#endif 
    6468 
    6569/* Buffer content: 
    6670 * 
    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. 
    6978 * 
    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. 
    7784 * 
    78  * History count (hist_cnt) is a constant value, initialized upon  
    79  * creation. 
     85 * More extra is excess samples produced by PLC (PLC frame generation may  
     86 * produce more than exact one frame). 
    8087 * 
    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. 
    8390 * 
    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 * 
    8795 */ 
    8896 
     
    9098struct pjmedia_wsola 
    9199{ 
    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 
    108117#if defined(PJ_HAS_FLOATING_POINT) && PJ_HAS_FLOATING_POINT!=0 
    109     float    *hanning;          /* Hanning window.                      */ 
     118    float               *hanning;           /* Hanning window.              */ 
    110119#else 
    111     pj_uint16_t *hanning;       /* Hanning window.                      */ 
     120    pj_uint16_t         *hanning;           /* Hanning window.              */ 
    112121#endif 
    113122 
    114     pj_timestamp ts;            /* Running timestamp.                   */ 
     123    pj_timestamp         ts;                /* Running timestamp.           */ 
    115124}; 
    116125 
     
    125134 * diff level = (template[1]+..+template[n]) - (target[1]+..+target[n]) 
    126135 */ 
    127 static short *find_pitch(short *frm, short *beg, short *end,  
     136static pj_int16_t *find_pitch(pj_int16_t *frm, pj_int16_t *beg, pj_int16_t *end,  
    128137                         unsigned template_cnt, int first) 
    129138{ 
    130     short *sr, *best=beg; 
     139    pj_int16_t *sr, *best=beg; 
    131140    int best_corr = 0x7FFFFFFF; 
    132141    int frm_sum = 0; 
     
    186195 * Floating point version. 
    187196 */ 
    188 #include <math.h> 
    189197 
    190198#if (PJMEDIA_WSOLA_IMP==PJMEDIA_WSOLA_IMP_WSOLA) 
    191199 
    192 static short *find_pitch(short *frm, short *beg, short *end,  
     200static pj_int16_t *find_pitch(pj_int16_t *frm, pj_int16_t *beg, pj_int16_t *end,  
    193201                         unsigned template_cnt, int first) 
    194202{ 
    195     short *sr, *best=beg; 
     203    pj_int16_t *sr, *best=beg; 
    196204    double best_corr = 0; 
    197205 
     
    241249#endif 
    242250 
    243 static void overlapp_add(short dst[], unsigned count, 
    244                          short l[], short r[], 
     251static void overlapp_add(pj_int16_t dst[], unsigned count, 
     252                         pj_int16_t l[], pj_int16_t r[], 
    245253                         float w[]) 
    246254{ 
     
    248256 
    249257    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 
     262static void overlapp_add_simple(pj_int16_t dst[], unsigned count, 
     263                                pj_int16_t l[], pj_int16_t r[]) 
    256264{ 
    257265    float step = (float)(1.0 / count), stepdown = 1.0; 
     
    259267 
    260268    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)); 
    262270        stepdown -= step; 
    263271    } 
     
    272280 
    273281    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)) ); 
    275283    } 
    276284} 
     
    285293#if (PJMEDIA_WSOLA_IMP==PJMEDIA_WSOLA_IMP_WSOLA) 
    286294 
    287 static short *find_pitch(short *frm, short *beg, short *end,  
     295static pj_int16_t *find_pitch(pj_int16_t *frm, pj_int16_t *beg, pj_int16_t *end,  
    288296                         unsigned template_cnt, int first) 
    289297{ 
    290     short *sr, *best=beg; 
     298    pj_int16_t *sr, *best=beg; 
    291299    pj_int64_t best_corr = 0; 
    292300 
     
    338346 
    339347 
    340 static void overlapp_add(short dst[], unsigned count, 
    341                          short l[], short r[], 
     348static void overlapp_add(pj_int16_t dst[], unsigned count, 
     349                         pj_int16_t l[], pj_int16_t r[], 
    342350                         pj_uint16_t w[]) 
    343351{ 
     
    345353 
    346354    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]) +  
    348356                          (int)(r[i]) * (int)(w[i])) >> WINDOW_BITS); 
    349357    } 
    350358} 
    351359 
    352 static void overlapp_add_simple(short dst[], unsigned count, 
    353                                 short l[], short r[]) 
     360static void overlapp_add_simple(pj_int16_t dst[], unsigned count, 
     361                                pj_int16_t l[], pj_int16_t r[]) 
    354362{ 
    355363    int step = ((WINDOW_MAX_VAL+1) / count),  
     
    358366 
    359367    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); 
    361369        stepdown -= step; 
    362370    } 
     
    399407        pj_uint64_t cos_val; 
    400408 
    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)) ); */ 
    402410 
    403411        phase = (pj_uint32_t)(PJ_INT64(0xFFFFFFFF) * i / (count*2-1)); 
     
    424432{ 
    425433    pjmedia_wsola *wsola; 
     434    pj_status_t status; 
    426435 
    427436    PJ_ASSERT_RETURN(pool && clock_rate && samples_per_frame && p_wsola, 
     
    431440    PJ_ASSERT_RETURN(channel_count > 0, PJ_EINVAL); 
    432441 
     442    /* Allocate wsola and initialize vars */ 
    433443    wsola = PJ_POOL_ZALLOC_T(pool, pjmedia_wsola); 
    434      
    435444    wsola->clock_rate= (pj_uint16_t) clock_rate; 
    436445    wsola->samples_per_frame = (pj_uint16_t) samples_per_frame; 
    437446    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 */ 
    468485    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 */ 
    472490    if ((options & PJMEDIA_WSOLA_NO_DISCARD) == 0) { 
    473         wsola->erasebuf = (short*)pj_pool_calloc(pool, samples_per_frame * 
     491        wsola->erase_buf = (pj_int16_t*)pj_pool_calloc(pool, samples_per_frame * 
    474492                                                       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); 
    477498 
    478499    *p_wsola = wsola; 
     
    496517    PJ_UNUSED_ARG(options); 
    497518 
    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 
    501522    return PJ_SUCCESS; 
    502523} 
     
    506527{ 
    507528    unsigned generated = 0; 
    508     unsigned frmsz = wsola->samples_per_frame; 
    509529    unsigned rep; 
    510530 
     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, &reg1, &reg1_len,  
     536                                      &reg2, &reg2_len); 
     537    CHECK_(reg2_len == 0); 
     538 
    511539    for (rep=1;; ++rep) { 
    512         short *start, *frm; 
     540        pj_int16_t *start, *templ; 
    513541        unsigned min_dist, max_dist, dist; 
    514542 
    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->template_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); 
    523551 
    524552        /* Should we make sure that "start" is really aligned to 
     
    528556 
    529557        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); 
    531560        } 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); 
    533563        } 
    534564 
    535565        /* 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; 
    537571 
    538572        /* 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); 
    541576 
    542577        /* Copy the merged frame */ 
    543         pjmedia_copy_samples(frm, wsola->mergebuf, frmsz); 
     578        pjmedia_copy_samples(templ, wsola->merge_buf, wsola->hanning_size); 
    544579 
    545580        /* 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); 
    549583 
    550584        generated += dist; 
     
    559593 
    560594 
    561 static unsigned compress(pjmedia_wsola *wsola, short *buf, unsigned count, 
     595static unsigned compress(pjmedia_wsola *wsola, pj_int16_t *buf, unsigned count, 
    562596                         unsigned del_cnt) 
    563597{ 
     
    565599 
    566600    for (rep=1; ; ++rep) { 
    567         short *start, *end; 
    568         unsigned frmsz = wsola->samples_per_frame; 
     601        pj_int16_t *start, *end; 
    569602        unsigned dist; 
    570603 
    571         if ((count - del_cnt) <= frmsz) { 
    572         //if (count <= (del_cnt << 1)) { 
     604        if (count <= wsola->hanning_size + del_cnt) { 
    573605            TRACE_((THIS_FILE, "Not enough samples to compress!")); 
    574606            return samples_del; 
    575607        } 
    576608 
     609        // Make start distance to del_cnt, so discard will be performed in 
     610        // only one iteration. 
    577611        //start = buf + (frmsz >> 1); 
    578612        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); 
    587622        dist = start - buf; 
    588623 
    589624        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); 
    591626        } 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); 
    598633 
    599634        count -= dist; 
     
    614649 
    615650PJ_DEF(pj_status_t) pjmedia_wsola_save( pjmedia_wsola *wsola,  
    616                                         short frm[],  
     651                                        pj_int16_t frm[],  
    617652                                        pj_bool_t prev_lost) 
    618653{ 
    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 */ 
    670661    wsola->expand_cnt = 0; 
    671662    wsola->ts.u64 += wsola->samples_per_frame; 
    672663 
    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, &reg1, &reg1_len,  
     671                                          &reg2, &reg2_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); 
    674706} 
    675707 
    676708 
    677709PJ_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    { 
    699721        unsigned new_samples; 
    700722 
    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; 
    704728 
    705729        /* Expand buffer */ 
    706730        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))); 
    717733        wsola->expand_cnt++; 
    718734    } 
    719735 
    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); 
    721744 
    722745    return PJ_SUCCESS; 
     
    725748 
    726749PJ_DEF(pj_status_t) pjmedia_wsola_discard( pjmedia_wsola *wsola,  
    727                                            short buf1[], 
     750                                           pj_int16_t buf1[], 
    728751                                           unsigned buf1_cnt,  
    729                                            short buf2[], 
     752                                           pj_int16_t buf2[], 
    730753                                           unsigned buf2_cnt, 
    731754                                           unsigned *del_cnt) 
     
    735758 
    736759    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. */ 
    740761        *del_cnt = compress(wsola, buf1, buf1_cnt, *del_cnt); 
    741  
    742762    } else { 
    743763        PJ_ASSERT_RETURN(buf2, PJ_EINVAL); 
     
    745765        if (buf1_cnt < ERASE_CNT * wsola->samples_per_frame && 
    746766            buf2_cnt < ERASE_CNT * wsola->samples_per_frame && 
    747             wsola->erasebuf == NULL) 
     767            wsola->erase_buf == NULL) 
    748768        { 
    749             /* We need erasebuf but WSOLA was created with  
     769            /* We need erase_buf but WSOLA was created with  
    750770             * PJMEDIA_WSOLA_NO_DISCARD flag. 
    751771             */ 
     
    755775 
    756776        if (buf2_cnt >= ERASE_CNT * wsola->samples_per_frame) { 
     777            /* Enough space to perform compress in the second buffer. */ 
    757778            *del_cnt = compress(wsola, buf2, buf2_cnt, *del_cnt); 
    758779        } 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             */ 
    759784            unsigned max; 
    760785 
     
    765790                max = buf2_cnt; 
    766791 
    767             pjmedia_move_samples(buf1+buf1_cnt-(*del_cnt), buf2,  
    768                                  max); 
     792            pjmedia_move_samples(buf1 + buf1_cnt - (*del_cnt), buf2, max); 
     793 
    769794            if (max < buf2_cnt) { 
    770795                pjmedia_move_samples(buf2, buf2+(*del_cnt),  
    771796                                     buf2_cnt-max); 
    772797            } 
    773  
    774798        } 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 */ 
    777804            unsigned rem_cnt; 
    778805 
    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; 
    781808                 
    782                 rem_cnt = buf1_cnt + buf2_cnt - buf_cnt; 
     809                rem_cnt = buf1_cnt + buf2_cnt - buf_size; 
    783810                rem = buf2 + buf2_cnt - rem_cnt; 
    784811                 
     
    788815            } 
    789816 
    790             pjmedia_copy_samples(wsola->erasebuf, buf1, buf1_cnt); 
    791             pjmedia_copy_samples(wsola->erasebuf+buf1_cnt, buf2,  
    792                                  buf_cnt-buf1_cnt); 
    793  
    794             *del_cnt = compress(wsola, wsola->erasebuf, 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); 
    797824 
    798825            /* Copy back to buffers */ 
    799             if (buf_cnt == buf1_cnt) { 
    800                 pjmedia_copy_samples(buf1, wsola->erasebuf, buf_cnt); 
     826            if (buf_size == buf1_cnt) { 
     827                pjmedia_copy_samples(buf1, wsola->erase_buf, buf_size); 
    801828                if (rem_cnt) { 
    802829                    pjmedia_move_samples(buf2, rem, rem_cnt); 
    803830                } 
    804             } else if (buf_cnt < buf1_cnt) { 
    805                 pjmedia_copy_samples(buf1, wsola->erasebuf, buf_cnt); 
     831            } else if (buf_size < buf1_cnt) { 
     832                pjmedia_copy_samples(buf1, wsola->erase_buf, buf_size); 
    806833                if (rem_cnt) { 
    807834                    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; 
    810837                    } 
    811                     pjmedia_copy_samples(buf1+buf_cnt, rem, c); 
     838                    pjmedia_copy_samples(buf1+buf_size, rem, c); 
    812839                    rem += c; 
    813840                    rem_cnt -= c; 
     
    816843                } 
    817844            } else { 
    818                 pjmedia_copy_samples(buf1, wsola->erasebuf, buf1_cnt); 
    819                 pjmedia_copy_samples(buf2, wsola->erasebuf+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); 
    821848                if (rem_cnt) { 
    822                     pjmedia_move_samples(buf2+buf_cnt-buf1_cnt, rem, 
     849                    pjmedia_move_samples(buf2+buf_size-buf1_cnt, rem, 
    823850                                         rem_cnt); 
    824851                } 
    825852            } 
    826  
     853             
    827854        } 
    828855    } 
     
    883910 
    884911PJ_DEF(pj_status_t) pjmedia_wsola_save( pjmedia_wsola *wsola,  
    885                                         short frm[],  
     912                                        pj_int16_t frm[],  
    886913                                        pj_bool_t prev_lost) 
    887914{ 
     
    895922 
    896923PJ_DEF(pj_status_t) pjmedia_wsola_generate( pjmedia_wsola *wsola,  
    897                                             short frm[]) 
     924                                            pj_int16_t frm[]) 
    898925{ 
    899926    pjmedia_zero_samples(frm, wsola->samples_per_frame); 
     
    903930 
    904931PJ_DEF(pj_status_t) pjmedia_wsola_discard( pjmedia_wsola *wsola,  
    905                                            short buf1[], 
     932                                           pj_int16_t buf1[], 
    906933                                           unsigned buf1_cnt,  
    907                                            short buf2[], 
     934                                           pj_int16_t buf2[], 
    908935                                           unsigned buf2_cnt, 
    909936                                           unsigned *del_cnt) 
    910937{ 
    911     pj_assert(buf1_cnt + buf2_cnt >= wsola->samples_per_frame); 
     938    CHECK_(buf1_cnt + buf2_cnt >= wsola->samples_per_frame); 
    912939 
    913940    PJ_UNUSED_ARG(buf1); 
Note: See TracChangeset for help on using the changeset viewer.