xref: /aosp_15_r20/frameworks/av/media/module/codecs/amrnb/enc/src/autocorr.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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