1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40
41#include <qaudio.h>
42#include <qmath.h>
43#include <QDebug>
44
45QT_BEGIN_NAMESPACE
46
47#define LOG100 4.60517018599
48
49static void qRegisterAudioMetaTypes()
50{
51 qRegisterMetaType<QAudio::Error>();
52 qRegisterMetaType<QAudio::State>();
53 qRegisterMetaType<QAudio::Mode>();
54 qRegisterMetaType<QAudio::Role>();
55 qRegisterMetaType<QAudio::VolumeScale>();
56}
57
58Q_CONSTRUCTOR_FUNCTION(qRegisterAudioMetaTypes)
59
60/*!
61 \namespace QAudio
62 \ingroup multimedia-namespaces
63 \brief The QAudio namespace contains enums used by the audio classes.
64 \inmodule QtMultimedia
65 \ingroup multimedia
66 \ingroup multimedia_audio
67*/
68
69/*!
70 \enum QAudio::Error
71
72 \value NoError No errors have occurred
73 \value OpenError An error occurred opening the audio device
74 \value IOError An error occurred during read/write of audio device
75 \value UnderrunError Audio data is not being fed to the audio device at a fast enough rate
76 \value FatalError A non-recoverable error has occurred, the audio device is not usable at this time.
77*/
78
79/*!
80 \enum QAudio::State
81
82 \value ActiveState Audio data is being processed, this state is set after start() is called
83 and while audio data is available to be processed.
84 \value SuspendedState The audio stream is in a suspended state. Entered after suspend() is called
85 or when another stream takes control of the audio device. In the later case,
86 a call to resume will return control of the audio device to this stream. This
87 should usually only be done upon user request.
88 \value StoppedState The audio device is closed, and is not processing any audio data
89 \value IdleState The QIODevice passed in has no data and audio system's buffer is empty, this state
90 is set after start() is called and while no audio data is available to be processed.
91 \value InterruptedState This stream is in a suspended state because another higher priority stream currently
92 has control of the audio device. Playback cannot resume until the higher priority
93 stream relinquishes control of the audio device.
94*/
95
96/*!
97 \enum QAudio::Mode
98
99 \value AudioOutput audio output device
100 \value AudioInput audio input device
101*/
102
103/*!
104 \enum QAudio::Role
105
106 This enum describes the role of an audio stream.
107
108 \value UnknownRole The role is unknown or undefined
109 \value MusicRole Music
110 \value VideoRole Soundtrack from a movie or a video
111 \value VoiceCommunicationRole Voice communications, such as telephony
112 \value AlarmRole Alarm
113 \value NotificationRole Notification, such as an incoming e-mail or a chat request
114 \value RingtoneRole Ringtone
115 \value AccessibilityRole For accessibility, such as with a screen reader
116 \value SonificationRole Sonification, such as with user interface sounds
117 \value GameRole Game audio
118 \value CustomRole The role is specified by QMediaPlayer::customAudioRole()
119
120 \since 5.6
121 \sa QMediaPlayer::setAudioRole()
122*/
123
124/*!
125 \enum QAudio::VolumeScale
126
127 This enum defines the different audio volume scales.
128
129 \value LinearVolumeScale Linear scale. \c 0.0 (0%) is silence and \c 1.0 (100%) is full
130 volume. All Qt Multimedia classes that have an audio volume use
131 a linear scale.
132 \value CubicVolumeScale Cubic scale. \c 0.0 (0%) is silence and \c 1.0 (100%) is full
133 volume.
134 \value LogarithmicVolumeScale Logarithmic Scale. \c 0.0 (0%) is silence and \c 1.0 (100%) is
135 full volume. UI volume controls should usually use a logarithmic
136 scale.
137 \value DecibelVolumeScale Decibel (dB, amplitude) logarithmic scale. \c -200 is silence
138 and \c 0 is full volume.
139
140 \since 5.8
141 \sa QAudio::convertVolume()
142*/
143
144namespace QAudio
145{
146
147/*!
148 \fn qreal QAudio::convertVolume(qreal volume, VolumeScale from, VolumeScale to)
149
150 Converts an audio \a volume \a from a volume scale \a to another, and returns the result.
151
152 Depending on the context, different scales are used to represent audio volume. All Qt Multimedia
153 classes that have an audio volume use a linear scale, the reason is that the loudness of a
154 speaker is controlled by modulating its voltage on a linear scale. The human ear on the other
155 hand, perceives loudness in a logarithmic way. Using a logarithmic scale for volume controls
156 is therefore appropriate in most applications. The decibel scale is logarithmic by nature and
157 is commonly used to define sound levels, it is usually used for UI volume controls in
158 professional audio applications. The cubic scale is a computationally cheap approximation of a
159 logarithmic scale, it provides more control over lower volume levels.
160
161 The following example shows how to convert the volume value from a slider control before passing
162 it to a QMediaPlayer. As a result, the perceived increase in volume is the same when increasing
163 the volume slider from 20 to 30 as it is from 50 to 60:
164
165 \snippet multimedia-snippets/audio.cpp Volume conversion
166
167 \since 5.8
168 \sa VolumeScale, QMediaPlayer::setVolume(), QAudioOutput::setVolume(),
169 QAudioInput::setVolume(), QSoundEffect::setVolume(), QMediaRecorder::setVolume()
170*/
171qreal convertVolume(qreal volume, VolumeScale from, VolumeScale to)
172{
173 switch (from) {
174 case LinearVolumeScale:
175 volume = qMax(a: qreal(0), b: volume);
176 switch (to) {
177 case LinearVolumeScale:
178 return volume;
179 case CubicVolumeScale:
180 return qPow(x: volume, y: qreal(1 / 3.0));
181 case LogarithmicVolumeScale:
182 return 1 - std::exp(x: -volume * LOG100);
183 case DecibelVolumeScale:
184 if (volume < 0.001)
185 return qreal(-200);
186 else
187 return qreal(20.0) * std::log10(x: volume);
188 }
189 break;
190 case CubicVolumeScale:
191 volume = qMax(a: qreal(0), b: volume);
192 switch (to) {
193 case LinearVolumeScale:
194 return volume * volume * volume;
195 case CubicVolumeScale:
196 return volume;
197 case LogarithmicVolumeScale:
198 return 1 - std::exp(x: -volume * volume * volume * LOG100);
199 case DecibelVolumeScale:
200 if (volume < 0.001)
201 return qreal(-200);
202 else
203 return qreal(3.0 * 20.0) * std::log10(x: volume);
204 }
205 break;
206 case LogarithmicVolumeScale:
207 volume = qMax(a: qreal(0), b: volume);
208 switch (to) {
209 case LinearVolumeScale:
210 if (volume > 0.99)
211 return 1;
212 else
213 return -std::log(x: 1 - volume) / LOG100;
214 case CubicVolumeScale:
215 if (volume > 0.99)
216 return 1;
217 else
218 return qPow(x: -std::log(x: 1 - volume) / LOG100, y: qreal(1 / 3.0));
219 case LogarithmicVolumeScale:
220 return volume;
221 case DecibelVolumeScale:
222 if (volume < 0.001)
223 return qreal(-200);
224 else if (volume > 0.99)
225 return 0;
226 else
227 return qreal(20.0) * std::log10(x: -std::log(x: 1 - volume) / LOG100);
228 }
229 break;
230 case DecibelVolumeScale:
231 switch (to) {
232 case LinearVolumeScale:
233 return qPow(x: qreal(10.0), y: volume / qreal(20.0));
234 case CubicVolumeScale:
235 return qPow(x: qreal(10.0), y: volume / qreal(3.0 * 20.0));
236 case LogarithmicVolumeScale:
237 if (qFuzzyIsNull(d: volume))
238 return 1;
239 else
240 return 1 - std::exp(x: -qPow(x: qreal(10.0), y: volume / qreal(20.0)) * LOG100);
241 case DecibelVolumeScale:
242 return volume;
243 }
244 break;
245 }
246
247 return volume;
248}
249
250}
251
252#ifndef QT_NO_DEBUG_STREAM
253QDebug operator<<(QDebug dbg, QAudio::Error error)
254{
255 QDebugStateSaver saver(dbg);
256 dbg.nospace();
257 switch (error) {
258 case QAudio::NoError:
259 dbg << "NoError";
260 break;
261 case QAudio::OpenError:
262 dbg << "OpenError";
263 break;
264 case QAudio::IOError:
265 dbg << "IOError";
266 break;
267 case QAudio::UnderrunError:
268 dbg << "UnderrunError";
269 break;
270 case QAudio::FatalError:
271 dbg << "FatalError";
272 break;
273 }
274 return dbg;
275}
276
277QDebug operator<<(QDebug dbg, QAudio::State state)
278{
279 QDebugStateSaver saver(dbg);
280 dbg.nospace();
281 switch (state) {
282 case QAudio::ActiveState:
283 dbg << "ActiveState";
284 break;
285 case QAudio::SuspendedState:
286 dbg << "SuspendedState";
287 break;
288 case QAudio::StoppedState:
289 dbg << "StoppedState";
290 break;
291 case QAudio::IdleState:
292 dbg << "IdleState";
293 break;
294 case QAudio::InterruptedState:
295 dbg << "InterruptedState";
296 break;
297 }
298 return dbg;
299}
300
301QDebug operator<<(QDebug dbg, QAudio::Mode mode)
302{
303 QDebugStateSaver saver(dbg);
304 dbg.nospace();
305 switch (mode) {
306 case QAudio::AudioInput:
307 dbg << "AudioInput";
308 break;
309 case QAudio::AudioOutput:
310 dbg << "AudioOutput";
311 break;
312 }
313 return dbg;
314}
315
316QDebug operator<<(QDebug dbg, QAudio::Role role)
317{
318 QDebugStateSaver saver(dbg);
319 dbg.nospace();
320 switch (role) {
321 case QAudio::UnknownRole:
322 dbg << "UnknownRole";
323 break;
324 case QAudio::AccessibilityRole:
325 dbg << "AccessibilityRole";
326 break;
327 case QAudio::AlarmRole:
328 dbg << "AlarmRole";
329 break;
330 case QAudio::GameRole:
331 dbg << "GameRole";
332 break;
333 case QAudio::MusicRole:
334 dbg << "MusicRole";
335 break;
336 case QAudio::NotificationRole:
337 dbg << "NotificationRole";
338 break;
339 case QAudio::RingtoneRole:
340 dbg << "RingtoneRole";
341 break;
342 case QAudio::SonificationRole:
343 dbg << "SonificationRole";
344 break;
345 case QAudio::VideoRole:
346 dbg << "VideoRole";
347 break;
348 case QAudio::VoiceCommunicationRole:
349 dbg << "VoiceCommunicationRole";
350 break;
351 case QAudio::CustomRole:
352 dbg << "CustomRole";
353 break;
354 }
355 return dbg;
356}
357
358QDebug operator<<(QDebug dbg, QAudio::VolumeScale scale)
359{
360 QDebugStateSaver saver(dbg);
361 dbg.nospace();
362 switch (scale) {
363 case QAudio::LinearVolumeScale:
364 dbg << "LinearVolumeScale";
365 break;
366 case QAudio::CubicVolumeScale:
367 dbg << "CubicVolumeScale";
368 break;
369 case QAudio::LogarithmicVolumeScale:
370 dbg << "LogarithmicVolumeScale";
371 break;
372 case QAudio::DecibelVolumeScale:
373 dbg << "DecibelVolumeScale";
374 break;
375 }
376 return dbg;
377}
378
379#endif
380
381
382QT_END_NAMESPACE
383
384

source code of qtmultimedia/src/multimedia/audio/qaudio.cpp