[dahdi-commits] kpfleming: branch linux/kpfleming/modular_ec r4397 - /linux/team/kpfleming/mo...
SVN commits to the DAHDI project
dahdi-commits at lists.digium.com
Wed Jun 18 17:05:53 CDT 2008
Author: kpfleming
Date: Wed Jun 18 17:05:53 2008
New Revision: 4397
URL: http://svn.digium.com/view/dahdi?view=rev&rev=4397
Log:
convert rest of echo cans to modules, bring single-use header files into the modules that use them, and disable calling echo can functions for now until the code is ready to test
Added:
linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi_echocan_kb1.c
- copied, changed from r4392, linux/team/kpfleming/modular_ec/drivers/dahdi/kb1ec.h
linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi_echocan_mg2.c
- copied, changed from r4392, linux/team/kpfleming/modular_ec/drivers/dahdi/mg2ec.h
linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi_echocan_sec2.c
- copied, changed from r4392, linux/team/kpfleming/modular_ec/drivers/dahdi/sec-2.h
Removed:
linux/team/kpfleming/modular_ec/drivers/dahdi/kb1ec.h
linux/team/kpfleming/modular_ec/drivers/dahdi/kb1ec_const.h
linux/team/kpfleming/modular_ec/drivers/dahdi/mg2ec.h
linux/team/kpfleming/modular_ec/drivers/dahdi/mg2ec_const.h
linux/team/kpfleming/modular_ec/drivers/dahdi/sec-2.h
Modified:
linux/team/kpfleming/modular_ec/drivers/dahdi/Kbuild
linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi-base.c
linux/team/kpfleming/modular_ec/drivers/dahdi/fir.h
Modified: linux/team/kpfleming/modular_ec/drivers/dahdi/Kbuild
URL: http://svn.digium.com/view/dahdi/linux/team/kpfleming/modular_ec/drivers/dahdi/Kbuild?view=diff&rev=4397&r1=4396&r2=4397
==============================================================================
--- linux/team/kpfleming/modular_ec/drivers/dahdi/Kbuild (original)
+++ linux/team/kpfleming/modular_ec/drivers/dahdi/Kbuild Wed Jun 18 17:05:53 2008
@@ -26,6 +26,9 @@
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_JPAH) += dahdi_echocan_jpah.o
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_STEVE) += dahdi_echocan_sec.o
+obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_STEVE2) += dahdi_echocan_sec2.o
+obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_KB1) += dahdi_echocan_kb1.o
+obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_MG2) += dahdi_echocan_mg2.o
CFLAGS_MODULE += -I$(src)
EXTRA_CFLAGS += $(ECHO_CAN_CFLAGS)
Modified: linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi-base.c
URL: http://svn.digium.com/view/dahdi/linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi-base.c?view=diff&rev=4397&r1=4396&r2=4397
==============================================================================
--- linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi-base.c (original)
+++ linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi-base.c Wed Jun 18 17:05:53 2008
@@ -333,22 +333,7 @@
static struct dahdi_zone *tone_zones[DAHDI_TONE_ZONE_MAX];
-#define NUM_SIGS 10
-
-/* Echo cancellation */
-#if defined(ECHO_CAN_HPEC)
-#include "hpec/hpec_dahdi.h"
-#elif defined(ECHO_CAN_STEVE)
-#include "sec.h"
-#elif defined(ECHO_CAN_STEVE2)
-#include "sec-2.h"
-#elif defined(ECHO_CAN_KB1)
-#include "kb1ec.h"
-#elif defined(ECHO_CAN_MG2)
-#include "mg2ec.h"
-#elif defined(ECHO_CAN_JP1)
-#include "jpah.h"
-#endif
+#define NUM_SIGS 10
#ifdef DEFINE_RWLOCK
static DEFINE_RWLOCK(echocan_list_lock);
@@ -1078,8 +1063,8 @@
if (rxgain)
kfree(rxgain);
- if (ec)
- echo_can_free(ec);
+// if (ec)
+// echo_can_free(ec);
if (readchunkpreec)
kfree(readchunkpreec);
@@ -2282,8 +2267,8 @@
if (rxgain)
kfree(rxgain);
- if (ec)
- echo_can_free(ec);
+// if (ec)
+// echo_can_free(ec);
return 0;
}
@@ -4514,8 +4499,8 @@
chan->echotimer = 0;
spin_unlock_irqrestore(&chan->lock, flags);
hw_echocancel_off(chan);
- if (tec)
- echo_can_free(tec);
+// if (tec)
+// echo_can_free(tec);
return 0;
}
@@ -4543,8 +4528,8 @@
chan->ec = NULL;
spin_unlock_irqrestore(&chan->lock, flags);
- if (tec)
- echo_can_free(tec);
+// if (tec)
+// echo_can_free(tec);
ret = -ENODEV;
@@ -4570,8 +4555,8 @@
ecp->tap_length = deftaps;
}
- if ((ret = echo_can_create(ecp, params, &ec)))
- goto exit_with_free;
+// if ((ret = echo_can_create(ecp, params, &ec)))
+// goto exit_with_free;
spin_lock_irqsave(&chan->lock, flags);
chan->echocancel = ecp->tap_length;
@@ -4668,8 +4653,8 @@
if (rxgain)
kfree(rxgain);
- if (ec)
- echo_can_free(ec);
+// if (ec)
+// echo_can_free(ec);
if (oldconf) dahdi_check_conf(oldconf);
}
break;
@@ -4718,8 +4703,8 @@
chan->flags |= (DAHDI_FLAG_PPP | DAHDI_FLAG_HDLC | DAHDI_FLAG_FCS);
hw_echocancel_off(chan);
- if (tec)
- echo_can_free(tec);
+// if (tec)
+// echo_can_free(tec);
} else
return -ENOMEM;
}
@@ -5321,7 +5306,7 @@
ms->echostate = ECHO_STATE_IDLE;
ms->echolastupdate = 0;
ms->echotimer = 0;
- echo_can_free(ms->ec);
+// echo_can_free(ms->ec);
ms->ec = NULL;
__qevent(ss, DAHDI_EVENT_EC_DISABLED);
break;
@@ -6147,33 +6132,25 @@
ss->echostate = ECHO_STATE_TRAINING;
}
if (ss->echostate == ECHO_STATE_TRAINING) {
- if (echo_can_traintap(ss->ec, ss->echolastupdate++, rxlin)) {
+// if (echo_can_traintap(ss->ec, ss->echolastupdate++, rxlin)) {
#if 0
- printk("Finished training (%d taps trained)!\n", ss->echolastupdate);
+// printk("Finished training (%d taps trained)!\n", ss->echolastupdate);
#endif
- ss->echostate = ECHO_STATE_ACTIVE;
- }
+// ss->echostate = ECHO_STATE_ACTIVE;
+// }
}
rxlin = 0;
rxchunk[x] = DAHDI_LIN2X((int)rxlin, ss);
}
} else {
-#if !defined(DAHDI_EC_ARRAY_UPDATE)
- for (x=0;x<DAHDI_CHUNKSIZE;x++) {
- rxlin = DAHDI_XLAW(rxchunk[x], ss);
- rxlin = echo_can_update(ss->ec, DAHDI_XLAW(txchunk[x], ss), rxlin);
- rxchunk[x] = DAHDI_LIN2X((int) rxlin, ss);
- }
-#else /* defined(DAHDI_EC_ARRAY_UPDATE) */
short rxlins[DAHDI_CHUNKSIZE], txlins[DAHDI_CHUNKSIZE];
for (x = 0; x < DAHDI_CHUNKSIZE; x++) {
rxlins[x] = DAHDI_XLAW(rxchunk[x], ss);
txlins[x] = DAHDI_XLAW(txchunk[x], ss);
}
- echo_can_array_update(ss->ec, rxlins, txlins);
+// echo_can_array_update(ss->ec, rxlins, txlins);
for (x = 0; x < DAHDI_CHUNKSIZE; x++)
rxchunk[x] = DAHDI_LIN2X((int) rxlins[x], ss);
-#endif /* defined(DAHDI_EC_ARRAY_UPDATE) */
}
#if defined(CONFIG_DAHDI_MMX) || defined(ECHO_CAN_FP)
kernel_fpu_end();
@@ -6275,7 +6252,7 @@
ms->echostate = ECHO_STATE_IDLE;
ms->echolastupdate = 0;
ms->echotimer = 0;
- echo_can_free(ms->ec);
+// echo_can_free(ms->ec);
ms->ec = NULL;
break;
}
@@ -7570,8 +7547,6 @@
#ifdef CONFIG_DAHDI_WATCHDOG
watchdog_cleanup();
#endif
-
- echo_can_shutdown();
}
module_init(dahdi_init);
Copied: linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi_echocan_kb1.c (from r4392, linux/team/kpfleming/modular_ec/drivers/dahdi/kb1ec.h)
URL: http://svn.digium.com/view/dahdi/linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi_echocan_kb1.c?view=diff&rev=4397&p1=linux/team/kpfleming/modular_ec/drivers/dahdi/kb1ec.h&r1=4392&p2=linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi_echocan_kb1.c&r2=4397
==============================================================================
--- linux/team/kpfleming/modular_ec/drivers/dahdi/kb1ec.h (original)
+++ linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi_echocan_kb1.c Wed Jun 18 17:05:53 2008
@@ -3,7 +3,7 @@
*
* by Kris Boutilier
*
- * Based upon mech2.h
+ * Based upon mec2.h
*
* Copyright (C) 2002, Digium, Inc.
*
@@ -23,15 +23,20 @@
*
*/
-#ifndef _MARK2_ECHO_H
-#define _MARK2_ECHO_H
-
#include <linux/kernel.h>
#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/init.h>
#include <linux/ctype.h>
-
-#define MALLOC(a) kmalloc((a), GFP_KERNEL)
-#define FREE(a) kfree(a)
+#include <linux/moduleparam.h>
+
+#include <dahdi/kernel.h>
+
+static int debug;
+
+#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
+#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
/* Uncomment to provide summary statistics for overall echo can performance every 4000 samples */
/* #define MEC2_STATS 4000 */
@@ -42,8 +47,71 @@
/* Get optimized routines for math */
#include "arith.h"
-/* Bring in definitions for the various constants and thresholds */
-#include "kb1ec_const.h"
+/*
+ Important constants for tuning kb1 echo can
+ */
+
+/* Convergence (aka. adaptation) speed -- higher means slower */
+#define DEFAULT_BETA1_I 2048
+
+/* Constants for various power computations */
+#define DEFAULT_SIGMA_LY_I 7
+#define DEFAULT_SIGMA_LU_I 7
+#define DEFAULT_ALPHA_ST_I 5 /* near-end speech detection sensitivity factor */
+#define DEFAULT_ALPHA_YT_I 5
+
+#define DEFAULT_CUTOFF_I 128
+
+/* Define the near-end speech hangover counter: if near-end speech
+ * is declared, hcntr is set equal to hangt (see pg. 432)
+ */
+#define DEFAULT_HANGT 600 /* in samples, so 600 samples = 75ms */
+
+/* define the residual error suppression threshold */
+#define DEFAULT_SUPPR_I 16 /* 16 = -24db */
+
+/* This is the minimum reference signal power estimate level
+ * that will result in filter adaptation.
+ * If this is too low then background noise will cause the filter
+ * coefficients to constantly be updated.
+ */
+#define MIN_UPDATE_THRESH_I 4096
+
+/* The number of samples used to update coefficients using the
+ * the block update method (M). It should be related back to the
+ * length of the echo can.
+ * ie. it only updates coefficients when (sample number MOD default_m) = 0
+ *
+ * Getting this wrong may cause an oops. Consider yourself warned!
+ */
+#define DEFAULT_M 16 /* every 16th sample */
+
+/* If AGGRESSIVE supression is enabled, then we start cancelling residual
+ * echos again even while there is potentially the very end of a near-side
+ * signal present.
+ * This defines how many samples of DEFAULT_HANGT can remain before we
+ * kick back in
+ */
+#define AGGRESSIVE_HCNTR 160 /* in samples, so 160 samples = 20ms */
+
+
+/***************************************************************/
+/* The following knobs are not implemented in the current code */
+
+/* we need a dynamic level of suppression varying with the ratio of the
+ power of the echo to the power of the reference signal this is
+ done so that we have a smoother background.
+ we have a higher suppression when the power ratio is closer to
+ suppr_ceil and reduces logarithmically as we approach suppr_floor.
+ */
+#define SUPPR_FLOOR -64
+#define SUPPR_CEIL -24
+
+/* in a second departure, we calculate the residual error suppression
+ * as a percentage of the reference signal energy level. The threshold
+ * is defined in terms of dB below the reference signal.
+ */
+#define RES_SUPR_FACTOR -20
#ifndef NULL
#define NULL 0
@@ -133,20 +201,6 @@
unsigned int aggressive:1;
};
-static void echo_can_init(void)
-{
- printk("DAHDI Echo Canceller: KB1\n");
-}
-
-static void echo_can_identify(char *buf, size_t len)
-{
- dahdi_copy_string(buf, "KB1", len);
-}
-
-static void echo_can_shutdown(void)
-{
-}
-
static inline void init_cb_s(echo_can_cb_s *cb, int len, void *where)
{
cb->buf_d = (short *)where;
@@ -238,14 +292,13 @@
}
-static inline void echo_can_free(struct echo_can_state *ec)
-{
- FREE(ec);
-}
-
-static inline short echo_can_update(struct echo_can_state *ec, short iref, short isig)
-{
-
+static void echo_can_free(struct echo_can_state *ec)
+{
+ kfree(ec);
+}
+
+static inline short sample_update(struct echo_can_state *ec, short iref, short isig)
+{
/* Declare local variables that are used more than once */
/* ... */
int k;
@@ -521,6 +574,17 @@
return u;
}
+static void echo_can_update(struct echo_can_state *ec, short *iref, short *isig)
+{
+ unsigned int x;
+ short result;
+
+ for (x = 0; x < DAHDI_CHUNKSIZE; x++) {
+ result = sample_update(ec, *iref, *isig);
+ *isig++ = result;
+ }
+}
+
static int echo_can_create(struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p,
struct echo_can_state **ec)
{
@@ -548,7 +612,7 @@
2 * sizeof(short) * (maxu) + /* u_s */
2 * sizeof(short) * ecp->tap_length; /* y_tilde_s */
- if (!(*ec = MALLOC(size)))
+ if (!(*ec = kmalloc(size, GFP_KERNEL)))
return -ENOMEM;
memset(*ec, 0, size);
@@ -575,7 +639,7 @@
return 0;
}
-static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val)
+static int echo_can_traintap(struct echo_can_state *ec, int pos, short val)
{
/* Set the hangover counter to the length of the can to
* avoid adjustments occuring immediately after initial forced training
@@ -594,4 +658,37 @@
return 0;
}
-#endif
+static const struct dahdi_echocan me = {
+ .name = "KB1",
+ .echo_can_create = echo_can_create,
+ .echo_can_free = echo_can_free,
+ .echo_can_array_update = echo_can_update,
+ .echo_can_traintap = echo_can_traintap,
+};
+
+static int __init mod_init(void)
+{
+ if (dahdi_register_echocan(&me, THIS_MODULE)) {
+ module_printk(KERN_ERR, "could not register with DAHDI core\n");
+
+ return -EPERM;
+ }
+
+ module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", me.name);
+
+ return 0;
+}
+
+static void __exit mod_exit(void)
+{
+ dahdi_unregister_echocan(&me);
+}
+
+module_param(debug, int, S_IRUGO | S_IWUSR);
+
+MODULE_DESCRIPTION("DAHDI 'KB1' Echo Canceler");
+MODULE_AUTHOR("Kris Boutilier");
+MODULE_LICENSE("GPL v2");
+
+module_init(mod_init);
+module_exit(mod_exit);
Copied: linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi_echocan_mg2.c (from r4392, linux/team/kpfleming/modular_ec/drivers/dahdi/mg2ec.h)
URL: http://svn.digium.com/view/dahdi/linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi_echocan_mg2.c?view=diff&rev=4397&p1=linux/team/kpfleming/modular_ec/drivers/dahdi/mg2ec.h&r1=4392&p2=linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi_echocan_mg2.c&r2=4397
==============================================================================
--- linux/team/kpfleming/modular_ec/drivers/dahdi/mg2ec.h (original)
+++ linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi_echocan_mg2.c Wed Jun 18 17:05:53 2008
@@ -23,15 +23,20 @@
*
*/
-#ifndef _MG2_ECHO_H
-#define _MG2_ECHO_H
-
#include <linux/kernel.h>
#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/init.h>
#include <linux/ctype.h>
-
-#define MALLOC(a) kmalloc((a), GFP_KERNEL)
-#define FREE(a) kfree(a)
+#include <linux/moduleparam.h>
+
+#include <dahdi/kernel.h>
+
+static int debug;
+
+#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
+#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
#define ABS(a) abs(a!=-32768?a:-32767)
@@ -56,8 +61,87 @@
/* Get optimized routines for math */
#include "arith.h"
-/* Bring in definitions for the various constants and thresholds */
-#include "mg2ec_const.h"
+/*
+ Important constants for tuning mg2 echo can
+ */
+
+/* Convergence (aka. adaptation) speed -- higher means slower */
+#define DEFAULT_BETA1_I 2048
+
+/* Constants for various power computations */
+#define DEFAULT_SIGMA_LY_I 7
+#define DEFAULT_SIGMA_LU_I 7
+#define DEFAULT_ALPHA_ST_I 5 /* near-end speech detection sensitivity factor */
+#define DEFAULT_ALPHA_YT_I 5
+
+#define DEFAULT_CUTOFF_I 128
+
+/* Define the near-end speech hangover counter: if near-end speech
+ * is declared, hcntr is set equal to hangt (see pg. 432)
+ */
+#define DEFAULT_HANGT 600 /* in samples, so 600 samples = 75ms */
+
+/* define the residual error suppression threshold */
+#define DEFAULT_SUPPR_I 16 /* 16 = -24db */
+
+/* This is the minimum reference signal power estimate level
+ * that will result in filter adaptation.
+ * If this is too low then background noise will cause the filter
+ * coefficients to constantly be updated.
+ */
+#define MIN_UPDATE_THRESH_I 2048
+
+/* The number of samples used to update coefficients using the
+ * the block update method (M). It should be related back to the
+ * length of the echo can.
+ * ie. it only updates coefficients when (sample number MOD default_m) = 0
+ *
+ * Getting this wrong may cause an oops. Consider yourself warned!
+ */
+#define DEFAULT_M 16 /* every 16th sample */
+
+/* If AGGRESSIVE supression is enabled, then we start cancelling residual
+ * echos again even while there is potentially the very end of a near-side
+ * signal present.
+ * This defines how many samples of DEFAULT_HANGT can remain before we
+ * kick back in
+ */
+#define AGGRESSIVE_HCNTR 160 /* in samples, so 160 samples = 20ms */
+
+/* Treat sample as error if it has a different sign as the
+ * input signal and is this number larger in ABS() as
+ * the input-signal */
+#define MAX_SIGN_ERROR 3000
+
+/* Number of coefficients really used for calculating the
+ * simulated echo. The value specifies how many of the
+ * biggest coefficients are used for calculating rs.
+ * This helps on long echo-tails by artificially limiting
+ * the number of coefficients for the calculation and
+ * preventing overflows.
+ * Comment this to deactivate the code */
+#define USED_COEFFS 64
+
+/* Backup coefficients every this number of samples */
+#define BACKUP 256
+
+/***************************************************************/
+/* The following knobs are not implemented in the current code */
+
+/* we need a dynamic level of suppression varying with the ratio of the
+ power of the echo to the power of the reference signal this is
+ done so that we have a smoother background.
+ we have a higher suppression when the power ratio is closer to
+ suppr_ceil and reduces logarithmically as we approach suppr_floor.
+ */
+#define SUPPR_FLOOR -64
+#define SUPPR_CEIL -24
+
+/* in a second departure, we calculate the residual error suppression
+ * as a percentage of the reference signal energy level. The threshold
+ * is defined in terms of dB below the reference signal.
+ */
+#define RES_SUPR_FACTOR -20
#define DC_NORMALIZE
@@ -159,20 +243,6 @@
};
-static void echo_can_init(void)
-{
- printk("DAHDI Echo Canceller: MG2\n");
-}
-
-static void echo_can_identify(char *buf, size_t len)
-{
- dahdi_copy_string(buf, "MG2", len);
-}
-
-static void echo_can_shutdown(void)
-{
-}
-
static inline void init_cb_s(echo_can_cb_s *cb, int len, void *where)
{
cb->buf_d = (short *)where;
@@ -270,12 +340,12 @@
}
-static inline void echo_can_free(struct echo_can_state *ec)
+static void echo_can_free(struct echo_can_state *ec)
{
#if defined(DC_NORMALIZE) && defined(MEC2_DCBIAS_MESSAGE)
printk("EC: DC bias calculated: %d V\n", ec->dc_estimate >> 15);
#endif
- FREE(ec);
+ kfree(ec);
}
#ifdef DC_NORMALIZE
@@ -286,9 +356,8 @@
}
#endif
-static inline short echo_can_update(struct echo_can_state *ec, short iref, short isig)
-{
-
+static inline short sample_update(struct echo_can_state *ec, short iref, short isig)
+{
/* Declare local variables that are used more than once */
/* ... */
int k;
@@ -640,6 +709,17 @@
/* Increment the sample index and return the corrected sample */
ec->i_d++;
return u;
+}
+
+static void echo_can_update(struct echo_can_state *ec, short *iref, short *isig)
+{
+ unsigned int x;
+ short result;
+
+ for (x = 0; x < DAHDI_CHUNKSIZE; x++) {
+ result = sample_update(ec, *iref, *isig);
+ *isig++ = result;
+ }
}
static int echo_can_create(struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p,
@@ -670,7 +750,7 @@
2 * sizeof(short) * (maxu) + /* u_s */
2 * sizeof(short) * ecp->tap_length; /* y_tilde_s */
- if (!(*ec = MALLOC(size)))
+ if (!(*ec = kmalloc(size, GFP_KERNEL)))
return -ENOMEM;
memset(*ec, 0, size);
@@ -697,7 +777,7 @@
return 0;
}
-static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val)
+static int echo_can_traintap(struct echo_can_state *ec, int pos, short val)
{
/* Set the hangover counter to the length of the can to
* avoid adjustments occuring immediately after initial forced training
@@ -722,4 +802,37 @@
return 0;
}
-#endif
+static const struct dahdi_echocan me = {
+ .name = "MG2",
+ .echo_can_create = echo_can_create,
+ .echo_can_free = echo_can_free,
+ .echo_can_array_update = echo_can_update,
+ .echo_can_traintap = echo_can_traintap,
+};
+
+static int __init mod_init(void)
+{
+ if (dahdi_register_echocan(&me, THIS_MODULE)) {
+ module_printk(KERN_ERR, "could not register with DAHDI core\n");
+
+ return -EPERM;
+ }
+
+ module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", me.name);
+
+ return 0;
+}
+
+static void __exit mod_exit(void)
+{
+ dahdi_unregister_echocan(&me);
+}
+
+module_param(debug, int, S_IRUGO | S_IWUSR);
+
+MODULE_DESCRIPTION("DAHDI 'MG2' Echo Canceler");
+MODULE_AUTHOR("Michael Gernoth");
+MODULE_LICENSE("GPL v2");
+
+module_init(mod_init);
+module_exit(mod_exit);
Copied: linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi_echocan_sec2.c (from r4392, linux/team/kpfleming/modular_ec/drivers/dahdi/sec-2.h)
URL: http://svn.digium.com/view/dahdi/linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi_echocan_sec2.c?view=diff&rev=4397&p1=linux/team/kpfleming/modular_ec/drivers/dahdi/sec-2.h&r1=4392&p2=linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi_echocan_sec2.c&r2=4397
==============================================================================
--- linux/team/kpfleming/modular_ec/drivers/dahdi/sec-2.h (original)
+++ linux/team/kpfleming/modular_ec/drivers/dahdi/dahdi_echocan_sec2.c Wed Jun 18 17:05:53 2008
@@ -36,22 +36,20 @@
Improve double talk detector (iterative!)
*/
-#ifndef _DAHDI_SEC_H
-#define _DAHDI_SEC_H
-
-#ifdef __KERNEL__
#include <linux/kernel.h>
#include <linux/slab.h>
-#define MALLOC(a) kmalloc((a), GFP_KERNEL)
-#define FREE(a) kfree(a)
-#else
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <string.h>
-#define MALLOC(a) malloc(a)
-#define FREE(a) free(a)
-#endif
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ctype.h>
+#include <linux/moduleparam.h>
+
+#include <dahdi/kernel.h>
+
+static int debug;
+
+#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
+#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
#include "fir.h"
@@ -97,23 +95,6 @@
was skipped, for test purposes */
};
-static void echo_can_free(struct echo_can_state *ec);
-static int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx);
-
-static void echo_can_init(void)
-{
- printk("DAHDI Echo Canceller: STEVE2%s\n", DAHDI_ECHO_AGGRESSIVE);
-}
-
-static void echo_can_identify(char *buf, size_t len)
-{
- dahdi_copy_string(buf, "STEVE2", len);
-}
-
-static void echo_can_shutdown(void)
-{
-}
-
/*
* According to Jim...
*/
@@ -138,7 +119,7 @@
size = sizeof(**ec) + ecp->tap_length * sizeof(int32_t) + ecp->tap_length * 3 * sizeof(int16_t);
- if (!(*ec = MALLOC(size)))
+ if (!(*ec = kmalloc(size, GFP_KERNEL)))
return -ENOMEM;
memset(*ec, 0, size);
@@ -160,14 +141,14 @@
}
/*- End of function --------------------------------------------------------*/
-static inline void echo_can_free(struct echo_can_state *ec)
+static void echo_can_free(struct echo_can_state *ec)
{
fir16_free(&ec->fir_state);
- FREE(ec);
+ kfree(ec);
}
/*- End of function --------------------------------------------------------*/
-static inline int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx)
+static inline int16_t sample_update(struct echo_can_state *ec, int16_t tx, int16_t rx)
{
int offset1;
int offset2;
@@ -297,143 +278,21 @@
return clean_rx;
}
-
-#if 0
-static inline int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx)
-{
- int offset;
- int limit;
- int32_t echo_value;
- int clean_rx;
- int nsuppr;
- int i;
- int correction;
-
- ec->tx_history[ec->curr_pos] = tx;
-
- /* Evaluate the echo - i.e. apply the FIR filter */
- /* Assume the gain of the FIR does not exceed unity. Exceeding unity
- would seem like a rather poor thing for an echo cancellor to do :)
- This means we can compute the result with a total disregard for
- overflows. 16bits x 16bits -> 31bits, so no overflow can occur in
- any multiply. While accumulating we may overflow and underflow the
- 32 bit scale often. However, if the gain does not exceed unity,
- everything should work itself out, and the final result will be
- OK, without any saturation logic. */
- /* Overflow is very much possible here, and we do nothing about it because
- of the compute costs */
- /* 16 bit coeffs for the LMS give lousy results (maths good, actual sound
- bad!), but 32 bit coeffs require some shifting. On balance 32 bit seems
- best */
- offset = ec->curr_pos;
- limit = ec->taps - offset;
- echo_value = 0;
- for (i = 0; i < limit; i++)
- echo_value += (ec->fir_taps[i] >> 16)*ec->tx_history[i + offset];
- offset = ec->taps - ec->curr_pos;
- for ( ; i < ec->taps; i++)
- echo_value += (ec->fir_taps[i] >> 16)*ec->tx_history[i - offset];
- echo_value >>= 16;
-
- /* And the answer is..... */
- clean_rx = rx - echo_value;
-
- /* That was the easy part. Now we need to adapt! */
- if (ec->nonupdate_dwell > 0)
- ec->nonupdate_dwell--;
-
- /* If there is very little being transmitted, any attempt to train is
- futile. We would either be training on the far end's noise or signal,
- the channel's own noise, or our noise. Either way, this is hardly good
- training, so don't do it (avoid trouble). */
- /* If the received power is very low, either we are sending very little or
- we are already well adapted. There is little point in trying to improve
- the adaption under these circumstanceson, so don't do it (reduce the
- compute load). */
- if (ec->tx_power > MIN_TX_POWER_FOR_ADAPTION
- &&
- ec->rx_power > MIN_RX_POWER_FOR_ADAPTION)
- {
- /* This is a really crude piece of decision logic, but it does OK
- for now. */
- if (ec->tx_power > 2*ec->rx_power)
- {
- /* There is no far-end speech detected */
- if (ec->nonupdate_dwell == 0)
- {
- /* ... and we are not in the dwell time from previous speech. */
- //nsuppr = saturate((clean_rx << 16)/ec->tx_power);
- nsuppr = clean_rx >> 3;
-
- /* Update the FIR taps */
- offset = ec->curr_pos;
- limit = ec->taps - offset;
- ec->latest_correction = 0;
- for (i = 0; i < limit; i++)
- {
- correction = ec->tx_history[i + offset]*nsuppr;
- ec->fir_taps[i] += correction;
- //ec->latest_correction += abs(correction);
- }
- offset = ec->taps - ec->curr_pos;
- for ( ; i < ec->taps; i++)
- {
- correction = ec->tx_history[i - offset]*nsuppr;
- ec->fir_taps[i] += correction;
- //ec->latest_correction += abs(correction);
- }
- }
- else
- {
- ec->latest_correction = -3;
- }
- }
- else
- {
- ec->nonupdate_dwell = NONUPDATE_DWELL_TIME;
- ec->latest_correction = -2;
- }
- }
- else
- {
- ec->nonupdate_dwell = 0;
- ec->latest_correction = -1;
- }
- /* Calculate short term power levels using very simple single pole IIRs */
- /* TODO: Is the nasty modulus approach the fastest, or would a real
- tx*tx power calculation actually be faster? */
- ec->tx_power += ((abs(tx) - ec->tx_power) >> 5);
- ec->rx_power += ((abs(rx) - ec->rx_power) >> 5);
- ec->clean_rx_power += ((abs(clean_rx) - ec->clean_rx_power) >> 5);
-
-#if defined(XYZZY)
- if (ec->use_suppressor)
- {
- ec->supp_test1 += (ec->tx_history[ec->curr_pos] - ec->tx_history[(ec->curr_pos - 7) & ec->tap_mask]);
- ec->supp_test2 += (ec->tx_history[(ec->curr_pos - 24) & ec->tap_mask] - ec->tx_history[(ec->curr_pos - 31) & ec->tap_mask]);
- if (ec->supp_test1 > 42 && ec->supp_test2 > 42)
- supp_change = 25;
- else
- supp_change = 50;
- supp = supp_change + k1*ec->supp1 + k2*ec->supp2;
- ec->supp2 = ec->supp1;
- ec->supp1 = supp;
- clean_rx *= (1 - supp);
- }
-#endif
-
- if (ec->use_nlp && ec->rx_power < 32)
- clean_rx = 0;
-
- /* Roll around the rolling buffer */
- ec->curr_pos = (ec->curr_pos + 1) & ec->tap_mask;
-
- return clean_rx;
-}
/*- End of function --------------------------------------------------------*/
-#endif
-
-static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val)
+
+static void echo_can_update(struct echo_can_state *ec, short *iref, short *isig)
+{
+ unsigned int x;
+ short result;
+
+ for (x = 0; x < DAHDI_CHUNKSIZE; x++) {
+ result = sample_update(ec, *iref, *isig);
+ *isig++ = result;
+ }
+}
+/*- End of function --------------------------------------------------------*/
+
+static int echo_can_traintap(struct echo_can_state *ec, int pos, short val)
{
/* Reset hang counter to avoid adjustments after
initial forced training */
@@ -447,5 +306,37 @@
return 0;
}
-/*- End of file ------------------------------------------------------------*/
-#endif
+static const struct dahdi_echocan me = {
+ .name = "STEVE2",
+ .echo_can_create = echo_can_create,
+ .echo_can_free = echo_can_free,
+ .echo_can_array_update = echo_can_update,
+ .echo_can_traintap = echo_can_traintap,
+};
+
+static int __init mod_init(void)
+{
+ if (dahdi_register_echocan(&me, THIS_MODULE)) {
+ module_printk(KERN_ERR, "could not register with DAHDI core\n");
+
+ return -EPERM;
+ }
+
+ module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", me.name);
+
+ return 0;
+}
+
+static void __exit mod_exit(void)
+{
+ dahdi_unregister_echocan(&me);
+}
+
+module_param(debug, int, S_IRUGO | S_IWUSR);
+
+MODULE_DESCRIPTION("DAHDI 'STEVE2' Echo Canceler");
+MODULE_AUTHOR("Steve Underwood <steveu at coppice.org>");
+MODULE_LICENSE("GPL");
+
+module_init(mod_init);
+module_exit(mod_exit);
Modified: linux/team/kpfleming/modular_ec/drivers/dahdi/fir.h
URL: http://svn.digium.com/view/dahdi/linux/team/kpfleming/modular_ec/drivers/dahdi/fir.h?view=diff&rev=4397&r1=4396&r2=4397
==============================================================================
--- linux/team/kpfleming/modular_ec/drivers/dahdi/fir.h (original)
+++ linux/team/kpfleming/modular_ec/drivers/dahdi/fir.h Wed Jun 18 17:05:53 2008
@@ -51,7 +51,7 @@
fir->taps = taps;
fir->curr_pos = taps - 1;
fir->coeffs = coeffs;
- fir->history = MALLOC (taps*sizeof (int16_t));
+ fir->history = kmalloc(taps*sizeof (int16_t), GFP_KERNEL);
if (fir->history)
memset (fir->history, '\0', taps*sizeof (int16_t));
}
@@ -59,7 +59,7 @@
static inline void fir16_free (fir16_state_t *fir)
{
- FREE (fir->history);
+ kfree(fir->history);
}
/*- End of function --------------------------------------------------------*/
@@ -92,7 +92,7 @@
fir->taps = taps;
fir->curr_pos = taps - 1;
fir->coeffs = coeffs;
- fir->history = MALLOC (taps*sizeof (int16_t));
+ fir->history = kmalloc(taps*sizeof (int16_t), GFP_KERNEL);
if (fir->history)
memset (fir->history, '\0', taps*sizeof (int16_t));
}
@@ -100,7 +100,7 @@
static inline void fir32_free (fir32_state_t *fir)
{
- FREE (fir->history);
+ kfree(fir->history);
}
/*- End of function --------------------------------------------------------*/
More information about the dahdi-commits
mailing list