1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | */ |
5 | |
6 | #include <linux/time.h> |
7 | #include <linux/export.h> |
8 | #include <sound/core.h> |
9 | #include <sound/gus.h> |
10 | #define __GUS_TABLES_ALLOC__ |
11 | #include "gus_tables.h" |
12 | |
13 | EXPORT_SYMBOL(snd_gf1_atten_table); /* for snd-gus-synth module */ |
14 | |
15 | unsigned short snd_gf1_lvol_to_gvol_raw(unsigned int vol) |
16 | { |
17 | unsigned short e, m, tmp; |
18 | |
19 | if (vol > 65535) |
20 | vol = 65535; |
21 | tmp = vol; |
22 | e = 7; |
23 | if (tmp < 128) { |
24 | while (e > 0 && tmp < (1 << e)) |
25 | e--; |
26 | } else { |
27 | while (tmp > 255) { |
28 | tmp >>= 1; |
29 | e++; |
30 | } |
31 | } |
32 | m = vol - (1 << e); |
33 | if (m > 0) { |
34 | if (e > 8) |
35 | m >>= e - 8; |
36 | else if (e < 8) |
37 | m <<= 8 - e; |
38 | m &= 255; |
39 | } |
40 | return (e << 8) | m; |
41 | } |
42 | |
43 | #if 0 |
44 | |
45 | unsigned int snd_gf1_gvol_to_lvol_raw(unsigned short gf1_vol) |
46 | { |
47 | unsigned int rvol; |
48 | unsigned short e, m; |
49 | |
50 | if (!gf1_vol) |
51 | return 0; |
52 | e = gf1_vol >> 8; |
53 | m = (unsigned char) gf1_vol; |
54 | rvol = 1 << e; |
55 | if (e > 8) |
56 | return rvol | (m << (e - 8)); |
57 | return rvol | (m >> (8 - e)); |
58 | } |
59 | |
60 | unsigned int snd_gf1_calc_ramp_rate(struct snd_gus_card * gus, |
61 | unsigned short start, |
62 | unsigned short end, |
63 | unsigned int us) |
64 | { |
65 | static const unsigned char vol_rates[19] = |
66 | { |
67 | 23, 24, 26, 28, 29, 31, 32, 34, |
68 | 36, 37, 39, 40, 42, 44, 45, 47, |
69 | 49, 50, 52 |
70 | }; |
71 | unsigned short range, increment, value, i; |
72 | |
73 | start >>= 4; |
74 | end >>= 4; |
75 | if (start < end) |
76 | us /= end - start; |
77 | else |
78 | us /= start - end; |
79 | range = 4; |
80 | value = gus->gf1.enh_mode ? |
81 | vol_rates[0] : |
82 | vol_rates[gus->gf1.active_voices - 14]; |
83 | for (i = 0; i < 3; i++) { |
84 | if (us < value) { |
85 | range = i; |
86 | break; |
87 | } else |
88 | value <<= 3; |
89 | } |
90 | if (range == 4) { |
91 | range = 3; |
92 | increment = 1; |
93 | } else |
94 | increment = (value + (value >> 1)) / us; |
95 | return (range << 6) | (increment & 0x3f); |
96 | } |
97 | |
98 | #endif /* 0 */ |
99 | |
100 | unsigned short snd_gf1_translate_freq(struct snd_gus_card * gus, unsigned int freq16) |
101 | { |
102 | freq16 >>= 3; |
103 | if (freq16 < 50) |
104 | freq16 = 50; |
105 | if (freq16 & 0xf8000000) { |
106 | freq16 = ~0xf8000000; |
107 | snd_printk(KERN_ERR "snd_gf1_translate_freq: overflow - freq = 0x%x\n" , freq16); |
108 | } |
109 | return ((freq16 << 9) + (gus->gf1.playback_freq >> 1)) / gus->gf1.playback_freq; |
110 | } |
111 | |
112 | #if 0 |
113 | |
114 | short snd_gf1_compute_vibrato(short cents, unsigned short fc_register) |
115 | { |
116 | static const short vibrato_table[] = |
117 | { |
118 | 0, 0, 32, 592, 61, 1175, 93, 1808, |
119 | 124, 2433, 152, 3007, 182, 3632, 213, 4290, |
120 | 241, 4834, 255, 5200 |
121 | }; |
122 | |
123 | long depth; |
124 | const short *vi1, *vi2; |
125 | short pcents, v1; |
126 | |
127 | pcents = cents < 0 ? -cents : cents; |
128 | for (vi1 = vibrato_table, vi2 = vi1 + 2; pcents > *vi2; vi1 = vi2, vi2 += 2); |
129 | v1 = *(vi1 + 1); |
130 | /* The FC table above is a list of pairs. The first number in the pair */ |
131 | /* is the cents index from 0-255 cents, and the second number in the */ |
132 | /* pair is the FC adjustment needed to change the pitch by the indexed */ |
133 | /* number of cents. The table was created for an FC of 32768. */ |
134 | /* The following expression does a linear interpolation against the */ |
135 | /* approximated log curve in the table above, and then scales the number */ |
136 | /* by the FC before the LFO. This calculation also adjusts the output */ |
137 | /* value to produce the appropriate depth for the hardware. The depth */ |
138 | /* is 2 * desired FC + 1. */ |
139 | depth = (((int) (*(vi2 + 1) - *vi1) * (pcents - *vi1) / (*vi2 - *vi1)) + v1) * fc_register >> 14; |
140 | if (depth) |
141 | depth++; |
142 | if (depth > 255) |
143 | depth = 255; |
144 | return cents < 0 ? -(short) depth : (short) depth; |
145 | } |
146 | |
147 | unsigned short snd_gf1_compute_pitchbend(unsigned short pitchbend, unsigned short sens) |
148 | { |
149 | static const long log_table[] = {1024, 1085, 1149, 1218, 1290, 1367, 1448, 1534, 1625, 1722, 1825, 1933}; |
150 | int wheel, sensitivity; |
151 | unsigned int mantissa, f1, f2; |
152 | unsigned short semitones, f1_index, f2_index, f1_power, f2_power; |
153 | char bend_down = 0; |
154 | int bend; |
155 | |
156 | if (!sens) |
157 | return 1024; |
158 | wheel = (int) pitchbend - 8192; |
159 | sensitivity = ((int) sens * wheel) / 128; |
160 | if (sensitivity < 0) { |
161 | bend_down = 1; |
162 | sensitivity = -sensitivity; |
163 | } |
164 | semitones = (unsigned int) (sensitivity >> 13); |
165 | mantissa = sensitivity % 8192; |
166 | f1_index = semitones % 12; |
167 | f2_index = (semitones + 1) % 12; |
168 | f1_power = semitones / 12; |
169 | f2_power = (semitones + 1) / 12; |
170 | f1 = log_table[f1_index] << f1_power; |
171 | f2 = log_table[f2_index] << f2_power; |
172 | bend = (int) ((((f2 - f1) * mantissa) >> 13) + f1); |
173 | if (bend_down) |
174 | bend = 1048576L / bend; |
175 | return bend; |
176 | } |
177 | |
178 | unsigned short snd_gf1_compute_freq(unsigned int freq, |
179 | unsigned int rate, |
180 | unsigned short mix_rate) |
181 | { |
182 | unsigned int fc; |
183 | int scale = 0; |
184 | |
185 | while (freq >= 4194304L) { |
186 | scale++; |
187 | freq >>= 1; |
188 | } |
189 | fc = (freq << 10) / rate; |
190 | if (fc > 97391L) { |
191 | fc = 97391; |
192 | snd_printk(KERN_ERR "patch: (1) fc frequency overflow - %u\n" , fc); |
193 | } |
194 | fc = (fc * 44100UL) / mix_rate; |
195 | while (scale--) |
196 | fc <<= 1; |
197 | if (fc > 65535L) { |
198 | fc = 65535; |
199 | snd_printk(KERN_ERR "patch: (2) fc frequency overflow - %u\n" , fc); |
200 | } |
201 | return (unsigned short) fc; |
202 | } |
203 | |
204 | #endif /* 0 */ |
205 | |