shithub: aacenc

Download patch

ref: d12f80faa4a0a08a38cb05de3960b2a6e01569df
parent: 60fa9e81165a47bf492e0835459e2dedf72df660
author: menno <menno>
date: Fri May 18 09:38:19 EDT 2001

Cleaned up backward prediction code

--- a/libfaac/backpred.c
+++ b/libfaac/backpred.c
@@ -16,396 +16,343 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: backpred.c,v 1.1 2001/05/02 05:40:15 menno Exp $
+ * $Id: backpred.c,v 1.2 2001/05/18 13:38:19 menno Exp $
  */
 
-/**********************************************************************
-
-INPUT:
-act_spec[]: the current frame's spectral components to be encoded.
-last_spec[]: the previous frame's quantized spectral error components 
-btype: the current frame's window type
-nsfb: the number of scalefactor bands
-isfb_width[]: scalefactor bandwidth
-
-OUTPUT:
-act_spec[]: the current frame's spectral error components to be encoded
-pred_global_flag: global prediction enable/disable flag
-pred_sbf_glag[]: enable/disable flag for each scalefactor band
-reset_group: number for the reset group => if -1, then no reset
-***********************************************************************/
-
 #include <math.h>
+#include "frame.h"
 #include "coder.h"
 #include "channels.h"
 #include "backpred.h"
 
-/* Make these work for mulitchannels */  /* CL, 1/98 */
-/*static int psy_init = 0;
-static float dr[LPC][FLEN_LONG/2],e[LPC+1+1][FLEN_LONG/2];
-static float K[LPC+1][FLEN_LONG/2], R[LPC+1][FLEN_LONG/2];
-static float VAR[LPC+1][FLEN_LONG/2], KOR[LPC+1][FLEN_LONG/2];
-static float sb_samples_pred[FLEN_LONG/2];
-static int thisLineNeedsResetting[FLEN_LONG/2];
-static int reset_count = 0;*/
 
-
-static int psy_init_mc[MAX_CHANNELS];
-static float dr_mc[MAX_CHANNELS][LPC][FLEN_LONG/2],e_mc[MAX_CHANNELS][LPC+1+1][FLEN_LONG/2];
-static float K_mc[MAX_CHANNELS][LPC+1][FLEN_LONG/2], R_mc[MAX_CHANNELS][LPC+1][FLEN_LONG/2];
-static float VAR_mc[MAX_CHANNELS][LPC+1][FLEN_LONG/2], KOR_mc[MAX_CHANNELS][LPC+1][FLEN_LONG/2];
-static float sb_samples_pred_mc[MAX_CHANNELS][FLEN_LONG/2];
-static int thisLineNeedsResetting_mc[MAX_CHANNELS][FLEN_LONG/2];
-static int reset_count_mc[MAX_CHANNELS];
-
-/* Max prediction band as function of fs index */
-int MAX_PRED_SFB[][2] = {
-		     {96000,33},
-		     {88200,33},
-		     {64000,38},
-		     {48000,40},
-		     {44100,40},
-		     {32000,40},
-		     {24000,41},
-		     {22050,41}, 
-		     {16000,37}, 
-		     {12000,37}, 
-		     {11025,37},
-			 {8000,34},
-		     {-1,0}};
-
-int GetMaxPredSfb(int samplingRateIdx)
+void PredInit(faacEncHandle hEncoder)
 {
-	return MAX_PRED_SFB[samplingRateIdx][1];
-}
+	unsigned int channel;
 
