ref: 4da5aaebe94a8a13ceea2c001b1fd5161ef33e9b
parent: 07a18e8f102dd3d94d93f8f65da5da2f293ca294
author: menno <menno>
date: Wed May 2 01:40:16 EDT 2001
Added support for MAIN AAC object type
--- a/frontend/main.c
+++ b/frontend/main.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: main.c,v 1.14 2001/04/19 13:20:33 menno Exp $
+ * $Id: main.c,v 1.15 2001/05/02 05:39:14 menno Exp $
*/
#ifdef _WIN32
@@ -74,7 +74,7 @@
{
printf("USAGE: %s -options infile outfile\n", argv[0]);
printf("Options:\n");
- printf(" -pX AAC object type, X=LC2 gives MPEG2 LC,");
+ printf(" -pX AAC object type, X=LC2 gives MPEG2 LC,\n");
printf(" X=LC4 gives MPEG4 LC and X=LTP gives LTP\n");
printf(" -nm Don\'t use mid/side coding\n");
printf(" -tns Use TNS coding\n");
--- /dev/null
+++ b/libfaac/backpred.c
@@ -1,0 +1,426 @@
+/*
+ * FAAC - Freeware Advanced Audio Coder
+ * Copyright (C) 2001 Menno Bakker
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * 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 $
+ */
+
+/**********************************************************************
+
+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 "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)
+{
+ return MAX_PRED_SFB[samplingRateIdx][1];
+}
+
+
+
+void PredInit()
+{
+ int i;
+
+ for (i=0;i<MAX_CHANNELS;i++) {
+ psy_init_mc[i] = 0;
+ reset_count_mc[i] = 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)
+{
+ 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;
+
+ /* 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 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];
+
+ 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 (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;
+ }
+
+
+ /**************************************************/
+ /* Compute state using last_spec */
+ /**************************************************/
+ for (i=0;i<FLEN_LONG/2;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];
+ }
+
+
+ /**************************************************/
+ /* 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;
+ }
+ }
+ }
+
+
+
+ /**************************************************/
+ /* Compute predictor coefficients, predicted data */
+ /**************************************************/
+ for (i=0;i<FLEN_LONG/2;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 (k=0; k<FLEN_LONG/2; 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 (isRightWithCommonWindow) {
+
+ /**************************************************/
+ /* Use predictor data from the left channel. */
+ /**************************************************/
+ CopyPredInfo(&(coderInfo[chanNum]),&(coderInfo[leftChanNum]));
+
+ /* 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;
+ }
+ }
+ }
+#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 {
+
+ /**************************************************/
+ /* 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;
+ }
+
+ 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)++;
+
+ /* 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 */
+ }
+
+
+ /* Code segment added by JB */
+
+ /* 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;
+ }
+ /* End of code segment */
+
+}
+
+
+void CopyPredInfo(CoderInfo *right, CoderInfo *left)
+{
+ int band;
+
+ right->pred_global_flag = left->pred_global_flag;
+ right->reset_group_number = left->reset_group_number;
+
+ for (band = 0; band<MAX_SCFAC_BANDS; band++) {
+ right->pred_sfb_flag[band] = left->pred_sfb_flag[band];
+ }
+}
+
+
+
+
--- /dev/null
+++ b/libfaac/backpred.h
@@ -1,0 +1,56 @@
+/*
+ * FAAC - Freeware Advanced Audio Coder
+ * Copyright (C) 2001 Menno Bakker
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * 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 $
+ */
+
+#ifndef _AAC_BACK_H_INCLUDED
+#define _AAC_BACK_H_INCLUDED
+
+#define PRED_ALPHA 0.90625
+#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
+
+/* Reset every RESET_FRAME frames. */
+#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 PredInit();
+
+void CopyPredInfo(CoderInfo *right, CoderInfo *left);
+
+
+#endif
--- a/libfaac/bitstream.c
+++ b/libfaac/bitstream.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: bitstream.c,v 1.13 2001/04/19 13:20:34 menno Exp $
+ * $Id: bitstream.c,v 1.14 2001/05/02 05:39:14 menno Exp $
*/
#include <stdlib.h>
@@ -54,6 +54,7 @@
bits += WriteLFE(&coderInfo[channel],
&channelInfo[channel],
bitStream,
+ hEncoder->config.aacObjectType,
1);
} else {
/* Write out sce */
@@ -60,6 +61,7 @@
bits += WriteSCE(&coderInfo[channel],
&channelInfo[channel],
bitStream,
+ hEncoder->config.aacObjectType,
1);
}
@@ -71,6 +73,7 @@
&coderInfo[channelInfo[channel].paired_ch],
&channelInfo[channel],
bitStream,
+ hEncoder->config.aacObjectType,
1);
}
}
@@ -130,6 +133,7 @@
bits += WriteLFE(&coderInfo[channel],
&channelInfo[channel],
bitStream,
+ hEncoder->config.aacObjectType,
0);
} else {
/* Write out sce */
@@ -136,6 +140,7 @@
bits += WriteSCE(&coderInfo[channel],
&channelInfo[channel],
bitStream,
+ hEncoder->config.aacObjectType,
0);
}
@@ -147,6 +152,7 @@
&coderInfo[channelInfo[channel].paired_ch],
&channelInfo[channel],
bitStream,
+ hEncoder->config.aacObjectType,
0);
}
}
@@ -230,6 +236,7 @@
CoderInfo *coderInfoR,
ChannelInfo *channelInfo,
BitStream* bitStream,
+ int objectType,
int writeFlag)
{
int bits = 0;
@@ -253,7 +260,7 @@
if (channelInfo->common_window) {
int numWindows, maxSfb;
- bits += WriteICSInfo(coderInfoL, bitStream, writeFlag);
+ bits += WriteICSInfo(coderInfoL, bitStream, objectType, writeFlag);
numWindows = coderInfoL->num_window_groups;
maxSfb = coderInfoL->max_sfb;
@@ -275,8 +282,8 @@
}
/* Write individual_channel_stream elements */
- bits += WriteICS(coderInfoL, bitStream, channelInfo->common_window, writeFlag);
- bits += WriteICS(coderInfoR, bitStream, channelInfo->common_window, writeFlag);
+ bits += WriteICS(coderInfoL, bitStream, channelInfo->common_window, objectType, writeFlag);
+ bits += WriteICS(coderInfoR, bitStream, channelInfo->common_window, objectType, writeFlag);
return bits;
}
@@ -284,6 +291,7 @@
static int WriteSCE(CoderInfo *coderInfo,
ChannelInfo *channelInfo,
BitStream *bitStream,
+ int objectType,
int writeFlag)
{
int bits = 0;
@@ -300,7 +308,7 @@
bits += LEN_TAG;
/* Write an Individual Channel Stream element */
- bits += WriteICS(coderInfo, bitStream, 0, writeFlag);
+ bits += WriteICS(coderInfo, bitStream, 0, objectType, writeFlag);
return bits;
}
@@ -308,6 +316,7 @@
static int WriteLFE(CoderInfo *coderInfo,
ChannelInfo *channelInfo,
BitStream *bitStream,
+ int objectType,
int writeFlag)
{
int bits = 0;
@@ -324,7 +333,7 @@
bits += LEN_TAG;
/* Write an individual_channel_stream element */
- bits += WriteICS(coderInfo, bitStream, 0, writeFlag);
+ bits += WriteICS(coderInfo, bitStream, 0, objectType, writeFlag);
return bits;
}
@@ -331,6 +340,7 @@
static int WriteICSInfo(CoderInfo *coderInfo,
BitStream *bitStream,
+ int objectType,
int writeFlag)
{
int grouping_bits;
@@ -365,8 +375,10 @@
PutBit(bitStream, coderInfo->max_sfb, LEN_MAX_SFBL);
}
bits += LEN_MAX_SFBL;
- bits += WriteLTPPredictorData(coderInfo, bitStream, writeFlag);
- /* bits += WritePredictorData(coderInfo, bitStream, writeFlag); */
+ if (objectType == LTP)
+ bits += WriteLTPPredictorData(coderInfo, bitStream, writeFlag);
+ else
+ bits += WritePredictorData(coderInfo, bitStream, writeFlag);
}
return bits;
@@ -375,6 +387,7 @@
static int WriteICS(CoderInfo *coderInfo,
BitStream *bitStream,
int commonWindow,
+ int objectType,
int writeFlag)
{
/* this function writes out an individual_channel_stream to the bitstream and */
@@ -388,7 +401,7 @@
/* Write ics information */
if (!commonWindow) {
- bits += WriteICSInfo(coderInfo, bitStream, writeFlag);
+ bits += WriteICSInfo(coderInfo, bitStream, objectType, writeFlag);
}
bits += SortBookNumbers(coderInfo, bitStream, writeFlag);
@@ -446,6 +459,42 @@
}
return (bits);
+}
+
+static int WritePredictorData(CoderInfo *coderInfo,
+ BitStream *bitStream,
+ int writeFlag)
+{
+ int bits = 0;
+
+ /* Write global predictor data present */
+ short predictorDataPresent = coderInfo->pred_global_flag;
+ int numBands = min(coderInfo->max_pred_sfb, coderInfo->nr_of_sfb);
+
+ if (writeFlag) {
+ PutBit(bitStream, predictorDataPresent, LEN_PRED_PRES); /* predictor_data_present */
+ if (predictorDataPresent) {
+ int b;
+ if (coderInfo->reset_group_number == -1) {
+ PutBit(bitStream, 0, LEN_PRED_RST); /* No prediction reset */
+ } else {
+ PutBit(bitStream, 1, LEN_PRED_RST);
+ PutBit(bitStream, (unsigned long)coderInfo->reset_group_number,
+ LEN_PRED_RSTGRP);
+ }
+
+ for (b=0;b<numBands;b++) {
+ PutBit(bitStream, coderInfo->pred_sfb_flag[b], LEN_PRED_ENAB);
+ }
+ }
+ }
+ bits = LEN_PRED_PRES;
+ bits += (predictorDataPresent) ?
+ (LEN_PRED_RST +
+ ((coderInfo->reset_group_number)!=-1)*LEN_PRED_RSTGRP +
+ numBands*LEN_PRED_ENAB) : 0;
+
+ return bits;
}
static int WritePulseData(CoderInfo *coderInfo,
--- a/libfaac/bitstream.h
+++ b/libfaac/bitstream.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: bitstream.h,v 1.5 2001/04/19 13:20:34 menno Exp $
+ * $Id: bitstream.h,v 1.6 2001/05/02 05:39:14 menno Exp $
*/
#ifndef BITSTREAM_H
@@ -144,30 +144,39 @@
CoderInfo *coderInfoR,
ChannelInfo *channelInfo,
BitStream* bitStream,
+ int objectType,
int writeFlag);
static int WriteSCE(CoderInfo *coderInfo,
ChannelInfo *channelInfo,
BitStream *bitStream,
+ int objectType,
int writeFlag);
static int WriteLFE(CoderInfo *coderInfo,
ChannelInfo *channelInfo,
BitStream *bitStream,
+ int objectType,
int writeFlag);
static int WriteICSInfo(CoderInfo *coderInfo,
BitStream *bitStream,
+ int objectType,
int writeFlag);
static int WriteICS(CoderInfo *coderInfo,
BitStream *bitStream,
int commonWindow,
+ int objectType,
int writeFlag);
static int WriteLTPPredictorData(CoderInfo *coderInfo,
BitStream *bitStream,
int writeFlag);
+
+static int WritePredictorData(CoderInfo *coderInfo,
+ BitStream *bitStream,
+ int writeFlag);
static int WritePulseData(CoderInfo *coderInfo,
BitStream *bitStream,
--- 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.5 2001/04/11 13:50:31 menno Exp $
+ * $Id: coder.h,v 1.6 2001/05/02 05:39:14 menno Exp $
*/
#ifndef CODER_H
@@ -52,7 +52,6 @@
#define LEN_TNS_NFILTL 2
#define LEN_TNS_NFILTS 1
-#define LPC 1
#define DELAY 2048
#define LEN_LTP_DATA_PRESENT 1
#define LEN_LTP_LAG 11
@@ -146,6 +145,11 @@
TnsInfo tnsInfo;
LtpInfo ltpInfo;
+
+ int max_pred_sfb;
+ int pred_global_flag;
+ int pred_sfb_flag[MAX_SCFAC_BANDS];
+ int reset_group_number;
} CoderInfo;
--- a/libfaac/frame.c
+++ b/libfaac/frame.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: frame.c,v 1.18 2001/04/19 13:20:34 menno Exp $
+ * $Id: frame.c,v 1.19 2001/05/02 05:39:14 menno Exp $
*/
/*
@@ -24,6 +24,7 @@
* 2001/01/17: menno: Added frequency cut off filter.
* 2001/02/28: menno: Added Temporal Noise Shaping.
* 2001/03/05: menno: Added Long Term Prediction.
+ * 2001/05/01: menno: Added backward prediction.
*
*/
@@ -42,6 +43,7 @@
#include "psych.h"
#include "tns.h"
#include "ltp.h"
+#include "backpred.h"
faacEncConfigurationPtr FAACAPI faacEncGetCurrentConfiguration(faacEncHandle hEncoder)
@@ -60,10 +62,14 @@
hEncoder->config.aacObjectType = config->aacObjectType;
hEncoder->config.mpegVersion = config->mpegVersion;
- /* No SSR / MAIN supported for now */
- if ((hEncoder->config.aacObjectType != LTP)&&(hEncoder->config.aacObjectType != LOW))
+ /* No SSR supported for now */
+ if (hEncoder->config.aacObjectType == SSR)
return 0;
+ /* LTP only with MPEG4 */
+ if ((hEncoder->config.aacObjectType == LTP) && (hEncoder->config.mpegVersion != MPEG4))
+ return 0;
+
/* Re-init TNS for new profile */
TnsInit(hEncoder);
@@ -121,6 +127,9 @@
hEncoder->coderInfo[channel].num_window_groups = 1;
hEncoder->coderInfo[channel].window_group_length[0] = 1;
+ /* FIXME: Use sr_idx here */
+ hEncoder->coderInfo[channel].max_pred_sfb = GetMaxPredSfb(hEncoder->sampleRateIdx);
+
hEncoder->sampleBuff[channel] = NULL;
hEncoder->nextSampleBuff[channel] = NULL;
hEncoder->next2SampleBuff[channel] = NULL;
@@ -138,6 +147,8 @@
LtpInit(hEncoder);
+ PredInit();
+
AACQuantizeInit(hEncoder->coderInfo, hEncoder->numChannels);
HuffmanInit(hEncoder->coderInfo, hEncoder->numChannels);
@@ -360,6 +371,24 @@
}
}
+ for(channel = 0; channel < numChannels; channel++)
+ {
+ if ((aacObjectType == MAIN) && (!channelInfo[channel].lfe)) {
+ int numPredBands = min(coderInfo[channel].max_pred_sfb, coderInfo[channel].nr_of_sfb);
+ PredCalcPrediction(hEncoder->freqBuff[channel],
+ coderInfo[channel].requantFreq,
+ coderInfo[channel].block_type,
+ numPredBands,
+ (coderInfo[channel].block_type==ONLY_SHORT_WINDOW)?
+ hEncoder->srInfo->cb_width_short:hEncoder->srInfo->cb_width_long,
+ coderInfo,
+ channelInfo,
+ channel);
+ } else {
+ coderInfo[channel].pred_global_flag = 0;
+ }
+ }
+
MSEncode(coderInfo, channelInfo, hEncoder->freqBuff, numChannels, allowMidside);
/* Quantize and code the signal */
@@ -393,7 +422,7 @@
else
tnsDecInfo = NULL;
- if ((!channelInfo[channel].lfe) && (mpegVersion == MPEG4) && (aacObjectType == LTP)) { /* no reconstruction needed for LFE channel*/
+ if ((!channelInfo[channel].lfe) && (aacObjectType == LTP)) { /* no reconstruction needed for LFE channel*/
LtpReconstruct(&coderInfo[channel], &(coderInfo[channel].ltpInfo),
coderInfo[channel].requantFreq);
--- a/libfaac/libfaac.dsp
+++ b/libfaac/libfaac.dsp
@@ -89,6 +89,10 @@
# End Source File
# Begin Source File
+SOURCE=.\backpred.c
+# End Source File
+# Begin Source File
+
SOURCE=.\bitstream.c
# End Source File
# Begin Source File
@@ -138,6 +142,10 @@
# Begin Source File
SOURCE=.\aacquant.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\backpred.h
# End Source File
# Begin Source File
--- a/todo.txt
+++ b/todo.txt
@@ -7,8 +7,10 @@
- DONE: Write GUI
- DONE: Add TNS
- DONE: Add LTP
+- 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
- Add PNS
-- Add backward prediction (MPEG2-AAC)????
- Add IS
- Add bit reservoir control
- Add pulse coding
@@ -18,8 +20,6 @@
- Clean up psychoacoustics code
- Better grouping support
- Add Window shape switching
-- Test (and maybe fix) sample rates other than 44100 Hz
-- Test (and maybe fix) multichannel and mono support
- Improve command line tool (wildcards)
- Write documentation for library interface
- Speedup?? (no priority)