backpred.c
资源名称:NETVIDEO.rar [点击查看]
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:11k
源码类别:
流媒体/Mpeg4/MP4
开发平台:
Visual C++
- /*
- * FAAC - Freeware Advanced Audio Coder
- * Copyright (C) 2001 Menno Bakker
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: backpred.c,v 1.3 2001/06/04 23:02:24 wmay Exp $
- */
- #include <math.h>
- #include "frame.h"
- #include "coder.h"
- #include "channels.h"
- #include "backpred.h"
- void PredInit(faacEncHandle hEncoder)
- {
- unsigned int channel;
- for (channel = 0; channel < hEncoder->numChannels; channel++) {
- BwpInfo *bwpInfo = &(hEncoder->coderInfo[channel].bwpInfo);
- 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,
- int chanNum)
- {
- 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;
- 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 = &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));
- 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;
- }
- return;
- }
- /**************************************************/
- /* 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];
- }
- 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<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<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 (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];
- }
- /***********************************************************/
- /* 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<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<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;
- 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<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)++;
- /* 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)
- {
- pred_global_flag[0] = 1;
- for (i = 0; i < nsfb; i++)
- pred_sfb_flag[i] = 0;
- }
- }
- 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];
- }
- }