Re: [AD] Allegro's mixer

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


New update. :)

The mixer now does full signed 24-bit mixing in a signed 32-bit buffer. This should mean there's a theoretical max of 255 samples without risk of wrapping (or 127 stereo samples with mono output). Also, the interpolation mixer interpolates in full 24-bits, though it dropped from an 8-bit interpolation level to 7-bit (maybe this can be fixed?). I would also be curious to see if the hq1 mixer out performs the low quality stereo mixer now. It's a definate possibility, IMHO. It definately has a better performance-to-quality ratio. Any performance loss (if any) is more than made up with the added quality and preciseness.

The default set_volume_per_voice has been set to 1, so 1 panned sample will never be clamped and distort. It should be easy enough to set it to be -1 again if you wish (just change the default value of the global), but this way closer emulates the DX mixer that Allegro can, and most often does, use. I would also recommend discouraging future use of set_volume_per_voice without good reason. There is absolutely no risk of overflow with Allegro's maximum of 64 digital voices, even with an over-sampled volume level (via set_volume_per_voice(0)) and 64 simultanious stereo samples on a mono buffer. Any resulting distortion can be controlled with set_volume, which is a lot easier for both using in the program, and exposing for the end user should you want to (exposing set_volume_per_voice to the end user has always been discouraged anyway).

This time I attached a .diff file, to be applied to the original mixer.c from the 4.1.13 source tree (from within the src subdir).
--- mixer.c.orig	2004-03-21 03:08:55.000000000 +0000
+++ mixer.c	2004-03-21 03:00:10.000000000 +0000
@@ -35,8 +35,10 @@
 {
    int playing;               /* are we active? */
    int stereo;                /* mono or stereo input data? */
-   unsigned char *data8;      /* data for 8 bit samples */
-   unsigned short *data16;    /* data for 16 bit samples */
+   union {
+      unsigned char *u8;      /* data for 8 bit samples */
+      unsigned short *u16;    /* data for 16 bit samples */
+   } data;
    long pos;                  /* fixed point position in sample */
    long diff;                 /* fixed point speed of play */
    long len;                  /* fixed point sample length */
@@ -44,10 +46,12 @@
    long loop_end;             /* fixed point loop end position */
    int lvol;                  /* left channel volume */
    int rvol;                  /* right channel volume */
+   AL_METHOD(void, mix_samples, (struct MIXER_VOICE *, PHYS_VOICE *, signed int *, int));
 } MIXER_VOICE;
 
 
 #define MIX_VOLUME_LEVELS     32
+
 #define MIX_FIX_SHIFT         8
 #define MIX_FIX_SCALE         (1<<MIX_FIX_SHIFT)
 
@@ -59,32 +63,12 @@
 static MIXER_VOICE mixer_voice[MIXER_MAX_SFX];
 
 /* temporary sample mixing buffer */
-static unsigned short *mix_buffer = NULL; 
+static signed int *mix_buffer = NULL; 
 
 /* lookup table for converting sample volumes */
-typedef signed short MIXER_VOL_TABLE[256];
+typedef signed int MIXER_VOL_TABLE[256];
 static MIXER_VOL_TABLE *mix_vol_table = NULL;
 
-/* lookup table for amplifying and clipping samples */
-static unsigned short *mix_clip_table = NULL;
-
-#define MIX_RES_16            14
-#define MIX_RES_8             10
-
-/* alternative table system for high-quality sample mixing */
-#define BITS_PAN              7 
-#define BITS_VOL              7 
-#define BITS_MIXER_CORE       32
-#define BITS_SAMPLES          16
-
-typedef unsigned short VOLUME_T;
-
-#define BITS_TOT (BITS_PAN+BITS_VOL) 
-#define ENTRIES_VOL_TABLE (1<<BITS_TOT)
-#define SIZE_VOLUME_TABLE (sizeof(VOLUME_T)*ENTRIES_VOL_TABLE)
-
-static VOLUME_T *volume_table = NULL;
-
 /* flags for the mixing code */
 static int mix_voices;
 static int mix_size;
@@ -93,7 +77,7 @@
 static int mix_16bit;
 
 /* shift factor for volume per voice */
-static int voice_volume_scale = -1;
+static int voice_volume_scale = 1;
 
 static void mixer_lock_mem(void);
 
@@ -114,41 +98,36 @@
  *  - pass 1 if you want to pan a full-volume sample to one side without
  *    distortion,
  *  - each time the scale parameter increases by 1, the volume halves.
- *
- *  This must be called _before_ install_sound().
  */
+static void update_mixer_volume(MIXER_VOICE *mv, PHYS_VOICE *pv);
 void set_volume_per_voice(int scale)
 {
-   voice_volume_scale = scale;
-}
-
-
-/* create_volume_table:
- *  Builds a volume table for the high quality 16 bit mixing mode.
- */
-static int create_volume_table(int vol_scale)
-{
-   double step;
-   double acum = 0;
-   int i;
-
-   if (!volume_table) {
-      volume_table = (VOLUME_T *)malloc(SIZE_VOLUME_TABLE);
-      if (!volume_table)
-	 return 1;
-      LOCK_DATA(volume_table, SIZE_VOLUME_TABLE);
-   }
-
-   step = (double)(32768 >> vol_scale) / ENTRIES_VOL_TABLE;
+	int i;
 
-   for (i=0; i<ENTRIES_VOL_TABLE; i++, acum+=step)
-      volume_table[i] = acum;
-
-   return 0;
+	if(scale < 0)
+	{
+		/* Work out the # of voices and the needed scale */
+		scale = 1;
+		for(i = 1;i < mix_voices;i <<= 1)
+			scale++;
+
+		/* Backwards compatiblity with 3.12 */
+		if(scale < 2)
+			scale = 2;
+	}
+
+	voice_volume_scale = scale;
+
+	/* Scale 0 could overflow the lq volume table */
+	if((!_sound_hq) && (scale < 1))
+		voice_volume_scale = 1;
+
+	/* Update the mixer voices' volumes */
+	for(i = 0;i < MIXER_MAX_SFX;++i)
+		update_mixer_volume(mixer_voice+i, _phys_voice+i);
 }
 
 
