From 901804d724d49f316cd2bf51ec1cd2cd9fb9eb91 Mon Sep 17 00:00:00 2001
From: Chris Robinson <chris.kcat@gmail.com>
Date: Wed, 12 Apr 2017 18:26:07 -0700
Subject: Store the ambisonic order separate from the channel enum

---
 Alc/ALc.c                 | 157 +++++++++++++++++------------------------
 Alc/backends/alsa.c       |  11 +--
 Alc/backends/coreaudio.c  |   8 +--
 Alc/backends/dsound.c     | 176 ++++++++++++++++++++++------------------------
 Alc/backends/jack.c       |  10 ++-
 Alc/backends/mmdevapi.c   |  15 ++--
 Alc/backends/opensl.c     |  10 ++-
 Alc/backends/oss.c        |  16 +++--
 Alc/backends/portaudio.c  |   4 +-
 Alc/backends/pulseaudio.c |  48 +++++++++++--
 Alc/backends/qsa.c        |  20 +++---
 Alc/backends/sndio.c      |   6 +-
 Alc/backends/solaris.c    |  12 ++--
 Alc/backends/wave.c       |  25 ++++---
 Alc/backends/winmm.c      |   8 +--
 Alc/converter.c           |   2 +-
 Alc/panning.c             |  31 ++++----
 17 files changed, 280 insertions(+), 279 deletions(-)

(limited to 'Alc')

diff --git a/Alc/ALc.c b/Alc/ALc.c
index 47bd19e4..2a636c59 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -1367,14 +1367,12 @@ const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
     case DevFmtX51Rear: return "5.1 Surround (Rear)";
     case DevFmtX61: return "6.1 Surround";
     case DevFmtX71: return "7.1 Surround";
-    case DevFmtAmbi1: return "Ambisonic (1st Order)";
-    case DevFmtAmbi2: return "Ambisonic (2nd Order)";
-    case DevFmtAmbi3: return "Ambisonic (3rd Order)";
+    case DevFmtAmbi3D: return "Ambisonic 3D";
     }
     return "(unknown channels)";
 }
 
-extern inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
+extern inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type, ALsizei ambiorder);
 ALsizei BytesFromDevFmt(enum DevFmtType type)
 {
     switch(type)
@@ -1389,7 +1387,7 @@ ALsizei BytesFromDevFmt(enum DevFmtType type)
     }
     return 0;
 }
-ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans)
+ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans, ALsizei ambiorder)
 {
     switch(chans)
     {
@@ -1400,9 +1398,9 @@ ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans)
     case DevFmtX51Rear: return 6;
     case DevFmtX61: return 7;
     case DevFmtX71: return 8;
-    case DevFmtAmbi1: return 4;
-    case DevFmtAmbi2: return 9;
-    case DevFmtAmbi3: return 16;
+    case DevFmtAmbi3D: return (ambiorder >= 3) ? 16 :
+                              (ambiorder == 2) ? 9 :
+                              (ambiorder == 1) ? 4 : 1;
     }
     return 0;
 }
@@ -1585,40 +1583,32 @@ void SetDefaultWFXChannelOrder(ALCdevice *device)
         device->RealOut.ChannelName[6] = SideLeft;
         device->RealOut.ChannelName[7] = SideRight;
         break;
-    case DevFmtAmbi1:
+    case DevFmtAmbi3D:
         device->RealOut.ChannelName[0] = Aux0;
-        device->RealOut.ChannelName[1] = Aux1;
-        device->RealOut.ChannelName[2] = Aux2;
-        device->RealOut.ChannelName[3] = Aux3;
-        break;
-    case DevFmtAmbi2:
-        device->RealOut.ChannelName[0] = Aux0;
-        device->RealOut.ChannelName[1] = Aux1;
-        device->RealOut.ChannelName[2] = Aux2;
-        device->RealOut.ChannelName[3] = Aux3;
-        device->RealOut.ChannelName[4] = Aux4;
-        device->RealOut.ChannelName[5] = Aux5;
-        device->RealOut.ChannelName[6] = Aux6;
-        device->RealOut.ChannelName[7] = Aux7;
-        device->RealOut.ChannelName[8] = Aux8;
-        break;
-    case DevFmtAmbi3:
-        device->RealOut.ChannelName[0] = Aux0;
-        device->RealOut.ChannelName[1] = Aux1;
-        device->RealOut.ChannelName[2] = Aux2;
-        device->RealOut.ChannelName[3] = Aux3;
-        device->RealOut.ChannelName[4] = Aux4;
-        device->RealOut.ChannelName[5] = Aux5;
-        device->RealOut.ChannelName[6] = Aux6;
-        device->RealOut.ChannelName[7] = Aux7;
-        device->RealOut.ChannelName[8] = Aux8;
-        device->RealOut.ChannelName[9] = Aux9;
-        device->RealOut.ChannelName[10] = Aux10;
-        device->RealOut.ChannelName[11] = Aux11;
-        device->RealOut.ChannelName[12] = Aux12;
-        device->RealOut.ChannelName[13] = Aux13;
-        device->RealOut.ChannelName[14] = Aux14;
-        device->RealOut.ChannelName[15] = Aux15;
+        if(device->AmbiOrder > 0)
+        {
+            device->RealOut.ChannelName[1] = Aux1;
+            device->RealOut.ChannelName[2] = Aux2;
+            device->RealOut.ChannelName[3] = Aux3;
+        }
+        if(device->AmbiOrder > 1)
+        {
+            device->RealOut.ChannelName[4] = Aux4;
+            device->RealOut.ChannelName[5] = Aux5;
+            device->RealOut.ChannelName[6] = Aux6;
+            device->RealOut.ChannelName[7] = Aux7;
+            device->RealOut.ChannelName[8] = Aux8;
+        }
+        if(device->AmbiOrder > 2)
+        {
+            device->RealOut.ChannelName[9]  = Aux9;
+            device->RealOut.ChannelName[10] = Aux10;
+            device->RealOut.ChannelName[11] = Aux11;
+            device->RealOut.ChannelName[12] = Aux12;
+            device->RealOut.ChannelName[13] = Aux13;
+            device->RealOut.ChannelName[14] = Aux14;
+            device->RealOut.ChannelName[15] = Aux15;
+        }
         break;
     }
 }
@@ -1661,9 +1651,7 @@ void SetDefaultChannelOrder(ALCdevice *device)
     case DevFmtQuad:
     case DevFmtX51:
     case DevFmtX61:
-    case DevFmtAmbi1:
-    case DevFmtAmbi2:
-    case DevFmtAmbi3:
+    case DevFmtAmbi3D:
         SetDefaultWFXChannelOrder(device);
         break;
     }
