effect_position.c
author Ryan C. Gordon <icculus@icculus.org>
Mon, 15 Jan 2007 16:14:04 +0000
changeset 339 30996c5fd448
parent 330 ffdb98273d59
child 359 83eaf245b7e7
permissions -rw-r--r--
Updated my email address everywhere I spewed it.
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
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);
icculus@330
   625
        Uint16 swaplr = (Uint16) ((Sint16) (((float) samplr * args->left_rear_f)
slouken@245
   626
                                    * args->distance_f) + 32768);
icculus@330
   627
        Uint16 swaprr = (Uint16) ((Sint16) (((float) samprr * args->right_rear_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);
icculus@330
   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);
icculus@330
   676
        Uint16 swaplr = (Uint16) ((Sint16) (((float) samplr * args->left_rear_f)
slouken@245
   677
                                    * args->distance_f) + 32768);
icculus@330
   678
        Uint16 swaprr = (Uint16) ((Sint16) (((float) samprr * args->right_rear_f)
slouken@245
   679
                                    * args->distance_f) + 32768);
icculus@330
   680
        Uint16 swapce = (Uint16) ((Sint16) (((float) sampce * args->center_f)
slouken@245
   681
                                    * args->distance_f) + 32768);
icculus@330
   682
        Uint16 swapwf = (Uint16) ((Sint16) (((float) sampwf * args->lfe_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@250
  1182
                        f = _Eff_position_u8_c4;
slouken@245
  1183
	    		break;
slouken@245
  1184
	    	    case 6:
slouken@250
  1185
                        f = _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@251
  1198
                        f = _Eff_position_s8_c4;
slouken@245
  1199
	    		break;
slouken@245
  1200
	    	    case 6:
slouken@251
  1201
                        f = _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) {
icculus@330
  1420
        /* left = right = 255 => angle = 0, to unregister effect as when channels = 2 */
slouken@245
  1421
    	/* left = 255 =>  angle = -90;  left = 0 => angle = +89 */
icculus@330
  1422
        int angle = 0;
icculus@330
  1423
        if ((left != 255) || (right != 255)) {
icculus@330
  1424
	    angle = (int)left;
icculus@330
  1425
    	    angle = 127 - angle;
icculus@330
  1426
	    angle = -angle;
icculus@330
  1427
    	    angle = angle * 90 / 128; /* Make it larger for more effect? */
icculus@330
  1428
        }
icculus@330
  1429
        return( Mix_SetPosition(channel, angle, 0) );
slouken@245
  1430
    }
slouken@245
  1431
slouken@245
  1432
    f = get_position_effect_func(format, channels);
slouken@113
  1433
    if (f == NULL)
slouken@113
  1434
        return(0);
slouken@113
  1435
slouken@113
  1436
    args = get_position_arg(channel);
slouken@113
  1437
    if (!args)
slouken@113
  1438
        return(0);
slouken@113
  1439
slouken@113
  1440
        /* it's a no-op; unregister the effect, if it's registered. */
icculus@330
  1441
    if ((args->distance_u8 == 255) && (left == 255) && (right == 255)) {
icculus@330
  1442
        if (args->in_use) {
icculus@330
  1443
            return(Mix_UnregisterEffect(channel, f));
icculus@330
  1444
        } else {
icculus@330
  1445
	  return(1);
icculus@330
  1446
        }
slouken@113
  1447
    }
slouken@113
  1448
slouken@113
  1449
    args->left_u8 = left;
slouken@245
  1450
    args->left_f = ((float) left) / 255.0f;
slouken@113
  1451
    args->right_u8 = right;
slouken@114
  1452
    args->right_f = ((float) right) / 255.0f;
slouken@245
  1453
    args->room_angle = 0;
slouken@245
  1454
slouken@113
  1455
    if (!args->in_use) {
slouken@113
  1456
        args->in_use = 1;
slouken@113
  1457
        return(Mix_RegisterEffect(channel, f, _Eff_PositionDone, (void *) args));
slouken@113
  1458
    }
slouken@113
  1459
slouken@113
  1460
    return(1);
slouken@113
  1461
}
slouken@113
  1462
slouken@113
  1463
slouken@113
  1464
int Mix_SetDistance(int channel, Uint8 distance)
slouken@113
  1465
{
slouken@113
  1466
    Mix_EffectFunc_t f = NULL;
slouken@113
  1467
    Uint16 format;
slouken@113
  1468
    position_args *args = NULL;
slouken@245
  1469
    int channels;
slouken@113
  1470
slouken@245
  1471
    Mix_QuerySpec(NULL, &format, &channels);
slouken@245
  1472
    f = get_position_effect_func(format, channels);
slouken@113
  1473
    if (f == NULL)
slouken@113
  1474
        return(0);
slouken@113
  1475
slouken@113
  1476
    args = get_position_arg(channel);
slouken@113
  1477
    if (!args)
slouken@113
  1478
        return(0);
slouken@113
  1479
slouken@113
  1480
    distance = 255 - distance;  /* flip it to our scale. */
slouken@113
  1481
slouken@113
  1482
        /* it's a no-op; unregister the effect, if it's registered. */
icculus@330
  1483
    if ((distance == 255) && (args->left_u8 == 255) && (args->right_u8 == 255)) {
icculus@330
  1484
        if (args->in_use) {
icculus@330
  1485
            return(Mix_UnregisterEffect(channel, f));
icculus@330
  1486
        } else {
icculus@330
  1487
            return(1);
icculus@330
  1488
        }
slouken@113
  1489
    }
slouken@113
  1490
slouken@113
  1491
    args->distance_u8 = distance;
slouken@114
  1492
    args->distance_f = ((float) distance) / 255.0f;
slouken@113
  1493
    if (!args->in_use) {
slouken@113
  1494
        args->in_use = 1;
slouken@113
  1495
        return(Mix_RegisterEffect(channel, f, _Eff_PositionDone, (void *) args));
slouken@113
  1496
    }
slouken@113
  1497
slouken@113
  1498
    return(1);
slouken@113
  1499
}
slouken@113
  1500
slouken@113
  1501
slouken@113
  1502
int Mix_SetPosition(int channel, Sint16 angle, Uint8 distance)
slouken@113
  1503
{
slouken@113
  1504
    Mix_EffectFunc_t f = NULL;
slouken@113
  1505
    Uint16 format;
slouken@113
  1506
    int channels;
slouken@113
  1507
    position_args *args = NULL;
slouken@245
  1508
    Sint16 room_angle;
slouken@113
  1509
slouken@113
  1510
    Mix_QuerySpec(NULL, &format, &channels);
slouken@245
  1511
    f = get_position_effect_func(format, channels);
slouken@113
  1512
    if (f == NULL)
slouken@113
  1513
        return(0);
slouken@113
  1514
slouken@113
  1515
        /* unwind the angle...it'll be between 0 and 359. */
slouken@113
  1516
    while (angle >= 360) angle -= 360;
slouken@113
  1517
    while (angle < 0) angle += 360;
slouken@113
  1518
slouken@113
  1519
    args = get_position_arg(channel);
slouken@113
  1520
    if (!args)
slouken@113
  1521
        return(0);
slouken@113
  1522
slouken@113
  1523
        /* it's a no-op; unregister the effect, if it's registered. */
icculus@330
  1524
    if ((!distance) && (!angle)) {
icculus@330
  1525
        if (args->in_use) {
icculus@330
  1526
            return(Mix_UnregisterEffect(channel, f));
icculus@330
  1527
        } else {
icculus@330
  1528
	  return(1);
icculus@330
  1529
	}
icculus@330
  1530
    }
slouken@113
  1531
slouken@113
  1532
    if (channels == 2)
slouken@113
  1533
    {
slouken@245
  1534
	if (angle > 180)
slouken@245
  1535
		room_angle = 180; /* exchange left and right channels */
slouken@245
  1536
	else room_angle = 0;
slouken@113
  1537
    }
slouken@113
  1538
slouken@245
  1539
    if (channels == 4 || channels == 6)
slouken@245
  1540
    {
slouken@245
  1541
	if (angle > 315) room_angle = 0;
slouken@245
  1542
	else if (angle > 225) room_angle = 270;
slouken@245
  1543
	else if (angle > 135) room_angle = 180;
slouken@245
  1544
	else if (angle > 45) room_angle = 90;
slouken@245
  1545
	else room_angle = 0;
slouken@245
  1546
    }
slouken@245
  1547
slouken@245
  1548
slouken@113
  1549
    distance = 255 - distance;  /* flip it to scale Mix_SetDistance() uses. */
slouken@113
  1550
slouken@245
  1551
    set_amplitudes(channels, angle, room_angle);
slouken@245
  1552
slouken@245
  1553
    args->left_u8 = speaker_amplitude[0];
slouken@245
  1554
    args->left_f = ((float) speaker_amplitude[0]) / 255.0f;
slouken@245
  1555
    args->right_u8 = speaker_amplitude[1];
slouken@245
  1556
    args->right_f = ((float) speaker_amplitude[1]) / 255.0f;
slouken@245
  1557
    args->left_rear_u8 = speaker_amplitude[2];
slouken@245
  1558
    args->left_rear_f = ((float) speaker_amplitude[2]) / 255.0f;
slouken@245
  1559
    args->right_rear_u8 = speaker_amplitude[3];
slouken@245
  1560
    args->right_rear_f = ((float) speaker_amplitude[3]) / 255.0f;
slouken@245
  1561
    args->center_u8 = speaker_amplitude[4];
slouken@245
  1562
    args->center_f = ((float) speaker_amplitude[4]) / 255.0f;
icculus@330
  1563
    args->lfe_u8 = speaker_amplitude[5];
icculus@330
  1564
    args->lfe_f = ((float) speaker_amplitude[5]) / 255.0f;
slouken@113
  1565
    args->distance_u8 = distance;
slouken@114
  1566
    args->distance_f = ((float) distance) / 255.0f;
slouken@245
  1567
    args->room_angle = room_angle;
slouken@113
  1568
    if (!args->in_use) {
slouken@113
  1569
        args->in_use = 1;
slouken@113
  1570
        return(Mix_RegisterEffect(channel, f, _Eff_PositionDone, (void *) args));
slouken@113
  1571
    }
slouken@113
  1572
slouken@113
  1573
    return(1);
slouken@113
  1574
}
slouken@113
  1575
slouken@113
  1576
slouken@113
  1577
/* end of effects_position.c ... */
slouken@113
  1578