Index: /pjproject/trunk/pjlib/include/pj/os.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/os.h	(revision 227)
+++ /pjproject/trunk/pjlib/include/pj/os.h	(revision 228)
@@ -891,28 +891,4 @@
  */
 #if defined(PJ_HAS_HIGH_RES_TIMER) && PJ_HAS_HIGH_RES_TIMER != 0
-
-/**
- * This structure represents high resolution (64bit) time value. The time
- * values represent time in cycles, which is retrieved by calling
- * #pj_get_timestamp().
- */
-typedef union pj_timestamp
-{
-    struct
-    {
-#if defined(PJ_IS_LITTLE_ENDIAN) && PJ_IS_LITTLE_ENDIAN!=0
-	pj_uint32_t lo;     /**< Low 32-bit value of the 64-bit value. */
-	pj_uint32_t hi;     /**< high 32-bit value of the 64-bit value. */
-#else
-	pj_uint32_t hi;     /**< high 32-bit value of the 64-bit value. */
-	pj_uint32_t lo;     /**< Low 32-bit value of the 64-bit value. */
-#endif
-    } u32;                  /**< The 64-bit value as two 32-bit values. */
-
-#if PJ_HAS_INT64
-    pj_uint64_t u64;        /**< The whole 64-bit value, where available. */
-#endif
-} pj_timestamp;
-
 
 /**
Index: /pjproject/trunk/pjlib/include/pj/types.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/types.h	(revision 227)
+++ /pjproject/trunk/pjlib/include/pj/types.h	(revision 228)
@@ -121,4 +121,28 @@
 };
 
+/**
+ * This structure represents high resolution (64bit) time value. The time
+ * values represent time in cycles, which is retrieved by calling
+ * #pj_get_timestamp().
+ */
+typedef union pj_timestamp
+{
+    struct
+    {
+#if defined(PJ_IS_LITTLE_ENDIAN) && PJ_IS_LITTLE_ENDIAN!=0
+	pj_uint32_t lo;     /**< Low 32-bit value of the 64-bit value. */
+	pj_uint32_t hi;     /**< high 32-bit value of the 64-bit value. */
+#else
+	pj_uint32_t hi;     /**< high 32-bit value of the 64-bit value. */
+	pj_uint32_t lo;     /**< Low 32-bit value of the 64-bit value. */
+#endif
+    } u32;                  /**< The 64-bit value as two 32-bit values. */
+
+#if PJ_HAS_INT64
+    pj_uint64_t u64;        /**< The whole 64-bit value, where available. */
+#endif
+} pj_timestamp;
+
+
 
 /**
Index: /pjproject/trunk/pjmedia/build/pjmedia.dsp
===================================================================
--- /pjproject/trunk/pjmedia/build/pjmedia.dsp	(revision 227)
+++ /pjproject/trunk/pjmedia/build/pjmedia.dsp	(revision 228)
@@ -162,9 +162,9 @@
 # Begin Source File
 
+SOURCE=..\src\pjmedia\silencedet.c
+# End Source File
+# Begin Source File
+
 SOURCE=..\src\pjmedia\stream.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\pjmedia\vad.c
 # End Source File
 # End Group
@@ -238,4 +238,8 @@
 # Begin Source File
 
+SOURCE=..\include\pjmedia\silencedet.h
+# End Source File
+# Begin Source File
+
 SOURCE=..\include\pjmedia\sound.h
 # End Source File
@@ -247,8 +251,4 @@
 
 SOURCE=..\include\pjmedia\types.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\include\pjmedia\vad.h
 # End Source File
 # Begin Source File
Index: /pjproject/trunk/pjmedia/include/pjmedia/jbuf.h
===================================================================
--- /pjproject/trunk/pjmedia/include/pjmedia/jbuf.h	(revision 227)
+++ /pjproject/trunk/pjmedia/include/pjmedia/jbuf.h	(revision 228)
@@ -16,4 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+/*
+ * Based on implementation kindly contributed by Switchlab, Ltd.
  */
 #ifndef __PJMEDIA_JBUF_H__
Index: /pjproject/trunk/pjmedia/include/pjmedia/silencedet.h
===================================================================
--- /pjproject/trunk/pjmedia/include/pjmedia/silencedet.h	(revision 228)
+++ /pjproject/trunk/pjmedia/include/pjmedia/silencedet.h	(revision 228)
@@ -0,0 +1,120 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#ifndef __PJMEDIA_SILENCE_DET_H__
+#define __PJMEDIA_SILENCE_DET_H__
+
+
+/**
+ * @file silencedet.h
+ * @brief Adaptive silence detector.
+ */
+#include <pjmedia/types.h>
+
+PJ_BEGIN_DECL
+
+
+/**
+ * Opaque declaration for silence detector.
+ */
+typedef struct pjmedia_silence_det pjmedia_silence_det;
+
+
+/**
+ * Create voice activity detector with default settings. The default settings
+ * are to perform adaptive silence detection, which adjusts the noise level
+ * dynamically based on current input level.
+ *
+ * @param pool		Pool for allocating the structure.
+ * @param p_sd		Pointer to receive the silence detector instance.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_silence_det_create( pj_pool_t *pool,
+						 pjmedia_silence_det **p_sd );
+
+
+/**
+ * Set the sd to operate in adaptive mode.
+ *
+ * @param sd	        The silence detector
+ * @param frame_size	Number of samples per frame.
+ *
+ * @return	        PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_silence_det_set_adaptive( pjmedia_silence_det *sd,
+						       unsigned frame_size);
+
+
+/**
+ * Set the sd to operate in fixed threshold mode.
+ *
+ * @param sd		    The silence detector
+ * @param frame_size Number of samplse per frame.
+ * @param threshold	    The silence threshold.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_silence_det_set_fixed( pjmedia_silence_det *sd,
+						    unsigned frame_size,
+						    unsigned threshold );
+
+/**
+ * Disable the silence detector.
+ *
+ * @param sd		The silence detector
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_silence_det_disable( pjmedia_silence_det *sd );
+
+
+/**
+ * Calculate average signal level for the given samples.
+ *
+ * @param samples	Pointer to 16-bit PCM samples.
+ * @param count		Number of samples in the input.
+ *
+ * @return		The average signal level, which simply is total level
+ *			divided by number of samples.
+ */
+PJ_DECL(pj_int32_t) pjmedia_silence_det_calc_avg_signal( const pj_int16_t samples[],
+							 pj_size_t count );
+
+
+/**
+ * Perform voice activity detection on the given input samples.
+ *
+ * @param sd		The silence detector instance.
+ * @param samples	Pointer to 16-bit PCM input samples.
+ * @param count		Number of samples in the input.
+ * @param p_level	Optional pointer to receive average signal level
+ *			of the input samples.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_bool_t) pjmedia_silence_det_detect_silence( pjmedia_silence_det *sd,
+						       const pj_int16_t samples[],
+						       pj_size_t count,
+						       pj_int32_t *p_level);
+
+
+PJ_END_DECL
+
+#endif	/* __PJMEDIA_SILENCE_DET_H__ */
+
Index: project/trunk/pjmedia/include/pjmedia/vad.h
===================================================================
--- /pjproject/trunk/pjmedia/include/pjmedia/vad.h	(revision 227)
+++ 	(revision )
@@ -1,120 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
- */
-#ifndef __PJMEDIA_VAD_H__
-#define __PJMEDIA_VAD_H__
-
-
-/**
- * @file vad.h
- * @brief Simple, adaptive silence detector.
- */
-#include <pjmedia/types.h>
-
-PJ_BEGIN_DECL
-
-
-/**
- * @see pjmedia_vad
- */
-typedef struct pjmedia_vad  pjmedia_vad;
-
-
-/**
- * Create voice activity detector with default settings. The default settings
- * are to perform adaptive silence detection, which adjusts the noise level
- * dynamically based on current input level.
- *
- * @param pool		Pool for allocating the structure.
- * @param p_vad		Pointer to receive the VAD instance.
- *
- * @return		PJ_SUCCESS on success.
- */
-PJ_DECL(pj_status_t) pjmedia_vad_create( pj_pool_t *pool,
-					 pjmedia_vad **p_vad );
-
-
-/**
- * Set the vad to operate in adaptive mode.
- *
- * @param vad		    The vad
- * @param frame_size Number of samplse per frame.
- *
- * @return		    PJ_SUCCESS on success.
- */
-PJ_DECL(pj_status_t) pjmedia_vad_set_adaptive( pjmedia_vad *vad,
-					       unsigned frame_size);
-
-
-/**
- * Set the vad to operate in fixed threshold mode.
- *
- * @param vad		    The vad
- * @param frame_size Number of samplse per frame.
- * @param threshold	    The silence threshold.
- *
- * @return		    PJ_SUCCESS on success.
- */
-PJ_DECL(pj_status_t) pjmedia_vad_set_fixed( pjmedia_vad *vad,
-					    unsigned frame_size,
-					    unsigned threshold );
-
-/**
- * Disable the vad.
- *
- * @param vad		The vad
- *
- * @return		PJ_SUCCESS on success.
- */
-PJ_DECL(pj_status_t) pjmedia_vad_disable( pjmedia_vad *vad );
-
-
-/**
- * Calculate average signal level for the given samples.
- *
- * @param samples	Pointer to 16-bit PCM samples.
- * @param count		Number of samples in the input.
- *
- * @return		The average signal level, which simply is total level
- *			divided by number of samples.
- */
-PJ_DECL(pj_int32_t) pjmedia_vad_calc_avg_signal( const pj_int16_t samples[],
-						 pj_size_t count );
-
-
-/**
- * Perform voice activity detection on the given input samples.
- *
- * @param vad		The VAD instance.
- * @param samples	Pointer to 16-bit PCM input samples.
- * @param count		Number of samples in the input.
- * @param p_level	Optional pointer to receive average signal level
- *			of the input samples.
- *
- * @return		PJ_SUCCESS on success.
- */
-PJ_DECL(pj_bool_t) pjmedia_vad_detect_silence( pjmedia_vad *vad,
-					       const pj_int16_t samples[],
-					       pj_size_t count,
-					       pj_int32_t *p_level);
-
-
-PJ_END_DECL
-
-#endif	/* __PJMEDIA_VAD_H__ */
-
Index: /pjproject/trunk/pjmedia/src/pjmedia/conference.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/conference.c	(revision 227)
+++ /pjproject/trunk/pjmedia/src/pjmedia/conference.c	(revision 228)
@@ -18,5 +18,5 @@
  */
 #include <pjmedia/conference.h>
