📄 awe_wave.c
字号:
/* * sound/awe_wave.c * * The low level driver for the AWE32/Sound Blaster 32 wave table synth. * version 0.2.0a; Oct. 30, 1996 * * (C) 1996 Takashi Iwai * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. 2. * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *//* if you're using obsolete VoxWare 3.0.x on Linux 1.2.x (or FreeBSD), * uncomment the following line */#define AWE_OBSOLETE_VOXWARE#ifdef AWE_OBSOLETE_VOXWARE#ifdef __FreeBSD__# include <i386/isa/sound/sound_config.h>#else# include "sound_config.h"#endif#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AWE32)#define CONFIG_AWE32_SYNTH#endif#else /* AWE_OBSOLETE_VOXWARE */#include "../sound_config.h"#endif /* AWE_OBSOLETE_VOXWARE *//*----------------------------------------------------------------* * compile condition *----------------------------------------------------------------*//* initialize FM passthrough even without extended RAM *//*#define AWE_ALWAYS_INIT_FM*//* debug on */#define AWE_DEBUG_ON/* verify checksum for uploading samples */#define AWE_CHECKSUM_DATA#define AWE_CHECKSUM_MEMORY/* disable interruption during sequencer operation *//*#define AWE_NEED_DISABLE_INTR*//* use buffered access to user wave data */#define AWE_USE_BUFFERED_IO#ifdef linux/* i tested this only on my linux */#define INLINE __inline__#else#define INLINE /**/#endif/*----------------------------------------------------------------*/#ifdef CONFIG_AWE32_SYNTH#include <i386/isa/sound/awe_hw.h>#include <i386/isa/sound/awe_voice.h>#ifdef AWE_OBSOLETE_VOXWARE#ifdef __FreeBSD__#define SEQUENCER_C#endif#include <i386/isa/sound/tuning.h>#else#include "../tuning.h"#endif#ifdef linux# include <linux/ultrasound.h>#elif defined(__FreeBSD__)# include <machine/ultrasound.h>#endif/*---------------------------------------------------------------- * debug message *----------------------------------------------------------------*/#ifdef AWE_DEBUG_ONstatic int debug_mode = 0;#define DEBUG(LVL,XXX) {if (debug_mode > LVL) { XXX; }}#define ERRMSG(XXX) {if (debug_mode) { XXX; }}#define FATALERR(XXX) XXX#else#define DEBUG(LVL,XXX) /**/#define ERRMSG(XXX) XXX#define FATALERR(XXX) XXX#endif/*---------------------------------------------------------------- * bank and voice record *----------------------------------------------------------------*//* bank record */typedef struct _awe_voice_list { unsigned char bank, instr; awe_voice_info v; struct _awe_voice_list *next_instr; struct _awe_voice_list *next_bank;} awe_voice_list;/* sample and information table */static awe_sample_info *samples;static awe_voice_list *infos;#define AWE_MAX_PRESETS 256#define AWE_DEFAULT_BANK 0/* preset table index */static awe_voice_list *preset_table[AWE_MAX_PRESETS];/*---------------------------------------------------------------- * voice table *----------------------------------------------------------------*/#define AWE_FX_BYTES ((AWE_FX_END+7)/8)typedef struct _voice_info { int state; /* status (on = 1, off = 0) */ int note; /* midi key (0-127) */ int velocity; /* midi velocity (0-127) */ int bender; /* midi pitchbend (-8192 - 8192) */ int bender_range; /* midi bender range (x100) */ int panning; /* panning (0-127) */ int main_vol; /* channel volume (0-127) */ int expression_vol; /* midi expression (0-127) */ /* EMU8000 parameters */ int apitch; /* pitch parameter */ int avol; /* volume parameter */ /* instrument parameters */ int bank; /* current tone bank */ int instr; /* current program */ awe_voice_list *vrec; awe_voice_info *sample; /* channel effects */ unsigned char fx_flags[AWE_FX_BYTES]; short fx[AWE_FX_END];} voice_info;static voice_info voices[AWE_MAX_VOICES];/*---------------------------------------------------------------- * global variables *----------------------------------------------------------------*//* awe32 base address (overwritten at initialization) */static int awe_base = 0;/* memory byte size (overwritten at initialization) */static long awe_mem_size = 0;/* maximum channels for playing */static int awe_max_voices = AWE_MAX_VOICES;static long free_mem_ptr = 0; /* free word byte size */static int free_info = 0; /* free info tables */static int last_info = 0; /* last loaded info index */static int free_sample = 0; /* free sample tables */static int last_sample = 0; /* last loaded sample index */static int loaded_once = 0; /* samples are loaded after init? */static unsigned short current_sf_id = 0; /* internal id */static int reverb_mode = 0; /* reverb mode */static int chorus_mode = 0; /* chorus mode */static unsigned short init_atten = 32; /* 12dB */static int awe_present = 0; /* awe device present? */static int awe_busy = 0; /* awe device opened? */static int awe_gus_bank = AWE_DEFAULT_BANK; /* GUS default bank number */static struct synth_info awe_info = { "AWE32 Synth", /* name */ 0, /* device */ SYNTH_TYPE_SAMPLE, /* synth_type */ SAMPLE_TYPE_AWE32, /* synth_subtype */ 0, /* perc_mode (obsolete) */ AWE_MAX_VOICES, /* nr_voices */ 0, /* nr_drums (obsolete) */ AWE_MAX_INFOS /* instr_bank_size */};static struct voice_alloc_info *voice_alloc; /* set at initialization *//*---------------------------------------------------------------- * function prototypes *----------------------------------------------------------------*/#ifndef AWE_OBSOLETE_VOXWAREstatic int awe_check_port(void);static void awe_request_region(void);static void awe_release_region(void);#endifstatic void awe_reset_samples(void);/* emu8000 chip i/o access */static void awe_poke(unsigned short cmd, unsigned short port, unsigned short data);static void awe_poke_dw(unsigned short cmd, unsigned short port, unsigned long data);static unsigned short awe_peek(unsigned short cmd, unsigned short port);static unsigned long awe_peek_dw(unsigned short cmd, unsigned short port);static void awe_wait(unsigned short delay);/* initialize emu8000 chip */static void awe_initialize(void);/* set voice parameters */static void awe_init_voice_info(awe_voice_info *vp);static void awe_init_voice_parm(awe_voice_parm *pp);static int freq_to_note(int freq);static int calc_rate_offset(int Hz);/*static int calc_parm_delay(int msec);*/static int calc_parm_hold(int msec);static int calc_parm_attack(int msec);static int calc_parm_decay(int msec);static int calc_parm_search(int msec, short *table);/* turn on/off note */static void awe_note_on(int voice);static void awe_note_off(int voice);static void awe_terminate(int voice);static void awe_exclusive_off(int voice);/* calculate voice parameters */static void awe_set_pitch(int voice);static void awe_set_volume(int voice);static void awe_set_pan(int voice, int forced);static void awe_fx_fmmod(int voice);static void awe_fx_tremfrq(int voice);static void awe_fx_fm2frq2(int voice);static void awe_fx_cutoff(int voice);static void awe_fx_initpitch(int voice);static void awe_calc_pitch(int voice);static void awe_calc_pitch_from_freq(int voice, int freq);static void awe_calc_volume(int voice);static void awe_voice_init(int voice, int inst_only);/* sequencer interface */static int awe_open(int dev, int mode);static void awe_close(int dev);static int awe_ioctl(int dev, unsigned int cmd, caddr_t arg);static int awe_kill_note(int dev, int voice, int note, int velocity);static int awe_start_note(int dev, int v, int note_num, int volume);static int awe_set_instr(int dev, int voice, int instr_no);static void awe_reset(int dev);static void awe_hw_control(int dev, unsigned char *event);static int awe_load_patch(int dev, int format, const char *addr, int offs, int count, int pmgr_flag);static void awe_aftertouch(int dev, int voice, int pressure);static void awe_controller(int dev, int voice, int ctrl_num, int value);static void awe_panning(int dev, int voice, int value);static void awe_volume_method(int dev, int mode);static int awe_patchmgr(int dev, struct patmgr_info *rec);static void awe_bender(int dev, int voice, int value);static int awe_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc);static void awe_setup_voice(int dev, int voice, int chn);/* hardware controls */static void awe_hw_gus_control(int dev, int cmd, unsigned char *event);static void awe_hw_awe_control(int dev, int cmd, unsigned char *event);/* voice search */static awe_voice_info *awe_search_voice(int voice, int note);static awe_voice_list *awe_search_instr(int bank, int preset);/* load / remove patches */static void awe_check_loaded(void);static int awe_load_info(awe_patch_info *patch, const char *addr);static int awe_load_data(awe_patch_info *patch, const char *addr);static int awe_load_guspatch(const char *addr, int offs, int size, int pmgr_flag);static int awe_write_wave_data(const char *addr, long offset, int size);static awe_voice_list *awe_get_removed_list(awe_voice_list *curp);static void awe_remove_samples(void);static short awe_set_sample(awe_voice_info *vp);/* lowlevel functions */static void awe_init_audio(void);static void awe_init_dma(void);static void awe_init_array(void);static void awe_send_array(unsigned short *data);static void awe_tweak(void);static void awe_init_fm(void);static int awe_open_dram_for_write(int offset);static int awe_open_dram_for_read(int offset);static void awe_open_dram_for_check(void);static void awe_close_dram(void);static void awe_close_dram_for_read(void);static void awe_write_dram(unsigned short c);static int awe_detect(void);static int awe_check_dram(void);static void awe_set_chorus_mode(int mode);static void awe_set_reverb_mode(int mode);#ifdef AWE_OBSOLETE_VOXWARE#define awe_check_port() 0 /* always false */#define awe_request_region() /* nothing */#define awe_release_region() /* nothing */#else /* AWE_OBSOLETE_VOXWARE *//* the following macros are osbolete */#define PERMANENT_MALLOC(type,var,size,memptr) \ var = (type)(sound_mem_blocks[sound_nblocks++] = vmalloc(size))#define RET_ERROR(err) -err#endif /* AWE_OBSOLETE_VOXWARE */#ifdef AWE_NEED_DISABLE_INTR#define DECL_INTR_FLAGS(x) unsigned long x#else#undef DISABLE_INTR#undef RESTORE_INTR#define DECL_INTR_FLAGS(x) /**/#define DISABLE_INTR(x) /**/#define RESTORE_INTR(x) /**/#endif/* macros for Linux and FreeBSD compatibility */#undef OUTW#undef COPY_FROM_USER#undef GET_BYTE_FROM_USER#undef GET_SHORT_FROM_USER#undef IOCTL_TO_USER #ifdef linux# define NO_DATA_ERR ENODATA# define OUTW(data, addr) outw(data, addr)# define COPY_FROM_USER(target, source, offs, count) \ memcpy_fromfs( ((caddr_t)(target)),(source)+(offs),(count) )# define GET_BYTE_FROM_USER(target, addr, offs) \ *((char *)&(target)) = get_fs_byte( (addr)+(offs) )# define GET_SHORT_FROM_USER(target, addr, offs) \ *((short *)&(target)) = get_fs_word( (addr)+(offs) )# define IOCTL_TO_USER(target, offs, source, count) \ memcpy_tofs ( ((caddr_t)(target)),(source)+(offs),(count) )# define BZERO(target,len) \ memset( (caddr_t)target, '\0', len )# define MEMCPY(dst,src,len) \ memcpy((caddr_t)dst, (caddr_t)src, len)#elif defined(__FreeBSD__)# define NO_DATA_ERR EINVAL# define OUTW(data, addr) outw(addr, data)# define COPY_FROM_USER(target, source, offs, count) \ uiomove( ((caddr_t)(target)),(count),((struct uio *)(source)) )# define GET_BYTE_FROM_USER(target, addr, offs) \ uiomove( ((char*)&(target)), 1, ((struct uio *)(addr)) )# define GET_SHORT_FROM_USER(target, addr, offs) \ uiomove( ((char*)&(target)), 2, ((struct uio *)(addr)) )# define IOCTL_TO_USER(target, offs, source, count) \ memcpy( &((target)[offs]), (source), (count) )# define BZERO(target,len) \ bzero( (caddr_t)target, len )# define MEMCPY(dst,src,len) \ bcopy((caddr_t)src, (caddr_t)dst, len)#endif/*---------------------------------------------------------------- * synth operation table *----------------------------------------------------------------*/static struct synth_operations awe_operations ={ &awe_info, 0, SYNTH_TYPE_SAMPLE, SAMPLE_TYPE_AWE32, awe_open, awe_close, awe_ioctl, awe_kill_note, awe_start_note, awe_set_instr, awe_reset, awe_hw_control, awe_load_patch, awe_aftertouch, awe_controller, awe_panning, awe_volume_method, awe_patchmgr, awe_bender, awe_alloc, awe_setup_voice};/*================================================================ * attach / unload interface *================================================================*/#ifdef AWE_OBSOLETE_VOXWARElong attach_awe_obsolete(long mem_start, struct address_info *hw_config)#elseint attach_awe(void)#endif{ /* check presence of AWE32 card */ if (! awe_detect()) { printk("AWE32: not detected\n"); return 0; } /* check AWE32 ports are available */ if (awe_check_port()) { printk("AWE32: I/O area already used.\n"); return 0; } /* allocate sample tables */ PERMANENT_MALLOC(awe_sample_info *, samples, AWE_MAX_SAMPLES * sizeof(awe_sample_info), mem_start); PERMANENT_MALLOC(awe_voice_list *, infos, AWE_MAX_INFOS * sizeof(awe_voice_list), mem_start); if (samples == NULL || infos == NULL) { printk("AWE32: can't allocate sample tables\n"); return 0; } if (num_synths >= MAX_SYNTH_DEV) printk("AWE32 Error: too many synthesizers\n"); else { voice_alloc = &awe_operations.alloc; voice_alloc->max_voice = awe_max_voices; synth_devs[num_synths++] = &awe_operations; } /* reserve I/O ports for awedrv */ awe_request_region(); /* clear all samples */ awe_reset_samples(); /* intialize AWE32 hardware */ awe_initialize();#if 0 /* Drivers shouldn't be this chatty by default */ printk("<AWE32 SynthCard (%dk)>\n", (int)awe_mem_size/1024);#endif sprintf(awe_info.name, "AWE32 Synth (%dk)", (int)awe_mem_size/1024); /* set reverb & chorus modes */ awe_set_reverb_mode(reverb_mode); awe_set_chorus_mode(chorus_mode); awe_present = 1;#ifdef AWE_OBSOLETE_VOXWARE return mem_start;#else return 1;#endif}void unload_awe(void){ if (awe_present) { awe_reset_samples();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -