summaryrefslogtreecommitdiff
path: root/audio_codec/libraac/sbrfreq.c (plain)
blob: e3910469dafca92c25987229f530158d7327b6c0
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)
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 ASSERT(nQ <= MAX_NUM_NOISE_FLOOR_BANDS); /* required from 4.6.18.3.6 */
395
396 iLast = 0;
397 freqNoise[0] = freqLow[0];
398 for (k = 1; k <= nQ; k++) {
399 i = iLast + (nLow - iLast) / (nQ + 1 - k); /* truncating division */
400 freqNoise[k] = freqLow[i];
401 iLast = i;
402 }
403
404 return nQ;
405}
406
407/**************************************************************************************
408 * Function: BuildPatches
409 *
410 * Description: build high frequency patches (4.6.18.6.3)
411 *
412 * Inputs: master frequency table
413 * number of bands in low resolution frequency table
414 * index of first QMF subband in master freq table (k0)
415 * index of starting QMF subband for SBR (kStart)
416 * number of QMF bands in high resolution frequency table
417 * sample rate index
418 *
419 * Outputs: starting subband for each patch
420 * number of subbands in each patch
421 *
422 * Return: number of patches
423 **************************************************************************************/
424static int BuildPatches(unsigned char *patchNumSubbands, unsigned char *patchStartSubband, unsigned char *freqMaster,
425 int nMaster, int k0, int kStart, int numQMFBands, int sampRateIdx)
426{
427 int i, j, k;
428 int msb, sb, usb, numPatches, goalSB, oddFlag;
429
430 msb = k0;
431 usb = kStart;
432 numPatches = 0;
433 goalSB = goalSBTab[sampRateIdx];
434
435 if (nMaster == 0) {
436 patchNumSubbands[0] = 0;
437 patchStartSubband[0] = 0;
438 return 0;
439 }
440
441 if (goalSB < kStart + numQMFBands) {
442 k = 0;
443 for (i = 0; freqMaster[i] < goalSB; i++) {
444 k = i + 1;
445 }
446 } else {
447 k = nMaster;
448 }
449
450 do {
451 j = k + 1;
452 do {
453 j--;
454 sb = freqMaster[j];
455 oddFlag = (sb - 2 + k0) & 0x01;
456 } while (sb > k0 - 1 + msb - oddFlag);
457
458 patchNumSubbands[numPatches] = MAX(sb - usb, 0);
459 patchStartSubband[numPatches] = k0 - oddFlag - patchNumSubbands[numPatches];
460
461 /* from MPEG reference code - slightly different from spec */
462 if ((patchNumSubbands[numPatches] < 3) && (numPatches > 0)) {
463 break;
464 }
465
466 if (patchNumSubbands[numPatches] > 0) {
467 usb = sb;
468 msb = sb;
469 numPatches++;
470 } else {
471 msb = kStart;
472 }
473
474 if (freqMaster[k] - sb < 3) {
475 k = nMaster;
476 }
477
478 } while (sb != (kStart + numQMFBands) && numPatches <= MAX_NUM_PATCHES);
479
480 return numPatches;
481}
482
483/**************************************************************************************
484 * Function: FindFreq
485 *
486 * Description: search buffer of unsigned chars for a specific value
487 *
488 * Inputs: buffer of elements to search
489 * number of elements to search
490 * value to search for
491 *
492 * Outputs: none
493 *
494 * Return: non-zero if the value is found anywhere in the buffer, zero otherwise
495 **************************************************************************************/
496static int FindFreq(unsigned char *freq, int nFreq, unsigned char val)
497{
498 int k;
499
500 for (k = 0; k < nFreq; k++) {
501 if (freq[k] == val) {
502 return 1;
503 }
504 }
505
506 return 0;
507}
508
509/**************************************************************************************
510 * Function: RemoveFreq
511 *
512 * Description: remove one element from a buffer of unsigned chars
513 *
514 * Inputs: buffer of elements
515 * number of elements
516 * index of element to remove
517 *
518 * Outputs: new buffer of length nFreq-1
519 *
520 * Return: none
521 **************************************************************************************/
522static void RemoveFreq(unsigned char *freq, int nFreq, int removeIdx)
523{
524 int k;
525
526 if (removeIdx >= nFreq) {
527 return;
528 }
529
530 for (k = removeIdx; k < nFreq - 1; k++) {
531 freq[k] = freq[k + 1];
532 }
533}
534
535/**************************************************************************************
536 * Function: CalcFreqLimiter
537 *
538 * Description: calculate limiter frequency table (4.6.18.3.2.3)
539 *
540 * Inputs: number of subbands in each patch
541 * low resolution frequency table
542 * number of bands in low resolution frequency table
543 * index of starting QMF subband for SBR (kStart)
544 * number of limiter bands
545 * number of patches
546 *
547 * Outputs: limiter frequency table
548 *
549 * Return: number of bands in limiter frequency table
550 **************************************************************************************/
551static int CalcFreqLimiter(unsigned char *freqLimiter, unsigned char *patchNumSubbands, unsigned char *freqLow,
552 int nLow, int kStart, int limiterBands, int numPatches)
553{
554 int k, bands, nLimiter, nOctaves;
555 int limBandsPerOctave[3] = {120, 200, 300}; /* [1.2, 2.0, 3.0] * 100 */
556 unsigned char patchBorders[MAX_NUM_PATCHES + 1];
557
558 /* simple case */
559 if (limiterBands == 0) {
560 freqLimiter[0] = freqLow[0] - kStart;
561 freqLimiter[1] = freqLow[nLow] - kStart;
562 return 1;
563 }
564
565 bands = limBandsPerOctave[limiterBands - 1];
566 patchBorders[0] = kStart;
567
568 /* from MPEG reference code - slightly different from spec (top border) */
569 for (k = 1; k < numPatches; k++) {
570 patchBorders[k] = patchBorders[k - 1] + patchNumSubbands[k - 1];
571 }
572 patchBorders[k] = freqLow[nLow];
573
574 for (k = 0; k <= nLow; k++) {
575 freqLimiter[k] = freqLow[k];
576 }
577
578 for (k = 1; k < numPatches; k++) {
579 freqLimiter[k + nLow] = patchBorders[k];
580 }
581
582 k = 1;
583 nLimiter = nLow + numPatches - 1;
584 BubbleSort(freqLimiter, nLimiter + 1);
585
586 while (k <= nLimiter) {
587 nOctaves = log2Tab[freqLimiter[k]] - log2Tab[freqLimiter[k - 1]]; /* Q28 */
588 nOctaves = (nOctaves >> 9) * bands; /* Q19, max bands = 300 < 2^9 */
589 if (nOctaves < (49 << 19)) { /* compare with 0.49*100, in Q19 */
590 if (freqLimiter[k] == freqLimiter[k - 1] || FindFreq(patchBorders, numPatches + 1, freqLimiter[k]) == 0) {
591 RemoveFreq(freqLimiter, nLimiter + 1, k);
592 nLimiter--;
593 } else if (FindFreq(patchBorders, numPatches + 1, freqLimiter[k - 1]) == 0) {
594 RemoveFreq(freqLimiter, nLimiter + 1, k - 1);
595 nLimiter--;
596 } else {
597 k++;
598 }
599 } else {
600 k++;
601 }
602 }
603
604 /* store limiter boundaries as offsets from kStart */
605 for (k = 0; k <= nLimiter; k++) {
606 freqLimiter[k] -= kStart;
607 }
608
609 return nLimiter;
610}
611
612/**************************************************************************************
613 * Function: CalcFreqTables
614 *
615 * Description: calulate master and derived frequency tables, and patches
616 *
617 * Inputs: initialized SBRHeader struct for this SCE/CPE block
618 * initialized SBRFreq struct for this SCE/CPE block
619 * sample rate index of output sample rate (after SBR)
620 *
621 * Outputs: master and derived frequency tables, and patches
622 *
623 * Return: non-zero if error, zero otherwise
624 **************************************************************************************/
625int CalcFreqTables(SBRHeader *sbrHdr, SBRFreq *sbrFreq, int sampRateIdx)
626{
627 int k0, k2;
628
629 k0 = k0Tab[sampRateIdx][sbrHdr->startFreq];
630
631 if (sbrHdr->stopFreq == 14) {
632 k2 = 2 * k0;
633 } else if (sbrHdr->stopFreq == 15) {
634 k2 = 3 * k0;
635 } else {
636 k2 = k2Tab[sampRateIdx][sbrHdr->stopFreq];
637 }
638 if (k2 > 64) {
639 k2 = 64;
640 }
641
642 /* calculate master frequency table */
643 if (sbrHdr->freqScale == 0) {
644 sbrFreq->nMaster = CalcFreqMasterScaleZero(sbrFreq->freqMaster, sbrHdr->alterScale, k0, k2);
645 } else {
646 sbrFreq->nMaster = CalcFreqMaster(sbrFreq->freqMaster, sbrHdr->freqScale, sbrHdr->alterScale, k0, k2);
647 }
648
649 /* calculate high frequency table and related parameters */
650 sbrFreq->nHigh = CalcFreqHigh(sbrFreq->freqHigh, sbrFreq->freqMaster, sbrFreq->nMaster, sbrHdr->crossOverBand);
651 sbrFreq->numQMFBands = sbrFreq->freqHigh[sbrFreq->nHigh] - sbrFreq->freqHigh[0];
652 sbrFreq->kStart = sbrFreq->freqHigh[0];
653
654 /* calculate low frequency table */
655 sbrFreq->nLow = CalcFreqLow(sbrFreq->freqLow, sbrFreq->freqHigh, sbrFreq->nHigh);
656
657 /* calculate noise floor frequency table */
658 sbrFreq->numNoiseFloorBands = CalcFreqNoise(sbrFreq->freqNoise, sbrFreq->freqLow, sbrFreq->nLow, sbrFreq->kStart, k2, sbrHdr->noiseBands);
659
660 /* calculate limiter table */
661 sbrFreq->numPatches = BuildPatches(sbrFreq->patchNumSubbands, sbrFreq->patchStartSubband, sbrFreq->freqMaster,
662 sbrFreq->nMaster, k0, sbrFreq->kStart, sbrFreq->numQMFBands, sampRateIdx);
663 sbrFreq->nLimiter = CalcFreqLimiter(sbrFreq->freqLimiter, sbrFreq->patchNumSubbands, sbrFreq->freqLow, sbrFreq->nLow, sbrFreq->kStart,
664 sbrHdr->limiterBands, sbrFreq->numPatches);
665
666 return 0;
667}
668