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 | |
14 | QT_BEGIN_NAMESPACE |
15 | |
16 | namespace QtPrivate { |
17 | template <QAudioFormat::SampleFormat> struct AudioSampleFormatHelper |
18 | { |
19 | }; |
20 | |
21 | template <> struct AudioSampleFormatHelper<QAudioFormat::UInt8> |
22 | { |
23 | using value_type = unsigned char; |
24 | static constexpr value_type Default = 128; |
25 | }; |
26 | |
27 | template <> struct AudioSampleFormatHelper<QAudioFormat::Int16> |
28 | { |
29 | using value_type = short; |
30 | static constexpr value_type Default = 0; |
31 | }; |
32 | |
33 | template <> struct AudioSampleFormatHelper<QAudioFormat::Int32> |
34 | { |
35 | using value_type = int; |
36 | static constexpr value_type Default = 0; |
37 | }; |
38 | |
39 | template <> struct AudioSampleFormatHelper<QAudioFormat::Float> |
40 | { |
41 | using value_type = float; |
42 | static constexpr value_type Default = 0.; |
43 | }; |
44 | |
45 | } |
46 | |
47 | template <QAudioFormat::ChannelConfig config, QAudioFormat::SampleFormat format> |
48 | struct QAudioFrame |
49 | { |
50 | private: |
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); |
61 | public: |
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 | |
95 | template <QAudioFormat::SampleFormat Format> |
96 | using QAudioFrameMono = QAudioFrame<QAudioFormat::ChannelConfigMono, Format>; |
97 | |
98 | template <QAudioFormat::SampleFormat Format> |
99 | using QAudioFrameStereo = QAudioFrame<QAudioFormat::ChannelConfigStereo, Format>; |
100 | |
101 | template <QAudioFormat::SampleFormat Format> |
102 | using QAudioFrame2Dot1 = QAudioFrame<QAudioFormat::ChannelConfig2Dot1, Format>; |
103 | |
104 | template <QAudioFormat::SampleFormat Format> |
105 | using QAudioFrameSurround5Dot1 = QAudioFrame<QAudioFormat::ChannelConfigSurround5Dot1, Format>; |
106 | |
107 | template <QAudioFormat::SampleFormat Format> |
108 | using QAudioFrameSurround7Dot1 = QAudioFrame<QAudioFormat::ChannelConfigSurround7Dot1, Format>; |
109 | |
110 | |
111 | class QAudioBufferPrivate; |
112 | QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QAudioBufferPrivate, Q_MULTIMEDIA_EXPORT) |
113 | |
114 | class Q_MULTIMEDIA_EXPORT QAudioBuffer |
115 | { |
116 | public: |
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 | } |
163 | private: |
164 | const void* constData() const noexcept; |
165 | const void* data() const noexcept; |
166 | void *data(); |
167 | |
168 | QExplicitlySharedDataPointer<QAudioBufferPrivate> d; |
169 | }; |
170 | |
171 | QT_END_NAMESPACE |
172 | |
173 | Q_DECLARE_METATYPE(QAudioBuffer) |
174 | |
175 | #endif // QAUDIOBUFFER_H |
176 | |