Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qwindowsaudioutils.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6#include "qdebug.h"
7#include "ks.h"
8#include "ksmedia.h"
9
10#include <audioclient.h>
11
13
15 { QAudioFormat::FrontLeft // SPEAKER_FRONT_LEFT (0x1)
16 , QAudioFormat::FrontRight // SPEAKER_FRONT_RIGHT (0x2)
17 , QAudioFormat::FrontCenter // SPEAKER_FRONT_CENTER (0x4)
18 , QAudioFormat::LFE // SPEAKER_LOW_FREQUENCY (0x8)
19 , QAudioFormat::BackLeft // SPEAKER_BACK_LEFT (0x10)
20 , QAudioFormat::BackRight // SPEAKER_BACK_RIGHT (0x20)
21 , QAudioFormat::FrontLeftOfCenter // SPEAKER_FRONT_LEFT_OF_CENTER (0x40)
22 , QAudioFormat::FrontRightOfCenter// SPEAKER_FRONT_RIGHT_OF_CENTER (0x80)
23 , QAudioFormat::BackCenter // SPEAKER_BACK_CENTER (0x100)
24 , QAudioFormat::SideLeft // SPEAKER_SIDE_LEFT (0x200)
25 , QAudioFormat::SideRight // SPEAKER_SIDE_RIGHT (0x400)
26 , QAudioFormat::TopCenter // SPEAKER_TOP_CENTER (0x800)
27 , QAudioFormat::TopFrontLeft // SPEAKER_TOP_FRONT_LEFT (0x1000)
28 , QAudioFormat::TopFrontCenter // SPEAKER_TOP_FRONT_CENTER (0x2000)
29 , QAudioFormat::TopFrontRight // SPEAKER_TOP_FRONT_RIGHT (0x4000)
30 , QAudioFormat::TopBackLeft // SPEAKER_TOP_BACK_LEFT (0x8000)
31 , QAudioFormat::TopBackCenter // SPEAKER_TOP_BACK_CENTER (0x10000)
32 , QAudioFormat::TopBackRight // SPEAKER_TOP_BACK_RIGHT (0x20000)
33 };
34
36{
37 quint32 config = 0;
38 int set = 0;
39 for (auto c : channelFormatMap) {
40 if (mask & 1) {
42 ++set;
43 }
44 if (set >= count)
45 break;
46 mask >>= 1;
47 }
49}
50
52{
53 UINT32 mask = 0;
54 quint32 i = 0;
55 for (auto c : channelFormatMap) {
57 mask |= 1 << i;
58 ++i;
59 }
60 return mask;
61}
62
64{
65 if (!format.isValid())
66 return false;
67
68 wfx.Format.nSamplesPerSec = format.sampleRate();
69 wfx.Format.wBitsPerSample = wfx.Samples.wValidBitsPerSample = format.bytesPerSample()*8;
70 wfx.Format.nChannels = format.channelCount();
71 wfx.Format.nBlockAlign = (wfx.Format.wBitsPerSample / 8) * wfx.Format.nChannels;
72 wfx.Format.nAvgBytesPerSec = wfx.Format.nBlockAlign * wfx.Format.nSamplesPerSec;
73 wfx.Format.cbSize = 0;
74
75 if (format.sampleFormat() == QAudioFormat::Float) {
76 wfx.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
77 wfx.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
78 } else {
79 wfx.Format.wFormatTag = WAVE_FORMAT_PCM;
80 wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
81 }
82
83 if (format.channelCount() > 2) {
84 wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
85 wfx.Format.cbSize = 22;
86 wfx.dwChannelMask = format.channelConfig() == QAudioFormat::ChannelConfigUnknown ? KSAUDIO_SPEAKER_DIRECTOUT
87 : DWORD(format.channelConfig());
88 }
89
90 return true;
91}
92
94{
96 out.setSampleRate(in.nSamplesPerSec);
97 out.setChannelCount(in.nChannels);
98 if (in.wFormatTag == WAVE_FORMAT_PCM) {
99 if (in.wBitsPerSample == 8)
100 out.setSampleFormat(QAudioFormat::UInt8);
101 else if (in.wBitsPerSample == 16)
102 out.setSampleFormat(QAudioFormat::Int16);
103 else if (in.wBitsPerSample == 32)
104 out.setSampleFormat(QAudioFormat::Int32);
105 } else if (in.wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
106 if (in.cbSize >= 22) {
107 auto wfe = reinterpret_cast<const WAVEFORMATEXTENSIBLE &>(in);
108 if (wfe.SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
109 out.setSampleFormat(QAudioFormat::Float);
110 if (qPopulationCount(wfe.dwChannelMask) >= in.nChannels)
111 out.setChannelConfig(maskToChannelConfig(wfe.dwChannelMask, in.nChannels));
112 }
113 } else if (in.wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
114 out.setSampleFormat(QAudioFormat::Float);
115 }
116
117 return out;
118}
119
121{
123 if (!mediaType)
124 return format;
125
126 UINT32 val = 0;
127 if (SUCCEEDED(mediaType->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &val))) {
129 } else {
130 qWarning() << "Could not determine channel count from IMFMediaType";
131 return {};
132 }
133
134 if (SUCCEEDED(mediaType->GetUINT32(MF_MT_AUDIO_CHANNEL_MASK, &val))) {
135 if (int(qPopulationCount(val)) >= format.channelCount())
136 format.setChannelConfig(maskToChannelConfig(val, format.channelCount()));
137 }
138
139 if (SUCCEEDED(mediaType->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &val))) {
140 format.setSampleRate(int(val));
141 }
142 UINT32 bitsPerSample = 0;
143 mediaType->GetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, &bitsPerSample);
144
145 GUID subType;
146 if (SUCCEEDED(mediaType->GetGUID(MF_MT_SUBTYPE, &subType))) {
147 if (subType == MFAudioFormat_Float) {
148 format.setSampleFormat(QAudioFormat::Float);
149 } else if (bitsPerSample == 8) {
150 format.setSampleFormat(QAudioFormat::UInt8);
151 } else if (bitsPerSample == 16) {
152 format.setSampleFormat(QAudioFormat::Int16);
153 } else if (bitsPerSample == 32){
154 format.setSampleFormat(QAudioFormat::Int32);
155 }
156 }
157 return format;
158}
159
161{
162 ComPtr<IMFMediaType> mediaType;
163
164 if (!format.isValid())
165 return mediaType;
166
167 wmf.mfCreateMediaType(mediaType.GetAddressOf());
168
169 mediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
170 if (format.sampleFormat() == QAudioFormat::Float) {
171 mediaType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_Float);
172 } else {
173 mediaType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);
174 }
175
176 mediaType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, UINT32(format.channelCount()));
177 if (format.channelConfig() != QAudioFormat::ChannelConfigUnknown)
178 mediaType->SetUINT32(MF_MT_AUDIO_CHANNEL_MASK, channelConfigToMask(format.channelConfig()));
179 mediaType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, UINT32(format.sampleRate()));
180 auto alignmentBlock = UINT32(format.bytesPerFrame());
181 mediaType->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, alignmentBlock);
182 auto avgBytesPerSec = UINT32(format.sampleRate() * format.bytesPerFrame());
183 mediaType->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, avgBytesPerSec);
184 mediaType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, UINT32(format.bytesPerSample()*8));
185 mediaType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
186
187 return mediaType;
188}
189
190std::optional<quint32> QWindowsAudioUtils::audioClientFramesInUse(IAudioClient *client)
191{
192 Q_ASSERT(client);
193 UINT32 framesPadding = 0;
194 if (SUCCEEDED(client->GetCurrentPadding(&framesPadding)))
195 return framesPadding;
196 return {};
197}
198
199std::optional<quint32> QWindowsAudioUtils::audioClientFramesAllocated(IAudioClient *client)
200{
201 Q_ASSERT(client);
202 UINT32 bufferFrameCount = 0;
203 if (SUCCEEDED(client->GetBufferSize(&bufferFrameCount)))
204 return bufferFrameCount;
205 return {};
206}
207
The QAudioFormat class stores audio stream parameter information.
AudioChannelPosition
Describes the possible audio channel positions.
constexpr ChannelConfig channelConfig() const noexcept
Returns the current channel configuration.
constexpr void setChannelCount(int channelCount) noexcept
Sets the channel count to channels.
ChannelConfig
\variable QAudioFormat::NChannelPositions
Combined button and popup list for selecting options.
std::optional< quint32 > audioClientFramesInUse(IAudioClient *client)
Q_MULTIMEDIA_EXPORT QAudioFormat mediaTypeToFormat(IMFMediaType *mediaType)
std::optional< quint32 > audioClientFramesAllocated(IAudioClient *client)
ComPtr< IMFMediaType > formatToMediaType(QWindowsMediaFoundation &, const QAudioFormat &format)
QAudioFormat waveFormatExToFormat(const WAVEFORMATEX &in)
bool formatToWaveFormatExtensible(const QAudioFormat &format, WAVEFORMATEXTENSIBLE &wfx)
QAudioFormat::ChannelConfig maskToChannelConfig(UINT32 mask, int count)
Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR uint qPopulationCount(quint32 v) noexcept
EGLConfig config
#define qWarning
Definition qlogging.h:166
GLenum GLenum GLsizei count
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLint GLsizei GLsizei GLenum format
const GLubyte * c
GLuint GLfloat * val
GLuint in
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
unsigned int quint32
Definition qtypes.h:50
static UINT32 channelConfigToMask(QAudioFormat::ChannelConfig config)
static QT_BEGIN_NAMESPACE QAudioFormat::AudioChannelPosition channelFormatMap[]
QFuture< QSet< QChar > > set
[10]
QTextStream out(stdout)
[7]