Ignore:
Timestamp:
Oct 21, 2013 3:11:14 AM (9 years ago)
Author:
nanang
Message:

Close #1705: Added playback and capture callbacks for echo canceller algo. Note that this changeset also modified current Speex AEC algo behaviors:

  • applied this two APIs model for Speex AEC algo
  • enabled Speex AGC preprocessing
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/echo_common.c

    r3841 r4622  
    7575                             unsigned options, 
    7676                             void *reserved ); 
     77    pj_status_t (*ec_playback)(void *state, 
     78                             pj_int16_t *play_frm ); 
     79    pj_status_t (*ec_capture)(void *state, 
     80                             pj_int16_t *rec_frm, 
     81                             unsigned options ); 
    7782}; 
    7883 
     
    99104    &speex_aec_destroy, 
    100105    &speex_aec_reset, 
    101     &speex_aec_cancel_echo 
     106    &speex_aec_cancel_echo, 
     107    &speex_aec_playback, 
     108    &speex_aec_capture 
    102109}; 
    103110#endif 
     
    183190    } 
    184191 
     192    /* Completeness check for EC operation playback and capture, they must 
     193     * be implemented both or none. 
     194     */ 
     195    pj_assert(!ec->op->ec_capture == !ec->op->ec_playback); 
     196 
    185197    PJ_LOG(5,(ec->obj_name, "Creating %s", ec->op->name)); 
    186198 
     
    194206    } 
    195207 
    196     /* Create latency buffers */ 
    197     ptime = samples_per_frame * 1000 / clock_rate; 
    198     if (latency_ms > ptime) { 
    199         /* Normalize latency with delaybuf/WSOLA latency */ 
    200         latency_ms -= PJ_MIN(ptime, PJMEDIA_WSOLA_DELAY_MSEC); 
    201     } 
    202     if (latency_ms < ptime) { 
    203         /* Give at least one frame delay to simplify programming */ 
    204         latency_ms = ptime; 
    205     } 
    206     lat_cnt = latency_ms / ptime; 
    207     while (lat_cnt--)  { 
    208         struct frame *frm; 
    209  
    210         frm = (struct frame*) pj_pool_alloc(pool, (samples_per_frame<<1) + 
    211                                                   sizeof(struct frame)); 
    212         pj_list_push_back(&ec->lat_free, frm); 
    213     } 
    214  
    215     /* Create delay buffer to compensate drifts */ 
    216     if (options & PJMEDIA_ECHO_USE_SIMPLE_FIFO) 
    217         delay_buf_opt |= PJMEDIA_DELAY_BUF_SIMPLE_FIFO; 
    218     status = pjmedia_delay_buf_create(ec->pool, ec->obj_name, clock_rate,  
    219                                       samples_per_frame, channel_count, 
    220                                       (PJMEDIA_SOUND_BUFFER_COUNT+1) * ptime, 
    221                                       delay_buf_opt, &ec->delay_buf); 
    222     if (status != PJ_SUCCESS) { 
    223         pj_pool_release(pool); 
    224         return status; 
     208    /* If EC algo does not have playback and capture callbakcs, 
     209     * create latency buffer and delay buffer to handle drift. 
     210     */ 
     211    if (ec->op->ec_playback && ec->op->ec_capture) { 
     212        latency_ms = 0; 
     213    } else { 
     214        /* Create latency buffers */ 
     215        ptime = samples_per_frame * 1000 / clock_rate; 
     216        if (latency_ms > ptime) { 
     217            /* Normalize latency with delaybuf/WSOLA latency */ 
     218            latency_ms -= PJ_MIN(ptime, PJMEDIA_WSOLA_DELAY_MSEC); 
     219        } 
     220        if (latency_ms < ptime) { 
     221            /* Give at least one frame delay to simplify programming */ 
     222            latency_ms = ptime; 
     223        } 
     224        lat_cnt = latency_ms / ptime; 
     225        while (lat_cnt--)  { 
     226            struct frame *frm; 
     227 
     228            frm = (struct frame*) pj_pool_alloc(pool, (samples_per_frame<<1) + 
     229                                                      sizeof(struct frame)); 
     230            pj_list_push_back(&ec->lat_free, frm); 
     231        } 
     232 
     233        /* Create delay buffer to compensate drifts */ 
     234        if (options & PJMEDIA_ECHO_USE_SIMPLE_FIFO) 
     235            delay_buf_opt |= PJMEDIA_DELAY_BUF_SIMPLE_FIFO; 
     236        status = pjmedia_delay_buf_create(ec->pool, ec->obj_name, clock_rate,  
     237                                          samples_per_frame, channel_count, 
     238                                          (PJMEDIA_SOUND_BUFFER_COUNT+1) * ptime, 
     239                                          delay_buf_opt, &ec->delay_buf); 
     240        if (status != PJ_SUCCESS) { 
     241            pj_pool_release(pool); 
     242            return status; 
     243        } 
    225244    } 
    226245 
     
    268287    } 
    269288    echo->lat_ready = PJ_FALSE; 
    270     pjmedia_delay_buf_reset(echo->delay_buf); 
     289    if (echo->delay_buf) 
     290        pjmedia_delay_buf_reset(echo->delay_buf); 
    271291    echo->op->ec_reset(echo->state); 
    272292    return PJ_SUCCESS; 
     
    280300                                           pj_int16_t *play_frm ) 
    281301{ 
     302    /* If EC algo has playback handler, just pass the frame. */ 
     303    if (echo->op->ec_playback) { 
     304        return (*echo->op->ec_playback)(echo->state, play_frm); 
     305    } 
     306 
    282307    /* Playing frame should be stored, as it will be used by echo_capture()  
    283308     * as reference frame, delay buffer is used for storing the playing frames 
     
    333358    pj_status_t status, rc; 
    334359 
     360    /* If EC algo has capture handler, just pass the frame. */ 
     361    if (echo->op->ec_capture) { 
     362        return (*echo->op->ec_capture)(echo->state, rec_frm, options); 
     363    } 
     364 
    335365    if (!echo->lat_ready) { 
    336366        /* Prefetching to fill in the desired latency */ 
Note: See TracChangeset for help on using the changeset viewer.