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