Maarten Lankhorst : mmdevapi: Implement audio formats.

Alexandre Julliard julliard at winehq.org
Tue Apr 20 11:32:23 CDT 2010


Module: wine
Branch: master
Commit: bcaa470607b771ca4eb9b232dc8f944497a0c8b7
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=bcaa470607b771ca4eb9b232dc8f944497a0c8b7

Author: Maarten Lankhorst <m.b.lankhorst at gmail.com>
Date:   Mon Apr 19 11:52:50 2010 +0200

mmdevapi: Implement audio formats.

---

 dlls/mmdevapi/audio.c |  147 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 145 insertions(+), 2 deletions(-)

diff --git a/dlls/mmdevapi/audio.c b/dlls/mmdevapi/audio.c
index baaa943..fcefc5a 100644
--- a/dlls/mmdevapi/audio.c
+++ b/dlls/mmdevapi/audio.c
@@ -78,10 +78,153 @@ typedef struct ACImpl {
 
 static const IAudioClientVtbl ACImpl_Vtbl;
 
+static int get_format_PCM(WAVEFORMATEX *format)
+{
+    if (format->nChannels > 2) {
+        FIXME("nChannels > 2 not documented for WAVE_FORMAT_PCM!\n");
+        return 0;
+    }
+
+    format->cbSize = 0;
+
+    if (format->nBlockAlign != format->wBitsPerSample/8*format->nChannels) {
+        WARN("Invalid nBlockAlign %u, from %u %u\n",
+             format->nBlockAlign, format->wBitsPerSample, format->nChannels);
+        return 0;
+    }
+
+    switch (format->wBitsPerSample) {
+        case 8: {
+            switch (format->nChannels) {
+            case 1: return AL_FORMAT_MONO8;
+            case 2: return AL_FORMAT_STEREO8;
+            }
+        }
+        case 16: {
+            switch (format->nChannels) {
+            case 1: return AL_FORMAT_MONO16;
+            case 2: return AL_FORMAT_STEREO16;
+            }
+        }
+    }
+
+    if (!(format->wBitsPerSample % 8))
+        WARN("Could not get OpenAL format (%d-bit, %d channels)\n",
+             format->wBitsPerSample, format->nChannels);
+    return 0;
+}
+
+/* Speaker configs */
+#define MONO SPEAKER_FRONT_CENTER
+#define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)
+#define REAR (SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
+#define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
+#define X5DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
+#define X6DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_CENTER|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
+#define X7DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
+
+static int get_format_EXT(WAVEFORMATEX *format)
+{
+    WAVEFORMATEXTENSIBLE *wfe;
+
+    if(format->cbSize < sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX)) {
+        WARN("Invalid cbSize specified for WAVE_FORMAT_EXTENSIBLE (%d)\n", format->cbSize);
+        return 0;
+    }
+
+    wfe = (WAVEFORMATEXTENSIBLE*)format;
+    wfe->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
+    if (wfe->Samples.wValidBitsPerSample &&
+        wfe->Samples.wValidBitsPerSample != format->wBitsPerSample) {
+        FIXME("wValidBitsPerSample(%u) != wBitsPerSample(%u) unsupported\n",
+              wfe->Samples.wValidBitsPerSample, format->wBitsPerSample);
+        return 0;
+    }
+
+    TRACE("Extensible values:\n"
+          "    Samples     = %d\n"
+          "    ChannelMask = 0x%08x\n"
+          "    SubFormat   = %s\n",
+          wfe->Samples.wReserved, wfe->dwChannelMask,
+          debugstr_guid(&wfe->SubFormat));
+
+    if (wfe->dwChannelMask != MONO
+        && wfe->dwChannelMask != STEREO
+        && !palIsExtensionPresent("AL_EXT_MCFORMATS")) {
+        /* QUAD PCM might still work, special case */
+        if (palIsExtensionPresent("AL_LOKI_quadriphonic")
+            && IsEqualGUID(&wfe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)
+            && wfe->dwChannelMask == QUAD) {
+            if (format->wBitsPerSample == 16)
+                return AL_FORMAT_QUAD16_LOKI;
+            else if (format->wBitsPerSample == 8)
+                return AL_FORMAT_QUAD8_LOKI;
+        }
+        WARN("Not all formats available\n");
+        return 0;
+    }
+
+    if(IsEqualGUID(&wfe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) {
+        if (format->wBitsPerSample == 8) {
+            switch (wfe->dwChannelMask) {
+            case   MONO: return AL_FORMAT_MONO8;
+            case STEREO: return AL_FORMAT_STEREO8;
+            case   REAR: return AL_FORMAT_REAR8;
+            case   QUAD: return AL_FORMAT_QUAD8;
+            case X5DOT1: return AL_FORMAT_51CHN8;
+            case X6DOT1: return AL_FORMAT_61CHN8;
+            case X7DOT1: return AL_FORMAT_71CHN8;
+            default: break;
+            }
+        } else if (format->wBitsPerSample  == 16) {
+            switch (wfe->dwChannelMask) {
+            case   MONO: return AL_FORMAT_MONO16;
+            case STEREO: return AL_FORMAT_STEREO16;
+            case   REAR: return AL_FORMAT_REAR16;
+            case   QUAD: return AL_FORMAT_QUAD16;
+            case X5DOT1: return AL_FORMAT_51CHN16;
+            case X6DOT1: return AL_FORMAT_61CHN16;
+            case X7DOT1: return AL_FORMAT_71CHN16;
+            default: break;
+            }
+        }
+        else if (!(format->wBitsPerSample  % 8))
+            ERR("Could not get OpenAL PCM format (%d-bit, mask 0x%08x)\n",
+                format->wBitsPerSample, wfe->dwChannelMask);
+        return 0;
+    }
+    else if(IsEqualGUID(&wfe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
+        if (format->wBitsPerSample != 32) {
+            WARN("Invalid valid bits %u/32\n", format->wBitsPerSample);
+            return 0;
+        }
+        switch (wfe->dwChannelMask) {
+        case   MONO: return AL_FORMAT_MONO_FLOAT32;
+        case STEREO: return AL_FORMAT_STEREO_FLOAT32;
+        case   REAR: return AL_FORMAT_REAR32;
+        case   QUAD: return AL_FORMAT_QUAD32;
+        case X5DOT1: return AL_FORMAT_51CHN32;
+        case X6DOT1: return AL_FORMAT_61CHN32;
+        case X7DOT1: return AL_FORMAT_71CHN32;
+        default:
+            ERR("Could not get OpenAL float format (%d-bit, mask 0x%08x)\n",
+                format->wBitsPerSample, wfe->dwChannelMask);
+            return 0;
+        }
+    }
+    else if (!IsEqualGUID(&wfe->SubFormat, &GUID_NULL))
+        ERR("Unhandled extensible format: %s\n", debugstr_guid(&wfe->SubFormat));
+    return 0;
+}
+
 static ALint get_format(WAVEFORMATEX *in)
 {
-    FIXME("stub\n");
-    return AL_FORMAT_STEREO_FLOAT32;
+    int ret = 0;
+    if (in->wFormatTag == WAVE_FORMAT_PCM)
+        ret = get_format_PCM(in);
+    else if (in->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
+        ret = get_format_EXT(in);
+    return ret;
 }
 
 static REFERENCE_TIME gettime(void) {




More information about the wine-cvs mailing list