Changeset 2116


Ignore:
Timestamp:
Jul 10, 2008 3:04:27 PM (11 years ago)
Author:
nanang
Message:

Updated delay buffer to use circular buffer

Location:
pjproject/trunk/pjmedia
Files:
2 edited

Legend:

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

    r2039 r2116  
    151151PJ_END_DECL 
    152152 
     153/** 
     154 * @} 
     155 */ 
    153156 
    154157#endif  /* __PJMEDIA_DELAYBUF_H__ */ 
  • pjproject/trunk/pjmedia/src/pjmedia/delaybuf.c

    r2039 r2116  
    1919 
    2020#include <pjmedia/delaybuf.h> 
     21#include <pjmedia/circbuf.h> 
    2122#include <pjmedia/errno.h> 
    2223#include <pjmedia/wsola.h> 
     
    6162    char             obj_name[PJ_MAX_OBJ_NAME]; 
    6263    pj_lock_t       *lock;              /**< Lock object.                    */ 
    63     pj_int16_t      *frame_buf; 
    6464    unsigned         samples_per_frame; /**< Number of samples in one frame  */ 
    6565    unsigned         ptime;             /**< Frame time, in ms               */ 
    6666    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  */ 
    7370    unsigned         eff_cnt;           /**< Effective count of buffered  
    7471                                             samples to keep the optimum 
     
    129126        return status; 
    130127 
    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; 
    133131 
    134132    status = pjmedia_wsola_create(pool, clock_rate, samples_per_frame, 1, 
    135                                   PJMEDIA_WSOLA_NO_PLC, &b->wsola); 
     133                                  0, &b->wsola); 
    136134    if (status != PJ_SUCCESS) 
    137135        return status; 
     
    169167static void shrink_buffer(pjmedia_delay_buf *b, unsigned erase_cnt) 
    170168{ 
     169    pj_int16_t *buf1, *buf2; 
    171170    unsigned buf1len; 
    172171    unsigned buf2len; 
    173172    pj_status_t status; 
    174173 
    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. 
    181185         */ 
    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); 
    218190 
    219191        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))); 
    221193    } 
    222194} 
     
    266238 
    267239    /* 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    { 
    269243        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); 
    271245 
    272246        shrink_buffer(b, erase_cnt); 
    273247        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)); 
    275251    } 
    276252} 
     
    294270 
    295271    /* 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) 
    297274    { 
    298275        unsigned erase_cnt; 
     
    300277        /* shrink one frame or just the diff? */ 
    301278        //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; 
    303281 
    304282        shrink_buffer(b, erase_cnt); 
     
    308286         * samples get rough transition which may produce tick noise. 
    309287         */ 
    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); 
    317295 
    318296            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))); 
    320299        } 
    321300    } 
    322301 
    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); 
    340303 
    341304    pj_lock_release(b->lock); 
     
    355318 
    356319    /* 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) { 
    358321 
    359322        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))); 
    361324 
    362325        status = pjmedia_wsola_generate(b->wsola, frame); 
     
    364327        if (status == PJ_SUCCESS) { 
    365328            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) { 
    367330                pj_lock_release(b->lock); 
    368331                return PJ_SUCCESS; 
     
    370333 
    371334            /* 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); 
    387336 
    388337        } else { 
     338            unsigned buf_len = pjmedia_circ_buf_get_len(b->circ_buf); 
     339             
    389340            /* Give all what delay buffer has, then pad with zeroes */ 
    390341            PJ_LOG(4,(b->obj_name,"Error generating frame, status=%d",  
    391342                      status)); 
    392343 
    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); 
    410350 
    411351            pj_lock_release(b->lock); 
     
    415355    } 
    416356 
    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); 
    432358 
    433359    pj_lock_release(b->lock); 
     
    445371    b->recalc_timer = RECALC_TIME; 
    446372 
    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 */ 
    450377    pjmedia_wsola_reset(b->wsola, 0); 
    451378 
Note: See TracChangeset for help on using the changeset viewer.