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

📄 awe_wave.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		rec->instr = instr;		if (i < nvoices - 1)			rec->next_instr = rec + 1;		else			rec->next_instr = curp;		rec->next_bank = NULL;		/* copy awe_voice_info parameters */		COPY_FROM_USER(&rec->v, addr, offset, sizeof(awe_voice_info));		offset += sizeof(awe_voice_info);		rec->v.sf_id = current_sf_id;		if (rec->v.mode & AWE_MODE_INIT_PARM)			awe_init_voice_parm(&rec->v.parm);		awe_set_sample(&rec->v);	}	/* prepend to top of the list */	infos[free_info].next_bank = preset_table[instr];	preset_table[instr] = &infos[free_info];	free_info += nvoices;	return 0;}/* load wave sample data */static intawe_load_data(awe_patch_info *patch, const char *addr){	long offset;	int size;	int rc;	if (free_sample >= AWE_MAX_SAMPLES) {		ERRMSG(printk("AWE32 Error: Sample table full\n"));		return RET_ERROR(ENOSPC);	}	size = (patch->len - sizeof(awe_sample_info)) / 2;	offset = sizeof(awe_patch_info);	COPY_FROM_USER(&samples[free_sample], addr, offset,		       sizeof(awe_sample_info));	offset += sizeof(awe_sample_info);	if (size != samples[free_sample].size) {		ERRMSG(printk("AWE32 Warning: sample size differed (%d != %d)\n",		       (int)samples[free_sample].size, (int)size));		samples[free_sample].size = size;	}	if (samples[free_sample].size > 0)		if ((rc = awe_write_wave_data(addr, offset, size)) != 0)			return rc;	awe_check_loaded();	samples[free_sample].sf_id = current_sf_id;	free_sample++;	return 0;}/* check the other samples are already loaded */static voidawe_check_loaded(void){	if (!loaded_once) {		/* it's the first time */		last_sample = free_sample;		last_info = free_info;		current_sf_id++;		loaded_once = 1;	}}/*----------------------------------------------------------------*/static const char *readbuf_addr;static long readbuf_offs;static int readbuf_flags;#ifdef AWE_USE_BUFFERED_IO#define TMP_WAVBUF_SIZE		4096static unsigned short readbuf[TMP_WAVBUF_SIZE];static int readbuf_size, readbuf_cur, readbuf_left;/* read through temporary buffer */static unsigned shortawe_readbuf_word(int pos){	if (readbuf_left <= 0) {		int i;		if (readbuf_size - pos < TMP_WAVBUF_SIZE)			readbuf_left = readbuf_size - pos;		else			readbuf_left = TMP_WAVBUF_SIZE;		/* read from user buffer */		if (readbuf_flags & AWE_SAMPLE_8BITS) {			unsigned char *pbuf = (unsigned char *)readbuf;			COPY_FROM_USER(pbuf, readbuf_addr,				       readbuf_offs + pos, readbuf_left);			/* convert 8bit -> 16bit */			for (i = readbuf_left - 1; i >= 0; i--)				readbuf[i] = pbuf[i] << 8;		} else {			COPY_FROM_USER(readbuf, readbuf_addr,				       readbuf_offs + pos * 2, readbuf_left*2);		}		if (readbuf_flags & AWE_SAMPLE_UNSIGNED) {			/* unsigned -> signed */			for (i = 0; i < readbuf_left; i++)				readbuf[i] ^= 0x8000;		}		readbuf_cur = 0;	}	readbuf_left--;	return readbuf[readbuf_cur++];}#else  /* AWE_USE_BUFFERED_IO */#define awe_readbuf_word(pos)  awe_read_word(pos)#endif  /* AWE_USE_BUFFERED_IO *//* initialize read buffer */static voidawe_init_readbuf(const char *addr, long offset, int size, int mode_flags){	readbuf_addr = addr;	readbuf_offs = offset;	readbuf_flags = mode_flags;#ifdef AWE_USE_BUFFERED_IO	readbuf_size = size;	readbuf_left = 0;	readbuf_cur = 0;#endif}/* read directly from user buffer */static unsigned shortawe_read_word(int pos){	unsigned short c;	/* read from user buffer */	if (readbuf_flags & AWE_SAMPLE_8BITS) {		unsigned char cc;		GET_BYTE_FROM_USER(cc, readbuf_addr, readbuf_offs + pos);		c = cc << 8; /* convert 8bit -> 16bit */	} else {		GET_SHORT_FROM_USER(c, readbuf_addr, readbuf_offs + pos * 2);	}	if (readbuf_flags & AWE_SAMPLE_UNSIGNED)		c ^= 0x8000; /* unsigned -> signed */	return c;}#define BLANK_LOOP_START	8#define BLANK_LOOP_END		40#define BLANK_LOOP_SIZE		48/* loading onto memory */static int awe_write_wave_data(const char *addr, long offset, int size){	awe_sample_info *sp = &samples[free_sample];	int i, truesize;	int rc;	unsigned long csum1, csum2;	DECL_INTR_FLAGS(flags);	/* be sure loop points start < end */	if (sp->loopstart > sp->loopend) {		long tmp = sp->loopstart;		sp->loopstart = sp->loopend;		sp->loopend = tmp;	}	/* compute true data size to be loaded */	truesize = size;	if (sp->mode_flags & AWE_SAMPLE_BIDIR_LOOP)		truesize += sp->loopend - sp->loopstart;	if (sp->mode_flags & AWE_SAMPLE_NO_BLANK)		truesize += BLANK_LOOP_SIZE;	if (size > 0 && free_mem_ptr + truesize >= awe_mem_size/2) {		ERRMSG(printk("AWE32 Error: Sample memory full\n"));		return RET_ERROR(ENOSPC);	}	/* recalculate address offset */	sp->end -= sp->start;	sp->loopstart -= sp->start;	sp->loopend -= sp->start;	sp->size = truesize;	sp->start = free_mem_ptr + AWE_DRAM_OFFSET;	sp->end += free_mem_ptr + AWE_DRAM_OFFSET;	sp->loopstart += free_mem_ptr + AWE_DRAM_OFFSET;	sp->loopend += free_mem_ptr + AWE_DRAM_OFFSET;	DISABLE_INTR(flags);	if ((rc = awe_open_dram_for_write(free_mem_ptr)) != 0) {		RESTORE_INTR(flags);		return rc;	}	awe_init_readbuf(addr, offset, size, sp->mode_flags);	csum1 = 0;	for (i = 0; i < size; i++) {		unsigned short c;		c = awe_readbuf_word(i);		csum1 += c;		awe_write_dram(c);		if (i == sp->loopend &&		    (sp->mode_flags & AWE_SAMPLE_BIDIR_LOOP)) {			int looplen = sp->loopend - sp->loopstart;			/* copy reverse loop */			int k;			for (k = 0; k < looplen; k++) {				/* non-buffered data */				c = awe_read_word(i - k);				awe_write_dram(c);			}		}	}	/* if no blank loop is attached in the sample, add it */	if (sp->mode_flags & AWE_SAMPLE_NO_BLANK) {		for (i = 0; i < BLANK_LOOP_SIZE; i++)			awe_write_dram(0);		if (sp->mode_flags & AWE_SAMPLE_SINGLESHOT) {			sp->loopstart = sp->end + BLANK_LOOP_START;			sp->loopend = sp->end + BLANK_LOOP_END;		}		sp->size += BLANK_LOOP_SIZE;	}	awe_close_dram();	RESTORE_INTR(flags);	if (sp->checksum_flag) {#ifdef AWE_CHECKSUM_DATA		if (sp->checksum_flag != 2 && csum1 != sp->checksum) {			ERRMSG(printk("AWE32: [%d] checksum mismatch on data %x:%x\n",			       free_sample,			       (int)samples[free_sample].checksum,			       (int)csum1));			return RET_ERROR(NO_DATA_ERR);		}#endif /* AWE_CHECKSUM_DATA */#ifdef AWE_CHECKSUM_MEMORY		DISABLE_INTR(flags);		if (awe_open_dram_for_read(free_mem_ptr) == 0) {			csum2 = 0;			for (i = 0; i < size; i++) {				unsigned short c;				c = awe_peek(AWE_SMLD);				csum2 += c;			}			awe_close_dram_for_read();			if (csum2 != samples[free_sample].checksum) {				RESTORE_INTR(flags);				ERRMSG(printk("AWE32: [%d] checksum mismatch on DRAM %x:%x\n",					      free_sample,					      (int)samples[free_sample].checksum,					      (int)csum2));				return RET_ERROR(NO_DATA_ERR);			}		}		RESTORE_INTR(flags);#endif /* AWE_CHECKSUM_MEMORY */	}	free_mem_ptr += sp->size;	/* re-initialize FM passthrough */	DISABLE_INTR(flags);	awe_init_fm();	awe_tweak();	RESTORE_INTR(flags);	return 0;}/* calculate GUS envelope time: * is this correct?  i have no idea.. */static intcalc_gus_envelope_time(int rate, int start, int end){	int r, p, t;	r = (3 - ((rate >> 6) & 3)) * 3;	p = rate & 0x3f;	t = end - start;	if (t < 0) t = -t;	if (13 > r)		t = t << (13 - r);	else		t = t >> (r - 13);	return (t * 10) / (p * 441);}#define calc_gus_sustain(val)  (0x7f - vol_table[(val)/2])#define calc_gus_attenuation(val)	vol_table[(val)/2]/* load GUS patch */static intawe_load_guspatch(const char *addr, int offs, int size, int pmgr_flag){	struct patch_info patch;	awe_voice_list *rec, *curp;	long sizeof_patch;	int note;	int rc;	sizeof_patch = (long)&patch.data[0] - (long)&patch; /* header size */	if (free_sample >= AWE_MAX_SAMPLES) {		ERRMSG(printk("AWE32 Error: Sample table full\n"));		return RET_ERROR(ENOSPC);	}	if (free_info >= AWE_MAX_INFOS) {		ERRMSG(printk("AWE32 Error: Too many voice informations\n"));		return RET_ERROR(ENOSPC);	}	if (size < sizeof_patch) {		ERRMSG(printk("AWE32 Error: Patch header too short\n"));		return RET_ERROR(EINVAL);	}	COPY_FROM_USER(((char*)&patch) + offs, addr, offs, sizeof_patch - offs);	size -= sizeof_patch;	if (size < patch.len) {		FATALERR(printk("AWE32 Warning: Patch record too short (%d<%d)\n",		       size, (int)patch.len));		patch.len = size;	}	samples[free_sample].sf_id = 0;	samples[free_sample].sample = free_sample;	samples[free_sample].start = 0;	samples[free_sample].end = patch.len;	samples[free_sample].loopstart = patch.loop_start;	samples[free_sample].loopend = patch.loop_end;	samples[free_sample].size = patch.len;	/* set up mode flags */	samples[free_sample].mode_flags = 0;	if (!(patch.mode & WAVE_16_BITS))		samples[free_sample].mode_flags |= AWE_SAMPLE_8BITS;	if (patch.mode & WAVE_UNSIGNED)		samples[free_sample].mode_flags |= AWE_SAMPLE_UNSIGNED;	samples[free_sample].mode_flags |= AWE_SAMPLE_NO_BLANK;	if (!(patch.mode & (WAVE_LOOPING|WAVE_BIDIR_LOOP)))		samples[free_sample].mode_flags |= AWE_SAMPLE_SINGLESHOT;	if (patch.mode & WAVE_BIDIR_LOOP)		samples[free_sample].mode_flags |= AWE_SAMPLE_BIDIR_LOOP;	DEBUG(0,printk("AWE32: [sample %d mode %x]\n", patch.instr_no,		       samples[free_sample].mode_flags));	if (patch.mode & WAVE_16_BITS) {		/* convert to word offsets */		samples[free_sample].size /= 2;		samples[free_sample].end /= 2;		samples[free_sample].loopstart /= 2;		samples[free_sample].loopend /= 2;	}	samples[free_sample].checksum_flag = 0;	samples[free_sample].checksum = 0;	if ((rc = awe_write_wave_data(addr, sizeof_patch,				      samples[free_sample].size)) != 0)		return rc;	awe_check_loaded();	samples[free_sample].sf_id = current_sf_id;	free_sample++;	/* set up voice info */	rec = &infos[free_info];	awe_init_voice_info(&rec->v);	rec->v.sf_id = current_sf_id;	rec->v.sample = free_sample - 1; /* the last sample */	rec->v.rate_offset = calc_rate_offset(patch.base_freq);	note = freq_to_note(patch.base_note);	rec->v.root = note / 100;	rec->v.tune = -(note % 100);	rec->v.low = freq_to_note(patch.low_note) / 100;	rec->v.high = freq_to_note(patch.high_note) / 100;	DEBUG(1,printk("AWE32: [gus base offset=%d, note=%d, range=%d-%d(%d-%d)]\n",		       rec->v.rate_offset, note,		       rec->v.low, rec->v.high,	      patch.low_note, patch.high_note));	/* panning position; -128 - 127 => 0-127 */	rec->v.pan = (patch.panning + 128) / 2;	/* detuning is ignored */	/* 6points volume envelope */	if (patch.mode & WAVE_ENVELOPES) {		int attack, hold, decay, release;		attack = calc_gus_envelope_time			(patch.env_rate[0], 0, patch.env_offset[0]);		hold = calc_gus_envelope_time			(patch.env_rate[1], patch.env_offset[0],			 patch.env_offset[1]);		decay = calc_gus_envelope_time			(patch.env_rate[2], patch.env_offset[1],			 patch.env_offset[2]);		release = calc_gus_envelope_time			(patch.env_rate[3], patch.env_offset[1],			 patch.env_offset[4]);		release += calc_gus_envelope_time			(patch.env_rate[4], patch.env_offset[3],			 patch.env_offset[4]);		release += calc_gus_envelope_time			(patch.env_rate[5], patch.env_offset[4],			 patch.env_offset[5]);		rec->v.parm.volatkhld = (calc_parm_attack(attack) << 8) |			calc_parm_hold(hold);		rec->v.parm.voldcysus = (calc_gus_sustain(patch.env_offset[2]) << 8) |			calc_parm_decay(decay);		rec->v.parm.volrelease = 0x8000 | calc_parm_decay(release);		DEBUG(2,printk("AWE32: [gusenv atk=%d, hld=%d, dcy=%d, rel=%d]\n", attack, hold, decay, release));		rec->v.attenuation = calc_gus_attenuation(patch.env_offset[0]);	}	/* tremolo effect */	if (patch.mode & WAVE_TREMOLO) {		int rate = (patch.tremolo_rate * 1000 / 38) / 42;		rec->v.parm.tremfrq = ((patch.tremolo_depth / 2) << 8) | rate;		DEBUG(2,printk("AWE32: [gusenv tremolo rate=%d, dep=%d, tremfrq=%x]\n",			       patch.tremolo_rate, patch.tremolo_depth,			       rec->v.parm.tremfrq));	}	/* vibrato effect */	if (patch.mode & WAVE_VIBRATO) {		int rate = (patch.vibrato_rate * 1000 / 38) / 42;		rec->v.parm.fm2frq2 = ((patch.vibrato_depth / 6) << 8) | rate;		DEBUG(2,printk("AWE32: [gusenv vibrato rate=%d, dep=%d, tremfrq=%x]\n",			       patch.tremolo_rate, patch.tremolo_depth,			       rec->v.parm.tremfrq));	}		/* scale_freq, scale_factor, volume, and fractions not implemented */	/* set the voice index */	awe_set_sample(&rec->v);	/* prepend to top of the list */	curp = awe_search_instr(awe_gus_bank, patch.instr_no);	rec->bank = awe_gus_bank;	rec->instr = patch.instr_no;	rec->next_instr = curp;	rec->next_bank = preset_table[rec->instr];	preset_table[rec->instr] = rec;	free_info++;	return 0;}/* remove samples with current sf_id from instrument list */static awe_voice_list *awe_get_removed_list(awe_voice_list *curp){	awe_voice_list *lastp, **prevp;	int maxc;	lastp = curp;	prevp = &lastp;	for (maxc = AWE_MAX_INFOS;	     curp && maxc; curp = curp->next_instr, maxc--) {		if (curp->v.sf_id == current_sf_id)			*prevp = curp->next_instr;		else			prevp = &curp->next_instr;	}	return lastp;}/* remove last loaded samples */static voidawe_remove_samples(void){	awe_voice_list **prevp, *p, *nextp;	int maxc;	int i;	if (last_sample == free_sample && last_info == free_info)		return;	/* remove the records from preset table */	for (i = 0; i < AWE_MAX_PRESETS; i++) {		prevp = &preset_table[i];		for (maxc = AWE_MAX_INFOS, p = preset_table[i];		     p && maxc; p = nextp, maxc--) {			nextp = p->next_bank;			p = awe_get_removed_li

⌨️ 快捷键说明

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