Commit a45e0114 authored by Jaroslav Kysela's avatar Jaroslav Kysela

[ALSA] GUS - Remove unused gus_lfo.c file

GUS Library
Signed-off-by: default avatarAdrian Bunk <bunk@stusta.de>
Signed-off-by: default avatarJaroslav Kysela <perex@suse.cz>
parent 9024d50a
/*
* Copyright (c) by Jaroslav Kysela <perex@suse.cz>
* Routines for control of LFO generators (tremolo & vibrato) for
* GF1/InterWave chips...
*
*
* 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 <sound/core.h>
#include <sound/gus.h>
/*
* called by engine routines
*/
static signed char snd_gf1_lfo_compute_value(snd_gus_card_t * gus,
unsigned char *ptr)
{
unsigned int twaveinc, depth_delta;
signed int result;
unsigned short control, twave, depth, depth_final;
unsigned char *ptr1;
control = *(unsigned short *) (ptr + 0x00);
ptr1 = ptr + ((control & 0x4000) >> 12);
/* 1. add TWAVEINC to TWAVE and write the result back */
/* LFO update rate is 689Hz, effect timer is in ms */
if (gus->gf1.timer_slave)
twaveinc = (689 * gus->gf1.timer_master_gus->gf1.effect_timer) / 1000;
else
twaveinc = (689 * gus->gf1.effect_timer) / 1000;
if (!twaveinc)
twaveinc++;
#if 0
printk("twaveinc = 0x%x, effect_timer = %i\n", twaveinc, gus->gf1.effect_timer);
#endif
depth = *(unsigned short *) (ptr1 + 0x0a);
depth_final = *(unsigned char *) (ptr + 0x02) << 5;
if (depth != depth_final) {
depth_delta = ((twaveinc * *(ptr + 0x03)) + *(unsigned short *) (ptr + 0x04));
*(unsigned short *) (ptr + 0x04) = depth_delta % 8000;
depth_delta /= 8000;
if (depth < depth_final) {
if (depth + depth_delta > depth_final)
depth = depth_final;
else
depth += depth_delta;
}
if (depth > depth_final) {
if (depth - depth_delta < depth_final)
depth = depth_final;
else
depth -= depth_delta;
}
*(unsigned short *) (ptr1 + 0x0a) = depth;
}
twaveinc *= (unsigned int) control & 0x7ff;
twaveinc += *(unsigned short *) (ptr + 0x06);
*(unsigned short *) (ptr + 0x06) = twaveinc % 1000;
twave = *(unsigned short *) (ptr1 + 0x08);
twave += (unsigned short) (twaveinc / (unsigned int) 1000);
*(unsigned short *) (ptr1 + 0x08) = twave;
if (!(control & 0x2000)) {
/* 2. if shift is low */
if (twave & 0x4000) { /* bit 14 high -> invert TWAVE 13-0 */
twave ^= 0x3fff;
twave &= ~0x4000;
}
/* TWAVE bit 15 is exclusive or'd with the invert bit (12) */
twave ^= (control & 0x1000) << 3;
} else {
/* 2. if shift is high */
if (twave & 0x8000) /* bit 15 high -> invert TWAVE 14-0 */
twave ^= 0x7fff;
/* the invert bit (12) is used as sign bit */
if (control & 0x1000)
twave |= 0x8000;
else
twave &= ~0x8000;
}
/* 3. multiply the 14-bit LFO waveform magnitude by 13-bit DEPTH */
#if 0
printk("c=0x%x,tw=0x%x,to=0x%x,d=0x%x,df=0x%x,di=0x%x,r=0x%x,r1=%i\n",
control, twave,
*(unsigned short *) (ptr1 + 0x08),
depth, depth_final, *(ptr + 0x03),
(twave & 0x7fff) * depth, ((twave & 0x7fff) * depth) >> 21);
#endif
result = (twave & 0x7fff) * depth;
if (result) {
/* shift */
result >>= 21;
result &= 0x3f;
}
/* add sign */
if (twave & 0x8000)
result = -result;
#if 0
printk("lfo final value = %i\n", result);
#endif
return result;
}
static void snd_gf1_lfo_register_setup(snd_gus_card_t * gus,
snd_gf1_voice_t * voice,
int lfo_type)
{
unsigned long flags;
if (gus->gf1.enh_mode) {
CLI(&flags);
gf1_select_voice(gus, voice->number);
if (lfo_type & 1) {
snd_gf1_write8(gus, GF1_VB_FREQUENCY_LFO, voice->lfo_fc);
voice->lfo_fc = 0;
}
if (lfo_type & 2) {
snd_gf1_write8(gus, GF1_VB_VOLUME_LFO, voice->lfo_volume);
voice->lfo_volume = 0;
}
STI(&flags);
} else {
/*
* ok.. with old GF1 chip can be only vibrato emulated...
* volume register can be in volume ramp state, so tremolo isn't simple..
*/
if (!(lfo_type & 1))
return;
#if 0
if (voice->lfo_fc)
printk("setup - %i = %i\n", voice->number, voice->lfo_fc);
#endif
CLI(&flags);
gf1_select_voice(gus, voice->number);
snd_gf1_write16(gus, GF1_VW_FREQUENCY, voice->fc_register + voice->lfo_fc);
STI(&flags);
}
}
void snd_gf1_lfo_effect_interrupt(snd_gus_card_t * gus, snd_gf1_voice_t * voice)
{
unsigned char *ptr;
#if 0
if (voice->number != 0)
return;
#endif
ptr = gus->gf1.lfos + ((voice->number) << 5);
/* 1. vibrato */
if (*(unsigned short *) (ptr + 0x00) & 0x8000)
voice->lfo_fc = snd_gf1_lfo_compute_value(gus, ptr);
/* 2. tremolo */
ptr += 16;
if (*(unsigned short *) (ptr + 0x00) & 0x8000)
voice->lfo_volume = snd_gf1_lfo_compute_value(gus, ptr);
/* 3. register setup */
snd_gf1_lfo_register_setup(gus, voice, 3);
}
/*
*/
void snd_gf1_lfo_init(snd_gus_card_t * gus)
{
if (gus->gf1.hw_lfo) {
snd_gf1_i_write16(gus, GF1_GW_LFO_BASE, 0x0000);
snd_gf1_dram_setmem(gus, 0, 0x0000, 1024);
/* now enable LFO */
snd_gf1_i_write8(gus, GF1_GB_GLOBAL_MODE, snd_gf1_i_look8(gus, GF1_GB_GLOBAL_MODE) | 0x02);
}
if (gus->gf1.sw_lfo) {
#if 1
gus->gf1.lfos = snd_calloc(1024);
if (!gus->gf1.lfos)
#endif
gus->gf1.sw_lfo = 0;
}
}
void snd_gf1_lfo_done(snd_gus_card_t * gus)
{
if (gus->gf1.sw_lfo) {
if (gus->gf1.lfos) {
snd_gf1_free(gus->gf1.lfos, 1024);
gus->gf1.lfos = NULL;
}
}
}
void snd_gf1_lfo_program(snd_gus_card_t * gus, int voice, int lfo_type,
struct ULTRA_STRU_IW_LFO_PROGRAM *program)
{
unsigned int lfo_addr, wave_select;
wave_select = (program->freq_and_control & 0x4000) >> 12;
lfo_addr = (voice << 5) | (lfo_type << 4);
if (gus->gf1.hw_lfo) {
#if 0
printk("LMCI = 0x%x\n", snd_gf1_i_look8(gus, 0x53));
printk("lfo_program: lfo_addr=0x%x,wave_sel=0x%x,fac=0x%x,df=0x%x,di=0x%x,twave=0x%x,depth=0x%x\n",
lfo_addr, wave_select,
program->freq_and_control,
program->depth_final,
program->depth_inc,
program->twave,
program->depth);
#endif
snd_gf1_poke(gus, lfo_addr + 0x02, program->depth_final);
snd_gf1_poke(gus, lfo_addr + 0x03, program->depth_inc);
snd_gf1_pokew(gus, lfo_addr + 0x08 + wave_select, program->twave);
snd_gf1_pokew(gus, lfo_addr + 0x0a + wave_select, program->depth);
snd_gf1_pokew(gus, lfo_addr + 0x00, program->freq_and_control);
#if 0
{
int i = 0;
for (i = 0; i < 16; i++)
printk("%02x:", snd_gf1_peek(gus, lfo_addr + i));
printk("\n");
}
#endif
}
if (gus->gf1.sw_lfo) {
unsigned char *ptr = gus->gf1.lfos + lfo_addr;
*(ptr + 0x02) = program->depth_final;
*(ptr + 0x03) = program->depth_inc;
*(unsigned short *) (ptr + 0x08 + wave_select) = program->twave;
*(unsigned short *) (ptr + 0x0a + wave_select) = program->depth;
*(unsigned short *) (ptr + 0x00) = program->freq_and_control;
}
}
void snd_gf1_lfo_enable(snd_gus_card_t * gus, int voice, int lfo_type)
{
unsigned int lfo_addr;
lfo_addr = (voice << 5) | (lfo_type << 4);
if (gus->gf1.hw_lfo)
snd_gf1_pokew(gus, lfo_addr + 0x00, snd_gf1_peekw(gus, lfo_addr + 0x00) | 0x8000);
if (gus->gf1.sw_lfo) {
unsigned char *ptr = gus->gf1.lfos + lfo_addr;
*(unsigned short *) (ptr + 0x00) |= 0x8000;
}
}
void snd_gf1_lfo_disable(snd_gus_card_t * gus, int voice, int lfo_type)
{
unsigned int lfo_addr;
lfo_addr = (voice << 5) | (lfo_type << 4);
if (gus->gf1.hw_lfo)
snd_gf1_pokew(gus, lfo_addr + 0x00,
snd_gf1_peekw(gus, lfo_addr + 0x00) & ~0x8000);
if (gus->gf1.sw_lfo) {
unsigned char *ptr = gus->gf1.lfos + lfo_addr;
*(unsigned short *) (ptr + 0x00) &= ~0x8000;
}
}
void snd_gf1_lfo_change_freq(snd_gus_card_t * gus, int voice,
int lfo_type, int freq)
{
unsigned int lfo_addr;
lfo_addr = (voice << 5) | (lfo_type << 4);
if (gus->gf1.hw_lfo)
snd_gf1_pokew(gus, lfo_addr + 0x00,
(snd_gf1_peekw(gus, lfo_addr + 0x00) & ~0x7ff) | (freq & 0x7ff));
if (gus->gf1.sw_lfo) {
unsigned long flags;
unsigned char *ptr = gus->gf1.lfos + lfo_addr;
CLI(&flags);
*(unsigned short *) (ptr + 0x00) &= ~0x7ff;
*(unsigned short *) (ptr + 0x00) |= freq & 0x7ff;
STI(&flags);
}
}
void snd_gf1_lfo_change_depth(snd_gus_card_t * gus, int voice,
int lfo_type, int depth)
{
unsigned long flags;
unsigned int lfo_addr;
unsigned short control = 0;
unsigned char *ptr;
lfo_addr = (voice << 5) | (lfo_type << 4);
ptr = gus->gf1.lfos + lfo_addr;
if (gus->gf1.hw_lfo)
control = snd_gf1_peekw(gus, lfo_addr + 0x00);
if (gus->gf1.sw_lfo)
control = *(unsigned short *) (ptr + 0x00);
if (depth < 0) {
control |= 0x1000;
depth = -depth;
} else
control &= ~0x1000;
if (gus->gf1.hw_lfo) {
CLI(&flags);
snd_gf1_poke(gus, lfo_addr + 0x02, (unsigned char) depth);
snd_gf1_pokew(gus, lfo_addr + 0x0a + ((control & 0x4000) >> 12), depth << 5);
snd_gf1_pokew(gus, lfo_addr + 0x00, control);
STI(&flags);
}
if (gus->gf1.sw_lfo) {
unsigned char *ptr = gus->gf1.lfos + lfo_addr;
CLI(&flags);
*(ptr + 0x02) = (unsigned char) depth;
*(unsigned short *) (ptr + 0x0a + ((control & 0x4000) >> 12)) = depth << 5;
*(unsigned short *) (ptr + 0x00) = control;
STI(&flags);
}
}
void snd_gf1_lfo_setup(snd_gus_card_t * gus, int voice, int lfo_type,
int freq, int current_depth, int depth, int sweep,
int shape)
{
struct ULTRA_STRU_IW_LFO_PROGRAM program;
program.freq_and_control = 0x8000 | (freq & 0x7ff);
if (shape & ULTRA_STRU_IW_LFO_SHAPE_POSTRIANGLE)
program.freq_and_control |= 0x2000;
if (depth < 0) {
program.freq_and_control |= 0x1000;
depth = -depth;
}
program.twave = 0;
program.depth = current_depth;
program.depth_final = depth;
if (sweep) {
program.depth_inc = (unsigned char) (((int) ((depth << 5) - current_depth) << 9) / (sweep * 4410L));
if (!program.depth_inc)
program.depth_inc++;
} else
program.depth = (unsigned short) (depth << 5);
snd_gf1_lfo_program(gus, voice, lfo_type, &program);
}
void snd_gf1_lfo_shutdown(snd_gus_card_t * gus, int voice, int lfo_type)
{
unsigned long flags;
unsigned int lfo_addr;
lfo_addr = (voice << 5) | (lfo_type << 4);
if (gus->gf1.hw_lfo) {
snd_gf1_pokew(gus, lfo_addr + 0x00, 0x0000);
CLI(&flags);
gf1_select_voice(gus, voice);
snd_gf1_write8(gus, lfo_type == ULTRA_LFO_VIBRATO ? GF1_VB_FREQUENCY_LFO : GF1_VB_VOLUME_LFO, 0);
STI(&flags);
}
if (gus->gf1.sw_lfo) {
unsigned char *ptr = gus->gf1.lfos + lfo_addr;
snd_gf1_voice_t *pvoice;
*(unsigned short *) (ptr + 0x00) = 0;
*(unsigned short *) (ptr + 0x04) = 0;
*(unsigned short *) (ptr + 0x06) = 0;
if (gus->gf1.syn_voices) {
pvoice = gus->gf1.syn_voices + voice;
if (lfo_type == ULTRA_LFO_VIBRATO)
pvoice->lfo_fc = 0;
else
pvoice->lfo_volume = 0;
snd_gf1_lfo_register_setup(gus, pvoice, lfo_type == ULTRA_LFO_VIBRATO ? 1 : 2);
} else if (gus->gf1.enh_mode) {
CLI(&flags);
gf1_select_voice(gus, voice);
snd_gf1_write8(gus, lfo_type == ULTRA_LFO_VIBRATO ? GF1_VB_FREQUENCY_LFO : GF1_VB_VOLUME_LFO, 0);
STI(&flags);
}
}
}
void snd_gf1_lfo_command(snd_gus_card_t * gus, int voice, unsigned char *data)
{
int lfo_type;
int lfo_command;
int temp1, temp2;
lfo_type = *data >> 7;
lfo_command = *data & 0x7f;
switch (lfo_command) {
case ULTRA_LFO_SETUP: /* setup */
temp1 = snd_gf1_get_word(data, 2);
temp2 = snd_gf1_get_word(data, 4);
snd_gf1_lfo_setup(gus, voice, lfo_type, temp1 & 0x7ff, 0, temp2 > 255 ? 255 : temp2, snd_gf1_get_byte(data, 1), (temp1 & 0x2000) >> 13);
break;
case ULTRA_LFO_FREQ: /* freq */
snd_gf1_lfo_change_depth(gus, voice, lfo_type, snd_gf1_get_word(data, 2));
break;
case ULTRA_LFO_DEPTH: /* depth */
snd_gf1_lfo_change_freq(gus, voice, lfo_type, snd_gf1_get_word(data, 2));
break;
case ULTRA_LFO_ENABLE: /* enable */
snd_gf1_lfo_enable(gus, voice, lfo_type);
break;
case ULTRA_LFO_DISABLE: /* disable */
snd_gf1_lfo_disable(gus, voice, lfo_type);
break;
case ULTRA_LFO_SHUTDOWN: /* shutdown */
snd_gf1_lfo_shutdown(gus, voice, lfo_type);
break;
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment