summaryrefslogtreecommitdiff
path: root/apps/misc.c
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2022-11-22 04:10:35 +0000
committerAidan MacDonald <amachronic@protonmail.com>2023-01-22 21:19:57 +0000
commit5b27e2255a8bbb8645f089b8e721343bba5bd396 (patch)
treebd29ddf9d2a0c07b1541ad4bace7ff4aedcb3c14 /apps/misc.c
parent15c4447b6681cadba960aa9275592049afa96893 (diff)
downloadrockbox-5b27e2255a8bbb8645f089b8e721343bba5bd396.tar.gz
rockbox-5b27e2255a8bbb8645f089b8e721343bba5bd396.zip
Add perceptual volume adjustment
The perceived loudness change of a change in volume depends on the listening volume: at high volumes a 1 dB increment is noticeable, but at low volumes a larger increment is needed to get a comparable change in loudness. Perceptual volume adjustment accounts for this fact, and divides the hardware volume range into a number of steps. Each step changes the dB volume by a variable amount, with most of the steps concentrated at higher volumes. This makes it possible to sweep over the entire hardware volume range quickly, without losing the ability to finely adjust the volume at normal listening levels. Use "Volume Adjustment Mode" in the system settings menu to select perceptual volume mode. The number of steps used is controlled by "Number of Volume Steps". (Number of steps has no effect in direct adjustment mode.) It's still possible to set a specific dB volume level from the sound settings menu when perceptual volume is enabled, and perceptual volume does not affect the volume displayed by themes. Change-Id: I6f91fd3f7c5e2d323a914e47b5653033e92b4b3b
Diffstat (limited to 'apps/misc.c')
-rw-r--r--apps/misc.c107
1 files changed, 107 insertions, 0 deletions
diff --git a/apps/misc.c b/apps/misc.c
index fd840749cb..e10fceb9af 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -824,6 +824,113 @@ void setvol(void)
824 settings_save(); 824 settings_save();
825} 825}
826 826
827#ifdef HAVE_PERCEPTUAL_VOLUME
828static short norm_tab[MAX_NORM_VOLUME_STEPS+2];
829static int norm_tab_num_steps;
830static int norm_tab_size;
831
832static void update_norm_tab(void)
833{
834 const int lim = global_settings.volume_adjust_norm_steps;
835 if (lim == norm_tab_num_steps)
836 return;
837 norm_tab_num_steps = lim;
838
839 const int min = sound_min(SOUND_VOLUME);
840 const int max = sound_max(SOUND_VOLUME);
841 const int step = sound_steps(SOUND_VOLUME);
842
843 /* Ensure the table contains the minimum volume */
844 norm_tab[0] = min;
845 norm_tab_size = 1;
846
847 for (int i = 0; i < lim; ++i)
848 {
849 int vol = from_normalized_volume(i, min, max, lim);
850 int rem = vol % step;
851
852 vol -= rem;
853 if (abs(rem) > step/2)
854 vol += rem < 0 ? -step : step;
855
856 /* Add volume step, ignoring any duplicate entries that may
857 * occur due to rounding */
858 if (vol != norm_tab[norm_tab_size-1])
859 norm_tab[norm_tab_size++] = vol;
860 }
861
862 /* Ensure the table contains the maximum volume */
863 if (norm_tab[norm_tab_size-1] != max)
864 norm_tab[norm_tab_size++] = max;
865}
866
867void set_normalized_volume(int vol)
868{
869 update_norm_tab();
870
871 if (vol < 0)
872 vol = 0;
873 if (vol >= norm_tab_size)
874 vol = norm_tab_size - 1;
875
876 global_settings.volume = norm_tab[vol];
877}
878
879int get_normalized_volume(void)
880{
881 update_norm_tab();
882
883 int a = 0, b = norm_tab_size - 1;
884 while (a != b)
885 {
886 int i = (a + b + 1) / 2;
887 if (global_settings.volume < norm_tab[i])
888 b = i - 1;
889 else
890 a = i;
891 }
892
893 return a;
894}
895#else
896void set_normalized_volume(int vol)
897{
898 global_settings.volume = vol * sound_steps(SOUND_VOLUME);
899}
900
901int get_normalized_volume(void)
902{
903 return global_settings.volume / sound_steps(SOUND_VOLUME);
904}
905#endif
906
907void adjust_volume(int steps)
908{
909#ifdef HAVE_PERCEPTUAL_VOLUME
910 adjust_volume_ex(steps, global_settings.volume_adjust_mode);
911#else
912 adjust_volume_ex(steps, VOLUME_ADJUST_DIRECT);
913#endif
914}
915
916void adjust_volume_ex(int steps, enum volume_adjust_mode mode)
917{
918 switch (mode)
919 {
920 case VOLUME_ADJUST_PERCEPTUAL:
921#ifdef HAVE_PERCEPTUAL_VOLUME
922 set_normalized_volume(get_normalized_volume() + steps);
923 break;
924#endif
925 case VOLUME_ADJUST_DIRECT:
926 default:
927 global_settings.volume += steps * sound_steps(SOUND_VOLUME);
928 break;
929 }
930
931 setvol();
932}
933
827char* strrsplt(char* str, int c) 934char* strrsplt(char* str, int c)
828{ 935{
829 char* s = strrchr(str, c); 936 char* s = strrchr(str, c);