SDL_mixer: Mix_SetPosition() and cracking sound

I was investigating cracking sound and found this in effect_position.c in Mix_SetPosition():

angle = SDL_abs(angle) % 360;  /* make angle between 0 and 359. */

Documentation for Mix_SetPosition() says:

(angle) will be reduced as neccesary (540 becomes 180 degrees, -100 becomes 260).

However if i pass angle -90, this becomes angle = SDL_abs(-90) % 360, 90 % 360 is obviously 90, so channel position changes from (intended) left (-90) to the (unintended) right (90). Removing SDL_abs doesn’t help either, -90 % 360 = -90, so it’s not between 0…360.

I think intention was to perform modulo operation on angle, so -90 % 360 = 270 - this makes sense and matches documentation, i changed this line to

angle = (angle % 360 + 360) % 360;  /* make angle between 0 and 359. */

and this kinda works.

But it also might be that i’m doing something wrong with mixer. Am i missing anything or shall i report bug or send patch or something?

Regarding cracking sound: i think the problem is in this bit of Mix_SetPosition():

    if (channels == 2)
    if (angle > 180)
        room_angle = 180; /* exchange left and right channels */
    else room_angle = 0;

And then in set_amplitudes() channels seemingly swapped as advertised, but i don’t quite understand how this works.

  1. Why channels are swapped if effect is behind observer? I thought that if effect is on the left from the observer, it will stay on the left regardless if it’s in front of behind, no?
  2. set_amplitudes() is adjusting something in static array:
static Uint8 speaker_amplitude[6];

But what if i have several effects playing at the same time, won’t setting this up for second (or third) effect discard settings for first effect?

Steps to reproduce my issue looks like this:

  1. Create effect directly in front of player
  2. Rotate player slightly to the right (5-10 degrees)
  3. Adjust effect position with Mix_SetPosition() (angle would be something like 360-7=353)
  4. Rotate player slightly to the left (10-20 degrees)
  5. Adjust effect position with Mix_SetPosition() (angle would be something like 0+7=7)
  6. Repeat steps 2-5

The point is to change angle to the opposite across zero while effect is still playing. When i do that, sound starts cracking. If i disable “exchange left and right channels” then effect is playing without cracking.

What am i doing wrong? Shouldn’t i call Mix_SetPosition() or is there some specific place where it is appropriate to call this function to adjust effect for changed position relatively to observer? Or maybe my mixer settings incorrect?

Any ideas?