/* Apply presets
* Copyright 2002-2008 Gabriel Bouvigne
* Copyright 2007-2012 Robert Hegemann
*/
#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) lame_set_##opt(val); \
else if (!(fabs(float(lame_get_##opt() - def)) > 0)) lame_set_##opt(val);
#define SET__OPTION(opt, val, def) if (enforce) lame_set_##opt(val); \
else if (!(fabs(lame_get_##opt() - def) > 0)) lame_set_##opt(val);
#undef Min
#undef Max
static inline int min_int(int a, int b) {return a < b ? a : b;}
static inline int max_int(int a, int b) {return a > b ? a : b;}
struct vbr_presets_t{
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;
};
/* *INDENT-OFF* */
/* Switch mappings for VBR mode VBR_RH */
static const vbr_presets_t vbr_old_switch_map[] = {
/* q l 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}
};
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))
void lame_global_flags::apply_vbr_preset(int a,bool enforce) {
vbr_presets_t const *vbr_preset = get_vbr_preset(lame_get_VBR());
float x = 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);
lame_set_VBR_q(set->vbr_q);
SET_OPTION(quant_comp, set->quant_comp, -1);
SET_OPTION(quant_comp_short, set->quant_comp_s, -1);
if (set->expY) lame_set_experimentalY(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() == vbr_mt || lame_get_VBR() == vbr_mtrh) {
lame_set_ATHtype(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) {
lame_set_exp_nspsytune(lame_get_exp_nspsytune() | 2);
}
if (set->sfb21mod > 0) {
int const nsp = lame_get_exp_nspsytune();
int const val = (nsp >> 20) & 63;
if (!val) {
int const sf21mod = (set->sfb21mod << 20) | nsp;
lame_set_exp_nspsytune(sf21mod);
}
}
SET__OPTION(msfix, set->msfix, -1);
if (!enforce) {
VBR_q = a;
VBR_q_frac = x;
}
internal_flags->cfg.minval = set->minval;
{ /* take care of gain adjustments */
double const x = fabs(scale);
double const y = (x > 0.f) ? (10.f * log10(x)) : 0.f;
internal_flags->cfg.ATHfixpoint = set->ath_fixpoint - y;
}
}
int lame_global_flags::apply_abr_preset(int p, bool 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 = p;
r = nearestBitrateFullIndex(p);
(void) lame_set_VBR(vbr_abr);
(void) lame_set_VBR_mean_bitrate_kbps((actual_bitrate));
(void) lame_set_VBR_mean_bitrate_kbps(min_int(lame_get_VBR_mean_bitrate_kbps(), 320));
(void) lame_set_VBR_mean_bitrate_kbps(max_int(lame_get_VBR_mean_bitrate_kbps(), 8));
(void) lame_set_brate(lame_get_VBR_mean_bitrate_kbps());
/* parameters for which there is no proper set/get interface */
if (abr_switch_map[r].safejoint > 0)
(void) lame_set_exp_nspsytune(lame_get_exp_nspsytune() | 2); /* safejoint */
if (abr_switch_map[r].sfscale > 0)
(void) lame_set_sfscale(1);
SET_OPTION(quant_comp, abr_switch_map[r].quant_comp, -1);
SET_OPTION(quant_comp_short, abr_switch_map[r].quant_comp_s, -1);
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 */
set_scale(get_scale() * 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;
internal_flags->cfg.minval = 5. * (abr_switch_map[r].abr_kbps / 320.);
return p;
}
int lame_global_flags::apply_preset(int p, bool enforce) {
/*translate legacy presets */
switch (p) {
case R3MIX: {
p = V3;
lame_set_VBR(vbr_mtrh);
}break;
case MEDIUM:
case MEDIUM_FAST: {
p = V4;
lame_set_VBR(vbr_mtrh);
}break;
case STANDARD:
case STANDARD_FAST: {
p = V2;
lame_set_VBR(vbr_mtrh);
}break;
case EXTREME:
case EXTREME_FAST: {
p = V0;
lame_set_VBR(vbr_mtrh);
}break;
case INSANE: {
p = 320;
preset = p;
apply_abr_preset(p, enforce);
lame_set_VBR(vbr_off);
return p;
}
}
preset = p;
{
switch (p) {
case V9: apply_vbr_preset(9, enforce); return p;
case V8: apply_vbr_preset(8, enforce); return p;
case V7: apply_vbr_preset(7, enforce); return p;
case V6: apply_vbr_preset(6, enforce); return p;
case V5: apply_vbr_preset(5, enforce); return p;
case V4: apply_vbr_preset(4, enforce); return p;
case V3: apply_vbr_preset(3, enforce); return p;
case V2: apply_vbr_preset(2, enforce); return p;
case V1: apply_vbr_preset(1, enforce); return p;
case V0: apply_vbr_preset(0, enforce); return p;
}
}
if (8 <= p && p <= 320) {
return apply_abr_preset(p, enforce);
}
preset = 0; /*no corresponding preset found */
return p;
}
Detected encoding: ASCII (7 bit) | 2
|