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