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/cor_h_x.c
35 
36      Date: 09/07/2000
37 
38 ------------------------------------------------------------------------------
39  REVISION HISTORY
40 
41  Description: Created a separate file for cor_h_x function.
42 
43  Description: Synchronized file with UMTS versin 3.2.0. Updated coding
44               template.
45 
46  Description: Made the following changes per comments from Phase 2/3 review:
47               1. Modified FOR loop in the code to count down.
48               2. Fixed typecasting issue with TI C compiler.
49 
50  Description: Added call to round() and L_shl() functions in the last FOR
51               loop to make code bit-exact. Updated copyright year.
52 
53  Description: Modified to pass pOverflow in via a pointer, rather than
54  invoking it as a global variable.
55 
56  Description: Made the following changes
57               1. Unrolled the correlation loop and add mechanism control
58                  to compute odd or even number of computations.
59               2. Use pointer to avoid continuos addresses calculation
60               2. Eliminated math operations that check for saturation.
61 
62  Description: Changed round function name to pv_round to avoid conflict with
63               round function in C standard library.
64 
65  Description:
66 
67 ------------------------------------------------------------------------------
68 */
69 
70 /*----------------------------------------------------------------------------
71 ; INCLUDES
72 ----------------------------------------------------------------------------*/
73 #include "typedef.h"
74 #include "cnst.h"
75 #include "cor_h_x.h"
76 #include "basic_op.h"
77 
78 /*----------------------------------------------------------------------------
79 ; MACROS
80 ; Define module specific macros here
81 ----------------------------------------------------------------------------*/
82 
83 
84 /*----------------------------------------------------------------------------
85 ; DEFINES
86 ; Include all pre-processor statements here. Include conditional
87 ; compile variables also.
88 ----------------------------------------------------------------------------*/
89 
90 /*----------------------------------------------------------------------------
91 ; LOCAL FUNCTION DEFINITIONS
92 ; Function Prototype declaration
93 ----------------------------------------------------------------------------*/
94 
95 /*----------------------------------------------------------------------------
96 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
97 ; Variable declaration - defined here and used outside this module
98 ----------------------------------------------------------------------------*/
99 
100 /*----------------------------------------------------------------------------
101 ; EXTERNAL FUNCTION REFERENCES
102 ; Declare functions defined elsewhere and referenced in this module
103 ----------------------------------------------------------------------------*/
104 
105 /*----------------------------------------------------------------------------
106 ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
107 ; Declare variables used in this module but defined elsewhere
108 ----------------------------------------------------------------------------*/
109 
110 /*
111 ------------------------------------------------------------------------------
112  FUNCTION NAME: cor_h_x
113 ------------------------------------------------------------------------------
114  INPUT AND OUTPUT DEFINITIONS
115 
116  Inputs:
117     h = vector containing the impulse response of the weighted synthesis
118         filter; vector contents are of type Word16; vector length is
119         2 * L_SUBFR
120     x = target signal vector; vector contents are of type Word16; vector
121         length is L_SUBFR
122     dn = vector containing the correlation between the target and the
123          impulse response; vector contents are of type Word16; vector
124          length is L_CODE
125     sf = scaling factor of type Word16 ; 2 when mode is MR122, 1 for all
126          other modes
127 
128  Outputs:
129     dn contents are the newly calculated correlation values
130 
131     pOverflow = pointer of type Flag * to overflow indicator.
132 
133  Returns:
134     None
135 
136  Global Variables Used:
137     None
138 
139  Local Variables Needed:
140     None
141 
142 ------------------------------------------------------------------------------
143  FUNCTION DESCRIPTION
144 
145  This function computes the correlation between the target signal (x) and the
146  impulse response (h).
147 
148  The correlation is given by: d[n] = sum_{i=n}^{L-1} x[i] h[i-n],
149  where: n=0,...,L-1
150 
151  d[n] is normalized such that the sum of 5 maxima of d[n] corresponding to
152  each position track does not saturate.
153 
154 ------------------------------------------------------------------------------
155  REQUIREMENTS
156 
157  None
158 
159 ------------------------------------------------------------------------------
160  REFERENCES
161 
162  cor_h.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
163 
164 ------------------------------------------------------------------------------
165  PSEUDO-CODE
166 
167 void cor_h_x (
168     Word16 h[],    // (i): impulse response of weighted synthesis filter
169     Word16 x[],    // (i): target
170     Word16 dn[],   // (o): correlation between target and h[]
171     Word16 sf      // (i): scaling factor: 2 for 12.2, 1 for others
172 )
173 {
174     cor_h_x2(h, x, dn, sf, NB_TRACK, STEP);
175 }
176 
177 
178 void cor_h_x2 (
179     Word16 h[],    // (i): impulse response of weighted synthesis filter
180     Word16 x[],    // (i): target
181     Word16 dn[],   // (o): correlation between target and h[]
182     Word16 sf,     // (i): scaling factor: 2 for 12.2, 1 for others
183     Word16 nb_track,// (i): the number of ACB tracks
184     Word16 step    // (i): step size from one pulse position to the next
185                            in one track
186 )
187 {
188     Word16 i, j, k;
189     Word32 s, y32[L_CODE], max, tot;
190 
191     // first keep the result on 32 bits and find absolute maximum
192 
193     tot = 5;
194 
195     for (k = 0; k < nb_track; k++)
196     {
197         max = 0;
198         for (i = k; i < L_CODE; i += step)
199         {
200             s = 0;
201             for (j = i; j < L_CODE; j++)
202                 s = L_mac (s, x[j], h[j - i]);
203 
204             y32[i] = s;
205 
206             s = L_abs (s);
207             if (L_sub (s, max) > (Word32) 0L)
208                 max = s;
209         }
210         tot = L_add (tot, L_shr (max, 1));
211     }
212 
213     j = sub (norm_l (tot), sf);
214 
215     for (i = 0; i < L_CODE; i++)
216     {
217         dn[i] = pv_round (L_shl (y32[i], j));
218     }
219 }
220 
221 ------------------------------------------------------------------------------
222  RESOURCES USED [optional]
223 
224  When the code is written for a specific target processor the
225  the resources used should be documented below.
226 
227  HEAP MEMORY USED: x bytes
228 
229  STACK MEMORY USED: x bytes
230 
231  CLOCK CYCLES: (cycle count equation for this function) + (variable
232                 used to represent cycle count for each subroutine
233                 called)
234      where: (cycle count variable) = cycle count for [subroutine
235                                      name]
236 
237 ------------------------------------------------------------------------------
238  CAUTION [optional]
239  [State any special notes, constraints or cautions for users of this function]
240 
241 ------------------------------------------------------------------------------
242 */
243 
cor_h_x(Word16 h[],Word16 x[],Word16 dn[],Word16 sf,Flag * pOverflow)244 void cor_h_x(
245     Word16 h[],       /* (i): impulse response of weighted synthesis filter */
246     Word16 x[],       /* (i): target                                        */
247     Word16 dn[],      /* (o): correlation between target and h[]            */
248     Word16 sf,        /* (i): scaling factor: 2 for 12.2, 1 for others      */
249     Flag   *pOverflow /* (o): pointer to overflow flag                      */
250 )
251 {
252     Word16 i;
253     Word16 j;
254     Word16 k;
255 
256     Word32 s;
257     Word32 y32[L_CODE];
258     Word32 max;
259     Word32 tot;
260 
261     Word16 *p_x;
262     Word16 *p_ptr;
263     Word32 *p_y32;
264 
265 
266     tot = 5;
267     for (k = 0; k < NB_TRACK; k++)              /* NB_TRACK = 5 */
268     {
269         max = 0;
270         for (i = k; i < L_CODE; i += STEP)      /* L_CODE = 40; STEP = 5 */
271         {
272             s = 0;
273             p_x = &x[i];
274             p_ptr = h;
275 
276             for (j = (L_CODE - i - 1) >> 1; j != 0; j--)
277             {
278                 s += ((Word32) * (p_x++) * *(p_ptr++)) << 1;
279                 s += ((Word32) * (p_x++) * *(p_ptr++)) << 1;
280             }
281 
282             s += ((Word32) * (p_x++) * *(p_ptr++)) << 1;
283 
284             if (!((L_CODE - i) & 1))    /* if even number of iterations */
285             {
286                 s += ((Word32) * (p_x++) * *(p_ptr++)) << 1;
287             }
288 
289             y32[i] = s;
290 
291             if (s < 0)
292             {
293                 s = -s;
294             }
295 
296             if (s > max)
297             {
298                 max = s;
299             }
300         }
301 
302         tot += (max >> 1);
303     }
304 
305 
306     j = norm_l(tot) - sf;
307 
308     p_ptr = dn;
309     p_y32 = y32;;
310 
311     for (i = L_CODE >> 1; i != 0; i--)
312     {
313         s = L_shl(*(p_y32++), j, pOverflow);
314         *(p_ptr++) = (s + 0x00008000) >> 16;
315         s = L_shl(*(p_y32++), j, pOverflow);
316         *(p_ptr++) = (s + 0x00008000) >> 16;
317     }
318 
319     return;
320 }
321