// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QAUDIOBUFFER_H #define QAUDIOBUFFER_H #include #include #include #include QT_BEGIN_NAMESPACE namespace QtPrivate { template struct AudioSampleFormatHelper { }; template <> struct AudioSampleFormatHelper { using value_type = unsigned char; static constexpr value_type Default = 128; }; template <> struct AudioSampleFormatHelper { using value_type = short; static constexpr value_type Default = 0; }; template <> struct AudioSampleFormatHelper { using value_type = int; static constexpr value_type Default = 0; }; template <> struct AudioSampleFormatHelper { using value_type = float; static constexpr value_type Default = 0.; }; } template struct QAudioFrame { private: // popcount in qalgorithms.h is unfortunately not constexpr on MSVC. // Use this here as a fallback static constexpr int constexprPopcount(quint32 i) { i = i - ((i >> 1) & 0x55555555); // add pairs of bits i = (i & 0x33333333) + ((i >> 2) & 0x33333333); // quads i = (i + (i >> 4)) & 0x0F0F0F0F; // groups of 8 return (i * 0x01010101) >> 24; // horizontal sum of bytes } static constexpr int nChannels = constexprPopcount(config); public: using value_type = typename QtPrivate::AudioSampleFormatHelper::value_type; value_type channels[nChannels]; static constexpr int positionToIndex(QAudioFormat::AudioChannelPosition pos) { if (!(config & (1u << pos))) return -1; uint maskedChannels = config & ((1u << pos) - 1); return qPopulationCount(maskedChannels); } value_type value(QAudioFormat::AudioChannelPosition pos) const { int idx = positionToIndex(pos); if (idx < 0) return QtPrivate::AudioSampleFormatHelper::Default; return channels[idx]; } void setValue(QAudioFormat::AudioChannelPosition pos, value_type val) { int idx = positionToIndex(pos); if (idx < 0) return; channels[idx] = val; } value_type operator[](QAudioFormat::AudioChannelPosition pos) const { return value(pos); } constexpr void clear() { for (int i = 0; i < nChannels; ++i) channels[i] = QtPrivate::AudioSampleFormatHelper::Default; } }; template using QAudioFrameMono = QAudioFrame; template using QAudioFrameStereo = QAudioFrame; template using QAudioFrame2Dot1 = QAudioFrame; template using QAudioFrameSurround5Dot1 = QAudioFrame; template using QAudioFrameSurround7Dot1 = QAudioFrame; class QAudioBufferPrivate; QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QAudioBufferPrivate, Q_MULTIMEDIA_EXPORT) class Q_MULTIMEDIA_EXPORT QAudioBuffer { public: QAudioBuffer() noexcept; QAudioBuffer(const QAudioBuffer &other) noexcept; QAudioBuffer(const QByteArray &data, const QAudioFormat &format, qint64 startTime = -1); QAudioBuffer(int numFrames, const QAudioFormat &format, qint64 startTime = -1); // Initialized to empty ~QAudioBuffer(); QAudioBuffer& operator=(const QAudioBuffer &other); QAudioBuffer(QAudioBuffer &&other) noexcept = default; QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QAudioBuffer) void swap(QAudioBuffer &other) noexcept { d.swap(other.d); } bool isValid() const noexcept { return d != nullptr; }; void detach(); QAudioFormat format() const noexcept; qsizetype frameCount() const noexcept; qsizetype sampleCount() const noexcept; qsizetype byteCount() const noexcept; qint64 duration() const noexcept; qint64 startTime() const noexcept; // Structures for easier access to data typedef QAudioFrameMono U8M; typedef QAudioFrameMono S16M; typedef QAudioFrameMono S32M; typedef QAudioFrameMono F32M; typedef QAudioFrameStereo U8S; typedef QAudioFrameStereo S16S; typedef QAudioFrameStereo S32S; typedef QAudioFrameStereo F32S; template const T* constData() const { return static_cast(constData()); } template const T* data() const { return static_cast(data()); } template T* data() { return static_cast(data()); } private: const void* constData() const noexcept; const void* data() const noexcept; void *data(); QExplicitlySharedDataPointer d; }; QT_END_NAMESPACE Q_DECLARE_METATYPE(QAudioBuffer) #endif // QAUDIOBUFFER_H