1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 /* 12 * lpc_masking_model.c 13 * 14 * LPC analysis and filtering functions 15 * 16 */ 17 18 #include "lpc_masking_model.h" 19 20 #include <limits.h> /* For LLONG_MAX and LLONG_MIN. */ 21 #include "codec.h" 22 #include "entropy_coding.h" 23 #include "settings.h" 24 25 /* The conversion is implemented by the step-down algorithm */ 26 void WebRtcSpl_AToK_JSK( 27 int16_t *a16, /* Q11 */ 28 int16_t useOrder, 29 int16_t *k16 /* Q15 */ 30 ) 31 { 32 int m, k; 33 int32_t tmp32[MAX_AR_MODEL_ORDER]; 34 int32_t tmp32b; 35 int32_t tmp_inv_denum32; 36 int16_t tmp_inv_denum16; 37 38 k16[useOrder-1] = a16[useOrder] << 4; // Q11<<4 => Q15 39 40 for (m=useOrder-1; m>0; m--) { 41 // (1 - k^2) in Q30 42 tmp_inv_denum32 = 1073741823 - k16[m] * k16[m]; 43 tmp_inv_denum16 = (int16_t)(tmp_inv_denum32 >> 15); // (1 - k^2) in Q15. 44 45 for (k=1; k<=m; k++) { 46 tmp32b = (a16[k] << 16) - ((k16[m] * a16[m - k + 1]) << 1); 47 48 tmp32[k] = WebRtcSpl_DivW32W16(tmp32b, tmp_inv_denum16); //Q27/Q15 = Q12 49 } 50 51 for (k=1; k<m; k++) { 52 a16[k] = (int16_t)(tmp32[k] >> 1); // Q12>>1 => Q11 53 } 54 55 tmp32[m] = WEBRTC_SPL_SAT(4092, tmp32[m], -4092); 56 k16[m - 1] = (int16_t)(tmp32[m] << 3); // Q12<<3 => Q15 57 } 58 59 return; 60 } 61 62 63 64 65 66 int16_t WebRtcSpl_LevinsonW32_JSK( 67 int32_t *R, /* (i) Autocorrelation of length >= order+1 */ 68 int16_t *A, /* (o) A[0..order] LPC coefficients (Q11) */ 69 int16_t *K, /* (o) K[0...order-1] Reflection coefficients (Q15) */ 70 int16_t order /* (i) filter order */ 71 ) { 72 int16_t i, j; 73 int16_t R_hi[LEVINSON_MAX_ORDER+1], R_low[LEVINSON_MAX_ORDER+1]; 74 /* Aurocorr coefficients in high precision */ 75 int16_t A_hi[LEVINSON_MAX_ORDER+1], A_low[LEVINSON_MAX_ORDER+1]; 76 /* LPC coefficients in high precicion */ 77 int16_t A_upd_hi[LEVINSON_MAX_ORDER+1], A_upd_low[LEVINSON_MAX_ORDER+1]; 78 /* LPC coefficients for next iteration */ 79 int16_t K_hi, K_low; /* reflection coefficient in high precision */ 80 int16_t Alpha_hi, Alpha_low, Alpha_exp; /* Prediction gain Alpha in high precision 81 and with scale factor */ 82 int16_t tmp_hi, tmp_low; 83 int32_t temp1W32, temp2W32, temp3W32; 84 int16_t norm; 85 86 /* Normalize the autocorrelation R[0]...R[order+1] */ 87 88 norm = WebRtcSpl_NormW32(R[0]); 89 90 for (i=order;i>=0;i--) { 91 temp1W32 = R[i] << norm; 92 /* Put R in hi and low format */ 93 R_hi[i] = (int16_t)(temp1W32 >> 16); 94 R_low[i] = (int16_t)((temp1W32 - ((int32_t)R_hi[i] << 16)) >> 1); 95 } 96 97 /* K = A[1] = -R[1] / R[0] */ 98 99 temp2W32 = (R_hi[1] << 16) + (R_low[1] << 1); /* R[1] in Q31 */ 100 temp3W32 = WEBRTC_SPL_ABS_W32(temp2W32); /* abs R[1] */ 101 temp1W32 = WebRtcSpl_DivW32HiLow(temp3W32, R_hi[0], R_low[0]); /* abs(R[1])/R[0] in Q31 */ 102 /* Put back the sign on R[1] */ 103 if (temp2W32 > 0) { 104 temp1W32 = -temp1W32; 105 } 106 107 /* Put K in hi and low format */ 108 K_hi = (int16_t)(temp1W32 >> 16); 109 K_low = (int16_t)((temp1W32 - ((int32_t)K_hi << 16)) >> 1); 110 111 /* Store first reflection coefficient */ 112 K[0] = K_hi; 113 114 temp1W32 >>= 4; /* A[1] in Q27. */ 115 116 /* Put A[1] in hi and low format */ 117 A_hi[1] = (int16_t)(temp1W32 >> 16); 118 A_low[1] = (int16_t)((temp1W32 - ((int32_t)A_hi[1] << 16)) >> 1); 119 120 /* Alpha = R[0] * (1-K^2) */ 121 122 temp1W32 = (((K_hi * K_low) >> 14) + K_hi * K_hi) << 1; /* = k^2 in Q31 */ 123 124 temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); /* Guard against <0 */ 125 temp1W32 = (int32_t)0x7fffffffL - temp1W32; /* temp1W32 = (1 - K[0]*K[0]) in Q31 */ 126 127 /* Store temp1W32 = 1 - K[0]*K[0] on hi and low format */ 128 tmp_hi = (int16_t)(temp1W32 >> 16); 129 tmp_low = (int16_t)((temp1W32 - ((int32_t)tmp_hi << 16)) >> 1); 130 131 /* Calculate Alpha in Q31 */ 132 temp1W32 = (R_hi[0] * tmp_hi + ((R_hi[0] * tmp_low) >> 15) + 133 ((R_low[0] * tmp_hi) >> 15)) << 1; 134 135 /* Normalize Alpha and put it in hi and low format */ 136 137 Alpha_exp = WebRtcSpl_NormW32(temp1W32); 138 temp1W32 <<= Alpha_exp; 139 Alpha_hi = (int16_t)(temp1W32 >> 16); 140 Alpha_low = (int16_t)((temp1W32 - ((int32_t)Alpha_hi<< 16)) >> 1); 141 142 /* Perform the iterative calculations in the 143 Levinson Durbin algorithm */ 144 145 for (i=2; i<=order; i++) 146 { 147 148 /* ---- 149 \ 150 temp1W32 = R[i] + > R[j]*A[i-j] 151 / 152 ---- 153 j=1..i-1 154 */ 155 156 temp1W32 = 0; 157 158 for(j=1; j<i; j++) { 159 /* temp1W32 is in Q31 */ 160 temp1W32 += ((R_hi[j] * A_hi[i - j]) << 1) + 161 ((((R_hi[j] * A_low[i - j]) >> 15) + 162 ((R_low[j] * A_hi[i - j]) >> 15)) << 1); 163 } 164 165 temp1W32 <<= 4; 166 temp1W32 += (R_hi[i] << 16) + (R_low[i] << 1); 167 168 /* K = -temp1W32 / Alpha */ 169 temp2W32 = WEBRTC_SPL_ABS_W32(temp1W32); /* abs(temp1W32) */ 170 temp3W32 = WebRtcSpl_DivW32HiLow(temp2W32, Alpha_hi, Alpha_low); /* abs(temp1W32)/Alpha */ 171 172 /* Put the sign of temp1W32 back again */ 173 if (temp1W32 > 0) { 174 temp3W32 = -temp3W32; 175 } 176 177 /* Use the Alpha shifts from earlier to denormalize */ 178 norm = WebRtcSpl_NormW32(temp3W32); 179 if ((Alpha_exp <= norm)||(temp3W32==0)) { 180 temp3W32 <<= Alpha_exp; 181 } else { 182 if (temp3W32 > 0) 183 { 184 temp3W32 = (int32_t)0x7fffffffL; 185 } else 186 { 187 temp3W32 = (int32_t)0x80000000L; 188 } 189 } 190 191 /* Put K on hi and low format */ 192 K_hi = (int16_t)(temp3W32 >> 16); 193 K_low = (int16_t)((temp3W32 - ((int32_t)K_hi << 16)) >> 1); 194 195 /* Store Reflection coefficient in Q15 */ 196 K[i-1] = K_hi; 197 198 /* Test for unstable filter. If unstable return 0 and let the 199 user decide what to do in that case 200 */ 201 202 if ((int32_t)WEBRTC_SPL_ABS_W16(K_hi) > (int32_t)32740) { 203 return(-i); /* Unstable filter */ 204 } 205 206 /* 207 Compute updated LPC coefficient: Anew[i] 208 Anew[j]= A[j] + K*A[i-j] for j=1..i-1 209 Anew[i]= K 210 */ 211 212 for(j=1; j<i; j++) 213 { 214 temp1W32 = (A_hi[j] << 16) + (A_low[j] << 1); // temp1W32 = A[j] in Q27 215 216 temp1W32 += (K_hi * A_hi[i - j] + ((K_hi * A_low[i - j]) >> 15) + 217 ((K_low * A_hi[i - j]) >> 15)) << 1; // temp1W32 += K*A[i-j] in Q27. 218 219 /* Put Anew in hi and low format */ 220 A_upd_hi[j] = (int16_t)(temp1W32 >> 16); 221 A_upd_low[j] = (int16_t)((temp1W32 - ((int32_t)A_upd_hi[j] << 16)) >> 1); 222 } 223 224 temp3W32 >>= 4; /* temp3W32 = K in Q27 (Convert from Q31 to Q27) */ 225 226 /* Store Anew in hi and low format */ 227 A_upd_hi[i] = (int16_t)(temp3W32 >> 16); 228 A_upd_low[i] = (int16_t)((temp3W32 - ((int32_t)A_upd_hi[i] << 16)) >> 1); 229 230 /* Alpha = Alpha * (1-K^2) */ 231 232 temp1W32 = (((K_hi * K_low) >> 14) + K_hi * K_hi) << 1; /* K*K in Q31 */ 233 234 temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); /* Guard against <0 */ 235 temp1W32 = (int32_t)0x7fffffffL - temp1W32; /* 1 - K*K in Q31 */ 236 237 /* Convert 1- K^2 in hi and low format */ 238 tmp_hi = (int16_t)(temp1W32 >> 16); 239 tmp_low = (int16_t)((temp1W32 - ((int32_t)tmp_hi << 16)) >> 1); 240 241 /* Calculate Alpha = Alpha * (1-K^2) in Q31 */ 242 temp1W32 = (Alpha_hi * tmp_hi + ((Alpha_hi * tmp_low) >> 15) + 243 ((Alpha_low * tmp_hi) >> 15)) << 1; 244 245 /* Normalize Alpha and store it on hi and low format */ 246 247 norm = WebRtcSpl_NormW32(temp1W32); 248 temp1W32 <<= norm; 249 250 Alpha_hi = (int16_t)(temp1W32 >> 16); 251 Alpha_low = (int16_t)((temp1W32 - ((int32_t)Alpha_hi << 16)) >> 1); 252 253 /* Update the total nomalization of Alpha */ 254 Alpha_exp = Alpha_exp + norm; 255 256 /* Update A[] */ 257 258 for(j=1; j<=i; j++) 259 { 260 A_hi[j] =A_upd_hi[j]; 261 A_low[j] =A_upd_low[j]; 262 } 263 } 264 265 /* 266 Set A[0] to 1.0 and store the A[i] i=1...order in Q12 267 (Convert from Q27 and use rounding) 268 */ 269 270 A[0] = 2048; 271 272 for(i=1; i<=order; i++) { 273 /* temp1W32 in Q27 */ 274 temp1W32 = (A_hi[i] << 16) + (A_low[i] << 1); 275 /* Round and store upper word */ 276 A[i] = (int16_t)((temp1W32 + 32768) >> 16); 277 } 278 return(1); /* Stable filters */ 279 } 280 281 282 283 284 285 /* window */ 286 /* Matlab generation of floating point code: 287 * t = (1:256)/257; r = 1-(1-t).^.45; w = sin(r*pi).^3; w = w/sum(w); plot((1:256)/8, w); grid; 288 * for k=1:16, fprintf(1, '%.8f, ', w(k*16 + (-15:0))); fprintf(1, '\n'); end 289 * All values are multiplyed with 2^21 in fixed point code. 290 */ 291 static const int16_t kWindowAutocorr[WINLEN] = { 292 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 5, 6, 293 8, 10, 12, 14, 17, 20, 24, 28, 33, 38, 43, 49, 294 56, 63, 71, 79, 88, 98, 108, 119, 131, 143, 157, 171, 295 186, 202, 219, 237, 256, 275, 296, 318, 341, 365, 390, 416, 296 444, 472, 502, 533, 566, 600, 635, 671, 709, 748, 789, 831, 297 875, 920, 967, 1015, 1065, 1116, 1170, 1224, 1281, 1339, 1399, 1461, 298 1525, 1590, 1657, 1726, 1797, 1870, 1945, 2021, 2100, 2181, 2263, 2348, 299 2434, 2523, 2614, 2706, 2801, 2898, 2997, 3099, 3202, 3307, 3415, 3525, 300 3637, 3751, 3867, 3986, 4106, 4229, 4354, 4481, 4611, 4742, 4876, 5012, 301 5150, 5291, 5433, 5578, 5725, 5874, 6025, 6178, 6333, 6490, 6650, 6811, 302 6974, 7140, 7307, 7476, 7647, 7820, 7995, 8171, 8349, 8529, 8711, 8894, 303 9079, 9265, 9453, 9642, 9833, 10024, 10217, 10412, 10607, 10803, 11000, 11199, 304 11398, 11597, 11797, 11998, 12200, 12401, 12603, 12805, 13008, 13210, 13412, 13614, 305 13815, 14016, 14216, 14416, 14615, 14813, 15009, 15205, 15399, 15591, 15782, 15971, 306 16157, 16342, 16524, 16704, 16881, 17056, 17227, 17395, 17559, 17720, 17877, 18030, 307 18179, 18323, 18462, 18597, 18727, 18851, 18970, 19082, 19189, 19290, 19384, 19471, 308 19551, 19623, 19689, 19746, 19795, 19835, 19867, 19890, 19904, 19908, 19902, 19886, 309 19860, 19823, 19775, 19715, 19644, 19561, 19465, 19357, 19237, 19102, 18955, 18793, 310 18618, 18428, 18223, 18004, 17769, 17518, 17252, 16970, 16672, 16357, 16025, 15677, 311 15311, 14929, 14529, 14111, 13677, 13225, 12755, 12268, 11764, 11243, 10706, 10152, 312 9583, 8998, 8399, 7787, 7162, 6527, 5883, 5231, 4576, 3919, 3265, 2620, 313 1990, 1386, 825, 333 314 }; 315 316 317 /* By using a hearing threshold level in dB of -28 dB (higher value gives more noise), 318 the H_T_H (in float) can be calculated as: 319 H_T_H = pow(10.0, 0.05 * (-28.0)) = 0.039810717055350 320 In Q19, H_T_H becomes round(0.039810717055350*2^19) ~= 20872, i.e. 321 H_T_H = 20872/524288.0, and H_T_HQ19 = 20872; 322 */ 323 324 325 /* The bandwidth expansion vectors are created from: 326 kPolyVecLo=[0.900000,0.810000,0.729000,0.656100,0.590490,0.531441,0.478297,0.430467,0.387420,0.348678,0.313811,0.282430]; 327 kPolyVecHi=[0.800000,0.640000,0.512000,0.409600,0.327680,0.262144]; 328 round(kPolyVecLo*32768) 329 round(kPolyVecHi*32768) 330 */ 331 static const int16_t kPolyVecLo[12] = { 332 29491, 26542, 23888, 21499, 19349, 17414, 15673, 14106, 12695, 11425, 10283, 9255 333 }; 334 static const int16_t kPolyVecHi[6] = { 335 26214, 20972, 16777, 13422, 10737, 8590 336 }; 337 338 static __inline int32_t log2_Q8_LPC( uint32_t x ) { 339 340 int32_t zeros; 341 int16_t frac; 342 343 zeros=WebRtcSpl_NormU32(x); 344 frac = (int16_t)(((x << zeros) & 0x7FFFFFFF) >> 23); 345 346 /* log2(x) */ 347 return ((31 - zeros) << 8) + frac; 348 } 349 350 static const int16_t kMulPitchGain = -25; /* 200/256 in Q5 */ 351 static const int16_t kChngFactor = 3523; /* log10(2)*10/4*0.4/1.4=log10(2)/1.4= 0.2150 in Q14 */ 352 static const int16_t kExp2 = 11819; /* 1/log(2) */ 353 const int kShiftLowerBand = 11; /* Shift value for lower band in Q domain. */ 354 const int kShiftHigherBand = 12; /* Shift value for higher band in Q domain. */ 355 356 void WebRtcIsacfix_GetVars(const int16_t *input, const int16_t *pitchGains_Q12, 357 uint32_t *oldEnergy, int16_t *varscale) 358 { 359 int k; 360 uint32_t nrgQ[4]; 361 int16_t nrgQlog[4]; 362 int16_t tmp16, chng1, chng2, chng3, chng4, tmp, chngQ, oldNrgQlog, pgQ, pg3; 363 int32_t expPg32; 364 int16_t expPg, divVal; 365 int16_t tmp16_1, tmp16_2; 366 367 /* Calculate energies of first and second frame halfs */ 368 nrgQ[0]=0; 369 for (k = QLOOKAHEAD/2; k < (FRAMESAMPLES/4 + QLOOKAHEAD) / 2; k++) { 370 nrgQ[0] += (uint32_t)(input[k] * input[k]); 371 } 372 nrgQ[1]=0; 373 for ( ; k < (FRAMESAMPLES/2 + QLOOKAHEAD) / 2; k++) { 374 nrgQ[1] += (uint32_t)(input[k] * input[k]); 375 } 376 nrgQ[2]=0; 377 for ( ; k < (FRAMESAMPLES * 3 / 4 + QLOOKAHEAD) / 2; k++) { 378 nrgQ[2] += (uint32_t)(input[k] * input[k]); 379 } 380 nrgQ[3]=0; 381 for ( ; k < (FRAMESAMPLES + QLOOKAHEAD) / 2; k++) { 382 nrgQ[3] += (uint32_t)(input[k] * input[k]); 383 } 384 385 for ( k=0; k<4; k++) { 386 nrgQlog[k] = (int16_t)log2_Q8_LPC(nrgQ[k]); /* log2(nrgQ) */ 387 } 388 oldNrgQlog = (int16_t)log2_Q8_LPC(*oldEnergy); 389 390 /* Calculate average level change */ 391 chng1 = WEBRTC_SPL_ABS_W16(nrgQlog[3]-nrgQlog[2]); 392 chng2 = WEBRTC_SPL_ABS_W16(nrgQlog[2]-nrgQlog[1]); 393 chng3 = WEBRTC_SPL_ABS_W16(nrgQlog[1]-nrgQlog[0]); 394 chng4 = WEBRTC_SPL_ABS_W16(nrgQlog[0]-oldNrgQlog); 395 tmp = chng1+chng2+chng3+chng4; 396 chngQ = (int16_t)(tmp * kChngFactor >> 10); /* Q12 */ 397 chngQ += 2926; /* + 1.0/1.4 in Q12 */ 398 399 /* Find average pitch gain */ 400 pgQ = 0; 401 for (k=0; k<4; k++) 402 { 403 pgQ += pitchGains_Q12[k]; 404 } 405 406 pg3 = (int16_t)(pgQ * pgQ >> 11); // pgQ in Q(12+2)=Q14. Q14*Q14>>11 => Q17 407 pg3 = (int16_t)(pgQ * pg3 >> 13); /* Q14*Q17>>13 =>Q18 */ 408 /* kMulPitchGain = -25 = -200 in Q-3. */ 409 pg3 = (int16_t)(pg3 * kMulPitchGain >> 5); // Q10 410 tmp16=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(kExp2,pg3,13);/* Q13*Q10>>13 => Q10*/ 411 if (tmp16<0) { 412 tmp16_2 = (0x0400 | (tmp16 & 0x03FF)); 413 tmp16_1 = ((uint16_t)(tmp16 ^ 0xFFFF) >> 10) - 3; /* Gives result in Q14 */ 414 if (tmp16_1<0) 415 expPg = -(tmp16_2 << -tmp16_1); 416 else 417 expPg = -(tmp16_2 >> tmp16_1); 418 } else 419 expPg = (int16_t) -16384; /* 1 in Q14, since 2^0=1 */ 420 421 expPg32 = (int32_t)expPg << 8; /* Q22 */ 422 divVal = WebRtcSpl_DivW32W16ResW16(expPg32, chngQ); /* Q22/Q12=Q10 */ 423 424 tmp16=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(kExp2,divVal,13);/* Q13*Q10>>13 => Q10*/ 425 if (tmp16<0) { 426 tmp16_2 = (0x0400 | (tmp16 & 0x03FF)); 427 tmp16_1 = ((uint16_t)(tmp16 ^ 0xFFFF) >> 10) - 3; /* Gives result in Q14 */ 428 if (tmp16_1<0) 429 expPg = tmp16_2 << -tmp16_1; 430 else 431 expPg = tmp16_2 >> tmp16_1; 432 } else 433 expPg = (int16_t) 16384; /* 1 in Q14, since 2^0=1 */ 434 435 *varscale = expPg-1; 436 *oldEnergy = nrgQ[3]; 437 } 438 439 440 441 static __inline int16_t exp2_Q10_T(int16_t x) { // Both in and out in Q10 442 443 int16_t tmp16_1, tmp16_2; 444 445 tmp16_2=(int16_t)(0x0400|(x&0x03FF)); 446 tmp16_1 = -(x >> 10); 447 if(tmp16_1>0) 448 return tmp16_2 >> tmp16_1; 449 else 450 return tmp16_2 << -tmp16_1; 451 452 } 453 454 455 // Declare function pointers. 456 AutocorrFix WebRtcIsacfix_AutocorrFix; 457 CalculateResidualEnergy WebRtcIsacfix_CalculateResidualEnergy; 458 459 /* This routine calculates the residual energy for LPC. 460 * Formula as shown in comments inside. 461 */ 462 int32_t WebRtcIsacfix_CalculateResidualEnergyC(int lpc_order, 463 int32_t q_val_corr, 464 int q_val_polynomial, 465 int16_t* a_polynomial, 466 int32_t* corr_coeffs, 467 int* q_val_residual_energy) { 468 int i = 0, j = 0; 469 int shift_internal = 0, shift_norm = 0; 470 int32_t tmp32 = 0, word32_high = 0, word32_low = 0, residual_energy = 0; 471 int64_t sum64 = 0, sum64_tmp = 0; 472 473 for (i = 0; i <= lpc_order; i++) { 474 for (j = i; j <= lpc_order; j++) { 475 /* For the case of i == 0: residual_energy += 476 * a_polynomial[j] * corr_coeffs[i] * a_polynomial[j - i]; 477 * For the case of i != 0: residual_energy += 478 * a_polynomial[j] * corr_coeffs[i] * a_polynomial[j - i] * 2; 479 */ 480 481 tmp32 = a_polynomial[j] * a_polynomial[j - i]; 482 /* tmp32 in Q(q_val_polynomial * 2). */ 483 if (i != 0) { 484 tmp32 <<= 1; 485 } 486 sum64_tmp = (int64_t)tmp32 * (int64_t)corr_coeffs[i]; 487 sum64_tmp >>= shift_internal; 488 489 /* Test overflow and sum the result. */ 490 if(((sum64_tmp > 0 && sum64 > 0) && (LLONG_MAX - sum64 < sum64_tmp)) || 491 ((sum64_tmp < 0 && sum64 < 0) && (LLONG_MIN - sum64 > sum64_tmp))) { 492 /* Shift right for overflow. */ 493 shift_internal += 1; 494 sum64 >>= 1; 495 sum64 += sum64_tmp >> 1; 496 } else { 497 sum64 += sum64_tmp; 498 } 499 } 500 } 501 502 word32_high = (int32_t)(sum64 >> 32); 503 word32_low = (int32_t)sum64; 504 505 // Calculate the value of shifting (shift_norm) for the 64-bit sum. 506 if(word32_high != 0) { 507 shift_norm = 32 - WebRtcSpl_NormW32(word32_high); 508 residual_energy = (int32_t)(sum64 >> shift_norm); 509 } else { 510 if((word32_low & 0x80000000) != 0) { 511 shift_norm = 1; 512 residual_energy = (uint32_t)word32_low >> 1; 513 } else { 514 shift_norm = WebRtcSpl_NormW32(word32_low); 515 residual_energy = word32_low << shift_norm; 516 shift_norm = -shift_norm; 517 } 518 } 519 520 /* Q(q_val_polynomial * 2) * Q(q_val_corr) >> shift_internal >> shift_norm 521 * = Q(q_val_corr - shift_internal - shift_norm + q_val_polynomial * 2) 522 */ 523 *q_val_residual_energy = q_val_corr - shift_internal - shift_norm 524 + q_val_polynomial * 2; 525 526 return residual_energy; 527 } 528 529 void WebRtcIsacfix_GetLpcCoef(int16_t *inLoQ0, 530 int16_t *inHiQ0, 531 MaskFiltstr_enc *maskdata, 532 int16_t snrQ10, 533 const int16_t *pitchGains_Q12, 534 int32_t *gain_lo_hiQ17, 535 int16_t *lo_coeffQ15, 536 int16_t *hi_coeffQ15) 537 { 538 int k, n, ii; 539 int pos1, pos2; 540 int sh_lo, sh_hi, sh, ssh, shMem; 541 int16_t varscaleQ14; 542 543 int16_t tmpQQlo, tmpQQhi; 544 int32_t tmp32; 545 int16_t tmp16,tmp16b; 546 547 int16_t polyHI[ORDERHI+1]; 548 int16_t rcQ15_lo[ORDERLO], rcQ15_hi[ORDERHI]; 549 550 551 int16_t DataLoQ6[WINLEN], DataHiQ6[WINLEN]; 552 int32_t corrloQQ[ORDERLO+2]; 553 int32_t corrhiQQ[ORDERHI+1]; 554 int32_t corrlo2QQ[ORDERLO+1]; 555 int16_t scale; 556 int16_t QdomLO, QdomHI, newQdomHI, newQdomLO; 557 558 int32_t res_nrgQQ; 559 int32_t sqrt_nrg; 560 561 /* less-noise-at-low-frequencies factor */ 562 int16_t aaQ14; 563 564 /* Multiplication with 1/sqrt(12) ~= 0.28901734104046 can be done by convertion to 565 Q15, i.e. round(0.28901734104046*32768) = 9471, and use 9471/32768.0 ~= 0.289032 566 */ 567 int16_t snrq; 568 int shft; 569 570 int16_t tmp16a; 571 int32_t tmp32a, tmp32b, tmp32c; 572 573 int16_t a_LOQ11[ORDERLO+1]; 574 int16_t k_vecloQ15[ORDERLO]; 575 int16_t a_HIQ12[ORDERHI+1]; 576 int16_t k_vechiQ15[ORDERHI]; 577 578 int16_t stab; 579 580 snrq=snrQ10; 581 582 /* SNR= C * 2 ^ (D * snrq) ; C=0.289, D=0.05*log2(10)=0.166 (~=172 in Q10)*/ 583 tmp16 = (int16_t)(snrq * 172 >> 10); // Q10 584 tmp16b = exp2_Q10_T(tmp16); // Q10 585 snrq = (int16_t)(tmp16b * 285 >> 10); // Q10 586 587 /* change quallevel depending on pitch gains and level fluctuations */ 588 WebRtcIsacfix_GetVars(inLoQ0, pitchGains_Q12, &(maskdata->OldEnergy), &varscaleQ14); 589 590 /* less-noise-at-low-frequencies factor */ 591 /* Calculation of 0.35 * (0.5 + 0.5 * varscale) in fixpoint: 592 With 0.35 in Q16 (0.35 ~= 22938/65536.0 = 0.3500061) and varscaleQ14 in Q14, 593 we get Q16*Q14>>16 = Q14 594 */ 595 aaQ14 = (int16_t)((22938 * (8192 + (varscaleQ14 >> 1)) + 32768) >> 16); 596 597 /* Calculate tmp = (1.0 + aa*aa); in Q12 */ 598 tmp16 = (int16_t)(aaQ14 * aaQ14 >> 15); // Q14*Q14>>15 = Q13 599 tmpQQlo = 4096 + (tmp16 >> 1); // Q12 + Q13>>1 = Q12. 600 601 /* Calculate tmp = (1.0+aa) * (1.0+aa); */ 602 tmp16 = 8192 + (aaQ14 >> 1); // 1+a in Q13. 603 tmpQQhi = (int16_t)(tmp16 * tmp16 >> 14); // Q13*Q13>>14 = Q12 604 605 /* replace data in buffer by new look-ahead data */ 606 for (pos1 = 0; pos1 < QLOOKAHEAD; pos1++) { 607 maskdata->DataBufferLoQ0[pos1 + WINLEN - QLOOKAHEAD] = inLoQ0[pos1]; 608 } 609 610 for (k = 0; k < SUBFRAMES; k++) { 611 612 /* Update input buffer and multiply signal with window */ 613 for (pos1 = 0; pos1 < WINLEN - UPDATE/2; pos1++) { 614 maskdata->DataBufferLoQ0[pos1] = maskdata->DataBufferLoQ0[pos1 + UPDATE/2]; 615 maskdata->DataBufferHiQ0[pos1] = maskdata->DataBufferHiQ0[pos1 + UPDATE/2]; 616 DataLoQ6[pos1] = (int16_t)(maskdata->DataBufferLoQ0[pos1] * 617 kWindowAutocorr[pos1] >> 15); // Q0*Q21>>15 = Q6 618 DataHiQ6[pos1] = (int16_t)(maskdata->DataBufferHiQ0[pos1] * 619 kWindowAutocorr[pos1] >> 15); // Q0*Q21>>15 = Q6 620 } 621 pos2 = (int16_t)(k * UPDATE / 2); 622 for (n = 0; n < UPDATE/2; n++, pos1++) { 623 maskdata->DataBufferLoQ0[pos1] = inLoQ0[QLOOKAHEAD + pos2]; 624 maskdata->DataBufferHiQ0[pos1] = inHiQ0[pos2++]; 625 DataLoQ6[pos1] = (int16_t)(maskdata->DataBufferLoQ0[pos1] * 626 kWindowAutocorr[pos1] >> 15); // Q0*Q21>>15 = Q6 627 DataHiQ6[pos1] = (int16_t)(maskdata->DataBufferHiQ0[pos1] * 628 kWindowAutocorr[pos1] >> 15); // Q0*Q21>>15 = Q6 629 } 630 631 /* Get correlation coefficients */ 632 /* The highest absolute value measured inside DataLo in the test set 633 For DataHi, corresponding value was 160. 634 635 This means that it should be possible to represent the input values 636 to WebRtcSpl_AutoCorrelation() as Q6 values (since 307*2^6 = 637 19648). Of course, Q0 will also work, but due to the low energy in 638 DataLo and DataHi, the outputted autocorrelation will be more accurate 639 and mimic the floating point code better, by being in an high as possible 640 Q-domain. 641 */ 642 643 WebRtcIsacfix_AutocorrFix(corrloQQ,DataLoQ6,WINLEN, ORDERLO+1, &scale); 644 QdomLO = 12-scale; // QdomLO is the Q-domain of corrloQQ 645 sh_lo = WebRtcSpl_NormW32(corrloQQ[0]); 646 QdomLO += sh_lo; 647 for (ii=0; ii<ORDERLO+2; ii++) { 648 corrloQQ[ii] <<= sh_lo; 649 } 650 /* It is investigated whether it was possible to use 16 bits for the 651 32-bit vector corrloQQ, but it didn't work. */ 652 653 WebRtcIsacfix_AutocorrFix(corrhiQQ,DataHiQ6,WINLEN, ORDERHI, &scale); 654 655 QdomHI = 12-scale; // QdomHI is the Q-domain of corrhiQQ 656 sh_hi = WebRtcSpl_NormW32(corrhiQQ[0]); 657 QdomHI += sh_hi; 658 for (ii=0; ii<ORDERHI+1; ii++) { 659 corrhiQQ[ii] <<= sh_hi; 660 } 661 662 /* less noise for lower frequencies, by filtering/scaling autocorrelation sequences */ 663 664 /* Calculate corrlo2[0] = tmpQQlo * corrlo[0] - 2.0*tmpQQlo * corrlo[1];*/ 665 // |corrlo2QQ| in Q(QdomLO-5). 666 corrlo2QQ[0] = (WEBRTC_SPL_MUL_16_32_RSFT16(tmpQQlo, corrloQQ[0]) >> 1) - 667 (WEBRTC_SPL_MUL_16_32_RSFT16(aaQ14, corrloQQ[1]) >> 2); 668 669 /* Calculate corrlo2[n] = tmpQQlo * corrlo[n] - tmpQQlo * (corrlo[n-1] + corrlo[n+1]);*/ 670 for (n = 1; n <= ORDERLO; n++) { 671 672 tmp32 = (corrloQQ[n - 1] >> 1) + (corrloQQ[n + 1] >> 1); // Q(QdomLO-1). 673 corrlo2QQ[n] = (WEBRTC_SPL_MUL_16_32_RSFT16(tmpQQlo, corrloQQ[n]) >> 1) - 674 (WEBRTC_SPL_MUL_16_32_RSFT16(aaQ14, tmp32) >> 2); 675 } 676 QdomLO -= 5; 677 678 /* Calculate corrhi[n] = tmpQQhi * corrhi[n]; */ 679 for (n = 0; n <= ORDERHI; n++) { 680 corrhiQQ[n] = WEBRTC_SPL_MUL_16_32_RSFT16(tmpQQhi, corrhiQQ[n]); // Q(12+QdomHI-16) = Q(QdomHI-4) 681 } 682 QdomHI -= 4; 683 684 /* add white noise floor */ 685 /* corrlo2QQ is in Q(QdomLO) and corrhiQQ is in Q(QdomHI) */ 686 /* Calculate corrlo2[0] += 9.5367431640625e-7; and 687 corrhi[0] += 9.5367431640625e-7, where the constant is 1/2^20 */ 688 689 tmp32 = WEBRTC_SPL_SHIFT_W32((int32_t) 1, QdomLO-20); 690 corrlo2QQ[0] += tmp32; 691 tmp32 = WEBRTC_SPL_SHIFT_W32((int32_t) 1, QdomHI-20); 692 corrhiQQ[0] += tmp32; 693 694 /* corrlo2QQ is in Q(QdomLO) and corrhiQQ is in Q(QdomHI) before the following 695 code segment, where we want to make sure we get a 1-bit margin */ 696 for (n = 0; n <= ORDERLO; n++) { 697 corrlo2QQ[n] >>= 1; // Make sure we have a 1-bit margin. 698 } 699 QdomLO -= 1; // Now, corrlo2QQ is in Q(QdomLO), with a 1-bit margin 700 701 for (n = 0; n <= ORDERHI; n++) { 702 corrhiQQ[n] >>= 1; // Make sure we have a 1-bit margin. 703 } 704 QdomHI -= 1; // Now, corrhiQQ is in Q(QdomHI), with a 1-bit margin 705 706 707 newQdomLO = QdomLO; 708 709 for (n = 0; n <= ORDERLO; n++) { 710 int32_t tmp, tmpB, tmpCorr; 711 int16_t alpha=328; //0.01 in Q15 712 int16_t beta=324; //(1-0.01)*0.01=0.0099 in Q15 713 int16_t gamma=32440; //(1-0.01)=0.99 in Q15 714 715 if (maskdata->CorrBufLoQQ[n] != 0) { 716 shMem=WebRtcSpl_NormW32(maskdata->CorrBufLoQQ[n]); 717 sh = QdomLO - maskdata->CorrBufLoQdom[n]; 718 if (sh<=shMem) { 719 tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufLoQQ[n], sh); // Get CorrBufLoQQ to same domain as corrlo2 720 tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha, tmp); 721 } else if ((sh-shMem)<7){ 722 tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufLoQQ[n], shMem); // Shift up CorrBufLoQQ as much as possible 723 // Shift |alpha| the number of times required to get |tmp| in QdomLO. 724 tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha << (sh - shMem), tmp); 725 } else { 726 tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufLoQQ[n], shMem); // Shift up CorrBufHiQQ as much as possible 727 // Shift |alpha| as much as possible without overflow the number of 728 // times required to get |tmp| in QdomLO. 729 tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha << 6, tmp); 730 tmpCorr = corrloQQ[n] >> (sh - shMem - 6); 731 tmp = tmp + tmpCorr; 732 maskdata->CorrBufLoQQ[n] = tmp; 733 newQdomLO = QdomLO-(sh-shMem-6); 734 maskdata->CorrBufLoQdom[n] = newQdomLO; 735 } 736 } else 737 tmp = 0; 738 739 tmp = tmp + corrlo2QQ[n]; 740 741 maskdata->CorrBufLoQQ[n] = tmp; 742 maskdata->CorrBufLoQdom[n] = QdomLO; 743 744 tmp=WEBRTC_SPL_MUL_16_32_RSFT15(beta, tmp); 745 tmpB=WEBRTC_SPL_MUL_16_32_RSFT15(gamma, corrlo2QQ[n]); 746 corrlo2QQ[n] = tmp + tmpB; 747 } 748 if( newQdomLO!=QdomLO) { 749 for (n = 0; n <= ORDERLO; n++) { 750 if (maskdata->CorrBufLoQdom[n] != newQdomLO) 751 corrloQQ[n] >>= maskdata->CorrBufLoQdom[n] - newQdomLO; 752 } 753 QdomLO = newQdomLO; 754 } 755 756 757 newQdomHI = QdomHI; 758 759 for (n = 0; n <= ORDERHI; n++) { 760 int32_t tmp, tmpB, tmpCorr; 761 int16_t alpha=328; //0.01 in Q15 762 int16_t beta=324; //(1-0.01)*0.01=0.0099 in Q15 763 int16_t gamma=32440; //(1-0.01)=0.99 in Q1 764 if (maskdata->CorrBufHiQQ[n] != 0) { 765 shMem=WebRtcSpl_NormW32(maskdata->CorrBufHiQQ[n]); 766 sh = QdomHI - maskdata->CorrBufHiQdom[n]; 767 if (sh<=shMem) { 768 tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufHiQQ[n], sh); // Get CorrBufHiQQ to same domain as corrhi 769 tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha, tmp); 770 tmpCorr = corrhiQQ[n]; 771 tmp = tmp + tmpCorr; 772 maskdata->CorrBufHiQQ[n] = tmp; 773 maskdata->CorrBufHiQdom[n] = QdomHI; 774 } else if ((sh-shMem)<7) { 775 tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufHiQQ[n], shMem); // Shift up CorrBufHiQQ as much as possible 776 // Shift |alpha| the number of times required to get |tmp| in QdomHI. 777 tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha << (sh - shMem), tmp); 778 tmpCorr = corrhiQQ[n]; 779 tmp = tmp + tmpCorr; 780 maskdata->CorrBufHiQQ[n] = tmp; 781 maskdata->CorrBufHiQdom[n] = QdomHI; 782 } else { 783 tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufHiQQ[n], shMem); // Shift up CorrBufHiQQ as much as possible 784 // Shift |alpha| as much as possible without overflow the number of 785 // times required to get |tmp| in QdomHI. 786 tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha << 6, tmp); 787 tmpCorr = corrhiQQ[n] >> (sh - shMem - 6); 788 tmp = tmp + tmpCorr; 789 maskdata->CorrBufHiQQ[n] = tmp; 790 newQdomHI = QdomHI-(sh-shMem-6); 791 maskdata->CorrBufHiQdom[n] = newQdomHI; 792 } 793 } else { 794 tmp = corrhiQQ[n]; 795 tmpCorr = tmp; 796 maskdata->CorrBufHiQQ[n] = tmp; 797 maskdata->CorrBufHiQdom[n] = QdomHI; 798 } 799 800 tmp=WEBRTC_SPL_MUL_16_32_RSFT15(beta, tmp); 801 tmpB=WEBRTC_SPL_MUL_16_32_RSFT15(gamma, tmpCorr); 802 corrhiQQ[n] = tmp + tmpB; 803 } 804 805 if( newQdomHI!=QdomHI) { 806 for (n = 0; n <= ORDERHI; n++) { 807 if (maskdata->CorrBufHiQdom[n] != newQdomHI) 808 corrhiQQ[n] >>= maskdata->CorrBufHiQdom[n] - newQdomHI; 809 } 810 QdomHI = newQdomHI; 811 } 812 813 stab=WebRtcSpl_LevinsonW32_JSK(corrlo2QQ, a_LOQ11, k_vecloQ15, ORDERLO); 814 815 if (stab<0) { // If unstable use lower order 816 a_LOQ11[0]=2048; 817 for (n = 1; n <= ORDERLO; n++) { 818 a_LOQ11[n]=0; 819 } 820 821 stab=WebRtcSpl_LevinsonW32_JSK(corrlo2QQ, a_LOQ11, k_vecloQ15, 8); 822 } 823 824 825 WebRtcSpl_LevinsonDurbin(corrhiQQ, a_HIQ12, k_vechiQ15, ORDERHI); 826 827 /* bandwidth expansion */ 828 for (n = 1; n <= ORDERLO; n++) { 829 a_LOQ11[n] = (int16_t)((kPolyVecLo[n - 1] * a_LOQ11[n] + (1 << 14)) >> 830 15); 831 } 832 833 834 polyHI[0] = a_HIQ12[0]; 835 for (n = 1; n <= ORDERHI; n++) { 836 a_HIQ12[n] = (int16_t)(((int32_t)(kPolyVecHi[n - 1] * a_HIQ12[n]) + 837 (1 << 14)) >> 15); 838 polyHI[n] = a_HIQ12[n]; 839 } 840 841 /* Normalize the corrlo2 vector */ 842 sh = WebRtcSpl_NormW32(corrlo2QQ[0]); 843 for (n = 0; n <= ORDERLO; n++) { 844 corrlo2QQ[n] <<= sh; 845 } 846 QdomLO += sh; /* Now, corrlo2QQ is still in Q(QdomLO) */ 847 848 849 /* residual energy */ 850 851 sh_lo = 31; 852 res_nrgQQ = WebRtcIsacfix_CalculateResidualEnergy(ORDERLO, QdomLO, 853 kShiftLowerBand, a_LOQ11, corrlo2QQ, &sh_lo); 854 855 /* Convert to reflection coefficients */ 856 WebRtcSpl_AToK_JSK(a_LOQ11, ORDERLO, rcQ15_lo); 857 858 if (sh_lo & 0x0001) { 859 res_nrgQQ >>= 1; 860 sh_lo-=1; 861 } 862 863 864 if( res_nrgQQ > 0 ) 865 { 866 sqrt_nrg=WebRtcSpl_Sqrt(res_nrgQQ); 867 868 /* add hearing threshold and compute the gain */ 869 /* lo_coeff = varscale * S_N_R / (sqrt_nrg + varscale * H_T_H); */ 870 871 tmp32a = varscaleQ14 >> 1; // H_T_HQ19=65536 (16-17=-1) 872 ssh = sh_lo >> 1; // sqrt_nrg is in Qssh. 873 sh = ssh - 14; 874 tmp32b = WEBRTC_SPL_SHIFT_W32(tmp32a, sh); // Q14->Qssh 875 tmp32c = sqrt_nrg + tmp32b; // Qssh (denominator) 876 tmp32a = varscaleQ14 * snrq; // Q24 (numerator) 877 878 sh = WebRtcSpl_NormW32(tmp32c); 879 shft = 16 - sh; 880 tmp16a = (int16_t) WEBRTC_SPL_SHIFT_W32(tmp32c, -shft); // Q(ssh-shft) (denominator) 881 882 tmp32b = WebRtcSpl_DivW32W16(tmp32a, tmp16a); // Q(24-ssh+shft) 883 sh = ssh-shft-7; 884 *gain_lo_hiQ17 = WEBRTC_SPL_SHIFT_W32(tmp32b, sh); // Gains in Q17 885 } 886 else 887 { 888 *gain_lo_hiQ17 = 100; // Gains in Q17 889 } 890 gain_lo_hiQ17++; 891 892 /* copy coefficients to output array */ 893 for (n = 0; n < ORDERLO; n++) { 894 *lo_coeffQ15 = (int16_t) (rcQ15_lo[n]); 895 lo_coeffQ15++; 896 } 897 /* residual energy */ 898 sh_hi = 31; 899 res_nrgQQ = WebRtcIsacfix_CalculateResidualEnergy(ORDERHI, QdomHI, 900 kShiftHigherBand, a_HIQ12, corrhiQQ, &sh_hi); 901 902 /* Convert to reflection coefficients */ 903 WebRtcSpl_LpcToReflCoef(polyHI, ORDERHI, rcQ15_hi); 904 905 if (sh_hi & 0x0001) { 906 res_nrgQQ >>= 1; 907 sh_hi-=1; 908 } 909 910 911 if( res_nrgQQ > 0 ) 912 { 913 sqrt_nrg=WebRtcSpl_Sqrt(res_nrgQQ); 914 915 916 /* add hearing threshold and compute the gain */ 917 /* hi_coeff = varscale * S_N_R / (sqrt_nrg + varscale * H_T_H); */ 918 919 tmp32a = varscaleQ14 >> 1; // H_T_HQ19=65536 (16-17=-1) 920 921 ssh = sh_hi >> 1; // |sqrt_nrg| is in Qssh. 922 sh = ssh - 14; 923 tmp32b = WEBRTC_SPL_SHIFT_W32(tmp32a, sh); // Q14->Qssh 924 tmp32c = sqrt_nrg + tmp32b; // Qssh (denominator) 925 tmp32a = varscaleQ14 * snrq; // Q24 (numerator) 926 927 sh = WebRtcSpl_NormW32(tmp32c); 928 shft = 16 - sh; 929 tmp16a = (int16_t) WEBRTC_SPL_SHIFT_W32(tmp32c, -shft); // Q(ssh-shft) (denominator) 930 931 tmp32b = WebRtcSpl_DivW32W16(tmp32a, tmp16a); // Q(24-ssh+shft) 932 sh = ssh-shft-7; 933 *gain_lo_hiQ17 = WEBRTC_SPL_SHIFT_W32(tmp32b, sh); // Gains in Q17 934 } 935 else 936 { 937 *gain_lo_hiQ17 = 100; // Gains in Q17 938 } 939 gain_lo_hiQ17++; 940 941 942 /* copy coefficients to output array */ 943 for (n = 0; n < ORDERHI; n++) { 944 *hi_coeffQ15 = rcQ15_hi[n]; 945 hi_coeffQ15++; 946 } 947 } 948 } 949