1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 /****************************************************************************************
19 Portions of this file are derived from the following 3GPP standard:
20
21 3GPP TS 26.073
22 ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
23 Available from http://www.3gpp.org
24
25 (C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
26 Permission to distribute, modify and use this file under the standard license
27 terms listed above has been obtained from the copyright holder.
28 ****************************************************************************************/
29 /*
30 ------------------------------------------------------------------------------
31
32
33
34 Pathname: ./audio/gsm-amr/c/src/autocorr.c
35
36 Date: 05/15/2000
37
38 ------------------------------------------------------------------------------
39 REVISION HISTORY
40
41 Description: Put into template...starting optimization.
42
43 Description: Removed call to mult_r routine.
44
45 Description: Modified Input/Output Definitions section to comply with the
46 current template. Fixed tabs.
47
48 Description: Updated Input/Output definitions by making them more
49 descriptive.
50
51 Description: Synchronized file with UMTS version 3.2.0. Updated coding
52 template.
53
54 Description: Made the following changes per comments from Phase 2/3 review:
55 1. Added full pathname of file.
56 2. Fixed typecasting issue with TI compiler.
57 3. Modified FOR loops to count down.
58 4. Added comment to the code.
59
60 Description: Removed extern to global paramter (Flag Overflow) and replaced
61 by passing in a pointer to Overflow. Also, made several small changes to
62 bring code more in line with PV Standards.
63
64 Description:
65 1. Added pointer to avoid adding offsets in every pass
66 2. Break last loop in two nested loop to speed up processing
67 3. Removed extra check for overflow by doing scaling right
68 after overflow is detected.
69 4. Eliminated calls to basic operations (like extract) not
70 needed because of the nature of the number (all bounded)
71
72 Description:
73 1. Fixed for:
74 overflow check was looking for positive number before a left
75 shift. When numbers were big enough, positive numbers after
76 shifted became negative, causing a 1/0 division).
77 Fixed so now it checks for numbers lesser than 0x40000000
78 before the left shift
79
80 Description:
81 1.Modified check for saturation to match bit exact test.
82 Also, when saturation is reached, a faster loop is used
83 (with no energy accumulation) to speed up processing
84
85
86 Description:
87 1.Added pointer initialization to for loop when saturation
88 is found. This because some compiler ( like Vcpp in release
89 mode) when optimizing code, may remove pointer information
90 once the loop is broken.
91
92 Description: Added casting to eliminate warnings
93
94 Description: Replaced "int" and/or "char" with OSCL defined types.
95
96 Description: Using inlines from fxp_arithmetic.h.
97
98 Description: Replacing fxp_arithmetic.h with basic_op.h.
99
100 Description:
101
102 ----------------------------------------------------------------------------*/
103
104 /*----------------------------------------------------------------------------
105 ; INCLUDES
106 ----------------------------------------------------------------------------*/
107 #include "autocorr.h"
108 #include "typedef.h"
109 #include "basic_op.h"
110 #include "oper_32b.h"
111 #include "cnst.h"
112
113 /*----------------------------------------------------------------------------
114 ; MACROS
115 ; Define module specific macros here
116 ----------------------------------------------------------------------------*/
117
118
119 /*----------------------------------------------------------------------------
120 ; DEFINES
121 ; Include all pre-processor statements here. Include conditional
122 ; compile variables also.
123 ----------------------------------------------------------------------------*/
124
125
126 /*----------------------------------------------------------------------------
127 ; LOCAL FUNCTION DEFINITIONS
128 ; Function Prototype declaration
129 ----------------------------------------------------------------------------*/
130
131 /*----------------------------------------------------------------------------
132 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
133 ; Variable declaration - defined here and used outside this module
134 ----------------------------------------------------------------------------*/
135
136 /*----------------------------------------------------------------------------
137 ; EXTERNAL FUNCTION REFERENCES
138 ; Declare functions defined elsewhere and referenced in this module
139 ----------------------------------------------------------------------------*/
140
141
142 /*----------------------------------------------------------------------------
143 ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
144 ; Declare variables used in this module but defined elsewhere
145 ----------------------------------------------------------------------------*/
146
147 /*
148 ------------------------------------------------------------------------------
149 FUNCTION NAME: Autocorr
150 ----------------------------------------------------------------------------
151 INPUT AND OUTPUT DEFINITIONS
152
153 Inputs:
154 x = buffer of input signals of type Word16
155 m = LPC order of type Word16
156 wind = buffer of window signals of type Word16
157 r_h = buffer containing the high word of the autocorrelation values
158 of type Word16
159 r_l = buffer containing the low word of the autocorrelation values
160 of type Word16
161
162 pOverflow = pointer to variable of type Flag *, which indicates if
163 overflow occurs.
164
165 Outputs:
166 r_h buffer contains the high word of the new autocorrelation values
167 r_l buffer contains the low word of the new autocorrelation values
168 pOverflow -> 1 if overflow occurs.
169
170 Returns:
171 norm = normalized autocorrelation at lag zero of type Word16
172
173 Global Variables Used:
174 None
175
176 Local Variables Needed:
177 None
178
179 ------------------------------------------------------------------------------
180 FUNCTION DESCRIPTION
181
182 This function windows the input signal with the provided window
183 then calculates the autocorrelation values for lags of 0,1,...m,
184 where m is the passed in LPC order.
185
186 ------------------------------------------------------------------------------
187 REQUIREMENTS
188
189 None.
190
191 ------------------------------------------------------------------------------
192 REFERENCES
193
194 autocorr.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
195
196 ------------------------------------------------------------------------------
197 PSEUDO-CODE
198
199 Word16 Autocorr (
200 Word16 x[], // (i) : Input signal (L_WINDOW)
201 Word16 m, // (i) : LPC order
202 Word16 r_h[], // (o) : Autocorrelations (msb)
203 Word16 r_l[], // (o) : Autocorrelations (lsb)
204 const Word16 wind[] // (i) : window for LPC analysis (L_WINDOW)
205 )
206 {
207 Word16 i, j, norm;
208 Word16 y[L_WINDOW];
209 Word32 sum;
210 Word16 overfl, overfl_shft;
211
212 // Windowing of signal
213
214 for (i = 0; i < L_WINDOW; i++)
215 {
216 y[i] = mult_r (x[i], wind[i]);
217 }
218
219 // Compute r[0] and test for overflow
220
221 overfl_shft = 0;
222
223 do
224 {
225 overfl = 0;
226 sum = 0L;
227
228 for (i = 0; i < L_WINDOW; i++)
229 {
230 sum = L_mac (sum, y[i], y[i]);
231 }
232
233 // If overflow divide y[] by 4
234
235 if (L_sub (sum, MAX_32) == 0L)
236 {
237 overfl_shft = add (overfl_shft, 4);
238 overfl = 1; // Set the overflow flag
239
240 for (i = 0; i < L_WINDOW; i++)
241 {
242 y[i] = shr (y[i], 2);
243 }
244 }
245 }
246 while (overfl != 0);
247
248 sum = L_add (sum, 1L); // Avoid the case of all zeros
249
250 // Normalization of r[0]
251
252 norm = norm_l (sum);
253 sum = L_shl (sum, norm);
254 L_Extract (sum, &r_h[0], &r_l[0]); // Put in DPF format (see oper_32b)
255
256 // r[1] to r[m]
257
258 for (i = 1; i <= m; i++)
259 {
260 sum = 0;
261
262 for (j = 0; j < L_WINDOW - i; j++)
263 {
264 sum = L_mac (sum, y[j], y[j + i]);
265 }
266
267 sum = L_shl (sum, norm);
268 L_Extract (sum, &r_h[i], &r_l[i]);
269 }
270
271 norm = sub (norm, overfl_shft);
272
273 return norm;
274 }
275
276
277 ------------------------------------------------------------------------------
278 RESOURCES USED [optional]
279
280 When the code is written for a specific target processor the
281 the resources used should be documented below.
282
283 HEAP MEMORY USED: x bytes
284
285 STACK MEMORY USED: x bytes
286
287 CLOCK CYCLES: (cycle count equation for this function) + (variable
288 used to represent cycle count for each subroutine
289 called)
290 where: (cycle count variable) = cycle count for [subroutine
291 name]
292
293 ------------------------------------------------------------------------------
294 CAUTION [optional]
295 [State any special notes, constraints or cautions for users of this function]
296
297 ------------------------------------------------------------------------------
298 */
299
Autocorr(Word16 x[],Word16 m,Word16 r_h[],Word16 r_l[],const Word16 wind[],Flag * pOverflow)300 Word16 Autocorr(
301 Word16 x[], /* (i) : Input signal (L_WINDOW) */
302 Word16 m, /* (i) : LPC order */
303 Word16 r_h[], /* (o) : Autocorrelations (msb) */
304 Word16 r_l[], /* (o) : Autocorrelations (lsb) */
305 const Word16 wind[], /* (i) : window for LPC analysis (L_WINDOW) */
306 Flag *pOverflow /* (o) : indicates overflow */
307 )
308 {
309 Word16 i;
310 Word16 j;
311 Word16 norm;
312
313 Word16 y[L_WINDOW];
314 Word32 sum;
315 Word16 overfl_shft;
316
317
318 /* Added for optimization */
319
320
321 Word16 temp;
322 Word16 *p_x;
323 Word16 *p_y;
324 Word16 *p_y_1;
325 Word16 *p_y_ref;
326 Word16 *p_rh;
327 Word16 *p_rl;
328 const Word16 *p_wind;
329 p_y = y;
330 p_x = x;
331 p_wind = wind;
332 /*
333 * Windowing of the signal
334 */
335
336 OSCL_UNUSED_ARG(pOverflow);
337
338 sum = 0L;
339 j = 0;
340
341 for (i = L_WINDOW; i != 0; i--)
342 {
343 temp = (amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_wind++), 0x04000)) >> 15;
344 *(p_y++) = temp;
345
346 sum += ((Word32)temp * temp) << 1;
347 if (sum < 0)
348 {
349 /*
350 * if oveflow exist, then stop accumulation
351 */
352 j = 1;
353 break;
354 }
355
356 }
357 /*
358 * if oveflow existed, complete windowing operation
359 * without computing energy
360 */
361
362 if (j)
363 {
364 p_y = &y[L_WINDOW-i];
365 p_x = &x[L_WINDOW-i];
366 p_wind = &wind[L_WINDOW-i];
367
368 for (; i != 0; i--)
369 {
370 temp = (amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_wind++), 0x04000)) >> 15;
371 *(p_y++) = temp;
372 }
373 }
374
375
376 /*
377 * Compute r[0] and test for overflow
378 */
379
380 overfl_shft = 0;
381
382 /*
383 * scale down by 1/4 only when needed
384 */
385 while (j == 1)
386 {
387 /* If overflow divide y[] by 4 */
388 /* FYI: For better resolution, we could */
389 /* divide y[] by 2 */
390 overfl_shft += 4;
391 p_y = &y[0];
392 sum = 0L;
393
394 for (i = (L_WINDOW >> 1); i != 0 ; i--)
395 {
396 temp = *p_y >> 2;
397 *(p_y++) = temp;
398 sum += ((Word32)temp * temp) << 1;
399 temp = *p_y >> 2;
400 *(p_y++) = temp;
401 sum += ((Word32)temp * temp) << 1;
402 }
403 if (sum > 0)
404 {
405 j = 0;
406 }
407
408 }
409
410 sum += 1L; /* Avoid the case of all zeros */
411
412 /* Normalization of r[0] */
413
414 norm = norm_l(sum);
415
416 sum <<= norm;
417
418 /* Put in DPF format (see oper_32b) */
419 r_h[0] = (Word16)(sum >> 16);
420 r_l[0] = (Word16)((sum >> 1) - ((Word32)(r_h[0]) << 15));
421
422 /* r[1] to r[m] */
423
424 p_y_ref = &y[L_WINDOW - 1 ];
425 p_rh = &r_h[m];
426 p_rl = &r_l[m];
427
428 for (i = m; i > 0; i--)
429 {
430 sum = 0;
431
432 p_y = &y[L_WINDOW - i - 1];
433 p_y_1 = p_y_ref;
434
435 for (j = (L_WINDOW - i - 1) >> 1; j != 0; j--)
436 {
437 sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum);
438 sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum);
439 }
440
441 sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum);
442
443 if (((L_WINDOW - i - 1) & 1))
444 {
445 sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum);
446 }
447
448 sum <<= (norm + 1);
449
450 *(p_rh) = (Word16)(sum >> 16);
451 *(p_rl--) = (Word16)((sum >> 1) - ((Word32) * (p_rh--) << 15));
452
453 }
454
455 norm -= overfl_shft;
456
457 return (norm);
458
459 } /* Autocorr */
460