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/****************************************************************************************
19Portions 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)
26Permission to distribute, modify and use this file under the standard license
27terms 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
142Word16 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----------------------------------------------------------------------------*/
229Word16 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