Blame libmp3lame/psymodel.c

Packit 47f805
/*
Packit 47f805
 *      psymodel.c
Packit 47f805
 *
Packit 47f805
 *      Copyright (c) 1999-2000 Mark Taylor
Packit 47f805
 *      Copyright (c) 2001-2002 Naoki Shibata
Packit 47f805
 *      Copyright (c) 2000-2003 Takehiro Tominaga
Packit 47f805
 *      Copyright (c) 2000-2012 Robert Hegemann
Packit 47f805
 *      Copyright (c) 2000-2005 Gabriel Bouvigne
Packit 47f805
 *      Copyright (c) 2000-2005 Alexander Leidinger
Packit 47f805
 *
Packit 47f805
 * This library is free software; you can redistribute it and/or
Packit 47f805
 * modify it under the terms of the GNU Library General Public
Packit 47f805
 * License as published by the Free Software Foundation; either
Packit 47f805
 * version 2 of the License, or (at your option) any later version.
Packit 47f805
 *
Packit 47f805
 * This library is distributed in the hope that it will be useful,
Packit 47f805
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 47f805
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 47f805
 * Library General Public License for more details.
Packit 47f805
 *
Packit 47f805
 * You should have received a copy of the GNU Library General Public
Packit 47f805
 * License along with this library; if not, write to the
Packit 47f805
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Packit 47f805
 * Boston, MA 02111-1307, USA.
Packit 47f805
 */
Packit 47f805
Packit 47f805
/* $Id: psymodel.c,v 1.216 2017/09/06 19:38:23 aleidinger Exp $ */
Packit 47f805
Packit 47f805
Packit 47f805
/*
Packit 47f805
PSYCHO ACOUSTICS
Packit 47f805
Packit 47f805
Packit 47f805
This routine computes the psycho acoustics, delayed by one granule.  
Packit 47f805
Packit 47f805
Input: buffer of PCM data (1024 samples).  
Packit 47f805
Packit 47f805
This window should be centered over the 576 sample granule window.
Packit 47f805
The routine will compute the psycho acoustics for
Packit 47f805
this granule, but return the psycho acoustics computed
Packit 47f805
for the *previous* granule.  This is because the block
Packit 47f805
type of the previous granule can only be determined
Packit 47f805
after we have computed the psycho acoustics for the following
Packit 47f805
granule.  
Packit 47f805
Packit 47f805
Output:  maskings and energies for each scalefactor band.
Packit 47f805
block type, PE, and some correlation measures.  
Packit 47f805
The PE is used by CBR modes to determine if extra bits
Packit 47f805
from the bit reservoir should be used.  The correlation
Packit 47f805
measures are used to determine mid/side or regular stereo.
Packit 47f805
*/
Packit 47f805
/*
Packit 47f805
Notation:
Packit 47f805
Packit 47f805
barks:  a non-linear frequency scale.  Mapping from frequency to
Packit 47f805
        barks is given by freq2bark()
Packit 47f805
Packit 47f805
scalefactor bands: The spectrum (frequencies) are broken into 
Packit 47f805
                   SBMAX "scalefactor bands".  Thes bands
Packit 47f805
                   are determined by the MPEG ISO spec.  In
Packit 47f805
                   the noise shaping/quantization code, we allocate
Packit 47f805
                   bits among the partition bands to achieve the
Packit 47f805
                   best possible quality
Packit 47f805
Packit 47f805
partition bands:   The spectrum is also broken into about
Packit 47f805
                   64 "partition bands".  Each partition 
Packit 47f805
                   band is about .34 barks wide.  There are about 2-5
Packit 47f805
                   partition bands for each scalefactor band.
Packit 47f805
Packit 47f805
LAME computes all psycho acoustic information for each partition
Packit 47f805
band.  Then at the end of the computations, this information
Packit 47f805
is mapped to scalefactor bands.  The energy in each scalefactor
Packit 47f805
band is taken as the sum of the energy in all partition bands
Packit 47f805
which overlap the scalefactor band.  The maskings can be computed
Packit 47f805
in the same way (and thus represent the average masking in that band)
Packit 47f805
or by taking the minmum value multiplied by the number of
Packit 47f805
partition bands used (which represents a minimum masking in that band).
Packit 47f805
*/
Packit 47f805
/*
Packit 47f805
The general outline is as follows:
Packit 47f805
Packit 47f805
1. compute the energy in each partition band
Packit 47f805
2. compute the tonality in each partition band
Packit 47f805
3. compute the strength of each partion band "masker"
Packit 47f805
4. compute the masking (via the spreading function applied to each masker)
Packit 47f805
5. Modifications for mid/side masking.  
Packit 47f805
Packit 47f805
Each partition band is considiered a "masker".  The strength
Packit 47f805
of the i'th masker in band j is given by:
Packit 47f805
Packit 47f805
    s3(bark(i)-bark(j))*strength(i)
Packit 47f805
Packit 47f805
The strength of the masker is a function of the energy and tonality.
Packit 47f805
The more tonal, the less masking.  LAME uses a simple linear formula
Packit 47f805
(controlled by NMT and TMN) which says the strength is given by the
Packit 47f805
energy divided by a linear function of the tonality.
Packit 47f805
*/
Packit 47f805
/*
Packit 47f805
s3() is the "spreading function".  It is given by a formula
Packit 47f805
determined via listening tests.  
Packit 47f805
Packit 47f805
The total masking in the j'th partition band is the sum over
Packit 47f805
all maskings i.  It is thus given by the convolution of
Packit 47f805
the strength with s3(), the "spreading function."
Packit 47f805
Packit 47f805
masking(j) = sum_over_i  s3(i-j)*strength(i)  = s3 o strength
Packit 47f805
Packit 47f805
where "o" = convolution operator.  s3 is given by a formula determined
Packit 47f805
via listening tests.  It is normalized so that s3 o 1 = 1.
Packit 47f805
Packit 47f805
Note: instead of a simple convolution, LAME also has the
Packit 47f805
option of using "additive masking"
Packit 47f805
Packit 47f805
The most critical part is step 2, computing the tonality of each
Packit 47f805
partition band.  LAME has two tonality estimators.  The first
Packit 47f805
is based on the ISO spec, and measures how predictiable the
Packit 47f805
signal is over time.  The more predictable, the more tonal.
Packit 47f805
The second measure is based on looking at the spectrum of
Packit 47f805
a single granule.  The more peaky the spectrum, the more
Packit 47f805
tonal.  By most indications, the latter approach is better.
Packit 47f805
Packit 47f805
Finally, in step 5, the maskings for the mid and side
Packit 47f805
channel are possibly increased.  Under certain circumstances,
Packit 47f805
noise in the mid & side channels is assumed to also
Packit 47f805
be masked by strong maskers in the L or R channels.
Packit 47f805
Packit 47f805
Packit 47f805
Other data computed by the psy-model:
Packit 47f805
Packit 47f805
ms_ratio        side-channel / mid-channel masking ratio (for previous granule)
Packit 47f805
ms_ratio_next   side-channel / mid-channel masking ratio for this granule
Packit 47f805
Packit 47f805
percep_entropy[2]     L and R values (prev granule) of PE - A measure of how 
Packit 47f805
                      much pre-echo is in the previous granule
Packit 47f805
percep_entropy_MS[2]  mid and side channel values (prev granule) of percep_entropy
Packit 47f805
energy[4]             L,R,M,S energy in each channel, prev granule
Packit 47f805
blocktype_d[2]        block type to use for previous granule
Packit 47f805
*/
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
#ifdef HAVE_CONFIG_H
Packit 47f805
# include <config.h>
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#include <float.h>
Packit 47f805
Packit 47f805
#include "lame.h"
Packit 47f805
#include "machine.h"
Packit 47f805
#include "encoder.h"
Packit 47f805
#include "util.h"
Packit 47f805
#include "psymodel.h"
Packit 47f805
#include "lame_global_flags.h"
Packit 47f805
#include "fft.h"
Packit 47f805
#include "lame-analysis.h"
Packit 47f805
Packit 47f805
Packit 47f805
#define NSFIRLEN 21
Packit 47f805
Packit 47f805
#ifdef M_LN10
Packit 47f805
#define  LN_TO_LOG10  (M_LN10/10)
Packit 47f805
#else
Packit 47f805
#define  LN_TO_LOG10  0.2302585093
Packit 47f805
#endif
Packit 47f805
Packit 47f805
Packit 47f805
/*
Packit 47f805
   L3psycho_anal.  Compute psycho acoustics.
Packit 47f805
Packit 47f805
   Data returned to the calling program must be delayed by one 
Packit 47f805
   granule. 
Packit 47f805
Packit 47f805
   This is done in two places.  
Packit 47f805
   If we do not need to know the blocktype, the copying
Packit 47f805
   can be done here at the top of the program: we copy the data for
Packit 47f805
   the last granule (computed during the last call) before it is
Packit 47f805
   overwritten with the new data.  It looks like this:
Packit 47f805
  
Packit 47f805
   0. static psymodel_data 
Packit 47f805
   1. calling_program_data = psymodel_data
Packit 47f805
   2. compute psymodel_data
Packit 47f805
    
Packit 47f805
   For data which needs to know the blocktype, the copying must be
Packit 47f805
   done at the end of this loop, and the old values must be saved:
Packit 47f805
   
Packit 47f805
   0. static psymodel_data_old 
Packit 47f805
   1. compute psymodel_data
Packit 47f805
   2. compute possible block type of this granule
Packit 47f805
   3. compute final block type of previous granule based on #2.
Packit 47f805
   4. calling_program_data = psymodel_data_old
Packit 47f805
   5. psymodel_data_old = psymodel_data
Packit 47f805
*/
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
/* psycho_loudness_approx
Packit 47f805
   jd - 2001 mar 12
Packit 47f805
in:  energy   - BLKSIZE/2 elements of frequency magnitudes ^ 2
Packit 47f805
     gfp      - uses out_samplerate, ATHtype (also needed for ATHformula)
Packit 47f805
returns: loudness^2 approximation, a positive value roughly tuned for a value
Packit 47f805
         of 1.0 for signals near clipping.
Packit 47f805
notes:   When calibrated, feeding this function binary white noise at sample
Packit 47f805
         values +32767 or -32768 should return values that approach 3.
Packit 47f805
         ATHformula is used to approximate an equal loudness curve.
Packit 47f805
future:  Data indicates that the shape of the equal loudness curve varies
Packit 47f805
         with intensity.  This function might be improved by using an equal
Packit 47f805
         loudness curve shaped for typical playback levels (instead of the
Packit 47f805
         ATH, that is shaped for the threshold).  A flexible realization might
Packit 47f805
         simply bend the existing ATH curve to achieve the desired shape.
Packit 47f805
         However, the potential gain may not be enough to justify an effort.
Packit 47f805
*/
Packit 47f805
static  FLOAT
Packit 47f805
psycho_loudness_approx(FLOAT const *energy, FLOAT const *eql_w)
Packit 47f805
{
Packit 47f805
    int     i;
Packit 47f805
    FLOAT   loudness_power;
Packit 47f805
Packit 47f805
    loudness_power = 0.0;
Packit 47f805
    /* apply weights to power in freq. bands */
Packit 47f805
    for (i = 0; i < BLKSIZE / 2; ++i)
Packit 47f805
        loudness_power += energy[i] * eql_w[i];
Packit 47f805
    loudness_power *= VO_SCALE;
Packit 47f805
Packit 47f805
    return loudness_power;
Packit 47f805
}
Packit 47f805
Packit 47f805
/* mask_add optimization */
Packit 47f805
/* init the limit values used to avoid computing log in mask_add when it is not necessary */
Packit 47f805
Packit 47f805
/* For example, with i = 10*log10(m2/m1)/10*16         (= log10(m2/m1)*16)
Packit 47f805
 *
Packit 47f805
 * abs(i)>8 is equivalent (as i is an integer) to
Packit 47f805
 * abs(i)>=9
Packit 47f805
 * i>=9 || i<=-9
Packit 47f805
 * equivalent to (as i is the biggest integer smaller than log10(m2/m1)*16 
Packit 47f805
 * or the smallest integer bigger than log10(m2/m1)*16 depending on the sign of log10(m2/m1)*16)
Packit 47f805
 * log10(m2/m1)>=9/16 || log10(m2/m1)<=-9/16
Packit 47f805
 * exp10 is strictly increasing thus this is equivalent to
Packit 47f805
 * m2/m1 >= 10^(9/16) || m2/m1<=10^(-9/16) which are comparisons to constants
Packit 47f805
 */
Packit 47f805
Packit 47f805
Packit 47f805
#define I1LIMIT 8       /* as in if(i>8)  */
Packit 47f805
#define I2LIMIT 23      /* as in if(i>24) -> changed 23 */
Packit 47f805
#define MLIMIT  15      /* as in if(m<15) */
Packit 47f805
Packit 47f805
/* pow(10, (I1LIMIT + 1) / 16.0); */
Packit 47f805
static const FLOAT ma_max_i1 = 3.6517412725483771;
Packit 47f805
/* pow(10, (I2LIMIT + 1) / 16.0); */
Packit 47f805
static const FLOAT ma_max_i2 = 31.622776601683793;
Packit 47f805
/* pow(10, (MLIMIT) / 10.0); */
Packit 47f805
static const FLOAT ma_max_m  = 31.622776601683793;
Packit 47f805
Packit 47f805
    /*This is the masking table:
Packit 47f805
       According to tonality, values are going from 0dB (TMN)
Packit 47f805
       to 9.3dB (NMT).
Packit 47f805
       After additive masking computation, 8dB are added, so
Packit 47f805
       final values are going from 8dB to 17.3dB
Packit 47f805
     */
Packit 47f805
static const FLOAT tab[] = {
Packit 47f805
    1.0 /*pow(10, -0) */ ,
Packit 47f805
    0.79433 /*pow(10, -0.1) */ ,
Packit 47f805
    0.63096 /*pow(10, -0.2) */ ,
Packit 47f805
    0.63096 /*pow(10, -0.2) */ ,
Packit 47f805
    0.63096 /*pow(10, -0.2) */ ,
Packit 47f805
    0.63096 /*pow(10, -0.2) */ ,
Packit 47f805
    0.63096 /*pow(10, -0.2) */ ,
Packit 47f805
    0.25119 /*pow(10, -0.6) */ ,
Packit 47f805
    0.11749             /*pow(10, -0.93) */
Packit 47f805
};
Packit 47f805
Packit 47f805
static const int tab_mask_add_delta[] = { 2, 2, 2, 1, 1, 1, 0, 0, -1 };
Packit 47f805
#define STATIC_ASSERT_EQUAL_DIMENSION(A,B) enum{static_assert_##A=1/((dimension_of(A) == dimension_of(B))?1:0)}
Packit 47f805
Packit 47f805
inline static int
Packit 47f805
mask_add_delta(int i)
Packit 47f805
{
Packit 47f805
    STATIC_ASSERT_EQUAL_DIMENSION(tab_mask_add_delta,tab);
Packit 47f805
    assert(i < (int)dimension_of(tab));
Packit 47f805
    return tab_mask_add_delta[i];
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
static void
Packit 47f805
init_mask_add_max_values(void)
Packit 47f805
{
Packit 47f805
#ifndef NDEBUG
Packit 47f805
    FLOAT const _ma_max_i1 = pow(10, (I1LIMIT + 1) / 16.0);
Packit 47f805
    FLOAT const _ma_max_i2 = pow(10, (I2LIMIT + 1) / 16.0);
Packit 47f805
    FLOAT const _ma_max_m = pow(10, (MLIMIT) / 10.0);
Packit 47f805
    assert(fabs(ma_max_i1 - _ma_max_i1) <= FLT_EPSILON);
Packit 47f805
    assert(fabs(ma_max_i2 - _ma_max_i2) <= FLT_EPSILON);
Packit 47f805
    assert(fabs(ma_max_m  - _ma_max_m ) <= FLT_EPSILON);
Packit 47f805
#endif
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
/* addition of simultaneous masking   Naoki Shibata 2000/7 */
Packit 47f805
inline static FLOAT
Packit 47f805
vbrpsy_mask_add(FLOAT m1, FLOAT m2, int b, int delta)
Packit 47f805
{
Packit 47f805
    static const FLOAT table2[] = {
Packit 47f805
        1.33352 * 1.33352, 1.35879 * 1.35879, 1.38454 * 1.38454, 1.39497 * 1.39497,
Packit 47f805
        1.40548 * 1.40548, 1.3537 * 1.3537, 1.30382 * 1.30382, 1.22321 * 1.22321,
Packit 47f805
        1.14758 * 1.14758,
Packit 47f805
        1
Packit 47f805
    };
Packit 47f805
Packit 47f805
    FLOAT   ratio;
Packit 47f805
Packit 47f805
    if (m1 < 0) {
Packit 47f805
        m1 = 0;
Packit 47f805
    }
Packit 47f805
    if (m2 < 0) {
Packit 47f805
        m2 = 0;
Packit 47f805
    }
Packit 47f805
    if (m1 <= 0) {
Packit 47f805
        return m2;
Packit 47f805
    }
Packit 47f805
    if (m2 <= 0) {
Packit 47f805
        return m1;
Packit 47f805
    }
Packit 47f805
    if (m2 > m1) {
Packit 47f805
        ratio = m2 / m1;
Packit 47f805
    }
Packit 47f805
    else {
Packit 47f805
        ratio = m1 / m2;
Packit 47f805
    }
Packit 47f805
    if (abs(b) <= delta) {       /* approximately, 1 bark = 3 partitions */
Packit 47f805
        /* originally 'if(i > 8)' */
Packit 47f805
        if (ratio >= ma_max_i1) {
Packit 47f805
            return m1 + m2;
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            int     i = (int) (FAST_LOG10_X(ratio, 16.0f));
Packit 47f805
            return (m1 + m2) * table2[i];
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    if (ratio < ma_max_i2) {
Packit 47f805
        return m1 + m2;
Packit 47f805
    }
Packit 47f805
    if (m1 < m2) {
Packit 47f805
        m1 = m2;
Packit 47f805
    }
Packit 47f805
    return m1;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
/* short block threshold calculation (part 2)
Packit 47f805
Packit 47f805
    partition band bo_s[sfb] is at the transition from scalefactor
Packit 47f805
    band sfb to the next one sfb+1; enn and thmm have to be split
Packit 47f805
    between them
Packit 47f805
*/
Packit 47f805
static void
Packit 47f805
convert_partition2scalefac(PsyConst_CB2SB_t const *const gd, FLOAT const *eb, FLOAT const *thr,
Packit 47f805
                           FLOAT enn_out[], FLOAT thm_out[])
Packit 47f805
{
Packit 47f805
    FLOAT   enn, thmm;
Packit 47f805
    int     sb, b, n = gd->n_sb;
Packit 47f805
    enn = thmm = 0.0f;
Packit 47f805
    for (sb = b = 0; sb < n; ++b, ++sb) {
Packit 47f805
        int const bo_sb = gd->bo[sb];
Packit 47f805
        int const npart = gd->npart;
Packit 47f805
        int const b_lim = bo_sb < npart ? bo_sb : npart;
Packit 47f805
        while (b < b_lim) {
Packit 47f805
            assert(eb[b] >= 0); /* iff failed, it may indicate some index error elsewhere */
Packit 47f805
            assert(thr[b] >= 0);
Packit 47f805
            enn += eb[b];
Packit 47f805
            thmm += thr[b];
Packit 47f805
            b++;
Packit 47f805
        }
Packit 47f805
        if (b >= npart) {
Packit 47f805
            enn_out[sb] = enn;
Packit 47f805
            thm_out[sb] = thmm;
Packit 47f805
            ++sb;
Packit 47f805
            break;
Packit 47f805
        }
Packit 47f805
        assert(eb[b] >= 0); /* iff failed, it may indicate some index error elsewhere */
Packit 47f805
        assert(thr[b] >= 0);
Packit 47f805
        {
Packit 47f805
            /* at transition sfb -> sfb+1 */
Packit 47f805
            FLOAT const w_curr = gd->bo_weight[sb];
Packit 47f805
            FLOAT const w_next = 1.0f - w_curr;
Packit 47f805
            enn += w_curr * eb[b];
Packit 47f805
            thmm += w_curr * thr[b];
Packit 47f805
            enn_out[sb] = enn;
Packit 47f805
            thm_out[sb] = thmm;
Packit 47f805
            enn = w_next * eb[b];
Packit 47f805
            thmm = w_next * thr[b];
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    /* zero initialize the rest */
Packit 47f805
    for (; sb < n; ++sb) {
Packit 47f805
        enn_out[sb] = 0;
Packit 47f805
        thm_out[sb] = 0;
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
static void
Packit 47f805
convert_partition2scalefac_s(lame_internal_flags * gfc, FLOAT const *eb, FLOAT const *thr, int chn,
Packit 47f805
                             int sblock)
Packit 47f805
{
Packit 47f805
    PsyStateVar_t *const psv = &gfc->sv_psy;
Packit 47f805
    PsyConst_CB2SB_t const *const gds = &gfc->cd_psy->s;
Packit 47f805
    FLOAT   enn[SBMAX_s], thm[SBMAX_s];
Packit 47f805
    int     sb;
Packit 47f805
    convert_partition2scalefac(gds, eb, thr, enn, thm);
Packit 47f805
    for (sb = 0; sb < SBMAX_s; ++sb) {
Packit 47f805
        psv->en[chn].s[sb][sblock] = enn[sb];
Packit 47f805
        psv->thm[chn].s[sb][sblock] = thm[sb];
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
/* longblock threshold calculation (part 2) */
Packit 47f805
static void
Packit 47f805
convert_partition2scalefac_l(lame_internal_flags * gfc, FLOAT const *eb, FLOAT const *thr, int chn)
Packit 47f805
{
Packit 47f805
    PsyStateVar_t *const psv = &gfc->sv_psy;
Packit 47f805
    PsyConst_CB2SB_t const *const gdl = &gfc->cd_psy->l;
Packit 47f805
    FLOAT  *enn = &psv->en[chn].l[0];
Packit 47f805
    FLOAT  *thm = &psv->thm[chn].l[0];
Packit 47f805
    convert_partition2scalefac(gdl, eb, thr, enn, thm);
Packit 47f805
}
Packit 47f805
Packit 47f805
static void
Packit 47f805
convert_partition2scalefac_l_to_s(lame_internal_flags * gfc, FLOAT const *eb, FLOAT const *thr,
Packit 47f805
                                  int chn)
Packit 47f805
{
Packit 47f805
    PsyStateVar_t *const psv = &gfc->sv_psy;
Packit 47f805
    PsyConst_CB2SB_t const *const gds = &gfc->cd_psy->l_to_s;
Packit 47f805
    FLOAT   enn[SBMAX_s], thm[SBMAX_s];
Packit 47f805
    int     sb, sblock;
Packit 47f805
    convert_partition2scalefac(gds, eb, thr, enn, thm);
Packit 47f805
    for (sb = 0; sb < SBMAX_s; ++sb) {
Packit 47f805
        FLOAT const scale = 1. / 64.f;
Packit 47f805
        FLOAT const tmp_enn = enn[sb];
Packit 47f805
        FLOAT const tmp_thm = thm[sb] * scale;
Packit 47f805
        for (sblock = 0; sblock < 3; ++sblock) {
Packit 47f805
            psv->en[chn].s[sb][sblock] = tmp_enn;
Packit 47f805
            psv->thm[chn].s[sb][sblock] = tmp_thm;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
static inline FLOAT
Packit 47f805
NS_INTERP(FLOAT x, FLOAT y, FLOAT r)
Packit 47f805
{
Packit 47f805
    /* was pow((x),(r))*pow((y),1-(r)) */
Packit 47f805
    if (r >= 1.0f)
Packit 47f805
        return x;       /* 99.7% of the time */
Packit 47f805
    if (r <= 0.0f)
Packit 47f805
        return y;
Packit 47f805
    if (y > 0.0f)
Packit 47f805
        return powf(x / y, r) * y; /* rest of the time */
Packit 47f805
    return 0.0f;        /* never happens */
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
static  FLOAT
Packit 47f805
pecalc_s(III_psy_ratio const *mr, FLOAT masking_lower)
Packit 47f805
{
Packit 47f805
    FLOAT   pe_s;
Packit 47f805
    static const FLOAT regcoef_s[] = {
Packit 47f805
        11.8,           /* these values are tuned only for 44.1kHz... */
Packit 47f805
        13.6,
Packit 47f805
        17.2,
Packit 47f805
        32,
Packit 47f805
        46.5,
Packit 47f805
        51.3,
Packit 47f805
        57.5,
Packit 47f805
        67.1,
Packit 47f805
        71.5,
Packit 47f805
        84.6,
Packit 47f805
        97.6,
Packit 47f805
        130,
Packit 47f805
/*      255.8 */
Packit 47f805
    };
Packit 47f805
    unsigned int sb, sblock;
Packit 47f805
Packit 47f805
    pe_s = 1236.28f / 4;
Packit 47f805
    for (sb = 0; sb < SBMAX_s - 1; sb++) {
Packit 47f805
        for (sblock = 0; sblock < 3; sblock++) {
Packit 47f805
            FLOAT const thm = mr->thm.s[sb][sblock];
Packit 47f805
            assert(sb < dimension_of(regcoef_s));
Packit 47f805
            if (thm > 0.0f) {
Packit 47f805
                FLOAT const x = thm * masking_lower;
Packit 47f805
                FLOAT const en = mr->en.s[sb][sblock];
Packit 47f805
                if (en > x) {
Packit 47f805
                    if (en > x * 1e10f) {
Packit 47f805
                        pe_s += regcoef_s[sb] * (10.0f * LOG10);
Packit 47f805
                    }
Packit 47f805
                    else {
Packit 47f805
                        assert(x > 0);
Packit 47f805
                        pe_s += regcoef_s[sb] * FAST_LOG10(en / x);
Packit 47f805
                    }
Packit 47f805
                }
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
Packit 47f805
    return pe_s;
Packit 47f805
}
Packit 47f805
Packit 47f805
static  FLOAT
Packit 47f805
pecalc_l(III_psy_ratio const *mr, FLOAT masking_lower)
Packit 47f805
{
Packit 47f805
    FLOAT   pe_l;
Packit 47f805
    static const FLOAT regcoef_l[] = {
Packit 47f805
        6.8,            /* these values are tuned only for 44.1kHz... */
Packit 47f805
        5.8,
Packit 47f805
        5.8,
Packit 47f805
        6.4,
Packit 47f805
        6.5,
Packit 47f805
        9.9,
Packit 47f805
        12.1,
Packit 47f805
        14.4,
Packit 47f805
        15,
Packit 47f805
        18.9,
Packit 47f805
        21.6,
Packit 47f805
        26.9,
Packit 47f805
        34.2,
Packit 47f805
        40.2,
Packit 47f805
        46.8,
Packit 47f805
        56.5,
Packit 47f805
        60.7,
Packit 47f805
        73.9,
Packit 47f805
        85.7,
Packit 47f805
        93.4,
Packit 47f805
        126.1,
Packit 47f805
/*      241.3 */
Packit 47f805
    };
Packit 47f805
    unsigned int sb;
Packit 47f805
Packit 47f805
    pe_l = 1124.23f / 4;
Packit 47f805
    for (sb = 0; sb < SBMAX_l - 1; sb++) {
Packit 47f805
        FLOAT const thm = mr->thm.l[sb];
Packit 47f805
        assert(sb < dimension_of(regcoef_l));
Packit 47f805
        if (thm > 0.0f) {
Packit 47f805
            FLOAT const x = thm * masking_lower;
Packit 47f805
            FLOAT const en = mr->en.l[sb];
Packit 47f805
            if (en > x) {
Packit 47f805
                if (en > x * 1e10f) {
Packit 47f805
                    pe_l += regcoef_l[sb] * (10.0f * LOG10);
Packit 47f805
                }
Packit 47f805
                else {
Packit 47f805
                    assert(x > 0);
Packit 47f805
                    pe_l += regcoef_l[sb] * FAST_LOG10(en / x);
Packit 47f805
                }
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
Packit 47f805
    return pe_l;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
static void
Packit 47f805
calc_energy(PsyConst_CB2SB_t const *l, FLOAT const *fftenergy, FLOAT * eb, FLOAT * max, FLOAT * avg)
Packit 47f805
{
Packit 47f805
    int     b, j;
Packit 47f805
Packit 47f805
    for (b = j = 0; b < l->npart; ++b) {
Packit 47f805
        FLOAT   ebb = 0, m = 0;
Packit 47f805
        int     i;
Packit 47f805
        for (i = 0; i < l->numlines[b]; ++i, ++j) {
Packit 47f805
            FLOAT const el = fftenergy[j];
Packit 47f805
            assert(el >= 0);
Packit 47f805
            ebb += el;
Packit 47f805
            if (m < el)
Packit 47f805
                m = el;
Packit 47f805
        }
Packit 47f805
        eb[b] = ebb;
Packit 47f805
        max[b] = m;
Packit 47f805
        avg[b] = ebb * l->rnumlines[b];
Packit 47f805
        assert(l->rnumlines[b] >= 0);
Packit 47f805
        assert(ebb >= 0);
Packit 47f805
        assert(eb[b] >= 0);
Packit 47f805
        assert(max[b] >= 0);
Packit 47f805
        assert(avg[b] >= 0);
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
static void
Packit 47f805
calc_mask_index_l(lame_internal_flags const *gfc, FLOAT const *max,
Packit 47f805
                  FLOAT const *avg, unsigned char *mask_idx)
Packit 47f805
{
Packit 47f805
    PsyConst_CB2SB_t const *const gdl = &gfc->cd_psy->l;
Packit 47f805
    FLOAT   m, a;
Packit 47f805
    int     b, k;
Packit 47f805
    int const last_tab_entry = sizeof(tab) / sizeof(tab[0]) - 1;
Packit 47f805
    b = 0;
Packit 47f805
    a = avg[b] + avg[b + 1];
Packit 47f805
    assert(a >= 0);
Packit 47f805
    if (a > 0.0f) {
Packit 47f805
        m = max[b];
Packit 47f805
        if (m < max[b + 1])
Packit 47f805
            m = max[b + 1];
Packit 47f805
        assert((gdl->numlines[b] + gdl->numlines[b + 1] - 1) > 0);
Packit 47f805
        a = 20.0f * (m * 2.0f - a)
Packit 47f805
            / (a * (gdl->numlines[b] + gdl->numlines[b + 1] - 1));
Packit 47f805
        k = (int) a;
Packit 47f805
        if (k > last_tab_entry)
Packit 47f805
            k = last_tab_entry;
Packit 47f805
        mask_idx[b] = k;
Packit 47f805
    }
Packit 47f805
    else {
Packit 47f805
        mask_idx[b] = 0;
Packit 47f805
    }
Packit 47f805
Packit 47f805
    for (b = 1; b < gdl->npart - 1; b++) {
Packit 47f805
        a = avg[b - 1] + avg[b] + avg[b + 1];
Packit 47f805
        assert(a >= 0);
Packit 47f805
        if (a > 0.0f) {
Packit 47f805
            m = max[b - 1];
Packit 47f805
            if (m < max[b])
Packit 47f805
                m = max[b];
Packit 47f805
            if (m < max[b + 1])
Packit 47f805
                m = max[b + 1];
Packit 47f805
            assert((gdl->numlines[b - 1] + gdl->numlines[b] + gdl->numlines[b + 1] - 1) > 0);
Packit 47f805
            a = 20.0f * (m * 3.0f - a)
Packit 47f805
                / (a * (gdl->numlines[b - 1] + gdl->numlines[b] + gdl->numlines[b + 1] - 1));
Packit 47f805
            k = (int) a;
Packit 47f805
            if (k > last_tab_entry)
Packit 47f805
                k = last_tab_entry;
Packit 47f805
            mask_idx[b] = k;
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            mask_idx[b] = 0;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    assert(b > 0);
Packit 47f805
    assert(b == gdl->npart - 1);
Packit 47f805
Packit 47f805
    a = avg[b - 1] + avg[b];
Packit 47f805
    assert(a >= 0);
Packit 47f805
    if (a > 0.0f) {
Packit 47f805
        m = max[b - 1];
Packit 47f805
        if (m < max[b])
Packit 47f805
            m = max[b];
Packit 47f805
        assert((gdl->numlines[b - 1] + gdl->numlines[b] - 1) > 0);
Packit 47f805
        a = 20.0f * (m * 2.0f - a)
Packit 47f805
            / (a * (gdl->numlines[b - 1] + gdl->numlines[b] - 1));
Packit 47f805
        k = (int) a;
Packit 47f805
        if (k > last_tab_entry)
Packit 47f805
            k = last_tab_entry;
Packit 47f805
        mask_idx[b] = k;
Packit 47f805
    }
Packit 47f805
    else {
Packit 47f805
        mask_idx[b] = 0;
Packit 47f805
    }
Packit 47f805
    assert(b == (gdl->npart - 1));
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
static void
Packit 47f805
vbrpsy_compute_fft_l(lame_internal_flags * gfc, const sample_t * const buffer[2], int chn,
Packit 47f805
                     int gr_out, FLOAT fftenergy[HBLKSIZE], FLOAT(*wsamp_l)[BLKSIZE])
Packit 47f805
{
Packit 47f805
    SessionConfig_t const *const cfg = &gfc->cfg;
Packit 47f805
    PsyStateVar_t *psv = &gfc->sv_psy;
Packit 47f805
    plotting_data *plt = cfg->analysis ? gfc->pinfo : 0;
Packit 47f805
    int     j;
Packit 47f805
Packit 47f805
    if (chn < 2) {
Packit 47f805
        fft_long(gfc, *wsamp_l, chn, buffer);
Packit 47f805
    }
Packit 47f805
    else if (chn == 2) {
Packit 47f805
        FLOAT const sqrt2_half = SQRT2 * 0.5f;
Packit 47f805
        /* FFT data for mid and side channel is derived from L & R */
Packit 47f805
        for (j = BLKSIZE - 1; j >= 0; --j) {
Packit 47f805
            FLOAT const l = wsamp_l[0][j];
Packit 47f805
            FLOAT const r = wsamp_l[1][j];
Packit 47f805
            wsamp_l[0][j] = (l + r) * sqrt2_half;
Packit 47f805
            wsamp_l[1][j] = (l - r) * sqrt2_half;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
Packit 47f805
    /*********************************************************************
Packit 47f805
    *  compute energies
Packit 47f805
    *********************************************************************/
Packit 47f805
    fftenergy[0] = wsamp_l[0][0];
Packit 47f805
    fftenergy[0] *= fftenergy[0];
Packit 47f805
Packit 47f805
    for (j = BLKSIZE / 2 - 1; j >= 0; --j) {
Packit 47f805
        FLOAT const re = (*wsamp_l)[BLKSIZE / 2 - j];
Packit 47f805
        FLOAT const im = (*wsamp_l)[BLKSIZE / 2 + j];
Packit 47f805
        fftenergy[BLKSIZE / 2 - j] = (re * re + im * im) * 0.5f;
Packit 47f805
    }
Packit 47f805
    /* total energy */
Packit 47f805
    {
Packit 47f805
        FLOAT   totalenergy = 0.0f;
Packit 47f805
        for (j = 11; j < HBLKSIZE; j++)
Packit 47f805
            totalenergy += fftenergy[j];
Packit 47f805
Packit 47f805
        psv->tot_ener[chn] = totalenergy;
Packit 47f805
    }
Packit 47f805
Packit 47f805
    if (plt) {
Packit 47f805
        for (j = 0; j < HBLKSIZE; j++) {
Packit 47f805
            plt->energy[gr_out][chn][j] = plt->energy_save[chn][j];
Packit 47f805
            plt->energy_save[chn][j] = fftenergy[j];
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
static void
Packit 47f805
vbrpsy_compute_fft_s(lame_internal_flags const *gfc, const sample_t * const buffer[2], int chn,
Packit 47f805
                     int sblock, FLOAT(*fftenergy_s)[HBLKSIZE_s], FLOAT(*wsamp_s)[3][BLKSIZE_s])
Packit 47f805
{
Packit 47f805
    int     j;
Packit 47f805
Packit 47f805
    if (sblock == 0 && chn < 2) {
Packit 47f805
        fft_short(gfc, *wsamp_s, chn, buffer);
Packit 47f805
    }
Packit 47f805
    if (chn == 2) {
Packit 47f805
        FLOAT const sqrt2_half = SQRT2 * 0.5f;
Packit 47f805
        /* FFT data for mid and side channel is derived from L & R */
Packit 47f805
        for (j = BLKSIZE_s - 1; j >= 0; --j) {
Packit 47f805
            FLOAT const l = wsamp_s[0][sblock][j];
Packit 47f805
            FLOAT const r = wsamp_s[1][sblock][j];
Packit 47f805
            wsamp_s[0][sblock][j] = (l + r) * sqrt2_half;
Packit 47f805
            wsamp_s[1][sblock][j] = (l - r) * sqrt2_half;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
Packit 47f805
    /*********************************************************************
Packit 47f805
    *  compute energies
Packit 47f805
    *********************************************************************/
Packit 47f805
    fftenergy_s[sblock][0] = (*wsamp_s)[sblock][0];
Packit 47f805
    fftenergy_s[sblock][0] *= fftenergy_s[sblock][0];
Packit 47f805
    for (j = BLKSIZE_s / 2 - 1; j >= 0; --j) {
Packit 47f805
        FLOAT const re = (*wsamp_s)[sblock][BLKSIZE_s / 2 - j];
Packit 47f805
        FLOAT const im = (*wsamp_s)[sblock][BLKSIZE_s / 2 + j];
Packit 47f805
        fftenergy_s[sblock][BLKSIZE_s / 2 - j] = (re * re + im * im) * 0.5f;
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
    /*********************************************************************
Packit 47f805
    * compute loudness approximation (used for ATH auto-level adjustment) 
Packit 47f805
    *********************************************************************/
Packit 47f805
static void
Packit 47f805
vbrpsy_compute_loudness_approximation_l(lame_internal_flags * gfc, int gr_out, int chn,
Packit 47f805
                                        const FLOAT fftenergy[HBLKSIZE])
Packit 47f805
{
Packit 47f805
    PsyStateVar_t *psv = &gfc->sv_psy;
Packit 47f805
    if (chn < 2) {      /*no loudness for mid/side ch */
Packit 47f805
        gfc->ov_psy.loudness_sq[gr_out][chn] = psv->loudness_sq_save[chn];
Packit 47f805
        psv->loudness_sq_save[chn] = psycho_loudness_approx(fftenergy, gfc->ATH->eql_w);
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
    /**********************************************************************
Packit 47f805
    *  Apply HPF of fs/4 to the input signal.
Packit 47f805
    *  This is used for attack detection / handling.
Packit 47f805
    **********************************************************************/
Packit 47f805
static void
Packit 47f805
vbrpsy_attack_detection(lame_internal_flags * gfc, const sample_t * const buffer[2], int gr_out,
Packit 47f805
                        III_psy_ratio masking_ratio[2][2], III_psy_ratio masking_MS_ratio[2][2],
Packit 47f805
                        FLOAT energy[4], FLOAT sub_short_factor[4][3], int ns_attacks[4][4],
Packit 47f805
                        int uselongblock[2])
Packit 47f805
{
Packit 47f805
    FLOAT   ns_hpfsmpl[2][576];
Packit 47f805
    SessionConfig_t const *const cfg = &gfc->cfg;
Packit 47f805
    PsyStateVar_t *const psv = &gfc->sv_psy;
Packit 47f805
    plotting_data *plt = cfg->analysis ? gfc->pinfo : 0;
Packit 47f805
    int const n_chn_out = cfg->channels_out;
Packit 47f805
    /* chn=2 and 3 = Mid and Side channels */
Packit 47f805
    int const n_chn_psy = (cfg->mode == JOINT_STEREO) ? 4 : n_chn_out;
Packit 47f805
    int     chn, i, j;
Packit 47f805
Packit 47f805
    memset(&ns_hpfsmpl[0][0], 0, sizeof(ns_hpfsmpl));
Packit 47f805
    /* Don't copy the input buffer into a temporary buffer */
Packit 47f805
    /* unroll the loop 2 times */
Packit 47f805
    for (chn = 0; chn < n_chn_out; chn++) {
Packit 47f805
        static const FLOAT fircoef[] = {
Packit 47f805
            -8.65163e-18 * 2, -0.00851586 * 2, -6.74764e-18 * 2, 0.0209036 * 2,
Packit 47f805
            -3.36639e-17 * 2, -0.0438162 * 2, -1.54175e-17 * 2, 0.0931738 * 2,
Packit 47f805
            -5.52212e-17 * 2, -0.313819 * 2
Packit 47f805
        };
Packit 47f805
        /* apply high pass filter of fs/4 */
Packit 47f805
        const sample_t *const firbuf = &buffer[chn][576 - 350 - NSFIRLEN + 192];
Packit 47f805
        assert(dimension_of(fircoef) == ((NSFIRLEN - 1) / 2));
Packit 47f805
        for (i = 0; i < 576; i++) {
Packit 47f805
            FLOAT   sum1, sum2;
Packit 47f805
            sum1 = firbuf[i + 10];
Packit 47f805
            sum2 = 0.0;
Packit 47f805
            for (j = 0; j < ((NSFIRLEN - 1) / 2) - 1; j += 2) {
Packit 47f805
                sum1 += fircoef[j] * (firbuf[i + j] + firbuf[i + NSFIRLEN - j]);
Packit 47f805
                sum2 += fircoef[j + 1] * (firbuf[i + j + 1] + firbuf[i + NSFIRLEN - j - 1]);
Packit 47f805
            }
Packit 47f805
            ns_hpfsmpl[chn][i] = sum1 + sum2;
Packit 47f805
        }
Packit 47f805
        masking_ratio[gr_out][chn].en = psv->en[chn];
Packit 47f805
        masking_ratio[gr_out][chn].thm = psv->thm[chn];
Packit 47f805
        if (n_chn_psy > 2) {
Packit 47f805
            /* MS maskings  */
Packit 47f805
            /*percep_MS_entropy         [chn-2]     = gfc -> pe  [chn];  */
Packit 47f805
            masking_MS_ratio[gr_out][chn].en = psv->en[chn + 2];
Packit 47f805
            masking_MS_ratio[gr_out][chn].thm = psv->thm[chn + 2];
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    for (chn = 0; chn < n_chn_psy; chn++) {
Packit 47f805
        FLOAT   attack_intensity[12];
Packit 47f805
        FLOAT   en_subshort[12];
Packit 47f805
        FLOAT   en_short[4] = { 0, 0, 0, 0 };
Packit 47f805
        FLOAT const *pf = ns_hpfsmpl[chn & 1];
Packit 47f805
        int     ns_uselongblock = 1;
Packit 47f805
Packit 47f805
        if (chn == 2) {
Packit 47f805
            for (i = 0, j = 576; j > 0; ++i, --j) {
Packit 47f805
                FLOAT const l = ns_hpfsmpl[0][i];
Packit 47f805
                FLOAT const r = ns_hpfsmpl[1][i];
Packit 47f805
                ns_hpfsmpl[0][i] = l + r;
Packit 47f805
                ns_hpfsmpl[1][i] = l - r;
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
        /*************************************************************** 
Packit 47f805
        * determine the block type (window type)
Packit 47f805
        ***************************************************************/
Packit 47f805
        /* calculate energies of each sub-shortblocks */
Packit 47f805
        for (i = 0; i < 3; i++) {
Packit 47f805
            en_subshort[i] = psv->last_en_subshort[chn][i + 6];
Packit 47f805
            assert(psv->last_en_subshort[chn][i + 4] > 0);
Packit 47f805
            attack_intensity[i] = en_subshort[i] / psv->last_en_subshort[chn][i + 4];
Packit 47f805
            en_short[0] += en_subshort[i];
Packit 47f805
        }
Packit 47f805
Packit 47f805
        for (i = 0; i < 9; i++) {
Packit 47f805
            FLOAT const *const pfe = pf + 576 / 9;
Packit 47f805
            FLOAT   p = 1.;
Packit 47f805
            for (; pf < pfe; pf++)
Packit 47f805
                if (p < fabs(*pf))
Packit 47f805
                    p = fabs(*pf);
Packit 47f805
            psv->last_en_subshort[chn][i] = en_subshort[i + 3] = p;
Packit 47f805
            en_short[1 + i / 3] += p;
Packit 47f805
            if (p > en_subshort[i + 3 - 2]) {
Packit 47f805
                assert(en_subshort[i + 3 - 2] > 0);
Packit 47f805
                p = p / en_subshort[i + 3 - 2];
Packit 47f805
            }
Packit 47f805
            else if (en_subshort[i + 3 - 2] > p * 10.0f) {
Packit 47f805
                assert(p > 0);
Packit 47f805
                p = en_subshort[i + 3 - 2] / (p * 10.0f);
Packit 47f805
            }
Packit 47f805
            else {
Packit 47f805
                p = 0.0;
Packit 47f805
            }
Packit 47f805
            attack_intensity[i + 3] = p;
Packit 47f805
        }
Packit 47f805
Packit 47f805
        /* pulse like signal detection for fatboy.wav and so on */
Packit 47f805
        for (i = 0; i < 3; ++i) {
Packit 47f805
            FLOAT const enn =
Packit 47f805
                en_subshort[i * 3 + 3] + en_subshort[i * 3 + 4] + en_subshort[i * 3 + 5];
Packit 47f805
            FLOAT   factor = 1.f;
Packit 47f805
            if (en_subshort[i * 3 + 5] * 6 < enn) {
Packit 47f805
                factor *= 0.5f;
Packit 47f805
                if (en_subshort[i * 3 + 4] * 6 < enn) {
Packit 47f805
                    factor *= 0.5f;
Packit 47f805
                }
Packit 47f805
            }
Packit 47f805
            sub_short_factor[chn][i] = factor;
Packit 47f805
        }
Packit 47f805
Packit 47f805
        if (plt) {
Packit 47f805
            FLOAT   x = attack_intensity[0];
Packit 47f805
            for (i = 1; i < 12; i++) {
Packit 47f805
                if (x < attack_intensity[i]) {
Packit 47f805
                    x = attack_intensity[i];
Packit 47f805
                }
Packit 47f805
            }
Packit 47f805
            plt->ers[gr_out][chn] = plt->ers_save[chn];
Packit 47f805
            plt->ers_save[chn] = x;
Packit 47f805
        }
Packit 47f805
Packit 47f805
        /* compare energies between sub-shortblocks */
Packit 47f805
        {
Packit 47f805
            FLOAT   x = gfc->cd_psy->attack_threshold[chn];
Packit 47f805
            for (i = 0; i < 12; i++) {
Packit 47f805
                if (ns_attacks[chn][i / 3] == 0) {
Packit 47f805
                    if (attack_intensity[i] > x) {
Packit 47f805
                        ns_attacks[chn][i / 3] = (i % 3) + 1;
Packit 47f805
                    }
Packit 47f805
                }
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
        /* should have energy change between short blocks, in order to avoid periodic signals */
Packit 47f805
        /* Good samples to show the effect are Trumpet test songs */
Packit 47f805
        /* GB: tuned (1) to avoid too many short blocks for test sample TRUMPET */
Packit 47f805
        /* RH: tuned (2) to let enough short blocks through for test sample FSOL and SNAPS */
Packit 47f805
        for (i = 1; i < 4; i++) {
Packit 47f805
            FLOAT const u = en_short[i - 1];
Packit 47f805
            FLOAT const v = en_short[i];
Packit 47f805
            FLOAT const m = Max(u, v);
Packit 47f805
            if (m < 40000) { /* (2) */
Packit 47f805
                if (u < 1.7f * v && v < 1.7f * u) { /* (1) */
Packit 47f805
                    if (i == 1 && ns_attacks[chn][0] <= ns_attacks[chn][i]) {
Packit 47f805
                        ns_attacks[chn][0] = 0;
Packit 47f805
                    }
Packit 47f805
                    ns_attacks[chn][i] = 0;
Packit 47f805
                }
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
Packit 47f805
        if (ns_attacks[chn][0] <= psv->last_attacks[chn]) {
Packit 47f805
            ns_attacks[chn][0] = 0;
Packit 47f805
        }
Packit 47f805
Packit 47f805
        if (psv->last_attacks[chn] == 3 ||
Packit 47f805
            ns_attacks[chn][0] + ns_attacks[chn][1] + ns_attacks[chn][2] + ns_attacks[chn][3]) {
Packit 47f805
            ns_uselongblock = 0;
Packit 47f805
Packit 47f805
            if (ns_attacks[chn][1] && ns_attacks[chn][0]) {
Packit 47f805
                ns_attacks[chn][1] = 0;
Packit 47f805
            }
Packit 47f805
            if (ns_attacks[chn][2] && ns_attacks[chn][1]) {
Packit 47f805
                ns_attacks[chn][2] = 0;
Packit 47f805
            }
Packit 47f805
            if (ns_attacks[chn][3] && ns_attacks[chn][2]) {
Packit 47f805
                ns_attacks[chn][3] = 0;
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
Packit 47f805
        if (chn < 2) {
Packit 47f805
            uselongblock[chn] = ns_uselongblock;
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            if (ns_uselongblock == 0) {
Packit 47f805
                uselongblock[0] = uselongblock[1] = 0;
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
Packit 47f805
        /* there is a one granule delay.  Copy maskings computed last call
Packit 47f805
         * into masking_ratio to return to calling program.
Packit 47f805
         */
Packit 47f805
        energy[chn] = psv->tot_ener[chn];
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
static void
Packit 47f805
vbrpsy_skip_masking_s(lame_internal_flags * gfc, int chn, int sblock)
Packit 47f805
{
Packit 47f805
    if (sblock == 0) {
Packit 47f805
        FLOAT  *nbs2 = &gfc->sv_psy.nb_s2[chn][0];
Packit 47f805
        FLOAT  *nbs1 = &gfc->sv_psy.nb_s1[chn][0];
Packit 47f805
        int const n = gfc->cd_psy->s.npart;
Packit 47f805
        int     b;
Packit 47f805
        for (b = 0; b < n; b++) {
Packit 47f805
            nbs2[b] = nbs1[b];
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
static void
Packit 47f805
vbrpsy_calc_mask_index_s(lame_internal_flags const *gfc, FLOAT const *max,
Packit 47f805
                         FLOAT const *avg, unsigned char *mask_idx)
Packit 47f805
{
Packit 47f805
    PsyConst_CB2SB_t const *const gds = &gfc->cd_psy->s;
Packit 47f805
    FLOAT   m, a;
Packit 47f805
    int     b, k;
Packit 47f805
    int const last_tab_entry = dimension_of(tab) - 1;
Packit 47f805
    b = 0;
Packit 47f805
    a = avg[b] + avg[b + 1];
Packit 47f805
    assert(a >= 0);
Packit 47f805
    if (a > 0.0f) {
Packit 47f805
        m = max[b];
Packit 47f805
        if (m < max[b + 1])
Packit 47f805
            m = max[b + 1];
Packit 47f805
        assert((gds->numlines[b] + gds->numlines[b + 1] - 1) > 0);
Packit 47f805
        a = 20.0f * (m * 2.0f - a)
Packit 47f805
            / (a * (gds->numlines[b] + gds->numlines[b + 1] - 1));
Packit 47f805
        k = (int) a;
Packit 47f805
        if (k > last_tab_entry)
Packit 47f805
            k = last_tab_entry;
Packit 47f805
        mask_idx[b] = k;
Packit 47f805
    }
Packit 47f805
    else {
Packit 47f805
        mask_idx[b] = 0;
Packit 47f805
    }
Packit 47f805
Packit 47f805
    for (b = 1; b < gds->npart - 1; b++) {
Packit 47f805
        a = avg[b - 1] + avg[b] + avg[b + 1];
Packit 47f805
        assert(b + 1 < gds->npart);
Packit 47f805
        assert(a >= 0);
Packit 47f805
        if (a > 0.0) {
Packit 47f805
            m = max[b - 1];
Packit 47f805
            if (m < max[b])
Packit 47f805
                m = max[b];
Packit 47f805
            if (m < max[b + 1])
Packit 47f805
                m = max[b + 1];
Packit 47f805
            assert((gds->numlines[b - 1] + gds->numlines[b] + gds->numlines[b + 1] - 1) > 0);
Packit 47f805
            a = 20.0f * (m * 3.0f - a)
Packit 47f805
                / (a * (gds->numlines[b - 1] + gds->numlines[b] + gds->numlines[b + 1] - 1));
Packit 47f805
            k = (int) a;
Packit 47f805
            if (k > last_tab_entry)
Packit 47f805
                k = last_tab_entry;
Packit 47f805
            mask_idx[b] = k;
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            mask_idx[b] = 0;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    assert(b > 0);
Packit 47f805
    assert(b == gds->npart - 1);
Packit 47f805
Packit 47f805
    a = avg[b - 1] + avg[b];
Packit 47f805
    assert(a >= 0);
Packit 47f805
    if (a > 0.0f) {
Packit 47f805
        m = max[b - 1];
Packit 47f805
        if (m < max[b])
Packit 47f805
            m = max[b];
Packit 47f805
        assert((gds->numlines[b - 1] + gds->numlines[b] - 1) > 0);
Packit 47f805
        a = 20.0f * (m * 2.0f - a)
Packit 47f805
            / (a * (gds->numlines[b - 1] + gds->numlines[b] - 1));
Packit 47f805
        k = (int) a;
Packit 47f805
        if (k > last_tab_entry)
Packit 47f805
            k = last_tab_entry;
Packit 47f805
        mask_idx[b] = k;
Packit 47f805
    }
Packit 47f805
    else {
Packit 47f805
        mask_idx[b] = 0;
Packit 47f805
    }
Packit 47f805
    assert(b == (gds->npart - 1));
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
static void
Packit 47f805
vbrpsy_compute_masking_s(lame_internal_flags * gfc, const FLOAT(*fftenergy_s)[HBLKSIZE_s],
Packit 47f805
                         FLOAT * eb, FLOAT * thr, int chn, int sblock)
Packit 47f805
{
Packit 47f805
    PsyStateVar_t *const psv = &gfc->sv_psy;
Packit 47f805
    PsyConst_CB2SB_t const *const gds = &gfc->cd_psy->s;
Packit 47f805
    FLOAT   max[CBANDS], avg[CBANDS];
Packit 47f805
    int     i, j, b;
Packit 47f805
    unsigned char mask_idx_s[CBANDS];
Packit 47f805
Packit 47f805
    memset(max, 0, sizeof(max));
Packit 47f805
    memset(avg, 0, sizeof(avg));
Packit 47f805
Packit 47f805
    for (b = j = 0; b < gds->npart; ++b) {
Packit 47f805
        FLOAT   ebb = 0, m = 0;
Packit 47f805
        int const n = gds->numlines[b];
Packit 47f805
        for (i = 0; i < n; ++i, ++j) {
Packit 47f805
            FLOAT const el = fftenergy_s[sblock][j];
Packit 47f805
            ebb += el;
Packit 47f805
            if (m < el)
Packit 47f805
                m = el;
Packit 47f805
        }
Packit 47f805
        eb[b] = ebb;
Packit 47f805
        assert(ebb >= 0);
Packit 47f805
        max[b] = m;
Packit 47f805
        assert(n > 0);
Packit 47f805
        avg[b] = ebb * gds->rnumlines[b];
Packit 47f805
        assert(avg[b] >= 0);
Packit 47f805
    }
Packit 47f805
    assert(b == gds->npart);
Packit 47f805
    assert(j == 129);
Packit 47f805
    vbrpsy_calc_mask_index_s(gfc, max, avg, mask_idx_s);
Packit 47f805
    for (j = b = 0; b < gds->npart; b++) {
Packit 47f805
        int     kk = gds->s3ind[b][0];
Packit 47f805
        int const last = gds->s3ind[b][1];
Packit 47f805
        int const delta = mask_add_delta(mask_idx_s[b]);
Packit 47f805
        int     dd, dd_n;
Packit 47f805
        FLOAT   x, ecb, avg_mask;
Packit 47f805
        FLOAT const masking_lower = gds->masking_lower[b] * gfc->sv_qnt.masking_lower;
Packit 47f805
Packit 47f805
        dd = mask_idx_s[kk];
Packit 47f805
        dd_n = 1;
Packit 47f805
        ecb = gds->s3[j] * eb[kk] * tab[mask_idx_s[kk]];
Packit 47f805
        ++j, ++kk;
Packit 47f805
        while (kk <= last) {
Packit 47f805
            dd += mask_idx_s[kk];
Packit 47f805
            dd_n += 1;
Packit 47f805
            x = gds->s3[j] * eb[kk] * tab[mask_idx_s[kk]];
Packit 47f805
            ecb = vbrpsy_mask_add(ecb, x, kk - b, delta);
Packit 47f805
            ++j, ++kk;
Packit 47f805
        }
Packit 47f805
        dd = (1 + 2 * dd) / (2 * dd_n);
Packit 47f805
        avg_mask = tab[dd] * 0.5f;
Packit 47f805
        ecb *= avg_mask;
Packit 47f805
#if 0                   /* we can do PRE ECHO control now here, or do it later */
Packit 47f805
        if (psv->blocktype_old[chn & 0x01] == SHORT_TYPE) {
Packit 47f805
            /* limit calculated threshold by even older granule */
Packit 47f805
            FLOAT const t1 = rpelev_s * psv->nb_s1[chn][b];
Packit 47f805
            FLOAT const t2 = rpelev2_s * psv->nb_s2[chn][b];
Packit 47f805
            FLOAT const tm = (t2 > 0) ? Min(ecb, t2) : ecb;
Packit 47f805
            thr[b] = (t1 > 0) ? NS_INTERP(Min(tm, t1), ecb, 0.6) : ecb;
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            /* limit calculated threshold by older granule */
Packit 47f805
            FLOAT const t1 = rpelev_s * psv->nb_s1[chn][b];
Packit 47f805
            thr[b] = (t1 > 0) ? NS_INTERP(Min(ecb, t1), ecb, 0.6) : ecb;
Packit 47f805
        }
Packit 47f805
#else /* we do it later */
Packit 47f805
        thr[b] = ecb;
Packit 47f805
#endif
Packit 47f805
        psv->nb_s2[chn][b] = psv->nb_s1[chn][b];
Packit 47f805
        psv->nb_s1[chn][b] = ecb;
Packit 47f805
        {
Packit 47f805
            /*  if THR exceeds EB, the quantization routines will take the difference
Packit 47f805
             *  from other bands. in case of strong tonal samples (tonaltest.wav)
Packit 47f805
             *  this leads to heavy distortions. that's why we limit THR here.
Packit 47f805
             */
Packit 47f805
            x = max[b];
Packit 47f805
            x *= gds->minval[b];
Packit 47f805
            x *= avg_mask;
Packit 47f805
            if (thr[b] > x) {
Packit 47f805
                thr[b] = x;
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
        if (masking_lower > 1) {
Packit 47f805
            thr[b] *= masking_lower;
Packit 47f805
        }
Packit 47f805
        if (thr[b] > eb[b]) {
Packit 47f805
            thr[b] = eb[b];
Packit 47f805
        }
Packit 47f805
        if (masking_lower < 1) {
Packit 47f805
            thr[b] *= masking_lower;
Packit 47f805
        }
Packit 47f805
Packit 47f805
        assert(thr[b] >= 0);
Packit 47f805
    }
Packit 47f805
    for (; b < CBANDS; ++b) {
Packit 47f805
        eb[b] = 0;
Packit 47f805
        thr[b] = 0;
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
static void
Packit 47f805
vbrpsy_compute_masking_l(lame_internal_flags * gfc, const FLOAT fftenergy[HBLKSIZE],
Packit 47f805
                         FLOAT eb_l[CBANDS], FLOAT thr[CBANDS], int chn)
Packit 47f805
{
Packit 47f805
    PsyStateVar_t *const psv = &gfc->sv_psy;
Packit 47f805
    PsyConst_CB2SB_t const *const gdl = &gfc->cd_psy->l;
Packit 47f805
    FLOAT   max[CBANDS], avg[CBANDS];
Packit 47f805
    unsigned char mask_idx_l[CBANDS + 2];
Packit 47f805
    int     k, b;
Packit 47f805
Packit 47f805
 /*********************************************************************
Packit 47f805
    *    Calculate the energy and the tonality of each partition.
Packit 47f805
 *********************************************************************/
Packit 47f805
    calc_energy(gdl, fftenergy, eb_l, max, avg);
Packit 47f805
    calc_mask_index_l(gfc, max, avg, mask_idx_l);
Packit 47f805
Packit 47f805
 /*********************************************************************
Packit 47f805
    *      convolve the partitioned energy and unpredictability
Packit 47f805
    *      with the spreading function, s3_l[b][k]
Packit 47f805
 ********************************************************************/
Packit 47f805
    k = 0;
Packit 47f805
    for (b = 0; b < gdl->npart; b++) {
Packit 47f805
        FLOAT   x, ecb, avg_mask, t;
Packit 47f805
        FLOAT const masking_lower = gdl->masking_lower[b] * gfc->sv_qnt.masking_lower;
Packit 47f805
        /* convolve the partitioned energy with the spreading function */
Packit 47f805
        int     kk = gdl->s3ind[b][0];
Packit 47f805
        int const last = gdl->s3ind[b][1];
Packit 47f805
        int const delta = mask_add_delta(mask_idx_l[b]);
Packit 47f805
        int     dd = 0, dd_n = 0;
Packit 47f805
Packit 47f805
        dd = mask_idx_l[kk];
Packit 47f805
        dd_n += 1;
Packit 47f805
        ecb = gdl->s3[k] * eb_l[kk] * tab[mask_idx_l[kk]];
Packit 47f805
        ++k, ++kk;
Packit 47f805
        while (kk <= last) {
Packit 47f805
            dd += mask_idx_l[kk];
Packit 47f805
            dd_n += 1;
Packit 47f805
            x = gdl->s3[k] * eb_l[kk] * tab[mask_idx_l[kk]];
Packit 47f805
            t = vbrpsy_mask_add(ecb, x, kk - b, delta);
Packit 47f805
#if 0
Packit 47f805
            ecb += eb_l[kk];
Packit 47f805
            if (ecb > t) {
Packit 47f805
                ecb = t;
Packit 47f805
            }
Packit 47f805
#else
Packit 47f805
            ecb = t;
Packit 47f805
#endif
Packit 47f805
            ++k, ++kk;
Packit 47f805
        }
Packit 47f805
        dd = (1 + 2 * dd) / (2 * dd_n);
Packit 47f805
        avg_mask = tab[dd] * 0.5f;
Packit 47f805
        ecb *= avg_mask;
Packit 47f805
Packit 47f805
        /****   long block pre-echo control   ****/
Packit 47f805
        /* dont use long block pre-echo control if previous granule was 
Packit 47f805
         * a short block.  This is to avoid the situation:   
Packit 47f805
         * frame0:  quiet (very low masking)  
Packit 47f805
         * frame1:  surge  (triggers short blocks)
Packit 47f805
         * frame2:  regular frame.  looks like pre-echo when compared to 
Packit 47f805
         *          frame0, but all pre-echo was in frame1.
Packit 47f805
         */
Packit 47f805
        /* chn=0,1   L and R channels
Packit 47f805
           chn=2,3   S and M channels.
Packit 47f805
         */
Packit 47f805
        if (psv->blocktype_old[chn & 0x01] == SHORT_TYPE) {
Packit 47f805
            FLOAT const ecb_limit = rpelev * psv->nb_l1[chn][b];
Packit 47f805
            if (ecb_limit > 0) {
Packit 47f805
                thr[b] = Min(ecb, ecb_limit);
Packit 47f805
            }
Packit 47f805
            else {
Packit 47f805
                /* Robert 071209:
Packit 47f805
                   Because we don't calculate long block psy when we know a granule
Packit 47f805
                   should be of short blocks, we don't have any clue how the granule
Packit 47f805
                   before would have looked like as a long block. So we have to guess
Packit 47f805
                   a little bit for this END_TYPE block.
Packit 47f805
                   Most of the time we get away with this sloppyness. (fingers crossed :)
Packit 47f805
                   The speed increase is worth it.
Packit 47f805
                 */
Packit 47f805
                thr[b] = Min(ecb, eb_l[b] * NS_PREECHO_ATT2);
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            FLOAT   ecb_limit_2 = rpelev2 * psv->nb_l2[chn][b];
Packit 47f805
            FLOAT   ecb_limit_1 = rpelev * psv->nb_l1[chn][b];
Packit 47f805
            FLOAT   ecb_limit;
Packit 47f805
            if (ecb_limit_2 <= 0) {
Packit 47f805
                ecb_limit_2 = ecb;
Packit 47f805
            }
Packit 47f805
            if (ecb_limit_1 <= 0) {
Packit 47f805
                ecb_limit_1 = ecb;
Packit 47f805
            }
Packit 47f805
            if (psv->blocktype_old[chn & 0x01] == NORM_TYPE) {
Packit 47f805
                ecb_limit = Min(ecb_limit_1, ecb_limit_2);
Packit 47f805
            }
Packit 47f805
            else {
Packit 47f805
                ecb_limit = ecb_limit_1;
Packit 47f805
            }
Packit 47f805
            thr[b] = Min(ecb, ecb_limit);
Packit 47f805
        }
Packit 47f805
        psv->nb_l2[chn][b] = psv->nb_l1[chn][b];
Packit 47f805
        psv->nb_l1[chn][b] = ecb;
Packit 47f805
        {
Packit 47f805
            /*  if THR exceeds EB, the quantization routines will take the difference
Packit 47f805
             *  from other bands. in case of strong tonal samples (tonaltest.wav)
Packit 47f805
             *  this leads to heavy distortions. that's why we limit THR here.
Packit 47f805
             */
Packit 47f805
            x = max[b];
Packit 47f805
            x *= gdl->minval[b];
Packit 47f805
            x *= avg_mask;
Packit 47f805
            if (thr[b] > x) {
Packit 47f805
                thr[b] = x;
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
        if (masking_lower > 1) {
Packit 47f805
            thr[b] *= masking_lower;
Packit 47f805
        }
Packit 47f805
        if (thr[b] > eb_l[b]) {
Packit 47f805
            thr[b] = eb_l[b];
Packit 47f805
        }
Packit 47f805
        if (masking_lower < 1) {
Packit 47f805
            thr[b] *= masking_lower;
Packit 47f805
        }
Packit 47f805
        assert(thr[b] >= 0);
Packit 47f805
    }
Packit 47f805
    for (; b < CBANDS; ++b) {
Packit 47f805
        eb_l[b] = 0;
Packit 47f805
        thr[b] = 0;
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
static void
Packit 47f805
vbrpsy_compute_block_type(SessionConfig_t const *cfg, int *uselongblock)
Packit 47f805
{
Packit 47f805
    int     chn;
Packit 47f805
Packit 47f805
    if (cfg->short_blocks == short_block_coupled
Packit 47f805
        /* force both channels to use the same block type */
Packit 47f805
        /* this is necessary if the frame is to be encoded in ms_stereo.  */
Packit 47f805
        /* But even without ms_stereo, FhG  does this */
Packit 47f805
        && !(uselongblock[0] && uselongblock[1]))
Packit 47f805
        uselongblock[0] = uselongblock[1] = 0;
Packit 47f805
Packit 47f805
    for (chn = 0; chn < cfg->channels_out; chn++) {
Packit 47f805
        /* disable short blocks */
Packit 47f805
        if (cfg->short_blocks == short_block_dispensed) {
Packit 47f805
            uselongblock[chn] = 1;
Packit 47f805
        }
Packit 47f805
        if (cfg->short_blocks == short_block_forced) {
Packit 47f805
            uselongblock[chn] = 0;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
static void
Packit 47f805
vbrpsy_apply_block_type(PsyStateVar_t * psv, int nch, int const *uselongblock, int *blocktype_d)
Packit 47f805
{
Packit 47f805
    int     chn;
Packit 47f805
Packit 47f805
    /* update the blocktype of the previous granule, since it depends on what
Packit 47f805
     * happend in this granule */
Packit 47f805
    for (chn = 0; chn < nch; chn++) {
Packit 47f805
        int     blocktype = NORM_TYPE;
Packit 47f805
        /* disable short blocks */
Packit 47f805
Packit 47f805
        if (uselongblock[chn]) {
Packit 47f805
            /* no attack : use long blocks */
Packit 47f805
            assert(psv->blocktype_old[chn] != START_TYPE);
Packit 47f805
            if (psv->blocktype_old[chn] == SHORT_TYPE)
Packit 47f805
                blocktype = STOP_TYPE;
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            /* attack : use short blocks */
Packit 47f805
            blocktype = SHORT_TYPE;
Packit 47f805
            if (psv->blocktype_old[chn] == NORM_TYPE) {
Packit 47f805
                psv->blocktype_old[chn] = START_TYPE;
Packit 47f805
            }
Packit 47f805
            if (psv->blocktype_old[chn] == STOP_TYPE)
Packit 47f805
                psv->blocktype_old[chn] = SHORT_TYPE;
Packit 47f805
        }
Packit 47f805
Packit 47f805
        blocktype_d[chn] = psv->blocktype_old[chn]; /* value returned to calling program */
Packit 47f805
        psv->blocktype_old[chn] = blocktype; /* save for next call to l3psy_anal */
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
/*************************************************************** 
Packit 47f805
 * compute M/S thresholds from Johnston & Ferreira 1992 ICASSP paper
Packit 47f805
 ***************************************************************/
Packit 47f805
Packit 47f805
static void
Packit 47f805
vbrpsy_compute_MS_thresholds(const FLOAT eb[4][CBANDS], FLOAT thr[4][CBANDS],
Packit 47f805
                             const FLOAT cb_mld[CBANDS], const FLOAT ath_cb[CBANDS], FLOAT athlower,
Packit 47f805
                             FLOAT msfix, int n)
Packit 47f805
{
Packit 47f805
    FLOAT const msfix2 = msfix * 2.f;
Packit 47f805
    FLOAT   rside, rmid;
Packit 47f805
    int     b;
Packit 47f805
    for (b = 0; b < n; ++b) {
Packit 47f805
        FLOAT const ebM = eb[2][b];
Packit 47f805
        FLOAT const ebS = eb[3][b];
Packit 47f805
        FLOAT const thmL = thr[0][b];
Packit 47f805
        FLOAT const thmR = thr[1][b];
Packit 47f805
        FLOAT   thmM = thr[2][b];
Packit 47f805
        FLOAT   thmS = thr[3][b];
Packit 47f805
Packit 47f805
        /* use this fix if L & R masking differs by 2db or less */
Packit 47f805
        /* if db = 10*log10(x2/x1) < 2 */
Packit 47f805
        /* if (x2 < 1.58*x1) { */
Packit 47f805
        if (thmL <= 1.58f * thmR && thmR <= 1.58f * thmL) {
Packit 47f805
            FLOAT const mld_m = cb_mld[b] * ebS;
Packit 47f805
            FLOAT const mld_s = cb_mld[b] * ebM;
Packit 47f805
            FLOAT const tmp_m = Min(thmS, mld_m);
Packit 47f805
            FLOAT const tmp_s = Min(thmM, mld_s);
Packit 47f805
            rmid = Max(thmM, tmp_m);
Packit 47f805
            rside = Max(thmS, tmp_s);
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            rmid = thmM;
Packit 47f805
            rside = thmS;
Packit 47f805
        }
Packit 47f805
        if (msfix > 0.f) {
Packit 47f805
            /***************************************************************/
Packit 47f805
            /* Adjust M/S maskings if user set "msfix"                     */
Packit 47f805
            /***************************************************************/
Packit 47f805
            /* Naoki Shibata 2000 */
Packit 47f805
            FLOAT   thmLR, thmMS;
Packit 47f805
            FLOAT const ath = ath_cb[b] * athlower;
Packit 47f805
            FLOAT const tmp_l = Max(thmL, ath);
Packit 47f805
            FLOAT const tmp_r = Max(thmR, ath);
Packit 47f805
            thmLR = Min(tmp_l, tmp_r);
Packit 47f805
            thmM = Max(rmid, ath);
Packit 47f805
            thmS = Max(rside, ath);
Packit 47f805
            thmMS = thmM + thmS;
Packit 47f805
            if (thmMS > 0.f && (thmLR * msfix2) < thmMS) {
Packit 47f805
                FLOAT const f = thmLR * msfix2 / thmMS;
Packit 47f805
                thmM *= f;
Packit 47f805
                thmS *= f;
Packit 47f805
                assert(thmMS > 0.f);
Packit 47f805
            }
Packit 47f805
            rmid = Min(thmM, rmid);
Packit 47f805
            rside = Min(thmS, rside);
Packit 47f805
        }
Packit 47f805
        if (rmid > ebM) {
Packit 47f805
            rmid = ebM;
Packit 47f805
        }
Packit 47f805
        if (rside > ebS) {
Packit 47f805
            rside = ebS;
Packit 47f805
        }
Packit 47f805
        thr[2][b] = rmid;
Packit 47f805
        thr[3][b] = rside;
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
/*
Packit 47f805
 * NOTE: the bitrate reduction from the inter-channel masking effect is low
Packit 47f805
 * compared to the chance of getting annyoing artefacts. L3psycho_anal_vbr does
Packit 47f805
 * not use this feature. (Robert 071216)
Packit 47f805
*/
Packit 47f805
Packit 47f805
int
Packit 47f805
L3psycho_anal_vbr(lame_internal_flags * gfc,
Packit 47f805
                  const sample_t * const buffer[2], int gr_out,
Packit 47f805
                  III_psy_ratio masking_ratio[2][2],
Packit 47f805
                  III_psy_ratio masking_MS_ratio[2][2],
Packit 47f805
                  FLOAT percep_entropy[2], FLOAT percep_MS_entropy[2],
Packit 47f805
                  FLOAT energy[4], int blocktype_d[2])
Packit 47f805
{
Packit 47f805
    SessionConfig_t const *const cfg = &gfc->cfg;
Packit 47f805
    PsyStateVar_t *const psv = &gfc->sv_psy;
Packit 47f805
    PsyConst_CB2SB_t const *const gdl = &gfc->cd_psy->l;
Packit 47f805
    PsyConst_CB2SB_t const *const gds = &gfc->cd_psy->s;
Packit 47f805
    plotting_data *plt = cfg->analysis ? gfc->pinfo : 0;
Packit 47f805
Packit 47f805
    III_psy_xmin last_thm[4];
Packit 47f805
Packit 47f805
    /* fft and energy calculation   */
Packit 47f805
    FLOAT(*wsamp_l)[BLKSIZE];
Packit 47f805
    FLOAT(*wsamp_s)[3][BLKSIZE_s];
Packit 47f805
    FLOAT   fftenergy[HBLKSIZE];
Packit 47f805
    FLOAT   fftenergy_s[3][HBLKSIZE_s];
Packit 47f805
    FLOAT   wsamp_L[2][BLKSIZE];
Packit 47f805
    FLOAT   wsamp_S[2][3][BLKSIZE_s];
Packit 47f805
    FLOAT   eb[4][CBANDS], thr[4][CBANDS];
Packit 47f805
Packit 47f805
    FLOAT   sub_short_factor[4][3];
Packit 47f805
    FLOAT   thmm;
Packit 47f805
    FLOAT const pcfact = 0.6f;
Packit 47f805
    FLOAT const ath_factor =
Packit 47f805
        (cfg->msfix > 0.f) ? (cfg->ATH_offset_factor * gfc->ATH->adjust_factor) : 1.f;
Packit 47f805
Packit 47f805
    const   FLOAT(*const_eb)[CBANDS] = (const FLOAT(*)[CBANDS]) eb;
Packit 47f805
    const   FLOAT(*const_fftenergy_s)[HBLKSIZE_s] = (const FLOAT(*)[HBLKSIZE_s]) fftenergy_s;
Packit 47f805
Packit 47f805
    /* block type  */
Packit 47f805
    int     ns_attacks[4][4] = { {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0} };
Packit 47f805
    int     uselongblock[2];
Packit 47f805
Packit 47f805
    /* usual variables like loop indices, etc..    */
Packit 47f805
    int     chn, sb, sblock;
Packit 47f805
Packit 47f805
    /* chn=2 and 3 = Mid and Side channels */
Packit 47f805
    int const n_chn_psy = (cfg->mode == JOINT_STEREO) ? 4 : cfg->channels_out;
Packit 47f805
Packit 47f805
    memcpy(&last_thm[0], &psv->thm[0], sizeof(last_thm));
Packit 47f805
Packit 47f805
    vbrpsy_attack_detection(gfc, buffer, gr_out, masking_ratio, masking_MS_ratio, energy,
Packit 47f805
                            sub_short_factor, ns_attacks, uselongblock);
Packit 47f805
Packit 47f805
    vbrpsy_compute_block_type(cfg, uselongblock);
Packit 47f805
Packit 47f805
    /* LONG BLOCK CASE */
Packit 47f805
    {
Packit 47f805
        for (chn = 0; chn < n_chn_psy; chn++) {
Packit 47f805
            int const ch01 = chn & 0x01;
Packit 47f805
Packit 47f805
            wsamp_l = wsamp_L + ch01;
Packit 47f805
            vbrpsy_compute_fft_l(gfc, buffer, chn, gr_out, fftenergy, wsamp_l);
Packit 47f805
            vbrpsy_compute_loudness_approximation_l(gfc, gr_out, chn, fftenergy);
Packit 47f805
            vbrpsy_compute_masking_l(gfc, fftenergy, eb[chn], thr[chn], chn);
Packit 47f805
        }
Packit 47f805
        if (cfg->mode == JOINT_STEREO) {
Packit 47f805
            if ((uselongblock[0] + uselongblock[1]) == 2) {
Packit 47f805
                vbrpsy_compute_MS_thresholds(const_eb, thr, gdl->mld_cb, gfc->ATH->cb_l,
Packit 47f805
                                             ath_factor, cfg->msfix, gdl->npart);
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
        /* TODO: apply adaptive ATH masking here ?? */
Packit 47f805
        for (chn = 0; chn < n_chn_psy; chn++) {
Packit 47f805
            convert_partition2scalefac_l(gfc, eb[chn], thr[chn], chn);
Packit 47f805
            convert_partition2scalefac_l_to_s(gfc, eb[chn], thr[chn], chn);
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    /* SHORT BLOCKS CASE */
Packit 47f805
    {
Packit 47f805
        int const force_short_block_calc = gfc->cd_psy->force_short_block_calc;
Packit 47f805
        for (sblock = 0; sblock < 3; sblock++) {
Packit 47f805
            for (chn = 0; chn < n_chn_psy; ++chn) {
Packit 47f805
                int const ch01 = chn & 0x01;
Packit 47f805
                if (uselongblock[ch01] && !force_short_block_calc) {
Packit 47f805
                    vbrpsy_skip_masking_s(gfc, chn, sblock);
Packit 47f805
                }
Packit 47f805
                else {
Packit 47f805
                    /* compute masking thresholds for short blocks */
Packit 47f805
                    wsamp_s = wsamp_S + ch01;
Packit 47f805
                    vbrpsy_compute_fft_s(gfc, buffer, chn, sblock, fftenergy_s, wsamp_s);
Packit 47f805
                    vbrpsy_compute_masking_s(gfc, const_fftenergy_s, eb[chn], thr[chn], chn,
Packit 47f805
                                             sblock);
Packit 47f805
                }
Packit 47f805
            }
Packit 47f805
            if (cfg->mode == JOINT_STEREO) {
Packit 47f805
                if ((uselongblock[0] + uselongblock[1]) == 0) {
Packit 47f805
                    vbrpsy_compute_MS_thresholds(const_eb, thr, gds->mld_cb, gfc->ATH->cb_s,
Packit 47f805
                                                 ath_factor, cfg->msfix, gds->npart);
Packit 47f805
                }
Packit 47f805
            }
Packit 47f805
            /* TODO: apply adaptive ATH masking here ?? */
Packit 47f805
            for (chn = 0; chn < n_chn_psy; ++chn) {
Packit 47f805
                int const ch01 = chn & 0x01;
Packit 47f805
                if (!uselongblock[ch01] || force_short_block_calc) {
Packit 47f805
                    convert_partition2scalefac_s(gfc, eb[chn], thr[chn], chn, sblock);
Packit 47f805
                }
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
Packit 47f805
        /****   short block pre-echo control   ****/
Packit 47f805
        for (chn = 0; chn < n_chn_psy; chn++) {
Packit 47f805
            for (sb = 0; sb < SBMAX_s; sb++) {
Packit 47f805
                FLOAT   new_thmm[3], prev_thm, t1, t2;
Packit 47f805
                for (sblock = 0; sblock < 3; sblock++) {
Packit 47f805
                    thmm = psv->thm[chn].s[sb][sblock];
Packit 47f805
                    thmm *= NS_PREECHO_ATT0;
Packit 47f805
Packit 47f805
                    t1 = t2 = thmm;
Packit 47f805
Packit 47f805
                    if (sblock > 0) {
Packit 47f805
                        prev_thm = new_thmm[sblock - 1];
Packit 47f805
                    }
Packit 47f805
                    else {
Packit 47f805
                        prev_thm = last_thm[chn].s[sb][2];
Packit 47f805
                    }
Packit 47f805
                    if (ns_attacks[chn][sblock] >= 2 || ns_attacks[chn][sblock + 1] == 1) {
Packit 47f805
                        t1 = NS_INTERP(prev_thm, thmm, NS_PREECHO_ATT1 * pcfact);
Packit 47f805
                    }
Packit 47f805
                    thmm = Min(t1, thmm);
Packit 47f805
                    if (ns_attacks[chn][sblock] == 1) {
Packit 47f805
                        t2 = NS_INTERP(prev_thm, thmm, NS_PREECHO_ATT2 * pcfact);
Packit 47f805
                    }
Packit 47f805
                    else if ((sblock == 0 && psv->last_attacks[chn] == 3)
Packit 47f805
                             || (sblock > 0 && ns_attacks[chn][sblock - 1] == 3)) { /* 2nd preceeding block */
Packit 47f805
                        switch (sblock) {
Packit 47f805
                        case 0:
Packit 47f805
                            prev_thm = last_thm[chn].s[sb][1];
Packit 47f805
                            break;
Packit 47f805
                        case 1:
Packit 47f805
                            prev_thm = last_thm[chn].s[sb][2];
Packit 47f805
                            break;
Packit 47f805
                        case 2:
Packit 47f805
                            prev_thm = new_thmm[0];
Packit 47f805
                            break;
Packit 47f805
                        }
Packit 47f805
                        t2 = NS_INTERP(prev_thm, thmm, NS_PREECHO_ATT2 * pcfact);
Packit 47f805
                    }
Packit 47f805
Packit 47f805
                    thmm = Min(t1, thmm);
Packit 47f805
                    thmm = Min(t2, thmm);
Packit 47f805
Packit 47f805
                    /* pulse like signal detection for fatboy.wav and so on */
Packit 47f805
                    thmm *= sub_short_factor[chn][sblock];
Packit 47f805
Packit 47f805
                    new_thmm[sblock] = thmm;
Packit 47f805
                }
Packit 47f805
                for (sblock = 0; sblock < 3; sblock++) {
Packit 47f805
                    psv->thm[chn].s[sb][sblock] = new_thmm[sblock];
Packit 47f805
                }
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    for (chn = 0; chn < n_chn_psy; chn++) {
Packit 47f805
        psv->last_attacks[chn] = ns_attacks[chn][2];
Packit 47f805
    }
Packit 47f805
Packit 47f805
Packit 47f805
    /*************************************************************** 
Packit 47f805
    * determine final block type
Packit 47f805
    ***************************************************************/
Packit 47f805
    vbrpsy_apply_block_type(psv, cfg->channels_out, uselongblock, blocktype_d);
Packit 47f805
Packit 47f805
    /*********************************************************************
Packit 47f805
    * compute the value of PE to return ... no delay and advance
Packit 47f805
    *********************************************************************/
Packit 47f805
    for (chn = 0; chn < n_chn_psy; chn++) {
Packit 47f805
        FLOAT  *ppe;
Packit 47f805
        int     type;
Packit 47f805
        III_psy_ratio const *mr;
Packit 47f805
Packit 47f805
        if (chn > 1) {
Packit 47f805
            ppe = percep_MS_entropy - 2;
Packit 47f805
            type = NORM_TYPE;
Packit 47f805
            if (blocktype_d[0] == SHORT_TYPE || blocktype_d[1] == SHORT_TYPE)
Packit 47f805
                type = SHORT_TYPE;
Packit 47f805
            mr = &masking_MS_ratio[gr_out][chn - 2];
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            ppe = percep_entropy;
Packit 47f805
            type = blocktype_d[chn];
Packit 47f805
            mr = &masking_ratio[gr_out][chn];
Packit 47f805
        }
Packit 47f805
        if (type == SHORT_TYPE) {
Packit 47f805
            ppe[chn] = pecalc_s(mr, gfc->sv_qnt.masking_lower);
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            ppe[chn] = pecalc_l(mr, gfc->sv_qnt.masking_lower);
Packit 47f805
        }
Packit 47f805
Packit 47f805
        if (plt) {
Packit 47f805
            plt->pe[gr_out][chn] = ppe[chn];
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    return 0;
Packit 47f805
}
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
/* 
Packit 47f805
 *   The spreading function.  Values returned in units of energy
Packit 47f805
 */
Packit 47f805
static  FLOAT
Packit 47f805
s3_func(FLOAT bark)
Packit 47f805
{
Packit 47f805
    FLOAT   tempx, x, tempy, temp;
Packit 47f805
    tempx = bark;
Packit 47f805
    if (tempx >= 0)
Packit 47f805
        tempx *= 3;
Packit 47f805
    else
Packit 47f805
        tempx *= 1.5;
Packit 47f805
Packit 47f805
    if (tempx >= 0.5 && tempx <= 2.5) {
Packit 47f805
        temp = tempx - 0.5;
Packit 47f805
        x = 8.0 * (temp * temp - 2.0 * temp);
Packit 47f805
    }
Packit 47f805
    else
Packit 47f805
        x = 0.0;
Packit 47f805
    tempx += 0.474;
Packit 47f805
    tempy = 15.811389 + 7.5 * tempx - 17.5 * sqrt(1.0 + tempx * tempx);
Packit 47f805
Packit 47f805
    if (tempy <= -60.0)
Packit 47f805
        return 0.0;
Packit 47f805
Packit 47f805
    tempx = exp((x + tempy) * LN_TO_LOG10);
Packit 47f805
Packit 47f805
    /* Normalization.  The spreading function should be normalized so that:
Packit 47f805
       +inf
Packit 47f805
       /
Packit 47f805
       |  s3 [ bark ]  d(bark)   =  1
Packit 47f805
       /
Packit 47f805
       -inf
Packit 47f805
     */
Packit 47f805
    tempx /= .6609193;
Packit 47f805
    return tempx;
Packit 47f805
}
Packit 47f805
Packit 47f805
#if 0
Packit 47f805
static  FLOAT
Packit 47f805
norm_s3_func(void)
Packit 47f805
{
Packit 47f805
    double  lim_a = 0, lim_b = 0;
Packit 47f805
    double  x = 0, l, h;
Packit 47f805
    for (x = 0; s3_func(x) > 1e-20; x -= 1);
Packit 47f805
    l = x;
Packit 47f805
    h = 0;
Packit 47f805
    while (fabs(h - l) > 1e-12) {
Packit 47f805
        x = (h + l) / 2;
Packit 47f805
        if (s3_func(x) > 0) {
Packit 47f805
            h = x;
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            l = x;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    lim_a = l;
Packit 47f805
    for (x = 0; s3_func(x) > 1e-20; x += 1);
Packit 47f805
    l = 0;
Packit 47f805
    h = x;
Packit 47f805
    while (fabs(h - l) > 1e-12) {
Packit 47f805
        x = (h + l) / 2;
Packit 47f805
        if (s3_func(x) > 0) {
Packit 47f805
            l = x;
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            h = x;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    lim_b = h;
Packit 47f805
    {
Packit 47f805
        double  sum = 0;
Packit 47f805
        int const m = 1000;
Packit 47f805
        int     i;
Packit 47f805
        for (i = 0; i <= m; ++i) {
Packit 47f805
            double  x = lim_a + i * (lim_b - lim_a) / m;
Packit 47f805
            double  y = s3_func(x);
Packit 47f805
            sum += y;
Packit 47f805
        }
Packit 47f805
        {
Packit 47f805
            double  norm = (m + 1) / (sum * (lim_b - lim_a));
Packit 47f805
            /*printf( "norm = %lf\n",norm); */
Packit 47f805
            return norm;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
#endif
Packit 47f805
Packit 47f805
static  FLOAT
Packit 47f805
stereo_demask(double f)
Packit 47f805
{
Packit 47f805
    /* setup stereo demasking thresholds */
Packit 47f805
    /* formula reverse enginerred from plot in paper */
Packit 47f805
    double  arg = freq2bark(f);
Packit 47f805
    arg = (Min(arg, 15.5) / 15.5);
Packit 47f805
Packit 47f805
    return pow(10.0, 1.25 * (1 - cos(PI * arg)) - 2.5);
Packit 47f805
}
Packit 47f805
Packit 47f805
static void
Packit 47f805
init_numline(PsyConst_CB2SB_t * gd, FLOAT sfreq, int fft_size,
Packit 47f805
             int mdct_size, int sbmax, int const *scalepos)
Packit 47f805
{
Packit 47f805
    FLOAT   b_frq[CBANDS + 1];
Packit 47f805
    FLOAT const mdct_freq_frac = sfreq / (2.0f * mdct_size);
Packit 47f805
    FLOAT const deltafreq = fft_size / (2.0f * mdct_size);
Packit 47f805
    int     partition[HBLKSIZE] = { 0 };
Packit 47f805
    int     i, j, ni;
Packit 47f805
    int     sfb;
Packit 47f805
    sfreq /= fft_size;
Packit 47f805
    j = 0;
Packit 47f805
    ni = 0;
Packit 47f805
    /* compute numlines, the number of spectral lines in each partition band */
Packit 47f805
    /* each partition band should be about DELBARK wide. */
Packit 47f805
    for (i = 0; i < CBANDS; i++) {
Packit 47f805
        FLOAT   bark1;
Packit 47f805
        int     j2, nl;
Packit 47f805
        bark1 = freq2bark(sfreq * j);
Packit 47f805
Packit 47f805
        b_frq[i] = sfreq * j;
Packit 47f805
Packit 47f805
        for (j2 = j; freq2bark(sfreq * j2) - bark1 < DELBARK && j2 <= fft_size / 2; j2++);
Packit 47f805
Packit 47f805
        nl = j2 - j;
Packit 47f805
        gd->numlines[i] = nl;
Packit 47f805
        gd->rnumlines[i] = (nl > 0) ? (1.0f / nl) : 0;
Packit 47f805
Packit 47f805
        ni = i + 1;
Packit 47f805
Packit 47f805
        while (j < j2) {
Packit 47f805
            assert(j < HBLKSIZE);
Packit 47f805
            partition[j++] = i;
Packit 47f805
        }
Packit 47f805
        if (j > fft_size / 2) {
Packit 47f805
            j = fft_size / 2;
Packit 47f805
            ++i;
Packit 47f805
            break;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    assert(i < CBANDS);
Packit 47f805
    b_frq[i] = sfreq * j;
Packit 47f805
Packit 47f805
    gd->n_sb = sbmax;
Packit 47f805
    gd->npart = ni;
Packit 47f805
Packit 47f805
    {
Packit 47f805
        j = 0;
Packit 47f805
        for (i = 0; i < gd->npart; i++) {
Packit 47f805
            int const nl = gd->numlines[i];
Packit 47f805
            FLOAT const freq = sfreq * (j + nl / 2);
Packit 47f805
            gd->mld_cb[i] = stereo_demask(freq);
Packit 47f805
            j += nl;
Packit 47f805
        }
Packit 47f805
        for (; i < CBANDS; ++i) {
Packit 47f805
            gd->mld_cb[i] = 1;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    for (sfb = 0; sfb < sbmax; sfb++) {
Packit 47f805
        int     i1, i2, bo;
Packit 47f805
        int     start = scalepos[sfb];
Packit 47f805
        int     end = scalepos[sfb + 1];
Packit 47f805
Packit 47f805
        i1 = floor(.5 + deltafreq * (start - .5));
Packit 47f805
        if (i1 < 0)
Packit 47f805
            i1 = 0;
Packit 47f805
        i2 = floor(.5 + deltafreq * (end - .5));
Packit 47f805
Packit 47f805
        if (i2 > fft_size / 2)
Packit 47f805
            i2 = fft_size / 2;
Packit 47f805
Packit 47f805
        bo = partition[i2];
Packit 47f805
        gd->bm[sfb] = (partition[i1] + partition[i2]) / 2;
Packit 47f805
        gd->bo[sfb] = bo;
Packit 47f805
Packit 47f805
        /* calculate how much of this band belongs to current scalefactor band */
Packit 47f805
        {
Packit 47f805
            FLOAT const f_tmp = mdct_freq_frac * end;
Packit 47f805
            FLOAT   bo_w = (f_tmp - b_frq[bo]) / (b_frq[bo + 1] - b_frq[bo]);
Packit 47f805
            if (bo_w < 0) {
Packit 47f805
                bo_w = 0;
Packit 47f805
            }
Packit 47f805
            else {
Packit 47f805
                if (bo_w > 1) {
Packit 47f805
                    bo_w = 1;
Packit 47f805
                }
Packit 47f805
            }
Packit 47f805
            gd->bo_weight[sfb] = bo_w;
Packit 47f805
        }
Packit 47f805
        gd->mld[sfb] = stereo_demask(mdct_freq_frac * start);
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
static void
Packit 47f805
compute_bark_values(PsyConst_CB2SB_t const *gd, FLOAT sfreq, int fft_size,
Packit 47f805
                    FLOAT * bval, FLOAT * bval_width)
Packit 47f805
{
Packit 47f805
    /* compute bark values of each critical band */
Packit 47f805
    int     k, j = 0, ni = gd->npart;
Packit 47f805
    sfreq /= fft_size;
Packit 47f805
    for (k = 0; k < ni; k++) {
Packit 47f805
        int const w = gd->numlines[k];
Packit 47f805
        FLOAT   bark1, bark2;
Packit 47f805
Packit 47f805
        bark1 = freq2bark(sfreq * (j));
Packit 47f805
        bark2 = freq2bark(sfreq * (j + w - 1));
Packit 47f805
        bval[k] = .5 * (bark1 + bark2);
Packit 47f805
Packit 47f805
        bark1 = freq2bark(sfreq * (j - .5));
Packit 47f805
        bark2 = freq2bark(sfreq * (j + w - .5));
Packit 47f805
        bval_width[k] = bark2 - bark1;
Packit 47f805
        j += w;
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
static int
Packit 47f805
init_s3_values(FLOAT ** p, int (*s3ind)[2], int npart,
Packit 47f805
               FLOAT const *bval, FLOAT const *bval_width, FLOAT const *norm)
Packit 47f805
{
Packit 47f805
    FLOAT   s3[CBANDS][CBANDS];
Packit 47f805
    /* The s3 array is not linear in the bark scale.
Packit 47f805
     * bval[x] should be used to get the bark value.
Packit 47f805
     */
Packit 47f805
    int     i, j, k;
Packit 47f805
    int     numberOfNoneZero = 0;
Packit 47f805
Packit 47f805
    memset(&s3[0][0], 0, sizeof(s3));
Packit 47f805
Packit 47f805
    /* s[i][j], the value of the spreading function,
Packit 47f805
     * centered at band j (masker), for band i (maskee)
Packit 47f805
     *
Packit 47f805
     * i.e.: sum over j to spread into signal barkval=i
Packit 47f805
     * NOTE: i and j are used opposite as in the ISO docs
Packit 47f805
     */
Packit 47f805
    for (i = 0; i < npart; i++) {
Packit 47f805
        for (j = 0; j < npart; j++) {
Packit 47f805
            FLOAT   v = s3_func(bval[i] - bval[j]) * bval_width[j];
Packit 47f805
            s3[i][j] = v * norm[i];
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    for (i = 0; i < npart; i++) {
Packit 47f805
        for (j = 0; j < npart; j++) {
Packit 47f805
            if (s3[i][j] > 0.0f)
Packit 47f805
                break;
Packit 47f805
        }
Packit 47f805
        s3ind[i][0] = j;
Packit 47f805
Packit 47f805
        for (j = npart - 1; j > 0; j--) {
Packit 47f805
            if (s3[i][j] > 0.0f)
Packit 47f805
                break;
Packit 47f805
        }
Packit 47f805
        s3ind[i][1] = j;
Packit 47f805
        numberOfNoneZero += (s3ind[i][1] - s3ind[i][0] + 1);
Packit 47f805
    }
Packit 47f805
    *p = lame_calloc(FLOAT, numberOfNoneZero);
Packit 47f805
    if (!*p)
Packit 47f805
        return -1;
Packit 47f805
Packit 47f805
    k = 0;
Packit 47f805
    for (i = 0; i < npart; i++)
Packit 47f805
        for (j = s3ind[i][0]; j <= s3ind[i][1]; j++)
Packit 47f805
            (*p)[k++] = s3[i][j];
Packit 47f805
Packit 47f805
    return 0;
Packit 47f805
}
Packit 47f805
Packit 47f805
int
Packit 47f805
psymodel_init(lame_global_flags const *gfp)
Packit 47f805
{
Packit 47f805
    lame_internal_flags *const gfc = gfp->internal_flags;
Packit 47f805
    SessionConfig_t *const cfg = &gfc->cfg;
Packit 47f805
    PsyStateVar_t *const psv = &gfc->sv_psy;
Packit 47f805
    PsyConst_t *gd;
Packit 47f805
    int     i, j, b, sb, k;
Packit 47f805
    FLOAT   bvl_a = 13, bvl_b = 24;
Packit 47f805
    FLOAT   snr_l_a = 0, snr_l_b = 0;
Packit 47f805
    FLOAT   snr_s_a = -8.25, snr_s_b = -4.5;
Packit 47f805
Packit 47f805
    FLOAT   bval[CBANDS];
Packit 47f805
    FLOAT   bval_width[CBANDS];
Packit 47f805
    FLOAT   norm[CBANDS];
Packit 47f805
    FLOAT const sfreq = cfg->samplerate_out;
Packit 47f805
Packit 47f805
    FLOAT   xav = 10, xbv = 12;
Packit 47f805
    FLOAT const minval_low = (0.f - cfg->minval);
Packit 47f805
Packit 47f805
    if (gfc->cd_psy != 0) {
Packit 47f805
        return 0;
Packit 47f805
    }
Packit 47f805
    memset(norm, 0, sizeof(norm));
Packit 47f805
Packit 47f805
    gd = lame_calloc(PsyConst_t, 1);
Packit 47f805
    gfc->cd_psy = gd;
Packit 47f805
Packit 47f805
    gd->force_short_block_calc = gfp->experimentalZ;
Packit 47f805
Packit 47f805
    psv->blocktype_old[0] = psv->blocktype_old[1] = NORM_TYPE; /* the vbr header is long blocks */
Packit 47f805
Packit 47f805
    for (i = 0; i < 4; ++i) {
Packit 47f805
        for (j = 0; j < CBANDS; ++j) {
Packit 47f805
            psv->nb_l1[i][j] = 1e20;
Packit 47f805
            psv->nb_l2[i][j] = 1e20;
Packit 47f805
            psv->nb_s1[i][j] = psv->nb_s2[i][j] = 1.0;
Packit 47f805
        }
Packit 47f805
        for (sb = 0; sb < SBMAX_l; sb++) {
Packit 47f805
            psv->en[i].l[sb] = 1e20;
Packit 47f805
            psv->thm[i].l[sb] = 1e20;
Packit 47f805
        }
Packit 47f805
        for (j = 0; j < 3; ++j) {
Packit 47f805
            for (sb = 0; sb < SBMAX_s; sb++) {
Packit 47f805
                psv->en[i].s[sb][j] = 1e20;
Packit 47f805
                psv->thm[i].s[sb][j] = 1e20;
Packit 47f805
            }
Packit 47f805
            psv->last_attacks[i] = 0;
Packit 47f805
        }
Packit 47f805
        for (j = 0; j < 9; j++)
Packit 47f805
            psv->last_en_subshort[i][j] = 10.;
Packit 47f805
    }
Packit 47f805
Packit 47f805
Packit 47f805
    /* init. for loudness approx. -jd 2001 mar 27 */
Packit 47f805
    psv->loudness_sq_save[0] = psv->loudness_sq_save[1] = 0.0;
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
    /*************************************************************************
Packit 47f805
     * now compute the psychoacoustic model specific constants
Packit 47f805
     ************************************************************************/
Packit 47f805
    /* compute numlines, bo, bm, bval, bval_width, mld */
Packit 47f805
    init_numline(&gd->l, sfreq, BLKSIZE, 576, SBMAX_l, gfc->scalefac_band.l);
Packit 47f805
    assert(gd->l.npart < CBANDS);
Packit 47f805
    compute_bark_values(&gd->l, sfreq, BLKSIZE, bval, bval_width);
Packit 47f805
Packit 47f805
    /* compute the spreading function */
Packit 47f805
    for (i = 0; i < gd->l.npart; i++) {
Packit 47f805
        double  snr = snr_l_a;
Packit 47f805
        if (bval[i] >= bvl_a) {
Packit 47f805
            snr = snr_l_b * (bval[i] - bvl_a) / (bvl_b - bvl_a)
Packit 47f805
                + snr_l_a * (bvl_b - bval[i]) / (bvl_b - bvl_a);
Packit 47f805
        }
Packit 47f805
        norm[i] = pow(10.0, snr / 10.0);
Packit 47f805
    }
Packit 47f805
    i = init_s3_values(&gd->l.s3, gd->l.s3ind, gd->l.npart, bval, bval_width, norm);
Packit 47f805
    if (i)
Packit 47f805
        return i;
Packit 47f805
Packit 47f805
    /* compute long block specific values, ATH and MINVAL */
Packit 47f805
    j = 0;
Packit 47f805
    for (i = 0; i < gd->l.npart; i++) {
Packit 47f805
        double  x;
Packit 47f805
Packit 47f805
        /* ATH */
Packit 47f805
        x = FLOAT_MAX;
Packit 47f805
        for (k = 0; k < gd->l.numlines[i]; k++, j++) {
Packit 47f805
            FLOAT const freq = sfreq * j / (1000.0 * BLKSIZE);
Packit 47f805
            FLOAT   level;
Packit 47f805
            /* freq = Min(.1,freq); *//* ATH below 100 Hz constant, not further climbing */
Packit 47f805
            level = ATHformula(cfg, freq * 1000) - 20; /* scale to FFT units; returned value is in dB */
Packit 47f805
            level = pow(10., 0.1 * level); /* convert from dB -> energy */
Packit 47f805
            level *= gd->l.numlines[i];
Packit 47f805
            if (x > level)
Packit 47f805
                x = level;
Packit 47f805
        }
Packit 47f805
        gfc->ATH->cb_l[i] = x;
Packit 47f805
Packit 47f805
        /* MINVAL.
Packit 47f805
           For low freq, the strength of the masking is limited by minval
Packit 47f805
           this is an ISO MPEG1 thing, dont know if it is really needed */
Packit 47f805
        /* FIXME: it does work to reduce low-freq problems in S53-Wind-Sax
Packit 47f805
           and lead-voice samples, but introduces some 3 kbps bit bloat too.
Packit 47f805
           TODO: Further refinement of the shape of this hack.
Packit 47f805
         */
Packit 47f805
        x = 20.0 * (bval[i] / xav - 1.0);
Packit 47f805
        if (x > 6) {
Packit 47f805
            x = 30;
Packit 47f805
        }
Packit 47f805
        if (x < minval_low) {
Packit 47f805
            x = minval_low;
Packit 47f805
        }
Packit 47f805
        if (cfg->samplerate_out < 44000) {
Packit 47f805
            x = 30;
Packit 47f805
        }
Packit 47f805
        x -= 8.;
Packit 47f805
        gd->l.minval[i] = pow(10.0, x / 10.) * gd->l.numlines[i];
Packit 47f805
    }
Packit 47f805
Packit 47f805
    /************************************************************************
Packit 47f805
     * do the same things for short blocks
Packit 47f805
     ************************************************************************/
Packit 47f805
    init_numline(&gd->s, sfreq, BLKSIZE_s, 192, SBMAX_s, gfc->scalefac_band.s);
Packit 47f805
    assert(gd->s.npart < CBANDS);
Packit 47f805
    compute_bark_values(&gd->s, sfreq, BLKSIZE_s, bval, bval_width);
Packit 47f805
Packit 47f805
    /* SNR formula. short block is normalized by SNR. is it still right ? */
Packit 47f805
    j = 0;
Packit 47f805
    for (i = 0; i < gd->s.npart; i++) {
Packit 47f805
        double  x;
Packit 47f805
        double  snr = snr_s_a;
Packit 47f805
        if (bval[i] >= bvl_a) {
Packit 47f805
            snr = snr_s_b * (bval[i] - bvl_a) / (bvl_b - bvl_a)
Packit 47f805
                + snr_s_a * (bvl_b - bval[i]) / (bvl_b - bvl_a);
Packit 47f805
        }
Packit 47f805
        norm[i] = pow(10.0, snr / 10.0);
Packit 47f805
Packit 47f805
        /* ATH */
Packit 47f805
        x = FLOAT_MAX;
Packit 47f805
        for (k = 0; k < gd->s.numlines[i]; k++, j++) {
Packit 47f805
            FLOAT const freq = sfreq * j / (1000.0 * BLKSIZE_s);
Packit 47f805
            FLOAT   level;
Packit 47f805
            /* freq = Min(.1,freq); *//* ATH below 100 Hz constant, not further climbing */
Packit 47f805
            level = ATHformula(cfg, freq * 1000) - 20; /* scale to FFT units; returned value is in dB */
Packit 47f805
            level = pow(10., 0.1 * level); /* convert from dB -> energy */
Packit 47f805
            level *= gd->s.numlines[i];
Packit 47f805
            if (x > level)
Packit 47f805
                x = level;
Packit 47f805
        }
Packit 47f805
        gfc->ATH->cb_s[i] = x;
Packit 47f805
Packit 47f805
        /* MINVAL.
Packit 47f805
           For low freq, the strength of the masking is limited by minval
Packit 47f805
           this is an ISO MPEG1 thing, dont know if it is really needed */
Packit 47f805
        x = 7.0 * (bval[i] / xbv - 1.0);
Packit 47f805
        if (bval[i] > xbv) {
Packit 47f805
            x *= 1 + log(1 + x) * 3.1;
Packit 47f805
        }
Packit 47f805
        if (bval[i] < xbv) {
Packit 47f805
            x *= 1 + log(1 - x) * 2.3;
Packit 47f805
        }
Packit 47f805
        if (x > 6) {
Packit 47f805
            x = 30;
Packit 47f805
        }
Packit 47f805
        if (x < minval_low) {
Packit 47f805
            x = minval_low;
Packit 47f805
        }
Packit 47f805
        if (cfg->samplerate_out < 44000) {
Packit 47f805
            x = 30;
Packit 47f805
        }
Packit 47f805
        x -= 8;
Packit 47f805
        gd->s.minval[i] = pow(10.0, x / 10) * gd->s.numlines[i];
Packit 47f805
    }
Packit 47f805
Packit 47f805
    i = init_s3_values(&gd->s.s3, gd->s.s3ind, gd->s.npart, bval, bval_width, norm);
Packit 47f805
    if (i)
Packit 47f805
        return i;
Packit 47f805
Packit 47f805
Packit 47f805
    init_mask_add_max_values();
Packit 47f805
    init_fft(gfc);
Packit 47f805
Packit 47f805
    /* setup temporal masking */
Packit 47f805
    gd->decay = exp(-1.0 * LOG10 / (temporalmask_sustain_sec * sfreq / 192.0));
Packit 47f805
Packit 47f805
    {
Packit 47f805
        FLOAT   msfix;
Packit 47f805
        msfix = NS_MSFIX;
Packit 47f805
        if (cfg->use_safe_joint_stereo)
Packit 47f805
            msfix = 1.0;
Packit 47f805
        if (fabs(cfg->msfix) > 0.0)
Packit 47f805
            msfix = cfg->msfix;
Packit 47f805
        cfg->msfix = msfix;
Packit 47f805
Packit 47f805
        /* spread only from npart_l bands.  Normally, we use the spreading
Packit 47f805
         * function to convolve from npart_l down to npart_l bands 
Packit 47f805
         */
Packit 47f805
        for (b = 0; b < gd->l.npart; b++)
Packit 47f805
            if (gd->l.s3ind[b][1] > gd->l.npart - 1)
Packit 47f805
                gd->l.s3ind[b][1] = gd->l.npart - 1;
Packit 47f805
    }
Packit 47f805
Packit 47f805
    /*  prepare for ATH auto adjustment:
Packit 47f805
     *  we want to decrease the ATH by 12 dB per second
Packit 47f805
     */
Packit 47f805
#define  frame_duration (576. * cfg->mode_gr / sfreq)
Packit 47f805
    gfc->ATH->decay = pow(10., -12. / 10. * frame_duration);
Packit 47f805
    gfc->ATH->adjust_factor = 0.01; /* minimum, for leading low loudness */
Packit 47f805
    gfc->ATH->adjust_limit = 1.0; /* on lead, allow adjust up to maximum */
Packit 47f805
#undef  frame_duration
Packit 47f805
Packit 47f805
    assert(gd->l.bo[SBMAX_l - 1] <= gd->l.npart);
Packit 47f805
    assert(gd->s.bo[SBMAX_s - 1] <= gd->s.npart);
Packit 47f805
Packit 47f805
    if (cfg->ATHtype != -1) {
Packit 47f805
        /* compute equal loudness weights (eql_w) */
Packit 47f805
        FLOAT   freq;
Packit 47f805
        FLOAT const freq_inc = (FLOAT) cfg->samplerate_out / (FLOAT) (BLKSIZE);
Packit 47f805
        FLOAT   eql_balance = 0.0;
Packit 47f805
        freq = 0.0;
Packit 47f805
        for (i = 0; i < BLKSIZE / 2; ++i) {
Packit 47f805
            /* convert ATH dB to relative power (not dB) */
Packit 47f805
            /*  to determine eql_w */
Packit 47f805
            freq += freq_inc;
Packit 47f805
            gfc->ATH->eql_w[i] = 1. / pow(10, ATHformula(cfg, freq) / 10);
Packit 47f805
            eql_balance += gfc->ATH->eql_w[i];
Packit 47f805
        }
Packit 47f805
        eql_balance = 1.0 / eql_balance;
Packit 47f805
        for (i = BLKSIZE / 2; --i >= 0;) { /* scale weights */
Packit 47f805
            gfc->ATH->eql_w[i] *= eql_balance;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    {
Packit 47f805
        for (b = j = 0; b < gd->s.npart; ++b) {
Packit 47f805
            for (i = 0; i < gd->s.numlines[b]; ++i) {
Packit 47f805
                ++j;
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
        assert(j == 129);
Packit 47f805
        for (b = j = 0; b < gd->l.npart; ++b) {
Packit 47f805
            for (i = 0; i < gd->l.numlines[b]; ++i) {
Packit 47f805
                ++j;
Packit 47f805
            }
Packit 47f805
        }
Packit 47f805
        assert(j == 513);
Packit 47f805
    }
Packit 47f805
    /* short block attack threshold */
Packit 47f805
    {
Packit 47f805
        float   x = gfp->attackthre;
Packit 47f805
        float   y = gfp->attackthre_s;
Packit 47f805
        if (x < 0) {
Packit 47f805
            x = NSATTACKTHRE;
Packit 47f805
        }
Packit 47f805
        if (y < 0) {
Packit 47f805
            y = NSATTACKTHRE_S;
Packit 47f805
        }
Packit 47f805
        gd->attack_threshold[0] = gd->attack_threshold[1] = gd->attack_threshold[2] = x;
Packit 47f805
        gd->attack_threshold[3] = y;
Packit 47f805
    }
Packit 47f805
    {
Packit 47f805
        float   sk_s = -10.f, sk_l = -4.7f;
Packit 47f805
        static float const sk[] =
Packit 47f805
            { -7.4, -7.4, -7.4, -9.5, -7.4, -6.1, -5.5, -4.7, -4.7, -4.7, -4.7 };
Packit 47f805
        if (gfp->VBR_q < 4) {
Packit 47f805
            sk_l = sk_s = sk[0];
Packit 47f805
        }
Packit 47f805
        else {
Packit 47f805
            sk_l = sk_s = sk[gfp->VBR_q] + gfp->VBR_q_frac * (sk[gfp->VBR_q] - sk[gfp->VBR_q + 1]);
Packit 47f805
        }
Packit 47f805
        b = 0;
Packit 47f805
        for (; b < gd->s.npart; b++) {
Packit 47f805
            float   m = (float) (gd->s.npart - b) / gd->s.npart;
Packit 47f805
            gd->s.masking_lower[b] = powf(10.f, sk_s * m * 0.1f);
Packit 47f805
        }
Packit 47f805
        for (; b < CBANDS; ++b) {
Packit 47f805
            gd->s.masking_lower[b] = 1.f;
Packit 47f805
        }
Packit 47f805
        b = 0;
Packit 47f805
        for (; b < gd->l.npart; b++) {
Packit 47f805
            float   m = (float) (gd->l.npart - b) / gd->l.npart;
Packit 47f805
            gd->l.masking_lower[b] = powf(10.f, sk_l * m * 0.1f);
Packit 47f805
        }
Packit 47f805
        for (; b < CBANDS; ++b) {
Packit 47f805
            gd->l.masking_lower[b] = 1.f;
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    memcpy(&gd->l_to_s, &gd->l, sizeof(gd->l_to_s));
Packit 47f805
    init_numline(&gd->l_to_s, sfreq, BLKSIZE, 192, SBMAX_s, gfc->scalefac_band.s);
Packit 47f805
    return 0;
Packit 47f805
}