mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-10-10 08:03:04 -04:00
misc: fix issues with perceptual volume calculations
The constant NVOL_FACTOR used in the calculations needs to be scaled if the target doesn't represent volumes in 1/10th dB units (ie. most targets). Using a wrong factor caused the results to be slightly "off", with wide steps between points on the upper end of the volume curve. Drop use_linear_dB_scale() because the magic constant involved has a similar problem (and we don't use this function anyway). Also, make sure to account for the guaranteed min/max points when generating the normalized volume table to avoid sometimes generating one or two extra volume steps very close to the min/max volumes. Change-Id: I5c15809a7306f14bb1befe6d29a5e2b5b0974eaa
This commit is contained in:
parent
ad9471be3b
commit
3f2ca20245
1 changed files with 20 additions and 35 deletions
51
apps/misc.c
51
apps/misc.c
|
|
@ -904,7 +904,7 @@ static void update_norm_tab(void)
|
||||||
norm_tab[0] = min;
|
norm_tab[0] = min;
|
||||||
norm_tab_size = 1;
|
norm_tab_size = 1;
|
||||||
|
|
||||||
for (int i = 0; i < lim; ++i)
|
for (int i = 1; i < lim - 1; ++i)
|
||||||
{
|
{
|
||||||
int vol = from_normalized_volume(i, min, max, lim);
|
int vol = from_normalized_volume(i, min, max, lim);
|
||||||
int rem = vol % step;
|
int rem = vol % step;
|
||||||
|
|
@ -1944,49 +1944,40 @@ int core_load_bmp(const char * filename, struct bitmap *bm, const int bmformat,
|
||||||
|
|
||||||
#define NVOL_FRACBITS 16
|
#define NVOL_FRACBITS 16
|
||||||
#define NVOL_UNITY (1L << NVOL_FRACBITS)
|
#define NVOL_UNITY (1L << NVOL_FRACBITS)
|
||||||
#define NVOL_FACTOR (600L << NVOL_FRACBITS)
|
|
||||||
|
|
||||||
#define NVOL_MAX_LINEAR_DB_SCALE (240L << NVOL_FRACBITS)
|
|
||||||
|
|
||||||
#define nvol_div(x,y) fp_div((x), (y), NVOL_FRACBITS)
|
#define nvol_div(x,y) fp_div((x), (y), NVOL_FRACBITS)
|
||||||
#define nvol_mul(x,y) fp_mul((x), (y), NVOL_FRACBITS)
|
#define nvol_mul(x,y) fp_mul((x), (y), NVOL_FRACBITS)
|
||||||
#define nvol_exp10(x) fp_exp10((x), NVOL_FRACBITS)
|
#define nvol_exp10(x) fp_exp10((x), NVOL_FRACBITS)
|
||||||
#define nvol_log10(x) fp_log10((x), NVOL_FRACBITS)
|
#define nvol_log10(x) fp_log10((x), NVOL_FRACBITS)
|
||||||
|
|
||||||
static bool use_linear_dB_scale(long min_vol, long max_vol)
|
static long get_nvol_factor(void)
|
||||||
{
|
{
|
||||||
/*
|
long factor = 600L << NVOL_FRACBITS;
|
||||||
* Alsamixer uses a linear scale for small ranges.
|
long numdecimals = sound_numdecimals(SOUND_VOLUME);
|
||||||
* Commented out so perceptual volume works as advertised on all targets.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
return max_vol - min_vol <= NVOL_MAX_LINEAR_DB_SCALE;
|
|
||||||
*/
|
|
||||||
|
|
||||||
(void)min_vol;
|
if (numdecimals == 0)
|
||||||
(void)max_vol;
|
factor /= 10;
|
||||||
return false;
|
|
||||||
|
/* nothing *actually* needs this, but: */
|
||||||
|
while (numdecimals > 1)
|
||||||
|
factor *= 10;
|
||||||
|
|
||||||
|
return factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
long to_normalized_volume(long vol, long min_vol, long max_vol, long max_norm)
|
long to_normalized_volume(long vol, long min_vol, long max_vol, long max_norm)
|
||||||
{
|
{
|
||||||
long norm, min_norm;
|
long norm, min_norm;
|
||||||
|
long factor = get_nvol_factor();
|
||||||
|
|
||||||
vol <<= NVOL_FRACBITS;
|
vol <<= NVOL_FRACBITS;
|
||||||
min_vol <<= NVOL_FRACBITS;
|
min_vol <<= NVOL_FRACBITS;
|
||||||
max_vol <<= NVOL_FRACBITS;
|
max_vol <<= NVOL_FRACBITS;
|
||||||
max_norm <<= NVOL_FRACBITS;
|
max_norm <<= NVOL_FRACBITS;
|
||||||
|
|
||||||
if (use_linear_dB_scale(min_vol, max_vol))
|
min_norm = nvol_exp10(nvol_div(min_vol - max_vol, factor));
|
||||||
{
|
norm = nvol_exp10(nvol_div(vol - max_vol, factor));
|
||||||
norm = nvol_div(vol - min_vol, max_vol - min_vol);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
min_norm = nvol_exp10(nvol_div(min_vol - max_vol, NVOL_FACTOR));
|
|
||||||
norm = nvol_exp10(nvol_div(vol - max_vol, NVOL_FACTOR));
|
|
||||||
norm = nvol_div(norm - min_norm, NVOL_UNITY - min_norm);
|
norm = nvol_div(norm - min_norm, NVOL_UNITY - min_norm);
|
||||||
}
|
|
||||||
|
|
||||||
return nvol_mul(norm, max_norm) >> NVOL_FRACBITS;
|
return nvol_mul(norm, max_norm) >> NVOL_FRACBITS;
|
||||||
}
|
}
|
||||||
|
|
@ -1994,6 +1985,7 @@ long to_normalized_volume(long vol, long min_vol, long max_vol, long max_norm)
|
||||||
long from_normalized_volume(long norm, long min_vol, long max_vol, long max_norm)
|
long from_normalized_volume(long norm, long min_vol, long max_vol, long max_norm)
|
||||||
{
|
{
|
||||||
long vol, min_norm;
|
long vol, min_norm;
|
||||||
|
long factor = get_nvol_factor();
|
||||||
|
|
||||||
norm <<= NVOL_FRACBITS;
|
norm <<= NVOL_FRACBITS;
|
||||||
min_vol <<= NVOL_FRACBITS;
|
min_vol <<= NVOL_FRACBITS;
|
||||||
|
|
@ -2002,16 +1994,9 @@ long from_normalized_volume(long norm, long min_vol, long max_vol, long max_norm
|
||||||
|
|
||||||
vol = nvol_div(norm, max_norm);
|
vol = nvol_div(norm, max_norm);
|
||||||
|
|
||||||
if (use_linear_dB_scale(min_vol, max_vol))
|
min_norm = nvol_exp10(nvol_div(min_vol - max_vol, factor));
|
||||||
{
|
|
||||||
vol = nvol_mul(vol, max_vol - min_vol) + min_vol;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
min_norm = nvol_exp10(nvol_div(min_vol - max_vol, NVOL_FACTOR));
|
|
||||||
vol = nvol_mul(vol, NVOL_UNITY - min_norm) + min_norm;
|
vol = nvol_mul(vol, NVOL_UNITY - min_norm) + min_norm;
|
||||||
vol = nvol_mul(nvol_log10(vol), NVOL_FACTOR) + max_vol;
|
vol = nvol_mul(nvol_log10(vol), factor) + max_vol;
|
||||||
}
|
|
||||||
|
|
||||||
return vol >> NVOL_FRACBITS;
|
return vol >> NVOL_FRACBITS;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue