1 /*
2  *  TwoLAME: an optimized MPEG Audio Layer Two encoder
3  *
4  *  Copyright (C) 2001-2004 Michael Cheng
5  *  Copyright (C) 2004-2018 The TwoLAME Project
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Lesser General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2.1 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public
18  *  License along with this library; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22 
23 
24 #include <stdio.h>
25 #include <math.h>
26 
27 #include "twolame.h"
28 #include "common.h"
29 #include "ath.h"
30 
31 
32 /* freq in hz */
twolame_ath_db(FLOAT f,FLOAT value)33 FLOAT twolame_ath_db(FLOAT f, FLOAT value)
34 {
35     /* from Painter & Spanias modified by Gabriel Bouvigne to better fit the reality ath = 3.640 *
36        pow(f,-0.8) - 6.800 * exp(-0.6*pow(f-3.4,2.0)) + 6.000 * exp(-0.15*pow(f-8.7,2.0)) + 0.6*
37        0.001 * pow(f,4.0);
38 
39 
40        In the past LAME was using the Painter &Spanias formula. But we had some recurrent problems
41        with HF content. We measured real ATH values, and found the older formula to be inacurate in
42        the higher part. So we made this new formula and this solved most of HF problematic
43        testcases. The tradeoff is that in VBR mode it increases a lot the bitrate. */
44 
45 
46     /* this curve can be udjusted according to the VBR scale: it adjusts from something close to
47        Painter & Spanias on V9 up to Bouvigne's formula for V0. This way the VBR bitrate is more
48        balanced according to the -V value. */
49 
50     FLOAT ath;
51     FLOAT valueold = 0.0;
52 
53     if (f < -.3)
54         f = 3410;
55 
56     f /= 1000;                  // convert to khz
57     f = MAX(0.01, f);
58     f = MIN(18.0, f);
59 
60     ath = 3.640 * pow(f, -0.8)
61           - 6.800 * exp(-0.6 * pow(f - 3.4, 2.0))
62           + 6.000 * exp(-0.15 * pow(f - 8.7, 2.0))
63           + (0.6 + 0.04 * valueold) * 0.001 * pow(f, 4.0);
64 
65     /* MFC Feb 2003 I've changed the fudge technique on the code. The "-l [float]" value
66        raises/lowers the ATH by this many dB */
67     return (ath + value);
68 }
69 
70 
71 /* Convert ATH values from dB into energy values as required by the psycho model */
twolame_ath_energy(FLOAT freq,FLOAT value)72 FLOAT twolame_ath_energy(FLOAT freq, FLOAT value)
73 {
74     FLOAT db;
75     db = twolame_ath_db(freq, 0) + value;   // Originally: ath_db(freq,value)
76     /* The values in the standard, and from the ATH formula are in dB. In the psycho model we are
77        working in the energy domain. Hence the values that are in the absthr_X tables are not in
78        dB. This function converts from dB into the energy domain. As noted on the LAME mailing list
79        from years ago (MFC FIX find the reference), the absolute threhsold of hearing values in the
80        tables in the standard are dodgy - the ATH in the tables do not correspond to any previously
81        known values of the ATH. From ISO 11172 Tables D.4.x "A value of 0dB represents a level in
82        the absolute threshold calculation of 96dB below the energy of a sine wave of amplitude
83        32760." But I still don't know why the factor of 41.837375 is the value that it is. MFC Feb
84        2003 */
85     return (pow(10.0, (db + 41.837375) * 0.1));
86 }
87 
88 
89 /* Convert a frequency (in Hz) to a bark value
90    Taken from LAME. MFC Feb 2003
91    see for example "Zwicker: Psychoakustik, 1982; ISBN 3-540-11401-7 */
twolame_ath_freq2bark(FLOAT freq)92 FLOAT twolame_ath_freq2bark(FLOAT freq)
93 {
94     if (freq < 0)
95         freq = 0;
96     freq = freq * 0.001;
97     return 13.0 * atan(.76 * freq) + 3.5 * atan(freq * freq / (7.5 * 7.5));
98 }
99 
100 // vim:ts=4:sw=4:nowrap:
101