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