Merge from vendor branch OPENSSH:
[dragonfly.git] / sys / dev / sound / isa / i386 / gus / gus_vol.c
1 /*
2  * gus_vol.c - Compute volume for GUS.
3  * 
4  * Greg Lee 1993.
5  *
6  * $DragonFly: src/sys/dev/sound/isa/i386/gus/Attic/gus_vol.c,v 1.2 2003/08/07 21:17:12 dillon Exp $
7  */
8 #include <i386/isa/sound/sound_config.h>
9
10 #ifdef CONFIG_GUS
11 #include "gus_linearvol.h"
12
13 #define GUS_VOLUME      gus_wave_volume
14
15
16 extern int      gus_wave_volume;
17 unsigned short  gus_adagio_vol(int vel, int mainv, int xpn, int voicev);
18 unsigned short  gus_linear_vol(int vol, int mainvol);
19
20 /*
21  * Calculate gus volume from note velocity, main volume, expression, and
22  * intrinsic patch volume given in patch library.  Expression is multiplied
23  * in, so it emphasizes differences in note velocity, while main volume is
24  * added in -- I don't know whether this is right, but it seems reasonable to
25  * me.  (In the previous stage, main volume controller messages were changed
26  * to expression controller messages, if they were found to be used for
27  * dynamic volume adjustments, so here, main volume can be assumed to be
28  * constant throughout a song.)
29  * 
30  * Intrinsic patch volume is added in, but if over 64 is also multiplied in, so
31  * we can give a big boost to very weak voices like nylon guitar and the
32  * basses.  The normal value is 64.  Strings are assigned lower values.
33  */
34 unsigned short
35 gus_adagio_vol(int vel, int mainv, int xpn, int voicev)
36 {
37     int             i, m, n, x;
38
39     /*
40      * A voice volume of 64 is considered neutral, so adjust the main
41      * volume if something other than this neutral value was assigned in
42      * the patch library.
43      */
44     x = 256 + 6 * (voicev - 64);
45
46     /*
47      * Boost expression by voice volume above neutral.
48      */
49     if (voicev > 65)
50         xpn += voicev - 64;
51     xpn += (voicev - 64) / 2;
52
53     /*
54      * Combine multiplicative and level components.
55      */
56     x = vel * xpn * 6 + (voicev / 4) * x;
57
58 #ifdef GUS_VOLUME
59     /*
60      * Further adjustment by installation-specific master volume control
61      * (default 60).
62      */
63     x = (x * GUS_VOLUME * GUS_VOLUME) / 10000;
64 #endif
65
66 #ifdef GUS_USE_CHN_MAIN_VOLUME
67     /*
68      * Experimental support for the channel main volume
69      */
70
71     mainv = (mainv / 2) + 64;   /* Scale to 64 to 127 */
72     x = (x * mainv * mainv) / 16384;
73 #endif
74
75     if (x < 2)
76         return (0);
77     else if (x >= 65535)
78         return ((15 << 8) | 255);
79
80     /*
81      * Convert to gus's logarithmic form with 4 bit exponent i and 8 bit
82      * mantissa m.
83      */
84     n = x;
85     i = 7;
86     if (n < 128) {
87         while (i > 0 && n < (1 << i))
88             i--;
89     } else
90         while (n > 255) {
91             n >>= 1;
92             i++;
93         }
94     /*
95      * Mantissa is part of linear volume not expressed in exponent.
96      * (This is not quite like real logs -- I wonder if it's right.)
97      */
98     m = x - (1 << i);
99
100     /*
101      * Adjust mantissa to 8 bits.
102      */
103     if (m > 0) {
104         if (i > 8)
105             m >>= i - 8;
106         else if (i < 8)
107             m <<= 8 - i;
108     }
109     return ((i << 8) + m);
110 }
111
112 /*
113  * Volume-values are interpreted as linear values. Volume is based on the
114  * value supplied with SEQ_START_NOTE(), channel main volume (if compiled in)
115  * and the volume set by the mixer-device (default 60%).
116  */
117
118 unsigned short
119 gus_linear_vol(int vol, int mainvol)
120 {
121     int             mixer_mainvol;
122
123     RANGE (vol, 0, 127) ;
124
125 #ifdef GUS_VOLUME
126     mixer_mainvol = GUS_VOLUME;
127 #else
128     mixer_mainvol = 100;
129 #endif
130
131 #ifdef GUS_USE_CHN_MAIN_VOLUME
132     RANGE (mainvol, 0, 127);
133 #else
134     mainvol = 127;
135 #endif
136
137     return gus_linearvol[(((vol * mainvol) / 127) * mixer_mainvol) / 100];
138 }
139
140 #endif