Ignore:
Timestamp:
Aug 4, 2006 11:08:00 AM (18 years ago)
Author:
bennylp
Message:

More experimentation with AEC: (1) added media port to create bidirectional port from two unidirectional ports, (2) split AEC functionality into AEC algorithm (aec.h) and AEC media port (aec_port.h), (3) Added the AEC functionality in the sound_port.c.

File:
1 edited

Legend:

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

    r643 r646  
    1818 */ 
    1919#include <pjmedia/aec_port.h> 
    20 #include "../pjmedia-codec/speex/speex_echo.h" 
     20#include <pjmedia/aec.h> 
    2121#include <pjmedia/errno.h> 
    2222#include <pj/assert.h> 
     
    2727#define THIS_FILE   "aec_port.c" 
    2828#define SIGNATURE   PJMEDIA_PORT_SIGNATURE('A', 'E', 'C', ' ') 
     29#define BUF_COUNT   32 
    2930 
    30  
    31 struct aec_port 
     31struct aec 
    3232{ 
    3333    pjmedia_port     base; 
    3434    pjmedia_port    *dn_port; 
    35     SpeexEchoState  *state; 
    36     pj_int16_t      *tmp_frame; 
    37     pj_bool_t        has_frame; 
    38     pj_int16_t      *last_frame; 
     35    pjmedia_aec     *aec; 
    3936}; 
    4037 
     
    5350{ 
    5451    const pj_str_t AEC = { "AEC", 3 }; 
    55     struct aec_port *aec_port; 
    56     int sampling_rate; 
     52    struct aec *aec; 
     53    pj_status_t status; 
    5754 
    5855    PJ_ASSERT_RETURN(pool && dn_port && p_port, PJ_EINVAL); 
     
    6057                     PJ_EINVAL); 
    6158 
    62     /* Create and initialize the port */ 
    63     aec_port = pj_pool_zalloc(pool, sizeof(struct aec_port)); 
     59    /* Create the port and the AEC itself */ 
     60    aec = pj_pool_zalloc(pool, sizeof(struct aec)); 
    6461     
    65     pjmedia_port_info_init(&aec_port->base.info, &AEC, SIGNATURE, 
     62    pjmedia_port_info_init(&aec->base.info, &AEC, SIGNATURE, 
    6663                           dn_port->info.clock_rate,  
    6764                           dn_port->info.channel_count,  
     
    6966                           dn_port->info.samples_per_frame); 
    7067 
    71     aec_port->state = speex_echo_state_init(dn_port->info.samples_per_frame, 
    72                                             tail_length); 
    73  
    74     /* Set sampling rate */ 
    75     sampling_rate = 0; 
    76     speex_echo_ctl(aec_port->state, SPEEX_ECHO_GET_SAMPLING_RATE,  
    77                    &sampling_rate); 
    78     sampling_rate = dn_port->info.clock_rate; 
    79     speex_echo_ctl(aec_port->state, SPEEX_ECHO_SET_SAMPLING_RATE,  
    80                    &sampling_rate); 
     68    status = pjmedia_aec_create(pool, dn_port->info.clock_rate,  
     69                                dn_port->info.samples_per_frame, 
     70                                tail_length, 0, &aec->aec); 
     71    if (status != PJ_SUCCESS) 
     72        return status; 
    8173 
    8274    /* More init */ 
    83     aec_port->dn_port = dn_port; 
    84     aec_port->base.get_frame = &aec_get_frame; 
    85     aec_port->base.put_frame = &aec_put_frame; 
    86     aec_port->base.on_destroy = &aec_on_destroy; 
    87  
    88     aec_port->last_frame = pj_pool_zalloc(pool, sizeof(pj_int16_t) * 
    89                                             dn_port->info.samples_per_frame); 
    90     aec_port->tmp_frame = pj_pool_zalloc(pool, sizeof(pj_int16_t) * 
    91                                             dn_port->info.samples_per_frame); 
     75    aec->dn_port = dn_port; 
     76    aec->base.get_frame = &aec_get_frame; 
     77    aec->base.put_frame = &aec_put_frame; 
     78    aec->base.on_destroy = &aec_on_destroy; 
    9279 
    9380    /* Done */ 
    94     *p_port = &aec_port->base; 
     81    *p_port = &aec->base; 
    9582 
    96     PJ_LOG(4,(THIS_FILE, "AEC created for port %.*s, clock_rate=%d, " 
    97                          "samples per frame=%d, tail length=%d ms",  
    98                          (int)dn_port->info.name.slen, 
    99                          dn_port->info.name.ptr, 
    100                          dn_port->info.clock_rate, 
    101                          dn_port->info.samples_per_frame, 
    102                          tail_length * 1000 / dn_port->info.clock_rate)); 
    10383    return PJ_SUCCESS; 
    10484} 
     
    10888                                 const pjmedia_frame *frame) 
    10989{ 
    110     struct aec_port *aec_port = (struct aec_port*)this_port; 
     90    struct aec *aec = (struct aec*)this_port; 
    11191 
    11292    PJ_ASSERT_RETURN(this_port->info.signature == SIGNATURE, PJ_EINVAL); 
    11393 
    114     if (frame->type == PJMEDIA_FRAME_TYPE_NONE || !aec_port->has_frame) { 
    115         return pjmedia_port_put_frame(aec_port->dn_port, frame); 
     94    if (frame->type == PJMEDIA_FRAME_TYPE_NONE ) { 
     95        return pjmedia_port_put_frame(aec->dn_port, frame); 
    11696    } 
    11797 
     
    11999                     PJ_EINVAL); 
    120100 
    121     speex_echo_cancel(aec_port->state,  
    122                       (const spx_int16_t*)frame->buf,  
    123                       (const spx_int16_t*)aec_port->last_frame, 
    124                       (spx_int16_t*)aec_port->tmp_frame,  
    125                       NULL); 
     101    pjmedia_aec_capture(aec->aec, frame->buf, 0); 
    126102 
    127     pjmedia_copy_samples(frame->buf, aec_port->tmp_frame, 
    128                          this_port->info.samples_per_frame); 
    129  
    130     return pjmedia_port_put_frame(aec_port->dn_port, frame); 
     103    return pjmedia_port_put_frame(aec->dn_port, frame); 
    131104} 
    132105 
     
    135108                                  pjmedia_frame *frame) 
    136109{ 
    137     struct aec_port *aec_port = (struct aec_port*)this_port; 
     110    struct aec *aec = (struct aec*)this_port; 
    138111    pj_status_t status; 
    139112 
    140113    PJ_ASSERT_RETURN(this_port->info.signature == SIGNATURE, PJ_EINVAL); 
    141114 
    142     status = pjmedia_port_get_frame(aec_port->dn_port, frame); 
    143     if (status==PJ_SUCCESS && frame->type==PJMEDIA_FRAME_TYPE_AUDIO) { 
    144         aec_port->has_frame = PJ_TRUE; 
    145         pjmedia_copy_samples(aec_port->tmp_frame, frame->buf, 
    146                              this_port->info.samples_per_frame); 
    147     } else { 
    148         aec_port->has_frame = PJ_FALSE;  
     115    status = pjmedia_port_get_frame(aec->dn_port, frame); 
     116    if (status!=PJ_SUCCESS || frame->type!=PJMEDIA_FRAME_TYPE_AUDIO) { 
     117        pjmedia_zero_samples(frame->buf, this_port->info.samples_per_frame); 
    149118    } 
     119 
     120    pjmedia_aec_playback(aec->aec, frame->buf); 
    150121 
    151122    return status; 
     
    155126static pj_status_t aec_on_destroy(pjmedia_port *this_port) 
    156127{ 
    157     struct aec_port *aec_port = (struct aec_port*)this_port; 
     128    struct aec *aec = (struct aec*)this_port; 
    158129 
    159130    PJ_ASSERT_RETURN(this_port->info.signature == SIGNATURE, PJ_EINVAL); 
    160131 
    161     speex_echo_state_destroy(aec_port->state); 
     132    pjmedia_aec_destroy(aec->aec); 
    162133 
    163134    return PJ_SUCCESS; 
Note: See TracChangeset for help on using the changeset viewer.