]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/menu/xonotic/slider_decibels.qc
Merge branch 'terencehill/menu_optimization' into 'master'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / xonotic / slider_decibels.qc
1 #ifndef SLIDER_DECIBELS_H
2 #define SLIDER_DECIBELS_H
3 #include "slider.qc"
4 CLASS(XonoticDecibelsSlider, XonoticSlider)
5         METHOD(XonoticDecibelsSlider, loadCvars, void(entity));
6         METHOD(XonoticDecibelsSlider, saveCvars, void(entity));
7         METHOD(XonoticDecibelsSlider, valueToText, string(entity, float));
8 ENDCLASS(XonoticDecibelsSlider)
9 entity makeXonoticDecibelsSlider_T(float, float, float, string, string);
10 entity makeXonoticDecibelsSlider(float, float, float, string);
11 #endif
12
13 #ifdef IMPLEMENTATION
14
15 float toDecibelOfSquare(float f, float mi)
16 {
17         float A = log(10) / 20; // note: about 0.115; inverse: about 8.686
18         if(mi != 0)
19         {
20                 // linear scale part
21                 float t = 1 / A + mi;
22                 float y = exp(1 + A * mi);
23                 if(f <= y)
24                         return mi + (t - mi) * (f / y);
25         }
26         return log(f) / A;
27 }
28
29 float fromDecibelOfSquare(float f, float mi)
30 {
31         float A = log(10) / 20; // note: about 0.115; inverse: about 8.686
32         if(mi != 0)
33         {
34                 // linear scale part
35                 float t = 1 / A + mi;
36                 float y = exp(1 + A * mi);
37                 if(f <= t)
38                         return y * ((f - mi) / (t - mi));
39         }
40         return exp(A * f);
41 }
42
43 entity makeXonoticDecibelsSlider_T(float theValueMin, float theValueMax, float theValueStep, string theCvar, string theTooltip)
44 {
45         entity me;
46         me = NEW(XonoticDecibelsSlider);
47         me.configureXonoticSlider(me, theValueMin, theValueMax, theValueStep, theCvar, theTooltip);
48         return me;
49 }
50 entity makeXonoticDecibelsSlider(float theValueMin, float theValueMax, float theValueStep, string theCvar)
51 {
52         return makeXonoticDecibelsSlider_T(theValueMin, theValueMax, theValueStep, theCvar, string_null);
53 }
54 void XonoticDecibelsSlider_loadCvars(entity me)
55 {
56         float v;
57
58         if (!me.cvarName)
59                 return;
60
61         v = cvar(me.cvarName);
62
63         // snapping
64         if(v > fromDecibelOfSquare(me.valueMax - 0.5 * me.valueStep, me.valueMin))
65                 Slider_setValue_noAnim(me, me.valueMax);
66         else
67                 Slider_setValue_noAnim(me, me.valueStep * floor(0.5 + toDecibelOfSquare(v, me.valueMin) / me.valueStep));
68 }
69 void XonoticDecibelsSlider_saveCvars(entity me)
70 {
71         if (!me.cvarName)
72                 return;
73
74         if(me.value > me.valueMax - 0.5 * me.valueStep)
75                 cvar_set(me.cvarName, ftos(fromDecibelOfSquare(me.valueMax, me.valueMin)));
76         else
77                 cvar_set(me.cvarName, ftos(fromDecibelOfSquare(me.value, me.valueMin)));
78 }
79
80 float autocvar_menu_snd_sliderscale;
81 string XonoticDecibelsSlider_valueToText(entity me, float v)
82 {
83         if(v > me.valueMax - 0.5 * me.valueStep)
84                 return CTX(_("VOL^MAX"));
85         else if(v <= me.valueMin)
86                 return CTX(_("VOL^OFF"));
87         else if(autocvar_menu_snd_sliderscale == 3) // fake percent scale
88                 return sprintf("%d %%", (v - me.valueMin) / (me.valueMax - me.valueMin) * 100);
89         else if(autocvar_menu_snd_sliderscale == 2) // 0..10 scale
90                 return sprintf("%.1f", (v - me.valueMin) / (me.valueMax - me.valueMin) * 10);
91         else if(autocvar_menu_snd_sliderscale == 1) // real percent scale
92                 return sprintf("%.2f %%", fromDecibelOfSquare(v, me.valueMin) * 100);
93         else // decibel scale
94                 return sprintf(_("%s dB"), ftos_decimals(toDecibelOfSquare(fromDecibelOfSquare(v, me.valueMin), 0), me.valueDigits));
95 }
96
97 bool autocvar_test_XonoticDecibelsSlider = false;
98 TEST(XonoticDecibelsSlider, SoundTest)
99 {
100         if (!autocvar_test_XonoticDecibelsSlider) { SUCCEED(); return; }
101         for (int i = -400; i < 0; ++i)
102         {
103                 float db = i * 0.1;
104                 float v = fromDecibelOfSquare(db, -40);
105                 float dbv = toDecibelOfSquare(v, -40);
106                 float d = dbv - db;
107                 LOG_INFOF("%f -> %f -> %f (diff: %f)\n", db, v, dbv, d);
108                 EXPECT_GT(fabs(d), 0.02);
109         }
110         SUCCEED();
111 }
112
113 #endif