[Datatype-cvs] aac/codec/fixpt/decoder/real dequant.c, 1.1, 1.2 sbr.c, 1.1, 1.2 sbr.h, 1.1, 1.2 sbrfreq.c, 1.1, 1.2 sbrhfadj.c, 1.1, 1.2 stproc.c, 1.1, 1.2

[Datatype-cvs] aac/codec/fixpt/decoder/real dequant.c, 1.1, 1.2 sbr.c, 1.1, 1.2 sbr.h, 1.1, 1.2 sbrfreq.c, 1.1, 1.2 sbrhfadj.c, 1.1, 1.2 stproc.c, 1.1, 1.2

jrecker at helixcommunity.org jrecker at helixcommunity.org
Fri May 20 11:05:44 PDT 2005


Update of /cvsroot/datatype/aac/codec/fixpt/decoder/real
In directory cvs-new:/tmp/cvs-serv10133

Modified Files:
	dequant.c sbr.c sbr.h sbrfreq.c sbrhfadj.c stproc.c 
Log Message:
Updated SBR decoder to match corrections in spec
- affects logic for patch generation, limiter bands, sinusoids


Index: stproc.c
===================================================================
RCS file: /cvsroot/datatype/aac/codec/fixpt/decoder/real/stproc.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- stproc.c	26 Feb 2005 01:47:35 -0000	1.1
+++ stproc.c	20 May 2005 18:05:41 -0000	1.2
@@ -76,7 +76,7 @@
  *
  * Return:      none
  *
- * Notes:       assume 1 guard bit in input
+ * Notes:       assume no guard bits in input
  *              gains 0 int bits
  **************************************************************************************/
 static void StereoProcessGroup(int *coefL, int *coefR, const short *sfbTab, 
@@ -125,16 +125,24 @@
 				} while (--width);
 			}
 		} else if ( cbIdx != 13 && ((msMaskPres == 1 && (msMask & 0x01)) || msMaskPres == 2) ) {
-			/* mid-side stereo (assumes 1 GB in inputs) */
+			/* mid-side stereo (assumes no GB in inputs) */
 			do {
 				cl = *coefL;	
 				cr = *coefR;
 
-				sf = cl + cr;
+				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);
-
-				cl -= cr;
 				*coefR++ = cl;
 				gbMaskR |= FASTABS(cl);
 			} while (--width);

Index: sbr.c
===================================================================
RCS file: /cvsroot/datatype/aac/codec/fixpt/decoder/real/sbr.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- sbr.c	26 Feb 2005 01:47:35 -0000	1.1
+++ sbr.c	20 May 2005 18:05:41 -0000	1.2
@@ -269,6 +269,11 @@
 		return ERR_AAC_NONE;
 	}
 
+	if (upsampleOnly) {
+		sbrFreq->kStart = 32;
+		sbrFreq->numQMFBands = 0;
+	}
+
 	for (ch = 0; ch < chBlock; ch++) {
 		sbrGrid = &(psi->sbrGrid[chBase + ch]);	
 		sbrChan = &(psi->sbrChan[chBase + ch]);
@@ -287,7 +292,7 @@
 		}
 
 		/* step 1 - analysis QMF */
-		qmfaBands = (sbrHdr->count > 0 ? sbrFreq->kStart : 32);
+		qmfaBands = sbrFreq->kStart;
 		for (l = 0; l < 32; l++) {
 			gbMask = QMFAnalysis(inbuf + l*32, psi->delayQMFA[chBase + ch], psi->XBuf[l + HF_GEN][0], 
 				aacDecInfo->rawSampleFBits, &(psi->delayIdxQMFA[chBase + ch]), qmfaBands);
@@ -305,8 +310,28 @@
 				outptr += 64*aacDecInfo->nChans;
 			}
 		} else {
+			/* if previous frame had lower SBR starting freq than current, zero out the synthesized QMF
+			 *   bands so they aren't used as sources for patching
+			 * after patch generation, restore from delay buffer
+			 * can only happen after header reset
+			 */
+			for (k = sbrFreq->kStartPrev; k < sbrFreq->kStart; k++) {
+				for (l = 0; l < sbrGrid->envTimeBorder[0] + HF_ADJ; l++) {
+					psi->XBuf[l][k][0] = 0;
+					psi->XBuf[l][k][1] = 0;
+				}
+			}
+
 			/* step 2 - HF generation */
 			GenerateHighFreq(psi, sbrGrid, sbrFreq, sbrChan, ch);
+
+			/* restore SBR bands that were cleared before patch generation (time slots 0, 1 no longer needed) */
+			for (k = sbrFreq->kStartPrev; k < sbrFreq->kStart; k++) {
+				for (l = HF_ADJ; l < sbrGrid->envTimeBorder[0] + HF_ADJ; l++) {
+					psi->XBuf[l][k][0] = psi->XBufDelay[chBase + ch][l][k][0];
+					psi->XBuf[l][k][1] = psi->XBufDelay[chBase + ch][l][k][1];
+				}
+			}
 
 			/* step 3 - HF adjustment */
 			AdjustHighFreq(psi, sbrHdr, sbrGrid, sbrFreq, sbrChan, ch);

Index: sbrfreq.c
===================================================================
RCS file: /cvsroot/datatype/aac/codec/fixpt/decoder/real/sbrfreq.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- sbrfreq.c	26 Feb 2005 01:47:35 -0000	1.1
+++ sbrfreq.c	20 May 2005 18:05:41 -0000	1.2
@@ -444,6 +444,10 @@
 		patchNumSubbands[numPatches] = MAX(sb - usb, 0);
 		patchStartSubband[numPatches] = k0 - oddFlag - patchNumSubbands[numPatches];
 
+		/* from MPEG reference code - slightly different from spec */
+		if ((patchNumSubbands[numPatches] < 3) && (numPatches > 0))
+			break;
+
 		if (patchNumSubbands[numPatches] > 0) {
 			usb = sb;
 			msb = sb;
@@ -452,14 +456,10 @@
 			msb = kStart;
 		}
 
-		if (sb == freqMaster[k])
+		if (freqMaster[k] - sb < 3)
 			k = nMaster;
 
-		ASSERT(numPatches <= 5);
-	} while (sb != kStart + numQMFBands);
-
-	if (patchNumSubbands[numPatches-1] < 3 && numPatches > 1)
-		numPatches--;
+	} while (sb != (kStart + numQMFBands) && numPatches <= MAX_NUM_PATCHES);
 
 	return numPatches;
 }
@@ -546,8 +546,10 @@
 	bands = limBandsPerOctave[limiterBands - 1];
 	patchBorders[0] = kStart;
 
-	for (k = 1; k <= numPatches; k++)
+	/* from MPEG reference code - slightly different from spec (top border) */
+	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];

Index: dequant.c
===================================================================
RCS file: /cvsroot/datatype/aac/codec/fixpt/decoder/real/dequant.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- dequant.c	26 Feb 2005 01:47:34 -0000	1.1
+++ dequant.c	20 May 2005 18:05:41 -0000	1.2
@@ -137,7 +137,7 @@
  * Notes:       applies dequant formula y = pow(x, 4.0/3.0) * pow(2, (scale - 100)/4.0)
  *                * pow(2, FBITS_OUT_DQ_OFF)
  *              clips outputs to Q(FBITS_OUT_DQ_OFF)
