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 38typedef struct{ 39 Word32 sampleRate; 40 const UWord8 *paramLong; 41 const UWord8 *paramShort; 42}SFB_INFO_TAB; 43 44static const Word16 ABS_LEV = 20; 45static 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 51static const Word16 max_bark = 24; /* maximum bark-value */ 52static const Word16 maskLow = 30; /* in 1dB/bark */ 53static const Word16 maskHigh = 15; /* in 1*dB/bark */ 54static const Word16 c_ratio = 0x0029; /* pow(10.0f, -(29.0f/10.0f)) */ 55 56static const Word16 maskLowSprEnLong = 30; /* in 1dB/bark */ 57static const Word16 maskHighSprEnLong = 20; /* in 1dB/bark */ 58static const Word16 maskHighSprEnLongLowBr = 15; /* in 1dB/bark */ 59static const Word16 maskLowSprEnShort = 20; /* in 1dB/bark */ 60static const Word16 maskHighSprEnShort = 15; /* in 1dB/bark */ 61static const Word16 c_minRemainingThresholdFactor = 0x0148; /* 0.01 *(1 << 15)*/ 62static const Word32 c_maxsnr = 0x66666666; /* upper limit is -1 dB */ 63static const Word32 c_minsnr = 0x00624dd3; /* lower limit is -25 dB */ 64 65static const Word32 c_maxClipEnergyLong = 0x77359400; /* 2.0e9f*/ 66static const Word32 c_maxClipEnergyShort = 0x01dcd650; /* 2.0e9f/(AACENC_TRANS_FAC*AACENC_TRANS_FAC)*/ 67 68 69Word32 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**********************************************************************************/ 97static 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*****************************************************************************/ 122static 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*****************************************************************************/ 141static 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*****************************************************************************/ 187static 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*****************************************************************************/ 252static 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*****************************************************************************/ 278static 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*****************************************************************************/ 345Word16 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*****************************************************************************/ 429Word16 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