From 4db3ee4f7f9377f7c6543c5cb21fc277f0355c6e Mon Sep 17 00:00:00 2001 From: qwell Date: Tue, 24 Apr 2007 18:33:29 +0000 Subject: Backport pre-echocan debugging for ztmonitor git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.2@2434 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- zaptel-base.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 1 deletion(-) (limited to 'zaptel-base.c') 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;xflags & 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;xflags & 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) { -- cgit v1.2.3