mirror of
				https://github.com/cookiengineer/audacity
				synced 2025-10-31 14:13:50 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			405 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			405 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * presets.c -- Apply presets
 | |
|  *
 | |
|  *	Copyright (c) 2002-2008 Gabriel Bouvigne
 | |
|  *	Copyright (c) 2007-2012 Robert Hegemann
 | |
|  *
 | |
|  * This library is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU Library General Public
 | |
|  * License as published by the Free Software Foundation; either
 | |
|  * version 2 of the License, or (at your option) any later version.
 | |
|  *
 | |
|  * This library is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|  * Library General Public License for more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU Library General Public
 | |
|  * License along with this library; if not, write to the Free Software
 | |
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 | |
|  */
 | |
| 
 | |
| 
 | |
| #ifdef HAVE_CONFIG_H
 | |
| # include <config.h>
 | |
| #endif
 | |
| 
 | |
| #include "lame.h"
 | |
| #include "machine.h"
 | |
| #include "set_get.h"
 | |
| #include "encoder.h"
 | |
| #include "util.h"
 | |
| #include "lame_global_flags.h"
 | |
| 
 | |
| #define SET_OPTION(opt, val, def) if (enforce) \
 | |
|     (void) lame_set_##opt(gfp, val); \
 | |
|     else if (!(fabs(lame_get_##opt(gfp) - def) > 0)) \
 | |
|     (void) lame_set_##opt(gfp, val);
 | |
| 
 | |
| #define SET__OPTION(opt, val, def) if (enforce) \
 | |
|     lame_set_##opt(gfp, val); \
 | |
|     else if (!(fabs(lame_get_##opt(gfp) - def) > 0)) \
 | |
|     lame_set_##opt(gfp, val);
 | |
| 
 | |
| #undef Min
 | |
| #undef Max
 | |
| 
 | |
| static inline int
 | |
| min_int(int a, int b)
 | |
| {
 | |
|     if (a < b) {
 | |
|         return a;
 | |
|     }
 | |
|     return b;
 | |
| }
 | |
| 
 | |
| static inline int
 | |
| max_int(int a, int b)
 | |
| {
 | |
|     if (a > b) {
 | |
|         return a;
 | |
|     }
 | |
|     return b;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| typedef struct {
 | |
|     int     vbr_q;
 | |
|     int     quant_comp;
 | |
|     int     quant_comp_s;
 | |
|     int     expY;
 | |
|     FLOAT   st_lrm;          /*short threshold */
 | |
|     FLOAT   st_s;
 | |
|     FLOAT   masking_adj;
 | |
|     FLOAT   masking_adj_short;
 | |
|     FLOAT   ath_lower;
 | |
|     FLOAT   ath_curve;
 | |
|     FLOAT   ath_sensitivity;
 | |
|     FLOAT   interch;
 | |
|     int     safejoint;
 | |
|     int     sfb21mod;
 | |
|     FLOAT   msfix;
 | |
|     FLOAT   minval;
 | |
|     FLOAT   ath_fixpoint;
 | |
| } vbr_presets_t;
 | |
| 
 | |
|     /* *INDENT-OFF* */
 | |
|     
 | |
|     /* Switch mappings for VBR mode VBR_RH */
 | |
|     static const vbr_presets_t vbr_old_switch_map[] = {
 | |
|     /*vbr_q  qcomp_l  qcomp_s  expY  st_lrm   st_s  mask adj_l  adj_s  ath_lower  ath_curve  ath_sens  interChR  safejoint sfb21mod  msfix */
 | |
|         {0,       9,       9,    0,   5.20, 125.0,      -4.2,   -6.3,       4.8,       1,          0,   0,              2,      21,  0.97, 5, 100},
 | |
|         {1,       9,       9,    0,   5.30, 125.0,      -3.6,   -5.6,       4.5,       1.5,        0,   0,              2,      21,  1.35, 5, 100},
 | |
|         {2,       9,       9,    0,   5.60, 125.0,      -2.2,   -3.5,       2.8,       2,          0,   0,              2,      21,  1.49, 5, 100},
 | |
|         {3,       9,       9,    1,   5.80, 130.0,      -1.8,   -2.8,       2.6,       3,         -4,   0,              2,      20,  1.64, 5, 100},
 | |
|         {4,       9,       9,    1,   6.00, 135.0,      -0.7,   -1.1,       1.1,       3.5,       -8,   0,              2,       0,  1.79, 5, 100},
 | |
|         {5,       9,       9,    1,   6.40, 140.0,       0.5,    0.4,      -7.5,       4,        -12,   0.0002,         0,       0,  1.95, 5, 100},
 | |
|         {6,       9,       9,    1,   6.60, 145.0,       0.67,   0.65,    -14.7,       6.5,      -19,   0.0004,         0,       0,  2.30, 5, 100},
 | |
|         {7,       9,       9,    1,   6.60, 145.0,       0.8,    0.75,    -19.7,       8,        -22,   0.0006,         0,       0,  2.70, 5, 100},
 | |
|         {8,       9,       9,    1,   6.60, 145.0,       1.2,    1.15,    -27.5,      10,        -23,   0.0007,         0,       0,  0,    5, 100},
 | |
|         {9,       9,       9,    1,   6.60, 145.0,       1.6,    1.6,     -36,        11,        -25,   0.0008,         0,       0,  0,    5, 100},
 | |
|         {10,      9,       9,    1,   6.60, 145.0,       2.0,    2.0,     -36,        12,        -25,   0.0008,         0,       0,  0,    5, 100}
 | |
|     };
 | |
|     
 | |
|     static const vbr_presets_t vbr_mt_psy_switch_map[] = {
 | |
|     /*vbr_q  qcomp_l  qcomp_s  expY  st_lrm   st_s  mask adj_l  adj_s  ath_lower  ath_curve  ath_sens  ---  safejoint sfb21mod  msfix */
 | |
|         {0,       9,       9,    0,   4.20,  25.0,      -6.8,   -6.8,       7.1,       1,          0,   0,         2,      31,  1.000,  5, 100},
 | |
|         {1,       9,       9,    0,   4.20,  25.0,      -4.8,   -4.8,       5.4,       1.4,       -1,   0,         2,      27,  1.122,  5,  98},
 | |
|         {2,       9,       9,    0,   4.20,  25.0,      -2.6,   -2.6,       3.7,       2.0,       -3,   0,         2,      23,  1.288,  5,  97},
 | |
|         {3,       9,       9,    1,   4.20,  25.0,      -1.6,   -1.6,       2.0,       2.0,       -5,   0,         2,      18,  1.479,  5,  96},
 | |
|         {4,       9,       9,    1,   4.20,  25.0,      -0.0,   -0.0,       0.0,       2.0,       -8,   0,         2,      12,  1.698,  5,  95},
 | |
|         {5,       9,       9,    1,   4.20,  25.0,       1.3,    1.3,      -6,         3.5,      -11,   0,         2,       8,  1.950,  5,  94.2},
 | |
| #if 0
 | |
|         {6,       9,       9,    1,   4.50, 100.0,       1.5,    1.5,     -24.0,       6.0,      -14,   0,         2,       4,  2.239,  3,  93.9},
 | |
|         {7,       9,       9,    1,   4.80, 200.0,       1.7,    1.7,     -28.0,       9.0,      -20,   0,         2,       0,  2.570,  1,  93.6},
 | |
| #else
 | |
|         {6,       9,       9,    1,   4.50, 100.0,       2.2,    2.3,     -12.0,       6.0,      -14,   0,         2,       4,  2.239,  3,  93.9},
 | |
|         {7,       9,       9,    1,   4.80, 200.0,       2.7,    2.7,     -18.0,       9.0,      -17,   0,         2,       0,  2.570,  1,  93.6},
 | |
| #endif
 | |
|         {8,       9,       9,    1,   5.30, 300.0,       2.8,    2.8,     -21.0,      10.0,      -23,   0.0002,    0,       0,  2.951,  0,  93.3},
 | |
|         {9,       9,       9,    1,   6.60, 300.0,       2.8,    2.8,     -23.0,      11.0,      -25,   0.0006,    0,       0,  3.388,  0,  93.3},
 | |
|         {10,      9,       9,    1,  25.00, 300.0,       2.8,    2.8,     -25.0,      12.0,      -27,   0.0025,    0,       0,  3.500,  0,  93.3}
 | |
|     };
 | |
| 
 | |
|     /* *INDENT-ON* */
 | |
| 
 | |
| static vbr_presets_t const*
 | |
| get_vbr_preset(int v)
 | |
| {
 | |
|     switch (v) {
 | |
|     case vbr_mtrh:
 | |
|     case vbr_mt:
 | |
|         return &vbr_mt_psy_switch_map[0];
 | |
|     default:
 | |
|         return &vbr_old_switch_map[0];
 | |
|     }
 | |
| }
 | |
| 
 | |
| #define NOOP(m) (void)p.m
 | |
| #define LERP(m) (p.m = p.m + x * (q.m - p.m))
 | |
| 
 | |
| static void
 | |
| apply_vbr_preset(lame_global_flags * gfp, int a, int enforce)
 | |
| {
 | |
|     vbr_presets_t const *vbr_preset = get_vbr_preset(lame_get_VBR(gfp));
 | |
|     float   x = gfp->VBR_q_frac;
 | |
|     vbr_presets_t p = vbr_preset[a];
 | |
|     vbr_presets_t q = vbr_preset[a + 1];
 | |
|     vbr_presets_t const *set = &p;
 | |
| 
 | |
|     NOOP(vbr_q);
 | |
|     NOOP(quant_comp);
 | |
|     NOOP(quant_comp_s);
 | |
|     NOOP(expY);
 | |
|     LERP(st_lrm);
 | |
|     LERP(st_s);
 | |
|     LERP(masking_adj);
 | |
|     LERP(masking_adj_short);
 | |
|     LERP(ath_lower);
 | |
|     LERP(ath_curve);
 | |
|     LERP(ath_sensitivity);
 | |
|     LERP(interch);
 | |
|     NOOP(safejoint);
 | |
|     LERP(sfb21mod);
 | |
|     LERP(msfix);
 | |
|     LERP(minval);
 | |
|     LERP(ath_fixpoint);
 | |
| 
 | |
|     (void) lame_set_VBR_q(gfp, set->vbr_q);
 | |
|     SET_OPTION(quant_comp, set->quant_comp, -1.0);
 | |
|     SET_OPTION(quant_comp_short, set->quant_comp_s, -1.0);
 | |
|     if (set->expY) {
 | |
|         (void) lame_set_experimentalY(gfp, set->expY);
 | |
|     }
 | |
|     SET_OPTION(short_threshold_lrm, set->st_lrm, -1);
 | |
|     SET_OPTION(short_threshold_s, set->st_s, -1);
 | |
|     SET_OPTION(maskingadjust, set->masking_adj, 0);
 | |
|     SET_OPTION(maskingadjust_short, set->masking_adj_short, 0);
 | |
|     if (lame_get_VBR(gfp) == vbr_mt || lame_get_VBR(gfp) == vbr_mtrh) {
 | |
|         lame_set_ATHtype(gfp, 5);
 | |
|     }
 | |
|     SET_OPTION(ATHlower, set->ath_lower, 0);
 | |
|     SET_OPTION(ATHcurve, set->ath_curve, -1);
 | |
|     SET_OPTION(athaa_sensitivity, set->ath_sensitivity, 0);
 | |
|     if (set->interch > 0) {
 | |
|         SET_OPTION(interChRatio, set->interch, -1);
 | |
|     }
 | |
| 
 | |
|     /* parameters for which there is no proper set/get interface */
 | |
|     if (set->safejoint > 0) {
 | |
|         (void) lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 2);
 | |
|     }
 | |
|     if (set->sfb21mod > 0) {
 | |
|         int const nsp = lame_get_exp_nspsytune(gfp);
 | |
|         int const val = (nsp >> 20) & 63;
 | |
|         if (val == 0) {
 | |
|             int const sf21mod = (set->sfb21mod << 20) | nsp;
 | |
|             (void) lame_set_exp_nspsytune(gfp, sf21mod);
 | |
|         }
 | |
|     }
 | |
|     SET__OPTION(msfix, set->msfix, -1);
 | |
| 
 | |
|     if (enforce == 0) {
 | |
|         gfp->VBR_q = a;
 | |
|         gfp->VBR_q_frac = x;
 | |
|     }
 | |
|     gfp->internal_flags->cfg.minval = set->minval;
 | |
|     {   /* take care of gain adjustments */
 | |
|         double const x = fabs(gfp->scale);
 | |
|         double const y = (x > 0.f) ? (10.f * log10(x)) : 0.f;
 | |
|         gfp->internal_flags->cfg.ATHfixpoint = set->ath_fixpoint - y;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static int
 | |
| apply_abr_preset(lame_global_flags * gfp, int preset, int enforce)
 | |
| {
 | |
|     typedef struct {
 | |
|         int     abr_kbps;
 | |
|         int     quant_comp;
 | |
|         int     quant_comp_s;
 | |
|         int     safejoint;
 | |
|         FLOAT   nsmsfix;
 | |
|         FLOAT   st_lrm;      /*short threshold */
 | |
|         FLOAT   st_s;
 | |
|         FLOAT   scale;
 | |
|         FLOAT   masking_adj;
 | |
|         FLOAT   ath_lower;
 | |
|         FLOAT   ath_curve;
 | |
|         FLOAT   interch;
 | |
|         int     sfscale;
 | |
|     } abr_presets_t;
 | |
| 
 | |
| 
 | |
|     /* *INDENT-OFF* */
 | |
| 
 | |
|     /* 
 | |
|      *  Switch mappings for ABR mode
 | |
|      */
 | |
|     const abr_presets_t abr_switch_map[] = {        
 | |
|     /* kbps  quant q_s safejoint nsmsfix st_lrm  st_s  scale   msk ath_lwr ath_curve  interch , sfscale */
 | |
|       {  8,     9,  9,        0,      0,  6.60,  145,  0.95,    0,  -30.0,     11,    0.0012,        1}, /*   8, impossible to use in stereo */
 | |
|       { 16,     9,  9,        0,      0,  6.60,  145,  0.95,    0,  -25.0,     11,    0.0010,        1}, /*  16 */
 | |
|       { 24,     9,  9,        0,      0,  6.60,  145,  0.95,    0,  -20.0,     11,    0.0010,        1}, /*  24 */
 | |
|       { 32,     9,  9,        0,      0,  6.60,  145,  0.95,    0,  -15.0,     11,    0.0010,        1}, /*  32 */
 | |
|       { 40,     9,  9,        0,      0,  6.60,  145,  0.95,    0,  -10.0,     11,    0.0009,        1}, /*  40 */
 | |
|       { 48,     9,  9,        0,      0,  6.60,  145,  0.95,    0,  -10.0,     11,    0.0009,        1}, /*  48 */
 | |
|       { 56,     9,  9,        0,      0,  6.60,  145,  0.95,    0,   -6.0,     11,    0.0008,        1}, /*  56 */
 | |
|       { 64,     9,  9,        0,      0,  6.60,  145,  0.95,    0,   -2.0,     11,    0.0008,        1}, /*  64 */
 | |
|       { 80,     9,  9,        0,      0,  6.60,  145,  0.95,    0,     .0,      8,    0.0007,        1}, /*  80 */
 | |
|       { 96,     9,  9,        0,   2.50,  6.60,  145,  0.95,    0,    1.0,      5.5,  0.0006,        1}, /*  96 */
 | |
|       {112,     9,  9,        0,   2.25,  6.60,  145,  0.95,    0,    2.0,      4.5,  0.0005,        1}, /* 112 */
 | |
|       {128,     9,  9,        0,   1.95,  6.40,  140,  0.95,    0,    3.0,      4,    0.0002,        1}, /* 128 */
 | |
|       {160,     9,  9,        1,   1.79,  6.00,  135,  0.95,   -2,    5.0,      3.5,  0,             1}, /* 160 */
 | |
|       {192,     9,  9,        1,   1.49,  5.60,  125,  0.97,   -4,    7.0,      3,    0,             0}, /* 192 */
 | |
|       {224,     9,  9,        1,   1.25,  5.20,  125,  0.98,   -6,    9.0,      2,    0,             0}, /* 224 */
 | |
|       {256,     9,  9,        1,   0.97,  5.20,  125,  1.00,   -8,   10.0,      1,    0,             0}, /* 256 */
 | |
|       {320,     9,  9,        1,   0.90,  5.20,  125,  1.00,  -10,   12.0,      0,    0,             0}  /* 320 */
 | |
|     };
 | |
| 
 | |
|     /* *INDENT-ON* */
 | |
| 
 | |
|     /* Variables for the ABR stuff */
 | |
|     int     r;
 | |
|     int     actual_bitrate = preset;
 | |
| 
 | |
|     r = nearestBitrateFullIndex(preset);
 | |
|     
 | |
|     (void) lame_set_VBR(gfp, vbr_abr);
 | |
|     (void) lame_set_VBR_mean_bitrate_kbps(gfp, (actual_bitrate));
 | |
|     (void) lame_set_VBR_mean_bitrate_kbps(gfp, min_int(lame_get_VBR_mean_bitrate_kbps(gfp), 320));
 | |
|     (void) lame_set_VBR_mean_bitrate_kbps(gfp, max_int(lame_get_VBR_mean_bitrate_kbps(gfp), 8));
 | |
|     (void) lame_set_brate(gfp, lame_get_VBR_mean_bitrate_kbps(gfp));
 | |
| 
 | |
| 
 | |
|     /* parameters for which there is no proper set/get interface */
 | |
|     if (abr_switch_map[r].safejoint > 0)
 | |
|         (void) lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 2); /* safejoint */
 | |
| 
 | |
|     if (abr_switch_map[r].sfscale > 0)
 | |
|         (void) lame_set_sfscale(gfp, 1);
 | |
| 
 | |
| 
 | |
|     SET_OPTION(quant_comp, abr_switch_map[r].quant_comp, -1.0);
 | |
|     SET_OPTION(quant_comp_short, abr_switch_map[r].quant_comp_s, -1.0);
 | |
| 
 | |
|     SET__OPTION(msfix, abr_switch_map[r].nsmsfix, -1);
 | |
| 
 | |
|     SET_OPTION(short_threshold_lrm, abr_switch_map[r].st_lrm, -1);
 | |
|     SET_OPTION(short_threshold_s, abr_switch_map[r].st_s, -1);
 | |
| 
 | |
|     /* ABR seems to have big problems with clipping, especially at low bitrates */
 | |
|     /* so we compensate for that here by using a scale value depending on bitrate */
 | |
|     lame_set_scale(gfp, lame_get_scale(gfp) * abr_switch_map[r].scale);
 | |
| 
 | |
|     SET_OPTION(maskingadjust, abr_switch_map[r].masking_adj, 0);
 | |
|     if (abr_switch_map[r].masking_adj > 0) {
 | |
|         SET_OPTION(maskingadjust_short, abr_switch_map[r].masking_adj * .9, 0);
 | |
|     }
 | |
|     else {
 | |
|         SET_OPTION(maskingadjust_short, abr_switch_map[r].masking_adj * 1.1, 0);
 | |
|     }
 | |
| 
 | |
| 
 | |
|     SET_OPTION(ATHlower, abr_switch_map[r].ath_lower, 0);
 | |
|     SET_OPTION(ATHcurve, abr_switch_map[r].ath_curve, -1);
 | |
| 
 | |
|     SET_OPTION(interChRatio, abr_switch_map[r].interch, -1);
 | |
| 
 | |
|     (void) abr_switch_map[r].abr_kbps;
 | |
| 
 | |
|     gfp->internal_flags->cfg.minval = 5. * (abr_switch_map[r].abr_kbps / 320.);
 | |
| 
 | |
|     return preset;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| int
 | |
| apply_preset(lame_global_flags * gfp, int preset, int enforce)
 | |
| {
 | |
|     /*translate legacy presets */
 | |
|     switch (preset) {
 | |
|     case R3MIX:
 | |
|         {
 | |
|             preset = V3;
 | |
|             (void) lame_set_VBR(gfp, vbr_mtrh);
 | |
|             break;
 | |
|         }
 | |
|     case MEDIUM:
 | |
|     case MEDIUM_FAST:
 | |
|         {
 | |
|             preset = V4;
 | |
|             (void) lame_set_VBR(gfp, vbr_mtrh);
 | |
|             break;
 | |
|         }
 | |
|     case STANDARD:
 | |
|     case STANDARD_FAST:
 | |
|         {
 | |
|             preset = V2;
 | |
|             (void) lame_set_VBR(gfp, vbr_mtrh);
 | |
|             break;
 | |
|         }
 | |
|     case EXTREME:
 | |
|     case EXTREME_FAST:
 | |
|         {
 | |
|             preset = V0;
 | |
|             (void) lame_set_VBR(gfp, vbr_mtrh);
 | |
|             break;
 | |
|         }
 | |
|     case INSANE:
 | |
|         {
 | |
|             preset = 320;
 | |
|             gfp->preset = preset;
 | |
|             (void) apply_abr_preset(gfp, preset, enforce);
 | |
|             lame_set_VBR(gfp, vbr_off);
 | |
|             return preset;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     gfp->preset = preset;
 | |
|     {
 | |
|         switch (preset) {
 | |
|         case V9:
 | |
|             apply_vbr_preset(gfp, 9, enforce);
 | |
|             return preset;
 | |
|         case V8:
 | |
|             apply_vbr_preset(gfp, 8, enforce);
 | |
|             return preset;
 | |
|         case V7:
 | |
|             apply_vbr_preset(gfp, 7, enforce);
 | |
|             return preset;
 | |
|         case V6:
 | |
|             apply_vbr_preset(gfp, 6, enforce);
 | |
|             return preset;
 | |
|         case V5:
 | |
|             apply_vbr_preset(gfp, 5, enforce);
 | |
|             return preset;
 | |
|         case V4:
 | |
|             apply_vbr_preset(gfp, 4, enforce);
 | |
|             return preset;
 | |
|         case V3:
 | |
|             apply_vbr_preset(gfp, 3, enforce);
 | |
|             return preset;
 | |
|         case V2:
 | |
|             apply_vbr_preset(gfp, 2, enforce);
 | |
|             return preset;
 | |
|         case V1:
 | |
|             apply_vbr_preset(gfp, 1, enforce);
 | |
|             return preset;
 | |
|         case V0:
 | |
|             apply_vbr_preset(gfp, 0, enforce);
 | |
|             return preset;
 | |
|         default:
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
|     if (8 <= preset && preset <= 320) {
 | |
|         return apply_abr_preset(gfp, preset, enforce);
 | |
|     }
 | |
| 
 | |
|     gfp->preset = 0;    /*no corresponding preset found */
 | |
|     return preset;
 | |
| }
 |