Changeset 646


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.

Location:
pjproject/trunk
Files:
5 added
7 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/build/pjmedia.dsp

    r642 r646  
    9292# Begin Source File 
    9393 
     94SOURCE=..\src\pjmedia\aec_speex.c 
     95# End Source File 
     96# Begin Source File 
     97 
    9498SOURCE=..\src\pjmedia\alaw_ulaw.c 
     99# End Source File 
     100# Begin Source File 
     101 
     102SOURCE=..\src\pjmedia\bidirectional.c 
    95103# End Source File 
    96104# Begin Source File 
     
    232240# Begin Source File 
    233241 
     242SOURCE=..\include\pjmedia\aec.h 
     243# End Source File 
     244# Begin Source File 
     245 
    234246SOURCE=..\include\pjmedia\aec_port.h 
     247# End Source File 
     248# Begin Source File 
     249 
     250SOURCE=..\include\pjmedia\bidirectional.h 
    235251# End Source File 
    236252# Begin Source File 
  • pjproject/trunk/pjmedia/include/pjmedia.h

    r642 r646  
    2626 
    2727#include <pjmedia/types.h> 
     28#include <pjmedia/aec.h> 
    2829#include <pjmedia/aec_port.h> 
     30#include <pjmedia/bidirectional.h> 
    2931#include <pjmedia/clock.h> 
    3032#include <pjmedia/codec.h> 
  • 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; 
  • pjproject/trunk/pjmedia/src/pjmedia/sound_port.c

    r582 r646  
    1818 */ 
    1919#include <pjmedia/sound_port.h> 
     20#include <pjmedia/aec.h> 
    2021#include <pjmedia/errno.h> 
    2122#include <pjmedia/plc.h> 
     
    2526#include <pj/string.h>      /* pj_memset() */ 
    2627 
     28#ifndef PJMEDIA_SOUND_HAS_AEC 
     29#   define PJMEDIA_SOUND_HAS_AEC        1 
     30#endif 
     31 
     32#if defined(PJMEDIA_SOUND_HAS_AEC) && PJMEDIA_SOUND_HAS_AEC!=0 
     33#   include <speex/speex_echo.h> 
     34#endif 
    2735 
    2836//#define SIMULATE_LOST_PCT   20 
    29  
     37#define AEC_TAIL    500     /* in ms */ 
    3038 
    3139#define THIS_FILE           "sound_port.c" 
     
    4957    unsigned             options; 
    5058 
     59    pjmedia_aec         *aec; 
    5160    pjmedia_plc         *plc; 
    5261 
     
    105114    if (snd_port->plc) 
    106115        pjmedia_plc_save(snd_port->plc, output); 
     116 
     117    if (snd_port->aec) { 
     118        pjmedia_aec_playback(snd_port->aec, output); 
     119    } 
     120 
    107121 
    108122    return PJ_SUCCESS; 
     
    122136 
    123137 
     138    if (snd_port->aec) { 
     139        pjmedia_aec_playback(snd_port->aec, output); 
     140    } 
     141 
    124142    return PJ_SUCCESS; 
    125143} 
     
    132150static pj_status_t rec_cb(/* in */   void *user_data, 
    133151                          /* in */   pj_uint32_t timestamp, 
    134                           /* in */   const void *input, 
     152                          /* in */   void *input, 
    135153                          /* in*/    unsigned size) 
    136154{ 
     
    138156    pjmedia_port *port; 
    139157    pjmedia_frame frame; 
     158 
     159    /* Cancel echo */ 
     160    if (snd_port->aec) { 
     161        pjmedia_aec_capture(snd_port->aec, input, 0); 
     162    } 
    140163 
    141164    /* We're risking accessing the port without holding any mutex. 
     
    228251    } 
    229252 
     253    /* Create AEC only when direction is full duplex */ 
     254    if (snd_port->dir == PJMEDIA_DIR_CAPTURE_PLAYBACK) { 
     255        status = pjmedia_aec_create(pool, snd_port->clock_rate,  
     256                                    snd_port->samples_per_frame,  
     257                                    snd_port->clock_rate * AEC_TAIL / 1000, 
     258                                    0, &snd_port->aec); 
     259        if (status != PJ_SUCCESS) 
     260            snd_port->aec = NULL; 
     261    } 
     262 
    230263    /* Start sound stream. */ 
    231264    status = pjmedia_snd_stream_start(snd_port->snd_stream); 
     
    251284        pjmedia_snd_stream_close(snd_port->snd_stream); 
    252285        snd_port->snd_stream = NULL; 
     286    } 
     287 
     288    /* Destroy AEC */ 
     289    if (snd_port->aec) { 
     290        pjmedia_aec_destroy(snd_port->aec); 
     291        snd_port->aec = NULL; 
    253292    } 
    254293 
  • pjproject/trunk/pjsip-apps/build

    • Property svn:ignore
      •  

        old new  
        88*.suo 
        99*.pdb 
         10*.wav 
        1011activex-pjsua_p.c 
        1112dlldata.c 
  • pjproject/trunk/pjsip-apps/build/samples.dsp

    r585 r646  
    8787# Begin Source File 
    8888 
     89SOURCE=..\src\samples\aectest.c 
     90# End Source File 
     91# Begin Source File 
     92 
    8993SOURCE=..\src\samples\confbench.c 
    9094# End Source File 
  • pjproject/trunk/pjsip-apps/src/samples/debug.c

    r601 r646  
    2828 *  #include "playfile.c" 
    2929 */ 
    30 #include "pjsip-perf.c" 
     30#include "aectest.c" 
    3131 
Note: See TracChangeset for help on using the changeset viewer.