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#ifndef QAUDIOBUFFER_H
5#define QAUDIOBUFFER_H
6
7#include <QtCore/qshareddata.h>
8
9#include <QtMultimedia/qtmultimediaglobal.h>
10
11#include <QtMultimedia/qaudio.h>
12#include <QtMultimedia/qaudioformat.h>
13
14QT_BEGIN_NAMESPACE
15
16namespace QtPrivate {
17template <QAudioFormat::SampleFormat> struct AudioSampleFormatHelper
18{
19};
20
21template <> struct AudioSampleFormatHelper<QAudioFormat::UInt8>
22{
23 using value_type = unsigned char;
24 static constexpr value_type Default = 128;
25};
26
27template <> struct AudioSampleFormatHelper<QAudioFormat::Int16>
28{
29 using value_type = short;
30 static constexpr value_type Default = 0;
31};
32
33template <> struct AudioSampleFormatHelper<QAudioFormat::Int32>
34{
35 using value_type = int;
36 static constexpr value_type Default = 0;
37};
38
39template <> struct AudioSampleFormatHelper<QAudioFormat::Float>
40{
41 using value_type = float;
42 static constexpr value_type Default = 0.;
43};
44
45}
46
47template <QAudioFormat::ChannelConfig config, QAudioFormat::SampleFormat format>
48struct QAudioFrame
49{
50private:
51 // popcount in qalgorithms.h is unfortunately not constexpr on MSVC.
52 // Use this here as a fallback
53 static constexpr int constexprPopcount(quint32 i)
54 {
55 i = i - ((i >> 1) & 0x55555555); // add pairs of bits
56 i = (i & 0x33333333) + ((i >> 2) & 0x33333333); // quads
57 i = (i + (i >> 4)) & 0x0F0F0F0F; // groups of 8
58 return (i * 0x01010101) >> 24; // horizontal sum of bytes
59 }
60 static constexpr int nChannels = constexprPopcount(i: config);
61public:
62 using value_type = typename QtPrivate::AudioSampleFormatHelper<format>::value_type;
63 value_type channels[nChannels];
64 static constexpr int positionToIndex(QAudioFormat::AudioChannelPosition pos)
65 {
66 if (!(config & (1u << pos)))
67 return -1;
68
69 uint maskedChannels = config & ((1u << pos) - 1);
70 return qPopulationCount(v: maskedChannels);
71 }
72
73
74 value_type value(QAudioFormat::AudioChannelPosition pos) const {
75 int idx = positionToIndex(pos);
76 if (idx < 0)
77 return QtPrivate::AudioSampleFormatHelper<format>::Default;
78 return channels[idx];
79 }
80 void setValue(QAudioFormat::AudioChannelPosition pos, value_type val) {
81 int idx = positionToIndex(pos);
82 if (idx < 0)
83 return;
84 channels[idx] = val;
85 }
86 value_type operator[](QAudioFormat::AudioChannelPosition pos) const {
87 return value(pos);
88 }
89 constexpr void clear() {
90 for (int i = 0; i < nChannels; ++i)
91 channels[i] = QtPrivate::AudioSampleFormatHelper<format>::Default;
92 }
93};
94
95template <QAudioFormat::SampleFormat Format>
96using QAudioFrameMono = QAudioFrame<QAudioFormat::ChannelConfigMono, Format>;
97
98template <QAudioFormat::SampleFormat Format>
99using QAudioFrameStereo = QAudioFrame<QAudioFormat::ChannelConfigStereo, Format>;
100
101template <QAudioFormat::SampleFormat Format>
102using QAudioFrame2Dot1 = QAudioFrame<QAudioFormat::ChannelConfig2Dot1, Format>;
103
104template <QAudioFormat::SampleFormat Format>
105using QAudioFrameSurround5Dot1 = QAudioFrame<QAudioFormat::ChannelConfigSurround5Dot1, Format>;
106
107template <QAudioFormat::SampleFormat Format>
108using QAudioFrameSurround7Dot1 = QAudioFrame<QAudioFormat::ChannelConfigSurround7Dot1, Format>;
109
110
111class QAudioBufferPrivate;
112QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QAudioBufferPrivate, Q_MULTIMEDIA_EXPORT)
113
114class Q_MULTIMEDIA_EXPORT QAudioBuffer
115{
116public:
117 QAudioBuffer() noexcept;
118 QAudioBuffer(const QAudioBuffer &other) noexcept;
119 QAudioBuffer(const QByteArray &data, const QAudioFormat &format, qint64 startTime = -1);
120 QAudioBuffer(int numFrames, const QAudioFormat &format, qint64 startTime = -1); // Initialized to empty
121 ~QAudioBuffer();
122
123 QAudioBuffer& operator=(const QAudioBuffer &other);
124
125 QAudioBuffer(QAudioBuffer &&other) noexcept = default;
126 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QAudioBuffer)
127 void swap(QAudioBuffer &other) noexcept
128 { d.swap(other&: other.d); }
129
130 bool isValid() const noexcept { return d != nullptr; };
131
132 void detach();
133
134 QAudioFormat format() const noexcept;
135
136 qsizetype frameCount() const noexcept;
137 qsizetype sampleCount() const noexcept;
138 qsizetype byteCount() const noexcept;
139
140 qint64 duration() const noexcept;
141 qint64 startTime() const noexcept;
142
143 // Structures for easier access to data
144 typedef QAudioFrameMono<QAudioFormat::UInt8> U8M;
145 typedef QAudioFrameMono<QAudioFormat::Int16> S16M;
146 typedef QAudioFrameMono<QAudioFormat::Int32> S32M;
147 typedef QAudioFrameMono<QAudioFormat::Float> F32M;
148
149 typedef QAudioFrameStereo<QAudioFormat::UInt8> U8S;
150 typedef QAudioFrameStereo<QAudioFormat::Int16> S16S;
151 typedef QAudioFrameStereo<QAudioFormat::Int32> S32S;
152 typedef QAudioFrameStereo<QAudioFormat::Float> F32S;
153
154 template <typename T> const T* constData() const {
155 return static_cast<const T*>(constData());
156 }
157 template <typename T> const T* data() const {
158 return static_cast<const T*>(data());
159 }
160 template <typename T> T* data() {
161 return static_cast<T*>(data());
162 }
163private:
164 const void* constData() const noexcept;
165 const void* data() const noexcept;
166 void *data();
167
168 QExplicitlySharedDataPointer<QAudioBufferPrivate> d;
169};
170
171QT_END_NAMESPACE
172
173Q_DECLARE_METATYPE(QAudioBuffer)
174
175#endif // QAUDIOBUFFER_H
176

source code of qtmultimedia/src/multimedia/audio/qaudiobuffer.h