summaryrefslogtreecommitdiffstats
path: root/src/plugins/windowsaudio
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/windowsaudio')
-rw-r--r--src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp199
-rw-r--r--src/plugins/windowsaudio/qwindowsaudiodeviceinfo.h6
-rw-r--r--src/plugins/windowsaudio/qwindowsaudioinput.cpp21
-rw-r--r--src/plugins/windowsaudio/qwindowsaudioinput.h5
-rw-r--r--src/plugins/windowsaudio/qwindowsaudiooutput.cpp119
-rw-r--r--src/plugins/windowsaudio/qwindowsaudiooutput.h5
-rw-r--r--src/plugins/windowsaudio/qwindowsaudioutils.cpp111
-rw-r--r--src/plugins/windowsaudio/qwindowsaudioutils.h67
-rw-r--r--src/plugins/windowsaudio/windowsaudio.pro6
9 files changed, 293 insertions, 246 deletions
diff --git a/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp b/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp
index ede60c963..801f792e0 100644
--- a/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp
+++ b/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp
@@ -47,6 +47,7 @@
#include <QtCore/QDataStream>
#include <mmsystem.h>
#include "qwindowsaudiodeviceinfo.h"
+#include "qwindowsaudioutils.h"
#if defined(Q_CC_MINGW) && !defined(__MINGW64_VERSION_MAJOR)
struct IBaseFilter; // Needed for strmif.h from stock MinGW.
@@ -167,8 +168,7 @@ QString QWindowsAudioDeviceInfo::deviceName() const
QStringList QWindowsAudioDeviceInfo::supportedCodecs()
{
- updateLists();
- return codecz;
+ return QStringList() << QStringLiteral("audio/pcm");
}
QList<int> QWindowsAudioDeviceInfo::supportedSampleRates()
@@ -191,8 +191,7 @@ QList<int> QWindowsAudioDeviceInfo::supportedSampleSizes()
QList<QAudioFormat::Endian> QWindowsAudioDeviceInfo::supportedByteOrders()
{
- updateLists();
- return byteOrderz;
+ return QList<QAudioFormat::Endian>() << QAudioFormat::LittleEndian;
}
QList<QAudioFormat::SampleType> QWindowsAudioDeviceInfo::supportedSampleTypes()
@@ -213,118 +212,50 @@ void QWindowsAudioDeviceInfo::close()
bool QWindowsAudioDeviceInfo::testSettings(const QAudioFormat& format) const
{
- // Set nearest to closest settings that do work.
- // See if what is in settings will work (return value).
-
- bool failed = false;
- bool match = false;
-
- // check codec
- for( int i = 0; i < codecz.count(); i++) {
- if (format.codec() == codecz.at(i))
- match = true;
- }
- if (!match) failed = true;
-
- // check channel
- match = false;
- if (!failed) {
- for (int i = 0; i < channelz.count(); i++) {
- if (format.channelCount() == channelz.at(i)) {
- match = true;
- break;
- }
- }
- if (!match)
- failed = true;
- }
-
- // check sampleRate
- match = false;
- if (!failed) {
- for (int i = 0; i < sampleRatez.count(); i++) {
- if (format.sampleRate() == sampleRatez.at(i)) {
- match = true;
- break;
- }
- }
- if (!match)
- failed = true;
- }
-
- // check sample size
- match = false;
- if (!failed) {
- for( int i = 0; i < sizez.count(); i++) {
- if (format.sampleSize() == sizez.at(i)) {
- match = true;
- break;
- }
- }
- if (!match)
- failed = true;
- }
-
- // check byte order
- match = false;
- if (!failed) {
- for( int i = 0; i < byteOrderz.count(); i++) {
- if (format.byteOrder() == byteOrderz.at(i)) {
- match = true;
- break;
- }
- }
- if (!match)
- failed = true;
- }
-
- // check sample type
- match = false;
- if (!failed) {
- for( int i = 0; i < typez.count(); i++) {
- if (format.sampleType() == typez.at(i)) {
- match = true;
- break;
- }
+ WAVEFORMATEXTENSIBLE wfx;
+ if (qt_convertFormat(format, &wfx)) {
+ // query only, do not open device
+ if (mode == QAudio::AudioOutput) {
+ return (waveOutOpen(NULL, UINT_PTR(devId), &wfx.Format, NULL, NULL,
+ WAVE_FORMAT_QUERY) == MMSYSERR_NOERROR);
+ } else { // AudioInput
+ return (waveInOpen(NULL, UINT_PTR(devId), &wfx.Format, NULL, NULL,
+ WAVE_FORMAT_QUERY) == MMSYSERR_NOERROR);
}
- if (!match)
- failed = true;
}
- if(!failed) {
- // settings work
- return true;
- }
return false;
}
void QWindowsAudioDeviceInfo::updateLists()
{
- // redo all lists based on current settings
- bool match = false;
+ if (!sizez.isEmpty())
+ return;
+
+ bool hasCaps = false;
DWORD fmt = 0;
if(mode == QAudio::AudioOutput) {
WAVEOUTCAPS woc;
if (waveOutGetDevCaps(devId, &woc, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) {
- match = true;
+ hasCaps = true;
fmt = woc.dwFormats;
}
} else {
WAVEINCAPS woc;
if (waveInGetDevCaps(devId, &woc, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR) {
- match = true;
+ hasCaps = true;
fmt = woc.dwFormats;
}
}
+
sizez.clear();
sampleRatez.clear();
channelz.clear();
- byteOrderz.clear();
typez.clear();
- codecz.clear();
- if(match) {
+ if (hasCaps) {
+ // Check sample size
if ((fmt & WAVE_FORMAT_1M08)
|| (fmt & WAVE_FORMAT_1S08)
|| (fmt & WAVE_FORMAT_2M08)
@@ -334,8 +265,7 @@ void QWindowsAudioDeviceInfo::updateLists()
|| (fmt & WAVE_FORMAT_48M08)
|| (fmt & WAVE_FORMAT_48S08)
|| (fmt & WAVE_FORMAT_96M08)
- || (fmt & WAVE_FORMAT_96S08)
- ) {
+ || (fmt & WAVE_FORMAT_96S08)) {
sizez.append(8);
}
if ((fmt & WAVE_FORMAT_1M16)
@@ -347,10 +277,11 @@ void QWindowsAudioDeviceInfo::updateLists()
|| (fmt & WAVE_FORMAT_48M16)
|| (fmt & WAVE_FORMAT_48S16)
|| (fmt & WAVE_FORMAT_96M16)
- || (fmt & WAVE_FORMAT_96S16)
- ) {
+ || (fmt & WAVE_FORMAT_96S16)) {
sizez.append(16);
}
+
+ // Check sample rate
if ((fmt & WAVE_FORMAT_1M08)
|| (fmt & WAVE_FORMAT_1S08)
|| (fmt & WAVE_FORMAT_1M16)
@@ -381,23 +312,81 @@ void QWindowsAudioDeviceInfo::updateLists()
|| (fmt & WAVE_FORMAT_96S16)) {
sampleRatez.append(96000);
}
- channelz.append(1);
- channelz.append(2);
- if (mode == QAudio::AudioOutput) {
- channelz.append(4);
- channelz.append(6);
- channelz.append(8);
- }
- byteOrderz.append(QAudioFormat::LittleEndian);
+ // Check channel count
+ if (fmt & WAVE_FORMAT_1M08
+ || fmt & WAVE_FORMAT_1M16
+ || fmt & WAVE_FORMAT_2M08
+ || fmt & WAVE_FORMAT_2M16
+ || fmt & WAVE_FORMAT_4M08
+ || fmt & WAVE_FORMAT_4M16
+ || fmt & WAVE_FORMAT_48M08
+ || fmt & WAVE_FORMAT_48M16
+ || fmt & WAVE_FORMAT_96M08
+ || fmt & WAVE_FORMAT_96M16) {
+ channelz.append(1);
+ }
+ if (fmt & WAVE_FORMAT_1S08
+ || fmt & WAVE_FORMAT_1S16
+ || fmt & WAVE_FORMAT_2S08
+ || fmt & WAVE_FORMAT_2S16
+ || fmt & WAVE_FORMAT_4S08
+ || fmt & WAVE_FORMAT_4S16
+ || fmt & WAVE_FORMAT_48S08
+ || fmt & WAVE_FORMAT_48S16
+ || fmt & WAVE_FORMAT_96S08
+ || fmt & WAVE_FORMAT_96S16) {
+ channelz.append(2);
+ }
typez.append(QAudioFormat::SignedInt);
typez.append(QAudioFormat::UnSignedInt);
- codecz.append(QLatin1String("audio/pcm"));
+ // WAVEOUTCAPS and WAVEINCAPS contains information only for the previously tested parameters.
+ // WaveOut and WaveInt might actually support more formats, the only way to know is to try
+ // opening the device with it.
+ QAudioFormat testFormat;
+ testFormat.setCodec(QStringLiteral("audio/pcm"));
+ testFormat.setByteOrder(QAudioFormat::LittleEndian);
+ testFormat.setSampleType(QAudioFormat::SignedInt);
+ testFormat.setChannelCount(channelz.first());
+ testFormat.setSampleRate(sampleRatez.at(sampleRatez.size() / 2));
+ testFormat.setSampleSize(sizez.last());
+ const QAudioFormat defaultTestFormat(testFormat);
+
+ // Check if float samples are supported
+ testFormat.setSampleType(QAudioFormat::Float);
+ testFormat.setSampleSize(32);
+ if (testSettings(testFormat))
+ typez.append(QAudioFormat::Float);
+
+ // Check channel counts > 2
+ testFormat = defaultTestFormat;
+ for (int i = 3; i < 19; ++i) { // <mmreg.h> defines 18 different channels
+ testFormat.setChannelCount(i);
+ if (testSettings(testFormat))
+ channelz.append(i);
+ }
+
+ // Check more sample sizes
+ testFormat = defaultTestFormat;
+ QList<int> testSampleSizes = QList<int>() << 24 << 32 << 48 << 64;
+ Q_FOREACH (int s, testSampleSizes) {
+ testFormat.setSampleSize(s);
+ if (testSettings(testFormat))
+ sizez.append(s);
+ }
+
+ // Check more sample rates
+ testFormat = defaultTestFormat;
+ QList<int> testSampleRates = QList<int>() << 8000 << 16000 << 32000 << 88200 << 192000;
+ Q_FOREACH (int r, testSampleRates) {
+ testFormat.setSampleRate(r);
+ if (testSettings(testFormat))
+ sampleRatez.append(r);
+ }
+ std::sort(sampleRatez.begin(), sampleRatez.end());
}
- if (sampleRatez.count() > 0)
- sampleRatez.prepend(8000);
}
QList<QByteArray> QWindowsAudioDeviceInfo::availableDevices(QAudio::Mode mode)
diff --git a/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.h b/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.h
index 4bc9488cf..cdbde40d0 100644
--- a/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.h
+++ b/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.h
@@ -57,7 +57,6 @@
QT_BEGIN_NAMESPACE
-
const unsigned int MAX_SAMPLE_RATES = 5;
const unsigned int SAMPLE_RATES[] = { 8000, 11025, 22050, 44100, 48000 };
@@ -91,15 +90,14 @@ private:
QAudio::Mode mode;
QString device;
quint32 devId;
- QAudioFormat nearest;
QList<int> sampleRatez;
QList<int> channelz;
QList<int> sizez;
- QList<QAudioFormat::Endian> byteOrderz;
- QStringList codecz;
QList<QAudioFormat::SampleType> typez;
};
+
+
QT_END_NAMESPACE
diff --git a/src/plugins/windowsaudio/qwindowsaudioinput.cpp b/src/plugins/windowsaudio/qwindowsaudioinput.cpp
index 7ddd5391c..788db2d25 100644
--- a/src/plugins/windowsaudio/qwindowsaudioinput.cpp
+++ b/src/plugins/windowsaudio/qwindowsaudioinput.cpp
@@ -298,18 +298,9 @@ bool QWindowsAudioInput::open()
period_size = 0;
- if (!settings.isValid()) {
+ if (!qt_convertFormat(settings, &wfx)) {
qWarning("QAudioInput: open error, invalid format.");
- } else if (settings.channelCount() <= 0) {
- qWarning("QAudioInput: open error, invalid number of channels (%d).",
- settings.channelCount());
- } else if (settings.sampleSize() <= 0) {
- qWarning("QAudioInput: open error, invalid sample size (%d).",
- settings.sampleSize());
- } else if (settings.sampleRate() < 8000 || settings.sampleRate() > 96000) {
- qWarning("QAudioInput: open error, sample rate out of range (%d).", settings.sampleRate());
} else if (buffer_size == 0) {
-
buffer_size
= (settings.sampleRate()
* settings.channelCount()
@@ -329,20 +320,12 @@ bool QWindowsAudioInput::open()
timeStamp.restart();
elapsedTimeOffset = 0;
- wfx.nSamplesPerSec = settings.sampleRate();
- wfx.wBitsPerSample = settings.sampleSize();
- wfx.nChannels = settings.channelCount();
- wfx.cbSize = 0;
-
- wfx.wFormatTag = WAVE_FORMAT_PCM;
- wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
- wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
QDataStream ds(&m_device, QIODevice::ReadOnly);
quint32 deviceId;
ds >> deviceId;
- if (waveInOpen(&hWaveIn, UINT_PTR(deviceId), &wfx,
+ if (waveInOpen(&hWaveIn, UINT_PTR(deviceId), &wfx.Format,
(DWORD_PTR)&waveInProc,
(DWORD_PTR) this,
CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
diff --git a/src/plugins/windowsaudio/qwindowsaudioinput.h b/src/plugins/windowsaudio/qwindowsaudioinput.h
index 30388c7fd..a93fd9cb0 100644
--- a/src/plugins/windowsaudio/qwindowsaudioinput.h
+++ b/src/plugins/windowsaudio/qwindowsaudioinput.h
@@ -45,8 +45,7 @@
#ifndef QWINDOWSAUDIOINPUT_H
#define QWINDOWSAUDIOINPUT_H
-#include <QtCore/qt_windows.h>
-#include <mmsystem.h>
+#include "qwindowsaudioutils.h"
#include <QtCore/qfile.h>
#include <QtCore/qdebug.h>
@@ -121,7 +120,7 @@ private:
qint64 totalTimeValue;
bool pullMode;
bool resuming;
- WAVEFORMATEX wfx;
+ WAVEFORMATEXTENSIBLE wfx;
HWAVEIN hWaveIn;
MMRESULT result;
WAVEHDR* waveBlocks;
diff --git a/src/plugins/windowsaudio/qwindowsaudiooutput.cpp b/src/plugins/windowsaudio/qwindowsaudiooutput.cpp
index 1f1f34d4f..68e58646d 100644
--- a/src/plugins/windowsaudio/qwindowsaudiooutput.cpp
+++ b/src/plugins/windowsaudio/qwindowsaudiooutput.cpp
@@ -43,56 +43,11 @@
//
#include "qwindowsaudiooutput.h"
+#include "qwindowsaudiodeviceinfo.h"
+#include "qwindowsaudioutils.h"
#include <QtEndian>
#include <QtCore/QDataStream>
-#ifndef SPEAKER_FRONT_LEFT
- #define SPEAKER_FRONT_LEFT 0x00000001
- #define SPEAKER_FRONT_RIGHT 0x00000002
- #define SPEAKER_FRONT_CENTER 0x00000004
- #define SPEAKER_LOW_FREQUENCY 0x00000008
- #define SPEAKER_BACK_LEFT 0x00000010
- #define SPEAKER_BACK_RIGHT 0x00000020
- #define SPEAKER_FRONT_LEFT_OF_CENTER 0x00000040
- #define SPEAKER_FRONT_RIGHT_OF_CENTER 0x00000080
- #define SPEAKER_BACK_CENTER 0x00000100
- #define SPEAKER_SIDE_LEFT 0x00000200
- #define SPEAKER_SIDE_RIGHT 0x00000400
- #define SPEAKER_TOP_CENTER 0x00000800
- #define SPEAKER_TOP_FRONT_LEFT 0x00001000
- #define SPEAKER_TOP_FRONT_CENTER 0x00002000
- #define SPEAKER_TOP_FRONT_RIGHT 0x00004000
- #define SPEAKER_TOP_BACK_LEFT 0x00008000
- #define SPEAKER_TOP_BACK_CENTER 0x00010000
- #define SPEAKER_TOP_BACK_RIGHT 0x00020000
- #define SPEAKER_RESERVED 0x7FFC0000
- #define SPEAKER_ALL 0x80000000
-#endif
-
-#ifndef _WAVEFORMATEXTENSIBLE_
-
- #define _WAVEFORMATEXTENSIBLE_
- typedef struct
- {
- WAVEFORMATEX Format; // Base WAVEFORMATEX data
- union
- {
- WORD wValidBitsPerSample; // Valid bits in each sample container
- WORD wSamplesPerBlock; // Samples per block of audio data; valid
- // if wBitsPerSample=0 (but rarely used).
- WORD wReserved; // Zero if neither case above applies.
- } Samples;
- DWORD dwChannelMask; // Positions of the audio channels
- GUID SubFormat; // Format identifier GUID
- } WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE, *LPPWAVEFORMATEXTENSIBLE;
- typedef const WAVEFORMATEXTENSIBLE* LPCWAVEFORMATEXTENSIBLE;
-
-#endif
-
-#if !defined(WAVE_FORMAT_EXTENSIBLE)
-#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
-#endif
-
//#define DEBUG_AUDIO 1
QT_BEGIN_NAMESPACE
@@ -265,16 +220,8 @@ bool QWindowsAudioOutput::open()
period_size = 0;
- if (!settings.isValid()) {
+ if (!qt_convertFormat(settings, &wfx)) {
qWarning("QAudioOutput: open error, invalid format.");
- } else if (settings.channelCount() <= 0) {
- qWarning("QAudioOutput: open error, invalid number of channels (%d).",
- settings.channelCount());
- } else if (settings.sampleSize() <= 0) {
- qWarning("QAudioOutput: open error, invalid sample size (%d).",
- settings.sampleSize());
- } else if (settings.sampleRate() < 8000 || settings.sampleRate() > 96000) {
- qWarning("QAudioOutput: open error, sample rate out of range (%d).", settings.sampleRate());
} else if (buffer_size == 0) {
// Default buffer size, 200ms, default period size is 40ms
buffer_size
@@ -308,67 +255,19 @@ bool QWindowsAudioOutput::open()
timeStamp.restart();
elapsedTimeOffset = 0;
- wfx.nSamplesPerSec = settings.sampleRate();
- wfx.wBitsPerSample = settings.sampleSize();
- wfx.nChannels = settings.channelCount();
- wfx.cbSize = 0;
-
- bool surround = false;
-
- if (settings.channelCount() > 2)
- surround = true;
-
- wfx.wFormatTag = WAVE_FORMAT_PCM;
- wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
- wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
-
QDataStream ds(&m_device, QIODevice::ReadOnly);
quint32 deviceId;
ds >> deviceId;
- if (!surround) {
- if (waveOutOpen(&hWaveOut, UINT_PTR(deviceId), &wfx,
+ if (waveOutOpen(&hWaveOut, UINT_PTR(deviceId), &wfx.Format,
(DWORD_PTR)&waveOutProc,
(DWORD_PTR) this,
CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
- errorState = QAudio::OpenError;
- deviceState = QAudio::StoppedState;
- emit stateChanged(deviceState);
- qWarning("QAudioOutput: open error");
- return false;
- }
- } else {
- WAVEFORMATEXTENSIBLE wfex;
- wfex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
- wfex.Format.nChannels = settings.channelCount();
- wfex.Format.wBitsPerSample = settings.sampleSize();
- wfex.Format.nSamplesPerSec = settings.sampleRate();
- wfex.Format.nBlockAlign = wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
- wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*wfex.Format.nBlockAlign;
- wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
- static const GUID _KSDATAFORMAT_SUBTYPE_PCM = {
- 0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
- wfex.SubFormat=_KSDATAFORMAT_SUBTYPE_PCM;
- wfex.Format.cbSize=22;
-
- wfex.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
- if (settings.channelCount() >= 4)
- wfex.dwChannelMask |= SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
- if (settings.channelCount() >= 6)
- wfex.dwChannelMask |= SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY;
- if (settings.channelCount() == 8)
- wfex.dwChannelMask |= SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT;
-
- if (waveOutOpen(&hWaveOut, UINT_PTR(deviceId), &wfex.Format,
- (DWORD_PTR)&waveOutProc,
- (DWORD_PTR) this,
- CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
- errorState = QAudio::OpenError;
- deviceState = QAudio::StoppedState;
- emit stateChanged(deviceState);
- qWarning("QAudioOutput: open error");
- return false;
- }
+ errorState = QAudio::OpenError;
+ deviceState = QAudio::StoppedState;
+ emit stateChanged(deviceState);
+ qWarning("QAudioOutput: open error");
+ return false;
}
totalTimeValue = 0;
diff --git a/src/plugins/windowsaudio/qwindowsaudiooutput.h b/src/plugins/windowsaudio/qwindowsaudiooutput.h
index 09c1897f4..9a101ac13 100644
--- a/src/plugins/windowsaudio/qwindowsaudiooutput.h
+++ b/src/plugins/windowsaudio/qwindowsaudiooutput.h
@@ -45,8 +45,7 @@
#ifndef QWINDOWSAUDIOOUTPUT_H
#define QWINDOWSAUDIOOUTPUT_H
-#include <QtCore/qt_windows.h>
-#include <mmsystem.h>
+#include "qwindowsaudioutils.h"
#include <QtCore/qdebug.h>
#include <QtCore/qtimer.h>
@@ -132,7 +131,7 @@ private:
bool open();
void close();
- WAVEFORMATEX wfx;
+ WAVEFORMATEXTENSIBLE wfx;
HWAVEOUT hWaveOut;
MMRESULT result;
WAVEHDR header;
diff --git a/src/plugins/windowsaudio/qwindowsaudioutils.cpp b/src/plugins/windowsaudio/qwindowsaudioutils.cpp
new file mode 100644
index 000000000..36a8d750f
--- /dev/null
+++ b/src/plugins/windowsaudio/qwindowsaudioutils.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwindowsaudioutils.h"
+
+#ifndef SPEAKER_FRONT_LEFT
+ #define SPEAKER_FRONT_LEFT 0x00000001
+ #define SPEAKER_FRONT_RIGHT 0x00000002
+ #define SPEAKER_FRONT_CENTER 0x00000004
+ #define SPEAKER_LOW_FREQUENCY 0x00000008
+ #define SPEAKER_BACK_LEFT 0x00000010
+ #define SPEAKER_BACK_RIGHT 0x00000020
+ #define SPEAKER_FRONT_LEFT_OF_CENTER 0x00000040
+ #define SPEAKER_FRONT_RIGHT_OF_CENTER 0x00000080
+ #define SPEAKER_BACK_CENTER 0x00000100
+ #define SPEAKER_SIDE_LEFT 0x00000200
+ #define SPEAKER_SIDE_RIGHT 0x00000400
+ #define SPEAKER_TOP_CENTER 0x00000800
+ #define SPEAKER_TOP_FRONT_LEFT 0x00001000
+ #define SPEAKER_TOP_FRONT_CENTER 0x00002000
+ #define SPEAKER_TOP_FRONT_RIGHT 0x00004000
+ #define SPEAKER_TOP_BACK_LEFT 0x00008000
+ #define SPEAKER_TOP_BACK_CENTER 0x00010000
+ #define SPEAKER_TOP_BACK_RIGHT 0x00020000
+ #define SPEAKER_RESERVED 0x7FFC0000
+ #define SPEAKER_ALL 0x80000000
+#endif
+
+#ifndef WAVE_FORMAT_EXTENSIBLE
+ #define WAVE_FORMAT_EXTENSIBLE 0xFFFE
+#endif
+
+#ifndef WAVE_FORMAT_IEEE_FLOAT
+ #define WAVE_FORMAT_IEEE_FLOAT 0x0003
+#endif
+
+static const GUID _KSDATAFORMAT_SUBTYPE_PCM = {
+ 0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
+
+static const GUID _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {
+ 0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
+
+QT_BEGIN_NAMESPACE
+
+bool qt_convertFormat(const QAudioFormat &format, WAVEFORMATEXTENSIBLE *wfx)
+{
+ if (!wfx
+ || !format.isValid()
+ || format.codec() != QStringLiteral("audio/pcm")
+ || format.sampleRate() <= 0
+ || format.channelCount() <= 0
+ || format.sampleSize() <= 0
+ || format.byteOrder() != QAudioFormat::LittleEndian) {
+ return false;
+ }
+
+ wfx->Format.nSamplesPerSec = format.sampleRate();
+ wfx->Format.wBitsPerSample = wfx->Samples.wValidBitsPerSample = format.sampleSize();
+ wfx->Format.nChannels = format.channelCount();
+ wfx->Format.nBlockAlign = (wfx->Format.wBitsPerSample / 8) * wfx->Format.nChannels;
+ wfx->Format.nAvgBytesPerSec = wfx->Format.nBlockAlign * wfx->Format.nSamplesPerSec;
+ wfx->Format.cbSize = 0;
+
+ if (format.sampleType() == QAudioFormat::Float) {
+ wfx->Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
+ wfx->SubFormat = _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
+ } else {
+ wfx->Format.wFormatTag = WAVE_FORMAT_PCM;
+ wfx->SubFormat = _KSDATAFORMAT_SUBTYPE_PCM;
+ }
+
+ if (format.channelCount() > 2) {
+ wfx->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
+ wfx->Format.cbSize = 22;
+ wfx->dwChannelMask = 0xFFFFFFFF >> (32 - format.channelCount());
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/windowsaudio/qwindowsaudioutils.h b/src/plugins/windowsaudio/qwindowsaudioutils.h
new file mode 100644
index 000000000..1f282cea1
--- /dev/null
+++ b/src/plugins/windowsaudio/qwindowsaudioutils.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSAUDIOUTILS_H
+#define QWINDOWSAUDIOUTILS_H
+
+#include <qaudioformat.h>
+#include <QtCore/qt_windows.h>
+#include <mmsystem.h>
+
+#ifndef _WAVEFORMATEXTENSIBLE_
+
+ #define _WAVEFORMATEXTENSIBLE_
+ typedef struct
+ {
+ WAVEFORMATEX Format; // Base WAVEFORMATEX data
+ union
+ {
+ WORD wValidBitsPerSample; // Valid bits in each sample container
+ WORD wSamplesPerBlock; // Samples per block of audio data; valid
+ // if wBitsPerSample=0 (but rarely used).
+ WORD wReserved; // Zero if neither case above applies.
+ } Samples;
+ DWORD dwChannelMask; // Positions of the audio channels
+ GUID SubFormat; // Format identifier GUID
+ } WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE, *LPPWAVEFORMATEXTENSIBLE;
+ typedef const WAVEFORMATEXTENSIBLE* LPCWAVEFORMATEXTENSIBLE;
+
+#endif
+
+QT_BEGIN_NAMESPACE
+
+bool qt_convertFormat(const QAudioFormat &format, WAVEFORMATEXTENSIBLE *wfx);
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSAUDIOUTILS_H
diff --git a/src/plugins/windowsaudio/windowsaudio.pro b/src/plugins/windowsaudio/windowsaudio.pro
index ead73251b..7e8e4320b 100644
--- a/src/plugins/windowsaudio/windowsaudio.pro
+++ b/src/plugins/windowsaudio/windowsaudio.pro
@@ -12,13 +12,15 @@ HEADERS += \
qwindowsaudioplugin.h \
qwindowsaudiodeviceinfo.h \
qwindowsaudioinput.h \
- qwindowsaudiooutput.h
+ qwindowsaudiooutput.h \
+ qwindowsaudioutils.h
SOURCES += \
qwindowsaudioplugin.cpp \
qwindowsaudiodeviceinfo.cpp \
qwindowsaudioinput.cpp \
- qwindowsaudiooutput.cpp
+ qwindowsaudiooutput.cpp \
+ qwindowsaudioutils.cpp
OTHER_FILES += \
windowsaudio.json