www.pudn.com > bladeenc-0.90.0-src.zip > l3psy.c


/* 
			(c) Copyright 1998, 1999 - Tord Jansson 
			======================================= 
 
		This file is part of the BladeEnc MP3 Encoder, based on 
		ISO's reference code for MPEG Layer 3 compression, and might 
		contain smaller or larger sections that are directly taken 
		from ISO's reference code. 
 
		All changes to the ISO reference code herein are either 
		copyrighted by Tord Jansson (tord.jansson@swipnet.se) 
		or sublicensed to Tord Jansson by a third party. 
 
	BladeEnc is free software; you can redistribute this file 
	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. 
 
*/ 
 
#include  
#include "common.h" 
#include "encoder.h" 
#include "l3psy.h" 
#include "l3side.h" 
 
 
#define maximum(x,y) ( (x>y) ? x : y ) 
#define minimum(x,y) ( (xcrit_band[j]) 
			j++; 
    	fthr[i]=j-1+(temp1-crit_band[j-1])/(crit_band[j]-crit_band[j-1]); 
    } 
    partition[0] = 0; 
 
	/* temp2 is the counter of the number of frequency lines in each partition */ 
 
	temp2 = 1; 
    cbval[0]=fthr[0]; 
    bval_lo=fthr[0]; 
    for(i=1;i0.33) 
		{ 
        	partition[i]=partition[i-1]+1; 
        	cbval[partition[i-1]] = cbval[partition[i-1]]/temp2; 
        	cbval[partition[i]] = fthr[i]; 
        	bval_lo = fthr[i]; 
        	numlines[partition[i-1]] = temp2; 
        	temp2 = 1; 
        } 
        else 
		{ 
        	partition[i]=partition[i-1]; 
        	cbval[partition[i]] += fthr[i]; 
 
        	temp2++; 
		} 
    } 
    numlines[partition[i-1]] = temp2; 
    cbval[partition[i-1]] = cbval[partition[i-1]]/temp2; 
 
/************************************************************************ 
 * Now compute the spreading function, s[j][i], the value of the spread-* 
 * ing function, centered at band j, for band i, store for later use    * 
 ************************************************************************/ 
	for(j=0;j=0.5 && temp1<=2.5) 
			{ 
            	temp2 = temp1 - 0.5; 
            	temp2 = 8.0 * (temp2*temp2 - 2.0 * temp2); 
			} 
			else 
				temp2 = 0; 
			temp1 += 0.474; 
			temp3 = 15.811389+7.5*temp1-17.5*sqrt((double) (1.0+temp1*temp1)); 
			if(temp3 <= -100) 
				s[i][j] = 0; 
			else 
			{ 
            	temp3 = (temp2 + temp3)*LN_TO_LOG10; 
            	s[i][j] = exp(temp3); 
			} 
		} 
    } 
 
	/* Calculate Tone Masking Noise values */ 
    for(j=0;j24.5) ? temp1 : 24.5; 
 
  		/* Calculate normalization factors for the net spreading functions */ 
        rnorm[j] = 0; 
        for(i=0;i= 0 ) 
	    { 
			eb[tp] += energy[j]; 
			cb[tp] += cw[j] * energy[j]; 
	    } 
	} 
 
 
