Index: pjproject/trunk/pjmedia/src/pjmedia/echo_speex.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/echo_speex.c	(revision 2039)
+++ pjproject/trunk/pjmedia/src/pjmedia/echo_speex.c	(revision 2198)
@@ -20,9 +20,5 @@
 #include <pjmedia/echo.h>
 #include <pjmedia/errno.h>
-#include <pjmedia/silencedet.h>
 #include <pj/assert.h>
-#include <pj/lock.h>
-#include <pj/log.h>
-#include <pj/os.h>
 #include <pj/pool.h>
 #include <speex/speex_echo.h>
@@ -30,208 +26,4 @@
 
 #include "echo_internal.h"
-
-#define THIS_FILE	"echo_speex.c"
-#define BUF_COUNT	PJMEDIA_SOUND_BUFFER_COUNT
-#define MIN_PREFETCH	2
-#define MAX_PREFETCH	(BUF_COUNT*2/3)
-
-
-
-#if 0
-# define TRACE_(expr)  PJ_LOG(5,expr)
-#else
-# define TRACE_(expr)
-#endif
-
-
-typedef struct pjmedia_frame_queue pjmedia_frame_queue;
-
-struct fq_frame
-{
-    PJ_DECL_LIST_MEMBER(struct fq_frame);
-    void	*buf;
-    unsigned	 size;
-    pj_uint32_t	 seq;
-};
-
-struct pjmedia_frame_queue
-{
-    char	     obj_name[PJ_MAX_OBJ_NAME];
-    unsigned	     frame_size;
-    int		     samples_per_frame;
-    unsigned	     count;
-    unsigned	     max_count;
-    struct fq_frame  frame_list;
-    struct fq_frame  free_list;
-
-    int		     seq_delay;
-    int		     prefetch_count;
-};
-
-PJ_DEF(pj_status_t) pjmedia_frame_queue_create( pj_pool_t *pool,
-					        const char *name,
-					        unsigned frame_size,
-					        unsigned samples_per_frame,
-					        unsigned max_count,
-					        pjmedia_frame_queue **p_fq)
-{
-    pjmedia_frame_queue *fq;
-    unsigned i;
-
-    fq = PJ_POOL_ZALLOC_T(pool, pjmedia_frame_queue);
-
-    pj_ansi_snprintf(fq->obj_name, sizeof(fq->obj_name), name, fq);
-    fq->obj_name[sizeof(fq->obj_name)-1] = '\0';
-
-    fq->max_count = max_count;
-    fq->frame_size = frame_size;
-    fq->samples_per_frame = samples_per_frame;
-    fq->count = 0;
-
-    pj_list_init(&fq->frame_list);
-    pj_list_init(&fq->free_list);
-
-    for (i=0; i<max_count; ++i) {
-	struct fq_frame *f;
-
-	f = PJ_POOL_ZALLOC_T(pool, struct fq_frame);
-	f->buf = pj_pool_alloc(pool, frame_size);
-
-	pj_list_push_back(&fq->free_list, f);
-	
-    }
-
-    *p_fq = fq;
-    return PJ_SUCCESS;
-}
-
-PJ_DEF(pj_status_t) pjmedia_frame_queue_init( pjmedia_frame_queue *fq,
-					      int seq_delay,
-					      int prefetch_count)
-{
-    if (prefetch_count > MAX_PREFETCH)
-	prefetch_count = MAX_PREFETCH;
-
-    fq->seq_delay = seq_delay;
-    fq->prefetch_count = prefetch_count;
-    fq->count = 0;
-    pj_list_merge_first(&fq->free_list, &fq->frame_list);
-
-    PJ_LOG(5,(fq->obj_name, "AEC reset, delay=%d, prefetch=%d", 
-	      fq->seq_delay, fq->prefetch_count));
-
-    return PJ_SUCCESS;
-}
-
-PJ_DEF(pj_bool_t) pjmedia_frame_queue_empty( pjmedia_frame_queue *fq )
-{
-    return pj_list_empty(&fq->frame_list);
-}
-
-PJ_DEF(int) pjmedia_frame_queue_get_prefetch( pjmedia_frame_queue *fq )
-{
-    return fq->prefetch_count;
-}
-
-PJ_DEF(pj_status_t) pjmedia_frame_queue_put( pjmedia_frame_queue *fq,
-					     const void *framebuf,
-					     unsigned size,
-					     pj_uint32_t timestamp )
-{
-    struct fq_frame *f;
-
-    TRACE_((fq->obj_name, "PUT seq=%d, count=%d", 
-	    timestamp / fq->samples_per_frame, fq->count));
-
-    if (pj_list_empty(&fq->free_list)) {
-	PJ_LOG(5,(fq->obj_name, 
-		  " AEC info: queue is full, frame discarded "
-		  "[count=%d, seq=%d]",
-		  fq->max_count, timestamp / fq->samples_per_frame));
-	//pjmedia_frame_queue_init(fq, fq->seq_delay, fq->prefetch_count);
-	return PJ_ETOOMANY;
-    }
-
-    PJ_ASSERT_RETURN(size <= fq->frame_size, PJ_ETOOBIG);
-
-    f = fq->free_list.next;
-    pj_list_erase(f);
-
-    pj_memcpy(f->buf, framebuf, size);
-    f->size = size;
-    f->seq = timestamp / fq->samples_per_frame;
-
-    pj_list_push_back(&fq->frame_list, f);
-    ++fq->count;
-
-    return PJ_SUCCESS;
-}
-
-PJ_DEF(pj_status_t) pjmedia_frame_queue_get( pjmedia_frame_queue *fq,
-					     pj_uint32_t get_timestamp,
-					     void **framebuf,
-					     unsigned *size )
-{
-    pj_uint32_t frame_seq;
-    struct fq_frame *f;
-
-    frame_seq = get_timestamp/fq->samples_per_frame + fq->seq_delay -
-		fq->prefetch_count;
-
-    TRACE_((fq->obj_name, "GET seq=%d for seq=%d delay=%d, prefetch=%d", 
-	    get_timestamp/fq->samples_per_frame, frame_seq, fq->seq_delay, 
-	    fq->prefetch_count));
-
-    *size = 0;
-
-    /* Remove old frames */
-    for (;!pj_list_empty(&fq->frame_list);) {
-	f = fq->frame_list.next;
-	if (f->seq >= frame_seq)
-	    break;
-
-	PJ_LOG(5,(fq->obj_name, 
-		  " AEC Info: old frame removed (seq=%d, want=%d, count=%d)",
-		  f->seq, frame_seq, fq->count));
-	pj_list_erase(f);
-	--fq->count;
-	pj_list_push_back(&fq->free_list, f);
-    }
-
-    if (pj_list_empty(&fq->frame_list)) {
-	PJ_LOG(5,(fq->obj_name, 
-		  " AEC Info: empty queue for seq=%d!",
-		  frame_seq));
-	return PJ_ENOTFOUND;
-    }
-
-    f = fq->frame_list.next;
-
-    if (f->seq > frame_seq) {
-	PJ_LOG(5,(fq->obj_name, 
-		  " AEC Info: prefetching (first seq=%d)",
-		  f->seq));
-	return -1;
-    }
-
-    pj_list_erase(f);
-    --fq->count;
-
-    *framebuf = (void*)f->buf;
-    *size = f->size;
-
-    TRACE_((fq->obj_name, " returning frame with seq=%d, count=%d", 
-	    f->seq, fq->count));
-
-    pj_list_push_front(&fq->free_list, f);
-    return PJ_SUCCESS;
-}
-
-enum
-{
-    TS_FLAG_PLAY = 1,
-    TS_FLAG_REC	 = 2,
-    TS_FLAG_OK	 = 3,
-};
 
 typedef struct speex_ec
