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