📄 psymodel.c
字号:
/* * psymodel.c * * Copyright (c) 1999 Mark Taylor * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library 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. */#include "util.h"#include "encoder.h"#include "psymodel.h"#include "l3side.h"#include <assert.h>#include "tables.h"#include "fft.h"#ifdef M_LN10#define LN_TO_LOG10 (M_LN10/10)#else#define LN_TO_LOG10 0.2302585093#endifint L3para_read( lame_global_flags *gfp, FLOAT8 sfreq, int numlines[CBANDS],int numlines_s[CBANDS], FLOAT8 minval[CBANDS], FLOAT8 s3_l[CBANDS][CBANDS], FLOAT8 s3_s[CBANDS][CBANDS], FLOAT8 SNR_s[CBANDS], int bu_l[SBPSY_l], int bo_l[SBPSY_l], FLOAT8 w1_l[SBPSY_l], FLOAT8 w2_l[SBPSY_l], int bu_s[SBPSY_s], int bo_s[SBPSY_s], FLOAT8 w1_s[SBPSY_s], FLOAT8 w2_s[SBPSY_s], int *, int *, int *, int *); int L3psycho_anal( lame_global_flags *gfp, short int *buffer[2],int gr_out , FLOAT8 *ms_ratio, FLOAT8 *ms_ratio_next, FLOAT8 *ms_ener_ratio, III_psy_ratio masking_ratio[2][2], III_psy_ratio masking_MS_ratio[2][2], FLOAT8 percep_entropy[2],FLOAT8 percep_MS_entropy[2], int blocktype_d[2]){ lame_internal_flags *gfc=gfp->internal_flags;/* to get a good cache performance, one has to think about * the sequence, in which the variables are used. * (Note: these static variables have been moved to the gfc-> struct, * and their order in memory is layed out in util.h) */ /* fft and energy calculation */ FLOAT (*wsamp_l)[BLKSIZE]; FLOAT (*wsamp_s)[3][BLKSIZE_s]; FLOAT tot_ener[4]; /* convolution */ FLOAT8 eb[CBANDS]; FLOAT8 cb[CBANDS]; FLOAT8 thr[CBANDS]; /* ratios */ FLOAT8 ms_ratio_l=0,ms_ratio_s=0; /* block type */ int blocktype[2],uselongblock[2]; /* usual variables like loop indices, etc.. */ int numchn, chn, samplerate; int b, i, j, k; int sb,sblock; FLOAT cwlimit; /* use a simplified spreading function: */ /*#define NEWS3 */ #if 1 /* AAC values, results in more masking over MP3 values */# define TMN 18# define NMT 6#else /* MP3 values */# define TMN 29# define NMT 6#endif if(gfc->psymodel_init==0) { FLOAT8 SNR_s[CBANDS]; gfc->psymodel_init=1; samplerate = gfp->out_samplerate; switch(gfp->out_samplerate){ case 32000: break; case 44100: break; case 48000: break; case 16000: break; case 22050: break; case 24000: break; case 8000: samplerate *= 2; break; /* kludge so mpeg2.5 uses mpeg2 tables for now */ case 11025: samplerate *= 2; break; case 12000: samplerate *= 2; break; default: ERRORF("error, invalid sampling frequency: %d Hz\n", gfp->out_samplerate); return -1; } gfc->ms_ener_ratio_old=.25; gfc->blocktype_old[0]=STOP_TYPE; gfc->blocktype_old[1]=STOP_TYPE; gfc->blocktype_old[0]=SHORT_TYPE; gfc->blocktype_old[1]=SHORT_TYPE; for (i=0; i<4; ++i) { for (j=0; j<CBANDS; ++j) { gfc->nb_1[i][j]=1e20; gfc->nb_2[i][j]=1e20; } for ( sb = 0; sb < SBPSY_l; sb++ ) { gfc->en[i].l[sb] = 1e20; gfc->thm[i].l[sb] = 1e20; } for (j=0; j<3; ++j) { for ( sb = 0; sb < SBPSY_s; sb++ ) { gfc->en[i].s[sb][j] = 1e20; gfc->thm[i].s[sb][j] = 1e20; } } } /* gfp->cwlimit = sfreq*j/1024.0; */ gfc->cw_lower_index=6; if (gfp->cwlimit>0) cwlimit=gfp->cwlimit; else cwlimit=8.8717; gfc->cw_upper_index = cwlimit*1000.0*1024.0/((FLOAT8)samplerate); gfc->cw_upper_index=Min(HBLKSIZE-4,gfc->cw_upper_index); /* j+3 < HBLKSIZE-1 */ gfc->cw_upper_index=Max(6,gfc->cw_upper_index); for ( j = 0; j < HBLKSIZE; j++ ) gfc->cw[j] = 0.4; i=L3para_read( gfp,(FLOAT8) samplerate,gfc->numlines_l,gfc->numlines_s, gfc->minval,gfc->s3_l,gfc->s3_s,SNR_s,gfc->bu_l, gfc->bo_l,gfc->w1_l,gfc->w2_l, gfc->bu_s,gfc->bo_s, gfc->w1_s,gfc->w2_s,&gfc->npart_l_orig,&gfc->npart_l, &gfc->npart_s_orig,&gfc->npart_s ); if (i!=0) return -1; /* npart_l_orig = number of partition bands before convolution */ /* npart_l = number of partition bands after convolution */ for (i=0; i<gfc->npart_l; i++) { for (j = 0; j < gfc->npart_l_orig; j++) { if (gfc->s3_l[i][j] != 0.0) break; } gfc->s3ind[i][0] = j; for (j = gfc->npart_l_orig - 1; j > 0; j--) { if (gfc->s3_l[i][j] != 0.0) break; } gfc->s3ind[i][1] = j; } for (i=0; i<gfc->npart_s; i++) { for (j = 0; j < gfc->npart_s_orig; j++) { if (gfc->s3_s[i][j] != 0.0) break; } gfc->s3ind_s[i][0] = j; for (j = gfc->npart_s_orig - 1; j > 0; j--) { if (gfc->s3_s[i][j] != 0.0) break; } gfc->s3ind_s[i][1] = j; } /* #include "debugscalefac.c" */ #define rpelev 2#define rpelev2 16 /* compute norm_l, norm_s instead of relying on table data */ for ( b = 0;b < gfc->npart_l; b++ ) { FLOAT8 norm=0; for ( k = gfc->s3ind[b][0]; k <= gfc->s3ind[b][1]; k++ ) { norm += gfc->s3_l[b][k]; } for ( k = gfc->s3ind[b][0]; k <= gfc->s3ind[b][1]; k++ ) { gfc->s3_l[b][k] /= norm; } /*DEBUGF("%i norm=%f norm_l=%f \n",b,1/norm,norm_l[b]);*/ } for ( b = 0;b < gfc->npart_s; b++ ) { FLOAT8 norm=0; for ( k = gfc->s3ind_s[b][0]; k <= gfc->s3ind_s[b][1]; k++ ) { norm += gfc->s3_s[b][k]; } for ( k = gfc->s3ind_s[b][0]; k <= gfc->s3ind_s[b][1]; k++ ) { gfc->s3_s[b][k] *= SNR_s[b] / norm; } /*DEBUGF("%i norm=%f norm_s=%f \n",b,1/norm,norm_l[b]);*/ } init_fft(); } /************************* End of Initialization *****************************/ numchn = gfc->stereo; /* chn=2 and 3 = Mid and Side channels */ if (gfp->mode == MPG_MD_JOINT_STEREO) numchn=4; for (chn=0; chn<numchn; chn++) { /* there is a one granule delay. Copy maskings computed last call * into masking_ratio to return to calling program. */ if (chn<2) { /* LR maskings */ percep_entropy[chn] = gfc->pe[chn]; masking_ratio[gr_out][chn].thm = gfc->thm[chn]; masking_ratio[gr_out][chn].en = gfc->en[chn]; }else{ /* MS maskings */ percep_MS_entropy[chn-2] = gfc->pe[chn]; masking_MS_ratio[gr_out][chn-2].en = gfc->en[chn]; masking_MS_ratio[gr_out][chn-2].thm = gfc->thm[chn]; } /********************************************************************** * compute FFTs **********************************************************************/ wsamp_s = gfc->wsamp_S+(chn & 1); wsamp_l = gfc->wsamp_L+(chn & 1); if (chn<2) { fft_long ( *wsamp_l, chn, buffer); fft_short( *wsamp_s, chn, buffer); } /* FFT data for mid and side channel is derived from L & R */ if (chn == 2) { for (j = BLKSIZE-1; j >=0 ; --j) { FLOAT l = gfc->wsamp_L[0][j]; FLOAT r = gfc->wsamp_L[1][j]; gfc->wsamp_L[0][j] = (l+r)*(FLOAT)(SQRT2*0.5); gfc->wsamp_L[1][j] = (l-r)*(FLOAT)(SQRT2*0.5); } for (b = 2; b >= 0; --b) { for (j = BLKSIZE_s-1; j >= 0 ; --j) { FLOAT l = gfc->wsamp_S[0][b][j]; FLOAT r = gfc->wsamp_S[1][b][j]; gfc->wsamp_S[0][b][j] = (l+r)*(FLOAT)(SQRT2*0.5); gfc->wsamp_S[1][b][j] = (l-r)*(FLOAT)(SQRT2*0.5); } } } /********************************************************************** * compute energies **********************************************************************/ gfc->energy[0] = (*wsamp_l)[0]; gfc->energy[0] *= gfc->energy[0]; tot_ener[chn] = gfc->energy[0]; /* sum total energy at nearly no extra cost */ for (j=BLKSIZE/2-1; j >= 0; --j) { FLOAT re = (*wsamp_l)[BLKSIZE/2-j]; FLOAT im = (*wsamp_l)[BLKSIZE/2+j]; gfc->energy[BLKSIZE/2-j] = (re * re + im * im) * (FLOAT)0.5; if (BLKSIZE/2-j > 10) tot_ener[chn] += gfc->energy[BLKSIZE/2-j]; } for (b = 2; b >= 0; --b) { gfc->energy_s[b][0] = (*wsamp_s)[b][0]; gfc->energy_s[b][0] *= gfc->energy_s [b][0]; for (j=BLKSIZE_s/2-1; j >= 0; --j) { FLOAT re = (*wsamp_s)[b][BLKSIZE_s/2-j]; FLOAT im = (*wsamp_s)[b][BLKSIZE_s/2+j]; gfc->energy_s[b][BLKSIZE_s/2-j] = (re * re + im * im) * (FLOAT)0.5; } } if(gfp->gtkflag) { for (j=0; j<HBLKSIZE ; j++) { gfc->pinfo->energy[gr_out][chn][j]=gfc->energy_save[chn][j]; gfc->energy_save[chn][j]=gfc->energy[j]; } } /********************************************************************** * compute unpredicatability of first six spectral lines * **********************************************************************/ for ( j = 0; j < gfc->cw_lower_index; j++ ) { /* calculate unpredictability measure cw */ FLOAT an, a1, a2; FLOAT bn, b1, b2; FLOAT rn, r1, r2; FLOAT numre, numim, den; a2 = gfc-> ax_sav[chn][1][j]; b2 = gfc-> bx_sav[chn][1][j]; r2 = gfc-> rx_sav[chn][1][j]; a1 = gfc-> ax_sav[chn][1][j] = gfc-> ax_sav[chn][0][j]; b1 = gfc-> bx_sav[chn][1][j] = gfc-> bx_sav[chn][0][j]; r1 = gfc-> rx_sav[chn][1][j] = gfc-> rx_sav[chn][0][j]; an = gfc-> ax_sav[chn][0][j] = (*wsamp_l)[j]; bn = gfc-> bx_sav[chn][0][j] = j==0 ? (*wsamp_l)[0] : (*wsamp_l)[BLKSIZE-j]; rn = gfc-> rx_sav[chn][0][j] = sqrt(gfc->energy[j]); { /* square (x1,y1) */ if( r1 != 0 ) { numre = (a1*b1); numim = (a1*a1-b1*b1)*(FLOAT)0.5; den = r1*r1; } else { numre = 1; numim = 0; den = 1; } } { /* multiply by (x2,-y2) */ if( r2 != 0 ) { FLOAT tmp2 = (numim+numre)*(a2+b2)*(FLOAT)0.5; FLOAT tmp1 = -a2*numre+tmp2; numre = -b2*numim+tmp2; numim = tmp1; den *= r2; } else { /* do nothing */ } } { /* r-prime factor */ FLOAT tmp = (2*r1-r2)/den; numre *= tmp; numim *= tmp; } den=rn+fabs(2*r1-r2); if( den != 0 ) { numre = (an+bn)*(FLOAT)0.5-numre; numim = (an-bn)*(FLOAT)0.5-numim; den = sqrt(numre*numre+numim*numim)/den; } gfc->cw[j] = den; } /********************************************************************** * compute unpredicatibility of next 200 spectral lines * **********************************************************************/ for ( j = gfc->cw_lower_index; j < gfc->cw_upper_index; j += 4 ) {/* calculate unpredictability measure cw */ FLOAT rn, r1, r2; FLOAT numre, numim, den; k = (j+2) / 4; { /* square (x1,y1) */ r1 = gfc->energy_s[0][k]; if( r1 != 0 ) { FLOAT a1 = (*wsamp_s)[0][k]; FLOAT b1 = (*wsamp_s)[0][BLKSIZE_s-k]; /* k is never 0 */ numre = (a1*b1); numim = (a1*a1-b1*b1)*(FLOAT)0.5; den = r1; r1 = sqrt(r1); } else { numre = 1; numim = 0; den = 1; } } { /* multiply by (x2,-y2) */ r2 = gfc->energy_s[2][k]; if( r2 != 0 ) { FLOAT a2 = (*wsamp_s)[2][k]; FLOAT b2 = (*wsamp_s)[2][BLKSIZE_s-k]; FLOAT tmp2 = (numim+numre)*(a2+b2)*(FLOAT)0.5; FLOAT tmp1 = -a2*numre+tmp2; numre = -b2*numim+tmp2; numim = tmp1; r2 = sqrt(r2); den *= r2; } else { /* do nothing */ } } { /* r-prime factor */ FLOAT tmp = (2*r1-r2)/den; numre *= tmp; numim *= tmp; } rn = sqrt(gfc->energy_s[1][k]); den=rn+fabs(2*r1-r2); if( den != 0 ) { FLOAT an = (*wsamp_s)[1][k]; FLOAT bn = (*wsamp_s)[1][BLKSIZE_s-k]; numre = (an+bn)*(FLOAT)0.5-numre; numim = (an-bn)*(FLOAT)0.5-numim; den = sqrt(numre*numre+numim*numim)/den; } gfc->cw[j+1] = gfc->cw[j+2] = gfc->cw[j+3] = gfc->cw[j] = den; } #if 0 for ( j = 14; j < HBLKSIZE-4; j += 4 ) {/* calculate energy from short ffts */ FLOAT8 tot,ave; k = (j+2) / 4; for (tot=0, sblock=0; sblock < 3; sblock++) tot+=gfc->energy_s[sblock][k]; ave = gfc->energy[j+1]+ gfc->energy[j+2]+ gfc->energy[j+3]+ gfc->energy[j]; ave /= 4.; /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -