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