-
 /* _mixer_init:
  *  Initialises the sample mixing code, returning 0 on success. You should
  *  pass it the number of samples you want it to mix each time the refill
@@ -162,28 +141,10 @@
 int _mixer_init(int bufsize, int freq, int stereo, int is16bit, int *voices)
 {
    int i, j;
-   int clip_size;
-   int clip_scale;
-   int clip_max;
-   int mix_vol_scale;
-
-   mix_voices = 1;
-   mix_vol_scale = -1;
-
-   while ((mix_voices < MIXER_MAX_SFX) && (mix_voices < *voices)) {
-      mix_voices <<= 1;
-      mix_vol_scale++;
-   }
-
-   if (voice_volume_scale >= 0)
-      mix_vol_scale = voice_volume_scale;
-   else {
-      /* backward compatibility with 3.12 version */
-      if (mix_vol_scale < 2)
-         mix_vol_scale = 2;
-   }
 
-   *voices = mix_voices;
+   mix_voices = *voices;
+   if(mix_voices > MIXER_MAX_SFX)
+      *voices = mix_voices = MIXER_MAX_SFX;
 
    mix_size = bufsize;
    mix_freq = freq;
@@ -192,75 +153,37 @@
 
    for (i=0; i<MIXER_MAX_SFX; i++) {
       mixer_voice[i].playing = FALSE;
-      mixer_voice[i].data8 = NULL;
-      mixer_voice[i].data16 = NULL;
+      mixer_voice[i].data.u8 = NULL;
+      mixer_voice[i].data.u16 = NULL;
    }
 
    /* temporary buffer for sample mixing */
-   mix_buffer = malloc(mix_size*sizeof(short));
+   mix_buffer = malloc(mix_size * sizeof(*mix_buffer));
    if (!mix_buffer)
       return -1;
 
-   LOCK_DATA(mix_buffer, mix_size*sizeof(short));
+   LOCK_DATA(mix_buffer, mix_size * sizeof(*mix_buffer));
 
-   /* volume table for mixing samples into the temporary buffer */
-   mix_vol_table = malloc(sizeof(MIXER_VOL_TABLE) * MIX_VOLUME_LEVELS);
-   if (!mix_vol_table) {
-      free(mix_buffer);
-      mix_buffer = NULL;
-      return -1;
-   }
-
-   LOCK_DATA(mix_vol_table, sizeof(MIXER_VOL_TABLE) * MIX_VOLUME_LEVELS);
-
-   for (j=0; j<MIX_VOLUME_LEVELS; j++)
-      for (i=0; i<256; i++)
-         mix_vol_table[j][i] = ((i-128) * j * 128 / MIX_VOLUME_LEVELS) >> mix_vol_scale;
-
-   if ((_sound_hq) && (mix_stereo) && (mix_16bit)) {
-      /* make high quality table if requested and output is 16 bit stereo */
-      if (create_volume_table(mix_vol_scale) != 0)
-	 return -1;
-   }
-   else
+   /* 16 bit output isn't required for the high quality mixers */
+   if ((!_sound_hq) || (!mix_stereo)) {
+	  /* no high quality mixer available */
       _sound_hq = 0;
 
-   /* lookup table for amplifying and clipping sample buffers */
-   if (mix_16bit) {
-      clip_size = 1 << MIX_RES_16;
-      clip_scale = 18 - MIX_RES_16;
-      clip_max = 0xFFFF;
-   }
-   else {
-      clip_size = 1 << MIX_RES_8;
-      clip_scale = 10 - MIX_RES_8;
-      clip_max = 0xFF;
-   }
-
-   /* We now always use a clip table, owing to the new set_volume_per_voice()
-    * functionality. It is not a big loss in performance.
-    */
-   mix_clip_table = malloc(sizeof(short) * clip_size);
-   if (!mix_clip_table) {
-      free(mix_buffer);
-      mix_buffer = NULL;
-      free(mix_vol_table);
-      mix_vol_table = NULL;
-      free(volume_table);
-      volume_table = NULL;
-      return -1;
-   }
+      /* volume table for mixing samples into the temporary buffer */
+      mix_vol_table = malloc(sizeof(MIXER_VOL_TABLE) * MIX_VOLUME_LEVELS);
+      if (!mix_vol_table) {
+         free(mix_buffer);
+         mix_buffer = NULL;
+         return -1;
+      }
 
-   LOCK_DATA(mix_clip_table, sizeof(short) * clip_size);
+      LOCK_DATA(mix_vol_table, sizeof(MIXER_VOL_TABLE) * MIX_VOLUME_LEVELS);
 
-   /* clip extremes of the sample range */
-   for (i=0; i<clip_size*3/8; i++) {
-      mix_clip_table[i] = 0;
-      mix_clip_table[clip_size-1-i] = clip_max;
+      for (j=0; j<MIX_VOLUME_LEVELS; j++)
+         for (i=0; i<256; i++)
+            mix_vol_table[j][i] = ((i-128) * 256 * j / MIX_VOLUME_LEVELS) << 8;
    }
-
-   for (i=0; i<clip_size/4; i++)
-      mix_clip_table[clip_size*3/8 + i] = i<<clip_scale;
+   /* We no longer need to use prebuilt stuff for the high quality mixers */
 
    mixer_lock_mem();
 
@@ -294,20 +217,9 @@
       free(mix_vol_table);
       mix_vol_table = NULL;
    }
-
-   if (mix_clip_table) {
-      free(mix_clip_table);
-      mix_clip_table = NULL;
-   }
-
-   if (volume_table) {
-      free(volume_table);
-      volume_table = NULL;
-   }
 }
 
 
-
 /* update_mixer_volume:
  *  Called whenever the voice volume or pan changes, to update the mixer 
  *  amplification table indexes.
@@ -317,37 +229,37 @@
    int vol, pan, lvol, rvol;
 
    if (_sound_hq) {
-      vol = pv->vol>>13;
-      pan = pv->pan>>13;
+	  /* now use full 16 bit volume ranges */
+      vol = pv->vol>>12;
+      pan = pv->pan>>12;
 
       /* no need to check for mix_stereo if we're using hq */
-      lvol = vol*(127-pan);
+      lvol = vol*(255-pan);
       rvol = vol*pan;
 
