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