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 Pathname: ./audio/gsm-amr/c/src/syn_filt.c 31 32 ------------------------------------------------------------------------------ 33 REVISION HISTORY 34 35 Description: Making changes based on comments from the review meeting. 36 37 Description: Added typedef to Input/Output Definition section. 38 39 Description: Synchronized file with UMTS version 3.2.0. Updated coding 40 template. 41 42 Description: Fixed typecasting issue with the TI C compiler. 43 44 Description: Modified FOR loops to count down. 45 46 Description: Modified FOR loop to count up again so that the correct values 47 are stored in the tmp buffer. Updated copyright year. 48 49 Description: 50 - Modified for loop and introduced pointers to avoid adding 51 offsets 52 - Eliminated check for saturation given that the max values of input 53 data and coefficients will not saturate the multiply and 54 accumulation 55 - eliminated memcpy to update history buffer in every pass. This is 56 done now just updating the pointers. 57 58 Description: 59 1. Eliminated unused include files. 60 2. Unrolled loops to process twice as many samples as before, 61 this saves on memory accesses to the vector coeff. a[] and 62 elements in the history buffer of this recursive filter 63 64 Description: 65 1. Added overflow check inside both loops. (this is needed just 66 to satisfy bit exactness on the decoder, a faster 67 implementation will add an extra shift, do the same, 68 but will not be bit exact, and it may have better audio 69 quality because will avoid clipping) 70 2. Added include file for constant definitions 71 72 Description: Replaced OSCL mem type functions and eliminated include 73 files that now are chosen by OSCL definitions 74 75 Description: Replaced "int" and/or "char" with OSCL defined types. 76 77 Description: Changed round function name to pv_round to avoid conflict with 78 round function in C standard library. 79 80 Description: Using fxp_arithmetic.h that includes inline assembly functions 81 for ARM and linux-arm. 82 83 Description: Replacing fxp_arithmetic.h with basic_op.h. 84 85 Who: Date: 86 Description: 87 88 ------------------------------------------------------------------------------ 89 */ 90 91 /*---------------------------------------------------------------------------- 92 ; INCLUDES 93 ----------------------------------------------------------------------------*/ 94 95 #include <string.h> 96 97 #include "syn_filt.h" 98 #include "cnst.h" 99 #include "basic_op.h" 100 101 #include "basic_op.h" 102 103 /*---------------------------------------------------------------------------- 104 ; MACROS 105 ; Define module specific macros here 106 ----------------------------------------------------------------------------*/ 107 108 109 /*---------------------------------------------------------------------------- 110 ; DEFINES 111 ; Include all pre-processor statements here. Include conditional 112 ; compile variables also. 113 ----------------------------------------------------------------------------*/ 114 115 /*---------------------------------------------------------------------------- 116 ; LOCAL FUNCTION DEFINITIONS 117 ; Function Prototype declaration 118 ----------------------------------------------------------------------------*/ 119 120 /*---------------------------------------------------------------------------- 121 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS 122 ; Variable declaration - defined here and used outside this module 123 ----------------------------------------------------------------------------*/ 124 125 126 /* 127 ------------------------------------------------------------------------------ 128 FUNCTION NAME: Syn_filt 129 ------------------------------------------------------------------------------ 130 INPUT AND OUTPUT DEFINITIONS 131 132 Inputs: 133 a = buffer containing the prediction coefficients (Word16) max 2^12 134 x = input signal buffer (Word16) max 2^15 135 y = output signal buffer (Word16) 136 lg = size of filtering (Word16) 137 mem = memory buffer associated with this filtering (Word16) 138 update = flag to indicate memory update; 0=no update, 1=update memory 139 (Word16) 140 141 Outputs: 142 mem buffer is changed to be the last M data points of the output signal 143 if update was set to 1 144 y buffer contains the newly calculated filter output 145 146 Returns: 147 None 148 149 Global Variables Used: 150 None 151 152 Local Variables Needed: 153 None 154 155 ------------------------------------------------------------------------------ 156 FUNCTION DESCRIPTION 157 158 Perform synthesis filtering through 1/A(z) 159 160 ------------------------------------------------------------------------------ 161 REQUIREMENTS 162 163 None 164 165 ------------------------------------------------------------------------------ 166 REFERENCES 167 168 syn_filt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 169 170 ------------------------------------------------------------------------------ 171 PSEUDO-CODE 172 173 void Syn_filt ( 174 Word16 a[], // (i) : a[M+1] prediction coefficients (M=10) 175 Word16 x[], // (i) : input signal 176 Word16 y[], // (o) : output signal 177 Word16 lg, // (i) : size of filtering 178 Word16 mem[], // (i/o) : memory associated with this filtering. 179 Word16 update // (i) : 0=no update, 1=update of memory. 180 ) 181 { 182 Word16 i, j; 183 Word32 s; 184 Word16 tmp[80]; // This is usually done by memory allocation (lg+M) 185 Word16 *yy; 186 187 // Copy mem[] to yy[] 188 189 yy = tmp; 190 191 for (i = 0; i < M; i++) 192 { 193 *yy++ = mem[i]; 194 } 195 196 // Do the filtering. 197 198 for (i = 0; i < lg; i++) 199 { 200 s = L_mult (x[i], a[0]); 201 for (j = 1; j <= M; j++) 202 { 203 s = L_msu (s, a[j], yy[-j]); 204 } 205 s = L_shl (s, 3); 206 *yy++ = pv_round (s); 207 } 208 209 for (i = 0; i < lg; i++) 210 { 211 y[i] = tmp[i + M]; 212 } 213 214 // Update of memory if update==1 215 216 if (update != 0) 217 { 218 for (i = 0; i < M; i++) 219 { 220 mem[i] = y[lg - M + i]; 221 } 222 } 223 return; 224 } 225 226 ------------------------------------------------------------------------------ 227 RESOURCES USED [optional] 228 229 When the code is written for a specific target processor the 230 the resources used should be documented below. 231 232 HEAP MEMORY USED: x bytes 233 234 STACK MEMORY USED: x bytes 235 236 CLOCK CYCLES: (cycle count equation for this function) + (variable 237 used to represent cycle count for each subroutine 238 called) 239 where: (cycle count variable) = cycle count for [subroutine 240 name] 241 242 ------------------------------------------------------------------------------ 243 CAUTION [optional] 244 [State any special notes, constraints or cautions for users of this function] 245 246 ------------------------------------------------------------------------------ 247 */ 248 249 void Syn_filt( 250 Word16 a[], /* (i) : a[M+1] prediction coefficients (M=10) */ 251 Word16 x[], /* (i) : input signal */ 252 Word16 y[], /* (o) : output signal */ 253 Word16 lg, /* (i) : size of filtering (40) */ 254 Word16 mem[], /* (i/o) : memory associated with this filtering. */ 255 Word16 update /* (i) : 0=no update, 1=update of memory. */ 256 ) 257 { 258 Word16 i, j; 259 Word32 s1; 260 Word32 s2; 261 Word16 tmp[2*M]; /* This is usually done by memory allocation (lg+M) */ 262 Word16 *yy; 263 264 Word16 *p_a; 265 Word16 *p_yy1; 266 Word16 *p_y; 267 Word16 *p_x; 268 Word16 temp; 269 /* Copy mem[] to yy[] */ 270 271 yy = tmp; 272 273 memcpy(yy, mem, M*sizeof(Word16)); 274 275 yy = yy + M; 276 277 /* Do the filtering. */ 278 279 p_y = y; 280 p_x = x; 281 p_yy1 = &yy[-1]; 282 283 for (i = M >> 1; i != 0; i--) 284 { 285 p_a = a; 286 287 s1 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a), 0x00000800L); 288 s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a++), 0x00000800L); 289 s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1); 290 291 for (j = (M >> 1) - 2; j != 0; j--) 292 { 293 s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2); 294 s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1); 295 s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2); 296 s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1); 297 s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2); 298 s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1); 299 } 300 301 /* check for overflow on s1 */ 302 if ((UWord32)(s1 - 0xf8000000L) < 0x0fffffffL) 303 { 304 temp = (Word16)(s1 >> 12); 305 } 306 else if (s1 > 0x07ffffffL) 307 { 308 temp = MAX_16; 309 } 310 else 311 { 312 temp = MIN_16; 313 } 314 315 s2 = amrnb_fxp_msu_16_by_16bb((Word32)a[1], (Word32)temp, s2); 316 317 *(yy++) = temp; 318 *(p_y++) = temp; 319 320 p_yy1 = yy; 321 322 /* check for overflow on s2 */ 323 if ((UWord32)(s2 - 0xf8000000L) < 0x0fffffffL) 324 { 325 temp = (Word16)(s2 >> 12); 326 } 327 else if (s2 > 0x07ffffffL) 328 { 329 temp = MAX_16; 330 } 331 else 332 { 333 temp = MIN_16; 334 } 335 336 *(yy++) = temp; 337 *(p_y++) = temp; 338 } 339 340 p_yy1 = &y[M-1]; 341 342 for (i = (lg - M) >> 1; i != 0; i--) 343 { 344 p_a = a; 345 346 s1 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a), 0x00000800L); 347 s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a++), 0x00000800L); 348 s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1); 349 350 for (j = (M >> 1) - 2; j != 0; j--) 351 { 352 s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2); 353 s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1); 354 s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2); 355 s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1); 356 s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2); 357 s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1); 358 } 359 360 if ((UWord32)(s1 - 0xf8000000L) < 0x0fffffffL) 361 { 362 temp = (Word16)(s1 >> 12); 363 } 364 else if (s1 > 0x07ffffffL) 365 { 366 temp = MAX_16; 367 } 368 else 369 { 370 temp = MIN_16; 371 } 372 373 s2 = amrnb_fxp_msu_16_by_16bb((Word32)a[1], (Word32)temp, s2); 374 375 *(p_y++) = temp; 376 p_yy1 = p_y; 377 378 if ((UWord32)(s2 - 0xf8000000L) < 0x0fffffffL) 379 { 380 *(p_y++) = (Word16)(s2 >> 12); 381 } 382 else if (s2 > 0x07ffffffL) 383 { 384 *(p_y++) = MAX_16; 385 } 386 else 387 { 388 *(p_y++) = MIN_16; 389 } 390 } 391 392 /* Update of memory if update==1 */ 393 if (update != 0) 394 { 395 memcpy(mem, &y[lg-M], M*sizeof(Word16)); 396 } 397 398 return; 399 } 400