123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675 |
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/slab.h>
- #include "echo.h"
- #define MIN_TX_POWER_FOR_ADAPTION 64
- #define MIN_RX_POWER_FOR_ADAPTION 64
- #define DTD_HANGOVER 600
- #define DC_LOG2BETA 3
- #ifdef __bfin__
- static inline void lms_adapt_bg(struct oslec_state *ec, int clean, int shift)
- {
- int i;
- int offset1;
- int offset2;
- int factor;
- int exp;
- int16_t *phist;
- int n;
- if (shift > 0)
- factor = clean << shift;
- else
- factor = clean >> -shift;
-
- offset2 = ec->curr_pos;
- offset1 = ec->taps - offset2;
- phist = &ec->fir_state_bg.history[offset2];
-
-
- n = ec->taps;
- for (i = 0; i < n; i++) {
- exp = *phist++ * factor;
- ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15);
- }
-
-
- }
- #else
- static inline void lms_adapt_bg(struct oslec_state *ec, int clean, int shift)
- {
- int i;
- int offset1;
- int offset2;
- int factor;
- int exp;
- if (shift > 0)
- factor = clean << shift;
- else
- factor = clean >> -shift;
-
- offset2 = ec->curr_pos;
- offset1 = ec->taps - offset2;
- for (i = ec->taps - 1; i >= offset1; i--) {
- exp = (ec->fir_state_bg.history[i - offset1] * factor);
- ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15);
- }
- for (; i >= 0; i--) {
- exp = (ec->fir_state_bg.history[i + offset2] * factor);
- ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15);
- }
- }
- #endif
- static inline int top_bit(unsigned int bits)
- {
- if (bits == 0)
- return -1;
- else
- return (int)fls((int32_t) bits) - 1;
- }
- struct oslec_state *oslec_create(int len, int adaption_mode)
- {
- struct oslec_state *ec;
- int i;
- const int16_t *history;
- ec = kzalloc(sizeof(*ec), GFP_KERNEL);
- if (!ec)
- return NULL;
- ec->taps = len;
- ec->log2taps = top_bit(len);
- ec->curr_pos = ec->taps - 1;
- ec->fir_taps16[0] =
- kcalloc(ec->taps, sizeof(int16_t), GFP_KERNEL);
- if (!ec->fir_taps16[0])
- goto error_oom_0;
- ec->fir_taps16[1] =
- kcalloc(ec->taps, sizeof(int16_t), GFP_KERNEL);
- if (!ec->fir_taps16[1])
- goto error_oom_1;
- history = fir16_create(&ec->fir_state, ec->fir_taps16[0], ec->taps);
- if (!history)
- goto error_state;
- history = fir16_create(&ec->fir_state_bg, ec->fir_taps16[1], ec->taps);
- if (!history)
- goto error_state_bg;
- for (i = 0; i < 5; i++)
- ec->xvtx[i] = ec->yvtx[i] = ec->xvrx[i] = ec->yvrx[i] = 0;
- ec->cng_level = 1000;
- oslec_adaption_mode(ec, adaption_mode);
- ec->snapshot = kcalloc(ec->taps, sizeof(int16_t), GFP_KERNEL);
- if (!ec->snapshot)
- goto error_snap;
- ec->cond_met = 0;
- ec->pstates = 0;
- ec->ltxacc = ec->lrxacc = ec->lcleanacc = ec->lclean_bgacc = 0;
- ec->ltx = ec->lrx = ec->lclean = ec->lclean_bg = 0;
- ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
- ec->lbgn = ec->lbgn_acc = 0;
- ec->lbgn_upper = 200;
- ec->lbgn_upper_acc = ec->lbgn_upper << 13;
- return ec;
- error_snap:
- fir16_free(&ec->fir_state_bg);
- error_state_bg:
- fir16_free(&ec->fir_state);
- error_state:
- kfree(ec->fir_taps16[1]);
- error_oom_1:
- kfree(ec->fir_taps16[0]);
- error_oom_0:
- kfree(ec);
- return NULL;
- }
- EXPORT_SYMBOL_GPL(oslec_create);
- void oslec_free(struct oslec_state *ec)
- {
- int i;
- fir16_free(&ec->fir_state);
- fir16_free(&ec->fir_state_bg);
- for (i = 0; i < 2; i++)
- kfree(ec->fir_taps16[i]);
- kfree(ec->snapshot);
- kfree(ec);
- }
- EXPORT_SYMBOL_GPL(oslec_free);
- void oslec_adaption_mode(struct oslec_state *ec, int adaption_mode)
- {
- ec->adaption_mode = adaption_mode;
- }
- EXPORT_SYMBOL_GPL(oslec_adaption_mode);
- void oslec_flush(struct oslec_state *ec)
- {
- int i;
- ec->ltxacc = ec->lrxacc = ec->lcleanacc = ec->lclean_bgacc = 0;
- ec->ltx = ec->lrx = ec->lclean = ec->lclean_bg = 0;
- ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
- ec->lbgn = ec->lbgn_acc = 0;
- ec->lbgn_upper = 200;
- ec->lbgn_upper_acc = ec->lbgn_upper << 13;
- ec->nonupdate_dwell = 0;
- fir16_flush(&ec->fir_state);
- fir16_flush(&ec->fir_state_bg);
- ec->fir_state.curr_pos = ec->taps - 1;
- ec->fir_state_bg.curr_pos = ec->taps - 1;
- for (i = 0; i < 2; i++)
- memset(ec->fir_taps16[i], 0, ec->taps * sizeof(int16_t));
- ec->curr_pos = ec->taps - 1;
- ec->pstates = 0;
- }
- EXPORT_SYMBOL_GPL(oslec_flush);
- void oslec_snapshot(struct oslec_state *ec)
- {
- memcpy(ec->snapshot, ec->fir_taps16[0], ec->taps * sizeof(int16_t));
- }
- EXPORT_SYMBOL_GPL(oslec_snapshot);
- int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx)
- {
- int32_t echo_value;
- int clean_bg;
- int tmp;
- int tmp1;
-
- ec->tx = tx;
- ec->rx = rx;
- tx >>= 1;
- rx >>= 1;
-
- if (ec->adaption_mode & ECHO_CAN_USE_RX_HPF) {
- tmp = rx << 15;
-
- tmp -= (tmp >> 4);
- ec->rx_1 += -(ec->rx_1 >> DC_LOG2BETA) + tmp - ec->rx_2;
-
- tmp1 = ec->rx_1 >> 15;
- if (tmp1 > 16383)
- tmp1 = 16383;
- if (tmp1 < -16383)
- tmp1 = -16383;
- rx = tmp1;
- ec->rx_2 = tmp;
- }
-
- {
- int new, old;
-
- new = (int)tx * (int)tx;
- old = (int)ec->fir_state.history[ec->fir_state.curr_pos] *
- (int)ec->fir_state.history[ec->fir_state.curr_pos];
- ec->pstates +=
- ((new - old) + (1 << (ec->log2taps - 1))) >> ec->log2taps;
- if (ec->pstates < 0)
- ec->pstates = 0;
- }
-
- ec->ltxacc += abs(tx) - ec->ltx;
- ec->ltx = (ec->ltxacc + (1 << 4)) >> 5;
- ec->lrxacc += abs(rx) - ec->lrx;
- ec->lrx = (ec->lrxacc + (1 << 4)) >> 5;
-
- ec->fir_state.coeffs = ec->fir_taps16[0];
- echo_value = fir16(&ec->fir_state, tx);
- ec->clean = rx - echo_value;
- ec->lcleanacc += abs(ec->clean) - ec->lclean;
- ec->lclean = (ec->lcleanacc + (1 << 4)) >> 5;
-
- echo_value = fir16(&ec->fir_state_bg, tx);
- clean_bg = rx - echo_value;
- ec->lclean_bgacc += abs(clean_bg) - ec->lclean_bg;
- ec->lclean_bg = (ec->lclean_bgacc + (1 << 4)) >> 5;
-
-
- ec->factor = 0;
- ec->shift = 0;
- if ((ec->nonupdate_dwell == 0)) {
- int p, logp, shift;
-
- p = MIN_TX_POWER_FOR_ADAPTION + ec->pstates;
- logp = top_bit(p) + ec->log2taps;
- shift = 30 - 2 - logp;
- ec->shift = shift;
- lms_adapt_bg(ec, clean_bg, shift);
- }
-
- ec->adapt = 0;
- if ((ec->lrx > MIN_RX_POWER_FOR_ADAPTION) && (ec->lrx > ec->ltx))
- ec->nonupdate_dwell = DTD_HANGOVER;
- if (ec->nonupdate_dwell)
- ec->nonupdate_dwell--;
-
-
- if ((ec->adaption_mode & ECHO_CAN_USE_ADAPTION) &&
- (ec->nonupdate_dwell == 0) &&
-
- (8 * ec->lclean_bg < 7 * ec->lclean) &&
-
- (8 * ec->lclean_bg < ec->ltx)) {
- if (ec->cond_met == 6) {
-
- ec->adapt = 1;
- memcpy(ec->fir_taps16[0], ec->fir_taps16[1],
- ec->taps * sizeof(int16_t));
- } else
- ec->cond_met++;
- } else
- ec->cond_met = 0;
-
- ec->clean_nlp = ec->clean;
- if (ec->adaption_mode & ECHO_CAN_USE_NLP) {
-
- if ((16 * ec->lclean < ec->ltx)) {
-
- if (ec->adaption_mode & ECHO_CAN_USE_CNG) {
- ec->cng_level = ec->lbgn;
-
- ec->cng_rndnum =
- 1664525U * ec->cng_rndnum + 1013904223U;
- ec->cng_filter =
- ((ec->cng_rndnum & 0xFFFF) - 32768 +
- 5 * ec->cng_filter) >> 3;
- ec->clean_nlp =
- (ec->cng_filter * ec->cng_level * 8) >> 14;
- } else if (ec->adaption_mode & ECHO_CAN_USE_CLIP) {
-
- if (ec->clean_nlp > ec->lbgn)
- ec->clean_nlp = ec->lbgn;
- if (ec->clean_nlp < -ec->lbgn)
- ec->clean_nlp = -ec->lbgn;
- } else {
-
- ec->clean_nlp = 0;
- }
- } else {
-
- if (ec->lclean < 40) {
- ec->lbgn_acc += abs(ec->clean) - ec->lbgn;
- ec->lbgn = (ec->lbgn_acc + (1 << 11)) >> 12;
- }
- }
- }
-
- if (ec->curr_pos <= 0)
- ec->curr_pos = ec->taps;
- ec->curr_pos--;
- if (ec->adaption_mode & ECHO_CAN_DISABLE)
- ec->clean_nlp = rx;
-
- return (int16_t) ec->clean_nlp << 1;
- }
- EXPORT_SYMBOL_GPL(oslec_update);
- int16_t oslec_hpf_tx(struct oslec_state *ec, int16_t tx)
- {
- int tmp;
- int tmp1;
- if (ec->adaption_mode & ECHO_CAN_USE_TX_HPF) {
- tmp = tx << 15;
-
- tmp -= (tmp >> 4);
- ec->tx_1 += -(ec->tx_1 >> DC_LOG2BETA) + tmp - ec->tx_2;
- tmp1 = ec->tx_1 >> 15;
- if (tmp1 > 32767)
- tmp1 = 32767;
- if (tmp1 < -32767)
- tmp1 = -32767;
- tx = tmp1;
- ec->tx_2 = tmp;
- }
- return tx;
- }
- EXPORT_SYMBOL_GPL(oslec_hpf_tx);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("David Rowe");
- MODULE_DESCRIPTION("Open Source Line Echo Canceller");
- MODULE_VERSION("0.3.0");
|