psy_configuration.c revision e2e838afcf03e603a41a0455846eaf9614537c16
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                         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                           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