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 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 173void 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#ifdef __clang__ 249__attribute__((no_sanitize("integer"))) 250#endif 251void Syn_filt( 252 Word16 a[], /* (i) : a[M+1] prediction coefficients (M=10) */ 253 Word16 x[], /* (i) : input signal */ 254 Word16 y[], /* (o) : output signal */ 255 Word16 lg, /* (i) : size of filtering (40) */ 256 Word16 mem[], /* (i/o) : memory associated with this filtering. */ 257 Word16 update /* (i) : 0=no update, 1=update of memory. */ 258) 259{ 260 Word16 i, j; 261 Word32 s1; 262 Word32 s2; 263 Word16 tmp[2*M]; /* This is usually done by memory allocation (lg+M) */ 264 Word16 *yy; 265 266 Word16 *p_a; 267 Word16 *p_yy1; 268 Word16 *p_y; 269 Word16 *p_x; 270 Word16 temp; 271 /* Copy mem[] to yy[] */ 272 273 yy = tmp; 274 275 memcpy(yy, mem, M*sizeof(Word16)); 276 277 yy = yy + M; 278 279 /* Do the filtering. */ 280 281 p_y = y; 282 p_x = x; 283 p_yy1 = &yy[-1]; 284 285 for (i = M >> 1; i != 0; i--) 286 { 287 p_a = a; 288 289 s1 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a), 0x00000800L); 290 s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a++), 0x00000800L); 291 s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1); 292 293 for (j = (M >> 1) - 2; j != 0; j--) 294 { 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 s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2); 300 s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1); 301 } 302 303 /* check for overflow on s1 */ 304 if ((UWord32)(s1 - 0xf8000000L) < 0x0fffffffL) 305 { 306 temp = (Word16)(s1 >> 12); 307 } 308 else if (s1 > 0x07ffffffL) 309 { 310 temp = MAX_16; 311 } 312 else 313 { 314 temp = MIN_16; 315 } 316 317 s2 = amrnb_fxp_msu_16_by_16bb((Word32)a[1], (Word32)temp, s2); 318 319 *(yy++) = temp; 320 *(p_y++) = temp; 321 322 p_yy1 = yy; 323 324 /* check for overflow on s2 */ 325 if ((UWord32)(s2 - 0xf8000000L) < 0x0fffffffL) 326 { 327 temp = (Word16)(s2 >> 12); 328 } 329 else if (s2 > 0x07ffffffL) 330 { 331 temp = MAX_16; 332 } 333 else 334 { 335 temp = MIN_16; 336 } 337 338 *(yy++) = temp; 339 *(p_y++) = temp; 340 } 341 342 p_yy1 = &y[M-1]; 343 344 for (i = (lg - M) >> 1; i != 0; i--) 345 { 346 p_a = a; 347 348 s1 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a), 0x00000800L); 349 s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a++), 0x00000800L); 350 s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1); 351 352 for (j = (M >> 1) - 2; j != 0; j--) 353 { 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 s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2); 359 s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1); 360 } 361 362 if ((UWord32)(s1 - 0xf8000000L) < 0x0fffffffL) 363 { 364 temp = (Word16)(s1 >> 12); 365 } 366 else if (s1 > 0x07ffffffL) 367 { 368 temp = MAX_16; 369 } 370 else 371 { 372 temp = MIN_16; 373 } 374 375 s2 = amrnb_fxp_msu_16_by_16bb((Word32)a[1], (Word32)temp, s2); 376 377 *(p_y++) = temp; 378 p_yy1 = p_y; 379 380 if ((UWord32)(s2 - 0xf8000000L) < 0x0fffffffL) 381 { 382 *(p_y++) = (Word16)(s2 >> 12); 383 } 384 else if (s2 > 0x07ffffffL) 385 { 386 *(p_y++) = MAX_16; 387 } 388 else 389 { 390 *(p_y++) = MIN_16; 391 } 392 } 393 394 /* Update of memory if update==1 */ 395 if (update != 0) 396 { 397 memcpy(mem, &y[lg-M], M*sizeof(Word16)); 398 } 399 400 return; 401} 402