123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641 |
-
- #include "sbr.h"
- #include "assembly.h"
- static void BubbleSort(unsigned char *v, int nItems)
- {
- int i;
- unsigned char t;
- while (nItems >= 2) {
- for (i = 0; i < nItems-1; i++) {
- if (v[i+1] < v[i]) {
- t = v[i+1];
- v[i+1] = v[i];
- v[i] = t;
- }
- }
- nItems--;
- }
- }
- static unsigned char VMin(unsigned char *v, int nItems)
- {
- int i;
- unsigned char vMin;
- vMin = v[0];
- for (i = 1; i < nItems; i++) {
- if (v[i] < vMin)
- vMin = v[i];
- }
- return vMin;
- }
- static unsigned char VMax(unsigned char *v, int nItems)
- {
- int i;
- unsigned char vMax;
- vMax = v[0];
- for (i = 1; i < nItems; i++) {
- if (v[i] > vMax)
- vMax = v[i];
- }
- return vMax;
- }
- static int CalcFreqMasterScaleZero(unsigned char *freqMaster, int alterScale, int k0, int k2)
- {
- int nMaster, k, nBands, k2Achieved, dk, vDk[64], k2Diff;
- if (alterScale) {
- dk = 2;
- nBands = 2 * ((k2 - k0 + 2) >> 2);
- } else {
- dk = 1;
- nBands = 2 * ((k2 - k0) >> 1);
- }
- if (nBands <= 0)
- return 0;
- k2Achieved = k0 + nBands * dk;
- k2Diff = k2 - k2Achieved;
- for (k = 0; k < nBands; k++)
- vDk[k] = dk;
- if (k2Diff > 0) {
- k = nBands - 1;
- while (k2Diff) {
- vDk[k]++;
- k--;
- k2Diff--;
- }
- } else if (k2Diff < 0) {
- k = 0;
- while (k2Diff) {
- vDk[k]--;
- k++;
- k2Diff++;
- }
- }
- nMaster = nBands;
- freqMaster[0] = k0;
- for (k = 1; k <= nBands; k++)
- freqMaster[k] = freqMaster[k-1] + vDk[k-1];
- return nMaster;
- }
- static const int mBandTab[3] PROGMEM = {6, 5, 4};
- static const int invWarpTab[2] PROGMEM = {0x40000000, 0x313b13b1};
- static int CalcFreqMaster(unsigned char *freqMaster, int freqScale, int alterScale, int k0, int k2)
- {
- int bands, twoRegions, k, k1, t, vLast, vCurr, pCurr;
- int invWarp, nBands0, nBands1, change;
- unsigned char vDk1Min, vDk0Max;
- unsigned char *vDelta;
- if (freqScale < 1 || freqScale > 3)
- return -1;
- bands = mBandTab[freqScale - 1];
- invWarp = invWarpTab[alterScale];
-
- if (k2*10000 > 22449*k0) {
- twoRegions = 1;
- k1 = 2*k0;
- } else {
- twoRegions = 0;
- k1 = k2;
- }
-
-
- t = (log2Tab[k1] - log2Tab[k0]) >> 3;
- nBands0 = 2 * (((bands * t) + (1 << 24)) >> 25);
-
- t = RatioPowInv(k1, k0, nBands0);
- pCurr = k0 << 24;
- vLast = k0;
- vDelta = freqMaster + 1;
- for (k = 0; k < nBands0; k++) {
- pCurr = MULSHIFT32(pCurr, t) << 8;
- vCurr = (pCurr + (1 << 23)) >> 24;
- vDelta[k] = (vCurr - vLast);
- vLast = vCurr;
- }
-
- BubbleSort(vDelta, nBands0);
- vDk0Max = VMax(vDelta, nBands0);
-
- freqMaster[0] = k0;
- for (k = 1; k <= nBands0; k++)
- freqMaster[k] += freqMaster[k-1];
-
- if (!twoRegions)
- return nBands0;
-
- t = (log2Tab[k2] - log2Tab[k1]) >> 3;
- t = MULSHIFT32(bands * t, invWarp) << 2;
- nBands1 = 2 * ((t + (1 << 24)) >> 25);
-
-
- t = RatioPowInv(k2, k1, nBands1);
- pCurr = k1 << 24;
- vLast = k1;
- vDelta = freqMaster + nBands0 + 1;
- for (k = 0; k < nBands1; k++) {
- pCurr = MULSHIFT32(pCurr, t) << 8;
- vCurr = (pCurr + (1 << 23)) >> 24;
- vDelta[k] = (vCurr - vLast);
- vLast = vCurr;
- }
-
- vDk1Min = VMin(vDelta, nBands1);
- if (vDk1Min < vDk0Max) {
- BubbleSort(vDelta, nBands1);
- change = vDk0Max - vDelta[0];
- if (change > ((vDelta[nBands1 - 1] - vDelta[0]) >> 1))
- change = ((vDelta[nBands1 - 1] - vDelta[0]) >> 1);
- vDelta[0] += change;
- vDelta[nBands1-1] -= change;
- }
- BubbleSort(vDelta, nBands1);
-
- for (k = 1; k <= nBands1; k++)
- freqMaster[k + nBands0] += freqMaster[k + nBands0 - 1];
- return (nBands0 + nBands1);
- }
- static int CalcFreqHigh(unsigned char *freqHigh, unsigned char *freqMaster, int nMaster, int crossOverBand)
- {
- int k, nHigh;
- nHigh = nMaster - crossOverBand;
- for (k = 0; k <= nHigh; k++)
- freqHigh[k] = freqMaster[k + crossOverBand];
-
- return nHigh;
- }
- static int CalcFreqLow(unsigned char *freqLow, unsigned char *freqHigh, int nHigh)
- {
- int k, nLow, oddFlag;
- nLow = nHigh - (nHigh >> 1);
- freqLow[0] = freqHigh[0];
- oddFlag = nHigh & 0x01;
- for (k = 1; k <= nLow; k++)
- freqLow[k] = freqHigh[2*k - oddFlag];
- return nLow;
- }
- static int CalcFreqNoise(unsigned char *freqNoise, unsigned char *freqLow, int nLow, int kStart, int k2, int noiseBands)
- {
- int i, iLast, k, nQ, lTop, lBottom;
- lTop = log2Tab[k2];
- lBottom = log2Tab[kStart];
- nQ = noiseBands*((lTop - lBottom) >> 2);
- nQ = (nQ + (1 << 25)) >> 26;
- if (nQ < 1)
- nQ = 1;
- ASSERT(nQ <= MAX_NUM_NOISE_FLOOR_BANDS);
- iLast = 0;
- freqNoise[0] = freqLow[0];
- for (k = 1; k <= nQ; k++) {
- i = iLast + (nLow - iLast) / (nQ + 1 - k);
- freqNoise[k] = freqLow[i];
- iLast = i;
- }
- return nQ;
- }
- static int BuildPatches(unsigned char *patchNumSubbands, unsigned char *patchStartSubband, unsigned char *freqMaster,
- int nMaster, int k0, int kStart, int numQMFBands, int sampRateIdx)
- {
- int i, j, k;
- int msb, sb, usb, numPatches, goalSB, oddFlag;
- msb = k0;
- usb = kStart;
- numPatches = 0;
- goalSB = goalSBTab[sampRateIdx];
- if (nMaster == 0) {
- patchNumSubbands[0] = 0;
- patchStartSubband[0] = 0;
- return 0;
- }
- if (goalSB < kStart + numQMFBands) {
- k = 0;
- for (i = 0; freqMaster[i] < goalSB; i++)
- k = i+1;
- } else {
- k = nMaster;
- }
- do {
- j = k+1;
- do {
- j--;
- sb = freqMaster[j];
- oddFlag = (sb - 2 + k0) & 0x01;
- } while (sb > k0 - 1 + msb - oddFlag);
- patchNumSubbands[numPatches] = MAX(sb - usb, 0);
- patchStartSubband[numPatches] = k0 - oddFlag - patchNumSubbands[numPatches];
-
- if ((patchNumSubbands[numPatches] < 3) && (numPatches > 0))
- break;
- if (patchNumSubbands[numPatches] > 0) {
- usb = sb;
- msb = sb;
- numPatches++;
- } else {
- msb = kStart;
- }
- if (freqMaster[k] - sb < 3)
- k = nMaster;
- } while (sb != (kStart + numQMFBands) && numPatches <= MAX_NUM_PATCHES);
- return numPatches;
- }
- static int FindFreq(unsigned char *freq, int nFreq, unsigned char val)
- {
- int k;
- for (k = 0; k < nFreq; k++) {
- if (freq[k] == val)
- return 1;
- }
- return 0;
- }
- static void RemoveFreq(unsigned char *freq, int nFreq, int removeIdx)
- {
- int k;
- if (removeIdx >= nFreq)
- return;
- for (k = removeIdx; k < nFreq - 1; k++)
- freq[k] = freq[k+1];
- }
- static int CalcFreqLimiter(unsigned char *freqLimiter, unsigned char *patchNumSubbands, unsigned char *freqLow,
- int nLow, int kStart, int limiterBands, int numPatches)
- {
- int k, bands, nLimiter, nOctaves;
- int limBandsPerOctave[3] = {120, 200, 300};
- unsigned char patchBorders[MAX_NUM_PATCHES + 1];
-
- if (limiterBands == 0) {
- freqLimiter[0] = freqLow[0] - kStart;
- freqLimiter[1] = freqLow[nLow] - kStart;
- return 1;
- }
- bands = limBandsPerOctave[limiterBands - 1];
- patchBorders[0] = kStart;
-
- for (k = 1; k < numPatches; k++)
- patchBorders[k] = patchBorders[k-1] + patchNumSubbands[k-1];
- patchBorders[k] = freqLow[nLow];
- for (k = 0; k <= nLow; k++)
- freqLimiter[k] = freqLow[k];
- for (k = 1; k < numPatches; k++)
- freqLimiter[k+nLow] = patchBorders[k];
- k = 1;
- nLimiter = nLow + numPatches - 1;
- BubbleSort(freqLimiter, nLimiter + 1);
- while (k <= nLimiter) {
- nOctaves = log2Tab[freqLimiter[k]] - log2Tab[freqLimiter[k-1]];
- nOctaves = (nOctaves >> 9) * bands;
- if (nOctaves < (49 << 19)) {
- if (freqLimiter[k] == freqLimiter[k-1] || FindFreq(patchBorders, numPatches + 1, freqLimiter[k]) == 0) {
- RemoveFreq(freqLimiter, nLimiter + 1, k);
- nLimiter--;
- } else if (FindFreq(patchBorders, numPatches + 1, freqLimiter[k-1]) == 0) {
- RemoveFreq(freqLimiter, nLimiter + 1, k-1);
- nLimiter--;
- } else {
- k++;
- }
- } else {
- k++;
- }
- }
-
- for (k = 0; k <= nLimiter; k++)
- freqLimiter[k] -= kStart;
- return nLimiter;
- }
- int CalcFreqTables(SBRHeader *sbrHdr, SBRFreq *sbrFreq, int sampRateIdx)
- {
- int k0, k2;
- k0 = k0Tab[sampRateIdx][sbrHdr->startFreq];
- if (sbrHdr->stopFreq == 14)
- k2 = 2*k0;
- else if (sbrHdr->stopFreq == 15)
- k2 = 3*k0;
- else
- k2 = k2Tab[sampRateIdx][sbrHdr->stopFreq];
- if (k2 > 64)
- k2 = 64;
-
- if (sbrHdr->freqScale == 0)
- sbrFreq->nMaster = CalcFreqMasterScaleZero(sbrFreq->freqMaster, sbrHdr->alterScale, k0, k2);
- else
- sbrFreq->nMaster = CalcFreqMaster(sbrFreq->freqMaster, sbrHdr->freqScale, sbrHdr->alterScale, k0, k2);
-
- sbrFreq->nHigh = CalcFreqHigh(sbrFreq->freqHigh, sbrFreq->freqMaster, sbrFreq->nMaster, sbrHdr->crossOverBand);
- sbrFreq->numQMFBands = sbrFreq->freqHigh[sbrFreq->nHigh] - sbrFreq->freqHigh[0];
- sbrFreq->kStart = sbrFreq->freqHigh[0];
-
- sbrFreq->nLow = CalcFreqLow(sbrFreq->freqLow, sbrFreq->freqHigh, sbrFreq->nHigh);
-
- sbrFreq->numNoiseFloorBands = CalcFreqNoise(sbrFreq->freqNoise, sbrFreq->freqLow, sbrFreq->nLow, sbrFreq->kStart, k2, sbrHdr->noiseBands);
-
- sbrFreq->numPatches = BuildPatches(sbrFreq->patchNumSubbands, sbrFreq->patchStartSubband, sbrFreq->freqMaster,
- sbrFreq->nMaster, k0, sbrFreq->kStart, sbrFreq->numQMFBands, sampRateIdx);
- sbrFreq->nLimiter = CalcFreqLimiter(sbrFreq->freqLimiter, sbrFreq->patchNumSubbands, sbrFreq->freqLow, sbrFreq->nLow, sbrFreq->kStart,
- sbrHdr->limiterBands, sbrFreq->numPatches);
- return 0;
- }
|