| 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/qtaudio.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 | |