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/g_pitch.c
35
36 Date: 06/12/2000
37
38 ------------------------------------------------------------------------------
39 REVISION HISTORY
40
41 Description: Placed into template and began to optimize.
42
43 Description: Synchronized file with UMTS version 3.2.0. Updated coding
44 template. Removed unnecessary include files.
45
46 Description: Replaced basic_op.h and oper_32b.h with the header files of the
47 math functions used in the file. Fixed typecasting issue with
48 TI compiler.
49
50 Description: Passing in pointer to overflow flag for EPOC compatibility. .
51
52 Description:
53 1. Eliminated unused include files.
54 2. Replaced array addressing by pointers
55 3. Eliminated math operations that unnecessary checked for
56 saturation, in some cases this by shifting before adding and
57 in other cases by evaluating the operands
58 4. Unrolled loops to speed up processing
59
60 Description: Replaced OSCL mem type functions and eliminated include
61 files that now are chosen by OSCL definitions
62
63 Description: Replaced "int" and/or "char" with OSCL defined types.
64
65 Description: Changed round function name to pv_round to avoid conflict with
66 round function in C standard library.
67
68 Description: Using inlines from fxp_arithmetic.h .
69
70 Description: Replacing fxp_arithmetic.h with basic_op.h.
71
72 Description:
73
74 ------------------------------------------------------------------------------
75 */
76
77 /*----------------------------------------------------------------------------
78 ; INCLUDES
79 ----------------------------------------------------------------------------*/
80 #include "g_pitch.h"
81 #include "mode.h"
82 #include "cnst.h"
83 #include "basic_op.h"
84
85 /*----------------------------------------------------------------------------
86 ; MACROS
87 ; Define module specific macros here
88 ----------------------------------------------------------------------------*/
89
90
91 /*----------------------------------------------------------------------------
92 ; DEFINES
93 ; Include all pre-processor statements here. Include conditional
94 ; compile variables also.
95 ----------------------------------------------------------------------------*/
96
97 /*----------------------------------------------------------------------------
98 ; LOCAL FUNCTION DEFINITIONS
99 ; Function Prototype declaration
100 ----------------------------------------------------------------------------*/
101
102 /*----------------------------------------------------------------------------
103 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
104 ; Variable declaration - defined here and used outside this module
105 ----------------------------------------------------------------------------*/
106
107
108 /*
109 ------------------------------------------------------------------------------
110 FUNCTION NAME: G_pitch
111 ------------------------------------------------------------------------------
112 INPUT AND OUTPUT DEFINITIONS
113
114 Inputs:
115 mode = AMR mode (enum Mode)
116 xn = pointer to pitch target buffer (Word16)
117 y1 = pointer to filtered adaptive codebook buffer (Word16)
118 g_coeff = pointer to buffer of correlations needed for gain quantization
119 (Word16)
120 L_subfr = length of subframe (Word16)
121 pOverflow = pointer to overflow flag (Flag)
122
123 Outputs:
124 g_coeff contains the mantissa and exponent of the two dot products.
125 pOverflow -> 1 if an overflow occurs
126
127 Returns:
128 gain = ratio of dot products.(Word16)
129
130 Global Variables Used:
131 None.
132
133 Local Variables Needed:
134 None.
135
136 ------------------------------------------------------------------------------
137 FUNCTION DESCRIPTION
138
139 This function computes the pitch (adaptive codebook) gain. The adaptive
140 codebook gain is given by
141
142 g = <x[], y[]> / <y[], y[]>
143
144 where: x[] is the target vector
145 y[] is the filtered adaptive codevector
146 <> denotes dot product.
147
148 The gain is limited to the range [0,1.2] (=0..19661 Q14)
149
150 ------------------------------------------------------------------------------
151 REQUIREMENTS
152
153 None.
154
155 ------------------------------------------------------------------------------
156 REFERENCES
157
158 g_pitch.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
159
160 ------------------------------------------------------------------------------
161 PSEUDO-CODE
162
163 Word16 G_pitch ( // o : Gain of pitch lag saturated to 1.2
164 enum Mode mode, // i : AMR mode
165 Word16 xn[], // i : Pitch target.
166 Word16 y1[], // i : Filtered adaptive codebook.
167 Word16 g_coeff[], // i : Correlations need for gain quantization
168 Word16 L_subfr // i : Length of subframe.
169 )
170 {
171 Word16 i;
172 Word16 xy, yy, exp_xy, exp_yy, gain;
173 Word32 s;
174
175 Word16 scaled_y1[L_SUBFR]; // Usually dynamic allocation of (L_subfr)
176
177 // divide "y1[]" by 4 to avoid overflow
178
179 // The reference ETSI code uses a global overflow Flag. However in the actual
180 // implementation a pointer to the overflow flag is passed into the function.
181
182 for (i = 0; i < L_subfr; i++)
183 {
184 scaled_y1[i] = shr (y1[i], 2);
185 }
186
187 // Compute scalar product <y1[],y1[]>
188
189 // Q12 scaling / MR122
190 Overflow = 0;
191 s = 1L; // Avoid case of all zeros
192 for (i = 0; i < L_subfr; i++)
193 {
194 s = L_mac (s, y1[i], y1[i]);
195 }
196 if (Overflow == 0) // Test for overflow
197 {
198 exp_yy = norm_l (s);
199 yy = pv_round (L_shl (s, exp_yy));
200 }
201 else
202 {
203 s = 1L; // Avoid case of all zeros
204 for (i = 0; i < L_subfr; i++)
205 {
206 s = L_mac (s, scaled_y1[i], scaled_y1[i]);
207 }
208 exp_yy = norm_l (s);
209 yy = pv_round (L_shl (s, exp_yy));
210 exp_yy = sub (exp_yy, 4);
211 }
212
213 // Compute scalar product <xn[],y1[]>
214
215 Overflow = 0;
216 s = 1L; // Avoid case of all zeros
217
218 for (i = 0; i < L_subfr; i++)
219 {
220 s = L_mac(s, xn[i], y1[i]);
221 }
222 if (Overflow == 0)
223 {
224 exp_xy = norm_l (s);
225 xy = pv_round (L_shl (s, exp_xy));
226 }
227 else
228 {
229 s = 1L; // Avoid case of all zeros
230 for (i = 0; i < L_subfr; i++)
231 {
232 s = L_mac (s, xn[i], scaled_y1[i]);
233 }
234 exp_xy = norm_l (s);
235 xy = pv_round (L_shl (s, exp_xy));
236 exp_xy = sub (exp_xy, 2);
237 }
238
239 g_coeff[0] = yy;
240 g_coeff[1] = sub (15, exp_yy);
241 g_coeff[2] = xy;
242 g_coeff[3] = sub (15, exp_xy);
243
244 // If (xy < 4) gain = 0
245
246 i = sub (xy, 4);
247
248 if (i < 0)
249 return ((Word16) 0);
250
251 // compute gain = xy/yy
252
253 xy = shr (xy, 1); // Be sure xy < yy
254 gain = div_s (xy, yy);
255
256 i = sub (exp_xy, exp_yy); // Denormalization of division
257 gain = shr (gain, i);
258
259 // if(gain >1.2) gain = 1.2
260
261 if (sub (gain, 19661) > 0)
262 {
263 gain = 19661;
264 }
265
266 if (sub(mode, MR122) == 0)
267 {
268 // clear 2 LSBits
269 gain = gain & 0xfffC;
270 }
271
272 return (gain);
273 }
274
275 ------------------------------------------------------------------------------
276 RESOURCES USED [optional]
277
278 When the code is written for a specific target processor the
279 the resources used should be documented below.
280
281 HEAP MEMORY USED: x bytes
282
283 STACK MEMORY USED: x bytes
284
285 CLOCK CYCLES: (cycle count equation for this function) + (variable
286 used to represent cycle count for each subroutine
287 called)
288 where: (cycle count variable) = cycle count for [subroutine
289 name]
290
291 ------------------------------------------------------------------------------
292 CAUTION [optional]
293 [State any special notes, constraints or cautions for users of this function]
294
295 ------------------------------------------------------------------------------
296 */
297
G_pitch(enum Mode mode,Word16 xn[],Word16 y1[],Word16 g_coeff[],Word16 L_subfr,Flag * pOverflow)298 Word16 G_pitch( /* o : Gain of pitch lag saturated to 1.2 */
299 enum Mode mode, /* i : AMR mode */
300 Word16 xn[], /* i : Pitch target. Q0 */
301 Word16 y1[], /* i : Filtered adaptive codebook. Q12 */
302 Word16 g_coeff[], /* i : Correlations need for gain quantization */
303 Word16 L_subfr, /* i : Length of subframe. */
304 Flag *pOverflow /* i/o : Overflow flag */
305 )
306 {
307
308 Word16 i;
309 Word16 xy;
310 Word16 yy;
311 Word16 exp_xy;
312 Word16 exp_yy;
313 Word16 gain;
314 Word16 tmp;
315 Word32 s;
316 Word32 s1;
317 Word32 L_temp; /* Use this as an intermediate value */
318 Word16 *p_xn = &xn[0];
319 Word16 *p_y1 = &y1[0];
320
321 /* Compute scalar product <y1[],y1[]> */
322
323 /* Q12 scaling / MR122 */
324 *pOverflow = 0;
325 s = 0;
326
327 for (i = L_subfr >> 2; i != 0; i--)
328 {
329 s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
330 p_y1++;
331 s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
332 p_y1++;
333 s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
334 p_y1++;
335 s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
336 p_y1++;
337 }
338 if ((s >= 0) & (s < 0x40000000))
339 {
340 s <<= 1;
341 s += 1; /* Avoid case of all zeros */
342
343 exp_yy = norm_l(s); /* Note 0<=exp_yy <= 31 */
344 L_temp = s << exp_yy;
345 yy = pv_round(L_temp, pOverflow);
346 }
347 else
348 {
349 s = 0; /* Avoid case of all zeros */
350 p_y1 = &y1[0];
351 for (i = (L_subfr >> 1); i != 0; i--)
352 {
353 tmp = *(p_y1++) >> 2;
354 s = amrnb_fxp_mac_16_by_16bb((Word32) tmp, (Word32) tmp, s);
355 tmp = *(p_y1++) >> 2;
356 s = amrnb_fxp_mac_16_by_16bb((Word32) tmp, (Word32) tmp, s);
357 }
358
359 s <<= 1;
360 s += 1; /* Avoid case of all zeros */
361
362 exp_yy = norm_l(s);
363 L_temp = s << exp_yy;
364 yy = pv_round(L_temp, pOverflow);
365 exp_yy = exp_yy - 4;
366
367 }
368
369 /* Compute scalar product <xn[],y1[]> */
370
371 s = 0;
372 p_y1 = &y1[0];
373 *pOverflow = 0;
374
375 for (i = L_subfr; i != 0; i--)
376 {
377 L_temp = ((Word32) * (p_xn++) * *(p_y1++));
378 s1 = s;
379 s = s1 + L_temp;
380
381 if ((s1 ^ L_temp) > 0)
382 {
383 if ((s1 ^ s) < 0)
384 {
385 *pOverflow = 1;
386 break;
387 }
388 }
389 }
390
391 if (!(*pOverflow))
392 {
393
394 s <<= 1;
395 s += 1; /* Avoid case of all zeros */
396
397 exp_xy = norm_l(s); /* Note 0<=exp_yy <= 31 */
398 L_temp = s << exp_xy;
399 xy = pv_round(L_temp, pOverflow);
400 }
401 else
402 {
403 s = 0; /* re-initialize calculations */
404 p_y1 = &y1[0];
405 p_xn = &xn[0];
406 for (i = (L_subfr >> 2); i != 0; i--)
407 {
408 L_temp = (Word32)(*(p_y1++) >> 2);
409 s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
410 L_temp = (Word32)(*(p_y1++) >> 2);
411 s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
412 L_temp = (Word32)(*(p_y1++) >> 2);
413 s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
414 L_temp = (Word32)(*(p_y1++) >> 2);
415 s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
416 }
417
418 s <<= 1;
419 s += 1; /* Avoid case of all zeros */
420
421 exp_xy = norm_l(s);
422 L_temp = s << exp_xy;
423 xy = pv_round(L_temp, pOverflow);
424 exp_xy = exp_xy - 4;
425
426 }
427
428 g_coeff[0] = yy;
429 g_coeff[1] = 15 - exp_yy;
430 g_coeff[2] = xy;
431 g_coeff[3] = 15 - exp_xy;
432
433 /* If (xy < 4) gain = 0 */
434 if (xy < 4)
435 {
436 return ((Word16) 0);
437 }
438
439 /* compute gain = xy/yy */
440 /* Be sure xy < yy */
441
442 xy = xy >> 1;
443
444 gain = div_s(xy, yy);
445
446 i = exp_xy - exp_yy; /* Denormalization of division */
447
448 gain = shr(gain, i, pOverflow);
449
450
451 /* if(gain >1.2) gain = 1.2 */
452 if (gain > 19661)
453 {
454 gain = 19661;
455 }
456
457 if (mode == MR122)
458 {
459 /* clear 2 LSBits */
460 gain = gain & 0xfffC;
461 }
462
463 return(gain);
464
465 }
466