psymodel.c

Go to the documentation of this file.
00001 /*
00002  *      psymodel.c
00003  *
00004  *      Copyright (c) 1999-2000 Mark Taylor
00005  *      Copyright (c) 2001-2002 Naoki Shibata
00006  *      Copyright (c) 2000-2003 Takehiro Tominaga
00007  *      Copyright (c) 2000-2007 Robert Hegemann
00008  *      Copyright (c) 2000-2005 Gabriel Bouvigne
00009  *      Copyright (c) 2000-2005 Alexander Leidinger
00010  *
00011  * This library is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU Lesser General Public
00013  * License as published by the Free Software Foundation; either
00014  * version 2 of the License, or (at your option) any later version.
00015  *
00016  * This library is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  * Library General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Lesser General Public
00022  * License along with this library; if not, write to the
00023  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00024  * Boston, MA 02111-1307, USA.
00025  */
00026 
00027 /* $Id: psymodel.c,v 1.160 2007/08/11 21:44:24 robert Exp $ */
00028 
00029 
00030 /*
00031 PSYCHO ACOUSTICS
00032 
00033 
00034 This routine computes the psycho acoustics, delayed by one granule.  
00035 
00036 Input: buffer of PCM data (1024 samples).  
00037 
00038 This window should be centered over the 576 sample granule window.
00039 The routine will compute the psycho acoustics for
00040 this granule, but return the psycho acoustics computed
00041 for the *previous* granule.  This is because the block
00042 type of the previous granule can only be determined
00043 after we have computed the psycho acoustics for the following
00044 granule.  
00045 
00046 Output:  maskings and energies for each scalefactor band.
00047 block type, PE, and some correlation measures.  
00048 The PE is used by CBR modes to determine if extra bits
00049 from the bit reservoir should be used.  The correlation
00050 measures are used to determine mid/side or regular stereo.
00051 */
00052 /*
00053 Notation:
00054 
00055 barks:  a non-linear frequency scale.  Mapping from frequency to
00056         barks is given by freq2bark()
00057 
00058 scalefactor bands: The spectrum (frequencies) are broken into 
00059                    SBMAX "scalefactor bands".  Thes bands
00060                    are determined by the MPEG ISO spec.  In
00061                    the noise shaping/quantization code, we allocate
00062                    bits among the partition bands to achieve the
00063                    best possible quality
00064 
00065 partition bands:   The spectrum is also broken into about
00066                    64 "partition bands".  Each partition 
00067                    band is about .34 barks wide.  There are about 2-5
00068                    partition bands for each scalefactor band.
00069 
00070 LAME computes all psycho acoustic information for each partition
00071 band.  Then at the end of the computations, this information
00072 is mapped to scalefactor bands.  The energy in each scalefactor
00073 band is taken as the sum of the energy in all partition bands
00074 which overlap the scalefactor band.  The maskings can be computed
00075 in the same way (and thus represent the average masking in that band)
00076 or by taking the minmum value multiplied by the number of
00077 partition bands used (which represents a minimum masking in that band).
00078 */
00079 /*
00080 The general outline is as follows:
00081 
00082 1. compute the energy in each partition band
00083 2. compute the tonality in each partition band
00084 3. compute the strength of each partion band "masker"
00085 4. compute the masking (via the spreading function applied to each masker)
00086 5. Modifications for mid/side masking.  
00087 
00088 Each partition band is considiered a "masker".  The strength
00089 of the i'th masker in band j is given by:
00090 
00091     s3(bark(i)-bark(j))*strength(i)
00092 
00093 The strength of the masker is a function of the energy and tonality.
00094 The more tonal, the less masking.  LAME uses a simple linear formula
00095 (controlled by NMT and TMN) which says the strength is given by the
00096 energy divided by a linear function of the tonality.
00097 */
00098 /*
00099 s3() is the "spreading function".  It is given by a formula
00100 determined via listening tests.  
00101 
00102 The total masking in the j'th partition band is the sum over
00103 all maskings i.  It is thus given by the convolution of
00104 the strength with s3(), the "spreading function."
00105 
00106 masking(j) = sum_over_i  s3(i-j)*strength(i)  = s3 o strength
00107 
00108 where "o" = convolution operator.  s3 is given by a formula determined
00109 via listening tests.  It is normalized so that s3 o 1 = 1.
00110 
00111 Note: instead of a simple convolution, LAME also has the
00112 option of using "additive masking"
00113 
00114 The most critical part is step 2, computing the tonality of each
00115 partition band.  LAME has two tonality estimators.  The first
00116 is based on the ISO spec, and measures how predictiable the
00117 signal is over time.  The more predictable, the more tonal.
00118 The second measure is based on looking at the spectrum of
00119 a single granule.  The more peaky the spectrum, the more
00120 tonal.  By most indications, the latter approach is better.
00121 
00122 Finally, in step 5, the maskings for the mid and side
00123 channel are possibly increased.  Under certain circumstances,
00124 noise in the mid & side channels is assumed to also
00125 be masked by strong maskers in the L or R channels.
00126 
00127 
00128 Other data computed by the psy-model:
00129 
00130 ms_ratio        side-channel / mid-channel masking ratio (for previous granule)
00131 ms_ratio_next   side-channel / mid-channel masking ratio for this granule
00132 
00133 percep_entropy[2]     L and R values (prev granule) of PE - A measure of how 
00134                       much pre-echo is in the previous granule
00135 percep_entropy_MS[2]  mid and side channel values (prev granule) of percep_entropy
00136 energy[4]             L,R,M,S energy in each channel, prev granule
00137 blocktype_d[2]        block type to use for previous granule
00138 */
00139 
00140 
00141 
00142 
00143 #ifdef HAVE_CONFIG_H
00144 # include <config.h>
00145 #endif
00146 
00147 #include "lame.h"
00148 #include "machine.h"
00149 #include "encoder.h"
00150 #include "util.h"
00151 #include "psymodel.h"
00152 #include "lame_global_flags.h"
00153 #include "fft.h"
00154 #include "lame-analysis.h"
00155 
00156 
00157 #define NSFIRLEN 21
00158 
00159 #ifdef M_LN10
00160 #define         LN_TO_LOG10             (M_LN10/10)
00161 #else
00162 #define         LN_TO_LOG10             0.2302585093
00163 #endif
00164 
00165 #ifdef NON_LINEAR_PSY
00166 
00167 static const float non_linear_psy_constant = .3;
00168 
00169 #define NON_LINEAR_SCALE_ITEM(x)   pow((x), non_linear_psy_constant)
00170 #define NON_LINEAR_SCALE_SUM(x)    pow((x), 1/non_linear_psy_constant)
00171 
00172 #if 0
00173 #define NON_LINEAR_SCALE_ENERGY(x) pow(10, (x)/10)
00174 #else
00175 #define NON_LINEAR_SCALE_ENERGY(x) (x)
00176 #endif
00177 
00178 #else
00179 
00180 #define NON_LINEAR_SCALE_ITEM(x)   (x)
00181 #define NON_LINEAR_SCALE_SUM(x)    (x)
00182 #define NON_LINEAR_SCALE_ENERGY(x) (x)
00183 
00184 #endif
00185 
00186 
00187 /*
00188    L3psycho_anal.  Compute psycho acoustics.
00189 
00190    Data returned to the calling program must be delayed by one 
00191    granule. 
00192 
00193    This is done in two places.  
00194    If we do not need to know the blocktype, the copying
00195    can be done here at the top of the program: we copy the data for
00196    the last granule (computed during the last call) before it is
00197    overwritten with the new data.  It looks like this:
00198   
00199    0. static psymodel_data 
00200    1. calling_program_data = psymodel_data
00201    2. compute psymodel_data
00202     
00203    For data which needs to know the blocktype, the copying must be
00204    done at the end of this loop, and the old values must be saved:
00205    
00206    0. static psymodel_data_old 
00207    1. compute psymodel_data
00208    2. compute possible block type of this granule
00209    3. compute final block type of previous granule based on #2.
00210    4. calling_program_data = psymodel_data_old
00211    5. psymodel_data_old = psymodel_data
00212 */
00213 
00214 
00215 
00216 
00217 
00218 /* psycho_loudness_approx
00219    jd - 2001 mar 12
00220 in:  energy   - BLKSIZE/2 elements of frequency magnitudes ^ 2
00221      gfp      - uses out_samplerate, ATHtype (also needed for ATHformula)
00222 returns: loudness^2 approximation, a positive value roughly tuned for a value
00223          of 1.0 for signals near clipping.
00224 notes:   When calibrated, feeding this function binary white noise at sample
00225          values +32767 or -32768 should return values that approach 3.
00226          ATHformula is used to approximate an equal loudness curve.
00227 future:  Data indicates that the shape of the equal loudness curve varies
00228          with intensity.  This function might be improved by using an equal
00229          loudness curve shaped for typical playback levels (instead of the
00230          ATH, that is shaped for the threshold).  A flexible realization might
00231          simply bend the existing ATH curve to achieve the desired shape.
00232          However, the potential gain may not be enough to justify an effort.
00233 */
00234 static  FLOAT
00235 psycho_loudness_approx(FLOAT const *energy, lame_internal_flags const *gfc)
00236 {
00237     int     i;
00238     FLOAT   loudness_power;
00239 
00240     loudness_power = 0.0;
00241     /* apply weights to power in freq. bands */
00242     for (i = 0; i < BLKSIZE / 2; ++i)
00243         loudness_power += energy[i] * gfc->ATH->eql_w[i];
00244     loudness_power *= VO_SCALE;
00245 
00246     return loudness_power;
00247 }
00248 
00249 static void
00250 compute_ffts(lame_global_flags const *gfp,
00251              FLOAT fftenergy[HBLKSIZE],
00252              FLOAT(*fftenergy_s)[HBLKSIZE_s],
00253              FLOAT(*wsamp_l)[BLKSIZE],
00254              FLOAT(*wsamp_s)[3][BLKSIZE_s], int gr_out, int chn, const sample_t * buffer[2]
00255     )
00256 {
00257     int     b, j;
00258     lame_internal_flags *const gfc = gfp->internal_flags;
00259     if (chn < 2) {
00260         fft_long(gfc, *wsamp_l, chn, buffer);
00261         fft_short(gfc, *wsamp_s, chn, buffer);
00262     }
00263     /* FFT data for mid and side channel is derived from L & R */
00264     else if (chn == 2) {
00265         for (j = BLKSIZE - 1; j >= 0; --j) {
00266             FLOAT const l = wsamp_l[0][j];
00267             FLOAT const r = wsamp_l[1][j];
00268             wsamp_l[0][j] = (l + r) * (FLOAT) (SQRT2 * 0.5);
00269             wsamp_l[1][j] = (l - r) * (FLOAT) (SQRT2 * 0.5);
00270         }
00271         for (b = 2; b >= 0; --b) {
00272             for (j = BLKSIZE_s - 1; j >= 0; --j) {
00273                 FLOAT const l = wsamp_s[0][b][j];
00274                 FLOAT const r = wsamp_s[1][b][j];
00275                 wsamp_s[0][b][j] = (l + r) * (FLOAT) (SQRT2 * 0.5);
00276                 wsamp_s[1][b][j] = (l - r) * (FLOAT) (SQRT2 * 0.5);
00277             }
00278         }
00279     }
00280 
00281     /*********************************************************************
00282      *  compute energies
00283      *********************************************************************/
00284     fftenergy[0] = NON_LINEAR_SCALE_ENERGY(wsamp_l[0][0]);
00285     fftenergy[0] *= fftenergy[0];
00286 
00287     for (j = BLKSIZE / 2 - 1; j >= 0; --j) {
00288         FLOAT const re = (*wsamp_l)[BLKSIZE / 2 - j];
00289         FLOAT const im = (*wsamp_l)[BLKSIZE / 2 + j];
00290         fftenergy[BLKSIZE / 2 - j] = NON_LINEAR_SCALE_ENERGY((re * re + im * im) * 0.5f);
00291     }
00292     for (b = 2; b >= 0; --b) {
00293         fftenergy_s[b][0] = (*wsamp_s)[b][0];
00294         fftenergy_s[b][0] *= fftenergy_s[b][0];
00295         for (j = BLKSIZE_s / 2 - 1; j >= 0; --j) {
00296             FLOAT const re = (*wsamp_s)[b][BLKSIZE_s / 2 - j];
00297             FLOAT const im = (*wsamp_s)[b][BLKSIZE_s / 2 + j];
00298             fftenergy_s[b][BLKSIZE_s / 2 - j] = NON_LINEAR_SCALE_ENERGY((re * re + im * im) * 0.5f);
00299         }
00300     }
00301     /* total energy */
00302     {
00303         FLOAT   totalenergy = 0.0;
00304         for (j = 11; j < HBLKSIZE; j++)
00305             totalenergy += fftenergy[j];
00306 
00307         gfc->tot_ener[chn] = totalenergy;
00308     }
00309 
00310     if (gfp->analysis) {
00311         for (j = 0; j < HBLKSIZE; j++) {
00312             gfc->pinfo->energy[gr_out][chn][j] = gfc->pinfo->energy_save[chn][j];
00313             gfc->pinfo->energy_save[chn][j] = fftenergy[j];
00314         }
00315         gfc->pinfo->pe[gr_out][chn] = gfc->pe[chn];
00316     }
00317 
00318     /*********************************************************************
00319      * compute loudness approximation (used for ATH auto-level adjustment) 
00320      *********************************************************************/
00321     if (gfp->athaa_loudapprox == 2 && chn < 2) { /*no loudness for mid/side ch */
00322         gfc->loudness_sq[gr_out][chn] = gfc->loudness_sq_save[chn];
00323         gfc->loudness_sq_save[chn]
00324             = psycho_loudness_approx(fftenergy, gfc);
00325     }
00326 }
00327 
00328 /* mask_add optimization */
00329 /* init the limit values used to avoid computing log in mask_add when it is not necessary */
00330 
00331 /* For example, with i = 10*log10(m2/m1)/10*16         (= log10(m2/m1)*16)
00332  *
00333  * abs(i)>8 is equivalent (as i is an integer) to
00334  * abs(i)>=9
00335  * i>=9 || i<=-9
00336  * equivalent to (as i is the biggest integer smaller than log10(m2/m1)*16 
00337  * or the smallest integer bigger than log10(m2/m1)*16 depending on the sign of log10(m2/m1)*16)
00338  * log10(m2/m1)>=9/16 || log10(m2/m1)<=-9/16
00339  * exp10 is strictly increasing thus this is equivalent to
00340  * m2/m1 >= 10^(9/16) || m2/m1<=10^(-9/16) which are comparisons to constants
00341  */
00342 
00343 
00344 #define I1LIMIT 8       /* as in if(i>8)  */
00345 #define I2LIMIT 23      /* as in if(i>24) -> changed 23 */
00346 #define MLIMIT  15      /* as in if(m<15) */
00347 
00348 static FLOAT ma_max_i1;
00349 static FLOAT ma_max_i2;
00350 static FLOAT ma_max_m;
00351 
00352 
00353 
00354 static void
00355 init_mask_add_max_values(void)
00356 {
00357     ma_max_i1 = pow(10, (I1LIMIT + 1) / 16.0);
00358     ma_max_i2 = pow(10, (I2LIMIT + 1) / 16.0);
00359     ma_max_m = pow(10, (MLIMIT) / 10.0);
00360 }
00361 
00362 
00363 
00364 
00365 /* addition of simultaneous masking   Naoki Shibata 2000/7 */
00366 inline static FLOAT
00367 mask_add(FLOAT m1, FLOAT m2, int kk, int b, lame_internal_flags const *gfc, int shortblock)
00368 {
00369     static const FLOAT table1[] = {
00370         3.3246 * 3.3246, 3.23837 * 3.23837, 3.15437 * 3.15437, 3.00412 * 3.00412, 2.86103 * 2.86103,
00371         2.65407 * 2.65407, 2.46209 * 2.46209, 2.284 * 2.284,
00372         2.11879 * 2.11879, 1.96552 * 1.96552, 1.82335 * 1.82335, 1.69146 * 1.69146,
00373         1.56911 * 1.56911, 1.46658 * 1.46658, 1.37074 * 1.37074, 1.31036 * 1.31036,
00374         1.25264 * 1.25264, 1.20648 * 1.20648, 1.16203 * 1.16203, 1.12765 * 1.12765,
00375         1.09428 * 1.09428, 1.0659 * 1.0659, 1.03826 * 1.03826, 1.01895 * 1.01895,
00376         1
00377     };
00378 
00379     static const FLOAT table2[] = {
00380         1.33352 * 1.33352, 1.35879 * 1.35879, 1.38454 * 1.38454, 1.39497 * 1.39497,
00381         1.40548 * 1.40548, 1.3537 * 1.3537, 1.30382 * 1.30382, 1.22321 * 1.22321,
00382         1.14758 * 1.14758,
00383         1
00384     };
00385 
00386     static const FLOAT table3[] = {
00387         2.35364 * 2.35364, 2.29259 * 2.29259, 2.23313 * 2.23313, 2.12675 * 2.12675,
00388         2.02545 * 2.02545, 1.87894 * 1.87894, 1.74303 * 1.74303, 1.61695 * 1.61695,
00389         1.49999 * 1.49999, 1.39148 * 1.39148, 1.29083 * 1.29083, 1.19746 * 1.19746,
00390         1.11084 * 1.11084, 1.03826 * 1.03826
00391     };
00392 
00393 
00394     int     i;
00395     FLOAT   ratio;
00396 
00397 
00398     if (m2 > m1) {
00399         if (m2 < (m1 * ma_max_i2))
00400             ratio = m2 / m1;
00401         else
00402             return (m1 + m2);
00403     }
00404     else {
00405         if (m1 >= (m2 * ma_max_i2))
00406             return (m1 + m2);
00407         ratio = m1 / m2;
00408     }
00409     /*i = abs(10*log10(m2 / m1)/10*16);
00410        m = 10*log10((m1+m2)/gfc->ATH->cb[k]); */
00411 
00412 
00413     /* Should always be true, just checking */
00414     assert(m1 >= 0);
00415     assert(m2 >= 0);
00416 
00417 
00418     m1 += m2;
00419 
00420     if ((unsigned int) (b + 3) <= 3 + 3) { /* approximately, 1 bark = 3 partitions */
00421         /* 65% of the cases */
00422         /* originally 'if(i > 8)' */
00423         if (ratio >= ma_max_i1) {
00424             /* 43% of the total */
00425             return m1;
00426         }
00427 
00428         /* 22% of the total */
00429         i = (int)(FAST_LOG10_X(ratio, 16.0));
00430         return m1 * table2[i];
00431     }
00432 
00433     /* m<15 equ log10((m1+m2)/gfc->ATH->cb[k])<1.5
00434      * equ (m1+m2)/gfc->ATH->cb[k]<10^1.5
00435      * equ (m1+m2)<10^1.5 * gfc->ATH->cb[k]
00436      */
00437 
00438     i = (int)FAST_LOG10_X(ratio, 16.0);
00439     if (shortblock) {
00440         m2 = gfc->ATH->cb_s[kk] * gfc->ATH->adjust;
00441     }
00442     else {
00443         m2 = gfc->ATH->cb_l[kk] * gfc->ATH->adjust;
00444     }
00445     assert(m2 >= 0);
00446     if (m1 < ma_max_m * m2) {
00447         /* 3% of the total */
00448         /* Originally if (m > 0) { */
00449         if (m1 > m2) {
00450             FLOAT   f, r;
00451 
00452             f = 1.0;
00453             if (i <= 13)
00454                 f = table3[i];
00455 
00456             r = FAST_LOG10_X(m1 / m2, 10.0 / 15.0);
00457             return m1 * ((table1[i] - f) * r + f);
00458         }
00459 
00460         if (i > 13)
00461             return m1;
00462 
00463         return m1 * table3[i];
00464     }
00465 
00466 
00467     /* 10% of total */
00468     return m1 * table1[i];
00469 }
00470 
00471 
00472 /*************************************************************** 
00473  * compute interchannel masking effects
00474  ***************************************************************/
00475 static void
00476 calc_interchannel_masking(lame_global_flags const *gfp, FLOAT ratio)
00477 {
00478     lame_internal_flags *const gfc = gfp->internal_flags;
00479     int     sb, sblock;
00480     FLOAT   l, r;
00481     if (gfc->channels_out > 1) {
00482         for (sb = 0; sb < SBMAX_l; sb++) {
00483             l = gfc->thm[0].l[sb];
00484             r = gfc->thm[1].l[sb];
00485             gfc->thm[0].l[sb] += r * ratio;
00486             gfc->thm[1].l[sb] += l * ratio;
00487         }
00488         for (sb = 0; sb < SBMAX_s; sb++) {
00489             for (sblock = 0; sblock < 3; sblock++) {
00490                 l = gfc->thm[0].s[sb][sblock];
00491                 r = gfc->thm[1].s[sb][sblock];
00492                 gfc->thm[0].s[sb][sblock] += r * ratio;
00493                 gfc->thm[1].s[sb][sblock] += l * ratio;
00494             }
00495         }
00496     }
00497 }
00498 
00499 
00500 
00501 /*************************************************************** 
00502  * compute M/S thresholds from Johnston & Ferreira 1992 ICASSP paper
00503  ***************************************************************/
00504 static void
00505 msfix1(lame_internal_flags * gfc)
00506 {
00507     int     sb, sblock;
00508     FLOAT   rside, rmid, mld;
00509     for (sb = 0; sb < SBMAX_l; sb++) {
00510         /* use this fix if L & R masking differs by 2db or less */
00511         /* if db = 10*log10(x2/x1) < 2 */
00512         /* if (x2 < 1.58*x1) { */
00513         if (gfc->thm[0].l[sb] > 1.58 * gfc->thm[1].l[sb]
00514             || gfc->thm[1].l[sb] > 1.58 * gfc->thm[0].l[sb])
00515             continue;
00516 
00517         mld = gfc->mld_l[sb] * gfc->en[3].l[sb];
00518         rmid = Max(gfc->thm[2].l[sb], Min(gfc->thm[3].l[sb], mld));
00519 
00520         mld = gfc->mld_l[sb] * gfc->en[2].l[sb];
00521         rside = Max(gfc->thm[3].l[sb], Min(gfc->thm[2].l[sb], mld));
00522         gfc->thm[2].l[sb] = rmid;
00523         gfc->thm[3].l[sb] = rside;
00524     }
00525 
00526     for (sb = 0; sb < SBMAX_s; sb++) {
00527         for (sblock = 0; sblock < 3; sblock++) {
00528             if (gfc->thm[0].s[sb][sblock] > 1.58 * gfc->thm[1].s[sb][sblock]
00529                 || gfc->thm[1].s[sb][sblock] > 1.58 * gfc->thm[0].s[sb][sblock])
00530                 continue;
00531 
00532             mld = gfc->mld_s[sb] * gfc->en[3].s[sb][sblock];
00533             rmid = Max(gfc->thm[2].s[sb][sblock], Min(gfc->thm[3].s[sb][sblock], mld));
00534 
00535             mld = gfc->mld_s[sb] * gfc->en[2].s[sb][sblock];
00536             rside = Max(gfc->thm[3].s[sb][sblock], Min(gfc->thm[2].s[sb][sblock], mld));
00537 
00538             gfc->thm[2].s[sb][sblock] = rmid;
00539             gfc->thm[3].s[sb][sblock] = rside;
00540         }
00541     }
00542 }
00543 
00544 /*************************************************************** 
00545  * Adjust M/S maskings if user set "msfix"
00546  ***************************************************************/
00547 /* Naoki Shibata 2000 */
00548 static void
00549 ns_msfix(lame_internal_flags * gfc, FLOAT msfix, FLOAT athadjust)
00550 {
00551     int     sb, sblock;
00552     FLOAT   msfix2 = msfix;
00553     FLOAT   athlower = pow(10, athadjust);
00554 
00555     msfix *= 2.0;
00556     msfix2 *= 2.0;
00557     for (sb = 0; sb < SBMAX_l; sb++) {
00558         FLOAT   thmLR, thmM, thmS, ath;
00559         ath = (gfc->ATH->cb_l[gfc->bm_l[sb]]) * athlower;
00560         thmLR = Min(Max(gfc->thm[0].l[sb], ath), Max(gfc->thm[1].l[sb], ath));
00561         thmM = Max(gfc->thm[2].l[sb], ath);
00562         thmS = Max(gfc->thm[3].l[sb], ath);
00563         if (thmLR * msfix < thmM + thmS) {
00564             FLOAT const f = thmLR * msfix2 / (thmM + thmS);
00565             thmM *= f;
00566             thmS *= f;
00567             assert( thmM+thmS > 0 );
00568         }
00569         gfc->thm[2].l[sb] = Min(thmM, gfc->thm[2].l[sb]);
00570         gfc->thm[3].l[sb] = Min(thmS, gfc->thm[3].l[sb]);
00571     }
00572 
00573     athlower *= ((FLOAT) BLKSIZE_s / BLKSIZE);
00574     for (sb = 0; sb < SBMAX_s; sb++) {
00575         for (sblock = 0; sblock < 3; sblock++) {
00576             FLOAT   thmLR, thmM, thmS, ath;
00577             ath = (gfc->ATH->cb_s[gfc->bm_s[sb]]) * athlower;
00578             thmLR = Min(Max(gfc->thm[0].s[sb][sblock], ath), Max(gfc->thm[1].s[sb][sblock], ath));
00579             thmM = Max(gfc->thm[2].s[sb][sblock], ath);
00580             thmS = Max(gfc->thm[3].s[sb][sblock], ath);
00581 
00582             if (thmLR * msfix < thmM + thmS) {
00583                 FLOAT const f = thmLR * msfix / (thmM + thmS);
00584                 thmM *= f;
00585                 thmS *= f;
00586                 assert( thmM+thmS > 0 );
00587             }
00588             gfc->thm[2].s[sb][sblock] = Min(gfc->thm[2].s[sb][sblock], thmM);
00589             gfc->thm[3].s[sb][sblock] = Min(gfc->thm[3].s[sb][sblock], thmS);
00590         }
00591     }
00592 }
00593 
00594 /* short block threshold calculation (part 2)
00595 
00596     partition band bo_s[sfb] is at the transition from scalefactor
00597     band sfb to the next one sfb+1; enn and thmm have to be split
00598     between them
00599 */
00600 static void
00601 convert_partition2scalefac_s(lame_internal_flags * gfc, FLOAT const *eb, FLOAT const* thr, int chn, int sblock)
00602 {
00603     FLOAT   enn, thmm;
00604     int     sb, b;
00605     enn = thmm = 0.0;
00606     for (sb = b = 0; sb < SBMAX_s; ++b, ++sb) {
00607         int const bo_s_sb = gfc->bo_s[sb];
00608         int const npart_s = gfc->npart_s;
00609         int const b_lim = bo_s_sb < npart_s ? bo_s_sb : npart_s;
00610         while (b < b_lim) {
00611             assert( eb[b] >= 0 );   /* iff failed, it may indicate some index error elsewhere */
00612             assert( thr[b] >= 0 );
00613             enn += eb[b];
00614             thmm += thr[b];
00615             b++;
00616         }
00617         gfc->en[chn].s[sb][sblock] = enn;
00618         gfc->thm[chn].s[sb][sblock] = thmm;
00619 
00620         if (b >= npart_s) {
00621             ++sb;
00622             break;
00623         }
00624         assert( eb[b] >= 0 );   /* iff failed, it may indicate some index error elsewhere */
00625         assert( thr[b] >= 0 );
00626         {
00627             /* at transition sfb -> sfb+1 */
00628             FLOAT const w_curr = gfc->PSY->bo_s_weight[sb];
00629             FLOAT const w_next = 1.0 - w_curr; 
00630             enn = w_curr * eb[b];
00631             thmm = w_curr * thr[b];
00632             gfc->en[chn].s[sb][sblock] += enn;
00633             gfc->thm[chn].s[sb][sblock] += thmm;
00634             enn = w_next * eb[b];
00635             thmm = w_next * thr[b];
00636         }
00637     }
00638     /* zero initialize the rest */
00639     for (; sb < SBMAX_s; ++sb) {
00640         gfc->en[chn].s[sb][sblock] = 0;
00641         gfc->thm[chn].s[sb][sblock] = 0;
00642     }
00643 }
00644 
00645 /* longblock threshold calculation (part 2) */
00646 static void
00647 convert_partition2scalefac_l(lame_internal_flags * gfc, FLOAT const *eb, FLOAT const *thr, int chn)
00648 {
00649     FLOAT   enn, thmm;
00650     int     sb, b;
00651     enn = thmm = 0.0;
00652     for (sb = b = 0; sb < SBMAX_l; ++b, ++sb) {
00653         int const bo_l_sb = gfc->bo_l[sb];
00654         int const npart_l = gfc->npart_l;
00655         int const b_lim = bo_l_sb < npart_l ? bo_l_sb : npart_l;
00656         while (b < b_lim) {
00657             assert( eb[b] >= 0 );   /* iff failed, it may indicate some index error elsewhere */
00658             assert( thr[b] >= 0 );
00659             enn += eb[b];
00660             thmm += thr[b];
00661             b++;
00662         }
00663         gfc->en[chn].l[sb] = enn;
00664         gfc->thm[chn].l[sb] = thmm;
00665 
00666         if (b >= npart_l) {
00667             ++sb;
00668             break;
00669         }
00670         assert( eb[b] >= 0 );
00671         assert( thr[b] >= 0 );
00672         {
00673             /* at transition sfb -> sfb+1 */
00674             FLOAT const w_curr = gfc->PSY->bo_l_weight[sb];
00675             FLOAT const w_next = 1.0 - w_curr; 
00676             enn = w_curr * eb[b];
00677             thmm = w_curr * thr[b];
00678             gfc->en[chn].l[sb] += enn;
00679             gfc->thm[chn].l[sb] += thmm;
00680             enn = w_next * eb[b];
00681             thmm = w_next * thr[b];
00682         }
00683     }
00684     /* zero initialize the rest */
00685     for (; sb < SBMAX_l; ++sb) {
00686         gfc->en[chn].l[sb] = 0;
00687         gfc->thm[chn].l[sb] = 0;
00688     }
00689 }
00690 
00691 static void
00692 compute_masking_s(lame_global_flags const *gfp,
00693                   FLOAT const (*fftenergy_s)[HBLKSIZE_s],
00694                   FLOAT * eb, FLOAT * thr, int chn, int sblock)
00695 {
00696     lame_internal_flags *const gfc = gfp->internal_flags;
00697     FLOAT   max[CBANDS];
00698     int     i, j, b;
00699 
00700     for (b = j = 0; b < gfc->npart_s; ++b) {
00701         FLOAT   ebb = 0, m = 0;
00702         int const n = gfc->numlines_s[b];
00703         for (i = 0; i < n; ++i, ++j) {
00704             FLOAT const el = fftenergy_s[sblock][j];
00705             ebb += el;
00706             if (m < el)
00707                 m = el;
00708         }
00709         eb[b] = ebb;
00710         max[b] = m;
00711     }
00712     assert( b == gfc->npart_s );
00713     assert( j == 129 );
00714     for (j = b = 0; b < gfc->npart_s; b++) {
00715         int     kk = gfc->s3ind_s[b][0];
00716         FLOAT   ecb = gfc->s3_ss[j++] * eb[kk++];
00717         while (kk <= gfc->s3ind_s[b][1]) {
00718             FLOAT const x = gfc->s3_ss[j] * eb[kk];
00719 #ifdef SHORT_BLOCK_MASK_ADD
00720             ecb = mask_add(ecb, x, kk, kk - b, gfc, 1);
00721 #else
00722             ecb += x;
00723 #endif
00724             ++j, ++kk;
00725         }
00726         if (gfp->VBR == vbr_mtrh || gfp->VBR == vbr_mt) {
00727             ecb *= 0.158489319246111; /* pow(10,-0.8) */
00728         }
00729 
00730         {               /* limit calculated threshold by previous granule */
00731             FLOAT const x = rpelev_s * gfc->nb_s1[chn][b];
00732             thr[b] = Min(ecb, x);
00733         }
00734         if (gfc->blocktype_old[chn & 1] == SHORT_TYPE) {
00735             /* limit calculated threshold by even older granule */
00736             FLOAT const x = rpelev2_s * gfc->nb_s2[chn][b];
00737             FLOAT const y = thr[b];
00738             thr[b] = Min(x, y);
00739         }
00740 
00741         if (gfp->VBR == vbr_mtrh || gfp->VBR == vbr_mt) {
00742             /*  if THR exceeds EB, the quantization routines will take the difference
00743              *  from other bands. in case of strong tonal samples (tonaltest.wav)
00744              *  this leads to heavy distortions. that's why we limit THR here.
00745              */
00746             FLOAT   x = max[b];
00747             x *= gfc->numlines_s[b];
00748             x *= gfc->minval_s[b];
00749 #if 0
00750             x *= 0.5f;
00751 #else
00752             x *= 0.158489319246111; /* pow(10,-0.8) */
00753 #endif
00754             /* no tonality estimation here
00755                if (eb[b] > 0.0f) {
00756                x *= eb2[b]/eb[b];
00757                }
00758              */
00759             if (thr[b] > x) {
00760                 thr[b] = x;
00761             }
00762         }
00763 
00764         gfc->nb_s2[chn][b] = gfc->nb_s1[chn][b];
00765         gfc->nb_s1[chn][b] = ecb;
00766         assert(thr[b] >= 0);
00767     }
00768 }
00769 
00770 static void
00771 block_type_set(lame_global_flags const *gfp, int *uselongblock, int *blocktype_d, int *blocktype)
00772 {
00773     lame_internal_flags *const gfc = gfp->internal_flags;
00774     int     chn;
00775 
00776     if (gfp->short_blocks == short_block_coupled
00777         /* force both channels to use the same block type */
00778         /* this is necessary if the frame is to be encoded in ms_stereo.  */
00779         /* But even without ms_stereo, FhG  does this */
00780         && !(uselongblock[0] && uselongblock[1]))
00781         uselongblock[0] = uselongblock[1] = 0;
00782 
00783     /* update the blocktype of the previous granule, since it depends on what
00784      * happend in this granule */
00785     for (chn = 0; chn < gfc->channels_out; chn++) {
00786         blocktype[chn] = NORM_TYPE;
00787         /* disable short blocks */
00788         if (gfp->short_blocks == short_block_dispensed)
00789             uselongblock[chn] = 1;
00790         if (gfp->short_blocks == short_block_forced)
00791             uselongblock[chn] = 0;
00792 
00793         if (uselongblock[chn]) {
00794             /* no attack : use long blocks */
00795             assert(gfc->blocktype_old[chn] != START_TYPE);
00796             if (gfc->blocktype_old[chn] == SHORT_TYPE)
00797                 blocktype[chn] = STOP_TYPE;
00798         }
00799         else {
00800             /* attack : use short blocks */
00801             blocktype[chn] = SHORT_TYPE;
00802             if (gfc->blocktype_old[chn] == NORM_TYPE) {
00803                 gfc->blocktype_old[chn] = START_TYPE;
00804             }
00805             if (gfc->blocktype_old[chn] == STOP_TYPE)
00806                 gfc->blocktype_old[chn] = SHORT_TYPE;
00807         }
00808 
00809         blocktype_d[chn] = gfc->blocktype_old[chn]; /* value returned to calling program */
00810         gfc->blocktype_old[chn] = blocktype[chn]; /* save for next call to l3psy_anal */
00811     }
00812 }
00813 
00814 static void
00815 determine_block_type(lame_global_flags const *gfp, FLOAT const fftenergy_s[3][HBLKSIZE_s],
00816                      int uselongblock[], int chn, int gr_out, FLOAT * pe)
00817 {
00818     lame_internal_flags const *const gfc = gfp->internal_flags;
00819     int     j;
00820     /*************************************************************** 
00821      * determine the block type (window type) based on L & R cannels
00822      ***************************************************************/
00823     /* compute PE for all 4 channels */
00824     FLOAT   mn, mx, ma = 0, mb = 0, mc = 0;
00825     for (j = HBLKSIZE_s / 2; j < HBLKSIZE_s; j++) {
00826         ma += fftenergy_s[0][j];
00827         mb += fftenergy_s[1][j];
00828         mc += fftenergy_s[2][j];
00829     }
00830     mn = Min(ma, mb);
00831     mn = Min(mn, mc);
00832     mx = Max(ma, mb);
00833     mx = Max(mx, mc);
00834 
00835     if (gfp->analysis) {
00836         gfc->pinfo->ers[gr_out][chn] = gfc->pinfo->ers_save[chn];
00837         gfc->pinfo->ers_save[chn] = (mx / (1e-12 + mn));
00838     }
00839 
00840     /* bit allocation is based on pe.  */
00841     if (mx > mn) {
00842         FLOAT const tmp = FAST_LOG_X(mx / (1e-12 + mn), 400.0);
00843         if (tmp > *pe)
00844             *pe = tmp;
00845     }
00846 
00847     /* block type is based just on L or R channel */
00848     if (chn < 2) {
00849         uselongblock[chn] = 1;
00850 
00851         /* tuned for t1.wav.  doesnt effect most other samples */
00852         if (*pe > 3000)
00853             uselongblock[chn] = 0;
00854 
00855         if (mx > 30 * mn) { /* big surge of energy - always use short blocks */
00856             uselongblock[chn] = 0;
00857         }
00858         else if ((mx > 10 * mn) && (*pe > 1000)) { /* medium surge, medium pe - use short blocks */
00859             uselongblock[chn] = 0;
00860         }
00861     }
00862 }
00863 
00864 int
00865 L3psycho_anal(lame_global_flags const *gfp,
00866               const sample_t * buffer[2], int gr_out,
00867               FLOAT * ms_ratio,
00868               FLOAT * ms_ratio_next,
00869               III_psy_ratio masking_ratio[2][2],
00870               III_psy_ratio masking_MS_ratio[2][2],
00871               FLOAT percep_entropy[2], FLOAT percep_MS_entropy[2],
00872               FLOAT energy[4], int blocktype_d[2])
00873 {
00874     lame_internal_flags *const gfc = gfp->internal_flags;
00875 
00876     /* fft and energy calculation   */
00877     FLOAT   wsamp_L[2][BLKSIZE];
00878     FLOAT   wsamp_S[2][3][BLKSIZE_s];
00879     FLOAT   fftenergy[HBLKSIZE];
00880     FLOAT   fftenergy_s[3][HBLKSIZE_s];
00881 
00882     /* convolution   */
00883     FLOAT   eb[CBANDS + 1];
00884     FLOAT   cb[CBANDS];
00885     FLOAT   thr[CBANDS + 1];
00886 
00887     /* ratios    */
00888     FLOAT   ms_ratio_l = 0, ms_ratio_s = 0;
00889 
00890     /* block type  */
00891     int     blocktype[2], uselongblock[2];
00892 
00893     /* usual variables like loop indices, etc..    */
00894     int     numchn, chn;
00895     int     b, i, j, k;
00896     int     sb, sblock;
00897 
00898     /*  rh 20040301: the following loops do access one off the limits
00899      *  so I increase  the array dimensions by one and initialize the
00900      *  accessed values to zero
00901      */
00902     assert(gfc->npart_s <= CBANDS);
00903     assert(gfc->npart_l <= CBANDS);
00904     eb[gfc->npart_s] = 0;
00905     thr[gfc->npart_s] = 0;
00906     eb[gfc->npart_l] = 0;
00907     thr[gfc->npart_l] = 0;
00908 
00909     numchn = gfc->channels_out;
00910     /* chn=2 and 3 = Mid and Side channels */
00911     if (gfp->mode == JOINT_STEREO)
00912         numchn = 4;
00913 
00914     for (chn = 0; chn < numchn; chn++) {
00915         FLOAT(*wsamp_l)[BLKSIZE];
00916         FLOAT(*wsamp_s)[3][BLKSIZE_s];
00917         FLOAT   max[CBANDS];
00918         energy[chn] = gfc->tot_ener[chn];
00919 
00920         /* there is a one granule delay.  Copy maskings computed last call
00921          * into masking_ratio to return to calling program.
00922          */
00923         if (chn < 2) {
00924             /* LR maskings  */
00925             percep_entropy[chn] = gfc->pe[chn];
00926             masking_ratio[gr_out][chn].en = gfc->en[chn];
00927             masking_ratio[gr_out][chn].thm = gfc->thm[chn];
00928         }
00929         else {
00930             /* MS maskings  */
00931             percep_MS_entropy[chn - 2] = gfc->pe[chn];
00932             masking_MS_ratio[gr_out][chn - 2].en = gfc->en[chn];
00933             masking_MS_ratio[gr_out][chn - 2].thm = gfc->thm[chn];
00934         }
00935 
00936         /*********************************************************************
00937          *  compute FFTs
00938          *********************************************************************/
00939         wsamp_s = wsamp_S + (chn & 1);
00940         wsamp_l = wsamp_L + (chn & 1);
00941         compute_ffts(gfp, fftenergy, fftenergy_s, wsamp_l, wsamp_s, gr_out, chn, buffer);
00942 
00943         /*********************************************************************
00944          *    compute unpredicatability of first six spectral lines
00945          *********************************************************************/
00946         for (j = 0; j < CW_LOWER_INDEX; j++) {
00947             /* calculate unpredictability measure cw */
00948             FLOAT   a2, b2, r1, r2;
00949             FLOAT   numre, numim, den;
00950 
00951             a2 = gfc->ax_sav[chn][1][j];
00952             b2 = gfc->bx_sav[chn][1][j];
00953 
00954             r2 = gfc->rx_sav[chn][1][j];
00955             r1 = gfc->rx_sav[chn][1][j] = gfc->rx_sav[chn][0][j];
00956 
00957             /* square (x1,y1) */
00958             if (r1 != 0.0) {
00959                 FLOAT const a1 = gfc->ax_sav[chn][1][j] = gfc->ax_sav[chn][0][j];
00960                 FLOAT const b1 = gfc->bx_sav[chn][1][j] = gfc->bx_sav[chn][0][j];
00961                 den = r1 * r1;
00962                 numre = a1 * b1;
00963                 numim = den - b1 * b1;
00964             }
00965             else {
00966                 /* no aging is needed for ax_sav[chn][0][j] and that of bx
00967                    because if r1=0, r2 should be 0 for next time. */
00968                 den = numre = 1.0;
00969                 numim = 0.0;
00970             }
00971 
00972             /* multiply by (x2,-y2) */
00973             if (r2 != 0.0) {
00974                 FLOAT const tmp2 = (numim + numre) * (a2 + b2) * 0.5f;
00975                 FLOAT const tmp1 = -a2 * numre + tmp2;
00976                 numre = -b2 * numim + tmp2;
00977                 numim = tmp1;
00978                 den *= r2;
00979             }
00980 
00981             r1 = 2.0f * r1 - r2;
00982             r2 = gfc->rx_sav[chn][0][j] = sqrt(fftenergy[j]);
00983             r2 = r2 + fabs(r1);
00984             if (r2 != 0) {
00985                 FLOAT const an = gfc->ax_sav[chn][0][j] = wsamp_l[0][j];
00986                 FLOAT const bn = gfc->bx_sav[chn][0][j] =
00987                     (j == 0 ? wsamp_l[0][0] : wsamp_l[0][BLKSIZE - j]);
00988                 assert( den != 0 );
00989                 den = r1 / den * 2.0;
00990                 numre = (an + bn) - numre * den;
00991                 numim = (an - bn) - numim * den;
00992                 r2 = sqrt(numre * numre + numim * numim) / (r2 * 2.0);
00993             }
00994             gfc->cw[j] = r2;
00995         }
00996 
00997         /**********************************************************************
00998          *     compute unpredicatibility of next 200 spectral lines
00999          *********************************************************************/
01000         for (; j < gfc->cw_upper_index; j += 4) {
01001             /* calculate unpredictability measure cw */
01002             FLOAT   rn, r1, r2;
01003             FLOAT   numre, numim, den;
01004             k = (j + 2) / 4;
01005             /* square (x1,y1) */
01006             r1 = fftenergy_s[0][k];
01007             if (r1 != 0.0) {
01008                 FLOAT const a1 = (*wsamp_s)[0][k];
01009                 FLOAT const b1 = (*wsamp_s)[0][BLKSIZE_s - k]; /* k is never 0 */
01010                 numre = a1 * b1;
01011                 numim = r1 - b1 * b1;
01012                 den = r1;
01013                 r1 = sqrt(r1);
01014             }
01015             else {
01016                 den = numre = 1.0;
01017                 numim = 0.0;
01018             }
01019 
01020             /* multiply by (x2,-y2) */
01021             r2 = fftenergy_s[2][k];
01022             if (r2 != 0.0) {
01023                 FLOAT const a2 = (*wsamp_s)[2][k];
01024                 FLOAT const b2 = (*wsamp_s)[2][BLKSIZE_s - k];
01025 
01026                 FLOAT const tmp2 = (numim + numre) * (a2 + b2) * 0.5f;
01027                 FLOAT const tmp1 = tmp2 - a2 * numre;
01028                 numre = tmp2 - b2 * numim;
01029                 numim = tmp1;
01030 
01031                 r2 = sqrt(r2);
01032                 den *= r2;
01033             }
01034 
01035             /* r-prime factor */
01036             rn = sqrt(fftenergy_s[1][k]) + fabs(2 * r1 - r2);
01037             if (rn != 0) {
01038                 FLOAT const an = (*wsamp_s)[1][k];
01039                 FLOAT const bn = (*wsamp_s)[1][BLKSIZE_s - k];
01040                 assert( den != 0 );
01041                 den = (2 * r1 - r2) / den * 2.0f;
01042                 numre = (an + bn) - numre * den;
01043                 numim = (an - bn) - numim * den;
01044                 rn = sqrt(numre * numre + numim * numim) / (rn * 2.0f);
01045             }
01046             gfc->cw[j + 1] = gfc->cw[j + 2] = gfc->cw[j + 3] = gfc->cw[j] = rn;
01047         }
01048 
01049         /**********************************************************************
01050          *    Calculate the energy and the unpredictability in the threshold
01051          *    calculation partitions
01052          *********************************************************************/
01053 
01054         for (b = j = 0; j < gfc->cw_upper_index && gfc->numlines_l[b] && b < gfc->npart_l; ++b) {
01055             FLOAT   m = 0;
01056             FLOAT   ebb = 0, cbb = 0;
01057             int const n = gfc->numlines_l[b];
01058             for (i = 0; i < n; ++i, ++j) {
01059                 FLOAT const el = fftenergy[j];
01060                 FLOAT const el_cw = el * gfc->cw[j];
01061                 ebb += NON_LINEAR_SCALE_ITEM(el);
01062                 /* XXX: should "* gfc->cw[j])" be outside of the scaling? */
01063                 cbb += NON_LINEAR_SCALE_ITEM(el_cw);
01064                 if (m < el)
01065                     m = el;
01066             }
01067             eb[b] = NON_LINEAR_SCALE_SUM(ebb);
01068             cb[b] = NON_LINEAR_SCALE_SUM(cbb);
01069             max[b] = m;
01070         }
01071         for (; b < gfc->npart_l; ++b) {
01072             FLOAT   m = 0, ebb = 0;
01073             int const n = gfc->numlines_l[b];
01074             for (i = 0; i < n; ++i, ++j) {
01075                 FLOAT const el = fftenergy[j];
01076                 ebb += NON_LINEAR_SCALE_ITEM(el);
01077                 if (m < el)
01078                     m = el;
01079             }
01080             eb[b] = NON_LINEAR_SCALE_SUM(ebb);
01081             /* XXX: should the "* .4" be outside of the scaling? */
01082             cb[b] = NON_LINEAR_SCALE_SUM(ebb * 0.4);
01083             max[b] = m;
01084         }
01085         assert( b == gfc->npart_l );
01086         assert( j == 513 );
01087 
01088         /**********************************************************************
01089          *      convolve the partitioned energy and unpredictability
01090          *      with the spreading function, s3_l[b][k](packed into s3_ll)
01091          *********************************************************************/
01092         /*  calculate percetual entropy */
01093         gfc->pe[chn] = 0;
01094         k = 0;
01095         for (b = 0; b < gfc->npart_l; b++) {
01096             FLOAT   tbb, ecb, ctb, reduction;
01097             int     kk;
01098             ecb = ctb = 0.;
01099             for (kk = gfc->s3ind[b][0]; kk <= gfc->s3ind[b][1]; kk++) {
01100                 /* sprdngf for Layer III */
01101                 ecb += gfc->s3_ll[k] * eb[kk];
01102                 ctb += gfc->s3_ll[k] * cb[kk];
01103                 k++;
01104             }
01105 
01106 /* calculate the tonality of each threshold calculation partition 
01107  * calculate the SNR in each threshold calculation partition 
01108  * tonality = -0.299 - .43*log(ctb/ecb);
01109  * tonality = 0:           use NMT   (lots of masking)
01110  * tonality = 1:           use TMN   (little masking)
01111  */
01112             tbb = ecb;
01113             if (tbb != 0.0) {
01114                 tbb = ctb / tbb;
01115                 /* convert to tonality index */
01116                 /* tonality small:   tbb=1 */
01117                 /* tonality large:   tbb=-.299 */
01118                 tbb = CONV1 + FAST_LOG_X(tbb, CONV2);
01119                 if (tbb < 0.0)
01120                     tbb = exp(-LN_TO_LOG10 * NMT);
01121                 else if (tbb > 1.0)
01122                     tbb = exp(-LN_TO_LOG10 * TMN);
01123                 else
01124                     tbb = exp(-LN_TO_LOG10 * ((TMN - NMT) * tbb + NMT));
01125                 reduction = tbb * exp(LN_TO_LOG10 * NMT);
01126             }
01127             else {
01128                 reduction = 1.0f;
01129             }
01130 
01131 /* at this point, tbb represents the amount the spreading function
01132  * will be reduced.  The smaller the value, the less masking.
01133  * minval[] = 1 (0db)     says just use tbb.
01134  * minval[]= .01 (-20db)  says reduce spreading function by at least 20db.
01135  */
01136             tbb = Min(gfc->minval_l[b], tbb);
01137             ecb *= tbb;
01138 
01139             /* long block pre-echo control.   */
01140             /* rpelev=2.0, rpelev2=16.0 */
01141             /* note: all surges in PE are because of this pre-echo formula
01142              * for thr[b].  If it this is not used, PE is always around 600
01143              */
01144             /* dont use long block pre-echo control if previous granule was
01145              * a short block.  This is to avoid the situation:   
01146              * frame0:  quiet (very low masking)  
01147              * frame1:  surge  (triggers short blocks)
01148              * frame2:  regular frame. looks like pre-echo when compared to
01149              *          frame0, but all pre-echo was in frame1.
01150              */
01151             /* chn=0,1   L and R channels
01152                chn=2,3   S and M channels.  
01153              */
01154             thr[b] = Min(ecb, rpelev * gfc->nb_1[chn][b]);
01155             if (gfc->blocktype_old[chn & 1] != SHORT_TYPE && thr[b] > rpelev2 * gfc->nb_2[chn][b])
01156                 thr[b] = rpelev2 * gfc->nb_2[chn][b];
01157 
01158             if (gfp->VBR == vbr_mtrh || gfp->VBR == vbr_mt) {
01159                 /*  if THR exceeds EB, the quantization routines will take the difference
01160                  *  from other bands. in case of strong tonal samples (tonaltest.wav, Wind Saxophon)
01161                  *  this leads to heavy distortions. that's why we limit THR here.
01162                  */
01163                 FLOAT   x = max[b];
01164                 x *= gfc->numlines_l[b];
01165                 x *= gfc->minval_l[b];
01166 #if 0
01167                 x *= 0.5f;
01168 #else
01169                 x *= 0.158489319246111; /* pow(10,-0.8) */
01170 #endif
01171                 x *= reduction;
01172                 if (thr[b] > x) {
01173                     thr[b] = x;
01174                 }
01175             }
01176 
01177             gfc->nb_2[chn][b] = gfc->nb_1[chn][b];
01178             gfc->nb_1[chn][b] = ecb;
01179 
01180             ecb = Max(thr[b], gfc->ATH->cb_l[b] * gfc->ATH->adjust);
01181             if (ecb < eb[b]) {
01182                 assert( eb[b] > 0 );
01183                 gfc->pe[chn] -= gfc->numlines_l[b] * FAST_LOG(ecb / eb[b]);
01184             }
01185         }
01186 
01187         determine_block_type(gfp, fftenergy_s, uselongblock, chn, gr_out, &gfc->pe[chn]);
01188 
01189         /* compute masking thresholds for long blocks */
01190         convert_partition2scalefac_l(gfc, eb, thr, chn);
01191 
01192         /* compute masking thresholds for short blocks */
01193         for (sblock = 0; sblock < 3; sblock++) {
01194             compute_masking_s(gfp, fftenergy_s, eb, thr, chn, sblock);
01195             convert_partition2scalefac_s(gfc, eb, thr, chn, sblock);
01196         }
01197     }                   /* end loop over chn */
01198 
01199     if (gfp->interChRatio != 0.0)
01200         calc_interchannel_masking(gfp, gfp->interChRatio);
01201 
01202     if (gfp->mode == JOINT_STEREO) {
01203         FLOAT   db, x1, x2, sidetot = 0, tot = 0;
01204         msfix1(gfc);
01205         if (gfp->msfix != 0.0)
01206             ns_msfix(gfc, gfp->msfix, gfp->ATHlower * gfc->ATH->adjust);
01207 
01208         /* determin ms_ratio from masking thresholds */
01209         /* use ms_stereo (ms_ratio < .35) if average thresh. diff < 5 db */
01210         for (sb = SBMAX_l / 4; sb < SBMAX_l; sb++) {
01211             x1 = Min(gfc->thm[0].l[sb], gfc->thm[1].l[sb]);
01212             x2 = Max(gfc->thm[0].l[sb], gfc->thm[1].l[sb]);
01213             /* thresholds difference in db */
01214             if (x2 >= 1000 * x1)
01215                 db = 3;
01216             else {
01217                 assert( x1 > 0 );
01218                 db = FAST_LOG10(x2 / x1);
01219             }
01220             /*  DEBUGF(gfc,"db = %f %e %e  \n",db,gfc->thm[0].l[sb],gfc->thm[1].l[sb]); */
01221             sidetot += db;
01222             tot++;
01223         }
01224         assert( tot > 0 );
01225         ms_ratio_l = (sidetot / tot) * 0.7; /* was .35*(sidetot/tot)/5.0*10 */
01226         ms_ratio_l = Min(ms_ratio_l, 0.5);
01227 
01228         sidetot = 0;
01229         tot = 0;
01230         for (sblock = 0; sblock < 3; sblock++)
01231             for (sb = SBMAX_s / 4; sb < SBMAX_s; sb++) {
01232                 x1 = Min(gfc->thm[0].s[sb][sblock], gfc->thm[1].s[sb][sblock]);
01233                 x2 = Max(gfc->thm[0].s[sb][sblock], gfc->thm[1].s[sb][sblock]);
01234                 /* thresholds difference in db */
01235                 if (x2 >= 1000 * x1)
01236                     db = 3;
01237                 else {
01238                     assert( x1 > 0 );
01239                     db = FAST_LOG10(x2 / x1);
01240                 }
01241                 sidetot += db;
01242                 tot++;
01243             }
01244             assert( tot > 0 );
01245         ms_ratio_s = (sidetot / tot) * 0.7; /* was .35*(sidetot/tot)/5.0*10 */
01246         ms_ratio_s = Min(ms_ratio_s, .5);
01247     }
01248 
01249     /*************************************************************** 
01250      * determine final block type
01251      ***************************************************************/
01252     block_type_set(gfp, uselongblock, blocktype_d, blocktype);
01253 
01254     if (blocktype_d[0] == SHORT_TYPE && blocktype_d[1] == SHORT_TYPE)
01255         *ms_ratio = gfc->ms_ratio_s_old;
01256     else
01257         *ms_ratio = gfc->ms_ratio_l_old;
01258 
01259     gfc->ms_ratio_s_old = ms_ratio_s;
01260     gfc->ms_ratio_l_old = ms_ratio_l;
01261 
01262     /* we dont know the block type of this frame yet - assume long */
01263     *ms_ratio_next = ms_ratio_l;
01264 
01265     return 0;
01266 }
01267 
01268 
01269 
01270 
01271 static inline FLOAT
01272 NS_INTERP(FLOAT x, FLOAT y, FLOAT r)
01273 {
01274     /* was pow((x),(r))*pow((y),1-(r)) */
01275     if (r == 1.0)
01276         return x;       /* 99.7% of the time */
01277     if (r == 0.0)
01278         return y;
01279     if (y > 0.0)
01280         return pow(x / y, r) * y; /* rest of the time */
01281     return 0.0;         /* never happens */
01282 }
01283 
01284 
01285 
01286 static  FLOAT
01287 pecalc_s(III_psy_ratio const *mr, FLOAT masking_lower)
01288 {
01289     FLOAT   pe_s;
01290     static const FLOAT regcoef_s[] = {
01291         11.8,           /* these values are tuned only for 44.1kHz... */
01292         13.6,
01293         17.2,
01294         32,
01295         46.5,
01296         51.3,
01297         57.5,
01298         67.1,
01299         71.5,
01300         84.6,
01301         97.6,
01302         130,
01303 /*      255.8 */
01304     };
01305     int     sb, sblock;
01306 
01307     pe_s = 1236.28 / 4;
01308     for (sb = 0; sb < SBMAX_s - 1; sb++) {
01309         for (sblock = 0; sblock < 3; sblock++) {
01310             FLOAT   x;
01311             if (regcoef_s[sb] == 0.0 || mr->thm.s[sb][sblock] <= 0.0 || mr->en.s[sb][sblock]
01312                 <= (x = mr->thm.s[sb][sblock] * masking_lower))
01313                 continue;
01314 
01315             if (mr->en.s[sb][sblock] > x * 1e10)
01316                 pe_s += regcoef_s[sb] * (10.0 * LOG10);
01317             else {
01318                 assert( x > 0 );
01319                 pe_s += regcoef_s[sb] * FAST_LOG10(mr->en.s[sb][sblock] / x);
01320             }
01321         }
01322     }
01323 
01324     return pe_s;
01325 }
01326 
01327 static  FLOAT
01328 pecalc_l(III_psy_ratio const *mr, FLOAT masking_lower)
01329 {
01330     FLOAT   pe_l;
01331     static const FLOAT regcoef_l[] = {
01332         6.8,            /* these values are tuned only for 44.1kHz... */
01333         5.8,
01334         5.8,
01335         6.4,
01336         6.5,
01337         9.9,
01338         12.1,
01339         14.4,
01340         15,
01341         18.9,
01342         21.6,
01343         26.9,
01344         34.2,
01345         40.2,
01346         46.8,
01347         56.5,
01348         60.7,
01349         73.9,
01350         85.7,
01351         93.4,
01352         126.1,
01353 /*      241.3 */
01354     };
01355     int     sb;
01356 
01357     pe_l = 1124.23 / 4;
01358     for (sb = 0; sb < SBMAX_l - 1; sb++) {
01359         FLOAT   x;
01360         if (mr->thm.l[sb] <= 0.0 || mr->en.l[sb] <= (x = mr->thm.l[sb] * masking_lower))
01361             continue;
01362 
01363         if (mr->en.l[sb] > x * 1e10)
01364             pe_l += regcoef_l[sb] * (10.0 * LOG10);
01365         else
01366             pe_l += regcoef_l[sb] * FAST_LOG10(mr->en.l[sb] / x);
01367     }
01368 
01369     return pe_l;
01370 }
01371 
01372 
01373 
01374 
01375 int
01376 L3psycho_anal_ns(lame_global_flags const *gfp,
01377                  const sample_t * buffer[2], int gr_out,
01378                  III_psy_ratio masking_ratio[2][2],
01379                  III_psy_ratio masking_MS_ratio[2][2],
01380                  FLOAT percep_entropy[2], FLOAT percep_MS_entropy[2],
01381                  FLOAT energy[4], int blocktype_d[2])
01382 {
01383 /* to get a good cache performance, one has to think about
01384  * the sequence, in which the variables are used.  
01385  * (Note: these static variables have been moved to the gfc-> struct,
01386  * and their order in memory is layed out in util.h)
01387  */
01388     lame_internal_flags *const gfc = gfp->internal_flags;
01389 
01390     /* fft and energy calculation   */
01391     FLOAT   wsamp_L[2][BLKSIZE];
01392     FLOAT   wsamp_S[2][3][BLKSIZE_s];
01393 
01394     /* block type  */
01395     int     blocktype[2], uselongblock[2];
01396 
01397     /* usual variables like loop indices, etc..    */
01398     int     numchn, chn;
01399     int     b, i, j, k;
01400     int     sb, sblock;
01401 
01402     /* variables used for --nspsytune */
01403     FLOAT   ns_hpfsmpl[2][576];
01404     FLOAT   pcfact;
01405 
01406     numchn = gfc->channels_out;
01407     /* chn=2 and 3 = Mid and Side channels */
01408     if (gfp->mode == JOINT_STEREO)
01409         numchn = 4;
01410 
01411     if (gfp->VBR == vbr_off)
01412         pcfact = gfc->ResvMax == 0 ? 0 : ((FLOAT) gfc->ResvSize) / gfc->ResvMax * 0.5;
01413     else if (gfp->VBR == vbr_rh || gfp->VBR == vbr_mtrh || gfp->VBR == vbr_mt) {
01414         /*static const FLOAT pcQns[10]={1.0,1.0,1.0,0.8,0.6,0.5,0.4,0.3,0.2,0.1};
01415            pcfact = pcQns[gfp->VBR_q]; */
01416         pcfact = 0.6;
01417     }
01418     else
01419         pcfact = 1.0;
01420 
01421     /**********************************************************************
01422      *  Apply HPF of fs/4 to the input signal.
01423      *  This is used for attack detection / handling.
01424      **********************************************************************/
01425     /* Don't copy the input buffer into a temporary buffer */
01426     /* unroll the loop 2 times */
01427     for (chn = 0; chn < gfc->channels_out; chn++) {
01428         static const FLOAT fircoef[] = {
01429             -8.65163e-18 * 2, -0.00851586 * 2, -6.74764e-18 * 2, 0.0209036 * 2,
01430             -3.36639e-17 * 2, -0.0438162 * 2, -1.54175e-17 * 2, 0.0931738 * 2,
01431             -5.52212e-17 * 2, -0.313819 * 2
01432         };
01433         /* apply high pass filter of fs/4 */
01434         const sample_t *const firbuf = &buffer[chn][576 - 350 - NSFIRLEN + 192];
01435         assert(sizeof(fircoef)/sizeof(fircoef[0]) == ((NSFIRLEN - 1) / 2));
01436         for (i = 0; i < 576; i++) {
01437             FLOAT   sum1, sum2;
01438             sum1 = firbuf[i + 10];
01439             sum2 = 0.0;
01440             for (j = 0; j < ((NSFIRLEN - 1) / 2)-1; j += 2) {
01441                 sum1 += fircoef[j] * (firbuf[i + j] + firbuf[i + NSFIRLEN - j]);
01442                 sum2 += fircoef[j + 1] * (firbuf[i + j + 1] + firbuf[i + NSFIRLEN - j - 1]);
01443             }
01444             ns_hpfsmpl[chn][i] = sum1 + sum2;
01445         }
01446         masking_ratio[gr_out][chn].en = gfc->en[chn];
01447         masking_ratio[gr_out][chn].thm = gfc->thm[chn];
01448         if (numchn > 2) {
01449             /* MS maskings  */
01450             /*percep_MS_entropy         [chn-2]     = gfc -> pe  [chn];  */
01451             masking_MS_ratio[gr_out][chn].en = gfc->en[chn + 2];
01452             masking_MS_ratio[gr_out][chn].thm = gfc->thm[chn + 2];
01453         }
01454     }
01455 
01456     for (chn = 0; chn < numchn; chn++) {
01457         FLOAT(*wsamp_l)[BLKSIZE];
01458         FLOAT(*wsamp_s)[3][BLKSIZE_s];
01459         FLOAT   en_subshort[12];
01460         FLOAT   en_short[4] = { 0 };
01461         FLOAT   attack_intensity[12];
01462         int     ns_uselongblock = 1;
01463         FLOAT   attackThreshold;
01464         FLOAT   max[CBANDS], avg[CBANDS];
01465         int     ns_attacks[4] = { 0 };
01466         FLOAT   fftenergy[HBLKSIZE];
01467         FLOAT   fftenergy_s[3][HBLKSIZE_s];
01468         /* convolution   */
01469         FLOAT   eb[CBANDS + 1], eb2[CBANDS];
01470         FLOAT   thr[CBANDS + 1];
01471 
01472 
01473         /*This is the masking table:
01474            According to tonality, values are going from 0dB (TMN)
01475            to 9.3dB (NMT).
01476            After additive masking computation, 8dB are added, so
01477            final values are going from 8dB to 17.3dB
01478          */
01479         static const FLOAT tab[] = {
01480             1.0 /*pow(10, -0) */ ,
01481             0.79433 /*pow(10, -0.1) */ ,
01482             0.63096 /*pow(10, -0.2) */ ,
01483             0.63096 /*pow(10, -0.2) */ ,
01484             0.63096 /*pow(10, -0.2) */ ,
01485             0.63096 /*pow(10, -0.2) */ ,
01486             0.63096 /*pow(10, -0.2) */ ,
01487             0.25119 /*pow(10, -0.6) */ ,
01488             0.11749     /*pow(10, -0.93) */
01489         };
01490 
01491         /*  rh 20040301: the following loops do access one off the limits
01492          *  so I increase  the array dimensions by one and initialize the
01493          *  accessed values to zero
01494          */
01495         assert(gfc->npart_s <= CBANDS);
01496         assert(gfc->npart_l <= CBANDS);
01497         eb[gfc->npart_s] = 0;
01498         thr[gfc->npart_s] = 0;
01499         eb[gfc->npart_l] = 0;
01500         thr[gfc->npart_l] = 0;
01501 
01502  /*************************************************************** 
01503   * determine the block type (window type)
01504   ***************************************************************/
01505         /* calculate energies of each sub-shortblocks */
01506         for (i = 0; i < 3; i++) {
01507             en_subshort[i] = gfc->nsPsy.last_en_subshort[chn][i + 6];
01508             assert(gfc->nsPsy.last_en_subshort[chn][i + 4] > 0);
01509             attack_intensity[i]
01510                 = en_subshort[i] / gfc->nsPsy.last_en_subshort[chn][i + 4];
01511             en_short[0] += en_subshort[i];
01512         }
01513 
01514         if (chn == 2) {
01515             for (i = 0; i < 576; i++) {
01516                 FLOAT   l, r;
01517                 l = ns_hpfsmpl[0][i];
01518                 r = ns_hpfsmpl[1][i];
01519                 ns_hpfsmpl[0][i] = l + r;
01520                 ns_hpfsmpl[1][i] = l - r;
01521             }
01522         }
01523         {
01524             FLOAT const *pf = ns_hpfsmpl[chn & 1];
01525             for (i = 0; i < 9; i++) {
01526                 FLOAT const *const pfe = pf + 576 / 9;
01527                 FLOAT   p = 1.;
01528                 for (; pf < pfe; pf++)
01529                     if (p < fabs(*pf))
01530                         p = fabs(*pf);
01531 
01532                 gfc->nsPsy.last_en_subshort[chn][i] = en_subshort[i + 3] = p;
01533                 en_short[1 + i / 3] += p;
01534                 if (p > en_subshort[i + 3 - 2]) {
01535                     assert(en_subshort[i + 3 - 2] > 0);
01536                     p = p / en_subshort[i + 3 - 2];
01537                 }
01538                 else if (en_subshort[i + 3 - 2] > p * 10.0) {
01539                     assert( p > 0 );
01540                     p = en_subshort[i + 3 - 2] / (p * 10.0);
01541                 }
01542                 else
01543                     p = 0.0;
01544                 attack_intensity[i + 3] = p;
01545             }
01546         }
01547 
01548         if (gfp->analysis) {
01549             FLOAT   x = attack_intensity[0];
01550             for (i = 1; i < 12; i++)
01551                 if (x < attack_intensity[i])
01552                     x = attack_intensity[i];
01553             gfc->pinfo->ers[gr_out][chn] = gfc->pinfo->ers_save[chn];
01554             gfc->pinfo->ers_save[chn] = x;
01555         }
01556 
01557         /* compare energies between sub-shortblocks */
01558         attackThreshold = (chn == 3)
01559             ? gfc->nsPsy.attackthre_s : gfc->nsPsy.attackthre;
01560         for (i = 0; i < 12; i++)
01561             if (!ns_attacks[i / 3] && attack_intensity[i] > attackThreshold)
01562                 ns_attacks[i / 3] = (i % 3) + 1;
01563 
01564         /* should have energy change between short blocks,
01565            in order to avoid periodic signals */
01566         for (i = 1; i < 4; i++) {
01567             float   ratio;
01568             if (en_short[i - 1] > en_short[i]) {
01569                 assert( en_short[i] > 0 );
01570                 ratio = en_short[i - 1] / en_short[i];
01571             }
01572             else {
01573                 assert( en_short[i-1] > 0 );
01574                 ratio = en_short[i] / en_short[i - 1];
01575             }
01576             if (ratio < 1.7) {
01577                 ns_attacks[i] = 0;
01578                 if (i == 1)
01579                     ns_attacks[0] = 0;
01580             }
01581         }
01582 
01583         if (ns_attacks[0] && gfc->nsPsy.last_attacks[chn])
01584             ns_attacks[0] = 0;
01585 
01586         if (gfc->nsPsy.last_attacks[chn] == 3 ||
01587             ns_attacks[0] + ns_attacks[1] + ns_attacks[2] + ns_attacks[3]) {
01588             ns_uselongblock = 0;
01589 
01590             if (ns_attacks[1] && ns_attacks[0])
01591                 ns_attacks[1] = 0;
01592             if (ns_attacks[2] && ns_attacks[1])
01593                 ns_attacks[2] = 0;
01594             if (ns_attacks[3] && ns_attacks[2])
01595                 ns_attacks[3] = 0;
01596         }
01597 
01598         if (chn < 2) {
01599             uselongblock[chn] = ns_uselongblock;
01600         }
01601         else {
01602             if (ns_uselongblock == 0) {
01603                 uselongblock[0] = uselongblock[1] = 0;
01604             }
01605         }
01606 
01607         /* there is a one granule delay.  Copy maskings computed last call
01608          * into masking_ratio to return to calling program.
01609          */
01610         energy[chn] = gfc->tot_ener[chn];
01611 
01612  /*********************************************************************
01613   *  compute FFTs
01614   *********************************************************************/
01615         wsamp_s = wsamp_S + (chn & 1);
01616         wsamp_l = wsamp_L + (chn & 1);
01617         compute_ffts(gfp, fftenergy, fftenergy_s, wsamp_l, wsamp_s, gr_out, chn, buffer);
01618 
01619         /* compute masking thresholds for short blocks */
01620         for (sblock = 0; sblock < 3; sblock++) {
01621             FLOAT   enn, thmm;
01622             compute_masking_s(gfp, fftenergy_s, eb, thr, chn, sblock);
01623             convert_partition2scalefac_s(gfc, eb, thr, chn, sblock);
01624 
01625             /****   short block pre-echo control   ****/
01626             for (sb = 0; sb < SBMAX_s; sb++) {
01627                 thmm = gfc->thm[chn].s[sb][sblock];
01628 
01629                 thmm *= NS_PREECHO_ATT0;
01630                 if (ns_attacks[sblock] >= 2 || ns_attacks[sblock + 1] == 1) {
01631                     int const idx = (sblock != 0) ? sblock - 1 : 2;
01632                     double const p = NS_INTERP(gfc->thm[chn].s[sb][idx],
01633                                                thmm, NS_PREECHO_ATT1 * pcfact);
01634                     thmm = Min(thmm, p);
01635                 }
01636 
01637                 if (ns_attacks[sblock] == 1) {
01638                     int const idx = (sblock != 0) ? sblock - 1 : 2;
01639                     double const p = NS_INTERP(gfc->thm[chn].s[sb][idx],
01640                                                thmm, NS_PREECHO_ATT2 * pcfact);
01641                     thmm = Min(thmm, p);
01642                 }
01643                 else if ((sblock != 0 && ns_attacks[sblock - 1] == 3)
01644                          || (sblock == 0 && gfc->nsPsy.last_attacks[chn] == 3)) {
01645                     int const idx = (sblock != 2) ? sblock + 1 : 0;
01646                     double const p = NS_INTERP(gfc->thm[chn].s[sb][idx],
01647                                                thmm, NS_PREECHO_ATT2 * pcfact);
01648                     thmm = Min(thmm, p);
01649                 }
01650 
01651                 /* pulse like signal detection for fatboy.wav and so on */
01652                 enn = en_subshort[sblock * 3 + 3] + en_subshort[sblock * 3 + 4]
01653                     + en_subshort[sblock * 3 + 5];
01654                 if (en_subshort[sblock * 3 + 5] * 6 < enn) {
01655                     thmm *= 0.5;
01656                     if (en_subshort[sblock * 3 + 4] * 6 < enn)
01657                         thmm *= 0.5;
01658                 }
01659 
01660                 gfc->thm[chn].s[sb][sblock] = thmm;
01661             }
01662         }
01663         gfc->nsPsy.last_attacks[chn] = ns_attacks[2];
01664 
01665  /*********************************************************************
01666   *    Calculate the energy and the tonality of each partition.
01667   *********************************************************************/
01668         for (b = j = 0; b < gfc->npart_l; ++b) {
01669             FLOAT   ebb = 0, m = 0;
01670             for (i = 0; i < gfc->numlines_l[b]; ++i, ++j) {
01671                 FLOAT const el = fftenergy[j];
01672                 assert(el >= 0);
01673                 ebb += el;
01674                 if (m < el)
01675                     m = el;
01676             }
01677             eb[b] = ebb;
01678             max[b] = m;
01679             avg[b] = ebb * gfc->rnumlines_l[b];
01680             assert( gfc->rnumlines_l[b] >= 0 );
01681             assert( ebb >= 0 );
01682             assert( eb[b] >= 0 );
01683             assert( max[b] >= 0 );
01684             assert( avg[b] >= 0 );
01685         }
01686         assert( b == gfc->npart_l );
01687         assert( j == 513 );
01688         {
01689             FLOAT   m, a;
01690             int const last_tab_entry = sizeof(tab) / sizeof(tab[0])-1;
01691             b = 0;
01692             a = avg[b] + avg[b+1];
01693             assert(a >= 0);
01694             if (a != 0.0) {
01695                 m = max[b];
01696                 if (m < max[b+1])
01697                     m = max[b+1];
01698                 assert( (gfc->numlines_l[b] + gfc->numlines_l[b+1] - 1) > 0 );
01699                 a = 20.0 * (m * 2.0 - a)
01700                     / (a * (gfc->numlines_l[b] + gfc->numlines_l[b+1] - 1));
01701                 k = (int) a;
01702                 if (k > last_tab_entry)
01703                     k = last_tab_entry;
01704                 a = eb[b] * tab[k];
01705             }
01706             eb2[b] = a;
01707 
01708             for (b = 1; b < gfc->npart_l - 1; b++) {
01709                 a = avg[b - 1] + avg[b] + avg[b + 1];
01710                 assert( a >= 0 );
01711                 if (a != 0.0) {
01712                     m = max[b - 1];
01713                     if (m < max[b])
01714                         m = max[b];
01715                     if (m < max[b + 1])
01716                         m = max[b + 1];
01717                     assert( (gfc->numlines_l[b - 1] + gfc->numlines_l[b] + gfc->numlines_l[b + 1] -
01718                             1) > 0 );
01719                     a = 20.0 * (m * 3.0 - a)
01720                         / (a *
01721                            (gfc->numlines_l[b - 1] + gfc->numlines_l[b] + gfc->numlines_l[b + 1] -
01722                             1));
01723                     k = (int) a;
01724                     if (k > last_tab_entry)
01725                         k = last_tab_entry;
01726                     a = eb[b] * tab[k];
01727                 }
01728                 eb2[b] = a;
01729                 assert(eb2[b] >= 0);
01730             }
01731             assert( b > 0 );
01732             assert( b == gfc->npart_l-1 );
01733 
01734             a = avg[b-1] + avg[b];
01735             assert( a >= 0 );
01736             if (a > 0.0) {
01737                 m = max[b-1];
01738                 if (m < max[b])
01739                     m = max[b];
01740                 assert( (gfc->numlines_l[b-1] + gfc->numlines_l[b] - 1) > 0 );
01741                 a = 20.0 * (m * 2.0 - a)
01742                     / (a *
01743                        (gfc->numlines_l[b-1] + gfc->numlines_l[b] - 1));
01744                 k = (int) a;
01745                 if (k > last_tab_entry)
01746                     k = last_tab_entry;
01747                 a = eb[b] * tab[k];
01748             }
01749             eb2[b] = a;
01750             assert(b == (gfc->npart_l - 1));
01751             assert(eb2[b] >= 0);
01752         }
01753 
01754  /*********************************************************************
01755   *      convolve the partitioned energy and unpredictability
01756   *      with the spreading function, s3_l[b][k]
01757   ********************************************************************/
01758 #undef GPSYCHO_BLOCK_TYPE_DECISION
01759 #ifdef GPSYCHO_BLOCK_TYPE_DECISION
01760         {
01761             FLOAT   pe = 0;
01762 #endif
01763             k = 0;
01764             for (b = 0; b < gfc->npart_l; b++) {
01765                 FLOAT   ecb;
01766                 /* convolve the partitioned energy with the spreading function */
01767                 int     kk = gfc->s3ind[b][0];
01768                 ecb = gfc->s3_ll[k++] * eb2[kk];
01769                 while (++kk <= gfc->s3ind[b][1])
01770                     ecb = mask_add(ecb, gfc->s3_ll[k++] * eb2[kk], kk, kk - b, gfc, 0);
01771                 ecb *= 0.158489319246111; /* pow(10,-0.8) */
01772 
01773      /****   long block pre-echo control   ****/
01774                 /* dont use long block pre-echo control if previous granule was 
01775                  * a short block.  This is to avoid the situation:   
01776                  * frame0:  quiet (very low masking)  
01777                  * frame1:  surge  (triggers short blocks)
01778                  * frame2:  regular frame.  looks like pre-echo when compared to 
01779                  *          frame0, but all pre-echo was in frame1.
01780                  */
01781                 /* chn=0,1   L and R channels
01782                    chn=2,3   S and M channels.
01783                  */
01784 
01785                 if (gfc->blocktype_old[chn & 1] == SHORT_TYPE)
01786                     thr[b] = ecb; /* Min(ecb, rpelev*gfc->nb_1[chn][b]); */
01787                 else
01788                     thr[b] = NS_INTERP(Min(ecb,
01789                                            Min(rpelev * gfc->nb_1[chn][b],
01790                                                rpelev2 * gfc->nb_2[chn][b])), ecb, pcfact);
01791 
01792                 if (gfp->VBR == vbr_mtrh || gfp->VBR == vbr_mt) {
01793                     /*  if THR exceeds EB, the quantization routines will take the difference
01794                      *  from other bands. in case of strong tonal samples (tonaltest.wav)
01795                      *  this leads to heavy distortions. that's why we limit THR here.
01796                      */
01797                     FLOAT   x = max[b];
01798                     x *= gfc->numlines_l[b];
01799                     x *= gfc->minval_l[b];
01800 #if 0
01801                     x *= 0.5f;
01802 #else
01803                     x *= 0.158489319246111; /* pow(10,-0.8) */
01804 #endif
01805                     if (eb[b] > 0.0f) {
01806                         x *= eb2[b] / eb[b];
01807                     }
01808                     if (thr[b] > x) {
01809                         thr[b] = x;
01810                     }
01811                 }
01812 
01813                 gfc->nb_2[chn][b] = gfc->nb_1[chn][b];
01814                 gfc->nb_1[chn][b] = ecb;
01815 #ifdef GPSYCHO_BLOCK_TYPE_DECISION
01816                 /* this pe does not match GPSYCHO's pe, because of difference in 
01817                  * convolution calculation, (mask_add etc.). Therefore the block
01818                  * switching does not happen exactly as in GPSYCHO.
01819                  */
01820                 pe -= gfc->numlines_l[b] * FAST_LOG(ecb / eb[b]);
01821 #endif
01822             }
01823 #ifdef GPSYCHO_BLOCK_TYPE_DECISION
01824             determine_block_type(gfp, fftenergy_s, uselongblock, chn, gr_out, &pe);
01825         }
01826 #endif
01827         /* compute masking thresholds for long blocks */
01828         convert_partition2scalefac_l(gfc, eb, thr, chn);
01829 
01830     }                   /* end loop over chn */
01831 
01832     if (gfp->interChRatio != 0.0)
01833         calc_interchannel_masking(gfp, gfp->interChRatio);
01834 
01835     if (gfp->mode == JOINT_STEREO) {
01836         FLOAT   msfix;
01837         msfix1(gfc);
01838         msfix = gfp->msfix;
01839         if (msfix != 0.0)
01840             ns_msfix(gfc, msfix, gfp->ATHlower * gfc->ATH->adjust);
01841     }
01842 
01843     /*************************************************************** 
01844      * determine final block type
01845      ***************************************************************/
01846     block_type_set(gfp, uselongblock, blocktype_d, blocktype);
01847 
01848     /*********************************************************************
01849      * compute the value of PE to return ... no delay and advance
01850      *********************************************************************/
01851     for (chn = 0; chn < numchn; chn++) {
01852         FLOAT  *ppe;
01853         int     type;
01854         III_psy_ratio const *mr;
01855 
01856         if (chn > 1) {
01857             ppe = percep_MS_entropy - 2;
01858             type = NORM_TYPE;
01859             if (blocktype_d[0] == SHORT_TYPE || blocktype_d[1] == SHORT_TYPE)
01860                 type = SHORT_TYPE;
01861             mr = &masking_MS_ratio[gr_out][chn - 2];
01862         }
01863         else {
01864             ppe = percep_entropy;
01865             type = blocktype_d[chn];
01866             mr = &masking_ratio[gr_out][chn];
01867         }
01868 
01869         if (type == SHORT_TYPE)
01870             ppe[chn] = pecalc_s(mr, gfc->masking_lower);
01871         else
01872             ppe[chn] = pecalc_l(mr, gfc->masking_lower);
01873 
01874 
01875         if (gfp->analysis)
01876             gfc->pinfo->pe[gr_out][chn] = ppe[chn];
01877 
01878     }
01879     return 0;
01880 }
01881 
01882 
01883 
01884 
01885 
01886 /* 
01887  *   The spreading function.  Values returned in units of energy
01888  */
01889 static  FLOAT
01890 s3_func(FLOAT bark)
01891 {
01892     FLOAT   tempx, x, tempy, temp;
01893     tempx = bark;
01894     if (tempx >= 0)
01895         tempx *= 3;
01896     else
01897         tempx *= 1.5;
01898 
01899     if (tempx >= 0.5 && tempx <= 2.5) {
01900         temp = tempx - 0.5;
01901         x = 8.0 * (temp * temp - 2.0 * temp);
01902     }
01903     else
01904         x = 0.0;
01905     tempx += 0.474;
01906     tempy = 15.811389 + 7.5 * tempx - 17.5 * sqrt(1.0 + tempx * tempx);
01907 
01908     if (tempy <= -60.0)
01909         return 0.0;
01910 
01911     tempx = exp((x + tempy) * LN_TO_LOG10);
01912 
01913     /* Normalization.  The spreading function should be normalized so that:
01914        +inf
01915        /
01916        |  s3 [ bark ]  d(bark)   =  1
01917        /
01918        -inf
01919      */
01920     tempx /= .6609193;
01921     return tempx;
01922 }
01923 
01924 static int
01925 init_numline(int *numlines, int *bo, int *bm,
01926              FLOAT * bval, FLOAT * bval_width, FLOAT * mld, FLOAT * bo_w,
01927              FLOAT sfreq, int blksize, int const *scalepos, FLOAT deltafreq, int sbmax)
01928 {
01929     FLOAT   b_frq[CBANDS+1];
01930     FLOAT   f_tmp;
01931     FLOAT   sample_freq_frac = sfreq / ( sbmax > 15 ? 2*576 : 2*192 );
01932     int     partition[HBLKSIZE] = { 0 };
01933     int     i, j, k;
01934     int     sfb;
01935     sfreq /= blksize;
01936     j = 0;
01937     /* compute numlines, the number of spectral lines in each partition band */
01938     /* each partition band should be about DELBARK wide. */
01939     for (i = 0; i < CBANDS; i++) {
01940         FLOAT   bark1;
01941         int     j2;
01942         bark1 = freq2bark(sfreq * j);
01943         
01944         b_frq[i] = sfreq * j;
01945 
01946         for (j2 = j; freq2bark(sfreq * j2) - bark1 < DELBARK && j2 <= blksize / 2; j2++);
01947 
01948         numlines[i] = j2 - j;
01949 
01950         while (j < j2)
01951             partition[j++] = i;
01952         if (j > blksize / 2) {
01953             j = blksize / 2;
01954             ++i;
01955             break;
01956         }
01957     }
01958     b_frq[i] = sfreq * j;
01959 
01960     for (sfb = 0; sfb < sbmax; sfb++) {
01961         int     i1, i2, start, end;
01962         FLOAT   arg;
01963         start = scalepos[sfb];
01964         end = scalepos[sfb + 1];
01965 
01966         i1 = floor(.5 + deltafreq * (start - .5));
01967         if (i1 < 0)
01968             i1 = 0;
01969         i2 = floor(.5 + deltafreq * (end - .5));
01970 
01971         if (i2 > blksize / 2)
01972             i2 = blksize / 2;
01973 
01974         bm[sfb] = (partition[i1] + partition[i2]) / 2;
01975         bo[sfb] = partition[i2];
01976         
01977         f_tmp = sample_freq_frac * end;        
01978          /* calculate how much of this band belongs to current scalefactor band */
01979         bo_w[sfb] = (f_tmp-b_frq[bo[sfb]])/(b_frq[bo[sfb]+1]-b_frq[bo[sfb]]);
01980         if ( bo_w[sfb] < 0 ) {
01981             bo_w[sfb] = 0;
01982         }
01983         else {
01984             if ( bo_w[sfb] > 1 ) {
01985                 bo_w[sfb] = 1;
01986             }
01987         }
01988         /* setup stereo demasking thresholds */
01989         /* formula reverse enginerred from plot in paper */
01990         arg = freq2bark(sfreq * scalepos[sfb] * deltafreq);
01991         arg = (Min(arg, 15.5) / 15.5);
01992 
01993         mld[sfb] = pow(10.0, 1.25 * (1 - cos(PI * arg)) - 2.5);
01994     }
01995 
01996     /* compute bark values of each critical band */
01997     j = 0;
01998     for (k = 0; k < i + 1; k++) {
01999         int const w = numlines[k];
02000         FLOAT   bark1, bark2;
02001 
02002         bark1 = freq2bark(sfreq * (j));
02003         bark2 = freq2bark(sfreq * (j + w - 1));
02004         bval[k] = .5 * (bark1 + bark2);
02005 
02006         bark1 = freq2bark(sfreq * (j - .5));
02007         bark2 = freq2bark(sfreq * (j + w - .5));
02008         bval_width[k] = bark2 - bark1;
02009         j += w;
02010     }
02011 
02012     return i + 1;
02013 }
02014 
02015 static int
02016 init_s3_values(lame_global_flags const *gfp,
02017                FLOAT ** p,
02018                int (*s3ind)[2], int npart, FLOAT const *bval, FLOAT const *bval_width,
02019                FLOAT const *norm)
02020 {
02021     FLOAT   s3[CBANDS][CBANDS];
02022     /* The s3 array is not linear in the bark scale.
02023      * bval[x] should be used to get the bark value.
02024      */
02025     int const flag = (gfp->VBR == vbr_mtrh || gfp->VBR == vbr_mt);
02026     int     i, j, k;
02027     int     numberOfNoneZero = 0;
02028 
02029     /* s[i][j], the value of the spreading function,
02030      * centered at band j (masker), for band i (maskee)
02031      *
02032      * i.e.: sum over j to spread into signal barkval=i
02033      * NOTE: i and j are used opposite as in the ISO docs
02034      */
02035     for (i = 0; i < npart; i++) {
02036         FLOAT   sum = 0.f;
02037         for (j = 0; j < npart; j++) {
02038             FLOAT   v = s3_func(bval[i] - bval[j]) * bval_width[j];
02039             sum += v;
02040             s3[i][j] = v * norm[i];
02041         }
02042         if (flag && sum > 0.f) {
02043             for (j = 0; j < npart; j++) {
02044                 s3[i][j] /= sum;
02045             }
02046         }
02047     }
02048     for (i = 0; i < npart; i++) {
02049         for (j = 0; j < npart; j++) {
02050             if (s3[i][j] != 0.0f)
02051                 break;
02052         }
02053         s3ind[i][0] = j;
02054 
02055         for (j = npart - 1; j > 0; j--) {
02056             if (s3[i][j] != 0.0f)
02057                 break;
02058         }
02059         s3ind[i][1] = j;
02060         numberOfNoneZero += (s3ind[i][1] - s3ind[i][0] + 1);
02061     }
02062     *p = malloc(sizeof(FLOAT) * numberOfNoneZero);
02063     if (!*p)
02064         return -1;
02065 
02066     k = 0;
02067     for (i = 0; i < npart; i++)
02068         for (j = s3ind[i][0]; j <= s3ind[i][1]; j++)
02069             (*p)[k++] = s3[i][j];
02070 
02071     return 0;
02072 }
02073 
02074 int
02075 psymodel_init(lame_global_flags * gfp)
02076 {
02077     lame_internal_flags *const gfc = gfp->internal_flags;
02078     int     i, j, b, sb, k;
02079 
02080     FLOAT   bval[CBANDS];
02081     FLOAT   bval_width[CBANDS];
02082     FLOAT   norm[CBANDS];
02083     FLOAT const sfreq = gfp->out_samplerate;
02084 
02085     gfc->ms_ener_ratio_old = .25;
02086     gfc->blocktype_old[0] = gfc->blocktype_old[1] = NORM_TYPE; /* the vbr header is long blocks */
02087 
02088     for (i = 0; i < 4; ++i) {
02089         for (j = 0; j < CBANDS; ++j) {
02090             gfc->nb_1[i][j] = 1e20;
02091             gfc->nb_2[i][j] = 1e20;
02092             gfc->nb_s1[i][j] = gfc->nb_s2[i][j] = 1.0;
02093         }
02094         for (sb = 0; sb < SBMAX_l; sb++) {
02095             gfc->en[i].l[sb] = 1e20;
02096             gfc->thm[i].l[sb] = 1e20;
02097         }
02098         for (j = 0; j < 3; ++j) {
02099             for (sb = 0; sb < SBMAX_s; sb++) {
02100                 gfc->en[i].s[sb][j] = 1e20;
02101                 gfc->thm[i].s[sb][j] = 1e20;
02102             }
02103             gfc->nsPsy.last_attacks[i] = 0;
02104         }
02105         for (j = 0; j < 9; j++)
02106             gfc->nsPsy.last_en_subshort[i][j] = 10.;
02107     }
02108 
02109 
02110 
02111     j = (int)(gfc->PSY->cwlimit / (sfreq / BLKSIZE));
02112     if (j > HBLKSIZE - 4) /* j+3 < HBLKSIZE-1 */
02113         j = HBLKSIZE - 4;
02114     if (j < CW_LOWER_INDEX)
02115         j = CW_LOWER_INDEX;
02116     gfc->cw_upper_index = j;
02117 
02118     for (j = 0; j < HBLKSIZE; j++)
02119         gfc->cw[j] = 0.4f;
02120 
02121     /* init. for loudness approx. -jd 2001 mar 27 */
02122     gfc->loudness_sq_save[0] = gfc->loudness_sq_save[1] = 0.0;
02123 
02124 
02125 
02126 
02127     /*************************************************************************
02128      * now compute the psychoacoustic model specific constants
02129      ************************************************************************/
02130     /* compute numlines, bo, bm, bval, bval_width, mld */
02131     gfc->npart_l
02132         = init_numline(gfc->numlines_l, gfc->bo_l, gfc->bm_l,
02133                        bval, bval_width, gfc->mld_l, gfc->PSY->bo_l_weight,
02134                        sfreq, BLKSIZE, gfc->scalefac_band.l, BLKSIZE / (2.0 * 576), SBMAX_l);
02135     assert(gfc->npart_l <= CBANDS);
02136     /* compute the spreading function */
02137     for (i = 0; i < gfc->npart_l; i++) {
02138         norm[i] = 1.0;
02139         if (gfc->numlines_l[i] > 0) {
02140             gfc->rnumlines_l[i] = 1.0 / gfc->numlines_l[i];
02141         }
02142         else {
02143             gfc->rnumlines_l[i] = 0;
02144         }
02145     }
02146     i = init_s3_values(gfp, &gfc->s3_ll, gfc->s3ind, gfc->npart_l, bval, bval_width, norm);
02147     if (i)
02148         return i;
02149 
02150     /* compute long block specific values, ATH and MINVAL */
02151     j = 0;
02152     for (i = 0; i < gfc->npart_l; i++) {
02153         double  x;
02154 
02155         /* ATH */
02156         x = FLOAT_MAX;
02157         for (k = 0; k < gfc->numlines_l[i]; k++, j++) {
02158             FLOAT const freq = sfreq * j / (1000.0 * BLKSIZE);
02159             FLOAT   level;
02160             /* freq = Min(.1,freq); *//* ATH below 100 Hz constant, not further climbing */
02161             level = ATHformula(freq * 1000, gfp) - 20; /* scale to FFT units; returned value is in dB */
02162             level = pow(10., 0.1 * level); /* convert from dB -> energy */
02163             level *= gfc->numlines_l[i];
02164             if (x > level)
02165                 x = level;
02166         }
02167         gfc->ATH->cb_l[i] = x;
02168 
02169         /* MINVAL.
02170            For low freq, the strength of the masking is limited by minval
02171            this is an ISO MPEG1 thing, dont know if it is really needed */
02172         x = (-20 + bval[i] * 20.0 / 10.0);
02173         if (bval[i] > 10)
02174             x = 0;
02175         gfc->minval_l[i] = pow(10.0, x / 10);
02176     }
02177 
02178     /************************************************************************
02179      * do the same things for short blocks
02180      ************************************************************************/
02181     gfc->npart_s
02182         = init_numline(gfc->numlines_s, gfc->bo_s, gfc->bm_s,
02183                        bval, bval_width, gfc->mld_s, gfc->PSY->bo_s_weight,
02184                        sfreq, BLKSIZE_s, gfc->scalefac_band.s, BLKSIZE_s / (2.0 * 192), SBMAX_s);
02185     assert(gfc->npart_s <= CBANDS);
02186 
02187     /* SNR formula. short block is normalized by SNR. is it still right ? */
02188     j = 0;
02189     for (i = 0; i < gfc->npart_s; i++) {
02190         double  x;
02191         double  snr = -8.25;
02192         if (bval[i] >= 13)
02193             snr = -4.5 * (bval[i] - 13) / (24.0 - 13.0)
02194                 - 8.25 * (bval[i] - 24) / (13.0 - 24.0);
02195 
02196         norm[i] = pow(10.0, snr / 10.0);
02197 
02198         /* ATH */
02199         x = FLOAT_MAX;
02200         for (k = 0; k < gfc->numlines_s[i]; k++, j++) {
02201             FLOAT const freq = sfreq * j / (1000.0 * BLKSIZE_s);
02202             FLOAT   level;
02203             /* freq = Min(.1,freq); *//* ATH below 100 Hz constant, not further climbing */
02204             level = ATHformula(freq * 1000, gfp) - 20; /* scale to FFT units; returned value is in dB */
02205             level = pow(10., 0.1 * level); /* convert from dB -> energy */
02206             level *= gfc->numlines_s[i];
02207             if (x > level)
02208                 x = level;
02209         }
02210         gfc->ATH->cb_s[i] = x;
02211 
02212         /* MINVAL.
02213            For low freq, the strength of the masking is limited by minval
02214            this is an ISO MPEG1 thing, dont know if it is really needed */
02215         x = (-20 + bval[i] * 20.0 / 10.0);
02216         if (bval[i] > 10)
02217             x = 0;
02218         gfc->minval_s[i] = pow(10.0, x / 10);
02219     }
02220 
02221     i = init_s3_values(gfp, &gfc->s3_ss, gfc->s3ind_s, gfc->npart_s, bval, bval_width, norm);
02222     if (i)
02223         return i;
02224 
02225 
02226     init_mask_add_max_values();
02227     init_fft(gfc);
02228 
02229     /* setup temporal masking */
02230     gfc->decay = exp(-1.0 * LOG10 / (temporalmask_sustain_sec * sfreq / 192.0));
02231 
02232     if (gfp->psymodel == PSY_NSPSYTUNE) {
02233         FLOAT   msfix;
02234         msfix = NS_MSFIX;
02235         if (gfp->exp_nspsytune & 2)
02236             msfix = 1.0;
02237         if (gfp->msfix != 0.0)
02238             msfix = gfp->msfix;
02239         gfp->msfix = msfix;
02240 
02241         /* spread only from npart_l bands.  Normally, we use the spreading
02242          * function to convolve from npart_l down to npart_l bands 
02243          */
02244         for (b = 0; b < gfc->npart_l; b++)
02245             if (gfc->s3ind[b][1] > gfc->npart_l - 1)
02246                 gfc->s3ind[b][1] = gfc->npart_l - 1;
02247     }
02248 
02249     /*  prepare for ATH auto adjustment:
02250      *  we want to decrease the ATH by 12 dB per second
02251      */
02252 #define  frame_duration (576. * gfc->mode_gr / sfreq)
02253     gfc->ATH->decay = pow(10., -12. / 10. * frame_duration);
02254     gfc->ATH->adjust = 0.01; /* minimum, for leading low loudness */
02255     gfc->ATH->adjust_limit = 1.0; /* on lead, allow adjust up to maximum */
02256 #undef  frame_duration
02257 
02258     gfc->bo_s[SBMAX_s - 1]--;
02259     assert(gfc->bo_l[SBMAX_l - 1] <= gfc->npart_l);
02260     assert(gfc->bo_s[SBMAX_s - 1] <= gfc->npart_s);
02261 
02262     if (gfp->ATHtype != -1) {
02263         /* compute equal loudness weights (eql_w) */
02264         FLOAT   freq;
02265         FLOAT const freq_inc = (FLOAT)gfp->out_samplerate / (FLOAT)(BLKSIZE);
02266         FLOAT   eql_balance = 0.0;
02267         freq = 0.0;
02268         for (i = 0; i < BLKSIZE / 2; ++i) {
02269             /* convert ATH dB to relative power (not dB) */
02270             /*  to determine eql_w */
02271             freq += freq_inc;
02272             gfc->ATH->eql_w[i] = 1. / pow(10, ATHformula(freq, gfp) / 10);
02273             eql_balance += gfc->ATH->eql_w[i];
02274         }
02275         eql_balance = 1.0 / eql_balance;
02276         for (i = BLKSIZE / 2; --i >= 0;) { /* scale weights */
02277             gfc->ATH->eql_w[i] *= eql_balance;
02278         }
02279     }
02280     {
02281         int i = 0, j, b;
02282         for (b = j = 0; b < gfc->npart_s; ++b) {
02283             for (i = 0; i < gfc->numlines_s[b]; ++i) {
02284                 ++j;
02285             }
02286         }
02287         assert( j == 129 );
02288         for (b = j = 0; b < gfc->npart_l; ++b) {
02289             for (i = 0; i < gfc->numlines_l[b]; ++i ) {
02290                 ++j;
02291             }
02292         }
02293         assert( j == 513 );
02294     }
02295     return 0;
02296 }

Generated on Sun Dec 2 11:34:19 2007 for LAME by  doxygen 1.5.2