-      /* adjust for 127*127<128*128-1 */
-      lvol += lvol>>6;
-      rvol += rvol>>6;
-
-      mv->lvol = MID(0, lvol, ENTRIES_VOL_TABLE-1);
-      mv->rvol = MID(0, rvol, ENTRIES_VOL_TABLE-1);
+	  /* Multiply 2 to emulate the old behavior of voice_scale=0 being
+	   * 1 step louder than regular volume
+	   */
+      mv->lvol = (MID(0, lvol, 65535) << 1) >> voice_volume_scale;
+      mv->rvol = (MID(0, rvol, 65535) << 1) >> voice_volume_scale;
    }
    else {
       vol = pv->vol >> 12;
       pan = pv->pan >> 12;
 
       if (mix_stereo) {
-	 lvol = vol * (256-pan) * MIX_VOLUME_LEVELS / 65536;
+	 lvol = vol * (255-pan) * MIX_VOLUME_LEVELS / 65536;
 	 rvol = vol * pan * MIX_VOLUME_LEVELS / 65536;
       }
       else if (mv->stereo) {
-	 lvol = vol * (256-pan) * MIX_VOLUME_LEVELS / 131072;
+	 lvol = vol * (255-pan) * MIX_VOLUME_LEVELS / 131072;
 	 rvol = vol * pan * MIX_VOLUME_LEVELS / 131072;
       }
       else
 	 lvol = rvol = vol * MIX_VOLUME_LEVELS / 512;
 
-      mv->lvol = MID(0, lvol, MIX_VOLUME_LEVELS-1);
-      mv->rvol = MID(0, rvol, MIX_VOLUME_LEVELS-1);
+      mv->lvol = (MID(0, lvol, MIX_VOLUME_LEVELS-1) << 1) >> voice_volume_scale;
+      mv->rvol = (MID(0, rvol, MIX_VOLUME_LEVELS-1) << 1) >> voice_volume_scale;
    }
 }
 
@@ -466,9 +378,9 @@
 	    if (spl->pos < spl->loop_start) {                                \
 	       if (voice->playmode & PLAYMODE_BIDIR) {                       \
 		  spl->diff = -spl->diff;                                    \
-                  /* however far the sample has overshot, move it the same */\
-                  /* distance from the loop point, within the loop section */\
-                  spl->pos = (spl->loop_start << 1) - spl->pos;              \
+		  /* however far the sample has overshot, move it the same */\
+		  /* distance from the loop point, within the loop section */\
+		  spl->pos = (spl->loop_start << 1) - spl->pos;              \
 		  voice->playmode ^= PLAYMODE_BACKWARD;                      \
 	       }                                                             \
 	       else                                                          \
@@ -601,12 +513,12 @@
  *  Mixes from an eight bit sample into a mono buffer, until either len 
  *  samples have been mixed or until the end of the sample is reached.
  */
-static void mix_mono_8x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
+static void mix_mono_8x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len)
 {
-   signed short *vol = (short *)(mix_vol_table + spl->lvol);
+   signed int *vol = (int *)(mix_vol_table + spl->lvol);
 
    #define MIX()                                                             \
-      *(buf++) += vol[spl->data8[spl->pos>>MIX_FIX_SHIFT]];
+      *(buf++) += vol[spl->data.u8[spl->pos>>MIX_FIX_SHIFT]];
 
    MIXER();
 
@@ -621,14 +533,14 @@
  *  Mixes from an eight bit stereo sample into a mono buffer, until either 
  *  len samples have been mixed or until the end of the sample is reached.
  */
-static void mix_mono_8x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
+static void mix_mono_8x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len)
 {
-   signed short *lvol = (short *)(mix_vol_table + spl->lvol);
-   signed short *rvol = (short *)(mix_vol_table + spl->rvol);
+   signed int *lvol = (int *)(mix_vol_table + spl->lvol);
+   signed int *rvol = (int *)(mix_vol_table + spl->rvol);
 
    #define MIX()                                                             \
-      *(buf)   += lvol[spl->data8[(spl->pos>>MIX_FIX_SHIFT)*2]];             \
-      *(buf++) += rvol[spl->data8[(spl->pos>>MIX_FIX_SHIFT)*2+1]];
+      *(buf)   += lvol[spl->data.u8[(spl->pos>>MIX_FIX_SHIFT)*2]];             \
+      *(buf++) += rvol[spl->data.u8[(spl->pos>>MIX_FIX_SHIFT)*2+1]];
 
    MIXER();
 
@@ -643,12 +555,12 @@
  *  Mixes from a 16 bit sample into a mono buffer, until either len samples 
  *  have been mixed or until the end of the sample is reached.
  */
-static void mix_mono_16x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
+static void mix_mono_16x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len)
 {
-   signed short *vol = (short *)(mix_vol_table + spl->lvol);
+   signed int *vol = (int *)(mix_vol_table + spl->lvol);
 
    #define MIX()                                                             \
-      *(buf++) += vol[(spl->data16[spl->pos>>MIX_FIX_SHIFT])>>8];
+      *(buf++) += vol[(spl->data.u16[spl->pos>>MIX_FIX_SHIFT])>>8];
 
    MIXER();
 
@@ -663,14 +575,14 @@
  *  Mixes from a 16 bit stereo sample into a mono buffer, until either len 
  *  samples have been mixed or until the end of the sample is reached.
  */
-static void mix_mono_16x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
+static void mix_mono_16x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len)
 {
-   signed short *lvol = (short *)(mix_vol_table + spl->lvol);
-   signed short *rvol = (short *)(mix_vol_table + spl->rvol);
+   signed int *lvol = (int *)(mix_vol_table + spl->lvol);
+   signed int *rvol = (int *)(mix_vol_table + spl->rvol);
 
    #define MIX()                                                             \
-      *(buf)   += lvol[(spl->data16[(spl->pos>>MIX_FIX_SHIFT)*2])>>8];       \
-      *(buf++) += rvol[(spl->data16[(spl->pos>>MIX_FIX_SHIFT)*2+1])>>8];
+      *(buf)   += lvol[(spl->data.u16[(spl->pos>>MIX_FIX_SHIFT)*2])>>8];       \
+      *(buf++) += rvol[(spl->data.u16[(spl->pos>>MIX_FIX_SHIFT)*2+1])>>8];
 
    MIXER();
 
@@ -685,16 +597,16 @@
  *  Mixes from an eight bit sample into a stereo buffer, until either len 
  *  samples have been mixed or until the end of the sample is reached.
  */
-static void mix_stereo_8x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
+static void mix_stereo_8x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len)
 {
-   signed short *lvol = (short *)(mix_vol_table + spl->lvol);
-   signed short *rvol = (short *)(mix_vol_table + spl->rvol);
+   signed int *lvol = (int *)(mix_vol_table + spl->lvol);
+   signed int *rvol = (int *)(mix_vol_table + spl->rvol);
 
    len >>= 1;
 
    #define MIX()                                                             \
-      *(buf++) += lvol[spl->data8[spl->pos>>MIX_FIX_SHIFT]];                 \
-      *(buf++) += rvol[spl->data8[spl->pos>>MIX_FIX_SHIFT]];
+      *(buf++) += lvol[spl->data.u8[spl->pos>>MIX_FIX_SHIFT]];                 \
+      *(buf++) += rvol[spl->data.u8[spl->pos>>MIX_FIX_SHIFT]];
 
    MIXER();
 
@@ -709,16 +621,16 @@
  *  Mixes from an eight bit stereo sample into a stereo buffer, until either 
  *  len samples have been mixed or until the end of the sample is reached.
  */
-static void mix_stereo_8x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
+static void mix_stereo_8x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len)
 {
-   signed short *lvol = (short *)(mix_vol_table + spl->lvol);
-   signed short *rvol = (short *)(mix_vol_table + spl->rvol);
+   signed int *lvol = (int *)(mix_vol_table + spl->lvol);
+   signed int *rvol = (int *)(mix_vol_table + spl->rvol);
 
    len >>= 1;
 
    #define MIX()                                                             \
-      *(buf++) += lvol[spl->data8[(spl->pos>>MIX_FIX_SHIFT)*2]];             \
-      *(buf++) += rvol[spl->data8[(spl->pos>>MIX_FIX_SHIFT)*2+1]];
+      *(buf++) += lvol[spl->data.u8[(spl->pos>>MIX_FIX_SHIFT)*2]];             \
+      *(buf++) += rvol[spl->data.u8[(spl->pos>>MIX_FIX_SHIFT)*2+1]];
 
    MIXER();
 
@@ -733,16 +645,16 @@
  *  Mixes from a 16 bit sample into a stereo buffer, until either len samples 
  *  have been mixed or until the end of the sample is reached.
  */
-static void mix_stereo_16x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
+static void mix_stereo_16x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len)
 {
-   signed short *lvol = (short *)(mix_vol_table + spl->lvol);
-   signed short *rvol = (short *)(mix_vol_table + spl->rvol);
+   signed int *lvol = (int *)(mix_vol_table + spl->lvol);
+   signed int *rvol = (int *)(mix_vol_table + spl->rvol);
 
    len >>= 1;
 
    #define MIX()                                                             \
-      *(buf++) += lvol[(spl->data16[spl->pos>>MIX_FIX_SHIFT])>>8];           \
-      *(buf++) += rvol[(spl->data16[spl->pos>>MIX_FIX_SHIFT])>>8];
+      *(buf++) += lvol[(spl->data.u16[spl->pos>>MIX_FIX_SHIFT])>>8];           \
+      *(buf++) += rvol[(spl->data.u16[spl->pos>>MIX_FIX_SHIFT])>>8];
 
    MIXER();
 
@@ -757,16 +669,16 @@
  *  Mixes from a 16 bit stereo sample into a stereo buffer, until either len 
  *  samples have been mixed or until the end of the sample is reached.
  */
-static void mix_stereo_16x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
+static void mix_stereo_16x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len)
 {
-   signed short *lvol = (short *)(mix_vol_table + spl->lvol);
-   signed short *rvol = (short *)(mix_vol_table + spl->rvol);
+   signed int *lvol = (int *)(mix_vol_table + spl->lvol);
+   signed int *rvol = (int *)(mix_vol_table + spl->rvol);
 
    len >>= 1;
 
    #define MIX()                                                             \
-      *(buf++) += lvol[(spl->data16[(spl->pos>>MIX_FIX_SHIFT)*2])>>8];       \
-      *(buf++) += rvol[(spl->data16[(spl->pos>>MIX_FIX_SHIFT)*2+1])>>8];
+      *(buf++) += lvol[(spl->data.u16[(spl->pos>>MIX_FIX_SHIFT)*2])>>8];       \
+      *(buf++) += rvol[(spl->data.u16[(spl->pos>>MIX_FIX_SHIFT)*2+1])>>8];
 
    MIXER();
 
@@ -775,23 +687,21 @@
 
 END_OF_STATIC_FUNCTION(mix_stereo_16x2_samples);
 
-
-
 /* mix_hq1_8x1_samples:
  *  Mixes from a mono 8 bit sample into a high quality stereo buffer, 
  *  until either len samples have been mixed or until the end of the 
  *  sample is reached.
  */
-static void mix_hq1_8x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
+static void mix_hq1_8x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len)
 {
-   int lvol = volume_table[spl->lvol];
-   int rvol = volume_table[spl->rvol];
+   int lvol = spl->lvol;
+   int rvol = spl->rvol;
 
    len >>= 1;
 
    #define MIX()                                                             \
-      *(buf++) += ((spl->data8[spl->pos>>MIX_FIX_SHIFT]-0x80)*lvol)>>8;      \
-      *(buf++) += ((spl->data8[spl->pos>>MIX_FIX_SHIFT]-0x80)*rvol)>>8;
+	  *(buf++) += ((spl->data.u8[spl->pos>>MIX_FIX_SHIFT]-0x80)*lvol);	\
+	  *(buf++) += ((spl->data.u8[spl->pos>>MIX_FIX_SHIFT]-0x80)*rvol);
 
    MIXER();
 
@@ -807,16 +717,16 @@
  *  until either len samples have been mixed or until the end of the 
  *  sample is reached.
  */
-static void mix_hq1_8x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
+static void mix_hq1_8x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len)
 {
-   int lvol = volume_table[spl->lvol];
-   int rvol = volume_table[spl->rvol];
+   int lvol = spl->lvol;
+   int rvol = spl->rvol;
 
    len >>= 1;
 
    #define MIX()                                                             \
-      *(buf++) += ((spl->data8[(spl->pos>>MIX_FIX_SHIFT)*2]-0x80)*lvol)>>8;  \
-      *(buf++) += ((spl->data8[(spl->pos>>MIX_FIX_SHIFT)*2+1]-0x80)*rvol)>>8;
+	  *(buf++) += ((spl->data.u8[(spl->pos>>MIX_FIX_SHIFT)*2]-0x80)*lvol);  \
+	  *(buf++) += ((spl->data.u8[(spl->pos>>MIX_FIX_SHIFT)*2+1]-0x80)*rvol);
 
    MIXER();
 
@@ -832,16 +742,16 @@
  *  until either len samples have been mixed or until the end of the sample 
  *  is reached.
  */
-static void mix_hq1_16x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
+static void mix_hq1_16x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len)
 {
-   int lvol = volume_table[spl->lvol];
-   int rvol = volume_table[spl->rvol];
+   int lvol = spl->lvol;
+   int rvol = spl->rvol;
 
    len >>= 1;
 
    #define MIX()                                                             \
-      *(buf++) += ((spl->data16[spl->pos>>MIX_FIX_SHIFT]-0x8000)*lvol)>>16;  \
-      *(buf++) += ((spl->data16[spl->pos>>MIX_FIX_SHIFT]-0x8000)*rvol)>>16;
+	  *(buf++) += ((spl->data.u16[spl->pos>>MIX_FIX_SHIFT]-0x8000)*lvol)>>8;  \
+	  *(buf++) += ((spl->data.u16[spl->pos>>MIX_FIX_SHIFT]-0x8000)*rvol)>>8;
 
    MIXER();
 
@@ -857,16 +767,16 @@
  *  until either len samples have been mixed or until the end of the sample 
  *  is reached.
  */
-static void mix_hq1_16x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
+static void mix_hq1_16x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len)
 {
-   int lvol = volume_table[spl->lvol];
-   int rvol = volume_table[spl->rvol];
+   int lvol = spl->lvol;
+   int rvol = spl->rvol;
 
    len >>= 1;
 
    #define MIX()                                                                 \
-      *(buf++) += ((spl->data16[(spl->pos>>MIX_FIX_SHIFT)*2]-0x8000)*lvol)>>16;  \
-      *(buf++) += ((spl->data16[(spl->pos>>MIX_FIX_SHIFT)*2+1]-0x8000)*rvol)>>16;
+	  *(buf++) += ((spl->data.u16[(spl->pos>>MIX_FIX_SHIFT)*2]-0x8000)*lvol)>>8;  \
+	  *(buf++) += ((spl->data.u16[(spl->pos>>MIX_FIX_SHIFT)*2+1]-0x8000)*rvol)>>8;
 
    MIXER();
 
@@ -876,16 +786,18 @@
 END_OF_STATIC_FUNCTION(mix_hq1_16x2_samples);
 
 
+/* Helper to apply a 16-bit volume to a 24-bit sample */
+#define MULSC(a, b) ((int)((LONG_LONG)((a) << 4) * ((b) << 12) >> 32))
 
 /* mix_hq2_8x1_samples:
  *  Mixes from a mono 8 bit sample into an interpolated stereo buffer, 
  *  until either len samples have been mixed or until the end of the 
  *  sample is reached.
  */
-static void mix_hq2_8x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
+static void mix_hq2_8x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len)
 {
-   int lvol = volume_table[spl->lvol];
-   int rvol = volume_table[spl->rvol];
+   int lvol = spl->lvol;
+   int rvol = spl->rvol;
    int v, v1, v2;
 
    len >>= 1;
@@ -893,24 +805,24 @@
    #define MIX()                                                             \
       v = spl->pos>>MIX_FIX_SHIFT;                                           \
 									     \
-      v1 = spl->data8[v];                                                    \
-                                                                             \
+      v1 = spl->data.u8[v] << 16;                                            \
+                                         \
       if (spl->pos >= spl->len-MIX_FIX_SCALE) {                              \
          if ((voice->playmode & (PLAYMODE_LOOP |                             \
                                  PLAYMODE_BIDIR)) == PLAYMODE_LOOP &&        \
              spl->loop_start < spl->loop_end && spl->loop_end == spl->len)   \
-            v2 = spl->data8[spl->loop_start>>MIX_FIX_SHIFT];                 \
+            v2 = spl->data.u8[spl->loop_start>>MIX_FIX_SHIFT] << 16;         \
          else                                                                \
-            v2 = 0x80;                                                       \
+            v2 = 0x800000;                                                   \
       }                                                                      \
       else                                                                   \
-	 v2 = spl->data8[v+1];                                               \
-									     \
-      v = spl->pos & (MIX_FIX_SCALE-1);                                      \
-      v = (v1*(MIX_FIX_SCALE-v) + v2*v) / MIX_FIX_SCALE;                     \
+	 v2 = spl->data.u8[v+1] << 16;                                           \
 									     \
-      *(buf++) += ((v-0x80)*lvol)>>8;                                        \
-      *(buf++) += ((v-0x80)*rvol)>>8;
+      v = (spl->pos & (MIX_FIX_SCALE-1)) >> 1;                               \
+	  v = (((v2 - v1) * v) >> (MIX_FIX_SHIFT-1)) + v1;                       \
+										 \
+	  *(buf++) += MULSC(v-0x800000, lvol);                                   \
+	  *(buf++) += MULSC(v-0x800000, rvol);
 
    MIXER();
 
@@ -926,41 +838,41 @@
  *  until either len samples have been mixed or until the end of the 
  *  sample is reached.
  */
-static void mix_hq2_8x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
+static void mix_hq2_8x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len)
 {
-   int lvol = volume_table[spl->lvol];
-   int rvol = volume_table[spl->rvol];
+   int lvol = spl->lvol;
+   int rvol = spl->rvol;
    int v, va, v1a, v2a, vb, v1b, v2b;
 
    len >>= 1;
 
    #define MIX()                                                             \
       v = (spl->pos>>MIX_FIX_SHIFT) << 1; /* x2 for stereo */                \
-                                                                             \
-      v1a = spl->data8[v];                                                   \
-      v1b = spl->data8[v+1];                                                 \
+	\
+      v1a = spl->data.u8[v] << 16;                                           \
+      v1b = spl->data.u8[v+1] << 16;                                         \
 									     \
       if (spl->pos >= spl->len-MIX_FIX_SCALE) {                              \
          if ((voice->playmode & (PLAYMODE_LOOP |                             \
                                  PLAYMODE_BIDIR)) == PLAYMODE_LOOP &&        \
              spl->loop_start < spl->loop_end && spl->loop_end == spl->len) { \
-            v2a = spl->data8[((spl->loop_start>>MIX_FIX_SHIFT)<<1)];         \
-            v2b = spl->data8[((spl->loop_start>>MIX_FIX_SHIFT)<<1)+1];       \
+            v2a = spl->data.u8[((spl->loop_start>>MIX_FIX_SHIFT)<<1)] << 16; \
+            v2b = spl->data.u8[((spl->loop_start>>MIX_FIX_SHIFT)<<1)+1] << 16; \
          }                                                                   \
          else                                                                \
-            v2a = v2b = 0x80;                                                \
+            v2a = v2b = 0x800000;                                            \
       }                                                                      \
       else {                                                                 \
-	 v2a = spl->data8[v+2];                                              \
-	 v2b = spl->data8[v+3];                                              \
+	 v2a = spl->data.u8[v+2] << 16;                                          \
+	 v2b = spl->data.u8[v+3] << 16;                                          \
       }                                                                      \
 									     \
-      v = spl->pos & (MIX_FIX_SCALE-1);                                      \
-      va = (v1a*(MIX_FIX_SCALE-v) + v2a*v) / MIX_FIX_SCALE;                  \
-      vb = (v1b*(MIX_FIX_SCALE-v) + v2b*v) / MIX_FIX_SCALE;                  \
+      v = (spl->pos & (MIX_FIX_SCALE-1)) >> 1;                               \
+      va = (((v2a - v1a) * v) >> (MIX_FIX_SHIFT-1)) + v1a;                       \
+      vb = (((v2b - v1b) * v) >> (MIX_FIX_SHIFT-1)) + v1b;                       \
 									     \
-      *(buf++) += ((va-0x80)*lvol)>>8;                                       \
-      *(buf++) += ((vb-0x80)*rvol)>>8;
+	  *(buf++) += MULSC(va-0x800000, lvol);                                  \
+	  *(buf++) += MULSC(vb-0x800000, rvol);
 
    MIXER();
 
@@ -976,10 +888,10 @@
  *  until either len samples have been mixed or until the end of the sample 
  *  is reached.
  */
-static void mix_hq2_16x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
+static void mix_hq2_16x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len)
 {
-   int lvol = volume_table[spl->lvol];
-   int rvol = volume_table[spl->rvol];
+   int lvol = spl->lvol;
+   int rvol = spl->rvol;
    int v, v1, v2;
 
    len >>= 1;
@@ -987,24 +899,24 @@
    #define MIX()                                                             \
       v = spl->pos>>MIX_FIX_SHIFT;                                           \
                                                                              \
-      v1 = spl->data16[v];                                                   \
+      v1 = (int)spl->data.u16[v] << 8;                                       \
 									     \
       if (spl->pos >= spl->len-MIX_FIX_SCALE) {                              \
          if ((voice->playmode & (PLAYMODE_LOOP |                             \
                                  PLAYMODE_BIDIR)) == PLAYMODE_LOOP &&        \
              spl->loop_start < spl->loop_end && spl->loop_end == spl->len)   \
-            v2 = spl->data16[spl->loop_start>>MIX_FIX_SHIFT];                \
+            v2 = (int)spl->data.u16[spl->loop_start>>MIX_FIX_SHIFT] << 8;    \
          else                                                                \
-            v2 = 0x8000;                                                     \
+            v2 = 0x800000;                                                   \
       }                                                                      \
       else                                                                   \
-	 v2 = spl->data16[v+1];                                              \
+	 v2 = (int)spl->data.u16[v+1] << 8;                                      \
 									     \
-      v = spl->pos & (MIX_FIX_SCALE-1);                                      \
-      v = (v1*(MIX_FIX_SCALE-v) + v2*v) / MIX_FIX_SCALE;                     \
+      v = (spl->pos & (MIX_FIX_SCALE-1)) >> 1;                               \
+	  v = (((v2 - v1) * v) >> (MIX_FIX_SHIFT-1)) + v1;                       \
 									     \
-      *(buf++) += ((v-0x8000)*lvol)>>16;                                     \
-      *(buf++) += ((v-0x8000)*rvol)>>16;
+	  *(buf++) += MULSC(v-0x800000, lvol);                                   \
+	  *(buf++) += MULSC(v-0x800000, rvol);
 
    MIXER();
 
@@ -1020,10 +932,10 @@
  *  until either len samples have been mixed or until the end of the sample 
  *  is reached.
  */
-static void mix_hq2_16x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)
+static void mix_hq2_16x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len)
 {
-   int lvol = volume_table[spl->lvol];
-   int rvol = volume_table[spl->rvol];
+   int lvol = spl->lvol;
+   int rvol = spl->rvol;
    int v, va, v1a, v2a, vb, v1b, v2b;
 
    len >>= 1;
@@ -1031,30 +943,30 @@
    #define MIX()                                                             \
       v = (spl->pos>>MIX_FIX_SHIFT) << 1; /* x2 for stereo */                \
                                                                              \
-      v1a = spl->data16[v];                                                  \
-      v1b = spl->data16[v+1];                                                \
+      v1a = (int)spl->data.u16[v] << 8;                                      \
+      v1b = (int)spl->data.u16[v+1] << 8;                                    \
 									     \
       if (spl->pos >= spl->len-MIX_FIX_SCALE) {                              \
          if ((voice->playmode & (PLAYMODE_LOOP |                             \
                                  PLAYMODE_BIDIR)) == PLAYMODE_LOOP &&        \
              spl->loop_start < spl->loop_end && spl->loop_end == spl->len) { \
-            v2a = spl->data16[((spl->loop_start>>MIX_FIX_SHIFT)<<1)];        \
-            v2b = spl->data16[((spl->loop_start>>MIX_FIX_SHIFT)<<1)+1];      \
+            v2a = (int)spl->data.u16[((spl->loop_start>>MIX_FIX_SHIFT)<<1)] << 8; \
+            v2b = (int)spl->data.u16[((spl->loop_start>>MIX_FIX_SHIFT)<<1)+1] << 8; \
          }                                                                   \
          else                                                                \
-            v2a = v2b = 0x8000;                                              \
+            v2a = v2b = 0x800000;                                            \
       }                                                                      \
       else {                                                                 \
-	 v2a = spl->data16[v+2];                                             \
-	 v2b = spl->data16[v+3];                                             \
+	 v2a = (int)spl->data.u16[v+2] << 8;                                     \
+	 v2b = (int)spl->data.u16[v+3] << 8;                                     \
       }                                                                      \
 									     \
-      v = spl->pos & (MIX_FIX_SCALE-1);                                      \
-      va = (v1a*(MIX_FIX_SCALE-v) + v2a*v) / MIX_FIX_SCALE;                  \
-      vb = (v1b*(MIX_FIX_SCALE-v) + v2b*v) / MIX_FIX_SCALE;                  \
+      v = (spl->pos & (MIX_FIX_SCALE-1)) >> 1;                               \
+      va = (((v2a - v1a) * v) >> (MIX_FIX_SHIFT-1)) + v1a;                       \
+      vb = (((v2b - v1b) * v) >> (MIX_FIX_SHIFT-1)) + v1b;                       \
 									     \
-      *(buf++) += ((va-0x8000)*lvol)>>16;                                    \
-      *(buf++) += ((vb-0x8000)*rvol)>>16;
+	  *(buf++) += MULSC(va-0x800000, lvol);                                    \
+	  *(buf++) += MULSC(vb-0x800000, rvol);
 
    MIXER();
 
@@ -1064,6 +976,24 @@
 END_OF_STATIC_FUNCTION(mix_hq2_16x2_samples);
 
 
+/* clamp_val:
+ *  Clamps the given sample volume to a signed 24-bit value
+ */
+static INLINE int clamp_val(int s)
+{
+	/* Clamp to min */
+	s -= -(1<<23);
+	s &= (~s) >> 31;
+	s += -(1<<23);
+
+	/* Clamp to max */
+	s -= (1<<23)-1;
+	s &= s >> 31;
+	s += (1<<23)-1;
+
+	return s;
+}
+
 
 /* _mix_some_samples:
  *  Mixes samples into a buffer in conventional memory (the buf parameter
@@ -1074,116 +1004,22 @@
  */
 void _mix_some_samples(unsigned long buf, unsigned short seg, int issigned)
 {
+   signed int *p = mix_buffer;
    int i;
-   unsigned short *p = mix_buffer;
-   unsigned long *l = (unsigned long *)p;
 
    /* clear mixing buffer */
-   for (i=0; i<mix_size/2; i++)
-      *(l++) = 0x80008000;
+   memset(p, 0, mix_size * sizeof(*p));
 
 #ifdef ALLEGRO_MULTITHREADED
    system_driver->lock_mutex(mixer_mutex);
 #endif
 
-   if (_sound_hq >= 2) {
-      /* top quality interpolated 16 bit mixing */
-      for (i=0; i<mix_voices; i++) {
-	 if (mixer_voice[i].playing) {
-            if ((_phys_voice[i].vol > 0) || (_phys_voice[i].dvol > 0)) {
-	       if (mixer_voice[i].stereo) {
-	          /* stereo input -> interpolated output */
-	          if (mixer_voice[i].data8)
-		     mix_hq2_8x2_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
-	          else
-		     mix_hq2_16x2_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
-	       }
-	       else {
-	          /* mono input -> interpolated output */
-	          if (mixer_voice[i].data8)
-		     mix_hq2_8x1_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
-	          else
-		     mix_hq2_16x1_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
-	       }
-            }
-            else
-               mix_silent_samples(mixer_voice+i, _phys_voice+i, mix_size>>1);
-	 }
-      }
-   }
-   else if (_sound_hq) {
-      /* high quality 16 bit mixing */
-      for (i=0; i<mix_voices; i++) {
-	 if (mixer_voice[i].playing) {
-	    if ((_phys_voice[i].vol > 0) || (_phys_voice[i].dvol > 0)) {
-	       if (mixer_voice[i].stereo) {
-	          /* stereo input -> high quality output */
-	          if (mixer_voice[i].data8)
-		     mix_hq1_8x2_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
-	          else
-		     mix_hq1_16x2_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
-	       }
-	       else {
-	          /* mono input -> high quality output */
-	          if (mixer_voice[i].data8)
-		     mix_hq1_8x1_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
-	          else
-		     mix_hq1_16x1_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
-	       }
-            }
-            else
-               mix_silent_samples(mixer_voice+i, _phys_voice+i, mix_size>>1);
-	 }
-      }
-   }
-   else if (mix_stereo) { 
-      /* lower quality (faster) stereo mixing */
-      for (i=0; i<mix_voices; i++) {
-	 if (mixer_voice[i].playing) {
-	    if ((_phys_voice[i].vol > 0) || (_phys_voice[i].dvol > 0)) {
-	       if (mixer_voice[i].stereo) {
-	          /* stereo input -> stereo output */
-	          if (mixer_voice[i].data8)
-		     mix_stereo_8x2_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
-	          else
-		     mix_stereo_16x2_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
-	       }
-	       else {
-	          /* mono input -> stereo output */
-	          if (mixer_voice[i].data8)
-		     mix_stereo_8x1_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
-	          else
-		     mix_stereo_16x1_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
-	       }
-            }
-            else
-               mix_silent_samples(mixer_voice+i, _phys_voice+i, mix_size>>1);
-	 }
-      }
-   }
-   else {
-      /* lower quality (fast) mono mixing */
-      for (i=0; i<mix_voices; i++) {
-	 if (mixer_voice[i].playing) {
-	    if ((_phys_voice[i].vol > 0) || (_phys_voice[i].dvol > 0)) {
-	       if (mixer_voice[i].stereo) {
-	          /* stereo input -> mono output */
-	          if (mixer_voice[i].data8)
-		     mix_mono_8x2_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
-	          else
-		     mix_mono_16x2_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
-	       }
-	       else {
-	          /* mono input -> mono output */
-	          if (mixer_voice[i].data8)
-		     mix_mono_8x1_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
-	          else
-		     mix_mono_16x1_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
-	       }
-            }
-            else
-               mix_silent_samples(mixer_voice+i, _phys_voice+i, mix_size);
-	 }
+   for (i=0; i<mix_voices; i++) {
+      if (mixer_voice[i].playing) {
+         if ((_phys_voice[i].vol > 0) || (_phys_voice[i].dvol > 0))
+            mixer_voice[i].mix_samples(mixer_voice+i, _phys_voice+i, p, mix_size);
+         else
+            mix_silent_samples(mixer_voice+i, _phys_voice+i, mix_size>>1);
       }
    }
 
@@ -1193,18 +1029,18 @@
 
    _farsetsel(seg);
 
-   /* transfer to conventional memory buffer using a clip table */
+   /* transfer to the sound driver's buffer */
    if (mix_16bit) {
       if (issigned) {
 	 for (i=0; i<mix_size; i++) {
-	    _farnspokew(buf, mix_clip_table[*p >> (16-MIX_RES_16)] ^ 0x8000);
+	    _farnspokew(buf, clamp_val(*p) >> 8);
 	    buf += sizeof(short);
 	    p++;
          }
       }
       else {
 	 for (i=0; i<mix_size; i++) {
-	    _farnspokew(buf, mix_clip_table[*p >> (16-MIX_RES_16)]);
+	        _farnspokew(buf, (signed short)(clamp_val(*p) >> 8) ^ 0x8000);
             buf += sizeof(short);
             p++;
          }
@@ -1212,7 +1048,7 @@
    }
    else {
       for (i=0; i<mix_size; i++) {
-	 _farnspokeb(buf, mix_clip_table[*p >> (16-MIX_RES_8)]);
+	     _farnspokeb(buf, (signed char)(clamp_val(*p) >> 16) ^ 0x80);
          buf++;
          p++;
       }
@@ -1235,13 +1071,78 @@
    mixer_voice[voice].loop_start = sample->loop_start << MIX_FIX_SHIFT;
    mixer_voice[voice].loop_end = sample->loop_end << MIX_FIX_SHIFT;
 
-   if (sample->bits == 8) {
-      mixer_voice[voice].data8 = sample->data;
-      mixer_voice[voice].data16 = NULL;
+   if (sample->bits == 8)
+      mixer_voice[voice].data.u8 = sample->data;
+   else
+      mixer_voice[voice].data.u16 = sample->data;
+
+   /* top quality interpolated 16 bit mixing */
+   if (_sound_hq >= 2) {
+       /* stereo input -> interpolated output */
+       if (sample->stereo) {
+          if (sample->bits == 8)
+		     mixer_voice[voice].mix_samples = mix_hq2_8x2_samples;
+          else
+		     mixer_voice[voice].mix_samples = mix_hq2_16x2_samples;
+       }
+       /* mono input -> interpolated output */
+       else {
+          if (sample->bits == 8)
+		     mixer_voice[voice].mix_samples = mix_hq2_8x1_samples;
+          else
+		     mixer_voice[voice].mix_samples = mix_hq2_16x1_samples;
+       }
+   }
+   /* high quality 16 bit mixing */
+   else if (_sound_hq) {
+       /* stereo input -> high quality output */
+       if (sample->stereo) {
+          if (sample->bits == 8)
+		     mixer_voice[voice].mix_samples = mix_hq1_8x2_samples;
+          else
+		     mixer_voice[voice].mix_samples = mix_hq1_16x2_samples;
+       }
+       /* mono input -> high quality output */
+       else {
+          if (sample->bits == 8)
+		     mixer_voice[voice].mix_samples = mix_hq1_8x1_samples;
+          else
+		     mixer_voice[voice].mix_samples = mix_hq1_16x1_samples;
+       }
+   }
+   /* lower quality (faster) stereo mixing */
+   else if (mix_stereo) { 
+       /* stereo input -> stereo output */
+       if (sample->stereo) {
+          if (sample->bits == 8)
+		     mixer_voice[voice].mix_samples = mix_stereo_8x2_samples;
+          else
+		     mixer_voice[voice].mix_samples = mix_stereo_16x2_samples;
+       }
+       /* mono input -> stereo output */
+       else {
+          if (sample->bits == 8)
+		     mixer_voice[voice].mix_samples = mix_stereo_8x1_samples;
+          else
+		     mixer_voice[voice].mix_samples = mix_stereo_16x1_samples;
+       }
    }
+   /* lower quality (fast) mono mixing */
    else {
-      mixer_voice[voice].data8 = NULL;
-      mixer_voice[voice].data16 = sample->data;
+       /* stereo input -> mono output */
+       if (sample->stereo) {
+          if (sample->bits == 8)
+		     mixer_voice[voice].mix_samples = mix_mono_8x2_samples;
+          else
+		     mixer_voice[voice].mix_samples = mix_mono_16x2_samples;
+       }
+       /* mono input -> mono output */
+       else {
+          if (sample->bits == 8)
+		     mixer_voice[voice].mix_samples = mix_mono_8x1_samples;
+          else
+		     mixer_voice[voice].mix_samples = mix_mono_16x1_samples;
+       }
    }
 
    update_mixer_volume(mixer_voice+voice, _phys_voice+voice);
@@ -1262,8 +1163,8 @@
 #endif
 
    mixer_voice[voice].playing = FALSE;
-   mixer_voice[voice].data8 = NULL;
-   mixer_voice[voice].data16 = NULL;
+   mixer_voice[voice].data.u8 = NULL;
+   mixer_voice[voice].data.u16 = NULL;
 
 #ifdef ALLEGRO_MULTITHREADED
    system_driver->unlock_mutex(mixer_mutex);
@@ -1544,7 +1445,6 @@
    LOCK_VARIABLE(mixer_voice);
    LOCK_VARIABLE(mix_buffer);
    LOCK_VARIABLE(mix_vol_table);
-   LOCK_VARIABLE(mix_clip_table);
    LOCK_VARIABLE(mix_voices);
    LOCK_VARIABLE(mix_size);
    LOCK_VARIABLE(mix_freq);


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/