• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetSRIndex(Word32 sampleRate)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 **********************************************************************************/
atan_1000(Word32 val)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 *****************************************************************************/
BarcLineValue(Word16 noOfLines,Word16 fftLine,Word32 samplingFreq)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 *****************************************************************************/
initThrQuiet(Word16 numPb,const Word16 * pbOffset,Word16 * pbBarcVal,Word32 * pbThresholdQuiet)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 *****************************************************************************/
initSpreading(Word16 numPb,Word16 * pbBarcValue,Word16 * pbMaskLoFactor,Word16 * pbMaskHiFactor,Word16 * pbMaskLoFactorSprEn,Word16 * pbMaskHiFactorSprEn,const Word32 bitrate,const Word16 blockType)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 *****************************************************************************/
initBarcValues(Word16 numPb,const Word16 * pbOffset,Word16 numLines,Word32 samplingFrequency,Word16 * pbBval)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 *****************************************************************************/
initMinSnr(const Word32 bitrate,const Word32 samplerate,const Word16 numLines,const Word16 * sfbOffset,const Word16 * pbBarcVal,const Word16 sfbActive,Word16 * sfbMinSnr)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 *****************************************************************************/
InitPsyConfigurationLong(Word32 bitrate,Word32 samplerate,Word16 bandwidth,PSY_CONFIGURATION_LONG * psyConf)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 *****************************************************************************/
InitPsyConfigurationShort(Word32 bitrate,Word32 samplerate,Word16 bandwidth,PSY_CONFIGURATION_SHORT * psyConf)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