Swizzle ALSA channels for 5.1 output to match DirectSound and CoreAudio.
authorRyan C. Gordon <icculus@icculus.org>
Fri, 23 Jun 2006 08:35:48 +0000
changeset 1878 d7c9d7f42881
parent 1877 9b02a5b97f79
child 1879 cb232e63552c
Swizzle ALSA channels for 5.1 output to match DirectSound and CoreAudio. Untested, but potentially fixes Bugzilla #110.
src/audio/alsa/SDL_alsa_audio.c
--- a/src/audio/alsa/SDL_alsa_audio.c	Fri Jun 23 08:15:47 2006 +0000
+++ b/src/audio/alsa/SDL_alsa_audio.c	Fri Jun 23 08:35:48 2006 +0000
@@ -264,14 +264,63 @@
 	}
 }
 
+
+/*
+ * http://bugzilla.libsdl.org/show_bug.cgi?id=110
+ * "For Linux ALSA, this is FL-FR-RL-RR-C-LFE
+ *  and for Windows DirectX [and CoreAudio], this is FL-FR-C-LFE-RL-RR"
+ */
+#define SWIZ6(T) \
+    T *ptr = (T *) mixbuf; \
+    const Uint32 count = (this->spec.samples / 6); \
+    Uint32 i; \
+    for (i = 0; i < count; i++, ptr += 6) { \
+        T tmp; \
+        tmp = ptr[2]; ptr[2] = ptr[4]; ptr[4] = tmp; \
+        tmp = ptr[3]; ptr[3] = ptr[5]; ptr[5] = tmp; \
+    }
+
+static __inline__ void swizzle_alsa_channels_6_64bit(_THIS) { SWIZ6(Uint64); }
+static __inline__ void swizzle_alsa_channels_6_32bit(_THIS) { SWIZ6(Uint32); }
+static __inline__ void swizzle_alsa_channels_6_16bit(_THIS) { SWIZ6(Uint16); }
+static __inline__ void swizzle_alsa_channels_6_8bit(_THIS) { SWIZ6(Uint8); }
+
+#undef SWIZ6
+
+
+/*
+ * Called right before feeding this->mixbuf to the hardware. Swizzle channels
+ *  from Windows/Mac order to the format alsalib will want.
+ */
+static __inline__ void swizzle_alsa_channels(_THIS)
+{
+    if (this->spec.channels == 6) {
+        const Uint16 fmtsize = (this->spec.format & 0xFF); /* bits/channel. */
+        if (fmtsize == 16)
+            swizzle_alsa_channels_6_16bit(this);
+        else if (fmtsize == 8)
+            swizzle_alsa_channels_6_8bit(this);
+        else if (fmtsize == 32)
+            swizzle_alsa_channels_6_32bit(this);
+        else if (fmtsize == 64)
+            swizzle_alsa_channels_6_64bit(this);
+    }
+
+    /* !!! FIXME: update this for 7.1 if needed, later. */
+}
+
+
 static void ALSA_PlayAudio(_THIS)
 {
 	int           status;
 	int           sample_len;
 	signed short *sample_buf;
 
+	swizzle_alsa_channels(this);
+
 	sample_len = this->spec.samples;
 	sample_buf = (signed short *)mixbuf;
+
 	while ( sample_len > 0 ) {
 		status = SDL_NAME(snd_pcm_writei)(pcm_handle, sample_buf, sample_len);
 		if ( status < 0 ) {