Changeset 1827


Ignore:
Timestamp:
Feb 28, 2008 8:22:16 PM (16 years ago)
Author:
bennylp
Message:

Modify WSOLA discard to support erasing frame from non-contiguous buffer

Location:
pjproject/trunk/pjmedia
Files:
3 edited

Legend:

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

    r1734 r1827  
    191191{ 
    192192#if 1 
    193     pj_bzero(samples, count*sizeof(pj_int16_t)); 
     193    pj_bzero(samples, (count<<1)); 
    194194#elif 0 
    195195    unsigned i; 
     
    213213{ 
    214214#if 1 
    215     pj_memcpy(dst, src, count*sizeof(pj_int16_t)); 
     215    pj_memcpy(dst, src, (count<<1)); 
    216216#elif 0 
    217217    unsigned i; 
     
    227227 
    228228/** 
     229 * This is a general purpose function to copy samples from/to buffers with 
     230 * equal size. Since this function is needed by many parts of the library,  
     231 * by putting this functionality in one place, it enables some. 
     232 * clever people to optimize this function. 
     233 */ 
     234PJ_INLINE(void) pjmedia_move_samples(pj_int16_t *dst, const pj_int16_t *src, 
     235                                     unsigned count) 
     236{ 
     237#if 1 
     238    pj_memmove(dst, src, (count<<1)); 
     239#elif 0 
     240    unsigned i; 
     241    for (i=0; i<count; ++i) dst[i] = src[i]; 
     242#else 
     243    unsigned i; 
     244    count >>= 1; 
     245    for (i=0; i<count; ++i)  
     246        ((pj_int32_t*)dst)[i] = ((pj_int32_t*)src)[i]; 
     247#endif 
     248} 
     249 
     250/** 
    229251 * @} 
    230252 */ 
  • pjproject/trunk/pjmedia/include/pjmedia/wsola.h

    r1824 r1827  
    5959     * Specify that the WSOLA will not be used for PLC. 
    6060     */ 
    61     PJMEDIA_WSOLA_NO_PLC = 2 
     61    PJMEDIA_WSOLA_NO_PLC = 2, 
     62 
     63    /** 
     64     * Specify that the WSOLA will not be used to discard frames in 
     65     * non-contiguous buffer. 
     66     */ 
     67    PJMEDIA_WSOLA_NO_DISCARD = 4 
    6268}; 
    6369 
     
    130136/** 
    131137 * Compress or compact the specified buffer by removing some audio samples 
    132  * from the buffer, without altering the pitch. 
     138 * from the buffer, without altering the pitch. For this function to work,  
     139 * total length of the buffer must be more than twice \a erase_cnt. 
    133140 *  
    134141 * @param wsola     WSOLA session. 
    135  * @param buf       Pointer to buffer. For this function to work, the buffer 
    136  *                  must contain more than twice \a erase_cnt number of  
    137  *                  samples. 
    138  * @param buf_cnt   Number of samples in the buffer. 
     142 * @param buf1      Pointer to buffer.  
     143 * @param buf1_cnt  Number of samples in the buffer. 
     144 * @param buf2      Pointer to second buffer, if the buffer is not 
     145 *                  contiguous. Otherwise this parameter must be NULL. 
     146 * @param buf2_cnt  Number of samples in the second buffer, if the buffer 
     147 *                  is not contiguous. Otherwise this parameter should be 
     148 *                  zero. 
    139149 * @param erase_cnt On input, specify the number of samples to be erased. 
    140150 *                  This function may erase more or less than the requested  
     
    147157 */ 
    148158PJ_DECL(pj_status_t) pjmedia_wsola_discard(pjmedia_wsola *wsola,  
    149                                            short buf[], 
    150                                            unsigned buf_cnt,  
     159                                           short buf1[], 
     160                                           unsigned buf1_cnt,  
     161                                           short buf2[], 
     162                                           unsigned buf2_cnt, 
    151163                                           unsigned *erase_cnt); 
    152164 
  • pjproject/trunk/pjmedia/src/pjmedia/wsola.c

    r1826 r1827  
    3939#define GEN_EXTRA_PTIME (0.0) 
    4040 
     41/* Number of frames in erase buffer */ 
     42#define ERASE_CNT       ((unsigned)3) 
     43 
    4144 
    4245#ifndef M_PI 
     
    6770    short    *frm;              /* Pointer to next frame to play in buf */ 
    6871    short    *mergebuf;         /* Temporary merge buffer.              */ 
     72    short    *erasebuf;         /* Temporary erase buffer.              */ 
    6973#if defined(PJ_HAS_FLOATING_POINT) && PJ_HAS_FLOATING_POINT!=0 
    7074    float    *hanning;          /* Hanning window.                      */ 
     
    330334    } 
    331335 
     336    if ((options & PJMEDIA_WSOLA_NO_DISCARD) == 0) { 
     337        wsola->erasebuf = (short*)pj_pool_calloc(pool, samples_per_frame * 
     338                                                       ERASE_CNT, 
     339                                                 sizeof(short)); 
     340    } 
     341 
    332342    *p_wsola = wsola; 
    333343    return PJ_SUCCESS; 
     
    366376 
    367377        dist = wsola->frm - start; 
    368         memmove(wsola->frm + frmsz, start + frmsz,  
    369                 (wsola->buf+wsola->cur_cnt - (start+frmsz)) << 1); 
    370  
    371         memcpy(wsola->frm, wsola->mergebuf, frmsz << 1); 
     378        pjmedia_move_samples(wsola->frm + frmsz, start + frmsz,  
     379                             wsola->buf+wsola->cur_cnt - (start+frmsz)); 
     380 
     381        pjmedia_copy_samples(wsola->frm, wsola->mergebuf, frmsz); 
    372382 
    373383        wsola->cur_cnt = (pj_uint16_t)(wsola->cur_cnt + dist); 
     
    385395 
    386396static unsigned compress(pjmedia_wsola *wsola, short *buf, unsigned count, 
    387                          unsigned erase_cnt) 
     397                         unsigned del_cnt) 
    388398{ 
    389399    unsigned samples_del = 0, rep; 
     
    394404        unsigned dist; 
    395405 
    396         if (count <= (erase_cnt << 1)) { 
     406        if (count <= (del_cnt << 1)) { 
    397407            TRACE_((THIS_FILE, "Not enough samples to compress!")); 
    398408            return samples_del; 
     
    415425        } 
    416426 
    417         memmove(buf + frmsz, buf + frmsz + dist, 
    418                 (count - frmsz - dist) * 2); 
     427        pjmedia_move_samples(buf + frmsz, buf + frmsz + dist, 
     428                             count - frmsz - dist); 
    419429 
    420430        count -= dist; 
    421431        samples_del += dist; 
    422432 
    423         if (samples_del >= erase_cnt) { 
     433        if (samples_del >= del_cnt) { 
    424434            TRACE_((THIS_FILE,  
    425435                    "Erased %d of %d requested after %d iteration(s)", 
    426                     samples_del, erase_cnt, rep)); 
     436                    samples_del, del_cnt, rep)); 
    427437            break; 
    428438        } 
     
    453463 
    454464         
    455         memcpy(frm, wsola->frm, wsola->samples_per_frame << 1); 
     465        pjmedia_copy_samples(frm, wsola->frm, wsola->samples_per_frame); 
    456466        wsola->cur_cnt = (pj_uint16_t)(wsola->hist_cnt +  
    457467                                       wsola->samples_per_frame); 
    458         memmove(wsola->buf, wsola->buf+wsola->samples_per_frame,  
    459                 wsola->cur_cnt << 1); 
     468        pjmedia_move_samples(wsola->buf, wsola->buf+wsola->samples_per_frame, 
     469                              wsola->cur_cnt); 
    460470 
    461471    } else { 
     
    466476        } 
    467477 
    468         memcpy(wsola->buf + wsola->cur_cnt, frm,  
    469                wsola->samples_per_frame << 1); 
    470         memcpy(frm, wsola->frm,  
    471                wsola->samples_per_frame << 1); 
    472         memmove(wsola->buf, wsola->buf+wsola->samples_per_frame,  
    473                 wsola->cur_cnt << 1); 
     478        pjmedia_copy_samples(wsola->buf + wsola->cur_cnt, frm,  
     479                             wsola->samples_per_frame); 
     480        pjmedia_copy_samples(frm, wsola->frm,  
     481                             wsola->samples_per_frame); 
     482        pjmedia_move_samples(wsola->buf, wsola->buf+wsola->samples_per_frame, 
     483                             wsola->cur_cnt); 
    474484    } 
    475485     
     
    493503         * rather than generating a new one. 
    494504         */ 
    495         memcpy(frm, wsola->frm, wsola->samples_per_frame << 1); 
    496         memmove(wsola->buf, wsola->buf+wsola->samples_per_frame,  
    497                 (wsola->cur_cnt - wsola->samples_per_frame) << 1); 
     505        pjmedia_copy_samples(frm, wsola->frm, wsola->samples_per_frame); 
     506        pjmedia_move_samples(wsola->buf, wsola->buf+wsola->samples_per_frame, 
     507                             wsola->cur_cnt - wsola->samples_per_frame); 
    498508 
    499509        pj_assert(wsola->cur_cnt >=  
     
    512522        expand(wsola, new_samples); 
    513523 
    514         memcpy(frm, wsola->frm, wsola->samples_per_frame << 1); 
    515         memmove(wsola->buf, wsola->buf+wsola->samples_per_frame,  
    516                 (wsola->cur_cnt - wsola->samples_per_frame) << 1); 
     524        pjmedia_copy_samples(frm, wsola->frm, wsola->samples_per_frame); 
     525        pjmedia_move_samples(wsola->buf, wsola->buf+wsola->samples_per_frame, 
     526                             wsola->cur_cnt - wsola->samples_per_frame); 
    517527 
    518528        pj_assert(wsola->cur_cnt >=  
     
    531541 
    532542PJ_DEF(pj_status_t) pjmedia_wsola_discard( pjmedia_wsola *wsola,  
    533                                            short buf[], 
    534                                            unsigned buf_cnt,  
    535                                            unsigned *erase_cnt) 
    536 { 
    537     PJ_ASSERT_RETURN(wsola && buf && buf_cnt && erase_cnt, PJ_EINVAL); 
    538     PJ_ASSERT_RETURN(*erase_cnt, PJ_EINVAL); 
    539  
    540     *erase_cnt = compress(wsola, buf, buf_cnt, *erase_cnt); 
    541     return (*erase_cnt) > 0 ? PJ_SUCCESS : PJ_ETOOSMALL; 
    542 } 
    543  
    544  
     543                                           short buf1[], 
     544                                           unsigned buf1_cnt,  
     545                                           short buf2[], 
     546                                           unsigned buf2_cnt, 
     547                                           unsigned *del_cnt) 
     548{ 
     549    PJ_ASSERT_RETURN(wsola && buf1 && buf1_cnt && del_cnt, PJ_EINVAL); 
     550    PJ_ASSERT_RETURN(*del_cnt, PJ_EINVAL); 
     551 
     552    if (buf2_cnt == 0) { 
     553        /* Buffer is contiguous space, no need to use temporary 
     554         * buffer. 
     555         */ 
     556        *del_cnt = compress(wsola, buf1, buf1_cnt, *del_cnt); 
     557 
     558    } else { 
     559        PJ_ASSERT_RETURN(buf2, PJ_EINVAL); 
     560 
     561        if (buf1_cnt < ERASE_CNT * wsola->samples_per_frame && 
     562            buf2_cnt < ERASE_CNT * wsola->samples_per_frame && 
     563            wsola->erasebuf == NULL) 
     564        { 
     565            /* We need erasebuf but WSOLA was created with  
     566             * PJMEDIA_WSOLA_NO_DISCARD flag. 
     567             */ 
     568            pj_assert(!"WSOLA need erase buffer!"); 
     569            return PJ_EINVALIDOP; 
     570        } 
     571 
     572        if (buf2_cnt >= ERASE_CNT * wsola->samples_per_frame) { 
     573            *del_cnt = compress(wsola, buf2, buf2_cnt, *del_cnt); 
     574        } else if (buf1_cnt >= ERASE_CNT * wsola->samples_per_frame) { 
     575            unsigned max; 
     576 
     577            *del_cnt = compress(wsola, buf1, buf1_cnt, *del_cnt); 
     578 
     579            max = *del_cnt; 
     580            if (max > buf2_cnt) 
     581                max = buf2_cnt; 
     582 
     583            pjmedia_move_samples(buf1+buf1_cnt-(*del_cnt), buf2,  
     584                                 max); 
     585            if (max < buf2_cnt) { 
     586                pjmedia_move_samples(buf2, buf2+(*del_cnt),  
     587                                     buf2_cnt-max); 
     588            } 
     589 
     590        } else { 
     591            unsigned buf_cnt = buf1_cnt + buf2_cnt; 
     592            unsigned max; 
     593 
     594            if (buf_cnt > ERASE_CNT * wsola->samples_per_frame) 
     595                buf_cnt = ERASE_CNT * wsola->samples_per_frame; 
     596 
     597            pjmedia_copy_samples(wsola->erasebuf, buf1, buf1_cnt); 
     598            pjmedia_copy_samples(wsola->erasebuf+buf1_cnt, buf2,  
     599                                 buf_cnt-buf1_cnt); 
     600 
     601            *del_cnt = compress(wsola, wsola->erasebuf, buf_cnt, *del_cnt); 
     602 
     603            buf_cnt -= (*del_cnt); 
     604 
     605            max = buf_cnt; 
     606            if (max > buf1_cnt) 
     607                max = buf1_cnt; 
     608            pjmedia_copy_samples(buf1, wsola->erasebuf, max); 
     609 
     610            if (max < buf_cnt) { 
     611                pjmedia_copy_samples(buf2, wsola->erasebuf+max, buf_cnt-max); 
     612            } 
     613        } 
     614    } 
     615 
     616    return (*del_cnt) > 0 ? PJ_SUCCESS : PJ_ETOOSMALL; 
     617} 
     618 
     619 
Note: See TracChangeset for help on using the changeset viewer.