| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376 | /* ***** BEGIN LICENSE BLOCK *****  * Version: RCSL 1.0/RPSL 1.0  *   * Portions Copyright (c) 1995-2002 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  * Version 1.0 (the "RPSL") available at  * http://www.helixcommunity.org/content/rpsl unless you have licensed  * the file under the RealNetworks Community Source License Version 1.0  * (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 MP3 decoder * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) * August 2003 * * dqchan.c - dequantization of transform coefficients **************************************************************************************/#include "coder.h"#include "assembly.h"typedef int ARRAY3[3];	/* for short-block reordering *//* optional pre-emphasis for high-frequency scale factor bands */static const char preTab[22] = { 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,3,3,3,2,0 };/* pow(2,-i/4) for i=0..3, Q31 format */const int pow14[4] PROGMEM = { 	0x7fffffff, 0x6ba27e65, 0x5a82799a, 0x4c1bf829};/* pow(2,-i/4) * pow(j,4/3) for i=0..3 j=0..15, Q25 format */const int pow43_14[4][16] PROGMEM = {{	0x00000000, 0x10000000, 0x285145f3, 0x453a5cdb, /* Q28 */	0x0cb2ff53, 0x111989d6, 0x15ce31c8, 0x1ac7f203, 	0x20000000, 0x257106b9, 0x2b16b4a3, 0x30ed74b4, 	0x36f23fa5, 0x3d227bd3, 0x437be656, 0x49fc823c, },{	0x00000000, 0x0d744fcd, 0x21e71f26, 0x3a36abd9, 	0x0aadc084, 0x0e610e6e, 0x12560c1d, 0x168523cf, 	0x1ae89f99, 0x1f7c03a4, 0x243bae49, 0x29249c67, 	0x2e34420f, 0x33686f85, 0x38bf3dff, 0x3e370182, },{	0x00000000, 0x0b504f33, 0x1c823e07, 0x30f39a55, 	0x08facd62, 0x0c176319, 0x0f6b3522, 0x12efe2ad, 	0x16a09e66, 0x1a79a317, 0x1e77e301, 0x2298d5b4, 	0x26da56fc, 0x2b3a902a, 0x2fb7e7e7, 0x3450f650, },{	0x00000000, 0x09837f05, 0x17f910d7, 0x2929c7a9, 	0x078d0dfa, 0x0a2ae661, 0x0cf73154, 0x0fec91cb, 	0x1306fe0a, 0x16434a6c, 0x199ee595, 0x1d17ae3d, 	0x20abd76a, 0x2459d551, 0x28204fbb, 0x2bfe1808, },};/* pow(j,4/3) for j=16..63, Q23 format */const int pow43[] PROGMEM = {	0x1428a2fa, 0x15db1bd6, 0x1796302c, 0x19598d85, 	0x1b24e8bb, 0x1cf7fcfa, 0x1ed28af2, 0x20b4582a, 	0x229d2e6e, 0x248cdb55, 0x26832fda, 0x28800000, 	0x2a832287, 0x2c8c70a8, 0x2e9bc5d8, 0x30b0ff99, 	0x32cbfd4a, 0x34eca001, 0x3712ca62, 0x393e6088, 	0x3b6f47e0, 0x3da56717, 0x3fe0a5fc, 0x4220ed72, 	0x44662758, 0x46b03e7c, 0x48ff1e87, 0x4b52b3f3, 	0x4daaebfd, 0x5007b497, 0x5268fc62, 0x54ceb29c, 	0x5738c721, 0x59a72a59, 0x5c19cd35, 0x5e90a129, 	0x610b9821, 0x638aa47f, 0x660db90f, 0x6894c90b, 	0x6b1fc80c, 0x6daeaa0d, 0x70416360, 0x72d7e8b0, 	0x75722ef9, 0x78102b85, 0x7ab1d3ec, 0x7d571e09, };/* sqrt(0.5) in Q31 format */#define SQRTHALF 0x5a82799a/* * Minimax polynomial approximation to pow(x, 4/3), over the range *  poly43lo: x = [0.5, 0.7071] *  poly43hi: x = [0.7071, 1.0] * * Relative error < 1E-7 * Coefs are scaled by 4, 2, 1, 0.5, 0.25 */static const unsigned int poly43lo[5] PROGMEM = { 0x29a0bda9, 0xb02e4828, 0x5957aa1b, 0x236c498d, 0xff581859 };static const unsigned int poly43hi[5] PROGMEM = { 0x10852163, 0xd333f6a4, 0x46e9408b, 0x27c2cef0, 0xfef577b4 };/* pow(2, i*4/3) as exp and frac */const int pow2exp[8] PROGMEM = { 14, 13, 11, 10, 9, 7, 6, 5 };const int pow2frac[8] PROGMEM = {	0x6597fa94, 0x50a28be6, 0x7fffffff, 0x6597fa94, 	0x50a28be6, 0x7fffffff, 0x6597fa94, 0x50a28be6};/************************************************************************************** * Function:    DequantBlock * * Description: Ken's highly-optimized, low memory dequantizer performing the operation *              y = pow(x, 4.0/3.0) * pow(2, 25 - scale/4.0) * * Inputs:      input buffer of decode Huffman codewords (signed-magnitude) *              output buffer of same length (in-place (outbuf = inbuf) is allowed) *              number of samples *               * Outputs:     dequantized samples in Q25 format * * Return:      bitwise-OR of the unsigned outputs (for guard bit calculations) **************************************************************************************//* __attribute__ ((section (".data"))) */ static int DequantBlock(int *inbuf, int *outbuf, int num, int scale){	int tab4[4];	int scalef, scalei, shift;	int sx, x, y;	int mask = 0;	const int *tab16; 	const unsigned int *coef;	tab16 = pow43_14[scale & 0x3];	scalef = pow14[scale & 0x3];	scalei = MIN(scale >> 2, 31);	/* smallest input scale = -47, so smallest scalei = -12 */	/* cache first 4 values */	shift = MIN(scalei + 3, 31);	shift = MAX(shift, 0);	tab4[0] = 0;	tab4[1] = tab16[1] >> shift;	tab4[2] = tab16[2] >> shift;	tab4[3] = tab16[3] >> shift;	do {		sx = *inbuf++;		x = sx & 0x7fffffff;	/* sx = sign|mag */		if (x < 4) {			y = tab4[x];		} else if (x < 16) {			y = tab16[x];			y = (scalei < 0) ? y << -scalei : y >> scalei;		} else {			if (x < 64) {				y = pow43[x-16];				/* fractional scale */				y = MULSHIFT32(y, scalef);				shift = scalei - 3;			} else {				/* normalize to [0x40000000, 0x7fffffff] */				x <<= 17;				shift = 0;				if (x < 0x08000000)					x <<= 4, shift += 4;				if (x < 0x20000000)					x <<= 2, shift += 2;				if (x < 0x40000000)					x <<= 1, shift += 1;				coef = (x < SQRTHALF) ? poly43lo : poly43hi;				/* polynomial */				y = coef[0];				y = MULSHIFT32(y, x) + coef[1];				y = MULSHIFT32(y, x) + coef[2];				y = MULSHIFT32(y, x) + coef[3];				y = MULSHIFT32(y, x) + coef[4];				y = MULSHIFT32(y, pow2frac[shift]) << 3;				/* fractional scale */				y = MULSHIFT32(y, scalef);				shift = scalei - pow2exp[shift];			}			/* integer scale */			if (shift < 0) {				shift = -shift;				if (y > (0x7fffffff >> shift))					y = 0x7fffffff;		/* clip */				else					y <<= shift;			} else {				y >>= shift;			}		}		/* sign and store */		mask |= y;		*outbuf++ = (sx < 0) ? -y : y;	} while (--num);	return mask;}/************************************************************************************** * Function:    DequantChannel * * Description: dequantize one granule, one channel worth of decoded Huffman codewords * * Inputs:      sample buffer (decoded Huffman codewords), length = MAX_NSAMP samples *              work buffer for reordering short-block, length = MAX_REORDER_SAMPS *                samples (3 * width of largest short-block critical band) *              non-zero bound for this channel/granule *              valid FrameHeader, SideInfoSub, ScaleFactorInfoSub, and CriticalBandInfo *                structures for this channel/granule * * Outputs:     MAX_NSAMP dequantized samples in sampleBuf *              updated non-zero bound (indicating which samples are != 0 after DQ) *              filled-in cbi structure indicating start and end critical bands * * Return:      minimum number of guard bits in dequantized sampleBuf * * Notes:       dequantized samples in Q(DQ_FRACBITS_OUT) format  **************************************************************************************//* __attribute__ ((section (".data"))) */ int DequantChannel(int *sampleBuf, int *workBuf, int *nonZeroBound, FrameHeader *fh, SideInfoSub *sis, 					ScaleFactorInfoSub *sfis, CriticalBandInfo *cbi){	int i, j, w, cb;	int /* cbStartL, */ cbEndL, cbStartS, cbEndS;	int nSamps, nonZero, sfactMultiplier, gbMask;	int globalGain, gainI;	int cbMax[3];	ARRAY3 *buf;    /* short block reorder */		/* set default start/end points for short/long blocks - will update with non-zero cb info */	if (sis->blockType == 2) {		// cbStartL = 0;		if (sis->mixedBlock) { 			cbEndL = (fh->ver == MPEG1 ? 8 : 6); 			cbStartS = 3; 		} else {			cbEndL = 0; 			cbStartS = 0;		}		cbEndS = 13;	} else {		/* long block */		//cbStartL = 0;		cbEndL =   22;		cbStartS = 13;		cbEndS =   13;	}	cbMax[2] = cbMax[1] = cbMax[0] = 0;	gbMask = 0;	i = 0;	/* sfactScale = 0 --> quantizer step size = 2	 * sfactScale = 1 --> quantizer step size = sqrt(2)	 *   so sfactMultiplier = 2 or 4 (jump through globalGain by powers of 2 or sqrt(2))	 */	sfactMultiplier = 2 * (sis->sfactScale + 1);	/* offset globalGain by -2 if midSide enabled, for 1/sqrt(2) used in MidSideProc()	 *  (DequantBlock() does 0.25 * gainI so knocking it down by two is the same as 	 *   dividing every sample by sqrt(2) = multiplying by 2^-.5)	 */	globalGain = sis->globalGain;	if (fh->modeExt >> 1)		 globalGain -= 2;	globalGain += IMDCT_SCALE;		/* scale everything by sqrt(2), for fast IMDCT36 */	/* long blocks */	for (cb = 0; cb < cbEndL; cb++) {		nonZero = 0;		nSamps = fh->sfBand->l[cb + 1] - fh->sfBand->l[cb];		gainI = 210 - globalGain + sfactMultiplier * (sfis->l[cb] + (sis->preFlag ? (int)preTab[cb] : 0));		nonZero |= DequantBlock(sampleBuf + i, sampleBuf + i, nSamps, gainI);		i += nSamps;		/* update highest non-zero critical band */		if (nonZero) 			cbMax[0] = cb;		gbMask |= nonZero;		if (i >= *nonZeroBound) 			break;	}	/* set cbi (Type, EndS[], EndSMax will be overwritten if we proceed to do short blocks) */	cbi->cbType = 0;			/* long only */	cbi->cbEndL  = cbMax[0];	cbi->cbEndS[0] = cbi->cbEndS[1] = cbi->cbEndS[2] = 0;	cbi->cbEndSMax = 0;	/* early exit if no short blocks */	if (cbStartS >= 12) 		return CLZ(gbMask) - 1;		/* short blocks */	cbMax[2] = cbMax[1] = cbMax[0] = cbStartS;	for (cb = cbStartS; cb < cbEndS; cb++) {		nSamps = fh->sfBand->s[cb + 1] - fh->sfBand->s[cb];		for (w = 0; w < 3; w++) {			nonZero =  0;			gainI = 210 - globalGain + 8*sis->subBlockGain[w] + sfactMultiplier*(sfis->s[cb][w]);			nonZero |= DequantBlock(sampleBuf + i + nSamps*w, workBuf + nSamps*w, nSamps, gainI);			/* update highest non-zero critical band */			if (nonZero)				cbMax[w] = cb;			gbMask |= nonZero;		}		/* reorder blocks */		buf = (ARRAY3 *)(sampleBuf + i);		i += 3*nSamps;		for (j = 0; j < nSamps; j++) {			buf[j][0] = workBuf[0*nSamps + j];			buf[j][1] = workBuf[1*nSamps + j];			buf[j][2] = workBuf[2*nSamps + j];		}		ASSERT(3*nSamps <= MAX_REORDER_SAMPS);		if (i >= *nonZeroBound) 			break;	}	/* i = last non-zero INPUT sample processed, which corresponds to highest possible non-zero 	 *     OUTPUT sample (after reorder)	 * however, the original nzb is no longer necessarily true	 *   for each cb, buf[][] is updated with 3*nSamps samples (i increases 3*nSamps each time)	 *   (buf[j + 1][0] = 3 (input) samples ahead of buf[j][0])     * so update nonZeroBound to i	 */	*nonZeroBound = i;	ASSERT(*nonZeroBound <= MAX_NSAMP);	cbi->cbType = (sis->mixedBlock ? 2 : 1);	/* 2 = mixed short/long, 1 = short only */	cbi->cbEndS[0] = cbMax[0];	cbi->cbEndS[1] = cbMax[1];	cbi->cbEndS[2] = cbMax[2];	cbi->cbEndSMax = cbMax[0];	cbi->cbEndSMax = MAX(cbi->cbEndSMax, cbMax[1]);	cbi->cbEndSMax = MAX(cbi->cbEndSMax, cbMax[2]);	return CLZ(gbMask) - 1;}
 |