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