Merged Ryan's 5.1 audio fix from SDL 1.2 SDL-1.3
authorSam Lantinga <slouken@libsdl.org>
Fri, 23 Jun 2006 09:01:08 +0000
branchSDL-1.3
changeset 1702 a7ad7081b977
parent 1701 442248d4e738
child 1703 a51dfda0ff33
Merged Ryan's 5.1 audio fix from SDL 1.2
src/audio/alsa/SDL_alsa_audio.c
--- a/src/audio/alsa/SDL_alsa_audio.c	Fri Jun 23 08:48:24 2006 +0000
+++ b/src/audio/alsa/SDL_alsa_audio.c	Fri Jun 23 09:01:08 2006 +0000
@@ -351,6 +351,69 @@
     }
 }
 
+
+/*
+ * 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)
 {
@@ -358,8 +421,11 @@
     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);
@@ -372,8 +438,7 @@
                 do {
                     SDL_Delay(1);
                     status = SDL_NAME(snd_pcm_resume) (pcm_handle);
-                }
-                while (status == -EAGAIN);
+                } while (status == -EAGAIN);
             }
             if (status < 0) {
                 status = SDL_NAME(snd_pcm_prepare) (pcm_handle);