effect_position.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 21 Aug 2004 12:27:02 +0000
changeset 245 63b3650714de
parent 241 503416fca921
child 250 cf822f8dc1bf
permissions -rw-r--r--
Here are patches for SDL12 and SDL_mixer for 4 or 6 channel
surround sound on Linux using the Alsa driver. To use them, naturally
you need a sound card that will do 4 or 6 channels and probably also a
recent version of the Alsa drivers and library. Since the only SDL
output driver that knows about surround sound is the Alsa driver,
you���ll want to choose it, using:

export SDL_AUDIODRIVER=alsa

There are no syntactic changes to the programming API. No new
library calls, no differences in arguments.

There are two semantic changes:

(1) For library calls with number of channels as an argument, formerly
you could use only 1 or 2 for the number of channels. Now you
can also use 4 or 6.

(2) The two "left" and "right" arguments to Mix_SetPanning, for the
case of 4 or 6 channels, no longer simply control the volumes of
the left and right channels. Now the "left" argument is converted
to an angle and Mix_SetPosition is called, and the "right" argu-
ment is ignored.

With two exceptions, so far as I know, the modified SDL12 and
SDL_mixer work the same way as the original versions, when opened for
1 or 2 channel output. The two exceptions are bugs which I fixed.
Well, the first, anyway, is a bug for sure. When rate conversions up
or down by a factor of two are applied (in src/audio/SDL_audiocvt.c),
streams with different numbers of channels (that is, mono and stereo)
are treated the same way: either each sample is copied or every other
sample is omitted. This is ok for mono, but for stereo, it is frames
that should be copied or omitted, where by "frame" I mean a portion of
the stream containing one sample for each channel. (In the SDL source,
confusingly, sometimes frames are called "samples".) So for these
rate conversions, stereo streams have to be treated differently, and
they are, in my modified version.

The other problem that might be characterized as a bug arises
when SDL_mixer is passed a multichannel chunk which does not have an
integral number of frames. Due to the way the effect_position code
loops over frames, when the chunk ends with a partial frame, memory
outside the chunk buffer will be accessed. In the case of stereo,
it���s possible that because malloc may give more memory than requested,
this potential problem never actually causes a segment fault. I don���t
know. For 6 channel chunks, I do know, and it does cause segment
faults.


If SDL_mixer is passed defective chunks and this causes a segment
fault, arguably, that���s not a bug in SDL_mixer. Still, whether or not
it counts as a bug, it���s easy to protect against, so why not? I added
code in mixer.c to discard any partial frame at the end of a chunk.

Then what about when SDL or SDL_mixer is opened for 4 or 6 chan-
nel output? What happens with the parts of the current library
designed for stereo? I don���t know whether I���ve covered all the bases,
but I���ve tried:

(1) For playing 2 channel waves, or other cases where SDL knows it has
to match up a 2 channel source with a 4 or 6 channel output, I���ve
added code in SDL_audiocvt.c to make the necessary conversions.

(2) For playing midis using timidity, I���ve converted timidity to do 4
or 6 channel output, upon request.

(3) For playing mods using mikmod, I put ad hoc code in music.c to
convert the stereo output that mikmod produces to 4 or 6 chan-
nels. Obviously it would be better to change the mikmod code to
mix down into 4 or 6 channels, but I have a hard time following
the code in mikmod, so I didn���t do that.

(4) For playing mp3s, I put ad hoc code in smpeg to copy channels in
the case when 4 or 6 channel output is needed.

(5) There seems to be no problem with .ogg files - stereo .oggs can be
up converted as .wavs are.

(6) The effect_position code in SDL_mixer is now generalized to in-
clude the cases of 4 and 6 channel streams.

I���ve done a very limited amount of compatibility testing for some
of the games using SDL I happen to have. For details, see the file
TESTS.

I���ve put into a separate archive, Surround-SDL-testfiles.tgz, a
couple of 6 channel wave files for testing and a 6 channel ogg file.
If you have the right hardware and version of Alsa, you should be able
to play the wave files with the Alsa utility aplay (and hear all
channels, except maybe lfe, for chan-id.wav, since it���s rather faint).
Don���t expect aplay to give good sound, though. There���s something
wrong with the current version of aplay.

The canyon.ogg file is to test loading of 6 channel oggs. After
patching and compiling, you can play it with playmus. (My version of
ogg123 will not play it, and I had to patch mplayer to get it to play
6 channel oggs.)

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