Index: pjproject/trunk/pjmedia/src/pjmedia/echo_speex.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/aec_speex.c	(revision 648)
+++ pjproject/trunk/pjmedia/src/pjmedia/echo_speex.c	(revision 653)
@@ -18,5 +18,5 @@
  */
 
-#include <pjmedia/aec.h>
+#include <pjmedia/echo.h>
 #include <pjmedia/errno.h>
 #include <pjmedia/silencedet.h>
@@ -30,6 +30,27 @@
 
 
-#define THIS_FILE   "aec_speex.c"
+#define THIS_FILE   "echo_speex.c"
 #define BUF_COUNT   8
+
+/*
+ * Prototypes
+ */
+PJ_DECL(pj_status_t) speex_aec_create(pj_pool_t *pool,
+				      unsigned clock_rate,
+				      unsigned samples_per_frame,
+				      unsigned tail_ms,
+				      unsigned options,
+				      void **p_state );
+PJ_DECL(pj_status_t) speex_aec_destroy(void *state );
+PJ_DECL(pj_status_t) speex_aec_playback(void *state,
+				        pj_int16_t *play_frm );
+PJ_DECL(pj_status_t) speex_aec_capture(void *state,
+				       pj_int16_t *rec_frm,
+				       unsigned options );
+PJ_DECL(pj_status_t) speex_aec_cancel_echo(void *state,
+					   pj_int16_t *rec_frm,
+					   const pj_int16_t *play_frm,
+					   unsigned options,
+					   void *reserved );
 
 
@@ -39,5 +60,5 @@
 };
 
-struct pjmedia_aec
+typedef struct speex_ec
 {
     SpeexEchoState	 *state;
@@ -54,5 +75,5 @@
     unsigned	     wpos;		/* Index to put newest frame.	    */
     struct frame     frames[BUF_COUNT];	/* Playback frame buffers.	    */
-};
+} speex_ec;
 
 
@@ -61,68 +82,86 @@
  * Create the AEC. 
  */
-PJ_DEF(pj_status_t) pjmedia_aec_create( pj_pool_t *pool,
-					unsigned clock_rate,
-					unsigned samples_per_frame,
-					unsigned tail_ms,
-					unsigned options,
-					pjmedia_aec **p_aec )
-{
-    pjmedia_aec *aec;
+PJ_DEF(pj_status_t) speex_aec_create(pj_pool_t *pool,
+				     unsigned clock_rate,
+				     unsigned samples_per_frame,
+				     unsigned tail_ms,
+				     unsigned options,
+				     void **p_echo )
+{
+    speex_ec *echo;
     int sampling_rate;
     unsigned i;
+    int disabled;
     pj_status_t status;
 
-    *p_aec = NULL;
-
-    aec = pj_pool_zalloc(pool, sizeof(pjmedia_aec));
-    PJ_ASSERT_RETURN(aec != NULL, PJ_ENOMEM);
-
-    status = pj_lock_create_simple_mutex(pool, "aec%p", &aec->lock);
-    if (status != PJ_SUCCESS)
-	return status;
-
-    aec->samples_per_frame = samples_per_frame;
-    aec->options = options;
-
-    aec->state = speex_echo_state_init(samples_per_frame,
+    *p_echo = NULL;
+
+    echo = pj_pool_zalloc(pool, sizeof(speex_ec));
+    PJ_ASSERT_RETURN(echo != NULL, PJ_ENOMEM);
+
+    if (options & PJMEDIA_ECHO_NO_LOCK) {
+	status = pj_lock_create_null_mutex(pool, "aec%p", &echo->lock);
+	if (status != PJ_SUCCESS)
+	    return status;
+    } else {
+	status = pj_lock_create_simple_mutex(pool, "aec%p", &echo->lock);
+	if (status != PJ_SUCCESS)
+	    return status;
+    }
+
+    echo->samples_per_frame = samples_per_frame;
+    echo->options = options;
+
+    echo->state = speex_echo_state_init(samples_per_frame,
 					clock_rate * tail_ms / 1000);
-    if (aec->state == NULL) {
-	pj_lock_destroy(aec->lock);
+    if (echo->state == NULL) {
+	pj_lock_destroy(echo->lock);
 	return PJ_ENOMEM;
     }
 
-    aec->preprocess = speex_preprocess_state_init(samples_per_frame, 
-						  clock_rate);
-    if (aec->preprocess == NULL) {
-	speex_echo_state_destroy(aec->state);
-	pj_lock_destroy(aec->lock);
+    echo->preprocess = speex_preprocess_state_init(samples_per_frame, 
+						   clock_rate);
+    if (echo->preprocess == NULL) {
+	speex_echo_state_destroy(echo->state);
+	pj_lock_destroy(echo->lock);
 	return PJ_ENOMEM;
     }
+
+    /* Disable all preprocessing, we only want echo cancellation */
+    disabled = 0;
+    speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_DENOISE, 
+			 &disabled);
+    speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_AGC, 
+			 &disabled);
+    speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_VAD, 
+			 &disabled);
+    speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_DEREVERB, 
+			 &disabled);
 
     /* Set sampling rate */
     sampling_rate = clock_rate;
-    speex_echo_ctl(aec->state, SPEEX_ECHO_SET_SAMPLING_RATE, 
+    speex_echo_ctl(echo->state, SPEEX_ECHO_SET_SAMPLING_RATE, 
 		   &sampling_rate);
 
     /* Create temporary frame for echo cancellation */
-    aec->tmp_frame = pj_pool_zalloc(pool, 2 * samples_per_frame);
-    PJ_ASSERT_RETURN(aec->tmp_frame != NULL, PJ_ENOMEM);
+    echo->tmp_frame = pj_pool_zalloc(pool, 2 * samples_per_frame);
+    PJ_ASSERT_RETURN(echo->tmp_frame != NULL, PJ_ENOMEM);
 
     /* Create temporary frame to receive residue */
-    aec->residue = pj_pool_zalloc(pool, sizeof(spx_int32_t) * 
+    echo->residue = pj_pool_zalloc(pool, sizeof(spx_int32_t) * 
 					    samples_per_frame);
-    PJ_ASSERT_RETURN(aec->residue != NULL, PJ_ENOMEM);
+    PJ_ASSERT_RETURN(echo->residue != NULL, PJ_ENOMEM);
 
     /* Create internal playback buffers */
     for (i=0; i<BUF_COUNT; ++i) {
-	aec->frames[i].buf = pj_pool_zalloc(pool, samples_per_frame * 2);
-	PJ_ASSERT_RETURN(aec->frames[i].buf != NULL, PJ_ENOMEM);
+	echo->frames[i].buf = pj_pool_zalloc(pool, samples_per_frame * 2);
+	PJ_ASSERT_RETURN(echo->frames[i].buf != NULL, PJ_ENOMEM);
     }
 
 
     /* Done */
-    *p_aec = aec;
-
-    PJ_LOG(4,(THIS_FILE, "Echo canceller/AEC created, clock_rate=%d, "
+    *p_echo = echo;
+
+    PJ_LOG(4,(THIS_FILE, "Speex Echo canceller/AEC created, clock_rate=%d, "
 			 "samples per frame=%d, tail length=%d ms", 
 			 clock_rate,
@@ -137,24 +176,26 @@
  * Destroy AEC
  */
-PJ_DEF(pj_status_t) pjmedia_aec_destroy(pjmedia_aec *aec )
-{
-    PJ_ASSERT_RETURN(aec && aec->state, PJ_EINVAL);
-
-    if (aec->lock)
-	pj_lock_acquire(aec->lock);
-
-    if (aec->state) {
-	speex_echo_state_destroy(aec->state);
-	aec->state = NULL;
-    }
-
-    if (aec->preprocess) {
-	speex_preprocess_state_destroy(aec->preprocess);
-	aec->preprocess = NULL;
-    }
-
-    if (aec->lock) {
-	pj_lock_destroy(aec->lock);
-	aec->lock = NULL;
+PJ_DEF(pj_status_t) speex_aec_destroy(void *state )
+{
+    speex_ec *echo = state;
+
+    PJ_ASSERT_RETURN(echo && echo->state, PJ_EINVAL);
+
+    if (echo->lock)
+	pj_lock_acquire(echo->lock);
+
+    if (echo->state) {
+	speex_echo_state_destroy(echo->state);
+	echo->state = NULL;
+    }
+
+    if (echo->preprocess) {
+	speex_preprocess_state_destroy(echo->preprocess);
+	echo->preprocess = NULL;
+    }
+
+    if (echo->lock) {
+	pj_lock_destroy(echo->lock);
+	echo->lock = NULL;
     }
 
@@ -166,30 +207,32 @@
  * Let the AEC knows that a frame has been played to the speaker.
  */
-PJ_DEF(pj_status_t) pjmedia_aec_playback(pjmedia_aec *aec,
-					 pj_int16_t *play_frm )
-{
+PJ_DEF(pj_status_t) speex_aec_playback(void *state,
+				       pj_int16_t *play_frm )
+{
+    speex_ec *echo = state;
+
     /* Sanity checks */
-    PJ_ASSERT_RETURN(aec && play_frm, PJ_EINVAL);
+    PJ_ASSERT_RETURN(echo && play_frm, PJ_EINVAL);
 
     /* The AEC must be configured to support internal playback buffer */
-    PJ_ASSERT_RETURN(aec->frames[0].buf != NULL, PJ_EINVALIDOP);
-
-    pj_lock_acquire(aec->lock);
+    PJ_ASSERT_RETURN(echo->frames[0].buf != NULL, PJ_EINVALIDOP);
+
+    pj_lock_acquire(echo->lock);
 
     /* Check for overflows */
-    if (aec->wpos == aec->rpos) {
-	PJ_LOG(5,(THIS_FILE, "AEC overflow (playback runs faster, "
+    if (echo->wpos == echo->rpos) {
+	PJ_LOG(5,(THIS_FILE, "Speex AEC overflow (playback runs faster, "
 			     "wpos=%d, rpos=%d)",
-			     aec->wpos, aec->rpos));
-	aec->rpos = (aec->wpos - BUF_COUNT/2) % BUF_COUNT;
-	speex_echo_state_reset(aec->state);
+			     echo->wpos, echo->rpos));
+	echo->rpos = (echo->wpos - BUF_COUNT/2) % BUF_COUNT;
+	speex_echo_state_reset(echo->state);
     }
 
     /* Save fhe frame */
-    pjmedia_copy_samples(aec->frames[aec->wpos].buf,
-			 play_frm, aec->samples_per_frame);
-    aec->wpos = (aec->wpos+1) % BUF_COUNT;
-
-    pj_lock_release(aec->lock);
+    pjmedia_copy_samples(echo->frames[echo->wpos].buf,
+			 play_frm, echo->samples_per_frame);
+    echo->wpos = (echo->wpos+1) % BUF_COUNT;
+
+    pj_lock_release(echo->lock);
 
     return PJ_SUCCESS;
@@ -200,30 +243,31 @@
  * Let the AEC knows that a frame has been captured from the microphone.
  */
-PJ_DEF(pj_status_t) pjmedia_aec_capture( pjmedia_aec *aec,
-					 pj_int16_t *rec_frm,
-					 unsigned options )
-{
+PJ_DEF(pj_status_t) speex_aec_capture( void *state,
+				       pj_int16_t *rec_frm,
+				       unsigned options )
+{
+    speex_ec *echo = state;
     pj_status_t status;
 
     /* Sanity checks */
-    PJ_ASSERT_RETURN(aec && rec_frm, PJ_EINVAL);
+    PJ_ASSERT_RETURN(echo && rec_frm, PJ_EINVAL);
 
     /* The AEC must be configured to support internal playback buffer */
-    PJ_ASSERT_RETURN(aec->frames[0].buf != NULL, PJ_EINVALIDOP);
+    PJ_ASSERT_RETURN(echo->frames[0].buf != NULL, PJ_EINVALIDOP);
 
     /* Lock mutex */
-    pj_lock_acquire(aec->lock);
+    pj_lock_acquire(echo->lock);
 
 
     /* Check for underflow */
-    if (aec->rpos == aec->wpos) {
+    if (echo->rpos == echo->wpos) {
 	/* Return frame as it is */
-	pj_lock_release(aec->lock);
-
-	PJ_LOG(5,(THIS_FILE, "AEC underflow (capture runs faster than "
+	pj_lock_release(echo->lock);
+
+	PJ_LOG(5,(THIS_FILE, "Speex AEC underflow (capture runs faster than "
 			     "playback, wpos=%d, rpos=%d)", 
-			     aec->wpos, aec->rpos));
-	aec->rpos = (aec->wpos - BUF_COUNT/2) % BUF_COUNT;
-	speex_echo_state_reset(aec->state);
+			     echo->wpos, echo->rpos));
+	echo->rpos = (echo->wpos - BUF_COUNT/2) % BUF_COUNT;
+	speex_echo_state_reset(echo->state);
 
 	return PJ_SUCCESS;
@@ -232,11 +276,11 @@
 
     /* Cancel echo */
-    status = pjmedia_aec_cancel_echo(aec, rec_frm, 
-				     aec->frames[aec->rpos].buf, options,
-				     NULL);
-
-    aec->rpos = (aec->rpos + 1) % BUF_COUNT;
-
-    pj_lock_release(aec->lock);
+    status = speex_aec_cancel_echo(echo, rec_frm, 
+				   echo->frames[echo->rpos].buf, options,
+				   NULL);
+
+    echo->rpos = (echo->rpos + 1) % BUF_COUNT;
+
+    pj_lock_release(echo->lock);
     return status;
 }
@@ -246,27 +290,29 @@
  * Perform echo cancellation.
  */
-PJ_DEF(pj_status_t) pjmedia_aec_cancel_echo( pjmedia_aec *aec,
-					     pj_int16_t *rec_frm,
-					     const pj_int16_t *play_frm,
-					     unsigned options,
-					     void *reserved )
-{
+PJ_DEF(pj_status_t) speex_aec_cancel_echo( void *state,
+					   pj_int16_t *rec_frm,
+					   const pj_int16_t *play_frm,
+					   unsigned options,
+					   void *reserved )
+{
+    speex_ec *echo = state;
+
     /* Sanity checks */
-    PJ_ASSERT_RETURN(aec && rec_frm && play_frm && options==0 &&
+    PJ_ASSERT_RETURN(echo && rec_frm && play_frm && options==0 &&
 		     reserved==NULL, PJ_EINVAL);
 
     /* Cancel echo, put output in temporary buffer */
-    speex_echo_cancel(aec->state, (const spx_int16_t*)rec_frm, 
+    speex_echo_cancel(echo->state, (const spx_int16_t*)rec_frm, 
 		      (const spx_int16_t*)play_frm, 
-		      (spx_int16_t*)aec->tmp_frame, 
-		      aec->residue);
+		      (spx_int16_t*)echo->tmp_frame, 
+		      echo->residue);
 
 
     /* Preprocess output */
-    speex_preprocess(aec->preprocess, (spx_int16_t*)aec->tmp_frame, 
-		     aec->residue);
+    speex_preprocess(echo->preprocess, (spx_int16_t*)echo->tmp_frame, 
+		     echo->residue);
 
     /* Copy temporary buffer back to original rec_frm */
-    pjmedia_copy_samples(rec_frm, aec->tmp_frame, aec->samples_per_frame);
+    pjmedia_copy_samples(rec_frm, echo->tmp_frame, echo->samples_per_frame);
 
     return PJ_SUCCESS;
