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
qdarwinaudiodevice.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies).
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <QtCore/private/qcore_mac_p.h>
7
8#include <QtMultimedia/private/qcoreaudioutils_p.h>
9#include <QtMultimedia/private/qaudioformat_p.h>
10#ifdef Q_OS_MACOS
11#include <QtMultimedia/private/qmacosaudiodatautils_p.h>
12#endif
13
14#include <optional>
15
16QT_BEGIN_NAMESPACE
17
18namespace {
19
21 QAudioDevice::Mode mode,
22 QAudioFormat::ChannelConfig channelConfig)
23{
24 QAudioFormat format;
25 format.setSampleRate(44100);
26 format.setSampleFormat(QAudioFormat::Int16);
27 format.setChannelCount(mode == QAudioDevice::Input ? 1 : 2);
28 format.setChannelConfig(channelConfig);
29 return format;
30}
31
32[[nodiscard]] QAudioFormat::ChannelConfig qGetDefaultChannelLayout(QAudioDevice::Mode mode)
33{
34 return (mode == QAudioDevice::Input) ? QAudioFormat::ChannelConfigMono : QAudioFormat::ChannelConfigStereo;
35}
36
37[[nodiscard]] QString qGetDefaultDescription(const QByteArray &id)
38{
39 return QString::fromUtf8(id);
40}
41
42#ifdef Q_OS_MACOS
43
44[[nodiscard]] std::optional<QAudioFormat> qGetPreferredFormatForCoreAudioDevice(
45 QAudioDevice::Mode mode,
46 AudioDeviceID deviceId)
47{
48 using namespace QCoreAudioUtils;
49
50 const auto audioDevicePropertyStreamsAddress =
51 makePropertyAddress(kAudioDevicePropertyStreams, mode);
52
53 if (auto streamIDs = getAudioPropertyList<AudioStreamID>(deviceId, audioDevicePropertyStreamsAddress)) {
54 const auto audioDevicePhysicalFormatPropertyAddress =
55 makePropertyAddress(kAudioStreamPropertyPhysicalFormat, mode);
56
57 for (auto streamID : *streamIDs) {
58 if (auto streamDescription = getAudioProperty<AudioStreamBasicDescription>(
59 streamID, audioDevicePhysicalFormatPropertyAddress)) {
60 return QCoreAudioUtils::toQAudioFormat(*streamDescription);
61 }
62 }
63 }
64
65 return std::nullopt;
66}
67
68[[nodiscard]] std::optional<QAudioFormat::ChannelConfig> qGetChannelLayoutForCoreAudioDevice(
69 QAudioDevice::Mode mode,
70 AudioDeviceID deviceId)
71{
72 using namespace QCoreAudioUtils;
73
74 const auto propertyAddress =
75 makePropertyAddress(kAudioDevicePropertyPreferredChannelLayout, mode);
76
77 if (auto layout = getAudioPropertyWithFlexibleArrayMember<AudioChannelLayout>(deviceId, propertyAddress))
78 return QCoreAudioUtils::fromAudioChannelLayout(layout.get());
79
80 return std::nullopt;
81}
82
83[[nodiscard]] std::optional<QString> qGetDescriptionForCoreAudioDevice(
84 QAudioDevice::Mode mode,
85 AudioDeviceID deviceId)
86{
87 using namespace QCoreAudioUtils;
88
89 const auto propertyAddress = makePropertyAddress(kAudioObjectPropertyName, mode);
90 if (auto name = getAudioProperty<QCFString>(deviceId, propertyAddress))
91 return name;
92
93 return std::nullopt;
94}
95
96[[nodiscard]] std::optional<int> qSupportedNumberOfChannels(
97 QAudioDevice::Mode mode,
98 AudioDeviceID deviceId)
99{
100 using namespace QCoreAudioUtils;
101
102 const auto audioDevicePropertyStreamsAddress =
103 makePropertyAddress(kAudioDevicePropertyStreams, mode);
104
105 auto streamIDs = getAudioPropertyList<AudioStreamID>(deviceId, audioDevicePropertyStreamsAddress);
106 if (!streamIDs)
107 return std::nullopt;
108
109 const auto propVirtualFormat = makePropertyAddress(kAudioStreamPropertyVirtualFormat, mode);
110
111 int ret{};
112
113 for (auto streamID : *streamIDs) {
114 auto streamDescription = getAudioProperty<AudioStreamBasicDescription>(streamID, propVirtualFormat);
115 if (!streamDescription)
116 continue;
117 ret += streamDescription->mChannelsPerFrame;
118 }
119
120 return ret;
121}
122
123#endif
124
125} // namespace
126
127#ifdef Q_OS_MACOS
128
129static QString getDescription(AudioDeviceID id, const QByteArray &device, QAudioDevice::Mode mode)
130{
131 if (auto optionalDescription = qGetDescriptionForCoreAudioDevice(mode, id))
132 return *optionalDescription;
133 return qGetDefaultDescription(device);
134}
135
136QCoreAudioDeviceInfo::QCoreAudioDeviceInfo(AudioDeviceID id, const QByteArray &device, QAudioDevice::Mode mode):
137 QAudioDevicePrivate{
138 device,
139 mode,
140 getDescription(id, device, mode),
141 }
142{
143 const std::optional<QAudioFormat::ChannelConfig> channelConfigOpt =
144 qGetChannelLayoutForCoreAudioDevice(mode, id);
145 if (channelConfigOpt.has_value())
146 channelConfiguration = channelConfigOpt.value();
147 else
148 channelConfiguration = qGetDefaultChannelLayout(mode);
149
150 const std::optional<QAudioFormat> preferredFormatOpt =
151 qGetPreferredFormatForCoreAudioDevice(mode, id);
152 if (preferredFormatOpt.has_value())
153 preferredFormat = preferredFormatOpt.value();
154 else
155 preferredFormat = qDefaultPreferredFormat(mode, channelConfiguration);
156
157 minimumSampleRate = QtMultimediaPrivate::allSupportedSampleRates.front();
158 maximumSampleRate = QtMultimediaPrivate::allSupportedSampleRates.back();
159 minimumChannelCount = 1;
160 maximumChannelCount = qSupportedNumberOfChannels(mode, id).value_or(16);
161
162 supportedSampleFormats = qAllSupportedSampleFormats();
163}
164
165#else
166
167QCoreAudioDeviceInfo::QCoreAudioDeviceInfo(const QByteArray &device, QAudioDevice::Mode mode)
168 : QAudioDevicePrivate(device, mode, qGetDefaultDescription(device))
169{
170 channelConfiguration = qGetDefaultChannelLayout(mode);
171 preferredFormat = qDefaultPreferredFormat(mode, channelConfiguration);
172
173 minimumSampleRate = 1;
174 maximumSampleRate = 96000;
175 minimumChannelCount = 1;
176 maximumChannelCount = 16;
177 supportedSampleFormats = qAllSupportedSampleFormats();
178}
179
180#endif
181
182QT_END_NAMESPACE
QAudioFormat::ChannelConfig qGetDefaultChannelLayout(QAudioDevice::Mode mode)
QAudioFormat qDefaultPreferredFormat(QAudioDevice::Mode mode, QAudioFormat::ChannelConfig channelConfig)
QString qGetDefaultDescription(const QByteArray &id)