📄 awe_wave.c
字号:
awe_release_region(); }}#ifdef AWE_OBSOLETE_VOXWAREint probe_awe_obsolete(struct address_info *hw_config){ return 1; /*return awe_detect();*/}#endif/*================================================================ * clear sample tables *================================================================*/static voidawe_reset_samples(void){ int i; /* free all bank tables */ for (i = 0; i < AWE_MAX_PRESETS; i++) { preset_table[i] = NULL; } free_mem_ptr = 0; last_sample = free_sample = 0; last_info = free_info = 0; current_sf_id = 0; loaded_once = 0;}/*================================================================ * EMU register access *================================================================*//* select a given AWE32 pointer */static int awe_cur_cmd = -1;#define awe_set_cmd(cmd) \if (awe_cur_cmd != cmd) { OUTW(cmd, awe_base + 0x802); awe_cur_cmd = cmd; }#define awe_port(port) (awe_base - 0x620 + port)/* write 16bit data */INLINE static voidawe_poke(unsigned short cmd, unsigned short port, unsigned short data){ awe_set_cmd(cmd); OUTW(data, awe_port(port));}/* write 32bit data */INLINE static voidawe_poke_dw(unsigned short cmd, unsigned short port, unsigned long data){ awe_set_cmd(cmd); OUTW(data, awe_port(port)); /* write lower 16 bits */ OUTW(data >> 16, awe_port(port)+2); /* write higher 16 bits */}/* read 16bit data */INLINE static unsigned shortawe_peek(unsigned short cmd, unsigned short port){ unsigned short k; awe_set_cmd(cmd); k = inw(awe_port(port)); return k;}/* read 32bit data */INLINE static unsigned longawe_peek_dw(unsigned short cmd, unsigned short port){ unsigned long k1, k2; awe_set_cmd(cmd); k1 = inw(awe_port(port)); k2 = inw(awe_port(port)+2); k1 |= k2 << 16; return k1;}/* wait delay number of AWE32 44100Hz clocks */static voidawe_wait(unsigned short delay){ unsigned short clock, target; unsigned short port = awe_port(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;}#ifndef AWE_OBSOLETE_VOXWARE/*================================================================ * port check / request * 0x620-622, 0xA20-A22, 0xE20-E22 *================================================================*/static intawe_check_port(void){ return (check_region(awe_port(Data0), 3) || check_region(awe_port(Data1), 3) || check_region(awe_port(Data3), 3));}static voidawe_request_region(void){ request_region(awe_port(Data0), 3, "sound driver (AWE32)"); request_region(awe_port(Data1), 3, "sound driver (AWE32)"); request_region(awe_port(Data3), 3, "sound driver (AWE32)");}static voidawe_release_region(void){ release_region(awe_port(Data0), 3); release_region(awe_port(Data1), 3); release_region(awe_port(Data3), 3);}#endif /* !AWE_OBSOLETE_VOXWARE *//*================================================================ * AWE32 initialization *================================================================*/static voidawe_initialize(void){ unsigned short data; DECL_INTR_FLAGS(flags); DEBUG(0,printk("AWE32: initializing..\n")); DISABLE_INTR(flags); /* check for an error condition */ data = awe_peek(AWE_U1); if (!(data & 0x000F) == 0x000C) { FATALERR(printk("AWE32: can't initialize AWE32\n")); } /* initialize hardware configuration */ awe_poke(AWE_HWCF1, 0x0059); awe_poke(AWE_HWCF2, 0x0020); /* disable audio output */ awe_poke(AWE_HWCF3, 0x0000); /* initialize audio channels */ awe_init_audio(); /* initialize init array */ awe_init_dma(); awe_init_array(); /* check DRAM memory size */ awe_mem_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); data = awe_peek(AWE_HWCF2); if (~data & 0x40) { FATALERR(printk("AWE32: Unable to initialize AWE32.\n")); } RESTORE_INTR(flags);}/*================================================================ * AWE32 voice parameters *================================================================*//* initialize voice_info record */static voidawe_init_voice_info(awe_voice_info *vp){ vp->sf_id = 0; 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;} /* convert frequency mHz to abstract cents (= midi key * 100) */static intfreq_to_note(int mHz){ /* abscents = log(mHz/8176) / log(2) * 1200 */ unsigned long max_val = (unsigned long)0xffffffff / 10000; int i, times; unsigned long base; unsigned long 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 *----------------------------------------------------------------*//* attack & decay/release time table (mHz) */static short attack_time_tbl[128] = {32767, 5939, 3959, 2969, 2375, 1979, 1696, 1484, 1319, 1187, 1079, 989, 913, 848, 791, 742, 698, 659, 625, 593, 565, 539, 516, 494, 475, 456, 439, 424, 409, 395, 383, 371, 359, 344, 330, 316, 302, 290, 277, 266, 255, 244, 233, 224, 214, 205, 196, 188, 180, 173, 165, 158, 152, 145, 139, 133, 127, 122, 117, 112, 107, 103, 98, 94, 90, 86, 83, 79, 76, 73, 69, 67, 64, 61, 58, 56, 54, 51, 49, 47, 45, 43, 41, 39, 38, 36, 35, 33, 32, 30, 29, 28, 27, 25, 24, 23, 22, 21, 20, 20, 19, 18, 17, 16, 16, 15, 14, 14, 13, 13, 12, 11, 11, 10, 10, 10, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 0,};static short decay_time_tbl[128] = {32767, 3651, 3508, 3371, 3239, 3113, 2991, 2874, 2761, 2653, 2550, 2450, 2354, 2262, 2174, 2089, 2007, 1928, 1853, 1781, 1711, 1644, 1580, 1518, 1459, 1401, 1347, 1294, 1243, 1195, 1148, 1103, 1060, 1018, 979, 940, 904, 868, 834, 802, 770, 740, 711, 683, 657, 631, 606, 582, 560, 538, 517, 496, 477, 458, 440, 423, 407, 391, 375, 361, 347, 333, 320, 307, 295, 284, 273, 262, 252, 242, 232, 223, 215, 206, 198, 190, 183, 176, 169, 162, 156, 150, 144, 138, 133, 128, 123, 118, 113, 109, 104, 100, 96, 93, 89, 85, 82, 79, 76, 73, 70, 67, 64, 62, 60, 57, 55, 53, 51, 49, 47, 45, 43, 41, 40, 38, 37, 35, 34, 32, 31, 30, 29, 28, 27, 25, 24, 0,};/*static intcalc_parm_delay(int msec){ return (0x8000 - msec * 1000 / 725);}*/static intcalc_parm_hold(int msec){ int val = 0x7f - (unsigned char)(msec / 92); if (val < 1) val = 1; if (val > 127) val = 127; return val;}static intcalc_parm_attack(int msec){ return calc_parm_search(msec, attack_time_tbl);}static intcalc_parm_decay(int msec){ return calc_parm_search(msec, decay_time_tbl);}static intcalc_parm_search(int msec, short *table){ int left = 0, right = 127, mid; while (left < right) { mid = (left + right) / 2; if (msec < (int)table[mid]) left = mid + 1; else right = mid; } return left;}/*================================================================ * effects table *================================================================*//* set an effect value */#define FX_SET(v,type,value) \(voices[v].fx_flags[(type)/8] |= (1<<((type)%8)),\ voices[v].fx[type] = (value))/* check the effect value is set */#define FX_ON(v,type) (voices[v].fx_flags[(type)/8] & (1<<((type)%8)))#if 0#define FX_BYTE(v,type,value)\ (FX_ON(v,type) ? (unsigned char)voices[v].fx[type] :\ (unsigned char)(value))#define FX_WORD(v,type,value)\ (FX_ON(v,type) ? (unsigned short)voices[v].fx[type] :\ (unsigned short)(value))#else/* get byte effect value */static unsigned char FX_BYTE(int v, int type, unsigned char value){ unsigned char tmp; if (FX_ON(v,type)) tmp = (unsigned char)voices[v].fx[type]; else tmp = value; DEBUG(4,printk("AWE32: [-- byte(%d) = %x]\n", type, tmp)); return tmp;}/* get word effect value */static unsigned short FX_WORD(int v, int type, unsigned short value){ unsigned short tmp; if (FX_ON(v,type)) tmp = (unsigned short)voices[v].fx[type]; else tmp = value; DEBUG(4,printk("AWE32: [-- word(%d) = %x]\n", type, tmp)); return tmp;}#endif/* get word (upper=type1/lower=type2) effect value */static unsigned short FX_COMB(int v, int type1, int type2, unsigned short value){ unsigned short tmp; if (FX_ON(v, type1)) tmp = (unsigned short)(voices[v].fx[type1]) << 8; else tmp = value & 0xff00; if (FX_ON(v, type2)) tmp |= (unsigned short)(voices[v].fx[type2]) & 0xff; else tmp |= value & 0xff; DEBUG(4,printk("AWE32: [-- comb(%d/%d) = %x]\n", type1, type2, tmp)); return tmp;}/* address offset */static longFX_OFFSET(int voice, int lo, int hi){ awe_voice_info *vp; long addr; if ((vp = voices[voice].sample) == NULL || vp->index < 0) return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -