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

📄 awe_wave.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
 *   reset status of all voices, and clear sample position flag */static intawe_open(int dev, int mode){	if (awe_busy)		return RET_ERROR(EBUSY);	awe_busy = 1;	awe_reset(dev);	/* clear sample position flag */	loaded_once = 0;	/* set GUS bank to default */	awe_gus_bank = AWE_DEFAULT_BANK;	return 0;}/* close device: *   reset all voices again (terminate sounds) */static voidawe_close(int dev){	awe_reset(dev);	awe_busy = 0;}/* sequencer I/O control: */static intawe_ioctl(int dev, unsigned int cmd, caddr_t arg){	switch (cmd) {	case SNDCTL_SYNTH_INFO:		awe_info.nr_voices = awe_max_voices;		IOCTL_TO_USER((char*)arg, 0, &awe_info, sizeof(awe_info));		return 0;		break;	case SNDCTL_SEQ_RESETSAMPLES:		awe_reset_samples();		awe_reset(dev); /* better to reset emu8k chip... */		return 0;		break;	case SNDCTL_SEQ_PERCMODE:		/* what's this? */		return 0;		break;	case SNDCTL_SYNTH_MEMAVL:		DEBUG(0,printk("AWE32: [ioctl memavl = %d]\n", (int)free_mem_ptr));		return awe_mem_size - free_mem_ptr*2;	default:		ERRMSG(printk("AWE32: unsupported ioctl %d\n", cmd));		return RET_ERROR(EINVAL);	}}/* kill a voice: *   not terminate, just release the voice. */static intawe_kill_note(int dev, int voice, int note, int velocity){	awe_voice_info *vp;	DECL_INTR_FLAGS(flags);	DEBUG(2,printk("AWE32: [off(%d)]\n", voice));	if (voice < 0 || voice >= awe_max_voices)		      return RET_ERROR(EINVAL);	if ((vp = voices[voice].sample) == NULL)		return 0;       	if (!(vp->mode & AWE_MODE_NORELEASE)) {		DISABLE_INTR(flags);		awe_note_off(voice);		RESTORE_INTR(flags);	}	awe_voice_init(voice, 1);	return 0;}/* search the note with the specified key range */static awe_voice_info *awe_search_voice(int voice, int note){	awe_voice_list *rec;	int maxc;	for (rec = voices[voice].vrec, maxc = AWE_MAX_INFOS;	     rec && maxc; rec = rec->next_instr, maxc--) {		if (rec->v.low <= note && note <= rec->v.high)			return &rec->v;	}	return NULL;}/* start a voice: *   if note is 255, identical with aftertouch function. *   Otherwise, start a voice with specified not and volume. */static intawe_start_note(int dev, int v, int note_num, int volume){	DECL_INTR_FLAGS(flags);	DEBUG(2,printk("AWE32: [on(%d) nt=%d vl=%d]\n", v, note_num, volume));	if (v < 0 || v >= awe_max_voices)		      return RET_ERROR(EINVAL);	/* an instrument must be set before starting a note */	if (voices[v].vrec == NULL) {		DEBUG(1,printk("AWE32: [-- vrec is null]\n"));		return 0;	}	if (note_num == 255) {		/* dynamic volume change; sample is already assigned */		if (! voices[v].state || voices[v].sample == NULL)			return 0;		/* calculate volume parameter */		voices[v].velocity = volume;		awe_calc_volume(v);		DISABLE_INTR(flags);		awe_set_volume(v);		RESTORE_INTR(flags);		return 0;	}	/* assign a sample with the corresponding note */	if ((voices[v].sample = awe_search_voice(v, note_num)) == NULL) {		DEBUG(1,printk("AWE32: [-- sample is null]\n"));		return 0;	}	/* calculate pitch & volume parameters */	voices[v].note = note_num;	voices[v].velocity = volume;	awe_calc_pitch(v);	awe_calc_volume(v);	DISABLE_INTR(flags);	/* turn off other voices (for drums) */	awe_exclusive_off(v);	/* turn on the voice */	awe_note_on(v);	voices[v].state = 1;	/* flag up */	RESTORE_INTR(flags);	return 0;}/* search instrument from preset table with the specified bank */static awe_voice_list *awe_search_instr(int bank, int preset){	awe_voice_list *p;	int maxc;	for (maxc = AWE_MAX_INFOS, p = preset_table[preset];	     p && maxc; p = p->next_bank, maxc--) {		if (p->bank == bank)			return p;	}	return NULL;}/* assign the instrument to a voice */static intawe_set_instr(int dev, int voice, int instr_no){	awe_voice_list *rec;	if (voice < 0 || voice >= awe_max_voices)		return RET_ERROR(EINVAL);	if (instr_no < 0 || instr_no >= AWE_MAX_PRESETS)		return RET_ERROR(EINVAL);	if ((rec = awe_search_instr(voices[voice].bank, instr_no)) == NULL) {		/* if bank is not defined, use the default bank 0 */		if (voices[voice].bank != AWE_DEFAULT_BANK &&		    (rec = awe_search_instr(AWE_DEFAULT_BANK, instr_no)) == NULL) {			DEBUG(1,printk("AWE32 Warning: can't find instrument %d\n", instr_no));			return 0;		}	}	voices[voice].instr = instr_no;	voices[voice].vrec = rec;	voices[voice].sample = NULL;  /* not set yet */	return 0;}/* reset all voices; terminate sounds and initialize parameters */static voidawe_reset(int dev){	int i;	/* don't turn off voice 31 and 32.  they are used also for FM voices */	for (i = 0; i < AWE_NORMAL_VOICES; i++) {		awe_terminate(i);		awe_voice_init(i, 0);	}	awe_init_fm();	awe_tweak();}/* hardware specific control: *   GUS specific and AWE32 specific controls are available. */static voidawe_hw_control(int dev, unsigned char *event){	int cmd = event[2];	if (cmd & _AWE_MODE_FLAG)		awe_hw_awe_control(dev, cmd & _AWE_MODE_VALUE_MASK, event);	else		awe_hw_gus_control(dev, cmd & _AWE_MODE_VALUE_MASK, event);}/* GUS compatible controls */static voidawe_hw_gus_control(int dev, int cmd, unsigned char *event){	int voice;	unsigned short p1;	short p2;	int plong;	DECL_INTR_FLAGS(flags);	voice = event[3];	p1 = *(unsigned short *) &event[4];	p2 = *(short *) &event[6];	plong = *(int*) &event[4];	switch (cmd) {	case _GUS_NUMVOICES:		if (p1 >= awe_max_voices)			printk("AWE32: num_voices: voices out of range %d\n", p1);		break;	case _GUS_VOICESAMPLE:		if (voice < awe_max_voices)			awe_set_instr(dev, voice, p1);		break;	case _GUS_VOICEON:		if (voice < awe_max_voices) {			DISABLE_INTR(flags);			awe_note_on(voice);			RESTORE_INTR(flags);		}		break;			case _GUS_VOICEOFF:		if (voice < awe_max_voices) {			DISABLE_INTR(flags);			awe_note_off(voice);			RESTORE_INTR(flags);		}		break;			case _GUS_VOICEMODE:		/* not supported */		break;	case _GUS_VOICEBALA:		/* -128 to 127 */		if (voice < awe_max_voices)			awe_panning(dev, voice, (short)p1);		break;	case _GUS_VOICEFREQ:		if (voice < awe_max_voices)			awe_calc_pitch_from_freq(voice, plong);		break;			case _GUS_VOICEVOL:	case _GUS_VOICEVOL2:		/* not supported yet */		break;	case _GUS_RAMPRANGE:	case _GUS_RAMPRATE:	case _GUS_RAMPMODE:	case _GUS_RAMPON:	case _GUS_RAMPOFF:		/* volume ramping not supported */		break;	case _GUS_VOLUME_SCALE:		break;	case _GUS_VOICE_POS:		if (voice < awe_max_voices) {			FX_SET(voice, AWE_FX_SAMPLE_START, (short)(plong & 0x7fff));			FX_SET(voice, AWE_FX_COARSE_SAMPLE_START, (plong >> 15) & 0xffff);		}		break;	}}/* AWE32 specific controls */static voidawe_hw_awe_control(int dev, int cmd, unsigned char *event){	int voice;	unsigned short p1;	short p2;	int chn;	chn = event[1];	voice = event[3];	p1 = *(unsigned short *) &event[4];	p2 = *(short *) &event[6];	#ifdef AWE_DEBUG_ON	switch (cmd) {	case _AWE_DEBUG_MODE:		debug_mode = p1;		printk("AWE32: debug mode = %d\n", debug_mode);		break;#endif	case _AWE_REVERB_MODE:		if (p1 <= 7) {			reverb_mode = p1;			DEBUG(0,printk("AWE32: reverb mode %d\n", reverb_mode));			awe_set_reverb_mode(reverb_mode);		}		break;	case _AWE_CHORUS_MODE:		if (p1 <= 7) {			chorus_mode = p1;			DEBUG(0,printk("AWE32: chorus mode %d\n", chorus_mode));			awe_set_chorus_mode(chorus_mode);		}		break;		      	case _AWE_REMOVE_LAST_SAMPLES:		DEBUG(0,printk("AWE32: remove last samples\n"));		awe_remove_samples();		break;	case _AWE_INITIALIZE_CHIP:		awe_initialize();		break;	case _AWE_SEND_EFFECT:		if (voice < awe_max_voices && p1 < AWE_FX_END) {			FX_SET(voice, p1, p2);			DEBUG(0,printk("AWE32: effects (%d) %d %d\n", voice, p1, voices[voice].fx[p1]));			if (fx_realtime[p1]) {				DEBUG(0,printk("AWE32: fx_realtime (%d)\n", voice));				fx_realtime[p1](voice);			}		}		break;	case _AWE_TERMINATE_CHANNEL:		if (voice < awe_max_voices) {			DEBUG(0,printk("AWE32: terminate (%d)\n", voice));			awe_terminate(voice);			awe_voice_init(voice, 1);		}		break;	case _AWE_TERMINATE_ALL:		DEBUG(0,printk("AWE32: terminate all\n"));		awe_reset(0);		break;	case _AWE_INITIAL_VOLUME:		DEBUG(0,printk("AWE32: init attenuation %d\n", p1));		init_atten = p1;		break;	case _AWE_SET_GUS_BANK:		DEBUG(0,printk("AWE32: set gus bank %d\n", p1));		awe_gus_bank = p1;		break;			default:		DEBUG(0,printk("AWE32: hw control cmd=%d voice=%d\n", cmd, voice));		break;	}}/*---------------------------------------------------------------- * load a sound patch: *   three types of patches are accepted: AWE, GUS, and SYSEX. *----------------------------------------------------------------*/static intawe_load_patch(int dev, int format, const char *addr,	       int offs, int count, int pmgr_flag){	awe_patch_info patch;	int rc = 0;	if (format == GUS_PATCH) {		return awe_load_guspatch(addr, offs, count, pmgr_flag);	} else if (format == SYSEX_PATCH) {		/* no system exclusive message supported yet */		return 0;	} else if (format != AWE_PATCH) {		FATALERR(printk("AWE32 Error: Invalid patch format (key) 0x%x\n", format));		return RET_ERROR(EINVAL);	}		if (count < sizeof(awe_patch_info)) {		FATALERR(printk("AWE32 Error: Patch header too short\n"));		return RET_ERROR(EINVAL);	}	COPY_FROM_USER(((char*)&patch) + offs, addr, offs, 		       sizeof(awe_patch_info) - offs);	count -= sizeof(awe_patch_info);	if (count < patch.len) {		FATALERR(printk("AWE32 Warning: Patch record too short (%d<%d)\n",		       count, (int)patch.len));		patch.len = count;	}		switch (patch.type) {	case AWE_LOAD_INFO:		rc = awe_load_info(&patch, addr);		break;	case AWE_LOAD_DATA:		rc = awe_load_data(&patch, addr);		/*		if (!pmgr_flag && rc == 0)			pmgr_inform(dev, PM_E_PATCH_LOADED, instr, free_sample, 0, 0);		*/		break;	default:		FATALERR(printk("AWE32 Error: unknown patch format type %d\n",		       patch.type));		rc = RET_ERROR(EINVAL);	}	return rc;}/* load voice information data */static intawe_load_info(awe_patch_info *patch, const char *addr){	awe_voice_list *rec, *curp;	long offset;	short i, nvoices;	unsigned char bank, instr;	int total_size;	if (patch->len < sizeof(awe_voice_rec)) {		FATALERR(printk("AWE32 Error: invalid patch info length\n"));		return RET_ERROR(EINVAL);	}	offset = sizeof(awe_patch_info);	GET_BYTE_FROM_USER(bank, addr, offset); offset++;	GET_BYTE_FROM_USER(instr, addr, offset); offset++;	GET_SHORT_FROM_USER(nvoices, addr, offset); offset+=2;	if (nvoices <= 0 || nvoices >= 100) {		FATALERR(printk("AWE32 Error: Illegal voice number %d\n", nvoices));		return RET_ERROR(EINVAL);	}	if (free_info + nvoices > AWE_MAX_INFOS) {		ERRMSG(printk("AWE32 Error: Too many voice informations\n"));		return RET_ERROR(ENOSPC);	}	total_size = sizeof(awe_voice_rec) + sizeof(awe_voice_info) * nvoices;	if (patch->len < total_size) {		ERRMSG(printk("AWE32 Error: patch length(%d) is smaller than nvoices(%d)\n",		       (int)patch->len, nvoices));		return RET_ERROR(EINVAL);	}	curp = awe_search_instr(bank, instr);	for (i = 0; i < nvoices; i++) {		rec = &infos[free_info + i];		rec->bank = bank;

⌨️ 快捷键说明

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