Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
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) {
41 config |= QAudioFormat::channelConfig(c);
42 ++set;
43 }
44 if (set >= count)
45 break;
46 mask >>= 1;
47 }
48 return QAudioFormat::ChannelConfig(config);
49}
50
52{
53 UINT32 mask = 0;
54 quint32 i = 0;
55 for (auto c : channelFormatMap) {
56 if (config & QAudioFormat::channelConfig(c))
57 mask |= 1 << i;
58 ++i;
59 }
60 return mask;
61}
62
63bool QWindowsAudioUtils::formatToWaveFormatExtensible(const QAudioFormat &format, WAVEFORMATEXTENSIBLE &wfx)
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
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
95{
96 WAVEFORMATEXTENSIBLE ret{};
97 if (formatToWaveFormatExtensible(format, ret))
98 return ret;
99
100 return std::nullopt;
101}
102
104{
105 QAudioFormat out;
106 out.setSampleRate(in.nSamplesPerSec);
107 out.setChannelCount(in.nChannels);
108 if (in.wFormatTag == WAVE_FORMAT_PCM) {
109 if (in.wBitsPerSample == 8)
111 else if (in.wBitsPerSample == 16)
113 else if (in.wBitsPerSample == 32)
115 } else if (in.wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
116 if (in.cbSize >= 22) {
117 auto wfe = reinterpret_cast<const WAVEFORMATEXTENSIBLE &>(in);
118 if (wfe.SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
120 if (qPopulationCount(wfe.dwChannelMask) >= in.nChannels)
121 out.setChannelConfig(maskToChannelConfig(wfe.dwChannelMask, in.nChannels));
122 }
123 } else if (in.wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
125 }
126
127 return out;
128}
129
130QAudioFormat QWindowsAudioUtils::mediaTypeToFormat(IMFMediaType *mediaType)
131{
132 QAudioFormat format;
133 if (!mediaType)
134 return format;
135
136 UINT32 val = 0;
137 if (SUCCEEDED(mediaType->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &val))) {
138 format.setChannelCount(int(val));
139 } else {
140 qWarning() << "Could not determine channel count from IMFMediaType";
141 return {};
142 }
143
144 if (SUCCEEDED(mediaType->GetUINT32(MF_MT_AUDIO_CHANNEL_MASK, &val))) {
145 if (int(qPopulationCount(val)) >= format.channelCount())
146 format.setChannelConfig(maskToChannelConfig(val, format.channelCount()));
147 }
148
149 if (SUCCEEDED(mediaType->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &val))) {
150 format.setSampleRate(int(val));
151 }
152 UINT32 bitsPerSample = 0;
153 mediaType->GetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, &bitsPerSample);
154
155 GUID subType;
156 if (SUCCEEDED(mediaType->GetGUID(MF_MT_SUBTYPE, &subType))) {
157 if (subType == MFAudioFormat_Float) {
159 } else if (bitsPerSample == 8) {
161 } else if (bitsPerSample == 16) {
163 } else if (bitsPerSample == 32){
165 }
166 }
167 return format;
168}
169
170ComPtr<IMFMediaType> QWindowsAudioUtils::formatToMediaType(QWindowsMediaFoundation &wmf, const QAudioFormat &format)
171{
172 ComPtr<IMFMediaType> mediaType;
173
174 if (!format.isValid())
175 return mediaType;
176
177 wmf.mfCreateMediaType(mediaType.GetAddressOf());
178
179 mediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
181 mediaType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_Float);
182 } else {
183 mediaType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);
184 }
185
186 mediaType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, UINT32(format.channelCount()));
187 if (format.channelConfig() != QAudioFormat::ChannelConfigUnknown)
188 mediaType->SetUINT32(MF_MT_AUDIO_CHANNEL_MASK, channelConfigToMask(format.channelConfig()));
189 mediaType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, UINT32(format.sampleRate()));
190 auto alignmentBlock = UINT32(format.bytesPerFrame());
191 mediaType->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, alignmentBlock);
192 auto avgBytesPerSec = UINT32(format.sampleRate() * format.bytesPerFrame());
193 mediaType->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, avgBytesPerSec);
194 mediaType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, UINT32(format.bytesPerSample()*8));
195 mediaType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
196
197 return mediaType;
198}
199
201{
202 Q_ASSERT(client);
203 UINT32 framesPadding = 0;
204 if (SUCCEEDED(client->GetCurrentPadding(&framesPadding)))
205 return framesPadding;
206 return {};
207}
208
210{
211 Q_ASSERT(client);
212 UINT32 bufferFrameCount = 0;
213 if (SUCCEEDED(client->GetBufferSize(&bufferFrameCount)))
214 return bufferFrameCount;
215 return {};
216}
217
218QT_END_NAMESPACE
The QAudioFormat class stores audio stream parameter information.
constexpr SampleFormat sampleFormat() const noexcept
Returns the current sample format.
constexpr void setChannelCount(int channelCount) noexcept
Sets the channel count to channels.
AudioChannelPosition
Describes the possible audio channel positions.
constexpr void setSampleFormat(SampleFormat f) noexcept
Sets the sample format to format.
constexpr bool isValid() const noexcept
Returns true if all of the parameters are valid.
constexpr int sampleRate() const noexcept
Returns the current sample rate in Hertz.
constexpr int bytesPerFrame() const
Returns the number of bytes required to represent one frame (a sample in each channel) in this format...
constexpr int channelCount() const noexcept
Returns the current channel count value.
constexpr int bytesPerSample() const noexcept
Returns the number of bytes required to represent one sample in this format.
constexpr void setSampleRate(int sampleRate) noexcept
Sets the sample rate to samplerate in Hertz.
ChannelConfig
\variable QAudioFormat::NChannelPositions
Combined button and popup list for selecting options.
std::optional< quint32 > allocatedFrames(IAudioClient *client)
std::optional< WAVEFORMATEXTENSIBLE > toWaveFormatExtensible(const QAudioFormat &format)
std::optional< quint32 > usedFrames(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)
static UINT32 channelConfigToMask(QAudioFormat::ChannelConfig config)
static QT_BEGIN_NAMESPACE QAudioFormat::AudioChannelPosition channelFormatMap[]