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 mul;
258 Word32 y32[L_CODE];
259 Word32 max;
260 Word32 tot;
261
262 Word16 *p_x;
263 Word16 *p_ptr;
264 Word32 *p_y32;
265
266
267 tot = 5;
268 for (k = 0; k < NB_TRACK; k++) /* NB_TRACK = 5 */
269 {
270 max = 0;
271 for (i = k; i < L_CODE; i += STEP) /* L_CODE = 40; STEP = 5 */
272 {
273 s = 0;
274 p_x = &x[i];
275 p_ptr = h;
276
277 for (j = (L_CODE - i - 1) >> 1; j != 0; j--)
278 {
279 __builtin_mul_overflow(*(p_x++), *(p_ptr++), &mul);
280 __builtin_add_overflow(s, mul << 1, &s);
281 __builtin_mul_overflow(*(p_x++), *(p_ptr++), &mul);
282 __builtin_add_overflow(s, mul << 1, &s);
283 }
284
285 __builtin_mul_overflow(*(p_x++), *(p_ptr++), &mul);
286 __builtin_add_overflow(s, mul << 1, &s);
287
288 if (!((L_CODE - i) & 1)) /* if even number of iterations */
289 {
290 __builtin_mul_overflow(*(p_x++), *(p_ptr++), &mul);
291 __builtin_add_overflow(s, mul << 1, &s);
292 }
293
294 y32[i] = s;
295
296 if (s < 0)
297 {
298 s = -s;
299 }
300
301 if (s > max)
302 {
303 max = s;
304 }
305 }
306
307 __builtin_add_overflow(tot, (max >> 1), &tot);
308 }
309
310
311 j = norm_l(tot) - sf;
312
313 p_ptr = dn;
314 p_y32 = y32;;
315
316 for (i = L_CODE >> 1; i != 0; i--)
317 {
318 Word32 result;
319 s = L_shl(*(p_y32++), j, pOverflow);
320 __builtin_add_overflow(s, 0x00008000, &result);
321 *(p_ptr++) = result >> 16;
322 s = L_shl(*(p_y32++), j, pOverflow);
323 __builtin_add_overflow(s, 0x00008000, &result);
324 *(p_ptr++) = result >> 16;
325 }
326
327 return;
328 }
329