File Index
Files and directories
Sign in
FILE

gus_volume.c

File preview with syntax highlighting.

linux-6.19.14/sound/isa/gus/gus_volume.c C
  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
 13EXPORT_SYMBOL(snd_gf1_atten_table); /* for snd-gus-synth module */
 14
 15unsigned 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
 45unsigned 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
 60unsigned 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
100unsigned 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		dev_err(gus->card->dev, "%s: overflow - freq = 0x%x\n",
108			__func__, freq16);
109	}
110	return ((freq16 << 9) + (gus->gf1.playback_freq >> 1)) / gus->gf1.playback_freq;
111}
112
113#if 0
114
115short snd_gf1_compute_vibrato(short cents, unsigned short fc_register)
116{
117	static const short vibrato_table[] =
118	{
119		0, 0, 32, 592, 61, 1175, 93, 1808,
120		124, 2433, 152, 3007, 182, 3632, 213, 4290,
121		241, 4834, 255, 5200
122	};
123
124	long depth;
125	const short *vi1, *vi2;
126	short pcents, v1;
127
128	pcents = cents < 0 ? -cents : cents;
129	for (vi1 = vibrato_table, vi2 = vi1 + 2; pcents > *vi2; vi1 = vi2, vi2 += 2);
130	v1 = *(vi1 + 1);
131	/* The FC table above is a list of pairs. The first number in the pair     */
132	/* is the cents index from 0-255 cents, and the second number in the       */
133	/* pair is the FC adjustment needed to change the pitch by the indexed     */
134	/* number of cents. The table was created for an FC of 32768.              */
135	/* The following expression does a linear interpolation against the        */
136	/* approximated log curve in the table above, and then scales the number   */
137	/* by the FC before the LFO. This calculation also adjusts the output      */
138	/* value to produce the appropriate depth for the hardware. The depth      */
139	/* is 2 * desired FC + 1.                                                  */
140	depth = (((int) (*(vi2 + 1) - *vi1) * (pcents - *vi1) / (*vi2 - *vi1)) + v1) * fc_register >> 14;
141	if (depth)
142		depth++;
143	if (depth > 255)
144		depth = 255;
145	return cents < 0 ? -(short) depth : (short) depth;
146}
147
148unsigned short snd_gf1_compute_pitchbend(unsigned short pitchbend, unsigned short sens)
149{
150	static const long log_table[] = {1024, 1085, 1149, 1218, 1290, 1367, 1448, 1534, 1625, 1722, 1825, 1933};
151	int wheel, sensitivity;
152	unsigned int mantissa, f1, f2;
153	unsigned short semitones, f1_index, f2_index, f1_power, f2_power;
154	char bend_down = 0;
155	int bend;
156
157	if (!sens)
158		return 1024;
159	wheel = (int) pitchbend - 8192;
160	sensitivity = ((int) sens * wheel) / 128;
161	if (sensitivity < 0) {
162		bend_down = 1;
163		sensitivity = -sensitivity;
164	}
165	semitones = (unsigned int) (sensitivity >> 13);
166	mantissa = sensitivity % 8192;
167	f1_index = semitones % 12;
168	f2_index = (semitones + 1) % 12;
169	f1_power = semitones / 12;
170	f2_power = (semitones + 1) / 12;
171	f1 = log_table[f1_index] << f1_power;
172	f2 = log_table[f2_index] << f2_power;
173	bend = (int) ((((f2 - f1) * mantissa) >> 13) + f1);
174	if (bend_down)
175		bend = 1048576L / bend;
176	return bend;
177}
178
179unsigned short snd_gf1_compute_freq(unsigned int freq,
180				    unsigned int rate,
181				    unsigned short mix_rate)
182{
183	unsigned int fc;
184	int scale = 0;
185
186	while (freq >= 4194304L) {
187		scale++;
188		freq >>= 1;
189	}
190	fc = (freq << 10) / rate;
191	if (fc > 97391L) {
192		fc = 97391;
193		pr_err("patch: (1) fc frequency overflow - %u\n", fc);
194	}
195	fc = (fc * 44100UL) / mix_rate;
196	while (scale--)
197		fc <<= 1;
198	if (fc > 65535L) {
199		fc = 65535;
200		pr_err("patch: (2) fc frequency overflow - %u\n", fc);
201	}
202	return (unsigned short) fc;
203}
204
205#endif  /*  0  */
~/ Read-only file preview.