Ignore:
Timestamp:
Jul 10, 2008 10:46:34 AM (16 years ago)
Author:
nanang
Message:

Added two APIs to pjmedia circular buffer: copy & pack buffer

File:
1 edited

Legend:

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

    r2098 r2114  
    1818 */ 
    1919 
    20 #ifndef pjmedia_circ_buf_H 
    21 #define pjmedia_circ_buf_H 
     20#ifndef __PJMEDIA_CIRC_BUF_H__ 
     21#define __PJMEDIA_CIRC_BUF_H__ 
    2222 
    2323/** 
     
    151151 *                          possitive number, in samples. 
    152152 * 
    153  * @return                  PJ_SUCCESS when successful, otherwise the appropriate  
    154  *                          error will be returned. 
     153 * @return                  PJ_SUCCESS when successful, otherwise  
     154 *                          the appropriate error will be returned. 
    155155 */ 
    156156PJ_INLINE(pj_status_t) pjmedia_circ_buf_adv_read_ptr(pjmedia_circ_buf *circbuf,  
     
    180180 *                          possitive number, in samples. 
    181181 * 
    182  * @return                  PJ_SUCCESS when successful, otherwise the appropriate  
    183  *                          error will be returned. 
     182 * @return                  PJ_SUCCESS when successful, otherwise  
     183 *                          the appropriate error will be returned. 
    184184 */ 
    185185PJ_INLINE(pj_status_t) pjmedia_circ_buf_adv_write_ptr(pjmedia_circ_buf *circbuf, 
     
    223223    } 
    224224 
    225     PJMEDIA_CIRC_BUF_CHECK(*reg1_len != 0 || (*reg1_len == 0 && circbuf->len == 0)); 
     225    PJMEDIA_CIRC_BUF_CHECK(*reg1_len != 0 || (*reg1_len == 0 &&  
     226                                              circbuf->len == 0)); 
    226227    PJMEDIA_CIRC_BUF_CHECK(*reg1_len + *reg2_len == circbuf->len); 
    227228} 
     
    258259    } 
    259260 
    260     PJMEDIA_CIRC_BUF_CHECK(*reg1_len != 0 || (*reg1_len == 0 && circbuf->len == 0)); 
    261     PJMEDIA_CIRC_BUF_CHECK(*reg1_len + *reg2_len == circbuf->capacity - circbuf->len); 
     261    PJMEDIA_CIRC_BUF_CHECK(*reg1_len != 0 || (*reg1_len == 0 &&  
     262                                              circbuf->len == 0)); 
     263    PJMEDIA_CIRC_BUF_CHECK(*reg1_len + *reg2_len == circbuf->capacity -  
     264                           circbuf->len); 
    262265} 
    263266 
     
    270273 * @param count             Number of samples being read. 
    271274 * 
    272  * @return                  PJ_SUCCESS when successful, otherwise the appropriate  
    273  *                          error will be returned. 
     275 * @return                  PJ_SUCCESS when successful, otherwise  
     276 *                          the appropriate error will be returned. 
    274277 */ 
    275278PJ_INLINE(pj_status_t) pjmedia_circ_buf_read(pjmedia_circ_buf *circbuf,  
     
    304307 * @param count             Number of samples being written. 
    305308 * 
    306  * @return                  PJ_SUCCESS when successful, otherwise the appropriate  
    307  *                          error will be returned. 
     309 * @return                  PJ_SUCCESS when successful, otherwise 
     310 *                          the appropriate error will be returned. 
    308311 */ 
    309312PJ_INLINE(pj_status_t) pjmedia_circ_buf_write(pjmedia_circ_buf *circbuf,  
     
    330333} 
    331334 
     335 
     336/** 
     337 * Copy audio samples from the circular buffer without changing its state.  
     338 * 
     339 * @param circbuf           The circular buffer. 
     340 * @param start_idx         Starting sample index to be copied. 
     341 * @param data              Buffer to store the read audio samples. 
     342 * @param count             Number of samples being read. 
     343 * 
     344 * @return                  PJ_SUCCESS when successful, otherwise  
     345 *                          the appropriate error will be returned. 
     346 */ 
     347PJ_INLINE(pj_status_t) pjmedia_circ_buf_copy(pjmedia_circ_buf *circbuf,  
     348                                             unsigned start_idx, 
     349                                             pj_int16_t *data,  
     350                                             unsigned count) 
     351{ 
     352    pj_int16_t *reg1, *reg2; 
     353    unsigned reg1cnt, reg2cnt; 
     354 
     355    /* Data in the buffer is less than requested */ 
     356    if (count + start_idx > circbuf->len) 
     357        return PJ_ETOOBIG; 
     358 
     359    pjmedia_circ_buf_get_read_regions(circbuf, &reg1, &reg1cnt,  
     360                                      &reg2, &reg2cnt); 
     361    if (reg1cnt > start_idx) { 
     362        unsigned tmp_len; 
     363        tmp_len = reg1cnt - start_idx; 
     364        if (tmp_len > count) 
     365            tmp_len = count; 
     366        pjmedia_copy_samples(data, reg1 + start_idx, tmp_len); 
     367        if (tmp_len < count) 
     368            pjmedia_copy_samples(data + tmp_len, reg2, count - tmp_len); 
     369    } else { 
     370        pjmedia_copy_samples(data, reg2 + start_idx - reg1cnt, count); 
     371    } 
     372 
     373    return PJ_SUCCESS; 
     374} 
     375 
     376 
     377/** 
     378 * Pack the buffer so the first sample will be in the beginning of the buffer. 
     379 * This will also make the buffer contiguous. 
     380 * 
     381 * @param circbuf           The circular buffer. 
     382 * 
     383 * @return                  PJ_SUCCESS when successful, otherwise  
     384 *                          the appropriate error will be returned. 
     385 */ 
     386PJ_INLINE(pj_status_t) pjmedia_circ_buf_pack_buffer(pjmedia_circ_buf *circbuf) 
     387{ 
     388    pj_int16_t *reg1, *reg2; 
     389    unsigned reg1cnt, reg2cnt; 
     390    unsigned gap; 
     391 
     392    pjmedia_circ_buf_get_read_regions(circbuf, &reg1, &reg1cnt,  
     393                                      &reg2, &reg2cnt); 
     394 
     395    /* Check if not contigue */ 
     396    if (reg2cnt != 0) { 
     397        /* Check if no space left to roll the buffer  
     398         * (or should this function provide temporary buffer?) 
     399         */ 
     400        gap = circbuf->capacity - pjmedia_circ_buf_get_len(circbuf); 
     401        if (gap == 0) 
     402            return PJ_ETOOBIG; 
     403 
     404        /* Roll buffer left using the gap until reg2cnt == 0 */ 
     405        do { 
     406            if (gap > reg2cnt) 
     407                gap = reg2cnt; 
     408            pjmedia_move_samples(reg1 - gap, reg1, reg1cnt); 
     409            pjmedia_copy_samples(reg1 + reg1cnt - gap, reg2, gap); 
     410            if (gap < reg2cnt) 
     411                pjmedia_move_samples(reg2, reg2 + gap, reg2cnt - gap); 
     412            reg1 -= gap; 
     413            reg1cnt += gap; 
     414            reg2cnt -= gap; 
     415        } while (reg2cnt > 0); 
     416    } 
     417 
     418    /* Finally, Shift samples to the left edge */ 
     419    if (reg1 != circbuf->buf) 
     420        pjmedia_move_samples(circbuf->buf, reg1,  
     421                             pjmedia_circ_buf_get_len(circbuf)); 
     422    circbuf->start = circbuf->buf; 
     423 
     424    return PJ_SUCCESS; 
     425} 
     426 
     427 
    332428PJ_END_DECL 
    333429 
Note: See TracChangeset for help on using the changeset viewer.