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 | #include <QDebug> |
4 | #include <qaudioformat.h> |
5 | #include <qalgorithms.h> |
6 | |
7 | QT_BEGIN_NAMESPACE |
8 | |
9 | /*! |
10 | \class QAudioFormat |
11 | \brief The QAudioFormat class stores audio stream parameter information. |
12 | |
13 | \inmodule QtMultimedia |
14 | \ingroup multimedia |
15 | \ingroup multimedia_audio |
16 | |
17 | An audio format specifies how data in a raw audio stream is arranged. For |
18 | example, how the stream is to be interpreted. |
19 | |
20 | QAudioFormat contains parameters that specify how the audio sample data |
21 | is arranged. These are the frequency, the number of channels, and the |
22 | sample format. The following table describes these in more detail. |
23 | |
24 | \table |
25 | \header |
26 | \li Parameter |
27 | \li Description |
28 | \row |
29 | \li Sample Rate |
30 | \li Samples per second of audio data in Hertz. |
31 | \row |
32 | \li Number of channels |
33 | \li The number of audio channels (typically one for mono |
34 | or two for stereo). These are the amount of consecutive |
35 | samples that together form one frame in the stream |
36 | \row |
37 | \li Sample format |
38 | \li The format of the audio samples in the stream |
39 | \endtable |
40 | |
41 | This class is used in conjunction with QAudioSource or |
42 | QAudioSink to allow you to specify the parameters of the audio |
43 | stream being read or written, or with QAudioBuffer when dealing with |
44 | samples in memory. |
45 | |
46 | You can obtain audio formats compatible with the audio device used |
47 | through functions in QAudioDevice. This class also lets you |
48 | query available parameter values for a device, so that you can set |
49 | the parameters yourself. See the \l QAudioDevice class |
50 | description for details. You need to know the format of the audio |
51 | streams you wish to play or record. |
52 | |
53 | Samples for all channels will be interleaved. |
54 | One sample for each channel for the same instant in time is referred |
55 | to as a frame in Qt Multimedia (and other places). |
56 | */ |
57 | |
58 | /*! |
59 | \fn QAudioFormat::QAudioFormat() |
60 | |
61 | Constructs a new audio format. |
62 | |
63 | Values are initialized as follows: |
64 | \list |
65 | \li sampleRate() = 0 |
66 | \li channelCount() = 0 |
67 | \li sampleFormat() = QAudioFormat::Unknown |
68 | \endlist |
69 | */ |
70 | |
71 | /*! |
72 | \fn QAudioFormat::QAudioFormat(const QAudioFormat &other) |
73 | |
74 | Construct a new audio format using \a other. |
75 | */ |
76 | |
77 | /*! |
78 | \fn QAudioFormat::~QAudioFormat() |
79 | |
80 | Destroy this audio format. |
81 | */ |
82 | |
83 | /*! |
84 | \fn bool QAudioFormat::operator==(const QAudioFormat &a, const QAudioFormat &b) |
85 | |
86 | Returns \c true if audio format \a a is equal to \a b, otherwise returns \c false. |
87 | */ |
88 | |
89 | /*! |
90 | \fn bool QAudioFormat::operator!=(const QAudioFormat &a, const QAudioFormat &b) |
91 | |
92 | Returns \c true if audio format \a a is not equal to \a b, otherwise returns \c false. |
93 | */ |
94 | |
95 | /*! |
96 | \fn bool QAudioFormat::isValid() const |
97 | |
98 | Returns \c true if all of the parameters are valid. |
99 | */ |
100 | |
101 | /*! |
102 | \fn void QAudioFormat::setSampleRate(int samplerate) |
103 | |
104 | Sets the sample rate to \a samplerate in Hertz. |
105 | */ |
106 | |
107 | /*! |
108 | \fn int QAudioFormat::sampleRate() const |
109 | |
110 | Returns the current sample rate in Hertz. |
111 | */ |
112 | |
113 | /*! |
114 | \enum QAudioFormat::AudioChannelPosition |
115 | |
116 | Describes the possible audio channel positions. These follow the standard |
117 | definition used in the 22.2 surround sound configuration. |
118 | |
119 | \value UnknownPosition Unknown position |
120 | \value FrontLeft |
121 | \value FrontRight |
122 | \value FrontCenter |
123 | \value LFE Low Frequency Effect channel (Subwoofer) |
124 | \value BackLeft |
125 | \value BackRight |
126 | \value FrontLeftOfCenter |
127 | \value FrontRightOfCenter |
128 | \value BackCenter |
129 | \value LFE2 |
130 | \value SideLeft |
131 | \value SideRight |
132 | \value TopFrontLeft |
133 | \value TopFrontRight |
134 | \value TopFrontCenter |
135 | \value TopCenter |
136 | \value TopBackLeft |
137 | \value TopBackRight |
138 | \value TopSideLeft |
139 | \value TopSideRight |
140 | \value TopBackCenter |
141 | \value BottomFrontCenter |
142 | \value BottomFrontLeft |
143 | \value BottomFrontRight |
144 | */ |
145 | /*! |
146 | \variable QAudioFormat::NChannelPositions |
147 | \internal |
148 | */ |
149 | |
150 | /*! |
151 | \enum QAudioFormat::ChannelConfig |
152 | |
153 | This enum describes a standardized audio channel layout. The most common |
154 | configurations are Mono, Stereo, 2.1 (stereo plus low frequency), 5.1 surround, |
155 | and 7.1 surround configurations. |
156 | |
157 | \value ChannelConfigUnknown The channel configuration is not known. |
158 | \value ChannelConfigMono The audio has one Center channel. |
159 | \value ChannelConfigStereo The audio has two channels, Left and Right. |
160 | \value ChannelConfig2Dot1 The audio has three channels, Left, Right and |
161 | LFE (low frequency effect). |
162 | \value ChannelConfig3Dot0 The audio has three channels, Left, Right, and |
163 | Center. |
164 | \value ChannelConfig3Dot1 The audio has four channels, Left, Right, Center, |
165 | and LFE (low frequency effect). |
166 | \value ChannelConfigSurround5Dot0 The audio has five channels, Left, Right, |
167 | Center, BackLeft, and BackRight. |
168 | \value ChannelConfigSurround5Dot1 The audio has 6 channels, Left, Right, |
169 | Center, LFE, BackLeft, and BackRight. |
170 | \value ChannelConfigSurround7Dot0 The audio has 7 channels, Left, Right, |
171 | Center, BackLeft, BackRight, SideLeft, and SideRight. |
172 | \value ChannelConfigSurround7Dot1 The audio has 8 channels, Left, Right, |
173 | Center, LFE, BackLeft, BackRight, SideLeft, and SideRight. |
174 | */ |
175 | |
176 | /*! |
177 | Sets the channel configuration to \a config. |
178 | |
179 | Sets the channel configuration of the audio format to one of the standard |
180 | audio channel configurations. |
181 | |
182 | \note that this will also modify the channel count. |
183 | */ |
184 | void QAudioFormat::setChannelConfig(ChannelConfig config) noexcept |
185 | { |
186 | m_channelConfig = config; |
187 | if (config != ChannelConfigUnknown) |
188 | m_channelCount = qPopulationCount(v: config); |
189 | } |
190 | |
191 | /*! |
192 | Returns the position of a certain audio \a channel inside an audio frame |
193 | for the given format. |
194 | Returns -1 if the channel does not exist for this format or the channel |
195 | configuration is unknown. |
196 | */ |
197 | int QAudioFormat::channelOffset(AudioChannelPosition channel) const noexcept |
198 | { |
199 | if (!(m_channelConfig & (1u << channel))) |
200 | return -1; |
201 | |
202 | uint maskedChannels = m_channelConfig & ((1u << channel) - 1); |
203 | return qPopulationCount(v: maskedChannels); |
204 | } |
205 | |
206 | /*! |
207 | \fn void QAudioFormat::setChannelCount(int channels) |
208 | |
209 | Sets the channel count to \a channels. Setting this also sets the channel |
210 | config to ChannelConfigUnknown. |
211 | */ |
212 | |
213 | /*! |
214 | \fn template <typename... Args> QAudioFormat::ChannelConfig QAudioFormat::channelConfig(Args... channels) |
215 | |
216 | Returns the current channel configuration for the given \a channels. |
217 | */ |
218 | /*! |
219 | \fn QAudioFormat::ChannelConfig QAudioFormat::channelConfig() const noexcept |
220 | |
221 | Returns the current channel configuration. |
222 | */ |
223 | |
224 | /*! |
225 | \fn int QAudioFormat::channelCount() const |
226 | |
227 | Returns the current channel count value. |
228 | |
229 | */ |
230 | |
231 | /*! |
232 | \fn void QAudioFormat::setSampleFormat(SampleFormat format) |
233 | |
234 | Sets the sample format to \a format. |
235 | |
236 | \sa QAudioFormat::SampleFormat |
237 | */ |
238 | |
239 | /*! |
240 | \fn QAudioFormat::SampleFormat QAudioFormat::sampleFormat() const |
241 | Returns the current sample format. |
242 | |
243 | \sa setSampleFormat() |
244 | */ |
245 | |
246 | /*! |
247 | Returns the number of bytes required for this audio format for \a microseconds. |
248 | |
249 | Returns 0 if this format is not valid. |
250 | |
251 | Note that some rounding may occur if \a microseconds is not an exact fraction of the |
252 | sampleRate(). |
253 | |
254 | \sa durationForBytes() |
255 | */ |
256 | qint32 QAudioFormat::bytesForDuration(qint64 microseconds) const |
257 | { |
258 | return bytesPerFrame() * framesForDuration(microseconds); |
259 | } |
260 | |
261 | /*! |
262 | Returns the number of microseconds represented by \a bytes in this format. |
263 | |
264 | Returns 0 if this format is not valid. |
265 | |
266 | Note that some rounding may occur if \a bytes is not an exact multiple |
267 | of the number of bytes per frame. |
268 | |
269 | \sa bytesForDuration() |
270 | */ |
271 | qint64 QAudioFormat::durationForBytes(qint32 bytes) const |
272 | { |
273 | // avoid compiler warnings about unused variables. [[maybe_unused]] in the header |
274 | // gives compiler errors on older gcc versions |
275 | Q_UNUSED(reserved); |
276 | |
277 | if (!isValid() || bytes <= 0) |
278 | return 0; |
279 | |
280 | // We round the byte count to ensure whole frames |
281 | return qint64(1000000LL * (bytes / bytesPerFrame())) / sampleRate(); |
282 | } |
283 | |
284 | /*! |
285 | Returns the number of bytes required for \a frameCount frames of this format. |
286 | |
287 | Returns 0 if this format is not valid. |
288 | |
289 | \sa bytesForDuration() |
290 | */ |
291 | qint32 QAudioFormat::bytesForFrames(qint32 frameCount) const |
292 | { |
293 | return frameCount * bytesPerFrame(); |
294 | } |
295 | |
296 | /*! |
297 | Returns the number of frames represented by \a byteCount in this format. |
298 | |
299 | Note that some rounding may occur if \a byteCount is not an exact multiple |
300 | of the number of bytes per frame. |
301 | |
302 | Each frame has one sample per channel. |
303 | |
304 | \sa framesForDuration() |
305 | */ |
306 | qint32 QAudioFormat::framesForBytes(qint32 byteCount) const |
307 | { |
308 | int size = bytesPerFrame(); |
309 | if (size > 0) |
310 | return byteCount / size; |
311 | return 0; |
312 | } |
313 | |
314 | /*! |
315 | Returns the number of frames required to represent \a microseconds in this format. |
316 | |
317 | Note that some rounding may occur if \a microseconds is not an exact fraction of the |
318 | \l sampleRate(). |
319 | */ |
320 | qint32 QAudioFormat::framesForDuration(qint64 microseconds) const |
321 | { |
322 | if (!isValid()) |
323 | return 0; |
324 | |
325 | return qint32((microseconds * sampleRate()) / 1000000LL); |
326 | } |
327 | |
328 | /*! |
329 | Return the number of microseconds represented by \a frameCount frames in this format. |
330 | */ |
331 | qint64 QAudioFormat::durationForFrames(qint32 frameCount) const |
332 | { |
333 | if (!isValid() || frameCount <= 0) |
334 | return 0; |
335 | |
336 | return (frameCount * 1000000LL) / sampleRate(); |
337 | } |
338 | |
339 | /*! |
340 | \fn int QAudioFormat::bytesPerFrame() const |
341 | |
342 | Returns the number of bytes required to represent one frame |
343 | (a sample in each channel) in this format. |
344 | |
345 | Returns 0 if this format is invalid. |
346 | */ |
347 | |
348 | /*! |
349 | \fn int QAudioFormat::bytesPerSample() const |
350 | Returns the number of bytes required to represent one sample in this format. |
351 | |
352 | Returns 0 if this format is invalid. |
353 | */ |
354 | |
355 | /*! |
356 | Normalizes the \a sample value to a number between -1 and 1. |
357 | The method depends on the QaudioFormat. |
358 | */ |
359 | float QAudioFormat::normalizedSampleValue(const void *sample) const |
360 | { |
361 | switch (m_sampleFormat) { |
362 | case UInt8: |
363 | return ((float)*reinterpret_cast<const quint8 *>(sample)) |
364 | / (float)std::numeric_limits<qint8>::max() |
365 | - 1.; |
366 | case Int16: |
367 | return ((float)*reinterpret_cast<const qint16 *>(sample)) |
368 | / (float)std::numeric_limits<qint16>::max(); |
369 | case Int32: |
370 | return ((float)*reinterpret_cast<const qint32 *>(sample)) |
371 | / (float)std::numeric_limits<qint32>::max(); |
372 | case Float: |
373 | return *reinterpret_cast<const float *>(sample); |
374 | case Unknown: |
375 | case NSampleFormats: |
376 | break; |
377 | } |
378 | |
379 | return 0.; |
380 | } |
381 | |
382 | /*! |
383 | Returns a default channel configuration for \a channelCount. |
384 | |
385 | Default configurations are defined for up to 8 channels, and correspond to |
386 | standard Mono, Stereo and Surround configurations. For higher channel counts, |
387 | this simply uses the first \a channelCount audio channels defined in |
388 | \l QAudioFormat::AudioChannelPosition. |
389 | */ |
390 | QAudioFormat::ChannelConfig QAudioFormat::defaultChannelConfigForChannelCount(int channelCount) |
391 | { |
392 | QAudioFormat::ChannelConfig config; |
393 | switch (channelCount) { |
394 | case 0: |
395 | config = QAudioFormat::ChannelConfigUnknown; |
396 | break; |
397 | case 1: |
398 | config = QAudioFormat::ChannelConfigMono; |
399 | break; |
400 | case 2: |
401 | config = QAudioFormat::ChannelConfigStereo; |
402 | break; |
403 | case 3: |
404 | config = QAudioFormat::ChannelConfig2Dot1; |
405 | break; |
406 | case 4: |
407 | config = QAudioFormat::channelConfig(channels: QAudioFormat::FrontLeft, channels: QAudioFormat::FrontRight, |
408 | channels: QAudioFormat::BackLeft, channels: QAudioFormat::BackRight); |
409 | break; |
410 | case 5: |
411 | config = QAudioFormat::ChannelConfigSurround5Dot0; |
412 | break; |
413 | case 6: |
414 | config = QAudioFormat::ChannelConfigSurround5Dot1; |
415 | break; |
416 | case 7: |
417 | config = QAudioFormat::ChannelConfigSurround7Dot0; |
418 | break; |
419 | case 8: |
420 | config = QAudioFormat::ChannelConfigSurround7Dot1; |
421 | break; |
422 | default: |
423 | // give up, simply use the first n channels |
424 | config = QAudioFormat::ChannelConfig((1 << (channelCount + 1)) - 1); |
425 | } |
426 | return config; |
427 | } |
428 | |
429 | /*! |
430 | \enum QAudioFormat::SampleFormat |
431 | |
432 | Qt will always expect and use samples in the endianness of the host platform. |
433 | When processing audio data from external sources yourself, ensure you convert |
434 | them to the correct endianness before writing them to a QAudioSink or |
435 | QAudioBuffer. |
436 | |
437 | \value Unknown Not Set |
438 | \value UInt8 Samples are unsigned 8 bit signed integers |
439 | \value Int16 Samples are 16 bit signed integers |
440 | \value Int32 Samples are 32 bit signed integers |
441 | \value Float Samples are floats |
442 | \omitvalue NSampleFormats |
443 | */ |
444 | |
445 | #ifndef QT_NO_DEBUG_STREAM |
446 | QDebug operator<<(QDebug dbg, QAudioFormat::SampleFormat type) |
447 | { |
448 | QDebugStateSaver saver(dbg); |
449 | dbg.nospace(); |
450 | switch (type) { |
451 | case QAudioFormat::UInt8: |
452 | dbg << "UInt8" ; |
453 | break; |
454 | case QAudioFormat::Int16: |
455 | dbg << "Int16" ; |
456 | break; |
457 | case QAudioFormat::Int32: |
458 | dbg << "Int32" ; |
459 | break; |
460 | case QAudioFormat::Float: |
461 | dbg << "Float" ; |
462 | break; |
463 | default: |
464 | dbg << "Unknown" ; |
465 | break; |
466 | } |
467 | return dbg; |
468 | } |
469 | |
470 | QDebug operator<<(QDebug dbg, const QAudioFormat &f) |
471 | { |
472 | dbg << "QAudioFormat(" << f.sampleRate() << "Hz, " << f.channelCount() << "Channels, " |
473 | << f.sampleFormat() << "Format )" ; |
474 | return dbg; |
475 | } |
476 | #endif |
477 | |
478 | QT_END_NAMESPACE |
479 | |