[asterisk-dev] [RFC] Modularising echo cancellers

Nic Bellamy nic.bellamy at vadacom.co.nz
Tue Jun 27 20:40:02 MST 2006


Hi all,
    I've developed a patch to Zaptel that modularises the software echo 
cancelers, allowing multiple ones to be loaded simultaneously.

In conjunction with this, I've developed a patch to Asterisk's chan_zap 
that allows setting which echo canceler to use on a per-channel basis 
(an "echocanceltype" parameter).

We have found this invaluable for evaluating different software 
cancelers in varying situations, and we're using in production at a 
number of sites on both E1 PRI and TDM400 analogue lines. It has allowed 
me to do fun things like modularising the MG2 changes from trunk, 
loading the module on a production system, and starting the use the new 
canceler after just issuing a "reload".

The patch is currently for Zaptel 1.2.x, and I'm looking for comments as 
to whether there's sufficient interest in it for me to forward-port it 
to trunk, and submit it for inclusion.

The basic API looks like this:

/* Register an echo canceler with Zaptel */
int zt_register_echocan(struct zt_echo_can *ec);
/* Unregister an echo canceler */
int zt_unregister_echocan(struct zt_echo_can *ec);
/* Find the canceler structure called "name". Handles locking and module 
use counts. */
struct zt_echo_can *zt_echo_can_get(char *name);
/* Return an instance of an echo canceler back to Zaptel, handling 
locking and module use counts */
void zt_echo_can_put(struct zt_echo_can *ec);

struct zt_echo_can {
        /* Module-visible bits */
        char name[ZT_ECHO_CAN_NAMELEN];
        struct module *owner;
        zt_echo_can_state_t *(*create)(int taps);
        void (*free)(zt_echo_can_state_t *ec);
        short (*update)(zt_echo_can_state_t *ec, short tx, short rx);
        /* update_block: run the echo canceler over a block of data.
         *
         * It must deal with the possibility of rx == out.
         */
        void (*update_block)(zt_echo_can_state_t *ec,
                        short *tx, short *rx, short *out, size_t len);
        int (*traintap)(zt_echo_can_state_t *ec, int pos, short val);

        /* Bits for Zaptel only */
        struct list_head list;
};

The userspace-kernelspace interface required changes to allow sending a 
canceler name, rather than just on/off requests, so I added a new IOCTL 
interface:

#define ZT_ECHO_CAN_NAMELEN     (16)
typedef struct zt_echocancelv2
{
        char name[ZT_ECHO_CAN_NAMELEN];
        int taps;
} ZT_ECHOCANCELV2_DATA;

/* Enable or disable echo cancellation on a channel (new version)
 * The number is zero to disable echo cancellation and non-zero
 * to enable echo cancellation.  If the number is between 32
 * and 256, it will also set the number of taps in the echo canceler
 */
#define ZT_ECHOCANCELV2         _IOW (ZT_CODE, 93, struct zt_echocancelv2)

The patch to chan_zap tries the V2 interface, then falls back to the 
original if it doesn't work - on the assumption that in general, the 
wrong canceler is better than no canceler.

One of the things I'd like to do going forward is to add a way of 
sending options from userspace up to the canceler to add runtime control 
of things like nonlinear processing, suppression, comfort noise 
generation, convergence speed, etc. (admittedly, most cancelers don't 
even have these knobs - yet). At this point it's only possible to 
specify the tail length.

Your thoughts?

If anyone wants to try out the full patch, send me an email offlist - 
I'll have to separate it out from my other fiddling, which I haven't 
done as yet. Oh, and it's only tested on Linux 2.6.x; I doubt it'll even 
compile on 2.4 without changes.

Regards,
    Nic.

-- 
Nic Bellamy - <nic.bellamy at vadacom.co.nz>
Head Of Engineering, Vadacom Ltd - http://www.vadacom.co.nz/
Ph. +64-9-974-2790 - DDI +64-9-974-2639 - Mob. +64-21-251-8954




More information about the asterisk-dev mailing list