diff options
Diffstat (limited to 'src/multimedia/audio/qaudiobuffer.h')
-rw-r--r-- | src/multimedia/audio/qaudiobuffer.h | 230 |
1 files changed, 127 insertions, 103 deletions
diff --git a/src/multimedia/audio/qaudiobuffer.h b/src/multimedia/audio/qaudiobuffer.h index bed387462..822619f31 100644 --- a/src/multimedia/audio/qaudiobuffer.h +++ b/src/multimedia/audio/qaudiobuffer.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// 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 @@ -43,89 +7,149 @@ #include <QtCore/qshareddata.h> #include <QtMultimedia/qtmultimediaglobal.h> -#include <QtMultimedia/qmultimedia.h> -#include <QtMultimedia/qaudio.h> +#include <QtMultimedia/qtaudio.h> #include <QtMultimedia/qaudioformat.h> QT_BEGIN_NAMESPACE -class QAbstractAudioBuffer; -class QAudioBufferPrivate; -class Q_MULTIMEDIA_EXPORT QAudioBuffer +namespace QtPrivate { +template <QAudioFormat::SampleFormat> struct AudioSampleFormatHelper +{ +}; + +template <> struct AudioSampleFormatHelper<QAudioFormat::UInt8> +{ + using value_type = unsigned char; + static constexpr value_type Default = 128; +}; + +template <> struct AudioSampleFormatHelper<QAudioFormat::Int16> +{ + using value_type = short; + static constexpr value_type Default = 0; +}; + +template <> struct AudioSampleFormatHelper<QAudioFormat::Int32> { + using value_type = int; + static constexpr value_type Default = 0; +}; + +template <> struct AudioSampleFormatHelper<QAudioFormat::Float> +{ + using value_type = float; + static constexpr value_type Default = 0.; +}; + +} + +template <QAudioFormat::ChannelConfig config, QAudioFormat::SampleFormat format> +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: - QAudioBuffer(); - QAudioBuffer(QAbstractAudioBuffer *provider); - QAudioBuffer(const QAudioBuffer &other); - QAudioBuffer(const QByteArray &data, const QAudioFormat &format, qint64 startTime = -1); - QAudioBuffer(int numFrames, const QAudioFormat &format, qint64 startTime = -1); // Initialized to empty + using value_type = typename QtPrivate::AudioSampleFormatHelper<format>::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); + } - QAudioBuffer& operator=(const QAudioBuffer &other); - ~QAudioBuffer(); + value_type value(QAudioFormat::AudioChannelPosition pos) const { + int idx = positionToIndex(pos); + if (idx < 0) + return QtPrivate::AudioSampleFormatHelper<format>::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<format>::Default; + } +}; + +template <QAudioFormat::SampleFormat Format> +using QAudioFrameMono = QAudioFrame<QAudioFormat::ChannelConfigMono, Format>; + +template <QAudioFormat::SampleFormat Format> +using QAudioFrameStereo = QAudioFrame<QAudioFormat::ChannelConfigStereo, Format>; + +template <QAudioFormat::SampleFormat Format> +using QAudioFrame2Dot1 = QAudioFrame<QAudioFormat::ChannelConfig2Dot1, Format>; - bool isValid() const; +template <QAudioFormat::SampleFormat Format> +using QAudioFrameSurround5Dot1 = QAudioFrame<QAudioFormat::ChannelConfigSurround5Dot1, Format>; - QAudioFormat format() const; +template <QAudioFormat::SampleFormat Format> +using QAudioFrameSurround7Dot1 = QAudioFrame<QAudioFormat::ChannelConfigSurround7Dot1, Format>; - int frameCount() const; - int sampleCount() const; - int byteCount() const; - qint64 duration() const; - qint64 startTime() const; +class QAudioBufferPrivate; +QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QAudioBufferPrivate, Q_MULTIMEDIA_EXPORT) - // Data modification - // void clear(); - // Other ideas - // operator *= - // operator += (need to be careful about different formats) +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(); - // Data access - const void* constData() const; // Does not detach, preferred - const void* data() const; // Does not detach - void *data(); // detaches + QAudioBuffer& operator=(const QAudioBuffer &other); - // Structures for easier access to stereo data - template <typename T> struct StereoFrameDefault { enum { Default = 0 }; }; + QAudioBuffer(QAudioBuffer &&other) noexcept = default; + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QAudioBuffer) + void swap(QAudioBuffer &other) noexcept + { d.swap(other.d); } - template <typename T> struct StereoFrame { + bool isValid() const noexcept { return d != nullptr; }; - StereoFrame() - : left(T(StereoFrameDefault<T>::Default)) - , right(T(StereoFrameDefault<T>::Default)) - { - } + void detach(); - StereoFrame(T leftSample, T rightSample) - : left(leftSample) - , right(rightSample) - { - } + QAudioFormat format() const noexcept; - StereoFrame& operator=(const StereoFrame &other) - { - // Two straight assigns is probably - // cheaper than a conditional check on - // self assignment - left = other.left; - right = other.right; - return *this; - } + qsizetype frameCount() const noexcept; + qsizetype sampleCount() const noexcept; + qsizetype byteCount() const noexcept; - T left; - T right; + qint64 duration() const noexcept; + qint64 startTime() const noexcept; - T average() const {return (left + right) / 2;} - void clear() {left = right = T(StereoFrameDefault<T>::Default);} - }; + // Structures for easier access to data + typedef QAudioFrameMono<QAudioFormat::UInt8> U8M; + typedef QAudioFrameMono<QAudioFormat::Int16> S16M; + typedef QAudioFrameMono<QAudioFormat::Int32> S32M; + typedef QAudioFrameMono<QAudioFormat::Float> F32M; - typedef StereoFrame<unsigned char> S8U; - typedef StereoFrame<signed char> S8S; - typedef StereoFrame<unsigned short> S16U; - typedef StereoFrame<signed short> S16S; - typedef StereoFrame<float> S32F; + typedef QAudioFrameStereo<QAudioFormat::UInt8> U8S; + typedef QAudioFrameStereo<QAudioFormat::Int16> S16S; + typedef QAudioFrameStereo<QAudioFormat::Int32> S32S; + typedef QAudioFrameStereo<QAudioFormat::Float> F32S; template <typename T> const T* constData() const { return static_cast<const T*>(constData()); @@ -137,12 +161,12 @@ public: return static_cast<T*>(data()); } private: - QAudioBufferPrivate *d; -}; - -template <> struct QAudioBuffer::StereoFrameDefault<unsigned char> { enum { Default = 128 }; }; -template <> struct QAudioBuffer::StereoFrameDefault<unsigned short> { enum { Default = 32768 }; }; + const void* constData() const noexcept; + const void* data() const noexcept; + void *data(); + QExplicitlySharedDataPointer<QAudioBufferPrivate> d; +}; QT_END_NAMESPACE |