xref: /aosp_15_r20/external/speex/tmv/mdf_tm.h (revision 28e138c64d234588b5cd2a8a403b584bd3036e4e)
1*28e138c6SAndroid Build Coastguard Worker /* Copyright (C) 2007 Hong Zhiqian */
2*28e138c6SAndroid Build Coastguard Worker /**
3*28e138c6SAndroid Build Coastguard Worker    @file mdf_tm.h
4*28e138c6SAndroid Build Coastguard Worker    @author Hong Zhiqian
5*28e138c6SAndroid Build Coastguard Worker    @brief Various compatibility routines for Speex (TriMedia version)
6*28e138c6SAndroid Build Coastguard Worker */
7*28e138c6SAndroid Build Coastguard Worker /*
8*28e138c6SAndroid Build Coastguard Worker    Redistribution and use in source and binary forms, with or without
9*28e138c6SAndroid Build Coastguard Worker    modification, are permitted provided that the following conditions
10*28e138c6SAndroid Build Coastguard Worker    are met:
11*28e138c6SAndroid Build Coastguard Worker 
12*28e138c6SAndroid Build Coastguard Worker    - Redistributions of source code must retain the above copyright
13*28e138c6SAndroid Build Coastguard Worker    notice, this list of conditions and the following disclaimer.
14*28e138c6SAndroid Build Coastguard Worker 
15*28e138c6SAndroid Build Coastguard Worker    - Redistributions in binary form must reproduce the above copyright
16*28e138c6SAndroid Build Coastguard Worker    notice, this list of conditions and the following disclaimer in the
17*28e138c6SAndroid Build Coastguard Worker    documentation and/or other materials provided with the distribution.
18*28e138c6SAndroid Build Coastguard Worker 
19*28e138c6SAndroid Build Coastguard Worker    - Neither the name of the Xiph.org Foundation nor the names of its
20*28e138c6SAndroid Build Coastguard Worker    contributors may be used to endorse or promote products derived from
21*28e138c6SAndroid Build Coastguard Worker    this software without specific prior written permission.
22*28e138c6SAndroid Build Coastguard Worker 
23*28e138c6SAndroid Build Coastguard Worker    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24*28e138c6SAndroid Build Coastguard Worker    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25*28e138c6SAndroid Build Coastguard Worker    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26*28e138c6SAndroid Build Coastguard Worker    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
27*28e138c6SAndroid Build Coastguard Worker    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28*28e138c6SAndroid Build Coastguard Worker    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29*28e138c6SAndroid Build Coastguard Worker    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30*28e138c6SAndroid Build Coastguard Worker    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31*28e138c6SAndroid Build Coastguard Worker    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32*28e138c6SAndroid Build Coastguard Worker    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33*28e138c6SAndroid Build Coastguard Worker    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*28e138c6SAndroid Build Coastguard Worker */
35*28e138c6SAndroid Build Coastguard Worker #include <ops/custom_defs.h>
36*28e138c6SAndroid Build Coastguard Worker #include "profile_tm.h"
37*28e138c6SAndroid Build Coastguard Worker 
38*28e138c6SAndroid Build Coastguard Worker // shifted power spectrum to fftwrap.c so that optimisation can be shared between mdf.c and preprocess.c
39*28e138c6SAndroid Build Coastguard Worker #define OVERRIDE_POWER_SPECTRUM
40*28e138c6SAndroid Build Coastguard Worker 
41*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
42*28e138c6SAndroid Build Coastguard Worker 
43*28e138c6SAndroid Build Coastguard Worker #else
44*28e138c6SAndroid Build Coastguard Worker 
45*28e138c6SAndroid Build Coastguard Worker #define OVERRIDE_FILTER_DC_NOTCH16
filter_dc_notch16(const spx_int16_t * restrict in,float radius,float * restrict out,int len,float * restrict mem)46*28e138c6SAndroid Build Coastguard Worker void filter_dc_notch16(
47*28e138c6SAndroid Build Coastguard Worker 	const spx_int16_t * restrict in,
48*28e138c6SAndroid Build Coastguard Worker 	float radius,
49*28e138c6SAndroid Build Coastguard Worker 	float * restrict out,
50*28e138c6SAndroid Build Coastguard Worker 	int len,
51*28e138c6SAndroid Build Coastguard Worker 	float * restrict mem
52*28e138c6SAndroid Build Coastguard Worker )
53*28e138c6SAndroid Build Coastguard Worker {
54*28e138c6SAndroid Build Coastguard Worker 	register int i;
55*28e138c6SAndroid Build Coastguard Worker 	register float den2, r1;
56*28e138c6SAndroid Build Coastguard Worker 	register float mem0, mem1;
57*28e138c6SAndroid Build Coastguard Worker 
58*28e138c6SAndroid Build Coastguard Worker 	FILTERDCNOTCH16_START();
59*28e138c6SAndroid Build Coastguard Worker 
60*28e138c6SAndroid Build Coastguard Worker 	r1 = 1 - radius;
61*28e138c6SAndroid Build Coastguard Worker 	den2 = (radius * radius) + (0.7 * r1 * r1);
62*28e138c6SAndroid Build Coastguard Worker 	mem0 = mem[0];
63*28e138c6SAndroid Build Coastguard Worker 	mem1 = mem[1];
64*28e138c6SAndroid Build Coastguard Worker 
65*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_FILTERDCNOTCH16)
66*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=4
67*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=1
68*28e138c6SAndroid Build Coastguard Worker #endif
69*28e138c6SAndroid Build Coastguard Worker 	for ( i=0 ; i<len ; ++i )
70*28e138c6SAndroid Build Coastguard Worker 	{
71*28e138c6SAndroid Build Coastguard Worker 		register float vin  = in[i];
72*28e138c6SAndroid Build Coastguard Worker 		register float vout = mem0 + vin;
73*28e138c6SAndroid Build Coastguard Worker 		register float rvout = radius * vout;
74*28e138c6SAndroid Build Coastguard Worker 
75*28e138c6SAndroid Build Coastguard Worker 		mem0 = mem1 + 2 * (-vin + rvout);
76*28e138c6SAndroid Build Coastguard Worker 		mem1 = vin - (den2 * vout);
77*28e138c6SAndroid Build Coastguard Worker 
78*28e138c6SAndroid Build Coastguard Worker 		out[i] = rvout;
79*28e138c6SAndroid Build Coastguard Worker 	}
80*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_FILTERDCNOTCH16)
81*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=0
82*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=0
83*28e138c6SAndroid Build Coastguard Worker #endif
84*28e138c6SAndroid Build Coastguard Worker 
85*28e138c6SAndroid Build Coastguard Worker 	mem[0] = mem0;
86*28e138c6SAndroid Build Coastguard Worker 	mem[1] = mem1;
87*28e138c6SAndroid Build Coastguard Worker 
88*28e138c6SAndroid Build Coastguard Worker 	FILTERDCNOTCH16_STOP();
89*28e138c6SAndroid Build Coastguard Worker }
90*28e138c6SAndroid Build Coastguard Worker 
91*28e138c6SAndroid Build Coastguard Worker #define OVERRIDE_MDF_INNER_PROD
mdf_inner_prod(const float * restrict x,const float * restrict y,int len)92*28e138c6SAndroid Build Coastguard Worker float mdf_inner_prod(
93*28e138c6SAndroid Build Coastguard Worker 	const float * restrict x,
94*28e138c6SAndroid Build Coastguard Worker 	const float * restrict y,
95*28e138c6SAndroid Build Coastguard Worker 	int len
96*28e138c6SAndroid Build Coastguard Worker )
97*28e138c6SAndroid Build Coastguard Worker {
98*28e138c6SAndroid Build Coastguard Worker 	register float sum = 0;
99*28e138c6SAndroid Build Coastguard Worker 
100*28e138c6SAndroid Build Coastguard Worker 	MDFINNERPROD_START();
101*28e138c6SAndroid Build Coastguard Worker 
102*28e138c6SAndroid Build Coastguard Worker 	len >>= 1;
103*28e138c6SAndroid Build Coastguard Worker 
104*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_MDFINNERPRODUCT)
105*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=4
106*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=1
107*28e138c6SAndroid Build Coastguard Worker #endif
108*28e138c6SAndroid Build Coastguard Worker 	while(len--)
109*28e138c6SAndroid Build Coastguard Worker 	{
110*28e138c6SAndroid Build Coastguard Worker 		register float acc0, acc1;
111*28e138c6SAndroid Build Coastguard Worker 
112*28e138c6SAndroid Build Coastguard Worker 		acc0 = (*x++) * (*y++);
113*28e138c6SAndroid Build Coastguard Worker 		acc1 = (*x++) * (*y++);
114*28e138c6SAndroid Build Coastguard Worker 
115*28e138c6SAndroid Build Coastguard Worker 		sum	 += acc0 + acc1;
116*28e138c6SAndroid Build Coastguard Worker 	}
117*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_MDFINNERPRODUCT)
118*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=0
119*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=0
120*28e138c6SAndroid Build Coastguard Worker #endif
121*28e138c6SAndroid Build Coastguard Worker 
122*28e138c6SAndroid Build Coastguard Worker 	MDFINNERPROD_STOP();
123*28e138c6SAndroid Build Coastguard Worker 
124*28e138c6SAndroid Build Coastguard Worker 	return sum;
125*28e138c6SAndroid Build Coastguard Worker }
126*28e138c6SAndroid Build Coastguard Worker 
127*28e138c6SAndroid Build Coastguard Worker #define OVERRIDE_SPECTRAL_MUL_ACCUM
spectral_mul_accum(const float * restrict X,const float * restrict Y,float * restrict acc,int N,int M)128*28e138c6SAndroid Build Coastguard Worker void spectral_mul_accum(
129*28e138c6SAndroid Build Coastguard Worker 	const float * restrict X,
130*28e138c6SAndroid Build Coastguard Worker 	const float * restrict Y,
131*28e138c6SAndroid Build Coastguard Worker 	float * restrict acc,
132*28e138c6SAndroid Build Coastguard Worker 	int N, int M
133*28e138c6SAndroid Build Coastguard Worker )
134*28e138c6SAndroid Build Coastguard Worker {
135*28e138c6SAndroid Build Coastguard Worker 	register int i, j;
136*28e138c6SAndroid Build Coastguard Worker 	register float Xi, Yi, Xii, Yii;
137*28e138c6SAndroid Build Coastguard Worker 	register int _N;
138*28e138c6SAndroid Build Coastguard Worker 
139*28e138c6SAndroid Build Coastguard Worker 	SPECTRALMULACCUM_START();
140*28e138c6SAndroid Build Coastguard Worker 
141*28e138c6SAndroid Build Coastguard Worker 	acc[0] = X[0] * Y[0];
142*28e138c6SAndroid Build Coastguard Worker 	_N = N-1;
143*28e138c6SAndroid Build Coastguard Worker 
144*28e138c6SAndroid Build Coastguard Worker 	for ( i=1 ; i<_N ; i+=2 )
145*28e138c6SAndroid Build Coastguard Worker 	{
146*28e138c6SAndroid Build Coastguard Worker 		Xi = X[i];
147*28e138c6SAndroid Build Coastguard Worker 		Yi = Y[i];
148*28e138c6SAndroid Build Coastguard Worker 		Xii = X[i+1];
149*28e138c6SAndroid Build Coastguard Worker 		Yii = Y[i+1];
150*28e138c6SAndroid Build Coastguard Worker 
151*28e138c6SAndroid Build Coastguard Worker 		acc[i]	= (Xi  * Yi - Xii * Yii);
152*28e138c6SAndroid Build Coastguard Worker 		acc[i+1]= (Xii * Yi + Xi  * Yii);
153*28e138c6SAndroid Build Coastguard Worker 	}
154*28e138c6SAndroid Build Coastguard Worker 
155*28e138c6SAndroid Build Coastguard Worker 	acc[_N] = X[_N] * Y[_N];
156*28e138c6SAndroid Build Coastguard Worker 
157*28e138c6SAndroid Build Coastguard Worker 	for ( j=1,X+=N,Y+=N ; j<M ; j++ )
158*28e138c6SAndroid Build Coastguard Worker 	{
159*28e138c6SAndroid Build Coastguard Worker 		acc[0] += X[0] * Y[0];
160*28e138c6SAndroid Build Coastguard Worker 
161*28e138c6SAndroid Build Coastguard Worker 		for ( i=1 ; i<N-1 ; i+=2 )
162*28e138c6SAndroid Build Coastguard Worker 		{
163*28e138c6SAndroid Build Coastguard Worker 			Xi = X[i];
164*28e138c6SAndroid Build Coastguard Worker 			Yi = Y[i];
165*28e138c6SAndroid Build Coastguard Worker 			Xii = X[i+1];
166*28e138c6SAndroid Build Coastguard Worker 			Yii = Y[i+1];
167*28e138c6SAndroid Build Coastguard Worker 
168*28e138c6SAndroid Build Coastguard Worker 			acc[i]	+= (Xi  * Yi - Xii * Yii);
169*28e138c6SAndroid Build Coastguard Worker 			acc[i+1]+= (Xii * Yi + Xi  * Yii);
170*28e138c6SAndroid Build Coastguard Worker 		}
171*28e138c6SAndroid Build Coastguard Worker 
172*28e138c6SAndroid Build Coastguard Worker 		acc[_N] += X[_N] * Y[_N];
173*28e138c6SAndroid Build Coastguard Worker 		X += N;
174*28e138c6SAndroid Build Coastguard Worker 		Y += N;
175*28e138c6SAndroid Build Coastguard Worker 	}
176*28e138c6SAndroid Build Coastguard Worker 
177*28e138c6SAndroid Build Coastguard Worker 	SPECTRALMULACCUM_STOP();
178*28e138c6SAndroid Build Coastguard Worker }
179*28e138c6SAndroid Build Coastguard Worker 
180*28e138c6SAndroid Build Coastguard Worker #define OVERRIDE_WEIGHTED_SPECTRAL_MUL_CONJ
weighted_spectral_mul_conj(const float * restrict w,const float p,const float * restrict X,const float * restrict Y,float * restrict prod,int N)181*28e138c6SAndroid Build Coastguard Worker void weighted_spectral_mul_conj(
182*28e138c6SAndroid Build Coastguard Worker 	const float * restrict w,
183*28e138c6SAndroid Build Coastguard Worker 	const float p,
184*28e138c6SAndroid Build Coastguard Worker 	const float * restrict X,
185*28e138c6SAndroid Build Coastguard Worker 	const float * restrict Y,
186*28e138c6SAndroid Build Coastguard Worker 	float * restrict prod,
187*28e138c6SAndroid Build Coastguard Worker 	int N
188*28e138c6SAndroid Build Coastguard Worker )
189*28e138c6SAndroid Build Coastguard Worker {
190*28e138c6SAndroid Build Coastguard Worker 	register int i, j;
191*28e138c6SAndroid Build Coastguard Worker    	register int _N;
192*28e138c6SAndroid Build Coastguard Worker 
193*28e138c6SAndroid Build Coastguard Worker 	WEIGHTEDSPECTRALMULCONJ_START();
194*28e138c6SAndroid Build Coastguard Worker 
195*28e138c6SAndroid Build Coastguard Worker 	prod[0] = p * w[0] * X[0] * Y[0];
196*28e138c6SAndroid Build Coastguard Worker 	_N = N-1;
197*28e138c6SAndroid Build Coastguard Worker 
198*28e138c6SAndroid Build Coastguard Worker 	for (i=1,j=1;i<_N;i+=2,j++)
199*28e138c6SAndroid Build Coastguard Worker 	{
200*28e138c6SAndroid Build Coastguard Worker 		register float W;
201*28e138c6SAndroid Build Coastguard Worker 		register float Xi, Yi, Xii, Yii;
202*28e138c6SAndroid Build Coastguard Worker 
203*28e138c6SAndroid Build Coastguard Worker 		Xi = X[i];
204*28e138c6SAndroid Build Coastguard Worker 		Yi = Y[i];
205*28e138c6SAndroid Build Coastguard Worker 		Xii = X[i+1];
206*28e138c6SAndroid Build Coastguard Worker 		Yii = Y[i+1];
207*28e138c6SAndroid Build Coastguard Worker 		W = p * w[j];
208*28e138c6SAndroid Build Coastguard Worker 
209*28e138c6SAndroid Build Coastguard Worker 
210*28e138c6SAndroid Build Coastguard Worker 		prod[i]	 = W * (Xi  * Yi + Xii * Yii);
211*28e138c6SAndroid Build Coastguard Worker 		prod[i+1]= W * (Xi  * Yii - Xii * Yi);
212*28e138c6SAndroid Build Coastguard Worker 	}
213*28e138c6SAndroid Build Coastguard Worker 
214*28e138c6SAndroid Build Coastguard Worker 	prod[_N] = p * w[j] * X[_N] * Y[_N];
215*28e138c6SAndroid Build Coastguard Worker 
216*28e138c6SAndroid Build Coastguard Worker 	WEIGHTEDSPECTRALMULCONJ_STOP();
217*28e138c6SAndroid Build Coastguard Worker }
218*28e138c6SAndroid Build Coastguard Worker 
219*28e138c6SAndroid Build Coastguard Worker #define OVERRIDE_MDF_ADJUST_PROP
mdf_adjust_prop(const float * restrict W,int N,int M,float * restrict prop)220*28e138c6SAndroid Build Coastguard Worker void mdf_adjust_prop(
221*28e138c6SAndroid Build Coastguard Worker 	const float * restrict W,
222*28e138c6SAndroid Build Coastguard Worker 	int N,
223*28e138c6SAndroid Build Coastguard Worker 	int M,
224*28e138c6SAndroid Build Coastguard Worker 	float * restrict prop
225*28e138c6SAndroid Build Coastguard Worker )
226*28e138c6SAndroid Build Coastguard Worker {
227*28e138c6SAndroid Build Coastguard Worker 	register int i, j;
228*28e138c6SAndroid Build Coastguard Worker 	register float max_sum = 1;
229*28e138c6SAndroid Build Coastguard Worker 	register float prop_sum = 1;
230*28e138c6SAndroid Build Coastguard Worker 
231*28e138c6SAndroid Build Coastguard Worker 	MDFADJUSTPROP_START();
232*28e138c6SAndroid Build Coastguard Worker 
233*28e138c6SAndroid Build Coastguard Worker 	for ( i=0 ; i<M ; ++i )
234*28e138c6SAndroid Build Coastguard Worker 	{
235*28e138c6SAndroid Build Coastguard Worker 		register float tmp = 1;
236*28e138c6SAndroid Build Coastguard Worker 		register int k = i * N;
237*28e138c6SAndroid Build Coastguard Worker 		register int l = k + N;
238*28e138c6SAndroid Build Coastguard Worker 		register float propi;
239*28e138c6SAndroid Build Coastguard Worker 
240*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_MDFADJUSTPROP)
241*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=4
242*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=1
243*28e138c6SAndroid Build Coastguard Worker #endif
244*28e138c6SAndroid Build Coastguard Worker 		for ( j=k ; j<l ; ++j )
245*28e138c6SAndroid Build Coastguard Worker 		{
246*28e138c6SAndroid Build Coastguard Worker 			register float wi = W[j];
247*28e138c6SAndroid Build Coastguard Worker 
248*28e138c6SAndroid Build Coastguard Worker 			tmp += wi * wi;
249*28e138c6SAndroid Build Coastguard Worker 		}
250*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_MDFADJUSTPROP)
251*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=0
252*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=0
253*28e138c6SAndroid Build Coastguard Worker #endif
254*28e138c6SAndroid Build Coastguard Worker 
255*28e138c6SAndroid Build Coastguard Worker 		propi  = spx_sqrt(tmp);
256*28e138c6SAndroid Build Coastguard Worker 		prop[i]= propi;
257*28e138c6SAndroid Build Coastguard Worker 		max_sum= fmux(propi > max_sum, propi, max_sum);
258*28e138c6SAndroid Build Coastguard Worker 	}
259*28e138c6SAndroid Build Coastguard Worker 
260*28e138c6SAndroid Build Coastguard Worker 	for ( i=0 ; i<M ; ++i )
261*28e138c6SAndroid Build Coastguard Worker 	{
262*28e138c6SAndroid Build Coastguard Worker 		register float propi = prop[i];
263*28e138c6SAndroid Build Coastguard Worker 
264*28e138c6SAndroid Build Coastguard Worker 		propi += .1f * max_sum;
265*28e138c6SAndroid Build Coastguard Worker 		prop_sum += propi;
266*28e138c6SAndroid Build Coastguard Worker 		prop[i] = propi;
267*28e138c6SAndroid Build Coastguard Worker 	}
268*28e138c6SAndroid Build Coastguard Worker 
269*28e138c6SAndroid Build Coastguard Worker 	prop_sum = 0.99f / prop_sum;
270*28e138c6SAndroid Build Coastguard Worker 	for ( i=0 ; i<M ; ++i )
271*28e138c6SAndroid Build Coastguard Worker 	{	prop[i] = prop_sum * prop[i];
272*28e138c6SAndroid Build Coastguard Worker 	}
273*28e138c6SAndroid Build Coastguard Worker 
274*28e138c6SAndroid Build Coastguard Worker 	MDFADJUSTPROP_STOP();
275*28e138c6SAndroid Build Coastguard Worker }
276*28e138c6SAndroid Build Coastguard Worker 
277*28e138c6SAndroid Build Coastguard Worker 
278*28e138c6SAndroid Build Coastguard Worker #define OVERRIDE_SPEEX_ECHO_GET_RESIDUAL
speex_echo_get_residual(SpeexEchoState * restrict st,float * restrict residual_echo,int len)279*28e138c6SAndroid Build Coastguard Worker void speex_echo_get_residual(
280*28e138c6SAndroid Build Coastguard Worker 	SpeexEchoState * restrict st,
281*28e138c6SAndroid Build Coastguard Worker 	float * restrict residual_echo,
282*28e138c6SAndroid Build Coastguard Worker 	int len
283*28e138c6SAndroid Build Coastguard Worker )
284*28e138c6SAndroid Build Coastguard Worker {
285*28e138c6SAndroid Build Coastguard Worker 	register int i;
286*28e138c6SAndroid Build Coastguard Worker 	register float leak2, leake;
287*28e138c6SAndroid Build Coastguard Worker 	register int N;
288*28e138c6SAndroid Build Coastguard Worker 	register float * restrict window;
289*28e138c6SAndroid Build Coastguard Worker 	register float * restrict last_y;
290*28e138c6SAndroid Build Coastguard Worker 	register float * restrict y;
291*28e138c6SAndroid Build Coastguard Worker 
292*28e138c6SAndroid Build Coastguard Worker 	SPEEXECHOGETRESIDUAL_START();
293*28e138c6SAndroid Build Coastguard Worker 
294*28e138c6SAndroid Build Coastguard Worker 	window = st->window;
295*28e138c6SAndroid Build Coastguard Worker 	last_y = st->last_y;
296*28e138c6SAndroid Build Coastguard Worker 	y = st->y;
297*28e138c6SAndroid Build Coastguard Worker 	N = st->window_size;
298*28e138c6SAndroid Build Coastguard Worker 
299*28e138c6SAndroid Build Coastguard Worker 
300*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOGETRESIDUAL)
301*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=4
302*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=1
303*28e138c6SAndroid Build Coastguard Worker #endif
304*28e138c6SAndroid Build Coastguard Worker 	for (i=0;i<N;i++)
305*28e138c6SAndroid Build Coastguard Worker 	{	y[i] = window[i] * last_y[i];
306*28e138c6SAndroid Build Coastguard Worker 	}
307*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOGETRESIDUAL)
308*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=0
309*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=0
310*28e138c6SAndroid Build Coastguard Worker #endif
311*28e138c6SAndroid Build Coastguard Worker 
312*28e138c6SAndroid Build Coastguard Worker 	spx_fft(st->fft_table, st->y, st->Y);
313*28e138c6SAndroid Build Coastguard Worker 	power_spectrum(st->Y, residual_echo, N);
314*28e138c6SAndroid Build Coastguard Worker 
315*28e138c6SAndroid Build Coastguard Worker 	leake = st->leak_estimate;
316*28e138c6SAndroid Build Coastguard Worker 	leak2 = fmux(leake > .5, 1, 2 * leake);
317*28e138c6SAndroid Build Coastguard Worker 	N = st->frame_size;
318*28e138c6SAndroid Build Coastguard Worker 
319*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOGETRESIDUAL)
320*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=4
321*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=1
322*28e138c6SAndroid Build Coastguard Worker #endif
323*28e138c6SAndroid Build Coastguard Worker 	for ( i=0 ; i<N ; ++i )
324*28e138c6SAndroid Build Coastguard Worker 	{	residual_echo[i] *= leak2;
325*28e138c6SAndroid Build Coastguard Worker 	}
326*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOGETRESIDUAL)
327*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=0
328*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=0
329*28e138c6SAndroid Build Coastguard Worker #endif
330*28e138c6SAndroid Build Coastguard Worker 
331*28e138c6SAndroid Build Coastguard Worker 	residual_echo[N] *= leak2;
332*28e138c6SAndroid Build Coastguard Worker 
333*28e138c6SAndroid Build Coastguard Worker #ifndef NO_REMARK
334*28e138c6SAndroid Build Coastguard Worker    (void)len;
335*28e138c6SAndroid Build Coastguard Worker #endif
336*28e138c6SAndroid Build Coastguard Worker 
337*28e138c6SAndroid Build Coastguard Worker    SPEEXECHOGETRESIDUAL_STOP();
338*28e138c6SAndroid Build Coastguard Worker }
339*28e138c6SAndroid Build Coastguard Worker #endif
340*28e138c6SAndroid Build Coastguard Worker 
341*28e138c6SAndroid Build Coastguard Worker 
mdf_preemph(SpeexEchoState * restrict st,spx_word16_t * restrict x,const spx_int16_t * restrict far_end,int framesize)342*28e138c6SAndroid Build Coastguard Worker void mdf_preemph(
343*28e138c6SAndroid Build Coastguard Worker 	SpeexEchoState * restrict st,
344*28e138c6SAndroid Build Coastguard Worker 	spx_word16_t * restrict x,
345*28e138c6SAndroid Build Coastguard Worker 	const spx_int16_t * restrict far_end,
346*28e138c6SAndroid Build Coastguard Worker 	int framesize
347*28e138c6SAndroid Build Coastguard Worker )
348*28e138c6SAndroid Build Coastguard Worker {
349*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t preemph = st->preemph;
350*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t memX = st->memX;
351*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t memD = st->memD;
352*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t * restrict input = st->input;
353*28e138c6SAndroid Build Coastguard Worker 	register int i;
354*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
355*28e138c6SAndroid Build Coastguard Worker 	register int saturated = st->saturated;
356*28e138c6SAndroid Build Coastguard Worker #endif
357*28e138c6SAndroid Build Coastguard Worker 
358*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
359*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=4
360*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=1
361*28e138c6SAndroid Build Coastguard Worker #endif
362*28e138c6SAndroid Build Coastguard Worker 	for ( i=0 ; i<framesize ; ++i )
363*28e138c6SAndroid Build Coastguard Worker 	{
364*28e138c6SAndroid Build Coastguard Worker 		register spx_int16_t far_endi = far_end[i];
365*28e138c6SAndroid Build Coastguard Worker 		register spx_word32_t tmp32;
366*28e138c6SAndroid Build Coastguard Worker 		register spx_word16_t inputi = input[i];
367*28e138c6SAndroid Build Coastguard Worker 
368*28e138c6SAndroid Build Coastguard Worker 		tmp32 = SUB32(EXTEND32(far_endi), EXTEND32(MULT16_16_P15(preemph,memX)));
369*28e138c6SAndroid Build Coastguard Worker 
370*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
371*28e138c6SAndroid Build Coastguard Worker 		saturated = mux(iabs(tmp32) > 32767, M+1, saturated);
372*28e138c6SAndroid Build Coastguard Worker 		tmp32 = iclipi(tmp32,32767);
373*28e138c6SAndroid Build Coastguard Worker #endif
374*28e138c6SAndroid Build Coastguard Worker 
375*28e138c6SAndroid Build Coastguard Worker 		x[i] = EXTRACT16(tmp32);
376*28e138c6SAndroid Build Coastguard Worker 		memX = far_endi;
377*28e138c6SAndroid Build Coastguard Worker 		tmp32 = SUB32(EXTEND32(inputi), EXTEND32(MULT16_16_P15(preemph, memD)));
378*28e138c6SAndroid Build Coastguard Worker 
379*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
380*28e138c6SAndroid Build Coastguard Worker 		saturated = mux( ((tmp32 > 32767) && (saturated == 0)), 1,
381*28e138c6SAndroid Build Coastguard Worker 					mux( ((tmp32 <-32767) && (saturated == 0)), 1, saturated ));
382*28e138c6SAndroid Build Coastguard Worker 		tmp32 = iclipi(tmp32,32767);
383*28e138c6SAndroid Build Coastguard Worker #endif
384*28e138c6SAndroid Build Coastguard Worker 		memD = inputi;
385*28e138c6SAndroid Build Coastguard Worker 		input[i] = tmp32;
386*28e138c6SAndroid Build Coastguard Worker 	}
387*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
388*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=0
389*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=0
390*28e138c6SAndroid Build Coastguard Worker #endif
391*28e138c6SAndroid Build Coastguard Worker 
392*28e138c6SAndroid Build Coastguard Worker 	st->memD = memD;
393*28e138c6SAndroid Build Coastguard Worker 	st->memX = memX;
394*28e138c6SAndroid Build Coastguard Worker 
395*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
396*28e138c6SAndroid Build Coastguard Worker 	st->saturated = saturated;
397*28e138c6SAndroid Build Coastguard Worker #endif
398*28e138c6SAndroid Build Coastguard Worker }
399*28e138c6SAndroid Build Coastguard Worker 
mdf_sub(spx_word16_t * restrict dest,const spx_word16_t * restrict src1,const spx_word16_t * restrict src2,int framesize)400*28e138c6SAndroid Build Coastguard Worker void mdf_sub(
401*28e138c6SAndroid Build Coastguard Worker 	spx_word16_t * restrict dest,
402*28e138c6SAndroid Build Coastguard Worker 	const spx_word16_t * restrict src1,
403*28e138c6SAndroid Build Coastguard Worker 	const spx_word16_t * restrict src2,
404*28e138c6SAndroid Build Coastguard Worker 	int framesize
405*28e138c6SAndroid Build Coastguard Worker )
406*28e138c6SAndroid Build Coastguard Worker {
407*28e138c6SAndroid Build Coastguard Worker 	register int i;
408*28e138c6SAndroid Build Coastguard Worker 
409*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
410*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=4
411*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=1
412*28e138c6SAndroid Build Coastguard Worker #endif
413*28e138c6SAndroid Build Coastguard Worker 
414*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
415*28e138c6SAndroid Build Coastguard Worker 	for ( i=0,framesize<<=1 ; i<framesize ; i+=4 )
416*28e138c6SAndroid Build Coastguard Worker 	{	register int src1i, src2i, desti;
417*28e138c6SAndroid Build Coastguard Worker 
418*28e138c6SAndroid Build Coastguard Worker 		src1i = ld32d(src1,i);
419*28e138c6SAndroid Build Coastguard Worker 		src2i = ld32d(src2,i);
420*28e138c6SAndroid Build Coastguard Worker 		desti = dspidualsub(src1i,src2i);
421*28e138c6SAndroid Build Coastguard Worker 		st32d(i, dest, desti);
422*28e138c6SAndroid Build Coastguard Worker 	}
423*28e138c6SAndroid Build Coastguard Worker #else
424*28e138c6SAndroid Build Coastguard Worker 	for ( i=0 ; i<framesize ; ++i )
425*28e138c6SAndroid Build Coastguard Worker 	{	dest[i] = src1[i] - src2[i];
426*28e138c6SAndroid Build Coastguard Worker 	}
427*28e138c6SAndroid Build Coastguard Worker #endif
428*28e138c6SAndroid Build Coastguard Worker 
429*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
430*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=0
431*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=0
432*28e138c6SAndroid Build Coastguard Worker #endif
433*28e138c6SAndroid Build Coastguard Worker }
434*28e138c6SAndroid Build Coastguard Worker 
mdf_sub_int(spx_word16_t * restrict dest,const spx_int16_t * restrict src1,const spx_int16_t * restrict src2,int framesize)435*28e138c6SAndroid Build Coastguard Worker void mdf_sub_int(
436*28e138c6SAndroid Build Coastguard Worker 	spx_word16_t * restrict dest,
437*28e138c6SAndroid Build Coastguard Worker 	const spx_int16_t * restrict src1,
438*28e138c6SAndroid Build Coastguard Worker 	const spx_int16_t * restrict src2,
439*28e138c6SAndroid Build Coastguard Worker 	int framesize
440*28e138c6SAndroid Build Coastguard Worker )
441*28e138c6SAndroid Build Coastguard Worker {
442*28e138c6SAndroid Build Coastguard Worker 	register int i, j;
443*28e138c6SAndroid Build Coastguard Worker 
444*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
445*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=4
446*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=1
447*28e138c6SAndroid Build Coastguard Worker #endif
448*28e138c6SAndroid Build Coastguard Worker 
449*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
450*28e138c6SAndroid Build Coastguard Worker 	for ( i=0,framesize<<=1 ; i<framesize ; i+=4 )
451*28e138c6SAndroid Build Coastguard Worker 	{	register int src1i, src2i, desti;
452*28e138c6SAndroid Build Coastguard Worker 
453*28e138c6SAndroid Build Coastguard Worker 		src1i = ld32d(src1,i);
454*28e138c6SAndroid Build Coastguard Worker 		src2i = ld32d(src2,i);
455*28e138c6SAndroid Build Coastguard Worker 		desti = dspidualsub(src1i,src2i);
456*28e138c6SAndroid Build Coastguard Worker 		st32d(i, dest, desti);
457*28e138c6SAndroid Build Coastguard Worker 	}
458*28e138c6SAndroid Build Coastguard Worker #else
459*28e138c6SAndroid Build Coastguard Worker 	for ( i=0,j=0 ; i<framesize ; i+=2,++j )
460*28e138c6SAndroid Build Coastguard Worker 	{	register int src1i, src2i, desti;
461*28e138c6SAndroid Build Coastguard Worker 
462*28e138c6SAndroid Build Coastguard Worker 
463*28e138c6SAndroid Build Coastguard Worker 		src1i = ld32d(src1,j);
464*28e138c6SAndroid Build Coastguard Worker 		src2i = ld32d(src2,j);
465*28e138c6SAndroid Build Coastguard Worker 		desti = dspidualsub(src1i,src2i);
466*28e138c6SAndroid Build Coastguard Worker 
467*28e138c6SAndroid Build Coastguard Worker 		dest[i] = sex16(desti);
468*28e138c6SAndroid Build Coastguard Worker 		dest[i+1] = asri(16,desti);
469*28e138c6SAndroid Build Coastguard Worker 	}
470*28e138c6SAndroid Build Coastguard Worker #endif
471*28e138c6SAndroid Build Coastguard Worker 
472*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
473*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=0
474*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=0
475*28e138c6SAndroid Build Coastguard Worker #endif
476*28e138c6SAndroid Build Coastguard Worker }
477*28e138c6SAndroid Build Coastguard Worker 
mdf_compute_weight_gradient(SpeexEchoState * restrict st,spx_word16_t * restrict X,int N,int M)478*28e138c6SAndroid Build Coastguard Worker void mdf_compute_weight_gradient(
479*28e138c6SAndroid Build Coastguard Worker 	SpeexEchoState * restrict st,
480*28e138c6SAndroid Build Coastguard Worker 	spx_word16_t * restrict X,
481*28e138c6SAndroid Build Coastguard Worker 	int N,
482*28e138c6SAndroid Build Coastguard Worker 	int M
483*28e138c6SAndroid Build Coastguard Worker )
484*28e138c6SAndroid Build Coastguard Worker {
485*28e138c6SAndroid Build Coastguard Worker 	register int i, j;
486*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t * restrict PHI = st->PHI;
487*28e138c6SAndroid Build Coastguard Worker 
488*28e138c6SAndroid Build Coastguard Worker 	for (j=M-1;j>=0;j--)
489*28e138c6SAndroid Build Coastguard Worker 	{
490*28e138c6SAndroid Build Coastguard Worker 		register spx_word32_t * restrict W = &(st->W[j*N]);
491*28e138c6SAndroid Build Coastguard Worker 
492*28e138c6SAndroid Build Coastguard Worker 		weighted_spectral_mul_conj(
493*28e138c6SAndroid Build Coastguard Worker 			st->power_1,
494*28e138c6SAndroid Build Coastguard Worker 			FLOAT_SHL(PSEUDOFLOAT(st->prop[j]),-15),
495*28e138c6SAndroid Build Coastguard Worker 			&X[(j+1)*N],
496*28e138c6SAndroid Build Coastguard Worker 			st->E,
497*28e138c6SAndroid Build Coastguard Worker 			st->PHI,
498*28e138c6SAndroid Build Coastguard Worker 			N);
499*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
500*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=4
501*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=1
502*28e138c6SAndroid Build Coastguard Worker #endif
503*28e138c6SAndroid Build Coastguard Worker 		for (i=0;i<N;i++)
504*28e138c6SAndroid Build Coastguard Worker 		{	W[i] = ADD32(W[i],PHI[i]);
505*28e138c6SAndroid Build Coastguard Worker 		}
506*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
507*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=0
508*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=0
509*28e138c6SAndroid Build Coastguard Worker #endif
510*28e138c6SAndroid Build Coastguard Worker 	}
511*28e138c6SAndroid Build Coastguard Worker }
512*28e138c6SAndroid Build Coastguard Worker 
mdf_update_weight(SpeexEchoState * restrict st,int N,int M,int framesize)513*28e138c6SAndroid Build Coastguard Worker void mdf_update_weight(
514*28e138c6SAndroid Build Coastguard Worker 	SpeexEchoState * restrict st,
515*28e138c6SAndroid Build Coastguard Worker 	int N,
516*28e138c6SAndroid Build Coastguard Worker 	int M,
517*28e138c6SAndroid Build Coastguard Worker 	int framesize
518*28e138c6SAndroid Build Coastguard Worker )
519*28e138c6SAndroid Build Coastguard Worker {
520*28e138c6SAndroid Build Coastguard Worker 	register int j;
521*28e138c6SAndroid Build Coastguard Worker 	register int cancel_count = st->cancel_count;
522*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t * restrict wtmp = st->wtmp;
523*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
524*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t * restrict wtmp2 = st->wtmp2;
525*28e138c6SAndroid Build Coastguard Worker 	register int i;
526*28e138c6SAndroid Build Coastguard Worker #endif
527*28e138c6SAndroid Build Coastguard Worker 
528*28e138c6SAndroid Build Coastguard Worker 	for ( j=0 ; j<M ; j++ )
529*28e138c6SAndroid Build Coastguard Worker 	{
530*28e138c6SAndroid Build Coastguard Worker 		register spx_word32_t * restrict W = &(st->W[j*N]);
531*28e138c6SAndroid Build Coastguard Worker 
532*28e138c6SAndroid Build Coastguard Worker 		if (j==0 || cancel_count%(M-1) == j-1)
533*28e138c6SAndroid Build Coastguard Worker 		{
534*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
535*28e138c6SAndroid Build Coastguard Worker 
536*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
537*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=4
538*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=1
539*28e138c6SAndroid Build Coastguard Worker #endif
540*28e138c6SAndroid Build Coastguard Worker 			for ( i=0 ; i<N ; i++ )
541*28e138c6SAndroid Build Coastguard Worker 				wtmp2[i] = EXTRACT16(PSHR32(W[i],NORMALIZE_SCALEDOWN+16));
542*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
543*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=0
544*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=0
545*28e138c6SAndroid Build Coastguard Worker #endif
546*28e138c6SAndroid Build Coastguard Worker 			spx_ifft(st->fft_table, wtmp2, wtmp);
547*28e138c6SAndroid Build Coastguard Worker 			memset(wtmp, 0, framesize * sizeof(spx_word16_t));
548*28e138c6SAndroid Build Coastguard Worker 
549*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
550*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=4
551*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=1
552*28e138c6SAndroid Build Coastguard Worker #endif
553*28e138c6SAndroid Build Coastguard Worker 			for (j=framesize; j<N ; ++j)
554*28e138c6SAndroid Build Coastguard Worker 			{	wtmp[j]=SHL16(wtmp[j],NORMALIZE_SCALEUP);
555*28e138c6SAndroid Build Coastguard Worker 			}
556*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
557*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=0
558*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=0
559*28e138c6SAndroid Build Coastguard Worker #endif
560*28e138c6SAndroid Build Coastguard Worker 
561*28e138c6SAndroid Build Coastguard Worker 			spx_fft(st->fft_table, wtmp, wtmp2);
562*28e138c6SAndroid Build Coastguard Worker 
563*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
564*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=4
565*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=1
566*28e138c6SAndroid Build Coastguard Worker #endif
567*28e138c6SAndroid Build Coastguard Worker 			for (i=0;i<N;i++)
568*28e138c6SAndroid Build Coastguard Worker 			{	W[i] -= SHL32(EXTEND32(wtmp2[i]),16+NORMALIZE_SCALEDOWN-NORMALIZE_SCALEUP-1);
569*28e138c6SAndroid Build Coastguard Worker 			}
570*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
571*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=0
572*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=0
573*28e138c6SAndroid Build Coastguard Worker #endif
574*28e138c6SAndroid Build Coastguard Worker 
575*28e138c6SAndroid Build Coastguard Worker #else
576*28e138c6SAndroid Build Coastguard Worker 			spx_ifft(st->fft_table, W, wtmp);
577*28e138c6SAndroid Build Coastguard Worker 			memset(&wtmp[framesize], 0, (N-framesize) * sizeof(spx_word16_t));
578*28e138c6SAndroid Build Coastguard Worker 			spx_fft(st->fft_table, wtmp, W);
579*28e138c6SAndroid Build Coastguard Worker #endif
580*28e138c6SAndroid Build Coastguard Worker 		}
581*28e138c6SAndroid Build Coastguard Worker 	}
582*28e138c6SAndroid Build Coastguard Worker }
583*28e138c6SAndroid Build Coastguard Worker 
584*28e138c6SAndroid Build Coastguard Worker #ifdef TWO_PATH
585*28e138c6SAndroid Build Coastguard Worker // first four parameters is passed by registers
586*28e138c6SAndroid Build Coastguard Worker // generate faster performance with 4 parameters functions
mdf_update_foreground(SpeexEchoState * restrict st,spx_word32_t Dbf,spx_word32_t Sff,spx_word32_t See)587*28e138c6SAndroid Build Coastguard Worker spx_word32_t mdf_update_foreground(
588*28e138c6SAndroid Build Coastguard Worker 	SpeexEchoState * restrict st,
589*28e138c6SAndroid Build Coastguard Worker 	spx_word32_t Dbf,
590*28e138c6SAndroid Build Coastguard Worker 	spx_word32_t Sff,
591*28e138c6SAndroid Build Coastguard Worker 	spx_word32_t See
592*28e138c6SAndroid Build Coastguard Worker )
593*28e138c6SAndroid Build Coastguard Worker {
594*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t Davg1 = st->Davg1;
595*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t Davg2 = st->Davg2;
596*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t Dvar1 = st->Dvar1;
597*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t Dvar2 = st->Dvar2;
598*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t * restrict input = st->input;
599*28e138c6SAndroid Build Coastguard Worker    	register int framesize = st->frame_size;
600*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t * restrict xx = st->x + framesize;
601*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t * restrict y = st->y + framesize;
602*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t * restrict ee = st->e + framesize;
603*28e138c6SAndroid Build Coastguard Worker 	register int update_foreground;
604*28e138c6SAndroid Build Coastguard Worker 	register int i;
605*28e138c6SAndroid Build Coastguard Worker     register int N = st->window_size;
606*28e138c6SAndroid Build Coastguard Worker 	register int M = st->M;
607*28e138c6SAndroid Build Coastguard Worker 
608*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
609*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t sc0 = SUB32(Sff,See);
610*28e138c6SAndroid Build Coastguard Worker 	register spx_float_t sc1 = FLOAT_MUL32U(Sff,Dbf);
611*28e138c6SAndroid Build Coastguard Worker 
612*28e138c6SAndroid Build Coastguard Worker 	Davg1 = ADD32(MULT16_32_Q15(QCONST16(.6f,15),Davg1), MULT16_32_Q15(QCONST16(.4f,15),sc0));
613*28e138c6SAndroid Build Coastguard Worker 	Davg2 = ADD32(MULT16_32_Q15(QCONST16(.85f,15),Davg2), MULT16_32_Q15(QCONST16(.15f,15),sc0));
614*28e138c6SAndroid Build Coastguard Worker 	Dvar1 = FLOAT_ADD(
615*28e138c6SAndroid Build Coastguard Worker 				FLOAT_MULT(VAR1_SMOOTH,Dvar1),
616*28e138c6SAndroid Build Coastguard Worker 				FLOAT_MUL32U(MULT16_32_Q15(QCONST16(.4f,15),Sff),
617*28e138c6SAndroid Build Coastguard Worker 				MULT16_32_Q15(QCONST16(.4f,15),Dbf)));
618*28e138c6SAndroid Build Coastguard Worker 	Dvar2 = FLOAT_ADD(
619*28e138c6SAndroid Build Coastguard Worker 				FLOAT_MULT(VAR2_SMOOTH,Dvar2),
620*28e138c6SAndroid Build Coastguard Worker 				FLOAT_MUL32U(MULT16_32_Q15(QCONST16(.15f,15),Sff),
621*28e138c6SAndroid Build Coastguard Worker 				MULT16_32_Q15(QCONST16(.15f,15),Dbf)));
622*28e138c6SAndroid Build Coastguard Worker #else
623*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t sc0 = Sff - See;
624*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t sc1 = Sff * Dbf;
625*28e138c6SAndroid Build Coastguard Worker 
626*28e138c6SAndroid Build Coastguard Worker 	Davg1 = .6*Davg1 + .4*sc0;
627*28e138c6SAndroid Build Coastguard Worker 	Davg2 = .85*Davg2 + .15*sc0;
628*28e138c6SAndroid Build Coastguard Worker 	Dvar1 = VAR1_SMOOTH*Dvar1 + .16*sc1;
629*28e138c6SAndroid Build Coastguard Worker 	Dvar2 = VAR2_SMOOTH*Dvar2 + .0225*sc1;
630*28e138c6SAndroid Build Coastguard Worker #endif
631*28e138c6SAndroid Build Coastguard Worker 
632*28e138c6SAndroid Build Coastguard Worker 	update_foreground =
633*28e138c6SAndroid Build Coastguard Worker 	   mux( FLOAT_GT(FLOAT_MUL32U(sc0, VABS(sc0)), sc1), 1,
634*28e138c6SAndroid Build Coastguard Worker 	   mux( FLOAT_GT(FLOAT_MUL32U(Davg1, VABS(Davg1)), FLOAT_MULT(VAR1_UPDATE,(Dvar1))), 1,
635*28e138c6SAndroid Build Coastguard Worker 	   mux( FLOAT_GT(FLOAT_MUL32U(Davg2, VABS(Davg2)), FLOAT_MULT(VAR2_UPDATE,(Dvar2))), 1, 0)));
636*28e138c6SAndroid Build Coastguard Worker 
637*28e138c6SAndroid Build Coastguard Worker 	if ( update_foreground )
638*28e138c6SAndroid Build Coastguard Worker 	{
639*28e138c6SAndroid Build Coastguard Worker 		register spx_word16_t * restrict windowf = st->window + framesize;
640*28e138c6SAndroid Build Coastguard Worker 		register spx_word16_t * restrict window = st->window;
641*28e138c6SAndroid Build Coastguard Worker 
642*28e138c6SAndroid Build Coastguard Worker 		st->Davg1 = st->Davg2 = 0;
643*28e138c6SAndroid Build Coastguard Worker 		st->Dvar1 = st->Dvar2 = FLOAT_ZERO;
644*28e138c6SAndroid Build Coastguard Worker 
645*28e138c6SAndroid Build Coastguard Worker 		memcpy(st->foreground, st->W, N*M*sizeof(spx_word32_t));
646*28e138c6SAndroid Build Coastguard Worker 
647*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
648*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=4
649*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=1
650*28e138c6SAndroid Build Coastguard Worker #endif
651*28e138c6SAndroid Build Coastguard Worker 		for ( i=0 ; i<framesize ; ++i)
652*28e138c6SAndroid Build Coastguard Worker 		{	register spx_word16_t wi = window[i];
653*28e138c6SAndroid Build Coastguard Worker 			register spx_word16_t wfi = windowf[i];
654*28e138c6SAndroid Build Coastguard Worker 			register spx_word16_t ei = ee[i];
655*28e138c6SAndroid Build Coastguard Worker 			register spx_word16_t yi = y[i];
656*28e138c6SAndroid Build Coastguard Worker 
657*28e138c6SAndroid Build Coastguard Worker 			ee[i] = MULT16_16_Q15(wfi,ei) +	MULT16_16_Q15(wi,yi);
658*28e138c6SAndroid Build Coastguard Worker 		}
659*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
660*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=0
661*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=0
662*28e138c6SAndroid Build Coastguard Worker #endif
663*28e138c6SAndroid Build Coastguard Worker 
664*28e138c6SAndroid Build Coastguard Worker 	} else
665*28e138c6SAndroid Build Coastguard Worker 	{
666*28e138c6SAndroid Build Coastguard Worker 		register int reset_background;
667*28e138c6SAndroid Build Coastguard Worker 
668*28e138c6SAndroid Build Coastguard Worker 		reset_background =
669*28e138c6SAndroid Build Coastguard Worker 			mux( FLOAT_GT(FLOAT_MUL32U(-(sc0),VABS(sc0)), FLOAT_MULT(VAR_BACKTRACK,sc1)), 1,
670*28e138c6SAndroid Build Coastguard Worker 			mux( FLOAT_GT(FLOAT_MUL32U(-(Davg1), VABS(Davg1)), FLOAT_MULT(VAR_BACKTRACK,Dvar1)), 1,
671*28e138c6SAndroid Build Coastguard Worker 			mux( FLOAT_GT(FLOAT_MUL32U(-(Davg2), VABS(Davg2)), FLOAT_MULT(VAR_BACKTRACK,Dvar2)), 1, 0)));
672*28e138c6SAndroid Build Coastguard Worker 
673*28e138c6SAndroid Build Coastguard Worker 		if ( reset_background )
674*28e138c6SAndroid Build Coastguard Worker 		{
675*28e138c6SAndroid Build Coastguard Worker 			memcpy(st->W, st->foreground, N*M*sizeof(spx_word32_t));
676*28e138c6SAndroid Build Coastguard Worker 			memcpy(y, ee, framesize * sizeof(spx_word16_t));
677*28e138c6SAndroid Build Coastguard Worker 			mdf_sub(xx,input,y,framesize);
678*28e138c6SAndroid Build Coastguard Worker 			See = Sff;
679*28e138c6SAndroid Build Coastguard Worker 			st->Davg1 = st->Davg2 = 0;
680*28e138c6SAndroid Build Coastguard Worker 			st->Dvar1 = st->Dvar2 = FLOAT_ZERO;
681*28e138c6SAndroid Build Coastguard Worker 		} else
682*28e138c6SAndroid Build Coastguard Worker 		{
683*28e138c6SAndroid Build Coastguard Worker 			st->Davg1 = Davg1;
684*28e138c6SAndroid Build Coastguard Worker 			st->Davg2 = Davg2;
685*28e138c6SAndroid Build Coastguard Worker 			st->Dvar1 = Dvar1;
686*28e138c6SAndroid Build Coastguard Worker 			st->Dvar2 = Dvar2;
687*28e138c6SAndroid Build Coastguard Worker 		}
688*28e138c6SAndroid Build Coastguard Worker 	}
689*28e138c6SAndroid Build Coastguard Worker 
690*28e138c6SAndroid Build Coastguard Worker 	return See;
691*28e138c6SAndroid Build Coastguard Worker }
692*28e138c6SAndroid Build Coastguard Worker #endif
693*28e138c6SAndroid Build Coastguard Worker 
mdf_compute_error_signal(SpeexEchoState * restrict st,const spx_int16_t * restrict in,spx_int16_t * restrict out,int framesize)694*28e138c6SAndroid Build Coastguard Worker void mdf_compute_error_signal(
695*28e138c6SAndroid Build Coastguard Worker 	SpeexEchoState * restrict st,
696*28e138c6SAndroid Build Coastguard Worker 	const spx_int16_t * restrict in,
697*28e138c6SAndroid Build Coastguard Worker 	spx_int16_t * restrict out,
698*28e138c6SAndroid Build Coastguard Worker 	int framesize
699*28e138c6SAndroid Build Coastguard Worker )
700*28e138c6SAndroid Build Coastguard Worker {
701*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t preemph = st->preemph;
702*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t memE = st->memE;
703*28e138c6SAndroid Build Coastguard Worker 	register int saturated = st->saturated;
704*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t * restrict e = st->e;
705*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t * restrict ee = st->e + framesize;
706*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t * restrict input = st->input;
707*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t * restrict xx = st->x + framesize;
708*28e138c6SAndroid Build Coastguard Worker 	register int i;
709*28e138c6SAndroid Build Coastguard Worker 
710*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
711*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=4
712*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=1
713*28e138c6SAndroid Build Coastguard Worker #endif
714*28e138c6SAndroid Build Coastguard Worker 	for ( i=0 ; i<framesize ; ++i )
715*28e138c6SAndroid Build Coastguard Worker 	{
716*28e138c6SAndroid Build Coastguard Worker 		register spx_word32_t tmp_out;
717*28e138c6SAndroid Build Coastguard Worker 		register spx_int16_t ini = in[i];
718*28e138c6SAndroid Build Coastguard Worker 		register int flg;
719*28e138c6SAndroid Build Coastguard Worker 
720*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
721*28e138c6SAndroid Build Coastguard Worker 
722*28e138c6SAndroid Build Coastguard Worker #ifdef TWO_PATH
723*28e138c6SAndroid Build Coastguard Worker 		tmp_out = SUB32(EXTEND32(input[i]), EXTEND32(ee[i]));
724*28e138c6SAndroid Build Coastguard Worker 		tmp_out = iclipi(tmp_out,32767);
725*28e138c6SAndroid Build Coastguard Worker #else
726*28e138c6SAndroid Build Coastguard Worker 		tmp_out = SUB32(EXTEND32(input[i]), EXTEND32(y[i]));
727*28e138c6SAndroid Build Coastguard Worker 		tmp_out = iclipi(tmp_out,32767);
728*28e138c6SAndroid Build Coastguard Worker #endif
729*28e138c6SAndroid Build Coastguard Worker 
730*28e138c6SAndroid Build Coastguard Worker #else
731*28e138c6SAndroid Build Coastguard Worker #ifdef TWO_PATH
732*28e138c6SAndroid Build Coastguard Worker 		tmp_out = SUB32(EXTEND32(input[i]), EXTEND32(ee[i]));
733*28e138c6SAndroid Build Coastguard Worker #else
734*28e138c6SAndroid Build Coastguard Worker 		tmp_out = SUB32(EXTEND32(input[i]), EXTEND32(y[i]));
735*28e138c6SAndroid Build Coastguard Worker #endif
736*28e138c6SAndroid Build Coastguard Worker 		tmp_out =
737*28e138c6SAndroid Build Coastguard Worker 			fmux( tmp_out > 32767, 32767,
738*28e138c6SAndroid Build Coastguard Worker 			fmux( tmp_out < -32768, -32768, tmp_out));
739*28e138c6SAndroid Build Coastguard Worker #endif
740*28e138c6SAndroid Build Coastguard Worker 
741*28e138c6SAndroid Build Coastguard Worker 		tmp_out = ADD32(tmp_out, EXTEND32(MULT16_16_P15(preemph,memE)));
742*28e138c6SAndroid Build Coastguard Worker 		flg = iabs(ini) >= 32000;
743*28e138c6SAndroid Build Coastguard Worker 		tmp_out = VMUX( flg, 0, tmp_out);
744*28e138c6SAndroid Build Coastguard Worker 		saturated = mux( flg && (saturated == 0), 1, saturated);
745*28e138c6SAndroid Build Coastguard Worker 
746*28e138c6SAndroid Build Coastguard Worker 		out[i] = (spx_int16_t)tmp_out;
747*28e138c6SAndroid Build Coastguard Worker 		memE = tmp_out;
748*28e138c6SAndroid Build Coastguard Worker 	}
749*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
750*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=0
751*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=0
752*28e138c6SAndroid Build Coastguard Worker #endif
753*28e138c6SAndroid Build Coastguard Worker 
754*28e138c6SAndroid Build Coastguard Worker 	st->memE = memE;
755*28e138c6SAndroid Build Coastguard Worker 	st->saturated = saturated;
756*28e138c6SAndroid Build Coastguard Worker 	memset(e, 0, framesize * sizeof(spx_word16_t));
757*28e138c6SAndroid Build Coastguard Worker 	memcpy(ee, xx, framesize * sizeof(spx_word16_t));
758*28e138c6SAndroid Build Coastguard Worker }
759*28e138c6SAndroid Build Coastguard Worker 
mdf_check(SpeexEchoState * restrict st,spx_int16_t * out,spx_word32_t Syy,spx_word32_t Sxx,spx_word32_t See,spx_word32_t Sff,spx_word32_t Sdd)760*28e138c6SAndroid Build Coastguard Worker inline int mdf_check(
761*28e138c6SAndroid Build Coastguard Worker   	SpeexEchoState * restrict st,
762*28e138c6SAndroid Build Coastguard Worker 	spx_int16_t * out,
763*28e138c6SAndroid Build Coastguard Worker 	spx_word32_t Syy,
764*28e138c6SAndroid Build Coastguard Worker 	spx_word32_t Sxx,
765*28e138c6SAndroid Build Coastguard Worker 	spx_word32_t See,
766*28e138c6SAndroid Build Coastguard Worker 	spx_word32_t Sff,
767*28e138c6SAndroid Build Coastguard Worker 	spx_word32_t Sdd
768*28e138c6SAndroid Build Coastguard Worker )
769*28e138c6SAndroid Build Coastguard Worker {
770*28e138c6SAndroid Build Coastguard Worker     register int N = st->window_size;
771*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t N1e9 = N * 1e9;
772*28e138c6SAndroid Build Coastguard Worker 	register int screwed_up = st->screwed_up;
773*28e138c6SAndroid Build Coastguard Worker 	register int framesize = st->frame_size;
774*28e138c6SAndroid Build Coastguard Worker 
775*28e138c6SAndroid Build Coastguard Worker 	if (!(Syy>=0 && Sxx>=0 && See >= 0)
776*28e138c6SAndroid Build Coastguard Worker #ifndef FIXED_POINT
777*28e138c6SAndroid Build Coastguard Worker 		|| !(Sff < N1e9 && Syy < N1e9 && Sxx < N1e9 )
778*28e138c6SAndroid Build Coastguard Worker #endif
779*28e138c6SAndroid Build Coastguard Worker       )
780*28e138c6SAndroid Build Coastguard Worker 	{
781*28e138c6SAndroid Build Coastguard Worker 		screwed_up += 50;
782*28e138c6SAndroid Build Coastguard Worker 		memset(out, 0, framesize * sizeof(spx_int16_t));
783*28e138c6SAndroid Build Coastguard Worker 
784*28e138c6SAndroid Build Coastguard Worker 	} else
785*28e138c6SAndroid Build Coastguard Worker 	{	screwed_up = mux( SHR32(Sff, 2) > ADD32(Sdd, SHR32(MULT16_16(N, 10000),6)), screwed_up+1, 0);
786*28e138c6SAndroid Build Coastguard Worker 	}
787*28e138c6SAndroid Build Coastguard Worker 
788*28e138c6SAndroid Build Coastguard Worker 	st->screwed_up = screwed_up;
789*28e138c6SAndroid Build Coastguard Worker 
790*28e138c6SAndroid Build Coastguard Worker 	return screwed_up;
791*28e138c6SAndroid Build Coastguard Worker }
792*28e138c6SAndroid Build Coastguard Worker 
mdf_smooth(spx_word32_t * restrict power,spx_word32_t * restrict Xf,int framesize,int M)793*28e138c6SAndroid Build Coastguard Worker void mdf_smooth(
794*28e138c6SAndroid Build Coastguard Worker 	spx_word32_t * restrict power,
795*28e138c6SAndroid Build Coastguard Worker 	spx_word32_t * restrict Xf,
796*28e138c6SAndroid Build Coastguard Worker 	int framesize,
797*28e138c6SAndroid Build Coastguard Worker 	int M
798*28e138c6SAndroid Build Coastguard Worker )
799*28e138c6SAndroid Build Coastguard Worker {
800*28e138c6SAndroid Build Coastguard Worker     register spx_word16_t ss, ss_1, pf, xff;
801*28e138c6SAndroid Build Coastguard Worker 	register int j;
802*28e138c6SAndroid Build Coastguard Worker 
803*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
804*28e138c6SAndroid Build Coastguard Worker 	ss=DIV32_16(11469,M);
805*28e138c6SAndroid Build Coastguard Worker 	ss_1 = SUB16(32767,ss);
806*28e138c6SAndroid Build Coastguard Worker #else
807*28e138c6SAndroid Build Coastguard Worker 	ss=.35/M;
808*28e138c6SAndroid Build Coastguard Worker 	ss_1 = 1-ss;
809*28e138c6SAndroid Build Coastguard Worker #endif
810*28e138c6SAndroid Build Coastguard Worker 
811*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
812*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=4
813*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=1
814*28e138c6SAndroid Build Coastguard Worker #endif
815*28e138c6SAndroid Build Coastguard Worker 	for ( j=0 ; j<framesize ; ++j )
816*28e138c6SAndroid Build Coastguard Worker 	{	register spx_word32_t pi  = power[j];
817*28e138c6SAndroid Build Coastguard Worker 		register spx_word32_t xfi = Xf[j];
818*28e138c6SAndroid Build Coastguard Worker 
819*28e138c6SAndroid Build Coastguard Worker 		power[j] = MULT16_32_Q15(ss_1,pi) + 1 + MULT16_32_Q15(ss,xfi);
820*28e138c6SAndroid Build Coastguard Worker 	}
821*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
822*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=0
823*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=0
824*28e138c6SAndroid Build Coastguard Worker #endif
825*28e138c6SAndroid Build Coastguard Worker 
826*28e138c6SAndroid Build Coastguard Worker 	pf = power[framesize];
827*28e138c6SAndroid Build Coastguard Worker 	xff = Xf[framesize];
828*28e138c6SAndroid Build Coastguard Worker 	power[framesize] = MULT16_32_Q15(ss_1,pf) + 1 + MULT16_32_Q15(ss,xff);
829*28e138c6SAndroid Build Coastguard Worker }
830*28e138c6SAndroid Build Coastguard Worker 
mdf_compute_filtered_spectra_crosscorrelations(SpeexEchoState * restrict st,spx_word32_t Syy,spx_word32_t See,int framesize)831*28e138c6SAndroid Build Coastguard Worker void mdf_compute_filtered_spectra_crosscorrelations(
832*28e138c6SAndroid Build Coastguard Worker  	SpeexEchoState * restrict st,
833*28e138c6SAndroid Build Coastguard Worker 	spx_word32_t Syy,
834*28e138c6SAndroid Build Coastguard Worker 	spx_word32_t See,
835*28e138c6SAndroid Build Coastguard Worker 	int framesize
836*28e138c6SAndroid Build Coastguard Worker )
837*28e138c6SAndroid Build Coastguard Worker {
838*28e138c6SAndroid Build Coastguard Worker 	register spx_float_t Pey = FLOAT_ONE;
839*28e138c6SAndroid Build Coastguard Worker 	register spx_float_t Pyy = FLOAT_ONE;
840*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t spec_average = st->spec_average;
841*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t * restrict pRf = st->Rf;
842*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t * restrict pYf = st->Yf;
843*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t * restrict pEh = st->Eh;
844*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t * restrict pYh = st->Yh;
845*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t beta0 = st->beta0;
846*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t beta_max = st->beta_max;
847*28e138c6SAndroid Build Coastguard Worker 	register spx_float_t alpha, alpha_1;
848*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t tmp32, tmpx;
849*28e138c6SAndroid Build Coastguard Worker 	register spx_float_t sPey = st->Pey;
850*28e138c6SAndroid Build Coastguard Worker 	register spx_float_t sPyy = st->Pyy;
851*28e138c6SAndroid Build Coastguard Worker 	register spx_float_t tmp;
852*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t leak_estimate;
853*28e138c6SAndroid Build Coastguard Worker 	register int j;
854*28e138c6SAndroid Build Coastguard Worker 	register spx_float_t  Eh, Yh;
855*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t _Ehj, _Rfj, _Yfj, _Yhj;
856*28e138c6SAndroid Build Coastguard Worker 
857*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
858*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t spec_average1 = SUB16(32767,spec_average);
859*28e138c6SAndroid Build Coastguard Worker #else
860*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t spec_average1 = 1 - spec_average;
861*28e138c6SAndroid Build Coastguard Worker #endif
862*28e138c6SAndroid Build Coastguard Worker 
863*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
864*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=4
865*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=1
866*28e138c6SAndroid Build Coastguard Worker #endif
867*28e138c6SAndroid Build Coastguard Worker 	for (j=framesize; j>0 ; --j)
868*28e138c6SAndroid Build Coastguard Worker 	{
869*28e138c6SAndroid Build Coastguard Worker 		_Ehj = pEh[j];
870*28e138c6SAndroid Build Coastguard Worker 		_Rfj = pRf[j];
871*28e138c6SAndroid Build Coastguard Worker 		_Yfj = pYf[j];
872*28e138c6SAndroid Build Coastguard Worker 		_Yhj = pYh[j];
873*28e138c6SAndroid Build Coastguard Worker 
874*28e138c6SAndroid Build Coastguard Worker 		Eh = PSEUDOFLOAT(_Rfj - _Ehj);
875*28e138c6SAndroid Build Coastguard Worker 		Yh = PSEUDOFLOAT(_Yfj - _Yhj);
876*28e138c6SAndroid Build Coastguard Worker 
877*28e138c6SAndroid Build Coastguard Worker 		Pey = FLOAT_ADD(Pey,FLOAT_MULT(Eh,Yh));
878*28e138c6SAndroid Build Coastguard Worker 		Pyy = FLOAT_ADD(Pyy,FLOAT_MULT(Yh,Yh));
879*28e138c6SAndroid Build Coastguard Worker 
880*28e138c6SAndroid Build Coastguard Worker 		pEh[j] = MAC16_32_Q15(MULT16_32_Q15(spec_average1, _Ehj), spec_average, _Rfj);
881*28e138c6SAndroid Build Coastguard Worker 		pYh[j] = MAC16_32_Q15(MULT16_32_Q15(spec_average1, _Yhj), spec_average, _Yfj);
882*28e138c6SAndroid Build Coastguard Worker    }
883*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
884*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=0
885*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=0
886*28e138c6SAndroid Build Coastguard Worker #endif
887*28e138c6SAndroid Build Coastguard Worker 	_Ehj = pEh[0];
888*28e138c6SAndroid Build Coastguard Worker 	_Rfj = pRf[0];
889*28e138c6SAndroid Build Coastguard Worker 	_Yfj = pYf[0];
890*28e138c6SAndroid Build Coastguard Worker 	_Yhj = pYh[0];
891*28e138c6SAndroid Build Coastguard Worker 
892*28e138c6SAndroid Build Coastguard Worker 	Eh = PSEUDOFLOAT(_Rfj - _Ehj);
893*28e138c6SAndroid Build Coastguard Worker 	Yh = PSEUDOFLOAT(_Yfj - _Yhj);
894*28e138c6SAndroid Build Coastguard Worker 
895*28e138c6SAndroid Build Coastguard Worker 	Pey = FLOAT_ADD(Pey,FLOAT_MULT(Eh,Yh));
896*28e138c6SAndroid Build Coastguard Worker 	Pyy = FLOAT_ADD(Pyy,FLOAT_MULT(Yh,Yh));
897*28e138c6SAndroid Build Coastguard Worker 
898*28e138c6SAndroid Build Coastguard Worker 	pEh[0] = MAC16_32_Q15(MULT16_32_Q15(spec_average1, _Ehj), spec_average, _Rfj);
899*28e138c6SAndroid Build Coastguard Worker 	pYh[0] = MAC16_32_Q15(MULT16_32_Q15(spec_average1, _Yhj), spec_average, _Yfj);
900*28e138c6SAndroid Build Coastguard Worker 
901*28e138c6SAndroid Build Coastguard Worker 	Pyy = FLOAT_SQRT(Pyy);
902*28e138c6SAndroid Build Coastguard Worker 	Pey = FLOAT_DIVU(Pey,Pyy);
903*28e138c6SAndroid Build Coastguard Worker 
904*28e138c6SAndroid Build Coastguard Worker 	tmp32 = MULT16_32_Q15(beta0,Syy);
905*28e138c6SAndroid Build Coastguard Worker 	tmpx = MULT16_32_Q15(beta_max,See);
906*28e138c6SAndroid Build Coastguard Worker 	tmp32 = VMUX(tmp32 > tmpx, tmpx, tmp32);
907*28e138c6SAndroid Build Coastguard Worker 	alpha = FLOAT_DIV32(tmp32, See);
908*28e138c6SAndroid Build Coastguard Worker 	alpha_1 = FLOAT_SUB(FLOAT_ONE, alpha);
909*28e138c6SAndroid Build Coastguard Worker 
910*28e138c6SAndroid Build Coastguard Worker 	sPey = FLOAT_ADD(FLOAT_MULT(alpha_1,sPey) , FLOAT_MULT(alpha,Pey));
911*28e138c6SAndroid Build Coastguard Worker 	sPyy = FLOAT_ADD(FLOAT_MULT(alpha_1,sPyy) , FLOAT_MULT(alpha,Pyy));
912*28e138c6SAndroid Build Coastguard Worker 	tmp = FLOAT_MULT(MIN_LEAK,sPyy);
913*28e138c6SAndroid Build Coastguard Worker 
914*28e138c6SAndroid Build Coastguard Worker #ifndef FIXED_POINT
915*28e138c6SAndroid Build Coastguard Worker 	sPyy = VMUX(FLOAT_LT(sPyy, FLOAT_ONE), FLOAT_ONE, sPyy);
916*28e138c6SAndroid Build Coastguard Worker 	sPey = VMUX(FLOAT_LT(sPey, tmp), tmp, sPey);
917*28e138c6SAndroid Build Coastguard Worker 	sPey = VMUX(FLOAT_LT(sPey, sPyy), sPey, sPyy);
918*28e138c6SAndroid Build Coastguard Worker #else
919*28e138c6SAndroid Build Coastguard Worker 	sPyy = FLOAT_LT(sPyy, FLOAT_ONE) ? FLOAT_ONE : sPyy;
920*28e138c6SAndroid Build Coastguard Worker 	sPey = FLOAT_LT(sPey, tmp) ? tmp : sPey;
921*28e138c6SAndroid Build Coastguard Worker 	sPey = FLOAT_LT(sPey, sPyy) ? sPey : sPyy;
922*28e138c6SAndroid Build Coastguard Worker #endif
923*28e138c6SAndroid Build Coastguard Worker 
924*28e138c6SAndroid Build Coastguard Worker 	leak_estimate = FLOAT_EXTRACT16(FLOAT_SHL(FLOAT_DIVU(sPey, sPyy),14));
925*28e138c6SAndroid Build Coastguard Worker 
926*28e138c6SAndroid Build Coastguard Worker 	leak_estimate = VMUX( leak_estimate > 16383, 32767, SHL16(leak_estimate,1));
927*28e138c6SAndroid Build Coastguard Worker 	st->Pey = sPey;
928*28e138c6SAndroid Build Coastguard Worker 	st->Pyy = sPyy;
929*28e138c6SAndroid Build Coastguard Worker 	st->leak_estimate = leak_estimate;
930*28e138c6SAndroid Build Coastguard Worker }
931*28e138c6SAndroid Build Coastguard Worker 
mdf_compute_RER(spx_word32_t See,spx_word32_t Syy,spx_word32_t Sey,spx_word32_t Sxx,spx_word16_t leake)932*28e138c6SAndroid Build Coastguard Worker inline spx_word16_t mdf_compute_RER(
933*28e138c6SAndroid Build Coastguard Worker  	spx_word32_t See,
934*28e138c6SAndroid Build Coastguard Worker 	spx_word32_t Syy,
935*28e138c6SAndroid Build Coastguard Worker 	spx_word32_t Sey,
936*28e138c6SAndroid Build Coastguard Worker 	spx_word32_t Sxx,
937*28e138c6SAndroid Build Coastguard Worker 	spx_word16_t leake
938*28e138c6SAndroid Build Coastguard Worker )
939*28e138c6SAndroid Build Coastguard Worker {
940*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t RER;
941*28e138c6SAndroid Build Coastguard Worker 
942*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
943*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t tmp32;
944*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t tmp;
945*28e138c6SAndroid Build Coastguard Worker 	spx_float_t bound = PSEUDOFLOAT(Sey);
946*28e138c6SAndroid Build Coastguard Worker 
947*28e138c6SAndroid Build Coastguard Worker 	tmp32 = MULT16_32_Q15(leake,Syy);
948*28e138c6SAndroid Build Coastguard Worker 	tmp32 = ADD32(SHR32(Sxx,13), ADD32(tmp32, SHL32(tmp32,1)));
949*28e138c6SAndroid Build Coastguard Worker 
950*28e138c6SAndroid Build Coastguard Worker 	bound = FLOAT_DIVU(FLOAT_MULT(bound, bound), PSEUDOFLOAT(ADD32(1,Syy)));
951*28e138c6SAndroid Build Coastguard Worker 	tmp   = FLOAT_EXTRACT32(bound);
952*28e138c6SAndroid Build Coastguard Worker 	tmp32 = imux( FLOAT_GT(bound, PSEUDOFLOAT(See)), See,
953*28e138c6SAndroid Build Coastguard Worker 			imux( tmp32 < tmp,  tmp, tmp32));
954*28e138c6SAndroid Build Coastguard Worker 
955*28e138c6SAndroid Build Coastguard Worker 	tmp   = SHR32(See,1);
956*28e138c6SAndroid Build Coastguard Worker 	tmp32 = imux(tmp32 > tmp, tmp, tmp32);
957*28e138c6SAndroid Build Coastguard Worker 	RER   = FLOAT_EXTRACT16(FLOAT_SHL(FLOAT_DIV32(tmp32,See),15));
958*28e138c6SAndroid Build Coastguard Worker #else
959*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t r0;
960*28e138c6SAndroid Build Coastguard Worker 
961*28e138c6SAndroid Build Coastguard Worker 	r0 = (Sey * Sey)/(1 + See * Syy);
962*28e138c6SAndroid Build Coastguard Worker 
963*28e138c6SAndroid Build Coastguard Worker 	RER = (.0001*Sxx + 3.* MULT16_32_Q15(leake,Syy)) / See;
964*28e138c6SAndroid Build Coastguard Worker 	RER = fmux( RER < r0, r0, RER);
965*28e138c6SAndroid Build Coastguard Worker 	RER = fmux( RER > .5, .5, RER);
966*28e138c6SAndroid Build Coastguard Worker #endif
967*28e138c6SAndroid Build Coastguard Worker 
968*28e138c6SAndroid Build Coastguard Worker 	return RER;
969*28e138c6SAndroid Build Coastguard Worker }
970*28e138c6SAndroid Build Coastguard Worker 
mdf_adapt(SpeexEchoState * restrict st,spx_word16_t RER,spx_word32_t Syy,spx_word32_t See,spx_word32_t Sxx)971*28e138c6SAndroid Build Coastguard Worker void mdf_adapt(
972*28e138c6SAndroid Build Coastguard Worker  	SpeexEchoState * restrict st,
973*28e138c6SAndroid Build Coastguard Worker 	spx_word16_t RER,
974*28e138c6SAndroid Build Coastguard Worker 	spx_word32_t Syy,
975*28e138c6SAndroid Build Coastguard Worker 	spx_word32_t See,
976*28e138c6SAndroid Build Coastguard Worker 	spx_word32_t Sxx
977*28e138c6SAndroid Build Coastguard Worker )
978*28e138c6SAndroid Build Coastguard Worker {
979*28e138c6SAndroid Build Coastguard Worker 	register spx_float_t  * restrict power_1 = st->power_1;
980*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t  * restrict power = st->power;
981*28e138c6SAndroid Build Coastguard Worker 	register int adapted = st->adapted;
982*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t sum_adapt = st->sum_adapt;
983*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t leake = st->leak_estimate;
984*28e138c6SAndroid Build Coastguard Worker 	register int framesize = st->frame_size;
985*28e138c6SAndroid Build Coastguard Worker 	register int i;
986*28e138c6SAndroid Build Coastguard Worker 	register int M = st->M;
987*28e138c6SAndroid Build Coastguard Worker 
988*28e138c6SAndroid Build Coastguard Worker 	adapted = mux( !adapted && sum_adapt > QCONST32(M,15) &&
989*28e138c6SAndroid Build Coastguard Worker 					MULT16_32_Q15(leake,Syy) > MULT16_32_Q15(QCONST16(.03f,15),Syy), 1, adapted);
990*28e138c6SAndroid Build Coastguard Worker 
991*28e138c6SAndroid Build Coastguard Worker 	if ( adapted )
992*28e138c6SAndroid Build Coastguard Worker 	{	register spx_word32_t * restrict Yf = st->Yf;
993*28e138c6SAndroid Build Coastguard Worker 		register spx_word32_t * restrict Rf = st->Rf;
994*28e138c6SAndroid Build Coastguard Worker 		register spx_word32_t r, e, e2;
995*28e138c6SAndroid Build Coastguard Worker 
996*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
997*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=4
998*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=1
999*28e138c6SAndroid Build Coastguard Worker #endif
1000*28e138c6SAndroid Build Coastguard Worker 		for ( i=0 ; i<framesize ; ++i )
1001*28e138c6SAndroid Build Coastguard Worker 		{
1002*28e138c6SAndroid Build Coastguard Worker 			r = SHL32(Yf[i],3);
1003*28e138c6SAndroid Build Coastguard Worker 			r = MULT16_32_Q15(leake,r);
1004*28e138c6SAndroid Build Coastguard Worker 			e = SHL32(Rf[i],3)+1;
1005*28e138c6SAndroid Build Coastguard Worker 
1006*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
1007*28e138c6SAndroid Build Coastguard Worker 			e2 = SHR32(e,1);
1008*28e138c6SAndroid Build Coastguard Worker 			r = mux( r > e2, e2, r);
1009*28e138c6SAndroid Build Coastguard Worker #else
1010*28e138c6SAndroid Build Coastguard Worker 			e2 = e * .5;
1011*28e138c6SAndroid Build Coastguard Worker 			r = fmux( r > e2, e2, r);
1012*28e138c6SAndroid Build Coastguard Worker #endif
1013*28e138c6SAndroid Build Coastguard Worker 
1014*28e138c6SAndroid Build Coastguard Worker 			r = MULT16_32_Q15(QCONST16(.7,15),r) +
1015*28e138c6SAndroid Build Coastguard Worker 				MULT16_32_Q15(QCONST16(.3,15),(spx_word32_t)(MULT16_32_Q15(RER,e)));
1016*28e138c6SAndroid Build Coastguard Worker 
1017*28e138c6SAndroid Build Coastguard Worker 			power_1[i] = FLOAT_SHL(FLOAT_DIV32_FLOAT(r,FLOAT_MUL32U(e,power[i]+10)),WEIGHT_SHIFT+16);
1018*28e138c6SAndroid Build Coastguard Worker 		}
1019*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
1020*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=0
1021*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=0
1022*28e138c6SAndroid Build Coastguard Worker #endif
1023*28e138c6SAndroid Build Coastguard Worker 
1024*28e138c6SAndroid Build Coastguard Worker 		r = SHL32(Yf[framesize],3);
1025*28e138c6SAndroid Build Coastguard Worker 		r = MULT16_32_Q15(leake,r);
1026*28e138c6SAndroid Build Coastguard Worker 		e = SHL32(Rf[framesize],3)+1;
1027*28e138c6SAndroid Build Coastguard Worker 
1028*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
1029*28e138c6SAndroid Build Coastguard Worker 		e2 = SHR32(e,1);
1030*28e138c6SAndroid Build Coastguard Worker 		r = mux( r > e2, e2, r);
1031*28e138c6SAndroid Build Coastguard Worker #else
1032*28e138c6SAndroid Build Coastguard Worker 		e2 = e * .5;
1033*28e138c6SAndroid Build Coastguard Worker 		r = fmux( r > e2, e2, r);
1034*28e138c6SAndroid Build Coastguard Worker #endif
1035*28e138c6SAndroid Build Coastguard Worker 
1036*28e138c6SAndroid Build Coastguard Worker 		r = MULT16_32_Q15(QCONST16(.7,15),r) +
1037*28e138c6SAndroid Build Coastguard Worker 			MULT16_32_Q15(QCONST16(.3,15),(spx_word32_t)(MULT16_32_Q15(RER,e)));
1038*28e138c6SAndroid Build Coastguard Worker 
1039*28e138c6SAndroid Build Coastguard Worker 		power_1[framesize] = FLOAT_SHL(FLOAT_DIV32_FLOAT(r,FLOAT_MUL32U(e,power[framesize]+10)),WEIGHT_SHIFT+16);
1040*28e138c6SAndroid Build Coastguard Worker 
1041*28e138c6SAndroid Build Coastguard Worker 	} else
1042*28e138c6SAndroid Build Coastguard Worker 	{
1043*28e138c6SAndroid Build Coastguard Worker 		register spx_word16_t adapt_rate=0;
1044*28e138c6SAndroid Build Coastguard Worker 		register int N = st->window_size;
1045*28e138c6SAndroid Build Coastguard Worker 
1046*28e138c6SAndroid Build Coastguard Worker 		if ( Sxx > SHR32(MULT16_16(N, 1000),6) )
1047*28e138c6SAndroid Build Coastguard Worker 		{	register spx_word32_t tmp32, tmp32q;
1048*28e138c6SAndroid Build Coastguard Worker 
1049*28e138c6SAndroid Build Coastguard Worker 			tmp32 = MULT16_32_Q15(QCONST16(.25f, 15), Sxx);
1050*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
1051*28e138c6SAndroid Build Coastguard Worker 			tmp32q = SHR32(See,2);
1052*28e138c6SAndroid Build Coastguard Worker 			tmp32  = mux(tmp32 > tmp32q, tmp32q, tmp32);
1053*28e138c6SAndroid Build Coastguard Worker #else
1054*28e138c6SAndroid Build Coastguard Worker 			tmp32q = 0.25 * See;
1055*28e138c6SAndroid Build Coastguard Worker 			tmp32 = fmux(tmp32 > tmp32q, tmp32q, tmp32);
1056*28e138c6SAndroid Build Coastguard Worker #endif
1057*28e138c6SAndroid Build Coastguard Worker 			adapt_rate = FLOAT_EXTRACT16(FLOAT_SHL(FLOAT_DIV32(tmp32, See),15));
1058*28e138c6SAndroid Build Coastguard Worker 		}
1059*28e138c6SAndroid Build Coastguard Worker 
1060*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
1061*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=4
1062*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=1
1063*28e138c6SAndroid Build Coastguard Worker #endif
1064*28e138c6SAndroid Build Coastguard Worker 		for (i=0;i<framesize;i++)
1065*28e138c6SAndroid Build Coastguard Worker 			power_1[i] = FLOAT_SHL(FLOAT_DIV32(EXTEND32(adapt_rate),ADD32(power[i],10)),WEIGHT_SHIFT+1);
1066*28e138c6SAndroid Build Coastguard Worker #if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
1067*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unrollexact=0
1068*28e138c6SAndroid Build Coastguard Worker #pragma TCS_unroll=0
1069*28e138c6SAndroid Build Coastguard Worker #endif
1070*28e138c6SAndroid Build Coastguard Worker 		power_1[framesize] = FLOAT_SHL(FLOAT_DIV32(EXTEND32(adapt_rate),ADD32(power[framesize],10)),WEIGHT_SHIFT+1);
1071*28e138c6SAndroid Build Coastguard Worker 		sum_adapt = ADD32(sum_adapt,adapt_rate);
1072*28e138c6SAndroid Build Coastguard Worker 	}
1073*28e138c6SAndroid Build Coastguard Worker 
1074*28e138c6SAndroid Build Coastguard Worker 	st->sum_adapt = sum_adapt;
1075*28e138c6SAndroid Build Coastguard Worker 	st->adapted = adapted;
1076*28e138c6SAndroid Build Coastguard Worker }
1077*28e138c6SAndroid Build Coastguard Worker 
1078*28e138c6SAndroid Build Coastguard Worker #define OVERRIDE_ECHO_CANCELLATION
speex_echo_cancellation(SpeexEchoState * restrict st,const spx_int16_t * restrict in,const spx_int16_t * restrict far_end,spx_int16_t * restrict out)1079*28e138c6SAndroid Build Coastguard Worker void speex_echo_cancellation(
1080*28e138c6SAndroid Build Coastguard Worker 	SpeexEchoState * restrict st,
1081*28e138c6SAndroid Build Coastguard Worker 	const spx_int16_t * restrict in,
1082*28e138c6SAndroid Build Coastguard Worker 	const spx_int16_t * restrict far_end,
1083*28e138c6SAndroid Build Coastguard Worker 	spx_int16_t * restrict out
1084*28e138c6SAndroid Build Coastguard Worker )
1085*28e138c6SAndroid Build Coastguard Worker {
1086*28e138c6SAndroid Build Coastguard Worker    	register int framesize = st->frame_size;
1087*28e138c6SAndroid Build Coastguard Worker    	register spx_word16_t * restrict x = st->x;
1088*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t * restrict xx = st->x + framesize;
1089*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t * restrict yy = st->y + framesize;
1090*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t * restrict ee = st->e + framesize;
1091*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t Syy, See, Sxx, Sdd, Sff;
1092*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t RER;
1093*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t Sey;
1094*28e138c6SAndroid Build Coastguard Worker 	register int j;
1095*28e138c6SAndroid Build Coastguard Worker 	register int N,M;
1096*28e138c6SAndroid Build Coastguard Worker #ifdef TWO_PATH
1097*28e138c6SAndroid Build Coastguard Worker 	register spx_word32_t Dbf;
1098*28e138c6SAndroid Build Coastguard Worker #endif
1099*28e138c6SAndroid Build Coastguard Worker 
1100*28e138c6SAndroid Build Coastguard Worker 	N = st->window_size;
1101*28e138c6SAndroid Build Coastguard Worker 	M = st->M;
1102*28e138c6SAndroid Build Coastguard Worker 	st->cancel_count++;
1103*28e138c6SAndroid Build Coastguard Worker 
1104*28e138c6SAndroid Build Coastguard Worker 	filter_dc_notch16(in, st->notch_radius, st->input, framesize, st->notch_mem);
1105*28e138c6SAndroid Build Coastguard Worker 	mdf_preemph(st, xx, far_end, framesize);
1106*28e138c6SAndroid Build Coastguard Worker 
1107*28e138c6SAndroid Build Coastguard Worker    	{
1108*28e138c6SAndroid Build Coastguard Worker 
1109*28e138c6SAndroid Build Coastguard Worker 	register spx_word16_t * restrict X = st->X;
1110*28e138c6SAndroid Build Coastguard Worker 
1111*28e138c6SAndroid Build Coastguard Worker 	for ( j=M-1 ; j>=0 ; j-- )
1112*28e138c6SAndroid Build Coastguard Worker 	{	register spx_word16_t * restrict Xdes = &(X[(j+1)*N]);
1113*28e138c6SAndroid Build Coastguard Worker 		register spx_word16_t * restrict Xsrc = &(X[j*N]);
1114*28e138c6SAndroid Build Coastguard Worker 
1115*28e138c6SAndroid Build Coastguard Worker 		memcpy(Xdes, Xsrc, N * sizeof(spx_word16_t));
1116*28e138c6SAndroid Build Coastguard Worker 	}
1117*28e138c6SAndroid Build Coastguard Worker 
1118*28e138c6SAndroid Build Coastguard Worker 	spx_fft(st->fft_table, x, X);
1119*28e138c6SAndroid Build Coastguard Worker 	memcpy(st->last_y, st->x, N * sizeof(spx_word16_t));
1120*28e138c6SAndroid Build Coastguard Worker 	Sxx = mdf_inner_prod(xx, xx, framesize);
1121*28e138c6SAndroid Build Coastguard Worker 	memcpy(x, xx, framesize * sizeof(spx_word16_t));
1122*28e138c6SAndroid Build Coastguard Worker 
1123*28e138c6SAndroid Build Coastguard Worker #ifdef TWO_PATH
1124*28e138c6SAndroid Build Coastguard Worker 	spectral_mul_accum(st->X, st->foreground, st->Y, N, M);
1125*28e138c6SAndroid Build Coastguard Worker 	spx_ifft(st->fft_table, st->Y, st->e);
1126*28e138c6SAndroid Build Coastguard Worker 	mdf_sub(xx, st->input, ee, framesize);
1127*28e138c6SAndroid Build Coastguard Worker 	Sff = mdf_inner_prod(xx, xx, framesize);
1128*28e138c6SAndroid Build Coastguard Worker #endif
1129*28e138c6SAndroid Build Coastguard Worker 
1130*28e138c6SAndroid Build Coastguard Worker 	mdf_adjust_prop (st->W, N, M, st->prop);
1131*28e138c6SAndroid Build Coastguard Worker 
1132*28e138c6SAndroid Build Coastguard Worker 	if (st->saturated == 0)
1133*28e138c6SAndroid Build Coastguard Worker 	{	mdf_compute_weight_gradient(st, X, N, M);
1134*28e138c6SAndroid Build Coastguard Worker 	} else
1135*28e138c6SAndroid Build Coastguard Worker 	{	st->saturated--;
1136*28e138c6SAndroid Build Coastguard Worker 	}
1137*28e138c6SAndroid Build Coastguard Worker 	}
1138*28e138c6SAndroid Build Coastguard Worker 
1139*28e138c6SAndroid Build Coastguard Worker 	mdf_update_weight(st, N, M, framesize);
1140*28e138c6SAndroid Build Coastguard Worker 	spectral_mul_accum(st->X, st->W, st->Y, N, M);
1141*28e138c6SAndroid Build Coastguard Worker 	spx_ifft(st->fft_table, st->Y, st->y);
1142*28e138c6SAndroid Build Coastguard Worker 
1143*28e138c6SAndroid Build Coastguard Worker #ifdef TWO_PATH
1144*28e138c6SAndroid Build Coastguard Worker 	mdf_sub(xx, ee, yy, framesize);
1145*28e138c6SAndroid Build Coastguard Worker 	Dbf = 10+mdf_inner_prod(xx, xx, framesize);
1146*28e138c6SAndroid Build Coastguard Worker #endif
1147*28e138c6SAndroid Build Coastguard Worker 
1148*28e138c6SAndroid Build Coastguard Worker 	mdf_sub(xx, st->input, yy, framesize);
1149*28e138c6SAndroid Build Coastguard Worker 	See = mdf_inner_prod(xx, xx, framesize);
1150*28e138c6SAndroid Build Coastguard Worker 
1151*28e138c6SAndroid Build Coastguard Worker #ifndef TWO_PATH
1152*28e138c6SAndroid Build Coastguard Worker 	Sff = See;
1153*28e138c6SAndroid Build Coastguard Worker #else
1154*28e138c6SAndroid Build Coastguard Worker 	See = mdf_update_foreground(st,Dbf,Sff,See);
1155*28e138c6SAndroid Build Coastguard Worker #endif
1156*28e138c6SAndroid Build Coastguard Worker 
1157*28e138c6SAndroid Build Coastguard Worker 
1158*28e138c6SAndroid Build Coastguard Worker 	mdf_compute_error_signal(st, in, out, framesize);
1159*28e138c6SAndroid Build Coastguard Worker 	Sey = mdf_inner_prod(ee, yy, framesize);
1160*28e138c6SAndroid Build Coastguard Worker 	Syy = mdf_inner_prod(yy, yy, framesize);
1161*28e138c6SAndroid Build Coastguard Worker 	Sdd = mdf_inner_prod(st->input, st->input, framesize);
1162*28e138c6SAndroid Build Coastguard Worker 
1163*28e138c6SAndroid Build Coastguard Worker 	if ( mdf_check(st,out,Syy,Sxx,See,Sff,Sdd) >= 50 )
1164*28e138c6SAndroid Build Coastguard Worker 	{	speex_warning("The echo canceller started acting funny and got slapped (reset). It swears it will behave now.");
1165*28e138c6SAndroid Build Coastguard Worker 		speex_echo_state_reset(st);
1166*28e138c6SAndroid Build Coastguard Worker 		return;
1167*28e138c6SAndroid Build Coastguard Worker 	}
1168*28e138c6SAndroid Build Coastguard Worker 
1169*28e138c6SAndroid Build Coastguard Worker 	See = MAX32(See, SHR32(MULT16_16(N, 100),6));
1170*28e138c6SAndroid Build Coastguard Worker 	spx_fft(st->fft_table, st->e, st->E);
1171*28e138c6SAndroid Build Coastguard Worker 	memset(st->y, 0, framesize * sizeof(spx_word16_t));
1172*28e138c6SAndroid Build Coastguard Worker 	spx_fft(st->fft_table, st->y, st->Y);
1173*28e138c6SAndroid Build Coastguard Worker 	power_spectrum(st->E, st->Rf, N);
1174*28e138c6SAndroid Build Coastguard Worker 	power_spectrum(st->Y, st->Yf, N);
1175*28e138c6SAndroid Build Coastguard Worker 	power_spectrum(st->X, st->Xf, N);
1176*28e138c6SAndroid Build Coastguard Worker 
1177*28e138c6SAndroid Build Coastguard Worker 	mdf_smooth(st->power,st->Xf,framesize, M);
1178*28e138c6SAndroid Build Coastguard Worker 	mdf_compute_filtered_spectra_crosscorrelations(st,Syy,See,framesize);
1179*28e138c6SAndroid Build Coastguard Worker 	RER = mdf_compute_RER(See,Syy,Sey,Sxx,st->leak_estimate);
1180*28e138c6SAndroid Build Coastguard Worker 	mdf_adapt(st, RER, Syy, See, Sxx);
1181*28e138c6SAndroid Build Coastguard Worker 
1182*28e138c6SAndroid Build Coastguard Worker 	if ( st->adapted )
1183*28e138c6SAndroid Build Coastguard Worker 	{	register spx_word16_t * restrict last_yy = st->last_y + framesize;
1184*28e138c6SAndroid Build Coastguard Worker 
1185*28e138c6SAndroid Build Coastguard Worker 		memcpy(st->last_y, last_yy, framesize * sizeof(spx_word16_t));
1186*28e138c6SAndroid Build Coastguard Worker 		mdf_sub_int(last_yy, in, out, framesize);
1187*28e138c6SAndroid Build Coastguard Worker 
1188*28e138c6SAndroid Build Coastguard Worker 	}
1189*28e138c6SAndroid Build Coastguard Worker }
1190*28e138c6SAndroid Build Coastguard Worker 
1191*28e138c6SAndroid Build Coastguard Worker 
1192*28e138c6SAndroid Build Coastguard Worker 
1193