+#define SWAP_LISTENERS(l1, l2, tmpl) { tmpl = (l1); (l1) = (l2); (l2) = tmpl; }
+
+void S_SetSpeakerLayout (void)
+{
+ unsigned int i;
+ listener_t swaplistener;
+ listener_t *listeners;
+
+ for (i = 0; i < SND_SPEAKERLAYOUTS; i++)
+ if (snd_speakerlayouts[i].channels == snd_renderbuffer->format.channels)
+ break;
+ if (i >= SND_SPEAKERLAYOUTS)
+ {
+ Con_Printf("S_SetSpeakerLayout: Can't find the speaker layout for %hu channels. Defaulting to mono output\n",
+ snd_renderbuffer->format.channels);
+ i = SND_SPEAKERLAYOUTS - 1;
+ }
+
+ snd_speakerlayout = snd_speakerlayouts[i];
+ listeners = snd_speakerlayout.listeners;
+
+ // Swap the left and right channels if snd_swapstereo is set
+ if (snd_swapstereo.integer)
+ {
+ switch (snd_speakerlayout.channels)
+ {
+ case 8:
+ SWAP_LISTENERS(listeners[6], listeners[7], swaplistener);
+ // no break
+ case 4:
+ case 6:
+ SWAP_LISTENERS(listeners[2], listeners[3], swaplistener);
+ // no break
+ case 2:
+ SWAP_LISTENERS(listeners[0], listeners[1], swaplistener);
+ break;
+
+ default:
+ case 1:
+ // Nothing to do
+ break;
+ }
+ }
+
+ // Convert our layout (= ALSA) to Win32/CoreAudio layout if necessary
+ if (!alsaspeakerlayout &&
+ (snd_speakerlayout.channels == 6 || snd_speakerlayout.channels == 8))
+ {
+ SWAP_LISTENERS(listeners[2], listeners[4], swaplistener);
+ SWAP_LISTENERS(listeners[3], listeners[5], swaplistener);
+ }
+}
+
+