+	for (channel = 0; channel < hEncoder->numChannels; channel++) {
+		BwpInfo *bwpInfo = &(hEncoder->coderInfo[channel].bwpInfo);
 
-
-void PredInit()
-{
-	int i;
-
-	for (i=0;i<MAX_CHANNELS;i++) {
-		psy_init_mc[i] = 0;
-		reset_count_mc[i] = 0;
+		bwpInfo->psy_init_mc = 0;
+		bwpInfo->reset_count_mc = 0;
 	}
 }
  
-void PredCalcPrediction( double *act_spec, double *last_spec, int btype, 
-			int nsfb, 
-			int *isfb_width, 
-			CoderInfo *coderInfo,
-			ChannelInfo *channelInfo,                  /* Pointer to Ch_Info */
-			int chanNum) 
+void PredCalcPrediction(double *act_spec, double *last_spec, int btype, 
+						int nsfb, 
+						int *isfb_width, 
+						CoderInfo *coderInfo,
+						ChannelInfo *channelInfo,
+						int chanNum) 
 {
-  int i, k, j, cb_long;
-  int leftChanNum;
-  int isRightWithCommonWindow;
-  float small, small_p, num_bit, snr[SBMAX_L];
-  float energy[FLEN_LONG/2], snr_p[FLEN_LONG/2], temp1, temp2;
-  ChannelInfo *thisChannel;
+	int i, k, j, cb_long;
+	int leftChanNum;
+	int isRightWithCommonWindow;
+	double num_bit, snr[SBMAX_L];
+	double energy[BLOCK_LEN_LONG], snr_p[BLOCK_LEN_LONG], temp1, temp2;
+	ChannelInfo *thisChannel;
 
-  /* Set pointers for specified channel number */
-  /* int psy_init; */
-  int *psy_init;
-  float (*dr)[FLEN_LONG/2],(*e)[FLEN_LONG/2];
-  float (*K)[FLEN_LONG/2], (*R)[FLEN_LONG/2];
-  float (*VAR)[FLEN_LONG/2], (*KOR)[FLEN_LONG/2];
-  float *sb_samples_pred;
-  int *thisLineNeedsResetting;
-  /* int reset_count; */
-  int *reset_count;
-  int *pred_global_flag;
-  int *pred_sfb_flag;
-  int *reset_group;
+	/* Set pointers for specified channel number */
+	/* int psy_init; */
+	int *psy_init;
+	double (*dr)[BLOCK_LEN_LONG],(*e)[BLOCK_LEN_LONG];
+	double (*K)[BLOCK_LEN_LONG], (*R)[BLOCK_LEN_LONG];
+	double (*VAR)[BLOCK_LEN_LONG], (*KOR)[BLOCK_LEN_LONG];
+	double *sb_samples_pred;
+	int *thisLineNeedsResetting;
+	/* int reset_count; */
+	int *reset_count;
+	int *pred_global_flag;
+	int *pred_sfb_flag;
+	int *reset_group;
 
-  /* Set pointers for this chanNum */
-  pred_global_flag = &(coderInfo[chanNum].pred_global_flag);
-  pred_sfb_flag = coderInfo[chanNum].pred_sfb_flag;
-  reset_group = &(coderInfo[chanNum].reset_group_number);
-  /* psy_init = psy_init_mc[chanNum]; */
-  psy_init = &psy_init_mc[chanNum];
-  dr = &dr_mc[chanNum][0];
-  e = &e_mc[chanNum][0];
-  K = &K_mc[chanNum][0]; 
-  R = &R_mc[chanNum][0];
-  VAR = &VAR_mc[chanNum][0];
-  KOR = &KOR_mc[chanNum][0];
-  sb_samples_pred = &sb_samples_pred_mc[chanNum][0];
-  thisLineNeedsResetting = &thisLineNeedsResetting_mc[chanNum][0];
-  reset_count = &reset_count_mc[chanNum];
+	/* Set pointers for this chanNum */
+	pred_global_flag = &(coderInfo[chanNum].pred_global_flag);
+	pred_sfb_flag = coderInfo[chanNum].pred_sfb_flag;
+	reset_group = &(coderInfo[chanNum].reset_group_number);
+	psy_init = &coderInfo[chanNum].bwpInfo.psy_init_mc;
+	dr = &coderInfo[chanNum].bwpInfo.dr_mc[0];
+	e = &coderInfo[chanNum].bwpInfo.e_mc[0];
+	K = &coderInfo[chanNum].bwpInfo.K_mc[0]; 
+	R = &coderInfo[chanNum].bwpInfo.R_mc[0];
+	VAR = &coderInfo[chanNum].bwpInfo.VAR_mc[0];
+	KOR = &coderInfo[chanNum].bwpInfo.KOR_mc[0];
+	sb_samples_pred = &coderInfo[chanNum].bwpInfo.sb_samples_pred_mc[0];
+	thisLineNeedsResetting = &coderInfo[chanNum].bwpInfo.thisLineNeedsResetting_mc[0];
+	reset_count = &coderInfo[chanNum].bwpInfo.reset_count_mc;
 
-  thisChannel = &(channelInfo[chanNum]);
-  *psy_init = (*psy_init && (btype!=2));
+	thisChannel = &(channelInfo[chanNum]);
+	*psy_init = (*psy_init && (btype!=2));
 
-  if((*psy_init) == 0) {
-    for (j=0; j<FLEN_LONG/2; j++) {
-      thisLineNeedsResetting[j]=1;
-    }
-    *psy_init = 1;
-  }
+	if((*psy_init) == 0) {
+		for (j=0; j<BLOCK_LEN_LONG; j++) {
+			thisLineNeedsResetting[j]=1;
+		}
+		*psy_init = 1;
+	}
 
-  if (btype==2) {
-    pred_global_flag[0]=0;
-    /* SHORT WINDOWS reset all the co-efficients    */
-    if (thisChannel->ch_is_left) {
-      (*reset_count)++;
-      if (*reset_count >= 31 * RESET_FRAME)
-	*reset_count = RESET_FRAME;
-      /*    *reset_count = ((*reset_count) / RESET_FRAME) * RESET_FRAME;*/
-    }
-    return;
-  }
+	if (btype==2) {
+		pred_global_flag[0]=0;
+		/* SHORT WINDOWS reset all the co-efficients    */
+		if (thisChannel->ch_is_left) {
+			(*reset_count)++;
+			if (*reset_count >= 31 * RESET_FRAME)
+				*reset_count = RESET_FRAME;
+		}
+		return;
+	}
 
 
-  /**************************************************/
-  /*  Compute state using last_spec                 */
-  /**************************************************/
-  for (i=0;i<FLEN_LONG/2;i++) 
+	/**************************************************/
+	/*  Compute state using last_spec                 */
+	/**************************************************/
+	for (i=0;i<BLOCK_LEN_LONG;i++) 
     {
-      /* e[0][i]=last_spec[i]; */ 
-      e[0][i]=last_spec[i]+sb_samples_pred[i];
-      
-      for(j=1;j<=LPC;j++)
-	e[j][i] = e[j-1][i]-K[j][i]*R[j-1][i];
-      
-      for(j=1;j<LPC;j++) 
-	dr[j][i] = K[j][i]*e[j-1][i];
-      
-      for(j=1;j<=LPC;j++) {
-	VAR[j][i] = ALPHA*VAR[j][i]+.5*(R[j-1][i]*R[j-1][i]+e[j-1][i]*e[j-1][i]);
-	KOR[j][i] = ALPHA*KOR[j][i]+R[j-1][i]*e[j-1][i];
-      }
+		/* e[0][i]=last_spec[i]; */ 
+		e[0][i]=last_spec[i]+sb_samples_pred[i];
+		
+		for(j=1;j<=LPC;j++)
+			e[j][i] = e[j-1][i]-K[j][i]*R[j-1][i];
+		
+		for(j=1;j<LPC;j++) 
+			dr[j][i] = K[j][i]*e[j-1][i];
+		
+		for(j=1;j<=LPC;j++) {
+			VAR[j][i] = ALPHA*VAR[j][i]+.5*(R[j-1][i]*R[j-1][i]+e[j-1][i]*e[j-1][i]);
+			KOR[j][i] = ALPHA*KOR[j][i]+R[j-1][i]*e[j-1][i];
+		}
 
-      for(j=LPC-1;j>=1;j--) 
-	R[j][i] = A*(R[j-1][i]-dr[j][i]);
-      R[0][i] = A*e[0][i];
+		for(j=LPC-1;j>=1;j--) 
+			R[j][i] = A*(R[j-1][i]-dr[j][i]);
+		R[0][i] = A*e[0][i];
     }
 
 
-  /**************************************************/
-  /* Reset state here if resets were sent           */
-  /**************************************************/
-   for (i=0;i<FLEN_LONG/2;i++) {
-     if (thisLineNeedsResetting[i]) {
-       for (j = 0; j <= LPC; j++)
-	 {
-	   K[j][i] = 0.0;
-	   e[j][i] = 0.0;
-	   R[j][i] = 0.0;
-	   VAR[j][i] = 1.0;
-	   KOR[j][i] = 0.0;
-	   dr[j][i] = 0.0;
-	 }
-     }
-   }
+	/**************************************************/
+	/* Reset state here if resets were sent           */
+	/**************************************************/
+	for (i=0;i<BLOCK_LEN_LONG;i++) {
+		if (thisLineNeedsResetting[i]) {
+			for (j = 0; j <= LPC; j++)
+			{
+				K[j][i] = 0.0;
+				e[j][i] = 0.0;
+				R[j][i] = 0.0;
+				VAR[j][i] = 1.0;
+				KOR[j][i] = 0.0;
+				dr[j][i] = 0.0;
+			}
+		}
+	}
 
 
 
-  /**************************************************/
-  /* Compute predictor coefficients, predicted data */
-  /**************************************************/
-   for (i=0;i<FLEN_LONG/2;i++) 
+	/**************************************************/
+	/* Compute predictor coefficients, predicted data */
+	/**************************************************/
+	for (i=0;i<BLOCK_LEN_LONG;i++) 
     {
-      for(j=1;j<=LPC;j++) {
-	if(VAR[j][i]>MINVAR)
-	  K[j][i] = KOR[j][i]/VAR[j][i]*B;
-	else
-	  K[j][i] = 0;
-      }
+		for(j=1;j<=LPC;j++) {
+			if(VAR[j][i]>MINVAR)
+				K[j][i] = KOR[j][i]/VAR[j][i]*B;
+			else
+				K[j][i] = 0;
+		}
     }
 
 
-   for (k=0; k<FLEN_LONG/2; k++)
+	for (k=0; k<BLOCK_LEN_LONG; k++)
     {
-      sb_samples_pred[k]=0.0;
-      for (i=1; i<=LPC; i++)
-	sb_samples_pred[k]+=K[i][k]*R[i-1][k];
+		sb_samples_pred[k]=0.0;
+		for (i=1; i<=LPC; i++)
+			sb_samples_pred[k]+=K[i][k]*R[i-1][k];
     }
 
 
-  /***********************************************************/
-  /* If this is the right channel of a channel_pair_element, */
-  /* AND common_window is 1 in this channel_pair_element,    */
-  /* THEN copy predictor data to use from the left channel.  */
-  /* ELSE determine independent predictor data and resets.   */
-  /***********************************************************/
-  /* BE CAREFUL HERE, this assumes that predictor data has   */
-  /* already been determined for the left channel!!          */
-  /***********************************************************/
-  isRightWithCommonWindow = 0;     /* Is this a right channel with common_window?*/
-  if ((thisChannel->cpe)&&( !(thisChannel->ch_is_left))) {
-    leftChanNum = thisChannel->paired_ch;
-    if (channelInfo[leftChanNum].common_window) {
-      isRightWithCommonWindow = 1;
-    }
-  }
+	/***********************************************************/
+	/* If this is the right channel of a channel_pair_element, */
+	/* AND common_window is 1 in this channel_pair_element,    */
+	/* THEN copy predictor data to use from the left channel.  */
+	/* ELSE determine independent predictor data and resets.   */
+	/***********************************************************/
+	/* BE CAREFUL HERE, this assumes that predictor data has   */
+	/* already been determined for the left channel!!          */
+	/***********************************************************/
+	isRightWithCommonWindow = 0;     /* Is this a right channel with common_window?*/
+	if ((thisChannel->cpe)&&( !(thisChannel->ch_is_left))) {
+		leftChanNum = thisChannel->paired_ch;
+		if (channelInfo[leftChanNum].common_window) {
+			isRightWithCommonWindow = 1;
+		}
+	}
 
-  if (isRightWithCommonWindow) {
-    
-    /**************************************************/
-    /* Use predictor data from the left channel.      */
-    /**************************************************/
-    CopyPredInfo(&(coderInfo[chanNum]),&(coderInfo[leftChanNum]));
+	if (isRightWithCommonWindow) {
+		
+		/**************************************************/
+		/* Use predictor data from the left channel.      */
+		/**************************************************/
+		CopyPredInfo(&(coderInfo[chanNum]),&(coderInfo[leftChanNum]));
 
-    /* Make sure to turn off bands with intensity stereo */
+		/* Make sure to turn off bands with intensity stereo */
 #if 0
-    if (thisChannel->is_info.is_present) {
-		for (i=0; i<nsfb; i++) {
-			if (thisChannel->is_info.is_used[i]) {
-				pred_sfb_flag[i] = 0;
+		if (thisChannel->is_info.is_present) {
+			for (i=0; i<nsfb; i++) {
+				if (thisChannel->is_info.is_used[i]) {
+					pred_sfb_flag[i] = 0;
+				}
 			}
 		}
-    }
 #endif
-    
-    cb_long=0;
-    for (i=0; i<nsfb; i++)
-      {
-	if (!pred_sfb_flag[i]) {
-	  for (j=cb_long; j<cb_long+isfb_width[i]; j++)
-	    sb_samples_pred[j]=0.0; 
-	}
-	cb_long+=isfb_width[i];
-      }
-    
-    /* Disable prediction for bands nsfb through SBMAX_L */ 
-    for (i=j;i<FLEN_LONG/2;i++) {
-      sb_samples_pred[i]=0.0;
-    }
-    for (i=nsfb;i<SBMAX_L;i++) {
-      pred_sfb_flag[i]=0;
-    }
-    
-    /* Is global enable set, if not enabled predicted samples are zeroed */
-    if(!pred_global_flag[0]) {
-      for (j=0; j<FLEN_LONG/2; j++)
-	sb_samples_pred[j]=0.0; 
-    }
-    for (j=0; j<FLEN_LONG/2; j++)
-      act_spec[j]-=sb_samples_pred[j];
-    
-  } else {
+		
+		cb_long=0;
+		for (i=0; i<nsfb; i++)
+		{
+			if (!pred_sfb_flag[i]) {
+				for (j=cb_long; j<cb_long+isfb_width[i]; j++)
+					sb_samples_pred[j]=0.0; 
+			}
+			cb_long+=isfb_width[i];
+		}
+		
+		/* Disable prediction for bands nsfb through SBMAX_L */ 
+		for (i=j;i<BLOCK_LEN_LONG;i++) {
+			sb_samples_pred[i]=0.0;
+		}
+		for (i=nsfb;i<SBMAX_L;i++) {
+			pred_sfb_flag[i]=0;
+		}
+		
+		/* Is global enable set, if not enabled predicted samples are zeroed */
+		if(!pred_global_flag[0]) {
+			for (j=0; j<BLOCK_LEN_LONG; j++)
+				sb_samples_pred[j]=0.0; 
+		}
+		for (j=0; j<BLOCK_LEN_LONG; j++)
+			act_spec[j]-=sb_samples_pred[j];
+		
+	} else {
 
-    /**************************************************/
-    /* Determine whether to enable/disable prediction */
-    /**************************************************/
-    
-    for (k=0; k<FLEN_LONG/2; k++)
-      {energy[k]=act_spec[k]*act_spec[k];
-       snr_p[k]=(act_spec[k]-sb_samples_pred[k])*(act_spec[k]-sb_samples_pred[k]);
-     }
-    
-    cb_long=0;
-    for (i=0; i<nsfb; i++)
-      {
-	pred_sfb_flag[i]=1;
-	temp1=0.0;
-	temp2=0.0;
-	for (j=cb_long; j<cb_long+isfb_width[i]; j++)
-	  {temp1+=energy[j]; temp2+=snr_p[j];}
-	if(temp2<1.e-20) temp2=1.e-20;
-	if(temp1!=0.0) {snr[i]=-10.*log10((double ) temp2/temp1);}
-	else snr[i]=0.0;
-	if(snr[i]<=0.0) {pred_sfb_flag[i]=0; 
-			 for (j=cb_long; j<cb_long+isfb_width[i]; j++)
-			   sb_samples_pred[j]=0.0; }
-	cb_long+=isfb_width[i];
-      }
-    
-    /* Disable prediction for bands nsfb through SBMAX_L */ 
-    for (i=j;i<FLEN_LONG/2;i++) {
-      sb_samples_pred[i]=0.0;
-    }
-    for (i=nsfb;i<SBMAX_L;i++) {
-      pred_sfb_flag[i]=0;
-    }
+		/**************************************************/
+		/* Determine whether to enable/disable prediction */
+		/**************************************************/
+		
+		for (k=0; k<BLOCK_LEN_LONG; k++) {
+			energy[k]=act_spec[k]*act_spec[k];
+			snr_p[k]=(act_spec[k]-sb_samples_pred[k])*(act_spec[k]-sb_samples_pred[k]);
+		}
+		
+		cb_long=0;
+		for (i=0; i<nsfb; i++) {
+			pred_sfb_flag[i]=1;
+			temp1=0.0;
+			temp2=0.0;
+			for (j=cb_long; j<cb_long+isfb_width[i]; j++) {
+				temp1+=energy[j];
+				temp2+=snr_p[j];
+			}
+			if(temp2<1.e-20)
+				temp2=1.e-20;
+			if(temp1!=0.0)
+				snr[i]=-10.*log10((double ) temp2/temp1);
+			else
+				snr[i]=0.0;
 
-    num_bit=0.0;
-    for (i=0; i<nsfb; i++)
-      if(snr[i]>0.0) num_bit+=snr[i]/6.*isfb_width[i];	
-    
-    /* Determine global enable, if not enabled predicted samples are zeroed */
-    pred_global_flag[0]=1;
-    if(num_bit<50) {
-      pred_global_flag[0]=0; num_bit=0.0; 
-      for (j=0; j<FLEN_LONG/2; j++)
-	sb_samples_pred[j]=0.0; 
-    }
-    for (j=0; j<FLEN_LONG/2; j++)
-      act_spec[j]-=sb_samples_pred[j];
-    
-  }
-  
-  /**********************************************************/
-  /* If this is a left channel, determine pred resets.      */
-  /* If this is a right channel, using pred reset data from */
-  /* left channel.  Keep left and right resets in sync.     */
-  /**********************************************************/
-  if ((thisChannel->cpe)&&( !(thisChannel->ch_is_left))) {
-    /*  if (!thisChannel->ch_is_left) {*/
-    /**********************************************************/
-    /* Using predictor reset data from the left channel.      */
-    /**********************************************************/
-    reset_count = &reset_count_mc[leftChanNum];
-    /* Reset the frame counter */
-    for (i=0;i<FLEN_LONG/2;i++) {
-      thisLineNeedsResetting[i]=0;
-    }
-    reset_group = &(coderInfo[chanNum].reset_group_number);
-    if (*reset_count % RESET_FRAME == 0)
-      { /* Send a reset in this frame */
-	*reset_group = *reset_count / 8;
-	for (i = *reset_group - 1; i < FLEN_LONG / 2; i += 30)
-	  {
-	    thisLineNeedsResetting[i]=1;
-	  }
-      }
-    else
-      *reset_group = -1;
-  } else {
-    /* Code segment added by JB */
-    /******************************************************************/
-    /* Determine whether a prediction reset is required - if so, then */
-    /* set reset flag for the appropriate group.                      */
-    /******************************************************************/
-    
-    /* Increase counter on left channel, keep left and right resets in sync */
-    (*reset_count)++;
+			if(snr[i]<=0.0) {
+				pred_sfb_flag[i]=0; 
+				for (j=cb_long; j<cb_long+isfb_width[i]; j++)
+					sb_samples_pred[j]=0.0;
+			}
+			cb_long+=isfb_width[i];
+		}
 
-    /* Reset the frame counter */
-    for (i=0;i<FLEN_LONG/2;i++) {
-      thisLineNeedsResetting[i]=0;
-    }
-    if (*reset_count >= 31 * RESET_FRAME)
-      *reset_count = RESET_FRAME;
-    if (*reset_count % RESET_FRAME == 0)
-      { /* Send a reset in this frame */
-	*reset_group = *reset_count / 8;
-	for (i = *reset_group - 1; i < FLEN_LONG / 2; i += 30)
-	  {
-	    thisLineNeedsResetting[i]=1;
-	  }
-      }
-    else
-      *reset_group = -1;
-    /* End of code segment */
- }
+		/* Disable prediction for bands nsfb through SBMAX_L */ 
+		for (i=j;i<BLOCK_LEN_LONG;i++) {
+			sb_samples_pred[i]=0.0;
+		}
+		for (i=nsfb;i<SBMAX_L;i++) {
+			pred_sfb_flag[i]=0;
+		}
 
+		num_bit=0.0;
+		for (i=0; i<nsfb; i++)
+			if(snr[i]>0.0)
+				num_bit+=snr[i]/6.*isfb_width[i];	
+			
+		/* Determine global enable, if not enabled predicted samples are zeroed */
+		pred_global_flag[0]=1;
+		if(num_bit<50) {
+			pred_global_flag[0]=0; num_bit=0.0; 
+			for (j=0; j<BLOCK_LEN_LONG; j++)
+				sb_samples_pred[j]=0.0; 
+		}
+		for (j=0; j<BLOCK_LEN_LONG; j++)
+			act_spec[j]-=sb_samples_pred[j];
+		
+	}
+	
+	/**********************************************************/
+	/* If this is a left channel, determine pred resets.      */
+	/* If this is a right channel, using pred reset data from */
+	/* left channel.  Keep left and right resets in sync.     */
+	/**********************************************************/
+	if ((thisChannel->cpe)&&( !(thisChannel->ch_is_left))) {
+		/*  if (!thisChannel->ch_is_left) {*/
+		/**********************************************************/
+		/* Using predictor reset data from the left channel.      */
+		/**********************************************************/
+		reset_count = &coderInfo[leftChanNum].bwpInfo.reset_count_mc;
+		/* Reset the frame counter */
+		for (i=0;i<BLOCK_LEN_LONG;i++) {
+			thisLineNeedsResetting[i]=0;
+		}
+		reset_group = &(coderInfo[chanNum].reset_group_number);
+		if (*reset_count % RESET_FRAME == 0)
+		{ /* Send a reset in this frame */
+			*reset_group = *reset_count / 8;
+			for (i = *reset_group - 1; i < BLOCK_LEN_LONG; i += 30)
+			{
+				thisLineNeedsResetting[i]=1;
+			}
+		}
+		else
+			*reset_group = -1;
+	} else {
+		/******************************************************************/
+		/* Determine whether a prediction reset is required - if so, then */
+		/* set reset flag for the appropriate group.                      */
+		/******************************************************************/
+		
+		/* Increase counter on left channel, keep left and right resets in sync */
+		(*reset_count)++;
 
-  /* Code segment added by JB */
+		/* Reset the frame counter */
+		for (i=0;i<BLOCK_LEN_LONG;i++) {
+			thisLineNeedsResetting[i]=0;
+		}
+		if (*reset_count >= 31 * RESET_FRAME)
+			*reset_count = RESET_FRAME;
+		if (*reset_count % RESET_FRAME == 0)
+		{ /* Send a reset in this frame */
+			*reset_group = *reset_count / 8;
+			for (i = *reset_group - 1; i < BLOCK_LEN_LONG; i += 30)
+			{
+				thisLineNeedsResetting[i]=1;
+			}
+		}
+		else
+			*reset_group = -1;
+	}
 
-  /* Ensure that prediction data is sent when there is a prediction
-   * reset.
-   */
-  if (*reset_group != -1 && pred_global_flag[0] == 0)
+
+	/* Ensure that prediction data is sent when there is a prediction
+	* reset.
+	*/
+	if (*reset_group != -1 && pred_global_flag[0] == 0)
     {
-      pred_global_flag[0] = 1;
-      for (i = 0; i < nsfb; i++)
-	pred_sfb_flag[i] = 0;
+		pred_global_flag[0] = 1;
+		for (i = 0; i < nsfb; i++)
+			pred_sfb_flag[i] = 0;
     }
-  /* End of code segment */
-  
 }
 
 
--- a/libfaac/backpred.h
+++ b/libfaac/backpred.h
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: backpred.h,v 1.1 2001/05/02 05:40:16 menno Exp $
+ * $Id: backpred.h,v 1.2 2001/05/18 13:38:19 menno Exp $
  */
 
 #ifndef _AAC_BACK_H_INCLUDED
@@ -26,27 +26,22 @@
 #define PRED_A		0.953125
 #define PRED_B		0.953125
 
-#define         FLEN_LONG              2048
-#define         SBMAX_L                49
-#define         LPC                    2
-#define         ALPHA                  PRED_ALPHA
-#define         A                      PRED_A
-#define         B                      PRED_B
-#define         MINVAR                 1.e-10
+#define ALPHA PRED_ALPHA
+#define A PRED_A
+#define B PRED_B
+#define MINVAR 1.e-10
 
 /* Reset every RESET_FRAME frames. */
-#define		RESET_FRAME	       8 
+#define RESET_FRAME 8
  
-int GetMaxPredSfb(int samplingRateIdx);
-
-void PredCalcPrediction( double *act_spec, 
-			 double *last_spec, 
-			 int btype, 
-			 int nsfb, 
-			 int *isfb_width,
-			 CoderInfo *coderInfo,
-			 ChannelInfo *channelInfo,
-			 int chanNum); 
+void PredCalcPrediction(double *act_spec,
+						double *last_spec,
+						int btype,
+						int nsfb,
+						int *isfb_width,
+						CoderInfo *coderInfo,
+						ChannelInfo *channelInfo,
+						int chanNum); 
 
 void PredInit();
 
--- a/libfaac/coder.h
+++ b/libfaac/coder.h
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: coder.h,v 1.6 2001/05/02 05:39:14 menno Exp $
+ * $Id: coder.h,v 1.7 2001/05/18 13:38:19 menno Exp $
  */
 
 #ifndef CODER_H
@@ -67,6 +67,8 @@
 #define CODESIZE 8
 #define NOK_LT_BLEN (3 * BLOCK_LEN_LONG)
 
+#define SBMAX_L 49
+#define LPC 2
 
 typedef struct {
 	int order;                           /* Filter order */
@@ -111,6 +113,18 @@
 	double *ltp_overlap_buffer;
 } LtpInfo;
 
+typedef struct
+{
+	int psy_init_mc;
+	double dr_mc[LPC][BLOCK_LEN_LONG],e_mc[LPC+1+1][BLOCK_LEN_LONG];
+	double K_mc[LPC+1][BLOCK_LEN_LONG], R_mc[LPC+1][BLOCK_LEN_LONG];
+	double VAR_mc[LPC+1][BLOCK_LEN_LONG], KOR_mc[LPC+1][BLOCK_LEN_LONG];
+	double sb_samples_pred_mc[BLOCK_LEN_LONG];
+	int thisLineNeedsResetting_mc[BLOCK_LEN_LONG];
+	int reset_count_mc;
+} BwpInfo;
+
+
 typedef struct {
 	int window_shape;
 	int prev_window_shape;
@@ -145,6 +159,7 @@
 
 	TnsInfo tnsInfo;
 	LtpInfo ltpInfo;
+	BwpInfo bwpInfo;
 
 	int max_pred_sfb;
 	int pred_global_flag;
--- a/libfaac/util.c
+++ b/libfaac/util.c
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: util.c,v 1.6 2001/02/28 18:39:34 menno Exp $
+ * $Id: util.c,v 1.7 2001/05/18 13:38:19 menno Exp $
  */
 
 #include <math.h>
@@ -55,6 +55,17 @@
 {
 	return 8000;
 }
+
+
+/* Max prediction band for backward predictionas function of fs index */
+const int MaxPredSfb[] = { 33, 33, 38, 40, 40, 40, 41, 41, 37, 37, 37, 34, 0 };
+
+int GetMaxPredSfb(int samplingRateIdx)
+{
+	return MaxPredSfb[samplingRateIdx];
+}
+
+
 
 /* Calculate bit_allocation based on PE */
 unsigned int BitAllocation(double pe, int short_block)
--- a/libfaac/util.h
+++ b/libfaac/util.h
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: util.h,v 1.5 2001/03/12 16:58:37 menno Exp $
+ * $Id: util.h,v 1.6 2001/05/18 13:38:19 menno Exp $
  */
 
 #ifndef UTIL_H
@@ -46,6 +46,7 @@
 #define SetMemory(block, value, size) memset(block, value, size)
 
 int GetSRIndex(unsigned int sampleRate);
+int GetMaxPredSfb(int samplingRateIdx);
 unsigned int MaxBitrate(unsigned long sampleRate);
 unsigned int MinBitrate();
 unsigned int MaxBitresSize(unsigned long bitRate, unsigned long sampleRate);
--- a/todo.txt
+++ b/todo.txt
@@ -10,6 +10,7 @@
 - DONE: Add backward prediction (MPEG2-AAC)????
 - DONE: Test (and maybe fix) sample rates other than 44100 Hz
 - DONE: Test (and maybe fix) multichannel and mono support
+- DONE: Figure out how to read and write ".mp4" format
 - Add PNS
 - Add IS
 - Add bit reservoir control
@@ -23,4 +24,3 @@
 - Improve command line tool (wildcards)
 - Write documentation for library interface
 - Speedup?? (no priority)
-- Figure out how to read and write ".mp4" format
\ No newline at end of file