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/****************************************************************************************
19Portions 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)
26Permission to distribute, modify and use this file under the standard license
27terms 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
199Word16 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
300Word16 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