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 Pathname: ./audio/gsm-amr/c/src/pstfilt.c 35 Functions: 36 Post_Filter_reset 37 Post_Filter 38 39 Date: 04/14/2000 40 41 ------------------------------------------------------------------------------ 42 REVISION HISTORY 43 44 Description: Changed template used to PV coding template. First attempt at 45 optimizing C code. 46 47 Description: Updated file per comments gathered from Phase 2/3 review. 48 49 Description: Added setting of Overflow flag in inlined code. 50 51 Description: Synchronized file with UMTS version 3.2.0. Updated coding 52 template. Removed unnecessary include files. 53 54 Description: Replaced basic_op.h with the header file of the math functions 55 used in the file. 56 57 Description: Made the following changes per comments from Phase 2/3 review: 58 1. Updated copyright year. 59 2. Modified FOR loops to count down. 60 3. Fixed typecasting issue with TI C compiler. 61 4. Added "break" statement after overflow condition occurs. 62 63 Description: Removed the functions pstfilt_init and pstfilt_exit. 64 The pst_filt related structure is no longer dynamically allocated. 65 66 Description: Modified code for EPOC changes where pOverflow is passed in 67 rather than allowing overflow to be a global variable. 68 69 Description: Replaced OSCL mem type functions and eliminated include 70 files that now are chosen by OSCL definitions 71 72 Description: Replaced "int" and/or "char" with defined types. 73 Added proper casting (Word32) to some left shifting operations 74 75 Description: 76 77 ------------------------------------------------------------------------------ 78 MODULE DESCRIPTION 79 80 This file contains the function that performs adaptive post-filtering on the 81 synthesized speech. It also contains the functions that initialize, reset, 82 and exit the post-filtering function. 83 84 ------------------------------------------------------------------------------ 85 */ 86 87 /*---------------------------------------------------------------------------- 88 ; INCLUDES 89 ----------------------------------------------------------------------------*/ 90 #include <string.h> 91 92 #include "pstfilt.h" 93 #include "typedef.h" 94 #include "mode.h" 95 #include "basicop_malloc.h" 96 #include "basic_op.h" 97 #include "weight_a.h" 98 #include "residu.h" 99 #include "copy.h" 100 #include "syn_filt.h" 101 #include "preemph.h" 102 #include "cnst.h" 103 104 /*---------------------------------------------------------------------------- 105 ; MACROS 106 ; Define module specific macros here 107 ----------------------------------------------------------------------------*/ 108 109 /*---------------------------------------------------------------------------- 110 ; DEFINES 111 ; Include all pre-processor statements here. Include conditional 112 ; compile variables also. 113 ----------------------------------------------------------------------------*/ 114 #define L_H 22 /* size of truncated impulse response of A(z/g1)/A(z/g2) */ 115 116 /*---------------------------------------------------------------------------- 117 ; LOCAL FUNCTION DEFINITIONS 118 ; Function Prototype declaration 119 ----------------------------------------------------------------------------*/ 120 121 /*---------------------------------------------------------------------------- 122 ; LOCAL VARIABLE DEFINITIONS 123 ; Variable declaration - defined here and used outside this module 124 ----------------------------------------------------------------------------*/ 125 126 /* Spectral expansion factors */ 127 static const Word16 gamma3_MR122[M] = 128 { 129 22938, 16057, 11240, 7868, 5508, 130 3856, 2699, 1889, 1322, 925 131 }; 132 133 static const Word16 gamma3[M] = 134 { 135 18022, 9912, 5451, 2998, 1649, 907, 499, 274, 151, 83 136 }; 137 138 static const Word16 gamma4_MR122[M] = 139 { 140 24576, 18432, 13824, 10368, 7776, 141 5832, 4374, 3281, 2461, 1846 142 }; 143 144 static const Word16 gamma4[M] = 145 { 146 22938, 16057, 11240, 7868, 5508, 3856, 2699, 1889, 1322, 925 147 }; 148 149 /*---------------------------------------------------------------------------- 150 ; EXTERNAL FUNCTION REFERENCES 151 ; Declare functions defined elsewhere and referenced in this module 152 ----------------------------------------------------------------------------*/ 153 154 /*---------------------------------------------------------------------------- 155 ; EXTERNAL VARIABLES REFERENCES 156 ; Declare variables used in this module but defined elsewhere 157 ----------------------------------------------------------------------------*/ 158 159 /* 160 ------------------------------------------------------------------------------ 161 FUNCTION NAME: Post_Filter_reset 162 ------------------------------------------------------------------------------ 163 INPUT AND OUTPUT DEFINITIONS 164 165 Inputs: 166 state = pointer to structure of type Post_FilterState 167 168 Outputs: 169 fields of the structure pointed to by state is initialized to zero 170 171 Returns: 172 return_value = 0, if reset was successful; -1, otherwise (int) 173 174 Global Variables Used: 175 None 176 177 Local Variables Needed: 178 None 179 180 ------------------------------------------------------------------------------ 181 FUNCTION DESCRIPTION 182 183 This function initializes the state memory used by the Post_Filter function 184 to zero. 185 186 ------------------------------------------------------------------------------ 187 REQUIREMENTS 188 189 None 190 191 ------------------------------------------------------------------------------ 192 REFERENCES 193 194 pstfilt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 195 196 ------------------------------------------------------------------------------ 197 PSEUDO-CODE 198 199 int Post_Filter_reset (Post_FilterState *state) 200 { 201 if (state == (Post_FilterState *) NULL){ 202 fprintf(stderr, "Post_Filter_reset: invalid parameter\n"); 203 return -1; 204 } 205 206 Set_zero (state->mem_syn_pst, M); 207 Set_zero (state->res2, L_SUBFR); 208 Set_zero (state->synth_buf, L_FRAME + M); 209 agc_reset(state->agc_state); 210 preemphasis_reset(state->preemph_state); 211 212 return 0; 213 } 214 215 ------------------------------------------------------------------------------ 216 RESOURCES USED [optional] 217 218 When the code is written for a specific target processor the 219 the resources used should be documented below. 220 221 HEAP MEMORY USED: x bytes 222 223 STACK MEMORY USED: x bytes 224 225 CLOCK CYCLES: (cycle count equation for this function) + (variable 226 used to represent cycle count for each subroutine 227 called) 228 where: (cycle count variable) = cycle count for [subroutine 229 name] 230 231 ------------------------------------------------------------------------------ 232 CAUTION [optional] 233 [State any special notes, constraints or cautions for users of this function] 234 235 ------------------------------------------------------------------------------ 236 */ 237 238 Word16 Post_Filter_reset(Post_FilterState *state) 239 { 240 if (state == (Post_FilterState *) NULL) 241 { 242 /*fprintf(stderr, "Post_Filter_reset: invalid parameter\n"); */ 243 return(-1); 244 } 245 246 memset(state->mem_syn_pst, 0, sizeof(Word16)*M); 247 memset(state->res2, 0, sizeof(Word16)*L_SUBFR); 248 memset(state->synth_buf, 0, sizeof(Word16)*(L_FRAME + M)); 249 agc_reset(&(state->agc_state)); 250 preemphasis_reset(&(state->preemph_state)); 251 252 return(0); 253 } 254 255 /****************************************************************************/ 256 257 /* 258 ------------------------------------------------------------------------------ 259 FUNCTION NAME: Post_Filter 260 ------------------------------------------------------------------------------ 261 INPUT AND OUTPUT DEFINITIONS 262 263 Inputs: 264 st = pointer to a structure of type Post_FilterState 265 mode = AMR mode 266 syn = pointer to a buffer containing synthesized speech; upon 267 exiting this function, it will contain the post-filtered 268 synthesized speech 269 Az_4 = pointer to the interpolated LPC parameters for all subframes 270 pOverflow = pointer to overflow indicator of type Flag 271 272 Outputs: 273 fields of the structure pointed to by st contains the updated field 274 values 275 syn buffer contains the post-filtered synthesized speech 276 pOverflow = 1 if overflow occurrs in the math functions called else 277 it is zero. 278 279 Returns: 280 return_value = 0 (int) 281 282 Global Variables Used: 283 None 284 285 Local Variables Needed: 286 None 287 288 ------------------------------------------------------------------------------ 289 FUNCTION DESCRIPTION 290 291 This function performs the post-filtering on the synthesized speech. The 292 post-filtering process is described as follows: 293 (1) inverse filtering of syn[] through A(z/0.7) to get res2[] 294 (2) tilt compensation filtering; 1 - MU*k*z^-1 295 (3) synthesis filtering through 1/A(z/0.75) 296 (4) adaptive gain control 297 298 ------------------------------------------------------------------------------ 299 REQUIREMENTS 300 301 None 302 303 ------------------------------------------------------------------------------ 304 REFERENCES 305 306 pstfilt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 307 308 ------------------------------------------------------------------------------ 309 PSEUDO-CODE 310 311 int Post_Filter ( 312 Post_FilterState *st, // i/o : post filter states 313 enum Mode mode, // i : AMR mode 314 Word16 *syn, // i/o : synthesis speech (postfiltered is output) 315 Word16 *Az_4 // i : interpolated LPC parameters in all subfr. 316 ) 317 { 318 *-------------------------------------------------------------------* 319 * Declaration of parameters * 320 *-------------------------------------------------------------------* 321 322 Word16 Ap3[MP1], Ap4[MP1]; // bandwidth expanded LP parameters 323 Word16 *Az; // pointer to Az_4: 324 // LPC parameters in each subframe 325 Word16 i_subfr; // index for beginning of subframe 326 Word16 h[L_H]; 327 328 Word16 i; 329 Word16 temp1, temp2; 330 Word32 L_tmp; 331 Word16 *syn_work = &st->synth_buf[M]; 332 333 334 *-----------------------------------------------------* 335 * Post filtering * 336 *-----------------------------------------------------* 337 338 Copy (syn, syn_work , L_FRAME); 339 340 Az = Az_4; 341 342 for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) 343 { 344 // Find weighted filter coefficients Ap3[] and ap[4] 345 346 if (sub(mode, MR122) == 0 || sub(mode, MR102) == 0) 347 { 348 Weight_Ai (Az, gamma3_MR122, Ap3); 349 Weight_Ai (Az, gamma4_MR122, Ap4); 350 } 351 else 352 { 353 Weight_Ai (Az, gamma3, Ap3); 354 Weight_Ai (Az, gamma4, Ap4); 355 } 356 357 // filtering of synthesis speech by A(z/0.7) to find res2[] 358 359 Residu (Ap3, &syn_work[i_subfr], st->res2, L_SUBFR); 360 361 // tilt compensation filter 362 363 // impulse response of A(z/0.7)/A(z/0.75) 364 365 Copy (Ap3, h, M + 1); 366 Set_zero (&h[M + 1], L_H - M - 1); 367 Syn_filt (Ap4, h, h, L_H, &h[M + 1], 0); 368 369 // 1st correlation of h[] 370 371 L_tmp = L_mult (h[0], h[0]); 372 for (i = 1; i < L_H; i++) 373 { 374 L_tmp = L_mac (L_tmp, h[i], h[i]); 375 } 376 temp1 = extract_h (L_tmp); 377 378 L_tmp = L_mult (h[0], h[1]); 379 for (i = 1; i < L_H - 1; i++) 380 { 381 L_tmp = L_mac (L_tmp, h[i], h[i + 1]); 382 } 383 temp2 = extract_h (L_tmp); 384 385 if (temp2 <= 0) 386 { 387 temp2 = 0; 388 } 389 else 390 { 391 temp2 = mult (temp2, MU); 392 temp2 = div_s (temp2, temp1); 393 } 394 395 preemphasis (st->preemph_state, st->res2, temp2, L_SUBFR); 396 397 // filtering through 1/A(z/0.75) 398 399 Syn_filt (Ap4, st->res2, &syn[i_subfr], L_SUBFR, st->mem_syn_pst, 1); 400 401 // scale output to input 402 403 agc (st->agc_state, &syn_work[i_subfr], &syn[i_subfr], 404 AGC_FAC, L_SUBFR); 405 406 Az += MP1; 407 } 408 409 // update syn_work[] buffer 410 411 Copy (&syn_work[L_FRAME - M], &syn_work[-M], M); 412 413 return 0; 414 } 415 416 ------------------------------------------------------------------------------ 417 RESOURCES USED [optional] 418 419 When the code is written for a specific target processor the 420 the resources used should be documented below. 421 422 HEAP MEMORY USED: x bytes 423 424 STACK MEMORY USED: x bytes 425 426 CLOCK CYCLES: (cycle count equation for this function) + (variable 427 used to represent cycle count for each subroutine 428 called) 429 where: (cycle count variable) = cycle count for [subroutine 430 name] 431 432 ------------------------------------------------------------------------------ 433 CAUTION [optional] 434 [State any special notes, constraints or cautions for users of this function] 435 436 ------------------------------------------------------------------------------ 437 */ 438 439 void Post_Filter( 440 Post_FilterState *st, /* i/o : post filter states */ 441 enum Mode mode, /* i : AMR mode */ 442 Word16 *syn, /* i/o : synthesis speech (postfiltered is output) */ 443 Word16 *Az_4, /* i : interpolated LPC parameters in all subfr. */ 444 Flag *pOverflow 445 ) 446 { 447 Word16 Ap3[MP1]; 448 Word16 Ap4[MP1]; /* bandwidth expanded LP parameters */ 449 Word16 *Az; /* pointer to Az_4: */ 450 /* LPC parameters in each subframe */ 451 register Word16 i_subfr; /* index for beginning of subframe */ 452 Word16 h[L_H]; 453 454 register Word16 i; 455 Word16 temp1; 456 Word16 temp2; 457 Word32 L_tmp; 458 Word32 L_tmp2; 459 Word16 *syn_work = &st->synth_buf[M]; 460 461 462 /*-----------------------------------------------------* 463 * Post filtering * 464 *-----------------------------------------------------*/ 465 466 Copy(syn, syn_work , L_FRAME); 467 468 Az = Az_4; 469 470 for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) 471 { 472 /* Find weighted filter coefficients Ap3[] and ap[4] */ 473 474 if (mode == MR122 || mode == MR102) 475 { 476 Weight_Ai(Az, gamma3_MR122, Ap3); 477 Weight_Ai(Az, gamma4_MR122, Ap4); 478 } 479 else 480 { 481 Weight_Ai(Az, gamma3, Ap3); 482 Weight_Ai(Az, gamma4, Ap4); 483 } 484 485 /* filtering of synthesis speech by A(z/0.7) to find res2[] */ 486 487 Residu(Ap3, &syn_work[i_subfr], st->res2, L_SUBFR); 488 489 /* tilt compensation filter */ 490 491 /* impulse response of A(z/0.7)/A(z/0.75) */ 492 493 Copy(Ap3, h, M + 1); 494 memset(&h[M + 1], 0, sizeof(Word16)*(L_H - M - 1)); 495 Syn_filt(Ap4, h, h, L_H, &h[M + 1], 0); 496 497 /* 1st correlation of h[] */ 498 499 L_tmp = 0; 500 501 for (i = L_H - 1; i >= 0; i--) 502 { 503 L_tmp2 = ((Word32) h[i]) * h[i]; 504 505 if (L_tmp2 != (Word32) 0x40000000L) 506 { 507 L_tmp2 = L_tmp2 << 1; 508 } 509 else 510 { 511 *pOverflow = 1; 512 L_tmp2 = MAX_32; 513 break; 514 } 515 516 L_tmp = L_add(L_tmp, L_tmp2, pOverflow); 517 } 518 temp1 = (Word16)(L_tmp >> 16); 519 520 L_tmp = 0; 521 522 for (i = L_H - 2; i >= 0; i--) 523 { 524 L_tmp2 = ((Word32) h[i]) * h[i + 1]; 525 526 if (L_tmp2 != (Word32) 0x40000000L) 527 { 528 L_tmp2 = L_tmp2 << 1; 529 } 530 else 531 { 532 *pOverflow = 1; 533 L_tmp2 = MAX_32; 534 break; 535 } 536 537 L_tmp = L_add(L_tmp, L_tmp2, pOverflow); 538 } 539 temp2 = (Word16)(L_tmp >> 16); 540 541 if (temp2 <= 0) 542 { 543 temp2 = 0; 544 } 545 else 546 { 547 L_tmp = (((Word32) temp2) * MU) >> 15; 548 549 /* Sign-extend product */ 550 if (L_tmp & (Word32) 0x00010000L) 551 { 552 L_tmp = L_tmp | (Word32) 0xffff0000L; 553 } 554 temp2 = (Word16) L_tmp; 555 556 temp2 = div_s(temp2, temp1); 557 } 558 559 preemphasis(&(st->preemph_state), st->res2, temp2, L_SUBFR, pOverflow); 560 561 /* filtering through 1/A(z/0.75) */ 562 563 Syn_filt(Ap4, st->res2, &syn[i_subfr], L_SUBFR, st->mem_syn_pst, 1); 564 565 /* scale output to input */ 566 567 agc(&(st->agc_state), &syn_work[i_subfr], &syn[i_subfr], 568 AGC_FAC, L_SUBFR, pOverflow); 569 570 Az += MP1; 571 } 572 573 /* update syn_work[] buffer */ 574 575 Copy(&syn_work[L_FRAME - M], &syn_work[-M], M); 576 577 return; 578 } 579