diff options
author | qwell <qwell@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-04-24 18:54:06 +0000 |
---|---|---|
committer | qwell <qwell@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-04-24 18:54:06 +0000 |
commit | a461c286fb7d9aae69594f2d89b4f0a853ef57e2 (patch) | |
tree | b95b8b903b93ebbc18eb805c8907038546eec2fc /zaptel.c | |
parent | dada4a9ae08e61724182a524fd4bb25b6188181d (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.c | 126 |
1 files changed, 125 insertions, 1 deletions
@@ -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) { |