annotate spandsp-0.0.3/spandsp-0.0.3/src/echo.c @ 5:f762bf195c4b

import spandsp-0.0.3
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 16:00:21 +0200
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
5
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
1 /*
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
2 * SpanDSP - a series of DSP components for telephony
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
3 *
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
4 * echo.c - A line echo canceller. This code is being developed
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
5 * against and partially complies with G168.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
6 *
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
7 * Written by Steve Underwood <steveu@coppice.org>
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
8 * and David Rowe <david_at_rowetel_dot_com>
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
9 *
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
10 * Copyright (C) 2001, 2003 Steve Underwood, 2007 David Rowe
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
11 *
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
12 * Based on a bit from here, a bit from there, eye of toad, ear of
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
13 * bat, 15 years of failed attempts by David and a few fried brain
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
14 * cells.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
15 *
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
16 * All rights reserved.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
17 *
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
18 * This program is free software; you can redistribute it and/or modify
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
19 * it under the terms of the GNU General Public License version 2, as
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
20 * published by the Free Software Foundation.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
21 *
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
22 * This program is distributed in the hope that it will be useful,
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
25 * GNU General Public License for more details.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
26 *
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
27 * You should have received a copy of the GNU General Public License
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
28 * along with this program; if not, write to the Free Software
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
29 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
30 *
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
31 * $Id: echo.c,v 1.20 2006/12/01 18:00:48 steveu Exp $
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
32 */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
33
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
34 /*! \file */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
35
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
36 /* Implementation Notes
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
37 David Rowe
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
38 April 2007
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
39
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
40 This code started life as Steve's NLMS algorithm with a tap
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
41 rotation algorithm to handle divergence during double talk. I
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
42 added a Geigel Double Talk Detector (DTD) [2] and performed some
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
43 G168 tests. However I had trouble meeting the G168 requirements,
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
44 especially for double talk - there were always cases where my DTD
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
45 failed, for example where near end speech was under the 6dB
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
46 threshold required for declaring double talk.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
47
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
48 So I tried a two path algorithm [1], which has so far given better
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
49 results. The original tap rotation/Geigel algorithm is available
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
50 in SVN http://svn.rowetel.com/software/oslec/tags/before_16bit.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
51 It's probably possible to make it work if some one wants to put some
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
52 serious work into it.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
53
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
54 At present no special treatment is provided for tones, which
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
55 generally cause NLMS algorithms to diverge. Initial runs of a
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
56 subset of the G168 tests for tones (e.g ./echo_test 6) show the
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
57 current algorithm is passing OK, which is kind of surprising. The
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
58 full set of tests needs to be performed to confirm this result.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
59
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
60 One other interesting change is that I have managed to get the NLMS
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
61 code to work with 16 bit coefficients, rather than the original 32
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
62 bit coefficents. This reduces the MIPs and storage required.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
63 I evaulated the 16 bit port using g168_tests.sh and listening tests
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
64 on 4 real-world samples.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
65
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
66 I also attempted the implementation of a block based NLMS update
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
67 [2] but although this passes g168_tests.sh it didn't converge well
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
68 on the real-world samples. I have no idea why, perhaps a scaling
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
69 problem. The block based code is also available in SVN
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
70 http://svn.rowetel.com/software/oslec/tags/before_16bit. If this
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
71 code can be debugged, it will lead to further reduction in MIPS, as
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
72 the block update code maps nicely onto DSP instruction sets (it's a
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
73 dot product) compared to the current sample-by-sample update.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
74
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
75 Steve also has some nice notes on echo cancellers in echo.h
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
76
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
77
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
78 References:
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
79
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
80 [1] Ochiai, Areseki, and Ogihara, "Echo Canceller with Two Echo
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
81 Path Models", IEEE Transactions on communications, COM-25,
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
82 No. 6, June
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
83 1977.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
84 http://www.rowetel.com/images/echo/dual_path_paper.pdf
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
85
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
86 [2] The classic, very useful paper that tells you how to
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
87 actually build a real world echo canceller:
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
88 Messerschmitt, Hedberg, Cole, Haoui, Winship, "Digital Voice
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
89 Echo Canceller with a TMS320020,
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
90 http://www.rowetel.com/images/echo/spra129.pdf
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
91
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
92 [3] I have written a series of blog posts on this work, here is
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
93 Part 1: http://www.rowetel.com/blog/?p=18
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
94
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
95 [4] The source code http://svn.rowetel.com/software/oslec/
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
96
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
97 [5] A nice reference on LMS filters:
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
98 http://en.wikipedia.org/wiki/Least_mean_squares_filter
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
99
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
100 Credits:
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
101
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
102 Thanks to Steve Underwood, Jean-Marc Valin, and Ramakrishnan
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
103 Muthukrishnan for their suggestions and email discussions. Thanks
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
104 also to those people who collected echo samples for me such as
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
105 Mark, Pawel, and Pavel.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
106 */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
107
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
108 #ifdef HAVE_CONFIG_H
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
109 #include <config.h>
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
110 #endif
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
111 #ifdef __KERNEL__
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
112 #include <linux/kernel.h> /* We're doing kernel work */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
113 #include <linux/module.h>
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
114 #include <linux/kernel.h>
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
115 #include <linux/slab.h>
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
116 #define malloc(a) kmalloc((a), GFP_KERNEL)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
117 #define free(a) kfree(a)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
118 #else
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
119 #include <stdio.h>
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
120 #include <stdlib.h>
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
121 #include <string.h>
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
122 #include <inttypes.h>
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
123
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
124 #endif
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
125
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
126 #include "spandsp/bit_operations.h"
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
127 #include "spandsp/echo.h"
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
128
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
129 #if !defined(NULL)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
130 #define NULL (void *) 0
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
131 #endif
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
132 #if !defined(FALSE)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
133 #define FALSE 0
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
134 #endif
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
135 #if !defined(TRUE)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
136 #define TRUE (!FALSE)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
137 #endif
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
138
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
139 #define MIN_TX_POWER_FOR_ADAPTION 64
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
140 #define MIN_RX_POWER_FOR_ADAPTION 64
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
141 #define DTD_HANGOVER 600 /* 600 samples, or 75ms */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
142 #define DC_LOG2BETA 3 /* log2() of DC filter Beta */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
143
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
144 /*-----------------------------------------------------------------------*\
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
145
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
146 FUNCTIONS
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
147
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
148 \*-----------------------------------------------------------------------*/
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
149
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
150 /* adapting coeffs using the traditional stochastic descent (N)LMS algorithm */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
151
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
152
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
153 #ifdef __BLACKFIN_ASM__
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
154 static void __inline__ lms_adapt_bg(echo_can_state_t *ec, int clean, int shift)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
155 {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
156 int i, j;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
157 int offset1;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
158 int offset2;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
159 int factor;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
160 int exp;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
161 int16_t *phist;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
162 int n;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
163
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
164 if (shift > 0)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
165 factor = clean << shift;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
166 else
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
167 factor = clean >> -shift;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
168
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
169 /* Update the FIR taps */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
170
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
171 offset2 = ec->curr_pos;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
172 offset1 = ec->taps - offset2;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
173 phist = &ec->fir_state_bg.history[offset2];
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
174
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
175 /* st: and en: help us locate the assembler in echo.s */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
176
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
177 //asm("st:");
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
178 n = ec->taps;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
179 for (i = 0, j = offset2; i < n; i++, j++)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
180 {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
181 exp = *phist++ * factor;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
182 ec->fir_taps16[1][i] += (int16_t) ((exp+(1<<14)) >> 15);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
183 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
184 //asm("en:");
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
185
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
186 /* Note the asm for the inner loop above generated by Blackfin gcc
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
187 4.1.1 is pretty good (note even parallel instructions used):
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
188
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
189 R0 = W [P0++] (X);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
190 R0 *= R2;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
191 R0 = R0 + R3 (NS) ||
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
192 R1 = W [P1] (X) ||
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
193 nop;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
194 R0 >>>= 15;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
195 R0 = R0 + R1;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
196 W [P1++] = R0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
197
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
198 A block based update algorithm would be much faster but the
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
199 above can't be improved on much. Every instruction saved in
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
200 the loop above is 2 MIPs/ch! The for loop above is where the
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
201 Blackfin spends most of it's time - about 17 MIPs/ch measured
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
202 with speedtest.c with 256 taps (32ms). Write-back and
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
203 Write-through cache gave about the same performance.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
204 */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
205 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
206
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
207 /*
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
208 IDEAS for further optimisation of lms_adapt_bg():
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
209
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
210 1/ The rounding is quite costly. Could we keep as 32 bit coeffs
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
211 then make filter pluck the MS 16-bits of the coeffs when filtering?
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
212 However this would lower potential optimisation of filter, as I
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
213 think the dual-MAC architecture requires packed 16 bit coeffs.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
214
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
215 2/ Block based update would be more efficient, as per comments above,
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
216 could use dual MAC architecture.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
217
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
218 3/ Look for same sample Blackfin LMS code, see if we can get dual-MAC
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
219 packing.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
220
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
221 4/ Execute the whole e/c in a block of say 20ms rather than sample
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
222 by sample. Processing a few samples every ms is inefficient.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
223 */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
224
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
225 #else
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
226 static __inline__ void lms_adapt_bg(echo_can_state_t *ec, int clean, int shift)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
227 {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
228 int i;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
229
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
230 int offset1;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
231 int offset2;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
232 int factor;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
233 int exp;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
234
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
235 if (shift > 0)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
236 factor = clean << shift;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
237 else
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
238 factor = clean >> -shift;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
239
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
240 /* Update the FIR taps */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
241
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
242 offset2 = ec->curr_pos;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
243 offset1 = ec->taps - offset2;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
244
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
245 for (i = ec->taps - 1; i >= offset1; i--)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
246 {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
247 exp = (ec->fir_state_bg.history[i - offset1]*factor);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
248 ec->fir_taps16[1][i] += (int16_t) ((exp+(1<<14)) >> 15);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
249 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
250 for ( ; i >= 0; i--)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
251 {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
252 exp = (ec->fir_state_bg.history[i + offset2]*factor);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
253 ec->fir_taps16[1][i] += (int16_t) ((exp+(1<<14)) >> 15);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
254 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
255 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
256 #endif
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
257
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
258 /*- End of function --------------------------------------------------------*/
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
259
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
260 echo_can_state_t *echo_can_create(int len, int adaption_mode)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
261 {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
262 echo_can_state_t *ec;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
263 int i;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
264 int j;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
265
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
266 ec = (echo_can_state_t *) malloc(sizeof(*ec));
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
267 if (ec == NULL)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
268 return NULL;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
269 memset(ec, 0, sizeof(*ec));
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
270
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
271 ec->taps = len;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
272 ec->log2taps = top_bit(len);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
273 ec->curr_pos = ec->taps - 1;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
274
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
275 for (i = 0; i < 2; i++)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
276 {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
277 if ((ec->fir_taps16[i] = (int16_t *) malloc((ec->taps)*sizeof(int16_t))) == NULL)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
278 {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
279 for (j = 0; j < i; j++)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
280 free(ec->fir_taps16[j]);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
281 free(ec);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
282 return NULL;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
283 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
284 memset(ec->fir_taps16[i], 0, (ec->taps)*sizeof(int16_t));
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
285 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
286
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
287 fir16_create(&ec->fir_state,
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
288 ec->fir_taps16[0],
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
289 ec->taps);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
290 fir16_create(&ec->fir_state_bg,
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
291 ec->fir_taps16[1],
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
292 ec->taps);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
293
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
294 for(i=0; i<5; i++) {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
295 ec->xvtx[i] = ec->yvtx[i] = ec->xvrx[i] = ec->yvrx[i] = 0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
296 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
297
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
298 ec->cng_level = 1000;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
299 echo_can_adaption_mode(ec, adaption_mode);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
300
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
301 ec->snapshot = (int16_t*)malloc(ec->taps*sizeof(int16_t));
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
302 memset(ec->snapshot, 0, sizeof(int16_t)*ec->taps);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
303
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
304 ec->cond_met = 0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
305 ec->Pstates = 0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
306 ec->Ltxacc = ec->Lrxacc = ec->Lcleanacc = ec->Lclean_bgacc = 0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
307 ec->Ltx = ec->Lrx = ec->Lclean = ec->Lclean_bg = 0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
308 ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
309 ec->Lbgn = ec->Lbgn_acc = 0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
310 ec->Lbgn_upper = 200;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
311 ec->Lbgn_upper_acc = ec->Lbgn_upper << 13;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
312
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
313 return ec;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
314 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
315 /*- End of function --------------------------------------------------------*/
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
316
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
317 void echo_can_free(echo_can_state_t *ec)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
318 {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
319 int i;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
320
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
321 fir16_free(&ec->fir_state);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
322 fir16_free(&ec->fir_state_bg);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
323 for (i = 0; i < 2; i++)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
324 free(ec->fir_taps16[i]);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
325 free(ec->snapshot);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
326 free(ec);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
327 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
328 /*- End of function --------------------------------------------------------*/
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
329
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
330 void echo_can_adaption_mode(echo_can_state_t *ec, int adaption_mode)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
331 {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
332 ec->adaption_mode = adaption_mode;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
333 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
334 /*- End of function --------------------------------------------------------*/
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
335
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
336 void echo_can_flush(echo_can_state_t *ec)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
337 {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
338 int i;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
339
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
340 ec->Ltxacc = ec->Lrxacc = ec->Lcleanacc = ec->Lclean_bgacc = 0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
341 ec->Ltx = ec->Lrx = ec->Lclean = ec->Lclean_bg = 0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
342 ec->tx_1 = ec->tx_2 = ec->rx_1 = ec->rx_2 = 0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
343
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
344 ec->Lbgn = ec->Lbgn_acc = 0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
345 ec->Lbgn_upper = 200;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
346 ec->Lbgn_upper_acc = ec->Lbgn_upper << 13;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
347
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
348 ec->nonupdate_dwell = 0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
349
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
350 fir16_flush(&ec->fir_state);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
351 fir16_flush(&ec->fir_state_bg);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
352 ec->fir_state.curr_pos = ec->taps - 1;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
353 ec->fir_state_bg.curr_pos = ec->taps - 1;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
354 for (i = 0; i < 2; i++)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
355 memset(ec->fir_taps16[i], 0, ec->taps*sizeof(int16_t));
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
356
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
357 ec->curr_pos = ec->taps - 1;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
358 ec->Pstates = 0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
359 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
360 /*- End of function --------------------------------------------------------*/
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
361
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
362 void echo_can_snapshot(echo_can_state_t *ec) {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
363 memcpy(ec->snapshot, ec->fir_taps16[0], ec->taps*sizeof(int16_t));
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
364 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
365 /*- End of function --------------------------------------------------------*/
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
366
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
367 /* Dual Path Echo Canceller ------------------------------------------------*/
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
368
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
369 int16_t echo_can_update(echo_can_state_t *ec, int16_t tx, int16_t rx)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
370 {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
371 int32_t echo_value;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
372 int clean_bg;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
373 int tmp, tmp1;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
374
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
375 /* Input scaling was found be required to prevent problems when tx
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
376 starts clipping. Another possible way to handle this would be the
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
377 filter coefficent scaling. */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
378
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
379 ec->tx = tx; ec->rx = rx;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
380 tx >>=1;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
381 rx >>=1;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
382
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
383 /*
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
384 Filter DC, 3dB point is 160Hz (I think), note 32 bit precision required
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
385 otherwise values do not track down to 0. Zero at DC, Pole at (1-Beta)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
386 only real axis. Some chip sets (like Si labs) don't need
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
387 this, but something like a $10 X100P card does. Any DC really slows
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
388 down convergence.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
389
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
390 Note: removes some low frequency from the signal, this reduces
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
391 the speech quality when listening to samples through headphones
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
392 but may not be obvious through a telephone handset.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
393
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
394 Note that the 3dB frequency in radians is approx Beta, e.g. for
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
395 Beta = 2^(-3) = 0.125, 3dB freq is 0.125 rads = 159Hz.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
396 */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
397
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
398 if (ec->adaption_mode & ECHO_CAN_USE_RX_HPF) {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
399 tmp = rx << 15;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
400 #if 1
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
401 /* Make sure the gain of the HPF is 1.0. This can still saturate a little under
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
402 impulse conditions, and it might roll to 32768 and need clipping on sustained peak
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
403 level signals. However, the scale of such clipping is small, and the error due to
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
404 any saturation should not markedly affect the downstream processing. */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
405 tmp -= (tmp >> 4);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
406 #endif
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
407 ec->rx_1 += -(ec->rx_1>>DC_LOG2BETA) + tmp - ec->rx_2;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
408
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
409 /* hard limit filter to prevent clipping. Note that at this stage
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
410 rx should be limited to +/- 16383 due to right shift above */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
411 tmp1 = ec->rx_1 >> 15;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
412 if (tmp1 > 16383) tmp1 = 16383;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
413 if (tmp1 < -16383) tmp1 = -16383;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
414 rx = tmp1;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
415 ec->rx_2 = tmp;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
416 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
417
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
418 /* Block average of power in the filter states. Used for
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
419 adaption power calculation. */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
420
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
421 {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
422 int new, old;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
423
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
424 /* efficient "out with the old and in with the new" algorithm so
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
425 we don't have to recalculate over the whole block of
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
426 samples. */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
427 new = (int)tx * (int)tx;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
428 old = (int)ec->fir_state.history[ec->fir_state.curr_pos] *
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
429 (int)ec->fir_state.history[ec->fir_state.curr_pos];
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
430 ec->Pstates += ((new - old) + (1<<(ec->log2taps-1))) >> ec->log2taps;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
431 if (ec->Pstates < 0) ec->Pstates = 0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
432 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
433
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
434 /* Calculate short term average levels using simple single pole IIRs */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
435
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
436 ec->Ltxacc += abs(tx) - ec->Ltx;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
437 ec->Ltx = (ec->Ltxacc + (1<<4)) >> 5;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
438 ec->Lrxacc += abs(rx) - ec->Lrx;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
439 ec->Lrx = (ec->Lrxacc + (1<<4)) >> 5;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
440
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
441 /* Foreground filter ---------------------------------------------------*/
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
442
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
443 ec->fir_state.coeffs = ec->fir_taps16[0];
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
444 echo_value = fir16(&ec->fir_state, tx);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
445 ec->clean = rx - echo_value;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
446 ec->Lcleanacc += abs(ec->clean) - ec->Lclean;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
447 ec->Lclean = (ec->Lcleanacc + (1<<4)) >> 5;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
448
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
449 /* Background filter ---------------------------------------------------*/
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
450
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
451 echo_value = fir16(&ec->fir_state_bg, tx);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
452 clean_bg = rx - echo_value;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
453 ec->Lclean_bgacc += abs(clean_bg) - ec->Lclean_bg;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
454 ec->Lclean_bg = (ec->Lclean_bgacc + (1<<4)) >> 5;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
455
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
456 /* Background Filter adaption -----------------------------------------*/
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
457
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
458 /* Almost always adap bg filter, just simple DT and energy
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
459 detection to minimise adaption in cases of strong double talk.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
460 However this is not critical for the dual path algorithm.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
461 */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
462 ec->factor = 0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
463 ec->shift = 0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
464 if ((ec->nonupdate_dwell == 0)) {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
465 int P, logP, shift;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
466
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
467 /* Determine:
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
468
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
469 f = Beta * clean_bg_rx/P ------ (1)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
470
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
471 where P is the total power in the filter states.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
472
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
473 The Boffins have shown that if we obey (1) we converge
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
474 quickly and avoid instability.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
475
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
476 The correct factor f must be in Q30, as this is the fixed
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
477 point format required by the lms_adapt_bg() function,
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
478 therefore the scaled version of (1) is:
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
479
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
480 (2^30) * f = (2^30) * Beta * clean_bg_rx/P
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
481 factor = (2^30) * Beta * clean_bg_rx/P ----- (2)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
482
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
483 We have chosen Beta = 0.25 by experiment, so:
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
484
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
485 factor = (2^30) * (2^-2) * clean_bg_rx/P
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
486
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
487 (30 - 2 - log2(P))
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
488 factor = clean_bg_rx 2 ----- (3)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
489
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
490 To avoid a divide we approximate log2(P) as top_bit(P),
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
491 which returns the position of the highest non-zero bit in
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
492 P. This approximation introduces an error as large as a
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
493 factor of 2, but the algorithm seems to handle it OK.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
494
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
495 Come to think of it a divide may not be a big deal on a
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
496 modern DSP, so its probably worth checking out the cycles
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
497 for a divide versus a top_bit() implementation.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
498 */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
499
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
500 P = MIN_TX_POWER_FOR_ADAPTION + ec->Pstates;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
501 logP = top_bit(P) + ec->log2taps;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
502 shift = 30 - 2 - logP;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
503 ec->shift = shift;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
504
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
505 lms_adapt_bg(ec, clean_bg, shift);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
506 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
507
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
508 /* very simple DTD to make sure we dont try and adapt with strong
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
509 near end speech */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
510
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
511 ec->adapt = 0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
512 if ((ec->Lrx > MIN_RX_POWER_FOR_ADAPTION) && (ec->Lrx > ec->Ltx))
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
513 ec->nonupdate_dwell = DTD_HANGOVER;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
514 if (ec->nonupdate_dwell)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
515 ec->nonupdate_dwell--;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
516
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
517 /* Transfer logic ------------------------------------------------------*/
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
518
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
519 /* These conditions are from the dual path paper [1], I messed with
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
520 them a bit to improve performance. */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
521
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
522 if ((ec->adaption_mode & ECHO_CAN_USE_ADAPTION) &&
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
523 (ec->nonupdate_dwell == 0) &&
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
524 (8*ec->Lclean_bg < 7*ec->Lclean) /* (ec->Lclean_bg < 0.875*ec->Lclean) */ &&
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
525 (8*ec->Lclean_bg < ec->Ltx) /* (ec->Lclean_bg < 0.125*ec->Ltx) */ )
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
526 {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
527 if (ec->cond_met == 6) {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
528 /* BG filter has had better results for 6 consecutive samples */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
529 ec->adapt = 1;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
530 memcpy(ec->fir_taps16[0], ec->fir_taps16[1], ec->taps*sizeof(int16_t));
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
531 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
532 else
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
533 ec->cond_met++;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
534 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
535 else
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
536 ec->cond_met = 0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
537
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
538 /* Non-Linear Processing ---------------------------------------------------*/
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
539
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
540 ec->clean_nlp = ec->clean;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
541 if (ec->adaption_mode & ECHO_CAN_USE_NLP)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
542 {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
543 /* Non-linear processor - a fancy way to say "zap small signals, to avoid
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
544 residual echo due to (uLaw/ALaw) non-linearity in the channel.". */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
545
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
546 if ((16*ec->Lclean < ec->Ltx))
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
547 {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
548 /* Our e/c has improved echo by at least 24 dB (each factor of 2 is 6dB,
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
549 so 2*2*2*2=16 is the same as 6+6+6+6=24dB) */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
550 if (ec->adaption_mode & ECHO_CAN_USE_CNG)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
551 {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
552 ec->cng_level = ec->Lbgn;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
553
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
554 /* Very elementary comfort noise generation. Just random
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
555 numbers rolled off very vaguely Hoth-like. DR: This
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
556 noise doesn't sound quite right to me - I suspect there
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
557 are some overlfow issues in the filtering as it's too
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
558 "crackly". TODO: debug this, maybe just play noise at
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
559 high level or look at spectrum.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
560 */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
561
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
562 ec->cng_rndnum = 1664525U*ec->cng_rndnum + 1013904223U;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
563 ec->cng_filter = ((ec->cng_rndnum & 0xFFFF) - 32768 + 5*ec->cng_filter) >> 3;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
564 ec->clean_nlp = (ec->cng_filter*ec->cng_level*8) >> 14;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
565
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
566 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
567 else if (ec->adaption_mode & ECHO_CAN_USE_CLIP)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
568 {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
569 /* This sounds much better than CNG */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
570 if (ec->clean_nlp > ec->Lbgn)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
571 ec->clean_nlp = ec->Lbgn;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
572 if (ec->clean_nlp < -ec->Lbgn)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
573 ec->clean_nlp = -ec->Lbgn;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
574 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
575 else
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
576 {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
577 /* just mute the residual, doesn't sound very good, used mainly
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
578 in G168 tests */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
579 ec->clean_nlp = 0;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
580 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
581 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
582 else {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
583 /* Background noise estimator. I tried a few algorithms
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
584 here without much luck. This very simple one seems to
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
585 work best, we just average the level using a slow (1 sec
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
586 time const) filter if the current level is less than a
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
587 (experimentally derived) constant. This means we dont
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
588 include high level signals like near end speech. When
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
589 combined with CNG or especially CLIP seems to work OK.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
590 */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
591 if (ec->Lclean < 40) {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
592 ec->Lbgn_acc += abs(ec->clean) - ec->Lbgn;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
593 ec->Lbgn = (ec->Lbgn_acc + (1<<11)) >> 12;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
594 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
595 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
596 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
597
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
598 /* Roll around the taps buffer */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
599 if (ec->curr_pos <= 0)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
600 ec->curr_pos = ec->taps;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
601 ec->curr_pos--;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
602
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
603 if (ec->adaption_mode & ECHO_CAN_DISABLE)
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
604 ec->clean_nlp = rx;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
605
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
606 /* Output scaled back up again to match input scaling */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
607
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
608 return (int16_t) ec->clean_nlp << 1;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
609 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
610
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
611 /*- End of function --------------------------------------------------------*/
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
612
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
613 /* This function is seperated from the echo canceller is it is usually called
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
614 as part of the tx process. See rx HP (DC blocking) filter above, it's
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
615 the same design.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
616
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
617 Some soft phones send speech signals with a lot of low frequency
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
618 energy, e.g. down to 20Hz. This can make the hybrid non-linear
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
619 which causes the echo canceller to fall over. This filter can help
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
620 by removing any low frequency before it gets to the tx port of the
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
621 hybrid.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
622
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
623 It can also help by removing and DC in the tx signal. DC is bad
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
624 for LMS algorithms.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
625
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
626 This is one of the classic DC removal filters, adjusted to provide sufficient
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
627 bass rolloff to meet the above requirement to protect hybrids from things that
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
628 upset them. The difference between successive samples produces a lousy HPF, and
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
629 then a suitably placed pole flattens things out. The final result is a nicely
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
630 rolled off bass end. The filtering is implemented with extended fractional
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
631 precision, which noise shapes things, giving very clean DC removal.
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
632 */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
633
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
634 int16_t echo_can_hpf_tx(echo_can_state_t *ec, int16_t tx) {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
635 int tmp, tmp1;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
636
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
637 if (ec->adaption_mode & ECHO_CAN_USE_TX_HPF) {
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
638 tmp = tx << 15;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
639 #if 1
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
640 /* Make sure the gain of the HPF is 1.0. The first can still saturate a little under
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
641 impulse conditions, and it might roll to 32768 and need clipping on sustained peak
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
642 level signals. However, the scale of such clipping is small, and the error due to
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
643 any saturation should not markedly affect the downstream processing. */
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
644 tmp -= (tmp >> 4);
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
645 #endif
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
646 ec->tx_1 += -(ec->tx_1>>DC_LOG2BETA) + tmp - ec->tx_2;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
647 tmp1 = ec->tx_1 >> 15;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
648 if (tmp1 > 32767) tmp1 = 32767;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
649 if (tmp1 < -32767) tmp1 = -32767;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
650 tx = tmp1;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
651 ec->tx_2 = tmp;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
652 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
653
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
654 return tx;
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
655 }
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
656
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
657 /*- End of function --------------------------------------------------------*/
f762bf195c4b import spandsp-0.0.3
Peter Meerwald <pmeerw@cosy.sbg.ac.at>
parents:
diff changeset
658 /*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.