⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 psymodel.c

📁 音频编码
💻 C
📖 第 1 页 / 共 4 页
字号:
	while (--kk > 0)	    ecb += fftenergy_s[sblock][j++];	eb[b] = ecb;    }    for (j = b = 0; b < gfc->npart_s; b++) {	int kk = gfc->s3ind_s[b][0];	FLOAT ecb = gfc->s3_ss[j++] * eb[kk++];	while (kk <= gfc->s3ind_s[b][1])	    ecb += gfc->s3_ss[j++] * eb[kk++];	thr[b] = Min( ecb, rpelev_s  * gfc->nb_s1[chn][b] );	if (gfc->blocktype_old[chn & 1] == SHORT_TYPE ) {	    thr[b] = Min(thr[b], rpelev2_s * gfc->nb_s2[chn][b]);	}	thr[b] = Max( thr[b],                  Min(gfc->ATH->cb[gfc->bm_s[b]] * athlower,                      thr[b] * 2) );	gfc->nb_s2[chn][b] = gfc->nb_s1[chn][b];	gfc->nb_s1[chn][b] = ecb;    assert( thr[b] >= 0 );    }}static voidblock_type_set(    lame_global_flags * gfp,    int *uselongblock,    int *blocktype_d,    int *blocktype    ){    lame_internal_flags *gfc=gfp->internal_flags;    int chn;    if (gfp->short_blocks == short_block_coupled	/* force both channels to use the same block type */	/* this is necessary if the frame is to be encoded in ms_stereo.  */	/* But even without ms_stereo, FhG  does this */	&& !(uselongblock[0] && uselongblock[1]))        uselongblock[0] = uselongblock[1] = 0;    /* update the blocktype of the previous granule, since it depends on what     * happend in this granule */    for (chn=0; chn<gfc->channels_out; chn++) {	blocktype[chn] = NORM_TYPE;	/* disable short blocks */	if (gfp->short_blocks == short_block_dispensed)	    uselongblock[chn]=1;	if (gfp->short_blocks == short_block_forced)	    uselongblock[chn]=0;	if (uselongblock[chn]) {	    /* no attack : use long blocks */	    assert( gfc->blocktype_old[chn] != START_TYPE );	    if (gfc->blocktype_old[chn] == SHORT_TYPE)		blocktype[chn] = STOP_TYPE;	} else {	    /* attack : use short blocks */	    blocktype[chn] = SHORT_TYPE;	    if (gfc->blocktype_old[chn] == NORM_TYPE) {		gfc->blocktype_old[chn] = START_TYPE;	    }	    if (gfc->blocktype_old[chn] == STOP_TYPE)		gfc->blocktype_old[chn] = SHORT_TYPE;	}	blocktype_d[chn] = gfc->blocktype_old[chn];  /* value returned to calling program */	gfc->blocktype_old[chn] = blocktype[chn];    /* save for next call to l3psy_anal */    }}static void determine_block_type( lame_global_flags * gfp, FLOAT fftenergy_s[3][HBLKSIZE_s], int uselongblock[],    int chn, int gr_out, FLOAT* pe ){    lame_internal_flags* gfc = gfp->internal_flags;    int j;	/*************************************************************** 	 * determine the block type (window type) based on L & R channels	 ***************************************************************/	/* compute PE for all 4 channels */	    FLOAT mn,mx,ma=0,mb=0,mc=0;            for ( j = HBLKSIZE_s/2; j < HBLKSIZE_s; j ++) {		ma += fftenergy_s[0][j];		mb += fftenergy_s[1][j];		mc += fftenergy_s[2][j];	    }	    mn = Min(ma,mb);	    mn = Min(mn,mc);	    mx = Max(ma,mb);	    mx = Max(mx,mc);#if defined(HAVE_GTK)	    if (gfp->analysis) {		gfc->pinfo->ers[gr_out][chn]=gfc->ers_save[chn];		gfc->ers_save[chn]=(mx/(1e-12+mn));	    }#endif	    /* bit allocation is based on pe.  */	    if (mx>mn) {		FLOAT tmp = FAST_LOG_X(mx/(1e-12+mn), 400.0);		if (tmp > *pe) *pe = tmp;	    }	    /* block type is based just on L or R channel */      	    if (chn<2) {		uselongblock[chn] = 1;		/* tuned for t1.wav.  doesnt effect most other samples */		if (*pe > 3000) 		    uselongblock[chn]=0;			if ( mx > 30*mn ) 		{/* big surge of energy - always use short blocks */		    uselongblock[chn] = 0;		}		else if ((mx > 10*mn) && (*pe > 1000))		{/* medium surge, medium pe - use short blocks */		    uselongblock[chn] = 0;		}	    }}int L3psycho_anal( lame_global_flags * gfp,                    const sample_t *buffer[2], int gr_out,                     FLOAT *ms_ratio,                    FLOAT *ms_ratio_next,		    III_psy_ratio masking_ratio[2][2],		    III_psy_ratio masking_MS_ratio[2][2],		    FLOAT percep_entropy[2],FLOAT percep_MS_entropy[2],                     FLOAT energy[4],                    int blocktype_d[2]){    lame_internal_flags *gfc=gfp->internal_flags;    /* fft and energy calculation   */    FLOAT wsamp_L[2][BLKSIZE];    FLOAT wsamp_S[2][3][BLKSIZE_s];    FLOAT fftenergy[HBLKSIZE];    FLOAT fftenergy_s[3][HBLKSIZE_s];    /* convolution   */    FLOAT eb[CBANDS+1];    FLOAT cb[CBANDS];    FLOAT thr[CBANDS+1];    /* ratios    */    FLOAT ms_ratio_l=0, ms_ratio_s=0;    /* block type  */    int blocktype[2],uselongblock[2];    /* usual variables like loop indices, etc..    */    int numchn, chn;    int b, i, j, k;    int sb,sblock;    /*  rh 20040301: the following loops do access one off the limits     *  so I increase  the array dimensions by one and initialize the     *  accessed values to zero     */    assert( gfc->npart_s <= CBANDS );    assert( gfc->npart_l <= CBANDS );    eb [gfc->npart_s] = 0;    thr[gfc->npart_s] = 0;    eb [gfc->npart_l] = 0;    thr[gfc->npart_l] = 0;    numchn = gfc->channels_out;    /* chn=2 and 3 = Mid and Side channels */    if (gfp->mode == JOINT_STEREO) numchn=4;    for (chn=0; chn<numchn; chn++) {	FLOAT (*wsamp_l)[BLKSIZE];	FLOAT (*wsamp_s)[3][BLKSIZE_s];	energy[chn] = gfc->tot_ener[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]  .en  = gfc -> en  [chn];	    masking_ratio    [gr_out] [chn]  .thm = gfc -> thm [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 = wsamp_S+(chn & 1);	wsamp_l = wsamp_L+(chn & 1);	compute_ffts(gfp, fftenergy, fftenergy_s,		     wsamp_l, wsamp_s, gr_out, chn, buffer);	/*********************************************************************	 *    compute unpredicatability of first six spectral lines	 *********************************************************************/	for ( j = 0; j < CW_LOWER_INDEX; j++ ) {	    /* calculate unpredictability measure cw */	    FLOAT a2, b2, 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];	    r1 = gfc-> rx_sav[chn][1][j] = gfc-> rx_sav[chn][0][j];	    /* square (x1,y1) */	    if (r1 != 0.0) {		FLOAT a1 = gfc-> ax_sav[chn][1][j] = gfc-> ax_sav[chn][0][j];		FLOAT b1 = gfc-> bx_sav[chn][1][j] = gfc-> bx_sav[chn][0][j];		den = r1*r1;		numre = a1*b1;		numim = den-b1*b1;	    } else {		/* no aging is needed for ax_sav[chn][0][j] and that of bx		   because if r1=0, r2 should be 0 for next time. */		den = numre = 1.0;		numim = 0.0;	    }	    /* multiply by (x2,-y2) */	    if (r2 != 0.0) {		FLOAT tmp2 = (numim+numre)*(a2+b2)*0.5f;		FLOAT tmp1 = -a2*numre+tmp2;		numre =      -b2*numim+tmp2;		numim = tmp1;		den *= r2;	    }	    r1 = 2.0f*r1-r2;	    r2 = gfc-> rx_sav[chn][0][j] = sqrt(fftenergy[j]);	    r2 = r2+fabs(r1);	    if (r2 != 0) {		FLOAT an = gfc-> ax_sav[chn][0][j] = wsamp_l[0][j];		FLOAT bn = gfc-> bx_sav[chn][0][j] = j==0 ? wsamp_l[0][0] : wsamp_l[0][BLKSIZE-j];  		den = r1/den*2.0;		numre = (an+bn)-numre*den;		numim = (an-bn)-numim*den;		r2 = sqrt(numre*numre+numim*numim)/(r2*2.0);	    }	    gfc->cw[j] = r2;	}	/**********************************************************************	 *     compute unpredicatibility of next 200 spectral lines	 *********************************************************************/	for (; 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 = fftenergy_s[0][k];	    if (r1 != 0.0) {		FLOAT a1 = (*wsamp_s)[0][k]; 		FLOAT b1 = (*wsamp_s)[0][BLKSIZE_s-k]; /* k is never 0 */		numre = a1*b1;		numim = r1-b1*b1;		den = r1;		r1 = sqrt(r1);	    } else {		den = numre = 1.0;		numim = 0.0;	    }	    /* multiply by (x2,-y2) */	    r2 = fftenergy_s[2][k];	    if (r2 != 0.0) {		FLOAT a2 = (*wsamp_s)[2][k]; 		FLOAT b2 = (*wsamp_s)[2][BLKSIZE_s-k];		FLOAT tmp2 = (numim+numre)*(a2+b2)*0.5f;		FLOAT tmp1 = tmp2-a2*numre;		numre =      tmp2-b2*numim;		numim = tmp1;		r2 = sqrt(r2);		den *= r2;	    }	    /* r-prime factor */	    rn = sqrt(fftenergy_s[1][k])+fabs(2*r1-r2);	    if (rn != 0) {		FLOAT an = (*wsamp_s)[1][k]; 		FLOAT bn = (*wsamp_s)[1][BLKSIZE_s-k];		den = (2*r1-r2)/den*2.0f;		numre = (an+bn)-numre*den;		numim = (an-bn)-numim*den;		rn = sqrt(numre*numre+numim*numim)/(rn*2.0f);	    }	    gfc->cw[j+1] = gfc->cw[j+2] = gfc->cw[j+3] = gfc->cw[j] = rn;	}	/**********************************************************************	 *    Calculate the energy and the unpredictability in the threshold	 *    calculation partitions	 *********************************************************************/	b = 0;	for (j = 0; j < gfc->cw_upper_index		 && gfc->numlines_l[b] && b < gfc->npart_l; ) {	    FLOAT ebb, cbb;	    ebb = NON_LINEAR_SCALE_ITEM(fftenergy[j]);	    cbb = NON_LINEAR_SCALE_ITEM(fftenergy[j] * gfc->cw[j]);	    j++;	    for (i = gfc->numlines_l[b] - 1; i > 0; i--) {		ebb += NON_LINEAR_SCALE_ITEM(fftenergy[j]);		/* XXX: should "* gfc->cw[j])" be outside of the scaling? */		cbb += NON_LINEAR_SCALE_ITEM(fftenergy[j] * gfc->cw[j]);		j++;	    }	    eb[b] = NON_LINEAR_SCALE_SUM(ebb);	    cb[b] = NON_LINEAR_SCALE_SUM(cbb);	    b++;	}	for (; b < gfc->npart_l; b++ ) {	    FLOAT ebb = NON_LINEAR_SCALE_ITEM(fftenergy[j++]);	    assert(gfc->numlines_l[b]);	    for (i = gfc->numlines_l[b] - 1; i > 0; i--) {		ebb += NON_LINEAR_SCALE_ITEM(fftenergy[j++]);	    }	    eb[b] = NON_LINEAR_SCALE_SUM(ebb);	    /* XXX: should the "* .4" be outside of the scaling? */	    cb[b] = NON_LINEAR_SCALE_SUM(ebb * 0.4);	}	/**********************************************************************	 *      convolve the partitioned energy and unpredictability	 *      with the spreading function, s3_l[b][k](packed into s3_ll)	 *********************************************************************/	/*  calculate percetual entropy */	gfc->pe[chn] = 0;	k = 0;	for ( b = 0;b < gfc->npart_l; b++ ) {	    FLOAT tbb,ecb,ctb;	    int kk;	    ecb = ctb = 0.;	    for (kk = gfc->s3ind[b][0]; kk <= gfc->s3ind[b][1]; kk++ ) {		/* sprdngf for Layer III */		ecb += gfc->s3_ll[k] * eb[kk];		ctb += gfc->s3_ll[k] * cb[kk];		k++;	    }/* calculate the tonality of each threshold calculation partition  * calculate the SNR in each threshold calculation partition  * tonality = -0.299 - .43*log(ctb/ecb); * tonality = 0:           use NMT   (lots of masking) * tonality = 1:           use TMN   (little masking) */	    tbb = ecb;	    if (tbb != 0.0) {		tbb = ctb / tbb;		/* convert to tonality index */		/* tonality small:   tbb=1 */		/* tonality large:   tbb=-.299 */		tbb = CONV1 + FAST_LOG_X(tbb, CONV2);		if (tbb < 0.0) tbb = exp(-LN_TO_LOG10*NMT);		else if (tbb > 1.0) tbb = exp(-LN_TO_LOG10*TMN);		else tbb = exp(-LN_TO_LOG10 * ( (TMN-NMT)*tbb + NMT ));	    }/* at this point, tbb represents the amount the spreading function * will be reduced.  The smaller the value, the less masking. * minval[] = 1 (0db)     says just use tbb. * minval[]= .01 (-20db)  says reduce spreading function by at least 20db. */	    tbb = Min(gfc->minval[b], tbb);	    /* stabilize tonality estimation */	    if (gfc->PSY->tonalityPatch && b > 5) {		FLOAT const x = 1.8699422;		FLOAT w = gfc->PSY->prvTonRed[b/2] * x;		if (tbb > w) 		    tbb = w;		gfc->PSY->prvTonRed[b] = tbb;	    }	    ecb *= tbb;	    /* long block pre-echo control.   */	    /* rpelev=2.0, rpelev2=16.0 */	    /* note: all surges in PE are because of this pre-echo formula	     * for thr[b].  If it this is not used, PE is always around 600	     */	    /* dont use long block pre-echo control if previous granule was	     * a short block.  This is to avoid the situation:   	     * frame0:  quiet (very low masking)  	     * frame1:  surge  (triggers short blocks)	     * frame2:  regular frame. looks like pre-echo when compared to	     *          frame0, but all pre-echo was in frame1.	     */	    /* chn=0,1   L and R channels	       chn=2,3   S and M channels.  	    */	    thr[b] = Min(ecb, rpelev*gfc->nb_1[chn][b]);	    if (gfc->blocktype_old[chn & 1] != SHORT_TYPE		&& thr[b] > rpelev2*gfc->nb_2[chn][b])		thr[b] = rpelev2*gfc->nb_2[chn][b];	    gfc->nb_2[chn][b] = gfc->nb_1[chn][b];	    gfc->nb_1[chn][b] = ecb;	    ecb = Max(thr[b], gfc->ATH->cb[b]*gfc->ATH->adjust);	    if (ecb < eb[b])		gfc->pe[chn] -= gfc->numlines_l[b] * FAST_LOG(ecb / eb[b]);	}    determine_block_type( gfp, fftenergy_s, uselongblock, chn, gr_out, &gfc->pe[chn] );	/* compute masking thresholds for long blocks */	convert_partition2scalefac_l(gfc, eb, thr, chn);	/* compute masking thresholds for short blocks */	for (sblock = 0; sblock < 3; sblock++) {	    FLOAT enn, thmm;	    compute_masking_s(gfc, fftenergy_s, eb, thr, chn,			      sblock,gfp->ATHlower*gfc->ATH->adjust);	    b = -1;	    enn = thmm = 0.0;	    for (sb = 0; sb < SBMAX_s; sb++) {		while (++b < gfc->bo_s[sb]) {		    enn  += eb[b];		    thmm += thr[b];		}		enn  += 0.5 * eb[b];    /* for the last sfb b is larger than npart_s!! */		thmm += 0.5 * thr[b];   /* rh 20040301 */        assert( enn >= 0 );        assert( thmm >= 0 );		gfc->en [chn].s[sb][sblock] = enn;		gfc->thm[chn].s[sb][sblock] = thmm;		enn  = 0.5 * eb[b];		thmm = 0.5 * thr[b];        assert( enn >= 0 );        assert( thmm >= 0 );	    }	    gfc->en [chn].s[sb-1][sblock] += enn;	    gfc->thm[chn].s[sb-1][sblock] += thmm;	}    } /* end loop over chn */    if (gfp->interChRatio != 0.0)	calc_interchannel_masking(gfp, gfp->interChRatio);    if (gfp->mode == JOINT_STEREO) {	FLOAT db,x1,x2,sidetot=0,tot=0;	msfix1(gfc);	if (gfp->msfix != 0.0)	    ns_msfix(gfc, gfp->msfix, gfp->ATHlower*gfc->ATH->adjust);	/* determin ms_ratio from masking thresholds*/	/* use ms_stereo (ms_ratio < .35) if average thresh. diff < 5 db */	for (sb= SBMAX_l/4 ; sb< SBMAX_l; sb ++ ) {	    x1 = Min(gfc->thm[0].l[sb],gfc->thm[1].l[sb]);	    x2 = Max(gfc->thm[0].l[sb],gfc->thm[1].l[sb]);	    /* thresholds difference in db */	    if (x2 >= 1000*x1)  db=3;	    else db = FAST_LOG10(x2/x1);  	    /*  DEBUGF(gfc,"db = %f %e %e  \n",db,gfc->thm[0].l[sb],gfc->thm[1].l[sb]);*/	    sidetot += db;	    tot++;	}	ms_ratio_l= (sidetot/tot)*0.7; /* was .35*(sidetot/tot)/5.0*10 */	ms_ratio_l = Min(ms_ratio_l,0.5);	sidetot=0; tot=0;	for ( sblock = 0; sblock < 3; sblock++ )	    for ( sb = SBMAX_s/4; sb < SBMAX_s; sb++ ) {		x1 = Min(gfc->thm[0].s[sb][sblock],gfc->thm[1].s[sb][sblock]);		x2 = Max(gfc->thm[0].s[sb][sblock],gfc->thm[1].s[sb][sblock]);		/* thresholds difference in db */		if (x2 >= 1000*x1)  db=3;		else db = FAST_LOG10(x2/x1);		sidetot += db;		tot++;	    }	ms_ratio_s = (sidetot/tot)*0.7; /* was .35*(sidetot/tot)/5.0*10 */	ms_ratio_s = Min(ms_ratio_s,.5);    }    /***************************************************************      * determine final block type     ***************************************************************/    block_type_set(gfp, uselongblock, blocktype_d, blocktype);    if (blocktype_d[0]==SHORT_TYPE && blocktype_d[1]==SHORT_TYPE)	*ms_ratio = gfc->ms_ratio_s_old;    else	*ms_ratio = gfc->ms_ratio_l_old;    gfc->ms_ratio_s_old = ms_ratio_s;    gfc->ms_ratio_l_old = ms_ratio_l;    /* we dont know the block type of this frame yet - assume long */    *ms_ratio_next = ms_ratio_l;    return 0;}/* mask_add optimization *//* init the limit values used to avoid computing log in mask_add when it is not necessary *//* For example, with i = 10*log10(m2/m1)/10*16         (= log10(m2/m1)*16) * * abs(i)>8 is equivalent (as i is an integer) to * abs(i)>=9 * i>=9 || i<=-9 * equivalent to (as i is the biggest integer smaller than log10(m2/m1)*16  * or the smallest integer bigger than log10(m2/m1)*16 depending on the sign of log10(m2/m1)*16) * log10(m2/m1)>=9/16 || log10(m2/m1)<=-9/16 * exp10 is strictly increasing thus this is equivalent to * m2/m1 >= 10^(9/16) || m2/m1<=10^(-9/16) which are comparisons to constants */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -