📄 awe_wave.c
字号:
*/static struct synth_operations awe_operations ={ owner: THIS_MODULE, id: "EMU8K", info: &awe_info, midi_dev: 0, synth_type: SYNTH_TYPE_SAMPLE, synth_subtype: SAMPLE_TYPE_AWE32, open: awe_open, close: awe_close, ioctl: awe_ioctl, kill_note: awe_kill_note, start_note: awe_start_note, set_instr: awe_set_instr_2, reset: awe_reset, hw_control: awe_hw_control, load_patch: awe_load_patch, aftertouch: awe_aftertouch, controller: awe_controller, panning: awe_panning, volume_method: awe_volume_method, bender: awe_bender, alloc_voice: awe_alloc, setup_voice: awe_setup_voice};/* * General attach / unload interface */static int __init _attach_awe(void){ if (awe_present) return 0; /* for OSS38.. called twice? */ /* check presence of AWE32 card */ if (! awe_detect()) { printk(KERN_ERR "AWE32: not detected\n"); return 0; } /* check AWE32 ports are available */ if (awe_check_port()) { printk(KERN_ERR "AWE32: I/O area already used.\n"); return 0; } /* set buffers to NULL */ sfhead = sftail = NULL; my_dev = sound_alloc_synthdev(); if (my_dev == -1) { printk(KERN_ERR "AWE32 Error: too many synthesizers\n"); return 0; } voice_alloc = &awe_operations.alloc; voice_alloc->max_voice = awe_max_voices; synth_devs[my_dev] = &awe_operations;#ifdef CONFIG_AWE32_MIXER attach_mixer();#endif#ifdef CONFIG_AWE32_MIDIEMU attach_midiemu();#endif /* reserve I/O ports for awedrv */ awe_request_region(); /* clear all samples */ awe_reset_samples(); /* intialize AWE32 hardware */ awe_initialize(); sprintf(awe_info.name, "AWE32-%s (RAM%dk)", AWEDRV_VERSION, memsize/1024); printk(KERN_INFO "<SoundBlaster EMU8000 (RAM%dk)>\n", memsize/1024); awe_present = TRUE; return 1;}static void free_tables(void){ if (sftail) { sf_list *p, *prev; for (p = sftail; p; p = prev) { prev = p->prev; awe_free_sf(p); } } sfhead = sftail = NULL;}static void __exit _unload_awe(void){ if (awe_present) { awe_reset_samples(); awe_release_region(); free_tables();#ifdef CONFIG_AWE32_MIXER unload_mixer();#endif#ifdef CONFIG_AWE32_MIDIEMU unload_midiemu();#endif sound_unload_synthdev(my_dev); awe_present = FALSE; }}/* * clear sample tables */static voidawe_reset_samples(void){ /* free all bank tables */ memset(preset_table, 0, sizeof(preset_table)); free_tables(); current_sf_id = 0; locked_sf_id = 0; patch_opened = 0;}/* * EMU register access *//* select a given AWE32 pointer */static int awe_ports[5];static int port_setuped = FALSE;static int awe_cur_cmd = -1;#define awe_set_cmd(cmd) \if (awe_cur_cmd != cmd) { outw(cmd, awe_ports[Pointer]); awe_cur_cmd = cmd; }/* store values to i/o port array */static void setup_ports(int port1, int port2, int port3){ awe_ports[0] = port1; if (port2 == 0) port2 = port1 + 0x400; awe_ports[1] = port2; awe_ports[2] = port2 + 2; if (port3 == 0) port3 = port1 + 0x800; awe_ports[3] = port3; awe_ports[4] = port3 + 2; port_setuped = TRUE;}/* write 16bit data */static voidawe_poke(unsigned short cmd, unsigned short port, unsigned short data){ awe_set_cmd(cmd); outw(data, awe_ports[port]);}/* write 32bit data */static voidawe_poke_dw(unsigned short cmd, unsigned short port, unsigned int data){ unsigned short addr = awe_ports[port]; awe_set_cmd(cmd); outw(data, addr); /* write lower 16 bits */ outw(data >> 16, addr + 2); /* write higher 16 bits */}/* read 16bit data */static unsigned shortawe_peek(unsigned short cmd, unsigned short port){ unsigned short k; awe_set_cmd(cmd); k = inw(awe_ports[port]); return k;}/* read 32bit data */static unsigned intawe_peek_dw(unsigned short cmd, unsigned short port){ unsigned int k1, k2; unsigned short addr = awe_ports[port]; awe_set_cmd(cmd); k1 = inw(addr); k2 = inw(addr + 2); k1 |= k2 << 16; return k1;}/* wait delay number of AWE32 44100Hz clocks */#ifdef WAIT_BY_LOOP /* wait by loop -- that's not good.. */static voidawe_wait(unsigned short delay){ unsigned short clock, target; unsigned short port = awe_ports[AWE_WC_Port]; int counter; /* sample counter */ awe_set_cmd(AWE_WC_Cmd); clock = (unsigned short)inw(port); target = clock + delay; counter = 0; if (target < clock) { for (; (unsigned short)inw(port) > target; counter++) if (counter > 65536) break; } for (; (unsigned short)inw(port) < target; counter++) if (counter > 65536) break;}#elsestatic void awe_wait(unsigned short delay){ current->state = TASK_INTERRUPTIBLE; schedule_timeout((HZ*(unsigned long)delay + 44099)/44100);}/*static void awe_wait(unsigned short delay){ udelay(((unsigned long)delay * 1000000L + 44099) / 44100);}*/#endif /* wait by loop *//* write a word data */#define awe_write_dram(c) awe_poke(AWE_SMLD, c)/* * port check / request * 0x620-623, 0xA20-A23, 0xE20-E23 */static int __initawe_check_port(void){ if (! port_setuped) return 0; return (check_region(awe_ports[0], 4) || check_region(awe_ports[1], 4) || check_region(awe_ports[3], 4));}static void __initawe_request_region(void){ if (! port_setuped) return; request_region(awe_ports[0], 4, "sound driver (AWE32)"); request_region(awe_ports[1], 4, "sound driver (AWE32)"); request_region(awe_ports[3], 4, "sound driver (AWE32)");}static void __exitawe_release_region(void){ if (! port_setuped) return; release_region(awe_ports[0], 4); release_region(awe_ports[1], 4); release_region(awe_ports[3], 4);}/* * initialization of AWE driver */static voidawe_initialize(void){ DEBUG(0,printk("AWE32: initializing..\n")); /* initialize hardware configuration */ awe_poke(AWE_HWCF1, 0x0059); awe_poke(AWE_HWCF2, 0x0020); /* disable audio; this seems to reduce a clicking noise a bit.. */ awe_poke(AWE_HWCF3, 0); /* initialize audio channels */ awe_init_audio(); /* initialize DMA */ awe_init_dma(); /* initialize init array */ awe_init_array(); /* check DRAM memory size */ awe_check_dram(); /* initialize the FM section of the AWE32 */ awe_init_fm(); /* set up voice envelopes */ awe_tweak(); /* enable audio */ awe_poke(AWE_HWCF3, 0x0004); /* set default values */ awe_init_ctrl_parms(TRUE); /* set equalizer */ awe_update_equalizer(); /* set reverb & chorus modes */ awe_update_reverb_mode(); awe_update_chorus_mode();}/* * AWE32 voice parameters *//* initialize voice_info record */static voidawe_init_voice_info(awe_voice_info *vp){ vp->sample = 0; vp->rate_offset = 0; vp->start = 0; vp->end = 0; vp->loopstart = 0; vp->loopend = 0; vp->mode = 0; vp->root = 60; vp->tune = 0; vp->low = 0; vp->high = 127; vp->vellow = 0; vp->velhigh = 127; vp->fixkey = -1; vp->fixvel = -1; vp->fixpan = -1; vp->pan = -1; vp->exclusiveClass = 0; vp->amplitude = 127; vp->attenuation = 0; vp->scaleTuning = 100; awe_init_voice_parm(&vp->parm);}/* initialize voice_parm record: * Env1/2: delay=0, attack=0, hold=0, sustain=0, decay=0, release=0. * Vibrato and Tremolo effects are zero. * Cutoff is maximum. * Chorus and Reverb effects are zero. */static voidawe_init_voice_parm(awe_voice_parm *pp){ pp->moddelay = 0x8000; pp->modatkhld = 0x7f7f; pp->moddcysus = 0x7f7f; pp->modrelease = 0x807f; pp->modkeyhold = 0; pp->modkeydecay = 0; pp->voldelay = 0x8000; pp->volatkhld = 0x7f7f; pp->voldcysus = 0x7f7f; pp->volrelease = 0x807f; pp->volkeyhold = 0; pp->volkeydecay = 0; pp->lfo1delay = 0x8000; pp->lfo2delay = 0x8000; pp->pefe = 0; pp->fmmod = 0; pp->tremfrq = 0; pp->fm2frq2 = 0; pp->cutoff = 0xff; pp->filterQ = 0; pp->chorus = 0; pp->reverb = 0;} #ifdef AWE_HAS_GUS_COMPATIBILITY/* convert frequency mHz to abstract cents (= midi key * 100) */static intfreq_to_note(int mHz){ /* abscents = log(mHz/8176) / log(2) * 1200 */ unsigned int max_val = (unsigned int)0xffffffff / 10000; int i, times; unsigned int base; unsigned int freq; int note, tune; if (mHz == 0) return 0; if (mHz < 0) return 12799; /* maximum */ freq = mHz; note = 0; for (base = 8176 * 2; freq >= base; base *= 2) { note += 12; if (note >= 128) /* over maximum */ return 12799; } base /= 2; /* to avoid overflow... */ times = 10000; while (freq > max_val) { max_val *= 10; times /= 10; base /= 10; } freq = freq * times / base; for (i = 0; i < 12; i++) { if (freq < semitone_tuning[i+1]) break; note++; } tune = 0; freq = freq * 10000 / semitone_tuning[i]; for (i = 0; i < 100; i++) { if (freq < cent_tuning[i+1]) break; tune++; } return note * 100 + tune;}/* convert Hz to AWE32 rate offset: * sample pitch offset for the specified sample rate * rate=44100 is no offset, each 4096 is 1 octave (twice). * eg, when rate is 22050, this offset becomes -4096. */static intcalc_rate_offset(int Hz){ /* offset = log(Hz / 44100) / log(2) * 4096 */ int freq, base, i; /* maybe smaller than max (44100Hz) */ if (Hz <= 0 || Hz >= 44100) return 0; base = 0; for (freq = Hz * 2; freq < 44100; freq *= 2) base++; base *= 1200; freq = 44100 * 10000 / (freq/2); for (i = 0; i < 12; i++) { if (freq < semitone_tuning[i+1]) break; base += 100; } freq = freq * 10000 / semitone_tuning[i]; for (i = 0; i < 100; i++) { if (freq < cent_tuning[i+1]) break; base++; } return -base * 4096 / 1200;}/* * convert envelope time parameter to AWE32 raw parameter */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -