1b815c7f3Sopenharmony_ci/*
2b815c7f3Sopenharmony_ci * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
3b815c7f3Sopenharmony_ci * Universitaet Berlin.  See the accompanying file "COPYRIGHT" for
4b815c7f3Sopenharmony_ci * details.  THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
5b815c7f3Sopenharmony_ci */
6b815c7f3Sopenharmony_ci
7b815c7f3Sopenharmony_ci#include <stdio.h>
8b815c7f3Sopenharmony_ci#include <assert.h>
9b815c7f3Sopenharmony_ci
10b815c7f3Sopenharmony_ci#include "gsm610_priv.h"
11b815c7f3Sopenharmony_ci
12b815c7f3Sopenharmony_ci/*
13b815c7f3Sopenharmony_ci *  4.2.11 .. 4.2.12 LONG TERM PREDICTOR (LTP) SECTION
14b815c7f3Sopenharmony_ci */
15b815c7f3Sopenharmony_ci
16b815c7f3Sopenharmony_ci
17b815c7f3Sopenharmony_ci/*
18b815c7f3Sopenharmony_ci * This module computes the LTP gain (bc) and the LTP lag (Nc)
19b815c7f3Sopenharmony_ci * for the long term analysis filter.   This is done by calculating a
20b815c7f3Sopenharmony_ci * maximum of the cross-correlation function between the current
21b815c7f3Sopenharmony_ci * sub-segment short term residual signal d [0..39] (output of
22b815c7f3Sopenharmony_ci * the short term analysis filter ; for simplification the index
23b815c7f3Sopenharmony_ci * of this array begins at 0 and ends at 39 for each sub-segment of the
24b815c7f3Sopenharmony_ci * RPE-LTP analysis) and the previous reconstructed short term
25b815c7f3Sopenharmony_ci * residual signal dp [-120 .. -1].  A dynamic scaling must be
26b815c7f3Sopenharmony_ci * performed to avoid overflow.
27b815c7f3Sopenharmony_ci */
28b815c7f3Sopenharmony_ci
29b815c7f3Sopenharmony_ci /* The next procedure exists in six versions.  First two integer
30b815c7f3Sopenharmony_ci  * version (if USE_FLOAT_MUL is not defined) ; then four floating
31b815c7f3Sopenharmony_ci  * point versions, twice with proper scaling (USE_FLOAT_MUL defined),
32b815c7f3Sopenharmony_ci  * once without (USE_FLOAT_MUL and FAST defined, and fast run-time
33b815c7f3Sopenharmony_ci  * option used).  Every pair has first a Cut version (see the -C
34b815c7f3Sopenharmony_ci  * option to toast or the LTP_CUT option to gsm_option ()), then the
35b815c7f3Sopenharmony_ci  * uncut one.  (For a detailed explanation of why this is altogether
36b815c7f3Sopenharmony_ci  * a bad idea, see Henry Spencer and Geoff Collyer, ``#ifdef Considered
37b815c7f3Sopenharmony_ci  * Harmful''.)
38b815c7f3Sopenharmony_ci  */
39b815c7f3Sopenharmony_ci
40b815c7f3Sopenharmony_ci#ifndef	USE_FLOAT_MUL
41b815c7f3Sopenharmony_ci
42b815c7f3Sopenharmony_ci#ifdef	LTP_CUT
43b815c7f3Sopenharmony_ci
44b815c7f3Sopenharmony_cistatic void Cut_Calculation_of_the_LTP_parameters (
45b815c7f3Sopenharmony_ci
46b815c7f3Sopenharmony_ci	struct gsm_state * st,
47b815c7f3Sopenharmony_ci
48b815c7f3Sopenharmony_ci	register int16_t	* d,		/* [0..39]	IN	*/
49b815c7f3Sopenharmony_ci	register int16_t	* dp,		/* [-120..-1]	IN	*/
50b815c7f3Sopenharmony_ci	int16_t		* bc_out,	/* 		OUT	*/
51b815c7f3Sopenharmony_ci	int16_t		* Nc_out	/* 		OUT	*/)
52b815c7f3Sopenharmony_ci{
53b815c7f3Sopenharmony_ci	register int	k, lambda ;
54b815c7f3Sopenharmony_ci	int16_t		Nc, bc ;
55b815c7f3Sopenharmony_ci	int16_t		wt [40] ;
56b815c7f3Sopenharmony_ci
57b815c7f3Sopenharmony_ci	int32_t	L_result ;
58b815c7f3Sopenharmony_ci	int32_t	L_max, L_power ;
59b815c7f3Sopenharmony_ci	int16_t		R, S, dmax, scal, best_k ;
60b815c7f3Sopenharmony_ci	int16_t		ltp_cut ;
61b815c7f3Sopenharmony_ci
62b815c7f3Sopenharmony_ci	register int16_t	temp, wt_k ;
63b815c7f3Sopenharmony_ci
64b815c7f3Sopenharmony_ci	/*  Search of the optimum scaling of d [0..39]. */
65b815c7f3Sopenharmony_ci	dmax = 0 ;
66b815c7f3Sopenharmony_ci	for (k = 0 ; k <= 39 ; k++)
67b815c7f3Sopenharmony_ci	{	temp = d [k] ;
68b815c7f3Sopenharmony_ci		temp = GSM_ABS (temp) ;
69b815c7f3Sopenharmony_ci		if (temp > dmax)
70b815c7f3Sopenharmony_ci		{	dmax = temp ;
71b815c7f3Sopenharmony_ci			best_k = k ;
72b815c7f3Sopenharmony_ci			}
73b815c7f3Sopenharmony_ci		}
74b815c7f3Sopenharmony_ci	temp = 0 ;
75b815c7f3Sopenharmony_ci	if (dmax == 0)
76b815c7f3Sopenharmony_ci		scal = 0 ;
77b815c7f3Sopenharmony_ci	else
78b815c7f3Sopenharmony_ci	{	assert (dmax > 0) ;
79b815c7f3Sopenharmony_ci		temp = gsm_norm ((int32_t) dmax << 16) ;
80b815c7f3Sopenharmony_ci		}
81b815c7f3Sopenharmony_ci	if (temp > 6) scal = 0 ;
82b815c7f3Sopenharmony_ci	else scal = 6 - temp ;
83b815c7f3Sopenharmony_ci	assert (scal >= 0) ;
84b815c7f3Sopenharmony_ci
85b815c7f3Sopenharmony_ci	/* Search for the maximum cross-correlation and coding of the LTP lag
86b815c7f3Sopenharmony_ci	 */
87b815c7f3Sopenharmony_ci	L_max = 0 ;
88b815c7f3Sopenharmony_ci	Nc = 40 ;	/* index for the maximum cross-correlation */
89b815c7f3Sopenharmony_ci	wt_k = SASR_W (d [best_k], scal) ;
90b815c7f3Sopenharmony_ci
91b815c7f3Sopenharmony_ci	for (lambda = 40 ; lambda <= 120 ; lambda++)
92b815c7f3Sopenharmony_ci	{	L_result = (int32_t) wt_k * dp [best_k - lambda] ;
93b815c7f3Sopenharmony_ci		if (L_result > L_max)
94b815c7f3Sopenharmony_ci		{	Nc = lambda ;
95b815c7f3Sopenharmony_ci			L_max = L_result ;
96b815c7f3Sopenharmony_ci			}
97b815c7f3Sopenharmony_ci		}
98b815c7f3Sopenharmony_ci	*Nc_out = Nc ;
99b815c7f3Sopenharmony_ci	L_max <<= 1 ;
100b815c7f3Sopenharmony_ci
101b815c7f3Sopenharmony_ci	/*  Rescaling of L_max
102b815c7f3Sopenharmony_ci	 */
103b815c7f3Sopenharmony_ci	assert (scal <= 100 && scal >= -100) ;
104b815c7f3Sopenharmony_ci	L_max = L_max >> (6 - scal) ;	/* sub (6, scal) */
105b815c7f3Sopenharmony_ci
106b815c7f3Sopenharmony_ci	assert (Nc <= 120 && Nc >= 40) ;
107b815c7f3Sopenharmony_ci
108b815c7f3Sopenharmony_ci	/*   Compute the power of the reconstructed short term residual
109b815c7f3Sopenharmony_ci	 *   signal dp [..]
110b815c7f3Sopenharmony_ci	 */
111b815c7f3Sopenharmony_ci	L_power = 0 ;
112b815c7f3Sopenharmony_ci	for (k = 0 ; k <= 39 ; k++)
113b815c7f3Sopenharmony_ci	{	register int32_t L_temp ;
114b815c7f3Sopenharmony_ci
115b815c7f3Sopenharmony_ci		L_temp = SASR_W (dp [k - Nc], 3) ;
116b815c7f3Sopenharmony_ci		L_power += L_temp * L_temp ;
117b815c7f3Sopenharmony_ci		}
118b815c7f3Sopenharmony_ci	L_power <<= 1 ;	/* from L_MULT */
119b815c7f3Sopenharmony_ci
120b815c7f3Sopenharmony_ci	/*  Normalization of L_max and L_power */
121b815c7f3Sopenharmony_ci
122b815c7f3Sopenharmony_ci	if (L_max <= 0)
123b815c7f3Sopenharmony_ci	{	*bc_out = 0 ;
124b815c7f3Sopenharmony_ci		return ;
125b815c7f3Sopenharmony_ci		}
126b815c7f3Sopenharmony_ci	if (L_max >= L_power)
127b815c7f3Sopenharmony_ci	{	*bc_out = 3 ;
128b815c7f3Sopenharmony_ci		return ;
129b815c7f3Sopenharmony_ci		}
130b815c7f3Sopenharmony_ci
131b815c7f3Sopenharmony_ci	temp = gsm_norm (L_power) ;
132b815c7f3Sopenharmony_ci
133b815c7f3Sopenharmony_ci	R = SASR (L_max << temp, 16) ;
134b815c7f3Sopenharmony_ci	S = SASR (L_power << temp, 16) ;
135b815c7f3Sopenharmony_ci
136b815c7f3Sopenharmony_ci	/*  Coding of the LTP gain
137b815c7f3Sopenharmony_ci	 */
138b815c7f3Sopenharmony_ci
139b815c7f3Sopenharmony_ci	/*  Table 4.3a must be used to obtain the level DLB [i] for the
140b815c7f3Sopenharmony_ci	 *  quantization of the LTP gain b to get the coded version bc.
141b815c7f3Sopenharmony_ci	 */
142b815c7f3Sopenharmony_ci	for (bc = 0 ; bc <= 2 ; bc++) if (R <= gsm_mult (S, gsm_DLB [bc])) break ;
143b815c7f3Sopenharmony_ci	*bc_out = bc ;
144b815c7f3Sopenharmony_ci}
145b815c7f3Sopenharmony_ci
146b815c7f3Sopenharmony_ci#endif 	/* LTP_CUT */
147b815c7f3Sopenharmony_ci
148b815c7f3Sopenharmony_cistatic void Calculation_of_the_LTP_parameters (
149b815c7f3Sopenharmony_ci	register int16_t	* d,		/* [0..39]	IN	*/
150b815c7f3Sopenharmony_ci	register int16_t	* dp,		/* [-120..-1]	IN	*/
151b815c7f3Sopenharmony_ci	int16_t		* bc_out,	/* 		OUT	*/
152b815c7f3Sopenharmony_ci	int16_t		* Nc_out	/* 		OUT	*/)
153b815c7f3Sopenharmony_ci{
154b815c7f3Sopenharmony_ci	register int	k, lambda ;
155b815c7f3Sopenharmony_ci	int16_t		Nc, bc ;
156b815c7f3Sopenharmony_ci	int16_t		wt [40] ;
157b815c7f3Sopenharmony_ci
158b815c7f3Sopenharmony_ci	int32_t	L_max, L_power ;
159b815c7f3Sopenharmony_ci	int16_t		R, S, dmax, scal ;
160b815c7f3Sopenharmony_ci	register int16_t	temp ;
161b815c7f3Sopenharmony_ci
162b815c7f3Sopenharmony_ci	/*  Search of the optimum scaling of d [0..39].
163b815c7f3Sopenharmony_ci	 */
164b815c7f3Sopenharmony_ci	dmax = 0 ;
165b815c7f3Sopenharmony_ci
166b815c7f3Sopenharmony_ci	for (k = 0 ; k <= 39 ; k++)
167b815c7f3Sopenharmony_ci	{	temp = d [k] ;
168b815c7f3Sopenharmony_ci		temp = GSM_ABS (temp) ;
169b815c7f3Sopenharmony_ci		if (temp > dmax) dmax = temp ;
170b815c7f3Sopenharmony_ci		}
171b815c7f3Sopenharmony_ci
172b815c7f3Sopenharmony_ci	temp = 0 ;
173b815c7f3Sopenharmony_ci	if (dmax == 0)
174b815c7f3Sopenharmony_ci		scal = 0 ;
175b815c7f3Sopenharmony_ci	else
176b815c7f3Sopenharmony_ci	{	assert (dmax > 0) ;
177b815c7f3Sopenharmony_ci		temp = gsm_norm ((int32_t) dmax << 16) ;
178b815c7f3Sopenharmony_ci		}
179b815c7f3Sopenharmony_ci
180b815c7f3Sopenharmony_ci	if (temp > 6) scal = 0 ;
181b815c7f3Sopenharmony_ci	else scal = 6 - temp ;
182b815c7f3Sopenharmony_ci
183b815c7f3Sopenharmony_ci	assert (scal >= 0) ;
184b815c7f3Sopenharmony_ci
185b815c7f3Sopenharmony_ci	/*  Initialization of a working array wt
186b815c7f3Sopenharmony_ci	 */
187b815c7f3Sopenharmony_ci
188b815c7f3Sopenharmony_ci	for (k = 0 ; k <= 39 ; k++) wt [k] = SASR_W (d [k], scal) ;
189b815c7f3Sopenharmony_ci
190b815c7f3Sopenharmony_ci	/* Search for the maximum cross-correlation and coding of the LTP lag */
191b815c7f3Sopenharmony_ci	L_max = 0 ;
192b815c7f3Sopenharmony_ci	Nc = 40 ;	/* index for the maximum cross-correlation */
193b815c7f3Sopenharmony_ci
194b815c7f3Sopenharmony_ci	for (lambda = 40 ; lambda <= 120 ; lambda++)
195b815c7f3Sopenharmony_ci	{
196b815c7f3Sopenharmony_ci
197b815c7f3Sopenharmony_ci# undef STEP
198b815c7f3Sopenharmony_ci#		define STEP(k) 	(int32_t) wt [k] * dp [k - lambda]
199b815c7f3Sopenharmony_ci
200b815c7f3Sopenharmony_ci		register int32_t L_result ;
201b815c7f3Sopenharmony_ci
202b815c7f3Sopenharmony_ci		L_result = STEP (0) ; L_result += STEP (1) ;
203b815c7f3Sopenharmony_ci		L_result += STEP (2) ; L_result += STEP (3) ;
204b815c7f3Sopenharmony_ci		L_result += STEP (4) ; L_result += STEP (5) ;
205b815c7f3Sopenharmony_ci		L_result += STEP (6) ; L_result += STEP (7) ;
206b815c7f3Sopenharmony_ci		L_result += STEP (8) ; L_result += STEP (9) ;
207b815c7f3Sopenharmony_ci		L_result += STEP (10) ; L_result += STEP (11) ;
208b815c7f3Sopenharmony_ci		L_result += STEP (12) ; L_result += STEP (13) ;
209b815c7f3Sopenharmony_ci		L_result += STEP (14) ; L_result += STEP (15) ;
210b815c7f3Sopenharmony_ci		L_result += STEP (16) ; L_result += STEP (17) ;
211b815c7f3Sopenharmony_ci		L_result += STEP (18) ; L_result += STEP (19) ;
212b815c7f3Sopenharmony_ci		L_result += STEP (20) ; L_result += STEP (21) ;
213b815c7f3Sopenharmony_ci		L_result += STEP (22) ; L_result += STEP (23) ;
214b815c7f3Sopenharmony_ci		L_result += STEP (24) ; L_result += STEP (25) ;
215b815c7f3Sopenharmony_ci		L_result += STEP (26) ; L_result += STEP (27) ;
216b815c7f3Sopenharmony_ci		L_result += STEP (28) ; L_result += STEP (29) ;
217b815c7f3Sopenharmony_ci		L_result += STEP (30) ; L_result += STEP (31) ;
218b815c7f3Sopenharmony_ci		L_result += STEP (32) ; L_result += STEP (33) ;
219b815c7f3Sopenharmony_ci		L_result += STEP (34) ; L_result += STEP (35) ;
220b815c7f3Sopenharmony_ci		L_result += STEP (36) ; L_result += STEP (37) ;
221b815c7f3Sopenharmony_ci		L_result += STEP (38) ; L_result += STEP (39) ;
222b815c7f3Sopenharmony_ci
223b815c7f3Sopenharmony_ci		if (L_result > L_max)
224b815c7f3Sopenharmony_ci		{	Nc = lambda ;
225b815c7f3Sopenharmony_ci			L_max = L_result ;
226b815c7f3Sopenharmony_ci			}
227b815c7f3Sopenharmony_ci		}
228b815c7f3Sopenharmony_ci
229b815c7f3Sopenharmony_ci	*Nc_out = Nc ;
230b815c7f3Sopenharmony_ci
231b815c7f3Sopenharmony_ci	L_max <<= 1 ;
232b815c7f3Sopenharmony_ci
233b815c7f3Sopenharmony_ci	/*  Rescaling of L_max
234b815c7f3Sopenharmony_ci	 */
235b815c7f3Sopenharmony_ci	assert (scal <= 100 && scal >= -100) ;
236b815c7f3Sopenharmony_ci	L_max = L_max >> (6 - scal) ;	/* sub (6, scal) */
237b815c7f3Sopenharmony_ci
238b815c7f3Sopenharmony_ci	assert (Nc <= 120 && Nc >= 40) ;
239b815c7f3Sopenharmony_ci
240b815c7f3Sopenharmony_ci	/*   Compute the power of the reconstructed short term residual
241b815c7f3Sopenharmony_ci	 *   signal dp [..]
242b815c7f3Sopenharmony_ci	 */
243b815c7f3Sopenharmony_ci	L_power = 0 ;
244b815c7f3Sopenharmony_ci	for (k = 0 ; k <= 39 ; k++)
245b815c7f3Sopenharmony_ci	{	register int32_t L_temp ;
246b815c7f3Sopenharmony_ci
247b815c7f3Sopenharmony_ci		L_temp = SASR_W (dp [k - Nc], 3) ;
248b815c7f3Sopenharmony_ci		L_power += L_temp * L_temp ;
249b815c7f3Sopenharmony_ci		}
250b815c7f3Sopenharmony_ci	L_power <<= 1 ;	/* from L_MULT */
251b815c7f3Sopenharmony_ci
252b815c7f3Sopenharmony_ci	/*  Normalization of L_max and L_power
253b815c7f3Sopenharmony_ci	 */
254b815c7f3Sopenharmony_ci
255b815c7f3Sopenharmony_ci	if (L_max <= 0)
256b815c7f3Sopenharmony_ci	{	*bc_out = 0 ;
257b815c7f3Sopenharmony_ci		return ;
258b815c7f3Sopenharmony_ci		}
259b815c7f3Sopenharmony_ci	if (L_max >= L_power)
260b815c7f3Sopenharmony_ci	{	*bc_out = 3 ;
261b815c7f3Sopenharmony_ci		return ;
262b815c7f3Sopenharmony_ci		}
263b815c7f3Sopenharmony_ci
264b815c7f3Sopenharmony_ci	temp = gsm_norm (L_power) ;
265b815c7f3Sopenharmony_ci
266b815c7f3Sopenharmony_ci	R = SASR_L (L_max << temp, 16) ;
267b815c7f3Sopenharmony_ci	S = SASR_L (L_power << temp, 16) ;
268b815c7f3Sopenharmony_ci
269b815c7f3Sopenharmony_ci	/*  Coding of the LTP gain
270b815c7f3Sopenharmony_ci	 */
271b815c7f3Sopenharmony_ci
272b815c7f3Sopenharmony_ci	/*  Table 4.3a must be used to obtain the level DLB [i] for the
273b815c7f3Sopenharmony_ci	 *  quantization of the LTP gain b to get the coded version bc.
274b815c7f3Sopenharmony_ci	 */
275b815c7f3Sopenharmony_ci	for (bc = 0 ; bc <= 2 ; bc++) if (R <= gsm_mult (S, gsm_DLB [bc])) break ;
276b815c7f3Sopenharmony_ci	*bc_out = bc ;
277b815c7f3Sopenharmony_ci}
278b815c7f3Sopenharmony_ci
279b815c7f3Sopenharmony_ci#else	/* USE_FLOAT_MUL */
280b815c7f3Sopenharmony_ci
281b815c7f3Sopenharmony_ci#ifdef	LTP_CUT
282b815c7f3Sopenharmony_ci
283b815c7f3Sopenharmony_cistatic void Cut_Calculation_of_the_LTP_parameters (
284b815c7f3Sopenharmony_ci	struct gsm_state * st,		/*              IN 	*/
285b815c7f3Sopenharmony_ci	register int16_t	* d,		/* [0..39]	IN	*/
286b815c7f3Sopenharmony_ci	register int16_t	* dp,		/* [-120..-1]	IN	*/
287b815c7f3Sopenharmony_ci	int16_t		* bc_out,	/* 		OUT	*/
288b815c7f3Sopenharmony_ci	int16_t		* Nc_out	/* 		OUT	*/)
289b815c7f3Sopenharmony_ci{
290b815c7f3Sopenharmony_ci	register int	k, lambda ;
291b815c7f3Sopenharmony_ci	int16_t		Nc, bc ;
292b815c7f3Sopenharmony_ci	int16_t		ltp_cut ;
293b815c7f3Sopenharmony_ci
294b815c7f3Sopenharmony_ci	float		wt_float [40] ;
295b815c7f3Sopenharmony_ci	float		dp_float_base [120], * dp_float = dp_float_base + 120 ;
296b815c7f3Sopenharmony_ci
297b815c7f3Sopenharmony_ci	int32_t	L_max, L_power ;
298b815c7f3Sopenharmony_ci	int16_t		R, S, dmax, scal ;
299b815c7f3Sopenharmony_ci	register int16_t	temp ;
300b815c7f3Sopenharmony_ci
301b815c7f3Sopenharmony_ci	/*  Search of the optimum scaling of d [0..39].
302b815c7f3Sopenharmony_ci	 */
303b815c7f3Sopenharmony_ci	dmax = 0 ;
304b815c7f3Sopenharmony_ci
305b815c7f3Sopenharmony_ci	for (k = 0 ; k <= 39 ; k++)
306b815c7f3Sopenharmony_ci	{	temp = d [k] ;
307b815c7f3Sopenharmony_ci		temp = GSM_ABS (temp) ;
308b815c7f3Sopenharmony_ci		if (temp > dmax) dmax = temp ;
309b815c7f3Sopenharmony_ci		}
310b815c7f3Sopenharmony_ci
311b815c7f3Sopenharmony_ci	temp = 0 ;
312b815c7f3Sopenharmony_ci	if (dmax == 0) scal = 0 ;
313b815c7f3Sopenharmony_ci	else
314b815c7f3Sopenharmony_ci	{	assert (dmax > 0) ;
315b815c7f3Sopenharmony_ci		temp = gsm_norm ((int32_t) dmax << 16) ;
316b815c7f3Sopenharmony_ci		}
317b815c7f3Sopenharmony_ci
318b815c7f3Sopenharmony_ci	if (temp > 6) scal = 0 ;
319b815c7f3Sopenharmony_ci	else scal = 6 - temp ;
320b815c7f3Sopenharmony_ci
321b815c7f3Sopenharmony_ci	assert (scal >= 0) ;
322b815c7f3Sopenharmony_ci	ltp_cut = (int32_t) SASR_W (dmax, scal) * st->ltp_cut / 100 ;
323b815c7f3Sopenharmony_ci
324b815c7f3Sopenharmony_ci	/*  Initialization of a working array wt */
325b815c7f3Sopenharmony_ci
326b815c7f3Sopenharmony_ci	for (k = 0 ; k < 40 ; k++)
327b815c7f3Sopenharmony_ci	{	register int16_t w = SASR_W (d [k], scal) ;
328b815c7f3Sopenharmony_ci		if (w < 0 ? w > -ltp_cut : w < ltp_cut)
329b815c7f3Sopenharmony_ci			wt_float [k] = 0.0 ;
330b815c7f3Sopenharmony_ci		else
331b815c7f3Sopenharmony_ci			wt_float [k] = w ;
332b815c7f3Sopenharmony_ci		}
333b815c7f3Sopenharmony_ci	for (k = -120 ; k < 0 ; k++) dp_float [k] = dp [k] ;
334b815c7f3Sopenharmony_ci
335b815c7f3Sopenharmony_ci	/* Search for the maximum cross-correlation and coding of the LTP lag
336b815c7f3Sopenharmony_ci	 */
337b815c7f3Sopenharmony_ci	L_max = 0 ;
338b815c7f3Sopenharmony_ci	Nc = 40 ;	/* index for the maximum cross-correlation */
339b815c7f3Sopenharmony_ci
340b815c7f3Sopenharmony_ci	for (lambda = 40 ; lambda <= 120 ; lambda += 9)
341b815c7f3Sopenharmony_ci	{	/*  Calculate L_result for l = lambda .. lambda + 9. */
342b815c7f3Sopenharmony_ci		register float *lp = dp_float - lambda ;
343b815c7f3Sopenharmony_ci
344b815c7f3Sopenharmony_ci		register float W ;
345b815c7f3Sopenharmony_ci		register float a = lp [-8], b = lp [-7], c = lp [-6],
346b815c7f3Sopenharmony_ci						d = lp [-5], e = lp [-4], f = lp [-3],
347b815c7f3Sopenharmony_ci						g = lp [-2], h = lp [-1] ;
348b815c7f3Sopenharmony_ci		register float E ;
349b815c7f3Sopenharmony_ci		register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0,
350b815c7f3Sopenharmony_ci						S5 = 0, S6 = 0, S7 = 0, S8 = 0 ;
351b815c7f3Sopenharmony_ci
352b815c7f3Sopenharmony_ci#		undef STEP
353b815c7f3Sopenharmony_ci#		define	STEP(K, a, b, c, d, e, f, g, h) \
354b815c7f3Sopenharmony_ci			if ((W = wt_float [K]) != 0.0) {	\
355b815c7f3Sopenharmony_ci			E = W * a ; S8 += E ;		\
356b815c7f3Sopenharmony_ci			E = W * b ; S7 += E ;		\
357b815c7f3Sopenharmony_ci			E = W * c ; S6 += E ;		\
358b815c7f3Sopenharmony_ci			E = W * d ; S5 += E ;		\
359b815c7f3Sopenharmony_ci			E = W * e ; S4 += E ;		\
360b815c7f3Sopenharmony_ci			E = W * f ; S3 += E ;		\
361b815c7f3Sopenharmony_ci			E = W * g ; S2 += E ;		\
362b815c7f3Sopenharmony_ci			E = W * h ; S1 += E ;		\
363b815c7f3Sopenharmony_ci			a = lp [K] ;				\
364b815c7f3Sopenharmony_ci			E = W * a ; S0 += E ; } else (a = lp [K])
365b815c7f3Sopenharmony_ci
366b815c7f3Sopenharmony_ci#		define	STEP_A(K)	STEP (K, a, b, c, d, e, f, g, h)
367b815c7f3Sopenharmony_ci#		define	STEP_B(K)	STEP (K, b, c, d, e, f, g, h, a)
368b815c7f3Sopenharmony_ci#		define	STEP_C(K)	STEP (K, c, d, e, f, g, h, a, b)
369b815c7f3Sopenharmony_ci#		define	STEP_D(K)	STEP (K, d, e, f, g, h, a, b, c)
370b815c7f3Sopenharmony_ci#		define	STEP_E(K)	STEP (K, e, f, g, h, a, b, c, d)
371b815c7f3Sopenharmony_ci#		define	STEP_F(K)	STEP (K, f, g, h, a, b, c, d, e)
372b815c7f3Sopenharmony_ci#		define	STEP_G(K)	STEP (K, g, h, a, b, c, d, e, f)
373b815c7f3Sopenharmony_ci#		define	STEP_H(K)	STEP (K, h, a, b, c, d, e, f, g)
374b815c7f3Sopenharmony_ci
375b815c7f3Sopenharmony_ci		STEP_A (0) ; STEP_B (1) ; STEP_C (2) ; STEP_D (3) ;
376b815c7f3Sopenharmony_ci		STEP_E (4) ; STEP_F (5) ; STEP_G (6) ; STEP_H (7) ;
377b815c7f3Sopenharmony_ci
378b815c7f3Sopenharmony_ci		STEP_A (8) ; STEP_B (9) ; STEP_C (10) ; STEP_D (11) ;
379b815c7f3Sopenharmony_ci		STEP_E (12) ; STEP_F (13) ; STEP_G (14) ; STEP_H (15) ;
380b815c7f3Sopenharmony_ci
381b815c7f3Sopenharmony_ci		STEP_A (16) ; STEP_B (17) ; STEP_C (18) ; STEP_D (19) ;
382b815c7f3Sopenharmony_ci		STEP_E (20) ; STEP_F (21) ; STEP_G (22) ; STEP_H (23) ;
383b815c7f3Sopenharmony_ci
384b815c7f3Sopenharmony_ci		STEP_A (24) ; STEP_B (25) ; STEP_C (26) ; STEP_D (27) ;
385b815c7f3Sopenharmony_ci		STEP_E (28) ; STEP_F (29) ; STEP_G (30) ; STEP_H (31) ;
386b815c7f3Sopenharmony_ci
387b815c7f3Sopenharmony_ci		STEP_A (32) ; STEP_B (33) ; STEP_C (34) ; STEP_D (35) ;
388b815c7f3Sopenharmony_ci		STEP_E (36) ; STEP_F (37) ; STEP_G (38) ; STEP_H (39) ;
389b815c7f3Sopenharmony_ci
390b815c7f3Sopenharmony_ci#		undef STEP_A
391b815c7f3Sopenharmony_ci#		undef STEP_B
392b815c7f3Sopenharmony_ci#		undef STEP_C
393b815c7f3Sopenharmony_ci#		undef STEP_D
394b815c7f3Sopenharmony_ci#		undef STEP_E
395b815c7f3Sopenharmony_ci#		undef STEP_F
396b815c7f3Sopenharmony_ci#		undef STEP_G
397b815c7f3Sopenharmony_ci#		undef STEP_H
398b815c7f3Sopenharmony_ci
399b815c7f3Sopenharmony_ci		if (S0 > L_max) { L_max = S0 ; Nc = lambda ; }
400b815c7f3Sopenharmony_ci		if (S1 > L_max) { L_max = S1 ; Nc = lambda + 1 ; }
401b815c7f3Sopenharmony_ci		if (S2 > L_max) { L_max = S2 ; Nc = lambda + 2 ; }
402b815c7f3Sopenharmony_ci		if (S3 > L_max) { L_max = S3 ; Nc = lambda + 3 ; }
403b815c7f3Sopenharmony_ci		if (S4 > L_max) { L_max = S4 ; Nc = lambda + 4 ; }
404b815c7f3Sopenharmony_ci		if (S5 > L_max) { L_max = S5 ; Nc = lambda + 5 ; }
405b815c7f3Sopenharmony_ci		if (S6 > L_max) { L_max = S6 ; Nc = lambda + 6 ; }
406b815c7f3Sopenharmony_ci		if (S7 > L_max) { L_max = S7 ; Nc = lambda + 7 ; }
407b815c7f3Sopenharmony_ci		if (S8 > L_max) { L_max = S8 ; Nc = lambda + 8 ; }
408b815c7f3Sopenharmony_ci
409b815c7f3Sopenharmony_ci	}
410b815c7f3Sopenharmony_ci	*Nc_out = Nc ;
411b815c7f3Sopenharmony_ci
412b815c7f3Sopenharmony_ci	L_max <<= 1 ;
413b815c7f3Sopenharmony_ci
414b815c7f3Sopenharmony_ci	/*  Rescaling of L_max
415b815c7f3Sopenharmony_ci	 */
416b815c7f3Sopenharmony_ci	assert (scal <= 100 && scal >= -100) ;
417b815c7f3Sopenharmony_ci	L_max = L_max >> (6 - scal) ;	/* sub (6, scal) */
418b815c7f3Sopenharmony_ci
419b815c7f3Sopenharmony_ci	assert (Nc <= 120 && Nc >= 40) ;
420b815c7f3Sopenharmony_ci
421b815c7f3Sopenharmony_ci	/*   Compute the power of the reconstructed short term residual
422b815c7f3Sopenharmony_ci	 *   signal dp [..]
423b815c7f3Sopenharmony_ci	 */
424b815c7f3Sopenharmony_ci	L_power = 0 ;
425b815c7f3Sopenharmony_ci	for (k = 0 ; k <= 39 ; k++)
426b815c7f3Sopenharmony_ci	{	register int32_t L_temp ;
427b815c7f3Sopenharmony_ci
428b815c7f3Sopenharmony_ci		L_temp = SASR_W (dp [k - Nc], 3) ;
429b815c7f3Sopenharmony_ci		L_power += L_temp * L_temp ;
430b815c7f3Sopenharmony_ci		}
431b815c7f3Sopenharmony_ci	L_power <<= 1 ;	/* from L_MULT */
432b815c7f3Sopenharmony_ci
433b815c7f3Sopenharmony_ci	/*  Normalization of L_max and L_power
434b815c7f3Sopenharmony_ci	 */
435b815c7f3Sopenharmony_ci
436b815c7f3Sopenharmony_ci	if (L_max <= 0)
437b815c7f3Sopenharmony_ci	{	*bc_out = 0 ;
438b815c7f3Sopenharmony_ci		return ;
439b815c7f3Sopenharmony_ci		}
440b815c7f3Sopenharmony_ci	if (L_max >= L_power)
441b815c7f3Sopenharmony_ci	{	*bc_out = 3 ;
442b815c7f3Sopenharmony_ci		return ;
443b815c7f3Sopenharmony_ci		}
444b815c7f3Sopenharmony_ci
445b815c7f3Sopenharmony_ci	temp = gsm_norm (L_power) ;
446b815c7f3Sopenharmony_ci
447b815c7f3Sopenharmony_ci	R = SASR (L_max << temp, 16) ;
448b815c7f3Sopenharmony_ci	S = SASR (L_power << temp, 16) ;
449b815c7f3Sopenharmony_ci
450b815c7f3Sopenharmony_ci	/*  Coding of the LTP gain
451b815c7f3Sopenharmony_ci	 */
452b815c7f3Sopenharmony_ci
453b815c7f3Sopenharmony_ci	/*  Table 4.3a must be used to obtain the level DLB [i] for the
454b815c7f3Sopenharmony_ci	 *  quantization of the LTP gain b to get the coded version bc.
455b815c7f3Sopenharmony_ci	 */
456b815c7f3Sopenharmony_ci	for (bc = 0 ; bc <= 2 ; bc++) if (R <= gsm_mult (S, gsm_DLB [bc])) break ;
457b815c7f3Sopenharmony_ci	*bc_out = bc ;
458b815c7f3Sopenharmony_ci}
459b815c7f3Sopenharmony_ci
460b815c7f3Sopenharmony_ci#endif /* LTP_CUT */
461b815c7f3Sopenharmony_ci
462b815c7f3Sopenharmony_cistatic void Calculation_of_the_LTP_parameters (
463b815c7f3Sopenharmony_ci	register int16_t	* din,		/* [0..39]	IN	*/
464b815c7f3Sopenharmony_ci	register int16_t	* dp,		/* [-120..-1]	IN	*/
465b815c7f3Sopenharmony_ci	int16_t		* bc_out,	/* 		OUT	*/
466b815c7f3Sopenharmony_ci	int16_t		* Nc_out	/* 		OUT	*/)
467b815c7f3Sopenharmony_ci{
468b815c7f3Sopenharmony_ci	register int	k, lambda ;
469b815c7f3Sopenharmony_ci	int16_t	Nc, bc ;
470b815c7f3Sopenharmony_ci
471b815c7f3Sopenharmony_ci	float	wt_float [40] ;
472b815c7f3Sopenharmony_ci	float	dp_float_base [120], * dp_float = dp_float_base + 120 ;
473b815c7f3Sopenharmony_ci
474b815c7f3Sopenharmony_ci	int32_t	L_max, L_power ;
475b815c7f3Sopenharmony_ci	int16_t		R, S, dmax, scal ;
476b815c7f3Sopenharmony_ci	register int16_t	temp ;
477b815c7f3Sopenharmony_ci
478b815c7f3Sopenharmony_ci	/*  Search of the optimum scaling of d [0..39].
479b815c7f3Sopenharmony_ci	 */
480b815c7f3Sopenharmony_ci	dmax = 0 ;
481b815c7f3Sopenharmony_ci
482b815c7f3Sopenharmony_ci	for (k = 0 ; k <= 39 ; k++)
483b815c7f3Sopenharmony_ci	{	temp = din [k] ;
484b815c7f3Sopenharmony_ci		temp = GSM_ABS (temp) ;
485b815c7f3Sopenharmony_ci		if (temp > dmax) dmax = temp ;
486b815c7f3Sopenharmony_ci		}
487b815c7f3Sopenharmony_ci
488b815c7f3Sopenharmony_ci	temp = 0 ;
489b815c7f3Sopenharmony_ci	if (dmax == 0) scal = 0 ;
490b815c7f3Sopenharmony_ci	else
491b815c7f3Sopenharmony_ci	{	assert (dmax > 0) ;
492b815c7f3Sopenharmony_ci		temp = gsm_norm ((int32_t) dmax << 16) ;
493b815c7f3Sopenharmony_ci		}
494b815c7f3Sopenharmony_ci
495b815c7f3Sopenharmony_ci	if (temp > 6) scal = 0 ;
496b815c7f3Sopenharmony_ci	else scal = 6 - temp ;
497b815c7f3Sopenharmony_ci
498b815c7f3Sopenharmony_ci	assert (scal >= 0) ;
499b815c7f3Sopenharmony_ci
500b815c7f3Sopenharmony_ci	/*  Initialization of a working array wt */
501b815c7f3Sopenharmony_ci
502b815c7f3Sopenharmony_ci	for (k = 0 ; k < 40 ; k++)		wt_float [k] = SASR_W (din [k], scal) ;
503b815c7f3Sopenharmony_ci	for (k = -120 ; k < 0 ; k++)	dp_float [k] = dp [k] ;
504b815c7f3Sopenharmony_ci
505b815c7f3Sopenharmony_ci	/* Search for the maximum cross-correlation and coding of the LTP lag
506b815c7f3Sopenharmony_ci	 */
507b815c7f3Sopenharmony_ci	L_max = 0 ;
508b815c7f3Sopenharmony_ci	Nc = 40 ;	/* index for the maximum cross-correlation */
509b815c7f3Sopenharmony_ci
510b815c7f3Sopenharmony_ci	for (lambda = 40 ; lambda <= 120 ; lambda += 9)
511b815c7f3Sopenharmony_ci	{	/*  Calculate L_result for l = lambda .. lambda + 9. */
512b815c7f3Sopenharmony_ci		register float *lp = dp_float - lambda ;
513b815c7f3Sopenharmony_ci
514b815c7f3Sopenharmony_ci		register float W ;
515b815c7f3Sopenharmony_ci		register float a = lp [-8], b = lp [-7], c = lp [-6],
516b815c7f3Sopenharmony_ci						d = lp [-5], e = lp [-4], f = lp [-3],
517b815c7f3Sopenharmony_ci						g = lp [-2], h = lp [-1] ;
518b815c7f3Sopenharmony_ci		register float E ;
519b815c7f3Sopenharmony_ci		register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0,
520b815c7f3Sopenharmony_ci						S5 = 0, S6 = 0, S7 = 0, S8 = 0 ;
521b815c7f3Sopenharmony_ci
522b815c7f3Sopenharmony_ci#		undef STEP
523b815c7f3Sopenharmony_ci#		define	STEP(K, a, b, c, d, e, f, g, h) \
524b815c7f3Sopenharmony_ci			W = wt_float [K] ;		\
525b815c7f3Sopenharmony_ci			E = W * a ; S8 += E ;		\
526b815c7f3Sopenharmony_ci			E = W * b ; S7 += E ;		\
527b815c7f3Sopenharmony_ci			E = W * c ; S6 += E ;		\
528b815c7f3Sopenharmony_ci			E = W * d ; S5 += E ;		\
529b815c7f3Sopenharmony_ci			E = W * e ; S4 += E ;		\
530b815c7f3Sopenharmony_ci			E = W * f ; S3 += E ;		\
531b815c7f3Sopenharmony_ci			E = W * g ; S2 += E ;		\
532b815c7f3Sopenharmony_ci			E = W * h ; S1 += E ;		\
533b815c7f3Sopenharmony_ci			a = lp [K] ;				\
534b815c7f3Sopenharmony_ci			E = W * a ; S0 += E
535b815c7f3Sopenharmony_ci
536b815c7f3Sopenharmony_ci#		define	STEP_A(K)	STEP (K, a, b, c, d, e, f, g, h)
537b815c7f3Sopenharmony_ci#		define	STEP_B(K)	STEP (K, b, c, d, e, f, g, h, a)
538b815c7f3Sopenharmony_ci#		define	STEP_C(K)	STEP (K, c, d, e, f, g, h, a, b)
539b815c7f3Sopenharmony_ci#		define	STEP_D(K)	STEP (K, d, e, f, g, h, a, b, c)
540b815c7f3Sopenharmony_ci#		define	STEP_E(K)	STEP (K, e, f, g, h, a, b, c, d)
541b815c7f3Sopenharmony_ci#		define	STEP_F(K)	STEP (K, f, g, h, a, b, c, d, e)
542b815c7f3Sopenharmony_ci#		define	STEP_G(K)	STEP (K, g, h, a, b, c, d, e, f)
543b815c7f3Sopenharmony_ci#		define	STEP_H(K)	STEP (K, h, a, b, c, d, e, f, g)
544b815c7f3Sopenharmony_ci
545b815c7f3Sopenharmony_ci		STEP_A (0) ; STEP_B (1) ; STEP_C (2) ; STEP_D (3) ;
546b815c7f3Sopenharmony_ci		STEP_E (4) ; STEP_F (5) ; STEP_G (6) ; STEP_H (7) ;
547b815c7f3Sopenharmony_ci
548b815c7f3Sopenharmony_ci		STEP_A (8) ; STEP_B (9) ; STEP_C (10) ; STEP_D (11) ;
549b815c7f3Sopenharmony_ci		STEP_E (12) ; STEP_F (13) ; STEP_G (14) ; STEP_H (15) ;
550b815c7f3Sopenharmony_ci
551b815c7f3Sopenharmony_ci		STEP_A (16) ; STEP_B (17) ; STEP_C (18) ; STEP_D (19) ;
552b815c7f3Sopenharmony_ci		STEP_E (20) ; STEP_F (21) ; STEP_G (22) ; STEP_H (23) ;
553b815c7f3Sopenharmony_ci
554b815c7f3Sopenharmony_ci		STEP_A (24) ; STEP_B (25) ; STEP_C (26) ; STEP_D (27) ;
555b815c7f3Sopenharmony_ci		STEP_E (28) ; STEP_F (29) ; STEP_G (30) ; STEP_H (31) ;
556b815c7f3Sopenharmony_ci
557b815c7f3Sopenharmony_ci		STEP_A (32) ; STEP_B (33) ; STEP_C (34) ; STEP_D (35) ;
558b815c7f3Sopenharmony_ci		STEP_E (36) ; STEP_F (37) ; STEP_G (38) ; STEP_H (39) ;
559b815c7f3Sopenharmony_ci
560b815c7f3Sopenharmony_ci#		undef STEP_A
561b815c7f3Sopenharmony_ci#		undef STEP_B
562b815c7f3Sopenharmony_ci#		undef STEP_C
563b815c7f3Sopenharmony_ci#		undef STEP_D
564b815c7f3Sopenharmony_ci#		undef STEP_E
565b815c7f3Sopenharmony_ci#		undef STEP_F
566b815c7f3Sopenharmony_ci#		undef STEP_G
567b815c7f3Sopenharmony_ci#		undef STEP_H
568b815c7f3Sopenharmony_ci
569b815c7f3Sopenharmony_ci		if (S0 > L_max) { L_max = S0 ; Nc = lambda ; }
570b815c7f3Sopenharmony_ci		if (S1 > L_max) { L_max = S1 ; Nc = lambda + 1 ; }
571b815c7f3Sopenharmony_ci		if (S2 > L_max) { L_max = S2 ; Nc = lambda + 2 ; }
572b815c7f3Sopenharmony_ci		if (S3 > L_max) { L_max = S3 ; Nc = lambda + 3 ; }
573b815c7f3Sopenharmony_ci		if (S4 > L_max) { L_max = S4 ; Nc = lambda + 4 ; }
574b815c7f3Sopenharmony_ci		if (S5 > L_max) { L_max = S5 ; Nc = lambda + 5 ; }
575b815c7f3Sopenharmony_ci		if (S6 > L_max) { L_max = S6 ; Nc = lambda + 6 ; }
576b815c7f3Sopenharmony_ci		if (S7 > L_max) { L_max = S7 ; Nc = lambda + 7 ; }
577b815c7f3Sopenharmony_ci		if (S8 > L_max) { L_max = S8 ; Nc = lambda + 8 ; }
578b815c7f3Sopenharmony_ci	}
579b815c7f3Sopenharmony_ci	*Nc_out = Nc ;
580b815c7f3Sopenharmony_ci
581b815c7f3Sopenharmony_ci	L_max <<= 1 ;
582b815c7f3Sopenharmony_ci
583b815c7f3Sopenharmony_ci	/*  Rescaling of L_max
584b815c7f3Sopenharmony_ci	 */
585b815c7f3Sopenharmony_ci	assert (scal <= 100 && scal >= -100) ;
586b815c7f3Sopenharmony_ci	L_max = L_max >> (6 - scal) ;	/* sub (6, scal) */
587b815c7f3Sopenharmony_ci
588b815c7f3Sopenharmony_ci	assert (Nc <= 120 && Nc >= 40) ;
589b815c7f3Sopenharmony_ci
590b815c7f3Sopenharmony_ci	/*   Compute the power of the reconstructed short term residual
591b815c7f3Sopenharmony_ci	 *   signal dp [..]
592b815c7f3Sopenharmony_ci	 */
593b815c7f3Sopenharmony_ci	L_power = 0 ;
594b815c7f3Sopenharmony_ci	for (k = 0 ; k <= 39 ; k++)
595b815c7f3Sopenharmony_ci	{	register int32_t L_temp ;
596b815c7f3Sopenharmony_ci
597b815c7f3Sopenharmony_ci		L_temp = SASR_W (dp [k - Nc], 3) ;
598b815c7f3Sopenharmony_ci		L_power += L_temp * L_temp ;
599b815c7f3Sopenharmony_ci		}
600b815c7f3Sopenharmony_ci	L_power <<= 1 ;	/* from L_MULT */
601b815c7f3Sopenharmony_ci
602b815c7f3Sopenharmony_ci	/*  Normalization of L_max and L_power
603b815c7f3Sopenharmony_ci	 */
604b815c7f3Sopenharmony_ci
605b815c7f3Sopenharmony_ci	if (L_max <= 0)
606b815c7f3Sopenharmony_ci	{	*bc_out = 0 ;
607b815c7f3Sopenharmony_ci		return ;
608b815c7f3Sopenharmony_ci		}
609b815c7f3Sopenharmony_ci	if (L_max >= L_power)
610b815c7f3Sopenharmony_ci	{	*bc_out = 3 ;
611b815c7f3Sopenharmony_ci		return ;
612b815c7f3Sopenharmony_ci		}
613b815c7f3Sopenharmony_ci
614b815c7f3Sopenharmony_ci	temp = gsm_norm (L_power) ;
615b815c7f3Sopenharmony_ci
616b815c7f3Sopenharmony_ci	R = SASR_L (L_max << temp, 16) ;
617b815c7f3Sopenharmony_ci	S = SASR_L (L_power << temp, 16) ;
618b815c7f3Sopenharmony_ci
619b815c7f3Sopenharmony_ci	/*  Coding of the LTP gain
620b815c7f3Sopenharmony_ci	 */
621b815c7f3Sopenharmony_ci
622b815c7f3Sopenharmony_ci	/*  Table 4.3a must be used to obtain the level DLB [i] for the
623b815c7f3Sopenharmony_ci	 *  quantization of the LTP gain b to get the coded version bc.
624b815c7f3Sopenharmony_ci	 */
625b815c7f3Sopenharmony_ci	for (bc = 0 ; bc <= 2 ; bc++) if (R <= gsm_mult (S, gsm_DLB [bc])) break ;
626b815c7f3Sopenharmony_ci	*bc_out = bc ;
627b815c7f3Sopenharmony_ci}
628b815c7f3Sopenharmony_ci
629b815c7f3Sopenharmony_ci#ifdef	FAST
630b815c7f3Sopenharmony_ci#ifdef	LTP_CUT
631b815c7f3Sopenharmony_ci
632b815c7f3Sopenharmony_cistatic void Cut_Fast_Calculation_of_the_LTP_parameters (
633b815c7f3Sopenharmony_ci	struct gsm_state * st,		/*              IN	*/
634b815c7f3Sopenharmony_ci	register int16_t	* d,		/* [0..39]	IN	*/
635b815c7f3Sopenharmony_ci	register int16_t	* dp,		/* [-120..-1]	IN	*/
636b815c7f3Sopenharmony_ci	int16_t		* bc_out,	/* 		OUT	*/
637b815c7f3Sopenharmony_ci	int16_t		* Nc_out	/* 		OUT	*/)
638b815c7f3Sopenharmony_ci{
639b815c7f3Sopenharmony_ci	register int	k, lambda ;
640b815c7f3Sopenharmony_ci	register float	wt_float ;
641b815c7f3Sopenharmony_ci	int16_t	Nc, bc ;
642b815c7f3Sopenharmony_ci	int16_t	wt_max, best_k, ltp_cut ;
643b815c7f3Sopenharmony_ci
644b815c7f3Sopenharmony_ci	float		dp_float_base [120], * dp_float = dp_float_base + 120 ;
645b815c7f3Sopenharmony_ci
646b815c7f3Sopenharmony_ci	register float	L_result, L_max, L_power ;
647b815c7f3Sopenharmony_ci
648b815c7f3Sopenharmony_ci	wt_max = 0 ;
649b815c7f3Sopenharmony_ci
650b815c7f3Sopenharmony_ci	for (k = 0 ; k < 40 ; ++k)
651b815c7f3Sopenharmony_ci	{	if (d [k] > wt_max) wt_max = d [best_k = k] ;
652b815c7f3Sopenharmony_ci		else if (-d [k] > wt_max) wt_max = -d [best_k = k] ;
653b815c7f3Sopenharmony_ci		}
654b815c7f3Sopenharmony_ci
655b815c7f3Sopenharmony_ci	assert (wt_max >= 0) ;
656b815c7f3Sopenharmony_ci	wt_float = (float) wt_max ;
657b815c7f3Sopenharmony_ci
658b815c7f3Sopenharmony_ci	for (k = -120 ; k < 0 ; ++k) dp_float [k] = (float) dp [k] ;
659b815c7f3Sopenharmony_ci
660b815c7f3Sopenharmony_ci	/* Search for the maximum cross-correlation and coding of the LTP lag */
661b815c7f3Sopenharmony_ci	L_max = 0 ;
662b815c7f3Sopenharmony_ci	Nc = 40 ;	/* index for the maximum cross-correlation */
663b815c7f3Sopenharmony_ci
664b815c7f3Sopenharmony_ci	for (lambda = 40 ; lambda <= 120 ; lambda++)
665b815c7f3Sopenharmony_ci	{	L_result = wt_float * dp_float [best_k - lambda] ;
666b815c7f3Sopenharmony_ci		if (L_result > L_max)
667b815c7f3Sopenharmony_ci		{	Nc = lambda ;
668b815c7f3Sopenharmony_ci			L_max = L_result ;
669b815c7f3Sopenharmony_ci			}
670b815c7f3Sopenharmony_ci		}
671b815c7f3Sopenharmony_ci
672b815c7f3Sopenharmony_ci	*Nc_out = Nc ;
673b815c7f3Sopenharmony_ci	if (L_max <= 0.)
674b815c7f3Sopenharmony_ci	{	*bc_out = 0 ;
675b815c7f3Sopenharmony_ci		return ;
676b815c7f3Sopenharmony_ci		}
677b815c7f3Sopenharmony_ci
678b815c7f3Sopenharmony_ci	/*  Compute the power of the reconstructed short term residual
679b815c7f3Sopenharmony_ci	 *  signal dp [..]
680b815c7f3Sopenharmony_ci	 */
681b815c7f3Sopenharmony_ci	dp_float -= Nc ;
682b815c7f3Sopenharmony_ci	L_power = 0 ;
683b815c7f3Sopenharmony_ci	for (k = 0 ; k < 40 ; ++k)
684b815c7f3Sopenharmony_ci	{	register float f = dp_float [k] ;
685b815c7f3Sopenharmony_ci		L_power += f * f ;
686b815c7f3Sopenharmony_ci		}
687b815c7f3Sopenharmony_ci
688b815c7f3Sopenharmony_ci	if (L_max >= L_power)
689b815c7f3Sopenharmony_ci	{	*bc_out = 3 ;
690b815c7f3Sopenharmony_ci		return ;
691b815c7f3Sopenharmony_ci		}
692b815c7f3Sopenharmony_ci
693b815c7f3Sopenharmony_ci	/*  Coding of the LTP gain
694b815c7f3Sopenharmony_ci	 *  Table 4.3a must be used to obtain the level DLB [i] for the
695b815c7f3Sopenharmony_ci	 *  quantization of the LTP gain b to get the coded version bc.
696b815c7f3Sopenharmony_ci	 */
697b815c7f3Sopenharmony_ci	lambda = L_max / L_power * 32768.0 ;
698b815c7f3Sopenharmony_ci	for (bc = 0 ; bc <= 2 ; ++bc) if (lambda <= gsm_DLB [bc]) break ;
699b815c7f3Sopenharmony_ci	*bc_out = bc ;
700b815c7f3Sopenharmony_ci}
701b815c7f3Sopenharmony_ci
702b815c7f3Sopenharmony_ci#endif /* LTP_CUT */
703b815c7f3Sopenharmony_ci
704b815c7f3Sopenharmony_cistatic void Fast_Calculation_of_the_LTP_parameters (
705b815c7f3Sopenharmony_ci	register int16_t	* din,		/* [0..39]	IN	*/
706b815c7f3Sopenharmony_ci	register int16_t	* dp,		/* [-120..-1]	IN	*/
707b815c7f3Sopenharmony_ci	int16_t		* bc_out,	/* 		OUT	*/
708b815c7f3Sopenharmony_ci	int16_t		* Nc_out	/* 		OUT	*/)
709b815c7f3Sopenharmony_ci{
710b815c7f3Sopenharmony_ci	register int	k, lambda ;
711b815c7f3Sopenharmony_ci	int16_t			Nc, bc ;
712b815c7f3Sopenharmony_ci
713b815c7f3Sopenharmony_ci	float		wt_float [40] ;
714b815c7f3Sopenharmony_ci	float		dp_float_base [120], * dp_float = dp_float_base + 120 ;
715b815c7f3Sopenharmony_ci
716b815c7f3Sopenharmony_ci	register float	L_max, L_power ;
717b815c7f3Sopenharmony_ci
718b815c7f3Sopenharmony_ci	for (k = 0 ; k < 40 ; ++k) wt_float [k] = (float) din [k] ;
719b815c7f3Sopenharmony_ci	for (k = -120 ; k < 0 ; ++k) dp_float [k] = (float) dp [k] ;
720b815c7f3Sopenharmony_ci
721b815c7f3Sopenharmony_ci	/* Search for the maximum cross-correlation and coding of the LTP lag */
722b815c7f3Sopenharmony_ci	L_max = 0 ;
723b815c7f3Sopenharmony_ci	Nc = 40 ;	/* index for the maximum cross-correlation */
724b815c7f3Sopenharmony_ci
725b815c7f3Sopenharmony_ci	for (lambda = 40 ; lambda <= 120 ; lambda += 9)
726b815c7f3Sopenharmony_ci	{	/*  Calculate L_result for l = lambda .. lambda + 9. */
727b815c7f3Sopenharmony_ci		register float *lp = dp_float - lambda ;
728b815c7f3Sopenharmony_ci
729b815c7f3Sopenharmony_ci		register float W ;
730b815c7f3Sopenharmony_ci		register float a = lp [-8], b = lp [-7], c = lp [-6],
731b815c7f3Sopenharmony_ci						d = lp [-5], e = lp [-4], f = lp [-3],
732b815c7f3Sopenharmony_ci						g = lp [-2], h = lp [-1] ;
733b815c7f3Sopenharmony_ci		register float E ;
734b815c7f3Sopenharmony_ci		register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0,
735b815c7f3Sopenharmony_ci						S5 = 0, S6 = 0, S7 = 0, S8 = 0 ;
736b815c7f3Sopenharmony_ci
737b815c7f3Sopenharmony_ci#		undef STEP
738b815c7f3Sopenharmony_ci#		define	STEP(K, a, b, c, d, e, f, g, h) \
739b815c7f3Sopenharmony_ci			W = wt_float [K] ;		\
740b815c7f3Sopenharmony_ci			E = W * a ; S8 += E ;		\
741b815c7f3Sopenharmony_ci			E = W * b ; S7 += E ;		\
742b815c7f3Sopenharmony_ci			E = W * c ; S6 += E ;		\
743b815c7f3Sopenharmony_ci			E = W * d ; S5 += E ;		\
744b815c7f3Sopenharmony_ci			E = W * e ; S4 += E ;		\
745b815c7f3Sopenharmony_ci			E = W * f ; S3 += E ;		\
746b815c7f3Sopenharmony_ci			E = W * g ; S2 += E ;		\
747b815c7f3Sopenharmony_ci			E = W * h ; S1 += E ;		\
748b815c7f3Sopenharmony_ci			a = lp [K] ;				\
749b815c7f3Sopenharmony_ci			E = W * a ; S0 += E
750b815c7f3Sopenharmony_ci
751b815c7f3Sopenharmony_ci#		define	STEP_A(K)	STEP (K, a, b, c, d, e, f, g, h)
752b815c7f3Sopenharmony_ci#		define	STEP_B(K)	STEP (K, b, c, d, e, f, g, h, a)
753b815c7f3Sopenharmony_ci#		define	STEP_C(K)	STEP (K, c, d, e, f, g, h, a, b)
754b815c7f3Sopenharmony_ci#		define	STEP_D(K)	STEP (K, d, e, f, g, h, a, b, c)
755b815c7f3Sopenharmony_ci#		define	STEP_E(K)	STEP (K, e, f, g, h, a, b, c, d)
756b815c7f3Sopenharmony_ci#		define	STEP_F(K)	STEP (K, f, g, h, a, b, c, d, e)
757b815c7f3Sopenharmony_ci#		define	STEP_G(K)	STEP (K, g, h, a, b, c, d, e, f)
758b815c7f3Sopenharmony_ci#		define	STEP_H(K)	STEP (K, h, a, b, c, d, e, f, g)
759b815c7f3Sopenharmony_ci
760b815c7f3Sopenharmony_ci		STEP_A (0) ; STEP_B (1) ; STEP_C (2) ; STEP_D (3) ;
761b815c7f3Sopenharmony_ci		STEP_E (4) ; STEP_F (5) ; STEP_G (6) ; STEP_H (7) ;
762b815c7f3Sopenharmony_ci
763b815c7f3Sopenharmony_ci		STEP_A (8) ; STEP_B (9) ; STEP_C (10) ; STEP_D (11) ;
764b815c7f3Sopenharmony_ci		STEP_E (12) ; STEP_F (13) ; STEP_G (14) ; STEP_H (15) ;
765b815c7f3Sopenharmony_ci
766b815c7f3Sopenharmony_ci		STEP_A (16) ; STEP_B (17) ; STEP_C (18) ; STEP_D (19) ;
767b815c7f3Sopenharmony_ci		STEP_E (20) ; STEP_F (21) ; STEP_G (22) ; STEP_H (23) ;
768b815c7f3Sopenharmony_ci
769b815c7f3Sopenharmony_ci		STEP_A (24) ; STEP_B (25) ; STEP_C (26) ; STEP_D (27) ;
770b815c7f3Sopenharmony_ci		STEP_E (28) ; STEP_F (29) ; STEP_G (30) ; STEP_H (31) ;
771b815c7f3Sopenharmony_ci
772b815c7f3Sopenharmony_ci		STEP_A (32) ; STEP_B (33) ; STEP_C (34) ; STEP_D (35) ;
773b815c7f3Sopenharmony_ci		STEP_E (36) ; STEP_F (37) ; STEP_G (38) ; STEP_H (39) ;
774b815c7f3Sopenharmony_ci
775b815c7f3Sopenharmony_ci		if (S0 > L_max) { L_max = S0 ; Nc = lambda ; }
776b815c7f3Sopenharmony_ci		if (S1 > L_max) { L_max = S1 ; Nc = lambda + 1 ; }
777b815c7f3Sopenharmony_ci		if (S2 > L_max) { L_max = S2 ; Nc = lambda + 2 ; }
778b815c7f3Sopenharmony_ci		if (S3 > L_max) { L_max = S3 ; Nc = lambda + 3 ; }
779b815c7f3Sopenharmony_ci		if (S4 > L_max) { L_max = S4 ; Nc = lambda + 4 ; }
780b815c7f3Sopenharmony_ci		if (S5 > L_max) { L_max = S5 ; Nc = lambda + 5 ; }
781b815c7f3Sopenharmony_ci		if (S6 > L_max) { L_max = S6 ; Nc = lambda + 6 ; }
782b815c7f3Sopenharmony_ci		if (S7 > L_max) { L_max = S7 ; Nc = lambda + 7 ; }
783b815c7f3Sopenharmony_ci		if (S8 > L_max) { L_max = S8 ; Nc = lambda + 8 ; }
784b815c7f3Sopenharmony_ci	}
785b815c7f3Sopenharmony_ci	*Nc_out = Nc ;
786b815c7f3Sopenharmony_ci
787b815c7f3Sopenharmony_ci	if (L_max <= 0.0)
788b815c7f3Sopenharmony_ci	{	*bc_out = 0 ;
789b815c7f3Sopenharmony_ci		return ;
790b815c7f3Sopenharmony_ci		}
791b815c7f3Sopenharmony_ci
792b815c7f3Sopenharmony_ci	/*  Compute the power of the reconstructed short term residual
793b815c7f3Sopenharmony_ci	 *  signal dp [..]
794b815c7f3Sopenharmony_ci	 */
795b815c7f3Sopenharmony_ci	dp_float -= Nc ;
796b815c7f3Sopenharmony_ci	L_power = 0 ;
797b815c7f3Sopenharmony_ci	for (k = 0 ; k < 40 ; ++k)
798b815c7f3Sopenharmony_ci	{	register float f = dp_float [k] ;
799b815c7f3Sopenharmony_ci		L_power += f * f ;
800b815c7f3Sopenharmony_ci		}
801b815c7f3Sopenharmony_ci
802b815c7f3Sopenharmony_ci	if (L_max >= L_power)
803b815c7f3Sopenharmony_ci	{	*bc_out = 3 ;
804b815c7f3Sopenharmony_ci		return ;
805b815c7f3Sopenharmony_ci		}
806b815c7f3Sopenharmony_ci
807b815c7f3Sopenharmony_ci	/*  Coding of the LTP gain
808b815c7f3Sopenharmony_ci	 *  Table 4.3a must be used to obtain the level DLB [i] for the
809b815c7f3Sopenharmony_ci	 *  quantization of the LTP gain b to get the coded version bc.
810b815c7f3Sopenharmony_ci	 */
811b815c7f3Sopenharmony_ci	lambda = L_max / L_power * 32768.0 ;
812b815c7f3Sopenharmony_ci	for (bc = 0 ; bc <= 2 ; ++bc) if (lambda <= gsm_DLB [bc]) break ;
813b815c7f3Sopenharmony_ci	*bc_out = bc ;
814b815c7f3Sopenharmony_ci}
815b815c7f3Sopenharmony_ci
816b815c7f3Sopenharmony_ci#endif	/* FAST 	 */
817b815c7f3Sopenharmony_ci#endif	/* USE_FLOAT_MUL */
818b815c7f3Sopenharmony_ci
819b815c7f3Sopenharmony_ci
820b815c7f3Sopenharmony_ci/* 4.2.12 */
821b815c7f3Sopenharmony_ci
822b815c7f3Sopenharmony_cistatic void Long_term_analysis_filtering (
823b815c7f3Sopenharmony_ci	int16_t		bc,	/* 					IN  */
824b815c7f3Sopenharmony_ci	int16_t		Nc,	/* 					IN  */
825b815c7f3Sopenharmony_ci	register int16_t	* dp,	/* previous d	[-120..-1]		IN  */
826b815c7f3Sopenharmony_ci	register int16_t	* d,	/* d		[0..39]			IN  */
827b815c7f3Sopenharmony_ci	register int16_t	* dpp,	/* estimate	[0..39]			OUT */
828b815c7f3Sopenharmony_ci	register int16_t	* e	/* long term res. signal [0..39]	OUT */)
829b815c7f3Sopenharmony_ci/*
830b815c7f3Sopenharmony_ci *  In this part, we have to decode the bc parameter to compute
831b815c7f3Sopenharmony_ci *  the samples of the estimate dpp [0..39].  The decoding of bc needs the
832b815c7f3Sopenharmony_ci *  use of table 4.3b.  The long term residual signal e [0..39]
833b815c7f3Sopenharmony_ci *  is then calculated to be fed to the RPE encoding section.
834b815c7f3Sopenharmony_ci */
835b815c7f3Sopenharmony_ci{
836b815c7f3Sopenharmony_ci	register int k ;
837b815c7f3Sopenharmony_ci
838b815c7f3Sopenharmony_ci#	undef STEP
839b815c7f3Sopenharmony_ci#	define STEP(BP)					\
840b815c7f3Sopenharmony_ci	for (k = 0 ; k <= 39 ; k++)		\
841b815c7f3Sopenharmony_ci	{	dpp [k] = GSM_MULT_R (BP, dp [k - Nc]) ;	\
842b815c7f3Sopenharmony_ci		e [k]	= GSM_SUB (d [k], dpp [k]) ;	\
843b815c7f3Sopenharmony_ci		}
844b815c7f3Sopenharmony_ci
845b815c7f3Sopenharmony_ci	switch (bc)
846b815c7f3Sopenharmony_ci	{	case 0:	STEP (3277) ; break ;
847b815c7f3Sopenharmony_ci		case 1:	STEP (11469) ; break ;
848b815c7f3Sopenharmony_ci		case 2: STEP (21299) ; break ;
849b815c7f3Sopenharmony_ci		case 3: STEP (32767) ; break ;
850b815c7f3Sopenharmony_ci		}
851b815c7f3Sopenharmony_ci}
852b815c7f3Sopenharmony_ci
853b815c7f3Sopenharmony_civoid Gsm_Long_Term_Predictor (	/* 4x for 160 samples */
854b815c7f3Sopenharmony_ci
855b815c7f3Sopenharmony_ci	struct gsm_state	* S,
856b815c7f3Sopenharmony_ci
857b815c7f3Sopenharmony_ci	int16_t	* d,	/* [0..39]   residual signal	IN	*/
858b815c7f3Sopenharmony_ci	int16_t	* dp,	/* [-120..-1] d'		IN	*/
859b815c7f3Sopenharmony_ci
860b815c7f3Sopenharmony_ci	int16_t	* e,	/* [0..39] 			OUT	*/
861b815c7f3Sopenharmony_ci	int16_t	* dpp,	/* [0..39] 			OUT	*/
862b815c7f3Sopenharmony_ci	int16_t	* Nc,	/* correlation lag		OUT	*/
863b815c7f3Sopenharmony_ci	int16_t	* bc	/* gain factor			OUT	*/)
864b815c7f3Sopenharmony_ci{
865b815c7f3Sopenharmony_ci	assert (d) ; assert (dp) ; assert (e) ;
866b815c7f3Sopenharmony_ci	assert (dpp) ; assert (Nc) ; assert (bc) ;
867b815c7f3Sopenharmony_ci
868b815c7f3Sopenharmony_ci#if defined (FAST) && defined (USE_FLOAT_MUL)
869b815c7f3Sopenharmony_ci	if (S->fast)
870b815c7f3Sopenharmony_ci#if defined (LTP_CUT)
871b815c7f3Sopenharmony_ci		if (S->ltp_cut)
872b815c7f3Sopenharmony_ci			Cut_Fast_Calculation_of_the_LTP_parameters (S,
873b815c7f3Sopenharmony_ci				d, dp, bc, Nc) ;
874b815c7f3Sopenharmony_ci		else
875b815c7f3Sopenharmony_ci#endif /* LTP_CUT */
876b815c7f3Sopenharmony_ci			Fast_Calculation_of_the_LTP_parameters (d, dp, bc, Nc) ;
877b815c7f3Sopenharmony_ci	else
878b815c7f3Sopenharmony_ci#endif /* FAST & USE_FLOAT_MUL */
879b815c7f3Sopenharmony_ci#ifdef LTP_CUT
880b815c7f3Sopenharmony_ci		if (S->ltp_cut)
881b815c7f3Sopenharmony_ci			Cut_Calculation_of_the_LTP_parameters (S, d, dp, bc, Nc) ;
882b815c7f3Sopenharmony_ci		else
883b815c7f3Sopenharmony_ci#endif
884b815c7f3Sopenharmony_ci			Calculation_of_the_LTP_parameters (d, dp, bc, Nc) ;
885b815c7f3Sopenharmony_ci
886b815c7f3Sopenharmony_ci	Long_term_analysis_filtering (*bc, *Nc, dp, d, dpp, e) ;
887b815c7f3Sopenharmony_ci}
888b815c7f3Sopenharmony_ci
889b815c7f3Sopenharmony_ci/* 4.3.2 */
890b815c7f3Sopenharmony_civoid Gsm_Long_Term_Synthesis_Filtering (
891b815c7f3Sopenharmony_ci	struct gsm_state	* S,
892b815c7f3Sopenharmony_ci
893b815c7f3Sopenharmony_ci	int16_t			Ncr,
894b815c7f3Sopenharmony_ci	int16_t			bcr,
895b815c7f3Sopenharmony_ci	register int16_t	* erp,	/* [0..39]		  	 IN */
896b815c7f3Sopenharmony_ci	register int16_t	* drp	/* [-120..-1] IN, [-120..40] OUT */)
897b815c7f3Sopenharmony_ci/*
898b815c7f3Sopenharmony_ci *  This procedure uses the bcr and Ncr parameter to realize the
899b815c7f3Sopenharmony_ci *  long term synthesis filtering.  The decoding of bcr needs
900b815c7f3Sopenharmony_ci *  table 4.3b.
901b815c7f3Sopenharmony_ci */
902b815c7f3Sopenharmony_ci{
903b815c7f3Sopenharmony_ci	register int 		k ;
904b815c7f3Sopenharmony_ci	int16_t			brp, drpp, Nr ;
905b815c7f3Sopenharmony_ci
906b815c7f3Sopenharmony_ci	/*  Check the limits of Nr.
907b815c7f3Sopenharmony_ci	 */
908b815c7f3Sopenharmony_ci	Nr = Ncr < 40 || Ncr > 120 ? S->nrp : Ncr ;
909b815c7f3Sopenharmony_ci	S->nrp = Nr ;
910b815c7f3Sopenharmony_ci	assert (Nr >= 40 && Nr <= 120) ;
911b815c7f3Sopenharmony_ci
912b815c7f3Sopenharmony_ci	/*  Decoding of the LTP gain bcr
913b815c7f3Sopenharmony_ci	 */
914b815c7f3Sopenharmony_ci	brp = gsm_QLB [bcr] ;
915b815c7f3Sopenharmony_ci
916b815c7f3Sopenharmony_ci	/*  Computation of the reconstructed short term residual
917b815c7f3Sopenharmony_ci	 *  signal drp [0..39]
918b815c7f3Sopenharmony_ci	 */
919b815c7f3Sopenharmony_ci	assert (brp != MIN_WORD) ;
920b815c7f3Sopenharmony_ci
921b815c7f3Sopenharmony_ci	for (k = 0 ; k <= 39 ; k++)
922b815c7f3Sopenharmony_ci	{	drpp = GSM_MULT_R (brp, drp [k - Nr]) ;
923b815c7f3Sopenharmony_ci		drp [k] = GSM_ADD (erp [k], drpp) ;
924b815c7f3Sopenharmony_ci		}
925b815c7f3Sopenharmony_ci
926b815c7f3Sopenharmony_ci	/*
927b815c7f3Sopenharmony_ci	 *  Update of the reconstructed short term residual signal
928b815c7f3Sopenharmony_ci	 *  drp [-1..-120]
929b815c7f3Sopenharmony_ci	 */
930b815c7f3Sopenharmony_ci
931b815c7f3Sopenharmony_ci	for (k = 0 ; k <= 119 ; k++) drp [-120 + k] = drp [-80 + k] ;
932b815c7f3Sopenharmony_ci}
933