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  Filename: /audio/gsm_amr/c/src/g_code.c
35 
36      Date: 01/31/2002
37 
38 ------------------------------------------------------------------------------
39  REVISION HISTORY
40 
41  Description: The return of L_mult was being stored in a Word16 before it was
42               being operated on (extract_h). Data loss happened here.
43 
44  Description:
45               1. Eliminated unused include files.
46               2. Replaced array addressing by pointers
47               3. Eliminated math operations that unnecessary checked for
48                  saturation, in some cases this by shifting before adding and
49                  in other cases by evaluating the operands
50               4. Unrolled loops to speed up processing
51               5. Eliminated calls to shifts left and right functions by adding
52                  if-else statements that do the same faster.
53 
54  Description:  Added casting to eliminate warnings
55 
56  Description:  Replaced "int" and/or "char" with OSCL defined types.
57 
58  Description: 1. Using inlines from fxp_arithmetic.h
59               2. Removing a compiler warning.
60 
61  Description: Replacing fxp_arithmetic.h with basic_op.h.
62 
63  Description:
64 
65 ------------------------------------------------------------------------------
66 */
67 
68 /*----------------------------------------------------------------------------
69 ; INCLUDES
70 ----------------------------------------------------------------------------*/
71 #include    "g_code.h"
72 #include    "cnst.h"
73 #include    "basic_op.h"
74 /*----------------------------------------------------------------------------
75 ; MACROS
76 ; [Define module specific macros here]
77 ----------------------------------------------------------------------------*/
78 
79 /*----------------------------------------------------------------------------
80 ; DEFINES
81 ; [Include all pre-processor statements here. Include conditional
82 ; compile variables also.]
83 ----------------------------------------------------------------------------*/
84 
85 /*----------------------------------------------------------------------------
86 ; LOCAL FUNCTION DEFINITIONS
87 ; [List function prototypes here]
88 ----------------------------------------------------------------------------*/
89 
90 /*----------------------------------------------------------------------------
91 ; LOCAL VARIABLE DEFINITIONS
92 ; [Variable declaration - defined here and used outside this module]
93 ----------------------------------------------------------------------------*/
94 
95 /*
96 ------------------------------------------------------------------------------
97  FUNCTION NAME: G_code
98 ------------------------------------------------------------------------------
99  INPUT AND OUTPUT DEFINITIONS
100 
101  Inputs:
102     xn2[] = target vector (Word16)
103     y2[] = filtered innovation vector
104     pOverflow = pointer to overflow (Flag)
105 
106  Outputs:
107     pOverflow -> 1 if the innovative gain calculation resulted in overflow
108 
109  Returns:
110     gain = Gain of Innovation code (Word16)
111 
112  Global Variables Used:
113     None
114 
115  Local Variables Needed:
116     None
117 
118 ------------------------------------------------------------------------------
119  FUNCTION DESCRIPTION
120 
121  This function computes the innovative codebook gain.
122 
123  The innovative codebook gain is given by
124     g = <x[], y[]> / <y[], y[]>
125 
126  where x[] is the target vector, y[] is the filtered innovative codevector,
127  and <> denotes dot product.
128 
129 ------------------------------------------------------------------------------
130  REQUIREMENTS
131 
132  None
133 
134 ------------------------------------------------------------------------------
135  REFERENCES
136 
137  [1] g_code.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
138 
139 ------------------------------------------------------------------------------
140  PSEUDO-CODE
141 
142 Word16 G_code (         // out   : Gain of innovation code
143     Word16 xn2[],       // in    : target vector
144     Word16 y2[]         // in    : filtered innovation vector
145 )
146 {
147     Word16 i;
148     Word16 xy, yy, exp_xy, exp_yy, gain;
149     Word16 scal_y2[L_SUBFR];
150     Word32 s;
151 
152 // The original ETSI implementation uses a global overflow flag. However in
153 // actual implementation a pointer to Overflow flag is passed into the
154 // function for access by the low level math functions.
155 
156     // Scale down Y[] by 2 to avoid overflow
157 
158     for (i = 0; i < L_SUBFR; i++)
159     {
160         scal_y2[i] = shr (y2[i], 1);
161     }
162 
163     // Compute scalar product <X[],Y[]>
164 
165     s = 1L; // Avoid case of all zeros
166     for (i = 0; i < L_SUBFR; i++)
167     {
168         s = L_mac (s, xn2[i], scal_y2[i]);
169     }
170     exp_xy = norm_l (s);
171     xy = extract_h (L_shl (s, exp_xy));
172 
173     // If (xy < 0) gain = 0
174 
175     if (xy <= 0)
176         return ((Word16) 0);
177 
178     // Compute scalar product <Y[],Y[]>
179 
180     s = 0L;
181     for (i = 0; i < L_SUBFR; i++)
182     {
183         s = L_mac (s, scal_y2[i], scal_y2[i]);
184     }
185     exp_yy = norm_l (s);
186     yy = extract_h (L_shl (s, exp_yy));
187 
188     // compute gain = xy/yy
189 
190     xy = shr (xy, 1);                 // Be sure xy < yy
191     gain = div_s (xy, yy);
192 
193     // Denormalization of division
194     i = add (exp_xy, 5);              // 15-1+9-18 = 5
195     i = sub (i, exp_yy);
196 
197     gain = shl (shr (gain, i), 1);    // Q0 -> Q1/
198 
199     return (gain);
200 }
201 
202 
203 ------------------------------------------------------------------------------
204  RESOURCES USED [optional]
205 
206  When the code is written for a specific target processor the
207  the resources used should be documented below.
208 
209  HEAP MEMORY USED: x bytes
210 
211  STACK MEMORY USED: x bytes
212 
213  CLOCK CYCLES: (cycle count equation for this function) + (variable
214                 used to represent cycle count for each subroutine
215                 called)
216      where: (cycle count variable) = cycle count for [subroutine
217                                      name]
218 
219 ------------------------------------------------------------------------------
220  CAUTION [optional]
221  [State any special notes, constraints or cautions for users of this function]
222 
223 ------------------------------------------------------------------------------
224 */
225 
226 /*----------------------------------------------------------------------------
227 ; FUNCTION CODE
228 ----------------------------------------------------------------------------*/
G_code(Word16 xn2[],Word16 y2[],Flag * pOverflow)229 Word16 G_code(          /* o     : Gain of innovation code         */
230     Word16 xn2[],       /* i     : target vector                   */
231     Word16 y2[],        /* i     : filtered innovation vector      */
232     Flag   *pOverflow   /* i/o   : overflow flag                   */
233 )
234 {
235     Word16 i;
236     Word16 xy, yy, exp_xy, exp_yy, gain;
237     Word32 s;
238 
239     Word16 *p_xn2 = xn2;
240     Word16 *p_y2  = y2;
241     Word16 temp;
242     Word32 temp2;
243 
244     OSCL_UNUSED_ARG(pOverflow);
245 
246     /* Compute scalar product <X[],Y[]> */
247     s = 0;
248 
249     for (i = (L_SUBFR >> 2); i != 0 ; i--)
250     {
251         temp2 = (Word32)(*(p_y2++) >> 1);
252         s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn2++), temp2, s);
253         temp2 = (Word32)(*(p_y2++) >> 1);
254         s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn2++), temp2, s);
255         temp2 = (Word32)(*(p_y2++) >> 1);
256         s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn2++), temp2, s);
257         temp2 = (Word32)(*(p_y2++) >> 1);
258         s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn2++), temp2, s);
259     }
260     s <<= 1;
261     exp_xy = norm_l(s + 1); /* Avoid case of all zeros, add 1 */
262 
263     if (exp_xy < 17)        /* extra right shift to be sure xy < yy */
264     {
265         xy = (Word16)(s >> (17 - exp_xy));
266     }
267     else
268     {
269         xy = (Word16)(s << (exp_xy - 17));
270     }
271 
272     /* If (xy < 0) gain = 0  */
273 
274     if (xy <= 0)
275     {
276         return ((Word16) 0);
277     }
278 
279     /* Compute scalar product <Y[],Y[]> */
280 
281     s = 0L;
282     p_y2  = y2;
283 
284     for (i = (L_SUBFR >> 1); i != 0 ; i--)
285     {
286         temp = *(p_y2++) >> 1;
287         s += ((Word32) temp * temp) >> 2;
288         temp = *(p_y2++) >> 1;
289         s += ((Word32) temp * temp) >> 2;
290     }
291     s <<= 3;
292     exp_yy = norm_l(s);
293 
294     if (exp_yy < 16)
295     {
296         yy = (Word16)(s >> (16 - exp_yy));
297     }
298     else
299     {
300         yy = (Word16)(s << (exp_yy - 16));
301     }
302 
303     gain = div_s(xy, yy);
304 
305     /* Denormalization of division */
306     i  = exp_xy + 5;                                /* 15-1+9-18 = 5 */
307     i -= exp_yy;
308 
309     // gain = shl (shr (gain, i), 1);    /* Q0 -> Q1 */
310 
311     if (i > 1)
312     {
313         gain >>= i - 1;
314     }
315     else
316     {
317         gain <<= 1 - i;
318     }
319 
320 
321     return (gain);
322 }
323