@@ -244,12 +36,4 @@
     unsigned		  options;
     pj_int16_t		 *tmp_frame;
-    spx_int32_t		 *residue;
-
-    pj_uint32_t		  play_ts,
-			  rec_ts,
-			  ts_flag;
-
-    pjmedia_frame_queue	 *frame_queue;
-    pj_lock_t		 *lock;		/* To protect buffers, if required  */
 } speex_ec;
 
@@ -261,7 +45,7 @@
 PJ_DEF(pj_status_t) speex_aec_create(pj_pool_t *pool,
 				     unsigned clock_rate,
+				     unsigned channel_count,
 				     unsigned samples_per_frame,
 				     unsigned tail_ms,
-				     unsigned latency_ms,
 				     unsigned options,
 				     void **p_echo )
@@ -269,5 +53,4 @@
     speex_ec *echo;
     int sampling_rate;
-    pj_status_t status;
 
     *p_echo = NULL;
@@ -276,26 +59,17 @@
     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->prefetch = (latency_ms * clock_rate / 1000) / samples_per_frame;
-    if (echo->prefetch < MIN_PREFETCH)
-	echo->prefetch = MIN_PREFETCH;
-    if (echo->prefetch > MAX_PREFETCH)
-	echo->prefetch = MAX_PREFETCH;
     echo->options = options;
 
-    echo->state = speex_echo_state_init(samples_per_frame,
-					clock_rate * tail_ms / 1000);
+#if 0
+    echo->state = speex_echo_state_init_mc(echo->samples_per_frame,
+					   clock_rate * tail_ms / 1000,
+					   channel_count, channel_count);
+#else
+    PJ_ASSERT_RETURN(channel_count==1, PJ_EINVAL);
+    echo->state = speex_echo_state_init(echo->samples_per_frame,
+    					clock_rate * tail_ms / 1000);
+#endif
     if (echo->state == NULL) {
-	pj_lock_destroy(echo->lock);
 	return PJ_ENOMEM;
     }
@@ -306,9 +80,8 @@
 		   &sampling_rate);
 
-    echo->preprocess = speex_preprocess_state_init(samples_per_frame, 
+    echo->preprocess = speex_preprocess_state_init(echo->samples_per_frame,
 						   clock_rate);
     if (echo->preprocess == NULL) {
 	speex_echo_state_destroy(echo->state);
-	pj_lock_destroy(echo->lock);
 	return PJ_ENOMEM;
     }
@@ -325,5 +98,5 @@
 			 &disabled);
     speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_DEREVERB, 
-			 &disabled);
+			 &enabled);
 #endif
 
@@ -334,31 +107,9 @@
 
     /* Create temporary frame for echo cancellation */
-    echo->tmp_frame = (pj_int16_t*) pj_pool_zalloc(pool, 2 * samples_per_frame);
+    echo->tmp_frame = (pj_int16_t*) pj_pool_zalloc(pool, 2*samples_per_frame);
     PJ_ASSERT_RETURN(echo->tmp_frame != NULL, PJ_ENOMEM);
-
-    /* Create temporary frame to receive residue */
-    echo->residue = (spx_int32_t*)
-		    pj_pool_zalloc(pool, sizeof(spx_int32_t) * 
-					    (samples_per_frame+1));
-    PJ_ASSERT_RETURN(echo->residue != NULL, PJ_ENOMEM);
-
-    /* Create frame queue */
-    status = pjmedia_frame_queue_create(pool, "aec%p", samples_per_frame*2,
-					samples_per_frame, BUF_COUNT, 
-					&echo->frame_queue);
-    if (status != PJ_SUCCESS) {
-	speex_preprocess_state_destroy(echo->preprocess);
-	speex_echo_state_destroy(echo->state);
-	pj_lock_destroy(echo->lock);
-	return status;
-    }
 
     /* Done */
     *p_echo = echo;
-
-    PJ_LOG(4,(THIS_FILE, "Speex Echo canceller/AEC created, clock_rate=%d, "
-			 "samples per frame=%d, tail length=%d ms, "
-			 "latency=%d ms", 
-			 clock_rate, samples_per_frame, tail_ms, latency_ms));
     return PJ_SUCCESS;
 
@@ -375,7 +126,4 @@
     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);
@@ -388,9 +136,4 @@
     }
 
-    if (echo->lock) {
-	pj_lock_destroy(echo->lock);
-	echo->lock = NULL;
-    }
-
     return PJ_SUCCESS;
 }
@@ -398,125 +141,10 @@
 
 /*
- * Let the AEC knows that a frame has been played to the speaker.
+ * Reset AEC
  */
-PJ_DEF(pj_status_t) speex_aec_playback(void *state,
-				       pj_int16_t *play_frm )
+PJ_DEF(void) speex_aec_reset(void *state )
 {
     speex_ec *echo = (speex_ec*) state;
-
-    /* Sanity checks */
-    PJ_ASSERT_RETURN(echo && play_frm, PJ_EINVAL);
-
-    /* The AEC must be configured to support internal playback buffer */
-    PJ_ASSERT_RETURN(echo->frame_queue!= NULL, PJ_EINVALIDOP);
-
-    pj_lock_acquire(echo->lock);
-
-    /* Inc timestamp */
-    echo->play_ts += echo->samples_per_frame;
-
-    /* Initialize frame delay. */
-    if ((echo->ts_flag & TS_FLAG_PLAY) == 0) {
-	echo->ts_flag |= TS_FLAG_PLAY;
-
-	if (echo->ts_flag == TS_FLAG_OK) {
-	    int seq_delay;
-
-	    seq_delay = ((int)echo->play_ts - (int)echo->rec_ts) / 
-			    (int)echo->samples_per_frame;
-	    pjmedia_frame_queue_init(echo->frame_queue, seq_delay, 
-				     echo->prefetch);
-	}
-    }
-
-    if (pjmedia_frame_queue_put(echo->frame_queue, play_frm, 
-				echo->samples_per_frame*2, 
-				echo->play_ts) != PJ_SUCCESS)
-    {
-	int seq_delay;
-
-	/* On full reset frame queue */
-	seq_delay = ((int)echo->play_ts - (int)echo->rec_ts) / 
-			(int)echo->samples_per_frame;
-	pjmedia_frame_queue_init(echo->frame_queue, seq_delay,
-				 echo->prefetch);
-
-	/* And re-put */
-	pjmedia_frame_queue_put(echo->frame_queue, play_frm, 
-				echo->samples_per_frame*2, 
-				echo->play_ts);
-    }
-
-    pj_lock_release(echo->lock);
-
-    return PJ_SUCCESS;
-}
-
-
-/*
- * Let the AEC knows that a frame has been captured from the microphone.
- */
-PJ_DEF(pj_status_t) speex_aec_capture( void *state,
-				       pj_int16_t *rec_frm,
-				       unsigned options )
-{
-    speex_ec *echo = (speex_ec*) state;
-    pj_status_t status = PJ_SUCCESS;
-
-    /* Sanity checks */
-    PJ_ASSERT_RETURN(echo && rec_frm, PJ_EINVAL);
-
-    /* The AEC must be configured to support internal playback buffer */
-    PJ_ASSERT_RETURN(echo->frame_queue!= NULL, PJ_EINVALIDOP);
-
-    /* Lock mutex */
-    pj_lock_acquire(echo->lock);
-
-    /* Inc timestamp */
-    echo->rec_ts += echo->samples_per_frame;
-
-    /* Init frame delay. */
-    if ((echo->ts_flag & TS_FLAG_REC) == 0) {
-	echo->ts_flag |= TS_FLAG_REC;
-
-	if (echo->ts_flag == TS_FLAG_OK) {
-	    int seq_delay;
-
-	    seq_delay = ((int)echo->play_ts - (int)echo->rec_ts) / 
-			    (int)echo->samples_per_frame;
-	    pjmedia_frame_queue_init(echo->frame_queue, seq_delay, 
-				     echo->prefetch);
-	}
-    }
-
-    /* Cancel echo */
-    if (echo->ts_flag == TS_FLAG_OK) {
-	void *play_buf;
-	unsigned size = 0;
-	
-	if (pjmedia_frame_queue_empty(echo->frame_queue)) {
-	    int seq_delay;
-
-	    seq_delay = ((int)echo->play_ts - (int)echo->rec_ts) / 
-			    (int)echo->samples_per_frame;
-	    pjmedia_frame_queue_init(echo->frame_queue, seq_delay, 
-				     echo->prefetch);
-	    status = -1;
-
-	} else {
-	    status = pjmedia_frame_queue_get(echo->frame_queue, echo->rec_ts,
-					     &play_buf, &size);
-	    if (size != 0) {
-		speex_aec_cancel_echo(echo, rec_frm, (pj_int16_t*)play_buf,
-				      options, NULL);
-	    }	
-	}
-
-	if (status != PJ_SUCCESS)
-	    speex_echo_state_reset(echo->state);
-    }
-
-    pj_lock_release(echo->lock);
-    return PJ_SUCCESS;
+    speex_echo_state_reset(echo->state);
 }
 