-#include <pjmedia/vad.h>
+#include <pjmedia/silencedet.h>
 #include <pjmedia/stream.h>
 #include <pjmedia/sound.h>
@@ -56,5 +56,5 @@
     int			 listener_cnt;	/**< Number of listeners.	    */
     pj_bool_t		*listeners;	/**< Array of listeners.	    */
-    pjmedia_vad		*vad;		/**< VAD for this port.		    */
+    pjmedia_silence_det	*vad;		/**< VAD for this port.		    */
 
     /* Tx buffer contains the frame to be "transmitted" to this port
@@ -140,9 +140,9 @@
 
     /* Create and init vad. */
-    status = pjmedia_vad_create( pool, &conf_port->vad);
+    status = pjmedia_silence_det_create( pool, &conf_port->vad);
     if (status != PJ_SUCCESS)
 	return status;
 
-    pjmedia_vad_set_adaptive(conf_port->vad, conf->samples_per_frame);
+    pjmedia_silence_det_set_adaptive(conf_port->vad, conf->samples_per_frame);
 
 
@@ -739,8 +739,8 @@
 
 	/* Do we have signal? */
-	silence = pjmedia_vad_detect_silence(conf_port->vad,
-					     output, 
-					     conf->samples_per_frame,
-					     &level);
+	silence = pjmedia_silence_det_detect_silence(conf_port->vad,
+						     output, 
+						     conf->samples_per_frame,
+						     &level);
 
 	/* Skip if we don't have signal. */
@@ -790,5 +790,5 @@
 	    frame.buf = NULL;
 	    frame.size = 0;
-	    
+
 	    if (conf_port->port)
 		pjmedia_port_put_frame(conf_port->port, &frame);
Index: /pjproject/trunk/pjmedia/src/pjmedia/jbuf.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/jbuf.c	(revision 227)
+++ /pjproject/trunk/pjmedia/src/pjmedia/jbuf.c	(revision 228)
@@ -17,4 +17,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
  */