/********************************************************************** 
*      convolve the partitioned energy and unpredictability           * 
*      with the spreading function, s3_l[b][k]                        * 
******************************************************************** */ 
	 
	for ( b = 0; b < CBANDS; b++ ) 
	{ 
	    ecb[b] = 0.0; 
	    ctb[b] = 0.0; 
	} 
	for ( b = 0;b < CBANDS; b++ ) 
	{ 
	    for ( k = 0; k < CBANDS; k++ ) 
	    { 
			ecb[b] += s3_l[b][k] * eb[k];	/* sprdngf for Layer III */ 
			ctb[b] += s3_l[b][k] * cb[k]; 
	    } 
	} 
 
	/* calculate the tonality of each threshold calculation partition */ 
	/* calculate the SNR in each threshhold calculation partition */ 
 
	for ( b = 0; b < CBANDS; b++ ) 
	{ 
	    double cbb,tbb; 
	    if (ecb[b] != 0.0 ) 
        { 
			cbb = ctb[b]/ecb[b]; 
        	if (cbb <0.01) cbb = 0.01; 
			cbb = log( cbb); 
        } 
	    else 
			cbb = 0.0 ; 
 
	    tbb = -0.299 - 0.43*cbb;  /* conv1=-0.299, conv2=-0.43 */ 
	    tbb = minimum( 1.0, maximum( 0.0, tbb) ) ;  /* 0 thr[b]+1.0 : for non sound portition */ 
	 
#define switch_pe  1800 
        blocktype = NORM_TYPE; 
	 
 
	if ( *pe < switch_pe ) 
	{				/* no attack : use long blocks */ 
		switch( blocktype_old[chn] ) 
	    { 
	    	case NORM_TYPE: 
	    	case STOP_TYPE: 
				blocktype = NORM_TYPE; 
				break; 
     
	      	case SHORT_TYPE: 
				blocktype = STOP_TYPE; 
			break; 
     
/*	      	case START_TYPE: 
				fprintf( stderr, "Error in block selecting\n" ); 
				abort(); 
				break; problem */ 
	    } 
 
	    /* threshold calculation (part 2) */ 
	    for ( sb = 0; sb < SBMAX_l; sb++ ) 
	    { 
			en[sb] = w1_l[sb] * eb[bu_l[sb]] + w2_l[sb] * eb[bo_l[sb]]; 
			thm[sb] = w1_l[sb] *thr[bu_l[sb]] + w2_l[sb] * thr[bo_l[sb]]; 
 
			for ( b = bu_l[sb]+1; b < bo_l[sb]; b++ ) 
			{ 
			    en[sb]  += eb[b]; 
			    thm[sb] += thr[b]; 
			} 
 
			if ( en[sb] != 0.0 ) 
				ratio[chn][sb] = thm[sb]/en[sb]; 
			else 
			    ratio[chn][sb] = 0.0; 
	    } 
	} 
	else  
	{ 
	    /* attack : use short blocks */ 
	    blocktype = SHORT_TYPE; 
	     
	    if ( blocktype_old[chn] == NORM_TYPE )  
			blocktype_old[chn] = START_TYPE; 
	    if ( blocktype_old[chn] == STOP_TYPE ) 
			blocktype_old[chn] = SHORT_TYPE ; 
	     
	    /* threshold calculation for short blocks */ 
	     
	    for ( sblock = 0; sblock < 3; sblock++ ) 
	    { 
			for ( b = 0; b < CBANDS_s; b++ ) 
			{ 
			    eb[b] = 0.0; 
			    ecb[b] = 0.0; 
			} 
 
			for ( j = 0; j < HBLKSIZE_s; j++ ) 
			    eb[partition_s[j]] += energy_s[sblock][j]; 
 
			for ( b = 0; b < CBANDS_s; b++ ) 
			    for ( k = 0; k < CBANDS_s; k++ ) 
					ecb[b] += s3_l[b][k] * eb[k]; 
 
			for ( b = 0; b < CBANDS_s; b++ ) 
			{ 
			    nb[b] = ecb[b] * norm_l[b] * exp( (double) SNR_s[b] * LN_TO_LOG10 ); 
			    thr[b] = maximum (qthr_s[b],nb[b]); 
			} 
 
			for ( sb = 0; sb < SBMAX_s; sb++ ) 
			{ 
			    en[sb] = w1_s[sb] * eb[bu_s[sb]] + w2_s[sb] * eb[bo_s[sb]]; 
			    thm[sb] = w1_s[sb] *thr[bu_s[sb]] + w2_s[sb] * thr[bo_s[sb]]; 
 
			    for ( b = bu_s[sb]+1; b < bo_s[sb]; b++ ) 
			    { 
					en[sb] += eb[b]; 
					thm[sb] += thr[b]; 
			    } 
 
			    if ( en[sb] != 0.0 ) 
					ratio_s[chn][sb][sblock] = thm[sb]/en[sb]; 
			    else 
					ratio_s[chn][sb][sblock] = 0.0; 
			} 
	    } 
	}  
	 
	cod_info->block_type = blocktype_old[chn]; 
	blocktype_old[chn] = blocktype; 
 
	if ( cod_info->block_type == NORM_TYPE ) 
	    cod_info->window_switching_flag = 0; 
	else 
	    cod_info->window_switching_flag = 1; 
 
	cod_info->mixed_block_flag = 0; 
} 
 
 
/*____ L3para_read() __________________________________________________________*/ 
 
void L3para_read( int sfreq, int *numlines, int *partition_l, double *minval, 
				  double *qthr_l, double *norm_l, double (*s3_l)[63], int *partition_s, 
				  double *qthr_s, double *norm_s, double *SNR, int *cbw_l, int *bu_l, 
				  int *bo_l, double *w1_l, double *w2_l, int *cbw_s, int *bu_s, 
				  int *bo_s, double *w1_s, double *w2_s ) 
{ 
   static double bval_l[CBANDS], bval_s[CBANDS]; 
   int   cbmax, cbmax_tp; 
   static double s3_s[CBANDS][CBANDS]; 
 
   int  sbmax ; 
   int  i,j,k,k2, part_max ; 
 
 
	 psyDataElem * rpa1; 
	 psyDataElem2 * rpa2; 
	 psyDataElem3 * rpa3; 
 
 
	 /* Read long block data */ 
 
 
	switch( sfreq ) 
	{ 
		case	32000: 
			rpa1 = psy_longBlock__32000_58; 
			cbmax_tp = 59; 
			break; 
		case	44100: 
			rpa1 = psy_longBlock_44100_62; 
			cbmax_tp = 63; 
			break; 
		case	48000: 
			rpa1 = psy_longBlock_48000_61; 
			cbmax_tp = 62; 
			break; 
		default: 
			return;		/* Just to avoid compiler warnings */ 
	} 
	 
	cbmax = cbmax_tp; 
	for(i=0,k2=0;ilines; 
		minval[i] = rpa1->minVal; 
		qthr_l[i] = rpa1->qthr; 
		norm_l[i] = rpa1->norm; 
		bval_l[i] = rpa1->bVal; 
		rpa1++; 
 
		for(k=0;k=i) 
				tempx = (bval_l[i] - bval_l[j])*3.0; 
            else 
				tempx = (bval_l[i] - bval_l[j])*1.5; 
/*             if (j>=i) tempx = (bval_l[j] - bval_l[i])*3.0; 
               else    tempx = (bval_l[j] - bval_l[i])*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) s3_l[i][j] = 0.0; 
             else                s3_l[i][j] = exp( (x + tempy)*LN_TO_LOG10 ); 
 
            } 
          } 
 
 
/* Read short block data */ 
 
	switch( sfreq ) 
	{ 
		case	32000: 
			rpa2 = psy_shortBlock_32000_41; 
			cbmax_tp = 42; 
			break; 
		case	44100: 
			rpa2 = psy_shortBlock_44100_38; 
			cbmax_tp = 39; 
			break; 
		case	48000: 
			rpa2 = psy_shortBlock_48000_37; 
			cbmax_tp = 38; 
			break; 
		default: 
			return;		/* Just to avoid compiler warnings */ 
	} 
 
 
 
	cbmax = cbmax_tp; 
	for(i=0,k2=0;ilines; 
		qthr_s[i] = rpa2->qthr; 
		norm_s[i] = rpa2->norm; 
		SNR[i] = rpa2->snr; 
		bval_s[i] = rpa2->bVal; 
		rpa2++; 
		 
		for(k=0;k=i) tempx = (bval_s[i] - bval_s[j])*3.0; 
               else    tempx = (bval_s[i] - bval_s[j])*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) s3_s[i][j] = 0.0; 
             else                s3_s[i][j] = exp( (x + tempy)*LN_TO_LOG10 ); 
            } 
          } 
/* Read long block data for converting threshold calculation 
   partitions to scale factor bands */ 
 
	switch( sfreq ) 
	{ 
		case	32000: 
			rpa3 = psy_data3_32000_20; 
			sbmax = 21; 
			break; 
		case	44100: 
			rpa3 = psy_data3_44100_20; 
			sbmax = 21; 
			break; 
		case	48000: 
			rpa3 = psy_data3_48000_20; 
			sbmax = 21; 
			break; 
		default: 
			return;		/* Just to avoid compiler warnings */ 
	} 
 
  for(i=0;icbw; 
		bu_l[i] = rpa3->bu; 
		bo_l[i] = rpa3->bo; 
		w1_l[i] = rpa3->w1; 
		w2_l[i] = rpa3->w2; 
		rpa3++;		 
	} 
 
/* Read short block data for converting threshold calculation 
   partitions to scale factor bands */ 
 
	switch( sfreq ) 
	{ 
		case	32000: 
			rpa3 = psy_data4_32000_11; 
			sbmax = 12; 
			break; 
		case	44100: 
			rpa3 = psy_data4_44100_11; 
			sbmax = 12; 
			break; 
		case	48000: 
			rpa3 = psy_data4_48000_11; 
			sbmax = 12; 
			break; 
	} 
 
  for(i=0;icbw; 
		bu_s[i] = rpa3->bu; 
		bo_s[i] = rpa3->bo; 
		w1_s[i] = rpa3->w1; 
		w2_s[i] = rpa3->w2; 
		rpa3++;		 
	}	 
 
}