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