0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093 #include <linux/kernel.h>
0094 #include <linux/module.h>
0095 #include <linux/slab.h>
0096
0097 #include "echo.h"
0098
0099 #define MIN_TX_POWER_FOR_ADAPTION 64
0100 #define MIN_RX_POWER_FOR_ADAPTION 64
0101 #define DTD_HANGOVER 600
0102 #define DC_LOG2BETA 3
0103
0104
0105
0106 static inline void lms_adapt_bg(struct oslec_state *ec, int clean, int shift)
0107 {
0108 int i;
0109
0110 int offset1;
0111 int offset2;
0112 int factor;
0113 int exp;
0114
0115 if (shift > 0)
0116 factor = clean << shift;
0117 else
0118 factor = clean >> -shift;
0119
0120
0121
0122 offset2 = ec->curr_pos;
0123 offset1 = ec->taps - offset2;
0124
0125 for (i = ec->taps - 1; i >= offset1; i--) {
0126 exp = (ec->fir_state_bg.history[i - offset1] * factor);
0127 ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15);
0128 }
0129 for (; i >= 0; i--) {
0130 exp = (ec->fir_state_bg.history[i + offset2] * factor);
0131 ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15);
0132 }
0133 }
0134
0135 static inline int top_bit(unsigned int bits)
0136 {
0137 if (bits == 0)
0138 return -1;
0139 else
0140 return (int)fls((int32_t) bits) - 1;
0141 }
0142
0143 struct oslec_state *oslec_create(int len, int adaption_mode)
0144 {
0145 struct oslec_state *ec;
0146 int i;
0147 const int16_t *history;
0148
0149 ec = kzalloc(sizeof(*ec), GFP_KERNEL);
0150 if (!ec)
0151 return NULL;
0152
0153 ec->taps = len;
0154 ec->log2taps = top_bit(len);
0155 ec->curr_pos = ec->taps - 1;
0156
0157 ec->fir_taps16[0] =
0158 kcalloc(ec->taps, sizeof(int16_t), GFP_KERNEL);
0159 if (!ec->fir_taps16[0])
0160 goto error_oom_0;
0161
0162 ec->fir_taps16[1] =
0163 kcalloc(ec->taps, sizeof(int16_t), GFP_KERNEL);
0164 if (!ec->fir_taps16[1])
0165 goto error_oom_1;
0166
0167 history = fir16_create(&ec->fir_state, ec->fir_taps16[0], ec->taps);
0168 if (!history)
0169 goto error_state;
0170 history = fir16_create(&ec->fir_state_bg, ec->fir_taps16[1], ec->taps);
0171 if (!history)
0172 goto error_state_bg;
0173
0174 for (i = 0; i < 5; i++)
0175 ec->xvtx[i] = ec->yvtx[i] = ec->xvrx[i] = ec->yvrx[i] = 0;
0176
0177 ec->cng_level = 1000;
0178 oslec_adaption_mode(ec, adaption_mode);
0179
0180 ec->snapshot = kcalloc(ec->taps, sizeof(int16_t), GFP_KERNEL);
0181 if (!ec->snapshot)
0182 goto error_snap;
0183
0184 ec->cond_met = 0;
0185 ec->pstates = 0;
0186 ec->ltxacc = ec->lrxacc = ec->lcleanacc = ec->lclean_bgacc = 0;
0187 ec->ltx = ec->lrx = ec->lclean = ec->lclean_bg = 0;
0188 ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
0189 ec->lbgn = ec->lbgn_acc = 0;
0190 ec->lbgn_upper = 200;
0191 ec->lbgn_upper_acc = ec->lbgn_upper << 13;
0192
0193 return ec;
0194
0195 error_snap:
0196 fir16_free(&ec->fir_state_bg);
0197 error_state_bg:
0198 fir16_free(&ec->fir_state);
0199 error_state:
0200 kfree(ec->fir_taps16[1]);
0201 error_oom_1:
0202 kfree(ec->fir_taps16[0]);
0203 error_oom_0:
0204 kfree(ec);
0205 return NULL;
0206 }
0207 EXPORT_SYMBOL_GPL(oslec_create);
0208
0209 void oslec_free(struct oslec_state *ec)
0210 {
0211 int i;
0212
0213 fir16_free(&ec->fir_state);
0214 fir16_free(&ec->fir_state_bg);
0215 for (i = 0; i < 2; i++)
0216 kfree(ec->fir_taps16[i]);
0217 kfree(ec->snapshot);
0218 kfree(ec);
0219 }
0220 EXPORT_SYMBOL_GPL(oslec_free);
0221
0222 void oslec_adaption_mode(struct oslec_state *ec, int adaption_mode)
0223 {
0224 ec->adaption_mode = adaption_mode;
0225 }
0226 EXPORT_SYMBOL_GPL(oslec_adaption_mode);
0227
0228 void oslec_flush(struct oslec_state *ec)
0229 {
0230 int i;
0231
0232 ec->ltxacc = ec->lrxacc = ec->lcleanacc = ec->lclean_bgacc = 0;
0233 ec->ltx = ec->lrx = ec->lclean = ec->lclean_bg = 0;
0234 ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
0235
0236 ec->lbgn = ec->lbgn_acc = 0;
0237 ec->lbgn_upper = 200;
0238 ec->lbgn_upper_acc = ec->lbgn_upper << 13;
0239
0240 ec->nonupdate_dwell = 0;
0241
0242 fir16_flush(&ec->fir_state);
0243 fir16_flush(&ec->fir_state_bg);
0244 ec->fir_state.curr_pos = ec->taps - 1;
0245 ec->fir_state_bg.curr_pos = ec->taps - 1;
0246 for (i = 0; i < 2; i++)
0247 memset(ec->fir_taps16[i], 0, ec->taps * sizeof(int16_t));
0248
0249 ec->curr_pos = ec->taps - 1;
0250 ec->pstates = 0;
0251 }
0252 EXPORT_SYMBOL_GPL(oslec_flush);
0253
0254 void oslec_snapshot(struct oslec_state *ec)
0255 {
0256 memcpy(ec->snapshot, ec->fir_taps16[0], ec->taps * sizeof(int16_t));
0257 }
0258 EXPORT_SYMBOL_GPL(oslec_snapshot);
0259
0260
0261
0262 int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx)
0263 {
0264 int32_t echo_value;
0265 int clean_bg;
0266 int tmp;
0267 int tmp1;
0268
0269
0270
0271
0272
0273
0274
0275 ec->tx = tx;
0276 ec->rx = rx;
0277 tx >>= 1;
0278 rx >>= 1;
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295 if (ec->adaption_mode & ECHO_CAN_USE_RX_HPF) {
0296 tmp = rx << 15;
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306 tmp -= (tmp >> 4);
0307
0308 ec->rx_1 += -(ec->rx_1 >> DC_LOG2BETA) + tmp - ec->rx_2;
0309
0310
0311
0312
0313
0314
0315 tmp1 = ec->rx_1 >> 15;
0316 if (tmp1 > 16383)
0317 tmp1 = 16383;
0318 if (tmp1 < -16383)
0319 tmp1 = -16383;
0320 rx = tmp1;
0321 ec->rx_2 = tmp;
0322 }
0323
0324
0325
0326
0327 {
0328 int new, old;
0329
0330
0331
0332
0333 new = (int)tx * (int)tx;
0334 old = (int)ec->fir_state.history[ec->fir_state.curr_pos] *
0335 (int)ec->fir_state.history[ec->fir_state.curr_pos];
0336 ec->pstates +=
0337 ((new - old) + (1 << (ec->log2taps - 1))) >> ec->log2taps;
0338 if (ec->pstates < 0)
0339 ec->pstates = 0;
0340 }
0341
0342
0343
0344 ec->ltxacc += abs(tx) - ec->ltx;
0345 ec->ltx = (ec->ltxacc + (1 << 4)) >> 5;
0346 ec->lrxacc += abs(rx) - ec->lrx;
0347 ec->lrx = (ec->lrxacc + (1 << 4)) >> 5;
0348
0349
0350
0351 ec->fir_state.coeffs = ec->fir_taps16[0];
0352 echo_value = fir16(&ec->fir_state, tx);
0353 ec->clean = rx - echo_value;
0354 ec->lcleanacc += abs(ec->clean) - ec->lclean;
0355 ec->lclean = (ec->lcleanacc + (1 << 4)) >> 5;
0356
0357
0358
0359 echo_value = fir16(&ec->fir_state_bg, tx);
0360 clean_bg = rx - echo_value;
0361 ec->lclean_bgacc += abs(clean_bg) - ec->lclean_bg;
0362 ec->lclean_bg = (ec->lclean_bgacc + (1 << 4)) >> 5;
0363
0364
0365
0366
0367
0368
0369
0370 ec->factor = 0;
0371 ec->shift = 0;
0372 if (!ec->nonupdate_dwell) {
0373 int p, logp, shift;
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408 p = MIN_TX_POWER_FOR_ADAPTION + ec->pstates;
0409 logp = top_bit(p) + ec->log2taps;
0410 shift = 30 - 2 - logp;
0411 ec->shift = shift;
0412
0413 lms_adapt_bg(ec, clean_bg, shift);
0414 }
0415
0416
0417
0418
0419 ec->adapt = 0;
0420 if ((ec->lrx > MIN_RX_POWER_FOR_ADAPTION) && (ec->lrx > ec->ltx))
0421 ec->nonupdate_dwell = DTD_HANGOVER;
0422 if (ec->nonupdate_dwell)
0423 ec->nonupdate_dwell--;
0424
0425
0426
0427
0428
0429
0430 if ((ec->adaption_mode & ECHO_CAN_USE_ADAPTION) &&
0431 (ec->nonupdate_dwell == 0) &&
0432
0433 (8 * ec->lclean_bg < 7 * ec->lclean) &&
0434
0435 (8 * ec->lclean_bg < ec->ltx)) {
0436 if (ec->cond_met == 6) {
0437
0438
0439
0440
0441 ec->adapt = 1;
0442 memcpy(ec->fir_taps16[0], ec->fir_taps16[1],
0443 ec->taps * sizeof(int16_t));
0444 } else
0445 ec->cond_met++;
0446 } else
0447 ec->cond_met = 0;
0448
0449
0450
0451 ec->clean_nlp = ec->clean;
0452 if (ec->adaption_mode & ECHO_CAN_USE_NLP) {
0453
0454
0455
0456
0457
0458
0459 if ((16 * ec->lclean < ec->ltx)) {
0460
0461
0462
0463
0464
0465 if (ec->adaption_mode & ECHO_CAN_USE_CNG) {
0466 ec->cng_level = ec->lbgn;
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479 ec->cng_rndnum =
0480 1664525U * ec->cng_rndnum + 1013904223U;
0481 ec->cng_filter =
0482 ((ec->cng_rndnum & 0xFFFF) - 32768 +
0483 5 * ec->cng_filter) >> 3;
0484 ec->clean_nlp =
0485 (ec->cng_filter * ec->cng_level * 8) >> 14;
0486
0487 } else if (ec->adaption_mode & ECHO_CAN_USE_CLIP) {
0488
0489 if (ec->clean_nlp > ec->lbgn)
0490 ec->clean_nlp = ec->lbgn;
0491 if (ec->clean_nlp < -ec->lbgn)
0492 ec->clean_nlp = -ec->lbgn;
0493 } else {
0494
0495
0496
0497
0498 ec->clean_nlp = 0;
0499 }
0500 } else {
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511 if (ec->lclean < 40) {
0512 ec->lbgn_acc += abs(ec->clean) - ec->lbgn;
0513 ec->lbgn = (ec->lbgn_acc + (1 << 11)) >> 12;
0514 }
0515 }
0516 }
0517
0518
0519 if (ec->curr_pos <= 0)
0520 ec->curr_pos = ec->taps;
0521 ec->curr_pos--;
0522
0523 if (ec->adaption_mode & ECHO_CAN_DISABLE)
0524 ec->clean_nlp = rx;
0525
0526
0527
0528 return (int16_t) ec->clean_nlp << 1;
0529 }
0530 EXPORT_SYMBOL_GPL(oslec_update);
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554 int16_t oslec_hpf_tx(struct oslec_state *ec, int16_t tx)
0555 {
0556 int tmp;
0557 int tmp1;
0558
0559 if (ec->adaption_mode & ECHO_CAN_USE_TX_HPF) {
0560 tmp = tx << 15;
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570 tmp -= (tmp >> 4);
0571
0572 ec->tx_1 += -(ec->tx_1 >> DC_LOG2BETA) + tmp - ec->tx_2;
0573 tmp1 = ec->tx_1 >> 15;
0574 if (tmp1 > 32767)
0575 tmp1 = 32767;
0576 if (tmp1 < -32767)
0577 tmp1 = -32767;
0578 tx = tmp1;
0579 ec->tx_2 = tmp;
0580 }
0581
0582 return tx;
0583 }
0584 EXPORT_SYMBOL_GPL(oslec_hpf_tx);
0585
0586 MODULE_LICENSE("GPL");
0587 MODULE_AUTHOR("David Rowe");
0588 MODULE_DESCRIPTION("Open Source Line Echo Canceller");
0589 MODULE_VERSION("0.3.0");