1/*
2 * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
3 * Universitaet Berlin.  See the accompanying file "COPYRIGHT" for
4 * details.  THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
5 */
6
7/* $Header: /tmp_amd/presto/export/kbs/jutta/src/gsm/RCS/lpc.c,v 1.5 1994/12/30 23:14:54 jutta Exp $ */
8
9#include <stdio.h>
10#include <assert.h>
11
12#include "private.h"
13
14#include "gsm.h"
15#include "proto.h"
16
17#undef	P
18
19/*
20 *  4.2.4 .. 4.2.7 LPC ANALYSIS SECTION
21 */
22
23/* 4.2.4 */
24
25
26static void Autocorrelation P2((s, L_ACF),
27	word     * s,		/* [0..159]	IN/OUT  */
28 	longword * L_ACF)	/* [0..8]	OUT     */
29/*
30 *  The goal is to compute the array L_ACF[k].  The signal s[i] must
31 *  be scaled in order to avoid an overflow situation.
32 */
33{
34	register int	k, i;
35
36	word		temp, smax, scalauto;
37
38#ifdef	USE_FLOAT_MUL
39	float		float_s[160];
40#endif
41
42	/*  Dynamic scaling of the array  s[0..159]
43	 */
44
45	/*  Search for the maximum.
46	 */
47	smax = 0;
48	for (k = 0; k <= 159; k++) {
49		temp = GSM_ABS( s[k] );
50		if (temp > smax) smax = temp;
51	}
52
53	/*  Computation of the scaling factor.
54	 */
55	if (smax == 0) scalauto = 0;
56	else {
57		assert(smax > 0);
58		scalauto = 4 - gsm_norm( (longword)smax << 16 );/* sub(4,..) */
59	}
60
61	/*  Scaling of the array s[0...159]
62	 */
63
64	if (scalauto > 0) {
65
66# ifdef USE_FLOAT_MUL
67#   define SCALE(n)	\
68	case n: for (k = 0; k <= 159; k++) \
69			float_s[k] = (float)	\
70				(s[k] = GSM_MULT_R(s[k], 16384 >> (n-1)));\
71		break;
72# else
73#   define SCALE(n)	\
74	case n: for (k = 0; k <= 159; k++) \
75			s[k] = GSM_MULT_R( s[k], 16384 >> (n-1) );\
76		break;
77# endif /* USE_FLOAT_MUL */
78
79		switch (scalauto) {
80		SCALE(1)
81		SCALE(2)
82		SCALE(3)
83		SCALE(4)
84		}
85# undef	SCALE
86	}
87# ifdef	USE_FLOAT_MUL
88	else for (k = 0; k <= 159; k++) float_s[k] = (float) s[k];
89# endif
90
91	/*  Compute the L_ACF[..].
92	 */
93	{
94# ifdef	USE_FLOAT_MUL
95		register float * sp = float_s;
96		register float   sl = *sp;
97
98#		define STEP(k)	 L_ACF[k] += (longword)(sl * sp[ -(k) ]);
99# else
100		word  * sp = s;
101		word    sl = *sp;
102
103#		define STEP(k)	 L_ACF[k] += ((longword)sl * sp[ -(k) ]);
104# endif
105
106#	define NEXTI	 sl = *++sp
107
108
109	for (k = 9; k--; L_ACF[k] = 0) ;
110
111	STEP (0);
112	NEXTI;
113	STEP(0); STEP(1);
114	NEXTI;
115	STEP(0); STEP(1); STEP(2);
116	NEXTI;
117	STEP(0); STEP(1); STEP(2); STEP(3);
118	NEXTI;
119	STEP(0); STEP(1); STEP(2); STEP(3); STEP(4);
120	NEXTI;
121	STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5);
122	NEXTI;
123	STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6);
124	NEXTI;
125	STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); STEP(7);
126
127	for (i = 8; i <= 159; i++) {
128
129		NEXTI;
130
131		STEP(0);
132		STEP(1); STEP(2); STEP(3); STEP(4);
133		STEP(5); STEP(6); STEP(7); STEP(8);
134	}
135
136	for (k = 9; k--; L_ACF[k] <<= 1) ;
137
138	}
139	/*   Rescaling of the array s[0..159]
140	 */
141	if (scalauto > 0) {
142		assert(scalauto <= 4);
143		for (k = 160; k--; *s++ <<= scalauto) ;
144	}
145}
146
147#if defined(USE_FLOAT_MUL) && defined(FAST)
148
149static void Fast_Autocorrelation P2((s, L_ACF),
150	word * s,		/* [0..159]	IN/OUT  */
151 	longword * L_ACF)	/* [0..8]	OUT     */
152{
153	register int	k, i;
154	float f_L_ACF[9];
155	float scale;
156
157	float          s_f[160];
158	register float *sf = s_f;
159
160	for (i = 0; i < 160; ++i) sf[i] = s[i];
161	for (k = 0; k <= 8; k++) {
162		register float L_temp2 = 0;
163		register float *sfl = sf - k;
164		for (i = k; i < 160; ++i) L_temp2 += sf[i] * sfl[i];
165		f_L_ACF[k] = L_temp2;
166	}
167	scale = MAX_LONGWORD / f_L_ACF[0];
168
169	for (k = 0; k <= 8; k++) {
170		L_ACF[k] = f_L_ACF[k] * scale;
171	}
172}
173#endif	/* defined (USE_FLOAT_MUL) && defined (FAST) */
174
175/* 4.2.5 */
176
177static void Reflection_coefficients P2( (L_ACF, r),
178	longword	* L_ACF,		/* 0...8	IN	*/
179	register word	* r			/* 0...7	OUT 	*/
180)
181{
182	register int	i, m, n;
183	register word	temp;
184	register longword ltmp;
185	word		ACF[9];	/* 0..8 */
186	word		P[  9];	/* 0..8 */
187	word		K[  9]; /* 2..8 */
188
189	/*  Schur recursion with 16 bits arithmetic.
190	 */
191
192	if (L_ACF[0] == 0) {
193		for (i = 8; i--; *r++ = 0) ;
194		return;
195	}
196
197	assert( L_ACF[0] != 0 );
198	temp = gsm_norm( L_ACF[0] );
199
200	assert(temp >= 0 && temp < 32);
201
202	/* ? overflow ? */
203	for (i = 0; i <= 8; i++) ACF[i] = SASR( L_ACF[i] << temp, 16 );
204
205	/*   Initialize array P[..] and K[..] for the recursion.
206	 */
207
208	for (i = 1; i <= 7; i++) K[ i ] = ACF[ i ];
209	for (i = 0; i <= 8; i++) P[ i ] = ACF[ i ];
210
211	/*   Compute reflection coefficients
212	 */
213	for (n = 1; n <= 8; n++, r++) {
214
215		temp = P[1];
216		temp = GSM_ABS(temp);
217		if (P[0] < temp) {
218			for (i = n; i <= 8; i++) *r++ = 0;
219			return;
220		}
221
222		*r = gsm_div( temp, P[0] );
223
224		assert(*r >= 0);
225		if (P[1] > 0) *r = -*r;		/* r[n] = sub(0, r[n]) */
226		assert (*r != MIN_WORD);
227		if (n == 8) return;
228
229		/*  Schur recursion
230		 */
231		temp = GSM_MULT_R( P[1], *r );
232		P[0] = GSM_ADD( P[0], temp );
233
234		for (m = 1; m <= 8 - n; m++) {
235			temp     = GSM_MULT_R( K[ m   ],    *r );
236			P[m]     = GSM_ADD(    P[ m+1 ],  temp );
237
238			temp     = GSM_MULT_R( P[ m+1 ],    *r );
239			K[m]     = GSM_ADD(    K[ m   ],  temp );
240		}
241	}
242}
243
244/* 4.2.6 */
245
246static void Transformation_to_Log_Area_Ratios P1((r),
247	register word	* r 			/* 0..7	   IN/OUT */
248)
249/*
250 *  The following scaling for r[..] and LAR[..] has been used:
251 *
252 *  r[..]   = integer( real_r[..]*32768. ); -1 <= real_r < 1.
253 *  LAR[..] = integer( real_LAR[..] * 16384 );
254 *  with -1.625 <= real_LAR <= 1.625
255 */
256{
257	register word	temp;
258	register int	i;
259
260
261	/* Computation of the LAR[0..7] from the r[0..7]
262	 */
263	for (i = 1; i <= 8; i++, r++) {
264
265		temp = *r;
266		temp = GSM_ABS(temp);
267		assert(temp >= 0);
268
269		if (temp < 22118) {
270			temp >>= 1;
271		} else if (temp < 31130) {
272			assert( temp >= 11059 );
273			temp -= 11059;
274		} else {
275			assert( temp >= 26112 );
276			temp -= 26112;
277			temp <<= 2;
278		}
279
280		*r = *r < 0 ? -temp : temp;
281		assert( *r != MIN_WORD );
282	}
283}
284
285/* 4.2.7 */
286
287static void Quantization_and_coding P1((LAR),
288	register word * LAR    	/* [0..7]	IN/OUT	*/
289)
290{
291	register word	temp;
292	longword	ltmp;
293
294
295	/*  This procedure needs four tables; the following equations
296	 *  give the optimum scaling for the constants:
297	 *
298	 *  A[0..7] = integer( real_A[0..7] * 1024 )
299	 *  B[0..7] = integer( real_B[0..7] *  512 )
300	 *  MAC[0..7] = maximum of the LARc[0..7]
301	 *  MIC[0..7] = minimum of the LARc[0..7]
302	 */
303
304#	undef STEP
305#	define	STEP( A, B, MAC, MIC )		\
306		temp = GSM_MULT( A,   *LAR );	\
307		temp = GSM_ADD(  temp,   B );	\
308		temp = GSM_ADD(  temp, 256 );	\
309		temp = SASR(     temp,   9 );	\
310		*LAR  =  temp>MAC ? MAC - MIC : (temp<MIC ? 0 : temp - MIC); \
311		LAR++;
312
313	STEP(  20480,     0,  31, -32 );
314	STEP(  20480,     0,  31, -32 );
315	STEP(  20480,  2048,  15, -16 );
316	STEP(  20480, -2560,  15, -16 );
317
318	STEP(  13964,    94,   7,  -8 );
319	STEP(  15360, -1792,   7,  -8 );
320	STEP(   8534,  -341,   3,  -4 );
321	STEP(   9036, -1144,   3,  -4 );
322
323#	undef	STEP
324}
325
326void Gsm_LPC_Analysis P3((S, s,LARc),
327	struct gsm_state *S,
328	word 		 * s,		/* 0..159 signals	IN/OUT	*/
329        word 		 * LARc)	/* 0..7   LARc's	OUT	*/
330{
331	longword	L_ACF[9];
332
333#if defined(USE_FLOAT_MUL) && defined(FAST)
334	if (S->fast) Fast_Autocorrelation (s,	  L_ACF );
335	else
336#endif
337	Autocorrelation			  (s,	  L_ACF	);
338	Reflection_coefficients		  (L_ACF, LARc	);
339	Transformation_to_Log_Area_Ratios (LARc);
340	Quantization_and_coding		  (LARc);
341}
342