1 /* 2 ** Copyright 2003-2010, VisualOn, Inc. 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 express or implied. 13 ** See the License for the specific language governing permissions and 14 ** limitations under the License. 15 */ 16 /******************************************************************************* 17 File: psy_configuration.c 18 19 Content: Psychoaccoustic configuration functions 20 21 *******************************************************************************/ 22 23 #include "basic_op.h" 24 #include "oper_32b.h" 25 #include "psy_configuration.h" 26 #include "adj_thr.h" 27 #include "aac_rom.h" 28 29 30 31 #define BARC_SCALE 100 /* integer barc values are scaled with 100 */ 32 #define LOG2_1000 301 /* log2*1000 */ 33 #define PI2_1000 1571 /* pi/2*1000*/ 34 #define ATAN_COEF1 3560 /* 1000/0.280872f*/ 35 #define ATAN_COEF2 281 /* 1000*0.280872f*/ 36 37 38 typedef struct{ 39 Word32 sampleRate; 40 const UWord8 *paramLong; 41 const UWord8 *paramShort; 42 }SFB_INFO_TAB; 43 44 static const Word16 ABS_LEV = 20; 45 static const Word16 BARC_THR_QUIET[] = {15, 10, 7, 2, 0, 0, 0, 0, 0, 0, 46 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47 3, 5, 10, 20, 30}; 48 49 50 51 static const Word16 max_bark = 24; /* maximum bark-value */ 52 static const Word16 maskLow = 30; /* in 1dB/bark */ 53 static const Word16 maskHigh = 15; /* in 1*dB/bark */ 54 static const Word16 c_ratio = 0x0029; /* pow(10.0f, -(29.0f/10.0f)) */ 55 56 static const Word16 maskLowSprEnLong = 30; /* in 1dB/bark */ 57 static const Word16 maskHighSprEnLong = 20; /* in 1dB/bark */ 58 static const Word16 maskHighSprEnLongLowBr = 15; /* in 1dB/bark */ 59 static const Word16 maskLowSprEnShort = 20; /* in 1dB/bark */ 60 static const Word16 maskHighSprEnShort = 15; /* in 1dB/bark */ 61 static const Word16 c_minRemainingThresholdFactor = 0x0148; /* 0.01 *(1 << 15)*/ 62 static const Word32 c_maxsnr = 0x66666666; /* upper limit is -1 dB */ 63 static const Word32 c_minsnr = 0x00624dd3; /* lower limit is -25 dB */ 64 65 static const Word32 c_maxClipEnergyLong = 0x77359400; /* 2.0e9f*/ 66 static const Word32 c_maxClipEnergyShort = 0x01dcd650; /* 2.0e9f/(AACENC_TRANS_FAC*AACENC_TRANS_FAC)*/ 67 68 69 Word32 GetSRIndex(Word32 sampleRate) 70 { 71 if (92017 <= sampleRate) return 0; 72 if (75132 <= sampleRate) return 1; 73 if (55426 <= sampleRate) return 2; 74 if (46009 <= sampleRate) return 3; 75 if (37566 <= sampleRate) return 4; 76 if (27713 <= sampleRate) return 5; 77 if (23004 <= sampleRate) return 6; 78 if (18783 <= sampleRate) return 7; 79 if (13856 <= sampleRate) return 8; 80 if (11502 <= sampleRate) return 9; 81 if (9391 <= sampleRate) return 10; 82 83 return 11; 84 } 85 86 87 /********************************************************************************* 88 * 89 * function name: atan_1000 90 * description: calculates 1000*atan(x/1000) 91 * based on atan approx for x > 0 92 * atan(x) = x/((float)1.0f+(float)0.280872f*x*x) if x < 1 93 * = pi/2 - x/((float)0.280872f +x*x) if x >= 1 94 * return: 1000*atan(x/1000) 95 * 96 **********************************************************************************/ 97 static Word16 atan_1000(Word32 val) 98 { 99 Word32 y; 100 101 102 if(L_sub(val, 1000) < 0) { 103 y = extract_l(((1000 * val) / (1000 + ((val * val) / ATAN_COEF1)))); 104 } 105 else { 106 y = PI2_1000 - ((1000 * val) / (ATAN_COEF2 + ((val * val) / 1000))); 107 } 108 109 return extract_l(y); 110 } 111 112 113 /***************************************************************************** 114 * 115 * function name: BarcLineValue 116 * description: Calculates barc value for one frequency line 117 * returns: barc value of line * BARC_SCALE 118 * input: number of lines in transform, index of line to check, Fs 119 * output: 120 * 121 *****************************************************************************/ 122 static Word16 BarcLineValue(Word16 noOfLines, Word16 fftLine, Word32 samplingFreq) 123 { 124 Word32 center_freq, temp, bvalFFTLine; 125 126 /* center frequency of fft line */ 127 center_freq = (fftLine * samplingFreq) / (noOfLines << 1); 128 temp = atan_1000((center_freq << 2) / (3*10)); 129 bvalFFTLine = 130 (26600 * atan_1000((center_freq*76) / 100) + 7*temp*temp) / (2*1000*1000 / BARC_SCALE); 131 132 return saturate(bvalFFTLine); 133 } 134 135 /***************************************************************************** 136 * 137 * function name: initThrQuiet 138 * description: init thredhold in quiet 139 * 140 *****************************************************************************/ 141 static void initThrQuiet(Word16 numPb, 142 const Word16 *pbOffset, 143 Word16 *pbBarcVal, 144 Word32 *pbThresholdQuiet) { 145 Word16 i; 146 Word16 barcThrQuiet; 147 148 for(i=0; i<numPb; i++) { 149 Word16 bv1, bv2; 150 151 152 if (i>0) 153 bv1 = (pbBarcVal[i] + pbBarcVal[i-1]) >> 1; 154 else 155 bv1 = pbBarcVal[i] >> 1; 156 157 158 if (i < (numPb - 1)) 159 bv2 = (pbBarcVal[i] + pbBarcVal[i+1]) >> 1; 160 else { 161 bv2 = pbBarcVal[i]; 162 } 163 164 bv1 = min((bv1 / BARC_SCALE), max_bark); 165 bv2 = min((bv2 / BARC_SCALE), max_bark); 166 167 barcThrQuiet = min(BARC_THR_QUIET[bv1], BARC_THR_QUIET[bv2]); 168 169 170 /* 171 we calculate 172 pow(10.0f,(float)(barcThrQuiet - ABS_LEV)*0.1)*(float)ABS_LOW*(pbOffset[i+1] - pbOffset[i]); 173 */ 174 175 pbThresholdQuiet[i] = pow2_xy((((barcThrQuiet - ABS_LEV) * 100) + 176 LOG2_1000*(14+2*LOG_NORM_PCM)), LOG2_1000) * (pbOffset[i+1] - pbOffset[i]); 177 } 178 } 179 180 181 /***************************************************************************** 182 * 183 * function name: initSpreading 184 * description: init energy spreading parameter 185 * 186 *****************************************************************************/ 187 static void initSpreading(Word16 numPb, 188 Word16 *pbBarcValue, 189 Word16 *pbMaskLoFactor, 190 Word16 *pbMaskHiFactor, 191 Word16 *pbMaskLoFactorSprEn, 192 Word16 *pbMaskHiFactorSprEn, 193 const Word32 bitrate, 194 const Word16 blockType) 195 { 196 Word16 i; 197 Word16 maskLowSprEn, maskHighSprEn; 198 199 200 if (sub(blockType, SHORT_WINDOW) != 0) { 201 maskLowSprEn = maskLowSprEnLong; 202 203 if (bitrate > 22000) 204 maskHighSprEn = maskHighSprEnLong; 205 else 206 maskHighSprEn = maskHighSprEnLongLowBr; 207 } 208 else { 209 maskLowSprEn = maskLowSprEnShort; 210 maskHighSprEn = maskHighSprEnShort; 211 } 212 213 for(i=0; i<numPb; i++) { 214 215 if (i > 0) { 216 Word32 dbVal; 217 Word16 dbark = pbBarcValue[i] - pbBarcValue[i-1]; 218 219 /* 220 we calulate pow(10.0f, -0.1*dbVal/BARC_SCALE) 221 */ 222 dbVal = (maskHigh * dbark); 223 pbMaskHiFactor[i] = round16(pow2_xy(L_negate(dbVal), (Word32)LOG2_1000)); /* 0.301 log10(2) */ 224 225 dbVal = (maskLow * dbark); 226 pbMaskLoFactor[i-1] = round16(pow2_xy(L_negate(dbVal),(Word32)LOG2_1000)); 227 228 229 dbVal = (maskHighSprEn * dbark); 230 pbMaskHiFactorSprEn[i] = round16(pow2_xy(L_negate(dbVal),(Word32)LOG2_1000)); 231 dbVal = (maskLowSprEn * dbark); 232 pbMaskLoFactorSprEn[i-1] = round16(pow2_xy(L_negate(dbVal),(Word32)LOG2_1000)); 233 } 234 else { 235 pbMaskHiFactor[i] = 0; 236 pbMaskLoFactor[numPb-1] = 0; 237 238 pbMaskHiFactorSprEn[i] = 0; 239 pbMaskLoFactorSprEn[numPb-1] = 0; 240 } 241 } 242 243 } 244 245 246 /***************************************************************************** 247 * 248 * function name: initBarcValues 249 * description: init bark value 250 * 251 *****************************************************************************/ 252 static void initBarcValues(Word16 numPb, 253 const Word16 *pbOffset, 254 Word16 numLines, 255 Word32 samplingFrequency, 256 Word16 *pbBval) 257 { 258 Word16 i; 259 Word16 pbBval0, pbBval1; 260 261 pbBval0 = 0; 262 263 for(i=0; i<numPb; i++){ 264 pbBval1 = BarcLineValue(numLines, pbOffset[i+1], samplingFrequency); 265 pbBval[i] = (pbBval0 + pbBval1) >> 1; 266 pbBval0 = pbBval1; 267 } 268 } 269 270 271 /***************************************************************************** 272 * 273 * function name: initMinSnr 274 * description: calculate min snr parameter 275 * minSnr(n) = 1/(2^sfbPemin(n)/w(n) - 1.5) 276 * 277 *****************************************************************************/ 278 static void initMinSnr(const Word32 bitrate, 279 const Word32 samplerate, 280 const Word16 numLines, 281 const Word16 *sfbOffset, 282 const Word16 *pbBarcVal, 283 const Word16 sfbActive, 284 Word16 *sfbMinSnr) 285 { 286 Word16 sfb; 287 Word16 barcWidth; 288 Word16 pePerWindow; 289 Word32 pePart; 290 Word32 snr; 291 Word16 pbVal0, pbVal1, shift; 292 293 /* relative number of active barks */ 294 295 296 pePerWindow = bits2pe(extract_l((bitrate * numLines) / samplerate)); 297 298 pbVal0 = 0; 299 300 for (sfb=0; sfb<sfbActive; sfb++) { 301 302 pbVal1 = (pbBarcVal[sfb] << 1) - pbVal0; 303 barcWidth = pbVal1 - pbVal0; 304 pbVal0 = pbVal1; 305 306 /* allow at least 2.4% of pe for each active barc */ 307 pePart = ((pePerWindow * 24) * (max_bark * barcWidth)) / 308 (pbBarcVal[sfbActive-1] * (sfbOffset[sfb+1] - sfbOffset[sfb])); 309 310 311 pePart = min(pePart, 8400); 312 pePart = max(pePart, 1400); 313 314 /* minSnr(n) = 1/(2^sfbPemin(n)/w(n) - 1.5)*/ 315 /* we add an offset of 2^16 to the pow functions */ 316 /* 0xc000 = 1.5*(1 << 15)*/ 317 318 snr = pow2_xy((pePart - 16*1000),1000) - 0x0000c000; 319 320 if(snr > 0x00008000) 321 { 322 shift = norm_l(snr); 323 snr = Div_32(0x00008000 << shift, snr << shift); 324 } 325 else 326 { 327 snr = 0x7fffffff; 328 } 329 330 /* upper limit is -1 dB */ 331 snr = min(snr, c_maxsnr); 332 /* lower limit is -25 dB */ 333 snr = max(snr, c_minsnr); 334 sfbMinSnr[sfb] = round16(snr); 335 } 336 337 } 338 339 /***************************************************************************** 340 * 341 * function name: InitPsyConfigurationLong 342 * description: init long block psychoacoustic configuration 343 * 344 *****************************************************************************/ 345 Word16 InitPsyConfigurationLong(Word32 bitrate, 346 Word32 samplerate, 347 Word16 bandwidth, 348 PSY_CONFIGURATION_LONG *psyConf) 349 { 350 Word32 samplerateindex; 351 Word16 sfbBarcVal[MAX_SFB_LONG]; 352 Word16 sfb; 353 354 /* 355 init sfb table 356 */ 357 samplerateindex = GetSRIndex(samplerate); 358 psyConf->sfbCnt = sfBandTotalLong[samplerateindex]; 359 psyConf->sfbOffset = sfBandTabLong + sfBandTabLongOffset[samplerateindex]; 360 psyConf->sampRateIdx = samplerateindex; 361 362 /* 363 calculate barc values for each pb 364 */ 365 initBarcValues(psyConf->sfbCnt, 366 psyConf->sfbOffset, 367 psyConf->sfbOffset[psyConf->sfbCnt], 368 samplerate, 369 sfbBarcVal); 370 371 /* 372 init thresholds in quiet 373 */ 374 initThrQuiet(psyConf->sfbCnt, 375 psyConf->sfbOffset, 376 sfbBarcVal, 377 psyConf->sfbThresholdQuiet); 378 379 /* 380 calculate spreading function 381 */ 382 initSpreading(psyConf->sfbCnt, 383 sfbBarcVal, 384 psyConf->sfbMaskLowFactor, 385 psyConf->sfbMaskHighFactor, 386 psyConf->sfbMaskLowFactorSprEn, 387 psyConf->sfbMaskHighFactorSprEn, 388 bitrate, 389 LONG_WINDOW); 390 391 /* 392 init ratio 393 */ 394 psyConf->ratio = c_ratio; 395 396 psyConf->maxAllowedIncreaseFactor = 2; 397 psyConf->minRemainingThresholdFactor = c_minRemainingThresholdFactor; /* 0.01 *(1 << 15)*/ 398 399 psyConf->clipEnergy = c_maxClipEnergyLong; 400 psyConf->lowpassLine = extract_l((bandwidth<<1) * FRAME_LEN_LONG / samplerate); 401 402 for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) { 403 if (sub(psyConf->sfbOffset[sfb], psyConf->lowpassLine) >= 0) 404 break; 405 } 406 psyConf->sfbActive = sfb; 407 408 /* 409 calculate minSnr 410 */ 411 initMinSnr(bitrate, 412 samplerate, 413 psyConf->sfbOffset[psyConf->sfbCnt], 414 psyConf->sfbOffset, 415 sfbBarcVal, 416 psyConf->sfbActive, 417 psyConf->sfbMinSnr); 418 419 420 return(0); 421 } 422 423 /***************************************************************************** 424 * 425 * function name: InitPsyConfigurationShort 426 * description: init short block psychoacoustic configuration 427 * 428 *****************************************************************************/ 429 Word16 InitPsyConfigurationShort(Word32 bitrate, 430 Word32 samplerate, 431 Word16 bandwidth, 432 PSY_CONFIGURATION_SHORT *psyConf) 433 { 434 Word32 samplerateindex; 435 Word16 sfbBarcVal[MAX_SFB_SHORT]; 436 Word16 sfb; 437 /* 438 init sfb table 439 */ 440 samplerateindex = GetSRIndex(samplerate); 441 psyConf->sfbCnt = sfBandTotalShort[samplerateindex]; 442 psyConf->sfbOffset = sfBandTabShort + sfBandTabShortOffset[samplerateindex]; 443 psyConf->sampRateIdx = samplerateindex; 444 /* 445 calculate barc values for each pb 446 */ 447 initBarcValues(psyConf->sfbCnt, 448 psyConf->sfbOffset, 449 psyConf->sfbOffset[psyConf->sfbCnt], 450 samplerate, 451 sfbBarcVal); 452 453 /* 454 init thresholds in quiet 455 */ 456 initThrQuiet(psyConf->sfbCnt, 457 psyConf->sfbOffset, 458 sfbBarcVal, 459 psyConf->sfbThresholdQuiet); 460 461 /* 462 calculate spreading function 463 */ 464 initSpreading(psyConf->sfbCnt, 465 sfbBarcVal, 466 psyConf->sfbMaskLowFactor, 467 psyConf->sfbMaskHighFactor, 468 psyConf->sfbMaskLowFactorSprEn, 469 psyConf->sfbMaskHighFactorSprEn, 470 bitrate, 471 SHORT_WINDOW); 472 473 /* 474 init ratio 475 */ 476 psyConf->ratio = c_ratio; 477 478 psyConf->maxAllowedIncreaseFactor = 2; 479 psyConf->minRemainingThresholdFactor = c_minRemainingThresholdFactor; 480 481 psyConf->clipEnergy = c_maxClipEnergyShort; 482 483 psyConf->lowpassLine = extract_l(((bandwidth << 1) * FRAME_LEN_SHORT) / samplerate); 484 485 for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) { 486 487 if (psyConf->sfbOffset[sfb] >= psyConf->lowpassLine) 488 break; 489 } 490 psyConf->sfbActive = sfb; 491 492 /* 493 calculate minSnr 494 */ 495 initMinSnr(bitrate, 496 samplerate, 497 psyConf->sfbOffset[psyConf->sfbCnt], 498 psyConf->sfbOffset, 499 sfbBarcVal, 500 psyConf->sfbActive, 501 psyConf->sfbMinSnr); 502 503 return(0); 504 } 505 506