linux/sound/isa/gus/gus_volume.c
<<
>>
Prefs
   1/*
   2 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
   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
  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
  27EXPORT_SYMBOL(snd_gf1_atten_table); /* for snd-gus-synth module */
  28
  29unsigned 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
  57#if 0
  58
  59unsigned 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
  74unsigned int snd_gf1_calc_ramp_rate(struct snd_gus_card * gus,
  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
 112#endif  /*  0  */
 113
 114unsigned short snd_gf1_translate_freq(struct snd_gus_card * gus, unsigned int freq16)
 115{
 116        freq16 >>= 3;
 117        if (freq16 < 50)
 118                freq16 = 50;
 119        if (freq16 & 0xf8000000) {
 120                freq16 = ~0xf8000000;
 121                snd_printk(KERN_ERR "snd_gf1_translate_freq: overflow - freq = 0x%x\n", freq16);
 122        }
 123        return ((freq16 << 9) + (gus->gf1.playback_freq >> 1)) / gus->gf1.playback_freq;
 124}
 125
 126#if 0
 127
 128short 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
 160unsigned 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
 191unsigned 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;
 205                snd_printk(KERN_ERR "patch: (1) fc frequency overflow - %u\n", fc);
 206        }
 207        fc = (fc * 44100UL) / mix_rate;
 208        while (scale--)
 209                fc <<= 1;
 210        if (fc > 65535L) {
 211                fc = 65535;
 212                snd_printk(KERN_ERR "patch: (2) fc frequency overflow - %u\n", fc);
 213        }
 214        return (unsigned short) fc;
 215}
 216
 217#endif  /*  0  */
 218