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