effect_position.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 21 Aug 2004 12:27:02 +0000
changeset 245 63b3650714de
parent 241 503416fca921
child 250 cf822f8dc1bf
permissions -rw-r--r--
Here are patches for SDL12 and SDL_mixer for 4 or 6 channel
surround sound on Linux using the Alsa driver. To use them, naturally
you need a sound card that will do 4 or 6 channels and probably also a
recent version of the Alsa drivers and library. Since the only SDL
output driver that knows about surround sound is the Alsa driver,
you���ll want to choose it, using:

export SDL_AUDIODRIVER=alsa

There are no syntactic changes to the programming API. No new
library calls, no differences in arguments.

There are two semantic changes:

(1) For library calls with number of channels as an argument, formerly
you could use only 1 or 2 for the number of channels. Now you
can also use 4 or 6.

(2) The two "left" and "right" arguments to Mix_SetPanning, for the
case of 4 or 6 channels, no longer simply control the volumes of
the left and right channels. Now the "left" argument is converted
to an angle and Mix_SetPosition is called, and the "right" argu-
ment is ignored.

With two exceptions, so far as I know, the modified SDL12 and
SDL_mixer work the same way as the original versions, when opened for
1 or 2 channel output. The two exceptions are bugs which I fixed.
Well, the first, anyway, is a bug for sure. When rate conversions up
or down by a factor of two are applied (in src/audio/SDL_audiocvt.c),
streams with different numbers of channels (that is, mono and stereo)
are treated the same way: either each sample is copied or every other
sample is omitted. This is ok for mono, but for stereo, it is frames
that should be copied or omitted, where by "frame" I mean a portion of
the stream containing one sample for each channel. (In the SDL source,
confusingly, sometimes frames are called "samples".) So for these
rate conversions, stereo streams have to be treated differently, and
they are, in my modified version.

The other problem that might be characterized as a bug arises
when SDL_mixer is passed a multichannel chunk which does not have an
integral number of frames. Due to the way the effect_position code
loops over frames, when the chunk ends with a partial frame, memory
outside the chunk buffer will be accessed. In the case of stereo,
it���s possible that because malloc may give more memory than requested,
this potential problem never actually causes a segment fault. I don���t
know. For 6 channel chunks, I do know, and it does cause segment
faults.


If SDL_mixer is passed defective chunks and this causes a segment
fault, arguably, that���s not a bug in SDL_mixer. Still, whether or not
it counts as a bug, it���s easy to protect against, so why not? I added
code in mixer.c to discard any partial frame at the end of a chunk.

Then what about when SDL or SDL_mixer is opened for 4 or 6 chan-
nel output? What happens with the parts of the current library
designed for stereo? I don���t know whether I���ve covered all the bases,
but I���ve tried:

(1) For playing 2 channel waves, or other cases where SDL knows it has
to match up a 2 channel source with a 4 or 6 channel output, I���ve
added code in SDL_audiocvt.c to make the necessary conversions.

(2) For playing midis using timidity, I���ve converted timidity to do 4
or 6 channel output, upon request.

(3) For playing mods using mikmod, I put ad hoc code in music.c to
convert the stereo output that mikmod produces to 4 or 6 chan-
nels. Obviously it would be better to change the mikmod code to
mix down into 4 or 6 channels, but I have a hard time following
the code in mikmod, so I didn���t do that.

(4) For playing mp3s, I put ad hoc code in smpeg to copy channels in
the case when 4 or 6 channel output is needed.

(5) There seems to be no problem with .ogg files - stereo .oggs can be
up converted as .wavs are.

(6) The effect_position code in SDL_mixer is now generalized to in-
clude the cases of 4 and 6 channel streams.

I���ve done a very limited amount of compatibility testing for some
of the games using SDL I happen to have. For details, see the file
TESTS.

I���ve put into a separate archive, Surround-SDL-testfiles.tgz, a
couple of 6 channel wave files for testing and a 6 channel ogg file.
If you have the right hardware and version of Alsa, you should be able
to play the wave files with the Alsa utility aplay (and hear all
channels, except maybe lfe, for chan-id.wav, since it���s rather faint).
Don���t expect aplay to give good sound, though. There���s something
wrong with the current version of aplay.

The canyon.ogg file is to test loading of 6 channel oggs. After
patching and compiling, you can play it with playmus. (My version of
ogg123 will not play it, and I had to patch mplayer to get it to play
6 channel oggs.)

Greg Lee <greg@ling.lll.hawaii.edu>
Thus, July 1, 2004
     1 /*
     2     SDL_mixer:  An audio mixer library based on the SDL library
     3     Copyright (C) 1997-2004 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Library General Public
     7     License as published by the Free Software Foundation; either
     8     version 2 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Library General Public License for more details.
    14 
    15     You should have received a copy of the GNU Library General Public
    16     License along with this library; if not, write to the Free
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    18 
    19     This file by Ryan C. Gordon (icculus@linuxgames.com)
    20 
    21     These are some internally supported special effects that use SDL_mixer's
    22     effect callback API. They are meant for speed over quality.  :)
    23 */
    24 
    25 /* $Id$ */
    26 
    27 #include <stdio.h>
    28 #include <stdlib.h>
    29 #include <string.h>
    30 
    31 #include "SDL.h"
    32 #include "SDL_mixer.h"
    33 #include "SDL_endian.h"
    34 
    35 #define __MIX_INTERNAL_EFFECT__
    36 #include "effects_internal.h"
    37 
    38 /* profile code:
    39     #include <sys/time.h>
    40     #include <unistd.h>
    41     struct timeval tv1;
    42     struct timeval tv2;
    43     
    44     gettimeofday(&tv1, NULL);
    45 
    46         ... do your thing here ...
    47 
    48     gettimeofday(&tv2, NULL);
    49     printf("%ld\n", tv2.tv_usec - tv1.tv_usec);
    50 */
    51 
    52 
    53 /*
    54  * Positional effects...panning, distance attenuation, etc.
    55  */
    56 
    57 typedef struct _Eff_positionargs
    58 {
    59     volatile float left_f;
    60     volatile float right_f;
    61     volatile Uint8 left_u8;
    62     volatile Uint8 right_u8;
    63     volatile float left_rear_f;
    64     volatile float right_rear_f;
    65     volatile float center_f;
    66     volatile float lfe_f;
    67     volatile Uint8 left_rear_u8;
    68     volatile Uint8 right_rear_u8;
    69     volatile Uint8 center_u8;
    70     volatile Uint8 lfe_u8;
    71     volatile float distance_f;
    72     volatile Uint8 distance_u8;
    73     volatile Sint16 room_angle;
    74     volatile int in_use;
    75     volatile int channels;
    76 } position_args;
    77 
    78 static position_args **pos_args_array = NULL;
    79 static position_args *pos_args_global = NULL;
    80 static int position_channels = 0;
    81 
    82 /* This just frees up the callback-specific data. */
    83 static void _Eff_PositionDone(int channel, void *udata)
    84 {
    85     if (channel < 0) {
    86         if (pos_args_global != NULL) {
    87             free(pos_args_global);
    88             pos_args_global = NULL;
    89         }
    90     }
    91 
    92     else if (pos_args_array[channel] != NULL) {
    93         free(pos_args_array[channel]);
    94         pos_args_array[channel] = NULL;
    95     }
    96 }
    97 
    98 
    99 static void _Eff_position_u8(int chan, void *stream, int len, void *udata)
   100 {
   101     volatile position_args *args = (volatile position_args *) udata;
   102     Uint8 *ptr = (Uint8 *) stream;
   103     int i;
   104 
   105         /*
   106          * if there's only a mono channnel (the only way we wouldn't have
   107          *  a len divisible by 2 here), then left_f and right_f are always
   108          *  1.0, and are therefore throwaways.
   109          */
   110     if (len % sizeof (Uint16) != 0) {
   111         *ptr = (Uint8) (((float) *ptr) * args->distance_f);
   112         ptr++;
   113         len--;
   114     }
   115 
   116     if (args->room_angle == 0)
   117     for (i = 0; i < len; i += sizeof (Uint8) * 2) {
   118         /* must adjust the sample so that 0 is the center */
   119         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   120             * args->right_f) * args->distance_f) + 128);
   121         ptr++;
   122         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   123             * args->left_f) * args->distance_f) + 128);
   124         ptr++;
   125     }
   126     else for (i = 0; i < len; i += sizeof (Uint8) * 2) {
   127         /* must adjust the sample so that 0 is the center */
   128         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   129             * args->left_f) * args->distance_f) + 128);
   130         ptr++;
   131         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   132             * args->right_f) * args->distance_f) + 128);
   133         ptr++;
   134     }
   135 }
   136 static void _Eff_position_u8_c4(int chan, void *stream, int len, void *udata)
   137 {
   138     volatile position_args *args = (volatile position_args *) udata;
   139     Uint8 *ptr = (Uint8 *) stream;
   140     int i;
   141 
   142         /*
   143          * if there's only a mono channnel (the only way we wouldn't have
   144          *  a len divisible by 2 here), then left_f and right_f are always
   145          *  1.0, and are therefore throwaways.
   146          */
   147     if (len % sizeof (Uint16) != 0) {
   148         *ptr = (Uint8) (((float) *ptr) * args->distance_f);
   149         ptr++;
   150         len--;
   151     }
   152 
   153     if (args->room_angle == 0)
   154     for (i = 0; i < len; i += sizeof (Uint8) * 6) {
   155         /* must adjust the sample so that 0 is the center */
   156         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   157             * args->left_f) * args->distance_f) + 128);
   158         ptr++;
   159         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   160             * args->right_f) * args->distance_f) + 128);
   161         ptr++;
   162         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   163             * args->left_rear_f) * args->distance_f) + 128);
   164         ptr++;
   165         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   166             * args->right_rear_f) * args->distance_f) + 128);
   167         ptr++;
   168     }
   169     else if (args->room_angle == 90)
   170     for (i = 0; i < len; i += sizeof (Uint8) * 6) {
   171         /* must adjust the sample so that 0 is the center */
   172         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   173             * args->right_f) * args->distance_f) + 128);
   174         ptr++;
   175         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   176             * args->right_rear_f) * args->distance_f) + 128);
   177         ptr++;
   178         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   179             * args->left_f) * args->distance_f) + 128);
   180         ptr++;
   181         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   182             * args->left_rear_f) * args->distance_f) + 128);
   183         ptr++;
   184     }
   185     else if (args->room_angle == 180)
   186     for (i = 0; i < len; i += sizeof (Uint8) * 6) {
   187         /* must adjust the sample so that 0 is the center */
   188         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   189             * args->right_rear_f) * args->distance_f) + 128);
   190         ptr++;
   191         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   192             * args->left_rear_f) * args->distance_f) + 128);
   193         ptr++;
   194         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   195             * args->right_f) * args->distance_f) + 128);
   196         ptr++;
   197         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   198             * args->left_f) * args->distance_f) + 128);
   199         ptr++;
   200     }
   201     else if (args->room_angle == 270)
   202     for (i = 0; i < len; i += sizeof (Uint8) * 6) {
   203         /* must adjust the sample so that 0 is the center */
   204         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   205             * args->left_rear_f) * args->distance_f) + 128);
   206         ptr++;
   207         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   208             * args->left_f) * args->distance_f) + 128);
   209         ptr++;
   210         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   211             * args->right_rear_f) * args->distance_f) + 128);
   212         ptr++;
   213         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   214             * args->right_f) * args->distance_f) + 128);
   215         ptr++;
   216     }
   217 }
   218 
   219 
   220 static void _Eff_position_u8_c6(int chan, void *stream, int len, void *udata)
   221 {
   222     volatile position_args *args = (volatile position_args *) udata;
   223     Uint8 *ptr = (Uint8 *) stream;
   224     int i;
   225 
   226         /*
   227          * if there's only a mono channnel (the only way we wouldn't have
   228          *  a len divisible by 2 here), then left_f and right_f are always
   229          *  1.0, and are therefore throwaways.
   230          */
   231     if (len % sizeof (Uint16) != 0) {
   232         *ptr = (Uint8) (((float) *ptr) * args->distance_f);
   233         ptr++;
   234         len--;
   235     }
   236 
   237     if (args->room_angle == 0)
   238     for (i = 0; i < len; i += sizeof (Uint8) * 6) {
   239         /* must adjust the sample so that 0 is the center */
   240         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   241             * args->left_f) * args->distance_f) + 128);
   242         ptr++;
   243         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   244             * args->right_f) * args->distance_f) + 128);
   245         ptr++;
   246         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   247             * args->left_rear_f) * args->distance_f) + 128);
   248         ptr++;
   249         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   250             * args->right_rear_f) * args->distance_f) + 128);
   251         ptr++;
   252         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   253             * args->center_f) * args->distance_f) + 128);
   254         ptr++;
   255         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   256             * args->lfe_f) * args->distance_f) + 128);
   257         ptr++;
   258     }
   259     else if (args->room_angle == 90)
   260     for (i = 0; i < len; i += sizeof (Uint8) * 6) {
   261         /* must adjust the sample so that 0 is the center */
   262         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   263             * args->right_f) * args->distance_f) + 128);
   264         ptr++;
   265         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   266             * args->right_rear_f) * args->distance_f) + 128);
   267         ptr++;
   268         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   269             * args->left_f) * args->distance_f) + 128);
   270         ptr++;
   271         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   272             * args->left_rear_f) * args->distance_f) + 128);
   273         ptr++;
   274         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   275             * args->right_rear_f) * args->distance_f/2) + 128)
   276             + (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   277             * args->right_f) * args->distance_f/2) + 128);
   278         ptr++;
   279         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   280             * args->lfe_f) * args->distance_f) + 128);
   281         ptr++;
   282     }
   283     else if (args->room_angle == 180)
   284     for (i = 0; i < len; i += sizeof (Uint8) * 6) {
   285         /* must adjust the sample so that 0 is the center */
   286         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   287             * args->right_rear_f) * args->distance_f) + 128);
   288         ptr++;
   289         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   290             * args->left_rear_f) * args->distance_f) + 128);
   291         ptr++;
   292         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   293             * args->right_f) * args->distance_f) + 128);
   294         ptr++;
   295         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   296             * args->left_f) * args->distance_f) + 128);
   297         ptr++;
   298         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   299             * args->right_rear_f) * args->distance_f/2) + 128)
   300             + (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   301             * args->left_rear_f) * args->distance_f/2) + 128);
   302         ptr++;
   303         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   304             * args->lfe_f) * args->distance_f) + 128);
   305         ptr++;
   306     }
   307     else if (args->room_angle == 270)
   308     for (i = 0; i < len; i += sizeof (Uint8) * 6) {
   309         /* must adjust the sample so that 0 is the center */
   310         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   311             * args->left_rear_f) * args->distance_f) + 128);
   312         ptr++;
   313         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   314             * args->left_f) * args->distance_f) + 128);
   315         ptr++;
   316         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   317             * args->right_rear_f) * args->distance_f) + 128);
   318         ptr++;
   319         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   320             * args->right_f) * args->distance_f) + 128);
   321         ptr++;
   322         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   323             * args->left_f) * args->distance_f/2) + 128)
   324             + (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   325             * args->left_rear_f) * args->distance_f/2) + 128);
   326         ptr++;
   327         *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) 
   328             * args->lfe_f) * args->distance_f) + 128);
   329         ptr++;
   330     }
   331 }
   332 
   333 
   334 /*
   335  * This one runs about 10.1 times faster than the non-table version, with
   336  *  no loss in quality. It does, however, require 64k of memory for the
   337  *  lookup table. Also, this will only update position information once per
   338  *  call; the non-table version always checks the arguments for each sample,
   339  *  in case the user has called Mix_SetPanning() or whatnot again while this
   340  *  callback is running.
   341  */
   342 static void _Eff_position_table_u8(int chan, void *stream, int len, void *udata)
   343 {
   344     volatile position_args *args = (volatile position_args *) udata;
   345     Uint8 *ptr = (Uint8 *) stream;
   346     Uint32 *p;
   347     int i;
   348     Uint8 *l = ((Uint8 *) _Eff_volume_table) + (256 * args->left_u8);
   349     Uint8 *r = ((Uint8 *) _Eff_volume_table) + (256 * args->right_u8);
   350     Uint8 *d = ((Uint8 *) _Eff_volume_table) + (256 * args->distance_u8);
   351 
   352     if (args->room_angle == 180) {
   353 	    Uint8 *temp = l;
   354 	    l = r;
   355 	    r = temp;
   356     }
   357         /*
   358          * if there's only a mono channnel, then l[] and r[] are always
   359          *  volume 255, and are therefore throwaways. Still, we have to
   360          *  be sure not to overrun the audio buffer...
   361          */
   362     while (len % sizeof (Uint32) != 0) {
   363         *ptr = d[l[*ptr]];
   364         ptr++;
   365         if (args->channels > 1) {
   366             *ptr = d[r[*ptr]];
   367             ptr++;
   368         }
   369         len -= args->channels;
   370     }
   371 
   372     p = (Uint32 *) ptr;
   373 
   374     for (i = 0; i < len; i += sizeof (Uint32)) {
   375 #if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
   376         *(p++) = (d[l[(*p & 0xFF000000) >> 24]] << 24) |
   377                  (d[r[(*p & 0x00FF0000) >> 16]] << 16) |
   378                  (d[l[(*p & 0x0000FF00) >>  8]] <<  8) |
   379                  (d[r[(*p & 0x000000FF)      ]]      ) ;
   380 #else
   381         *(p++) = (d[r[(*p & 0xFF000000) >> 24]] << 24) |
   382                  (d[l[(*p & 0x00FF0000) >> 16]] << 16) |
   383                  (d[r[(*p & 0x0000FF00) >>  8]] <<  8) |
   384                  (d[l[(*p & 0x000000FF)      ]]      ) ;
   385 #endif
   386     }
   387 }
   388 
   389 
   390 static void _Eff_position_s8(int chan, void *stream, int len, void *udata)
   391 {
   392     volatile position_args *args = (volatile position_args *) udata;
   393     Sint8 *ptr = (Sint8 *) stream;
   394     int i;
   395 
   396         /*
   397          * if there's only a mono channnel (the only way we wouldn't have
   398          *  a len divisible by 2 here), then left_f and right_f are always
   399          *  1.0, and are therefore throwaways.
   400          */
   401     if (len % sizeof (Sint16) != 0) {
   402         *ptr = (Sint8) (((float) *ptr) * args->distance_f);
   403         ptr++;
   404         len--;
   405     }
   406 
   407     if (args->room_angle == 180)
   408     for (i = 0; i < len; i += sizeof (Sint8) * 2) {
   409         *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f);
   410         ptr++;
   411         *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f);
   412         ptr++;
   413     }
   414     else
   415     for (i = 0; i < len; i += sizeof (Sint8) * 2) {
   416         *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f);
   417         ptr++;
   418         *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f);
   419         ptr++;
   420     }
   421 }
   422 static void _Eff_position_s8_c4(int chan, void *stream, int len, void *udata)
   423 {
   424     volatile position_args *args = (volatile position_args *) udata;
   425     Sint8 *ptr = (Sint8 *) stream;
   426     int i;
   427 
   428         /*
   429          * if there's only a mono channnel (the only way we wouldn't have
   430          *  a len divisible by 2 here), then left_f and right_f are always
   431          *  1.0, and are therefore throwaways.
   432          */
   433     if (len % sizeof (Sint16) != 0) {
   434         *ptr = (Sint8) (((float) *ptr) * args->distance_f);
   435         ptr++;
   436         len--;
   437     }
   438 
   439     for (i = 0; i < len; i += sizeof (Sint8) * 4) {
   440       switch (args->room_angle) {
   441        case 0:
   442         *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++;
   443         *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++;
   444         *ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++;
   445         *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++;
   446 	break;
   447        case 90:
   448         *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++;
   449         *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++;
   450         *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++;
   451         *ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++;
   452 	break;
   453        case 180:
   454         *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++;
   455         *ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++;
   456         *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++;
   457         *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++;
   458 	break;
   459        case 270:
   460         *ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++;
   461         *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++;
   462         *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++;
   463         *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++;
   464 	break;
   465       }
   466     }
   467 }
   468 static void _Eff_position_s8_c6(int chan, void *stream, int len, void *udata)
   469 {
   470     volatile position_args *args = (volatile position_args *) udata;
   471     Sint8 *ptr = (Sint8 *) stream;
   472     int i;
   473 
   474         /*
   475          * if there's only a mono channnel (the only way we wouldn't have
   476          *  a len divisible by 2 here), then left_f and right_f are always
   477          *  1.0, and are therefore throwaways.
   478          */
   479     if (len % sizeof (Sint16) != 0) {
   480         *ptr = (Sint8) (((float) *ptr) * args->distance_f);
   481         ptr++;
   482         len--;
   483     }
   484 
   485     for (i = 0; i < len; i += sizeof (Sint8) * 6) {
   486       switch (args->room_angle) {
   487        case 0:
   488         *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++;
   489         *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++;
   490         *ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++;
   491         *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++;
   492         *ptr = (Sint8)((((float) *ptr) * args->center_f) * args->distance_f); ptr++;
   493         *ptr = (Sint8)((((float) *ptr) * args->lfe_f) * args->distance_f); ptr++;
   494 	break;
   495        case 90:
   496         *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++;
   497         *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++;
   498         *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++;
   499         *ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++;
   500         *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f / 2)
   501            + (Sint8)((((float) *ptr) * args->right_f) * args->distance_f / 2); ptr++;
   502         *ptr = (Sint8)((((float) *ptr) * args->lfe_f) * args->distance_f); ptr++;
   503 	break;
   504        case 180:
   505         *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++;
   506         *ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++;
   507         *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++;
   508         *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++;
   509         *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f / 2)
   510            + (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f / 2); ptr++;
   511         *ptr = (Sint8)((((float) *ptr) * args->lfe_f) * args->distance_f); ptr++;
   512 	break;
   513        case 270:
   514         *ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++;
   515         *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++;
   516         *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++;
   517         *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++;
   518         *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f / 2)
   519            + (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f / 2); ptr++;
   520         *ptr = (Sint8)((((float) *ptr) * args->lfe_f) * args->distance_f); ptr++;
   521 	break;
   522       }
   523     }
   524 }
   525 
   526 
   527 /*
   528  * This one runs about 10.1 times faster than the non-table version, with
   529  *  no loss in quality. It does, however, require 64k of memory for the
   530  *  lookup table. Also, this will only update position information once per
   531  *  call; the non-table version always checks the arguments for each sample,
   532  *  in case the user has called Mix_SetPanning() or whatnot again while this
   533  *  callback is running.
   534  */
   535 static void _Eff_position_table_s8(int chan, void *stream, int len, void *udata)
   536 {
   537     volatile position_args *args = (volatile position_args *) udata;
   538     Sint8 *ptr = (Sint8 *) stream;
   539     Uint32 *p;
   540     int i;
   541     Sint8 *l = ((Sint8 *) _Eff_volume_table) + (256 * args->left_u8);
   542     Sint8 *r = ((Sint8 *) _Eff_volume_table) + (256 * args->right_u8);
   543     Sint8 *d = ((Sint8 *) _Eff_volume_table) + (256 * args->distance_u8);
   544 
   545     if (args->room_angle == 180) {
   546 	    Sint8 *temp = l;
   547 	    l = r;
   548 	    r = temp;
   549     }
   550 
   551 
   552     while (len % sizeof (Uint32) != 0) {
   553         *ptr = d[l[*ptr]];
   554         ptr++;
   555         if (args->channels > 1) {
   556             *ptr = d[r[*ptr]];
   557             ptr++;
   558         }
   559         len -= args->channels;
   560     }
   561 
   562     p = (Uint32 *) ptr;
   563 
   564     for (i = 0; i < len; i += sizeof (Uint32)) {
   565 #if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
   566         *(p++) = (d[l[((Sint16)(Sint8)((*p & 0xFF000000) >> 24))+128]] << 24) |
   567                  (d[r[((Sint16)(Sint8)((*p & 0x00FF0000) >> 16))+128]] << 16) |
   568                  (d[l[((Sint16)(Sint8)((*p & 0x0000FF00) >>  8))+128]] <<  8) |
   569                  (d[r[((Sint16)(Sint8)((*p & 0x000000FF)      ))+128]]      ) ;
   570 #else
   571         *(p++) = (d[r[((Sint16)(Sint8)((*p & 0xFF000000) >> 24))+128]] << 24) |
   572                  (d[l[((Sint16)(Sint8)((*p & 0x00FF0000) >> 16))+128]] << 16) |
   573                  (d[r[((Sint16)(Sint8)((*p & 0x0000FF00) >>  8))+128]] <<  8) |
   574                  (d[l[((Sint16)(Sint8)((*p & 0x000000FF)      ))+128]]      ) ;
   575 #endif
   576     }
   577 
   578 
   579 }
   580 
   581 
   582 /* !!! FIXME : Optimize the code for 16-bit samples? */
   583 
   584 static void _Eff_position_u16lsb(int chan, void *stream, int len, void *udata)
   585 {
   586     volatile position_args *args = (volatile position_args *) udata;
   587     Uint16 *ptr = (Uint16 *) stream;
   588     int i;
   589 
   590     for (i = 0; i < len; i += sizeof (Uint16) * 2) {
   591         Sint16 sampl = (Sint16) (SDL_SwapLE16(*(ptr+0)) - 32768);
   592         Sint16 sampr = (Sint16) (SDL_SwapLE16(*(ptr+1)) - 32768);
   593         
   594         Uint16 swapl = (Uint16) ((Sint16) (((float) sampl * args->left_f)
   595                                     * args->distance_f) + 32768);
   596         Uint16 swapr = (Uint16) ((Sint16) (((float) sampr * args->right_f)
   597                                     * args->distance_f) + 32768);
   598 
   599 	if (args->room_angle == 180) {
   600         	*(ptr++) = (Uint16) SDL_SwapLE16(swapr);
   601         	*(ptr++) = (Uint16) SDL_SwapLE16(swapl);
   602 	}
   603 	else {
   604         	*(ptr++) = (Uint16) SDL_SwapLE16(swapl);
   605         	*(ptr++) = (Uint16) SDL_SwapLE16(swapr);
   606 	}
   607     }
   608 }
   609 static void _Eff_position_u16lsb_c4(int chan, void *stream, int len, void *udata)
   610 {
   611     volatile position_args *args = (volatile position_args *) udata;
   612     Uint16 *ptr = (Uint16 *) stream;
   613     int i;
   614 
   615     for (i = 0; i < len; i += sizeof (Uint16) * 4) {
   616         Sint16 sampl = (Sint16) (SDL_SwapLE16(*(ptr+0)) - 32768);
   617         Sint16 sampr = (Sint16) (SDL_SwapLE16(*(ptr+1)) - 32768);
   618         Sint16 samplr = (Sint16) (SDL_SwapLE16(*(ptr+2)) - 32768);
   619         Sint16 samprr = (Sint16) (SDL_SwapLE16(*(ptr+3)) - 32768);
   620         
   621         Uint16 swapl = (Uint16) ((Sint16) (((float) sampl * args->left_f)
   622                                     * args->distance_f) + 32768);
   623         Uint16 swapr = (Uint16) ((Sint16) (((float) sampr * args->right_f)
   624                                     * args->distance_f) + 32768);
   625         Uint16 swaplr = (Uint16) ((Sint16) (((float) samplr * args->left_f)
   626                                     * args->distance_f) + 32768);
   627         Uint16 swaprr = (Uint16) ((Sint16) (((float) samprr * args->right_f)
   628                                     * args->distance_f) + 32768);
   629 
   630 	switch (args->room_angle) {
   631 		case 0:
   632         		*(ptr++) = (Uint16) SDL_SwapLE16(swapl);
   633         		*(ptr++) = (Uint16) SDL_SwapLE16(swapr);
   634         		*(ptr++) = (Uint16) SDL_SwapLE16(swaplr);
   635         		*(ptr++) = (Uint16) SDL_SwapLE16(swaprr);
   636 			break;
   637 		case 90:
   638         		*(ptr++) = (Uint16) SDL_SwapLE16(swapr);
   639         		*(ptr++) = (Uint16) SDL_SwapLE16(swaprr);
   640         		*(ptr++) = (Uint16) SDL_SwapLE16(swapl);
   641         		*(ptr++) = (Uint16) SDL_SwapLE16(swaplr);
   642 			break;
   643 		case 180:
   644         		*(ptr++) = (Uint16) SDL_SwapLE16(swaprr);
   645         		*(ptr++) = (Uint16) SDL_SwapLE16(swaplr);
   646         		*(ptr++) = (Uint16) SDL_SwapLE16(swapr);
   647         		*(ptr++) = (Uint16) SDL_SwapLE16(swapl);
   648 			break;
   649 		case 270:
   650         		*(ptr++) = (Uint16) SDL_SwapLE16(swaplr);
   651         		*(ptr++) = (Uint16) SDL_SwapLE16(swapl);
   652         		*(ptr++) = (Uint16) SDL_SwapLE16(swaprr);
   653         		*(ptr++) = (Uint16) SDL_SwapLE16(swapr);
   654 			break;
   655 	}
   656     }
   657 }
   658 static void _Eff_position_u16lsb_c6(int chan, void *stream, int len, void *udata)
   659 {
   660     volatile position_args *args = (volatile position_args *) udata;
   661     Uint16 *ptr = (Uint16 *) stream;
   662     int i;
   663 
   664     for (i = 0; i < len; i += sizeof (Uint16) * 6) {
   665         Sint16 sampl = (Sint16) (SDL_SwapLE16(*(ptr+0)) - 32768);
   666         Sint16 sampr = (Sint16) (SDL_SwapLE16(*(ptr+1)) - 32768);
   667         Sint16 samplr = (Sint16) (SDL_SwapLE16(*(ptr+2)) - 32768);
   668         Sint16 samprr = (Sint16) (SDL_SwapLE16(*(ptr+3)) - 32768);
   669         Sint16 sampce = (Sint16) (SDL_SwapLE16(*(ptr+4)) - 32768);
   670         Sint16 sampwf = (Sint16) (SDL_SwapLE16(*(ptr+5)) - 32768);
   671         
   672         Uint16 swapl = (Uint16) ((Sint16) (((float) sampl * args->left_f)
   673                                     * args->distance_f) + 32768);
   674         Uint16 swapr = (Uint16) ((Sint16) (((float) sampr * args->right_f)
   675                                     * args->distance_f) + 32768);
   676         Uint16 swaplr = (Uint16) ((Sint16) (((float) samplr * args->left_f)
   677                                     * args->distance_f) + 32768);
   678         Uint16 swaprr = (Uint16) ((Sint16) (((float) samprr * args->right_f)
   679                                     * args->distance_f) + 32768);
   680         Uint16 swapce = (Uint16) ((Sint16) (((float) sampce * args->left_f)
   681                                     * args->distance_f) + 32768);
   682         Uint16 swapwf = (Uint16) ((Sint16) (((float) sampwf * args->right_f)
   683                                     * args->distance_f) + 32768);
   684 
   685 	switch (args->room_angle) {
   686 		case 0:
   687         		*(ptr++) = (Uint16) SDL_SwapLE16(swapl);
   688         		*(ptr++) = (Uint16) SDL_SwapLE16(swapr);
   689         		*(ptr++) = (Uint16) SDL_SwapLE16(swaplr);
   690         		*(ptr++) = (Uint16) SDL_SwapLE16(swaprr);
   691         		*(ptr++) = (Uint16) SDL_SwapLE16(swapce);
   692         		*(ptr++) = (Uint16) SDL_SwapLE16(swapwf);
   693 			break;
   694 		case 90:
   695         		*(ptr++) = (Uint16) SDL_SwapLE16(swapr);
   696         		*(ptr++) = (Uint16) SDL_SwapLE16(swaprr);
   697         		*(ptr++) = (Uint16) SDL_SwapLE16(swapl);
   698         		*(ptr++) = (Uint16) SDL_SwapLE16(swaplr);
   699         		*(ptr++) = (Uint16) SDL_SwapLE16(swapr)/2 + (Uint16) SDL_SwapLE16(swaprr)/2;
   700         		*(ptr++) = (Uint16) SDL_SwapLE16(swapwf);
   701 			break;
   702 		case 180:
   703         		*(ptr++) = (Uint16) SDL_SwapLE16(swaprr);
   704         		*(ptr++) = (Uint16) SDL_SwapLE16(swaplr);
   705         		*(ptr++) = (Uint16) SDL_SwapLE16(swapr);
   706         		*(ptr++) = (Uint16) SDL_SwapLE16(swapl);
   707         		*(ptr++) = (Uint16) SDL_SwapLE16(swaprr)/2 + (Uint16) SDL_SwapLE16(swaplr)/2;
   708         		*(ptr++) = (Uint16) SDL_SwapLE16(swapwf);
   709 			break;
   710 		case 270:
   711         		*(ptr++) = (Uint16) SDL_SwapLE16(swaplr);
   712         		*(ptr++) = (Uint16) SDL_SwapLE16(swapl);
   713         		*(ptr++) = (Uint16) SDL_SwapLE16(swaprr);
   714         		*(ptr++) = (Uint16) SDL_SwapLE16(swapr);
   715         		*(ptr++) = (Uint16) SDL_SwapLE16(swapl)/2 + (Uint16) SDL_SwapLE16(swaplr)/2;
   716         		*(ptr++) = (Uint16) SDL_SwapLE16(swapwf);
   717 			break;
   718 	}
   719     }
   720 }
   721 
   722 static void _Eff_position_s16lsb(int chan, void *stream, int len, void *udata)
   723 {
   724     /* 16 signed bits (lsb) * 2 channels. */
   725     volatile position_args *args = (volatile position_args *) udata;
   726     Sint16 *ptr = (Sint16 *) stream;
   727     int i;
   728 
   729 #if 0
   730     if (len % (sizeof(Sint16) * 2)) {
   731 	    fprintf(stderr,"Not an even number of frames! len=%d\n", len);
   732 	    return;
   733     }
   734 #endif
   735 
   736     for (i = 0; i < len; i += sizeof (Sint16) * 2) {
   737         Sint16 swapl = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+0))) *
   738                                     args->left_f) * args->distance_f);
   739         Sint16 swapr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+1))) *
   740                                     args->right_f) * args->distance_f);
   741 	if (args->room_angle == 180) {
   742         	*(ptr++) = (Sint16) SDL_SwapLE16(swapr);
   743         	*(ptr++) = (Sint16) SDL_SwapLE16(swapl);
   744 	}
   745 	else {
   746         	*(ptr++) = (Sint16) SDL_SwapLE16(swapl);
   747         	*(ptr++) = (Sint16) SDL_SwapLE16(swapr);
   748 	}
   749     }
   750 }
   751 static void _Eff_position_s16lsb_c4(int chan, void *stream, int len, void *udata)
   752 {
   753     /* 16 signed bits (lsb) * 4 channels. */
   754     volatile position_args *args = (volatile position_args *) udata;
   755     Sint16 *ptr = (Sint16 *) stream;
   756     int i;
   757 
   758     for (i = 0; i < len; i += sizeof (Sint16) * 4) {
   759         Sint16 swapl = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+0))) *
   760                                     args->left_f) * args->distance_f);
   761         Sint16 swapr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+1))) *
   762                                     args->right_f) * args->distance_f);
   763         Sint16 swaplr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+1))) *
   764                                     args->left_rear_f) * args->distance_f);
   765         Sint16 swaprr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+2))) *
   766                                     args->right_rear_f) * args->distance_f);
   767 	switch (args->room_angle) {
   768 		case 0:
   769         		*(ptr++) = (Sint16) SDL_SwapLE16(swapl);
   770         		*(ptr++) = (Sint16) SDL_SwapLE16(swapr);
   771         		*(ptr++) = (Sint16) SDL_SwapLE16(swaplr);
   772         		*(ptr++) = (Sint16) SDL_SwapLE16(swaprr);
   773 			break;
   774 		case 90:
   775         		*(ptr++) = (Sint16) SDL_SwapLE16(swapr);
   776         		*(ptr++) = (Sint16) SDL_SwapLE16(swaprr);
   777         		*(ptr++) = (Sint16) SDL_SwapLE16(swapl);
   778         		*(ptr++) = (Sint16) SDL_SwapLE16(swaplr);
   779 			break;
   780 		case 180:
   781         		*(ptr++) = (Sint16) SDL_SwapLE16(swaprr);
   782         		*(ptr++) = (Sint16) SDL_SwapLE16(swaplr);
   783         		*(ptr++) = (Sint16) SDL_SwapLE16(swapr);
   784         		*(ptr++) = (Sint16) SDL_SwapLE16(swapl);
   785 			break;
   786 		case 270:
   787         		*(ptr++) = (Sint16) SDL_SwapLE16(swaplr);
   788         		*(ptr++) = (Sint16) SDL_SwapLE16(swapl);
   789         		*(ptr++) = (Sint16) SDL_SwapLE16(swaprr);
   790         		*(ptr++) = (Sint16) SDL_SwapLE16(swapr);
   791 			break;
   792 	}
   793     }
   794 }
   795 
   796 static void _Eff_position_s16lsb_c6(int chan, void *stream, int len, void *udata)
   797 {
   798     /* 16 signed bits (lsb) * 6 channels. */
   799     volatile position_args *args = (volatile position_args *) udata;
   800     Sint16 *ptr = (Sint16 *) stream;
   801     int i;
   802 
   803     for (i = 0; i < len; i += sizeof (Sint16) * 6) {
   804         Sint16 swapl = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+0))) *
   805                                     args->left_f) * args->distance_f);
   806         Sint16 swapr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+1))) *
   807                                     args->right_f) * args->distance_f);
   808         Sint16 swaplr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+2))) *
   809                                     args->left_rear_f) * args->distance_f);
   810         Sint16 swaprr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+3))) *
   811                                     args->right_rear_f) * args->distance_f);
   812         Sint16 swapce = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+4))) *
   813                                     args->center_f) * args->distance_f);
   814         Sint16 swapwf = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+5))) *
   815                                     args->lfe_f) * args->distance_f);
   816 	switch (args->room_angle) {
   817 		case 0:
   818         		*(ptr++) = (Sint16) SDL_SwapLE16(swapl);
   819         		*(ptr++) = (Sint16) SDL_SwapLE16(swapr);
   820         		*(ptr++) = (Sint16) SDL_SwapLE16(swaplr);
   821         		*(ptr++) = (Sint16) SDL_SwapLE16(swaprr);
   822         		*(ptr++) = (Sint16) SDL_SwapLE16(swapce);
   823         		*(ptr++) = (Sint16) SDL_SwapLE16(swapwf);
   824 			break;
   825 		case 90:
   826         		*(ptr++) = (Sint16) SDL_SwapLE16(swapr);
   827         		*(ptr++) = (Sint16) SDL_SwapLE16(swaprr);
   828         		*(ptr++) = (Sint16) SDL_SwapLE16(swapl);
   829         		*(ptr++) = (Sint16) SDL_SwapLE16(swaplr);
   830         		*(ptr++) = (Sint16) SDL_SwapLE16(swapr)/2 + (Sint16) SDL_SwapLE16(swaprr)/2;
   831         		*(ptr++) = (Sint16) SDL_SwapLE16(swapwf);
   832 			break;
   833 		case 180:
   834         		*(ptr++) = (Sint16) SDL_SwapLE16(swaprr);
   835         		*(ptr++) = (Sint16) SDL_SwapLE16(swaplr);
   836         		*(ptr++) = (Sint16) SDL_SwapLE16(swapr);
   837         		*(ptr++) = (Sint16) SDL_SwapLE16(swapl);
   838         		*(ptr++) = (Sint16) SDL_SwapLE16(swaprr)/2 + (Sint16) SDL_SwapLE16(swaplr)/2;
   839         		*(ptr++) = (Sint16) SDL_SwapLE16(swapwf);
   840 			break;
   841 		case 270:
   842         		*(ptr++) = (Sint16) SDL_SwapLE16(swaplr);
   843         		*(ptr++) = (Sint16) SDL_SwapLE16(swapl);
   844         		*(ptr++) = (Sint16) SDL_SwapLE16(swaprr);
   845         		*(ptr++) = (Sint16) SDL_SwapLE16(swapr);
   846         		*(ptr++) = (Sint16) SDL_SwapLE16(swapl)/2 + (Sint16) SDL_SwapLE16(swaplr)/2;
   847         		*(ptr++) = (Sint16) SDL_SwapLE16(swapwf);
   848 			break;
   849 	}
   850     }
   851 }
   852 
   853 static void _Eff_position_u16msb(int chan, void *stream, int len, void *udata)
   854 {
   855     /* 16 signed bits (lsb) * 2 channels. */
   856     volatile position_args *args = (volatile position_args *) udata;
   857     Uint16 *ptr = (Uint16 *) stream;
   858     int i;
   859 
   860     for (i = 0; i < len; i += sizeof (Sint16) * 2) {
   861         Sint16 sampl = (Sint16) (SDL_SwapBE16(*(ptr+0)) - 32768);
   862         Sint16 sampr = (Sint16) (SDL_SwapBE16(*(ptr+1)) - 32768);
   863         
   864         Uint16 swapl = (Uint16) ((Sint16) (((float) sampl * args->left_f)
   865                                     * args->distance_f) + 32768);
   866         Uint16 swapr = (Uint16) ((Sint16) (((float) sampr * args->right_f)
   867                                     * args->distance_f) + 32768);
   868 
   869 	if (args->room_angle == 180) {
   870         	*(ptr++) = (Uint16) SDL_SwapBE16(swapr);
   871         	*(ptr++) = (Uint16) SDL_SwapBE16(swapl);
   872 	}
   873 	else {
   874         	*(ptr++) = (Uint16) SDL_SwapBE16(swapl);
   875         	*(ptr++) = (Uint16) SDL_SwapBE16(swapr);
   876 	}
   877     }
   878 }
   879 static void _Eff_position_u16msb_c4(int chan, void *stream, int len, void *udata)
   880 {
   881     /* 16 signed bits (lsb) * 4 channels. */
   882     volatile position_args *args = (volatile position_args *) udata;
   883     Uint16 *ptr = (Uint16 *) stream;
   884     int i;
   885 
   886     for (i = 0; i < len; i += sizeof (Sint16) * 4) {
   887         Sint16 sampl = (Sint16) (SDL_SwapBE16(*(ptr+0)) - 32768);
   888         Sint16 sampr = (Sint16) (SDL_SwapBE16(*(ptr+1)) - 32768);
   889         Sint16 samplr = (Sint16) (SDL_SwapBE16(*(ptr+2)) - 32768);
   890         Sint16 samprr = (Sint16) (SDL_SwapBE16(*(ptr+3)) - 32768);
   891         
   892         Uint16 swapl = (Uint16) ((Sint16) (((float) sampl * args->left_f)
   893                                     * args->distance_f) + 32768);
   894         Uint16 swapr = (Uint16) ((Sint16) (((float) sampr * args->right_f)
   895                                     * args->distance_f) + 32768);
   896         Uint16 swaplr = (Uint16) ((Sint16) (((float) samplr * args->left_rear_f)
   897                                     * args->distance_f) + 32768);
   898         Uint16 swaprr = (Uint16) ((Sint16) (((float) samprr * args->right_rear_f)
   899                                     * args->distance_f) + 32768);
   900 
   901 	switch (args->room_angle) {
   902 		case 0:
   903         		*(ptr++) = (Uint16) SDL_SwapBE16(swapl);
   904         		*(ptr++) = (Uint16) SDL_SwapBE16(swapr);
   905         		*(ptr++) = (Uint16) SDL_SwapBE16(swaplr);
   906         		*(ptr++) = (Uint16) SDL_SwapBE16(swaprr);
   907 			break;
   908 		case 90:
   909         		*(ptr++) = (Uint16) SDL_SwapBE16(swapr);
   910         		*(ptr++) = (Uint16) SDL_SwapBE16(swaprr);
   911         		*(ptr++) = (Uint16) SDL_SwapBE16(swapl);
   912         		*(ptr++) = (Uint16) SDL_SwapBE16(swaplr);
   913 			break;
   914 		case 180:
   915         		*(ptr++) = (Uint16) SDL_SwapBE16(swaprr);
   916         		*(ptr++) = (Uint16) SDL_SwapBE16(swaplr);
   917         		*(ptr++) = (Uint16) SDL_SwapBE16(swapr);
   918         		*(ptr++) = (Uint16) SDL_SwapBE16(swapl);
   919 			break;
   920 		case 270:
   921         		*(ptr++) = (Uint16) SDL_SwapBE16(swaplr);
   922         		*(ptr++) = (Uint16) SDL_SwapBE16(swapl);
   923         		*(ptr++) = (Uint16) SDL_SwapBE16(swaprr);
   924         		*(ptr++) = (Uint16) SDL_SwapBE16(swapr);
   925 			break;
   926 	}
   927     }
   928 }
   929 static void _Eff_position_u16msb_c6(int chan, void *stream, int len, void *udata)
   930 {
   931     /* 16 signed bits (lsb) * 6 channels. */
   932     volatile position_args *args = (volatile position_args *) udata;
   933     Uint16 *ptr = (Uint16 *) stream;
   934     int i;
   935 
   936     for (i = 0; i < len; i += sizeof (Sint16) * 6) {
   937         Sint16 sampl = (Sint16) (SDL_SwapBE16(*(ptr+0)) - 32768);
   938         Sint16 sampr = (Sint16) (SDL_SwapBE16(*(ptr+1)) - 32768);
   939         Sint16 samplr = (Sint16) (SDL_SwapBE16(*(ptr+2)) - 32768);
   940         Sint16 samprr = (Sint16) (SDL_SwapBE16(*(ptr+3)) - 32768);
   941         Sint16 sampce = (Sint16) (SDL_SwapBE16(*(ptr+4)) - 32768);
   942         Sint16 sampwf = (Sint16) (SDL_SwapBE16(*(ptr+5)) - 32768);
   943         
   944         Uint16 swapl = (Uint16) ((Sint16) (((float) sampl * args->left_f)
   945                                     * args->distance_f) + 32768);
   946         Uint16 swapr = (Uint16) ((Sint16) (((float) sampr * args->right_f)
   947                                     * args->distance_f) + 32768);
   948         Uint16 swaplr = (Uint16) ((Sint16) (((float) samplr * args->left_rear_f)
   949                                     * args->distance_f) + 32768);
   950         Uint16 swaprr = (Uint16) ((Sint16) (((float) samprr * args->right_rear_f)
   951                                     * args->distance_f) + 32768);
   952         Uint16 swapce = (Uint16) ((Sint16) (((float) sampce * args->center_f)
   953                                     * args->distance_f) + 32768);
   954         Uint16 swapwf = (Uint16) ((Sint16) (((float) sampwf * args->lfe_f)
   955                                     * args->distance_f) + 32768);
   956 
   957 	switch (args->room_angle) {
   958 		case 0:
   959         		*(ptr++) = (Uint16) SDL_SwapBE16(swapl);
   960         		*(ptr++) = (Uint16) SDL_SwapBE16(swapr);
   961         		*(ptr++) = (Uint16) SDL_SwapBE16(swaplr);
   962         		*(ptr++) = (Uint16) SDL_SwapBE16(swaprr);
   963         		*(ptr++) = (Uint16) SDL_SwapBE16(swapce);
   964         		*(ptr++) = (Uint16) SDL_SwapBE16(swapwf);
   965 			break;
   966 		case 90:
   967         		*(ptr++) = (Uint16) SDL_SwapBE16(swapr);
   968         		*(ptr++) = (Uint16) SDL_SwapBE16(swaprr);
   969         		*(ptr++) = (Uint16) SDL_SwapBE16(swapl);
   970         		*(ptr++) = (Uint16) SDL_SwapBE16(swaplr);
   971         		*(ptr++) = (Uint16) SDL_SwapBE16(swapr)/2 + (Uint16) SDL_SwapBE16(swaprr)/2;
   972         		*(ptr++) = (Uint16) SDL_SwapBE16(swapwf);
   973 			break;
   974 		case 180:
   975         		*(ptr++) = (Uint16) SDL_SwapBE16(swaprr);
   976         		*(ptr++) = (Uint16) SDL_SwapBE16(swaplr);
   977         		*(ptr++) = (Uint16) SDL_SwapBE16(swapr);
   978         		*(ptr++) = (Uint16) SDL_SwapBE16(swapl);
   979         		*(ptr++) = (Uint16) SDL_SwapBE16(swaprr)/2 + (Uint16) SDL_SwapBE16(swaplr)/2;
   980         		*(ptr++) = (Uint16) SDL_SwapBE16(swapwf);
   981 			break;
   982 		case 270:
   983         		*(ptr++) = (Uint16) SDL_SwapBE16(swaplr);
   984         		*(ptr++) = (Uint16) SDL_SwapBE16(swapl);
   985         		*(ptr++) = (Uint16) SDL_SwapBE16(swaprr);
   986         		*(ptr++) = (Uint16) SDL_SwapBE16(swapr);
   987         		*(ptr++) = (Uint16) SDL_SwapBE16(swapl)/2 + (Uint16) SDL_SwapBE16(swaplr)/2;
   988         		*(ptr++) = (Uint16) SDL_SwapBE16(swapwf);
   989 			break;
   990 	}
   991     }
   992 }
   993 
   994 static void _Eff_position_s16msb(int chan, void *stream, int len, void *udata)
   995 {
   996     /* 16 signed bits (lsb) * 2 channels. */
   997     volatile position_args *args = (volatile position_args *) udata;
   998     Sint16 *ptr = (Sint16 *) stream;
   999     int i;
  1000 
  1001     for (i = 0; i < len; i += sizeof (Sint16) * 2) {
  1002         Sint16 swapl = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+0))) *
  1003                                     args->left_f) * args->distance_f);
  1004         Sint16 swapr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+1))) *
  1005                                     args->right_f) * args->distance_f);
  1006         *(ptr++) = (Sint16) SDL_SwapBE16(swapl);
  1007         *(ptr++) = (Sint16) SDL_SwapBE16(swapr);
  1008     }
  1009 }
  1010 static void _Eff_position_s16msb_c4(int chan, void *stream, int len, void *udata)
  1011 {
  1012     /* 16 signed bits (lsb) * 4 channels. */
  1013     volatile position_args *args = (volatile position_args *) udata;
  1014     Sint16 *ptr = (Sint16 *) stream;
  1015     int i;
  1016 
  1017     for (i = 0; i < len; i += sizeof (Sint16) * 4) {
  1018         Sint16 swapl = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+0))) *
  1019                                     args->left_f) * args->distance_f);
  1020         Sint16 swapr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+1))) *
  1021                                     args->right_f) * args->distance_f);
  1022         Sint16 swaplr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+2))) *
  1023                                     args->left_rear_f) * args->distance_f);
  1024         Sint16 swaprr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+3))) *
  1025                                     args->right_rear_f) * args->distance_f);
  1026 	switch (args->room_angle) {
  1027 		case 0:
  1028         		*(ptr++) = (Sint16) SDL_SwapBE16(swapl);
  1029         		*(ptr++) = (Sint16) SDL_SwapBE16(swapr);
  1030         		*(ptr++) = (Sint16) SDL_SwapBE16(swaplr);
  1031         		*(ptr++) = (Sint16) SDL_SwapBE16(swaprr);
  1032 			break;
  1033 		case 90:
  1034         		*(ptr++) = (Sint16) SDL_SwapBE16(swapr);
  1035         		*(ptr++) = (Sint16) SDL_SwapBE16(swaprr);
  1036         		*(ptr++) = (Sint16) SDL_SwapBE16(swapl);
  1037         		*(ptr++) = (Sint16) SDL_SwapBE16(swaplr);
  1038 			break;
  1039 		case 180:
  1040         		*(ptr++) = (Sint16) SDL_SwapBE16(swaprr);
  1041         		*(ptr++) = (Sint16) SDL_SwapBE16(swaplr);
  1042         		*(ptr++) = (Sint16) SDL_SwapBE16(swapr);
  1043         		*(ptr++) = (Sint16) SDL_SwapBE16(swapl);
  1044 			break;
  1045 		case 270:
  1046         		*(ptr++) = (Sint16) SDL_SwapBE16(swaplr);
  1047         		*(ptr++) = (Sint16) SDL_SwapBE16(swapl);
  1048         		*(ptr++) = (Sint16) SDL_SwapBE16(swaprr);
  1049         		*(ptr++) = (Sint16) SDL_SwapBE16(swapr);
  1050 			break;
  1051 	}
  1052     }
  1053 }
  1054 static void _Eff_position_s16msb_c6(int chan, void *stream, int len, void *udata)
  1055 {
  1056     /* 16 signed bits (lsb) * 6 channels. */
  1057     volatile position_args *args = (volatile position_args *) udata;
  1058     Sint16 *ptr = (Sint16 *) stream;
  1059     int i;
  1060 
  1061     for (i = 0; i < len; i += sizeof (Sint16) * 6) {
  1062         Sint16 swapl = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+0))) *
  1063                                     args->left_f) * args->distance_f);
  1064         Sint16 swapr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+1))) *
  1065                                     args->right_f) * args->distance_f);
  1066         Sint16 swaplr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+2))) *
  1067                                     args->left_rear_f) * args->distance_f);
  1068         Sint16 swaprr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+3))) *
  1069                                     args->right_rear_f) * args->distance_f);
  1070         Sint16 swapce = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+4))) *
  1071                                     args->center_f) * args->distance_f);
  1072         Sint16 swapwf = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+5))) *
  1073                                     args->lfe_f) * args->distance_f);
  1074 
  1075 	switch (args->room_angle) {
  1076 		case 0:
  1077         		*(ptr++) = (Sint16) SDL_SwapBE16(swapl);
  1078         		*(ptr++) = (Sint16) SDL_SwapBE16(swapr);
  1079         		*(ptr++) = (Sint16) SDL_SwapBE16(swaplr);
  1080         		*(ptr++) = (Sint16) SDL_SwapBE16(swaprr);
  1081         		*(ptr++) = (Sint16) SDL_SwapBE16(swapce);
  1082         		*(ptr++) = (Sint16) SDL_SwapBE16(swapwf);
  1083 			break;
  1084 		case 90:
  1085         		*(ptr++) = (Sint16) SDL_SwapBE16(swapr);
  1086         		*(ptr++) = (Sint16) SDL_SwapBE16(swaprr);
  1087         		*(ptr++) = (Sint16) SDL_SwapBE16(swapl);
  1088         		*(ptr++) = (Sint16) SDL_SwapBE16(swaplr);
  1089         		*(ptr++) = (Sint16) SDL_SwapBE16(swapr)/2 + (Sint16) SDL_SwapBE16(swaprr)/2;
  1090         		*(ptr++) = (Sint16) SDL_SwapBE16(swapwf);
  1091 			break;
  1092 		case 180:
  1093         		*(ptr++) = (Sint16) SDL_SwapBE16(swaprr);
  1094         		*(ptr++) = (Sint16) SDL_SwapBE16(swaplr);
  1095         		*(ptr++) = (Sint16) SDL_SwapBE16(swapr);
  1096         		*(ptr++) = (Sint16) SDL_SwapBE16(swapl);
  1097         		*(ptr++) = (Sint16) SDL_SwapBE16(swaprr)/2 + (Sint16) SDL_SwapBE16(swaplr)/2;
  1098         		*(ptr++) = (Sint16) SDL_SwapBE16(swapwf);
  1099 			break;
  1100 		case 270:
  1101         		*(ptr++) = (Sint16) SDL_SwapBE16(swaplr);
  1102         		*(ptr++) = (Sint16) SDL_SwapBE16(swapl);
  1103         		*(ptr++) = (Sint16) SDL_SwapBE16(swaprr);
  1104         		*(ptr++) = (Sint16) SDL_SwapBE16(swapr);
  1105         		*(ptr++) = (Sint16) SDL_SwapBE16(swapl)/2 + (Sint16) SDL_SwapBE16(swaplr)/2;
  1106         		*(ptr++) = (Sint16) SDL_SwapBE16(swapwf);
  1107 			break;
  1108 	}
  1109     }
  1110 }
  1111 
  1112 static void init_position_args(position_args *args)
  1113 {
  1114     memset(args, '\0', sizeof (position_args));
  1115     args->in_use = 0;
  1116     args->room_angle = 0;
  1117     args->left_u8 = args->right_u8 = args->distance_u8 = 255;
  1118     args->left_f  = args->right_f  = args->distance_f  = 1.0f;
  1119     args->left_rear_u8 = args->right_rear_u8 = args->center_u8 = args->lfe_u8 = 255;
  1120     args->left_rear_f = args->right_rear_f = args->center_f = args->lfe_f = 1.0f;
  1121     Mix_QuerySpec(NULL, NULL, (int *) &args->channels);
  1122 }
  1123 
  1124 
  1125 static position_args *get_position_arg(int channel)
  1126 {
  1127     void *rc;
  1128     int i;
  1129 
  1130     if (channel < 0) {
  1131         if (pos_args_global == NULL) {
  1132             pos_args_global = malloc(sizeof (position_args));
  1133             if (pos_args_global == NULL) {
  1134                 Mix_SetError("Out of memory");
  1135                 return(NULL);
  1136             }
  1137             init_position_args(pos_args_global);
  1138         }
  1139 
  1140         return(pos_args_global);
  1141     }
  1142 
  1143     if (channel >= position_channels) {
  1144         rc = realloc(pos_args_array, (channel + 1) * sizeof (position_args *));
  1145         if (rc == NULL) {
  1146             Mix_SetError("Out of memory");
  1147             return(NULL);
  1148         }
  1149         pos_args_array = (position_args **) rc;
  1150         for (i = position_channels; i <= channel; i++) {
  1151             pos_args_array[i] = NULL;
  1152         }
  1153         position_channels = channel + 1;
  1154     }
  1155 
  1156     if (pos_args_array[channel] == NULL) {
  1157         pos_args_array[channel] = (position_args *)malloc(sizeof(position_args));
  1158         if (pos_args_array[channel] == NULL) {
  1159             Mix_SetError("Out of memory");
  1160             return(NULL);
  1161         }
  1162         init_position_args(pos_args_array[channel]);
  1163     }
  1164 
  1165     return(pos_args_array[channel]);
  1166 }
  1167 
  1168 
  1169 static Mix_EffectFunc_t get_position_effect_func(Uint16 format, int channels)
  1170 {
  1171     Mix_EffectFunc_t f = NULL;
  1172 
  1173     switch (format) {
  1174         case AUDIO_U8:
  1175 	    switch (channels) {
  1176 		    case 1:
  1177 		    case 2:
  1178             		f = (_Eff_build_volume_table_u8()) ? _Eff_position_table_u8 :
  1179                                                  		_Eff_position_u8;
  1180 	    		break;
  1181 	    	    case 4:
  1182                         _Eff_position_u8_c4;
  1183 	    		break;
  1184 	    	    case 6:
  1185                         _Eff_position_u8_c6;
  1186 	    		break;
  1187 	    }
  1188             break;
  1189 
  1190         case AUDIO_S8:
  1191 	    switch (channels) {
  1192 		    case 1:
  1193 		    case 2:
  1194             		f = (_Eff_build_volume_table_s8()) ? _Eff_position_table_s8 :
  1195                                                  		_Eff_position_s8;
  1196 	    		break;
  1197 	    	    case 4:
  1198                         _Eff_position_s8_c4;
  1199 	    		break;
  1200 	    	    case 6:
  1201                         _Eff_position_s8_c6;
  1202 	    		break;
  1203 	    }
  1204             break;
  1205 
  1206         case AUDIO_U16LSB:
  1207 	    switch (channels) {
  1208 		    case 1:
  1209 		    case 2:
  1210             		f = _Eff_position_u16lsb;
  1211 	    		break;
  1212 	    	    case 4:
  1213             		f = _Eff_position_u16lsb_c4;
  1214 	    		break;
  1215 	    	    case 6:
  1216             		f = _Eff_position_u16lsb_c6;
  1217 	    		break;
  1218 	    }
  1219             break;
  1220 
  1221         case AUDIO_S16LSB:
  1222 	    switch (channels) {
  1223 		    case 1:
  1224 		    case 2:
  1225             		f = _Eff_position_s16lsb;
  1226 	    		break;
  1227 	    	    case 4:
  1228             		f = _Eff_position_s16lsb_c4;
  1229 	    		break;
  1230 	    	    case 6:
  1231             		f = _Eff_position_s16lsb_c6;
  1232 	    		break;
  1233 	    }
  1234             break;
  1235 
  1236         case AUDIO_U16MSB:
  1237 	    switch (channels) {
  1238 		    case 1:
  1239 		    case 2:
  1240             		f = _Eff_position_u16msb;
  1241 	    		break;
  1242 	    	    case 4:
  1243             		f = _Eff_position_u16msb_c4;
  1244 	    		break;
  1245 	    	    case 6:
  1246             		f = _Eff_position_u16msb_c6;
  1247 	    		break;
  1248 	    }
  1249             break;
  1250 
  1251         case AUDIO_S16MSB:
  1252 	    switch (channels) {
  1253 		    case 1:
  1254 		    case 2:
  1255             		f = _Eff_position_s16msb;
  1256 	    		break;
  1257 	    	    case 4:
  1258             		f = _Eff_position_s16msb_c4;
  1259 	    		break;
  1260 	    	    case 6:
  1261             		f = _Eff_position_s16msb_c6;
  1262 	    		break;
  1263 	    }
  1264             break;
  1265 
  1266         default:
  1267             Mix_SetError("Unsupported audio format");
  1268     }
  1269 
  1270     return(f);
  1271 }
  1272 
  1273 static Uint8 speaker_amplitude[6];
  1274 
  1275 static void set_amplitudes(int channels, int angle, int room_angle)
  1276 {
  1277     int left = 255, right = 255;
  1278     int left_rear = 255, right_rear = 255, center = 255;
  1279 
  1280         /* unwind the angle...it'll be between 0 and 359. */
  1281     while (angle >= 360) angle -= 360;
  1282     while (angle < 0) angle += 360;
  1283 
  1284     if (channels == 2)
  1285     {
  1286         /*
  1287          * We only attenuate by position if the angle falls on the far side
  1288          *  of center; That is, an angle that's due north would not attenuate
  1289          *  either channel. Due west attenuates the right channel to 0.0, and
  1290          *  due east attenuates the left channel to 0.0. Slightly east of
  1291          *  center attenuates the left channel a little, and the right channel
  1292          *  not at all. I think of this as occlusion by one's own head.  :)
  1293          *
  1294          *   ...so, we split our angle circle into four quadrants...
  1295          */
  1296         if (angle < 90) {
  1297             left = 255 - ((int) (255.0f * (((float) angle) / 89.0f)));
  1298         } else if (angle < 180) {
  1299             left = (int) (255.0f * (((float) (angle - 90)) / 89.0f));
  1300         } else if (angle < 270) {
  1301             right = 255 - ((int) (255.0f * (((float) (angle - 180)) / 89.0f)));
  1302         } else {
  1303             right = (int) (255.0f * (((float) (angle - 270)) / 89.0f));
  1304         }
  1305     }
  1306 
  1307     if (channels == 4 || channels == 6)
  1308     {
  1309         /*
  1310          *  An angle that's due north does not attenuate the center channel.
  1311          *  An angle in the first quadrant, 0-90, does not attenuate the RF.
  1312          *
  1313          *   ...so, we split our angle circle into 8 ...
  1314 	 *
  1315 	 *             CE
  1316 	 *             0
  1317 	 *     LF      |         RF
  1318 	 *             |
  1319 	 *  270<-------|----------->90
  1320 	 *             |
  1321 	 *     LR      |         RR
  1322 	 *            180
  1323 	 *   
  1324          */
  1325         if (angle < 45) {
  1326             left = ((int) (255.0f * (((float) (180 - angle)) / 179.0f)));
  1327             left_rear = 255 - ((int) (255.0f * (((float) (angle + 45)) / 89.0f)));
  1328             right_rear = 255 - ((int) (255.0f * (((float) (90 - angle)) / 179.0f)));
  1329         } else if (angle < 90) {
  1330             center = ((int) (255.0f * (((float) (225 - angle)) / 179.0f)));
  1331             left = ((int) (255.0f * (((float) (180 - angle)) / 179.0f)));
  1332             left_rear = 255 - ((int) (255.0f * (((float) (135 - angle)) / 89.0f)));
  1333             right_rear = ((int) (255.0f * (((float) (90 + angle)) / 179.0f)));
  1334         } else if (angle < 135) {
  1335             center = ((int) (255.0f * (((float) (225 - angle)) / 179.0f)));
  1336             left = 255 - ((int) (255.0f * (((float) (angle - 45)) / 89.0f)));
  1337             right = ((int) (255.0f * (((float) (270 - angle)) / 179.0f)));
  1338             left_rear = ((int) (255.0f * (((float) (angle)) / 179.0f)));
  1339         } else if (angle < 180) {
  1340             center = 255 - ((int) (255.0f * (((float) (angle - 90)) / 89.0f)));
  1341             left = 255 - ((int) (255.0f * (((float) (225 - angle)) / 89.0f)));
  1342             right = ((int) (255.0f * (((float) (270 - angle)) / 179.0f)));
  1343             left_rear = ((int) (255.0f * (((float) (angle)) / 179.0f)));
  1344         } else if (angle < 225) {
  1345             center = 255 - ((int) (255.0f * (((float) (270 - angle)) / 89.0f)));
  1346             left = ((int) (255.0f * (((float) (angle - 90)) / 179.0f)));
  1347             right = 255 - ((int) (255.0f * (((float) (angle - 135)) / 89.0f)));
  1348             right_rear = ((int) (255.0f * (((float) (360 - angle)) / 179.0f)));
  1349         } else if (angle < 270) {
  1350             center = ((int) (255.0f * (((float) (angle - 135)) / 179.0f)));
  1351             left = ((int) (255.0f * (((float) (angle - 90)) / 179.0f)));
  1352             right = 255 - ((int) (255.0f * (((float) (315 - angle)) / 89.0f)));
  1353             right_rear = ((int) (255.0f * (((float) (360 - angle)) / 179.0f)));
  1354         } else if (angle < 315) {
  1355             center = ((int) (255.0f * (((float) (angle - 135)) / 179.0f)));
  1356             right = ((int) (255.0f * (((float) (angle - 180)) / 179.0f)));
  1357             left_rear = ((int) (255.0f * (((float) (450 - angle)) / 179.0f)));
  1358             right_rear = 255 - ((int) (255.0f * (((float) (angle - 225)) / 89.0f)));
  1359         } else {
  1360             right = ((int) (255.0f * (((float) (angle - 180)) / 179.0f)));
  1361             left_rear = ((int) (255.0f * (((float) (450 - angle)) / 179.0f)));
  1362             right_rear = 255 - ((int) (255.0f * (((float) (405 - angle)) / 89.0f)));
  1363         }
  1364     }
  1365 
  1366     if (left < 0) left = 0; if (left > 255) left = 255;
  1367     if (right < 0) right = 0; if (right > 255) right = 255;
  1368     if (left_rear < 0) left_rear = 0; if (left_rear > 255) left_rear = 255;
  1369     if (right_rear < 0) right_rear = 0; if (right_rear > 255) right_rear = 255;
  1370     if (center < 0) center = 0; if (center > 255) center = 255;
  1371 
  1372     if (room_angle == 90) {
  1373     	speaker_amplitude[0] = (Uint8)left_rear;
  1374     	speaker_amplitude[1] = (Uint8)left;
  1375     	speaker_amplitude[2] = (Uint8)right_rear;
  1376     	speaker_amplitude[3] = (Uint8)right;
  1377     }
  1378     else if (room_angle == 180) {
  1379 	if (channels == 2) {
  1380     	    speaker_amplitude[0] = (Uint8)right;
  1381     	    speaker_amplitude[1] = (Uint8)left;
  1382 	}
  1383 	else {
  1384     	    speaker_amplitude[0] = (Uint8)right_rear;
  1385     	    speaker_amplitude[1] = (Uint8)left_rear;
  1386     	    speaker_amplitude[2] = (Uint8)right;
  1387     	    speaker_amplitude[3] = (Uint8)left;
  1388 	}
  1389     }
  1390     else if (room_angle == 270) {
  1391     	speaker_amplitude[0] = (Uint8)right;
  1392     	speaker_amplitude[1] = (Uint8)right_rear;
  1393     	speaker_amplitude[2] = (Uint8)left;
  1394     	speaker_amplitude[3] = (Uint8)left_rear;
  1395     }
  1396     else {
  1397     	speaker_amplitude[0] = (Uint8)left;
  1398     	speaker_amplitude[1] = (Uint8)right;
  1399     	speaker_amplitude[2] = (Uint8)left_rear;
  1400     	speaker_amplitude[3] = (Uint8)right_rear;
  1401     }
  1402     speaker_amplitude[4] = (Uint8)center;
  1403     speaker_amplitude[5] = 255;
  1404 }
  1405 
  1406 int Mix_SetPosition(int channel, Sint16 angle, Uint8 distance);
  1407 
  1408 int Mix_SetPanning(int channel, Uint8 left, Uint8 right)
  1409 {
  1410     Mix_EffectFunc_t f = NULL;
  1411     int channels;
  1412     Uint16 format;
  1413     position_args *args = NULL;
  1414     Mix_QuerySpec(NULL, &format, &channels);
  1415 
  1416     if (channels != 2 && channels != 4 && channels != 6)    /* it's a no-op; we call that successful. */
  1417         return(1);
  1418 
  1419     if (channels > 2) {
  1420     	/* left = 255 =>  angle = -90;  left = 0 => angle = +89 */
  1421     	int angle = (int)left;
  1422     	angle = 127 - angle;
  1423 	angle = -angle;
  1424     	angle = angle * 90 / 128; /* Make it larger for more effect? */
  1425 	return( Mix_SetPosition(channel, angle, 0) );
  1426     }
  1427 
  1428     f = get_position_effect_func(format, channels);
  1429     if (f == NULL)
  1430         return(0);
  1431 
  1432     args = get_position_arg(channel);
  1433     if (!args)
  1434         return(0);
  1435 
  1436         /* it's a no-op; unregister the effect, if it's registered. */
  1437     if ((args->distance_u8 == 255) && (left == 255) &&
  1438         (right == 255) && (args->in_use))
  1439     {
  1440         return(Mix_UnregisterEffect(channel, f));
  1441     }
  1442 
  1443     args->left_u8 = left;
  1444     args->left_f = ((float) left) / 255.0f;
  1445     args->right_u8 = right;
  1446     args->right_f = ((float) right) / 255.0f;
  1447     args->room_angle = 0;
  1448 
  1449     if (!args->in_use) {
  1450         args->in_use = 1;
  1451         return(Mix_RegisterEffect(channel, f, _Eff_PositionDone, (void *) args));
  1452     }
  1453 
  1454     return(1);
  1455 }
  1456 
  1457 
  1458 int Mix_SetDistance(int channel, Uint8 distance)
  1459 {
  1460     Mix_EffectFunc_t f = NULL;
  1461     Uint16 format;
  1462     position_args *args = NULL;
  1463     int channels;
  1464 
  1465     Mix_QuerySpec(NULL, &format, &channels);
  1466     f = get_position_effect_func(format, channels);
  1467     if (f == NULL)
  1468         return(0);
  1469 
  1470     args = get_position_arg(channel);
  1471     if (!args)
  1472         return(0);
  1473 
  1474     distance = 255 - distance;  /* flip it to our scale. */
  1475 
  1476         /* it's a no-op; unregister the effect, if it's registered. */
  1477     if ((distance == 255) && (args->left_u8 == 255) &&
  1478         (args->right_u8 == 255) && (args->in_use))
  1479     {
  1480         return(Mix_UnregisterEffect(channel, f));
  1481     }
  1482 
  1483     args->distance_u8 = distance;
  1484     args->distance_f = ((float) distance) / 255.0f;
  1485     if (!args->in_use) {
  1486         args->in_use = 1;
  1487         return(Mix_RegisterEffect(channel, f, _Eff_PositionDone, (void *) args));
  1488     }
  1489 
  1490     return(1);
  1491 }
  1492 
  1493 
  1494 int Mix_SetPosition(int channel, Sint16 angle, Uint8 distance)
  1495 {
  1496     Mix_EffectFunc_t f = NULL;
  1497     Uint16 format;
  1498     int channels;
  1499     position_args *args = NULL;
  1500     Sint16 room_angle;
  1501 
  1502     Mix_QuerySpec(NULL, &format, &channels);
  1503     f = get_position_effect_func(format, channels);
  1504     if (f == NULL)
  1505         return(0);
  1506 
  1507         /* unwind the angle...it'll be between 0 and 359. */
  1508     while (angle >= 360) angle -= 360;
  1509     while (angle < 0) angle += 360;
  1510 
  1511     args = get_position_arg(channel);
  1512     if (!args)
  1513         return(0);
  1514 
  1515         /* it's a no-op; unregister the effect, if it's registered. */
  1516     if ((!distance) && (!angle) && (args->in_use))
  1517         return(Mix_UnregisterEffect(channel, f));
  1518 
  1519     if (channels == 2)
  1520     {
  1521 	if (angle > 180)
  1522 		room_angle = 180; /* exchange left and right channels */
  1523 	else room_angle = 0;
  1524     }
  1525 
  1526     if (channels == 4 || channels == 6)
  1527     {
  1528 	if (angle > 315) room_angle = 0;
  1529 	else if (angle > 225) room_angle = 270;
  1530 	else if (angle > 135) room_angle = 180;
  1531 	else if (angle > 45) room_angle = 90;
  1532 	else room_angle = 0;
  1533     }
  1534 
  1535 
  1536     distance = 255 - distance;  /* flip it to scale Mix_SetDistance() uses. */
  1537 
  1538     set_amplitudes(channels, angle, room_angle);
  1539 
  1540     args->left_u8 = speaker_amplitude[0];
  1541     args->left_f = ((float) speaker_amplitude[0]) / 255.0f;
  1542     args->right_u8 = speaker_amplitude[1];
  1543     args->right_f = ((float) speaker_amplitude[1]) / 255.0f;
  1544     args->left_rear_u8 = speaker_amplitude[2];
  1545     args->left_rear_f = ((float) speaker_amplitude[2]) / 255.0f;
  1546     args->right_rear_u8 = speaker_amplitude[3];
  1547     args->right_rear_f = ((float) speaker_amplitude[3]) / 255.0f;
  1548     args->center_u8 = speaker_amplitude[4];
  1549     args->center_f = ((float) speaker_amplitude[4]) / 255.0f;
  1550     args->lfe_u8 = 255;
  1551     args->lfe_f = 255.0f;
  1552     args->distance_u8 = distance;
  1553     args->distance_f = ((float) distance) / 255.0f;
  1554     args->room_angle = room_angle;
  1555     if (!args->in_use) {
  1556         args->in_use = 1;
  1557         return(Mix_RegisterEffect(channel, f, _Eff_PositionDone, (void *) args));
  1558     }
  1559 
  1560     return(1);
  1561 }
  1562 
  1563 
  1564 /* end of effects_position.c ... */
  1565