Index: /pjproject/branches/1.x/pjmedia/include/pjmedia/delaybuf.h
===================================================================
--- /pjproject/branches/1.x/pjmedia/include/pjmedia/delaybuf.h	(revision 3566)
+++ /pjproject/branches/1.x/pjmedia/include/pjmedia/delaybuf.h	(revision 3567)
@@ -65,4 +65,17 @@
 
 /**
+ * Delay buffer options.
+ */
+typedef enum pjmedia_delay_buf_flag
+{
+    /**
+     * Use simple FIFO mechanism for the delay buffer, i.e.
+     * without WSOLA for expanding and shrinking audio samples.
+     */
+    PJMEDIA_DELAY_BUF_SIMPLE_FIFO = 1
+
+} pjmedia_delay_buf_flag;
+
+/**
  * Create the delay buffer. Once the delay buffer is created, it will
  * enter learning state unless the delay argument is specified, which
@@ -80,5 +93,10 @@
  *			    one frame time, default maximum delay used is
  *			    400 ms.
- * @param options	    Option flags, must be zero for now.
+ * @param options	    Options. If PJMEDIA_DELAY_BUF_SIMPLE_FIFO is
+ *                          specified, then a simple FIFO mechanism
+ *			    will be used instead of the adaptive
+ *                          implementation (which uses WSOLA to expand
+ *                          or shrink audio samples).
+ *			    See #pjmedia_delay_buf_flag for other options.
  * @param p_b		    Pointer to receive the delay buffer instance.
  *
Index: /pjproject/branches/1.x/pjmedia/include/pjmedia/echo.h
===================================================================
--- /pjproject/branches/1.x/pjmedia/include/pjmedia/echo.h	(revision 3566)
+++ /pjproject/branches/1.x/pjmedia/include/pjmedia/echo.h	(revision 3567)
@@ -89,5 +89,13 @@
      * canceller will not be called by different threads at the same time.
      */
-    PJMEDIA_ECHO_NO_LOCK = 16
+    PJMEDIA_ECHO_NO_LOCK = 16,
+
+    /**
+     * If PJMEDIA_ECHO_USE_SIMPLE_FIFO flag is specified, the delay buffer
+     * created for the echo canceller will use simple FIFO mechanism, i.e.
+     * without using WSOLA to expand and shrink audio samples.
+     */
+    PJMEDIA_ECHO_USE_SIMPLE_FIFO = 32
+
 
 } pjmedia_echo_flag;
Index: /pjproject/branches/1.x/pjmedia/src/pjmedia/delaybuf.c
===================================================================
--- /pjproject/branches/1.x/pjmedia/src/pjmedia/delaybuf.c	(revision 3566)
+++ /pjproject/branches/1.x/pjmedia/src/pjmedia/delaybuf.c	(revision 3567)
@@ -100,7 +100,4 @@
     PJ_ASSERT_RETURN(pool && samples_per_frame && clock_rate && channel_count &&
 		     p_b, PJ_EINVAL);
