/*
 *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
 *
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 */

#include <sound/driver.h>
#include <linux/time.h>
#include <sound/core.h>
#include <sound/gus.h>
#define __GUS_TABLES_ALLOC__
#include "gus_tables.h"

EXPORT_SYMBOL(snd_gf1_atten_table); /* for snd-gus-synth module */

unsigned short snd_gf1_lvol_to_gvol_raw(unsigned int vol)
{
	unsigned short e, m, tmp;

	if (vol > 65535)
		vol = 65535;
	tmp = vol;
	e = 7;
	if (tmp < 128) {
		while (e > 0 && tmp < (1 << e))
			e--;
	} else {
		while (tmp > 255) {
			tmp >>= 1;
			e++;
		}
	}
	m = vol - (1 << e);
	if (m > 0) {
		if (e > 8)
			m >>= e - 8;
		else if (e < 8)
			m <<= 8 - e;
		m &= 255;
	}
	return (e << 8) | m;
}

unsigned int snd_gf1_gvol_to_lvol_raw(unsigned short gf1_vol)
{
	unsigned int rvol;
	unsigned short e, m;

	if (!gf1_vol)
		return 0;
	e = gf1_vol >> 8;
	m = (unsigned char) gf1_vol;
	rvol = 1 << e;
	if (e > 8)
		return rvol | (m << (e - 8));
	return rvol | (m >> (8 - e));
}

unsigned int snd_gf1_calc_ramp_rate(snd_gus_card_t * gus,
				    unsigned short start,
				    unsigned short end,
				    unsigned int us)
{
	static unsigned char vol_rates[19] =
	{
		23, 24, 26, 28, 29, 31, 32, 34,
		36, 37, 39, 40, 42, 44, 45, 47,
		49, 50, 52
	};
	unsigned short range, increment, value, i;

	start >>= 4;
	end >>= 4;
	if (start < end)
		us /= end - start;
	else
		us /= start - end;
	range = 4;
	value = gus->gf1.enh_mode ?
	    vol_rates[0] :
	    vol_rates[gus->gf1.active_voices - 14];
	for (i = 0; i < 3; i++) {
		if (us < value) {
			range = i;
			break;
		} else
			value <<= 3;
	}
	if (range == 4) {
		range = 3;
		increment = 1;
	} else
		increment = (value + (value >> 1)) / us;
	return (range << 6) | (increment & 0x3f);
}

unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq16)
{
	freq16 >>= 3;
	if (freq16 < 50)
		freq16 = 50;
	if (freq16 & 0xf8000000) {
		freq16 = ~0xf8000000;
		snd_printk("snd_gf1_translate_freq: overflow - freq = 0x%x\n", freq16);
	}
	return ((freq16 << 9) + (gus->gf1.playback_freq >> 1)) / gus->gf1.playback_freq;
}

short snd_gf1_compute_vibrato(short cents, unsigned short fc_register)
{
	static short vibrato_table[] =
	{
		0, 0, 32, 592, 61, 1175, 93, 1808,
		124, 2433, 152, 3007, 182, 3632, 213, 4290,
		241, 4834, 255, 5200
	};

	long depth;
	short *vi1, *vi2, pcents, v1;

	pcents = cents < 0 ? -cents : cents;
	for (vi1 = vibrato_table, vi2 = vi1 + 2; pcents > *vi2; vi1 = vi2, vi2 += 2);
	v1 = *(vi1 + 1);
	/* The FC table above is a list of pairs. The first number in the pair     */
	/* is the cents index from 0-255 cents, and the second number in the       */
	/* pair is the FC adjustment needed to change the pitch by the indexed     */
	/* number of cents. The table was created for an FC of 32768.              */
	/* The following expression does a linear interpolation against the        */
	/* approximated log curve in the table above, and then scales the number   */
	/* by the FC before the LFO. This calculation also adjusts the output      */
	/* value to produce the appropriate depth for the hardware. The depth      */
	/* is 2 * desired FC + 1.                                                  */
	depth = (((int) (*(vi2 + 1) - *vi1) * (pcents - *vi1) / (*vi2 - *vi1)) + v1) * fc_register >> 14;
	if (depth)
		depth++;
	if (depth > 255)
		depth = 255;
	return cents < 0 ? -(short) depth : (short) depth;
}

unsigned short snd_gf1_compute_pitchbend(unsigned short pitchbend, unsigned short sens)
{
	static long log_table[] = {1024, 1085, 1149, 1218, 1290, 1367, 1448, 1534, 1625, 1722, 1825, 1933};
	int wheel, sensitivity;
	unsigned int mantissa, f1, f2;
	unsigned short semitones, f1_index, f2_index, f1_power, f2_power;
	char bend_down = 0;
	int bend;

	if (!sens)
		return 1024;
	wheel = (int) pitchbend - 8192;
	sensitivity = ((int) sens * wheel) / 128;
	if (sensitivity < 0) {
		bend_down = 1;
		sensitivity = -sensitivity;
	}
	semitones = (unsigned int) (sensitivity >> 13);
	mantissa = sensitivity % 8192;
	f1_index = semitones % 12;
	f2_index = (semitones + 1) % 12;
	f1_power = semitones / 12;
	f2_power = (semitones + 1) / 12;
	f1 = log_table[f1_index] << f1_power;
	f2 = log_table[f2_index] << f2_power;
	bend = (int) ((((f2 - f1) * mantissa) >> 13) + f1);
	if (bend_down)
		bend = 1048576L / bend;
	return bend;
}

unsigned short snd_gf1_compute_freq(unsigned int freq,
				    unsigned int rate,
				    unsigned short mix_rate)
{
	unsigned int fc;
	int scale = 0;

	while (freq >= 4194304L) {
		scale++;
		freq >>= 1;
	}
	fc = (freq << 10) / rate;
	if (fc > 97391L) {
		fc = 97391;
		snd_printk("patch: (1) fc frequency overflow - %u\n", fc);
	}
	fc = (fc * 44100UL) / mix_rate;
	while (scale--)
		fc <<= 1;
	if (fc > 65535L) {
		fc = 65535;
		snd_printk("patch: (2) fc frequency overflow - %u\n", fc);
	}
	return (unsigned short) fc;
}
