📄 awe_wave.c
字号:
if (KEY_CHAN_MATCH(voices[i].key, voice)) func(i, FALSE); break; }}/* * device open / close *//* open device: * reset status of all voices, and clear sample position flag */static intawe_open(int dev, int mode){ if (awe_busy) return -EBUSY; awe_busy = TRUE; /* set default mode */ awe_init_ctrl_parms(FALSE); atten_relative = TRUE; atten_offset = 0; drum_flags = DEFAULT_DRUM_FLAGS; playing_mode = AWE_PLAY_INDIRECT; /* reset voices & channels */ awe_reset(dev); patch_opened = 0; return 0;}/* close device: * reset all voices again (terminate sounds) */static voidawe_close(int dev){ awe_reset(dev); awe_busy = FALSE;}/* set miscellaneous mode parameters */static voidawe_init_ctrl_parms(int init_all){ int i; for (i = 0; i < AWE_MD_END; i++) { if (init_all || ctrl_parms[i].init_each_time) ctrls[i] = ctrl_parms[i].value; }}/* sequencer I/O control: */static intawe_ioctl(int dev, unsigned int cmd, caddr_t arg){ switch (cmd) { case SNDCTL_SYNTH_INFO: if (playing_mode == AWE_PLAY_DIRECT) awe_info.nr_voices = awe_max_voices; else awe_info.nr_voices = AWE_MAX_CHANNELS; memcpy((char*)arg, &awe_info, sizeof(awe_info)); return 0; break; case SNDCTL_SEQ_RESETSAMPLES: awe_reset(dev); awe_reset_samples(); return 0; break; case SNDCTL_SEQ_PERCMODE: /* what's this? */ return 0; break; case SNDCTL_SYNTH_MEMAVL: return memsize - awe_free_mem_ptr() * 2; default: printk(KERN_WARNING "AWE32: unsupported ioctl %d\n", cmd); return -EINVAL; }}static int voice_in_range(int voice){ if (playing_mode == AWE_PLAY_DIRECT) { if (voice < 0 || voice >= awe_max_voices) return FALSE; } else { if (voice < 0 || voice >= AWE_MAX_CHANNELS) return FALSE; } return TRUE;}static void release_voice(int voice, int do_sustain){ if (IS_NO_SOUND(voice)) return; if (do_sustain && (voices[voice].cinfo->sustained == 127 || voices[voice].sostenuto == 127)) voices[voice].state = AWE_ST_SUSTAINED; else { awe_note_off(voice); awe_fx_init(voices[voice].ch); awe_voice_init(voice, FALSE); }}/* release all notes */static void awe_note_off_all(int do_sustain){ int i; for (i = 0; i < awe_max_voices; i++) release_voice(i, do_sustain);}/* kill a voice: * not terminate, just release the voice. */static intawe_kill_note(int dev, int voice, int note, int velocity){ int i, v2, key; DEBUG(2,printk("AWE32: [off(%d) nt=%d vl=%d]\n", voice, note, velocity)); if (! voice_in_range(voice)) return -EINVAL; switch (playing_mode) { case AWE_PLAY_DIRECT: case AWE_PLAY_INDIRECT: key = AWE_VOICE_KEY(voice); break; case AWE_PLAY_MULTI2: v2 = voice_alloc->map[voice] >> 8; voice_alloc->map[voice] = 0; voice = v2; if (voice < 0 || voice >= AWE_MAX_CHANNELS) return -EINVAL; /* continue to below */ default: key = AWE_CHAN_KEY(voice, note); break; } for (i = 0; i < awe_max_voices; i++) { if (voices[i].key == key) release_voice(i, TRUE); } return 0;}static void start_or_volume_change(int voice, int velocity){ voices[voice].velocity = velocity; awe_calc_volume(voice); if (voices[voice].state == AWE_ST_STANDBY) awe_note_on(voice); else if (voices[voice].state == AWE_ST_ON) awe_set_volume(voice, FALSE);}static void set_and_start_voice(int voice, int state){ /* calculate pitch & volume parameters */ voices[voice].state = state; awe_calc_pitch(voice); awe_calc_volume(voice); if (state == AWE_ST_ON) awe_note_on(voice);}/* 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 voice, int note, int velocity){ int i, key, state, volonly; DEBUG(2,printk("AWE32: [on(%d) nt=%d vl=%d]\n", voice, note, velocity)); if (! voice_in_range(voice)) return -EINVAL; if (velocity == 0) state = AWE_ST_STANDBY; /* stand by for playing */ else state = AWE_ST_ON; /* really play */ volonly = FALSE; switch (playing_mode) { case AWE_PLAY_DIRECT: case AWE_PLAY_INDIRECT: key = AWE_VOICE_KEY(voice); if (note == 255) volonly = TRUE; break; case AWE_PLAY_MULTI2: voice = voice_alloc->map[voice] >> 8; if (voice < 0 || voice >= AWE_MAX_CHANNELS) return -EINVAL; /* continue to below */ default: if (note >= 128) { /* key volume mode */ note -= 128; volonly = TRUE; } key = AWE_CHAN_KEY(voice, note); break; } /* dynamic volume change */ if (volonly) { for (i = 0; i < awe_max_voices; i++) { if (voices[i].key == key) start_or_volume_change(i, velocity); } return 0; } /* if the same note still playing, stop it */ if (playing_mode != AWE_PLAY_DIRECT || ctrls[AWE_MD_EXCLUSIVE_SOUND]) { for (i = 0; i < awe_max_voices; i++) if (voices[i].key == key) { if (voices[i].state == AWE_ST_ON) { awe_note_off(i); awe_voice_init(i, FALSE); } else if (voices[i].state == AWE_ST_STANDBY) awe_voice_init(i, TRUE); } } /* allocate voices */ if (playing_mode == AWE_PLAY_DIRECT) awe_alloc_one_voice(voice, note, velocity); else awe_alloc_multi_voices(voice, note, velocity, key); /* turn off other voices exlusively (for drums) */ for (i = 0; i < awe_max_voices; i++) if (voices[i].key == key) awe_exclusive_off(i); /* set up pitch and volume parameters */ for (i = 0; i < awe_max_voices; i++) { if (voices[i].key == key && voices[i].state == AWE_ST_OFF) set_and_start_voice(i, state); } return 0;}/* calculate hash key */static intawe_search_key(int bank, int preset, int note){ unsigned int key;#if 1 /* new hash table */ if (bank == AWE_DRUM_BANK) key = preset + note + 128; else key = bank + preset;#else key = preset;#endif key %= AWE_MAX_PRESETS; return (int)key;}/* search instrument from hash table */static awe_voice_list *awe_search_instr(int bank, int preset, int note){ awe_voice_list *p; int key, key2; key = awe_search_key(bank, preset, note); for (p = preset_table[key]; p; p = p->next_bank) { if (p->instr == preset && p->bank == bank) return p; } key2 = awe_search_key(bank, preset, 0); /* search default */ if (key == key2) return NULL; for (p = preset_table[key2]; p; p = p->next_bank) { if (p->instr == preset && p->bank == bank) return p; } return NULL;}/* assign the instrument to a voice */static intawe_set_instr_2(int dev, int voice, int instr_no){ if (playing_mode == AWE_PLAY_MULTI2) { voice = voice_alloc->map[voice] >> 8; if (voice < 0 || voice >= AWE_MAX_CHANNELS) return -EINVAL; } return awe_set_instr(dev, voice, instr_no);}/* assign the instrument to a channel; voice is the channel number */static intawe_set_instr(int dev, int voice, int instr_no){ awe_chan_info *cinfo; if (! voice_in_range(voice)) return -EINVAL; if (instr_no < 0 || instr_no >= AWE_MAX_PRESETS) return -EINVAL; cinfo = &channels[voice]; cinfo->instr = instr_no; DEBUG(2,printk("AWE32: [program(%d) %d]\n", voice, instr_no)); return 0;}/* reset all voices; terminate sounds and initialize parameters */static voidawe_reset(int dev){ int i; current_alloc_time = 0; /* don't turn off voice 31 and 32. they are used also for FM voices */ for (i = 0; i < awe_max_voices; i++) { awe_terminate(i); awe_voice_init(i, TRUE); } for (i = 0; i < AWE_MAX_CHANNELS; i++) awe_channel_init(i, TRUE); for (i = 0; i < 16; i++) { awe_operations.chn_info[i].controllers[CTL_MAIN_VOLUME] = 127; awe_operations.chn_info[i].controllers[CTL_EXPRESSION] = 127; } 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);#ifdef AWE_HAS_GUS_COMPATIBILITY else awe_hw_gus_control(dev, cmd & _AWE_MODE_VALUE_MASK, event);#endif}#ifdef AWE_HAS_GUS_COMPATIBILITY/* GUS compatible controls */static voidawe_hw_gus_control(int dev, int cmd, unsigned char *event){ int voice, i, key; unsigned short p1; short p2; int plong; if (MULTI_LAYER_MODE()) return; if (cmd == _GUS_NUMVOICES) return; voice = event[3]; if (! voice_in_range(voice)) return; p1 = *(unsigned short *) &event[4]; p2 = *(short *) &event[6]; plong = *(int*) &event[4]; switch (cmd) { case _GUS_VOICESAMPLE: awe_set_instr(dev, voice, p1); return; case _GUS_VOICEBALA: /* 0 to 15 --> -128 to 127 */ awe_panning(dev, voice, ((int)p1 << 4) - 128); return; case _GUS_VOICEVOL: case _GUS_VOICEVOL2: /* not supported yet */ return; case _GUS_RAMPRANGE: case _GUS_RAMPRATE: case _GUS_RAMPMODE: case _GUS_RAMPON: case _GUS_RAMPOFF: /* volume ramping not supported */ return; case _GUS_VOLUME_SCALE: return; case _GUS_VOICE_POS: FX_SET(&channels[voice].fx, AWE_FX_SAMPLE_START, (short)(plong & 0x7fff)); FX_SET(&channels[voice].fx, AWE_FX_COARSE_SAMPLE_START, (plong >> 15) & 0xffff); return; } key = AWE_VOICE_KEY(voice); for (i = 0; i < awe_max_voices; i++) { if (voices[i].key == key) { switch (cmd) { case _GUS_VOICEON: awe_note_on(i); break; case _GUS_VOICEOFF: awe_terminate(i); awe_fx_init(voices[i].ch); awe_voice_init(i, TRUE); break; case _GUS_VOICEFADE: awe_note_off(i); awe_fx_init(voices[i].ch); awe_voice_init(i, FALSE); break; case _GUS_VOICEFREQ: awe_calc_pitch_from_freq(i, plong); break; } } }}#endif /* gus_compat *//* AWE32 specific controls */static voidawe_hw_awe_control(int dev, int cmd, unsigned char *event){ int voice; unsigned short p1; short p2; int i; voice = event[3]; if (! voice_in_range(voice)) return; if (playing_mode == AWE_PLAY_MULTI2) { voice = voice_alloc->map[voice] >> 8; if (voice < 0 || voice >= AWE_MAX_CHANNELS) return; } p1 = *(unsigned short *) &eve
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -