diff options
author | Lars Knoll <lars.knoll@qt.io> | 2021-06-11 20:50:44 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2021-06-19 22:57:55 +0200 |
commit | 83e9c2d8c3b278bae81a6060cc1657a95250f1ee (patch) | |
tree | dd469ebd3fa73a3b2b16eeec04eff6f90da2d47e | |
parent | 00cedc5107aecbe66619eef8baf18241ef3fc390 (diff) |
Add positioning information for channels to QAudioFormat
Just having a list of x channels without knowing where they are
spatially positioned is missing the most important part.
Reworked the QAudioBuffer access API to allow accessing data
with a specified frame layout.
Change-Id: I2aba20e62e97d80ca8873c97aa00f234ea210cd2
Reviewed-by: André de la Rocha <andre.rocha@qt.io>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
-rw-r--r-- | examples/multimedia/audiodecoder/audiodecoder.cpp | 2 | ||||
-rw-r--r-- | src/multimedia/audio/qaudiobuffer.h | 152 | ||||
-rw-r--r-- | src/multimedia/audio/qaudioformat.cpp | 72 | ||||
-rw-r--r-- | src/multimedia/audio/qaudioformat.h | 66 | ||||
-rw-r--r-- | tests/auto/unit/multimedia/qaudiobuffer/tst_qaudiobuffer.cpp | 165 | ||||
-rw-r--r-- | tests/auto/unit/multimedia/qaudioformat/tst_qaudioformat.cpp | 39 |
6 files changed, 358 insertions, 138 deletions
diff --git a/examples/multimedia/audiodecoder/audiodecoder.cpp b/examples/multimedia/audiodecoder/audiodecoder.cpp index f3492a52a..c65a3838c 100644 --- a/examples/multimedia/audiodecoder/audiodecoder.cpp +++ b/examples/multimedia/audiodecoder/audiodecoder.cpp @@ -133,7 +133,7 @@ void AudioDecoder::bufferReady() return; } - m_waveDecoder->write((const char *)buffer.constData(), buffer.byteCount()); + m_waveDecoder->write(buffer.constData<char>(), buffer.byteCount()); } void AudioDecoder::error(QAudioDecoder::Error error) diff --git a/src/multimedia/audio/qaudiobuffer.h b/src/multimedia/audio/qaudiobuffer.h index c7ac45a48..b4c58fe10 100644 --- a/src/multimedia/audio/qaudiobuffer.h +++ b/src/multimedia/audio/qaudiobuffer.h @@ -49,6 +49,101 @@ QT_BEGIN_NAMESPACE +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: + 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); + } + + + 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) const { + 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>; + +template <QAudioFormat::SampleFormat Format> +using QAudioFrameSurround5Dot1 = QAudioFrame<QAudioFormat::ChannelConfigSurround5Dot1, Format>; + +template <QAudioFormat::SampleFormat Format> +using QAudioFrameSurround7Dot1 = QAudioFrame<QAudioFormat::ChannelConfigSurround7Dot1, Format>; + + class QAudioBufferPrivate; QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QAudioBufferPrivate, Q_MULTIMEDIA_EXPORT) @@ -81,48 +176,16 @@ public: qint64 duration() const noexcept; qint64 startTime() const noexcept; - // Data access - const void* constData() const noexcept; - const void* data() const noexcept; - void *data(); + // 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; - // Structures for easier access to stereo data - template <typename T> struct StereoFrameDefault { enum { Default = 0 }; }; - - template <typename T> struct StereoFrame { - - StereoFrame() - : left(T(StereoFrameDefault<T>::Default)) - , right(T(StereoFrameDefault<T>::Default)) - { - } - - StereoFrame(T leftSample, T rightSample) - : left(leftSample) - , right(rightSample) - { - } - - 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; - } - - T left; - T right; - - T average() const {return (left + right) / 2;} - void clear() {left = right = T(StereoFrameDefault<T>::Default);} - }; - - typedef StereoFrame<unsigned char> S8U; - 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()); @@ -134,12 +197,13 @@ public: return static_cast<T*>(data()); } private: + const void* constData() const noexcept; + const void* data() const noexcept; + void *data(); + QExplicitlySharedDataPointer<QAudioBufferPrivate> d; }; -template <> struct QAudioBuffer::StereoFrameDefault<unsigned char> { enum { Default = 128 }; }; -template <> struct QAudioBuffer::StereoFrameDefault<unsigned short> { enum { Default = 32768 }; }; - QT_END_NAMESPACE Q_DECLARE_METATYPE(QAudioBuffer) diff --git a/src/multimedia/audio/qaudioformat.cpp b/src/multimedia/audio/qaudioformat.cpp index c29c82914..c9217372b 100644 --- a/src/multimedia/audio/qaudioformat.cpp +++ b/src/multimedia/audio/qaudioformat.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include <QDebug> #include <qaudioformat.h> +#include <qalgorithms.h> QT_BEGIN_NAMESPACE @@ -141,10 +142,78 @@ QT_BEGIN_NAMESPACE */ /*! + \enum AudioChannel + + The audio channels follow the standard definition used in + + \value Mono + \value Left + \value Right + \value Center + \value LFE Low Frequence Effect channel (Subwoofer) + \value RearLeft + \value RearRight, + \value SideLeft, + \value SideRight + \value RearCenter +*/ + + +/*! + \enum ChannelConfig + + This enum describes a standardized audio channel layout. The most common configurations are Mono, Stereo, 2.1 + (stereo plus low frequency) , 5.1 surround and 7.1 surround configurations. + + \value ChannelConfigUnknown The channel configuration is not known. + \value ChannelConfigMono The audio has one Center channel + \value ChannelConfigStereo The audio has two channels, Left and Right + \value ChannelConfig2Dot1 The audio has three channels, Left, Right and LFE (low frequency effect) + \value ChannelConfigSurround5Dot0 The audio has five channels, Left, Right, Center, BackLeft, BackRight + \value ChannelConfigSurround5Dot1 The audio has 6 channels, Left, Right, Center, LFE, BackLeft and BackRight + \value ChannelConfigSurround7Dot0 The audio has 7 channels, Left, Right, Center, BackLeft, BackRight, SideLeft and SideRight + \value ChannelConfigSurround7Dot1 The audio has 8 channels, Left, Right, Center, LFE, BackLeft, BackRight, SideLeft and SideRight +*/ + +/*! + Sets the channel configuration to \a config. + + Sets the channel configuration of the audio format to one of the standard + audio channel configurations. + + \note that this will also modify the channel count. +*/ +void QAudioFormat::setChannelConfig(ChannelConfig config) noexcept +{ + m_channelConfig = config; + if (config != ChannelConfigUnknown) + m_channelCount = qPopulationCount(config); +} + +/*! + Returns the position of a certain audio channel inside an audio frame for the given format. + Returns -1 if the channel does not exist for this format or the channel configuration is unknown. +*/ +int QAudioFormat::channelOffset(AudioChannelPosition channel) const noexcept +{ + if (!(m_channelConfig & (1u << channel))) + return -1; + + uint maskedChannels = m_channelConfig & ((1u << channel) - 1); + return qPopulationCount(maskedChannels); +} + +/*! \fn void QAudioFormat::setChannelCount(int channels) - Sets the channel count to \a channels. + Sets the channel count to \a channels. Setting this also sets the channel config to ChannelConfigUnknown. +*/ + + +/*! + \fn QAudioFormat::ChannelConfig QAudioFormat::channelConfig() const noexcept + Returns the current channel configuration. */ /*! @@ -198,7 +267,6 @@ qint64 QAudioFormat::durationForBytes(qint32 bytes) const { // avoid compiler warnings about unused variables. [[maybe_unused]] in the header // gives compiler errors on older gcc versions - Q_UNUSED(bitfields); Q_UNUSED(reserved); if (!isValid() || bytes <= 0) diff --git a/src/multimedia/audio/qaudioformat.h b/src/multimedia/audio/qaudioformat.h index c5580e7f2..40e8ed8eb 100644 --- a/src/multimedia/audio/qaudioformat.h +++ b/src/multimedia/audio/qaudioformat.h @@ -50,10 +50,17 @@ QT_BEGIN_NAMESPACE class QAudioFormatPrivate; +namespace QtPrivate { +template <typename... Args> +constexpr int channelConfig(Args... values) { + return (0 | ... | (1u << values)); +} +} + class QAudioFormat { public: - enum SampleFormat { + enum SampleFormat : quint16 { Unknown, UInt8, Int16, @@ -62,6 +69,52 @@ public: NSampleFormats }; + // This matches the speaker positions of a 22.2 audio layout. Stereo, Surround 5.1 and Surround 7.1 are subsets of these + enum AudioChannelPosition { + UnknownPosition, + FrontLeft, + FrontRight, + FrontCenter, + LFE, + BackLeft, + BackRight, + FrontLeftOfCenter, + FrontRightOfCenter, + BackCenter, + LFE2, + SideLeft, + SideRight, + TopFrontLeft, + TopFrontRight, + TopFrontCenter, + TopCenter, + TopBackLeft, + TopBackRight, + TopSideLeft, + TopSideRight, + TopBackCenter, + BottomFrontCenter, + BottomFrontLeft, + BottomFrontRight + }; + + enum ChannelConfig : quint32 { + ChannelConfigUnknown = 0, + ChannelConfigMono = QtPrivate::channelConfig(FrontCenter), + ChannelConfigStereo = QtPrivate::channelConfig(FrontLeft, FrontRight), + ChannelConfig2Dot1 = QtPrivate::channelConfig(FrontLeft, FrontRight, LFE), + ChannelConfigSurround5Dot0 = QtPrivate::channelConfig(FrontLeft, FrontRight, FrontCenter, BackLeft, BackRight), + ChannelConfigSurround5Dot1 = QtPrivate::channelConfig(FrontLeft, FrontRight, FrontCenter, LFE, BackLeft, BackRight), + ChannelConfigSurround7Dot0 = QtPrivate::channelConfig(FrontLeft, FrontRight, FrontCenter, BackLeft, BackRight, SideLeft, SideRight), + ChannelConfigSurround7Dot1 = QtPrivate::channelConfig(FrontLeft, FrontRight, FrontCenter, LFE, BackLeft, BackRight, SideLeft, SideRight), + }; + + template <typename... Args> + static ChannelConfig channelConfig(Args... channels) + { + return ChannelConfig(QtPrivate::channelConfig(channels...)); + } + constexpr bool isValid() const noexcept { return m_sampleRate > 0 && m_channelCount > 0 && m_sampleFormat != Unknown; @@ -70,9 +123,14 @@ public: constexpr void setSampleRate(int sampleRate) noexcept { m_sampleRate = sampleRate; } constexpr int sampleRate() const noexcept { return m_sampleRate; } - constexpr void setChannelCount(int channelCount) noexcept { m_channelCount = channelCount; } + Q_MULTIMEDIA_EXPORT void setChannelConfig(ChannelConfig config) noexcept; + constexpr ChannelConfig channelConfig() const noexcept { return m_channelConfig; } + + constexpr void setChannelCount(int channelCount) noexcept { m_channelConfig = ChannelConfigUnknown; m_channelCount = channelCount; } constexpr int channelCount() const noexcept { return m_channelCount; } + Q_MULTIMEDIA_EXPORT int channelOffset(AudioChannelPosition channel) const noexcept; + constexpr void setSampleFormat(SampleFormat f) noexcept { m_sampleFormat = f; } constexpr SampleFormat sampleFormat() const noexcept { return m_sampleFormat; } @@ -115,9 +173,9 @@ public: private: SampleFormat m_sampleFormat = SampleFormat::Unknown; - int m_sampleRate = 0; short m_channelCount = 0; - short bitfields = 0; + ChannelConfig m_channelConfig = ChannelConfigUnknown; + int m_sampleRate = 0; quint64 reserved = 0; }; diff --git a/tests/auto/unit/multimedia/qaudiobuffer/tst_qaudiobuffer.cpp b/tests/auto/unit/multimedia/qaudiobuffer/tst_qaudiobuffer.cpp index 2fab63a1a..875025559 100644 --- a/tests/auto/unit/multimedia/qaudiobuffer/tst_qaudiobuffer.cpp +++ b/tests/auto/unit/multimedia/qaudiobuffer/tst_qaudiobuffer.cpp @@ -81,9 +81,9 @@ void tst_QAudioBuffer::ctors() { // Null buffer QVERIFY(!mNull->isValid()); - QVERIFY(mNull->constData() == nullptr); - QVERIFY(mNull->data() == nullptr); - QVERIFY(((const QAudioBuffer*)mNull)->data() == nullptr); + QVERIFY(mNull->constData<char>() == nullptr); + QVERIFY(mNull->data<char>() == nullptr); + QVERIFY(((const QAudioBuffer*)mNull)->data<char>() == nullptr); QCOMPARE(mNull->duration(), 0LL); QCOMPARE(mNull->byteCount(), 0); QCOMPARE(mNull->sampleCount(), 0); @@ -92,9 +92,9 @@ void tst_QAudioBuffer::ctors() // Empty buffer QVERIFY(mEmpty->isValid()); - QVERIFY(mEmpty->constData() != nullptr); - QVERIFY(mEmpty->data() != nullptr); - QVERIFY(((const QAudioBuffer*)mEmpty)->data() != nullptr); + QVERIFY(mEmpty->constData<char>() != nullptr); + QVERIFY(mEmpty->data<char>() != nullptr); + QVERIFY(((const QAudioBuffer*)mEmpty)->data<char>() != nullptr); QCOMPARE(mEmpty->sampleCount(), 1000); QCOMPARE(mEmpty->frameCount(), 500); QCOMPARE(mEmpty->duration(), 50000LL); @@ -103,9 +103,9 @@ void tst_QAudioBuffer::ctors() // bytearray buffer QVERIFY(mFromArray->isValid()); - QVERIFY(mFromArray->constData() != nullptr); - QVERIFY(mFromArray->data() != nullptr); - QVERIFY(((const QAudioBuffer*)mFromArray)->data() != nullptr); + QVERIFY(mFromArray->constData<char>() != nullptr); + QVERIFY(mFromArray->data<char>() != nullptr); + QVERIFY(((const QAudioBuffer*)mFromArray)->data<char>() != nullptr); /// 4000 bytes at 10KHz, 2ch, 16bit = 40kBps -> 0.1s QCOMPARE(mFromArray->duration(), 100000LL); QCOMPARE(mFromArray->byteCount(), 4000); @@ -117,9 +117,9 @@ void tst_QAudioBuffer::ctors() // Now some invalid buffers QAudioBuffer badFormat(1000, QAudioFormat()); QVERIFY(!badFormat.isValid()); - QVERIFY(badFormat.constData() == nullptr); - QVERIFY(badFormat.data() == nullptr); - QVERIFY(((const QAudioBuffer*)&badFormat)->data() == nullptr); + QVERIFY(badFormat.constData<char>() == nullptr); + QVERIFY(badFormat.data<char>() == nullptr); + QVERIFY(((const QAudioBuffer*)&badFormat)->data<char>() == nullptr); QCOMPARE(badFormat.duration(), 0LL); QCOMPARE(badFormat.byteCount(), 0); QCOMPARE(badFormat.sampleCount(), 0); @@ -128,9 +128,9 @@ void tst_QAudioBuffer::ctors() QAudioBuffer badArray(QByteArray(), mFormat); QVERIFY(!badArray.isValid()); - QVERIFY(badArray.constData() == nullptr); - QVERIFY(badArray.data() == nullptr); - QVERIFY(((const QAudioBuffer*)&badArray)->data() == nullptr); + QVERIFY(badArray.constData<char>() == nullptr); + QVERIFY(badArray.data<char>() == nullptr); + QVERIFY(((const QAudioBuffer*)&badArray)->data<char>() == nullptr); QCOMPARE(badArray.duration(), 0LL); QCOMPARE(badArray.byteCount(), 0); QCOMPARE(badArray.sampleCount(), 0); @@ -139,9 +139,9 @@ void tst_QAudioBuffer::ctors() QAudioBuffer badBoth = QAudioBuffer(QByteArray(), QAudioFormat()); QVERIFY(!badBoth.isValid()); - QVERIFY(badBoth.constData() == nullptr); - QVERIFY(badBoth.data() == nullptr); - QVERIFY(((const QAudioBuffer*)&badBoth)->data() == nullptr); + QVERIFY(badBoth.constData<char>() == nullptr); + QVERIFY(badBoth.data<char>() == nullptr); + QVERIFY(((const QAudioBuffer*)&badBoth)->data<char>() == nullptr); QCOMPARE(badBoth.duration(), 0LL); QCOMPARE(badBoth.byteCount(), 0); QCOMPARE(badBoth.sampleCount(), 0); @@ -156,77 +156,77 @@ void tst_QAudioBuffer::assign() void tst_QAudioBuffer::constData() const { - const void *data = mEmpty->constData(); + const void *data = mEmpty->constData<void *>(); QVERIFY(data != nullptr); const unsigned int *idata = reinterpret_cast<const unsigned int*>(data); QCOMPARE(*idata, 0U); - const QAudioBuffer::S8U *sdata = mEmpty->constData<QAudioBuffer::S8U>(); + const QAudioBuffer::U8S *sdata = mEmpty->constData<QAudioBuffer::U8S>(); QVERIFY(sdata); - QCOMPARE(sdata->left, (unsigned char)0); - QCOMPARE(sdata->right, (unsigned char)0); + QCOMPARE(sdata->value(QAudioFormat::FrontLeft), (unsigned char)0); + QCOMPARE(sdata->value(QAudioFormat::FrontRight), (unsigned char)0); // The bytearray one should be 0x80 - data = mFromArray->constData(); + data = mFromArray->constData<void *>(); QVERIFY(data != nullptr); idata = reinterpret_cast<const unsigned int *>(data); QCOMPARE(*idata, 0x80808080); - sdata = mFromArray->constData<QAudioBuffer::S8U>(); - QCOMPARE(sdata->left, (unsigned char)0x80); - QCOMPARE(sdata->right, (unsigned char)0x80); + sdata = mFromArray->constData<QAudioBuffer::U8S>(); + QCOMPARE(sdata->value(QAudioFormat::FrontLeft), (unsigned char)0x80); + QCOMPARE(sdata->value(QAudioFormat::FrontRight), (unsigned char)0x80); } void tst_QAudioBuffer::data_const() const { - const void *data = ((const QAudioBuffer*)mEmpty)->data(); + const void *data = ((const QAudioBuffer*)mEmpty)->data<void *>(); QVERIFY(data != nullptr); const unsigned int *idata = reinterpret_cast<const unsigned int*>(data); QCOMPARE(*idata, 0U); - const QAudioBuffer::S8U *sdata = ((const QAudioBuffer*)mEmpty)->constData<QAudioBuffer::S8U>(); + const QAudioBuffer::U8S *sdata = ((const QAudioBuffer*)mEmpty)->constData<QAudioBuffer::U8S>(); QVERIFY(sdata); - QCOMPARE(sdata->left, (unsigned char)0); - QCOMPARE(sdata->right, (unsigned char)0); + QCOMPARE(sdata->value(QAudioFormat::FrontLeft), (unsigned char)0); + QCOMPARE(sdata->value(QAudioFormat::FrontRight), (unsigned char)0); // The bytearray one should be 0x80 - data = ((const QAudioBuffer*)mFromArray)->data(); + data = ((const QAudioBuffer*)mFromArray)->data<void *>(); QVERIFY(data != nullptr); idata = reinterpret_cast<const unsigned int *>(data); QCOMPARE(*idata, 0x80808080); - sdata = ((const QAudioBuffer*)mFromArray)->constData<QAudioBuffer::S8U>(); - QCOMPARE(sdata->left, (unsigned char)0x80); - QCOMPARE(sdata->right, (unsigned char)0x80); + sdata = ((const QAudioBuffer*)mFromArray)->constData<QAudioBuffer::U8S>(); + QCOMPARE(sdata->value(QAudioFormat::FrontLeft), (unsigned char)0x80); + QCOMPARE(sdata->value(QAudioFormat::FrontRight), (unsigned char)0x80); } void tst_QAudioBuffer::data() { - void *data = mEmpty->data(); + void *data = mEmpty->data<void *>(); QVERIFY(data != nullptr); unsigned int *idata = reinterpret_cast<unsigned int*>(data); QCOMPARE(*idata, 0U); - QAudioBuffer::S8U *sdata = mEmpty->data<QAudioBuffer::S8U>(); + QAudioBuffer::U8S *sdata = mEmpty->data<QAudioBuffer::U8S>(); QVERIFY(sdata); - QCOMPARE(sdata->left, (unsigned char)0); - QCOMPARE(sdata->right, (unsigned char)0); + QCOMPARE(sdata->value(QAudioFormat::FrontLeft), (unsigned char)0); + QCOMPARE(sdata->value(QAudioFormat::FrontRight), (unsigned char)0); // The bytearray one should be 0x80 - data = mFromArray->data(); + data = mFromArray->data<void *>(); QVERIFY(data != nullptr); idata = reinterpret_cast<unsigned int *>(data); QCOMPARE(*idata, 0x80808080); - sdata = mFromArray->data<QAudioBuffer::S8U>(); - QCOMPARE(sdata->left, (unsigned char)0x80); - QCOMPARE(sdata->right, (unsigned char)0x80); + sdata = mFromArray->data<QAudioBuffer::U8S>(); + QCOMPARE(sdata->value(QAudioFormat::FrontLeft), (unsigned char)0x80); + QCOMPARE(sdata->value(QAudioFormat::FrontRight), (unsigned char)0x80); } void tst_QAudioBuffer::durations() @@ -274,72 +274,63 @@ void tst_QAudioBuffer::durations_data() void tst_QAudioBuffer::stereoSample() { // Uninitialized (should default to zero level for type) - QAudioBuffer::S8U s8u; + QAudioBuffer::U8S u8s; QAudioBuffer::S16S s16s; - QAudioBuffer::S32F s32f; + QAudioBuffer::F32S f32s; + u8s.clear(); + s16s.clear(); + f32s.clear(); - QCOMPARE(s8u.left, (unsigned char) 0x80); - QCOMPARE(s8u.right, (unsigned char) 0x80); - QCOMPARE(s8u.average(), (unsigned char) 0x80); + QCOMPARE(u8s[QAudioFormat::FrontLeft], (unsigned char) 0x80); + QCOMPARE(u8s[QAudioFormat::FrontRight], (unsigned char) 0x80); - QCOMPARE(s16s.left, (signed short) 0x0); - QCOMPARE(s16s.right, (signed short) 0x0); - QCOMPARE(s16s.average(), (signed short) 0x0); + QCOMPARE(s16s[QAudioFormat::FrontLeft], (signed short) 0x0); + QCOMPARE(s16s[QAudioFormat::FrontRight], (signed short) 0x0); - QCOMPARE(s32f.left, 0.0f); - QCOMPARE(s32f.right, 0.0f); - QCOMPARE(s32f.average(), 0.0f); + QCOMPARE(f32s[QAudioFormat::FrontLeft], 0.0f); + QCOMPARE(f32s[QAudioFormat::FrontRight], 0.0f); // Initialized - QAudioBuffer::S8U s8u2(34, 145); - QAudioBuffer::S16S s16s2(-10000, 346); - QAudioBuffer::S32F s32f2(500.7f, -123.1f); + QAudioBuffer::U8S u8s2{34, 145}; + QAudioBuffer::S16S s16s2{-10000, 346}; + QAudioBuffer::F32S f32s2{500.7f, -123.1f}; - QCOMPARE(s8u2.left, (unsigned char) 34); - QCOMPARE(s8u2.right, (unsigned char) 145); - QCOMPARE(s8u2.average(), (unsigned char) 89); + QCOMPARE(u8s2[QAudioFormat::FrontLeft], (unsigned char) 34); + QCOMPARE(u8s2[QAudioFormat::FrontRight], (unsigned char) 145); - QCOMPARE(s16s2.left, (signed short) -10000); - QCOMPARE(s16s2.right, (signed short) 346); - QCOMPARE(s16s2.average(), (signed short) (-5000 + 173)); + QCOMPARE(s16s2[QAudioFormat::FrontLeft], (signed short) -10000); + QCOMPARE(s16s2[QAudioFormat::FrontRight], (signed short) 346); - QCOMPARE(s32f2.left, 500.7f); - QCOMPARE(s32f2.right, -123.1f); - QCOMPARE(s32f2.average(), (500.7f - 123.1f)/2); + QCOMPARE(f32s2[QAudioFormat::FrontLeft], 500.7f); + QCOMPARE(f32s2[QAudioFormat::FrontRight], -123.1f); // Assigned - s8u = s8u2; + u8s = u8s2; s16s = s16s2; - s32f = s32f2; + f32s = f32s2; - QCOMPARE(s8u.left, (unsigned char) 34); - QCOMPARE(s8u.right, (unsigned char) 145); - QCOMPARE(s8u.average(), (unsigned char) 89); + QCOMPARE(u8s[QAudioFormat::FrontLeft], (unsigned char) 34); + QCOMPARE(u8s[QAudioFormat::FrontRight], (unsigned char) 145); - QCOMPARE(s16s.left, (signed short) -10000); - QCOMPARE(s16s.right, (signed short) 346); - QCOMPARE(s16s.average(), (signed short) (-5000 + 173)); + QCOMPARE(s16s[QAudioFormat::FrontLeft], (signed short) -10000); + QCOMPARE(s16s[QAudioFormat::FrontRight], (signed short) 346); - QCOMPARE(s32f.left, 500.7f); - QCOMPARE(s32f.right, -123.1f); - QCOMPARE(s32f.average(), (500.7f - 123.1f)/2); + QCOMPARE(f32s[QAudioFormat::FrontLeft], 500.7f); + QCOMPARE(f32s[QAudioFormat::FrontRight], -123.1f); // Cleared - s8u.clear(); + u8s.clear(); s16s.clear(); - s32f.clear(); + f32s.clear(); - QCOMPARE(s8u.left, (unsigned char) 0x80); - QCOMPARE(s8u.right, (unsigned char) 0x80); - QCOMPARE(s8u.average(), (unsigned char) 0x80); + QCOMPARE(u8s[QAudioFormat::FrontLeft], (unsigned char) 0x80); + QCOMPARE(u8s[QAudioFormat::FrontRight], (unsigned char) 0x80); - QCOMPARE(s16s.left, (signed short) 0x0); - QCOMPARE(s16s.right, (signed short) 0x0); - QCOMPARE(s16s.average(), (signed short) 0x0); + QCOMPARE(s16s[QAudioFormat::FrontLeft], (signed short) 0x0); + QCOMPARE(s16s[QAudioFormat::FrontRight], (signed short) 0x0); - QCOMPARE(s32f.left, 0.0f); - QCOMPARE(s32f.right, 0.0f); - QCOMPARE(s32f.average(), 0.0f); + QCOMPARE(f32s[QAudioFormat::FrontLeft], 0.0f); + QCOMPARE(f32s[QAudioFormat::FrontRight], 0.0f); } diff --git a/tests/auto/unit/multimedia/qaudioformat/tst_qaudioformat.cpp b/tests/auto/unit/multimedia/qaudioformat/tst_qaudioformat.cpp index cdfedea1e..b2ee24808 100644 --- a/tests/auto/unit/multimedia/qaudioformat/tst_qaudioformat.cpp +++ b/tests/auto/unit/multimedia/qaudioformat/tst_qaudioformat.cpp @@ -51,6 +51,8 @@ private slots: void checkSampleRate(); void checkChannelCount(); + void channelConfig(); + void checkSizes(); void checkSizes_data(); }; @@ -162,6 +164,43 @@ void tst_QAudioFormat::checkChannelCount() QVERIFY(audioFormat.channelCount() == 5); } +void tst_QAudioFormat::channelConfig() +{ + QAudioFormat format; + format.setChannelConfig(QAudioFormat::ChannelConfig2Dot1); + QVERIFY(format.channelConfig() == QAudioFormat::ChannelConfig2Dot1); + QVERIFY(format.channelCount() == 3); + QVERIFY(format.channelOffset(QAudioFormat::FrontLeft) == 0); + QVERIFY(format.channelOffset(QAudioFormat::FrontRight) == 1); + QVERIFY(format.channelOffset(QAudioFormat::BackCenter) == -1); + + format.setChannelConfig(QAudioFormat::ChannelConfigSurround5Dot1); + QVERIFY(format.channelConfig() == QAudioFormat::ChannelConfigSurround5Dot1); + QVERIFY(format.channelCount() == 6); + QVERIFY(format.channelOffset(QAudioFormat::FrontLeft) == 0); + QVERIFY(format.channelOffset(QAudioFormat::FrontRight) == 1); + QVERIFY(format.channelOffset(QAudioFormat::FrontCenter) == 2); + QVERIFY(format.channelOffset(QAudioFormat::LFE) == 3); + QVERIFY(format.channelOffset(QAudioFormat::BackLeft) == 4); + QVERIFY(format.channelOffset(QAudioFormat::BackRight) == 5); + QVERIFY(format.channelOffset(QAudioFormat::BackCenter) == -1); + + auto config = QAudioFormat::channelConfig(QAudioFormat::FrontCenter, QAudioFormat::BackCenter, QAudioFormat::LFE); + format.setChannelConfig(config); + QVERIFY(format.channelConfig() == config); + QVERIFY(format.channelCount() == 3); + QVERIFY(format.channelOffset(QAudioFormat::FrontLeft) == -1); + QVERIFY(format.channelOffset(QAudioFormat::FrontRight) == -1); + QVERIFY(format.channelOffset(QAudioFormat::FrontCenter) == 0); + QVERIFY(format.channelOffset(QAudioFormat::LFE) == 1); + QVERIFY(format.channelOffset(QAudioFormat::BackLeft) == -1); + QVERIFY(format.channelOffset(QAudioFormat::BackRight) == -1); + QVERIFY(format.channelOffset(QAudioFormat::BackCenter) == 2); + + format.setChannelCount(2); + QVERIFY(format.channelConfig() == QAudioFormat::ChannelConfigUnknown); +} + void tst_QAudioFormat::checkSizes() { QFETCH(QAudioFormat, format); |