summaryrefslogtreecommitdiff
path: root/pjmedia
diff options
context:
space:
mode:
authorLiong Sauw Ming <ming@teluu.com>2011-05-15 12:54:28 +0000
committerLiong Sauw Ming <ming@teluu.com>2011-05-15 12:54:28 +0000
commit9d61f9ded11c24cef9c18962c65fda728e871568 (patch)
tree1313ee0a832c5830c956b8168e107610750d9417 /pjmedia
parent662b61f41a7da47a976ff29fd33ebfa860be05b7 (diff)
Fixed #1257: Option for using simple FIFO delay buffer in echo canceller.
git-svn-id: http://svn.pjsip.org/repos/pjproject/branches/1.x@3567 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia')
-rw-r--r--pjmedia/include/pjmedia/delaybuf.h20
-rw-r--r--pjmedia/include/pjmedia/echo.h10
-rw-r--r--pjmedia/src/pjmedia/delaybuf.c97
-rw-r--r--pjmedia/src/pjmedia/echo_common.c5
4 files changed, 88 insertions, 44 deletions
diff --git a/pjmedia/include/pjmedia/delaybuf.h b/pjmedia/include/pjmedia/delaybuf.h
index 9dcad5ee..09b01bbb 100644
--- a/pjmedia/include/pjmedia/delaybuf.h
+++ b/pjmedia/include/pjmedia/delaybuf.h
@@ -64,6 +64,19 @@ PJ_BEGIN_DECL
typedef struct pjmedia_delay_buf pjmedia_delay_buf;
/**
+ * 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
* in this case it will directly enter the running state.
@@ -79,7 +92,12 @@ typedef struct pjmedia_delay_buf pjmedia_delay_buf;
* in ms, if this value is negative or less than
* 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.
*
* @return PJ_SUCCESS if the delay buffer has been
diff --git a/pjmedia/include/pjmedia/echo.h b/pjmedia/include/pjmedia/echo.h
index f2c2210c..ba7f8897 100644
--- a/pjmedia/include/pjmedia/echo.h
+++ b/pjmedia/include/pjmedia/echo.h
@@ -88,7 +88,15 @@ typedef enum pjmedia_echo_flag
* for the echo canceller, but application will guarantee that echo
* 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;
diff --git a/pjmedia/src/pjmedia/delaybuf.c b/pjmedia/src/pjmedia/delaybuf.c
index 39f0e618..82618275 100644
--- a/pjmedia/src/pjmedia/delaybuf.c
+++ b/pjmedia/src/pjmedia/delaybuf.c
@@ -99,9 +99,6 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_create( pj_pool_t *pool,
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) {
name = "delaybuf";
@@ -126,11 +123,16 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_create( pj_pool_t *pool,
if (status != PJ_SUCCESS)
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 */
status = pj_lock_create_recursive_mutex(pool, b->obj_name,
@@ -147,15 +149,17 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_create( pj_pool_t *pool,
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);
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);
@@ -264,12 +268,14 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_put(pjmedia_delay_buf *b,
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;
+ }
}
/* Overflow checking */
@@ -277,13 +283,15 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_put(pjmedia_delay_buf *b,
b->max_cnt)
{
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,
* delaybuf needs to drop eldest samples, this is bad since the voice
@@ -297,9 +305,9 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_put(pjmedia_delay_buf *b,
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)));
}
}
@@ -312,13 +320,14 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_put(pjmedia_delay_buf *b,
PJ_DEF(pj_status_t) pjmedia_delay_buf_get( pjmedia_delay_buf *b,
pj_int16_t frame[])
{
- pj_status_t status;
+ pj_status_t status = PJ_SUCCESS;
PJ_ASSERT_RETURN(b && frame, PJ_EINVAL);
pj_lock_acquire(b->lock);
- update(b, OP_GET);
+ if (b->wsola)
+ update(b, OP_GET);
/* Starvation checking */
if (pjmedia_circ_buf_get_len(b->circ_buf) < b->samples_per_frame) {
@@ -326,24 +335,29 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_get( pjmedia_delay_buf *b,
PJ_LOG(4,(b->obj_name,"Underflow, buf_cnt=%d, will generate 1 frame",
pjmedia_circ_buf_get_len(b->circ_buf)));
- status = pjmedia_wsola_generate(b->wsola, frame);
+ 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;
- }
+ 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);
+ /* Put generated frame into buffer */
+ pjmedia_circ_buf_write(b->circ_buf, frame,
+ b->samples_per_frame);
+ }
+ }
- } else {
+ 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);
pjmedia_zero_samples(&frame[buf_len],
@@ -378,7 +392,8 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_reset(pjmedia_delay_buf *b)
pjmedia_circ_buf_reset(b->circ_buf);
/* Reset WSOLA */
- pjmedia_wsola_reset(b->wsola, 0);
+ if (b->wsola)
+ pjmedia_wsola_reset(b->wsola, 0);
pj_lock_release(b->lock);
diff --git a/pjmedia/src/pjmedia/echo_common.c b/pjmedia/src/pjmedia/echo_common.c
index 1cb2e311..532c37be 100644
--- a/pjmedia/src/pjmedia/echo_common.c
+++ b/pjmedia/src/pjmedia/echo_common.c
@@ -144,6 +144,7 @@ PJ_DEF(pj_status_t) pjmedia_echo_create2(pj_pool_t *pool,
pjmedia_echo_state **p_echo )
{
unsigned ptime, lat_cnt;
+ unsigned delay_buf_opt = 0;
pjmedia_echo_state *ec;
pj_status_t status;
@@ -211,10 +212,12 @@ PJ_DEF(pj_status_t) pjmedia_echo_create2(pj_pool_t *pool,
}
/* 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);
return status;