summaryrefslogtreecommitdiff
path: root/audio_codec/wfd_aac_decoder/sbrfreq.c (plain)
blob: 5d4b33175abb60b879a06ec7007904ddb122b728
1/* ***** BEGIN LICENSE BLOCK *****
2 * Source last modified: $Id: sbrfreq.c,v 1.2 2005/05/20 18:05:41 jrecker Exp $
3 *
4 * Portions Copyright (c) 1995-2005 RealNetworks, Inc. All Rights Reserved.
5 *
6 * The contents of this file, and the files included with this file,
7 * are subject to the current version of the RealNetworks Public
8 * Source License (the "RPSL") available at
9 * http://www.helixcommunity.org/content/rpsl unless you have licensed
10 * the file under the current version of the RealNetworks Community
11 * Source License (the "RCSL") available at
12 * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
13 * will apply. You may also obtain the license terms directly from
14 * RealNetworks. You may not use this file except in compliance with
15 * the RPSL or, if you have a valid RCSL with RealNetworks applicable
16 * to this file, the RCSL. Please see the applicable RPSL or RCSL for
17 * the rights, obligations and limitations governing use of the
18 * contents of the file.
19 *
20 * This file is part of the Helix DNA Technology. RealNetworks is the
21 * developer of the Original Code and owns the copyrights in the
22 * portions it created.
23 *
24 * This file, and the files included with this file, is distributed
25 * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
26 * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
27 * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
28 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
29 * ENJOYMENT OR NON-INFRINGEMENT.
30 *
31 * Technology Compatibility Kit Test Suite(s) Location:
32 * http://www.helixcommunity.org/content/tck
33 *
34 * Contributor(s):
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38/**************************************************************************************
39 * Fixed-point HE-AAC decoder
40 * Jon Recker (jrecker@real.com)
41 * February 2005
42 *
43 * sbrfreq.c - frequency band table calculation for SBR
44 **************************************************************************************/
45
46#include "sbr.h"
47#include "assembly.h"
48
49/**************************************************************************************
50 * Function: BubbleSort
51 *
52 * Description: in-place sort of unsigned chars
53 *
54 * Inputs: buffer of elements to sort
55 * number of elements to sort
56 *
57 * Outputs: sorted buffer
58 *
59 * Return: none
60 **************************************************************************************/
61static void BubbleSort(unsigned char *v, int nItems)
62{
63 int i;
64 unsigned char t;
65
66 while (nItems >= 2) {
67 for (i = 0; i < nItems - 1; i++) {
68 if (v[i + 1] < v[i]) {
69 t = v[i + 1];
70 v[i + 1] = v[i];
71 v[i] = t;
72 }
73 }
74 nItems--;
75 }
76}
77
78/**************************************************************************************
79 * Function: VMin
80 *
81 * Description: find smallest element in a buffer of unsigned chars
82 *
83 * Inputs: buffer of elements to search
84 * number of elements to search
85 *
86 * Outputs: none
87 *
88 * Return: smallest element in buffer
89 **************************************************************************************/
90static unsigned char VMin(unsigned char *v, int nItems)
91{
92 int i;
93 unsigned char vMin;
94
95 vMin = v[0];
96 for (i = 1; i < nItems; i++) {
97 if (v[i] < vMin) {
98 vMin = v[i];
99 }
100 }
101 return vMin;
102}
103
104/**************************************************************************************
105 * Function: VMax
106 *
107 * Description: find largest element in a buffer of unsigned chars
108 *
109 * Inputs: buffer of elements to search
110 * number of elements to search
111 *
112 * Outputs: none
113 *
114 * Return: largest element in buffer
115 **************************************************************************************/
116static unsigned char VMax(unsigned char *v, int nItems)
117{
118 int i;
119 unsigned char vMax;
120
121 vMax = v[0];
122 for (i = 1; i < nItems; i++) {
123 if (v[i] > vMax) {
124 vMax = v[i];
125 }
126 }
127 return vMax;
128}
129
130/**************************************************************************************
131 * Function: CalcFreqMasterScaleZero
132 *
133 * Description: calculate master frequency table when freqScale == 0
134 * (4.6.18.3.2.1, figure 4.39)
135 *
136 * Inputs: alterScale flag
137 * index of first QMF subband in master freq table (k0)
138 * index of last QMF subband (k2)
139 *
140 * Outputs: master frequency table
141 *
142 * Return: number of bands in master frequency table
143 *
144 * Notes: assumes k2 - k0 <= 48 and k2 >= k0 (4.6.18.3.6)
145 **************************************************************************************/
146static int CalcFreqMasterScaleZero(unsigned char *freqMaster, int alterScale, int k0, int k2)
147{
148 int nMaster, k, nBands, k2Achieved, dk, vDk[64], k2Diff;
149
150 if (alterScale) {
151 dk = 2;
152 nBands = 2 * ((k2 - k0 + 2) >> 2);
153 } else {
154 dk = 1;
155 nBands = 2 * ((k2 - k0) >> 1);
156 }
157
158 if (nBands <= 0) {
159 return 0;
160 }
161
162 k2Achieved = k0 + nBands * dk;
163 k2Diff = k2 - k2Achieved;
164 for (k = 0; k < nBands; k++) {
165 vDk[k] = dk;
166 }
167
168 if (k2Diff > 0) {
169 k = nBands - 1;
170 while (k2Diff) {
171 vDk[k]++;
172 k--;
173 k2Diff--;
174 }
175 } else if (k2Diff < 0) {
176 k = 0;
177 while (k2Diff) {
178 vDk[k]--;
179 k++;
180 k2Diff++;
181 }
182 }
183
184 nMaster = nBands;
185 freqMaster[0] = k0;
186 for (k = 1; k <= nBands; k++) {
187 freqMaster[k] = freqMaster[k - 1] + vDk[k - 1];
188 }
189
190 return nMaster;
191}
192
193/* mBandTab[i] = temp1[i] / 2 */
194static const int mBandTab[3] = {6, 5, 4};
195
196/* invWarpTab[i] = 1.0 / temp2[i], Q30 (see 4.6.18.3.2.1) */
197static const int invWarpTab[2] = {0x40000000, 0x313b13b1};
198
199/**************************************************************************************
200 * Function: CalcFreqMasterScale
201 *
202 * Description: calculate master frequency table when freqScale > 0
203 * (4.6.18.3.2.1, figure 4.39)
204 *
205 * Inputs: alterScale flag
206 * freqScale flag
207 * index of first QMF subband in master freq table (k0)
208 * index of last QMF subband (k2)
209 *
210 * Outputs: master frequency table
211 *
212 * Return: number of bands in master frequency table
213 *
214 * Notes: assumes k2 - k0 <= 48 and k2 >= k0 (4.6.18.3.6)
215 **************************************************************************************/
216static int CalcFreqMaster(unsigned char *freqMaster, int freqScale, int alterScale, int k0, int k2)
217{
218 int bands, twoRegions, k, k1, t, vLast, vCurr, pCurr;
219 int invWarp, nBands0, nBands1, change;
220 unsigned char vDk1Min, vDk0Max;
221 unsigned char *vDelta;
222
223 if (freqScale < 1 || freqScale > 3) {
224 return -1;
225 }
226
227 bands = mBandTab[freqScale - 1];
228 invWarp = invWarpTab[alterScale];
229
230 /* tested for all k0 = [5, 64], k2 = [k0, 64] */
231 if (k2 * 10000 > 22449 * k0) {
232 twoRegions = 1;
233 k1 = 2 * k0;
234 } else {
235 twoRegions = 0;
236 k1 = k2;
237 }
238
239 /* tested for all k0 = [5, 64], k1 = [k0, 64], freqScale = [1,3] */
240 t = (log2Tab[k1] - log2Tab[k0]) >> 3; /* log2(k1/k0), Q28 to Q25 */
241 nBands0 = 2 * (((bands * t) + (1 << 24)) >> 25); /* multiply by bands/2, round to nearest int (mBandTab has factor of 1/2 rolled in) */
242
243 /* tested for all valid combinations of k0, k1, nBands (from sampRate, freqScale, alterScale)
244 * roundoff error can be a problem with fixpt (e.g. pCurr = 12.499999 instead of 12.50003)
245 * because successive multiplication always undershoots a little bit, but this
246 * doesn't occur in any of the ratios we encounter from the valid k0/k1 bands in the spec
247 */
248 t = RatioPowInv(k1, k0, nBands0);
249 pCurr = k0 << 24;
250 vLast = k0;
251 vDelta = freqMaster + 1; /* operate in-place */
252 for (k = 0; k < nBands0; k++) {
253 pCurr = MULSHIFT32(pCurr, t) << 8; /* keep in Q24 */
254 vCurr = (pCurr + (1 << 23)) >> 24;
255 vDelta[k] = (vCurr - vLast);
256 vLast = vCurr;
257 }
258
259 /* sort the deltas and find max delta for first region */
260 BubbleSort(vDelta, nBands0);
261 vDk0Max = VMax(vDelta, nBands0);
262
263 /* fill master frequency table with bands from first region */
264 freqMaster[0] = k0;
265 for (k = 1; k <= nBands0; k++) {
266 freqMaster[k] += freqMaster[k - 1];
267 }
268
269 /* if only one region, then the table is complete */
270 if (!twoRegions) {
271 return nBands0;
272 }
273
274 /* tested for all k1 = [10, 64], k2 = [k0, 64], freqScale = [1,3] */
275 t = (log2Tab[k2] - log2Tab[k1]) >> 3; /* log2(k1/k0), Q28 to Q25 */
276 t = MULSHIFT32(bands * t, invWarp) << 2; /* multiply by bands/2, divide by warp factor, keep Q25 */
277 nBands1 = 2 * ((t + (1 << 24)) >> 25); /* round to nearest int */
278
279 /* see comments above for calculations in first region */
280 t = RatioPowInv(k2, k1, nBands1);
281 pCurr = k1 << 24;
282 vLast = k1;
283 vDelta = freqMaster + nBands0 + 1; /* operate in-place */
284 for (k = 0; k < nBands1; k++) {
285 pCurr = MULSHIFT32(pCurr, t) << 8; /* keep in Q24 */
286 vCurr = (pCurr + (1 << 23)) >> 24;
287 vDelta[k] = (vCurr - vLast);
288 vLast = vCurr;
289 }
290
291 /* sort the deltas, adjusting first and last if the second region has smaller deltas than the first */
292 vDk1Min = VMin(vDelta, nBands1);
293 if (vDk1Min < vDk0Max) {
294 BubbleSort(vDelta, nBands1);
295 change = vDk0Max - vDelta[0];
296 if (change > ((vDelta[nBands1 - 1] - vDelta[0]) >> 1)) {
297 change = ((vDelta[nBands1 - 1] - vDelta[0]) >> 1);
298 }
299 vDelta[0] += change;
300 vDelta[nBands1 - 1] -= change;
301 }
302 BubbleSort(vDelta, nBands1);
303
304 /* fill master frequency table with bands from second region
305 * Note: freqMaster[nBands0] = k1
306 */
307 for (k = 1; k <= nBands1; k++) {
308 freqMaster[k + nBands0] += freqMaster[k + nBands0 - 1];
309 }
310
311 return (nBands0 + nBands1);
312}
313
314/**************************************************************************************
315 * Function: CalcFreqHigh
316 *
317 * Description: calculate high resolution frequency table (4.6.18.3.2.2)
318 *
319 * Inputs: master frequency table
320 * number of bands in master frequency table
321 * crossover band from header
322 *
323 * Outputs: high resolution frequency table
324 *
325 * Return: number of bands in high resolution frequency table
326 **************************************************************************************/
327static int CalcFreqHigh(unsigned char *freqHigh, unsigned char *freqMaster, int nMaster, int crossOverBand)
328{
329 int k, nHigh;
330
331 nHigh = nMaster - crossOverBand;
332
333 for (k = 0; k <= nHigh; k++) {
334 freqHigh[k] = freqMaster[k + crossOverBand];
335 }
336
337 return nHigh;
338}
339
340/**************************************************************************************
341 * Function: CalcFreqLow
342 *
343 * Description: calculate low resolution frequency table (4.6.18.3.2.2)
344 *
345 * Inputs: high resolution frequency table
346 * number of bands in high resolution frequency table
347 *
348 * Outputs: low resolution frequency table
349 *
350 * Return: number of bands in low resolution frequency table
351 **************************************************************************************/
352static int CalcFreqLow(unsigned char *freqLow, unsigned char *freqHigh, int nHigh)
353{
354 int k, nLow, oddFlag;
355
356 nLow = nHigh - (nHigh >> 1);
357 freqLow[0] = freqHigh[0];
358 oddFlag = nHigh & 0x01;
359
360 for (k = 1; k <= nLow; k++) {
361 freqLow[k] = freqHigh[2 * k - oddFlag];
362 }
363
364 return nLow;
365}
366
367/**************************************************************************************
368 * Function: CalcFreqNoise
369 *
370 * Description: calculate noise floor frequency table (4.6.18.3.2.2)
371 *
372 * Inputs: low resolution frequency table
373 * number of bands in low resolution frequency table
374 * index of starting QMF subband for SBR (kStart)
375 * index of last QMF subband (k2)
376 * number of noise bands
377 *
378 * Outputs: noise floor frequency table
379 *
380 * Return: number of bands in noise floor frequency table
381 **************************************************************************************/
382static int CalcFreqNoise(unsigned char *freqNoise, unsigned char *freqLow, int nLow, int kStart, int k2, int noiseBands, int *err)
383{
384 int i, iLast, k, nQ, lTop, lBottom;
385
386 lTop = log2Tab[k2];
387 lBottom = log2Tab[kStart];
388 nQ = noiseBands * ((lTop - lBottom) >> 2); /* Q28 to Q26, noiseBands = [0,3] */
389 nQ = (nQ + (1 << 25)) >> 26;
390 if (nQ < 1) {
391 nQ = 1;
392 }
393
394 if (!(nQ <= MAX_NUM_NOISE_FLOOR_BANDS)) { /* required from 4.6.18.3.6 */
395 *err = ERR_AAC_SPEC_NOT_MATCH;
396 return ERR_AAC_SPEC_NOT_MATCH;
397 }
398
399 iLast = 0;
400 freqNoise[0] = freqLow[0];
401 for (k = 1; k <= nQ; k++) {
402 i = iLast + (nLow - iLast) / (nQ + 1 - k); /* truncating division */
403 freqNoise[k] = freqLow[i];
404 iLast = i;
405 }
406
407 return nQ;
408}
409
410/**************************************************************************************
411 * Function: BuildPatches
412 *
413 * Description: build high frequency patches (4.6.18.6.3)
414 *
415 * Inputs: master frequency table
416 * number of bands in low resolution frequency table
417 * index of first QMF subband in master freq table (k0)
418 * index of starting QMF subband for SBR (kStart)
419 * number of QMF bands in high resolution frequency table
420 * sample rate index
421 *
422 * Outputs: starting subband for each patch
423 * number of subbands in each patch
424 *
425 * Return: number of patches
426 **************************************************************************************/
427static int BuildPatches(unsigned char *patchNumSubbands, unsigned char *patchStartSubband, unsigned char *freqMaster,
428 int nMaster, int k0, int kStart, int numQMFBands, int sampRateIdx)
429{
430 int i, j, k;
431 int msb, sb, usb, numPatches, goalSB, oddFlag;
432
433 msb = k0;
434 usb = kStart;
435 numPatches = 0;
436 goalSB = goalSBTab[sampRateIdx];
437
438 if (nMaster == 0) {
439 patchNumSubbands[0] = 0;
440 patchStartSubband[0] = 0;
441 return 0;
442 }
443
444 if (goalSB < kStart + numQMFBands) {
445 k = 0;
446 for (i = 0; freqMaster[i] < goalSB; i++) {
447 k = i + 1;
448 }
449 } else {
450 k = nMaster;
451 }
452
453 do {
454 j = k + 1;
455 do {
456 j--;
457 sb = freqMaster[j];
458 oddFlag = (sb - 2 + k0) & 0x01;
459 } while (sb > k0 - 1 + msb - oddFlag);
460
461 patchNumSubbands[numPatches] = MAX(sb - usb, 0);
462 patchStartSubband[numPatches] = k0 - oddFlag - patchNumSubbands[numPatches];
463
464 /* from MPEG reference code - slightly different from spec */
465 if ((patchNumSubbands[numPatches] < 3) && (numPatches > 0)) {
466 break;
467 }
468
469 if (patchNumSubbands[numPatches] > 0) {
470 usb = sb;
471 msb = sb;
472 numPatches++;
473 } else {
474 msb = kStart;
475 }
476
477 if (freqMaster[k] - sb < 3) {
478 k = nMaster;
479 }
480
481 } while (sb != (kStart + numQMFBands) && numPatches <= MAX_NUM_PATCHES);
482
483 return numPatches;
484}
485
486/**************************************************************************************
487 * Function: FindFreq
488 *
489 * Description: search buffer of unsigned chars for a specific value
490 *
491 * Inputs: buffer of elements to search
492 * number of elements to search
493 * value to search for
494 *
495 * Outputs: none
496 *
497 * Return: non-zero if the value is found anywhere in the buffer, zero otherwise
498 **************************************************************************************/
499static int FindFreq(unsigned char *freq, int nFreq, unsigned char val)
500{
501 int k;
502
503 for (k = 0; k < nFreq; k++) {
504 if (freq[k] == val) {
505 return 1;
506 }
507 }
508
509 return 0;
510}
511
512/**************************************************************************************
513 * Function: RemoveFreq
514 *
515 * Description: remove one element from a buffer of unsigned chars
516 *
517 * Inputs: buffer of elements
518 * number of elements
519 * index of element to remove
520 *
521 * Outputs: new buffer of length nFreq-1
522 *
523 * Return: none
524 **************************************************************************************/
525static void RemoveFreq(unsigned char *freq, int nFreq, int removeIdx)
526{
527 int k;
528
529 if (removeIdx >= nFreq) {
530 return;
531 }
532
533 for (k = removeIdx; k < nFreq - 1; k++) {
534 freq[k] = freq[k + 1];
535 }
536}
537
538/**************************************************************************************
539 * Function: CalcFreqLimiter
540 *
541 * Description: calculate limiter frequency table (4.6.18.3.2.3)
542 *
543 * Inputs: number of subbands in each patch
544 * low resolution frequency table
545 * number of bands in low resolution frequency table
546 * index of starting QMF subband for SBR (kStart)
547 * number of limiter bands
548 * number of patches
549 *
550 * Outputs: limiter frequency table
551 *
552 * Return: number of bands in limiter frequency table
553 **************************************************************************************/
554static int CalcFreqLimiter(unsigned char *freqLimiter, unsigned char *patchNumSubbands, unsigned char *freqLow,
555 int nLow, int kStart, int limiterBands, int numPatches)
556{
557 int k, bands, nLimiter, nOctaves;
558 int limBandsPerOctave[3] = {120, 200, 300}; /* [1.2, 2.0, 3.0] * 100 */
559 unsigned char patchBorders[MAX_NUM_PATCHES + 1];
560
561 /* simple case */
562 if (limiterBands == 0) {
563 freqLimiter[0] = freqLow[0] - kStart;
564 freqLimiter[1] = freqLow[nLow] - kStart;
565 return 1;
566 }
567
568 bands = limBandsPerOctave[limiterBands - 1];
569 patchBorders[0] = kStart;
570
571 /* from MPEG reference code - slightly different from spec (top border) */
572 for (k = 1; k < numPatches; k++) {
573 patchBorders[k] = patchBorders[k - 1] + patchNumSubbands[k - 1];
574 }
575 patchBorders[k] = freqLow[nLow];
576
577 for (k = 0; k <= nLow; k++) {
578 freqLimiter[k] = freqLow[k];
579 }
580
581 for (k = 1; k < numPatches; k++) {
582 freqLimiter[k + nLow] = patchBorders[k];
583 }
584
585 k = 1;
586 nLimiter = nLow + numPatches - 1;
587 BubbleSort(freqLimiter, nLimiter + 1);
588
589 while (k <= nLimiter) {
590 nOctaves = log2Tab[freqLimiter[k]] - log2Tab[freqLimiter[k - 1]]; /* Q28 */
591 nOctaves = (nOctaves >> 9) * bands; /* Q19, max bands = 300 < 2^9 */
592 if (nOctaves < (49 << 19)) { /* compare with 0.49*100, in Q19 */
593 if (freqLimiter[k] == freqLimiter[k - 1] || FindFreq(patchBorders, numPatches + 1, freqLimiter[k]) == 0) {
594 RemoveFreq(freqLimiter, nLimiter + 1, k);
595 nLimiter--;
596 } else if (FindFreq(patchBorders, numPatches + 1, freqLimiter[k - 1]) == 0) {
597 RemoveFreq(freqLimiter, nLimiter + 1, k - 1);
598 nLimiter--;
599 } else {
600 k++;
601 }
602 } else {
603 k++;
604 }
605 }
606
607 /* store limiter boundaries as offsets from kStart */
608 for (k = 0; k <= nLimiter; k++) {
609 freqLimiter[k] -= kStart;
610 }
611
612 return nLimiter;
613}
614
615/**************************************************************************************
616 * Function: CalcFreqTables
617 *
618 * Description: calulate master and derived frequency tables, and patches
619 *
620 * Inputs: initialized SBRHeader struct for this SCE/CPE block
621 * initialized SBRFreq struct for this SCE/CPE block
622 * sample rate index of output sample rate (after SBR)
623 *
624 * Outputs: master and derived frequency tables, and patches
625 *
626 * Return: non-zero if error, zero otherwise
627 **************************************************************************************/
628int CalcFreqTables(SBRHeader *sbrHdr, SBRFreq *sbrFreq, int sampRateIdx)
629{
630 int k0, k2;
631 int err = ERR_AAC_NONE;
632 k0 = k0Tab[sampRateIdx][sbrHdr->startFreq];
633
634 if (sbrHdr->stopFreq == 14) {
635 k2 = 2 * k0;
636 } else if (sbrHdr->stopFreq == 15) {
637 k2 = 3 * k0;
638 } else {
639 k2 = k2Tab[sampRateIdx][sbrHdr->stopFreq];
640 }
641 if (k2 > 64) {
642 k2 = 64;
643 }
644
645 /* calculate master frequency table */
646 if (sbrHdr->freqScale == 0) {
647 sbrFreq->nMaster = CalcFreqMasterScaleZero(sbrFreq->freqMaster, sbrHdr->alterScale, k0, k2);
648 } else {
649 sbrFreq->nMaster = CalcFreqMaster(sbrFreq->freqMaster, sbrHdr->freqScale, sbrHdr->alterScale, k0, k2);
650 }
651
652 /* calculate high frequency table and related parameters */
653 sbrFreq->nHigh = CalcFreqHigh(sbrFreq->freqHigh, sbrFreq->freqMaster, sbrFreq->nMaster, sbrHdr->crossOverBand);
654 sbrFreq->numQMFBands = sbrFreq->freqHigh[sbrFreq->nHigh] - sbrFreq->freqHigh[0];
655 sbrFreq->kStart = sbrFreq->freqHigh[0];
656
657 /* calculate low frequency table */
658 sbrFreq->nLow = CalcFreqLow(sbrFreq->freqLow, sbrFreq->freqHigh, sbrFreq->nHigh);
659
660 /* calculate noise floor frequency table */
661 sbrFreq->numNoiseFloorBands = CalcFreqNoise(sbrFreq->freqNoise, sbrFreq->freqLow, sbrFreq->nLow, sbrFreq->kStart, k2, sbrHdr->noiseBands, &err);
662 if (err) {
663 return err;
664 }
665
666 /* calculate limiter table */
667 sbrFreq->numPatches = BuildPatches(sbrFreq->patchNumSubbands, sbrFreq->patchStartSubband, sbrFreq->freqMaster,
668 sbrFreq->nMaster, k0, sbrFreq->kStart, sbrFreq->numQMFBands, sampRateIdx);
669 sbrFreq->nLimiter = CalcFreqLimiter(sbrFreq->freqLimiter, sbrFreq->patchNumSubbands, sbrFreq->freqLow, sbrFreq->nLow, sbrFreq->kStart,
670 sbrHdr->limiterBands, sbrFreq->numPatches);
671
672 return ERR_AAC_NONE;
673}
674