summaryrefslogtreecommitdiff
path: root/zaptel-base.c
diff options
context:
space:
mode:
authorqwell <qwell@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-04-24 18:33:29 +0000
committerqwell <qwell@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-04-24 18:33:29 +0000
commit4db3ee4f7f9377f7c6543c5cb21fc277f0355c6e (patch)
treed898734bc3fb9a410b697d1faed035bce1b87fb7 /zaptel-base.c
parentd3f23546541b61feab4e9a671757b468537c6b9f (diff)
Backport pre-echocan debugging for ztmonitor
git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.2@2434 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'zaptel-base.c')
-rw-r--r--zaptel-base.c126
1 files changed, 125 insertions, 1 deletions
diff --git a/zaptel-base.c b/zaptel-base.c
index 8e0ac01..d45a87d 100644
--- a/zaptel-base.c
+++ b/zaptel-base.c
@@ -415,6 +415,8 @@ static struct zt_zone *tone_zones[ZT_TONE_ZONE_MAX];
#include "kb1ec.h"
#elif defined(ECHO_CAN_MG2)
#include "mg2ec.h"
+#elif defined(ECHO_CAN_JP1)
+#include "jpah.h"
#else
#include "mec3.h"
#endif
@@ -970,6 +972,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
@@ -982,6 +985,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;
@@ -1042,6 +1047,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) {
@@ -1653,6 +1659,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 */
@@ -3803,7 +3812,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 {
@@ -3856,6 +3868,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)))
@@ -4863,6 +4885,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,
@@ -5522,7 +5589,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)
@@ -5757,6 +5833,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) {