effect_position.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 02 Jan 2016 22:12:31 -0800
changeset 712 7e59d684b070
parent 711 f40c5ac95b12
child 718 fb0562cc1559
permissions -rw-r--r--
Updated to version 2.0.1
     1 /*
     2   SDL_mixer:  An audio mixer library based on the SDL library
     3   Copyright (C) 1997-2016 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     SDL_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