📄 awe_wave.c
字号:
/* 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 + -