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

📄 psymodel.c

📁 音频编码
💻 C
📖 第 1 页 / 共 4 页
字号:
	}	gfc->nsPsy.last_attacks[chn] = ns_attacks[2];	/*********************************************************************	 *    Calculate the energy and the tonality of each partition.	 *********************************************************************/	for (b = j = 0; b<gfc->npart_l; b++) {	    FLOAT ebb,m;	    m = ebb = fftenergy[j++];	    for (i = gfc->numlines_l[b] - 1; i > 0; --i) {		FLOAT el = fftenergy[j++];		ebb += el;		if (m < el)		    m = el;	    }	    eb[b] = ebb;	    max[b] = m;	    avg[b] = ebb * gfc->rnumlines_l[b];	}	if (gfc->nsPsy.pass1fp)	    nsPsy2dataRead(gfc->nsPsy.pass1fp, eb2, eb, chn, gfc->npart_l);	else {	    FLOAT m,a;	    a = avg[0] + avg[1];	    if (a != 0.0) {		m = max[0]; if (m < max[1]) m = max[1];		a = 20.0 * (m*2.0-a)		    / (a*(gfc->numlines_l[0] + gfc->numlines_l[1] - 1));		k = (int) a;		if (k > sizeof(tab)/sizeof(tab[0]) - 1)		    k = sizeof(tab)/sizeof(tab[0]) - 1;		a = eb[0] * tab[k];	    }	    eb2[0] = a;	    for (b = 1; b < gfc->npart_l-1; b++) {		a = avg[b-1] + avg[b] + avg[b+1];		if (a != 0.0) {		    m = max[b-1];		    if (m < max[b  ]) m = max[b];		    if (m < max[b+1]) m = max[b+1];		    a = 20.0 * (m*3.0-a)			/ (a*(gfc->numlines_l[b-1] + gfc->numlines_l[b] + gfc->numlines_l[b+1] - 1));		    k = (int) a;		    if (k > sizeof(tab)/sizeof(tab[0]) - 1)			k = sizeof(tab)/sizeof(tab[0]) - 1;		    a = eb[b] * tab[k];		}		eb2[b] = a;	    }	    a = avg[gfc->npart_l-2] + avg[gfc->npart_l-1];	    if (a != 0.0) {		m = max[gfc->npart_l-2];		if (m < max[gfc->npart_l-1])		    m = max[gfc->npart_l-1];		a = 20.0 * (m*2.0-a)		    / (a*(gfc->numlines_l[gfc->npart_l-2] + gfc->numlines_l[gfc->npart_l-1] - 1));		k = (int) a;		if (k > sizeof(tab)/sizeof(tab[0]) - 1)		    k = sizeof(tab)/sizeof(tab[0]) - 1;		a = eb[b] * tab[k];	    }	    eb2[b] = a;	}	/*********************************************************************	 *      convolve the partitioned energy and unpredictability	 *      with the spreading function, s3_l[b][k]	 ******************************************************************* */#undef GPSYCHO_BLOCK_TYPE_DECISION#ifdef GPSYCHO_BLOCK_TYPE_DECISION   {    FLOAT pe = 0;#endif	k = 0;	for ( b = 0;b < gfc->npart_l; b++ ) {	    FLOAT ecb;	    /* convolve the partitioned energy with the spreading function */	    int kk = gfc->s3ind[b][0];	    ecb = gfc->s3_ll[k++] * eb2[kk];	    while (++kk <= gfc->s3ind[b][1])		ecb = mask_add(ecb, gfc->s3_ll[k++] * eb2[kk], kk, kk-b, gfc);	    ecb *= 0.158489319246111; /* pow(10,-0.8) */	    /****   long block pre-echo control   ****/	    /* 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.	    */	    if (gfc->blocktype_old[chn & 1] == SHORT_TYPE)		thr[b] = ecb; /* Min(ecb, rpelev*gfc->nb_1[chn][b]); */	    else		thr[b] = NS_INTERP(Min(ecb,				       Min(rpelev*gfc->nb_1[chn][b],					   rpelev2*gfc->nb_2[chn][b])),				   ecb, pcfact);	    gfc->nb_2[chn][b] = gfc->nb_1[chn][b];	    gfc->nb_1[chn][b] = ecb;#ifdef GPSYCHO_BLOCK_TYPE_DECISION        /* this pe does not match GPSYCHO's pe, because of difference in          * convolution calculation, (mask_add etc.). Therefore the block         * switching does not happen exactly as in GPSYCHO.         */		pe -= gfc->numlines_l[b] * FAST_LOG(ecb / eb[b]);#endif    }#ifdef GPSYCHO_BLOCK_TYPE_DECISION    determine_block_type( gfp, fftenergy_s, uselongblock, chn, gr_out, &pe );   }#endif	/* compute masking thresholds for long blocks */	convert_partition2scalefac_l(gfc, eb, thr, chn);    } /* end loop over chn */    if (gfp->interChRatio != 0.0)	calc_interchannel_masking(gfp, gfp->interChRatio);    if (gfp->mode == JOINT_STEREO) {	FLOAT msfix;	msfix1(gfc);	msfix = gfp->msfix;	if (msfix != 0.0)	    ns_msfix(gfc, msfix, gfp->ATHlower*gfc->ATH->adjust);    }    /***************************************************************      * determine final block type     ***************************************************************/    block_type_set(gfp, uselongblock, blocktype_d, blocktype);    /*********************************************************************     * compute the value of PE to return ... no delay and advance     *********************************************************************/    for(chn=0;chn<numchn;chn++) {	FLOAT *ppe;	int type;	III_psy_ratio *mr;	if (chn > 1) {	    ppe = percep_MS_entropy - 2;	    type = NORM_TYPE;	    if (blocktype_d[0] == SHORT_TYPE || blocktype_d[1] == SHORT_TYPE)		type = SHORT_TYPE;	    mr = &masking_MS_ratio[gr_out][chn-2];	} else {	    ppe = percep_entropy;	    type = blocktype_d[chn];	    mr = &masking_ratio[gr_out][chn];	}	if (type == SHORT_TYPE)	    ppe[chn] = pecalc_s(mr, gfc->masking_lower);	else	    ppe[chn] = pecalc_l(mr, gfc->masking_lower);#if defined(HAVE_GTK)	if (gfp->analysis) gfc->pinfo->pe[gr_out][chn] = ppe[chn];#endif    }    return 0;}/*  *   The spreading function.  Values returned in units of energy */static FLOAT s3_func(FLOAT bark) {    FLOAT tempx,x,tempy,temp;    tempx = bark;    if (tempx>=0) tempx *= 3;    else tempx *=1.5;     if (tempx>=0.5 && tempx<=2.5)      {	temp = tempx - 0.5;	x = 8.0 * (temp*temp - 2.0 * temp);      }    else x = 0.0;    tempx += 0.474;    tempy = 15.811389 + 7.5*tempx - 17.5*sqrt(1.0+tempx*tempx);    if (tempy <= -60.0) return  0.0;    tempx = exp( (x + tempy)*LN_TO_LOG10 );     /* Normalization.  The spreading function should be normalized so that:         +inf           /           |  s3 [ bark ]  d(bark)   =  1           /         -inf    */    tempx /= .6609193;    return tempx;}static intinit_numline(    int *numlines, int *bo, int *bm,    FLOAT *bval, FLOAT *bval_width, FLOAT *mld,    FLOAT sfreq, int blksize, int *scalepos,    FLOAT deltafreq, int sbmax    ){    int partition[HBLKSIZE];    int i, j, k;    int sfb;    sfreq /= blksize;    j = 0;    /* compute numlines, the number of spectral lines in each partition band */    /* each partition band should be about DELBARK wide. */    for (i=0;i<CBANDS;i++) {	FLOAT bark1;	int j2;	bark1 = freq2bark(sfreq*j);	for (j2 = j; freq2bark(sfreq*j2) - bark1 < DELBARK && j2 <= blksize/2;	     j2++)	    ;	numlines[i] = j2 - j;	while (j<j2)	    partition[j++]=i;	if (j > blksize/2) break;    }    for ( sfb = 0; sfb < sbmax; sfb++ ) {	int i1,i2,start,end;	FLOAT arg;	start = scalepos[sfb];	end   = scalepos[sfb+1];	i1 = floor(.5 + deltafreq*(start-.5));	if (i1<0) i1=0;	i2 = floor(.5 + deltafreq*(end-.5));	if (i2>blksize/2) i2=blksize/2;	bm[sfb] = (partition[i1]+partition[i2])/2;	bo[sfb] = partition[i2];	/* setup stereo demasking thresholds */	/* formula reverse enginerred from plot in paper */	arg = freq2bark(sfreq*scalepos[sfb]*deltafreq);	arg = (Min(arg, 15.5)/15.5);	mld[sfb] = pow(10.0, 1.25*(1-cos(PI*arg))-2.5);    }    /* compute bark values of each critical band */    j = 0;    for (k = 0; k < i+1; k++) {	int w = numlines[k];	FLOAT  bark1,bark2;	bark1 = freq2bark (sfreq*(j    ));	bark2 = freq2bark (sfreq*(j+w-1));	bval[k] = .5*(bark1+bark2);	bark1 = freq2bark (sfreq*(j  -.5));	bark2 = freq2bark (sfreq*(j+w-.5));	bval_width[k] = bark2-bark1;	j += w;    }    return i+1;}static intinit_s3_values(    lame_internal_flags *gfc,    FLOAT **p,    int (*s3ind)[2],    int npart,    FLOAT *bval,    FLOAT *bval_width,    FLOAT *norm    ){    FLOAT s3[CBANDS][CBANDS];    /* The s3 array is not linear in the bark scale.     * bval[x] should be used to get the bark value.     */    int i, j, k;    int numberOfNoneZero = 0;    /* s[i][j], the value of the spreading function,     * centered at band j (masker), for band i (maskee)     *     * i.e.: sum over j to spread into signal barkval=i     * NOTE: i and j are used opposite as in the ISO docs     */    for (i = 0; i < npart; i++)	for (j = 0; j < npart; j++)	    s3[i][j] = s3_func(bval[i] - bval[j]) * bval_width[j] * norm[i];    for (i = 0; i < npart; i++) {	for (j = 0; j < npart; j++) {	    if (s3[i][j] != 0.0)		break;	}	s3ind[i][0] = j;	for (j = npart - 1; j > 0; j--) {	    if (s3[i][j] != 0.0)		break;	}	s3ind[i][1] = j;	numberOfNoneZero += (s3ind[i][1] - s3ind[i][0] + 1);    }    *p = malloc(sizeof(FLOAT)*numberOfNoneZero);    if (!*p)	return -1;    k = 0;    for (i = 0; i < npart; i++)	for (j = s3ind[i][0]; j <= s3ind[i][1]; j++)	    (*p)[k++] = s3[i][j];    return 0;}int psymodel_init(lame_global_flags *gfp){    lame_internal_flags *gfc=gfp->internal_flags;    int i,j,b,sb,k;    FLOAT bval[CBANDS];    FLOAT bval_width[CBANDS];    FLOAT norm[CBANDS];    FLOAT sfreq = gfp->out_samplerate;    gfc->ms_ener_ratio_old=.25;    gfc->blocktype_old[0] = gfc->blocktype_old[1] = NORM_TYPE; /* the vbr header is long blocks*/    for (i=0; i<4; ++i) {	for (j=0; j<CBANDS; ++j) {	    gfc->nb_1[i][j]=1e20;	    gfc->nb_2[i][j]=1e20;	    gfc->nb_s1[i][j] = gfc->nb_s2[i][j] = 1.0;	}	for ( sb = 0; sb < SBMAX_l; sb++ ) {	    gfc->en[i].l[sb] = 1e20;	    gfc->thm[i].l[sb] = 1e20;	}	for (j=0; j<3; ++j) {	    for ( sb = 0; sb < SBMAX_s; sb++ ) {		gfc->en[i].s[sb][j] = 1e20;		gfc->thm[i].s[sb][j] = 1e20;	    }	    gfc->nsPsy.last_attacks[i] = 0;	}	for(j=0;j<9;j++)	    gfc->nsPsy.last_en_subshort[i][j] = 10.;    }    j = gfc->PSY->cwlimit/(sfreq/BLKSIZE);    if (j > HBLKSIZE-4) /* j+3 < HBLKSIZE-1 */	j = HBLKSIZE-4;    if (j < CW_LOWER_INDEX)	j = CW_LOWER_INDEX;    gfc->cw_upper_index = j;    for (j = 0; j < HBLKSIZE; j++)	gfc->cw[j] = 0.4f;    /* init. for loudness approx. -jd 2001 mar 27*/    gfc->loudness_sq_save[0] = gfc->loudness_sq_save[1] = 0.0;    /*************************************************************************     * now compute the psychoacoustic model specific constants     ************************************************************************/    /* compute numlines, bo, bm, bval, bval_width, mld */    gfc->npart_l	= init_numline(gfc->numlines_l, gfc->bo_l, gfc->bm_l,		       bval, bval_width, gfc->mld_l,		       sfreq, BLKSIZE, 		       gfc->scalefac_band.l, BLKSIZE/(2.0*576), SBMAX_l);    assert(gfc->npart_l <= CBANDS);    /* compute the spreading function */    for(i=0;i<gfc->npart_l;i++) {	norm[i]=1.0;	gfc->rnumlines_l[i] = 1.0 / gfc->numlines_l[i];    }    i = init_s3_values(gfc, &gfc->s3_ll, gfc->s3ind,		       gfc->npart_l, bval, bval_width, norm);    if (i)	return i;    /* compute long block specific values, ATH and MINVAL */    j = 0;    for ( i = 0; i < gfc->npart_l; i++ ) {	double x;	/* ATH */	x = FLOAT_MAX;	for (k=0; k < gfc->numlines_l[i]; k++, j++) {	    FLOAT  freq = sfreq*j/(1000.0*BLKSIZE);	    FLOAT  level;	    /*	freq = Min(.1,freq);*/      /* ATH below 100 Hz constant, not further climbing */	    level  = ATHformula (freq*1000, gfp) - 20;   /* scale to FFT units; returned value is in dB */	    level  = pow ( 10., 0.1*level );   /* convert from dB -> energy */	    level *= gfc->numlines_l [i];	    if (x > level)		x = level;	}	gfc->ATH->cb[i] = x;	/* MINVAL.	   For low freq, the strength of the masking is limited by minval	   this is an ISO MPEG1 thing, dont know if it is really needed */	x = (-20+bval[i]*20.0/10.0);	if (bval[i]>10) x = 0;	gfc->minval[i]=pow(10.0,x/10);	gfc->PSY->prvTonRed[i] = gfc->minval[i];    }    /************************************************************************     * do the same things for short blocks     ************************************************************************/    gfc->npart_s	= init_numline(gfc->numlines_s, gfc->bo_s, gfc->bm_s,		       bval, bval_width, gfc->mld_s,		       sfreq, BLKSIZE_s,		       gfc->scalefac_band.s, BLKSIZE_s/(2.0*192), SBMAX_s);    assert(gfc->npart_s <= CBANDS);    /* SNR formula. short block is normalized by SNR. is it still right ? */    for(i=0;i<gfc->npart_s;i++) {	double snr=-8.25;	if (bval[i]>=13)	    snr = -4.5 * (bval[i]-13)/(24.0-13.0)		-8.25*(bval[i]-24)/(13.0-24.0);	norm[i]=pow(10.0,snr/10.0);    }    i = init_s3_values(gfc, &gfc->s3_ss, gfc->s3ind_s,		       gfc->npart_s, bval, bval_width, norm);    if (i)	return i;    init_mask_add_max_values();    init_fft(gfc);    /* setup temporal masking */    gfc->decay = exp(-1.0*LOG10/(temporalmask_sustain_sec*sfreq/192.0));    if (gfp->psymodel == PSY_NSPSYTUNE) {        FLOAT msfix;        msfix = NS_MSFIX;        if (gfp->exp_nspsytune & 2) msfix = 1.0;        if (gfp->msfix != 0.0) msfix = gfp->msfix;        gfp->msfix = msfix;        /* spread only from npart_l bands.  Normally, we use the spreading        * function to convolve from npart_l down to npart_l bands         */        for (b=0;b<gfc->npart_l;b++)            if (gfc->s3ind[b][1] > gfc->npart_l-1)                gfc->s3ind[b][1] = gfc->npart_l-1;    }    /*  prepare for ATH auto adjustment:     *  we want to decrease the ATH by 12 dB per second     */#define  frame_duration (576. * gfc->mode_gr / sfreq)    gfc->ATH->decay = pow(10., -12./10. * frame_duration);    gfc->ATH->adjust = 0.01; /* minimum, for leading low loudness */    gfc->ATH->adjust_limit = 1.0; /* on lead, allow adjust up to maximum */#undef  frame_duration    gfc->bo_s[SBMAX_s-1]--;    assert(gfc->bo_l[SBMAX_l-1] <= gfc->npart_l);    assert(gfc->bo_s[SBMAX_s-1] <= gfc->npart_s);    if (gfp->ATHtype != -1) { 	/* compute equal loudness weights (eql_w) */	FLOAT freq;	FLOAT freq_inc = gfp->out_samplerate / (BLKSIZE);	FLOAT eql_balance = 0.0;	freq = 0.0;	for( i = 0; i < BLKSIZE/2; ++i ) {	    /* convert ATH dB to relative power (not dB) */	    /*  to determine eql_w */	    freq += freq_inc;	    gfc->ATH->eql_w[i] = 1. / pow( 10, ATHformula( freq, gfp ) / 10 );	    eql_balance += gfc->ATH->eql_w[i];	}	eql_balance = 1.0 / eql_balance;	for( i = BLKSIZE/2; --i >= 0; ) { /* scale weights */	    gfc->ATH->eql_w[i] *= eql_balance;	}    }    return 0;}

⌨️ 快捷键说明

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