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