misc: fix issues with perceptual volume calculations

rockbox-gerrit-noreply--- via rockbox-cvs <[email protected]>
Newsgroups gmane.comp.systems.archos.rockbox.cvs
Message-ID <[email protected]>
commit 3f2ca2024544aca4a0dd78309fff115a75773091
Author: Aidan MacDonald <[email protected]>
Date:   Sun Feb 1 17:12:37 2026 +0000

    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

diff --git a/apps/misc.c b/apps/misc.c
index 39936f2b36..5c3d457d54 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -904,7 +904,7 @@ static void update_norm_tab(void)
     norm_tab[0] = min;
     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 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_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_mul(x,y) fp_mul((x), (y), NVOL_FRACBITS)
 #define nvol_exp10(x) fp_exp10((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)
 {
-    /*
-     * Alsamixer uses a linear scale for small ranges.
-     * Commented out so perceptual volume works as advertised on all targets.
-     */
-    /*
-    return max_vol - min_vol <= NVOL_MAX_LINEAR_DB_SCALE;
-    */
+    long factor = 600L << NVOL_FRACBITS;
+    long numdecimals = sound_numdecimals(SOUND_VOLUME);
 
-    (void)min_vol;
-    (void)max_vol;
-    return false;
+    if (numdecimals == 0)
+        factor /= 10;
+
+    /* 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 norm, min_norm;
+    long factor = get_nvol_factor();
 
     vol <<= NVOL_FRACBITS;
     min_vol <<= NVOL_FRACBITS;
     max_vol <<= NVOL_FRACBITS;
     max_norm <<= NVOL_FRACBITS;
 
-    if (use_linear_dB_scale(min_vol, max_vol))
-    {
-        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);
-    }
+    min_norm = nvol_exp10(nvol_div(min_vol - max_vol, factor));
+    norm = nvol_exp10(nvol_div(vol - max_vol, factor));
+    norm = nvol_div(norm - min_norm, NVOL_UNITY - min_norm);
 
     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 vol, min_norm;
+    long factor = get_nvol_factor();
 
     norm <<= 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);
 
-    if (use_linear_dB_scale(min_vol, max_vol))
-    {
-        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(nvol_log10(vol), NVOL_FACTOR) + max_vol;
-    }
+    min_norm = nvol_exp10(nvol_div(min_vol - max_vol, factor));
+    vol = nvol_mul(vol, NVOL_UNITY - min_norm) + min_norm;
+    vol = nvol_mul(nvol_log10(vol), factor) + max_vol;
 
     return vol >> NVOL_FRACBITS;
 }
-- 
rockbox-cvs mailing list
[email protected]
https://lists.haxx.se/mailman/listinfo/rockbox-cvs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.