-    PJ_ASSERT_RETURN(options==0, PJ_EINVAL);
-
-    PJ_UNUSED_ARG(options);
 
     if (!name) {
@@ -127,9 +124,14 @@
 	return status;
 
-    /* Create WSOLA */
-    status = pjmedia_wsola_create(pool, clock_rate, samples_per_frame, 1,
-				  PJMEDIA_WSOLA_NO_FADING, &b->wsola);
-    if (status != PJ_SUCCESS)
-	return status;
+    if (!(options & PJMEDIA_DELAY_BUF_SIMPLE_FIFO)) {
+        /* Create WSOLA */
+        status = pjmedia_wsola_create(pool, clock_rate, samples_per_frame, 1,
+				      PJMEDIA_WSOLA_NO_FADING, &b->wsola);
+        if (status != PJ_SUCCESS)
+	    return status;
+        PJ_LOG(5, (b->obj_name, "Using delay buffer with WSOLA."));
+    } else {
+        PJ_LOG(5, (b->obj_name, "Using simple FIFO delay buffer."));
+    }
 
     /* Finally, create mutex */
@@ -148,5 +150,5 @@
 PJ_DEF(pj_status_t) pjmedia_delay_buf_destroy(pjmedia_delay_buf *b)
 {
-    pj_status_t status;
+    pj_status_t status = PJ_SUCCESS;
 
     PJ_ASSERT_RETURN(b, PJ_EINVAL);
@@ -154,7 +156,9 @@
     pj_lock_acquire(b->lock);
 
-    status = pjmedia_wsola_destroy(b->wsola);
-    if (status == PJ_SUCCESS)
-	b->wsola = NULL;
+    if (b->wsola) {
+        status = pjmedia_wsola_destroy(b->wsola);
+        if (status == PJ_SUCCESS)
+	    b->wsola = NULL;
+    }
 
     pj_lock_release(b->lock);
@@ -265,10 +269,12 @@
     pj_lock_acquire(b->lock);
 
-    update(b, OP_PUT);
+    if (b->wsola) {
+        update(b, OP_PUT);
     
-    status = pjmedia_wsola_save(b->wsola, frame, PJ_FALSE);
-    if (status != PJ_SUCCESS) {
-	pj_lock_release(b->lock);
-	return status;
+        status = pjmedia_wsola_save(b->wsola, frame, PJ_FALSE);
+        if (status != PJ_SUCCESS) {
+	    pj_lock_release(b->lock);
+	    return status;
+        }
     }
 
@@ -278,11 +284,13 @@
     {
 	unsigned erase_cnt;
-	
-	/* shrink one frame or just the diff? */
-	//erase_cnt = b->samples_per_frame;
-	erase_cnt = pjmedia_circ_buf_get_len(b->circ_buf) + 
-		    b->samples_per_frame - b->max_cnt;
-
-	shrink_buffer(b, erase_cnt);
+
+        if (b->wsola) {
+	    /* shrink one frame or just the diff? */
+	    //erase_cnt = b->samples_per_frame;
+	    erase_cnt = pjmedia_circ_buf_get_len(b->circ_buf) + 
+		        b->samples_per_frame - b->max_cnt;
+
+	    shrink_buffer(b, erase_cnt);
+        }
 
 	/* Check if shrinking failed or erased count is less than requested,
@@ -298,7 +306,7 @@
 	    pjmedia_circ_buf_adv_read_ptr(b->circ_buf, erase_cnt);
 
-	    PJ_LOG(4,(b->obj_name,"Shrinking failed or insufficient, dropping"
-		      " %d eldest samples, buf_cnt=%d", erase_cnt, 
-		      pjmedia_circ_buf_get_len(b->circ_buf)));
+	    PJ_LOG(4,(b->obj_name,"%sDropping %d eldest samples, buf_cnt=%d",
+                      (b->wsola? "Shrinking failed or insufficient. ": ""),
+                      erase_cnt, pjmedia_circ_buf_get_len(b->circ_buf)));
 	}
     }
@@ -313,5 +321,5 @@
 					   pj_int16_t frame[])
 {
-    pj_status_t status;
+    pj_status_t status = PJ_SUCCESS;
 
     PJ_ASSERT_RETURN(b && frame, PJ_EINVAL);
@@ -319,5 +327,6 @@
     pj_lock_acquire(b->lock);
 
-    update(b, OP_GET);
+    if (b->wsola)
+        update(b, OP_GET);
 
     /* Starvation checking */
@@ -327,22 +336,27 @@
 		  pjmedia_circ_buf_get_len(b->circ_buf)));
 
-	status = pjmedia_wsola_generate(b->wsola, frame);
-
-	if (status == PJ_SUCCESS) {
-	    TRACE__((b->obj_name,"Successfully generate 1 frame"));
-	    if (pjmedia_circ_buf_get_len(b->circ_buf) == 0) {
-		pj_lock_release(b->lock);
-		return PJ_SUCCESS;
-	    }
-
-	    /* Put generated frame into buffer */
-	    pjmedia_circ_buf_write(b->circ_buf, frame, b->samples_per_frame);
-
-	} else {
+        if (b->wsola) {
+            status = pjmedia_wsola_generate(b->wsola, frame);
+
+	    if (status == PJ_SUCCESS) {
+	        TRACE__((b->obj_name,"Successfully generate 1 frame"));
+	        if (pjmedia_circ_buf_get_len(b->circ_buf) == 0) {
+		    pj_lock_release(b->lock);
+		    return PJ_SUCCESS;
+	        }
+
+	        /* Put generated frame into buffer */
+	        pjmedia_circ_buf_write(b->circ_buf, frame,
+                                       b->samples_per_frame);
+            }
+        }
+
+	if (!b->wsola || status != PJ_SUCCESS) {
 	    unsigned buf_len = pjmedia_circ_buf_get_len(b->circ_buf);
 	    
 	    /* Give all what delay buffer has, then pad with zeroes */
-	    PJ_LOG(4,(b->obj_name,"Error generating frame, status=%d", 
-		      status));
+            if (b->wsola)
+	        PJ_LOG(4,(b->obj_name,"Error generating frame, status=%d", 
+		          status));
 
 	    pjmedia_circ_buf_read(b->circ_buf, frame, buf_len);
@@ -379,5 +393,6 @@
 
     /* Reset WSOLA */
-    pjmedia_wsola_reset(b->wsola, 0);
+    if (b->wsola)
+        pjmedia_wsola_reset(b->wsola, 0);
 
     pj_lock_release(b->lock);
Index: /pjproject/branches/1.x/pjmedia/src/pjmedia/echo_common.c
===================================================================
--- /pjproject/branches/1.x/pjmedia/src/pjmedia/echo_common.c	(revision 3566)
+++ /pjproject/branches/1.x/pjmedia/src/pjmedia/echo_common.c	(revision 3567)
@@ -145,4 +145,5 @@
 {
     unsigned ptime, lat_cnt;
+    unsigned delay_buf_opt = 0;
     pjmedia_echo_state *ec;
     pj_status_t status;
@@ -212,8 +213,10 @@
 
     /* Create delay buffer to compensate drifts */
+    if (options & PJMEDIA_ECHO_USE_SIMPLE_FIFO)
+        delay_buf_opt |= PJMEDIA_DELAY_BUF_SIMPLE_FIFO;
     status = pjmedia_delay_buf_create(ec->pool, ec->obj_name, clock_rate, 
 				      samples_per_frame, channel_count,
 				      (PJMEDIA_SOUND_BUFFER_COUNT+1) * ptime,
-				      0, &ec->delay_buf);
+				      delay_buf_opt, &ec->delay_buf);
     if (status != PJ_SUCCESS) {
 	pj_pool_release(pool);
