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