Changeset 4622


Ignore:
Timestamp:
Oct 21, 2013 3:11:14 AM (8 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
Location:
pjproject/trunk/pjmedia/src/pjmedia
Files:
3 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 */ 
  • pjproject/trunk/pjmedia/src/pjmedia/echo_internal.h

    r3553 r4622  
    5757                                           unsigned options, 
    5858                                           void *reserved ); 
     59PJ_DECL(pj_status_t) speex_aec_playback(void *state, 
     60                                        pj_int16_t *play_frm ); 
     61PJ_DECL(pj_status_t) speex_aec_capture(void *state, 
     62                                       pj_int16_t *rec_frm, 
     63                                       unsigned options ); 
    5964 
    6065PJ_DECL(pj_status_t) ipp_aec_create(pj_pool_t *pool, 
  • pjproject/trunk/pjmedia/src/pjmedia/echo_speex.c

    r3664 r4622  
    110110#endif 
    111111 
     112    /* Enable AGC */ 
     113    { 
     114        spx_int32_t enabled = 1; 
     115        speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_AGC,  
     116                             &enabled); 
     117    } 
     118 
    112119    /* Control echo cancellation in the preprocessor */ 
    113120   speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_ECHO_STATE,  
     
    190197} 
    191198 
     199/* 
     200 * Let AEC know that a frame was queued to be played. 
     201 */ 
     202PJ_DEF(pj_status_t) speex_aec_playback( void *state, 
     203                                        pj_int16_t *play_frm ) 
     204{ 
     205    speex_ec *echo = (speex_ec*) state; 
     206 
     207    /* Sanity checks */ 
     208    PJ_ASSERT_RETURN(echo && play_frm, PJ_EINVAL); 
     209 
     210    speex_echo_playback(echo->state, (spx_int16_t*)play_frm); 
     211 
     212    return PJ_SUCCESS; 
     213 
     214} 
     215 
     216/* 
     217 * Perform echo cancellation to captured frame. 
     218 */ 
     219PJ_DEF(pj_status_t) speex_aec_capture( void *state, 
     220                                       pj_int16_t *rec_frm, 
     221                                       unsigned options ) 
     222{ 
     223    speex_ec *echo = (speex_ec*) state; 
     224 
     225    /* Sanity checks */ 
     226    PJ_ASSERT_RETURN(echo && rec_frm, PJ_EINVAL); 
     227 
     228    PJ_UNUSED_ARG(options); 
     229 
     230    /* Cancel echo */ 
     231    pjmedia_copy_samples(echo->tmp_frame, rec_frm, echo->samples_per_frame); 
     232    speex_echo_capture(echo->state, 
     233                       (spx_int16_t*)echo->tmp_frame, 
     234                       (spx_int16_t*)rec_frm); 
     235 
     236    /* Apply preprocessing */ 
     237    speex_preprocess_run(echo->preprocess, (spx_int16_t*)rec_frm); 
     238 
     239    return PJ_SUCCESS; 
     240} 
     241 
     242 
    192243#endif 
Note: See TracChangeset for help on using the changeset viewer.