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