+/*
+ * Based on implementation kindly contributed by Switchlab, Ltd.
+ */
 #include <pjmedia/jbuf.h>
 #include <pjmedia/errno.h>
Index: /pjproject/trunk/pjmedia/src/pjmedia/silencedet.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/silencedet.c	(revision 228)
+++ /pjproject/trunk/pjmedia/src/pjmedia/silencedet.c	(revision 228)
@@ -0,0 +1,269 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pjmedia/silencedet.h>
+#include <pjmedia/errno.h>
+#include <pj/assert.h>
+#include <pj/log.h>
+#include <pj/pool.h>
+
+
+#define THIS_FILE   "silencedet.c"
+
+typedef enum pjmedia_silence_det_mode {
+    VAD_MODE_NONE,
+    VAD_MODE_FIXED,
+    VAD_MODE_ADAPTIVE
+} pjmedia_silence_det_mode;
+
+
+/**
+ * This structure holds the silence detector state.
+ */
+struct pjmedia_silence_det
+{
+    int	      mode;		/**< VAD mode.				    */
+    unsigned  frame_size;	/**< Samples per frame.			    */
+
+
+    unsigned  min_signal_cnt;	/**< # of signal frames.before talk burst   */
+    unsigned  min_silence_cnt;	/**< # of silence frames before silence.    */
+    unsigned  recalc_cnt;	/**< # of frames before adaptive recalc.    */
+
+    pj_bool_t in_talk;		/**< In talk burst?			    */
+    unsigned  cur_cnt;		/**< # of frames in current mode.	    */
+    unsigned  signal_cnt;	/**< # of signal frames received.	    */
+    unsigned  silence_cnt;	/**< # of silence frames received	    */
+    unsigned  cur_threshold;	/**< Current silence threshold.		    */
+    unsigned  weakest_signal;	/**< Weakest signal detected.		    */
+    unsigned  loudest_silence;	/**< Loudest silence detected.		    */
+};
+
+
+
+unsigned char linear2ulaw(int pcm_val);
+
+
+PJ_DEF(pj_status_t) pjmedia_silence_det_create( pj_pool_t *pool,
+						pjmedia_silence_det **p_sd)
+{
+    pjmedia_silence_det *sd;
+
+    PJ_ASSERT_RETURN(pool && p_sd, PJ_EINVAL);
+
+    sd = pj_pool_zalloc(pool, sizeof(struct pjmedia_silence_det));
+
+    sd->weakest_signal = 0xFFFFFFFFUL;
+    sd->loudest_silence = 0;
+    sd->signal_cnt = 0;
+    sd->silence_cnt = 0;
+    
+    /* Restart in adaptive, silent mode */
+    sd->in_talk = PJ_FALSE;
+    pjmedia_silence_det_set_adaptive( sd, 160 );
+
+    *p_sd = sd;
+    return PJ_SUCCESS;
+}
+
+PJ_DEF(pj_status_t) pjmedia_silence_det_set_adaptive( pjmedia_silence_det *sd,
+						      unsigned frame_size)
+{
+    PJ_ASSERT_RETURN(sd && frame_size, PJ_EINVAL);
+
+    sd->frame_size = frame_size;
+    sd->mode = VAD_MODE_ADAPTIVE;
+    sd->min_signal_cnt = 10;
+    sd->min_silence_cnt = 64;
+    sd->recalc_cnt = 250;
+    sd->cur_threshold = 20;
+
+    return PJ_SUCCESS;
+}
+
+PJ_DEF(pj_status_t) pjmedia_silence_det_set_fixed( pjmedia_silence_det *sd,
+						   unsigned frame_size,
+						   unsigned threshold )
+{
+    PJ_ASSERT_RETURN(sd && frame_size, PJ_EINVAL);
+
+    sd->mode = VAD_MODE_FIXED;
+    sd->frame_size = frame_size;
+    sd->cur_threshold = threshold;
+
+    return PJ_SUCCESS;
+}
+
+PJ_DEF(pj_status_t) pjmedia_silence_det_disable( pjmedia_silence_det *sd )
+{
+    PJ_ASSERT_RETURN(sd, PJ_EINVAL);
+
+    sd->mode = VAD_MODE_NONE;
+
+    return PJ_SUCCESS;
+}
+
+
+PJ_DEF(pj_int32_t) pjmedia_silence_det_calc_avg_signal(const pj_int16_t samples[],
+						       pj_size_t count)
+{
+    pj_uint32_t sum = 0;
+    
+    const pj_int16_t * pcm = samples;
+    const pj_int16_t * end = samples + count;
+
+    if (count==0)
+	return 0;
+
+    while (pcm != end) {
+	if (*pcm < 0)
+	    sum -= *pcm++;
+	else
+	    sum += *pcm++;
+    }
+    
+    return (pj_int32_t)(sum / count);
+}
+
+PJ_DEF(pj_bool_t) pjmedia_silence_det_detect_silence( pjmedia_silence_det *sd,
+						      const pj_int16_t samples[],
+						      pj_size_t count,
+						      pj_int32_t *p_level)
+{
+    pj_uint32_t level;
+    pj_bool_t have_signal;
+
+    /* Always return false if VAD is disabled */
+    if (sd->mode == VAD_MODE_NONE) {
+	if (p_level)
+	    *p_level = -1;
+	return PJ_FALSE;
+    }
+    
+    /* Calculate average signal level. */
+    level = pjmedia_silence_det_calc_avg_signal(samples, count);
+    
+    /* Report to caller, if required. */
+    if (p_level)
+	*p_level = level;
+
+    /* Convert PCM level to ulaw */
+    level = linear2ulaw(level) ^ 0xff;
+    
+    /* Do we have signal? */
+    have_signal = level > sd->cur_threshold;
+    
+    /* We we're in transition between silence and signel, increment the 
+     * current frame counter. We will only switch mode when we have enough
+     * frames.
+     */
+    if (sd->in_talk != have_signal) {
+	unsigned limit;
+
+	sd->cur_cnt++;
+
+	limit = (sd->in_talk ? sd->min_silence_cnt : 
+				sd->min_signal_cnt);
+
+	if (sd->cur_cnt > limit) {
+
+	    /* Swap mode */
+	    sd->in_talk = !sd->in_talk;
+	    
+	    /* Restart adaptive cur_threshold measurements */
+	    sd->weakest_signal = 0xFFFFFFFFUL;
+	    sd->loudest_silence = 0;
+	    sd->signal_cnt = 0;
+	    sd->silence_cnt = 0;
+	}
+
+    } else {
+	/* Reset frame count */
+	sd->cur_cnt = 0;
+    }
+    
+    /* For fixed threshold sd, everything is done. */
+    if (sd->mode == VAD_MODE_FIXED) {
+	return !sd->in_talk;
+    }
+    
+
+    /* Count the number of silent and signal frames and calculate min/max */
+    if (have_signal) {
+	if (level < sd->weakest_signal)
+	    sd->weakest_signal = level;
+	sd->signal_cnt++;
+    }
+    else {
+	if (level > sd->loudest_silence)
+	    sd->loudest_silence = level;
+	sd->silence_cnt++;
+    }
+
+    /* See if we have had enough frames to look at proportions of 
+     * silence/signal frames.
+     */
+    if ((sd->signal_cnt + sd->silence_cnt) > sd->recalc_cnt) {
+	
+	/* Adjust silence threshold by looking at the proportions of
+	 * signal and silence frames.
+	 */
+	if (sd->signal_cnt >= sd->recalc_cnt) {
+	    /* All frames where signal frames.
+	     * Increase silence threshold.
+	     */
+	    sd->cur_threshold += (sd->weakest_signal - sd->cur_threshold)/4;
+	    PJ_LOG(6,(THIS_FILE, "Vad cur_threshold increased to %d",
+		      sd->cur_threshold));
+	}
+	else if (sd->silence_cnt >= sd->recalc_cnt) {
+	    /* All frames where silence frames.
+	     * Decrease silence threshold.
+	     */
+	    sd->cur_threshold = (sd->cur_threshold+sd->loudest_silence)/2+1;
+	    PJ_LOG(6,(THIS_FILE, "Vad cur_threshold decreased to %d",
+		      sd->cur_threshold));
+	}
+	else { 
+	    pj_bool_t updated = PJ_TRUE;
+
+	    /* Adjust according to signal/silence proportions. */
+	    if (sd->signal_cnt > sd->silence_cnt * 2)
+		sd->cur_threshold++;
+	    else if (sd->silence_cnt >  sd->signal_cnt* 2)
+		sd->cur_threshold--;
+	    else
+		updated = PJ_FALSE;
+
+	    if (updated) {
+		PJ_LOG(6,(THIS_FILE,
+			  "Vad cur_threshold updated to %d",
+			  sd->cur_threshold));
+	    }
+	}
+
+	/* Reset. */
+	sd->weakest_signal = 0xFFFFFFFFUL;
+	sd->loudest_silence = 0;
+	sd->signal_cnt = 0;
+	sd->silence_cnt = 0;
+    }
+    
+    return !sd->in_talk;
+}
+
Index: /pjproject/trunk/pjmedia/src/pjmedia/stream.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 227)
+++ /pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 228)
@@ -117,4 +117,10 @@
 
 
+/* RFC 2833 digit */
+static const char digitmap[16] = { '0', '1', '2', '3', 
+				   '4', '5', '6', '7', 
+				   '8', '9', '*', '#',
+				   'A', 'B', 'C', 'D'};
+
 /*
  * Print error.
@@ -231,5 +237,14 @@
 	stream->tx_dtmf_buf[0].start_ts = cur_ts;
 	pj_mutex_unlock(stream->jb_mutex);
-    }
+
+	if (stream->tx_dtmf_count)
+	    PJ_LOG(5,(THIS_FILE,"Sending DTMF digit id %c", 
+		      digitmap[stream->tx_dtmf_buf[0].event]));
+
+    } else if (duration == 0) {
+	PJ_LOG(5,(THIS_FILE,"Sending DTMF digit id %c", 
+		  digitmap[digit->event]));
+    }
+
 
     frame_out->size = 4;
@@ -368,8 +383,4 @@
 				  const void *payload, unsigned payloadlen)
 {
-    static const char digitmap[16] = { '0', '1', '2', '3', 
-				       '4', '5', '6', '7', 
-				       '8', '9', '*', '#',
-				       'A', 'B', 'C', 'D'};
     const pjmedia_rtp_dtmf_event *event = payload;
 
Index: project/trunk/pjmedia/src/pjmedia/vad.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/vad.c	(revision 227)
+++ 	(revision )
@@ -1,269 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
- */
-#include <pjmedia/vad.h>
-#include <pjmedia/errno.h>
-#include <pj/assert.h>
-#include <pj/log.h>
-#include <pj/pool.h>
-
-
-#define THIS_FILE   "vad.c"
-
-typedef enum pjmedia_vad_mode {
-    VAD_MODE_NONE,
-    VAD_MODE_FIXED,
-    VAD_MODE_ADAPTIVE
-} pjmedia_vad_mode;
-
-
-/**
- * This structure holds the vad state.
- */
-struct pjmedia_vad
-{
-    int	      mode;		/**< VAD mode.				    */
-    unsigned  frame_size;	/**< Samples per frame.			    */
-
-
-    unsigned  min_signal_cnt;	/**< # of signal frames.before talk burst   */
-    unsigned  min_silence_cnt;	/**< # of silence frames before silence.    */
-    unsigned  recalc_cnt;	/**< # of frames before adaptive recalc.    */
-
-    pj_bool_t in_talk;		/**< In talk burst?			    */
-    unsigned  cur_cnt;		/**< # of frames in current mode.	    */
-    unsigned  signal_cnt;	/**< # of signal frames received.	    */
-    unsigned  silence_cnt;	/**< # of silence frames received	    */
-    unsigned  cur_threshold;	/**< Current silence threshold.		    */
-    unsigned  weakest_signal;	/**< Weakest signal detected.		    */
-    unsigned  loudest_silence;	/**< Loudest silence detected.		    */
-};
-
-
-
-unsigned char linear2ulaw(int pcm_val);
-
-
-PJ_DEF(pj_status_t) pjmedia_vad_create( pj_pool_t *pool,
-					pjmedia_vad **p_vad)
-{
-    pjmedia_vad *vad;
-
-    PJ_ASSERT_RETURN(pool && p_vad, PJ_EINVAL);
-
-    vad = pj_pool_zalloc(pool, sizeof(struct pjmedia_vad));
-
-    vad->weakest_signal = 0xFFFFFFFFUL;
-    vad->loudest_silence = 0;
-    vad->signal_cnt = 0;
-    vad->silence_cnt = 0;
-    
-    /* Restart in adaptive, silent mode */
-    vad->in_talk = PJ_FALSE;
-    pjmedia_vad_set_adaptive( vad, 160 );
-
-    *p_vad = vad;
-    return PJ_SUCCESS;
-}
-
-PJ_DEF(pj_status_t) pjmedia_vad_set_adaptive( pjmedia_vad *vad,
-					      unsigned frame_size)
-{
-    PJ_ASSERT_RETURN(vad && frame_size, PJ_EINVAL);
-
-    vad->frame_size = frame_size;
-    vad->mode = VAD_MODE_ADAPTIVE;
-    vad->min_signal_cnt = 10;
-    vad->min_silence_cnt = 64;
-    vad->recalc_cnt = 250;
-    vad->cur_threshold = 20;
-
-    return PJ_SUCCESS;
-}
-
-PJ_DEF(pj_status_t) pjmedia_vad_set_fixed( pjmedia_vad *vad,
-					   unsigned frame_size,
-					   unsigned threshold )
-{
-    PJ_ASSERT_RETURN(vad && frame_size, PJ_EINVAL);
-
-    vad->mode = VAD_MODE_FIXED;
-    vad->frame_size = frame_size;
-    vad->cur_threshold = threshold;
-
-    return PJ_SUCCESS;
-}
-
-PJ_DEF(pj_status_t) pjmedia_vad_disable( pjmedia_vad *vad )
-{
-    PJ_ASSERT_RETURN(vad, PJ_EINVAL);
-
-    vad->mode = VAD_MODE_NONE;
-
-    return PJ_SUCCESS;
-}
-
-
-PJ_DEF(pj_int32_t) pjmedia_vad_calc_avg_signal(const pj_int16_t samples[],
-					       pj_size_t count)
-{
-    pj_uint32_t sum = 0;
-    
-    const pj_int16_t * pcm = samples;
-    const pj_int16_t * end = samples + count;
-
-    if (count==0)
-	return 0;
-
-    while (pcm != end) {
-	if (*pcm < 0)
-	    sum -= *pcm++;
-	else
-	    sum += *pcm++;
-    }
-    
-    return (pj_int32_t)(sum / count);
-}
-
-PJ_DEF(pj_bool_t) pjmedia_vad_detect_silence( pjmedia_vad *vad,
-					      const pj_int16_t samples[],
-					      pj_size_t count,
-					      pj_int32_t *p_level)
-{
-    pj_uint32_t level;
-    pj_bool_t have_signal;
-
-    /* Always return false if VAD is disabled */
-    if (vad->mode == VAD_MODE_NONE) {
-	if (p_level)
-	    *p_level = -1;
-	return PJ_FALSE;
-    }
-    
-    /* Calculate average signal level. */
-    level = pjmedia_vad_calc_avg_signal(samples, count);
-    
-    /* Report to caller, if required. */
-    if (p_level)
-	*p_level = level;
-
-    /* Convert PCM level to ulaw */
-    level = linear2ulaw(level) ^ 0xff;
-    
-    /* Do we have signal? */
-    have_signal = level > vad->cur_threshold;
-    
-    /* We we're in transition between silence and signel, increment the 
-     * current frame counter. We will only switch mode when we have enough
-     * frames.
-     */
-    if (vad->in_talk != have_signal) {
-	unsigned limit;
-
-	vad->cur_cnt++;
-
-	limit = (vad->in_talk ? vad->min_silence_cnt : 
-				vad->min_signal_cnt);
-
-	if (vad->cur_cnt > limit) {
-
-	    /* Swap mode */
-	    vad->in_talk = !vad->in_talk;
-	    
-	    /* Restart adaptive cur_threshold measurements */
-	    vad->weakest_signal = 0xFFFFFFFFUL;
-	    vad->loudest_silence = 0;
-	    vad->signal_cnt = 0;
-	    vad->silence_cnt = 0;
-	}
-
-    } else {
-	/* Reset frame count */
-	vad->cur_cnt = 0;
-    }
-    
-    /* For fixed threshold vad, everything is done. */
-    if (vad->mode == VAD_MODE_FIXED) {
-	return !vad->in_talk;
-    }
-    
-
-    /* Count the number of silent and signal frames and calculate min/max */
-    if (have_signal) {
-	if (level < vad->weakest_signal)
-	    vad->weakest_signal = level;
-	vad->signal_cnt++;
-    }
-    else {
-	if (level > vad->loudest_silence)
-	    vad->loudest_silence = level;
-	vad->silence_cnt++;
-    }
-
-    /* See if we have had enough frames to look at proportions of 
-     * silence/signal frames.
-     */
-    if ((vad->signal_cnt + vad->silence_cnt) > vad->recalc_cnt) {
-	
-	/* Adjust silence threshold by looking at the proportions of
-	 * signal and silence frames.
-	 */
-	if (vad->signal_cnt >= vad->recalc_cnt) {
-	    /* All frames where signal frames.
-	     * Increase silence threshold.
-	     */
-	    vad->cur_threshold += (vad->weakest_signal - vad->cur_threshold)/4;
-	    PJ_LOG(6,(THIS_FILE, "Vad cur_threshold increased to %d",
-		      vad->cur_threshold));
-	}
-	else if (vad->silence_cnt >= vad->recalc_cnt) {
-	    /* All frames where silence frames.
-	     * Decrease silence threshold.
-	     */
-	    vad->cur_threshold = (vad->cur_threshold+vad->loudest_silence)/2+1;
-	    PJ_LOG(6,(THIS_FILE, "Vad cur_threshold decreased to %d",
-		      vad->cur_threshold));
-	}
-	else { 
-	    pj_bool_t updated = PJ_TRUE;
-
-	    /* Adjust according to signal/silence proportions. */
-	    if (vad->signal_cnt > vad->silence_cnt * 2)
-		vad->cur_threshold++;
-	    else if (vad->silence_cnt >  vad->signal_cnt* 2)
-		vad->cur_threshold--;
-	    else
-		updated = PJ_FALSE;
-
-	    if (updated) {
-		PJ_LOG(6,(THIS_FILE,
-			  "Vad cur_threshold updated to %d",
-			  vad->cur_threshold));
-	    }
-	}
-
-	/* Reset. */
-	vad->weakest_signal = 0xFFFFFFFFUL;
-	vad->loudest_silence = 0;
-	vad->signal_cnt = 0;
-	vad->silence_cnt = 0;
-    }
-    
-    return !vad->in_talk;
-}
-
Index: /pjproject/trunk/pjsip/include/pjsip-simple/evsub.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsip-simple/evsub.h	(revision 227)
+++ /pjproject/trunk/pjsip/include/pjsip-simple/evsub.h	(revision 228)
@@ -174,7 +174,7 @@
      * the subscription.
      *
-     * This callback is OPTIONAL. When it is not implemented, the default 
-     * behavior is to refresh subscription by sending SUBSCRIBE with the
-     * interval set to current/last interval.
+     * This callback is OPTIONAL when PJSIP package such as presence or 
+     * refer is used; the event package will refresh subscription by sending
+     * SUBSCRIBE with the interval set to current/last interval.
      *
      * @param sub	The subscription instance.
@@ -186,6 +186,7 @@
      * refresh after the specified subscription interval.
      *
-     * This callback is OPTIONAL. When it is not implemented, the default
-     * behavior is to send NOTIFY to terminate the subscription.
+     * This callback is OPTIONAL when PJSIP package such as presence or 
+     * refer is used; the event package send NOTIFY to terminate the 
+     * subscription.
      */
     void (*on_server_timeout)(pjsip_evsub *sub);
@@ -400,5 +401,6 @@
 
 /**
- * Get the event subscription instance in the transaction.
+ * Get the event subscription instance associated with the specified 
+ * transaction.
  *
  * @param tsx		The transaction.
