diff options
author | Shaun Ruffell <sruffell@digium.com> | 2010-08-17 11:53:18 +0000 |
---|---|---|
committer | Shaun Ruffell <sruffell@digium.com> | 2010-08-17 11:53:18 +0000 |
commit | fe514454e37522c96392d5d6c65e83f1257e5662 (patch) | |
tree | 7bd03ea3b5a9d5f820f1b284b91aebb819de5ca3 /drivers/dahdi/voicebus | |
parent | 3f5401d777a967f003c9edadb8686932065e884d (diff) |
wcte12xp, wctdm24xxp: Add compile time option CONFIG_VOICEBUS_ECREFERENCE.
Add compile time option to improve the reference signal provided to
software echo cancelers. The intent here is for this functionality to
become the default behavior but more testing and work on the edge cases
is needed. It's being brought in now as a compile time option since there
have been reports that it helps in some environments.
Instead of using two buffers, which means that at best we're two
milliseconds behind, use a circular buffer where audio data is written
on the transmit side and read on the receive path. In this way high
latency values will not interfere with the operation of software
echo cancelers. DAHDI-291. DAHDI-387.
This work was originally on:
http://svn.asterisk.org/svn/dahdi/linux/team/sruffell/improved_ecreference@9143
and includes a generic kfifo replacement by Matt Fredrickson.
git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9144 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi/voicebus')
-rw-r--r-- | drivers/dahdi/voicebus/voicebus.c | 105 | ||||
-rw-r--r-- | drivers/dahdi/voicebus/voicebus.h | 15 |
2 files changed, 120 insertions, 0 deletions
diff --git a/drivers/dahdi/voicebus/voicebus.c b/drivers/dahdi/voicebus/voicebus.c index 9bc7386..351ccc9 100644 --- a/drivers/dahdi/voicebus/voicebus.c +++ b/drivers/dahdi/voicebus/voicebus.c @@ -94,6 +94,111 @@ #define OWN_BIT (1 << 31) +#ifdef CONFIG_VOICEBUS_ECREFERENCE + +/* + * These dahdi_fifo_xxx functions are currently only used by the voicebus + * drivers, but are named more generally to facilitate moving out in the + * future. They probably also could stand to be changed in order to use a + * kfifo implementation from the kernel if one is available. + * + */ + +struct dahdi_fifo { + size_t total_size; + u32 start; + u32 end; + u8 data[0]; +}; + +static unsigned int dahdi_fifo_used_space(struct dahdi_fifo *fifo) +{ + return (fifo->end >= fifo->start) ? fifo->end - fifo->start : + fifo->total_size - fifo->start + fifo->end; +} + +unsigned int __dahdi_fifo_put(struct dahdi_fifo *fifo, u8 *data, size_t size) +{ + int newinsertposition; + int cpy_one_len, cpy_two_len; + + if ((size + dahdi_fifo_used_space(fifo)) > (fifo->total_size - 1)) + return -1; + + if ((fifo->end + size) >= fifo->total_size) { + cpy_one_len = fifo->total_size - fifo->end; + cpy_two_len = fifo->end + size - fifo->total_size; + newinsertposition = cpy_two_len; + } else { + cpy_one_len = size; + cpy_two_len = 0; + newinsertposition = fifo->end + size; + } + + memcpy(&fifo->data[fifo->end], data, cpy_one_len); + + if (cpy_two_len) + memcpy(&fifo->data[0], &data[cpy_one_len], cpy_two_len); + + fifo->end = newinsertposition; + + return size; +} +EXPORT_SYMBOL(__dahdi_fifo_put); + +unsigned int __dahdi_fifo_get(struct dahdi_fifo *fifo, u8 *data, size_t size) +{ + int newbegin; + int cpy_one_len, cpy_two_len; + + if (size > dahdi_fifo_used_space(fifo)) + return 0; + + if ((fifo->start + size) >= fifo->total_size) { + cpy_one_len = fifo->total_size - fifo->start; + cpy_two_len = fifo->start + size - fifo->total_size; + newbegin = cpy_two_len; + } else { + cpy_one_len = size; + cpy_two_len = 0; + newbegin = fifo->start + size; + } + + memcpy(&data[0], &fifo->data[fifo->start], cpy_one_len); + + if (cpy_two_len) + memcpy(&data[cpy_one_len], &fifo->data[0], cpy_two_len); + + fifo->start = newbegin; + + return size; +} +EXPORT_SYMBOL(__dahdi_fifo_get); + +void dahdi_fifo_free(struct dahdi_fifo *fifo) +{ + kfree(fifo); +} +EXPORT_SYMBOL(dahdi_fifo_free); + +struct dahdi_fifo *dahdi_fifo_alloc(u32 maxsize, gfp_t alloc_flags) +{ + struct dahdi_fifo *fifo; + + fifo = kmalloc(maxsize + sizeof(*fifo) + 1, alloc_flags); + + if (!fifo) + return NULL; + + fifo->start = fifo->end = 0; + fifo->total_size = maxsize + 1; + + return fifo; +} +EXPORT_SYMBOL(dahdi_fifo_alloc); +#endif /* CONFIG_VOICEBUS_ECREFERENCE */ + + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) kmem_cache_t *voicebus_vbb_cache; #else diff --git a/drivers/dahdi/voicebus/voicebus.h b/drivers/dahdi/voicebus/voicebus.h index 6c67f15..53714f6 100644 --- a/drivers/dahdi/voicebus/voicebus.h +++ b/drivers/dahdi/voicebus/voicebus.h @@ -62,6 +62,21 @@ * (and not tasklet). */ #define CONFIG_VOICEBUS_INTERRUPT +/* Define this to use a FIFO for the software echocan reference. + * (experimental) */ +#undef CONFIG_VOICEBUS_ECREFERENCE + +#ifdef CONFIG_VOICEBUS_ECREFERENCE + +struct dahdi_fifo; +unsigned int __dahdi_fifo_put(struct dahdi_fifo *fifo, u8 *data, size_t size); +unsigned int __dahdi_fifo_get(struct dahdi_fifo *fifo, u8 *data, size_t size); +void dahdi_fifo_free(struct dahdi_fifo *fifo); +struct dahdi_fifo *dahdi_fifo_alloc(size_t maxsize, gfp_t alloc_flags); + +#endif + + struct voicebus; struct vbb { |