summaryrefslogtreecommitdiff
path: root/zaptel.c
diff options
context:
space:
mode:
authorqwell <qwell@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-04-24 18:54:06 +0000
committerqwell <qwell@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-04-24 18:54:06 +0000
commita461c286fb7d9aae69594f2d89b4f0a853ef57e2 (patch)
treeb95b8b903b93ebbc18eb805c8907038546eec2fc /zaptel.c
parentdada4a9ae08e61724182a524fd4bb25b6188181d (diff)
merge (manually) ztmonitor pre-echocan debugging
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@2436 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'zaptel.c')
-rw-r--r--zaptel.c126
1 files changed, 125 insertions, 1 deletions
diff --git a/zaptel.c b/zaptel.c
index d47bcb0..63d31de 100644
--- a/zaptel.c
+++ b/zaptel.c
@@ -115,6 +115,8 @@
#elif defined(ECHO_CAN_MG2)
#define ZAPTEL_ECHO_CANCELLER "MG2"
#include "mg2ec.h"
+#elif defined(ECHO_CAN_JP1)
+#include "jpah.h"
#else
#define ZAPTEL_ECHO_CANCELLER "MARK3"
#include "mec3.h"
@@ -991,6 +993,7 @@ static void close_channel(struct zt_chan *chan)
void *rxgain = NULL;
struct echo_can_state *ec = NULL;
int oldconf;
+ short *readchunkpreec;
#ifdef CONFIG_ZAPATA_PPP
struct ppp_channel *ppp;
#endif
@@ -1005,6 +1008,8 @@ static void close_channel(struct zt_chan *chan)
#endif
ec = chan->ec;
chan->ec = NULL;
+ readchunkpreec = chan->readchunkpreec;
+ chan->readchunkpreec = NULL;
chan->curtone = NULL;
chan->curzone = NULL;
chan->cadencepos = 0;
@@ -1065,6 +1070,7 @@ static void close_channel(struct zt_chan *chan)
kfree(rxgain);
if (ec)
echo_can_free(ec);
+ kfree(readchunkpreec);
#ifdef CONFIG_ZAPATA_PPP
if (ppp) {
@@ -1722,6 +1728,9 @@ static void zt_chan_unreg(struct zt_chan *chan)
((chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR ||
(chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORTX ||
(chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORBOTH ||
+ (chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR_RX_PREECHO ||
+ (chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR_TX_PREECHO ||
+ (chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORBOTH_PREECHO ||
(chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_DIGITALMON)) {
/* Take them out of conference with us */
/* release conference resource if any */
@@ -3927,7 +3936,10 @@ static int zt_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsign
if (!(chans[i]->flags & ZT_FLAG_AUDIO)) return (-EINVAL);
if ((stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR ||
(stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORTX ||
- (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORBOTH) {
+ (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORBOTH ||
+ (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR_RX_PREECHO ||
+ (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR_TX_PREECHO ||
+ (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORBOTH_PREECHO) {
/* Monitor mode -- it's a channel */
if ((stack.conf.confno < 0) || (stack.conf.confno >= ZT_MAX_CHANNELS) || !chans[stack.conf.confno]) return(-EINVAL);
} else {
@@ -3980,6 +3992,16 @@ static int zt_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsign
/* Get alias */
chans[i]->_confn = zt_get_conf_alias(stack.conf.confno);
}
+
+ if ((stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR_RX_PREECHO ||
+ (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR_TX_PREECHO ||
+ (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORBOTH_PREECHO)
+ chans[stack.conf.confno]->readchunkpreec = kmalloc(sizeof(*chans[stack.conf.confno]->readchunkpreec) * ZT_CHUNKSIZE, GFP_KERNEL);
+ else {
+ kfree(chans[stack.conf.confno]->readchunkpreec);
+ chans[stack.conf.confno]->readchunkpreec = NULL;
+ }
+
spin_unlock_irqrestore(&chan->lock, flags);
spin_unlock_irqrestore(&bigzaplock, flagso);
if (copy_to_user((struct zt_confinfo *) data,&stack.conf,sizeof(stack.conf)))
@@ -5000,6 +5022,51 @@ static inline void __zt_process_getaudio_chunk(struct zt_chan *ss, unsigned char
for (x=0;x<ZT_CHUNKSIZE;x++)
txb[x] = ZT_LIN2X(getlin[x], ms);
break;
+ case ZT_CONF_MONITOR_RX_PREECHO: /* Monitor a channel's rx mode */
+ /* if a pseudo-channel, ignore */
+ if (ms->flags & ZT_FLAG_PSEUDO)
+ break;
+
+ if (!chans[ms->confna]->readchunkpreec)
+ break;
+
+ /* Add monitored channel */
+ ACSS(getlin, chans[ms->confna]->flags & ZT_FLAG_PSEUDO ?
+ chans[ms->confna]->readchunkpreec : chans[ms->confna]->putlin);
+ for (x = 0; x < ZT_CHUNKSIZE; x++)
+ txb[x] = ZT_LIN2X(getlin[x], ms);
+
+ break;
+ case ZT_CONF_MONITOR_TX_PREECHO: /* Monitor a channel's tx mode */
+ /* if a pseudo-channel, ignore */
+ if (ms->flags & ZT_FLAG_PSEUDO)
+ break;
+
+ if (!chans[ms->confna]->readchunkpreec)
+ break;
+
+ /* Add monitored channel */
+ ACSS(getlin, chans[ms->confna]->flags & ZT_FLAG_PSEUDO ?
+ chans[ms->confna]->putlin : chans[ms->confna]->readchunkpreec);
+ for (x = 0; x < ZT_CHUNKSIZE; x++)
+ txb[x] = ZT_LIN2X(getlin[x], ms);
+
+ break;
+ case ZT_CONF_MONITORBOTH_PREECHO: /* monitor a channel's rx and tx mode */
+ /* if a pseudo-channel, ignore */
+ if (ms->flags & ZT_FLAG_PSEUDO)
+ break;
+
+ if (!chans[ms->confna]->readchunkpreec)
+ break;
+
+ ACSS(getlin, chans[ms->confna]->putlin);
+ ACSS(getlin, chans[ms->confna]->readchunkpreec);
+
+ for (x = 0; x < ZT_CHUNKSIZE; x++)
+ txb[x] = ZT_LIN2X(getlin[x], ms);
+
+ break;
case ZT_CONF_REALANDPSEUDO:
/* This strange mode takes the transmit buffer and
puts it on the conference, minus its last sample,
@@ -5688,7 +5755,16 @@ static inline void __zt_ec_chunk(struct zt_chan *ss, unsigned char *rxchunk, con
short rxlin, txlin;
int x;
unsigned long flags;
+
spin_lock_irqsave(&ss->lock, flags);
+
+ if (ss->readchunkpreec) {
+ /* Save a copy of the audio before the echo can has its way with it */
+ for (x = 0; x < ZT_CHUNKSIZE; x++)
+ /* We only ever really need to deal with signed linear - let's just convert it now */
+ ss->readchunkpreec[x] = ZT_XLAW(rxchunk[x], ss);
+ }
+
/* Perform echo cancellation on a chunk if necessary */
if (ss->ec) {
#if defined(CONFIG_ZAPTEL_MMX) || defined(ECHO_CAN_FP)
@@ -5912,6 +5988,54 @@ static inline void __zt_process_putaudio_chunk(struct zt_chan *ss, unsigned char
for(x=0;x<ZT_CHUNKSIZE;x++)
rxb[x] = ZT_LIN2X(putlin[x], ms);
break;
+ case ZT_CONF_MONITOR_RX_PREECHO: /* Monitor a channel's rx mode */
+ /* if not a pseudo-channel, ignore */
+ if (!(ms->flags & ZT_FLAG_PSEUDO))
+ break;
+
+ if (!chans[ms->confna]->readchunkpreec)
+ break;
+
+ /* Add monitored channel */
+ ACSS(putlin, chans[ms->confna]->flags & ZT_FLAG_PSEUDO ?
+ chans[ms->confna]->getlin : chans[ms->confna]->readchunkpreec);
+ for (x = 0; x < ZT_CHUNKSIZE; x++)
+ rxb[x] = ZT_LIN2X(putlin[x], ms);
+
+ break;
+ case ZT_CONF_MONITOR_TX_PREECHO: /* Monitor a channel's tx mode */
+ /* if not a pseudo-channel, ignore */
+ if (!(ms->flags & ZT_FLAG_PSEUDO))
+ break;
+
+ if (!chans[ms->confna]->readchunkpreec)
+ break;
+
+ /* Add monitored channel */
+ ACSS(putlin, chans[ms->confna]->flags & ZT_FLAG_PSEUDO ?
+ chans[ms->confna]->readchunkpreec : chans[ms->confna]->getlin);
+ for (x = 0; x < ZT_CHUNKSIZE; x++)
+ rxb[x] = ZT_LIN2X(putlin[x], ms);
+
+ break;
+ case ZT_CONF_MONITORBOTH_PREECHO: /* Monitor a channel's tx and rx mode */
+ /* if not a pseudo-channel, ignore */
+ if (!(ms->flags & ZT_FLAG_PSEUDO))
+ break;
+
+ if (!chans[ms->confna]->readchunkpreec)
+ break;
+
+ /* Note: Technically, saturation should be done at
+ the end of the whole addition, but for performance
+ reasons, we don't do that. Besides, it only matters
+ when you're so loud you're clipping anyway */
+ ACSS(putlin, chans[ms->confna]->getlin);
+ ACSS(putlin, chans[ms->confna]->readchunkpreec);
+ for (x = 0; x < ZT_CHUNKSIZE; x++)
+ rxb[x] = ZT_LIN2X(putlin[x], ms);
+
+ break;
case ZT_CONF_REALANDPSEUDO:
/* do normal conf mode processing */
if (ms->confmode & ZT_CONF_TALKER) {