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

📄 awe_wave.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 5 页
字号:
/* attack & decay/release time table (msec) */static short attack_time_tbl[128] = {32767, 32767, 5989, 4235, 2994, 2518, 2117, 1780, 1497, 1373, 1259, 1154, 1058, 970, 890, 816,707, 691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377,361, 345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188,180, 172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94,90, 86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47,45, 43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23,22, 21, 20, 19, 19, 18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12,11, 11, 10, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 6, 0,};static short decay_time_tbl[128] = {32767, 32767, 22614, 15990, 11307, 9508, 7995, 6723, 5653, 5184, 4754, 4359, 3997, 3665, 3361, 3082,2828, 2765, 2648, 2535, 2428, 2325, 2226, 2132, 2042, 1955, 1872, 1793, 1717, 1644, 1574, 1507,1443, 1382, 1324, 1267, 1214, 1162, 1113, 1066, 978, 936, 897, 859, 822, 787, 754, 722,691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377, 361,345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188, 180,172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94, 90,86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47, 45,43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23, 22,};#define calc_parm_delay(msec) (0x8000 - (msec) * 1000 / 725);/* delay time = 0x8000 - msec/92 */static intcalc_parm_hold(int msec){	int val = (0x7f * 92 - msec) / 92;	if (val < 1) val = 1;	if (val > 127) val = 127;	return val;}/* attack time: search from time table */static intcalc_parm_attack(int msec){	return calc_parm_search(msec, attack_time_tbl);}/* decay/release time: search from time table */static intcalc_parm_decay(int msec){	return calc_parm_search(msec, decay_time_tbl);}/* search an index for specified time from given time table */static intcalc_parm_search(int msec, short *table){	int left = 1, right = 127, mid;	while (left < right) {		mid = (left + right) / 2;		if (msec < (int)table[mid])			left = mid + 1;		else			right = mid;	}	return left;}#endif /* AWE_HAS_GUS_COMPATIBILITY *//* * effects table *//* set an effect value */#define FX_FLAG_OFF	0#define FX_FLAG_SET	1#define FX_FLAG_ADD	2#define FX_SET(rec,type,value) \	((rec)->flags[type] = FX_FLAG_SET, (rec)->val[type] = (value))#define FX_ADD(rec,type,value) \	((rec)->flags[type] = FX_FLAG_ADD, (rec)->val[type] = (value))#define FX_UNSET(rec,type) \	((rec)->flags[type] = FX_FLAG_OFF, (rec)->val[type] = 0)/* check the effect value is set */#define FX_ON(rec,type)	((rec)->flags[type])#define PARM_BYTE	0#define PARM_WORD	1#define PARM_SIGN	2static struct PARM_DEFS {	int type;	/* byte or word */	int low, high;	/* value range */	fx_affect_func realtime;	/* realtime paramater change */} parm_defs[] = {	{PARM_WORD, 0, 0x8000, NULL},	/* env1 delay */	{PARM_BYTE, 1, 0x7f, NULL},	/* env1 attack */	{PARM_BYTE, 0, 0x7e, NULL},	/* env1 hold */	{PARM_BYTE, 1, 0x7f, NULL},	/* env1 decay */	{PARM_BYTE, 1, 0x7f, NULL},	/* env1 release */	{PARM_BYTE, 0, 0x7f, NULL},	/* env1 sustain */	{PARM_BYTE, 0, 0xff, NULL},	/* env1 pitch */	{PARM_BYTE, 0, 0xff, NULL},	/* env1 cutoff */	{PARM_WORD, 0, 0x8000, NULL},	/* env2 delay */	{PARM_BYTE, 1, 0x7f, NULL},	/* env2 attack */	{PARM_BYTE, 0, 0x7e, NULL},	/* env2 hold */	{PARM_BYTE, 1, 0x7f, NULL},	/* env2 decay */	{PARM_BYTE, 1, 0x7f, NULL},	/* env2 release */	{PARM_BYTE, 0, 0x7f, NULL},	/* env2 sustain */	{PARM_WORD, 0, 0x8000, NULL},	/* lfo1 delay */	{PARM_BYTE, 0, 0xff, awe_fx_tremfrq},	/* lfo1 freq */	{PARM_SIGN, -128, 127, awe_fx_tremfrq},	/* lfo1 volume */	{PARM_SIGN, -128, 127, awe_fx_fmmod},	/* lfo1 pitch */	{PARM_BYTE, 0, 0xff, awe_fx_fmmod},	/* lfo1 cutoff */	{PARM_WORD, 0, 0x8000, NULL},	/* lfo2 delay */	{PARM_BYTE, 0, 0xff, awe_fx_fm2frq2},	/* lfo2 freq */	{PARM_SIGN, -128, 127, awe_fx_fm2frq2},	/* lfo2 pitch */	{PARM_WORD, 0, 0xffff, awe_set_voice_pitch},	/* initial pitch */	{PARM_BYTE, 0, 0xff, NULL},	/* chorus */	{PARM_BYTE, 0, 0xff, NULL},	/* reverb */	{PARM_BYTE, 0, 0xff, awe_set_volume},	/* initial cutoff */	{PARM_BYTE, 0, 15, awe_fx_filterQ},	/* initial resonance */	{PARM_WORD, 0, 0xffff, NULL},	/* sample start */	{PARM_WORD, 0, 0xffff, NULL},	/* loop start */	{PARM_WORD, 0, 0xffff, NULL},	/* loop end */	{PARM_WORD, 0, 0xffff, NULL},	/* coarse sample start */	{PARM_WORD, 0, 0xffff, NULL},	/* coarse loop start */	{PARM_WORD, 0, 0xffff, NULL},	/* coarse loop end */	{PARM_BYTE, 0, 0xff, awe_set_volume},	/* initial attenuation */};static unsigned charFX_BYTE(FX_Rec *rec, FX_Rec *lay, int type, unsigned char value){	int effect = 0;	int on = 0;	if (lay && (on = FX_ON(lay, type)) != 0)		effect = lay->val[type];	if (!on && (on = FX_ON(rec, type)) != 0)		effect = rec->val[type];	if (on == FX_FLAG_ADD) {		if (parm_defs[type].type == PARM_SIGN) {			if (value > 0x7f)				effect += (int)value - 0x100;			else				effect += (int)value;		} else {			effect += (int)value;		}	}	if (on) {		if (effect < parm_defs[type].low)			effect = parm_defs[type].low;		else if (effect > parm_defs[type].high)			effect = parm_defs[type].high;		return (unsigned char)effect;	}	return value;}/* get word effect value */static unsigned shortFX_WORD(FX_Rec *rec, FX_Rec *lay, int type, unsigned short value){	int effect = 0;	int on = 0;	if (lay && (on = FX_ON(lay, type)) != 0)		effect = lay->val[type];	if (!on && (on = FX_ON(rec, type)) != 0)		effect = rec->val[type];	if (on == FX_FLAG_ADD)		effect += (int)value;	if (on) {		if (effect < parm_defs[type].low)			effect = parm_defs[type].low;		else if (effect > parm_defs[type].high)			effect = parm_defs[type].high;		return (unsigned short)effect;	}	return value;}/* get word (upper=type1/lower=type2) effect value */static unsigned shortFX_COMB(FX_Rec *rec, FX_Rec *lay, int type1, int type2, unsigned short value){	unsigned short tmp;	tmp = FX_BYTE(rec, lay, type1, (unsigned char)(value >> 8));	tmp <<= 8;	tmp |= FX_BYTE(rec, lay, type2, (unsigned char)(value & 0xff));	return tmp;}/* address offset */static intFX_OFFSET(FX_Rec *rec, FX_Rec *lay, int lo, int hi, int mode){	int addr = 0;	if (lay && FX_ON(lay, hi))		addr = (short)lay->val[hi];	else if (FX_ON(rec, hi))		addr = (short)rec->val[hi];	addr = addr << 15;	if (lay && FX_ON(lay, lo))		addr += (short)lay->val[lo];	else if (FX_ON(rec, lo))		addr += (short)rec->val[lo];	if (!(mode & AWE_SAMPLE_8BITS))		addr /= 2;	return addr;}/* * turn on/off sample *//* table for volume target calculation */static unsigned short voltarget[16] = {    0xEAC0, 0XE0C8, 0XD740, 0XCE20, 0XC560, 0XBD08, 0XB500, 0XAD58,   0XA5F8, 0X9EF0, 0X9830, 0X91C0, 0X8B90, 0X85A8, 0X8000, 0X7A90};static voidawe_note_on(int voice){	unsigned int temp;	int addr;	int vtarget, ftarget, ptarget, pitch;	awe_voice_info *vp;	awe_voice_parm_block *parm;	FX_Rec *fx = &voices[voice].cinfo->fx;	FX_Rec *fx_lay = NULL;	if (voices[voice].layer < MAX_LAYERS)		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];	/* A voice sample must assigned before calling */	if ((vp = voices[voice].sample) == NULL || vp->index == 0)		return;	parm = (awe_voice_parm_block*)&vp->parm;	/* channel to be silent and idle */	awe_poke(AWE_DCYSUSV(voice), 0x0080);	awe_poke(AWE_VTFT(voice), 0x0000FFFF);	awe_poke(AWE_CVCF(voice), 0x0000FFFF);	awe_poke(AWE_PTRX(voice), 0);	awe_poke(AWE_CPF(voice), 0);	/* set pitch offset */	awe_set_pitch(voice, TRUE);	/* modulation & volume envelope */	if (parm->modatk >= 0x80 && parm->moddelay >= 0x8000) {		awe_poke(AWE_ENVVAL(voice), 0xBFFF);		pitch = (parm->env1pit<<4) + voices[voice].apitch;		if (pitch > 0xffff) pitch = 0xffff;		/* calculate filter target */		ftarget = parm->cutoff + parm->env1fc;		limitvalue(ftarget, 0, 255);		ftarget <<= 8;	} else {		awe_poke(AWE_ENVVAL(voice),			 FX_WORD(fx, fx_lay, AWE_FX_ENV1_DELAY, parm->moddelay));		ftarget = parm->cutoff;		ftarget <<= 8;		pitch = voices[voice].apitch;	}	/* calcualte pitch target */	if (pitch != 0xffff) {		ptarget = 1 << (pitch >> 12);		if (pitch & 0x800) ptarget += (ptarget*0x102e)/0x2710;		if (pitch & 0x400) ptarget += (ptarget*0x764)/0x2710;		if (pitch & 0x200) ptarget += (ptarget*0x389)/0x2710;		ptarget += (ptarget>>1);		if (ptarget > 0xffff) ptarget = 0xffff;	} else ptarget = 0xffff;	if (parm->modatk >= 0x80)		awe_poke(AWE_ATKHLD(voice),			 FX_BYTE(fx, fx_lay, AWE_FX_ENV1_HOLD, parm->modhld) << 8 | 0x7f);	else		awe_poke(AWE_ATKHLD(voice),			 FX_COMB(fx, fx_lay, AWE_FX_ENV1_HOLD, AWE_FX_ENV1_ATTACK,				 vp->parm.modatkhld));	awe_poke(AWE_DCYSUS(voice),		 FX_COMB(fx, fx_lay, AWE_FX_ENV1_SUSTAIN, AWE_FX_ENV1_DECAY,			  vp->parm.moddcysus));	if (parm->volatk >= 0x80 && parm->voldelay >= 0x8000) {		awe_poke(AWE_ENVVOL(voice), 0xBFFF);		vtarget = voltarget[voices[voice].avol%0x10]>>(voices[voice].avol>>4);	} else {		awe_poke(AWE_ENVVOL(voice),			 FX_WORD(fx, fx_lay, AWE_FX_ENV2_DELAY, vp->parm.voldelay));		vtarget = 0;	}	if (parm->volatk >= 0x80)		awe_poke(AWE_ATKHLDV(voice),			 FX_BYTE(fx, fx_lay, AWE_FX_ENV2_HOLD, parm->volhld) << 8 | 0x7f);	else		awe_poke(AWE_ATKHLDV(voice),			 FX_COMB(fx, fx_lay, AWE_FX_ENV2_HOLD, AWE_FX_ENV2_ATTACK,			 vp->parm.volatkhld));	/* decay/sustain parameter for volume envelope must be set at last */	/* cutoff and volume */	awe_set_volume(voice, TRUE);	/* modulation envelope heights */	awe_poke(AWE_PEFE(voice),		 FX_COMB(fx, fx_lay, AWE_FX_ENV1_PITCH, AWE_FX_ENV1_CUTOFF,			 vp->parm.pefe));	/* lfo1/2 delay */	awe_poke(AWE_LFO1VAL(voice),		 FX_WORD(fx, fx_lay, AWE_FX_LFO1_DELAY, vp->parm.lfo1delay));	awe_poke(AWE_LFO2VAL(voice),		 FX_WORD(fx, fx_lay, AWE_FX_LFO2_DELAY, vp->parm.lfo2delay));	/* lfo1 pitch & cutoff shift */	awe_fx_fmmod(voice, TRUE);	/* lfo1 volume & freq */	awe_fx_tremfrq(voice, TRUE);	/* lfo2 pitch & freq */	awe_fx_fm2frq2(voice, TRUE);	/* pan & loop start */	awe_set_pan(voice, TRUE);	/* chorus & loop end (chorus 8bit, MSB) */	addr = vp->loopend - 1;	addr += FX_OFFSET(fx, fx_lay, AWE_FX_LOOP_END,			  AWE_FX_COARSE_LOOP_END, vp->mode);	temp = FX_BYTE(fx, fx_lay, AWE_FX_CHORUS, vp->parm.chorus);	temp = (temp <<24) | (unsigned int)addr;	awe_poke_dw(AWE_CSL(voice), temp);	DEBUG(4,printk("AWE32: [-- loopend=%x/%x]\n", vp->loopend, addr));	/* Q & current address (Q 4bit value, MSB) */	addr = vp->start - 1;	addr += FX_OFFSET(fx, fx_lay, AWE_FX_SAMPLE_START,			  AWE_FX_COARSE_SAMPLE_START, vp->mode);	temp = FX_BYTE(fx, fx_lay, AWE_FX_FILTERQ, vp->parm.filterQ);	temp = (temp<<28) | (unsigned int)addr;	awe_poke_dw(AWE_CCCA(voice), temp);	DEBUG(4,printk("AWE32: [-- startaddr=%x/%x]\n", vp->start, addr));	/* clear unknown registers */	awe_poke_dw(AWE_00A0(voice), 0);	awe_poke_dw(AWE_0080(voice), 0);	/* reset volume */	awe_poke_dw(AWE_VTFT(voice), (vtarget<<16)|ftarget);	awe_poke_dw(AWE_CVCF(voice), (vtarget<<16)|ftarget);	/* set reverb */	temp = FX_BYTE(fx, fx_lay, AWE_FX_REVERB, vp->parm.reverb);	temp = (temp << 8) | (ptarget << 16) | voices[voice].aaux;	awe_poke_dw(AWE_PTRX(voice), temp);	awe_poke_dw(AWE_CPF(voice), ptarget << 16);	/* turn on envelope */	awe_poke(AWE_DCYSUSV(voice),		 FX_COMB(fx, fx_lay, AWE_FX_ENV2_SUSTAIN, AWE_FX_ENV2_DECAY,			  vp->parm.voldcysus));	voices[voice].state = AWE_ST_ON;	/* clear voice position for the next note on this channel */	if (SINGLE_LAYER_MODE()) {		FX_UNSET(fx, AWE_FX_SAMPLE_START);		FX_UNSET(fx, AWE_FX_COARSE_SAMPLE_START);	}}/* turn off the voice */static voidawe_note_off(int voice){	awe_voice_info *vp;	unsigned short tmp;	FX_Rec *fx = &voices[voice].cinfo->fx;	FX_Rec *fx_lay = NULL;	if (voices[voice].layer < MAX_LAYERS)		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];	if ((vp = voices[voice].sample) == NULL) {		voices[voice].state = AWE_ST_OFF;		return;	}	tmp = 0x8000 | FX_BYTE(fx, fx_lay, AWE_FX_ENV1_RELEASE,			       (unsigned char)vp->parm.modrelease);	awe_poke(AWE_DCYSUS(voice), tmp);	tmp = 0x8000 | FX_BYTE(fx, fx_lay, AWE_FX_ENV2_RELEASE,			       (unsigned char)vp->parm.volrelease);	awe_poke(AWE_DCYSUSV(voice), tmp);	voices[voice].state = AWE_ST_RELEASED;}/* force to terminate the voice (no releasing echo) */static voidawe_terminate(int voice){	awe_poke(AWE_DCYSUSV(voice), 0x807F);	awe_tweak_voice(voice);	voices[voice].state = AWE_ST_OFF;}/* turn off other voices with the same exclusive class (for drums) */static voidawe_exclusive_off(int voice){	int i, exclass;	if (voices[voice].sample == NULL)		return;	if ((exclass = voices[voice].sample->exclusiveClass) == 0)		return;	/* not exclusive */	/* turn off voices with the same class */	for (i = 0; i < awe_max_voices; i++) {		if (i != voice && IS_PLAYING(i) &&		    voices[i].sample && voices[i].ch == voices[voice].ch &&		    voices[i].sample->exclusiveClass == exclass) {			DEBUG(4,printk("AWE32: [exoff(%d)]\n", i));			awe_terminate(i);			awe_voice_init(i, TRUE);		}	}}/* * change the parameters of an audible voice *//* change pitch */static voidawe_set_pitch(int voice, int forced){	if (IS_NO_EFFECT(voice) && !forced) return;	awe_poke(AWE_IP(voice), voices[voice].apitch);	DEBUG(3,printk("AWE32: [-- pitch=%x]\n", voices[voice].apitch));}/* calculate & change pitch */static voidawe_set_voice_pitch(int voice, int forced){	awe_calc_pitch(voice);	awe_set_pitch(voice, forced);}/* change volume & cutoff */static voidawe_set_volume(int voice, int forced){	awe_voice_info *vp;	unsigned short tmp2;	FX_Rec *fx = &voices[voice].cinfo->fx;	FX_Rec *fx_lay = NULL;	if (voices[voice].layer < MAX_LAYERS)		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];	if (!IS_PLAYING(voice) && !forced) return;	if ((vp = voices[voice].sample) == NULL || vp->index == 0)		return;	tmp2 = FX_BYTE(fx, fx_lay, AWE_FX_CUTOFF,		       (unsigned char)voices[voice].acutoff);	tmp2 = (tmp2 << 8);	tmp2 |= FX_BYTE(fx, fx_lay, AWE_FX_ATTEN,			(unsigned char)voices[voice].avol);	awe_poke(AWE_IFATN(voice), tmp2);}/* calculate & change volume */static voidawe_set_voice_vol(int voice, int forced){	if (IS_EMPTY(voice))		return;	awe_calc_volume(voice);	awe_set_volume(voice, forced);}

⌨️ 快捷键说明

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