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

📄 trident_synth.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
		voice->Delta = (((freq << 12) + freq) / 48000) & 0x0000ffff;	outb((unsigned char) voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));	if (trident->device == TRIDENT_DEVICE_ID_NX) {		outb((unsigned char) voice->Delta, TRID_REG(trident, CH_NX_DELTA_CSO + 3));		outb((unsigned char) (voice->Delta >> 8), TRID_REG(trident, CH_NX_DELTA_ESO + 3));	} else {		outw((unsigned short) voice->Delta, TRID_REG(trident, CH_DX_ESO_DELTA));	}	spin_unlock_irqrestore(&trident->reg_lock, flags);}static void sample_volume(trident_t * trident, snd_trident_voice_t * voice, snd_seq_ev_volume_t * volume){	unsigned long flags;	unsigned short value;	spin_lock_irqsave(&trident->reg_lock, flags);	voice->GVSel = 0;	/* use global music volume */	voice->FMC = 0x03;	/* fixme: can we do something useful with FMC? */	if (volume->volume >= 0) {		volume->volume &= 0x3fff;		/* linear volume -> logarithmic attenuation conversion		 * uses EC register for greater resolution (6.6 bits) than Vol register (5.3 bits)		 * Vol register used when additional attenuation is required */		voice->RVol = 0;		voice->CVol = 0;		value = log_from_linear( volume->volume );		voice->Vol = 0;		voice->EC = (value & 0x3fff) >> 2;		if (value > 0x3fff) {			voice->EC |= 0xfc0;			if (value < 0x5f00 )				voice->Vol = ((value >> 8) - 0x3f) << 5;			else {				voice->Vol = 0x3ff;				voice->EC = 0xfff;			}		}	}	if (volume->lr >= 0) {		volume->lr &= 0x3fff;		/* approximate linear pan by attenuating channels */		if (volume->lr >= 0x2000) {	/* attenuate left (pan right) */			value = 0x3fff - volume->lr;			for (voice->Pan = 0; voice->Pan < 63; voice->Pan++ ) 				if (value >= pan_table[voice->Pan] )					break;		} else {			/* attenuate right (pan left) */			for (voice->Pan = 0; voice->Pan < 63; voice->Pan++ ) 				if ((unsigned int)volume->lr >= pan_table[voice->Pan] )					break;			voice->Pan |= 0x40;		}	}	outb((unsigned char) voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));	outl((voice->GVSel << 31) | ((voice->Pan & 0x0000007f) << 24) |		 ((voice->Vol & 0x000000ff) << 16) | ((voice->CTRL & 0x0000000f) << 12) |		 (voice->EC & 0x00000fff), TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC));	value = ((voice->FMC & 0x03) << 14) | ((voice->RVol & 0x7f) << 7) | (voice->CVol & 0x7f);	outw(value, TRID_REG(trident, CH_DX_FMC_RVOL_CVOL));	spin_unlock_irqrestore(&trident->reg_lock, flags);}static void sample_loop(trident_t * trident, snd_trident_voice_t * voice, snd_seq_ev_loop_t * loop){	unsigned long flags;	simple_instrument_t *simple;	snd_seq_kinstr_t *instr;	unsigned int loop_start, loop_end;	instr = snd_seq_instr_find(trident->synth.ilist, &voice->instr, 0, 1);	if (instr == NULL)		return;	voice->instr = instr->instr;	/* copy ID to speedup aliases */	simple = KINSTR_DATA(instr);	loop_start = loop->start >> 4;	loop_end = loop->end >> 4;	spin_lock_irqsave(&trident->reg_lock, flags);	voice->LBA = simple->address.memory + loop_start;	voice->CSO = 0;	voice->ESO = loop_end - loop_start - 1;	outb((unsigned char) voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));	outb((voice->LBA >> 16), TRID_REG(trident, CH_LBA + 2));	outw((voice->LBA & 0xffff), TRID_REG(trident, CH_LBA));	if (trident->device == TRIDENT_DEVICE_ID_NX) {		outb((voice->ESO >> 16), TRID_REG(trident, CH_NX_DELTA_ESO + 2));		outw((voice->ESO & 0xffff), TRID_REG(trident, CH_NX_DELTA_ESO));		outb((voice->CSO >> 16), TRID_REG(trident, CH_NX_DELTA_CSO + 2));		outw((voice->CSO & 0xffff), TRID_REG(trident, CH_NX_DELTA_CSO));	} else {		outw((voice->ESO & 0xffff), TRID_REG(trident, CH_DX_ESO_DELTA + 2));		outw((voice->CSO & 0xffff), TRID_REG(trident, CH_DX_CSO_ALPHA_FMS + 2));	}	spin_unlock_irqrestore(&trident->reg_lock, flags);	snd_seq_instr_free_use(trident->synth.ilist, instr);}static void sample_pos(trident_t * trident, snd_trident_voice_t * voice, snd_seq_position_t position){	unsigned long flags;	simple_instrument_t *simple;	snd_seq_kinstr_t *instr;	unsigned int value;	instr = snd_seq_instr_find(trident->synth.ilist, &voice->instr, 0, 1);	if (instr == NULL)		return;	voice->instr = instr->instr;	/* copy ID to speedup aliases */	simple = KINSTR_DATA(instr);	spin_lock_irqsave(&trident->reg_lock, flags);	if (simple->format & SIMPLE_WAVE_LOOP) {		if( position >= simple->loop_start ) {			voice->CSO = (position - simple->loop_start) >> 4;			voice->negCSO = 0;		} else {			voice->CSO = (simple->loop_start - position) >> 4;			voice->negCSO = 1;		}	} else {		voice->CSO = position >> 4;		voice->negCSO = 0;	}	/* set CSO sign */	value = inl(TRID_REG(trident, T4D_SIGN_CSO_A));	if( voice->negCSO ) {		value |= 1 << (voice->number&31);	} else {		value &= ~(1 << (voice->number&31));	}	outl(value,TRID_REG(trident, T4D_SIGN_CSO_A));		outb((unsigned char) voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));	if (trident->device == TRIDENT_DEVICE_ID_NX) {		outw((voice->CSO & 0xffff), TRID_REG(trident, CH_NX_DELTA_CSO));		outb((voice->CSO >> 16), TRID_REG(trident, CH_NX_DELTA_CSO + 2));	} else {		outw((voice->CSO & 0xffff), TRID_REG(trident, CH_DX_CSO_ALPHA_FMS) + 2);	}	spin_unlock_irqrestore(&trident->reg_lock, flags);	snd_seq_instr_free_use(trident->synth.ilist, instr);}static void sample_private1(trident_t * trident, snd_trident_voice_t * voice, unsigned char *data){}/* * Memory management / sample loading */static int snd_trident_simple_put_sample(void *private_data, simple_instrument_t * instr,					 char __user *data, long len, int atomic){	trident_t *trident = private_data;	int size = instr->size;	int shift = 0;	if (instr->format & SIMPLE_WAVE_BACKWARD ||	    instr->format & SIMPLE_WAVE_BIDIR ||	    instr->format & SIMPLE_WAVE_ULAW) 		return -EINVAL;	/* not supported */	if (instr->format & SIMPLE_WAVE_16BIT)		shift++;	if (instr->format & SIMPLE_WAVE_STEREO)		shift++;	size <<= shift;	if (trident->synth.current_size + size > trident->synth.max_size)		return -ENOMEM;	if (!access_ok(VERIFY_READ, data, size))		return -EFAULT;	if (trident->tlb.entries) {		snd_util_memblk_t *memblk;		memblk = snd_trident_synth_alloc(trident, size); 		if (memblk == NULL)			return -ENOMEM;		if (snd_trident_synth_copy_from_user(trident, memblk, 0, data, size) ) {			snd_trident_synth_free(trident, memblk);			return -EFAULT;		}		instr->address.ptr = (unsigned char*)memblk;		instr->address.memory = memblk->offset;	} else {		struct snd_dma_buffer dmab;		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci),					size, &dmab) < 0)			return -ENOMEM;		if (copy_from_user(dmab.area, data, size)) {			snd_dma_free_pages(&dmab);			return -EFAULT;		}		instr->address.ptr = dmab.area;		instr->address.memory = dmab.addr;	}	trident->synth.current_size += size;	return 0;}static int snd_trident_simple_get_sample(void *private_data, simple_instrument_t * instr,					 char __user *data, long len, int atomic){	//trident_t *trident = private_data;	int size = instr->size;	int shift = 0;	if (instr->format & SIMPLE_WAVE_16BIT)		shift++;	if (instr->format & SIMPLE_WAVE_STEREO)		shift++;	size <<= shift;	if (!access_ok(VERIFY_WRITE, data, size))		return -EFAULT;	/* FIXME: not implemented yet */	return -EBUSY;}static int snd_trident_simple_remove_sample(void *private_data, simple_instrument_t * instr,					    int atomic){	trident_t *trident = private_data;	int size = instr->size;	if (instr->format & SIMPLE_WAVE_16BIT)		size <<= 1;	if (instr->format & SIMPLE_WAVE_STEREO)		size <<= 1;	if (trident->tlb.entries) {		snd_util_memblk_t *memblk = (snd_util_memblk_t*)instr->address.ptr;		if (memblk)			snd_trident_synth_free(trident, memblk);		else			return -EFAULT;	} else {		struct snd_dma_buffer dmab;		dmab.dev.type = SNDRV_DMA_TYPE_DEV;		dmab.dev.dev = snd_dma_pci_data(trident->pci);		dmab.area = instr->address.ptr;		dmab.addr = instr->address.memory;		dmab.bytes = size;		snd_dma_free_pages(&dmab);	}	trident->synth.current_size -= size;	if (trident->synth.current_size < 0)	/* shouldn't need this check... */		trident->synth.current_size = 0;	return 0;}static void select_instrument(trident_t * trident, snd_trident_voice_t * v){	snd_seq_kinstr_t *instr;	instr = snd_seq_instr_find(trident->synth.ilist, &v->instr, 0, 1);	if (instr != NULL) {		if (instr->ops) {			if (!strcmp(instr->ops->instr_type, SNDRV_SEQ_INSTR_ID_SIMPLE))				snd_trident_simple_init(v);		}		snd_seq_instr_free_use(trident->synth.ilist, instr);	}}/* */static void event_sample(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v){	if (v->sample_ops && v->sample_ops->sample_stop)		v->sample_ops->sample_stop(p->trident, v, SAMPLE_STOP_IMMEDIATELY);	v->instr.std = ev->data.sample.param.sample.std;	if (v->instr.std & 0xff000000) {	/* private instrument */		v->instr.std &= 0x00ffffff;		v->instr.std |= (unsigned int)ev->source.client << 24;	}	v->instr.bank = ev->data.sample.param.sample.bank;	v->instr.prg = ev->data.sample.param.sample.prg;	select_instrument(p->trident, v);}static void event_cluster(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v){	if (v->sample_ops && v->sample_ops->sample_stop)		v->sample_ops->sample_stop(p->trident, v, SAMPLE_STOP_IMMEDIATELY);	v->instr.cluster = ev->data.sample.param.cluster.cluster;	select_instrument(p->trident, v);}static void event_start(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v){	if (v->sample_ops && v->sample_ops->sample_start)		v->sample_ops->sample_start(p->trident, v, ev->data.sample.param.position);}static void event_stop(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v){	if (v->sample_ops && v->sample_ops->sample_stop)		v->sample_ops->sample_stop(p->trident, v, ev->data.sample.param.stop_mode);}static void event_freq(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v){	if (v->sample_ops && v->sample_ops->sample_freq)		v->sample_ops->sample_freq(p->trident, v, ev->data.sample.param.frequency);}static void event_volume(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v){	if (v->sample_ops && v->sample_ops->sample_volume)		v->sample_ops->sample_volume(p->trident, v, &ev->data.sample.param.volume);}static void event_loop(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v){	if (v->sample_ops && v->sample_ops->sample_loop)		v->sample_ops->sample_loop(p->trident, v, &ev->data.sample.param.loop);}static void event_position(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v){	if (v->sample_ops && v->sample_ops->sample_pos)		v->sample_ops->sample_pos(p->trident, v, ev->data.sample.param.position);}

⌨️ 快捷键说明

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