effect_position.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 09 Sep 2017 12:14:24 -0700
changeset 733 bed6cd368f0d
parent 725 bdf7b8d20566
child 737 d3fa63933df2
permissions -rw-r--r--
Fixed spacing and added error messages for unsupported channels
     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             default:
  1209                 Mix_SetError("Unsupported audio channels");
  1210                 break;
  1211         }
  1212         break;
  1213 
  1214         case AUDIO_S8:
  1215         switch (channels) {
  1216             case 1:
  1217             case 2:
  1218                 f = (_Eff_build_volume_table_s8()) ? _Eff_position_table_s8 :
  1219                                                         _Eff_position_s8;
  1220                 break;
  1221             case 4:
  1222                 f = _Eff_position_s8_c4;
  1223                 break;
  1224             case 6:
  1225                 f = _Eff_position_s8_c6;
  1226                 break;
  1227             default:
  1228                 Mix_SetError("Unsupported audio channels");
  1229                 break;
  1230         }
  1231         break;
  1232 
  1233         case AUDIO_U16LSB:
  1234         switch (channels) {
  1235             case 1:
  1236             case 2:
  1237                 f = _Eff_position_u16lsb;
  1238                 break;
  1239             case 4:
  1240                 f = _Eff_position_u16lsb_c4;
  1241                 break;
  1242             case 6:
  1243                 f = _Eff_position_u16lsb_c6;
  1244                 break;
  1245             default:
  1246                 Mix_SetError("Unsupported audio channels");
  1247                 break;
  1248         }
  1249         break;
  1250 
  1251         case AUDIO_S16LSB:
  1252         switch (channels) {
  1253             case 1:
  1254             case 2:
  1255                 f = _Eff_position_s16lsb;
  1256                 break;
  1257             case 4:
  1258                 f = _Eff_position_s16lsb_c4;
  1259                 break;
  1260             case 6:
  1261                 f = _Eff_position_s16lsb_c6;
  1262                 break;
  1263             default:
  1264                 Mix_SetError("Unsupported audio channels");
  1265                 break;
  1266         }
  1267         break;
  1268 
  1269         case AUDIO_U16MSB:
  1270         switch (channels) {
  1271             case 1:
  1272             case 2:
  1273                 f = _Eff_position_u16msb;
  1274                 break;
  1275             case 4:
  1276                 f = _Eff_position_u16msb_c4;
  1277                 break;
  1278             case 6:
  1279                 f = _Eff_position_u16msb_c6;
  1280                 break;
  1281             default:
  1282                 Mix_SetError("Unsupported audio channels");
  1283                 break;
  1284         }
  1285         break;
  1286 
  1287         case AUDIO_S16MSB:
  1288         switch (channels) {
  1289             case 1:
  1290             case 2:
  1291                 f = _Eff_position_s16msb;
  1292                 break;
  1293             case 4:
  1294                 f = _Eff_position_s16msb_c4;
  1295                 break;
  1296             case 6:
  1297                 f = _Eff_position_s16msb_c6;
  1298                 break;
  1299             default:
  1300                 Mix_SetError("Unsupported audio channels");
  1301                 break;
  1302         }
  1303         break;
  1304 
  1305         default:
  1306             Mix_SetError("Unsupported audio format");
  1307             break;
  1308     }
  1309 
  1310     return(f);
  1311 }
  1312 
  1313 static Uint8 speaker_amplitude[6];
  1314 
  1315 static void set_amplitudes(int channels, int angle, int room_angle)
  1316 {
  1317     int left = 255, right = 255;
  1318     int left_rear = 255, right_rear = 255, center = 255;
  1319 
  1320     angle = SDL_abs(angle) % 360;  /* make angle between 0 and 359. */
  1321 
  1322     if (channels == 2)
  1323     {
  1324         /*
  1325          * We only attenuate by position if the angle falls on the far side
  1326          *  of center; That is, an angle that's due north would not attenuate
  1327          *  either channel. Due west attenuates the right channel to 0.0, and
  1328          *  due east attenuates the left channel to 0.0. Slightly east of
  1329          *  center attenuates the left channel a little, and the right channel
  1330          *  not at all. I think of this as occlusion by one's own head.  :)
  1331          *
  1332          *   ...so, we split our angle circle into four quadrants...
  1333          */
  1334         if (angle < 90) {
  1335             left = 255 - ((int) (255.0f * (((float) angle) / 89.0f)));
  1336         } else if (angle < 180) {
  1337             left = (int) (255.0f * (((float) (angle - 90)) / 89.0f));
  1338         } else if (angle < 270) {
  1339             right = 255 - ((int) (255.0f * (((float) (angle - 180)) / 89.0f)));
  1340         } else {
  1341             right = (int) (255.0f * (((float) (angle - 270)) / 89.0f));
  1342         }
  1343     }
  1344 
  1345     if (channels == 4 || channels == 6)
  1346     {
  1347         /*
  1348          *  An angle that's due north does not attenuate the center channel.
  1349          *  An angle in the first quadrant, 0-90, does not attenuate the RF.
  1350          *
  1351          *   ...so, we split our angle circle into 8 ...
  1352          *
  1353          *             CE
  1354          *             0
  1355          *     LF      |         RF
  1356          *             |
  1357          *  270<-------|----------->90
  1358          *             |
  1359          *     LR      |         RR
  1360          *            180
  1361          *
  1362          */
  1363         if (angle < 45) {
  1364             left = ((int) (255.0f * (((float) (180 - angle)) / 179.0f)));
  1365             left_rear = 255 - ((int) (255.0f * (((float) (angle + 45)) / 89.0f)));
  1366             right_rear = 255 - ((int) (255.0f * (((float) (90 - angle)) / 179.0f)));
  1367         } else if (angle < 90) {
  1368             center = ((int) (255.0f * (((float) (225 - angle)) / 179.0f)));
  1369             left = ((int) (255.0f * (((float) (180 - angle)) / 179.0f)));
  1370             left_rear = 255 - ((int) (255.0f * (((float) (135 - angle)) / 89.0f)));
  1371             right_rear = ((int) (255.0f * (((float) (90 + angle)) / 179.0f)));
  1372         } else if (angle < 135) {
  1373             center = ((int) (255.0f * (((float) (225 - angle)) / 179.0f)));
  1374             left = 255 - ((int) (255.0f * (((float) (angle - 45)) / 89.0f)));
  1375             right = ((int) (255.0f * (((float) (270 - angle)) / 179.0f)));
  1376             left_rear = ((int) (255.0f * (((float) (angle)) / 179.0f)));
  1377         } else if (angle < 180) {
  1378             center = 255 - ((int) (255.0f * (((float) (angle - 90)) / 89.0f)));
  1379             left = 255 - ((int) (255.0f * (((float) (225 - angle)) / 89.0f)));
  1380             right = ((int) (255.0f * (((float) (270 - angle)) / 179.0f)));
  1381             left_rear = ((int) (255.0f * (((float) (angle)) / 179.0f)));
  1382         } else if (angle < 225) {
  1383             center = 255 - ((int) (255.0f * (((float) (270 - angle)) / 89.0f)));
  1384             left = ((int) (255.0f * (((float) (angle - 90)) / 179.0f)));
  1385             right = 255 - ((int) (255.0f * (((float) (angle - 135)) / 89.0f)));
  1386             right_rear = ((int) (255.0f * (((float) (360 - angle)) / 179.0f)));
  1387         } else if (angle < 270) {
  1388             center = ((int) (255.0f * (((float) (angle - 135)) / 179.0f)));
  1389             left = ((int) (255.0f * (((float) (angle - 90)) / 179.0f)));
  1390             right = 255 - ((int) (255.0f * (((float) (315 - angle)) / 89.0f)));
  1391             right_rear = ((int) (255.0f * (((float) (360 - angle)) / 179.0f)));
  1392         } else if (angle < 315) {
  1393             center = ((int) (255.0f * (((float) (angle - 135)) / 179.0f)));
  1394             right = ((int) (255.0f * (((float) (angle - 180)) / 179.0f)));
  1395             left_rear = ((int) (255.0f * (((float) (450 - angle)) / 179.0f)));
  1396             right_rear = 255 - ((int) (255.0f * (((float) (angle - 225)) / 89.0f)));
  1397         } else {
  1398             right = ((int) (255.0f * (((float) (angle - 180)) / 179.0f)));
  1399             left_rear = ((int) (255.0f * (((float) (450 - angle)) / 179.0f)));
  1400             right_rear = 255 - ((int) (255.0f * (((float) (405 - angle)) / 89.0f)));
  1401         }
  1402     }
  1403 
  1404     if (left < 0) left = 0; if (left > 255) left = 255;
  1405     if (right < 0) right = 0; if (right > 255) right = 255;
  1406     if (left_rear < 0) left_rear = 0; if (left_rear > 255) left_rear = 255;
  1407     if (right_rear < 0) right_rear = 0; if (right_rear > 255) right_rear = 255;
  1408     if (center < 0) center = 0; if (center > 255) center = 255;
  1409 
  1410     if (room_angle == 90) {
  1411         speaker_amplitude[0] = (Uint8)left_rear;
  1412         speaker_amplitude[1] = (Uint8)left;
  1413         speaker_amplitude[2] = (Uint8)right_rear;
  1414         speaker_amplitude[3] = (Uint8)right;
  1415     }
  1416     else if (room_angle == 180) {
  1417     if (channels == 2) {
  1418             speaker_amplitude[0] = (Uint8)right;
  1419             speaker_amplitude[1] = (Uint8)left;
  1420     }
  1421     else {
  1422             speaker_amplitude[0] = (Uint8)right_rear;
  1423             speaker_amplitude[1] = (Uint8)left_rear;
  1424             speaker_amplitude[2] = (Uint8)right;
  1425             speaker_amplitude[3] = (Uint8)left;
  1426     }
  1427     }
  1428     else if (room_angle == 270) {
  1429         speaker_amplitude[0] = (Uint8)right;
  1430         speaker_amplitude[1] = (Uint8)right_rear;
  1431         speaker_amplitude[2] = (Uint8)left;
  1432         speaker_amplitude[3] = (Uint8)left_rear;
  1433     }
  1434     else {
  1435         speaker_amplitude[0] = (Uint8)left;
  1436         speaker_amplitude[1] = (Uint8)right;
  1437         speaker_amplitude[2] = (Uint8)left_rear;
  1438         speaker_amplitude[3] = (Uint8)right_rear;
  1439     }
  1440     speaker_amplitude[4] = (Uint8)center;
  1441     speaker_amplitude[5] = 255;
  1442 }
  1443 
  1444 int Mix_SetPosition(int channel, Sint16 angle, Uint8 distance);
  1445 
  1446 int Mix_SetPanning(int channel, Uint8 left, Uint8 right)
  1447 {
  1448     Mix_EffectFunc_t f = NULL;
  1449     int channels;
  1450     Uint16 format;
  1451     position_args *args = NULL;
  1452     int retval = 1;
  1453 
  1454     Mix_QuerySpec(NULL, &format, &channels);
  1455 
  1456     if (channels != 2 && channels != 4 && channels != 6)    /* it's a no-op; we call that successful. */
  1457         return(1);
  1458 
  1459     if (channels > 2) {
  1460         /* left = right = 255 => angle = 0, to unregister effect as when channels = 2 */
  1461         /* left = 255 =>  angle = -90;  left = 0 => angle = +89 */
  1462         int angle = 0;
  1463         if ((left != 255) || (right != 255)) {
  1464         angle = (int)left;
  1465             angle = 127 - angle;
  1466         angle = -angle;
  1467             angle = angle * 90 / 128; /* Make it larger for more effect? */
  1468         }
  1469         return( Mix_SetPosition(channel, angle, 0) );
  1470     }
  1471 
  1472     f = get_position_effect_func(format, channels);
  1473     if (f == NULL)
  1474         return(0);
  1475 
  1476     Mix_LockAudio();
  1477     args = get_position_arg(channel);
  1478     if (!args) {
  1479         Mix_UnlockAudio();
  1480         return(0);
  1481     }
  1482 
  1483         /* it's a no-op; unregister the effect, if it's registered. */
  1484     if ((args->distance_u8 == 255) && (left == 255) && (right == 255)) {
  1485         if (args->in_use) {
  1486             retval = _Mix_UnregisterEffect_locked(channel, f);
  1487             Mix_UnlockAudio();
  1488             return(retval);
  1489         } else {
  1490             Mix_UnlockAudio();
  1491             return(1);
  1492         }
  1493     }
  1494 
  1495     args->left_u8 = left;
  1496     args->left_f = ((float) left) / 255.0f;
  1497     args->right_u8 = right;
  1498     args->right_f = ((float) right) / 255.0f;
  1499     args->room_angle = 0;
  1500 
  1501     if (!args->in_use) {
  1502         args->in_use = 1;
  1503         retval=_Mix_RegisterEffect_locked(channel, f, _Eff_PositionDone, (void*)args);
  1504     }
  1505 
  1506     Mix_UnlockAudio();
  1507     return(retval);
  1508 }
  1509 
  1510 
  1511 int Mix_SetDistance(int channel, Uint8 distance)
  1512 {
  1513     Mix_EffectFunc_t f = NULL;
  1514     Uint16 format;
  1515     position_args *args = NULL;
  1516     int channels;
  1517     int retval = 1;
  1518 
  1519     Mix_QuerySpec(NULL, &format, &channels);
  1520     f = get_position_effect_func(format, channels);
  1521     if (f == NULL)
  1522         return(0);
  1523 
  1524     Mix_LockAudio();
  1525     args = get_position_arg(channel);
  1526     if (!args) {
  1527         Mix_UnlockAudio();
  1528         return(0);
  1529     }
  1530 
  1531     distance = 255 - distance;  /* flip it to our scale. */
  1532 
  1533         /* it's a no-op; unregister the effect, if it's registered. */
  1534     if ((distance == 255) && (args->left_u8 == 255) && (args->right_u8 == 255)) {
  1535         if (args->in_use) {
  1536             retval = _Mix_UnregisterEffect_locked(channel, f);
  1537             Mix_UnlockAudio();
  1538             return(retval);
  1539         } else {
  1540             Mix_UnlockAudio();
  1541             return(1);
  1542         }
  1543     }
  1544 
  1545     args->distance_u8 = distance;
  1546     args->distance_f = ((float) distance) / 255.0f;
  1547     if (!args->in_use) {
  1548         args->in_use = 1;
  1549         retval = _Mix_RegisterEffect_locked(channel, f, _Eff_PositionDone, (void *) args);
  1550     }
  1551 
  1552     Mix_UnlockAudio();
  1553     return(retval);
  1554 }
  1555 
  1556 
  1557 int Mix_SetPosition(int channel, Sint16 angle, Uint8 distance)
  1558 {
  1559     Mix_EffectFunc_t f = NULL;
  1560     Uint16 format;
  1561     int channels;
  1562     position_args *args = NULL;
  1563     Sint16 room_angle = 0;
  1564     int retval = 1;
  1565 
  1566     Mix_QuerySpec(NULL, &format, &channels);
  1567     f = get_position_effect_func(format, channels);
  1568     if (f == NULL)
  1569         return(0);
  1570 
  1571     angle = SDL_abs(angle) % 360;  /* make angle between 0 and 359. */
  1572 
  1573     Mix_LockAudio();
  1574     args = get_position_arg(channel);
  1575     if (!args) {
  1576         Mix_UnlockAudio();
  1577         return(0);
  1578     }
  1579 
  1580         /* it's a no-op; unregister the effect, if it's registered. */
  1581     if ((!distance) && (!angle)) {
  1582         if (args->in_use) {
  1583             retval = _Mix_UnregisterEffect_locked(channel, f);
  1584             Mix_UnlockAudio();
  1585             return(retval);
  1586         } else {
  1587             Mix_UnlockAudio();
  1588             return(1);
  1589         }
  1590     }
  1591 
  1592     if (channels == 2)
  1593     {
  1594     if (angle > 180)
  1595         room_angle = 180; /* exchange left and right channels */
  1596     else room_angle = 0;
  1597     }
  1598 
  1599     if (channels == 4 || channels == 6)
  1600     {
  1601     if (angle > 315) room_angle = 0;
  1602     else if (angle > 225) room_angle = 270;
  1603     else if (angle > 135) room_angle = 180;
  1604     else if (angle > 45) room_angle = 90;
  1605     else room_angle = 0;
  1606     }
  1607 
  1608 
  1609     distance = 255 - distance;  /* flip it to scale Mix_SetDistance() uses. */
  1610 
  1611     set_amplitudes(channels, angle, room_angle);
  1612 
  1613     args->left_u8 = speaker_amplitude[0];
  1614     args->left_f = ((float) speaker_amplitude[0]) / 255.0f;
  1615     args->right_u8 = speaker_amplitude[1];
  1616     args->right_f = ((float) speaker_amplitude[1]) / 255.0f;
  1617     args->left_rear_u8 = speaker_amplitude[2];
  1618     args->left_rear_f = ((float) speaker_amplitude[2]) / 255.0f;
  1619     args->right_rear_u8 = speaker_amplitude[3];
  1620     args->right_rear_f = ((float) speaker_amplitude[3]) / 255.0f;
  1621     args->center_u8 = speaker_amplitude[4];
  1622     args->center_f = ((float) speaker_amplitude[4]) / 255.0f;
  1623     args->lfe_u8 = speaker_amplitude[5];
  1624     args->lfe_f = ((float) speaker_amplitude[5]) / 255.0f;
  1625     args->distance_u8 = distance;
  1626     args->distance_f = ((float) distance) / 255.0f;
  1627     args->room_angle = room_angle;
  1628     if (!args->in_use) {
  1629         args->in_use = 1;
  1630         retval = _Mix_RegisterEffect_locked(channel, f, _Eff_PositionDone, (void *) args);
  1631     }
  1632 
  1633     Mix_UnlockAudio();
  1634     return(retval);
  1635 }
  1636 
  1637 
  1638 /* end of effects_position.c ... */
  1639