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
9QT_BEGIN_NAMESPACE
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
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 QtAudio::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 QtAudio::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 \sa QtAudio::convertVolume()
63*/
64
65#if defined(Q_QDOC)
66namespace QtAudio
67#else
68namespace QAudio
69#endif
70{
71
72/*!
73 Converts an audio \a volume \a from a volume scale \a to another, and returns the result.
74
75 Depending on the context, different scales are used to represent audio volume. All Qt Multimedia
76 classes that have an audio volume use a linear scale, the reason is that the loudness of a
77 speaker is controlled by modulating its voltage on a linear scale. The human ear on the other
78 hand, perceives loudness in a logarithmic way. Using a logarithmic scale for volume controls
79 is therefore appropriate in most applications. The decibel scale is logarithmic by nature and
80 is commonly used to define sound levels, it is usually used for UI volume controls in
81 professional audio applications. The cubic scale is a computationally cheap approximation of a
82 logarithmic scale, it provides more control over lower volume levels.
83
84 The following example shows how to convert the volume value from a slider control before passing
85 it to a QMediaPlayer. As a result, the perceived increase in volume is the same when increasing
86 the volume slider from 20 to 30 as it is from 50 to 60:
87
88 \snippet multimedia-snippets/audio.cpp Volume conversion
89
90 \sa VolumeScale, QAudioSink::setVolume(), QAudioSource::setVolume(),
91 QSoundEffect::setVolume()
92*/
93float convertVolume(float volume, VolumeScale from, VolumeScale to)
94{
95 switch (from) {
96 case LinearVolumeScale:
97 volume = qMax(a: float(0), b: volume);
98 switch (to) {
99 case LinearVolumeScale:
100 return volume;
101 case CubicVolumeScale:
102 return qPow(x: volume, y: float(1 / 3.0));
103 case LogarithmicVolumeScale:
104 return 1 - std::exp(x: -volume * LOG100);
105 case DecibelVolumeScale:
106 if (volume < 0.001)
107 return float(-200);
108 else
109 return float(20.0) * std::log10(x: volume);
110 }
111 break;
112 case CubicVolumeScale:
113 volume = qMax(a: float(0), b: volume);
114 switch (to) {
115 case LinearVolumeScale:
116 return volume * volume * volume;
117 case CubicVolumeScale:
118 return volume;
119 case LogarithmicVolumeScale:
120 return 1 - std::exp(x: -volume * volume * volume * LOG100);
121 case DecibelVolumeScale:
122 if (volume < 0.001)
123 return float(-200);
124 else
125 return float(3.0 * 20.0) * std::log10(x: volume);
126 }
127 break;
128 case LogarithmicVolumeScale:
129 volume = qMax(a: float(0), b: volume);
130 switch (to) {
131 case LinearVolumeScale:
132 if (volume > 0.99)
133 return 1;
134 else
135 return -std::log(x: 1 - volume) / LOG100;
136 case CubicVolumeScale:
137 if (volume > 0.99)
138 return 1;
139 else
140 return qPow(x: -std::log(x: 1 - volume) / LOG100, y: float(1 / 3.0));
141 case LogarithmicVolumeScale:
142 return volume;
143 case DecibelVolumeScale:
144 if (volume < 0.001)
145 return float(-200);
146 else if (volume > 0.99)
147 return 0;
148 else
149 return float(20.0) * std::log10(x: -std::log(x: 1 - volume) / LOG100);
150 }
151 break;
152 case DecibelVolumeScale:
153 switch (to) {
154 case LinearVolumeScale:
155 return qPow(x: float(10.0), y: volume / float(20.0));
156 case CubicVolumeScale:
157 return qPow(x: float(10.0), y: volume / float(3.0 * 20.0));
158 case LogarithmicVolumeScale:
159 if (qFuzzyIsNull(f: volume))
160 return 1;
161 else
162 return 1 - std::exp(x: -qPow(x: float(10.0), y: volume / float(20.0)) * LOG100);
163 case DecibelVolumeScale:
164 return volume;
165 }
166 break;
167 }
168
169 return volume;
170}
171
172}
173
174#ifndef QT_NO_DEBUG_STREAM
175QDebug operator<<(QDebug dbg, QAudio::Error error)
176{
177 QDebugStateSaver saver(dbg);
178 dbg.nospace();
179 switch (error) {
180 case QAudio::NoError:
181 dbg << "NoError";
182 break;
183 case QAudio::OpenError:
184 dbg << "OpenError";
185 break;
186 case QAudio::IOError:
187 dbg << "IOError";
188 break;
189 case QAudio::UnderrunError:
190 dbg << "UnderrunError";
191 break;
192 case QAudio::FatalError:
193 dbg << "FatalError";
194 break;
195 }
196 return dbg;
197}
198
199QDebug operator<<(QDebug dbg, QAudio::State state)
200{
201 QDebugStateSaver saver(dbg);
202 dbg.nospace();
203 switch (state) {
204 case QAudio::ActiveState:
205 dbg << "ActiveState";
206 break;
207 case QAudio::SuspendedState:
208 dbg << "SuspendedState";
209 break;
210 case QAudio::StoppedState:
211 dbg << "StoppedState";
212 break;
213 case QAudio::IdleState:
214 dbg << "IdleState";
215 break;
216 }
217 return dbg;
218}
219
220QDebug operator<<(QDebug dbg, QAudio::VolumeScale scale)
221{
222 QDebugStateSaver saver(dbg);
223 dbg.nospace();
224 switch (scale) {
225 case QAudio::LinearVolumeScale:
226 dbg << "LinearVolumeScale";
227 break;
228 case QAudio::CubicVolumeScale:
229 dbg << "CubicVolumeScale";
230 break;
231 case QAudio::LogarithmicVolumeScale:
232 dbg << "LogarithmicVolumeScale";
233 break;
234 case QAudio::DecibelVolumeScale:
235 dbg << "DecibelVolumeScale";
236 break;
237 }
238 return dbg;
239}
240
241#endif
242
243
244QT_END_NAMESPACE
245
246

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

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