Changeset 653
- Timestamp:
- Aug 6, 2006 12:07:13 PM (18 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 2 added
- 10 edited
- 4 moved
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/build/Makefile
r643 r653 66 66 export PJMEDIA_SRCDIR = ../src/pjmedia 67 67 export PJMEDIA_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \ 68 aec_port.o alaw_ulaw.o \ 69 clock_thread.o codec.o conference.o endpoint.o errno.o \ 68 alaw_ulaw.o clock_thread.o codec.o conference.o \ 69 echo_common.o echo_port.o echo_speex.o \ 70 echo_suppress.o endpoint.o errno.o \ 70 71 g711.o jbuf.o master_port.o mem_capture.o mem_player.o \ 71 72 null_port.o plc_common.o plc_g711.o \ -
pjproject/trunk/pjmedia/build/pjmedia.dsp
r646 r653 88 88 # Begin Source File 89 89 90 SOURCE=..\src\pjmedia\aec_port.c91 # End Source File92 # Begin Source File93 94 SOURCE=..\src\pjmedia\aec_speex.c95 # End Source File96 # Begin Source File97 98 90 SOURCE=..\src\pjmedia\alaw_ulaw.c 99 91 # End Source File … … 117 109 118 110 SOURCE=..\src\pjmedia\dsound.c 111 # End Source File 112 # Begin Source File 113 114 SOURCE=..\src\pjmedia\echo_common.c 115 # End Source File 116 # Begin Source File 117 118 SOURCE=..\src\pjmedia\echo_port.c 119 # End Source File 120 # Begin Source File 121 122 SOURCE=..\src\pjmedia\echo_speex.c 123 # End Source File 124 # Begin Source File 125 126 SOURCE=..\src\pjmedia\echo_suppress.c 119 127 # End Source File 120 128 # Begin Source File … … 240 248 # Begin Source File 241 249 242 SOURCE=..\include\pjmedia\aec.h243 # End Source File244 # Begin Source File245 246 SOURCE=..\include\pjmedia\aec_port.h247 # End Source File248 # Begin Source File249 250 250 SOURCE=..\include\pjmedia\bidirectional.h 251 251 # End Source File … … 269 269 270 270 SOURCE=..\include\pjmedia\doxygen.h 271 # End Source File 272 # Begin Source File 273 274 SOURCE=..\include\pjmedia\echo.h 275 # End Source File 276 # Begin Source File 277 278 SOURCE=..\include\pjmedia\echo_port.h 271 279 # End Source File 272 280 # Begin Source File -
pjproject/trunk/pjmedia/include/pjmedia.h
r646 r653 26 26 27 27 #include <pjmedia/types.h> 28 #include <pjmedia/aec.h>29 #include <pjmedia/aec_port.h>30 28 #include <pjmedia/bidirectional.h> 31 29 #include <pjmedia/clock.h> 32 30 #include <pjmedia/codec.h> 33 31 #include <pjmedia/conference.h> 32 #include <pjmedia/echo.h> 33 #include <pjmedia/echo_port.h> 34 #include <pjmedia/errno.h> 34 35 #include <pjmedia/endpoint.h> 35 #include <pjmedia/errno.h>36 36 #include <pjmedia/g711.h> 37 37 #include <pjmedia/jbuf.h> -
pjproject/trunk/pjmedia/include/pjmedia/config.h
r651 r653 171 171 172 172 /** 173 * Speex Accoustic Echo Cancellation (AEC). 174 * By default is enabled. 175 */ 176 #ifndef PJMEDIA_HAS_SPEEX_AEC 177 # define PJMEDIA_HAS_SPEEX_AEC 1 178 #endif 179 180 181 /** 173 182 * Support for sending and decoding RTCP port in SDP (RFC 3605). 174 183 * Default is yes. -
pjproject/trunk/pjmedia/include/pjmedia/echo.h
r652 r653 17 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 18 */ 19 #ifndef __PJMEDIA_ AEC_H__20 #define __PJMEDIA_ AEC_H__19 #ifndef __PJMEDIA_ECHO_H__ 20 #define __PJMEDIA_ECHO_H__ 21 21 22 22 23 23 /** 24 * @file aec.h25 * @brief AEC (Accoustic Echo Cancellation)API.24 * @file echo.h 25 * @brief Echo Cancellation API. 26 26 */ 27 27 #include <pjmedia/types.h> … … 30 30 31 31 /** 32 * @defgroup PJMEDIA_ AEC AEC AEC (Accoustic Echo Cancellation)32 * @defgroup PJMEDIA_Echo_Cancel Canceller Echo Cancellation 33 33 * @ingroup PJMEDIA_PORT 34 * @brief AEC (Accoustic Echo Cancellation)API.34 * @brief Echo Cancellation API. 35 35 * @{ 36 * 37 * This section describes API to perform echo cancellation to audio signal. 38 * There may be multiple echo canceller implementation in PJMEDIA, ranging 39 * from simple echo suppressor to a full Accoustic Echo Canceller/AEC. By 40 * using this API, application should be able to use which EC backend to 41 * use base on the requirement and capability of the platform. 36 42 */ 37 43 … … 41 47 42 48 /** 43 * Opaque type for PJMEDIA AEC.49 * Opaque type for PJMEDIA Echo Canceller state. 44 50 */ 45 typedef struct pjmedia_ aec pjmedia_aec;51 typedef struct pjmedia_echo_state pjmedia_echo_state; 46 52 47 53 48 54 /** 49 * Create the AEC. 55 * Echo cancellation options. 56 */ 57 typedef enum pjmedia_echo_flag 58 { 59 /** 60 * If PJMEDIA_ECHO_SIMPLE flag is specified during echo canceller 61 * creation, then a simple echo suppressor will be used instead of 62 * an accoustic echo cancellation. 63 */ 64 PJMEDIA_ECHO_SIMPLE = 1, 65 66 /** 67 * If PJMEDIA_ECHO_NO_LOCK flag is specified, no mutex will be created 68 * for the echo canceller, but application will guarantee that echo 69 * canceller will not be called by different threads at the same time. 70 */ 71 PJMEDIA_ECHO_NO_LOCK = 2 72 73 } pjmedia_echo_flag; 74 75 76 77 78 /** 79 * Create the echo canceller. 50 80 * 51 81 * @param pool Pool to allocate memory. … … 53 83 * @param samples_per_frame Number of samples per frame. 54 84 * @param tail_ms Tail length, miliseconds. 85 * @param options Options. If PJMEDIA_ECHO_SIMPLE is specified, 86 * then a simple echo suppressor implementation 87 * will be used instead of an accoustic echo 88 * cancellation. 89 * See #pjmedia_echo_flag for other options. 90 * @param p_echo Pointer to receive the Echo Canceller state. 55 91 * 56 * @return PJ_SUCCESS on success .92 * @return PJ_SUCCESS on success, or the appropriate status. 57 93 */ 58 PJ_DECL(pj_status_t) pjmedia_ aec_create(pj_pool_t *pool,94 PJ_DECL(pj_status_t) pjmedia_echo_create(pj_pool_t *pool, 59 95 unsigned clock_rate, 60 96 unsigned samples_per_frame, 61 97 unsigned tail_ms, 62 98 unsigned options, 63 pjmedia_ aec **p_aec);99 pjmedia_echo_state **p_echo ); 64 100 65 101 66 102 /** 67 * Destroy the AEC.103 * Destroy the Echo Canceller. 68 104 * 69 * @param aec The AEC. 105 * @param echo The Echo Canceller. 106 * 70 107 * @return PJ_SUCCESS on success. 71 108 */ 72 PJ_DECL(pj_status_t) pjmedia_ aec_destroy(pjmedia_aec *aec);109 PJ_DECL(pj_status_t) pjmedia_echo_destroy(pjmedia_echo_state *echo ); 73 110 74 111 75 112 /** 76 * Let the AECknows that a frame has been played to the speaker.77 * The AECwill keep the frame in its internal buffer, to be used78 * when cancelling the echo with #pjmedia_ aec_capture().113 * Let the Echo Canceller knows that a frame has been played to the speaker. 114 * The Echo Canceller will keep the frame in its internal buffer, to be used 115 * when cancelling the echo with #pjmedia_echo_capture(). 79 116 * 80 * @param aec The AEC. 81 * @param ts Optional timestamp to let the AEC knows the 82 * position of the frame relative to capture 83 * position. If NULL, the AEC assumes that 84 * application will supply the AEC with continuously 85 * increasing timestamp. 117 * @param echo The Echo Canceller. 86 118 * @param play_frm Sample buffer containing frame to be played 87 119 * (or has been played) to the playback device. … … 91 123 * @return PJ_SUCCESS on success. 92 124 */ 93 PJ_DECL(pj_status_t) pjmedia_ aec_playback( pjmedia_aec *aec,125 PJ_DECL(pj_status_t) pjmedia_echo_playback(pjmedia_echo_state *echo, 94 126 pj_int16_t *play_frm ); 95 127 96 128 97 129 /** 98 * Let the AEC knows that a frame has been captured from the microphone. 99 * The AEC will cancel the echo from the captured signal, using the 100 * internal buffer (supplied by #pjmedia_aec_playback()) as the 101 * FES (Far End Speech) reference. 130 * Let the Echo Canceller knows that a frame has been captured from 131 * the microphone. 132 * The Echo Canceller will cancel the echo from the captured signal, 133 * using the internal buffer (supplied by #pjmedia_echo_playback()) 134 * as the FES (Far End Speech) reference. 102 135 * 103 * @param aec The AEC.136 * @param echo The Echo Canceller. 104 137 * @param rec_frm On input, it contains the input signal (captured 105 138 * from microphone) which echo is to be removed. … … 113 146 * @return PJ_SUCCESS on success. 114 147 */ 115 PJ_DECL(pj_status_t) pjmedia_ aec_capture( pjmedia_aec *aec,148 PJ_DECL(pj_status_t) pjmedia_echo_capture(pjmedia_echo_state *echo, 116 149 pj_int16_t *rec_frm, 117 150 unsigned options ); … … 121 154 * Perform echo cancellation. 122 155 * 123 * @param aec The AEC.156 * @param echo The Echo Canceller. 124 157 * @param rec_frm On input, it contains the input signal (captured 125 158 * from microphone) which echo is to be removed. … … 136 169 * @return PJ_SUCCESS on success. 137 170 */ 138 PJ_DECL(pj_status_t) pjmedia_ aec_cancel_echo( pjmedia_aec *aec,139 140 141 142 171 PJ_DECL(pj_status_t) pjmedia_echo_cancel( pjmedia_echo_state *echo, 172 pj_int16_t *rec_frm, 173 const pj_int16_t *play_frm, 174 unsigned options, 175 void *reserved ); 143 176 144 177 … … 150 183 151 184 152 #endif /* __PJMEDIA_ AEC_H__ */185 #endif /* __PJMEDIA_ECHO_H__ */ 153 186 -
pjproject/trunk/pjmedia/include/pjmedia/echo_port.h
r652 r653 29 29 30 30 /** 31 * @defgroup PJMEDIA_ AEC_PORT AECPort31 * @defgroup PJMEDIA_ECHO_PORT Echo Cancellation Port 32 32 * @ingroup PJMEDIA_PORT 33 * @brief AEC (Accoustic Echo Cancellation) media port. 33 * @brief Echo Cancellation Port 34 * 35 * Echo canceller media port, using @ref PJMEDIA_Echo_Cancel backend. 34 36 * @{ 35 37 */ … … 40 42 41 43 /** 42 * Create AECport.44 * Create echo canceller port. 43 45 * 44 46 * @param pool Pool to allocate memory. 45 47 * @param dn_port Downstream port. 46 48 * @param tail_ms Tail length in miliseconds. 49 * @param options Options, as in #pjmedia_echo_create(). 47 50 * @param p_port Pointer to receive the port instance. 48 51 * 49 52 * @return PJ_SUCCESS on success. 50 53 */ 51 PJ_DECL(pj_status_t) pjmedia_ aec_port_create(pj_pool_t *pool,54 PJ_DECL(pj_status_t) pjmedia_echo_port_create(pj_pool_t *pool, 52 55 pjmedia_port *dn_port, 53 56 unsigned tail_ms, 57 unsigned options, 54 58 pjmedia_port **p_port ); 55 59 -
pjproject/trunk/pjmedia/include/pjmedia/sound_port.h
r648 r653 184 184 185 185 /** 186 * Enable accoustic echo cancellation (AEC) to the specified sound. 187 * The AEC can only be enabled for sound streams with full-duplex direction. 188 * 189 * And note, you should only change the AEC settings when the sound port 190 * is not connected to any downstream ports. 191 * 192 * @param snd_port The sound device port. 193 * @param pool Pool to re-create the AEC if necessary. 186 * Configure the echo cancellation tail length. By default, echo canceller 187 * is enabled in the sound device with the default tail length. After the 188 * sound port is created, application can query the current echo canceller 189 * tail length by calling #pjmedia_snd_port_get_ec_tail. 190 * 191 * Note that you should only change the EC settings when the sound port 192 * is not connected to any downstream ports, otherwise race condition may 193 * occur. 194 * 195 * @param snd_port The sound device port. 196 * @param pool Pool to re-create the echo canceller if necessary. 194 197 * @param tail_ms Maximum echo tail length to be supported, in 195 * miliseconds. If zero is specified, the AEC would198 * miliseconds. If zero is specified, the EC would 196 199 * be disabled. 197 200 * 198 201 * @return PJ_SUCCESS on success. 199 202 */ 200 PJ_DECL(pj_status_t) pjmedia_snd_port_set_ aec(pjmedia_snd_port *snd_port,201 202 203 204 205 /** 206 * Get current AEC tail length, in miliseconds. The tail length will be zero207 * if AEC is not enabled.203 PJ_DECL(pj_status_t) pjmedia_snd_port_set_ec_tail(pjmedia_snd_port *snd_port, 204 pj_pool_t *pool, 205 unsigned tail_ms); 206 207 208 /** 209 * Get current echo canceller tail length, in miliseconds. The tail length 210 * will be zero if EC is not enabled. 208 211 * 209 212 * @param snd_port The sound device port. … … 212 215 * @return PJ_SUCCESS on success. 213 216 */ 214 PJ_DECL(pj_status_t) pjmedia_snd_port_get_ aec_tail(pjmedia_snd_port *snd_port,215 217 PJ_DECL(pj_status_t) pjmedia_snd_port_get_ec_tail(pjmedia_snd_port *snd_port, 218 unsigned *p_length); 216 219 217 220 -
pjproject/trunk/pjmedia/src/pjmedia/echo_port.c
r652 r653 17 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 18 */ 19 #include <pjmedia/ aec_port.h>20 #include <pjmedia/ aec.h>19 #include <pjmedia/echo_port.h> 20 #include <pjmedia/echo.h> 21 21 #include <pjmedia/errno.h> 22 22 #include <pj/assert.h> … … 25 25 26 26 27 #define THIS_FILE " aec_port.c"28 #define SIGNATURE PJMEDIA_PORT_SIGNATURE(' A', 'E', 'C', '')27 #define THIS_FILE "ec_port.c" 28 #define SIGNATURE PJMEDIA_PORT_SIGNATURE('E', 'C', 'H', 'O') 29 29 #define BUF_COUNT 32 30 30 31 struct aec31 struct ec 32 32 { 33 pjmedia_port 34 pjmedia_port 35 pjmedia_ aec *aec;33 pjmedia_port base; 34 pjmedia_port *dn_port; 35 pjmedia_echo_state *ec; 36 36 }; 37 37 38 38 39 static pj_status_t aec_put_frame(pjmedia_port *this_port,40 41 static pj_status_t aec_get_frame(pjmedia_port *this_port,42 43 static pj_status_t aec_on_destroy(pjmedia_port *this_port);39 static pj_status_t ec_put_frame(pjmedia_port *this_port, 40 const pjmedia_frame *frame); 41 static pj_status_t ec_get_frame(pjmedia_port *this_port, 42 pjmedia_frame *frame); 43 static pj_status_t ec_on_destroy(pjmedia_port *this_port); 44 44 45 45 46 PJ_DEF(pj_status_t) pjmedia_ aec_port_create(pj_pool_t *pool,46 PJ_DEF(pj_status_t) pjmedia_echo_port_create(pj_pool_t *pool, 47 47 pjmedia_port *dn_port, 48 48 unsigned tail_ms, 49 unsigned options, 49 50 pjmedia_port **p_port ) 50 51 { 51 const pj_str_t AEC = { " AEC", 3};52 struct aec *aec;52 const pj_str_t AEC = { "EC", 2 }; 53 struct ec *ec; 53 54 pj_status_t status; 54 55 … … 58 59 59 60 /* Create the port and the AEC itself */ 60 aec = pj_pool_zalloc(pool, sizeof(struct aec));61 ec = pj_pool_zalloc(pool, sizeof(struct ec)); 61 62 62 pjmedia_port_info_init(& aec->base.info, &AEC, SIGNATURE,63 pjmedia_port_info_init(&ec->base.info, &AEC, SIGNATURE, 63 64 dn_port->info.clock_rate, 64 65 dn_port->info.channel_count, … … 66 67 dn_port->info.samples_per_frame); 67 68 68 status = pjmedia_ aec_create(pool, dn_port->info.clock_rate,69 dn_port->info.samples_per_frame,70 tail_ms, 0, &aec->aec);69 status = pjmedia_echo_create(pool, dn_port->info.clock_rate, 70 dn_port->info.samples_per_frame, 71 tail_ms, options, &ec->ec); 71 72 if (status != PJ_SUCCESS) 72 73 return status; 73 74 74 75 /* More init */ 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;76 ec->dn_port = dn_port; 77 ec->base.get_frame = &ec_get_frame; 78 ec->base.put_frame = &ec_put_frame; 79 ec->base.on_destroy = &ec_on_destroy; 79 80 80 81 /* Done */ 81 *p_port = & aec->base;82 *p_port = &ec->base; 82 83 83 84 return PJ_SUCCESS; … … 85 86 86 87 87 static pj_status_t aec_put_frame(pjmedia_port *this_port,88 static pj_status_t ec_put_frame( pjmedia_port *this_port, 88 89 const pjmedia_frame *frame) 89 90 { 90 struct aec *aec = (struct aec*)this_port;91 struct ec *ec = (struct ec*)this_port; 91 92 92 93 PJ_ASSERT_RETURN(this_port->info.signature == SIGNATURE, PJ_EINVAL); 93 94 94 95 if (frame->type == PJMEDIA_FRAME_TYPE_NONE ) { 95 return pjmedia_port_put_frame( aec->dn_port, frame);96 return pjmedia_port_put_frame(ec->dn_port, frame); 96 97 } 97 98 … … 99 100 PJ_EINVAL); 100 101 101 pjmedia_ aec_capture(aec->aec, frame->buf, 0);102 pjmedia_echo_capture(ec->ec, frame->buf, 0); 102 103 103 return pjmedia_port_put_frame( aec->dn_port, frame);104 return pjmedia_port_put_frame(ec->dn_port, frame); 104 105 } 105 106 106 107 107 static pj_status_t aec_get_frame( pjmedia_port *this_port,108 108 static pj_status_t ec_get_frame( pjmedia_port *this_port, 109 pjmedia_frame *frame) 109 110 { 110 struct aec *aec = (struct aec*)this_port;111 struct ec *ec = (struct ec*)this_port; 111 112 pj_status_t status; 112 113 113 114 PJ_ASSERT_RETURN(this_port->info.signature == SIGNATURE, PJ_EINVAL); 114 115 115 status = pjmedia_port_get_frame( aec->dn_port, frame);116 status = pjmedia_port_get_frame(ec->dn_port, frame); 116 117 if (status!=PJ_SUCCESS || frame->type!=PJMEDIA_FRAME_TYPE_AUDIO) { 117 118 pjmedia_zero_samples(frame->buf, this_port->info.samples_per_frame); 118 119 } 119 120 120 pjmedia_ aec_playback(aec->aec, frame->buf);121 pjmedia_echo_playback(ec->ec, frame->buf); 121 122 122 123 return status; … … 124 125 125 126 126 static pj_status_t aec_on_destroy(pjmedia_port *this_port)127 static pj_status_t ec_on_destroy(pjmedia_port *this_port) 127 128 { 128 struct aec *aec = (struct aec*)this_port;129 struct ec *ec = (struct ec*)this_port; 129 130 130 131 PJ_ASSERT_RETURN(this_port->info.signature == SIGNATURE, PJ_EINVAL); 131 132 132 pjmedia_ aec_destroy(aec->aec);133 pjmedia_echo_destroy(ec->ec); 133 134 134 135 return PJ_SUCCESS; -
pjproject/trunk/pjmedia/src/pjmedia/echo_speex.c
r652 r653 18 18 */ 19 19 20 #include <pjmedia/ aec.h>20 #include <pjmedia/echo.h> 21 21 #include <pjmedia/errno.h> 22 22 #include <pjmedia/silencedet.h> … … 30 30 31 31 32 #define THIS_FILE " aec_speex.c"32 #define THIS_FILE "echo_speex.c" 33 33 #define BUF_COUNT 8 34 35 /* 36 * Prototypes 37 */ 38 PJ_DECL(pj_status_t) speex_aec_create(pj_pool_t *pool, 39 unsigned clock_rate, 40 unsigned samples_per_frame, 41 unsigned tail_ms, 42 unsigned options, 43 void **p_state ); 44 PJ_DECL(pj_status_t) speex_aec_destroy(void *state ); 45 PJ_DECL(pj_status_t) speex_aec_playback(void *state, 46 pj_int16_t *play_frm ); 47 PJ_DECL(pj_status_t) speex_aec_capture(void *state, 48 pj_int16_t *rec_frm, 49 unsigned options ); 50 PJ_DECL(pj_status_t) speex_aec_cancel_echo(void *state, 51 pj_int16_t *rec_frm, 52 const pj_int16_t *play_frm, 53 unsigned options, 54 void *reserved ); 34 55 35 56 … … 39 60 }; 40 61 41 struct pjmedia_aec62 typedef struct speex_ec 42 63 { 43 64 SpeexEchoState *state; … … 54 75 unsigned wpos; /* Index to put newest frame. */ 55 76 struct frame frames[BUF_COUNT]; /* Playback frame buffers. */ 56 } ;77 } speex_ec; 57 78 58 79 … … 61 82 * Create the AEC. 62 83 */ 63 PJ_DEF(pj_status_t) pjmedia_aec_create(pj_pool_t *pool,64 65 66 67 68 pjmedia_aec **p_aec)69 { 70 pjmedia_aec *aec;84 PJ_DEF(pj_status_t) speex_aec_create(pj_pool_t *pool, 85 unsigned clock_rate, 86 unsigned samples_per_frame, 87 unsigned tail_ms, 88 unsigned options, 89 void **p_echo ) 90 { 91 speex_ec *echo; 71 92 int sampling_rate; 72 93 unsigned i; 94 int disabled; 73 95 pj_status_t status; 74 96 75 *p_aec = NULL; 76 77 aec = pj_pool_zalloc(pool, sizeof(pjmedia_aec)); 78 PJ_ASSERT_RETURN(aec != NULL, PJ_ENOMEM); 79 80 status = pj_lock_create_simple_mutex(pool, "aec%p", &aec->lock); 81 if (status != PJ_SUCCESS) 82 return status; 83 84 aec->samples_per_frame = samples_per_frame; 85 aec->options = options; 86 87 aec->state = speex_echo_state_init(samples_per_frame, 97 *p_echo = NULL; 98 99 echo = pj_pool_zalloc(pool, sizeof(speex_ec)); 100 PJ_ASSERT_RETURN(echo != NULL, PJ_ENOMEM); 101 102 if (options & PJMEDIA_ECHO_NO_LOCK) { 103 status = pj_lock_create_null_mutex(pool, "aec%p", &echo->lock); 104 if (status != PJ_SUCCESS) 105 return status; 106 } else { 107 status = pj_lock_create_simple_mutex(pool, "aec%p", &echo->lock); 108 if (status != PJ_SUCCESS) 109 return status; 110 } 111 112 echo->samples_per_frame = samples_per_frame; 113 echo->options = options; 114 115 echo->state = speex_echo_state_init(samples_per_frame, 88 116 clock_rate * tail_ms / 1000); 89 if ( aec->state == NULL) {90 pj_lock_destroy( aec->lock);117 if (echo->state == NULL) { 118 pj_lock_destroy(echo->lock); 91 119 return PJ_ENOMEM; 92 120 } 93 121 94 aec->preprocess = speex_preprocess_state_init(samples_per_frame,95 clock_rate);96 if ( aec->preprocess == NULL) {97 speex_echo_state_destroy( aec->state);98 pj_lock_destroy( aec->lock);122 echo->preprocess = speex_preprocess_state_init(samples_per_frame, 123 clock_rate); 124 if (echo->preprocess == NULL) { 125 speex_echo_state_destroy(echo->state); 126 pj_lock_destroy(echo->lock); 99 127 return PJ_ENOMEM; 100 128 } 129 130 /* Disable all preprocessing, we only want echo cancellation */ 131 disabled = 0; 132 speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_DENOISE, 133 &disabled); 134 speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_AGC, 135 &disabled); 136 speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_VAD, 137 &disabled); 138 speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_DEREVERB, 139 &disabled); 101 140 102 141 /* Set sampling rate */ 103 142 sampling_rate = clock_rate; 104 speex_echo_ctl( aec->state, SPEEX_ECHO_SET_SAMPLING_RATE,143 speex_echo_ctl(echo->state, SPEEX_ECHO_SET_SAMPLING_RATE, 105 144 &sampling_rate); 106 145 107 146 /* Create temporary frame for echo cancellation */ 108 aec->tmp_frame = pj_pool_zalloc(pool, 2 * samples_per_frame);109 PJ_ASSERT_RETURN( aec->tmp_frame != NULL, PJ_ENOMEM);147 echo->tmp_frame = pj_pool_zalloc(pool, 2 * samples_per_frame); 148 PJ_ASSERT_RETURN(echo->tmp_frame != NULL, PJ_ENOMEM); 110 149 111 150 /* Create temporary frame to receive residue */ 112 aec->residue = pj_pool_zalloc(pool, sizeof(spx_int32_t) *151 echo->residue = pj_pool_zalloc(pool, sizeof(spx_int32_t) * 113 152 samples_per_frame); 114 PJ_ASSERT_RETURN( aec->residue != NULL, PJ_ENOMEM);153 PJ_ASSERT_RETURN(echo->residue != NULL, PJ_ENOMEM); 115 154 116 155 /* Create internal playback buffers */ 117 156 for (i=0; i<BUF_COUNT; ++i) { 118 aec->frames[i].buf = pj_pool_zalloc(pool, samples_per_frame * 2);119 PJ_ASSERT_RETURN( aec->frames[i].buf != NULL, PJ_ENOMEM);157 echo->frames[i].buf = pj_pool_zalloc(pool, samples_per_frame * 2); 158 PJ_ASSERT_RETURN(echo->frames[i].buf != NULL, PJ_ENOMEM); 120 159 } 121 160 122 161 123 162 /* Done */ 124 *p_ aec = aec;125 126 PJ_LOG(4,(THIS_FILE, " Echo canceller/AEC created, clock_rate=%d, "163 *p_echo = echo; 164 165 PJ_LOG(4,(THIS_FILE, "Speex Echo canceller/AEC created, clock_rate=%d, " 127 166 "samples per frame=%d, tail length=%d ms", 128 167 clock_rate, … … 137 176 * Destroy AEC 138 177 */ 139 PJ_DEF(pj_status_t) pjmedia_aec_destroy(pjmedia_aec *aec ) 140 { 141 PJ_ASSERT_RETURN(aec && aec->state, PJ_EINVAL); 142 143 if (aec->lock) 144 pj_lock_acquire(aec->lock); 145 146 if (aec->state) { 147 speex_echo_state_destroy(aec->state); 148 aec->state = NULL; 149 } 150 151 if (aec->preprocess) { 152 speex_preprocess_state_destroy(aec->preprocess); 153 aec->preprocess = NULL; 154 } 155 156 if (aec->lock) { 157 pj_lock_destroy(aec->lock); 158 aec->lock = NULL; 178 PJ_DEF(pj_status_t) speex_aec_destroy(void *state ) 179 { 180 speex_ec *echo = state; 181 182 PJ_ASSERT_RETURN(echo && echo->state, PJ_EINVAL); 183 184 if (echo->lock) 185 pj_lock_acquire(echo->lock); 186 187 if (echo->state) { 188 speex_echo_state_destroy(echo->state); 189 echo->state = NULL; 190 } 191 192 if (echo->preprocess) { 193 speex_preprocess_state_destroy(echo->preprocess); 194 echo->preprocess = NULL; 195 } 196 197 if (echo->lock) { 198 pj_lock_destroy(echo->lock); 199 echo->lock = NULL; 159 200 } 160 201 … … 166 207 * Let the AEC knows that a frame has been played to the speaker. 167 208 */ 168 PJ_DEF(pj_status_t) pjmedia_aec_playback(pjmedia_aec *aec, 169 pj_int16_t *play_frm ) 170 { 209 PJ_DEF(pj_status_t) speex_aec_playback(void *state, 210 pj_int16_t *play_frm ) 211 { 212 speex_ec *echo = state; 213 171 214 /* Sanity checks */ 172 PJ_ASSERT_RETURN( aec&& play_frm, PJ_EINVAL);215 PJ_ASSERT_RETURN(echo && play_frm, PJ_EINVAL); 173 216 174 217 /* The AEC must be configured to support internal playback buffer */ 175 PJ_ASSERT_RETURN( aec->frames[0].buf != NULL, PJ_EINVALIDOP);176 177 pj_lock_acquire( aec->lock);218 PJ_ASSERT_RETURN(echo->frames[0].buf != NULL, PJ_EINVALIDOP); 219 220 pj_lock_acquire(echo->lock); 178 221 179 222 /* Check for overflows */ 180 if ( aec->wpos == aec->rpos) {181 PJ_LOG(5,(THIS_FILE, " AEC overflow (playback runs faster, "223 if (echo->wpos == echo->rpos) { 224 PJ_LOG(5,(THIS_FILE, "Speex AEC overflow (playback runs faster, " 182 225 "wpos=%d, rpos=%d)", 183 aec->wpos, aec->rpos));184 aec->rpos = (aec->wpos - BUF_COUNT/2) % BUF_COUNT;185 speex_echo_state_reset( aec->state);226 echo->wpos, echo->rpos)); 227 echo->rpos = (echo->wpos - BUF_COUNT/2) % BUF_COUNT; 228 speex_echo_state_reset(echo->state); 186 229 } 187 230 188 231 /* Save fhe frame */ 189 pjmedia_copy_samples( aec->frames[aec->wpos].buf,190 play_frm, aec->samples_per_frame);191 aec->wpos = (aec->wpos+1) % BUF_COUNT;192 193 pj_lock_release( aec->lock);232 pjmedia_copy_samples(echo->frames[echo->wpos].buf, 233 play_frm, echo->samples_per_frame); 234 echo->wpos = (echo->wpos+1) % BUF_COUNT; 235 236 pj_lock_release(echo->lock); 194 237 195 238 return PJ_SUCCESS; … … 200 243 * Let the AEC knows that a frame has been captured from the microphone. 201 244 */ 202 PJ_DEF(pj_status_t) pjmedia_aec_capture( pjmedia_aec *aec, 203 pj_int16_t *rec_frm, 204 unsigned options ) 205 { 245 PJ_DEF(pj_status_t) speex_aec_capture( void *state, 246 pj_int16_t *rec_frm, 247 unsigned options ) 248 { 249 speex_ec *echo = state; 206 250 pj_status_t status; 207 251 208 252 /* Sanity checks */ 209 PJ_ASSERT_RETURN( aec&& rec_frm, PJ_EINVAL);253 PJ_ASSERT_RETURN(echo && rec_frm, PJ_EINVAL); 210 254 211 255 /* The AEC must be configured to support internal playback buffer */ 212 PJ_ASSERT_RETURN( aec->frames[0].buf != NULL, PJ_EINVALIDOP);256 PJ_ASSERT_RETURN(echo->frames[0].buf != NULL, PJ_EINVALIDOP); 213 257 214 258 /* Lock mutex */ 215 pj_lock_acquire( aec->lock);259 pj_lock_acquire(echo->lock); 216 260 217 261 218 262 /* Check for underflow */ 219 if ( aec->rpos == aec->wpos) {263 if (echo->rpos == echo->wpos) { 220 264 /* Return frame as it is */ 221 pj_lock_release( aec->lock);222 223 PJ_LOG(5,(THIS_FILE, " AEC underflow (capture runs faster than "265 pj_lock_release(echo->lock); 266 267 PJ_LOG(5,(THIS_FILE, "Speex AEC underflow (capture runs faster than " 224 268 "playback, wpos=%d, rpos=%d)", 225 aec->wpos, aec->rpos));226 aec->rpos = (aec->wpos - BUF_COUNT/2) % BUF_COUNT;227 speex_echo_state_reset( aec->state);269 echo->wpos, echo->rpos)); 270 echo->rpos = (echo->wpos - BUF_COUNT/2) % BUF_COUNT; 271 speex_echo_state_reset(echo->state); 228 272 229 273 return PJ_SUCCESS; … … 232 276 233 277 /* Cancel echo */ 234 status = pjmedia_aec_cancel_echo(aec, rec_frm,235 aec->frames[aec->rpos].buf, options,236 237 238 aec->rpos = (aec->rpos + 1) % BUF_COUNT;239 240 pj_lock_release( aec->lock);278 status = speex_aec_cancel_echo(echo, rec_frm, 279 echo->frames[echo->rpos].buf, options, 280 NULL); 281 282 echo->rpos = (echo->rpos + 1) % BUF_COUNT; 283 284 pj_lock_release(echo->lock); 241 285 return status; 242 286 } … … 246 290 * Perform echo cancellation. 247 291 */ 248 PJ_DEF(pj_status_t) pjmedia_aec_cancel_echo( pjmedia_aec *aec, 249 pj_int16_t *rec_frm, 250 const pj_int16_t *play_frm, 251 unsigned options, 252 void *reserved ) 253 { 292 PJ_DEF(pj_status_t) speex_aec_cancel_echo( void *state, 293 pj_int16_t *rec_frm, 294 const pj_int16_t *play_frm, 295 unsigned options, 296 void *reserved ) 297 { 298 speex_ec *echo = state; 299 254 300 /* Sanity checks */ 255 PJ_ASSERT_RETURN( aec&& rec_frm && play_frm && options==0 &&301 PJ_ASSERT_RETURN(echo && rec_frm && play_frm && options==0 && 256 302 reserved==NULL, PJ_EINVAL); 257 303 258 304 /* Cancel echo, put output in temporary buffer */ 259 speex_echo_cancel( aec->state, (const spx_int16_t*)rec_frm,305 speex_echo_cancel(echo->state, (const spx_int16_t*)rec_frm, 260 306 (const spx_int16_t*)play_frm, 261 (spx_int16_t*) aec->tmp_frame,262 aec->residue);307 (spx_int16_t*)echo->tmp_frame, 308 echo->residue); 263 309 264 310 265 311 /* Preprocess output */ 266 speex_preprocess( aec->preprocess, (spx_int16_t*)aec->tmp_frame,267 aec->residue);312 speex_preprocess(echo->preprocess, (spx_int16_t*)echo->tmp_frame, 313 echo->residue); 268 314 269 315 /* Copy temporary buffer back to original rec_frm */ 270 pjmedia_copy_samples(rec_frm, aec->tmp_frame, aec->samples_per_frame);316 pjmedia_copy_samples(rec_frm, echo->tmp_frame, echo->samples_per_frame); 271 317 272 318 return PJ_SUCCESS; -
pjproject/trunk/pjmedia/src/pjmedia/sound_port.c
r650 r653 18 18 */ 19 19 #include <pjmedia/sound_port.h> 20 #include <pjmedia/ aec.h>20 #include <pjmedia/echo.h> 21 21 #include <pjmedia/errno.h> 22 22 #include <pjmedia/plc.h> … … 57 57 unsigned options; 58 58 59 pjmedia_ aec *aec;59 pjmedia_echo_state *ec_state; 60 60 unsigned aec_tail_len; 61 61 pjmedia_plc *plc; … … 116 116 pjmedia_plc_save(snd_port->plc, output); 117 117 118 if (snd_port-> aec) {119 pjmedia_ aec_playback(snd_port->aec, output);118 if (snd_port->ec_state) { 119 pjmedia_echo_playback(snd_port->ec_state, output); 120 120 } 121 121 … … 165 165 166 166 /* Cancel echo */ 167 if (snd_port-> aec) {168 pjmedia_ aec_capture(snd_port->aec, input, 0);167 if (snd_port->ec_state) { 168 pjmedia_echo_capture(snd_port->ec_state, input, 0); 169 169 } 170 170 … … 252 252 /* Create AEC only when direction is full duplex */ 253 253 if (snd_port->dir == PJMEDIA_DIR_CAPTURE_PLAYBACK) { 254 status = pjmedia_snd_port_set_ aec(snd_port, pool, AEC_TAIL);254 status = pjmedia_snd_port_set_ec_tail(snd_port, pool, AEC_TAIL); 255 255 if (status != PJ_SUCCESS) { 256 256 PJ_LOG(4,(THIS_FILE, "Unable to create AEC")); 257 snd_port-> aec= NULL;257 snd_port->ec_state = NULL; 258 258 } 259 259 } … … 285 285 286 286 /* Destroy AEC */ 287 if (snd_port-> aec) {288 pjmedia_ aec_destroy(snd_port->aec);289 snd_port-> aec= NULL;287 if (snd_port->ec_state) { 288 pjmedia_echo_destroy(snd_port->ec_state); 289 snd_port->ec_state = NULL; 290 290 } 291 291 … … 433 433 * Enable AEC 434 434 */ 435 PJ_DEF(pj_status_t) pjmedia_snd_port_set_ aec(pjmedia_snd_port *snd_port,436 pj_pool_t *pool,437 unsigned tail_ms)435 PJ_DEF(pj_status_t) pjmedia_snd_port_set_ec_tail(pjmedia_snd_port *snd_port, 436 pj_pool_t *pool, 437 unsigned tail_ms) 438 438 { 439 439 pj_status_t status; … … 445 445 446 446 /* Destroy AEC */ 447 if (snd_port-> aec) {448 pjmedia_ aec_destroy(snd_port->aec);449 snd_port-> aec= NULL;447 if (snd_port->ec_state) { 448 pjmedia_echo_destroy(snd_port->ec_state); 449 snd_port->ec_state = NULL; 450 450 } 451 451 … … 453 453 454 454 if (tail_ms != 0) { 455 status = pjmedia_ aec_create(pool, snd_port->clock_rate,455 status = pjmedia_echo_create(pool, snd_port->clock_rate, 456 456 snd_port->samples_per_frame, 457 tail_ms, 0, &snd_port-> aec);457 tail_ms, 0, &snd_port->ec_state); 458 458 if (status != PJ_SUCCESS) 459 snd_port-> aec= NULL;459 snd_port->ec_state = NULL; 460 460 } else { 461 PJ_LOG(4,(THIS_FILE, "AEC disabled in the sound port")); 461 PJ_LOG(4,(THIS_FILE, "Echo canceller is now disabled in the " 462 "sound port")); 462 463 status = PJ_SUCCESS; 463 464 } … … 468 469 469 470 /* Get AEC tail length */ 470 PJ_DEF(pj_status_t) pjmedia_snd_port_get_ aec_tail( pjmedia_snd_port *snd_port,471 471 PJ_DEF(pj_status_t) pjmedia_snd_port_get_ec_tail( pjmedia_snd_port *snd_port, 472 unsigned *p_length) 472 473 { 473 474 PJ_ASSERT_RETURN(snd_port && p_length, PJ_EINVAL); 474 *p_length = snd_port-> aec? snd_port->aec_tail_len : 0;475 *p_length = snd_port->ec_state ? snd_port->aec_tail_len : 0; 475 476 return PJ_SUCCESS; 476 477 } -
pjproject/trunk/pjsip-apps/build/Samples.mak
r578 r653 27 27 $(subst /,$(HOST_PSEP),$(PJMEDIA_CODEC_LIB)) \ 28 28 $(subst /,$(HOST_PSEP),$(PJMEDIA_LIB)) \ 29 $(subst /,$(HOST_PSEP),$(PJMEDIA_CODEC_LIB)) \ 29 30 $(subst /,$(HOST_PSEP),$(PJLIB_UTIL_LIB)) \ 30 31 $(subst /,$(HOST_PSEP),$(PJLIB_LIB)) -
pjproject/trunk/pjsip/docs/PJSUA-TESTING.txt
r648 r653 30 30 MULTIPLE ACCOUNTS (combo.cfg) 31 31 32 DIGEST with qop=auth (sipcenter?) 32 33 33 34 AUDIO QUALITY -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
r651 r653 2503 2503 2504 2504 /** 2505 * Configure the AEC settingsof the sound port.2505 * Configure the echo canceller tail length of the sound port. 2506 2506 * 2507 2507 * @param tail_ms The tail length, in miliseconds. Set to zero to … … 2510 2510 * @return PJ_SUCCESS on success. 2511 2511 */ 2512 PJ_DECL(pj_status_t) pjsua_set_ aec(unsigned tail_ms);2513 2514 2515 /** 2516 * Get current AECtail length.2512 PJ_DECL(pj_status_t) pjsua_set_ec_tail(unsigned tail_ms); 2513 2514 2515 /** 2516 * Get current echo canceller tail length. 2517 2517 * 2518 2518 * @param p_tail_ms Pointer to receive the tail length, in miliseconds. … … 2521 2521 * @return PJ_SUCCESS on success. 2522 2522 */ 2523 PJ_DECL(pj_status_t) pjsua_get_ aec(unsigned *p_tail_ms);2523 PJ_DECL(pj_status_t) pjsua_get_ec_tail(unsigned *p_tail_ms); 2524 2524 2525 2525 -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
r649 r653 970 970 971 971 /* Set AEC */ 972 pjmedia_snd_port_set_ aec(pjsua_var.snd_port, pjsua_var.pool,973 pjsua_var.media_cfg.ec_tail_len);972 pjmedia_snd_port_set_ec_tail(pjsua_var.snd_port, pjsua_var.pool, 973 pjsua_var.media_cfg.ec_tail_len); 974 974 975 975 /* Connect sound port to the bridge */ … … 1045 1045 * Configure the AEC settings of the sound port. 1046 1046 */ 1047 PJ_DEF(pj_status_t) pjsua_set_ aec(unsigned tail_ms)1047 PJ_DEF(pj_status_t) pjsua_set_ec_tail(unsigned tail_ms) 1048 1048 { 1049 1049 pjsua_var.media_cfg.ec_tail_len = tail_ms; 1050 1050 1051 1051 if (pjsua_var.snd_port) 1052 return pjmedia_snd_port_set_ aec(pjsua_var.snd_port, pjsua_var.pool,1053 tail_ms);1052 return pjmedia_snd_port_set_ec_tail(pjsua_var.snd_port, pjsua_var.pool, 1053 tail_ms); 1054 1054 1055 1055 return PJ_SUCCESS; … … 1060 1060 * Get current AEC tail length. 1061 1061 */ 1062 PJ_DEF(pj_status_t) pjsua_get_ aec(unsigned *p_tail_ms)1062 PJ_DEF(pj_status_t) pjsua_get_ec_tail(unsigned *p_tail_ms) 1063 1063 { 1064 1064 *p_tail_ms = pjsua_var.media_cfg.ec_tail_len;
Note: See TracChangeset
for help on using the changeset viewer.