@@ -1901,16 +1889,15 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
 
         UpdateClockBase(device);
 
+        device->Frequency = freq;
+        device->FmtChans = schans;
+        device->FmtType = stype;
         if(schans == ALC_BFORMAT3D_SOFT)
         {
-            device->FmtChans = DevFmtAmbi1 + (aorder-1);
+            device->AmbiOrder = aorder;
             device->AmbiLayout = alayout;
             device->AmbiScale = ascale;
         }
-        else
-            device->FmtChans = schans;
-        device->Frequency = freq;
-        device->FmtType = stype;
         device->NumMonoSources = numMono;
         device->NumStereoSources = numStereo;
 
@@ -2944,8 +2931,7 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum para
 
 static inline ALCsizei NumAttrsForDevice(ALCdevice *device)
 {
-    if(device->Type == Loopback && device->FmtChans >= DevFmtAmbi1 &&
-       device->FmtChans <= DevFmtAmbi3)
+    if(device->Type == Loopback && device->FmtChans == DevFmtAmbi3D)
         return 23;
     return 17;
 }
@@ -3060,7 +3046,7 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC
             }
             else
             {
-                if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3)
+                if(device->FmtChans == DevFmtAmbi3D)
                 {
                     values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
                     values[i++] = device->AmbiLayout;
@@ -3069,17 +3055,12 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC
                     values[i++] = device->AmbiScale;
 
                     values[i++] = ALC_AMBISONIC_ORDER_SOFT;
-                    values[i++] = device->FmtChans-DevFmtAmbi1+1;
-
-                    values[i++] = ALC_FORMAT_CHANNELS_SOFT;
-                    values[i++] = ALC_BFORMAT3D_SOFT;
-                }
-                else
-                {
-                    values[i++] = ALC_FORMAT_CHANNELS_SOFT;
-                    values[i++] = device->FmtChans;
+                    values[i++] = device->AmbiOrder;
                 }
 
+                values[i++] = ALC_FORMAT_CHANNELS_SOFT;
+                values[i++] = device->FmtChans;
+
                 values[i++] = ALC_FORMAT_TYPE_SOFT;
                 values[i++] = device->FmtType;
             }
@@ -3133,10 +3114,7 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC
                 alcSetError(device, ALC_INVALID_DEVICE);
                 return 0;
             }
-            if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3)
-                values[0] = ALC_BFORMAT3D_SOFT;
-            else
-                values[0] = device->FmtChans;
+            values[0] = device->FmtChans;
             return 1;
 
         case ALC_FORMAT_TYPE_SOFT:
@@ -3149,8 +3127,7 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC
             return 1;
 
         case ALC_AMBISONIC_LAYOUT_SOFT:
-            if(device->Type != Loopback || !(device->FmtChans >= DevFmtAmbi1 &&
-                                             device->FmtChans <= DevFmtAmbi3))
+            if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
             {
                 alcSetError(device, ALC_INVALID_DEVICE);
                 return 0;
@@ -3159,8 +3136,7 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC
             return 1;
 
         case ALC_AMBISONIC_SCALING_SOFT:
-            if(device->Type != Loopback || !(device->FmtChans >= DevFmtAmbi1 &&
-                                             device->FmtChans <= DevFmtAmbi3))
+            if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
             {
                 alcSetError(device, ALC_INVALID_DEVICE);
                 return 0;
@@ -3169,13 +3145,12 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC
             return 1;
 
         case ALC_AMBISONIC_ORDER_SOFT:
-            if(device->Type != Loopback || !(device->FmtChans >= DevFmtAmbi1 &&
-                                             device->FmtChans <= DevFmtAmbi3))
+            if(device->Type != Loopback || device->FmtChans != DevFmtAmbi3D)
             {
                 alcSetError(device, ALC_INVALID_DEVICE);
                 return 0;
             }
-            values[0] = device->FmtChans - DevFmtAmbi1 + 1;
+            values[0] = device->AmbiOrder;
             return 1;
 
         case ALC_MONO_SOURCES:
@@ -3280,7 +3255,7 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname,
                     }
                     else
                     {
-                        if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3)
+                        if(device->FmtChans == DevFmtAmbi3D)
                         {
                             values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
                             values[i++] = device->AmbiLayout;
@@ -3289,17 +3264,12 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname,
                             values[i++] = device->AmbiScale;
 
                             values[i++] = ALC_AMBISONIC_ORDER_SOFT;
-                            values[i++] = device->FmtChans-DevFmtAmbi1+1;
-
-                            values[i++] = ALC_FORMAT_CHANNELS_SOFT;
-                            values[i++] = ALC_BFORMAT3D_SOFT;
-                        }
-                        else
-                        {
-                            values[i++] = ALC_FORMAT_CHANNELS_SOFT;
-                            values[i++] = device->FmtChans;
+                            values[i++] = device->AmbiOrder;
                         }
 
+                        values[i++] = ALC_FORMAT_CHANNELS_SOFT;
+                        values[i++] = device->FmtChans;
+
                         values[i++] = ALC_FORMAT_TYPE_SOFT;
                         values[i++] = device->FmtType;
                     }
@@ -3825,17 +3795,18 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
         static const struct {
             const char name[16];
             enum DevFmtChannels chans;
+            ALsizei order;
         } chanlist[] = {
-            { "mono",       DevFmtMono   },
-            { "stereo",     DevFmtStereo },
-            { "quad",       DevFmtQuad   },
-            { "surround51", DevFmtX51    },
-            { "surround61", DevFmtX61    },
-            { "surround71", DevFmtX71    },
-            { "surround51rear", DevFmtX51Rear },
-            { "ambi1", DevFmtAmbi1 },
-            { "ambi2", DevFmtAmbi2 },
-            { "ambi3", DevFmtAmbi3 },
+            { "mono",       DevFmtMono,   0 },
+            { "stereo",     DevFmtStereo, 0 },
+            { "quad",       DevFmtQuad,   0 },
+            { "surround51", DevFmtX51,    0 },
+            { "surround61", DevFmtX61,    0 },
+            { "surround71", DevFmtX71,    0 },
+            { "surround51rear", DevFmtX51Rear, 0 },
+            { "ambi1", DevFmtAmbi3D, 1 },
+            { "ambi2", DevFmtAmbi3D, 2 },
+            { "ambi3", DevFmtAmbi3D, 3 },
         };
         size_t i;
 
@@ -3844,6 +3815,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
             if(strcasecmp(chanlist[i].name, fmt) == 0)
             {
                 device->FmtChans = chanlist[i].chans;
+                device->AmbiOrder = chanlist[i].order;
                 device->Flags |= DEVICE_CHANNELS_REQUEST;
                 break;
             }
@@ -4118,6 +4090,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName,
         return NULL;
     }
     device->IsHeadphones = AL_FALSE;
+    device->AmbiOrder = 0;
     device->AmbiLayout = AmbiLayout_Default;
     device->AmbiScale = AmbiNorm_Default;
 
diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c
index 4a7b81ba..40b68779 100644
--- a/Alc/backends/alsa.c
+++ b/Alc/backends/alsa.c
@@ -755,7 +755,7 @@ static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self)
     }
     CHECK(snd_pcm_hw_params_set_format(self->pcmHandle, hp, format));
     /* test and set channels (implicitly sets frame bits) */
-    if(snd_pcm_hw_params_test_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans)) < 0)
+    if(snd_pcm_hw_params_test_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder)) < 0)
     {
         static const enum DevFmtChannels channellist[] = {
             DevFmtStereo,
@@ -768,14 +768,15 @@ static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self)
 
         for(k = 0;k < COUNTOF(channellist);k++)
         {
-            if(snd_pcm_hw_params_test_channels(self->pcmHandle, hp, ChannelsFromDevFmt(channellist[k])) >= 0)
+            if(snd_pcm_hw_params_test_channels(self->pcmHandle, hp, ChannelsFromDevFmt(channellist[k], 0)) >= 0)
             {
                 device->FmtChans = channellist[k];
+                device->AmbiOrder = 0;
                 break;
             }
         }
     }
-    CHECK(snd_pcm_hw_params_set_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans)));
+    CHECK(snd_pcm_hw_params_set_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder)));
     /* set rate (implicitly constrains period/buffer parameters) */
     if(!GetConfigValueBool(alstr_get_cstr(device->DeviceName), "alsa", "allow-resampler", 0) ||
        !(device->Flags&DEVICE_FREQUENCY_REQUEST))
@@ -1039,7 +1040,7 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name)
     /* set format (implicitly sets sample bits) */
     CHECK(snd_pcm_hw_params_set_format(self->pcmHandle, hp, format));
     /* set channels (implicitly sets frame bits) */
-    CHECK(snd_pcm_hw_params_set_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans)));
+    CHECK(snd_pcm_hw_params_set_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder)));
     /* set rate (implicitly constrains period/buffer parameters) */
     CHECK(snd_pcm_hw_params_set_rate(self->pcmHandle, hp, device->Frequency, 0));
     /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */
@@ -1063,7 +1064,7 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name)
     {
         self->ring = ll_ringbuffer_create(
             device->UpdateSize*device->NumUpdates + 1,
-            FrameSizeFromDevFmt(device->FmtChans, device->FmtType)
+            FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder)
         );
         if(!self->ring)
         {
diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c
index 435c0fae..ec926d3d 100644
--- a/Alc/backends/coreaudio.c
+++ b/Alc/backends/coreaudio.c
@@ -319,7 +319,7 @@ static ALCboolean ALCcoreAudioPlayback_reset(ALCcoreAudioPlayback *self)
     }
 
     /* setup callback */
-    self->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    self->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
     input.inputProc = ALCcoreAudioPlayback_MixerProc;
     input.inputProcRefCon = self;
 
@@ -608,9 +608,7 @@ static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar
         case DevFmtX51Rear:
         case DevFmtX61:
         case DevFmtX71:
-        case DevFmtAmbi1:
-        case DevFmtAmbi2:
-        case DevFmtAmbi3:
+        case DevFmtAmbi3D:
             ERR("%s not supported\n", DevFmtChannelsString(device->FmtChans));
             goto error;
     }
@@ -624,7 +622,7 @@ static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar
 
     // save requested format description for later use
     self->format = requestedFormat;
-    self->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    self->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
 
     // Use intermediate format for sample rate conversion (outputFormat)
     // Set sample rate to the same as hardware for resampling later
diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c
index 3dc297ff..f730dc95 100644
--- a/Alc/backends/dsound.c
+++ b/Alc/backends/dsound.c
@@ -244,7 +244,7 @@ FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr)
         return 1;
     }
 
-    FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
     FragSize = device->UpdateSize * FrameSize;
 
     IDirectSoundBuffer_GetCurrentPosition(self->Buffer, &LastCursor, NULL);
@@ -474,9 +474,7 @@ static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self)
             case DevFmtMono:
                 OutputType.dwChannelMask = SPEAKER_FRONT_CENTER;
                 break;
-            case DevFmtAmbi1:
-            case DevFmtAmbi2:
-            case DevFmtAmbi3:
+            case DevFmtAmbi3D:
                 device->FmtChans = DevFmtStereo;
                 /*fall-through*/
             case DevFmtStereo:
@@ -529,7 +527,7 @@ static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self)
 retry_open:
         hr = S_OK;
         OutputType.Format.wFormatTag = WAVE_FORMAT_PCM;
-        OutputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans);
+        OutputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
         OutputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
         OutputType.Format.nBlockAlign = OutputType.Format.nChannels*OutputType.Format.wBitsPerSample/8;
         OutputType.Format.nSamplesPerSec = device->Frequency;
@@ -736,98 +734,94 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi
             break;
     }
 
-    //DirectSoundCapture Init code
-    hr = DirectSoundCaptureCreate(guid, &self->DSC, NULL);
-    if(SUCCEEDED(hr))
+    memset(&InputType, 0, sizeof(InputType));
+    switch(device->FmtChans)
     {
-        memset(&InputType, 0, sizeof(InputType));
-
-        switch(device->FmtChans)
-        {
-            case DevFmtMono:
-                InputType.dwChannelMask = SPEAKER_FRONT_CENTER;
-                break;
-            case DevFmtStereo:
-                InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
-                                          SPEAKER_FRONT_RIGHT;
-                break;
-            case DevFmtQuad:
-                InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
-                                          SPEAKER_FRONT_RIGHT |
-                                          SPEAKER_BACK_LEFT |
-                                          SPEAKER_BACK_RIGHT;
-                break;
-            case DevFmtX51:
-                InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
-                                          SPEAKER_FRONT_RIGHT |
-                                          SPEAKER_FRONT_CENTER |
-                                          SPEAKER_LOW_FREQUENCY |
-                                          SPEAKER_SIDE_LEFT |
-                                          SPEAKER_SIDE_RIGHT;
-                break;
-            case DevFmtX51Rear:
-                InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
-                                          SPEAKER_FRONT_RIGHT |
-                                          SPEAKER_FRONT_CENTER |
-                                          SPEAKER_LOW_FREQUENCY |
-                                          SPEAKER_BACK_LEFT |
-                                          SPEAKER_BACK_RIGHT;
-                break;
-            case DevFmtX61:
-                InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
-                                          SPEAKER_FRONT_RIGHT |
-                                          SPEAKER_FRONT_CENTER |
-                                          SPEAKER_LOW_FREQUENCY |
-                                          SPEAKER_BACK_CENTER |
-                                          SPEAKER_SIDE_LEFT |
-                                          SPEAKER_SIDE_RIGHT;
-                break;
-            case DevFmtX71:
-                InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
-                                          SPEAKER_FRONT_RIGHT |
-                                          SPEAKER_FRONT_CENTER |
-                                          SPEAKER_LOW_FREQUENCY |
-                                          SPEAKER_BACK_LEFT |
-                                          SPEAKER_BACK_RIGHT |
-                                          SPEAKER_SIDE_LEFT |
-                                          SPEAKER_SIDE_RIGHT;
-                break;
-            case DevFmtAmbi1:
-            case DevFmtAmbi2:
-            case DevFmtAmbi3:
-                break;
-        }
+        case DevFmtMono:
+            InputType.dwChannelMask = SPEAKER_FRONT_CENTER;
+            break;
+        case DevFmtStereo:
+            InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
+                                      SPEAKER_FRONT_RIGHT;
+            break;
+        case DevFmtQuad:
+            InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
+                                      SPEAKER_FRONT_RIGHT |
+                                      SPEAKER_BACK_LEFT |
+                                      SPEAKER_BACK_RIGHT;
+            break;
+        case DevFmtX51:
+            InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
+                                      SPEAKER_FRONT_RIGHT |
+                                      SPEAKER_FRONT_CENTER |
+                                      SPEAKER_LOW_FREQUENCY |
+                                      SPEAKER_SIDE_LEFT |
+                                      SPEAKER_SIDE_RIGHT;
+            break;
+        case DevFmtX51Rear:
+            InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
+                                      SPEAKER_FRONT_RIGHT |
+                                      SPEAKER_FRONT_CENTER |
+                                      SPEAKER_LOW_FREQUENCY |
+                                      SPEAKER_BACK_LEFT |
+                                      SPEAKER_BACK_RIGHT;
+            break;
+        case DevFmtX61:
+            InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
+                                      SPEAKER_FRONT_RIGHT |
+                                      SPEAKER_FRONT_CENTER |
+                                      SPEAKER_LOW_FREQUENCY |
+                                      SPEAKER_BACK_CENTER |
+                                      SPEAKER_SIDE_LEFT |
+                                      SPEAKER_SIDE_RIGHT;
+            break;
+        case DevFmtX71:
+            InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
+                                      SPEAKER_FRONT_RIGHT |
+                                      SPEAKER_FRONT_CENTER |
+                                      SPEAKER_LOW_FREQUENCY |
+                                      SPEAKER_BACK_LEFT |
+                                      SPEAKER_BACK_RIGHT |
+                                      SPEAKER_SIDE_LEFT |
+                                      SPEAKER_SIDE_RIGHT;
+            break;
+        case DevFmtAmbi3D:
+            WARN("%s capture not supported\n", DevFmtChannelsString(device->FmtChans));
+            return ALC_INVALID_ENUM;
+    }
 
-        InputType.Format.wFormatTag = WAVE_FORMAT_PCM;
-        InputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans);
-        InputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
-        InputType.Format.nBlockAlign = InputType.Format.nChannels*InputType.Format.wBitsPerSample/8;
-        InputType.Format.nSamplesPerSec = device->Frequency;
-        InputType.Format.nAvgBytesPerSec = InputType.Format.nSamplesPerSec*InputType.Format.nBlockAlign;
-        InputType.Format.cbSize = 0;
+    InputType.Format.wFormatTag = WAVE_FORMAT_PCM;
+    InputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
+    InputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
+    InputType.Format.nBlockAlign = InputType.Format.nChannels*InputType.Format.wBitsPerSample/8;
+    InputType.Format.nSamplesPerSec = device->Frequency;
+    InputType.Format.nAvgBytesPerSec = InputType.Format.nSamplesPerSec*InputType.Format.nBlockAlign;
+    InputType.Format.cbSize = 0;
+    InputType.Samples.wValidBitsPerSample = InputType.Format.wBitsPerSample;
+    if(device->FmtType == DevFmtFloat)
+        InputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
+    else
+        InputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
 
-        if(InputType.Format.nChannels > 2 || device->FmtType == DevFmtFloat)
-        {
-            InputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
-            InputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
-            InputType.Samples.wValidBitsPerSample = InputType.Format.wBitsPerSample;
-            if(device->FmtType == DevFmtFloat)
-                InputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
-            else
-                InputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
-        }
+    if(InputType.Format.nChannels > 2 || device->FmtType == DevFmtFloat)
+    {
+        InputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
+        InputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
+    }
 
-        samples = device->UpdateSize * device->NumUpdates;
-        samples = maxu(samples, 100 * device->Frequency / 1000);
+    samples = device->UpdateSize * device->NumUpdates;
+    samples = maxu(samples, 100 * device->Frequency / 1000);
 
-        memset(&DSCBDescription, 0, sizeof(DSCBUFFERDESC));
-        DSCBDescription.dwSize = sizeof(DSCBUFFERDESC);
-        DSCBDescription.dwFlags = 0;
-        DSCBDescription.dwBufferBytes = samples * InputType.Format.nBlockAlign;
-        DSCBDescription.lpwfxFormat = &InputType.Format;
+    memset(&DSCBDescription, 0, sizeof(DSCBUFFERDESC));
+    DSCBDescription.dwSize = sizeof(DSCBUFFERDESC);
+    DSCBDescription.dwFlags = 0;
+    DSCBDescription.dwBufferBytes = samples * InputType.Format.nBlockAlign;
+    DSCBDescription.lpwfxFormat = &InputType.Format;
 
+    //DirectSoundCapture Init code
+    hr = DirectSoundCaptureCreate(guid, &self->DSC, NULL);
+    if(SUCCEEDED(hr))
         hr = IDirectSoundCapture_CreateCaptureBuffer(self->DSC, &DSCBDescription, &self->DSCbuffer, NULL);
-    }
     if(SUCCEEDED(hr))
     {
          self->Ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates + 1,
@@ -921,7 +915,7 @@ static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self)
     if(!device->Connected)
         goto done;
 
-    FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
     BufferBytes = self->BufferBytes;
     LastCursor = self->Cursor;
 
diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c
index cce828e9..f43f8527 100644
--- a/Alc/backends/jack.c
+++ b/Alc/backends/jack.c
@@ -228,7 +228,9 @@ static int ALCjackPlayback_bufferSizeNotify(jack_nframes_t numframes, void *arg)
     TRACE("%u update size x%u\n", device->UpdateSize, device->NumUpdates);
 
     ll_ringbuffer_free(self->Ring);
-    self->Ring = ll_ringbuffer_create(bufsize, FrameSizeFromDevFmt(device->FmtChans, device->FmtType));
+    self->Ring = ll_ringbuffer_create(bufsize,
+        FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder)
+    );
     if(!self->Ring)
     {
         ERR("Failed to reallocate ringbuffer\n");
@@ -423,7 +425,7 @@ static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self)
     /* Force 32-bit float output. */
     device->FmtType = DevFmtFloat;
 
-    numchans = ChannelsFromDevFmt(device->FmtChans);
+    numchans = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
     for(i = 0;i < numchans;i++)
     {
         char name[64];
@@ -452,7 +454,9 @@ static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self)
     }
 
     ll_ringbuffer_free(self->Ring);
-    self->Ring = ll_ringbuffer_create(bufsize, FrameSizeFromDevFmt(device->FmtChans, device->FmtType));
+    self->Ring = ll_ringbuffer_create(bufsize,
+        FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder)
+    );
     if(!self->Ring)
     {
         ERR("Failed to allocate ringbuffer\n");
diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c
index a70607e4..43d8429d 100644
--- a/Alc/backends/mmdevapi.c
+++ b/Alc/backends/mmdevapi.c
@@ -922,9 +922,7 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self)
             OutputType.Format.nChannels = 1;
             OutputType.dwChannelMask = MONO;
             break;
-        case DevFmtAmbi1:
-        case DevFmtAmbi2:
-        case DevFmtAmbi3:
+        case DevFmtAmbi3D:
             device->FmtChans = DevFmtStereo;
             /*fall-through*/
         case DevFmtStereo:
@@ -1367,7 +1365,8 @@ FORCE_ALIGN int ALCmmdevCapture_recordProc(void *arg)
                 }
                 else
                 {
-                    size_t framesize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+                    size_t framesize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType,
+                                                           device->AmbiOrder);
                     ALuint len1 = minu(data[0].len, numsamples);
                     ALuint len2 = minu(data[1].len, numsamples-len1);
 
@@ -1636,9 +1635,7 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self)
             OutputType.dwChannelMask = X7DOT1;
             break;
 
-        case DevFmtAmbi1:
-        case DevFmtAmbi2:
-        case DevFmtAmbi3:
+        case DevFmtAmbi3D:
             return E_FAIL;
     }
     switch(device->FmtType)
@@ -1767,7 +1764,7 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self)
     if(device->Frequency != OutputType.Format.nSamplesPerSec || device->FmtType != srcType)
     {
         self->SampleConv = CreateSampleConverter(
-            srcType, device->FmtType, ChannelsFromDevFmt(device->FmtChans),
+            srcType, device->FmtType, ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder),
             OutputType.Format.nSamplesPerSec, device->Frequency
         );
         if(!self->SampleConv)
@@ -1800,7 +1797,7 @@ static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self)
     buffer_len = maxu(device->UpdateSize*device->NumUpdates + 1, buffer_len);
     ll_ringbuffer_free(self->Ring);
     self->Ring = ll_ringbuffer_create(buffer_len,
-        FrameSizeFromDevFmt(device->FmtChans, device->FmtType)
+        FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder)
     );
     if(!self->Ring)
     {
diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c
index 41f55120..622437b8 100644
--- a/Alc/backends/opensl.c
+++ b/Alc/backends/opensl.c
@@ -65,9 +65,7 @@ static SLuint32 GetChannelMask(enum DevFmtChannels chans)
                                SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
                                SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT|
                                SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
-        case DevFmtAmbi1:
-        case DevFmtAmbi2:
-        case DevFmtAmbi3:
+        case DevFmtAmbi3D:
             break;
     }
     return 0;
@@ -513,7 +511,7 @@ static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self)
     device->FmtType = DevFmtShort;
 
     SetDefaultWFXChannelOrder(device);
-    self->mFrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    self->mFrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
 
 
     loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
@@ -522,7 +520,7 @@ static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self)
 #ifdef SL_DATAFORMAT_PCM_EX
     SLDataFormat_PCM_EX format_pcm;
     format_pcm.formatType = SL_DATAFORMAT_PCM_EX;
-    format_pcm.numChannels = ChannelsFromDevFmt(device->FmtChans);
+    format_pcm.numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
     format_pcm.sampleRate = device->Frequency * 1000;
     format_pcm.bitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
     format_pcm.containerSize = format_pcm.bitsPerSample;
@@ -533,7 +531,7 @@ static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self)
 #else
     SLDataFormat_PCM format_pcm;
     format_pcm.formatType = SL_DATAFORMAT_PCM;
-    format_pcm.numChannels = ChannelsFromDevFmt(device->FmtChans);
+    format_pcm.numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
     format_pcm.samplesPerSec = device->Frequency * 1000;
     format_pcm.bitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
     format_pcm.containerSize = format_pcm.bitsPerSample;
diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c
index 6706405d..6774a789 100644
--- a/Alc/backends/oss.c
+++ b/Alc/backends/oss.c
@@ -280,7 +280,7 @@ static int ALCplaybackOSS_mixerProc(void *ptr)
     SetRTPriority();
     althrd_setname(althrd_current(), MIXER_THREAD_NAME);
 
-    frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
 
     ALCplaybackOSS_lock(self);
     while(!ATOMIC_LOAD_SEQ(&self->killNow) && device->Connected)
@@ -418,7 +418,7 @@ static ALCboolean ALCplaybackOSS_reset(ALCplaybackOSS *self)
     }
 
     periods = device->NumUpdates;
-    numChannels = ChannelsFromDevFmt(device->FmtChans);
+    numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
     ossSpeed = device->Frequency;
     frameSize = numChannels * BytesFromDevFmt(device->FmtType);
     /* According to the OSS spec, 16 bytes (log2(16)) is the minimum. */
@@ -444,7 +444,7 @@ static ALCboolean ALCplaybackOSS_reset(ALCplaybackOSS *self)
     }
 #undef CHECKERR
 
-    if((int)ChannelsFromDevFmt(device->FmtChans) != numChannels)
+    if((int)ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder) != numChannels)
     {
         ERR("Failed to set %s, got %d channels instead\n", DevFmtChannelsString(device->FmtChans), numChannels);
         return ALC_FALSE;
@@ -471,7 +471,9 @@ static ALCboolean ALCplaybackOSS_start(ALCplaybackOSS *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
 
-    self->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    self->data_size = device->UpdateSize * FrameSizeFromDevFmt(
+        device->FmtChans, device->FmtType, device->AmbiOrder
+    );
     self->mix_data = calloc(1, self->data_size);
 
     ATOMIC_STORE_SEQ(&self->killNow, AL_FALSE);
@@ -543,7 +545,7 @@ static int ALCcaptureOSS_recordProc(void *ptr)
     SetRTPriority();
     althrd_setname(althrd_current(), RECORD_THREAD_NAME);
 
-    frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
 
     while(!ATOMIC_LOAD_SEQ(&self->killNow))
     {
@@ -660,7 +662,7 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name)
     }
 
     periods = 4;
-    numChannels = ChannelsFromDevFmt(device->FmtChans);
+    numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
     frameSize = numChannels * BytesFromDevFmt(device->FmtType);
     ossSpeed = device->Frequency;
     log2FragmentSize = log2i(device->UpdateSize * device->NumUpdates *
@@ -690,7 +692,7 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name)
     }
 #undef CHECKERR
 
-    if((int)ChannelsFromDevFmt(device->FmtChans) != numChannels)
+    if((int)ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder) != numChannels)
     {
         ERR("Failed to set %s, got %d channels instead\n", DevFmtChannelsString(device->FmtChans), numChannels);
         close(self->fd);
diff --git a/Alc/backends/portaudio.c b/Alc/backends/portaudio.c
index b713f330..807e8000 100644
--- a/Alc/backends/portaudio.c
+++ b/Alc/backends/portaudio.c
@@ -399,7 +399,7 @@ static ALCenum ALCportCapture_open(ALCportCapture *self, const ALCchar *name)
 
     samples = device->UpdateSize * device->NumUpdates;
     samples = maxu(samples, 100 * device->Frequency / 1000);
-    frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
 
     self->ring = ll_ringbuffer_create(samples, frame_size);
     if(self->ring == NULL) return ALC_INVALID_VALUE;
@@ -433,7 +433,7 @@ static ALCenum ALCportCapture_open(ALCportCapture *self, const ALCchar *name)
             ERR("%s samples not supported\n", DevFmtTypeString(device->FmtType));
             return ALC_INVALID_VALUE;
     }
-    self->params.channelCount = ChannelsFromDevFmt(device->FmtChans);
+    self->params.channelCount = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
 
     err = Pa_OpenStream(&self->stream, &self->params, NULL,
         device->Frequency, paFramesPerBufferUnspecified, paNoFlag,
diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c
index 26557ea8..9e2d4f73 100644
--- a/Alc/backends/pulseaudio.c
+++ b/Alc/backends/pulseaudio.c
@@ -1014,7 +1014,7 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
             break;
     }
     self->spec.rate = device->Frequency;
-    self->spec.channels = ChannelsFromDevFmt(device->FmtChans);
+    self->spec.channels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
 
     if(pa_sample_spec_valid(&self->spec) == 0)
     {
@@ -1028,9 +1028,7 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
         case DevFmtMono:
             mapname = "mono";
             break;
-        case DevFmtAmbi1:
-        case DevFmtAmbi2:
-        case DevFmtAmbi3:
+        case DevFmtAmbi3D:
             device->FmtChans = DevFmtStereo;
             /*fall-through*/
         case DevFmtStereo:
@@ -1464,6 +1462,7 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name)
     ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
     const char *pulse_name = NULL;
     pa_stream_flags_t flags = 0;
+    const char *mapname = NULL;
     pa_channel_map chanmap;
     ALuint samples;
 
@@ -1488,9 +1487,6 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name)
 
     pa_threaded_mainloop_lock(self->loop);
 
-    self->spec.rate = device->Frequency;
-    self->spec.channels = ChannelsFromDevFmt(device->FmtChans);
-
     switch(device->FmtType)
     {
         case DevFmtUByte:
@@ -1513,6 +1509,44 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name)
             goto fail;
     }
 
+    switch(device->FmtChans)
+    {
+        case DevFmtMono:
+            mapname = "mono";
+            break;
+        case DevFmtStereo:
+            mapname = "front-left,front-right";
+            break;
+        case DevFmtQuad:
+            mapname = "front-left,front-right,rear-left,rear-right";
+            break;
+        case DevFmtX51:
+            mapname = "front-left,front-right,front-center,lfe,side-left,side-right";
+            break;
+        case DevFmtX51Rear:
+            mapname = "front-left,front-right,front-center,lfe,rear-left,rear-right";
+            break;
+        case DevFmtX61:
+            mapname = "front-left,front-right,front-center,lfe,rear-center,side-left,side-right";
+            break;
+        case DevFmtX71:
+            mapname = "front-left,front-right,front-center,lfe,rear-left,rear-right,side-left,side-right";
+            break;
+        case DevFmtAmbi3D:
+            ERR("%s capture samples not supported\n", DevFmtChannelsString(device->FmtChans));
+            pa_threaded_mainloop_unlock(self->loop);
+            goto fail;
+    }
+    if(!pa_channel_map_parse(&chanmap, mapname))
+    {
+        ERR("Failed to build channel map for %s\n", DevFmtChannelsString(device->FmtChans));
+        pa_threaded_mainloop_unlock(self->loop);
+        return ALC_FALSE;
+    }
+
+    self->spec.rate = device->Frequency;
+    self->spec.channels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
+
     if(pa_sample_spec_valid(&self->spec) == 0)
     {
         ERR("Invalid sample format\n");
diff --git a/Alc/backends/qsa.c b/Alc/backends/qsa.c
index 9563a918..9da55b59 100644
--- a/Alc/backends/qsa.c
+++ b/Alc/backends/qsa.c
@@ -179,7 +179,9 @@ FORCE_ALIGN static int qsa_proc_playback(void* ptr)
     param.sched_priority=param.sched_curpriority+1;
     SchedSet(0, 0, SCHED_NOCHANGE, &param);
 
-    const ALint frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    const ALint frame_size = FrameSizeFromDevFmt(
+        device->FmtChans, device->FmtType, device->AmbiOrder
+    );
 
     V0(device->Backend,lock)();
     while(!data->killNow)
@@ -361,14 +363,14 @@ static ALCboolean qsa_reset_playback(ALCdevice* device)
     data->cparams.start_mode=SND_PCM_START_FULL;
     data->cparams.stop_mode=SND_PCM_STOP_STOP;
 
-    data->cparams.buf.block.frag_size=device->UpdateSize*
-        ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType);
+    data->cparams.buf.block.frag_size=device->UpdateSize *
+        FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
     data->cparams.buf.block.frags_max=device->NumUpdates;
     data->cparams.buf.block.frags_min=device->NumUpdates;
 
     data->cparams.format.interleave=1;
     data->cparams.format.rate=device->Frequency;
-    data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans);
+    data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
     data->cparams.format.format=format;
 
     if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0)
@@ -552,7 +554,7 @@ static ALCboolean qsa_reset_playback(ALCdevice* device)
     SetDefaultChannelOrder(device);
 
     device->UpdateSize=data->csetup.buf.block.frag_size/
-        (ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType));
+        FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
     device->NumUpdates=data->csetup.buf.block.frags;
 
     data->size=data->csetup.buf.block.frag_size;
@@ -684,13 +686,13 @@ static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName)
     data->cparams.stop_mode=SND_PCM_STOP_STOP;
 
     data->cparams.buf.block.frag_size=device->UpdateSize*
-        ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType);
+        FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
     data->cparams.buf.block.frags_max=device->NumUpdates;
     data->cparams.buf.block.frags_min=device->NumUpdates;
 
     data->cparams.format.interleave=1;
     data->cparams.format.rate=device->Frequency;
-    data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans);
+    data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
     data->cparams.format.format=format;
 
     if(snd_pcm_plugin_params(data->pcmHandle, &data->cparams) < 0)
@@ -749,7 +751,7 @@ static ALCuint qsa_available_samples(ALCdevice* device)
 {
     qsa_data* data=(qsa_data*)device->ExtraData;
     snd_pcm_channel_status_t status;
-    ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    ALint frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
     ALint free_size;
     int rstatus;
 
@@ -785,7 +787,7 @@ static ALCenum qsa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint s
     int selectret;
     struct timeval timeout;
     int bytes_read;
-    ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
     ALint len=samples*frame_size;
     int rstatus;
 
diff --git a/Alc/backends/sndio.c b/Alc/backends/sndio.c
index ac2dc03f..47e05353 100644
--- a/Alc/backends/sndio.c
+++ b/Alc/backends/sndio.c
@@ -98,7 +98,7 @@ static int ALCsndioBackend_mixerProc(void *ptr)
     SetRTPriority();
     althrd_setname(althrd_current(), MIXER_THREAD_NAME);
 
-    frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
 
     while(!self->killNow && device->Connected)
     {
@@ -245,7 +245,9 @@ static ALCboolean ALCsndioBackend_start(ALCsndioBackend *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
 
-    self->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    self->data_size = device->UpdateSize * FrameSizeFromDevFmt(
+        device->FmtChans, device->FmtType, device->AmbiOrder
+    );
     al_free(self->mix_data);
     self->mix_data = al_calloc(16, self->data_size);
 
diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c
index 98c00525..5b3f6136 100644
--- a/Alc/backends/solaris.c
+++ b/Alc/backends/solaris.c
@@ -116,7 +116,7 @@ static int ALCsolarisBackend_mixerProc(void *ptr)
     SetRTPriority();
     althrd_setname(althrd_current(), MIXER_THREAD_NAME);
 
-    frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
 
     ALCsolarisBackend_lock(self);
     while(!ATOMIC_LOAD_SEQ(&self->killNow) && device->Connected)
@@ -209,7 +209,7 @@ static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self)
 
     if(device->FmtChans != DevFmtMono)
         device->FmtChans = DevFmtStereo;
-    numChannels = ChannelsFromDevFmt(device->FmtChans);
+    numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
     info.play.channels = numChannels;
 
     switch(device->FmtType)
@@ -243,9 +243,9 @@ static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self)
         return ALC_FALSE;
     }
 
-    if(ChannelsFromDevFmt(device->FmtChans) != (ALsizei)info.play.channels)
+    if(ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder) != (ALsizei)info.play.channels)
     {
-        ERR("Could not set %d channels, got %d instead\n", ChannelsFromDevFmt(device->FmtChans), info.play.channels);
+        ERR("Failed to set %s, got %u channels instead\n", DevFmtChannelsString(device->FmtChans), info.play.channels);
         return ALC_FALSE;
     }
 
@@ -265,7 +265,9 @@ static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self)
     SetDefaultChannelOrder(device);
 
     free(self->mix_data);
-    self->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    self->data_size = device->UpdateSize * FrameSizeFromDevFmt(
+        device->FmtChans, device->FmtType, device->AmbiOrder
+    );
     self->mix_data = calloc(1, self->data_size);
 
     return ALC_TRUE;
diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c
index 36d7cbca..c72a632b 100644
--- a/Alc/backends/wave.c
+++ b/Alc/backends/wave.c
@@ -127,7 +127,7 @@ static int ALCwaveBackend_mixerProc(void *ptr)
 
     althrd_setname(althrd_current(), MIXER_THREAD_NAME);
 
-    frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
 
     done = 0;
     if(altimespec_get(&start, AL_TIME_UTC) != AL_TIME_UTC)
@@ -251,7 +251,10 @@ static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self)
     clearerr(self->mFile);
 
     if(GetConfigValueBool(NULL, "wave", "bformat", 0))
-        device->FmtChans = DevFmtAmbi1;
+    {
+        device->FmtChans = DevFmtAmbi3D;
+        device->AmbiOrder = 1;
+    }
 
     switch(device->FmtType)
     {
@@ -279,9 +282,7 @@ static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self)
         case DevFmtX51Rear: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020; break;
         case DevFmtX61: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x100 | 0x200 | 0x400; break;
         case DevFmtX71: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x200 | 0x400; break;
-        case DevFmtAmbi1:
-        case DevFmtAmbi2:
-        case DevFmtAmbi3:
+        case DevFmtAmbi3D:
             /* .amb output requires FuMa */
             device->AmbiLayout = AmbiLayout_FuMa;
             device->AmbiScale = AmbiNorm_FuMa;
@@ -290,14 +291,14 @@ static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self)
             break;
     }
     bits = BytesFromDevFmt(device->FmtType) * 8;
-    channels = ChannelsFromDevFmt(device->FmtChans);
+    channels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
 
-    fprintf(self->mFile, "RIFF");
+    fputs("RIFF", self->mFile);
     fwrite32le(0xFFFFFFFF, self->mFile); // 'RIFF' header len; filled in at close
 
-    fprintf(self->mFile, "WAVE");
+    fputs("WAVE", self->mFile);
 
-    fprintf(self->mFile, "fmt ");
+    fputs("fmt ", self->mFile);
     fwrite32le(40, self->mFile); // 'fmt ' header len; 40 bytes for EXTENSIBLE
 
     // 16-bit val, format type id (extensible: 0xFFFE)
@@ -323,7 +324,7 @@ static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self)
                                (isbformat ? SUBTYPE_BFORMAT_PCM : SUBTYPE_PCM)), 1, 16, self->mFile);
     (void)val;
 
-    fprintf(self->mFile, "data");
+    fputs("data", self->mFile);
     fwrite32le(0xFFFFFFFF, self->mFile); // 'data' header len; filled in at close
 
     if(ferror(self->mFile))
@@ -342,7 +343,9 @@ static ALCboolean ALCwaveBackend_start(ALCwaveBackend *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
 
-    self->mSize = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    self->mSize = device->UpdateSize * FrameSizeFromDevFmt(
+        device->FmtChans, device->FmtType, device->AmbiOrder
+    );
     self->mBuffer = malloc(self->mSize);
     if(!self->mBuffer)
     {
diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c
index da0d67a1..b5b3cdb6 100644
--- a/Alc/backends/winmm.c
+++ b/Alc/backends/winmm.c
@@ -382,7 +382,7 @@ static ALCboolean ALCwinmmPlayback_start(ALCwinmmPlayback *self)
 
     // Create 4 Buffers
     BufferSize  = device->UpdateSize*device->NumUpdates / 4;
-    BufferSize *= FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    BufferSize *= FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
 
     BufferData = calloc(4, BufferSize);
     for(i = 0;i < 4;i++)
@@ -563,9 +563,7 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name)
         case DevFmtX51Rear:
         case DevFmtX61:
         case DevFmtX71:
-        case DevFmtAmbi1:
-        case DevFmtAmbi2:
-        case DevFmtAmbi3:
+        case DevFmtAmbi3D:
             return ALC_INVALID_ENUM;
     }
 
@@ -586,7 +584,7 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name)
     memset(&self->Format, 0, sizeof(WAVEFORMATEX));
     self->Format.wFormatTag = ((device->FmtType == DevFmtFloat) ?
                                WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM);
-    self->Format.nChannels = ChannelsFromDevFmt(device->FmtChans);
+    self->Format.nChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
     self->Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
     self->Format.nBlockAlign = self->Format.wBitsPerSample *
                                self->Format.nChannels / 8;
diff --git a/Alc/converter.c b/Alc/converter.c
index 38d51d47..56af8ff0 100644
--- a/Alc/converter.c
+++ b/Alc/converter.c
@@ -389,7 +389,7 @@ void ChannelConverterInput(ChannelConverter *converter, const ALvoid *src, ALflo
     if(converter->mSrcChans == converter->mDstChans)
     {
         LoadSamples(dst, src, 1, converter->mSrcType,
-                    frames*ChannelsFromDevFmt(converter->mSrcChans));
+                    frames*ChannelsFromDevFmt(converter->mSrcChans, 0));
         return;
     }
 
diff --git a/Alc/panning.c b/Alc/panning.c
index dcdcf36d..e4941720 100644
--- a/Alc/panning.c
+++ b/Alc/panning.c
@@ -620,13 +620,11 @@ static void InitPanning(ALCdevice *device)
             coeffcount = 16;
             break;
 
-        case DevFmtAmbi1:
-        case DevFmtAmbi2:
-        case DevFmtAmbi3:
+        case DevFmtAmbi3D:
             break;
     }
 
-    if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3)
+    if(device->FmtChans == DevFmtAmbi3D)
     {
         const char *devname = alstr_get_cstr(device->DeviceName);
         const ALsizei *acnmap = (device->AmbiLayout == AmbiLayout_FuMa) ? FuMa2ACN : ACN2ACN;
@@ -635,9 +633,9 @@ static void InitPanning(ALCdevice *device)
                                   /*(device->AmbiScale == AmbiNorm_N3D) ?*/ UnitScale;
         ALfloat nfc_delay = 0.0f;
 
-        count = (device->FmtChans == DevFmtAmbi3) ? 16 :
-                (device->FmtChans == DevFmtAmbi2) ? 9 :
-                (device->FmtChans == DevFmtAmbi1) ? 4 : 1;
+        count = (device->AmbiOrder == 3) ? 16 :
+                (device->AmbiOrder == 2) ? 9 :
+                (device->AmbiOrder == 1) ? 4 : 1;
         for(i = 0;i < count;i++)
         {
             ALsizei acn = acnmap[i];
@@ -647,7 +645,7 @@ static void InitPanning(ALCdevice *device)
         device->Dry.CoeffCount = 0;
         device->Dry.NumChannels = count;
 
-        if(device->FmtChans == DevFmtAmbi1)
+        if(device->AmbiOrder < 2)
         {
             device->FOAOut.Ambi = device->Dry.Ambi;
             device->FOAOut.CoeffCount = device->Dry.CoeffCount;
@@ -674,10 +672,7 @@ static void InitPanning(ALCdevice *device)
         {
             nfc_delay = clampf(nfc_delay, 0.001f, 1000.0f);
             InitNearFieldCtrl(device, nfc_delay * SPEEDOFSOUNDMETRESPERSEC,
-                              (device->FmtChans == DevFmtAmbi3) ? 3 :
-                              (device->FmtChans == DevFmtAmbi2) ? 2 : 1,
-                              true
-            );
+                              device->AmbiOrder, true);
         }
     }
     else
@@ -861,7 +856,7 @@ static void InitHQPanning(ALCdevice *device, const AmbDecConf *conf, const ALsiz
         device->FOAOut.NumChannels = count;
     }
 
-    device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans);
+    device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
 
     avg_dist = 0.0f;
     for(i = 0;i < conf->NumSpeakers;i++)
@@ -963,7 +958,7 @@ static void InitHrtfPanning(ALCdevice *device, bool hoa_mode)
         ambiup_reset(device->AmbiUp, device);
     }
 
-    device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans);
+    device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
 
     device->Hrtf->IrSize = BuildBFormatHrtf(device->HrtfHandle,
         device->Hrtf, device->Dry.NumChannels,
@@ -992,7 +987,7 @@ static void InitUhjPanning(ALCdevice *device)
     device->FOAOut.CoeffCount = device->Dry.CoeffCount;
     device->FOAOut.NumChannels = 0;
 
-    device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans);
+    device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
 }
 
 void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf_appreq, enum HrtfRequestMode hrtf_userreq)
@@ -1049,9 +1044,7 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf
             /* Mono, Stereo, and Ambisonics output don't use custom decoders. */
             case DevFmtMono:
             case DevFmtStereo:
-            case DevFmtAmbi1:
-            case DevFmtAmbi2:
-            case DevFmtAmbi3:
+            case DevFmtAmbi3D:
                 break;
         }
         if(layout)
@@ -1085,7 +1078,7 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf
         {
             bformatdec_free(device->AmbiDecoder);
             device->AmbiDecoder = NULL;
-            if(device->FmtChans > DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3)
+            if(device->FmtChans == DevFmtAmbi3D && device->AmbiOrder == 1)
             {
                 if(!device->AmbiUp)
                     device->AmbiUp = ambiup_alloc();
-- 
cgit v1.2.3