diff options
Diffstat (limited to 'apps/plugins/sdl/SDL_mixer/effect_position.c')
-rw-r--r-- | apps/plugins/sdl/SDL_mixer/effect_position.c | 1615 |
1 files changed, 1615 insertions, 0 deletions
diff --git a/apps/plugins/sdl/SDL_mixer/effect_position.c b/apps/plugins/sdl/SDL_mixer/effect_position.c new file mode 100644 index 0000000000..e0b467b12f --- /dev/null +++ b/apps/plugins/sdl/SDL_mixer/effect_position.c @@ -0,0 +1,1615 @@ +/* + SDL_mixer: An audio mixer library based on the SDL library + Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + This file by Ryan C. Gordon (icculus@icculus.org) + + These are some internally supported special effects that use SDL_mixer's + effect callback API. They are meant for speed over quality. :) +*/ + +/* $Id$ */ + +#include "SDL.h" +#include "SDL_mixer.h" +#include "SDL_endian.h" + +#define __MIX_INTERNAL_EFFECT__ +#include "effects_internal.h" + +/* profile code: + #include <sys/time.h> + #include <unistd.h> + struct timeval tv1; + struct timeval tv2; + + gettimeofday(&tv1, NULL); + + ... do your thing here ... + + gettimeofday(&tv2, NULL); + printf("%ld\n", tv2.tv_usec - tv1.tv_usec); +*/ + + +/* + * Positional effects...panning, distance attenuation, etc. + */ + +typedef struct _Eff_positionargs +{ + volatile float left_f; + volatile float right_f; + volatile Uint8 left_u8; + volatile Uint8 right_u8; + volatile float left_rear_f; + volatile float right_rear_f; + volatile float center_f; + volatile float lfe_f; + volatile Uint8 left_rear_u8; + volatile Uint8 right_rear_u8; + volatile Uint8 center_u8; + volatile Uint8 lfe_u8; + volatile float distance_f; + volatile Uint8 distance_u8; + volatile Sint16 room_angle; + volatile int in_use; + volatile int channels; +} position_args; + +static position_args **pos_args_array = NULL; +static position_args *pos_args_global = NULL; +static int position_channels = 0; + +void _Eff_PositionDeinit(void) +{ + int i; + for (i = 0; i < position_channels; i++) { + SDL_free(pos_args_array[i]); + } + + position_channels = 0; + + SDL_free(pos_args_global); + pos_args_global = NULL; + SDL_free(pos_args_array); + pos_args_array = NULL; +} + + +/* This just frees up the callback-specific data. */ +static void _Eff_PositionDone(int channel, void *udata) +{ + if (channel < 0) { + if (pos_args_global != NULL) { + SDL_free(pos_args_global); + pos_args_global = NULL; + } + } + + else if (pos_args_array[channel] != NULL) { + SDL_free(pos_args_array[channel]); + pos_args_array[channel] = NULL; + } +} + + +static void _Eff_position_u8(int chan, void *stream, int len, void *udata) +{ + volatile position_args *args = (volatile position_args *) udata; + Uint8 *ptr = (Uint8 *) stream; + int i; + + /* + * if there's only a mono channnel (the only way we wouldn't have + * a len divisible by 2 here), then left_f and right_f are always + * 1.0, and are therefore throwaways. + */ + if (len % sizeof (Uint16) != 0) { + *ptr = (Uint8) (((float) *ptr) * args->distance_f); + ptr++; + len--; + } + + if (args->room_angle == 180) + for (i = 0; i < len; i += sizeof (Uint8) * 2) { + /* must adjust the sample so that 0 is the center */ + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_f) * args->distance_f) + 128); + ptr++; + } + else for (i = 0; i < len; i += sizeof (Uint8) * 2) { + /* must adjust the sample so that 0 is the center */ + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_f) * args->distance_f) + 128); + ptr++; + } +} +static void _Eff_position_u8_c4(int chan, void *stream, int len, void *udata) +{ + volatile position_args *args = (volatile position_args *) udata; + Uint8 *ptr = (Uint8 *) stream; + int i; + + /* + * if there's only a mono channnel (the only way we wouldn't have + * a len divisible by 2 here), then left_f and right_f are always + * 1.0, and are therefore throwaways. + */ + if (len % sizeof (Uint16) != 0) { + *ptr = (Uint8) (((float) *ptr) * args->distance_f); + ptr++; + len--; + } + + if (args->room_angle == 0) + for (i = 0; i < len; i += sizeof (Uint8) * 6) { + /* must adjust the sample so that 0 is the center */ + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_rear_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_rear_f) * args->distance_f) + 128); + ptr++; + } + else if (args->room_angle == 90) + for (i = 0; i < len; i += sizeof (Uint8) * 6) { + /* must adjust the sample so that 0 is the center */ + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_rear_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_rear_f) * args->distance_f) + 128); + ptr++; + } + else if (args->room_angle == 180) + for (i = 0; i < len; i += sizeof (Uint8) * 6) { + /* must adjust the sample so that 0 is the center */ + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_rear_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_rear_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_f) * args->distance_f) + 128); + ptr++; + } + else if (args->room_angle == 270) + for (i = 0; i < len; i += sizeof (Uint8) * 6) { + /* must adjust the sample so that 0 is the center */ + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_rear_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_rear_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_f) * args->distance_f) + 128); + ptr++; + } +} + + +static void _Eff_position_u8_c6(int chan, void *stream, int len, void *udata) +{ + volatile position_args *args = (volatile position_args *) udata; + Uint8 *ptr = (Uint8 *) stream; + int i; + + /* + * if there's only a mono channnel (the only way we wouldn't have + * a len divisible by 2 here), then left_f and right_f are always + * 1.0, and are therefore throwaways. + */ + if (len % sizeof (Uint16) != 0) { + *ptr = (Uint8) (((float) *ptr) * args->distance_f); + ptr++; + len--; + } + + if (args->room_angle == 0) + for (i = 0; i < len; i += sizeof (Uint8) * 6) { + /* must adjust the sample so that 0 is the center */ + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_rear_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_rear_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->center_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->lfe_f) * args->distance_f) + 128); + ptr++; + } + else if (args->room_angle == 90) + for (i = 0; i < len; i += sizeof (Uint8) * 6) { + /* must adjust the sample so that 0 is the center */ + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_rear_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_rear_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_rear_f) * args->distance_f/2) + 128) + + (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_f) * args->distance_f/2) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->lfe_f) * args->distance_f) + 128); + ptr++; + } + else if (args->room_angle == 180) + for (i = 0; i < len; i += sizeof (Uint8) * 6) { + /* must adjust the sample so that 0 is the center */ + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_rear_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_rear_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_rear_f) * args->distance_f/2) + 128) + + (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_rear_f) * args->distance_f/2) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->lfe_f) * args->distance_f) + 128); + ptr++; + } + else if (args->room_angle == 270) + for (i = 0; i < len; i += sizeof (Uint8) * 6) { + /* must adjust the sample so that 0 is the center */ + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_rear_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_rear_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->right_f) * args->distance_f) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_f) * args->distance_f/2) + 128) + + (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->left_rear_f) * args->distance_f/2) + 128); + ptr++; + *ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) + * args->lfe_f) * args->distance_f) + 128); + ptr++; + } +} + + +/* + * This one runs about 10.1 times faster than the non-table version, with + * no loss in quality. It does, however, require 64k of memory for the + * lookup table. Also, this will only update position information once per + * call; the non-table version always checks the arguments for each sample, + * in case the user has called Mix_SetPanning() or whatnot again while this + * callback is running. + */ +static void _Eff_position_table_u8(int chan, void *stream, int len, void *udata) +{ + volatile position_args *args = (volatile position_args *) udata; + Uint8 *ptr = (Uint8 *) stream; + Uint32 *p; + int i; + Uint8 *l = ((Uint8 *) _Eff_volume_table) + (256 * args->left_u8); + Uint8 *r = ((Uint8 *) _Eff_volume_table) + (256 * args->right_u8); + Uint8 *d = ((Uint8 *) _Eff_volume_table) + (256 * args->distance_u8); + + if (args->room_angle == 180) { + Uint8 *temp = l; + l = r; + r = temp; + } + /* + * if there's only a mono channnel, then l[] and r[] are always + * volume 255, and are therefore throwaways. Still, we have to + * be sure not to overrun the audio buffer... + */ + while (len % sizeof (Uint32) != 0) { + *ptr = d[l[*ptr]]; + ptr++; + if (args->channels > 1) { + *ptr = d[r[*ptr]]; + ptr++; + } + len -= args->channels; + } + + p = (Uint32 *) ptr; + + for (i = 0; i < len; i += sizeof (Uint32)) { +#if (SDL_BYTEORDER == SDL_BIG_ENDIAN) + *p = (d[l[(*p & 0xFF000000) >> 24]] << 24) | + (d[r[(*p & 0x00FF0000) >> 16]] << 16) | + (d[l[(*p & 0x0000FF00) >> 8]] << 8) | + (d[r[(*p & 0x000000FF) ]] ) ; +#else + *p = (d[r[(*p & 0xFF000000) >> 24]] << 24) | + (d[l[(*p & 0x00FF0000) >> 16]] << 16) | + (d[r[(*p & 0x0000FF00) >> 8]] << 8) | + (d[l[(*p & 0x000000FF) ]] ) ; +#endif + ++p; + } +} + + +static void _Eff_position_s8(int chan, void *stream, int len, void *udata) +{ + volatile position_args *args = (volatile position_args *) udata; + Sint8 *ptr = (Sint8 *) stream; + int i; + + /* + * if there's only a mono channnel (the only way we wouldn't have + * a len divisible by 2 here), then left_f and right_f are always + * 1.0, and are therefore throwaways. + */ + if (len % sizeof (Sint16) != 0) { + *ptr = (Sint8) (((float) *ptr) * args->distance_f); + ptr++; + len--; + } + + if (args->room_angle == 180) + for (i = 0; i < len; i += sizeof (Sint8) * 2) { + *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); + ptr++; + *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); + ptr++; + } + else + for (i = 0; i < len; i += sizeof (Sint8) * 2) { + *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); + ptr++; + *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); + ptr++; + } +} +static void _Eff_position_s8_c4(int chan, void *stream, int len, void *udata) +{ + volatile position_args *args = (volatile position_args *) udata; + Sint8 *ptr = (Sint8 *) stream; + int i; + + /* + * if there's only a mono channnel (the only way we wouldn't have + * a len divisible by 2 here), then left_f and right_f are always + * 1.0, and are therefore throwaways. + */ + if (len % sizeof (Sint16) != 0) { + *ptr = (Sint8) (((float) *ptr) * args->distance_f); + ptr++; + len--; + } + + for (i = 0; i < len; i += sizeof (Sint8) * 4) { + switch (args->room_angle) { + case 0: + *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++; + break; + case 90: + *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++; + break; + case 180: + *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++; + break; + case 270: + *ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++; + break; + } + } +} +static void _Eff_position_s8_c6(int chan, void *stream, int len, void *udata) +{ + volatile position_args *args = (volatile position_args *) udata; + Sint8 *ptr = (Sint8 *) stream; + int i; + + /* + * if there's only a mono channnel (the only way we wouldn't have + * a len divisible by 2 here), then left_f and right_f are always + * 1.0, and are therefore throwaways. + */ + if (len % sizeof (Sint16) != 0) { + *ptr = (Sint8) (((float) *ptr) * args->distance_f); + ptr++; + len--; + } + + for (i = 0; i < len; i += sizeof (Sint8) * 6) { + switch (args->room_angle) { + case 0: + *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->center_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->lfe_f) * args->distance_f); ptr++; + break; + case 90: + *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f / 2) + + (Sint8)((((float) *ptr) * args->right_f) * args->distance_f / 2); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->lfe_f) * args->distance_f); ptr++; + break; + case 180: + *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f / 2) + + (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f / 2); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->lfe_f) * args->distance_f); ptr++; + break; + case 270: + *ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f / 2) + + (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f / 2); ptr++; + *ptr = (Sint8)((((float) *ptr) * args->lfe_f) * args->distance_f); ptr++; + break; + } + } +} + + +/* + * This one runs about 10.1 times faster than the non-table version, with + * no loss in quality. It does, however, require 64k of memory for the + * lookup table. Also, this will only update position information once per + * call; the non-table version always checks the arguments for each sample, + * in case the user has called Mix_SetPanning() or whatnot again while this + * callback is running. + */ +static void _Eff_position_table_s8(int chan, void *stream, int len, void *udata) +{ + volatile position_args *args = (volatile position_args *) udata; + Sint8 *ptr = (Sint8 *) stream; + Uint32 *p; + int i; + Sint8 *l = ((Sint8 *) _Eff_volume_table) + (256 * args->left_u8); + Sint8 *r = ((Sint8 *) _Eff_volume_table) + (256 * args->right_u8); + Sint8 *d = ((Sint8 *) _Eff_volume_table) + (256 * args->distance_u8); + + if (args->room_angle == 180) { + Sint8 *temp = l; + l = r; + r = temp; + } + + + while (len % sizeof (Uint32) != 0) { + *ptr = d[l[*ptr]]; + ptr++; + if (args->channels > 1) { + *ptr = d[r[*ptr]]; + ptr++; + } + len -= args->channels; + } + + p = (Uint32 *) ptr; + + for (i = 0; i < len; i += sizeof (Uint32)) { +#if (SDL_BYTEORDER == SDL_BIG_ENDIAN) + *p = (d[l[((Sint16)(Sint8)((*p & 0xFF000000) >> 24))+128]] << 24) | + (d[r[((Sint16)(Sint8)((*p & 0x00FF0000) >> 16))+128]] << 16) | + (d[l[((Sint16)(Sint8)((*p & 0x0000FF00) >> 8))+128]] << 8) | + (d[r[((Sint16)(Sint8)((*p & 0x000000FF) ))+128]] ) ; +#else + *p = (d[r[((Sint16)(Sint8)((*p & 0xFF000000) >> 24))+128]] << 24) | + (d[l[((Sint16)(Sint8)((*p & 0x00FF0000) >> 16))+128]] << 16) | + (d[r[((Sint16)(Sint8)((*p & 0x0000FF00) >> 8))+128]] << 8) | + (d[l[((Sint16)(Sint8)((*p & 0x000000FF) ))+128]] ) ; +#endif + ++p; + } + + +} + + +/* !!! FIXME : Optimize the code for 16-bit samples? */ + +static void _Eff_position_u16lsb(int chan, void *stream, int len, void *udata) +{ + volatile position_args *args = (volatile position_args *) udata; + Uint16 *ptr = (Uint16 *) stream; + int i; + + for (i = 0; i < len; i += sizeof (Uint16) * 2) { + Sint16 sampl = (Sint16) (SDL_SwapLE16(*(ptr+0)) - 32768); + Sint16 sampr = (Sint16) (SDL_SwapLE16(*(ptr+1)) - 32768); + + Uint16 swapl = (Uint16) ((Sint16) (((float) sampl * args->left_f) + * args->distance_f) + 32768); + Uint16 swapr = (Uint16) ((Sint16) (((float) sampr * args->right_f) + * args->distance_f) + 32768); + + if (args->room_angle == 180) { + *(ptr++) = (Uint16) SDL_SwapLE16(swapr); + *(ptr++) = (Uint16) SDL_SwapLE16(swapl); + } + else { + *(ptr++) = (Uint16) SDL_SwapLE16(swapl); + *(ptr++) = (Uint16) SDL_SwapLE16(swapr); + } + } +} +static void _Eff_position_u16lsb_c4(int chan, void *stream, int len, void *udata) +{ + volatile position_args *args = (volatile position_args *) udata; + Uint16 *ptr = (Uint16 *) stream; + int i; + + for (i = 0; i < len; i += sizeof (Uint16) * 4) { + Sint16 sampl = (Sint16) (SDL_SwapLE16(*(ptr+0)) - 32768); + Sint16 sampr = (Sint16) (SDL_SwapLE16(*(ptr+1)) - 32768); + Sint16 samplr = (Sint16) (SDL_SwapLE16(*(ptr+2)) - 32768); + Sint16 samprr = (Sint16) (SDL_SwapLE16(*(ptr+3)) - 32768); + + Uint16 swapl = (Uint16) ((Sint16) (((float) sampl * args->left_f) + * args->distance_f) + 32768); + Uint16 swapr = (Uint16) ((Sint16) (((float) sampr * args->right_f) + * args->distance_f) + 32768); + Uint16 swaplr = (Uint16) ((Sint16) (((float) samplr * args->left_rear_f) + * args->distance_f) + 32768); + Uint16 swaprr = (Uint16) ((Sint16) (((float) samprr * args->right_rear_f) + * args->distance_f) + 32768); + + switch (args->room_angle) { + case 0: + *(ptr++) = (Uint16) SDL_SwapLE16(swapl); + *(ptr++) = (Uint16) SDL_SwapLE16(swapr); + *(ptr++) = (Uint16) SDL_SwapLE16(swaplr); + *(ptr++) = (Uint16) SDL_SwapLE16(swaprr); + break; + case 90: + *(ptr++) = (Uint16) SDL_SwapLE16(swapr); + *(ptr++) = (Uint16) SDL_SwapLE16(swaprr); + *(ptr++) = (Uint16) SDL_SwapLE16(swapl); + *(ptr++) = (Uint16) SDL_SwapLE16(swaplr); + break; + case 180: + *(ptr++) = (Uint16) SDL_SwapLE16(swaprr); + *(ptr++) = (Uint16) SDL_SwapLE16(swaplr); + *(ptr++) = (Uint16) SDL_SwapLE16(swapr); + *(ptr++) = (Uint16) SDL_SwapLE16(swapl); + break; + case 270: + *(ptr++) = (Uint16) SDL_SwapLE16(swaplr); + *(ptr++) = (Uint16) SDL_SwapLE16(swapl); + *(ptr++) = (Uint16) SDL_SwapLE16(swaprr); + *(ptr++) = (Uint16) SDL_SwapLE16(swapr); + break; + } + } +} +static void _Eff_position_u16lsb_c6(int chan, void *stream, int len, void *udata) +{ + volatile position_args *args = (volatile position_args *) udata; + Uint16 *ptr = (Uint16 *) stream; + int i; + + for (i = 0; i < len; i += sizeof (Uint16) * 6) { + Sint16 sampl = (Sint16) (SDL_SwapLE16(*(ptr+0)) - 32768); + Sint16 sampr = (Sint16) (SDL_SwapLE16(*(ptr+1)) - 32768); + Sint16 samplr = (Sint16) (SDL_SwapLE16(*(ptr+2)) - 32768); + Sint16 samprr = (Sint16) (SDL_SwapLE16(*(ptr+3)) - 32768); + Sint16 sampce = (Sint16) (SDL_SwapLE16(*(ptr+4)) - 32768); + Sint16 sampwf = (Sint16) (SDL_SwapLE16(*(ptr+5)) - 32768); + + Uint16 swapl = (Uint16) ((Sint16) (((float) sampl * args->left_f) + * args->distance_f) + 32768); + Uint16 swapr = (Uint16) ((Sint16) (((float) sampr * args->right_f) + * args->distance_f) + 32768); + Uint16 swaplr = (Uint16) ((Sint16) (((float) samplr * args->left_rear_f) + * args->distance_f) + 32768); + Uint16 swaprr = (Uint16) ((Sint16) (((float) samprr * args->right_rear_f) + * args->distance_f) + 32768); + Uint16 swapce = (Uint16) ((Sint16) (((float) sampce * args->center_f) + * args->distance_f) + 32768); + Uint16 swapwf = (Uint16) ((Sint16) (((float) sampwf * args->lfe_f) + * args->distance_f) + 32768); + + switch (args->room_angle) { + case 0: + *(ptr++) = (Uint16) SDL_SwapLE16(swapl); + *(ptr++) = (Uint16) SDL_SwapLE16(swapr); + *(ptr++) = (Uint16) SDL_SwapLE16(swaplr); + *(ptr++) = (Uint16) SDL_SwapLE16(swaprr); + *(ptr++) = (Uint16) SDL_SwapLE16(swapce); + *(ptr++) = (Uint16) SDL_SwapLE16(swapwf); + break; + case 90: + *(ptr++) = (Uint16) SDL_SwapLE16(swapr); + *(ptr++) = (Uint16) SDL_SwapLE16(swaprr); + *(ptr++) = (Uint16) SDL_SwapLE16(swapl); + *(ptr++) = (Uint16) SDL_SwapLE16(swaplr); + *(ptr++) = (Uint16) SDL_SwapLE16(swapr)/2 + (Uint16) SDL_SwapLE16(swaprr)/2; + *(ptr++) = (Uint16) SDL_SwapLE16(swapwf); + break; + case 180: + *(ptr++) = (Uint16) SDL_SwapLE16(swaprr); + *(ptr++) = (Uint16) SDL_SwapLE16(swaplr); + *(ptr++) = (Uint16) SDL_SwapLE16(swapr); + *(ptr++) = (Uint16) SDL_SwapLE16(swapl); + *(ptr++) = (Uint16) SDL_SwapLE16(swaprr)/2 + (Uint16) SDL_SwapLE16(swaplr)/2; + *(ptr++) = (Uint16) SDL_SwapLE16(swapwf); + break; + case 270: + *(ptr++) = (Uint16) SDL_SwapLE16(swaplr); + *(ptr++) = (Uint16) SDL_SwapLE16(swapl); + *(ptr++) = (Uint16) SDL_SwapLE16(swaprr); + *(ptr++) = (Uint16) SDL_SwapLE16(swapr); + *(ptr++) = (Uint16) SDL_SwapLE16(swapl)/2 + (Uint16) SDL_SwapLE16(swaplr)/2; + *(ptr++) = (Uint16) SDL_SwapLE16(swapwf); + break; + } + } +} + +static void _Eff_position_s16lsb(int chan, void *stream, int len, void *udata) +{ + /* 16 signed bits (lsb) * 2 channels. */ + volatile position_args *args = (volatile position_args *) udata; + Sint16 *ptr = (Sint16 *) stream; + int i; + +#if 0 + if (len % (sizeof(Sint16) * 2)) { + fprintf(stderr,"Not an even number of frames! len=%d\n", len); + return; + } +#endif + + for (i = 0; i < len; i += sizeof (Sint16) * 2) { + Sint16 swapl = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+0))) * + args->left_f) * args->distance_f); + Sint16 swapr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+1))) * + args->right_f) * args->distance_f); + if (args->room_angle == 180) { + *(ptr++) = (Sint16) SDL_SwapLE16(swapr); + *(ptr++) = (Sint16) SDL_SwapLE16(swapl); + } + else { + *(ptr++) = (Sint16) SDL_SwapLE16(swapl); + *(ptr++) = (Sint16) SDL_SwapLE16(swapr); + } + } +} +static void _Eff_position_s16lsb_c4(int chan, void *stream, int len, void *udata) +{ + /* 16 signed bits (lsb) * 4 channels. */ + volatile position_args *args = (volatile position_args *) udata; + Sint16 *ptr = (Sint16 *) stream; + int i; + + for (i = 0; i < len; i += sizeof (Sint16) * 4) { + Sint16 swapl = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+0))) * + args->left_f) * args->distance_f); + Sint16 swapr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+1))) * + args->right_f) * args->distance_f); + Sint16 swaplr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+1))) * + args->left_rear_f) * args->distance_f); + Sint16 swaprr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+2))) * + args->right_rear_f) * args->distance_f); + switch (args->room_angle) { + case 0: + *(ptr++) = (Sint16) SDL_SwapLE16(swapl); + *(ptr++) = (Sint16) SDL_SwapLE16(swapr); + *(ptr++) = (Sint16) SDL_SwapLE16(swaplr); + *(ptr++) = (Sint16) SDL_SwapLE16(swaprr); + break; + case 90: + *(ptr++) = (Sint16) SDL_SwapLE16(swapr); + *(ptr++) = (Sint16) SDL_SwapLE16(swaprr); + *(ptr++) = (Sint16) SDL_SwapLE16(swapl); + *(ptr++) = (Sint16) SDL_SwapLE16(swaplr); + break; + case 180: + *(ptr++) = (Sint16) SDL_SwapLE16(swaprr); + *(ptr++) = (Sint16) SDL_SwapLE16(swaplr); + *(ptr++) = (Sint16) SDL_SwapLE16(swapr); + *(ptr++) = (Sint16) SDL_SwapLE16(swapl); + break; + case 270: + *(ptr++) = (Sint16) SDL_SwapLE16(swaplr); + *(ptr++) = (Sint16) SDL_SwapLE16(swapl); + *(ptr++) = (Sint16) SDL_SwapLE16(swaprr); + *(ptr++) = (Sint16) SDL_SwapLE16(swapr); + break; + } + } +} + +static void _Eff_position_s16lsb_c6(int chan, void *stream, int len, void *udata) +{ + /* 16 signed bits (lsb) * 6 channels. */ + volatile position_args *args = (volatile position_args *) udata; + Sint16 *ptr = (Sint16 *) stream; + int i; + + for (i = 0; i < len; i += sizeof (Sint16) * 6) { + Sint16 swapl = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+0))) * + args->left_f) * args->distance_f); + Sint16 swapr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+1))) * + args->right_f) * args->distance_f); + Sint16 swaplr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+2))) * + args->left_rear_f) * args->distance_f); + Sint16 swaprr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+3))) * + args->right_rear_f) * args->distance_f); + Sint16 swapce = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+4))) * + args->center_f) * args->distance_f); + Sint16 swapwf = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+5))) * + args->lfe_f) * args->distance_f); + switch (args->room_angle) { + case 0: + *(ptr++) = (Sint16) SDL_SwapLE16(swapl); + *(ptr++) = (Sint16) SDL_SwapLE16(swapr); + *(ptr++) = (Sint16) SDL_SwapLE16(swaplr); + *(ptr++) = (Sint16) SDL_SwapLE16(swaprr); + *(ptr++) = (Sint16) SDL_SwapLE16(swapce); + *(ptr++) = (Sint16) SDL_SwapLE16(swapwf); + break; + case 90: + *(ptr++) = (Sint16) SDL_SwapLE16(swapr); + *(ptr++) = (Sint16) SDL_SwapLE16(swaprr); + *(ptr++) = (Sint16) SDL_SwapLE16(swapl); + *(ptr++) = (Sint16) SDL_SwapLE16(swaplr); + *(ptr++) = (Sint16) SDL_SwapLE16(swapr)/2 + (Sint16) SDL_SwapLE16(swaprr)/2; + *(ptr++) = (Sint16) SDL_SwapLE16(swapwf); + break; + case 180: + *(ptr++) = (Sint16) SDL_SwapLE16(swaprr); + *(ptr++) = (Sint16) SDL_SwapLE16(swaplr); + *(ptr++) = (Sint16) SDL_SwapLE16(swapr); + *(ptr++) = (Sint16) SDL_SwapLE16(swapl); + *(ptr++) = (Sint16) SDL_SwapLE16(swaprr)/2 + (Sint16) SDL_SwapLE16(swaplr)/2; + *(ptr++) = (Sint16) SDL_SwapLE16(swapwf); + break; + case 270: + *(ptr++) = (Sint16) SDL_SwapLE16(swaplr); + *(ptr++) = (Sint16) SDL_SwapLE16(swapl); + *(ptr++) = (Sint16) SDL_SwapLE16(swaprr); + *(ptr++) = (Sint16) SDL_SwapLE16(swapr); + *(ptr++) = (Sint16) SDL_SwapLE16(swapl)/2 + (Sint16) SDL_SwapLE16(swaplr)/2; + *(ptr++) = (Sint16) SDL_SwapLE16(swapwf); + break; + } + } +} + +static void _Eff_position_u16msb(int chan, void *stream, int len, void *udata) +{ + /* 16 signed bits (lsb) * 2 channels. */ + volatile position_args *args = (volatile position_args *) udata; + Uint16 *ptr = (Uint16 *) stream; + int i; + + for (i = 0; i < len; i += sizeof (Sint16) * 2) { + Sint16 sampl = (Sint16) (SDL_SwapBE16(*(ptr+0)) - 32768); + Sint16 sampr = (Sint16) (SDL_SwapBE16(*(ptr+1)) - 32768); + + Uint16 swapl = (Uint16) ((Sint16) (((float) sampl * args->left_f) + * args->distance_f) + 32768); + Uint16 swapr = (Uint16) ((Sint16) (((float) sampr * args->right_f) + * args->distance_f) + 32768); + + if (args->room_angle == 180) { + *(ptr++) = (Uint16) SDL_SwapBE16(swapr); + *(ptr++) = (Uint16) SDL_SwapBE16(swapl); + } + else { + *(ptr++) = (Uint16) SDL_SwapBE16(swapl); + *(ptr++) = (Uint16) SDL_SwapBE16(swapr); + } + } +} +static void _Eff_position_u16msb_c4(int chan, void *stream, int len, void *udata) +{ + /* 16 signed bits (lsb) * 4 channels. */ + volatile position_args *args = (volatile position_args *) udata; + Uint16 *ptr = (Uint16 *) stream; + int i; + + for (i = 0; i < len; i += sizeof (Sint16) * 4) { + Sint16 sampl = (Sint16) (SDL_SwapBE16(*(ptr+0)) - 32768); + Sint16 sampr = (Sint16) (SDL_SwapBE16(*(ptr+1)) - 32768); + Sint16 samplr = (Sint16) (SDL_SwapBE16(*(ptr+2)) - 32768); + Sint16 samprr = (Sint16) (SDL_SwapBE16(*(ptr+3)) - 32768); + + Uint16 swapl = (Uint16) ((Sint16) (((float) sampl * args->left_f) + * args->distance_f) + 32768); + Uint16 swapr = (Uint16) ((Sint16) (((float) sampr * args->right_f) + * args->distance_f) + 32768); + Uint16 swaplr = (Uint16) ((Sint16) (((float) samplr * args->left_rear_f) + * args->distance_f) + 32768); + Uint16 swaprr = (Uint16) ((Sint16) (((float) samprr * args->right_rear_f) + * args->distance_f) + 32768); + + switch (args->room_angle) { + case 0: + *(ptr++) = (Uint16) SDL_SwapBE16(swapl); + *(ptr++) = (Uint16) SDL_SwapBE16(swapr); + *(ptr++) = (Uint16) SDL_SwapBE16(swaplr); + *(ptr++) = (Uint16) SDL_SwapBE16(swaprr); + break; + case 90: + *(ptr++) = (Uint16) SDL_SwapBE16(swapr); + *(ptr++) = (Uint16) SDL_SwapBE16(swaprr); + *(ptr++) = (Uint16) SDL_SwapBE16(swapl); + *(ptr++) = (Uint16) SDL_SwapBE16(swaplr); + break; + case 180: + *(ptr++) = (Uint16) SDL_SwapBE16(swaprr); + *(ptr++) = (Uint16) SDL_SwapBE16(swaplr); + *(ptr++) = (Uint16) SDL_SwapBE16(swapr); + *(ptr++) = (Uint16) SDL_SwapBE16(swapl); + break; + case 270: + *(ptr++) = (Uint16) SDL_SwapBE16(swaplr); + *(ptr++) = (Uint16) SDL_SwapBE16(swapl); + *(ptr++) = (Uint16) SDL_SwapBE16(swaprr); + *(ptr++) = (Uint16) SDL_SwapBE16(swapr); + break; + } + } +} +static void _Eff_position_u16msb_c6(int chan, void *stream, int len, void *udata) +{ + /* 16 signed bits (lsb) * 6 channels. */ + volatile position_args *args = (volatile position_args *) udata; + Uint16 *ptr = (Uint16 *) stream; + int i; + + for (i = 0; i < len; i += sizeof (Sint16) * 6) { + Sint16 sampl = (Sint16) (SDL_SwapBE16(*(ptr+0)) - 32768); + Sint16 sampr = (Sint16) (SDL_SwapBE16(*(ptr+1)) - 32768); + Sint16 samplr = (Sint16) (SDL_SwapBE16(*(ptr+2)) - 32768); + Sint16 samprr = (Sint16) (SDL_SwapBE16(*(ptr+3)) - 32768); + Sint16 sampce = (Sint16) (SDL_SwapBE16(*(ptr+4)) - 32768); + Sint16 sampwf = (Sint16) (SDL_SwapBE16(*(ptr+5)) - 32768); + + Uint16 swapl = (Uint16) ((Sint16) (((float) sampl * args->left_f) + * args->distance_f) + 32768); + Uint16 swapr = (Uint16) ((Sint16) (((float) sampr * args->right_f) + * args->distance_f) + 32768); + Uint16 swaplr = (Uint16) ((Sint16) (((float) samplr * args->left_rear_f) + * args->distance_f) + 32768); + Uint16 swaprr = (Uint16) ((Sint16) (((float) samprr * args->right_rear_f) + * args->distance_f) + 32768); + Uint16 swapce = (Uint16) ((Sint16) (((float) sampce * args->center_f) + * args->distance_f) + 32768); + Uint16 swapwf = (Uint16) ((Sint16) (((float) sampwf * args->lfe_f) + * args->distance_f) + 32768); + + switch (args->room_angle) { + case 0: + *(ptr++) = (Uint16) SDL_SwapBE16(swapl); + *(ptr++) = (Uint16) SDL_SwapBE16(swapr); + *(ptr++) = (Uint16) SDL_SwapBE16(swaplr); + *(ptr++) = (Uint16) SDL_SwapBE16(swaprr); + *(ptr++) = (Uint16) SDL_SwapBE16(swapce); + *(ptr++) = (Uint16) SDL_SwapBE16(swapwf); + break; + case 90: + *(ptr++) = (Uint16) SDL_SwapBE16(swapr); + *(ptr++) = (Uint16) SDL_SwapBE16(swaprr); + *(ptr++) = (Uint16) SDL_SwapBE16(swapl); + *(ptr++) = (Uint16) SDL_SwapBE16(swaplr); + *(ptr++) = (Uint16) SDL_SwapBE16(swapr)/2 + (Uint16) SDL_SwapBE16(swaprr)/2; + *(ptr++) = (Uint16) SDL_SwapBE16(swapwf); + break; + case 180: + *(ptr++) = (Uint16) SDL_SwapBE16(swaprr); + *(ptr++) = (Uint16) SDL_SwapBE16(swaplr); + *(ptr++) = (Uint16) SDL_SwapBE16(swapr); + *(ptr++) = (Uint16) SDL_SwapBE16(swapl); + *(ptr++) = (Uint16) SDL_SwapBE16(swaprr)/2 + (Uint16) SDL_SwapBE16(swaplr)/2; + *(ptr++) = (Uint16) SDL_SwapBE16(swapwf); + break; + case 270: + *(ptr++) = (Uint16) SDL_SwapBE16(swaplr); + *(ptr++) = (Uint16) SDL_SwapBE16(swapl); + *(ptr++) = (Uint16) SDL_SwapBE16(swaprr); + *(ptr++) = (Uint16) SDL_SwapBE16(swapr); + *(ptr++) = (Uint16) SDL_SwapBE16(swapl)/2 + (Uint16) SDL_SwapBE16(swaplr)/2; + *(ptr++) = (Uint16) SDL_SwapBE16(swapwf); + break; + } + } +} + +static void _Eff_position_s16msb(int chan, void *stream, int len, void *udata) +{ + /* 16 signed bits (lsb) * 2 channels. */ + volatile position_args *args = (volatile position_args *) udata; + Sint16 *ptr = (Sint16 *) stream; + int i; + + for (i = 0; i < len; i += sizeof (Sint16) * 2) { + Sint16 swapl = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+0))) * + args->left_f) * args->distance_f); + Sint16 swapr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+1))) * + args->right_f) * args->distance_f); + *(ptr++) = (Sint16) SDL_SwapBE16(swapl); + *(ptr++) = (Sint16) SDL_SwapBE16(swapr); + } +} +static void _Eff_position_s16msb_c4(int chan, void *stream, int len, void *udata) +{ + /* 16 signed bits (lsb) * 4 channels. */ + volatile position_args *args = (volatile position_args *) udata; + Sint16 *ptr = (Sint16 *) stream; + int i; + + for (i = 0; i < len; i += sizeof (Sint16) * 4) { + Sint16 swapl = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+0))) * + args->left_f) * args->distance_f); + Sint16 swapr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+1))) * + args->right_f) * args->distance_f); + Sint16 swaplr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+2))) * + args->left_rear_f) * args->distance_f); + Sint16 swaprr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+3))) * + args->right_rear_f) * args->distance_f); + switch (args->room_angle) { + case 0: + *(ptr++) = (Sint16) SDL_SwapBE16(swapl); + *(ptr++) = (Sint16) SDL_SwapBE16(swapr); + *(ptr++) = (Sint16) SDL_SwapBE16(swaplr); + *(ptr++) = (Sint16) SDL_SwapBE16(swaprr); + break; + case 90: + *(ptr++) = (Sint16) SDL_SwapBE16(swapr); + *(ptr++) = (Sint16) SDL_SwapBE16(swaprr); + *(ptr++) = (Sint16) SDL_SwapBE16(swapl); + *(ptr++) = (Sint16) SDL_SwapBE16(swaplr); + break; + case 180: + *(ptr++) = (Sint16) SDL_SwapBE16(swaprr); + *(ptr++) = (Sint16) SDL_SwapBE16(swaplr); + *(ptr++) = (Sint16) SDL_SwapBE16(swapr); + *(ptr++) = (Sint16) SDL_SwapBE16(swapl); + break; + case 270: + *(ptr++) = (Sint16) SDL_SwapBE16(swaplr); + *(ptr++) = (Sint16) SDL_SwapBE16(swapl); + *(ptr++) = (Sint16) SDL_SwapBE16(swaprr); + *(ptr++) = (Sint16) SDL_SwapBE16(swapr); + break; + } + } +} +static void _Eff_position_s16msb_c6(int chan, void *stream, int len, void *udata) +{ + /* 16 signed bits (lsb) * 6 channels. */ + volatile position_args *args = (volatile position_args *) udata; + Sint16 *ptr = (Sint16 *) stream; + int i; + + for (i = 0; i < len; i += sizeof (Sint16) * 6) { + Sint16 swapl = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+0))) * + args->left_f) * args->distance_f); + Sint16 swapr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+1))) * + args->right_f) * args->distance_f); + Sint16 swaplr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+2))) * + args->left_rear_f) * args->distance_f); + Sint16 swaprr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+3))) * + args->right_rear_f) * args->distance_f); + Sint16 swapce = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+4))) * + args->center_f) * args->distance_f); + Sint16 swapwf = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+5))) * + args->lfe_f) * args->distance_f); + + switch (args->room_angle) { + case 0: + *(ptr++) = (Sint16) SDL_SwapBE16(swapl); + *(ptr++) = (Sint16) SDL_SwapBE16(swapr); + *(ptr++) = (Sint16) SDL_SwapBE16(swaplr); + *(ptr++) = (Sint16) SDL_SwapBE16(swaprr); + *(ptr++) = (Sint16) SDL_SwapBE16(swapce); + *(ptr++) = (Sint16) SDL_SwapBE16(swapwf); + break; + case 90: + *(ptr++) = (Sint16) SDL_SwapBE16(swapr); + *(ptr++) = (Sint16) SDL_SwapBE16(swaprr); + *(ptr++) = (Sint16) SDL_SwapBE16(swapl); + *(ptr++) = (Sint16) SDL_SwapBE16(swaplr); + *(ptr++) = (Sint16) SDL_SwapBE16(swapr)/2 + (Sint16) SDL_SwapBE16(swaprr)/2; + *(ptr++) = (Sint16) SDL_SwapBE16(swapwf); + break; + case 180: + *(ptr++) = (Sint16) SDL_SwapBE16(swaprr); + *(ptr++) = (Sint16) SDL_SwapBE16(swaplr); + *(ptr++) = (Sint16) SDL_SwapBE16(swapr); + *(ptr++) = (Sint16) SDL_SwapBE16(swapl); + *(ptr++) = (Sint16) SDL_SwapBE16(swaprr)/2 + (Sint16) SDL_SwapBE16(swaplr)/2; + *(ptr++) = (Sint16) SDL_SwapBE16(swapwf); + break; + case 270: + *(ptr++) = (Sint16) SDL_SwapBE16(swaplr); + *(ptr++) = (Sint16) SDL_SwapBE16(swapl); + *(ptr++) = (Sint16) SDL_SwapBE16(swaprr); + *(ptr++) = (Sint16) SDL_SwapBE16(swapr); + *(ptr++) = (Sint16) SDL_SwapBE16(swapl)/2 + (Sint16) SDL_SwapBE16(swaplr)/2; + *(ptr++) = (Sint16) SDL_SwapBE16(swapwf); + break; + } + } +} + +static void init_position_args(position_args *args) +{ + memset(args, '\0', sizeof (position_args)); + args->in_use = 0; + args->room_angle = 0; + args->left_u8 = args->right_u8 = args->distance_u8 = 255; + args->left_f = args->right_f = args->distance_f = 1.0f; + args->left_rear_u8 = args->right_rear_u8 = args->center_u8 = args->lfe_u8 = 255; + args->left_rear_f = args->right_rear_f = args->center_f = args->lfe_f = 1.0f; + Mix_QuerySpec(NULL, NULL, (int *) &args->channels); +} + + +static position_args *get_position_arg(int channel) +{ + void *rc; + int i; + + if (channel < 0) { + if (pos_args_global == NULL) { + pos_args_global = SDL_malloc(sizeof (position_args)); + if (pos_args_global == NULL) { + Mix_SetError("Out of memory"); + return(NULL); + } + init_position_args(pos_args_global); + } + + return(pos_args_global); + } + + if (channel >= position_channels) { + rc = SDL_realloc(pos_args_array, (channel + 1) * sizeof (position_args *)); + if (rc == NULL) { + Mix_SetError("Out of memory"); + return(NULL); + } + pos_args_array = (position_args **) rc; + for (i = position_channels; i <= channel; i++) { + pos_args_array[i] = NULL; + } + position_channels = channel + 1; + } + + if (pos_args_array[channel] == NULL) { + pos_args_array[channel] = (position_args *)SDL_malloc(sizeof(position_args)); + if (pos_args_array[channel] == NULL) { + Mix_SetError("Out of memory"); + return(NULL); + } + init_position_args(pos_args_array[channel]); + } + + return(pos_args_array[channel]); +} + + +static Mix_EffectFunc_t get_position_effect_func(Uint16 format, int channels) +{ + Mix_EffectFunc_t f = NULL; + + switch (format) { + case AUDIO_U8: + switch (channels) { + case 1: + case 2: + f = (_Eff_build_volume_table_u8()) ? _Eff_position_table_u8 : + _Eff_position_u8; + break; + case 4: + f = _Eff_position_u8_c4; + break; + case 6: + f = _Eff_position_u8_c6; + break; + } + break; + + case AUDIO_S8: + switch (channels) { + case 1: + case 2: + f = (_Eff_build_volume_table_s8()) ? _Eff_position_table_s8 : + _Eff_position_s8; + break; + case 4: + f = _Eff_position_s8_c4; + break; + case 6: + f = _Eff_position_s8_c6; + break; + } + break; + + case AUDIO_U16LSB: + switch (channels) { + case 1: + case 2: + f = _Eff_position_u16lsb; + break; + case 4: + f = _Eff_position_u16lsb_c4; + break; + case 6: + f = _Eff_position_u16lsb_c6; + break; + } + break; + + case AUDIO_S16LSB: + switch (channels) { + case 1: + case 2: + f = _Eff_position_s16lsb; + break; + case 4: + f = _Eff_position_s16lsb_c4; + break; + case 6: + f = _Eff_position_s16lsb_c6; + break; + } + break; + + case AUDIO_U16MSB: + switch (channels) { + case 1: + case 2: + f = _Eff_position_u16msb; + break; + case 4: + f = _Eff_position_u16msb_c4; + break; + case 6: + f = _Eff_position_u16msb_c6; + break; + } + break; + + case AUDIO_S16MSB: + switch (channels) { + case 1: + case 2: + f = _Eff_position_s16msb; + break; + case 4: + f = _Eff_position_s16msb_c4; + break; + case 6: + f = _Eff_position_s16msb_c6; + break; + } + break; + + default: + Mix_SetError("Unsupported audio format"); + } + + return(f); +} + +static Uint8 speaker_amplitude[6]; + +static void set_amplitudes(int channels, int angle, int room_angle) +{ + int left = 255, right = 255; + int left_rear = 255, right_rear = 255, center = 255; + + angle = SDL_abs(angle) % 360; /* make angle between 0 and 359. */ + + if (channels == 2) + { + /* + * We only attenuate by position if the angle falls on the far side + * of center; That is, an angle that's due north would not attenuate + * either channel. Due west attenuates the right channel to 0.0, and + * due east attenuates the left channel to 0.0. Slightly east of + * center attenuates the left channel a little, and the right channel + * not at all. I think of this as occlusion by one's own head. :) + * + * ...so, we split our angle circle into four quadrants... + */ + if (angle < 90) { + left = 255 - ((int) (255.0f * (((float) angle) / 89.0f))); + } else if (angle < 180) { + left = (int) (255.0f * (((float) (angle - 90)) / 89.0f)); + } else if (angle < 270) { + right = 255 - ((int) (255.0f * (((float) (angle - 180)) / 89.0f))); + } else { + right = (int) (255.0f * (((float) (angle - 270)) / 89.0f)); + } + } + + if (channels == 4 || channels == 6) + { + /* + * An angle that's due north does not attenuate the center channel. + * An angle in the first quadrant, 0-90, does not attenuate the RF. + * + * ...so, we split our angle circle into 8 ... + * + * CE + * 0 + * LF | RF + * | + * 270<-------|----------->90 + * | + * LR | RR + * 180 + * + */ + if (angle < 45) { + left = ((int) (255.0f * (((float) (180 - angle)) / 179.0f))); + left_rear = 255 - ((int) (255.0f * (((float) (angle + 45)) / 89.0f))); + right_rear = 255 - ((int) (255.0f * (((float) (90 - angle)) / 179.0f))); + } else if (angle < 90) { + center = ((int) (255.0f * (((float) (225 - angle)) / 179.0f))); + left = ((int) (255.0f * (((float) (180 - angle)) / 179.0f))); + left_rear = 255 - ((int) (255.0f * (((float) (135 - angle)) / 89.0f))); + right_rear = ((int) (255.0f * (((float) (90 + angle)) / 179.0f))); + } else if (angle < 135) { + center = ((int) (255.0f * (((float) (225 - angle)) / 179.0f))); + left = 255 - ((int) (255.0f * (((float) (angle - 45)) / 89.0f))); + right = ((int) (255.0f * (((float) (270 - angle)) / 179.0f))); + left_rear = ((int) (255.0f * (((float) (angle)) / 179.0f))); + } else if (angle < 180) { + center = 255 - ((int) (255.0f * (((float) (angle - 90)) / 89.0f))); + left = 255 - ((int) (255.0f * (((float) (225 - angle)) / 89.0f))); + right = ((int) (255.0f * (((float) (270 - angle)) / 179.0f))); + left_rear = ((int) (255.0f * (((float) (angle)) / 179.0f))); + } else if (angle < 225) { + center = 255 - ((int) (255.0f * (((float) (270 - angle)) / 89.0f))); + left = ((int) (255.0f * (((float) (angle - 90)) / 179.0f))); + right = 255 - ((int) (255.0f * (((float) (angle - 135)) / 89.0f))); + right_rear = ((int) (255.0f * (((float) (360 - angle)) / 179.0f))); + } else if (angle < 270) { + center = ((int) (255.0f * (((float) (angle - 135)) / 179.0f))); + left = ((int) (255.0f * (((float) (angle - 90)) / 179.0f))); + right = 255 - ((int) (255.0f * (((float) (315 - angle)) / 89.0f))); + right_rear = ((int) (255.0f * (((float) (360 - angle)) / 179.0f))); + } else if (angle < 315) { + center = ((int) (255.0f * (((float) (angle - 135)) / 179.0f))); + right = ((int) (255.0f * (((float) (angle - 180)) / 179.0f))); + left_rear = ((int) (255.0f * (((float) (450 - angle)) / 179.0f))); + right_rear = 255 - ((int) (255.0f * (((float) (angle - 225)) / 89.0f))); + } else { + right = ((int) (255.0f * (((float) (angle - 180)) / 179.0f))); + left_rear = ((int) (255.0f * (((float) (450 - angle)) / 179.0f))); + right_rear = 255 - ((int) (255.0f * (((float) (405 - angle)) / 89.0f))); + } + } + + if (left < 0) left = 0; if (left > 255) left = 255; + if (right < 0) right = 0; if (right > 255) right = 255; + if (left_rear < 0) left_rear = 0; if (left_rear > 255) left_rear = 255; + if (right_rear < 0) right_rear = 0; if (right_rear > 255) right_rear = 255; + if (center < 0) center = 0; if (center > 255) center = 255; + + if (room_angle == 90) { + speaker_amplitude[0] = (Uint8)left_rear; + speaker_amplitude[1] = (Uint8)left; + speaker_amplitude[2] = (Uint8)right_rear; + speaker_amplitude[3] = (Uint8)right; + } + else if (room_angle == 180) { + if (channels == 2) { + speaker_amplitude[0] = (Uint8)right; + speaker_amplitude[1] = (Uint8)left; + } + else { + speaker_amplitude[0] = (Uint8)right_rear; + speaker_amplitude[1] = (Uint8)left_rear; + speaker_amplitude[2] = (Uint8)right; + speaker_amplitude[3] = (Uint8)left; + } + } + else if (room_angle == 270) { + speaker_amplitude[0] = (Uint8)right; + speaker_amplitude[1] = (Uint8)right_rear; + speaker_amplitude[2] = (Uint8)left; + speaker_amplitude[3] = (Uint8)left_rear; + } + else { + speaker_amplitude[0] = (Uint8)left; + speaker_amplitude[1] = (Uint8)right; + speaker_amplitude[2] = (Uint8)left_rear; + speaker_amplitude[3] = (Uint8)right_rear; + } + speaker_amplitude[4] = (Uint8)center; + speaker_amplitude[5] = 255; +} + +int Mix_SetPosition(int channel, Sint16 angle, Uint8 distance); + +int Mix_SetPanning(int channel, Uint8 left, Uint8 right) +{ + Mix_EffectFunc_t f = NULL; + int channels; + Uint16 format; + position_args *args = NULL; + int retval = 1; + + Mix_QuerySpec(NULL, &format, &channels); + + if (channels != 2 && channels != 4 && channels != 6) /* it's a no-op; we call that successful. */ + return(1); + + if (channels > 2) { + /* left = right = 255 => angle = 0, to unregister effect as when channels = 2 */ + /* left = 255 => angle = -90; left = 0 => angle = +89 */ + int angle = 0; + if ((left != 255) || (right != 255)) { + angle = (int)left; + angle = 127 - angle; + angle = -angle; + angle = angle * 90 / 128; /* Make it larger for more effect? */ + } + return( Mix_SetPosition(channel, angle, 0) ); + } + + f = get_position_effect_func(format, channels); + if (f == NULL) + return(0); + + SDL_LockAudio(); + args = get_position_arg(channel); + if (!args) { + SDL_UnlockAudio(); + return(0); + } + + /* it's a no-op; unregister the effect, if it's registered. */ + if ((args->distance_u8 == 255) && (left == 255) && (right == 255)) { + if (args->in_use) { + retval = _Mix_UnregisterEffect_locked(channel, f); + SDL_UnlockAudio(); + return(retval); + } else { + SDL_UnlockAudio(); + return(1); + } + } + + args->left_u8 = left; + args->left_f = ((float) left) / 255.0f; + args->right_u8 = right; + args->right_f = ((float) right) / 255.0f; + args->room_angle = 0; + + if (!args->in_use) { + args->in_use = 1; + retval=_Mix_RegisterEffect_locked(channel, f, _Eff_PositionDone, (void*)args); + } + + SDL_UnlockAudio(); + return(retval); +} + + +int Mix_SetDistance(int channel, Uint8 distance) +{ + Mix_EffectFunc_t f = NULL; + Uint16 format; + position_args *args = NULL; + int channels; + int retval = 1; + + Mix_QuerySpec(NULL, &format, &channels); + f = get_position_effect_func(format, channels); + if (f == NULL) + return(0); + + SDL_LockAudio(); + args = get_position_arg(channel); + if (!args) { + SDL_UnlockAudio(); + return(0); + } + + distance = 255 - distance; /* flip it to our scale. */ + + /* it's a no-op; unregister the effect, if it's registered. */ + if ((distance == 255) && (args->left_u8 == 255) && (args->right_u8 == 255)) { + if (args->in_use) { + retval = _Mix_UnregisterEffect_locked(channel, f); + SDL_UnlockAudio(); + return(retval); + } else { + SDL_UnlockAudio(); + return(1); + } + } + + args->distance_u8 = distance; + args->distance_f = ((float) distance) / 255.0f; + if (!args->in_use) { + args->in_use = 1; + retval = _Mix_RegisterEffect_locked(channel, f, _Eff_PositionDone, (void *) args); + } + + SDL_UnlockAudio(); + return(retval); +} + + +int Mix_SetPosition(int channel, Sint16 angle, Uint8 distance) +{ + Mix_EffectFunc_t f = NULL; + Uint16 format; + int channels; + position_args *args = NULL; + Sint16 room_angle = 0; + int retval = 1; + + Mix_QuerySpec(NULL, &format, &channels); + f = get_position_effect_func(format, channels); + if (f == NULL) + return(0); + + angle = SDL_abs(angle) % 360; /* make angle between 0 and 359. */ + + SDL_LockAudio(); + args = get_position_arg(channel); + if (!args) { + SDL_UnlockAudio(); + return(0); + } + + /* it's a no-op; unregister the effect, if it's registered. */ + if ((!distance) && (!angle)) { + if (args->in_use) { + retval = _Mix_UnregisterEffect_locked(channel, f); + SDL_UnlockAudio(); + return(retval); + } else { + SDL_UnlockAudio(); + return(1); + } + } + + if (channels == 2) + { + if (angle > 180) + room_angle = 180; /* exchange left and right channels */ + else room_angle = 0; + } + + if (channels == 4 || channels == 6) + { + if (angle > 315) room_angle = 0; + else if (angle > 225) room_angle = 270; + else if (angle > 135) room_angle = 180; + else if (angle > 45) room_angle = 90; + else room_angle = 0; + } + + + distance = 255 - distance; /* flip it to scale Mix_SetDistance() uses. */ + + set_amplitudes(channels, angle, room_angle); + + args->left_u8 = speaker_amplitude[0]; + args->left_f = ((float) speaker_amplitude[0]) / 255.0f; + args->right_u8 = speaker_amplitude[1]; + args->right_f = ((float) speaker_amplitude[1]) / 255.0f; + args->left_rear_u8 = speaker_amplitude[2]; + args->left_rear_f = ((float) speaker_amplitude[2]) / 255.0f; + args->right_rear_u8 = speaker_amplitude[3]; + args->right_rear_f = ((float) speaker_amplitude[3]) / 255.0f; + args->center_u8 = speaker_amplitude[4]; + args->center_f = ((float) speaker_amplitude[4]) / 255.0f; + args->lfe_u8 = speaker_amplitude[5]; + args->lfe_f = ((float) speaker_amplitude[5]) / 255.0f; + args->distance_u8 = distance; + args->distance_f = ((float) distance) / 255.0f; + args->room_angle = room_angle; + if (!args->in_use) { + args->in_use = 1; + retval = _Mix_RegisterEffect_locked(channel, f, _Eff_PositionDone, (void *) args); + } + + SDL_UnlockAudio(); + return(retval); +} + + +/* end of effects_position.c ... */ + |