| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
| Jaroslav Kysela | c1017a4 | 2007-10-15 09:50:19 +0200 | [diff] [blame] | 2 | *  Copyright (c) by Jaroslav Kysela <perex@perex.cz> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3 | * | 
|  | 4 | * | 
|  | 5 | *   This program is free software; you can redistribute it and/or modify | 
|  | 6 | *   it under the terms of the GNU General Public License as published by | 
|  | 7 | *   the Free Software Foundation; either version 2 of the License, or | 
|  | 8 | *   (at your option) any later version. | 
|  | 9 | * | 
|  | 10 | *   This program is distributed in the hope that it will be useful, | 
|  | 11 | *   but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 12 | *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 13 | *   GNU General Public License for more details. | 
|  | 14 | * | 
|  | 15 | *   You should have received a copy of the GNU General Public License | 
|  | 16 | *   along with this program; if not, write to the Free Software | 
|  | 17 | *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA | 
|  | 18 | * | 
|  | 19 | */ | 
|  | 20 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 21 | #include <linux/time.h> | 
|  | 22 | #include <sound/core.h> | 
|  | 23 | #include <sound/gus.h> | 
|  | 24 | #define __GUS_TABLES_ALLOC__ | 
|  | 25 | #include "gus_tables.h" | 
|  | 26 |  | 
|  | 27 | EXPORT_SYMBOL(snd_gf1_atten_table); /* for snd-gus-synth module */ | 
|  | 28 |  | 
|  | 29 | unsigned short snd_gf1_lvol_to_gvol_raw(unsigned int vol) | 
|  | 30 | { | 
|  | 31 | unsigned short e, m, tmp; | 
|  | 32 |  | 
|  | 33 | if (vol > 65535) | 
|  | 34 | vol = 65535; | 
|  | 35 | tmp = vol; | 
|  | 36 | e = 7; | 
|  | 37 | if (tmp < 128) { | 
|  | 38 | while (e > 0 && tmp < (1 << e)) | 
|  | 39 | e--; | 
|  | 40 | } else { | 
|  | 41 | while (tmp > 255) { | 
|  | 42 | tmp >>= 1; | 
|  | 43 | e++; | 
|  | 44 | } | 
|  | 45 | } | 
|  | 46 | m = vol - (1 << e); | 
|  | 47 | if (m > 0) { | 
|  | 48 | if (e > 8) | 
|  | 49 | m >>= e - 8; | 
|  | 50 | else if (e < 8) | 
|  | 51 | m <<= 8 - e; | 
|  | 52 | m &= 255; | 
|  | 53 | } | 
|  | 54 | return (e << 8) | m; | 
|  | 55 | } | 
|  | 56 |  | 
| Adrian Bunk | 209ac85 | 2005-05-23 10:29:53 +0200 | [diff] [blame] | 57 | #if 0 | 
|  | 58 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 59 | unsigned int snd_gf1_gvol_to_lvol_raw(unsigned short gf1_vol) | 
|  | 60 | { | 
|  | 61 | unsigned int rvol; | 
|  | 62 | unsigned short e, m; | 
|  | 63 |  | 
|  | 64 | if (!gf1_vol) | 
|  | 65 | return 0; | 
|  | 66 | e = gf1_vol >> 8; | 
|  | 67 | m = (unsigned char) gf1_vol; | 
|  | 68 | rvol = 1 << e; | 
|  | 69 | if (e > 8) | 
|  | 70 | return rvol | (m << (e - 8)); | 
|  | 71 | return rvol | (m >> (8 - e)); | 
|  | 72 | } | 
|  | 73 |  | 
| Takashi Iwai | 5e2da20 | 2005-11-17 14:36:44 +0100 | [diff] [blame] | 74 | unsigned int snd_gf1_calc_ramp_rate(struct snd_gus_card * gus, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 75 | unsigned short start, | 
|  | 76 | unsigned short end, | 
|  | 77 | unsigned int us) | 
|  | 78 | { | 
|  | 79 | static unsigned char vol_rates[19] = | 
|  | 80 | { | 
|  | 81 | 23, 24, 26, 28, 29, 31, 32, 34, | 
|  | 82 | 36, 37, 39, 40, 42, 44, 45, 47, | 
|  | 83 | 49, 50, 52 | 
|  | 84 | }; | 
|  | 85 | unsigned short range, increment, value, i; | 
|  | 86 |  | 
|  | 87 | start >>= 4; | 
|  | 88 | end >>= 4; | 
|  | 89 | if (start < end) | 
|  | 90 | us /= end - start; | 
|  | 91 | else | 
|  | 92 | us /= start - end; | 
|  | 93 | range = 4; | 
|  | 94 | value = gus->gf1.enh_mode ? | 
|  | 95 | vol_rates[0] : | 
|  | 96 | vol_rates[gus->gf1.active_voices - 14]; | 
|  | 97 | for (i = 0; i < 3; i++) { | 
|  | 98 | if (us < value) { | 
|  | 99 | range = i; | 
|  | 100 | break; | 
|  | 101 | } else | 
|  | 102 | value <<= 3; | 
|  | 103 | } | 
|  | 104 | if (range == 4) { | 
|  | 105 | range = 3; | 
|  | 106 | increment = 1; | 
|  | 107 | } else | 
|  | 108 | increment = (value + (value >> 1)) / us; | 
|  | 109 | return (range << 6) | (increment & 0x3f); | 
|  | 110 | } | 
|  | 111 |  | 
| Adrian Bunk | 209ac85 | 2005-05-23 10:29:53 +0200 | [diff] [blame] | 112 | #endif  /*  0  */ | 
|  | 113 |  | 
| Takashi Iwai | 5e2da20 | 2005-11-17 14:36:44 +0100 | [diff] [blame] | 114 | unsigned short snd_gf1_translate_freq(struct snd_gus_card * gus, unsigned int freq16) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 115 | { | 
|  | 116 | freq16 >>= 3; | 
|  | 117 | if (freq16 < 50) | 
|  | 118 | freq16 = 50; | 
|  | 119 | if (freq16 & 0xf8000000) { | 
|  | 120 | freq16 = ~0xf8000000; | 
| Takashi Iwai | 99b359b | 2005-10-20 18:26:44 +0200 | [diff] [blame] | 121 | snd_printk(KERN_ERR "snd_gf1_translate_freq: overflow - freq = 0x%x\n", freq16); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 122 | } | 
|  | 123 | return ((freq16 << 9) + (gus->gf1.playback_freq >> 1)) / gus->gf1.playback_freq; | 
|  | 124 | } | 
|  | 125 |  | 
| Adrian Bunk | 209ac85 | 2005-05-23 10:29:53 +0200 | [diff] [blame] | 126 | #if 0 | 
|  | 127 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 128 | short snd_gf1_compute_vibrato(short cents, unsigned short fc_register) | 
|  | 129 | { | 
|  | 130 | static short vibrato_table[] = | 
|  | 131 | { | 
|  | 132 | 0, 0, 32, 592, 61, 1175, 93, 1808, | 
|  | 133 | 124, 2433, 152, 3007, 182, 3632, 213, 4290, | 
|  | 134 | 241, 4834, 255, 5200 | 
|  | 135 | }; | 
|  | 136 |  | 
|  | 137 | long depth; | 
|  | 138 | short *vi1, *vi2, pcents, v1; | 
|  | 139 |  | 
|  | 140 | pcents = cents < 0 ? -cents : cents; | 
|  | 141 | for (vi1 = vibrato_table, vi2 = vi1 + 2; pcents > *vi2; vi1 = vi2, vi2 += 2); | 
|  | 142 | v1 = *(vi1 + 1); | 
|  | 143 | /* The FC table above is a list of pairs. The first number in the pair     */ | 
|  | 144 | /* is the cents index from 0-255 cents, and the second number in the       */ | 
|  | 145 | /* pair is the FC adjustment needed to change the pitch by the indexed     */ | 
|  | 146 | /* number of cents. The table was created for an FC of 32768.              */ | 
|  | 147 | /* The following expression does a linear interpolation against the        */ | 
|  | 148 | /* approximated log curve in the table above, and then scales the number   */ | 
|  | 149 | /* by the FC before the LFO. This calculation also adjusts the output      */ | 
|  | 150 | /* value to produce the appropriate depth for the hardware. The depth      */ | 
|  | 151 | /* is 2 * desired FC + 1.                                                  */ | 
|  | 152 | depth = (((int) (*(vi2 + 1) - *vi1) * (pcents - *vi1) / (*vi2 - *vi1)) + v1) * fc_register >> 14; | 
|  | 153 | if (depth) | 
|  | 154 | depth++; | 
|  | 155 | if (depth > 255) | 
|  | 156 | depth = 255; | 
|  | 157 | return cents < 0 ? -(short) depth : (short) depth; | 
|  | 158 | } | 
|  | 159 |  | 
|  | 160 | unsigned short snd_gf1_compute_pitchbend(unsigned short pitchbend, unsigned short sens) | 
|  | 161 | { | 
|  | 162 | static long log_table[] = {1024, 1085, 1149, 1218, 1290, 1367, 1448, 1534, 1625, 1722, 1825, 1933}; | 
|  | 163 | int wheel, sensitivity; | 
|  | 164 | unsigned int mantissa, f1, f2; | 
|  | 165 | unsigned short semitones, f1_index, f2_index, f1_power, f2_power; | 
|  | 166 | char bend_down = 0; | 
|  | 167 | int bend; | 
|  | 168 |  | 
|  | 169 | if (!sens) | 
|  | 170 | return 1024; | 
|  | 171 | wheel = (int) pitchbend - 8192; | 
|  | 172 | sensitivity = ((int) sens * wheel) / 128; | 
|  | 173 | if (sensitivity < 0) { | 
|  | 174 | bend_down = 1; | 
|  | 175 | sensitivity = -sensitivity; | 
|  | 176 | } | 
|  | 177 | semitones = (unsigned int) (sensitivity >> 13); | 
|  | 178 | mantissa = sensitivity % 8192; | 
|  | 179 | f1_index = semitones % 12; | 
|  | 180 | f2_index = (semitones + 1) % 12; | 
|  | 181 | f1_power = semitones / 12; | 
|  | 182 | f2_power = (semitones + 1) / 12; | 
|  | 183 | f1 = log_table[f1_index] << f1_power; | 
|  | 184 | f2 = log_table[f2_index] << f2_power; | 
|  | 185 | bend = (int) ((((f2 - f1) * mantissa) >> 13) + f1); | 
|  | 186 | if (bend_down) | 
|  | 187 | bend = 1048576L / bend; | 
|  | 188 | return bend; | 
|  | 189 | } | 
|  | 190 |  | 
|  | 191 | unsigned short snd_gf1_compute_freq(unsigned int freq, | 
|  | 192 | unsigned int rate, | 
|  | 193 | unsigned short mix_rate) | 
|  | 194 | { | 
|  | 195 | unsigned int fc; | 
|  | 196 | int scale = 0; | 
|  | 197 |  | 
|  | 198 | while (freq >= 4194304L) { | 
|  | 199 | scale++; | 
|  | 200 | freq >>= 1; | 
|  | 201 | } | 
|  | 202 | fc = (freq << 10) / rate; | 
|  | 203 | if (fc > 97391L) { | 
|  | 204 | fc = 97391; | 
| Takashi Iwai | 99b359b | 2005-10-20 18:26:44 +0200 | [diff] [blame] | 205 | snd_printk(KERN_ERR "patch: (1) fc frequency overflow - %u\n", fc); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 206 | } | 
|  | 207 | fc = (fc * 44100UL) / mix_rate; | 
|  | 208 | while (scale--) | 
|  | 209 | fc <<= 1; | 
|  | 210 | if (fc > 65535L) { | 
|  | 211 | fc = 65535; | 
| Takashi Iwai | 99b359b | 2005-10-20 18:26:44 +0200 | [diff] [blame] | 212 | snd_printk(KERN_ERR "patch: (2) fc frequency overflow - %u\n", fc); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 213 | } | 
|  | 214 | return (unsigned short) fc; | 
|  | 215 | } | 
| Adrian Bunk | 209ac85 | 2005-05-23 10:29:53 +0200 | [diff] [blame] | 216 |  | 
|  | 217 | #endif  /*  0  */ |