effect_position.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 15 Jul 2007 15:43:02 +0000
changeset 359 83eaf245b7e7
parent 339 30996c5fd448
child 373 6271eafc6e70
permissions -rw-r--r--
On shutdown, deallocate global memory we might have allocated for effects.

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