eabbaf16d5d5c6f376048a3df0bb51be1dcd2dbf
[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(float, float, float, string);
10 #endif
11
12 #ifdef IMPLEMENTATION
13
14 float toDecibelOfSquare(float f, float mi)
15 {
16         float A = log(10) / 20; // note: about 0.115; inverse: about 8.686
17         if(mi != 0)
18         {
19                 // linear scale part
20                 float t = 1 / A + mi;
21                 float y = exp(1 + A * mi);
22                 if(f <= y)
23                         return mi + (t - mi) * (f / y);
24         }
25         return log(f) / A;
26 }
27
28 float fromDecibelOfSquare(float f, float mi)
29 {
30         float A = log(10) / 20; // note: about 0.115; inverse: about 8.686
31         if(mi != 0)
32         {
33                 // linear scale part
34                 float t = 1 / A + mi;
35                 float y = exp(1 + A * mi);
36                 if(f <= t)
37                         return y * ((f - mi) / (t - mi));
38         }
39         return exp(A * f);
40 }
41
42 entity makeXonoticDecibelsSlider(float theValueMin, float theValueMax, float theValueStep, string theCvar)
43 {
44         entity me;
45         me = NEW(XonoticDecibelsSlider);
46         me.configureXonoticSlider(me, theValueMin, theValueMax, theValueStep, theCvar);
47         return me;
48 }
49 void XonoticDecibelsSlider_loadCvars(entity me)
50 {
51         float v;
52
53         if (!me.cvarName)
54                 return;
55
56         v = cvar(me.cvarName);
57
58         // snapping
59         if(v > fromDecibelOfSquare(me.valueMax - 0.5 * me.valueStep, me.valueMin))
60                 Slider_setValue(me, me.valueMax);
61         else
62                 Slider_setValue(me, me.valueStep * floor(0.5 + toDecibelOfSquare(v, me.valueMin) / me.valueStep) );
63 }
64 void XonoticDecibelsSlider_saveCvars(entity me)
65 {
66         if (!me.cvarName)
67                 return;
68
69         if(me.value > me.valueMax - 0.5 * me.valueStep)
70                 cvar_set(me.cvarName, ftos(fromDecibelOfSquare(me.valueMax, me.valueMin)));
71         else
72                 cvar_set(me.cvarName, ftos(fromDecibelOfSquare(me.value, me.valueMin)));
73 }
74
75 float autocvar_menu_snd_sliderscale;
76 string XonoticDecibelsSlider_valueToText(entity me, float v)
77 {
78         if(v > me.valueMax - 0.5 * me.valueStep)
79                 return CTX(_("VOL^MAX"));
80         else if(v <= me.valueMin)
81                 return CTX(_("VOL^OFF"));
82         else if(autocvar_menu_snd_sliderscale == 3) // fake percent scale
83                 return sprintf("%d %%", (v - me.valueMin) / (me.valueMax - me.valueMin) * 100);
84         else if(autocvar_menu_snd_sliderscale == 2) // 0..10 scale
85                 return sprintf("%.1f", (v - me.valueMin) / (me.valueMax - me.valueMin) * 10);
86         else if(autocvar_menu_snd_sliderscale == 1) // real percent scale
87                 return sprintf("%.2f %%", fromDecibelOfSquare(v, me.valueMin) * 100);
88         else // decibel scale
89                 return sprintf(_("%s dB"), ftos_decimals(toDecibelOfSquare(fromDecibelOfSquare(v, me.valueMin), 0), me.valueDigits));
90 }
91
92 void _TEST_XonoticDecibelsSlider()
93 {
94         float i;
95         for(i = -400; i < 0; ++i)
96         {
97                 float db = i * 0.1;
98                 float v = fromDecibelOfSquare(db, -40);
99                 float dbv = toDecibelOfSquare(v, -40);
100                 float d = dbv - db;
101                 LOG_INFOF("%f -> %f -> %f (diff: %f)\n", db, v, dbv, d);
102                 TEST_Check(fabs(d) > 0.02);
103         }
104         TEST_OK();
105 }
106
107 #endif