- *              output has >= 1 guard bit
+ *              output has no minimum number of guard bits
  **************************************************************************************/
 static int DequantBlock(int *inbuf, int nSamps, int scale)
 {
@@ -172,8 +172,8 @@
 			shift = 31;
 		for (x = 0; x < 4; x++) {
 			y = tab16[x];
-			if (y > (0x3fffffff >> shift))
-				y = 0x3fffffff;		/* clip (rare), guarantees at least 1 gb */
+			if (y > (0x7fffffff >> shift))
+				y = 0x7fffffff;		/* clip (rare) */
 			else
 				y <<= shift;
 			tab4[x] = y;
@@ -247,8 +247,8 @@
 				if (shift > 31)
 					shift = 31;
 
-				if (y > (0x3fffffff >> shift))
-					y = 0x3fffffff;		/* clip (rare), guarantees at least 1 gb */
+				if (y > (0x7fffffff >> shift))
+					y = 0x7fffffff;		/* clip (rare) */
 				else
 					y <<= shift;
 			} else {

Index: sbr.h
===================================================================
RCS file: /cvsroot/datatype/aac/codec/fixpt/decoder/real/sbr.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- sbr.h	26 Feb 2005 01:47:35 -0000	1.1
+++ sbr.h	20 May 2005 18:05:41 -0000	1.2
@@ -241,9 +241,8 @@
 	unsigned char         freqLimiter[MAX_QMF_BANDS / 2 + MAX_NUM_PATCHES];		/* max (intermediate) size = nLow + numPatches - 1 */
 
 	unsigned char         numPatches;
-	unsigned char         patchBorders[MAX_NUM_PATCHES+1];
-	unsigned char         patchNumSubbands[MAX_NUM_PATCHES];
-	unsigned char         patchStartSubband[MAX_NUM_PATCHES];
+	unsigned char         patchNumSubbands[MAX_NUM_PATCHES + 1];
+	unsigned char         patchStartSubband[MAX_NUM_PATCHES + 1];
 } SBRFreq;
 
 typedef struct _SBRChan {
@@ -257,7 +256,7 @@
 	unsigned char         invfMode[2][MAX_NUM_NOISE_FLOOR_BANDS];	/* invfMode[0/1][band] = prev/curr */
 	int                   chirpFact[MAX_NUM_NOISE_FLOOR_BANDS];		/* bwArray */
 	unsigned char         addHarmonicFlag[2];						/* addHarmonicFlag[0/1] = prev/curr */
-	unsigned char         addHarmonic[2][MAX_QMF_BANDS];			/* addHarmonic[0/1][band] = prev/curr */
+	unsigned char         addHarmonic[2][64];						/* addHarmonic[0/1][band] = prev/curr */
 	
 	int                   gbMask[2];	/* gbMask[0/1] = XBuf[0-31]/XBuf[32-39] */
 	signed char           laPrev;

Index: sbrhfadj.c
===================================================================
RCS file: /cvsroot/datatype/aac/codec/fixpt/decoder/real/sbrhfadj.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- sbrhfadj.c	26 Feb 2005 01:47:35 -0000	1.1
+++ sbrhfadj.c	20 May 2005 18:05:41 -0000	1.2
@@ -189,21 +189,25 @@
  **************************************************************************************/
 static int GetSMapped(SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int env, int band, int la)
 {
-	int bandStart, bandEnd, oddFlag;
+	int bandStart, bandEnd, oddFlag, r;
 
 	if (sbrGrid->freqRes[env]) {
 		/* high resolution */
-		if (env >= la || (sbrChan->addHarmonicFlag[0] && sbrChan->addHarmonic[0][band]))
-			return sbrChan->addHarmonic[1][band];
+		bandStart = band;
+		bandEnd = band+1;
 	} else {
 		/* low resolution (see CalcFreqLow() for mapping) */
 		oddFlag = sbrFreq->nHigh & 0x01;
-		bandStart = 2*band - oddFlag;		/* starting index for freqLow[band] */
-		bandEnd = 2*(band+1) - oddFlag;		/* ending index for freqLow[band+1] */
-		for (band = bandStart; band < bandEnd; band++) {
-			if (env >= la || (sbrChan->addHarmonicFlag[0] && sbrChan->addHarmonic[0][band]))
-				if (sbrChan->addHarmonic[1][band])
-					return 1;
+		bandStart = (band > 0 ? 2*band - oddFlag : 0);		/* starting index for freqLow[band] */
+		bandEnd = 2*(band+1) - oddFlag;						/* ending index for freqLow[band+1] */
+	}
+
+	/* sMapped = 1 if sIndexMapped == 1 for any frequency in this band */
+	for (band = bandStart; band < bandEnd; band++) {
+		if (sbrChan->addHarmonic[1][band]) {
+			r = ((sbrFreq->freqHigh[band+1] + sbrFreq->freqHigh[band]) >> 1);
+			if (env >= la || sbrChan->addHarmonic[0][r] == 1)
+				return 1;
 		}
 	}
 	return 0;
@@ -380,13 +384,28 @@
 			psi->sMapped = GetSMapped(sbrGrid, sbrFreq, sbrChan, env, psi->sBand, psi->la);
 		}
 
+		/* get sIndexMapped for this QMF subband */
 		sIndexMapped = 0;
-		if (env >= psi->la || (sbrChan->addHarmonicFlag[0] && sbrChan->addHarmonic[0][psi->highBand])) {
-			r = ((sbrFreq->freqHigh[psi->highBand+1] + sbrFreq->freqHigh[psi->highBand]) >> 1);	/* r = center band */
-			if (m == r - sbrFreq->kStart)
+		r = ((sbrFreq->freqHigh[psi->highBand+1] + sbrFreq->freqHigh[psi->highBand]) >> 1);
+		if (m + sbrFreq->kStart == r) {
+			/* r = center frequency, deltaStep = (env >= la || sIndexMapped'(r, numEnv'-1) == 1) */
+			if (env >= psi->la || sbrChan->addHarmonic[0][r] == 1)
 				sIndexMapped = sbrChan->addHarmonic[1][psi->highBand];
 		}
 
+		/* save sine flags from last envelope in this frame:
+		 *   addHarmonic[0][0...63] = saved sine present flag from previous frame, for each QMF subband
+		 *   addHarmonic[1][0...nHigh-1] = addHarmonic bit from current frame, for each high-res frequency band
+		 * from MPEG reference code - slightly different from spec
+		 *   (sIndexMapped'(m,LE'-1) can still be 0 when numEnv == psi->la)
+		 */
+		if (env == sbrGrid->numEnv - 1) {
+			if (m + sbrFreq->kStart == r)
+				sbrChan->addHarmonic[0][m + sbrFreq->kStart] = sbrChan->addHarmonic[1][psi->highBand];
+			else
+				sbrChan->addHarmonic[0][m + sbrFreq->kStart] = 0;
+		}
+
 		gain = psi->envDataDequant[ch][env][psi->sBand];
 		qm = MULSHIFT32(gain, psi->qqp1Inv) << 1;
 		sm = (sIndexMapped ? MULSHIFT32(gain, psi->qp1Inv) << 1 : 0);
@@ -819,9 +838,11 @@
 		hfReset = 0;	/* only set for first envelope after header reset */
 	}
 
-	/* save curr as prev for next time */
-	for (i = 0; i < MAX_QMF_BANDS; i++)
-		sbrChan->addHarmonic[0][i] = sbrChan->addHarmonic[1][i];
+	/* set saved sine flags to 0 for QMF bands outside of current frequency range */
+	for (i = 0; i < sbrFreq->freqLimiter[0] + sbrFreq->kStart; i++)
+		sbrChan->addHarmonic[0][i] = 0;
+	for (i = sbrFreq->freqLimiter[sbrFreq->nLimiter] + sbrFreq->kStart; i < 64; i++)
+		sbrChan->addHarmonic[0][i] = 0;
 	sbrChan->addHarmonicFlag[0] = sbrChan->addHarmonicFlag[1];
 
 	/* save la for next frame */




More information about the Datatype-cvs mailing list
 

Site Map   |   Terms of Use   |   Privacy Policy   |   Contact Us

Copyright © 1995-2007 RealNetworks, Inc. All rights reserved. RealNetworks and Helix are trademarks of RealNetworks.
All other trademarks or registered trademarks are the property of their respective holders.