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
4
5#include <qaudio.h>
6#include <qmath.h>
7#include <QDebug>
8
9QT_BEGIN_NAMESPACE
10
11#define LOG100 4.60517018599
12
13/*!
14 \namespace QAudio
15 \ingroup multimedia-namespaces
16 \brief The QAudio namespace contains enums used by the audio classes.
17 \inmodule QtMultimedia
18 \ingroup multimedia
19 \ingroup multimedia_audio
20*/
21
22/*!
23 \enum QAudio::Error
24
25 \value NoError No errors have occurred
26 \value OpenError An error occurred opening the audio device
27 \value IOError An error occurred during read/write of audio device
28 \value UnderrunError Audio data is not being fed to the audio device at a fast enough rate
29 \value FatalError A non-recoverable error has occurred, the audio device is not usable at this time.
30*/
31
32/*!
33 \enum QAudio::State
34
35 \value ActiveState Audio data is being processed, this state is set after start() is called
36 and while audio data is available to be processed.
37 \value SuspendedState The audio stream is in a suspended state. Entered after suspend() is called
38 or when another stream takes control of the audio device. In the later case,
39 a call to resume will return control of the audio device to this stream. This
40 should usually only be done upon user request.
41 \value StoppedState The audio device is closed, and is not processing any audio data
42 \value IdleState The QIODevice passed in has no data and audio system's buffer is empty, this state
43 is set after start() is called and while no audio data is available to be processed.
44*/
45
46/*!
47 \enum QAudio::VolumeScale
48
49 This enum defines the different audio volume scales.
50
51 \value LinearVolumeScale Linear scale. \c 0.0 (0%) is silence and \c 1.0 (100%) is full
52 volume. All Qt Multimedia classes that have an audio volume use
53 a linear scale.
54 \value CubicVolumeScale Cubic scale. \c 0.0 (0%) is silence and \c 1.0 (100%) is full
55 volume.
56 \value LogarithmicVolumeScale Logarithmic Scale. \c 0.0 (0%) is silence and \c 1.0 (100%) is
57 full volume. UI volume controls should usually use a logarithmic
58 scale.
59 \value DecibelVolumeScale Decibel (dB, amplitude) logarithmic scale. \c -200 is silence
60 and \c 0 is full volume.
61
62 \since 5.8
63 \sa QAudio::convertVolume()
64*/
65
66namespace QAudio
67{
68
69/*!
70 Converts an audio \a volume \a from a volume scale \a to another, and returns the result.
71
72 Depending on the context, different scales are used to represent audio volume. All Qt Multimedia
73 classes that have an audio volume use a linear scale, the reason is that the loudness of a
74 speaker is controlled by modulating its voltage on a linear scale. The human ear on the other
75 hand, perceives loudness in a logarithmic way. Using a logarithmic scale for volume controls
76 is therefore appropriate in most applications. The decibel scale is logarithmic by nature and
77 is commonly used to define sound levels, it is usually used for UI volume controls in
78 professional audio applications. The cubic scale is a computationally cheap approximation of a
79 logarithmic scale, it provides more control over lower volume levels.
80
81 The following example shows how to convert the volume value from a slider control before passing
82 it to a QMediaPlayer. As a result, the perceived increase in volume is the same when increasing
83 the volume slider from 20 to 30 as it is from 50 to 60:
84
85 \snippet multimedia-snippets/audio.cpp Volume conversion
86
87 \since 5.8
88 \sa VolumeScale, QAudioSink::setVolume(), QAudioSource::setVolume(),
89 QSoundEffect::setVolume()
90*/
91float convertVolume(float volume, VolumeScale from, VolumeScale to)
92{
93 switch (from) {
94 case LinearVolumeScale:
95 volume = qMax(a: float(0), b: volume);
96 switch (to) {
97 case LinearVolumeScale:
98 return volume;
99 case CubicVolumeScale:
100 return qPow(x: volume, y: float(1 / 3.0));
101 case LogarithmicVolumeScale:
102 return 1 - std::exp(x: -volume * LOG100);
103 case DecibelVolumeScale:
104 if (volume < 0.001)
105 return float(-200);
106 else
107 return float(20.0) * std::log10(x: volume);
108 }
109 break;
110 case CubicVolumeScale:
111 volume = qMax(a: float(0), b: volume);
112 switch (to) {
113 case LinearVolumeScale:
114 return volume * volume * volume;
115 case CubicVolumeScale:
116 return volume;
117 case LogarithmicVolumeScale:
118 return 1 - std::exp(x: -volume * volume * volume * LOG100);
119 case DecibelVolumeScale:
120 if (volume < 0.001)
121 return float(-200);
122 else
123 return float(3.0 * 20.0) * std::log10(x: volume);
124 }
125 break;
126 case LogarithmicVolumeScale:
127 volume = qMax(a: float(0), b: volume);
128 switch (to) {
129 case LinearVolumeScale:
130 if (volume > 0.99)
131 return 1;
132 else
133 return -std::log(x: 1 - volume) / LOG100;
134 case CubicVolumeScale:
135 if (volume > 0.99)
136 return 1;
137 else
138 return qPow(x: -std::log(x: 1 - volume) / LOG100, y: float(1 / 3.0));
139 case LogarithmicVolumeScale:
140 return volume;
141 case DecibelVolumeScale:
142 if (volume < 0.001)
143 return float(-200);
144 else if (volume > 0.99)
145 return 0;
146 else
147 return float(20.0) * std::log10(x: -std::log(x: 1 - volume) / LOG100);
148 }
149 break;
150 case DecibelVolumeScale:
151 switch (to) {
152 case LinearVolumeScale:
153 return qPow(x: float(10.0), y: volume / float(20.0));
154 case CubicVolumeScale:
155 return qPow(x: float(10.0), y: volume / float(3.0 * 20.0));
156 case LogarithmicVolumeScale:
157 if (qFuzzyIsNull(f: volume))
158 return 1;
159 else
160 return 1 - std::exp(x: -qPow(x: float(10.0), y: volume / float(20.0)) * LOG100);
161 case DecibelVolumeScale:
162 return volume;
163 }
164 break;
165 }
166
167 return volume;
168}
169
170}
171
172#ifndef QT_NO_DEBUG_STREAM
173QDebug operator<<(QDebug dbg, QAudio::Error error)
174{
175 QDebugStateSaver saver(dbg);
176 dbg.nospace();
177 switch (error) {
178 case QAudio::NoError:
179 dbg << "NoError";
180 break;
181 case QAudio::OpenError:
182 dbg << "OpenError";
183 break;
184 case QAudio::IOError:
185 dbg << "IOError";
186 break;
187 case QAudio::UnderrunError:
188 dbg << "UnderrunError";
189 break;
190 case QAudio::FatalError:
191 dbg << "FatalError";
192 break;
193 }
194 return dbg;
195}
196
197QDebug operator<<(QDebug dbg, QAudio::State state)
198{
199 QDebugStateSaver saver(dbg);
200 dbg.nospace();
201 switch (state) {
202 case QAudio::ActiveState:
203 dbg << "ActiveState";
204 break;
205 case QAudio::SuspendedState:
206 dbg << "SuspendedState";
207 break;
208 case QAudio::StoppedState:
209 dbg << "StoppedState";
210 break;
211 case QAudio::IdleState:
212 dbg << "IdleState";
213 break;
214 }
215 return dbg;
216}
217
218QDebug operator<<(QDebug dbg, QAudio::VolumeScale scale)
219{
220 QDebugStateSaver saver(dbg);
221 dbg.nospace();
222 switch (scale) {
223 case QAudio::LinearVolumeScale:
224 dbg << "LinearVolumeScale";
225 break;
226 case QAudio::CubicVolumeScale:
227 dbg << "CubicVolumeScale";
228 break;
229 case QAudio::LogarithmicVolumeScale:
230 dbg << "LogarithmicVolumeScale";
231 break;
232 case QAudio::DecibelVolumeScale:
233 dbg << "DecibelVolumeScale";
234 break;
235 }
236 return dbg;
237}
238
239#endif
240
241
242QT_END_NAMESPACE
243
244

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