This source file includes following definitions.
- lms_adapt_bg
- top_bit
- oslec_create
- oslec_free
- oslec_adaption_mode
- oslec_flush
- oslec_snapshot
- oslec_update
- oslec_hpf_tx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93 #include <linux/kernel.h>
94 #include <linux/module.h>
95 #include <linux/slab.h>
96
97 #include "echo.h"
98
99 #define MIN_TX_POWER_FOR_ADAPTION 64
100 #define MIN_RX_POWER_FOR_ADAPTION 64
101 #define DTD_HANGOVER 600
102 #define DC_LOG2BETA 3
103
104
105
106 static inline void lms_adapt_bg(struct oslec_state *ec, int clean, int shift)
107 {
108 int i;
109
110 int offset1;
111 int offset2;
112 int factor;
113 int exp;
114
115 if (shift > 0)
116 factor = clean << shift;
117 else
118 factor = clean >> -shift;
119
120
121
122 offset2 = ec->curr_pos;
123 offset1 = ec->taps - offset2;
124
125 for (i = ec->taps - 1; i >= offset1; i--) {
126 exp = (ec->fir_state_bg.history[i - offset1] * factor);
127 ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15);
128 }
129 for (; i >= 0; i--) {
130 exp = (ec->fir_state_bg.history[i + offset2] * factor);
131 ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15);
132 }
133 }
134
135 static inline int top_bit(unsigned int bits)
136 {
137 if (bits == 0)
138 return -1;
139 else
140 return (int)fls((int32_t) bits) - 1;
141 }
142
143 struct oslec_state *oslec_create(int len, int adaption_mode)
144 {
145 struct oslec_state *ec;
146 int i;
147 const int16_t *history;
148
149 ec = kzalloc(sizeof(*ec), GFP_KERNEL);
150 if (!ec)
151 return NULL;
152
153 ec->taps = len;
154 ec->log2taps = top_bit(len);
155 ec->curr_pos = ec->taps - 1;
156
157 ec->fir_taps16[0] =
158 kcalloc(ec->taps, sizeof(int16_t), GFP_KERNEL);
159 if (!ec->fir_taps16[0])
160 goto error_oom_0;
161
162 ec->fir_taps16[1] =
163 kcalloc(ec->taps, sizeof(int16_t), GFP_KERNEL);
164 if (!ec->fir_taps16[1])
165 goto error_oom_1;
166
167 history = fir16_create(&ec->fir_state, ec->fir_taps16[0], ec->taps);
168 if (!history)
169 goto error_state;
170 history = fir16_create(&ec->fir_state_bg, ec->fir_taps16[1], ec->taps);
171 if (!history)
172 goto error_state_bg;
173
174 for (i = 0; i < 5; i++)
175 ec->xvtx[i] = ec->yvtx[i] = ec->xvrx[i] = ec->yvrx[i] = 0;
176
177 ec->cng_level = 1000;
178 oslec_adaption_mode(ec, adaption_mode);
179
180 ec->snapshot = kcalloc(ec->taps, sizeof(int16_t), GFP_KERNEL);
181 if (!ec->snapshot)
182 goto error_snap;
183
184 ec->cond_met = 0;
185 ec->pstates = 0;
186 ec->ltxacc = ec->lrxacc = ec->lcleanacc = ec->lclean_bgacc = 0;
187 ec->ltx = ec->lrx = ec->lclean = ec->lclean_bg = 0;
188 ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
189 ec->lbgn = ec->lbgn_acc = 0;
190 ec->lbgn_upper = 200;
191 ec->lbgn_upper_acc = ec->lbgn_upper << 13;
192
193 return ec;
194
195 error_snap:
196 fir16_free(&ec->fir_state_bg);
197 error_state_bg:
198 fir16_free(&ec->fir_state);
199 error_state:
200 kfree(ec->fir_taps16[1]);
201 error_oom_1:
202 kfree(ec->fir_taps16[0]);
203 error_oom_0:
204 kfree(ec);
205 return NULL;
206 }
207 EXPORT_SYMBOL_GPL(oslec_create);
208
209 void oslec_free(struct oslec_state *ec)
210 {
211 int i;
212
213 fir16_free(&ec->fir_state);
214 fir16_free(&ec->fir_state_bg);
215 for (i = 0; i < 2; i++)
216 kfree(ec->fir_taps16[i]);
217 kfree(ec->snapshot);
218 kfree(ec);
219 }
220 EXPORT_SYMBOL_GPL(oslec_free);
221
222 void oslec_adaption_mode(struct oslec_state *ec, int adaption_mode)
223 {
224 ec->adaption_mode = adaption_mode;
225 }
226 EXPORT_SYMBOL_GPL(oslec_adaption_mode);
227
228 void oslec_flush(struct oslec_state *ec)
229 {
230 int i;
231
232 ec->ltxacc = ec->lrxacc = ec->lcleanacc = ec->lclean_bgacc = 0;
233 ec->ltx = ec->lrx = ec->lclean = ec->lclean_bg = 0;
234 ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
235
236 ec->lbgn = ec->lbgn_acc = 0;
237 ec->lbgn_upper = 200;
238 ec->lbgn_upper_acc = ec->lbgn_upper << 13;
239
240 ec->nonupdate_dwell = 0;
241
242 fir16_flush(&ec->fir_state);
243 fir16_flush(&ec->fir_state_bg);
244 ec->fir_state.curr_pos = ec->taps - 1;
245 ec->fir_state_bg.curr_pos = ec->taps - 1;
246 for (i = 0; i < 2; i++)
247 memset(ec->fir_taps16[i], 0, ec->taps * sizeof(int16_t));
248
249 ec->curr_pos = ec->taps - 1;
250 ec->pstates = 0;
251 }
252 EXPORT_SYMBOL_GPL(oslec_flush);
253
254 void oslec_snapshot(struct oslec_state *ec)
255 {
256 memcpy(ec->snapshot, ec->fir_taps16[0], ec->taps * sizeof(int16_t));
257 }
258 EXPORT_SYMBOL_GPL(oslec_snapshot);
259
260
261
262 int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx)
263 {
264 int32_t echo_value;
265 int clean_bg;
266 int tmp;
267 int tmp1;
268
269
270
271
272
273
274
275 ec->tx = tx;
276 ec->rx = rx;
277 tx >>= 1;
278 rx >>= 1;
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295 if (ec->adaption_mode & ECHO_CAN_USE_RX_HPF) {
296 tmp = rx << 15;
297
298
299
300
301
302
303
304
305
306 tmp -= (tmp >> 4);
307
308 ec->rx_1 += -(ec->rx_1 >> DC_LOG2BETA) + tmp - ec->rx_2;
309
310
311
312
313
314
315 tmp1 = ec->rx_1 >> 15;
316 if (tmp1 > 16383)
317 tmp1 = 16383;
318 if (tmp1 < -16383)
319 tmp1 = -16383;
320 rx = tmp1;
321 ec->rx_2 = tmp;
322 }
323
324
325
326
327 {
328 int new, old;
329
330
331
332
333 new = (int)tx * (int)tx;
334 old = (int)ec->fir_state.history[ec->fir_state.curr_pos] *
335 (int)ec->fir_state.history[ec->fir_state.curr_pos];
336 ec->pstates +=
337 ((new - old) + (1 << (ec->log2taps - 1))) >> ec->log2taps;
338 if (ec->pstates < 0)
339 ec->pstates = 0;
340 }
341
342
343
344 ec->ltxacc += abs(tx) - ec->ltx;
345 ec->ltx = (ec->ltxacc + (1 << 4)) >> 5;
346 ec->lrxacc += abs(rx) - ec->lrx;
347 ec->lrx = (ec->lrxacc + (1 << 4)) >> 5;
348
349
350
351 ec->fir_state.coeffs = ec->fir_taps16[0];
352 echo_value = fir16(&ec->fir_state, tx);
353 ec->clean = rx - echo_value;
354 ec->lcleanacc += abs(ec->clean) - ec->lclean;
355 ec->lclean = (ec->lcleanacc + (1 << 4)) >> 5;
356
357
358
359 echo_value = fir16(&ec->fir_state_bg, tx);
360 clean_bg = rx - echo_value;
361 ec->lclean_bgacc += abs(clean_bg) - ec->lclean_bg;
362 ec->lclean_bg = (ec->lclean_bgacc + (1 << 4)) >> 5;
363
364
365
366
367
368
369
370 ec->factor = 0;
371 ec->shift = 0;
372 if (!ec->nonupdate_dwell) {
373 int p, logp, shift;
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408 p = MIN_TX_POWER_FOR_ADAPTION + ec->pstates;
409 logp = top_bit(p) + ec->log2taps;
410 shift = 30 - 2 - logp;
411 ec->shift = shift;
412
413 lms_adapt_bg(ec, clean_bg, shift);
414 }
415
416
417
418
419 ec->adapt = 0;
420 if ((ec->lrx > MIN_RX_POWER_FOR_ADAPTION) && (ec->lrx > ec->ltx))
421 ec->nonupdate_dwell = DTD_HANGOVER;
422 if (ec->nonupdate_dwell)
423 ec->nonupdate_dwell--;
424
425
426
427
428
429
430 if ((ec->adaption_mode & ECHO_CAN_USE_ADAPTION) &&
431 (ec->nonupdate_dwell == 0) &&
432
433 (8 * ec->lclean_bg < 7 * ec->lclean) &&
434
435 (8 * ec->lclean_bg < ec->ltx)) {
436 if (ec->cond_met == 6) {
437
438
439
440
441 ec->adapt = 1;
442 memcpy(ec->fir_taps16[0], ec->fir_taps16[1],
443 ec->taps * sizeof(int16_t));
444 } else
445 ec->cond_met++;
446 } else
447 ec->cond_met = 0;
448
449
450
451 ec->clean_nlp = ec->clean;
452 if (ec->adaption_mode & ECHO_CAN_USE_NLP) {
453
454
455
456
457
458
459 if ((16 * ec->lclean < ec->ltx)) {
460
461
462
463
464
465 if (ec->adaption_mode & ECHO_CAN_USE_CNG) {
466 ec->cng_level = ec->lbgn;
467
468
469
470
471
472
473
474
475
476
477
478
479 ec->cng_rndnum =
480 1664525U * ec->cng_rndnum + 1013904223U;
481 ec->cng_filter =
482 ((ec->cng_rndnum & 0xFFFF) - 32768 +
483 5 * ec->cng_filter) >> 3;
484 ec->clean_nlp =
485 (ec->cng_filter * ec->cng_level * 8) >> 14;
486
487 } else if (ec->adaption_mode & ECHO_CAN_USE_CLIP) {
488
489 if (ec->clean_nlp > ec->lbgn)
490 ec->clean_nlp = ec->lbgn;
491 if (ec->clean_nlp < -ec->lbgn)
492 ec->clean_nlp = -ec->lbgn;
493 } else {
494
495
496
497
498 ec->clean_nlp = 0;
499 }
500 } else {
501
502
503
504
505
506
507
508
509
510
511 if (ec->lclean < 40) {
512 ec->lbgn_acc += abs(ec->clean) - ec->lbgn;
513 ec->lbgn = (ec->lbgn_acc + (1 << 11)) >> 12;
514 }
515 }
516 }
517
518
519 if (ec->curr_pos <= 0)
520 ec->curr_pos = ec->taps;
521 ec->curr_pos--;
522
523 if (ec->adaption_mode & ECHO_CAN_DISABLE)
524 ec->clean_nlp = rx;
525
526
527
528 return (int16_t) ec->clean_nlp << 1;
529 }
530 EXPORT_SYMBOL_GPL(oslec_update);
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554 int16_t oslec_hpf_tx(struct oslec_state *ec, int16_t tx)
555 {
556 int tmp;
557 int tmp1;
558
559 if (ec->adaption_mode & ECHO_CAN_USE_TX_HPF) {
560 tmp = tx << 15;
561
562
563
564
565
566
567
568
569
570 tmp -= (tmp >> 4);
571
572 ec->tx_1 += -(ec->tx_1 >> DC_LOG2BETA) + tmp - ec->tx_2;
573 tmp1 = ec->tx_1 >> 15;
574 if (tmp1 > 32767)
575 tmp1 = 32767;
576 if (tmp1 < -32767)
577 tmp1 = -32767;
578 tx = tmp1;
579 ec->tx_2 = tmp;
580 }
581
582 return tx;
583 }
584 EXPORT_SYMBOL_GPL(oslec_hpf_tx);
585
586 MODULE_LICENSE("GPL");
587 MODULE_AUTHOR("David Rowe");
588 MODULE_DESCRIPTION("Open Source Line Echo Canceller");
589 MODULE_VERSION("0.3.0");