📄 awe_wave.c
字号:
/* change pan; this could make a click noise.. */static voidawe_set_pan(int voice, int forced){ unsigned int temp; int addr; awe_voice_info *vp; 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_NO_EFFECT(voice) && !forced) return; if ((vp = voices[voice].sample) == NULL || vp->index == 0) return; /* pan & loop start (pan 8bit, MSB, 0:right, 0xff:left) */ if (vp->fixpan > 0) /* 0-127 */ temp = 255 - (int)vp->fixpan * 2; else { int pos = 0; if (vp->pan >= 0) /* 0-127 */ pos = (int)vp->pan * 2 - 128; pos += voices[voice].cinfo->panning; /* -128 - 127 */ temp = 127 - pos; } limitvalue(temp, 0, 255); if (ctrls[AWE_MD_PAN_EXCHANGE]) { temp = 255 - temp; } if (forced || temp != voices[voice].apan) { voices[voice].apan = temp; if (temp == 0) voices[voice].aaux = 0xff; else voices[voice].aaux = (-temp) & 0xff; addr = vp->loopstart - 1; addr += FX_OFFSET(fx, fx_lay, AWE_FX_LOOP_START, AWE_FX_COARSE_LOOP_START, vp->mode); temp = (temp<<24) | (unsigned int)addr; awe_poke_dw(AWE_PSST(voice), temp); DEBUG(4,printk("AWE32: [-- loopstart=%x/%x]\n", vp->loopstart, addr)); }}/* effects change during playing */static voidawe_fx_fmmod(int voice, int forced){ awe_voice_info *vp; 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_NO_EFFECT(voice) && !forced) return; if ((vp = voices[voice].sample) == NULL || vp->index == 0) return; awe_poke(AWE_FMMOD(voice), FX_COMB(fx, fx_lay, AWE_FX_LFO1_PITCH, AWE_FX_LFO1_CUTOFF, vp->parm.fmmod));}/* set tremolo (lfo1) volume & frequency */static voidawe_fx_tremfrq(int voice, int forced){ awe_voice_info *vp; 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_NO_EFFECT(voice) && !forced) return; if ((vp = voices[voice].sample) == NULL || vp->index == 0) return; awe_poke(AWE_TREMFRQ(voice), FX_COMB(fx, fx_lay, AWE_FX_LFO1_VOLUME, AWE_FX_LFO1_FREQ, vp->parm.tremfrq));}/* set lfo2 pitch & frequency */static voidawe_fx_fm2frq2(int voice, int forced){ awe_voice_info *vp; 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_NO_EFFECT(voice) && !forced) return; if ((vp = voices[voice].sample) == NULL || vp->index == 0) return; awe_poke(AWE_FM2FRQ2(voice), FX_COMB(fx, fx_lay, AWE_FX_LFO2_PITCH, AWE_FX_LFO2_FREQ, vp->parm.fm2frq2));}/* Q & current address (Q 4bit value, MSB) */static voidawe_fx_filterQ(int voice, int forced){ unsigned int addr; awe_voice_info *vp; 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_NO_EFFECT(voice) && !forced) return; if ((vp = voices[voice].sample) == NULL || vp->index == 0) return; addr = awe_peek_dw(AWE_CCCA(voice)) & 0xffffff; addr |= (FX_BYTE(fx, fx_lay, AWE_FX_FILTERQ, vp->parm.filterQ) << 28); awe_poke_dw(AWE_CCCA(voice), addr);}/* * calculate pitch offset * * 0xE000 is no pitch offset at 44100Hz sample. * Every 4096 is one octave. */static voidawe_calc_pitch(int voice){ voice_info *vp = &voices[voice]; awe_voice_info *ap; awe_chan_info *cp = voices[voice].cinfo; int offset; /* search voice information */ if ((ap = vp->sample) == NULL) return; if (ap->index == 0) { DEBUG(3,printk("AWE32: set sample (%d)\n", ap->sample)); if (awe_set_sample((awe_voice_list*)ap) == 0) return; } /* calculate offset */ if (ap->fixkey >= 0) { DEBUG(3,printk("AWE32: p-> fixkey(%d) tune(%d)\n", ap->fixkey, ap->tune)); offset = (ap->fixkey - ap->root) * 4096 / 12; } else { DEBUG(3,printk("AWE32: p(%d)-> root(%d) tune(%d)\n", vp->note, ap->root, ap->tune)); offset = (vp->note - ap->root) * 4096 / 12; DEBUG(4,printk("AWE32: p-> ofs=%d\n", offset)); } offset = (offset * ap->scaleTuning) / 100; DEBUG(4,printk("AWE32: p-> scale* ofs=%d\n", offset)); offset += ap->tune * 4096 / 1200; DEBUG(4,printk("AWE32: p-> tune+ ofs=%d\n", offset)); if (cp->bender != 0) { DEBUG(3,printk("AWE32: p-> bend(%d) %d\n", voice, cp->bender)); /* (819200: 1 semitone) ==> (4096: 12 semitones) */ offset += cp->bender * cp->bender_range / 2400; } /* add initial pitch correction */ if (FX_ON(&cp->fx_layer[vp->layer], AWE_FX_INIT_PITCH)) offset += cp->fx_layer[vp->layer].val[AWE_FX_INIT_PITCH]; else if (FX_ON(&cp->fx, AWE_FX_INIT_PITCH)) offset += cp->fx.val[AWE_FX_INIT_PITCH]; /* 0xe000: root pitch */ vp->apitch = 0xe000 + ap->rate_offset + offset; DEBUG(4,printk("AWE32: p-> sum aofs=%x, rate_ofs=%d\n", vp->apitch, ap->rate_offset)); if (vp->apitch > 0xffff) vp->apitch = 0xffff; if (vp->apitch < 0) vp->apitch = 0;}#ifdef AWE_HAS_GUS_COMPATIBILITY/* calculate MIDI key and semitone from the specified frequency */static voidawe_calc_pitch_from_freq(int voice, int freq){ voice_info *vp = &voices[voice]; awe_voice_info *ap; FX_Rec *fx = &voices[voice].cinfo->fx; FX_Rec *fx_lay = NULL; int offset; int note; if (voices[voice].layer < MAX_LAYERS) fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; /* search voice information */ if ((ap = vp->sample) == NULL) return; if (ap->index == 0) { DEBUG(3,printk("AWE32: set sample (%d)\n", ap->sample)); if (awe_set_sample((awe_voice_list*)ap) == 0) return; } note = freq_to_note(freq); offset = (note - ap->root * 100 + ap->tune) * 4096 / 1200; offset = (offset * ap->scaleTuning) / 100; if (fx_lay && FX_ON(fx_lay, AWE_FX_INIT_PITCH)) offset += fx_lay->val[AWE_FX_INIT_PITCH]; else if (FX_ON(fx, AWE_FX_INIT_PITCH)) offset += fx->val[AWE_FX_INIT_PITCH]; vp->apitch = 0xe000 + ap->rate_offset + offset; if (vp->apitch > 0xffff) vp->apitch = 0xffff; if (vp->apitch < 0) vp->apitch = 0;}#endif /* AWE_HAS_GUS_COMPATIBILITY *//* * calculate volume attenuation * * Voice volume is controlled by volume attenuation parameter. * So volume becomes maximum when avol is 0 (no attenuation), and * minimum when 255 (-96dB or silence). */static int vol_table[128] = { 255,111,95,86,79,74,70,66,63,61,58,56,54,52,50,49, 47,46,45,43,42,41,40,39,38,37,36,35,34,34,33,32, 31,31,30,29,29,28,27,27,26,26,25,24,24,23,23,22, 22,21,21,21,20,20,19,19,18,18,18,17,17,16,16,16, 15,15,15,14,14,14,13,13,13,12,12,12,11,11,11,10, 10,10,10,9,9,9,8,8,8,8,7,7,7,7,6,6, 6,6,5,5,5,5,5,4,4,4,4,3,3,3,3,3, 2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,};/* tables for volume->attenuation calculation */static unsigned char voltab1[128] = { 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x2b, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, 0x19, 0x19, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};static unsigned char voltab2[128] = { 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x24, 0x23, 0x22, 0x21, 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1c, 0x1b, 0x1a, 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x10, 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00};static unsigned char expressiontab[128] = { 0x7f, 0x6c, 0x62, 0x5a, 0x54, 0x50, 0x4b, 0x48, 0x45, 0x42, 0x40, 0x3d, 0x3b, 0x39, 0x38, 0x36, 0x34, 0x33, 0x31, 0x30, 0x2f, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x24, 0x23, 0x22, 0x21, 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, 0x1a, 0x19, 0x18, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};static voidawe_calc_volume(int voice){ voice_info *vp = &voices[voice]; awe_voice_info *ap; awe_chan_info *cp = voices[voice].cinfo; int vol; /* search voice information */ if ((ap = vp->sample) == NULL) return; ap = vp->sample; if (ap->index == 0) { DEBUG(3,printk("AWE32: set sample (%d)\n", ap->sample)); if (awe_set_sample((awe_voice_list*)ap) == 0) return; } if (ctrls[AWE_MD_NEW_VOLUME_CALC]) { int main_vol = cp->main_vol * ap->amplitude / 127; limitvalue(vp->velocity, 0, 127); limitvalue(main_vol, 0, 127); limitvalue(cp->expression_vol, 0, 127); vol = voltab1[main_vol] + voltab2[vp->velocity]; vol = (vol * 8) / 3; vol += ap->attenuation; if (cp->expression_vol < 127) vol += ((0x100 - vol) * expressiontab[cp->expression_vol])/128; vol += atten_offset; if (atten_relative) vol += ctrls[AWE_MD_ZERO_ATTEN]; limitvalue(vol, 0, 255); vp->avol = vol; } else { /* 0 - 127 */ vol = (vp->velocity * cp->main_vol * cp->expression_vol) / (127*127); vol = vol * ap->amplitude / 127; if (vol < 0) vol = 0; if (vol > 127) vol = 127; /* calc to attenuation */ vol = vol_table[vol]; vol += (int)ap->attenuation; vol += atten_offset; if (atten_relative) vol += ctrls[AWE_MD_ZERO_ATTEN]; if (vol > 255) vol = 255; vp->avol = vol; } if (cp->bank != AWE_DRUM_BANK && ((awe_voice_parm_block*)(&ap->parm))->volatk < 0x7d) { int atten; if (vp->velocity < 70) atten = 70; else atten = vp->velocity; vp->acutoff = (atten * ap->parm.cutoff + 0xa0) >> 7; } else { vp->acutoff = ap->parm.cutoff; } DEBUG(3,printk("AWE32: [-- voice(%d) vol=%x]\n", voice, vol));}/* change master volume */static voidawe_change_master_volume(short val){ limitvalue(val, 0, 127); atten_offset = vol_table[val]; atten_relative = TRUE; awe_update_volume();}/* update volumes of all available channels */static void awe_update_volume(void){ int i; for (i = 0; i < awe_max_voices; i++) awe_set_voice_vol(i, TRUE);}/* set sostenuto on */static void awe_sostenuto_on(int voice, int forced){ if (IS_NO_EFFECT(voice) && !forced) return; voices[voice].sostenuto = 127;}/* drop sustain */static void awe_sustain_off(int voice, int forced){ if (voices[voice].state == AWE_ST_SUSTAINED) { awe_note_off(voice); awe_fx_init(voices[voice].ch); awe_voice_init(voice, FALSE); }}/* terminate and initialize voice */static void awe_terminate_and_init(int voice, int forced){ awe_terminate(voice); awe_fx_init(voices[voice].ch); awe_voice_init(voice, TRUE);}/* * synth operation routines */#define AWE_VOICE_KEY(v) (0x8000 | (v))#define AWE_CHAN_KEY(c,n) (((c) << 8) | ((n) + 1))#define KEY_CHAN_MATCH(key,c) (((key) >> 8) == (c))/* initialize the voice */static voidawe_voice_init(int voice, int init_all){ voice_info *vp = &voices[voice]; /* reset voice search key */ if (playing_mode == AWE_PLAY_DIRECT) vp->key = AWE_VOICE_KEY(voice); else vp->key = 0; /* clear voice mapping */ voice_alloc->map[voice] = 0; /* touch the timing flag */ vp->time = current_alloc_time; /* initialize other parameters if necessary */ if (init_all) { vp->note = -1; vp->velocity = 0; vp->sostenuto = 0; vp->sample = NULL; vp->cinfo = &channels[voice]; vp->ch = voice; vp->state = AWE_ST_OFF; /* emu8000 parameters */ vp->apitch = 0; vp->avol = 255; vp->apan = -1; }}/* clear effects */static void awe_fx_init(int ch){ if (SINGLE_LAYER_MODE() && !ctrls[AWE_MD_KEEP_EFFECT]) { memset(&channels[ch].fx, 0, sizeof(channels[ch].fx)); memset(&channels[ch].fx_layer, 0, sizeof(&channels[ch].fx_layer)); }}/* initialize channel info */static void awe_channel_init(int ch, int init_all){ awe_chan_info *cp = &channels[ch]; cp->channel = ch; if (init_all) { cp->panning = 0; /* zero center */ cp->bender_range = 200; /* sense * 100 */ cp->main_vol = 127; if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(ch)) { cp->instr = ctrls[AWE_MD_DEF_DRUM]; cp->bank = AWE_DRUM_BANK; } else { cp->instr = ctrls[AWE_MD_DEF_PRESET]; cp->bank = ctrls[AWE_MD_DEF_BANK]; } } cp->bender = 0; /* zero tune skew */ cp->expression_vol = 127; cp->chan_press = 0; cp->sustained = 0; if (! ctrls[AWE_MD_KEEP_EFFECT]) { memset(&cp->fx, 0, sizeof(cp->fx)); memset(&cp->fx_layer, 0, sizeof(cp->fx_layer)); }}/* change the voice parameters; voice = channel */static void awe_voice_change(int voice, fx_affect_func func){ int i; switch (playing_mode) { case AWE_PLAY_DIRECT: func(voice, FALSE); break; case AWE_PLAY_INDIRECT: for (i = 0; i < awe_max_voices; i++) if (voices[i].key == AWE_VOICE_KEY(voice)) func(i, FALSE); break; default: for (i = 0; i < awe_max_voices; i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -