123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: stproc.c,v 1.3 2005/05/24 16:01:55 albertofloyd Exp $
- *
- * Portions Copyright (c) 1995-2005 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file,
- * are subject to the current version of the RealNetworks Public
- * Source License (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (the "RCSL") available at
- * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
- * will apply. You may also obtain the license terms directly from
- * RealNetworks. You may not use this file except in compliance with
- * the RPSL or, if you have a valid RCSL with RealNetworks applicable
- * to this file, the RCSL. Please see the applicable RPSL or RCSL for
- * the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the
- * portions it created.
- *
- * This file, and the files included with this file, is distributed
- * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
- * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
- * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
- * ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- /**************************************************************************************
- * Fixed-point HE-AAC decoder
- * Jon Recker (jrecker@real.com)
- * February 2005
- *
- * stproc.c - mid-side and intensity stereo processing
- **************************************************************************************/
- #include "coder.h"
- #include "assembly.h"
- /* pow14[0][i] = -pow(2, i/4.0)
- * pow14[1][i] = +pow(2, i/4.0)
- *
- * i = [0,1,2,3]
- * format = Q30
- */
- /**************************************************************************************
- * Function: StereoProcessGroup
- *
- * Description: apply mid-side and intensity stereo to group of transform coefficients
- *
- * Inputs: dequantized transform coefficients for both channels
- * pointer to appropriate scalefactor band table
- * mid-side mask enabled flag
- * buffer with mid-side mask (one bit for each scalefactor band)
- * bit offset into mid-side mask buffer
- * max coded scalefactor band
- * buffer of codebook indices for right channel
- * buffer of scalefactors for right channel, range = [0, 256]
- *
- * Outputs: updated transform coefficients in Q(FBITS_OUT_DQ_OFF)
- * updated minimum guard bit count for both channels
- *
- * Return: none
- *
- * Notes: assume no guard bits in input
- * gains 0 int bits
- **************************************************************************************/
- static void StereoProcessGroup(int *coefL, int *coefR, const /*short*/ int *sfbTab,
- int msMaskPres, unsigned char *msMaskPtr, int msMaskOffset, int maxSFB,
- unsigned char *cbRight, short *sfRight, int *gbCurrent)
- {
- //fb
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wnarrowing"
- static const int pow14[2][4] PROGMEM = {
- { 0xc0000000, 0xb3e407d7, 0xa57d8666, 0x945d819b },
- { 0x40000000, 0x4c1bf829, 0x5a82799a, 0x6ba27e65 }
- };
- #pragma GCC diagnostic pop
- int sfb, width, cbIdx, sf, cl, cr, scalef, scalei;
- int gbMaskL, gbMaskR;
- unsigned char msMask;
- msMask = (*msMaskPtr++) >> msMaskOffset;
- gbMaskL = 0;
- gbMaskR = 0;
- for (sfb = 0; sfb < maxSFB; sfb++) {
- width = sfbTab[sfb+1] - sfbTab[sfb]; /* assume >= 0 (see sfBandTabLong/sfBandTabShort) */
- cbIdx = cbRight[sfb];
- if (cbIdx == 14 || cbIdx == 15) {
- /* intensity stereo */
- if (msMaskPres == 1 && (msMask & 0x01))
- cbIdx ^= 0x01; /* invert_intensity(): 14 becomes 15, or 15 becomes 14 */
- sf = -sfRight[sfb]; /* negative since we use identity 0.5^(x) = 2^(-x) (see spec) */
- cbIdx &= 0x01; /* choose - or + scale factor */
- scalef = pow14[cbIdx][sf & 0x03];
- scalei = (sf >> 2) + 2; /* +2 to compensate for scalef = Q30 */
-
- if (scalei > 0) {
- if (scalei > 30)
- scalei = 30;
- do {
- cr = MULSHIFT32(*coefL++, scalef);
- CLIP_2N(cr, 31-scalei);
- cr <<= scalei;
- gbMaskR |= FASTABS(cr);
- *coefR++ = cr;
- } while (--width);
- } else {
- scalei = -scalei;
- if (scalei > 31)
- scalei = 31;
- do {
- cr = MULSHIFT32(*coefL++, scalef) >> scalei;
- gbMaskR |= FASTABS(cr);
- *coefR++ = cr;
- } while (--width);
- }
- } else if ( cbIdx != 13 && ((msMaskPres == 1 && (msMask & 0x01)) || msMaskPres == 2) ) {
- /* mid-side stereo (assumes no GB in inputs) */
- do {
- cl = *coefL;
- cr = *coefR;
- if ( (FASTABS(cl) | FASTABS(cr)) >> 30 ) {
- /* avoid overflow (rare) */
- cl >>= 1;
- sf = cl + (cr >> 1); CLIP_2N(sf, 30); sf <<= 1;
- cl = cl - (cr >> 1); CLIP_2N(cl, 30); cl <<= 1;
- } else {
- /* usual case */
- sf = cl + cr;
- cl -= cr;
- }
- *coefL++ = sf;
- gbMaskL |= FASTABS(sf);
- *coefR++ = cl;
- gbMaskR |= FASTABS(cl);
- } while (--width);
- } else {
- /* nothing to do */
- coefL += width;
- coefR += width;
- }
- /* get next mask bit (should be branchless on ARM) */
- msMask >>= 1;
- if (++msMaskOffset == 8) {
- msMask = *msMaskPtr++;
- msMaskOffset = 0;
- }
- }
- cl = CLZ(gbMaskL) - 1;
- if (gbCurrent[0] > cl)
- gbCurrent[0] = cl;
- cr = CLZ(gbMaskR) - 1;
- if (gbCurrent[1] > cr)
- gbCurrent[1] = cr;
- return;
- }
- /**************************************************************************************
- * Function: StereoProcess
- *
- * Description: apply mid-side and intensity stereo, if enabled
- *
- * Inputs: valid AACDecInfo struct (including dequantized transform coefficients)
- *
- * Outputs: updated transform coefficients in Q(FBITS_OUT_DQ_OFF)
- * updated minimum guard bit count for both channels
- *
- * Return: 0 if successful, -1 if error
- **************************************************************************************/
- int StereoProcess(AACDecInfo *aacDecInfo)
- {
- PSInfoBase *psi;
- ICSInfo *icsInfo;
- int gp, win, nSamps, msMaskOffset;
- int *coefL, *coefR;
- unsigned char *msMaskPtr;
- const /*short*/ int *sfbTab;
- /* validate pointers */
- if (!aacDecInfo || !aacDecInfo->psInfoBase)
- return -1;
- psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
- /* mid-side and intensity stereo require common_window == 1 (see MPEG4 spec, Correction 2, 2004) */
- if (psi->commonWin != 1 || aacDecInfo->currBlockID != AAC_ID_CPE)
- return 0;
- /* nothing to do */
- if (!psi->msMaskPresent && !psi->intensityUsed[1])
- return 0;
- icsInfo = &(psi->icsInfo[0]);
- if (icsInfo->winSequence == 2) {
- sfbTab = sfBandTabShort + sfBandTabShortOffset[psi->sampRateIdx];
- nSamps = NSAMPS_SHORT;
- } else {
- sfbTab = sfBandTabLong + sfBandTabLongOffset[psi->sampRateIdx];
- nSamps = NSAMPS_LONG;
- }
- coefL = psi->coef[0];
- coefR = psi->coef[1];
- /* do fused mid-side/intensity processing for each block (one long or eight short) */
- msMaskOffset = 0;
- msMaskPtr = psi->msMaskBits;
- for (gp = 0; gp < icsInfo->numWinGroup; gp++) {
- for (win = 0; win < icsInfo->winGroupLen[gp]; win++) {
- StereoProcessGroup(coefL, coefR, sfbTab, psi->msMaskPresent,
- msMaskPtr, msMaskOffset, icsInfo->maxSFB, psi->sfbCodeBook[1] + gp*icsInfo->maxSFB,
- psi->scaleFactors[1] + gp*icsInfo->maxSFB, psi->gbCurrent);
- coefL += nSamps;
- coefR += nSamps;
- }
- /* we use one bit per sfb, so there are maxSFB bits for each window group */
- msMaskPtr += (msMaskOffset + icsInfo->maxSFB) >> 3;
- msMaskOffset = (msMaskOffset + icsInfo->maxSFB) & 0x07;
- }
- ASSERT(coefL == psi->coef[0] + 1024);
- ASSERT(coefR == psi->coef[1] + 1024);
- return 0;
- }
|