⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gus_simple.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Routines for Gravis UltraSound soundcards - Simple instrument handlers *  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>#include "gus_tables.h"/* * */static void interrupt_wave(snd_gus_card_t *gus, snd_gus_voice_t *voice);static void interrupt_volume(snd_gus_card_t *gus, snd_gus_voice_t *voice);static void interrupt_effect(snd_gus_card_t *gus, snd_gus_voice_t *voice);static void sample_start(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_position_t position);static void sample_stop(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_stop_mode_t mode);static void sample_freq(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_frequency_t freq);static void sample_volume(snd_gus_card_t *card, snd_gus_voice_t *voice, snd_seq_ev_volume_t *volume);static void sample_loop(snd_gus_card_t *card, snd_gus_voice_t *voice, snd_seq_ev_loop_t *loop);static void sample_pos(snd_gus_card_t *card, snd_gus_voice_t *voice, snd_seq_position_t position);static void sample_private1(snd_gus_card_t *card, snd_gus_voice_t *voice, unsigned char *data);static snd_gus_sample_ops_t sample_ops = {	sample_start,	sample_stop,	sample_freq,	sample_volume,	sample_loop,	sample_pos,	sample_private1};#if 0static void note_stop(snd_gus_card_t *gus, snd_gus_voice_t *voice, int wait);static void note_wait(snd_gus_card_t *gus, snd_gus_voice_t *voice);static void note_off(snd_gus_card_t *gus, snd_gus_voice_t *voice);static void note_volume(snd_gus_card_t *card, snd_gus_voice_t *voice);static void note_pitchbend(snd_gus_card_t *card, snd_gus_voice_t *voice);static void note_vibrato(snd_gus_card_t *card, snd_gus_voice_t *voice);static void note_tremolo(snd_gus_card_t *card, snd_gus_voice_t *voice);static struct snd_gus_note_handlers note_commands = {	note_stop,	note_wait,	note_off,	note_volume,	note_pitchbend,	note_vibrato,	note_tremolo};static void chn_trigger_down(snd_gus_card_t *card, ultra_channel_t *channel, ultra_instrument_t *instrument, unsigned char note, unsigned char velocity, unsigned char priority );static void chn_trigger_up( ultra_card_t *card, ultra_note_t *note );static void chn_control( ultra_card_t *card, ultra_channel_t *channel, unsigned short p1, unsigned short p2 );static struct ULTRA_STRU_INSTRUMENT_CHANNEL_COMMANDS channel_commands = {  chn_trigger_down,  chn_trigger_up,  chn_control};#endifstatic void do_volume_envelope(snd_gus_card_t *card, snd_gus_voice_t *voice);static void do_pan_envelope(snd_gus_card_t *card, snd_gus_voice_t *voice);/* * */static void interrupt_wave(snd_gus_card_t *gus, snd_gus_voice_t *voice){	spin_lock(&gus->event_lock);	snd_gf1_stop_voice(gus, voice->number);	spin_lock(&gus->reg_lock);	snd_gf1_select_voice(gus, voice->number);	snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, 0);	spin_unlock(&gus->reg_lock);	voice->flags &= ~SNDRV_GF1_VFLG_RUNNING;	spin_unlock(&gus->event_lock);}static void interrupt_volume(snd_gus_card_t *gus, snd_gus_voice_t *voice){	spin_lock(&gus->event_lock);	if (voice->flags & SNDRV_GF1_VFLG_RUNNING)		do_volume_envelope(gus, voice);	else		snd_gf1_stop_voice(gus, voice->number);	spin_unlock(&gus->event_lock);}static void interrupt_effect(snd_gus_card_t *gus, snd_gus_voice_t *voice){	spin_lock(&gus->event_lock);	if ((voice->flags & (SNDRV_GF1_VFLG_RUNNING|SNDRV_GF1_VFLG_EFFECT_TIMER1)) ==	                    (SNDRV_GF1_VFLG_RUNNING|SNDRV_GF1_VFLG_EFFECT_TIMER1))		do_pan_envelope(gus, voice);	spin_unlock(&gus->event_lock);}/* * */static void do_volume_envelope(snd_gus_card_t *gus, snd_gus_voice_t *voice){	unsigned short next, rate, old_volume;	int program_next_ramp;	unsigned long flags;  	if (!gus->gf1.volume_ramp) {		spin_lock_irqsave(&gus->reg_lock, flags);		snd_gf1_select_voice(gus, voice->number);		snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);		snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, voice->gf1_volume);		/* printk("gf1_volume = 0x%x\n", voice->gf1_volume); */		spin_unlock_irqrestore(&gus->reg_lock, flags);		return;	}	program_next_ramp = 0;	rate = next = 0;	while (1) {		program_next_ramp = 0;		rate = next = 0;		switch (voice->venv_state) {		case VENV_BEFORE:			voice->venv_state = VENV_ATTACK;			voice->venv_value_next = 0;			spin_lock_irqsave(&gus->reg_lock, flags);			snd_gf1_select_voice(gus, voice->number);			snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);			snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, SNDRV_GF1_MIN_VOLUME);			spin_unlock_irqrestore(&gus->reg_lock, flags);			break;		case VENV_ATTACK:			voice->venv_state = VENV_SUSTAIN;			program_next_ramp++;			next = 255;			rate = gus->gf1.volume_ramp;			break;		case VENV_SUSTAIN:			voice->venv_state = VENV_RELEASE;			spin_lock_irqsave(&gus->reg_lock, flags);			snd_gf1_select_voice(gus, voice->number);			snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); 			snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, ((int)voice->gf1_volume * (int)voice->venv_value_next) / 255);			spin_unlock_irqrestore(&gus->reg_lock, flags);			return;		case VENV_RELEASE:			voice->venv_state = VENV_DONE;			program_next_ramp++;			next = 0;			rate = gus->gf1.volume_ramp;			break;		case VENV_DONE:			snd_gf1_stop_voice(gus, voice->number);			voice->flags &= ~SNDRV_GF1_VFLG_RUNNING;			return;		case VENV_VOLUME:			program_next_ramp++;			next = voice->venv_value_next;			rate = gus->gf1.volume_ramp;			voice->venv_state = voice->venv_state_prev;			break;		}		voice->venv_value_next = next;		if (!program_next_ramp)			continue;		spin_lock_irqsave(&gus->reg_lock, flags);		snd_gf1_select_voice(gus, voice->number);		snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);		old_volume = snd_gf1_read16(gus, SNDRV_GF1_VW_VOLUME) >> 8;		if (!rate) {			spin_unlock_irqrestore(&gus->reg_lock, flags);						continue;		}		next = (((int)voice->gf1_volume * (int)next) / 255) >> 8;		if (old_volume < SNDRV_GF1_MIN_OFFSET)			old_volume = SNDRV_GF1_MIN_OFFSET;		if (next < SNDRV_GF1_MIN_OFFSET)			next = SNDRV_GF1_MIN_OFFSET;		if (next > SNDRV_GF1_MAX_OFFSET)			next = SNDRV_GF1_MAX_OFFSET;		if (old_volume == next) {			spin_unlock_irqrestore(&gus->reg_lock, flags);			continue;		}		voice->volume_control &= ~0xc3;		voice->volume_control |= 0x20;		if (old_volume > next) {			snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, next);			snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, old_volume);			voice->volume_control |= 0x40;		} else {			snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, old_volume);			snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, next);		}		snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, rate);		snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, voice->volume_control);		if (!gus->gf1.enh_mode) {			snd_gf1_delay(gus);			snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, voice->volume_control);		}		spin_unlock_irqrestore(&gus->reg_lock, flags);					return;	}}static void do_pan_envelope(snd_gus_card_t *gus, snd_gus_voice_t *voice){	unsigned long flags;	unsigned char old_pan;#if 0	snd_gf1_select_voice(gus, voice->number);	printk(" -%i- do_pan_envelope - flags = 0x%x (0x%x -> 0x%x)\n",		voice->number,		voice->flags,		voice->gf1_pan,		snd_gf1_i_read8(gus, SNDRV_GF1_VB_PAN) & 0x0f);#endif	if (gus->gf1.enh_mode) {		voice->flags &= ~(SNDRV_GF1_VFLG_EFFECT_TIMER1|SNDRV_GF1_VFLG_PAN);		return;	}	if (!gus->gf1.smooth_pan) {		spin_lock_irqsave(&gus->reg_lock, flags);					snd_gf1_select_voice(gus, voice->number);		snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, voice->gf1_pan);		spin_unlock_irqrestore(&gus->reg_lock, flags);		return;	}	if (!(voice->flags & SNDRV_GF1_VFLG_PAN))		/* before */		voice->flags |= SNDRV_GF1_VFLG_EFFECT_TIMER1|SNDRV_GF1_VFLG_PAN;	spin_lock_irqsave(&gus->reg_lock, flags);				snd_gf1_select_voice(gus, voice->number);	old_pan = snd_gf1_read8(gus, SNDRV_GF1_VB_PAN) & 0x0f;	if (old_pan > voice->gf1_pan )		old_pan--;	if (old_pan < voice->gf1_pan)		old_pan++;	snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, old_pan);	spin_unlock_irqrestore(&gus->reg_lock, flags);	if (old_pan == voice->gf1_pan)			/* the goal was reached */		voice->flags &= ~(SNDRV_GF1_VFLG_EFFECT_TIMER1|SNDRV_GF1_VFLG_PAN);#if 0	snd_gf1_select_voice(gus, voice->number);	printk(" -%i- (1) do_pan_envelope - flags = 0x%x (0x%x -> 0x%x)\n",	       voice->number,	       voice->flags,	       voice->gf1_pan,	       snd_gf1_i_read8(gus, GF1_VB_PAN) & 0x0f);#endif}static void set_enhanced_pan(snd_gus_card_t *gus, snd_gus_voice_t *voice, unsigned short pan){	unsigned long flags;	unsigned short vlo, vro;  	vlo = SNDRV_GF1_ATTEN((SNDRV_GF1_ATTEN_TABLE_SIZE-1) - pan);	vro = SNDRV_GF1_ATTEN(pan);	if (pan != SNDRV_GF1_ATTEN_TABLE_SIZE - 1 && pan != 0) {		vlo >>= 1;		vro >>= 1;	}	vlo <<= 4;	vro <<= 4;#if 0	printk("vlo = 0x%x (0x%x), vro = 0x%x (0x%x)\n",			vlo, snd_gf1_i_read16(gus, GF1_VW_OFFSET_LEFT),			vro, snd_gf1_i_read16(gus, GF1_VW_OFFSET_RIGHT));#endif	spin_lock_irqsave(&gus->reg_lock, flags);				snd_gf1_select_voice(gus, voice->number);        snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_LEFT_FINAL, vlo);	snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_RIGHT_FINAL, vro);	spin_unlock_irqrestore(&gus->reg_lock, flags);				voice->vlo = vlo;	voice->vro = vro;}/* * */static void sample_start(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_position_t position){	unsigned long flags;	unsigned int begin, addr, addr_end, addr_start;	int w_16;	simple_instrument_t *simple;	snd_seq_kinstr_t *instr;	instr = snd_seq_instr_find(gus->gf1.ilist, &voice->instr, 0, 1);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -