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 Word32 mul;
316 Word16 overfl_shft;
317
318
319 /* Added for optimization */
320
321
322 Word16 temp;
323 Word16 *p_x;
324 Word16 *p_y;
325 Word16 *p_y_1;
326 Word16 *p_y_ref;
327 Word16 *p_rh;
328 Word16 *p_rl;
329 const Word16 *p_wind;
330 p_y = y;
331 p_x = x;
332 p_wind = wind;
333 /*
334 * Windowing of the signal
335 */
336
337 OSCL_UNUSED_ARG(pOverflow);
338
339 sum = 0L;
340 j = 0;
341
342 for (i = L_WINDOW; i != 0; i--)
343 {
344 temp = (amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_wind++), 0x04000)) >> 15;
345 *(p_y++) = temp;
346
347 __builtin_mul_overflow(temp, temp, &mul);
348 __builtin_add_overflow(sum, mul << 1, &sum);
349 if (sum < 0)
350 {
351 /*
352 * if oveflow exist, then stop accumulation
353 */
354 j = 1;
355 break;
356 }
357
358 }
359 /*
360 * if oveflow existed, complete windowing operation
361 * without computing energy
362 */
363
364 if (j)
365 {
366 p_y = &y[L_WINDOW-i];
367 p_x = &x[L_WINDOW-i];
368 p_wind = &wind[L_WINDOW-i];
369
370 for (; i != 0; i--)
371 {
372 temp = (amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_wind++), 0x04000)) >> 15;
373 *(p_y++) = temp;
374 }
375 }
376
377
378 /*
379 * Compute r[0] and test for overflow
380 */
381
382 overfl_shft = 0;
383
384 /*
385 * scale down by 1/4 only when needed
386 */
387 while (j == 1)
388 {
389 /* If overflow divide y[] by 4 */
390 /* FYI: For better resolution, we could */
391 /* divide y[] by 2 */
392 overfl_shft += 4;
393 p_y = &y[0];
394 sum = 0L;
395
396 for (i = (L_WINDOW >> 1); i != 0 ; i--)
397 {
398 temp = *p_y >> 2;
399 *(p_y++) = temp;
400 __builtin_mul_overflow(temp, temp, &mul);
401 __builtin_add_overflow(sum, mul << 1, &sum);
402 temp = *p_y >> 2;
403 *(p_y++) = temp;
404 __builtin_mul_overflow(temp, temp, &mul);
405 __builtin_add_overflow(sum, mul << 1, &sum);
406 }
407 if (sum > 0)
408 {
409 j = 0;
410 }
411
412 }
413
414 sum += 1L; /* Avoid the case of all zeros */
415
416 /* Normalization of r[0] */
417
418 norm = norm_l(sum);
419
420 sum <<= norm;
421
422 /* Put in DPF format (see oper_32b) */
423 r_h[0] = (Word16)(sum >> 16);
424 r_l[0] = (Word16)((sum >> 1) - ((Word32)(r_h[0]) << 15));
425
426 /* r[1] to r[m] */
427
428 p_y_ref = &y[L_WINDOW - 1 ];
429 p_rh = &r_h[m];
430 p_rl = &r_l[m];
431
432 for (i = m; i > 0; i--)
433 {
434 sum = 0;
435
436 p_y = &y[L_WINDOW - i - 1];
437 p_y_1 = p_y_ref;
438
439 for (j = (L_WINDOW - i - 1) >> 1; j != 0; j--)
440 {
441 sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum);
442 sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum);
443 }
444
445 sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum);
446
447 if (((L_WINDOW - i - 1) & 1))
448 {
449 sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum);
450 }
451
452 sum <<= (norm + 1);
453
454 *(p_rh) = (Word16)(sum >> 16);
455 *(p_rl--) = (Word16)((sum >> 1) - ((Word32) * (p_rh--) << 15));
456
457 }
458
459 norm -= overfl_shft;
460
461 return (norm);
462
463 } /* Autocorr */
464