patch-2.1.28 linux/drivers/sound/lowlevel/awe_wave.c
Next file: linux/drivers/sound/lowlevel/init.c
Previous file: linux/drivers/sound/lowlevel/awe_voice.h
Back to the patch index
Back to the overall index
- Lines: 3217
- Date:
Sun Feb 23 23:24:48 1997
- Orig file:
v2.1.27/linux/drivers/sound/lowlevel/awe_wave.c
- Orig date:
Wed Oct 30 21:17:02 1996
diff -u --recursive --new-file v2.1.27/linux/drivers/sound/lowlevel/awe_wave.c linux/drivers/sound/lowlevel/awe_wave.c
@@ -1,58 +1,54 @@
-/*================================================================
- * awe_wave.c -- driver for AWE32 wave table synth
- * version 0.2.0; Oct. 16, 1996
- * copyright (c) 1996 by Takashi Iwai
- *================================================================*/
-
-/* if you're using obsolete VoxWare 3.0.x on Linux 1.2.x (or FreeBSD),
- * uncomment the following line
+/*
+ * sound/awe_wave.c
+ *
+ * The low level driver for the AWE32/Sound Blaster 32 wave table synth.
+ * version 0.3.1b; Jan. 21, 1997
+ *
+ * Copyright (C) 1996,1997 Takashi Iwai
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* #define AWE_OBSOLETE_VOXWARE */
-#include "lowlevel.h"
-
-#ifdef AWE_OBSOLETE_VOXWARE
-
-#include "sound_config.h"
-#if !defined(EXCLUDE_AWE32)
-#define CONFIG_AWE32_SYNTH
+#define AWEDRV_VERSION "0.3.1b"
+#ifdef __FreeBSD__
+# include <i386/isa/sound/awe_config.h>
+#else
+# include "awe_config.h"
#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*/
-
/*----------------------------------------------------------------*/
#ifdef CONFIG_AWE32_SYNTH
-#include "awe_hw.h"
-#include "awe_voice.h"
+#ifdef __FreeBSD__
+# include <i386/isa/sound/awe_hw.h>
+# include <i386/isa/sound/awe_voice.h>
+#else
+# include "awe_hw.h"
+# include <linux/awe_voice.h>
+#endif
#ifdef AWE_OBSOLETE_VOXWARE
-#include "tuning.h"
+# ifdef __FreeBSD__
+# define SEQUENCER_C
+# include <i386/isa/sound/tuning.h>
+# else
+# include "tuning.h"
+# endif
#else
-#include "../tuning.h"
+# include "../tuning.h"
#endif
#ifdef linux
@@ -66,8 +62,8 @@
* debug message
*----------------------------------------------------------------*/
-#ifdef AWE_DEBUG_ON
static int debug_mode = 0;
+#ifdef AWE_DEBUG_ON
#define DEBUG(LVL,XXX) {if (debug_mode > LVL) { XXX; }}
#define ERRMSG(XXX) {if (debug_mode) { XXX; }}
#define FATALERR(XXX) XXX
@@ -95,6 +91,7 @@
#define AWE_MAX_PRESETS 256
#define AWE_DEFAULT_BANK 0
+#define AWE_DRUM_BANK 128
/* preset table index */
static awe_voice_list *preset_table[AWE_MAX_PRESETS];
@@ -103,35 +100,68 @@
* voice table
*----------------------------------------------------------------*/
-#define AWE_FX_BYTES ((AWE_FX_END+7)/8)
+/* effects table */
+#define AWE_FX_NBYTES ((AWE_FX_END+7)/8)
+typedef struct FX_Rec { /* channel effects */
+ unsigned char flags[AWE_FX_NBYTES];
+ short val[AWE_FX_END];
+} FX_Rec;
-typedef struct _voice_info {
- int state; /* status (on = 1, off = 0) */
- int note; /* midi key (0-127) */
- int velocity; /* midi velocity (0-127) */
+
+/* channel parameters */
+typedef struct _awe_chan_info {
+ int bank; /* current tone bank */
+ int instr; /* current program */
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) */
+ awe_voice_list *vrec; /* instrument list */
+ awe_voice_list *def_vrec; /* default instrument list */
+ FX_Rec fx; /* effects */
+ int sustained; /* sustain status in MIDI */
+} awe_chan_info;
+
+/* voice parameters */
+typedef struct _voice_info {
+ int state;
+#define AWE_ST_OFF 0 /* no sound */
+#define AWE_ST_ON 1 /* playing */
+#define AWE_ST_STANDBY 2 /* stand by for playing */
+#define AWE_ST_SUSTAINED 3 /* sustained */
+#define AWE_ST_MARK 4 /* marked for allocation */
+
+ int ch; /* midi channel */
+ int key; /* internal key for search */
+ int time; /* allocated time */
+ awe_chan_info *cinfo; /* channel info */
+
+ int note; /* midi key (0-127) */
+ int velocity; /* midi velocity (0-127) */
+ awe_voice_info *sample; /* assigned voice */
/* 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];
+ int apan; /* panning parameter */
} voice_info;
+/* voice information */
static voice_info voices[AWE_MAX_VOICES];
+#define IS_NO_SOUND(v) (voices[v].state == AWE_ST_OFF || voices[v].state == AWE_ST_STANDBY)
+#define IS_NO_EFFECT(v) (voices[v].state != AWE_ST_ON)
+#define IS_PLAYING(v) (!IS_NO_SOUND(v))
+
+
+/* MIDI channel effects information (for hw control) */
+#if AWE_MAX_CHANNELS < AWE_MAX_VOICES
+static awe_chan_info channels[AWE_MAX_VOICES];
+#else
+static awe_chan_info channels[AWE_MAX_CHANNELS];
+#endif
+
/*----------------------------------------------------------------
* global variables
@@ -155,12 +185,21 @@
static int reverb_mode = 0; /* reverb mode */
static int chorus_mode = 0; /* chorus mode */
-static unsigned short init_atten = 32; /* 12dB */
+static unsigned short init_atten = AWE_DEFAULT_ATTENUATION; /* 12dB below */
+
+static int awe_present = FALSE; /* awe device present? */
+static int awe_busy = FALSE; /* awe device opened? */
+
+#define DEFAULT_DRUM_FLAGS (1 << 9)
+#define IS_DRUM_CHANNEL(c) (drum_flags & (1 << (c)))
+static unsigned long drum_flags = DEFAULT_DRUM_FLAGS; /* channel flags */
+
+static int awe_channel_mode = 0; /* channel control mode */
-static int awe_present = 0; /* awe device present? */
-static int awe_busy = 0; /* awe device opened? */
+static int current_alloc_time = 0; /* voice allocation time */
static int awe_gus_bank = AWE_DEFAULT_BANK; /* GUS default bank number */
+static int awe_exclusive_sound = TRUE; /* exclusive sound on */
static struct synth_info awe_info = {
@@ -202,6 +241,7 @@
/* set voice parameters */
static void awe_init_voice_info(awe_voice_info *vp);
static void awe_init_voice_parm(awe_voice_parm *pp);
+#ifdef AWE_HAS_GUS_COMPATIBILITY
static int freq_to_note(int freq);
static int calc_rate_offset(int Hz);
/*static int calc_parm_delay(int msec);*/
@@ -209,26 +249,31 @@
static int calc_parm_attack(int msec);
static int calc_parm_decay(int msec);
static int calc_parm_search(int msec, short *table);
+#endif
/* 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);
+static void awe_exclusive_off(int voice, int exclass);
/* calculate voice parameters */
-static void awe_set_pitch(int voice);
-static void awe_set_volume(int voice);
+typedef void (*fx_affect_func)(int voice, int forced);
+static void awe_set_pitch(int voice, int forced);
+static void awe_set_voice_pitch(int voice, int forced);
+static void awe_set_volume(int voice, int forced);
+static void awe_set_voice_vol(int voice, int forced);
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_fx_fmmod(int voice, int forced);
+static void awe_fx_tremfrq(int voice, int forced);
+static void awe_fx_fm2frq2(int voice, int forced);
+static void awe_fx_cutoff(int voice, int forced);
static void awe_calc_pitch(int voice);
+#ifdef AWE_HAS_GUS_COMPATIBILITY
static void awe_calc_pitch_from_freq(int voice, int freq);
+#endif
static void awe_calc_volume(int voice);
-static void awe_voice_init(int voice, int inst_only);
+static void awe_voice_init(int voice);
/* sequencer interface */
static int awe_open(int dev, int mode);
@@ -237,6 +282,7 @@
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 int awe_set_instr_2(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,
@@ -245,23 +291,35 @@
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);
+#ifndef AWE_NO_PATCHMGR
+static int awe_patchmgr(int dev, struct patmgr_info *rec);
+#endif
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 */
+#ifdef AWE_HAS_GUS_COMPATIBILITY
static void awe_hw_gus_control(int dev, int cmd, unsigned char *event);
+#endif
static void awe_hw_awe_control(int dev, int cmd, unsigned char *event);
+static void awe_voice_change(int voice, fx_affect_func func);
+static void awe_sustain_off(int voice, int forced);
/* voice search */
-static awe_voice_info *awe_search_voice(int voice, int note);
static awe_voice_list *awe_search_instr(int bank, int preset);
+static int awe_search_multi_voices(awe_voice_list *rec, int note, int velocity, awe_voice_info **vlist);
+static void awe_alloc_multi_voices(int ch, int note, int velocity);
+static void awe_alloc_one_voice(int voice, int note, int velocity);
+static int awe_clear_voice(void);
/* 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);
+#ifdef AWE_HAS_GUS_COMPATIBILITY
static int awe_load_guspatch(const char *addr, int offs, int size, int pmgr_flag);
+#endif
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);
@@ -272,6 +330,7 @@
static void awe_init_dma(void);
static void awe_init_array(void);
static void awe_send_array(unsigned short *data);
+static void awe_tweak_voice(int voice);
static void awe_tweak(void);
static void awe_init_fm(void);
static int awe_open_dram_for_write(int offset);
@@ -280,6 +339,7 @@
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_base(int addr);
static int awe_detect(void);
static int awe_check_dram(void);
static void awe_set_chorus_mode(int mode);
@@ -302,17 +362,6 @@
#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
@@ -324,6 +373,8 @@
#ifdef linux
# define NO_DATA_ERR ENODATA
# define OUTW(data, addr) outw(data, addr)
+
+#ifdef AWE_NEW_KERNEL_INTERFACE
# define COPY_FROM_USER(target, source, offs, count) \
copy_from_user( ((caddr_t)(target)),(source)+(offs),(count) )
# define GET_BYTE_FROM_USER(target, addr, offs) \
@@ -332,8 +383,22 @@
get_user(target, (unsigned short*)&((addr)[offs]))
# define IOCTL_TO_USER(target, offs, source, count) \
copy_to_user ( ((caddr_t)(target)),(source)+(offs),(count) )
+#else /* AWE_NEW_KERNEL_INTERFACE */
+# 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) )
+#endif /* AWE_NEW_KERNEL_INTERFACE */
+
# 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)
@@ -347,6 +412,8 @@
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
@@ -356,6 +423,7 @@
static struct synth_operations awe_operations =
{
+ "EMU8K",
&awe_info,
0,
SYNTH_TYPE_SAMPLE,
@@ -365,7 +433,7 @@
awe_ioctl,
awe_kill_note,
awe_start_note,
- awe_set_instr,
+ awe_set_instr_2,
awe_reset,
awe_hw_control,
awe_load_patch,
@@ -373,6 +441,9 @@
awe_controller,
awe_panning,
awe_volume_method,
+#ifndef AWE_NO_PATCHMGR
+ awe_patchmgr,
+#endif
awe_bender,
awe_alloc,
awe_setup_voice
@@ -404,7 +475,7 @@
/* allocate sample tables */
PERMANENT_MALLOC(awe_sample_info *, samples,
- AWE_MAX_SAMPLES * sizeof(awe_sample_info), mem_start);
+ AWE_MAX_SAMPLES * AWE_SAMPLE_INFO_SIZE, mem_start);
PERMANENT_MALLOC(awe_voice_list *, infos,
AWE_MAX_INFOS * sizeof(awe_voice_list), mem_start);
if (samples == NULL || infos == NULL) {
@@ -429,14 +500,21 @@
/* intialize AWE32 hardware */
awe_initialize();
- printk("<AWE32 SynthCard (%dk)>\n", (int)awe_mem_size/1024);
- sprintf(awe_info.name, "AWE32 Synth (%dk)", (int)awe_mem_size/1024);
+#ifndef __FreeBSD__
+ printk("AWE32 Sound Driver v%s (DRAM %dk)\n",
+ AWEDRV_VERSION, (int)awe_mem_size/1024);
+#else
+ DEBUG(0,printk("AWE32 Sound Driver v%s (DRAM %dk)\n",
+ AWEDRV_VERSION, (int)awe_mem_size/1024));
+#endif
+ sprintf(awe_info.name, "AWE32 Driver v%s (DRAM %dk)",
+ AWEDRV_VERSION, (int)awe_mem_size/1024);
/* set reverb & chorus modes */
awe_set_reverb_mode(reverb_mode);
awe_set_chorus_mode(chorus_mode);
- awe_present = 1;
+ awe_present = TRUE;
#ifdef AWE_OBSOLETE_VOXWARE
return mem_start;
@@ -491,11 +569,13 @@
*================================================================*/
/* select a given AWE32 pointer */
-#define awe_set_cmd(cmd) OUTW(cmd, awe_base + 0x802)
+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 */
-static void
+INLINE static void
awe_poke(unsigned short cmd, unsigned short port, unsigned short data)
{
awe_set_cmd(cmd);
@@ -503,7 +583,7 @@
}
/* write 32bit data */
-static void
+INLINE static void
awe_poke_dw(unsigned short cmd, unsigned short port, unsigned long data)
{
awe_set_cmd(cmd);
@@ -512,7 +592,7 @@
}
/* read 16bit data */
-static unsigned short
+INLINE static unsigned short
awe_peek(unsigned short cmd, unsigned short port)
{
unsigned short k;
@@ -522,7 +602,7 @@
}
/* read 32bit data */
-static unsigned long
+INLINE static unsigned long
awe_peek_dw(unsigned short cmd, unsigned short port)
{
unsigned long k1, k2;
@@ -567,25 +647,25 @@
static int
awe_check_port(void)
{
- return (check_region(awe_port(Data0), 3) ||
- check_region(awe_port(Data1), 3) ||
- check_region(awe_port(Data3), 3));
+ return (check_region(awe_port(Data0), 4) ||
+ check_region(awe_port(Data1), 4) ||
+ check_region(awe_port(Data3), 4));
}
static void
awe_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)");
+ request_region(awe_port(Data0), 4, "sound driver (AWE32)");
+ request_region(awe_port(Data1), 4, "sound driver (AWE32)");
+ request_region(awe_port(Data3), 4, "sound driver (AWE32)");
}
static void
awe_release_region(void)
{
- release_region(awe_port(Data0), 3);
- release_region(awe_port(Data1), 3);
- release_region(awe_port(Data3), 3);
+ release_region(awe_port(Data0), 4);
+ release_region(awe_port(Data1), 4);
+ release_region(awe_port(Data3), 4);
}
#endif /* !AWE_OBSOLETE_VOXWARE */
@@ -597,30 +677,22 @@
static void
awe_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);
+ /* disable audio; this seems to reduce a clicking noise a bit.. */
+ awe_poke(AWE_HWCF3, 0);
/* initialize audio channels */
awe_init_audio();
- /* initialize init array */
+ /* initialize DMA */
awe_init_dma();
+
+ /* initialize init array */
awe_init_array();
/* check DRAM memory size */
@@ -634,13 +706,6 @@
/* 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);
}
@@ -720,6 +785,8 @@
}
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+
/* convert frequency mHz to abstract cents (= midi key * 100) */
static int
freq_to_note(int mHz)
@@ -811,27 +878,27 @@
* convert envelope time parameter to AWE32 raw parameter
*----------------------------------------------------------------*/
-/* attack & decay/release time table (mHz) */
+/* attack & decay/release time table (msec) */
static short attack_time_tbl[128] = {
-32767, 5939, 3959, 2969, 2375, 1979, 1696, 1484, 1319, 1187, 1079, 989, 913, 848, 791, 742,
+32767, 11878, 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,
+ 11, 10, 10, 10, 9, 9, 8, 8, 8, 7, 7, 7, 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,
+32767, 32766, 4589, 4400, 4219, 4045, 3879, 3719, 3566, 3419, 3279, 3144, 3014, 2890, 2771, 2657,
+ 2548, 2443, 2343, 2246, 2154, 2065, 1980, 1899, 1820, 1746, 1674, 1605, 1539, 1475, 1415, 1356,
+ 1301, 1247, 1196, 1146, 1099, 1054, 1011, 969, 929, 891, 854, 819, 785, 753, 722, 692,
+ 664, 636, 610, 585, 561, 538, 516, 494, 474, 455, 436, 418, 401, 384, 368, 353,
+ 339, 325, 311, 298, 286, 274, 263, 252, 242, 232, 222, 213, 204, 196, 188, 180,
+ 173, 166, 159, 152, 146, 140, 134, 129, 123, 118, 113, 109, 104, 100, 96, 92,
+ 88, 84, 81, 77, 74, 71, 68, 65, 63, 60, 58, 55, 53, 51, 49, 47,
+ 45, 43, 41, 39, 38, 36, 35, 33, 32, 30, 29, 28, 27, 26, 25, 24,
};
/*
@@ -842,6 +909,7 @@
}
*/
+/* delay time = 0x8000 - msec/92 */
static int
calc_parm_hold(int msec)
{
@@ -851,22 +919,25 @@
return val;
}
+/* attack time: search from time table */
static int
calc_parm_attack(int msec)
{
return calc_parm_search(msec, attack_time_tbl);
}
+/* decay/release time: search from time table */
static int
calc_parm_decay(int msec)
{
return calc_parm_search(msec, decay_time_tbl);
}
+/* search an index for specified time from given time table */
static int
calc_parm_search(int msec, short *table)
{
- int left = 0, right = 127, mid;
+ int left = 1, right = 127, mid;
while (left < right) {
mid = (left + right) / 2;
if (msec < (int)table[mid])
@@ -876,6 +947,7 @@
}
return left;
}
+#endif /* AWE_HAS_GUS_COMPATIBILITY */
/*================================================================
@@ -883,103 +955,53 @@
*================================================================*/
/* 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))
+#define FX_SET(rec,type,value) \
+ ((rec)->flags[(type)/8] |= (1 << ((type) % 8)), \
+ (rec)->val[type] = (value))
-#else
+/* check the effect value is set */
+#define FX_ON(rec,type) ((rec)->flags[(type)/8] & (1<<((type)%8)))
/* 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;
-}
-
+#define FX_BYTE(rec,type,value) \
+ (unsigned char)(FX_ON(rec,type) ? (rec)->val[type] : (value))
/* 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
+#define FX_WORD(rec,type,value) \
+ (unsigned short)(FX_ON(rec,type) ? (rec)->val[type] : (value))
/* get word (upper=type1/lower=type2) effect value */
-static unsigned short FX_COMB(int v, int type1, int type2, unsigned short value)
+static unsigned short
+FX_COMB(FX_Rec *rec, int type1, int type2, unsigned short value)
{
unsigned short tmp;
- if (FX_ON(v, type1))
- tmp = (unsigned short)(voices[v].fx[type1]) << 8;
+ if (FX_ON(rec, type1))
+ tmp = (unsigned short)(rec->val[type1]) << 8;
else
tmp = value & 0xff00;
- if (FX_ON(v, type2))
- tmp |= (unsigned short)(voices[v].fx[type2]) & 0xff;
+ if (FX_ON(rec, type2))
+ tmp |= (unsigned short)(rec->val[type2]) & 0xff;
else
tmp |= value & 0xff;
- DEBUG(4,printk("AWE32: [-- comb(%d/%d) = %x]\n", type1, type2, tmp));
return tmp;
}
/* address offset */
static long
-FX_OFFSET(int voice, int lo, int hi)
+FX_OFFSET(FX_Rec *rec, int lo, int hi, int mode)
{
- awe_voice_info *vp;
- long addr;
- if ((vp = voices[voice].sample) == NULL || vp->index < 0)
- return 0;
-
- addr = 0;
- if (FX_ON(voice, hi)) {
- addr = (short)voices[voice].fx[hi];
+ long addr = 0;
+ if (FX_ON(rec, hi)) {
+ addr = (short)rec->val[hi];
addr = addr << 15;
}
- if (FX_ON(voice, lo))
- addr += (short)voices[voice].fx[lo];
- if (!(vp->mode & (AWE_SAMPLE_8BITS<<6)))
+ if (FX_ON(rec, lo))
+ addr += (short)rec->val[lo];
+ if (!(mode & AWE_SAMPLE_8BITS))
addr /= 2;
return addr;
}
-typedef void (*fx_affect_func)(int voice);
-static fx_affect_func fx_realtime[] = {
- /* env1: delay, attack, hold, decay, release, sustain, pitch, cutoff*/
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* env2: delay, attack, hold, decay, release, sustain */
- NULL, NULL, NULL, NULL, NULL, NULL,
- /* lfo1: delay, freq, volume, pitch, cutoff */
- NULL, awe_fx_tremfrq, awe_fx_tremfrq, awe_fx_fmmod, awe_fx_fmmod,
- /* lfo2: delay, freq, pitch */
- NULL, awe_fx_fm2frq2, awe_fx_fm2frq2,
- /* global: initpitch, chorus, reverb, cutoff, filterQ */
- awe_fx_initpitch, NULL, NULL, awe_fx_cutoff, NULL,
- /* sample: start, loopstart, loopend */
- NULL, NULL, NULL,
-};
-
-
/*================================================================
* turn on/off sample
*================================================================*/
@@ -989,8 +1011,8 @@
{
unsigned long temp;
long addr;
- unsigned short tmp2;
awe_voice_info *vp;
+ FX_Rec *fx = &voices[voice].cinfo->fx;
/* A voice sample must assigned before calling */
if ((vp = voices[voice].sample) == NULL || vp->index < 0)
@@ -1005,71 +1027,65 @@
/* modulation & volume envelope */
awe_poke(AWE_ENVVAL(voice),
- FX_WORD(voice, AWE_FX_ENV1_DELAY, vp->parm.moddelay));
+ FX_WORD(fx, AWE_FX_ENV1_DELAY, vp->parm.moddelay));
awe_poke(AWE_ATKHLD(voice),
- FX_COMB(voice, AWE_FX_ENV1_ATTACK, AWE_FX_ENV1_HOLD,
+ FX_COMB(fx, AWE_FX_ENV1_HOLD, AWE_FX_ENV1_ATTACK,
vp->parm.modatkhld));
awe_poke(AWE_DCYSUS(voice),
- FX_COMB(voice, AWE_FX_ENV1_SUSTAIN, AWE_FX_ENV1_DECAY,
+ FX_COMB(fx, AWE_FX_ENV1_SUSTAIN, AWE_FX_ENV1_DECAY,
vp->parm.moddcysus));
awe_poke(AWE_ENVVOL(voice),
- FX_WORD(voice, AWE_FX_ENV2_DELAY, vp->parm.voldelay));
+ FX_WORD(fx, AWE_FX_ENV2_DELAY, vp->parm.voldelay));
awe_poke(AWE_ATKHLDV(voice),
- FX_COMB(voice, AWE_FX_ENV2_ATTACK, AWE_FX_ENV2_HOLD,
+ FX_COMB(fx, AWE_FX_ENV2_HOLD, AWE_FX_ENV2_ATTACK,
vp->parm.volatkhld));
/* decay/sustain parameter for volume envelope must be set at last */
/* pitch offset */
- awe_poke(AWE_IP(voice), voices[voice].apitch);
- DEBUG(3,printk("AWE32: [-- pitch=%x]\n", voices[voice].apitch));
+ awe_set_pitch(voice, TRUE);
/* cutoff and volume */
- tmp2 = FX_BYTE(voice, AWE_FX_CUTOFF, vp->parm.cutoff);
- tmp2 = (tmp2 << 8) | voices[voice].avol;
- awe_poke(AWE_IFATN(voice), tmp2);
+ awe_set_volume(voice, TRUE);
/* modulation envelope heights */
awe_poke(AWE_PEFE(voice),
- FX_COMB(voice, AWE_FX_ENV1_PITCH, AWE_FX_ENV1_CUTOFF,
+ FX_COMB(fx, AWE_FX_ENV1_PITCH, AWE_FX_ENV1_CUTOFF,
vp->parm.pefe));
/* lfo1/2 delay */
awe_poke(AWE_LFO1VAL(voice),
- FX_WORD(voice, AWE_FX_LFO1_DELAY, vp->parm.lfo1delay));
+ FX_WORD(fx, AWE_FX_LFO1_DELAY, vp->parm.lfo1delay));
awe_poke(AWE_LFO2VAL(voice),
- FX_WORD(voice, AWE_FX_LFO2_DELAY, vp->parm.lfo2delay));
+ FX_WORD(fx, AWE_FX_LFO2_DELAY, vp->parm.lfo2delay));
/* lfo1 pitch & cutoff shift */
- awe_poke(AWE_FMMOD(voice),
- FX_COMB(voice, AWE_FX_LFO1_PITCH, AWE_FX_LFO1_CUTOFF,
- vp->parm.fmmod));
+ awe_fx_fmmod(voice, TRUE);
/* lfo1 volume & freq */
- awe_poke(AWE_TREMFRQ(voice),
- FX_COMB(voice, AWE_FX_LFO1_VOLUME, AWE_FX_LFO1_FREQ,
- vp->parm.tremfrq));
+ awe_fx_tremfrq(voice, TRUE);
/* lfo2 pitch & freq */
- awe_poke(AWE_FM2FRQ2(voice),
- FX_COMB(voice, AWE_FX_LFO2_PITCH, AWE_FX_LFO2_FREQ,
- vp->parm.fm2frq2));
-
+ awe_fx_fm2frq2(voice, TRUE);
/* pan & loop start */
awe_set_pan(voice, 1);
/* chorus & loop end (chorus 8bit, MSB) */
addr = vp->loopend - 1;
- addr += FX_OFFSET(voice, AWE_FX_LOOP_END,
- AWE_FX_COARSE_LOOP_END);
- temp = FX_BYTE(voice, AWE_FX_CHORUS, vp->parm.chorus);
+ addr += FX_OFFSET(fx, AWE_FX_LOOP_END,
+ AWE_FX_COARSE_LOOP_END, vp->mode);
+ temp = FX_BYTE(fx, AWE_FX_CHORUS, vp->parm.chorus);
temp = (temp <<24) | (unsigned long)addr;
awe_poke_dw(AWE_CSL(voice), temp);
+ DEBUG(4,printk("AWE32: [-- loopend=%x/%x]\n",
+ (int)vp->loopend, (int)addr));
/* Q & current address (Q 4bit value, MSB) */
addr = vp->start - 1;
- addr += FX_OFFSET(voice, AWE_FX_SAMPLE_START,
- AWE_FX_COARSE_SAMPLE_START);
- temp = FX_BYTE(voice, AWE_FX_FILTERQ, vp->parm.filterQ);
+ addr += FX_OFFSET(fx, AWE_FX_SAMPLE_START,
+ AWE_FX_COARSE_SAMPLE_START, vp->mode);
+ temp = FX_BYTE(fx, AWE_FX_FILTERQ, vp->parm.filterQ);
temp = (temp<<28) | (unsigned long)addr;
awe_poke_dw(AWE_CCCA(voice), temp);
+ DEBUG(4,printk("AWE32: [-- startaddr=%x/%x]\n",
+ (int)vp->start, (int)addr));
/* reset volume */
awe_poke_dw(AWE_VTFT(voice), 0x0000FFFF);
@@ -1077,36 +1093,41 @@
/* turn on envelope */
awe_poke(AWE_DCYSUSV(voice),
- FX_COMB(voice, AWE_FX_ENV2_SUSTAIN, AWE_FX_ENV2_DECAY,
+ FX_COMB(fx, AWE_FX_ENV2_SUSTAIN, AWE_FX_ENV2_DECAY,
vp->parm.voldcysus));
/* set chorus */
- temp = FX_BYTE(voice, AWE_FX_REVERB, vp->parm.reverb);
+ temp = FX_BYTE(fx, AWE_FX_REVERB, vp->parm.reverb);
temp = (awe_peek_dw(AWE_PTRX(voice)) & 0xffff0000) | (temp<<8);
awe_poke_dw(AWE_PTRX(voice), temp);
awe_poke_dw(AWE_CPF(voice), 0x40000000);
-
- DEBUG(3,printk("AWE32: [-- start=%x loop=%x]\n",
- (int)vp->start, (int)vp->loopstart));
}
+
/* turn off the voice */
static void
awe_note_off(int voice)
{
awe_voice_info *vp;
unsigned short tmp;
- if ((vp = voices[voice].sample) == NULL || !voices[voice].state)
+ FX_Rec *fx = &voices[voice].cinfo->fx;
+ if ((vp = voices[voice].sample) == NULL) {
+ awe_voice_init(voice);
return;
- if (FX_ON(voice, AWE_FX_ENV1_RELEASE))
- tmp = 0x8000 | voices[voice].fx[AWE_FX_ENV1_RELEASE];
+ }
+
+ if (FX_ON(fx, AWE_FX_ENV1_RELEASE))
+ tmp = 0x8000 | fx->val[AWE_FX_ENV1_RELEASE];
else
tmp = vp->parm.modrelease;
awe_poke(AWE_DCYSUS(voice), tmp);
- if (FX_ON(voice, AWE_FX_ENV2_RELEASE))
- tmp = 0x8000 | voices[voice].fx[AWE_FX_ENV2_RELEASE];
+ if (FX_ON(fx, AWE_FX_ENV2_RELEASE))
+ tmp = 0x8000 | fx->val[AWE_FX_ENV2_RELEASE];
else
tmp = vp->parm.volrelease;
awe_poke(AWE_DCYSUSV(voice), tmp);
+ voices[voice].state = AWE_ST_OFF;
+
+ awe_voice_init(voice);
}
/* force to terminate the voice (no releasing echo) */
@@ -1114,29 +1135,27 @@
awe_terminate(int voice)
{
awe_poke(AWE_DCYSUSV(voice), 0x807F);
+ awe_tweak_voice(voice);
+ awe_voice_init(voice);
}
/* turn off other voices with the same exclusive class (for drums) */
static void
-awe_exclusive_off(int voice)
+awe_exclusive_off(int voice, int exclass)
{
- int i, excls;
+ int i;
- if (voices[voice].sample == NULL) /* no sample */
- return;
- excls = voices[voice].sample->exclusiveClass;
- if (excls == 0) /* not exclusive */
+ if (exclass == 0) /* not exclusive */
return;
/* turn off voices with the same class */
for (i = 0; i < awe_max_voices; i++) {
- if (i != voice && voices[voice].state &&
+ if (i != voice && IS_PLAYING(voice) &&
voices[i].sample &&
- voices[i].sample->exclusiveClass == excls) {
+ voices[i].sample->exclusiveClass == exclass) {
DEBUG(4,printk("AWE32: [exoff(%d)]\n", i));
awe_note_off(i);
- awe_voice_init(i, 1);
}
}
}
@@ -1148,26 +1167,47 @@
/* change pitch */
static void
-awe_set_pitch(int voice)
+awe_set_pitch(int voice, int forced)
{
- if (!voices[voice].state) return;
+ if (IS_NO_EFFECT(voice) && !forced) return;
awe_poke(AWE_IP(voice), voices[voice].apitch);
+ DEBUG(3,printk("AWE32: [-- pitch=%x]\n", voices[voice].apitch));
+}
+
+/* calculate & change pitch */
+static void
+awe_set_voice_pitch(int voice, int forced)
+{
+ awe_calc_pitch(voice);
+ awe_set_pitch(voice, forced);
}
/* change volume */
static void
-awe_set_volume(int voice)
+awe_set_volume(int voice, int forced)
{
awe_voice_info *vp;
unsigned short tmp2;
- if (!voices[voice].state) return;
+ FX_Rec *fx = &voices[voice].cinfo->fx;
+
+ if (IS_NO_EFFECT(voice) && !forced) return;
if ((vp = voices[voice].sample) == NULL || vp->index < 0)
return;
- tmp2 = FX_BYTE(voice, AWE_FX_CUTOFF, vp->parm.cutoff);
+
+ tmp2 = FX_BYTE(fx, AWE_FX_CUTOFF, vp->parm.cutoff);
tmp2 = (tmp2 << 8) | voices[voice].avol;
awe_poke(AWE_IFATN(voice), tmp2);
}
+/* calculate & change volume */
+static void
+awe_set_voice_vol(int voice, int forced)
+{
+ awe_calc_volume(voice);
+ awe_set_volume(voice, forced);
+}
+
+
/* change pan; this could make a click noise.. */
static void
awe_set_pan(int voice, int forced)
@@ -1175,8 +1215,9 @@
unsigned long temp;
long addr;
awe_voice_info *vp;
+ FX_Rec *fx = &voices[voice].cinfo->fx;
- if (!voices[voice].state && !forced) return;
+ if (IS_NO_EFFECT(voice) && !forced) return;
if ((vp = voices[voice].sample) == NULL || vp->index < 0)
return;
@@ -1187,7 +1228,7 @@
int pos = 0;
if (vp->pan >= 0) /* 0-127 */
pos = (int)vp->pan * 2 - 128;
- pos += voices[voice].panning; /* -128 - 127 */
+ pos += voices[voice].cinfo->panning; /* -128 - 127 */
pos = 127 - pos;
if (pos < 0)
temp = 0;
@@ -1196,76 +1237,75 @@
else
temp = pos;
}
- addr = vp->loopstart - 1;
- addr += FX_OFFSET(voice, AWE_FX_LOOP_START,
- AWE_FX_COARSE_LOOP_START);
- temp = (temp<<24) | (unsigned long)addr;
- awe_poke_dw(AWE_PSST(voice), temp);
+ if (forced || temp != voices[voice].apan) {
+ addr = vp->loopstart - 1;
+ addr += FX_OFFSET(fx, AWE_FX_LOOP_START,
+ AWE_FX_COARSE_LOOP_START, vp->mode);
+ temp = (temp<<24) | (unsigned long)addr;
+ awe_poke_dw(AWE_PSST(voice), temp);
+ voices[voice].apan = temp;
+ DEBUG(4,printk("AWE32: [-- loopstart=%x/%x]\n",
+ (int)vp->loopstart, (int)addr));
+ }
}
/* effects change during playing */
static void
-awe_fx_fmmod(int voice)
+awe_fx_fmmod(int voice, int forced)
{
awe_voice_info *vp;
- if (!voices[voice].state) return;
+ FX_Rec *fx = &voices[voice].cinfo->fx;
+ if (IS_NO_EFFECT(voice) && !forced) return;
if ((vp = voices[voice].sample) == NULL || vp->index < 0)
return;
awe_poke(AWE_FMMOD(voice),
- FX_COMB(voice, AWE_FX_LFO1_PITCH, AWE_FX_LFO1_CUTOFF,
+ FX_COMB(fx, AWE_FX_LFO1_PITCH, AWE_FX_LFO1_CUTOFF,
vp->parm.fmmod));
}
+/* set tremolo (lfo1) volume & frequency */
static void
-awe_fx_tremfrq(int voice)
+awe_fx_tremfrq(int voice, int forced)
{
awe_voice_info *vp;
- if (!voices[voice].state) return;
+ FX_Rec *fx = &voices[voice].cinfo->fx;
+ if (IS_NO_EFFECT(voice) && !forced) return;
if ((vp = voices[voice].sample) == NULL || vp->index < 0)
return;
awe_poke(AWE_TREMFRQ(voice),
- FX_COMB(voice, AWE_FX_LFO1_VOLUME, AWE_FX_LFO1_FREQ,
+ FX_COMB(fx, AWE_FX_LFO1_VOLUME, AWE_FX_LFO1_FREQ,
vp->parm.tremfrq));
}
+/* set lfo2 pitch & frequency */
static void
-awe_fx_fm2frq2(int voice)
+awe_fx_fm2frq2(int voice, int forced)
{
awe_voice_info *vp;
- if (!voices[voice].state) return;
+ FX_Rec *fx = &voices[voice].cinfo->fx;
+ if (IS_NO_EFFECT(voice) && !forced) return;
if ((vp = voices[voice].sample) == NULL || vp->index < 0)
return;
awe_poke(AWE_FM2FRQ2(voice),
- FX_COMB(voice, AWE_FX_LFO2_PITCH, AWE_FX_LFO2_FREQ,
+ FX_COMB(fx, AWE_FX_LFO2_PITCH, AWE_FX_LFO2_FREQ,
vp->parm.fm2frq2));
}
+/* set total cutoff & current pitch */
static void
-awe_fx_cutoff(int voice)
+awe_fx_cutoff(int voice, int forced)
{
unsigned short tmp2;
awe_voice_info *vp;
- if (!voices[voice].state) return;
+ FX_Rec *fx = &voices[voice].cinfo->fx;
+ if (IS_NO_EFFECT(voice)) return;
if ((vp = voices[voice].sample) == NULL || vp->index < 0)
return;
- tmp2 = FX_BYTE(voice, AWE_FX_CUTOFF, vp->parm.cutoff);
+ tmp2 = FX_BYTE(fx, AWE_FX_CUTOFF, vp->parm.cutoff);
tmp2 = (tmp2 << 8) | voices[voice].avol;
awe_poke(AWE_IFATN(voice), tmp2);
}
-static void
-awe_fx_initpitch(int voice)
-{
- if (!voices[voice].state) return;
- if (FX_ON(voice, AWE_FX_INIT_PITCH)) {
- DEBUG(3,printk("AWE32: initpitch ok\n"));
- } else {
- DEBUG(3,printk("AWE32: BAD initpitch %d\n", AWE_FX_INIT_PITCH));
- }
- awe_calc_pitch(voice);
- awe_poke(AWE_IP(voice), voices[voice].apitch);
-}
-
/*================================================================
* calculate pitch offset
@@ -1279,6 +1319,7 @@
{
voice_info *vp = &voices[voice];
awe_voice_info *ap;
+ awe_chan_info *cp = voices[voice].cinfo;
int offset;
/* search voice information */
@@ -1300,18 +1341,18 @@
}
offset += ap->tune * 4096 / 1200;
DEBUG(4,printk("AWE32: p-> tune+ ofs=%d\n", offset));
- if (vp->bender != 0) {
- DEBUG(3,printk("AWE32: p-> bend(%d) %d\n", voice, vp->bender));
+ if (cp->bender != 0) {
+ DEBUG(3,printk("AWE32: p-> bend(%d) %d\n", voice, cp->bender));
/* (819200: 1 semitone) ==> (4096: 12 semitones) */
- offset += vp->bender * vp->bender_range / 2400;
+ offset += cp->bender * cp->bender_range / 2400;
}
offset = (offset * ap->scaleTuning) / 100;
DEBUG(4,printk("AWE32: p-> scale* ofs=%d\n", offset));
/* add initial pitch correction */
- if (FX_ON(voice, AWE_FX_INIT_PITCH)) {
- DEBUG(3,printk("AWE32: fx_pitch(%d) %d\n", voice, vp->fx[AWE_FX_INIT_PITCH]));
- offset += vp->fx[AWE_FX_INIT_PITCH];
+ if (FX_ON(&cp->fx, AWE_FX_INIT_PITCH)) {
+ DEBUG(3,printk("AWE32: fx_pitch(%d) %d\n", voice, cp->fx.val[AWE_FX_INIT_PITCH]));
+ offset += cp->fx.val[AWE_FX_INIT_PITCH];
}
/* 0xe000: root pitch */
@@ -1324,11 +1365,14 @@
}
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+/* calculate MIDI key and semitone from the specified frequency */
static void
awe_calc_pitch_from_freq(int voice, int freq)
{
voice_info *vp = &voices[voice];
awe_voice_info *ap;
+ FX_Rec *fx = &voices[voice].cinfo->fx;
int offset;
int note;
@@ -1342,14 +1386,16 @@
note = freq_to_note(freq);
offset = (note - ap->root * 100 + ap->tune) * 4096 / 1200;
offset = (offset * ap->scaleTuning) / 100;
- if (FX_ON(voice, AWE_FX_INIT_PITCH))
- offset += vp->fx[AWE_FX_INIT_PITCH];
+ 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
@@ -1375,6 +1421,7 @@
{
voice_info *vp = &voices[voice];
awe_voice_info *ap;
+ awe_chan_info *cp = voices[voice].cinfo;
int vol;
/* search voice information */
@@ -1387,13 +1434,8 @@
return;
}
- if (vp->velocity < ap->vellow)
- vp->velocity = ap->vellow;
- else if (vp->velocity > ap->velhigh)
- vp->velocity = ap->velhigh;
-
/* 0 - 127 */
- vol = (vp->velocity * vp->main_vol * vp->expression_vol) / (127*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;
@@ -1412,35 +1454,52 @@
* synth operation routines
*================================================================*/
+#define AWE_VOICE_KEY(v) (0x8000 | (v))
+#define AWE_CHAN_KEY(c,n) (((c) << 8) | ((n) + 1))
+
/* initialize the voice */
static void
-awe_voice_init(int voice, int inst_only)
+awe_voice_init(int voice)
{
- if (! inst_only) {
- /* clear voice parameters */
- voices[voice].note = -1;
- voices[voice].velocity = 0;
- voices[voice].panning = 0; /* zero center */
- voices[voice].bender = 0; /* zero tune skew */
- voices[voice].bender_range = 200; /* sense * 100 */
- voices[voice].main_vol = 127;
- voices[voice].expression_vol = 127;
- voices[voice].bank = AWE_DEFAULT_BANK;
- voices[voice].instr = -1;
- voices[voice].vrec = NULL;
- voices[voice].sample = NULL;
- }
+ voices[voice].note = -1;
+ voices[voice].velocity = 0;
+ voices[voice].sample = NULL;
+ voices[voice].state = AWE_ST_OFF;
+ voices[voice].cinfo = &channels[voice];
+ voices[voice].ch = -1;
+ voices[voice].key = AWE_VOICE_KEY(voice);
+ voices[voice].time = current_alloc_time;
/* clear voice mapping */
- voices[voice].state = 0;
voice_alloc->map[voice] = 0;
/* emu8000 parameters */
voices[voice].apitch = 0;
voices[voice].avol = 255;
+ voices[voice].apan = -1;
/* clear effects */
- BZERO(voices[voice].fx_flags, sizeof(voices[voice].fx_flags));
+ if (! awe_channel_mode)
+ BZERO(&voices[voice].cinfo->fx, sizeof(FX_Rec));
+}
+
+/* initialize channel info */
+static void awe_channel_init(int ch)
+{
+ channels[ch].panning = 0; /* zero center */
+ channels[ch].bender = 0; /* zero tune skew */
+ channels[ch].bender_range = 200; /* sense * 100 */
+ channels[ch].main_vol = 127;
+ channels[ch].expression_vol = 127;
+ if (awe_channel_mode && IS_DRUM_CHANNEL(ch))
+ channels[ch].bank = AWE_DRUM_BANK;
+ else
+ channels[ch].bank = AWE_DEFAULT_BANK;
+ channels[ch].instr = 0;
+ channels[ch].vrec = NULL;
+ channels[ch].def_vrec = NULL;
+ channels[ch].sustained = 0;
+ BZERO(&channels[ch].fx, sizeof(FX_Rec));
}
@@ -1457,14 +1516,19 @@
if (awe_busy)
return RET_ERROR(EBUSY);
- awe_busy = 1;
+ awe_busy = TRUE;
awe_reset(dev);
/* clear sample position flag */
loaded_once = 0;
- /* set GUS bank to default */
+ /* set default mode */
+ init_atten = AWE_DEFAULT_ATTENUATION; /* 12dB below */
awe_gus_bank = AWE_DEFAULT_BANK;
+ drum_flags = DEFAULT_DRUM_FLAGS;
+ awe_exclusive_sound = TRUE;
+ awe_channel_mode = 0;
+
return 0;
}
@@ -1476,7 +1540,7 @@
awe_close(int dev)
{
awe_reset(dev);
- awe_busy = 0;
+ awe_busy = FALSE;
}
@@ -1494,7 +1558,7 @@
case SNDCTL_SEQ_RESETSAMPLES:
awe_reset_samples();
- awe_reset(dev); /* better to reset emu8k chip... */
+ awe_reset(dev);
return 0;
break;
@@ -1520,88 +1584,139 @@
static int
awe_kill_note(int dev, int voice, int note, int velocity)
{
- awe_voice_info *vp;
- DECL_INTR_FLAGS(flags);
+ int i, key, besttime;
- DEBUG(2,printk("AWE32: [off(%d)]\n", voice));
- if (voice < 0 || voice >= awe_max_voices)
- return RET_ERROR(EINVAL);
- if ((vp = voices[voice].sample) == NULL)
- return 0;
-
- if (!(vp->mode & AWE_MODE_NORELEASE)) {
- DISABLE_INTR(flags);
- awe_note_off(voice);
- RESTORE_INTR(flags);
+ DEBUG(2,printk("AWE32: [off(%d) nt=%d vl=%d]\n", voice, note, velocity));
+ if (awe_channel_mode) {
+ if (awe_channel_mode == 2) { /* get channel */
+ int v2 = voice_alloc->map[voice] >> 8;
+ voice_alloc->map[voice] = 0;
+ voice = v2;
+ }
+ if (voice < 0 || voice >= AWE_MAX_CHANNELS)
+ return RET_ERROR(EINVAL);
+ if (channels[voice].instr > 128)
+ note = channels[voice].instr - 128;
+ key = AWE_CHAN_KEY(voice, note);
+ } else {
+ if (voice < 0 || voice >= awe_max_voices)
+ return RET_ERROR(EINVAL);
+ key = AWE_VOICE_KEY(voice);
}
- awe_voice_init(voice, 1);
- return 0;
-}
-
-/* search the note with the specified key range */
-static awe_voice_info *
-awe_search_voice(int voice, int note)
-{
- awe_voice_list *rec;
- int maxc;
-
- for (rec = voices[voice].vrec, maxc = AWE_MAX_INFOS;
- rec && maxc; rec = rec->next_instr, maxc--) {
- if (rec->v.low <= note && note <= rec->v.high)
- return &rec->v;
+ besttime = current_alloc_time + 1;
+ for (i = 0; i < awe_max_voices; i++) {
+ if (voices[i].key == key) {
+ if (voices[i].time < besttime)
+ besttime = voices[i].time;
+ }
}
- return NULL;
+ for (i = 0; i < awe_max_voices; i++) {
+ if (voices[i].key == key &&
+ (!awe_exclusive_sound || voices[i].time == besttime)) {
+ if (voices[i].cinfo->sustained)
+ voices[i].state = AWE_ST_SUSTAINED;
+ else
+ awe_note_off(i);
+ }
+ }
+ return 0;
}
+
/* start a voice:
* if note is 255, identical with aftertouch function.
* Otherwise, start a voice with specified not and volume.
*/
static int
-awe_start_note(int dev, int v, int note_num, int volume)
+awe_start_note(int dev, int voice, int note, int velocity)
{
- DECL_INTR_FLAGS(flags);
+ int i, key, state, volonly;
- DEBUG(2,printk("AWE32: [on(%d) nt=%d vl=%d]\n", v, note_num, volume));
- if (v < 0 || v >= awe_max_voices)
+ DEBUG(2,printk("AWE32: [on(%d) nt=%d vl=%d]\n", voice, note, velocity));
+ volonly = 0;
+ if (awe_channel_mode) {
+ if (awe_channel_mode == 2) /* get channel */
+ voice = voice_alloc->map[voice] >> 8;
+ else if (voice & 0x80) { /* channel volume mode */
+ voice &= ~0x80;
+ volonly = 2;
+ }
+ if (voice < 0 || voice >= AWE_MAX_CHANNELS)
+ return RET_ERROR(EINVAL);
+ if (channels[voice].instr > 128)
+ note = channels[voice].instr - 128;
+ if (note >= 128) { /* key volume mode */
+ note -= 128;
+ volonly = 1;
+ }
+ key = AWE_CHAN_KEY(voice, note);
+ } else {
+ if (voice < 0 || voice >= awe_max_voices)
return RET_ERROR(EINVAL);
- /* an instrument must be set before starting a note */
- if (voices[v].vrec == NULL) {
- DEBUG(1,printk("AWE32: [-- vrec is null]\n"));
+ if (voices[voice].cinfo->instr > 128)
+ note = voices[voice].cinfo->instr - 128;
+ key = AWE_VOICE_KEY(voice);
+ if (note == 255)
+ volonly = 1;
+ }
+
+ /* dynamic volume change */
+ if (volonly) {
+ for (i = 0; i < awe_max_voices; i++) {
+ if ((volonly == 2 && voices[i].ch == voice) ||
+ voices[i].key == key) {
+ voices[i].velocity = velocity;
+ if (velocity == 0) /* for GUS compatibility */
+ return awe_kill_note(dev, voice, note, velocity);
+ awe_calc_volume(i);
+ state = voices[i].state;
+ voices[i].state = AWE_ST_ON;
+ if (state == AWE_ST_STANDBY)
+ awe_note_on(i);
+ else
+ awe_set_volume(i, FALSE);
+ }
+ }
return 0;
}
- if (note_num == 255) {
- /* dynamic volume change; sample is already assigned */
- if (! voices[v].state || voices[v].sample == NULL)
- return 0;
- /* calculate volume parameter */
- voices[v].velocity = volume;
- awe_calc_volume(v);
- DISABLE_INTR(flags);
- awe_set_volume(v);
- RESTORE_INTR(flags);
- return 0;
- }
- /* assign a sample with the corresponding note */
- if ((voices[v].sample = awe_search_voice(v, note_num)) == NULL) {
- DEBUG(1,printk("AWE32: [-- sample is null]\n"));
- return 0;
+ /* stop the sound if still playing */
+ if (awe_exclusive_sound) {
+ for (i = 0; i < awe_max_voices; i++)
+ if (voices[i].key == key &&
+ voices[i].state != AWE_ST_OFF)
+ awe_note_off(i);
}
- /* calculate pitch & volume parameters */
- voices[v].note = note_num;
- voices[v].velocity = volume;
- awe_calc_pitch(v);
- awe_calc_volume(v);
- DISABLE_INTR(flags);
+ /* allocate voices */
+ if (awe_channel_mode)
+ awe_alloc_multi_voices(voice, note, velocity);
+ else
+ awe_alloc_one_voice(voice, note, velocity);
+
/* turn off other voices (for drums) */
- awe_exclusive_off(v);
- /* turn on the voice */
- awe_note_on(v);
- voices[v].state = 1; /* flag up */
- RESTORE_INTR(flags);
+ for (i = 0; i < awe_max_voices; i++)
+ if (voices[i].key == key && voices[i].sample)
+ awe_exclusive_off(i, voices[i].sample->exclusiveClass);
+
+ if (velocity == 0)
+ state = AWE_ST_STANDBY; /* stand by for playing */
+ else
+ state = AWE_ST_ON; /* really play */
+
+ /* set up pitch and volume parameters */
+ for (i = 0; i < awe_max_voices; i++)
+ if (voices[i].key == key) {
+ /* calculate pitch & volume parameters */
+ voices[i].state = state;
+ voices[i].note = note;
+ voices[i].velocity = velocity;
+ awe_calc_pitch(i);
+ awe_calc_volume(i);
+ if (state == AWE_ST_ON)
+ awe_note_on(i);
+ }
return 0;
}
@@ -1625,28 +1740,58 @@
/* assign the instrument to a voice */
static int
+awe_set_instr_2(int dev, int voice, int instr_no)
+{
+ if (awe_channel_mode == 2)
+ voice = voice_alloc->map[voice] >> 8;
+ return awe_set_instr(dev, voice, instr_no);
+}
+
+/* assign the instrument to a voice */
+static int
awe_set_instr(int dev, int voice, int instr_no)
{
- awe_voice_list *rec;
+ awe_chan_info *cinfo;
+ int def_bank;
- if (voice < 0 || voice >= awe_max_voices)
- return RET_ERROR(EINVAL);
+ if (awe_channel_mode) {
+ /* skip the percussion instr in SEQ2 mode */
+ if (voice < 0 || voice >= AWE_MAX_CHANNELS)
+ return RET_ERROR(EINVAL);
+ cinfo = &channels[voice];
+ if (IS_DRUM_CHANNEL(voice))
+ def_bank = AWE_DRUM_BANK;
+ else
+ def_bank = cinfo->bank;
+ } else {
+ if (voice < 0 || voice >= awe_max_voices)
+ return RET_ERROR(EINVAL);
+ cinfo = voices[voice].cinfo;
+ def_bank = cinfo->bank;
+ }
if (instr_no < 0 || instr_no >= AWE_MAX_PRESETS)
return RET_ERROR(EINVAL);
- if ((rec = awe_search_instr(voices[voice].bank, instr_no)) == NULL) {
- /* if bank is not defined, use the default bank 0 */
- if (voices[voice].bank != AWE_DEFAULT_BANK &&
- (rec = awe_search_instr(AWE_DEFAULT_BANK, instr_no)) == NULL) {
- DEBUG(1,printk("AWE32 Warning: can't find instrument %d\n", instr_no));
- return 0;
- }
+ cinfo->vrec = NULL;
+ cinfo->def_vrec = NULL;
+ if (instr_no > 128) {
+ cinfo->vrec = awe_search_instr(128, cinfo->bank);
+ if (cinfo->bank != 0)
+ cinfo->def_vrec = awe_search_instr(128, 0);
+ } else {
+ cinfo->vrec = awe_search_instr(def_bank, instr_no);
+ if (def_bank == AWE_DRUM_BANK)
+ cinfo->def_vrec = awe_search_instr(def_bank, 0);
+ else
+ cinfo->def_vrec = awe_search_instr(AWE_DEFAULT_BANK, instr_no);
+ }
+ if (cinfo->vrec == NULL && cinfo->def_vrec == NULL) {
+ DEBUG(1,printk("AWE32 Warning: can't find instrument %d\n", instr_no));
+ return 0;
}
- voices[voice].instr = instr_no;
- voices[voice].vrec = rec;
- voices[voice].sample = NULL; /* not set yet */
+ cinfo->instr = instr_no;
return 0;
}
@@ -1657,10 +1802,15 @@
awe_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_NORMAL_VOICES; i++) {
+ for (i = 0; i < AWE_NORMAL_VOICES; i++)
awe_terminate(i);
- awe_voice_init(i, 0);
+ for (i = 0; i < AWE_MAX_CHANNELS; i++)
+ awe_channel_init(i);
+ 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();
@@ -1676,10 +1826,15 @@
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 void
awe_hw_gus_control(int dev, int cmd, unsigned char *event)
@@ -1688,7 +1843,6 @@
unsigned short p1;
short p2;
int plong;
- DECL_INTR_FLAGS(flags);
voice = event[3];
p1 = *(unsigned short *) &event[4];
@@ -1698,7 +1852,7 @@
switch (cmd) {
case _GUS_NUMVOICES:
if (p1 >= awe_max_voices)
- printk("AWE32: num_voices: voices out of range %d\n", p1);
+ DEBUG(0,printk("AWE32: num_voices: voices out of range %d\n", p1));
break;
case _GUS_VOICESAMPLE:
if (voice < awe_max_voices)
@@ -1706,19 +1860,13 @@
break;
case _GUS_VOICEON:
- if (voice < awe_max_voices) {
- DISABLE_INTR(flags);
+ if (voice < awe_max_voices)
awe_note_on(voice);
- RESTORE_INTR(flags);
- }
break;
case _GUS_VOICEOFF:
- if (voice < awe_max_voices) {
- DISABLE_INTR(flags);
+ if (voice < awe_max_voices)
awe_note_off(voice);
- RESTORE_INTR(flags);
- }
break;
case _GUS_VOICEMODE:
@@ -1726,9 +1874,9 @@
break;
case _GUS_VOICEBALA:
- /* -128 to 127 */
+ /* 0 to 15 --> -128 to 127 */
if (voice < awe_max_voices)
- awe_panning(dev, voice, (short)p1);
+ awe_panning(dev, voice, ((int)p1 << 4) - 128);
break;
case _GUS_VOICEFREQ:
@@ -1754,13 +1902,35 @@
case _GUS_VOICE_POS:
if (voice < awe_max_voices) {
- FX_SET(voice, AWE_FX_SAMPLE_START, (short)(plong & 0x7fff));
- FX_SET(voice, AWE_FX_COARSE_SAMPLE_START, (plong >> 15) & 0xffff);
+ FX_SET(&voices[voice].cinfo->fx, AWE_FX_SAMPLE_START,
+ (short)(plong & 0x7fff));
+ FX_SET(&voices[voice].cinfo->fx, AWE_FX_COARSE_SAMPLE_START,
+ (plong >> 15) & 0xffff);
}
break;
}
}
+#endif
+
+
+/* converter function table for realtime paramter change */
+
+static fx_affect_func fx_realtime[] = {
+ /* env1: delay, attack, hold, decay, release, sustain, pitch, cutoff*/
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* env2: delay, attack, hold, decay, release, sustain */
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ /* lfo1: delay, freq, volume, pitch, cutoff */
+ NULL, awe_fx_tremfrq, awe_fx_tremfrq, awe_fx_fmmod, awe_fx_fmmod,
+ /* lfo2: delay, freq, pitch */
+ NULL, awe_fx_fm2frq2, awe_fx_fm2frq2,
+ /* global: initpitch, chorus, reverb, cutoff, filterQ */
+ awe_set_voice_pitch, NULL, NULL, awe_fx_cutoff, NULL,
+ /* sample: start, loopstart, loopend */
+ NULL, NULL, NULL,
+};
+
/* AWE32 specific controls */
static void
@@ -1770,20 +1940,29 @@
unsigned short p1;
short p2;
int chn;
+ awe_chan_info *cinfo;
+ int i;
chn = event[1];
voice = event[3];
p1 = *(unsigned short *) &event[4];
p2 = *(short *) &event[6];
+ if (awe_channel_mode) {
+ if (voice < 0 || voice >= AWE_MAX_CHANNELS)
+ return;
+ cinfo = &channels[voice];
+ } else {
+ if (voice < 0 || voice >= awe_max_voices)
+ return;
+ cinfo = voices[voice].cinfo;
+ }
-#ifdef AWE_DEBUG_ON
switch (cmd) {
case _AWE_DEBUG_MODE:
debug_mode = p1;
printk("AWE32: debug mode = %d\n", debug_mode);
break;
-#endif
case _AWE_REVERB_MODE:
if (p1 <= 7) {
reverb_mode = p1;
@@ -1810,32 +1989,36 @@
break;
case _AWE_SEND_EFFECT:
- if (voice < awe_max_voices && p1 < AWE_FX_END) {
- FX_SET(voice, p1, p2);
- DEBUG(0,printk("AWE32: effects (%d) %d %d\n", voice, p1, voices[voice].fx[p1]));
+ if (p1 < AWE_FX_END) {
+ FX_SET(&cinfo->fx, p1, p2);
+ DEBUG(0,printk("AWE32: effects (%d) %d %d\n", voice, p1, cinfo->fx.val[p1]));
+ FX_SET(&cinfo->fx, p1, p2);
if (fx_realtime[p1]) {
DEBUG(0,printk("AWE32: fx_realtime (%d)\n", voice));
- fx_realtime[p1](voice);
+ awe_voice_change(voice, fx_realtime[p1]);
}
}
break;
- case _AWE_TERMINATE_CHANNEL:
- if (voice < awe_max_voices) {
- DEBUG(0,printk("AWE32: terminate (%d)\n", voice));
- awe_terminate(voice);
- awe_voice_init(voice, 1);
- }
- break;
-
case _AWE_TERMINATE_ALL:
DEBUG(0,printk("AWE32: terminate all\n"));
awe_reset(0);
break;
+ case _AWE_TERMINATE_CHANNEL:
+ awe_voice_change(voice, (fx_affect_func)awe_terminate);
+ break;
+
+ case _AWE_NOTEOFF_ALL:
+ for (i = 0; i < awe_max_voices; i++)
+ awe_note_off(i);
+ break;
+
case _AWE_INITIAL_VOLUME:
DEBUG(0,printk("AWE32: init attenuation %d\n", p1));
init_atten = p1;
+ for (i = 0; i < awe_max_voices; i++)
+ awe_set_voice_vol(i, FALSE);
break;
case _AWE_SET_GUS_BANK:
@@ -1843,6 +2026,46 @@
awe_gus_bank = p1;
break;
+ /* v0.3 stuffs */
+ case _AWE_CHANNEL_MODE:
+ DEBUG(0,printk("AWE32: channel mode = %d\n", p1));
+ awe_channel_mode = p1;
+ awe_reset(0);
+ break;
+
+ case _AWE_DRUM_CHANNELS:
+ DEBUG(0,printk("AWE32: drum flags = %x\n", p1));
+ drum_flags = p1;
+ break;
+
+ case _AWE_EXCLUSIVE_SOUND:
+ DEBUG(0,printk("AWE32: exclusive mode = %d\n", p1));
+ awe_exclusive_sound = p1;
+ break;
+
+ case _AWE_GET_CURRENT_MODE:
+ {
+ awe_mode_rec tmprec;
+ tmprec.base_addr = awe_base;
+ tmprec.mem_size = awe_mem_size / 2;
+ tmprec.max_voices = awe_max_voices;
+ tmprec.max_infos = AWE_MAX_INFOS;
+ tmprec.max_samples = AWE_MAX_SAMPLES;
+ tmprec.current_sf_id = current_sf_id;
+ tmprec.free_mem = free_mem_ptr;
+ tmprec.free_info = free_info;
+ tmprec.free_sample = free_sample;
+ tmprec.reverb_mode = reverb_mode;
+ tmprec.chorus_mode = chorus_mode;
+ tmprec.init_atten = init_atten;
+ tmprec.channel_mode = awe_channel_mode;
+ tmprec.gus_bank = awe_gus_bank;
+ tmprec.exclusive_sound = awe_exclusive_sound;
+ tmprec.drum_flags = drum_flags;
+ tmprec.debug_mode = debug_mode;
+ IOCTL_TO_USER(*(awe_mode_rec**)&event[4], 0, &tmprec, sizeof(tmprec));
+ break;
+ }
default:
DEBUG(0,printk("AWE32: hw control cmd=%d voice=%d\n", cmd, voice));
break;
@@ -1862,9 +2085,12 @@
awe_patch_info patch;
int rc = 0;
+#ifdef AWE_HAS_GUS_COMPATIBILITY
if (format == GUS_PATCH) {
return awe_load_guspatch(addr, offs, count, pmgr_flag);
- } else if (format == SYSEX_PATCH) {
+ } else
+#endif
+ if (format == SYSEX_PATCH) {
/* no system exclusive message supported yet */
return 0;
} else if (format != AWE_PATCH) {
@@ -1872,14 +2098,14 @@
return RET_ERROR(EINVAL);
}
- if (count < sizeof(awe_patch_info)) {
+ if (count < AWE_PATCH_INFO_SIZE) {
FATALERR(printk("AWE32 Error: Patch header too short\n"));
return RET_ERROR(EINVAL);
}
COPY_FROM_USER(((char*)&patch) + offs, addr, offs,
- sizeof(awe_patch_info) - offs);
+ AWE_PATCH_INFO_SIZE - offs);
- count -= sizeof(awe_patch_info);
+ count -= AWE_PATCH_INFO_SIZE;
if (count < patch.len) {
FATALERR(printk("AWE32 Warning: Patch record too short (%d<%d)\n",
count, (int)patch.len));
@@ -1919,12 +2145,12 @@
unsigned char bank, instr;
int total_size;
- if (patch->len < sizeof(awe_voice_rec)) {
+ if (patch->len < AWE_VOICE_REC_SIZE) {
FATALERR(printk("AWE32 Error: invalid patch info length\n"));
return RET_ERROR(EINVAL);
}
- offset = sizeof(awe_patch_info);
+ offset = AWE_PATCH_INFO_SIZE;
GET_BYTE_FROM_USER(bank, addr, offset); offset++;
GET_BYTE_FROM_USER(instr, addr, offset); offset++;
GET_SHORT_FROM_USER(nvoices, addr, offset); offset+=2;
@@ -1938,7 +2164,7 @@
return RET_ERROR(ENOSPC);
}
- total_size = sizeof(awe_voice_rec) + sizeof(awe_voice_info) * nvoices;
+ total_size = AWE_VOICE_REC_SIZE + AWE_VOICE_INFO_SIZE * nvoices;
if (patch->len < total_size) {
ERRMSG(printk("AWE32 Error: patch length(%d) is smaller than nvoices(%d)\n",
(int)patch->len, nvoices));
@@ -1958,8 +2184,8 @@
rec->next_bank = NULL;
/* copy awe_voice_info parameters */
- COPY_FROM_USER(&rec->v, addr, offset, sizeof(awe_voice_info));
- offset += sizeof(awe_voice_info);
+ COPY_FROM_USER(&rec->v, addr, offset, AWE_VOICE_INFO_SIZE);
+ offset += AWE_VOICE_INFO_SIZE;
rec->v.sf_id = current_sf_id;
if (rec->v.mode & AWE_MODE_INIT_PARM)
awe_init_voice_parm(&rec->v.parm);
@@ -1988,11 +2214,11 @@
return RET_ERROR(ENOSPC);
}
- size = (patch->len - sizeof(awe_sample_info)) / 2;
- offset = sizeof(awe_patch_info);
+ size = (patch->len - AWE_SAMPLE_INFO_SIZE) / 2;
+ offset = AWE_PATCH_INFO_SIZE;
COPY_FROM_USER(&samples[free_sample], addr, offset,
- sizeof(awe_sample_info));
- offset += sizeof(awe_sample_info);
+ AWE_SAMPLE_INFO_SIZE);
+ offset += AWE_SAMPLE_INFO_SIZE;
if (size != samples[free_sample].size) {
ERRMSG(printk("AWE32 Warning: sample size differed (%d != %d)\n",
(int)samples[free_sample].size, (int)size));
@@ -2015,14 +2241,51 @@
{
if (!loaded_once) {
/* it's the first time */
- last_sample = free_sample;
- last_info = free_info;
+ if (current_sf_id == 1) {
+ last_sample = free_sample;
+ last_info = free_info;
+ }
current_sf_id++;
loaded_once = 1;
}
}
+/*----------------------------------------------------------------*/
+
+static const char *readbuf_addr;
+static long readbuf_offs;
+static int readbuf_flags;
+
+/* initialize read buffer */
+static void
+awe_init_readbuf(const char *addr, long offset, int size, int mode_flags)
+{
+ readbuf_addr = addr;
+ readbuf_offs = offset;
+ readbuf_flags = mode_flags;
+}
+
+/* read directly from user buffer */
+static unsigned short
+awe_read_word(int pos)
+{
+ unsigned short c;
+ /* read from user buffer */
+ if (readbuf_flags & AWE_SAMPLE_8BITS) {
+ unsigned char cc;
+ GET_BYTE_FROM_USER(cc, readbuf_addr, readbuf_offs + pos);
+ c = cc << 8; /* convert 8bit -> 16bit */
+ } else {
+ GET_SHORT_FROM_USER(c, readbuf_addr, readbuf_offs + pos * 2);
+ }
+ if (readbuf_flags & AWE_SAMPLE_UNSIGNED)
+ c ^= 0x8000; /* unsigned -> signed */
+ return c;
+}
+
+
+
#define BLANK_LOOP_START 8
#define BLANK_LOOP_END 40
#define BLANK_LOOP_SIZE 48
@@ -2035,7 +2298,6 @@
int i, truesize;
int rc;
unsigned long csum1, csum2;
- DECL_INTR_FLAGS(flags);
/* be sure loop points start < end */
if (sp->loopstart > sp->loopend) {
@@ -2066,42 +2328,33 @@
sp->loopstart += free_mem_ptr + AWE_DRAM_OFFSET;
sp->loopend += free_mem_ptr + AWE_DRAM_OFFSET;
- DISABLE_INTR(flags);
if ((rc = awe_open_dram_for_write(free_mem_ptr)) != 0) {
- RESTORE_INTR(flags);
return rc;
}
+ awe_init_readbuf(addr, offset, size, sp->mode_flags);
csum1 = 0;
for (i = 0; i < size; i++) {
- unsigned char cc;
unsigned short c;
- if (sp->mode_flags & AWE_SAMPLE_8BITS) {
- GET_BYTE_FROM_USER(cc, addr, offset); offset++;
- c = cc << 8; /* convert 8bit -> 16bit */
- } else {
- GET_SHORT_FROM_USER(c, addr, offset); offset += 2;
- }
- if (sp->mode_flags & AWE_SAMPLE_UNSIGNED)
- c ^= 0x8000; /* unsigned -> signed */
+ c = awe_read_word(i);
csum1 += c;
awe_write_dram(c);
if (i == sp->loopend &&
- (sp->mode_flags & AWE_SAMPLE_BIDIR_LOOP)) {
+ (sp->mode_flags & (AWE_SAMPLE_BIDIR_LOOP|AWE_SAMPLE_REVERSE_LOOP))) {
int looplen = sp->loopend - sp->loopstart;
/* copy reverse loop */
int k;
for (k = 0; k < looplen; k++) {
- if (sp->mode_flags & AWE_SAMPLE_8BITS) {
- GET_BYTE_FROM_USER(cc, addr, offset-k);
- c = cc << 8;
- } else {
- GET_SHORT_FROM_USER(c, addr, offset-k*2);
- }
- if (sp->mode_flags & AWE_SAMPLE_UNSIGNED)
- c ^= 0x8000;
+ /* non-buffered data */
+ c = awe_read_word(i - k);
awe_write_dram(c);
}
+ if (sp->mode_flags & AWE_SAMPLE_BIDIR_LOOP) {
+ sp->end += looplen;
+ } else {
+ sp->start += looplen;
+ sp->end += looplen;
+ }
}
}
@@ -2117,19 +2370,15 @@
}
awe_close_dram();
- RESTORE_INTR(flags);
if (sp->checksum_flag) {
#ifdef AWE_CHECKSUM_DATA
if (sp->checksum_flag != 2 && csum1 != sp->checksum) {
ERRMSG(printk("AWE32: [%d] checksum mismatch on data %x:%x\n",
- free_sample,
- (int)samples[free_sample].checksum,
- (int)csum1));
+ free_sample, (int)sp->checksum, (int)csum1));
return RET_ERROR(NO_DATA_ERR);
}
#endif /* AWE_CHECKSUM_DATA */
#ifdef AWE_CHECKSUM_MEMORY
- DISABLE_INTR(flags);
if (awe_open_dram_for_read(free_mem_ptr) == 0) {
csum2 = 0;
for (i = 0; i < size; i++) {
@@ -2138,30 +2387,28 @@
csum2 += c;
}
awe_close_dram_for_read();
- if (csum2 != samples[free_sample].checksum) {
- RESTORE_INTR(flags);
+ if (csum1 != csum2) {
ERRMSG(printk("AWE32: [%d] checksum mismatch on DRAM %x:%x\n",
- free_sample,
- (int)samples[free_sample].checksum,
- (int)csum2));
+ free_sample, (int)csum1, (int)csum2));
return RET_ERROR(NO_DATA_ERR);
}
}
- RESTORE_INTR(flags);
#endif /* AWE_CHECKSUM_MEMORY */
}
free_mem_ptr += sp->size;
/* re-initialize FM passthrough */
- DISABLE_INTR(flags);
awe_init_fm();
awe_tweak();
- RESTORE_INTR(flags);
return 0;
}
+/*----------------------------------------------------------------*/
+
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+
/* calculate GUS envelope time:
* is this correct? i have no idea..
*/
@@ -2219,7 +2466,7 @@
samples[free_sample].start = 0;
samples[free_sample].end = patch.len;
samples[free_sample].loopstart = patch.loop_start;
- samples[free_sample].loopend = patch.loop_end;
+ samples[free_sample].loopend = patch.loop_end + 1;
samples[free_sample].size = patch.len;
/* set up mode flags */
@@ -2229,10 +2476,12 @@
if (patch.mode & WAVE_UNSIGNED)
samples[free_sample].mode_flags |= AWE_SAMPLE_UNSIGNED;
samples[free_sample].mode_flags |= AWE_SAMPLE_NO_BLANK;
- if (!(patch.mode & (WAVE_LOOPING|WAVE_BIDIR_LOOP)))
+ if (!(patch.mode & (WAVE_LOOPING|WAVE_BIDIR_LOOP|WAVE_LOOP_BACK)))
samples[free_sample].mode_flags |= AWE_SAMPLE_SINGLESHOT;
if (patch.mode & WAVE_BIDIR_LOOP)
samples[free_sample].mode_flags |= AWE_SAMPLE_BIDIR_LOOP;
+ if (patch.mode & WAVE_LOOP_BACK)
+ samples[free_sample].mode_flags |= AWE_SAMPLE_REVERSE_LOOP;
DEBUG(0,printk("AWE32: [sample %d mode %x]\n", patch.instr_no,
samples[free_sample].mode_flags));
@@ -2336,8 +2585,11 @@
return 0;
}
+#endif /* AWE_HAS_GUS_COMPATIBILITY */
-/* remove samples with current sf_id from instrument list */
+/*----------------------------------------------------------------*/
+
+/* remove samples with different sf_id from instrument list */
static awe_voice_list *
awe_get_removed_list(awe_voice_list *curp)
{
@@ -2347,7 +2599,7 @@
prevp = &lastp;
for (maxc = AWE_MAX_INFOS;
curp && maxc; curp = curp->next_instr, maxc--) {
- if (curp->v.sf_id == current_sf_id)
+ if (curp->v.sf_id != 1)
*prevp = curp->next_instr;
else
prevp = &curp->next_instr;
@@ -2364,9 +2616,14 @@
int maxc;
int i;
+ /* no sample is loaded yet */
if (last_sample == free_sample && last_info == free_info)
return;
+ /* only the primary samples are loaded */
+ if (current_sf_id <= 1)
+ return;
+
/* remove the records from preset table */
for (i = 0; i < AWE_MAX_PRESETS; i++) {
prevp = &preset_table[i];
@@ -2388,7 +2645,7 @@
free_sample = last_sample;
free_info = last_info;
- current_sf_id--;
+ current_sf_id = 1;
loaded_once = 0;
}
@@ -2407,7 +2664,7 @@
vp->loopstart += samples[i].loopstart;
vp->loopend += samples[i].loopend;
/* copy mode flags */
- vp->mode |= (samples[i].mode_flags << 6);
+ vp->mode = samples[i].mode_flags;
/* set index */
vp->index = i;
return i;
@@ -2421,16 +2678,17 @@
static void
awe_aftertouch(int dev, int voice, int pressure)
{
- DECL_INTR_FLAGS(flags);
-
DEBUG(2,printk("AWE32: [after(%d) %d]\n", voice, pressure));
- if (voice < 0 || voice >= awe_max_voices)
- return;
- voices[voice].velocity = pressure;
- awe_calc_volume(voice);
- DISABLE_INTR(flags);
- awe_set_volume(voice);
- RESTORE_INTR(flags);
+ if (awe_channel_mode == 2) {
+ int note = (voice_alloc->map[voice] & 0xff) - 1;
+ awe_start_note(dev, voice, note + 0x80, pressure);
+
+ } else if (awe_channel_mode == 0) {
+ if (voice < 0 || voice >= awe_max_voices)
+ return;
+ voices[voice].velocity = pressure;
+ awe_set_voice_vol(voice, FALSE);
+ }
}
@@ -2438,77 +2696,98 @@
static void
awe_controller(int dev, int voice, int ctrl_num, int value)
{
- DECL_INTR_FLAGS(flags);
+ awe_chan_info *cinfo;
- if (voice < 0 || voice >= awe_max_voices)
- return;
+ if (awe_channel_mode) {
+ if (awe_channel_mode == 2) /* get channel */
+ voice = voice_alloc->map[voice] >> 8;
+ if (voice < 0 || voice >= AWE_MAX_CHANNELS)
+ return;
+ cinfo = &channels[voice];
+ } else {
+ if (voice < 0 || voice >= awe_max_voices)
+ return;
+ cinfo = voices[voice].cinfo;
+ }
switch (ctrl_num) {
- case CTL_BANK_SELECT:
+ case CTL_BANK_SELECT: /* SEQ1 control */
DEBUG(2,printk("AWE32: [bank(%d) %d]\n", voice, value));
- voices[voice].bank = value;
+ cinfo->bank = value;
+ awe_set_instr(dev, voice, cinfo->instr);
break;
- case CTRL_PITCH_BENDER:
+ case CTRL_PITCH_BENDER: /* SEQ1 V2 contorl */
DEBUG(2,printk("AWE32: [bend(%d) %d]\n", voice, value));
/* zero centered */
- voices[voice].bender = value;
- awe_calc_pitch(voice);
- DISABLE_INTR(flags);
- awe_set_pitch(voice);
- RESTORE_INTR(flags);
+ cinfo->bender = value;
+ awe_voice_change(voice, awe_set_voice_pitch);
break;
- case CTRL_PITCH_BENDER_RANGE:
+ case CTRL_PITCH_BENDER_RANGE: /* SEQ1 V2 control */
DEBUG(2,printk("AWE32: [range(%d) %d]\n", voice, value));
- /* sense x 100 */
- voices[voice].bender_range = value;
+ /* value = sense x 100 */
+ cinfo->bender_range = value;
/* no audible pitch change yet.. */
break;
- case CTL_EXPRESSION:
- value /= 128;
- case CTRL_EXPRESSION:
+ case CTL_EXPRESSION: /* SEQ1 control */
+ if (!awe_channel_mode)
+ value /= 128;
+ case CTRL_EXPRESSION: /* SEQ1 V2 control */
DEBUG(2,printk("AWE32: [expr(%d) %d]\n", voice, value));
/* 0 - 127 */
- voices[voice].expression_vol = value;
- awe_calc_volume(voice);
- DISABLE_INTR(flags);
- awe_set_volume(voice);
- RESTORE_INTR(flags);
+ cinfo->expression_vol = value;
+ awe_voice_change(voice, awe_set_voice_vol);
break;
- case CTL_PAN:
+ case CTL_PAN: /* SEQ1 control */
DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, value));
/* (0-127) -> signed 8bit */
- voices[voice].panning = value * 2 - 128;
- DISABLE_INTR(flags);
- awe_set_pan(voice, 0);
- RESTORE_INTR(flags);
+ cinfo->panning = value * 2 - 128;
+ awe_voice_change(voice, awe_set_pan);
break;
- case CTL_MAIN_VOLUME:
- value = (value * 127) / 16383;
- case CTRL_MAIN_VOLUME:
+ case CTL_MAIN_VOLUME: /* SEQ1 control */
+ if (!awe_channel_mode)
+ value = (value * 100) / 16383;
+ case CTRL_MAIN_VOLUME: /* SEQ1 V2 control */
DEBUG(2,printk("AWE32: [mainvol(%d) %d]\n", voice, value));
/* 0 - 127 */
- voices[voice].main_vol = value;
- awe_calc_volume(voice);
- DISABLE_INTR(flags);
- awe_set_volume(voice);
- RESTORE_INTR(flags);
+ cinfo->main_vol = value;
+ awe_voice_change(voice, awe_set_voice_vol);
break;
case CTL_EXT_EFF_DEPTH: /* reverb effects: 0-127 */
DEBUG(2,printk("AWE32: [reverb(%d) %d]\n", voice, value));
- FX_SET(voice, AWE_FX_REVERB, value * 2);
- break;
+ FX_SET(&cinfo->fx, AWE_FX_REVERB, value * 2);
+ break;
case CTL_CHORUS_DEPTH: /* chorus effects: 0-127 */
DEBUG(2,printk("AWE32: [chorus(%d) %d]\n", voice, value));
- FX_SET(voice, AWE_FX_CHORUS, value * 2);
- break;
+ FX_SET(&cinfo->fx, AWE_FX_CHORUS, value * 2);
+ break;
+#ifdef AWE_ACCEPT_ALL_SOUNDS_CONTROLL
+ case 120: /* all sounds off */
+ {int i; for (i = 0; i < AWE_NORMAL_VOICES; i++)
+ awe_terminate(i);
+ }
+ /*awe_reset(0);*/
+ break;
+ case 123: /* all notes off */
+ {int i;
+ for (i = 0; i < awe_max_voices; i++)
+ awe_note_off(i);
+ }
+ break;
+#endif
+
+ case CTL_SUSTAIN: /* sustain the channel */
+ cinfo->sustained = value;
+ if (value == 0)
+ awe_voice_change(voice, awe_sustain_off);
+ break;
default:
DEBUG(0,printk("AWE32: [control(%d) ctrl=%d val=%d]\n",
@@ -2518,18 +2797,48 @@
}
+
+/* change the voice parameters */
+static void awe_voice_change(int voice, fx_affect_func func)
+{
+ int i;
+ if (! awe_channel_mode) {
+ func(voice, FALSE);
+ return;
+ }
+
+ for (i = 0; i < awe_max_voices; i++)
+ if (voices[i].ch == voice)
+ func(i, FALSE);
+}
+
+
+/* drop sustain */
+static void awe_sustain_off(int voice, int forced)
+{
+ if (voices[voice].state == AWE_ST_SUSTAINED)
+ awe_note_off(voice);
+}
+
+
/* voice pan change (value = -128 - 127) */
static void
awe_panning(int dev, int voice, int value)
{
- DECL_INTR_FLAGS(flags);
- if (voice >= 0 || voice < awe_max_voices) {
- voices[voice].panning = value;
- DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, voices[voice].panning));
- DISABLE_INTR(flags);
- awe_set_pan(voice, 0);
- RESTORE_INTR(flags);
+ awe_chan_info *cinfo;
+ if (awe_channel_mode) {
+ if (voice < 0 || voice >= AWE_MAX_CHANNELS)
+ return;
+ cinfo = &channels[voice];
+ } else {
+ if (voice < 0 || voice >= awe_max_voices)
+ return;
+ cinfo = voices[voice].cinfo;
}
+
+ cinfo->panning = value;
+ DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, cinfo->panning));
+ awe_voice_change(voice, awe_set_pan);
}
@@ -2542,63 +2851,173 @@
}
+#ifndef AWE_NO_PATCHMGR
+/* patch manager */
+static int
+awe_patchmgr(int dev, struct patmgr_info *rec)
+{
+ FATALERR(printk("AWE32 Warning: patch manager control not supported\n"));
+ return 0;
+}
+#endif
+
+
/* pitch wheel change: 0-16384 */
static void
awe_bender(int dev, int voice, int value)
{
- DECL_INTR_FLAGS(flags);
-
- if (voice < 0 || voice >= awe_max_voices)
- return;
+ awe_chan_info *cinfo;
+ if (awe_channel_mode) {
+ if (awe_channel_mode == 2)
+ voice = voice_alloc->map[voice] >> 8;
+ if (voice < 0 || voice >= AWE_MAX_CHANNELS)
+ return;
+ cinfo = &channels[voice];
+ } else {
+ if (voice < 0 || voice >= awe_max_voices)
+ return;
+ cinfo = voices[voice].cinfo;
+ }
/* convert to zero centered value */
- voices[voice].bender = value - 8192;
- DEBUG(2,printk("AWE32: [bend(%d) %d]\n", voice, voices[voice].bender));
- awe_calc_pitch(voice);
- DISABLE_INTR(flags);
- awe_set_pitch(voice);
- RESTORE_INTR(flags);
+ cinfo->bender = value - 8192;
+ DEBUG(2,printk("AWE32: [bend(%d) %d]\n", voice, cinfo->bender));
+ awe_voice_change(voice, awe_set_voice_pitch);
}
-
-/* search an empty voice; used by sequencer2 */
+/* calculate the number of voices for this note & velocity */
static int
-awe_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc)
+awe_search_multi_voices(awe_voice_list *rec, int note, int velocity, awe_voice_info **vlist)
{
- int i, p, best = -1, best_time = 0x7fffffff;
+ int maxc;
+ int nvoices;
+ unsigned short sf_id;
- p = alloc->ptr;
- /* First look for a completely stopped voice */
+ sf_id = current_sf_id;
+ nvoices = 0;
+ for (maxc = AWE_MAX_INFOS;
+ rec && maxc; rec = rec->next_instr, maxc--) {
+ if (rec->v.low <= note && note <= rec->v.high &&
+ velocity >= rec->v.vellow && velocity <= rec->v.velhigh) {
+ if (nvoices == 0)
+ sf_id = rec->v.sf_id;
+ else if (rec->v.sf_id != sf_id)
+ continue;
+ vlist[nvoices] = &rec->v;
+ nvoices++;
+ if (nvoices >= AWE_MAX_VOICES)
+ break;
+ }
+ }
+ return nvoices;
+}
- for (i = 0; i < alloc->max_voice; i++) {
- if (alloc->map[p] == 0) {
- alloc->ptr = p;
- return p;
+/* allocate voices corresponding note and velocity; supports multiple insts. */
+static void
+awe_alloc_multi_voices(int ch, int note, int velocity)
+{
+ int i, v, nvoices;
+ awe_voice_info *vlist[AWE_MAX_VOICES];
+
+ if (channels[ch].vrec == NULL && channels[ch].def_vrec == NULL)
+ awe_set_instr(0, ch, channels[ch].instr);
+
+ nvoices = awe_search_multi_voices(channels[ch].vrec, note, velocity, vlist);
+ if (nvoices == 0)
+ nvoices = awe_search_multi_voices(channels[ch].def_vrec, note, velocity, vlist);
+
+ /* allocate the voices */
+ current_alloc_time++;
+ for (i = 0; i < nvoices; i++) {
+ v = awe_clear_voice();
+ voices[v].key = AWE_CHAN_KEY(ch, note);
+ voices[v].ch = ch;
+ voices[v].time = current_alloc_time;
+ voices[v].cinfo = &channels[ch];
+ voices[v].sample = vlist[i];
+ voices[v].state = AWE_ST_MARK;
+ }
+
+ /* clear the mark in allocated voices */
+ for (i = 0; i < awe_max_voices; i++)
+ if (voices[i].state == AWE_ST_MARK)
+ voices[i].state = AWE_ST_OFF;
+}
+
+
+/* search an empty voice; used internally */
+static int
+awe_clear_voice(void)
+{
+ int i, time, best;
+
+ /* looking for the oldest empty voice */
+ best = -1;
+ time = 0x7fffffff;
+ for (i = 0; i < awe_max_voices; i++) {
+ if (voices[i].state == AWE_ST_OFF && voices[i].time < time) {
+ best = i;
+ time = voices[i].time;
}
- if (alloc->alloc_times[p] < best_time) {
- best = p;
- best_time = alloc->alloc_times[p];
+ }
+ if (best >= 0)
+ return best;
+
+ /* looking for the oldest sustained voice */
+ time = 0x7fffffff;
+ for (i = 0; i < awe_max_voices; i++) {
+ if (voices[i].state == AWE_ST_SUSTAINED &&
+ voices[i].time < time) {
+ best = i;
+ time = voices[i].time;
}
- p = (p + 1) % alloc->max_voice;
+ }
+ if (best >= 0) {
+ awe_note_off(best);
+ return best;
}
- /* Then look for a releasing voice */
- for (i = 0; i < alloc->max_voice; i++) {
- if (alloc->map[p] == 0xffff) {
- alloc->ptr = p;
- return p;
+ /* looking for the oldest voice not marked */
+ time = 0x7fffffff;
+ best = 0;
+ for (i = 0; i < awe_max_voices; i++) {
+ if (voices[i].state != AWE_ST_MARK && voices[i].time < time) {
+ best = i;
+ time = voices[i].time;
}
- p = (p + 1) % alloc->max_voice;
}
+ /*awe_terminate(best);*/
+ awe_note_off(best);
+ return best;
+}
- if (best >= 0)
- p = best;
- /* terminate the voice */
- if (voices[p].state)
- awe_terminate(p);
+/* allocate a voice corresponding note and velocity; single instrument */
+static void
+awe_alloc_one_voice(int voice, int note, int velocity)
+{
+ int nvoices;
+ awe_voice_info *vlist[AWE_MAX_VOICES];
+
+ if (voices[voice].cinfo->vrec == NULL && voices[voice].cinfo->def_vrec == NULL)
+ awe_set_instr(0, voice, voices[voice].cinfo->instr);
+
+ nvoices = awe_search_multi_voices(voices[voice].cinfo->vrec, note, velocity, vlist);
+ if (nvoices == 0)
+ nvoices = awe_search_multi_voices(voices[voice].cinfo->def_vrec, note, velocity, vlist);
- alloc->ptr = p;
- return p;
+ if (nvoices > 0) {
+ voices[voice].time = ++current_alloc_time;
+ voices[voice].sample = vlist[0]; /* use the first one */
+ }
+}
+
+
+/* search an empty voice; used by sequencer2 */
+static int
+awe_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc)
+{
+ awe_channel_mode = 2;
+ return awe_clear_voice();
}
@@ -2610,18 +3029,27 @@
if (synth_devs[dev] == NULL ||
(info = &synth_devs[dev]->chn_info[chn]) == NULL)
return;
+
if (voice < 0 || voice >= awe_max_voices)
return;
DEBUG(2,printk("AWE32: [setup(%d) ch=%d]\n", voice, chn));
- voices[voice].expression_vol = info->controllers[CTL_EXPRESSION];
- voices[voice].main_vol =
- (info->controllers[CTL_MAIN_VOLUME] * 100) / 128; /* 0 - 127 */
- voices[voice].panning =
+ channels[chn].expression_vol = info->controllers[CTL_EXPRESSION];
+ channels[chn].main_vol = info->controllers[CTL_MAIN_VOLUME];
+ channels[chn].panning =
info->controllers[CTL_PAN] * 2 - 128; /* signed 8bit */
- voices[voice].bender = info->bender_value; /* zero center */
- voices[voice].bank = info->controllers[CTL_BANK_SELECT];
- awe_set_instr(dev, voice, info->pgm_num);
+ channels[chn].bender = info->bender_value; /* zero center */
+ channels[chn].bank = info->controllers[CTL_BANK_SELECT];
+ channels[chn].sustained = info->controllers[CTL_SUSTAIN];
+ if (info->controllers[CTL_EXT_EFF_DEPTH]) {
+ FX_SET(&channels[chn].fx, AWE_FX_REVERB,
+ info->controllers[CTL_EXT_EFF_DEPTH] * 2);
+ }
+ if (info->controllers[CTL_CHORUS_DEPTH]) {
+ FX_SET(&channels[chn].fx, AWE_FX_CHORUS,
+ info->controllers[CTL_CHORUS_DEPTH] * 2);
+ }
+ awe_set_instr(dev, chn, info->pgm_num);
}
@@ -2637,9 +3065,10 @@
/* turn off envelope engines */
for (ch = 0; ch < AWE_MAX_VOICES; ch++) {
- awe_poke(AWE_DCYSUSV(ch), 0x0080);
+ awe_poke(AWE_DCYSUSV(ch), 0x80);
}
+ /* reset all other parameters to zero */
for (ch = 0; ch < AWE_MAX_VOICES; ch++) {
awe_poke(AWE_ENVVOL(ch), 0);
awe_poke(AWE_ENVVAL(ch), 0);
@@ -2672,14 +3101,14 @@
static void
awe_init_dma(void)
{
- awe_poke_dw(AWE_SMALR, 0x00000000);
- awe_poke_dw(AWE_SMARR, 0x00000000);
- awe_poke_dw(AWE_SMALW, 0x00000000);
- awe_poke_dw(AWE_SMARW, 0x00000000);
+ awe_poke_dw(AWE_SMALR, 0);
+ awe_poke_dw(AWE_SMARR, 0);
+ awe_poke_dw(AWE_SMALW, 0);
+ awe_poke_dw(AWE_SMARW, 0);
}
-/* initialization arrays */
+/* initialization arrays; from ADIP */
static unsigned short init1[128] = {
0x03ff, 0x0030, 0x07ff, 0x0130, 0x0bff, 0x0230, 0x0fff, 0x0330,
@@ -2718,6 +3147,7 @@
0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730,
0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30,
0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30,
+
0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330,
0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730,
0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30,
@@ -2806,35 +3236,39 @@
* set up awe32 channels to some known state.
*/
+/* set the envelope & LFO parameters to the default values; see ADIP */
+static void
+awe_tweak_voice(int i)
+{
+ /* set all mod/vol envelope shape to minimum */
+ awe_poke(AWE_ENVVOL(i), 0x8000);
+ awe_poke(AWE_ENVVAL(i), 0x8000);
+ awe_poke(AWE_DCYSUS(i), 0x7F7F);
+ awe_poke(AWE_ATKHLDV(i), 0x7F7F);
+ awe_poke(AWE_ATKHLD(i), 0x7F7F);
+ awe_poke(AWE_PEFE(i), 0); /* mod envelope height to zero */
+ awe_poke(AWE_LFO1VAL(i), 0x8000); /* no delay for LFO1 */
+ awe_poke(AWE_LFO2VAL(i), 0x8000);
+ awe_poke(AWE_IP(i), 0xE000); /* no pitch shift */
+ awe_poke(AWE_IFATN(i), 0xFF00); /* volume to minimum */
+ awe_poke(AWE_FMMOD(i), 0);
+ awe_poke(AWE_TREMFRQ(i), 0);
+ awe_poke(AWE_FM2FRQ2(i), 0);
+}
+
static void
awe_tweak(void)
{
int i;
-
- /* Set the envelope engine parameters to the "default" values for
- simply playing back unarticulated audio at 44.1kHz. Set all
- of the channels: */
-
- for (i = 0; i < AWE_MAX_VOICES; i++) {
- awe_poke(AWE_ENVVOL(i) , 0x8000);
- awe_poke(AWE_ENVVAL(i) , 0x8000);
- awe_poke(AWE_DCYSUS(i) , 0x7F7F);
- awe_poke(AWE_ATKHLDV(i) , 0x7F7F);
- awe_poke(AWE_LFO1VAL(i) , 0x8000);
- awe_poke(AWE_ATKHLD(i) , 0x7F7F);
- awe_poke(AWE_LFO2VAL(i) , 0x8000);
- awe_poke(AWE_IP(i) , 0xE000);
- awe_poke(AWE_IFATN(i) , 0xFF00);
- awe_poke(AWE_PEFE(i) , 0x0000);
- awe_poke(AWE_FMMOD(i) , 0x0000);
- awe_poke(AWE_TREMFRQ(i) , 0x0010);
- awe_poke(AWE_FM2FRQ2(i) , 0x0010);
- }
+ /* reset all channels */
+ for (i = 0; i < awe_max_voices; i++)
+ awe_tweak_voice(i);
}
/*
- * initializes the FM section of AWE32
+ * initializes the FM section of AWE32;
+ * see Vince Vu's unofficial AWE32 programming guide
*/
static void
@@ -2845,39 +3279,32 @@
if (awe_mem_size <= 0)
return;
#endif
- DEBUG(0,printk("AWE32: initializing FM\n"));
+ DEBUG(3,printk("AWE32: initializing FM\n"));
/* Initialize the last two channels for DRAM refresh and producing
the reverb and chorus effects for Yamaha OPL-3 synthesizer */
- awe_poke( AWE_DCYSUSV(30) , 0x0080);
- awe_poke_dw(AWE_PSST(30) , 0xFFFFFFE0);
- awe_poke_dw(AWE_CSL(30) , 0xFFFFFFE8);
- awe_poke_dw(AWE_PTRX(30) , 0x00FFFF00);
- awe_poke_dw(AWE_CPF(30) , 0x00000000);
- awe_poke_dw(AWE_CCCA(30) , 0x00FFFFE3);
-
- awe_poke( AWE_DCYSUSV(31) , 0x0080);
- awe_poke_dw(AWE_PSST(31) , 0x00FFFFE0);
- awe_poke_dw(AWE_CSL(31) , 0xFFFFFFE8);
- awe_poke_dw(AWE_PTRX(31) , 0x00FFFF00);
- awe_poke_dw(AWE_CPF(31) , 0x00000000);
- awe_poke_dw(AWE_CCCA(31) , 0x00FFFFE3);
-
- /* Timing loop */
-
- /* PTRX is 32 bit long but do not write to the MS byte */
- awe_poke(AWE_PTRX(30) , 0x0000);
-
- while(! (inw(awe_base-0x620+Pointer) & 0x1000));
- while( inw(awe_base-0x620+Pointer) & 0x1000);
-
- /* now write the MS byte of PTRX */
- OUTW(0x4828, awe_base-0x620+Data0+0x002);
-
- awe_poke( AWE_IFATN(28) , 0x0000);
- awe_poke_dw(AWE_VTFT(30) , 0x8000FFFF);
- awe_poke_dw(AWE_VTFT(31) , 0x8000FFFF);
+ /* 31: FM left channel, 0xffffe0-0xffffe8 */
+ awe_poke(AWE_DCYSUSV(30), 0x80);
+ awe_poke_dw(AWE_PSST(30), 0xFFFFFFE0); /* full left */
+ awe_poke_dw(AWE_CSL(30), 0x00FFFFE8 |
+ (DEF_FM_CHORUS_DEPTH << 24));
+ awe_poke_dw(AWE_PTRX(30), (DEF_FM_REVERB_DEPTH << 8));
+ awe_poke_dw(AWE_CPF(30), 0);
+ awe_poke_dw(AWE_CCCA(30), 0x00FFFFE3);
+
+ /* 32: FM right channel, 0xfffff0-0xfffff8 */
+ awe_poke(AWE_DCYSUSV(31), 0x80);
+ awe_poke_dw(AWE_PSST(31), 0x00FFFFF0); /* full right */
+ awe_poke_dw(AWE_CSL(31), 0x00FFFFF8 |
+ (DEF_FM_CHORUS_DEPTH << 24));
+ awe_poke_dw(AWE_PTRX(31), (DEF_FM_REVERB_DEPTH << 8));
+ awe_poke_dw(AWE_CPF(31), 0);
+ awe_poke_dw(AWE_CCCA(31), 0x00FFFFF3);
+
+ /* skew volume & cutoff */
+ awe_poke_dw(AWE_VTFT(30), 0x8000FFFF);
+ awe_poke_dw(AWE_VTFT(31), 0x8000FFFF);
/* change maximum channels to 30 */
awe_max_voices = AWE_NORMAL_VOICES;
@@ -2933,22 +3360,19 @@
static void
awe_open_dram_for_check(void)
{
- int k;
- unsigned long scratch;
-
- awe_poke(AWE_HWCF2 , 0x0020);
-
- for (k = 0; k < AWE_NORMAL_VOICES; k++) {
- awe_poke(AWE_DCYSUSV(k), 0x0080);
- awe_poke_dw(AWE_VTFT(k), 0x00000000);
- awe_poke_dw(AWE_CVCF(k), 0x00000000);
- awe_poke_dw(AWE_PTRX(k), 0x40000000);
- awe_poke_dw(AWE_CPF(k), 0x40000000);
- awe_poke_dw(AWE_PSST(k), 0x00000000);
- awe_poke_dw(AWE_CSL(k), 0x00000000);
- scratch = (((k&1) << 9) + 0x400);
- scratch = scratch << 16;
- awe_poke_dw(AWE_CCCA(k), scratch);
+ int i;
+ for (i = 0; i < AWE_NORMAL_VOICES; i++) {
+ awe_poke(AWE_DCYSUSV(i), 0x80);
+ awe_poke_dw(AWE_VTFT(i), 0);
+ awe_poke_dw(AWE_CVCF(i), 0);
+ awe_poke_dw(AWE_PTRX(i), 0x40000000);
+ awe_poke_dw(AWE_CPF(i), 0x40000000);
+ awe_poke_dw(AWE_PSST(i), 0);
+ awe_poke_dw(AWE_CSL(i), 0);
+ if (i & 1) /* DMA write */
+ awe_poke_dw(AWE_CCCA(i), 0x06000000);
+ else /* DMA read */
+ awe_poke_dw(AWE_CCCA(i), 0x04000000);
}
}
@@ -3037,13 +3461,6 @@
static void
awe_write_dram(unsigned short c)
{
- int k;
- /* wait until FULL bit in SMAxW register be false */
- for (k = 0; k < 10000; k++) {
- if (!(awe_peek_dw(AWE_SMALW) & 0x80000000))
- break;
- awe_wait(10);
- }
awe_poke(AWE_SMLD, c);
}
@@ -3051,27 +3468,34 @@
* detect presence of AWE32 and check memory size
*================================================================*/
+/* detect emu8000 chip on the specified address; from VV's guide */
+
+static int
+awe_detect_base(int addr)
+{
+ awe_base = addr;
+ if ((awe_peek(AWE_U1) & 0x000F) != 0x000C)
+ return 0;
+ if ((awe_peek(AWE_HWCF1) & 0x007E) != 0x0058)
+ return 0;
+ if ((awe_peek(AWE_HWCF2) & 0x0003) != 0x0003)
+ return 0;
+ DEBUG(0,printk("AWE32 found at %x\n", awe_base));
+ return 1;
+}
+
static int
awe_detect(void)
{
+ int base;
#ifdef AWE_DEFAULT_BASE_ADDR
- awe_base = AWE_DEFAULT_BASE_ADDR;
- if (((awe_peek(AWE_U1) & 0x000F) == 0x000C) &&
- ((awe_peek(AWE_HWCF1) & 0x007E) == 0x0058) &&
- ((awe_peek(AWE_HWCF2) & 0x0003) == 0x0003))
+ if (awe_detect_base(AWE_DEFAULT_BASE_ADDR))
return 1;
#endif
if (awe_base == 0) {
- for (awe_base = 0x620; awe_base <= 0x680; awe_base += 0x20) {
- if ((awe_peek(AWE_U1) & 0x000F) != 0x000C)
- continue;
- if ((awe_peek(AWE_HWCF1) & 0x007E) != 0x0058)
- continue;
- if ((awe_peek(AWE_HWCF2) & 0x0003) != 0x0003)
- continue;
- DEBUG(0,printk("AWE32 found at %x\n", awe_base));
- return 1;
- }
+ for (base = 0x620; base <= 0x680; base += 0x20)
+ if (awe_detect_base(base))
+ return 1;
}
FATALERR(printk("AWE32 not found\n"));
awe_base = 0;
@@ -3082,28 +3506,40 @@
/*================================================================
* check dram size on AWE board
*================================================================*/
+
+/* any three numbers you like */
+#define UNIQUE_ID1 0x1234
+#define UNIQUE_ID2 0x4321
+#define UNIQUE_ID3 0xFFFF
+
static int
awe_check_dram(void)
{
awe_open_dram_for_check();
- awe_poke_dw(AWE_SMALW , 0x00200000); /* DRAM start address */
- awe_poke( AWE_SMLD , 0x1234);
- awe_poke( AWE_SMLD , 0x7777);
+ /* set up unique two id numbers */
+ awe_poke_dw(AWE_SMALW, AWE_DRAM_OFFSET);
+ awe_poke(AWE_SMLD, UNIQUE_ID1);
+ awe_poke(AWE_SMLD, UNIQUE_ID2);
awe_mem_size = 0;
- while (awe_mem_size < 28*1024) { /* 28 MB is max onboard memory */
+ while (awe_mem_size < AWE_MAX_DRAM_SIZE) {
awe_wait(2);
- awe_poke_dw(AWE_SMALR, 0x00200000); /* Address for reading */
- awe_peek(AWE_SMLD); /* Discard stale data */
- if (awe_peek(AWE_SMLD) != 0x1234)
+ /* read a data on the DRAM start address */
+ awe_poke_dw(AWE_SMALR, AWE_DRAM_OFFSET);
+ awe_peek(AWE_SMLD); /* discard stale data */
+ if (awe_peek(AWE_SMLD) != UNIQUE_ID1)
break;
- if (awe_peek(AWE_SMLD) != 0x7777)
+ if (awe_peek(AWE_SMLD) != UNIQUE_ID2)
break;
- awe_mem_size += 32;
- /* Address for writing */
- awe_poke_dw(AWE_SMALW, 0x00200000+awe_mem_size*512L);
- awe_poke(AWE_SMLD, 0xFFFF);
+ awe_mem_size += 32; /* increment 32 Kbytes */
+ /* Write a unique data on the test address;
+ * if the address is out of range, the data is written on
+ * 0x200000(=AWE_DRAM_OFFSET). Then the two id words are
+ * broken by this data.
+ */
+ awe_poke_dw(AWE_SMALW, AWE_DRAM_OFFSET + awe_mem_size*512L);
+ awe_poke(AWE_SMLD, UNIQUE_ID3);
}
awe_close_dram();
@@ -3119,113 +3555,107 @@
/*================================================================
- * chorus and reverb controls
+ * chorus and reverb controls; from VV's guide
*================================================================*/
-static unsigned short ChorusEffects[24] =
-{
- 0xE600,0x03F6,0xBC2C,0xE608,0x031A,0xBC6E,0xE610,0x031A,
- 0xBC84,0xE620,0x0269,0xBC6E,0xE680,0x04D3,0xBCA6,0xE6E0,
- 0x044E,0xBC37,0xE600,0x0B06,0xBC00,0xE6C0,0x0B06,0xBC00
+/* 5 parameters for each chorus mode; 3 x 16bit, 2 x 32bit */
+static unsigned short chorus_parm[8][5] = {
+ {0xE600, 0x03F6, 0xBC2C ,0x0000, 0x006D}, /* chorus 1 */
+ {0xE608, 0x031A, 0xBC6E, 0x0000, 0x017C}, /* chorus 2 */
+ {0xE610, 0x031A, 0xBC84, 0x0000, 0x0083}, /* chorus 3 */
+ {0xE620, 0x0269, 0xBC6E, 0x0000, 0x017C}, /* chorus 4 */
+ {0xE680, 0x04D3, 0xBCA6, 0x0000, 0x005B}, /* feedback */
+ {0xE6E0, 0x044E, 0xBC37, 0x0000, 0x0026}, /* flanger */
+ {0xE600, 0x0B06, 0xBC00, 0xE000, 0x0083}, /* short delay */
+ {0xE6C0, 0x0B06, 0xBC00, 0xE000, 0x0083}, /* short delay + feedback */
};
-static unsigned long ChorusEffects2[] =
+static void awe_set_chorus_mode(int effect)
{
- 0x0000 ,0x006D,0x8000,0x0000,0x0000 ,0x017C,0x8000,0x0000,
- 0x0000 ,0x0083,0x8000,0x0000,0x0000 ,0x017C,0x8000,0x0000,
- 0x0000 ,0x005B,0x8000,0x0000,0x0000 ,0x0026,0x8000,0x0000,
- 0x6E000,0x0083,0x8000,0x0000,0x6E000,0x0083,0x8000,0x0000
-};
+ awe_poke(AWE_INIT3(9), chorus_parm[effect][0]);
+ awe_poke(AWE_INIT3(12), chorus_parm[effect][1]);
+ awe_poke(AWE_INIT4(3), chorus_parm[effect][2]);
+ awe_poke_dw(AWE_HWCF4, (unsigned long)chorus_parm[effect][3]);
+ awe_poke_dw(AWE_HWCF5, (unsigned long)chorus_parm[effect][4]);
+ awe_poke_dw(AWE_HWCF6, 0x8000);
+ awe_poke_dw(AWE_HWCF7, 0x0000);
+}
-static unsigned short ChorusCommand[14] =
-{
- 0x69,0xA20,0x6C,0xA20,0x63,0xA22,0x29,
- 0xA20,0x2A,0xA20,0x2D,0xA20,0x2E,0xA20
-};
+/*----------------------------------------------------------------*/
-static unsigned short ReverbEffects[224] =
-{
- /* Room 1 */
- 0xB488,0xA450,0x9550,0x84B5,0x383A,0x3EB5,0x72F4,
- 0x72A4,0x7254,0x7204,0x7204,0x7204,0x4416,0x4516,
- 0xA490,0xA590,0x842A,0x852A,0x842A,0x852A,0x8429,
- 0x8529,0x8429,0x8529,0x8428,0x8528,0x8428,0x8528,
- /* Room 2 */
- 0xB488,0xA458,0x9558,0x84B5,0x383A,0x3EB5,0x7284,
- 0x7254,0x7224,0x7224,0x7254,0x7284,0x4448,0x4548,
- 0xA440,0xA540,0x842A,0x852A,0x842A,0x852A,0x8429,
- 0x8529,0x8429,0x8529,0x8428,0x8528,0x8428,0x8528,
- /* Room 3 */
- 0xB488,0xA460,0x9560,0x84B5,0x383A,0x3EB5,0x7284,
- 0x7254,0x7224,0x7224,0x7254,0x7284,0x4416,0x4516,
- 0xA490,0xA590,0x842C,0x852C,0x842C,0x852C,0x842B,
- 0x852B,0x842B,0x852B,0x842A,0x852A,0x842A,0x852A,
- /* Hall 1 */
- 0xB488,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7284,
- 0x7254,0x7224,0x7224,0x7254,0x7284,0x4448,0x4548,
- 0xA440,0xA540,0x842B,0x852B,0x842B,0x852B,0x842A,
- 0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529,
- /* Hall 2 */
- 0xB488,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7254,
- 0x7234,0x7224,0x7254,0x7264,0x7294,0x44C3,0x45C3,
- 0xA404,0xA504,0x842A,0x852A,0x842A,0x852A,0x8429,
- 0x8529,0x8429,0x8529,0x8428,0x8528,0x8428,0x8528,
- /* Plate */
- 0xB4FF,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7234,
- 0x7234,0x7234,0x7234,0x7234,0x7234,0x4448,0x4548,
- 0xA440,0xA540,0x842A,0x852A,0x842A,0x852A,0x8429,
- 0x8529,0x8429,0x8529,0x8428,0x8528,0x8428,0x8528,
- /* Delay */
- 0xB4FF,0xA470,0x9500,0x84B5,0x333A,0x39B5,0x7204,
- 0x7204,0x7204,0x7204,0x7204,0x72F4,0x4400,0x4500,
- 0xA4FF,0xA5FF,0x8420,0x8520,0x8420,0x8520,0x8420,
- 0x8520,0x8420,0x8520,0x8420,0x8520,0x8420,0x8520,
- /* Panning Delay */
- 0xB4FF,0xA490,0x9590,0x8474,0x333A,0x39B5,0x7204,
- 0x7204,0x7204,0x7204,0x7204,0x72F4,0x4400,0x4500,
- 0xA4FF,0xA5FF,0x8420,0x8520,0x8420,0x8520,0x8420,
- 0x8520,0x8420,0x8520,0x8420,0x8520,0x8420,0x8520
+/* reverb mode settings; write the following 28 data of 16 bit length
+ * on the corresponding ports in the reverb_cmds array
+ */
+static unsigned short reverb_parm[8][28] = {
+{ /* room 1 */
+ 0xB488, 0xA450, 0x9550, 0x84B5, 0x383A, 0x3EB5, 0x72F4,
+ 0x72A4, 0x7254, 0x7204, 0x7204, 0x7204, 0x4416, 0x4516,
+ 0xA490, 0xA590, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
+ 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
+},
+{ /* room 2 */
+ 0xB488, 0xA458, 0x9558, 0x84B5, 0x383A, 0x3EB5, 0x7284,
+ 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
+ 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
+ 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
+},
+{ /* room 3 */
+ 0xB488, 0xA460, 0x9560, 0x84B5, 0x383A, 0x3EB5, 0x7284,
+ 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4416, 0x4516,
+ 0xA490, 0xA590, 0x842C, 0x852C, 0x842C, 0x852C, 0x842B,
+ 0x852B, 0x842B, 0x852B, 0x842A, 0x852A, 0x842A, 0x852A,
+},
+{ /* hall 1 */
+ 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7284,
+ 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
+ 0xA440, 0xA540, 0x842B, 0x852B, 0x842B, 0x852B, 0x842A,
+ 0x852A, 0x842A, 0x852A, 0x8429, 0x8529, 0x8429, 0x8529,
+},
+{ /* hall 2 */
+ 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7254,
+ 0x7234, 0x7224, 0x7254, 0x7264, 0x7294, 0x44C3, 0x45C3,
+ 0xA404, 0xA504, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
+ 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
+},
+{ /* plate */
+ 0xB4FF, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7234,
+ 0x7234, 0x7234, 0x7234, 0x7234, 0x7234, 0x4448, 0x4548,
+ 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
+ 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
+},
+{ /* delay */
+ 0xB4FF, 0xA470, 0x9500, 0x84B5, 0x333A, 0x39B5, 0x7204,
+ 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
+ 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
+ 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
+},
+{ /* panning delay */
+ 0xB4FF, 0xA490, 0x9590, 0x8474, 0x333A, 0x39B5, 0x7204,
+ 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
+ 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
+ 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
+},
};
-static unsigned short ReverbCommand[56] =
-{
- 0x43,0xA20,0x45,0xA20,0x7F,0xA22,0x47,0xA20,
- 0x54,0xA22,0x56,0xA22,0x4F,0xA20,0x57,0xA20,
- 0x5F,0xA20,0x47,0xA22,0x4F,0xA22,0x57,0xA22,
- 0x5D,0xA22,0x5F,0xA22,0x61,0xA20,0x63,0xA20,
- 0x49,0xA20,0x4B,0xA20,0x51,0xA20,0x53,0xA20,
- 0x59,0xA20,0x5B,0xA20,0x41,0xA22,0x43,0xA22,
- 0x49,0xA22,0x4B,0xA22,0x51,0xA22,0x53,0xA22
+static struct ReverbCmdPair {
+ unsigned short cmd, port;
+} reverb_cmds[28] = {
+ {AWE_INIT1(0x03)}, {AWE_INIT1(0x05)}, {AWE_INIT4(0x1F)}, {AWE_INIT1(0x07)},
+ {AWE_INIT2(0x14)}, {AWE_INIT2(0x16)}, {AWE_INIT1(0x0F)}, {AWE_INIT1(0x17)},
+ {AWE_INIT1(0x1F)}, {AWE_INIT2(0x07)}, {AWE_INIT2(0x0F)}, {AWE_INIT2(0x17)},
+ {AWE_INIT2(0x1D)}, {AWE_INIT2(0x1F)}, {AWE_INIT3(0x01)}, {AWE_INIT3(0x03)},
+ {AWE_INIT1(0x09)}, {AWE_INIT1(0x0B)}, {AWE_INIT1(0x11)}, {AWE_INIT1(0x13)},
+ {AWE_INIT1(0x19)}, {AWE_INIT1(0x1B)}, {AWE_INIT2(0x01)}, {AWE_INIT2(0x03)},
+ {AWE_INIT2(0x09)}, {AWE_INIT2(0x0B)}, {AWE_INIT2(0x11)}, {AWE_INIT2(0x13)},
};
-static void awe_set_chorus_mode(int effect)
-{
- int k;
- DECL_INTR_FLAGS(flags);
-
- DISABLE_INTR(flags);
- for (k = 0; k < 3; k++)
- awe_poke(ChorusCommand[k*2],
- ChorusCommand[k*2+1],
- ChorusEffects[k+effect*3]);
- for (k = 0; k < 4; k++)
- awe_poke_dw(ChorusCommand[6+k*2],
- ChorusCommand[6+k*2+1],
- ChorusEffects2[k+effect*4]);
- RESTORE_INTR(flags);
-}
static void awe_set_reverb_mode(int effect)
{
- int k;
- DECL_INTR_FLAGS(flags);
-
- DISABLE_INTR(flags);
- for (k = 0; k < 28; k++)
- awe_poke(ReverbCommand[k*2],
- ReverbCommand[k*2+1],
- ReverbEffects[k+effect*28]);
- RESTORE_INTR(flags);
+ int i;
+ for (i = 0; i < 28; i++)
+ awe_poke(reverb_cmds[i].cmd, reverb_cmds[i].port,
+ reverb_parm[effect][i]);
}
#endif /* CONFIG_AWE32_SYNTH */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov