diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2015-04-15 09:26:14 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2015-04-15 09:26:14 +0200 |
commit | 1925bb404ec47b6e074c5e3b334fe0be12176d7b (patch) | |
tree | 8d7d79ac1b3a549c20bb4fa77c6f457bf1bb61ea /src/plugins/windowsaudio | |
parent | 6187b72c51d0c05955d9d814baf8866b8e70fcfe (diff) | |
parent | f9145aca166ad2ca1514524ce88ded7834eb207c (diff) | |
download | qtmultimedia-1925bb404ec47b6e074c5e3b334fe0be12176d7b.tar.gz |
Merge remote-tracking branch 'origin/5.4' into 5.5
Conflicts:
src/multimedia/playback/playlistfileparser.cpp
src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp
Change-Id: I52950def2b8283ae15797d05d4ead6a1256eba19
Diffstat (limited to 'src/plugins/windowsaudio')
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp | 199 | ||||
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudiodeviceinfo.h | 6 | ||||
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudioinput.cpp | 21 | ||||
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudioinput.h | 5 | ||||
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudiooutput.cpp | 119 | ||||
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudiooutput.h | 5 | ||||
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudioutils.cpp | 111 | ||||
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudioutils.h | 67 | ||||
-rw-r--r-- | src/plugins/windowsaudio/windowsaudio.pro | 6 |
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 |