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