diff options
Diffstat (limited to 'src/multimedia/spatial')
-rw-r--r-- | src/multimedia/spatial/qambisonicdecoder.cpp | 229 | ||||
-rw-r--r-- | src/multimedia/spatial/qambisonicdecoder_p.h | 99 | ||||
-rw-r--r-- | src/multimedia/spatial/qambisonicdecoderdata_p.h | 423 | ||||
-rw-r--r-- | src/multimedia/spatial/qspatialaudioengine.cpp | 627 | ||||
-rw-r--r-- | src/multimedia/spatial/qspatialaudioengine.h | 111 | ||||
-rw-r--r-- | src/multimedia/spatial/qspatialaudioengine_p.h | 179 | ||||
-rw-r--r-- | src/multimedia/spatial/qspatialaudiolistener.cpp | 161 | ||||
-rw-r--r-- | src/multimedia/spatial/qspatialaudiolistener.h | 73 | ||||
-rw-r--r-- | src/multimedia/spatial/qspatialaudioroom.cpp | 418 | ||||
-rw-r--r-- | src/multimedia/spatial/qspatialaudioroom.h | 141 | ||||
-rw-r--r-- | src/multimedia/spatial/qspatialaudioroom_p.h | 83 | ||||
-rw-r--r-- | src/multimedia/spatial/qspatialaudiosoundsource.cpp | 617 | ||||
-rw-r--r-- | src/multimedia/spatial/qspatialaudiosoundsource.h | 161 | ||||
-rw-r--r-- | src/multimedia/spatial/qspatialaudiosoundsource_p.h | 95 | ||||
-rw-r--r-- | src/multimedia/spatial/qspatialaudiostereosource.cpp | 215 | ||||
-rw-r--r-- | src/multimedia/spatial/qspatialaudiostereosource.h | 102 |
16 files changed, 0 insertions, 3734 deletions
diff --git a/src/multimedia/spatial/qambisonicdecoder.cpp b/src/multimedia/spatial/qambisonicdecoder.cpp deleted file mode 100644 index a25754ef0..000000000 --- a/src/multimedia/spatial/qambisonicdecoder.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 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$ -** -****************************************************************************/ -#include "qambisonicdecoder_p.h" - -#include "qambisonicdecoderdata_p.h" -#include <cmath> - -QT_BEGIN_NAMESPACE - -// Ambisonic decoding is described in detail in https://ambisonics.dreamhosters.com/BLaH3.pdf. -// We're using a phase matched band splitting filter to split the ambisonic signal into a low -// and high frequency component and apply matrix conversions to those components individually -// as described in the document. -// -// We are currently not using a near field compensation filter, something that could potentially -// improve sound quality further. - - -struct QAmbisonicDecoderData -{ - QAudioFormat::ChannelConfig config; - const float *lf[3]; - const float *hf[3]; -}; - -static const QAmbisonicDecoderData decoderMap[] = -{ - { QAudioFormat::ChannelConfigMono, - { decoderMatrix_mono_1_lf, decoderMatrix_mono_2_lf, decoderMatrix_mono_3_lf }, - { decoderMatrix_mono_1_hf, decoderMatrix_mono_2_hf, decoderMatrix_mono_3_hf } - }, - { QAudioFormat::ChannelConfigStereo, - { decoderMatrix_stereo_1_lf, decoderMatrix_stereo_2_lf, decoderMatrix_stereo_3_lf }, - { decoderMatrix_stereo_1_hf, decoderMatrix_stereo_2_hf, decoderMatrix_stereo_3_hf } - }, - { QAudioFormat::ChannelConfig2Dot1, - { decoderMatrix_2dot1_1_lf, decoderMatrix_2dot1_2_lf, decoderMatrix_2dot1_3_lf }, - { decoderMatrix_2dot1_1_hf, decoderMatrix_2dot1_2_hf, decoderMatrix_2dot1_3_hf } - }, - { QAudioFormat::ChannelConfigSurround5Dot0, - { decoderMatrix_5dot0_1_lf, decoderMatrix_5dot0_2_lf, decoderMatrix_5dot0_3_lf }, - { decoderMatrix_5dot0_1_hf, decoderMatrix_5dot0_2_hf, decoderMatrix_5dot0_3_hf } - }, - { QAudioFormat::ChannelConfigSurround5Dot1, - { decoderMatrix_5dot1_1_lf, decoderMatrix_5dot1_2_lf, decoderMatrix_5dot1_3_lf }, - { decoderMatrix_5dot1_1_hf, decoderMatrix_5dot1_2_hf, decoderMatrix_5dot1_3_hf } - }, - { QAudioFormat::ChannelConfigSurround7Dot0, - { decoderMatrix_7dot0_1_lf, decoderMatrix_7dot0_2_lf, decoderMatrix_7dot0_3_lf }, - { decoderMatrix_7dot0_1_hf, decoderMatrix_7dot0_2_hf, decoderMatrix_7dot0_3_hf } - }, - { QAudioFormat::ChannelConfigSurround7Dot1, - { decoderMatrix_7dot1_1_lf, decoderMatrix_7dot1_2_lf, decoderMatrix_7dot1_3_lf }, - { decoderMatrix_7dot1_1_hf, decoderMatrix_7dot1_2_hf, decoderMatrix_7dot1_3_hf } - } -}; - - -// Implements a split second order IIR filter -// The audio data is split into a phase synced low and high frequency part -// This allows us to apply different factors to both parts for better sound -// localization when converting from ambisonic formats -// -// Details are described in https://ambisonics.dreamhosters.com/BLaH3.pdf, Appendix A.2. -class QAmbisonicDecoderFilter -{ -public: - QAmbisonicDecoderFilter() = default; - void configure(float sampleRate, float cutoffFrequency = 380) - { - double k = tan(M_PI*cutoffFrequency/sampleRate); - a1 = float(2.*(k*k - 1.)/(k*k + 2*k + 1.)); - a2 = float((k*k - 2*k + 1.)/(k*k + 2*k + 1.)); - - b0_lf = float(k*k/(k*k + 2*k + 1)); - b1_lf = 2.f*b0_lf; - - b0_hf = float(1./(k*k + 2*k + 1)); - b1_hf = -2.f*b0_hf; - } - - struct Output - { - float lf; - float hf; - }; - - Output next(float x) - { - float r_lf = x*b0_lf + - prevX[0]*b1_lf + - prevX[1]*b0_lf - - prevR_lf[0]*a1 - - prevR_lf[1]*a2; - float r_hf = x*b0_hf + - prevX[0]*b1_hf + - prevX[1]*b0_hf - - prevR_hf[0]*a1 - - prevR_hf[1]*a2; - prevX[1] = prevX[0]; - prevX[0] = x; - prevR_lf[1] = prevR_lf[0]; - prevR_lf[0] = r_lf; - prevR_hf[1] = prevR_hf[0]; - prevR_hf[0] = r_hf; - return { r_lf, r_hf }; - } - -private: - float a1 = 0.; - float a2 = 0.; - - float b0_hf = 0.; - float b1_hf = 0.; - - float b0_lf = 0.; - float b1_lf = 0.; - - float prevX[2] = {}; - float prevR_lf[2] = {}; - float prevR_hf[2] = {}; -}; - - -QAmbisonicDecoder::QAmbisonicDecoder(AmbisonicLevel ambisonicLevel, const QAudioFormat &format) - : level(ambisonicLevel) -{ - auto outputConfiguration = format.channelConfig(); - if (outputConfiguration == QAudioFormat::ChannelConfigUnknown) - outputConfiguration = format.defaultChannelConfigForChannelCount(format.channelCount()); - for (const auto &d : decoderMap) { - if (d.config == outputConfiguration) { - decoderData = &d; - break; - } - } - if (!decoderData) { - // ### FIXME: use a stereo config, fill other channels with 0 - } - - inputChannels = (level+1)*(level+1); - outputChannels = format.channelCount(); - - filters = new QAmbisonicDecoderFilter[inputChannels]; - for (int i = 0; i < inputChannels; ++i) - filters[i].configure(format.sampleRate()); -} - -void QAmbisonicDecoder::processBuffer(const float *input[], float *output, int nSamples) -{ - float *o = output; - memset(o, 0, nSamples*outputChannels*sizeof(float)); - - const float *matrix_hi = decoderData->hf[level]; - const float *matrix_lo = decoderData->hf[level]; - for (int i = 0; i < nSamples; ++i) { - QAmbisonicDecoderFilter::Output buf[maxAmbisonicChannels]; - for (int j = 0; j < inputChannels; ++j) - buf[j] = filters[j].next(input[j][i]); - for (int j = 0; j < inputChannels; ++j) { - for (int k = 0; k < outputChannels; ++k) - o[k] += matrix_lo[k*outputChannels + j]*buf[j].lf + matrix_hi[k*outputChannels + j]*buf[j].hf; - } - o += outputChannels; - } -} - -void QAmbisonicDecoder::processBuffer(const float *input[], short *output, int nSamples) -{ - if (level == 0) { - // ### copy W data - return; - } - const float *matrix_hi = decoderData->hf[level - 1]; - const float *matrix_lo = decoderData->hf[level - 1]; - for (int i = 0; i < nSamples; ++i) { - QAmbisonicDecoderFilter::Output buf[maxAmbisonicChannels]; - for (int j = 0; j < inputChannels; ++j) - buf[j] = filters[j].next(input[j][i]); - float o[32]; // we can't support more than 32 channels from our API - memset(o, 0, 32*sizeof(short)); - for (int j = 0; j < inputChannels; ++j) { - for (int k = 0; k < outputChannels; ++k) - o[k] += matrix_lo[k*outputChannels + j]*buf[j].lf + matrix_hi[k*outputChannels + j]*buf[j].hf; - } - for (int k = 0; k < outputChannels; ++k) - output[k] = static_cast<short>(o[k]*32768.); - output += outputChannels; - } -} - -QT_END_NAMESPACE - diff --git a/src/multimedia/spatial/qambisonicdecoder_p.h b/src/multimedia/spatial/qambisonicdecoder_p.h deleted file mode 100644 index 3c6d87b60..000000000 --- a/src/multimedia/spatial/qambisonicdecoder_p.h +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 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$ -** -****************************************************************************/ -#ifndef QAMBISONICDECODER_P_H -#define QAMBISONICDECODER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <qtmultimediaglobal_p.h> -#include <qaudioformat.h> - -QT_BEGIN_NAMESPACE - -struct QAmbisonicDecoderData; -class QAmbisonicDecoderFilter; - -class QAmbisonicDecoder -{ -public: - enum AmbisonicLevel - { - AmbisonicLevel1 = 1, - LowQuality = AmbisonicLevel1, - AmbisonicLevel2 = 2, - MediumQuality = AmbisonicLevel2, - AmbisonicLevel3 = 3, - HighQuality = AmbisonicLevel3 - }; - QAmbisonicDecoder(AmbisonicLevel ambisonicLevel, const QAudioFormat &format); - - int nInputChannels() const { return inputChannels; } - int nOutputChannels() const { return outputChannels; } - - int outputSize(int nSamples) const { return outputChannels * nSamples; } - - // input is planar, output interleaved - void processBuffer(const float *input[], float *output, int nSamples); - void processBuffer(const float *input[], short *output, int nSamples); - - static constexpr int maxAmbisonicChannels = 16; - static constexpr int maxAmbisonicLevel = 3; -private: - QAudioFormat format; - AmbisonicLevel level = AmbisonicLevel1; - int inputChannels = 0; - int outputChannels = 0; - const QAmbisonicDecoderData *decoderData = nullptr; - QAmbisonicDecoderFilter *filters = nullptr; - -}; - - -QT_END_NAMESPACE - -#endif diff --git a/src/multimedia/spatial/qambisonicdecoderdata_p.h b/src/multimedia/spatial/qambisonicdecoderdata_p.h deleted file mode 100644 index fa7b462f4..000000000 --- a/src/multimedia/spatial/qambisonicdecoderdata_p.h +++ /dev/null @@ -1,423 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ -#ifndef QAMBISONICDECODERDATA_P_H -#define QAMBISONICDECODERDATA_P_H - -#include <qtmultimediaglobal_p.h> - -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -// This file is generated by the matlab/octave file adt_generate_qt.m -// using the Ambisonic Decoder Toolbox (https://bitbucket.org/ambidecodertoolbox/adt/src/master/) - - -QT_BEGIN_NAMESPACE - -// Decoder matrix for mono, ambisonic level 1 -static constexpr float decoderMatrix_mono_1_lf[1*4] = { -0.471409f, 0.619827f, 0.000000f, 0.000000f, // C -}; - -// Decoder matrix for mono, ambisonic level 1 -static constexpr float decoderMatrix_mono_1_hf[1*4] = { -0.666673f, 0.506086f, 0.000000f, 0.000000f, // C -}; - -// Decoder matrix for mono, ambisonic level 2 -static constexpr float decoderMatrix_mono_2_lf[1*9] = { -0.471409f, 0.619827f, 0.000000f, 0.000000f, -0.138903f, 0.000000f, 0.000000f, 0.208318f, 0.000000f, // C -}; - -// Decoder matrix for mono, ambisonic level 2 -static constexpr float decoderMatrix_mono_2_hf[1*9] = { -0.745364f, 0.759129f, 0.000000f, 0.000000f, -0.087850f, 0.000000f, 0.000000f, 0.131752f, 0.000000f, // C -}; - -// Decoder matrix for mono, ambisonic level 3 -static constexpr float decoderMatrix_mono_3_lf[1*16] = { -0.471409f, 0.619827f, 0.000000f, 0.000000f, -0.138903f, 0.000000f, 0.000000f, 0.208318f, 0.000000f, 0.000000f, 0.080888f, 0.000000f, 0.000000f, 0.000000f, -0.097901f, 0.000000f, // C -}; - -// Decoder matrix for mono, ambisonic level 3 -static constexpr float decoderMatrix_mono_3_hf[1*16] = { -0.786398f, 0.890402f, 0.000000f, 0.000000f, -0.141888f, 0.000000f, 0.000000f, 0.212793f, 0.000000f, 0.000000f, 0.041121f, 0.000000f, 0.000000f, 0.000000f, -0.049771f, 0.000000f, // C -}; - -// Decoder matrix for stereo, ambisonic level 1 -static constexpr float decoderMatrix_stereo_1_lf[2*4] = { -0.280670f, 0.372187f, 0.240963f, 0.000000f, // L -0.280656f, 0.372181f, -0.240980f, 0.000000f, // R -}; - -// Decoder matrix for stereo, ambisonic level 1 -static constexpr float decoderMatrix_stereo_1_hf[2*4] = { -0.396928f, 0.303889f, 0.196746f, 0.000000f, // L -0.396908f, 0.303884f, -0.196759f, 0.000000f, // R -}; - -// Decoder matrix for stereo, ambisonic level 2 -static constexpr float decoderMatrix_stereo_2_lf[2*9] = { -0.280670f, 0.372187f, 0.240963f, 0.000000f, -0.085490f, 0.000000f, 0.000000f, 0.135154f, 0.311013f, // L -0.280656f, 0.372181f, -0.240980f, 0.000000f, -0.085579f, 0.000000f, 0.000000f, 0.135130f, -0.311015f, // R -}; - -// Decoder matrix for stereo, ambisonic level 2 -static constexpr float decoderMatrix_stereo_2_hf[2*9] = { -0.443779f, 0.455834f, 0.295119f, 0.000000f, -0.054068f, 0.000000f, 0.000000f, 0.085479f, 0.196702f, // L -0.443757f, 0.455826f, -0.295139f, 0.000000f, -0.054125f, 0.000000f, 0.000000f, 0.085464f, -0.196703f, // R -}; - -// Decoder matrix for stereo, ambisonic level 3 -static constexpr float decoderMatrix_stereo_3_lf[2*16] = { -0.280670f, 0.372187f, 0.240963f, 0.000000f, -0.085490f, 0.000000f, 0.000000f, 0.135154f, 0.311013f, 0.000000f, 0.045437f, 0.021103f, 0.000000f, 0.000000f, -0.035873f, 0.169918f, // L -0.280656f, 0.372181f, -0.240980f, 0.000000f, -0.085579f, 0.000000f, 0.000000f, 0.135130f, -0.311015f, 0.000000f, 0.045414f, -0.021065f, 0.000000f, 0.000000f, -0.035873f, -0.169892f, // R -}; - -// Decoder matrix for stereo, ambisonic level 3 -static constexpr float decoderMatrix_stereo_3_hf[2*16] = { -0.468210f, 0.534659f, 0.346152f, 0.000000f, -0.087326f, 0.000000f, 0.000000f, 0.138058f, 0.317696f, 0.000000f, 0.023099f, 0.010728f, 0.000000f, 0.000000f, -0.018237f, 0.086382f, // L -0.468186f, 0.534650f, -0.346176f, 0.000000f, -0.087418f, 0.000000f, 0.000000f, 0.138033f, -0.317697f, 0.000000f, 0.023087f, -0.010709f, 0.000000f, 0.000000f, -0.018237f, -0.086369f, // R -}; - -// Decoder matrix for 2dot1, ambisonic level 1 -static constexpr float decoderMatrix_2dot1_1_lf[3*4] = { -0.280670f, 0.372187f, 0.240963f, 0.000000f, // L -0.280656f, 0.372181f, -0.240980f, 0.000000f, // R -0.5f, 0.0f, 0.0f, 0.0f, // LFE -}; - -// Decoder matrix for 2dot1, ambisonic level 1 -static constexpr float decoderMatrix_2dot1_1_hf[3*4] = { -0.396928f, 0.303889f, 0.196746f, 0.000000f, // L -0.396908f, 0.303884f, -0.196759f, 0.000000f, // R -0.0f, 0.0f, 0.0f, 0.0f, // LFE -}; - -// Decoder matrix for 2dot1, ambisonic level 2 -static constexpr float decoderMatrix_2dot1_2_lf[3*9] = { -0.280670f, 0.372187f, 0.240963f, 0.000000f, -0.085490f, 0.000000f, 0.000000f, 0.135154f, 0.311013f, // L -0.280656f, 0.372181f, -0.240980f, 0.000000f, -0.085579f, 0.000000f, 0.000000f, 0.135130f, -0.311015f, // R -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // LFE -}; - -// Decoder matrix for 2dot1, ambisonic level 2 -static constexpr float decoderMatrix_2dot1_2_hf[3*9] = { -0.443779f, 0.455834f, 0.295119f, 0.000000f, -0.054068f, 0.000000f, 0.000000f, 0.085479f, 0.196702f, // L -0.443757f, 0.455826f, -0.295139f, 0.000000f, -0.054125f, 0.000000f, 0.000000f, 0.085464f, -0.196703f, // R -0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // LFE -}; - -// Decoder matrix for 2dot1, ambisonic level 3 -static constexpr float decoderMatrix_2dot1_3_lf[3*16] = { -0.280670f, 0.372187f, 0.240963f, 0.000000f, -0.085490f, 0.000000f, 0.000000f, 0.135154f, 0.311013f, 0.000000f, 0.045437f, 0.021103f, 0.000000f, 0.000000f, -0.035873f, 0.169918f, // L -0.280656f, 0.372181f, -0.240980f, 0.000000f, -0.085579f, 0.000000f, 0.000000f, 0.135130f, -0.311015f, 0.000000f, 0.045414f, -0.021065f, 0.000000f, 0.000000f, -0.035873f, -0.169892f, // R -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // LFE -}; - -// Decoder matrix for 2dot1, ambisonic level 3 -static constexpr float decoderMatrix_2dot1_3_hf[3*16] = { -0.468210f, 0.534659f, 0.346152f, 0.000000f, -0.087326f, 0.000000f, 0.000000f, 0.138058f, 0.317696f, 0.000000f, 0.023099f, 0.010728f, 0.000000f, 0.000000f, -0.018237f, 0.086382f, // L -0.468186f, 0.534650f, -0.346176f, 0.000000f, -0.087418f, 0.000000f, 0.000000f, 0.138033f, -0.317697f, 0.000000f, 0.023087f, -0.010709f, 0.000000f, 0.000000f, -0.018237f, -0.086369f, // R -0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // LFE -}; - -// Decoder matrix for 5dot0, ambisonic level 1 -static constexpr float decoderMatrix_5dot0_1_lf[5*4] = { -0.240964f, 0.257639f, 0.287251f, 0.000000f, // L -0.240957f, 0.257633f, -0.287251f, 0.000000f, // R -0.127854f, 0.219531f, 0.000000f, 0.000000f, // C -0.520591f, -0.419052f, 0.415955f, 0.000000f, // Ls -0.520596f, -0.419047f, -0.415960f, 0.000000f, // Rs -}; - -// Decoder matrix for 5dot0, ambisonic level 1 -static constexpr float decoderMatrix_5dot0_1_hf[5*4] = { -0.340774f, 0.210361f, 0.234540f, 0.000000f, // L -0.340764f, 0.210357f, -0.234540f, 0.000000f, // R -0.180812f, 0.179246f, 0.000000f, 0.000000f, // C -0.736226f, -0.342155f, 0.339626f, 0.000000f, // Ls -0.736233f, -0.342151f, -0.339630f, 0.000000f, // Rs -}; - -// Decoder matrix for 5dot0, ambisonic level 2 -static constexpr float decoderMatrix_5dot0_2_lf[5*9] = { -0.240964f, 0.257639f, 0.287251f, 0.000000f, -0.063536f, 0.000000f, 0.000000f, -0.026015f, 0.315018f, // L -0.240957f, 0.257633f, -0.287251f, 0.000000f, -0.063562f, 0.000000f, 0.000000f, -0.026018f, -0.315014f, // R -0.127854f, 0.219531f, 0.000000f, 0.000000f, -0.037403f, 0.000000f, 0.000000f, 0.222021f, 0.000000f, // C -0.520591f, -0.419052f, 0.415955f, 0.000000f, -0.092715f, 0.000000f, 0.000000f, -0.061595f, -0.083957f, // Ls -0.520596f, -0.419047f, -0.415960f, 0.000000f, -0.092693f, 0.000000f, 0.000000f, -0.061591f, 0.083957f, // Rs -}; - -// Decoder matrix for 5dot0, ambisonic level 2 -static constexpr float decoderMatrix_5dot0_2_hf[5*9] = { -0.380997f, 0.315542f, 0.351810f, 0.000000f, -0.040184f, 0.000000f, 0.000000f, -0.016453f, 0.199235f, // L -0.380986f, 0.315535f, -0.351809f, 0.000000f, -0.040200f, 0.000000f, 0.000000f, -0.016455f, -0.199232f, // R -0.202154f, 0.268870f, 0.000000f, 0.000000f, -0.023656f, 0.000000f, 0.000000f, 0.140418f, 0.000000f, // C -0.823126f, -0.513232f, 0.509439f, 0.000000f, -0.058638f, 0.000000f, 0.000000f, -0.038956f, -0.053099f, // Ls -0.823134f, -0.513226f, -0.509444f, 0.000000f, -0.058624f, 0.000000f, 0.000000f, -0.038954f, 0.053099f, // Rs -}; - -// Decoder matrix for 5dot0, ambisonic level 3 -static constexpr float decoderMatrix_5dot0_3_lf[5*16] = { -0.240964f, 0.257639f, 0.287251f, 0.000000f, -0.063536f, 0.000000f, 0.000000f, -0.026015f, 0.315018f, 0.000000f, 0.035335f, 0.041639f, 0.000000f, 0.000000f, -0.142145f, 0.134220f, // L -0.240957f, 0.257633f, -0.287251f, 0.000000f, -0.063562f, 0.000000f, 0.000000f, -0.026018f, -0.315014f, 0.000000f, 0.035320f, -0.041624f, 0.000000f, 0.000000f, -0.142141f, -0.134218f, // R -0.127854f, 0.219531f, 0.000000f, 0.000000f, -0.037403f, 0.000000f, 0.000000f, 0.222021f, 0.000000f, 0.000000f, 0.026162f, 0.000000f, 0.000000f, 0.000000f, 0.204779f, 0.000000f, // C -0.520591f, -0.419052f, 0.415955f, 0.000000f, -0.092715f, 0.000000f, 0.000000f, -0.061595f, -0.083957f, 0.000000f, -0.101526f, 0.068569f, 0.000000f, 0.000000f, -0.017680f, -0.126417f, // Ls -0.520596f, -0.419047f, -0.415960f, 0.000000f, -0.092693f, 0.000000f, 0.000000f, -0.061591f, 0.083957f, 0.000000f, -0.101519f, -0.068568f, 0.000000f, 0.000000f, -0.017687f, 0.126417f, // Rs -}; - -// Decoder matrix for 5dot0, ambisonic level 3 -static constexpr float decoderMatrix_5dot0_3_hf[5*16] = { -0.401972f, 0.370107f, 0.412646f, 0.000000f, -0.064901f, 0.000000f, 0.000000f, -0.026574f, 0.321786f, 0.000000f, 0.017964f, 0.021168f, 0.000000f, 0.000000f, -0.072263f, 0.068234f, // L -0.401960f, 0.370099f, -0.412646f, 0.000000f, -0.064928f, 0.000000f, 0.000000f, -0.026577f, -0.321782f, 0.000000f, 0.017956f, -0.021161f, 0.000000f, 0.000000f, -0.072261f, -0.068233f, // R -0.213283f, 0.315364f, 0.000000f, 0.000000f, -0.038207f, 0.000000f, 0.000000f, 0.226791f, 0.000000f, 0.000000f, 0.013300f, 0.000000f, 0.000000f, 0.000000f, 0.104104f, 0.000000f, // C -0.868441f, -0.601983f, 0.597533f, 0.000000f, -0.094707f, 0.000000f, 0.000000f, -0.062919f, -0.085760f, 0.000000f, -0.051613f, 0.034859f, 0.000000f, 0.000000f, -0.008988f, -0.064267f, // Ls -0.868449f, -0.601975f, -0.597540f, 0.000000f, -0.094684f, 0.000000f, 0.000000f, -0.062915f, 0.085761f, 0.000000f, -0.051609f, -0.034858f, 0.000000f, 0.000000f, -0.008992f, 0.064267f, // Rs -}; - -// Decoder matrix for 5dot1, ambisonic level 1 -static constexpr float decoderMatrix_5dot1_1_lf[6*4] = { -0.240964f, 0.257639f, 0.287251f, 0.000000f, // L -0.240957f, 0.257633f, -0.287251f, 0.000000f, // R -0.127854f, 0.219531f, 0.000000f, 0.000000f, // C -0.5f, 0.0f, 0.0f, 0.0f, // LFE -0.520591f, -0.419052f, 0.415955f, 0.000000f, // Ls -0.520596f, -0.419047f, -0.415960f, 0.000000f, // Rs -}; - -// Decoder matrix for 5dot1, ambisonic level 1 -static constexpr float decoderMatrix_5dot1_1_hf[6*4] = { -0.340774f, 0.210361f, 0.234540f, 0.000000f, // L -0.340764f, 0.210357f, -0.234540f, 0.000000f, // R -0.180812f, 0.179246f, 0.000000f, 0.000000f, // C -0.0f, 0.0f, 0.0f, 0.0f, // LFE -0.736226f, -0.342155f, 0.339626f, 0.000000f, // Ls -0.736233f, -0.342151f, -0.339630f, 0.000000f, // Rs -}; - -// Decoder matrix for 5dot1, ambisonic level 2 -static constexpr float decoderMatrix_5dot1_2_lf[6*9] = { -0.240964f, 0.257639f, 0.287251f, 0.000000f, -0.063536f, 0.000000f, 0.000000f, -0.026015f, 0.315018f, // L -0.240957f, 0.257633f, -0.287251f, 0.000000f, -0.063562f, 0.000000f, 0.000000f, -0.026018f, -0.315014f, // R -0.127854f, 0.219531f, 0.000000f, 0.000000f, -0.037403f, 0.000000f, 0.000000f, 0.222021f, 0.000000f, // C -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // LFE -0.520591f, -0.419052f, 0.415955f, 0.000000f, -0.092715f, 0.000000f, 0.000000f, -0.061595f, -0.083957f, // Ls -0.520596f, -0.419047f, -0.415960f, 0.000000f, -0.092693f, 0.000000f, 0.000000f, -0.061591f, 0.083957f, // Rs -}; - -// Decoder matrix for 5dot1, ambisonic level 2 -static constexpr float decoderMatrix_5dot1_2_hf[6*9] = { -0.380997f, 0.315542f, 0.351810f, 0.000000f, -0.040184f, 0.000000f, 0.000000f, -0.016453f, 0.199235f, // L -0.380986f, 0.315535f, -0.351809f, 0.000000f, -0.040200f, 0.000000f, 0.000000f, -0.016455f, -0.199232f, // R -0.202154f, 0.268870f, 0.000000f, 0.000000f, -0.023656f, 0.000000f, 0.000000f, 0.140418f, 0.000000f, // C -0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // LFE -0.823126f, -0.513232f, 0.509439f, 0.000000f, -0.058638f, 0.000000f, 0.000000f, -0.038956f, -0.053099f, // Ls -0.823134f, -0.513226f, -0.509444f, 0.000000f, -0.058624f, 0.000000f, 0.000000f, -0.038954f, 0.053099f, // Rs -}; - -// Decoder matrix for 5dot1, ambisonic level 3 -static constexpr float decoderMatrix_5dot1_3_lf[6*16] = { -0.240964f, 0.257639f, 0.287251f, 0.000000f, -0.063536f, 0.000000f, 0.000000f, -0.026015f, 0.315018f, 0.000000f, 0.035335f, 0.041639f, 0.000000f, 0.000000f, -0.142145f, 0.134220f, // L -0.240957f, 0.257633f, -0.287251f, 0.000000f, -0.063562f, 0.000000f, 0.000000f, -0.026018f, -0.315014f, 0.000000f, 0.035320f, -0.041624f, 0.000000f, 0.000000f, -0.142141f, -0.134218f, // R -0.127854f, 0.219531f, 0.000000f, 0.000000f, -0.037403f, 0.000000f, 0.000000f, 0.222021f, 0.000000f, 0.000000f, 0.026162f, 0.000000f, 0.000000f, 0.000000f, 0.204779f, 0.000000f, // C -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // LFE -0.520591f, -0.419052f, 0.415955f, 0.000000f, -0.092715f, 0.000000f, 0.000000f, -0.061595f, -0.083957f, 0.000000f, -0.101526f, 0.068569f, 0.000000f, 0.000000f, -0.017680f, -0.126417f, // Ls -0.520596f, -0.419047f, -0.415960f, 0.000000f, -0.092693f, 0.000000f, 0.000000f, -0.061591f, 0.083957f, 0.000000f, -0.101519f, -0.068568f, 0.000000f, 0.000000f, -0.017687f, 0.126417f, // Rs -}; - -// Decoder matrix for 5dot1, ambisonic level 3 -static constexpr float decoderMatrix_5dot1_3_hf[6*16] = { -0.401972f, 0.370107f, 0.412646f, 0.000000f, -0.064901f, 0.000000f, 0.000000f, -0.026574f, 0.321786f, 0.000000f, 0.017964f, 0.021168f, 0.000000f, 0.000000f, -0.072263f, 0.068234f, // L -0.401960f, 0.370099f, -0.412646f, 0.000000f, -0.064928f, 0.000000f, 0.000000f, -0.026577f, -0.321782f, 0.000000f, 0.017956f, -0.021161f, 0.000000f, 0.000000f, -0.072261f, -0.068233f, // R -0.213283f, 0.315364f, 0.000000f, 0.000000f, -0.038207f, 0.000000f, 0.000000f, 0.226791f, 0.000000f, 0.000000f, 0.013300f, 0.000000f, 0.000000f, 0.000000f, 0.104104f, 0.000000f, // C -0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // LFE -0.868441f, -0.601983f, 0.597533f, 0.000000f, -0.094707f, 0.000000f, 0.000000f, -0.062919f, -0.085760f, 0.000000f, -0.051613f, 0.034859f, 0.000000f, 0.000000f, -0.008988f, -0.064267f, // Ls -0.868449f, -0.601975f, -0.597540f, 0.000000f, -0.094684f, 0.000000f, 0.000000f, -0.062915f, 0.085761f, 0.000000f, -0.051609f, -0.034858f, 0.000000f, 0.000000f, -0.008992f, 0.064267f, // Rs -}; - -// Decoder matrix for 7dot0, ambisonic level 1 -static constexpr float decoderMatrix_7dot0_1_lf[7*4] = { -0.194124f, 0.244088f, 0.209910f, 0.000000f, // L -0.194108f, 0.244084f, -0.209914f, 0.000000f, // R -0.127854f, 0.219531f, 0.000000f, 0.000000f, // C -0.260404f, 0.000000f, 0.413172f, 0.000000f, // Ls -0.260430f, 0.000000f, -0.413179f, 0.000000f, // Rs -0.260425f, -0.357822f, 0.206589f, 0.000000f, // Lb -0.260400f, -0.357815f, -0.206595f, 0.000000f, // Rb -}; - -// Decoder matrix for 7dot0, ambisonic level 1 -static constexpr float decoderMatrix_7dot0_1_hf[7*4] = { -0.274533f, 0.199297f, 0.171391f, 0.000000f, // L -0.274510f, 0.199294f, -0.171394f, 0.000000f, // R -0.180812f, 0.179246f, 0.000000f, 0.000000f, // C -0.368266f, 0.000000f, 0.337353f, 0.000000f, // Ls -0.368304f, 0.000000f, -0.337359f, 0.000000f, // Rs -0.368297f, -0.292160f, 0.168680f, 0.000000f, // Lb -0.368261f, -0.292155f, -0.168684f, 0.000000f, // Rb -}; - -// Decoder matrix for 7dot0, ambisonic level 2 -static constexpr float decoderMatrix_7dot0_2_lf[7*9] = { -0.194124f, 0.244088f, 0.209910f, 0.000000f, -0.054359f, 0.000000f, 0.000000f, 0.046706f, 0.289736f, // L -0.194108f, 0.244084f, -0.209914f, 0.000000f, -0.054434f, 0.000000f, 0.000000f, 0.046694f, -0.289734f, // R -0.127854f, 0.219531f, 0.000000f, 0.000000f, -0.037403f, 0.000000f, 0.000000f, 0.222021f, 0.000000f, // C -0.260404f, 0.000000f, 0.413172f, 0.000000f, -0.071326f, 0.000000f, 0.000000f, -0.326534f, 0.000000f, // Ls -0.260430f, 0.000000f, -0.413179f, 0.000000f, -0.071237f, 0.000000f, 0.000000f, -0.326534f, 0.000000f, // Rs -0.260425f, -0.357822f, 0.206589f, 0.000000f, -0.071249f, 0.000000f, 0.000000f, 0.163267f, -0.282791f, // Lb -0.260400f, -0.357815f, -0.206595f, 0.000000f, -0.071359f, 0.000000f, 0.000000f, 0.163256f, 0.282788f, // Rb -}; - -// Decoder matrix for 7dot0, ambisonic level 2 -static constexpr float decoderMatrix_7dot0_2_hf[7*9] = { -0.306937f, 0.298946f, 0.257087f, 0.000000f, -0.034380f, 0.000000f, 0.000000f, 0.029540f, 0.183245f, // L -0.306912f, 0.298940f, -0.257091f, 0.000000f, -0.034427f, 0.000000f, 0.000000f, 0.029532f, -0.183244f, // R -0.202154f, 0.268870f, 0.000000f, 0.000000f, -0.023656f, 0.000000f, 0.000000f, 0.140418f, 0.000000f, // C -0.411734f, 0.000000f, 0.506030f, 0.000000f, -0.045111f, 0.000000f, 0.000000f, -0.206518f, 0.000000f, // Ls -0.411776f, 0.000000f, -0.506039f, 0.000000f, -0.045054f, 0.000000f, 0.000000f, -0.206518f, 0.000000f, // Rs -0.411768f, -0.438240f, 0.253019f, 0.000000f, -0.045062f, 0.000000f, 0.000000f, 0.103259f, -0.178853f, // Lb -0.411728f, -0.438232f, -0.253026f, 0.000000f, -0.045131f, 0.000000f, 0.000000f, 0.103252f, 0.178851f, // Rb -}; - -// Decoder matrix for 7dot0, ambisonic level 3 -static constexpr float decoderMatrix_7dot0_3_lf[7*16] = { -0.194124f, 0.244088f, 0.209910f, 0.000000f, -0.054359f, 0.000000f, 0.000000f, 0.046706f, 0.289736f, 0.000000f, 0.031236f, 0.027345f, 0.000000f, 0.000000f, -0.110659f, 0.194894f, // L -0.194108f, 0.244084f, -0.209914f, 0.000000f, -0.054434f, 0.000000f, 0.000000f, 0.046694f, -0.289734f, 0.000000f, 0.031217f, -0.027307f, 0.000000f, 0.000000f, -0.110659f, -0.194879f, // R -0.127854f, 0.219531f, 0.000000f, 0.000000f, -0.037403f, 0.000000f, 0.000000f, 0.222021f, 0.000000f, 0.000000f, 0.026162f, 0.000000f, 0.000000f, 0.000000f, 0.204779f, 0.000000f, // C -0.260404f, 0.000000f, 0.413172f, 0.000000f, -0.071326f, 0.000000f, 0.000000f, -0.326534f, 0.000000f, 0.000000f, 0.000000f, 0.055313f, 0.000000f, 0.000000f, 0.000000f, -0.185006f, // Ls -0.260430f, 0.000000f, -0.413179f, 0.000000f, -0.071237f, 0.000000f, 0.000000f, -0.326534f, 0.000000f, 0.000000f, 0.000000f, -0.055349f, 0.000000f, 0.000000f, 0.000000f, 0.185008f, // Rs -0.260425f, -0.357822f, 0.206589f, 0.000000f, -0.071249f, 0.000000f, 0.000000f, 0.163267f, -0.282791f, 0.000000f, -0.047935f, 0.027670f, 0.000000f, 0.000000f, 0.000000f, 0.185014f, // Lb -0.260400f, -0.357815f, -0.206595f, 0.000000f, -0.071359f, 0.000000f, 0.000000f, 0.163256f, 0.282788f, 0.000000f, -0.047893f, -0.027649f, 0.000000f, 0.000000f, 0.000000f, -0.184996f, // Rb -}; - -// Decoder matrix for 7dot0, ambisonic level 3 -static constexpr float decoderMatrix_7dot0_3_hf[7*16] = { -0.323835f, 0.350641f, 0.301543f, 0.000000f, -0.055527f, 0.000000f, 0.000000f, 0.047710f, 0.295961f, 0.000000f, 0.015880f, 0.013901f, 0.000000f, 0.000000f, -0.056256f, 0.099079f, // L -0.323808f, 0.350635f, -0.301549f, 0.000000f, -0.055604f, 0.000000f, 0.000000f, 0.047697f, -0.295959f, 0.000000f, 0.015870f, -0.013882f, 0.000000f, 0.000000f, -0.056256f, -0.099072f, // R -0.213283f, 0.315364f, 0.000000f, 0.000000f, -0.038207f, 0.000000f, 0.000000f, 0.226791f, 0.000000f, 0.000000f, 0.013300f, 0.000000f, 0.000000f, 0.000000f, 0.104104f, 0.000000f, // C -0.434401f, 0.000000f, 0.593535f, 0.000000f, -0.072859f, 0.000000f, 0.000000f, -0.333550f, 0.000000f, 0.000000f, 0.000000f, 0.028120f, 0.000000f, 0.000000f, 0.000000f, -0.094052f, // Ls -0.434446f, 0.000000f, -0.593546f, 0.000000f, -0.072768f, 0.000000f, 0.000000f, -0.333550f, 0.000000f, 0.000000f, 0.000000f, -0.028138f, 0.000000f, 0.000000f, 0.000000f, 0.094053f, // Rs -0.434437f, -0.514023f, 0.296773f, 0.000000f, -0.072780f, 0.000000f, 0.000000f, 0.166775f, -0.288867f, 0.000000f, -0.024369f, 0.014067f, 0.000000f, 0.000000f, 0.000000f, 0.094056f, // Lb -0.434395f, -0.514014f, -0.296781f, 0.000000f, -0.072892f, 0.000000f, 0.000000f, 0.166764f, 0.288864f, 0.000000f, -0.024348f, -0.014056f, 0.000000f, 0.000000f, 0.000000f, -0.094047f, // Rb -}; - -// Decoder matrix for 7dot1, ambisonic level 1 -static constexpr float decoderMatrix_7dot1_1_lf[8*4] = { -0.194124f, 0.244088f, 0.209910f, 0.000000f, // L -0.194108f, 0.244084f, -0.209914f, 0.000000f, // R -0.127854f, 0.219531f, 0.000000f, 0.000000f, // C -0.5f, 0.0f, 0.0f, 0.0f, // LFE -0.260404f, 0.000000f, 0.413172f, 0.000000f, // Ls -0.260430f, 0.000000f, -0.413179f, 0.000000f, // Rs -0.260425f, -0.357822f, 0.206589f, 0.000000f, // Lb -0.260400f, -0.357815f, -0.206595f, 0.000000f, // Rb -}; - -// Decoder matrix for 7dot1, ambisonic level 1 -static constexpr float decoderMatrix_7dot1_1_hf[8*4] = { -0.274533f, 0.199297f, 0.171391f, 0.000000f, // L -0.274510f, 0.199294f, -0.171394f, 0.000000f, // R -0.180812f, 0.179246f, 0.000000f, 0.000000f, // C -0.0f, 0.0f, 0.0f, 0.0f, // LFE -0.368266f, 0.000000f, 0.337353f, 0.000000f, // Ls -0.368304f, 0.000000f, -0.337359f, 0.000000f, // Rs -0.368297f, -0.292160f, 0.168680f, 0.000000f, // Lb -0.368261f, -0.292155f, -0.168684f, 0.000000f, // Rb -}; - -// Decoder matrix for 7dot1, ambisonic level 2 -static constexpr float decoderMatrix_7dot1_2_lf[8*9] = { -0.194124f, 0.244088f, 0.209910f, 0.000000f, -0.054359f, 0.000000f, 0.000000f, 0.046706f, 0.289736f, // L -0.194108f, 0.244084f, -0.209914f, 0.000000f, -0.054434f, 0.000000f, 0.000000f, 0.046694f, -0.289734f, // R -0.127854f, 0.219531f, 0.000000f, 0.000000f, -0.037403f, 0.000000f, 0.000000f, 0.222021f, 0.000000f, // C -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // LFE -0.260404f, 0.000000f, 0.413172f, 0.000000f, -0.071326f, 0.000000f, 0.000000f, -0.326534f, 0.000000f, // Ls -0.260430f, 0.000000f, -0.413179f, 0.000000f, -0.071237f, 0.000000f, 0.000000f, -0.326534f, 0.000000f, // Rs -0.260425f, -0.357822f, 0.206589f, 0.000000f, -0.071249f, 0.000000f, 0.000000f, 0.163267f, -0.282791f, // Lb -0.260400f, -0.357815f, -0.206595f, 0.000000f, -0.071359f, 0.000000f, 0.000000f, 0.163256f, 0.282788f, // Rb -}; - -// Decoder matrix for 7dot1, ambisonic level 2 -static constexpr float decoderMatrix_7dot1_2_hf[8*9] = { -0.306937f, 0.298946f, 0.257087f, 0.000000f, -0.034380f, 0.000000f, 0.000000f, 0.029540f, 0.183245f, // L -0.306912f, 0.298940f, -0.257091f, 0.000000f, -0.034427f, 0.000000f, 0.000000f, 0.029532f, -0.183244f, // R -0.202154f, 0.268870f, 0.000000f, 0.000000f, -0.023656f, 0.000000f, 0.000000f, 0.140418f, 0.000000f, // C -0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // LFE -0.411734f, 0.000000f, 0.506030f, 0.000000f, -0.045111f, 0.000000f, 0.000000f, -0.206518f, 0.000000f, // Ls -0.411776f, 0.000000f, -0.506039f, 0.000000f, -0.045054f, 0.000000f, 0.000000f, -0.206518f, 0.000000f, // Rs -0.411768f, -0.438240f, 0.253019f, 0.000000f, -0.045062f, 0.000000f, 0.000000f, 0.103259f, -0.178853f, // Lb -0.411728f, -0.438232f, -0.253026f, 0.000000f, -0.045131f, 0.000000f, 0.000000f, 0.103252f, 0.178851f, // Rb -}; - -// Decoder matrix for 7dot1, ambisonic level 3 -static constexpr float decoderMatrix_7dot1_3_lf[8*16] = { -0.194124f, 0.244088f, 0.209910f, 0.000000f, -0.054359f, 0.000000f, 0.000000f, 0.046706f, 0.289736f, 0.000000f, 0.031236f, 0.027345f, 0.000000f, 0.000000f, -0.110659f, 0.194894f, // L -0.194108f, 0.244084f, -0.209914f, 0.000000f, -0.054434f, 0.000000f, 0.000000f, 0.046694f, -0.289734f, 0.000000f, 0.031217f, -0.027307f, 0.000000f, 0.000000f, -0.110659f, -0.194879f, // R -0.127854f, 0.219531f, 0.000000f, 0.000000f, -0.037403f, 0.000000f, 0.000000f, 0.222021f, 0.000000f, 0.000000f, 0.026162f, 0.000000f, 0.000000f, 0.000000f, 0.204779f, 0.000000f, // C -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // LFE -0.260404f, 0.000000f, 0.413172f, 0.000000f, -0.071326f, 0.000000f, 0.000000f, -0.326534f, 0.000000f, 0.000000f, 0.000000f, 0.055313f, 0.000000f, 0.000000f, 0.000000f, -0.185006f, // Ls -0.260430f, 0.000000f, -0.413179f, 0.000000f, -0.071237f, 0.000000f, 0.000000f, -0.326534f, 0.000000f, 0.000000f, 0.000000f, -0.055349f, 0.000000f, 0.000000f, 0.000000f, 0.185008f, // Rs -0.260425f, -0.357822f, 0.206589f, 0.000000f, -0.071249f, 0.000000f, 0.000000f, 0.163267f, -0.282791f, 0.000000f, -0.047935f, 0.027670f, 0.000000f, 0.000000f, 0.000000f, 0.185014f, // Lb -0.260400f, -0.357815f, -0.206595f, 0.000000f, -0.071359f, 0.000000f, 0.000000f, 0.163256f, 0.282788f, 0.000000f, -0.047893f, -0.027649f, 0.000000f, 0.000000f, 0.000000f, -0.184996f, // Rb -}; - -// Decoder matrix for 7dot1, ambisonic level 3 -static constexpr float decoderMatrix_7dot1_3_hf[8*16] = { -0.323835f, 0.350641f, 0.301543f, 0.000000f, -0.055527f, 0.000000f, 0.000000f, 0.047710f, 0.295961f, 0.000000f, 0.015880f, 0.013901f, 0.000000f, 0.000000f, -0.056256f, 0.099079f, // L -0.323808f, 0.350635f, -0.301549f, 0.000000f, -0.055604f, 0.000000f, 0.000000f, 0.047697f, -0.295959f, 0.000000f, 0.015870f, -0.013882f, 0.000000f, 0.000000f, -0.056256f, -0.099072f, // R -0.213283f, 0.315364f, 0.000000f, 0.000000f, -0.038207f, 0.000000f, 0.000000f, 0.226791f, 0.000000f, 0.000000f, 0.013300f, 0.000000f, 0.000000f, 0.000000f, 0.104104f, 0.000000f, // C -0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // LFE -0.434401f, 0.000000f, 0.593535f, 0.000000f, -0.072859f, 0.000000f, 0.000000f, -0.333550f, 0.000000f, 0.000000f, 0.000000f, 0.028120f, 0.000000f, 0.000000f, 0.000000f, -0.094052f, // Ls -0.434446f, 0.000000f, -0.593546f, 0.000000f, -0.072768f, 0.000000f, 0.000000f, -0.333550f, 0.000000f, 0.000000f, 0.000000f, -0.028138f, 0.000000f, 0.000000f, 0.000000f, 0.094053f, // Rs -0.434437f, -0.514023f, 0.296773f, 0.000000f, -0.072780f, 0.000000f, 0.000000f, 0.166775f, -0.288867f, 0.000000f, -0.024369f, 0.014067f, 0.000000f, 0.000000f, 0.000000f, 0.094056f, // Lb -0.434395f, -0.514014f, -0.296781f, 0.000000f, -0.072892f, 0.000000f, 0.000000f, 0.166764f, 0.288864f, 0.000000f, -0.024348f, -0.014056f, 0.000000f, 0.000000f, 0.000000f, -0.094047f, // Rb -}; - -QT_END_NAMESPACE - -#endif - diff --git a/src/multimedia/spatial/qspatialaudioengine.cpp b/src/multimedia/spatial/qspatialaudioengine.cpp deleted file mode 100644 index 7ab89c1fa..000000000 --- a/src/multimedia/spatial/qspatialaudioengine.cpp +++ /dev/null @@ -1,627 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Spatial Audio module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL-NOGPL2$ -** 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 3 or (at your option) 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.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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include <qspatialaudioengine_p.h> -#include <qspatialaudiosoundsource_p.h> -#include <qspatialaudiostereosource.h> -#include <qspatialaudioroom_p.h> -#include <qspatialaudiolistener.h> -#include <resonance_audio_api_extensions.h> -#include <qambisonicdecoder_p.h> -#include <qaudiodecoder.h> -#include <qmediadevices.h> -#include <qiodevice.h> -#include <qaudiosink.h> -#include <qdebug.h> -#include <qelapsedtimer.h> - -QT_BEGIN_NAMESPACE - -class QAudioOutputStream : public QIODevice -{ - Q_OBJECT -public: - explicit QAudioOutputStream(QSpatialAudioEnginePrivate *d) - : d(d) - { - open(QIODevice::ReadOnly); - } - ~QAudioOutputStream(); - - qint64 readData(char *data, qint64 len) override; - - qint64 writeData(const char *, qint64) override; - - qint64 size() const override { return 0; } - qint64 bytesAvailable() const override { - return std::numeric_limits<qint64>::max(); - } - bool isSequential() const override { - return true; - } - bool atEnd() const override { - return false; - } - qint64 pos() const override { - return m_pos; - } - - Q_INVOKABLE void startOutput() { - QMutexLocker l(&d->mutex); - Q_ASSERT(!sink); - d->ambisonicDecoder.reset(new QAmbisonicDecoder(QAmbisonicDecoder::HighQuality, d->format)); - sink.reset(new QAudioSink(d->device, d->format)); - sink->setBufferSize(16384); - sink->start(this); - } - - Q_INVOKABLE void stopOutput() { - sink->stop(); - sink.reset(); - d->ambisonicDecoder.reset(); - delete this; - } - - void setPaused(bool paused) { - if (paused) - sink->suspend(); - else - sink->resume(); - } - -private: - qint64 m_pos = 0; - QSpatialAudioEnginePrivate *d = nullptr; - std::unique_ptr<QAudioSink> sink; -}; - - -QAudioOutputStream::~QAudioOutputStream() -{ -} - -qint64 QAudioOutputStream::writeData(const char *, qint64) -{ - return 0; -} - -qint64 QAudioOutputStream::readData(char *data, qint64 len) -{ - if (d->paused.loadRelaxed()) - return 0; - - d->updateRooms(); - - int nChannels = d->ambisonicDecoder ? d->ambisonicDecoder->nOutputChannels() : 2; - if (len < nChannels*int(sizeof(float))*QSpatialAudioEnginePrivate::bufferSize) - return 0; - - short *fd = (short *)data; - qint64 frames = len / nChannels / sizeof(short); - bool ok = true; - while (frames >= qint64(QSpatialAudioEnginePrivate::bufferSize)) { - // Fill input buffers - for (auto *source : qAsConst(d->sources)) { - auto *sp = QSpatialAudioSoundSourcePrivate::get(source); - float buf[QSpatialAudioEnginePrivate::bufferSize]; - sp->getBuffer(buf, QSpatialAudioEnginePrivate::bufferSize, 1); - d->api->SetInterleavedBuffer(sp->sourceId, buf, 1, QSpatialAudioEnginePrivate::bufferSize); - } - for (auto *source : qAsConst(d->stereoSources)) { - auto *sp = QSpatialAudioSound::get(source); - float buf[2*QSpatialAudioEnginePrivate::bufferSize]; - sp->getBuffer(buf, QSpatialAudioEnginePrivate::bufferSize, 2); - d->api->SetInterleavedBuffer(sp->sourceId, buf, 2, QSpatialAudioEnginePrivate::bufferSize); - } - - if (d->ambisonicDecoder && d->outputMode == QSpatialAudioEngine::Normal && d->format.channelCount() != 2) { - const float *channels[QAmbisonicDecoder::maxAmbisonicChannels]; - int nSamples = vraudio::getAmbisonicOutput(d->api, channels, d->ambisonicDecoder->nInputChannels()); - Q_ASSERT(d->ambisonicDecoder->nOutputChannels() <= 8); - d->ambisonicDecoder->processBuffer(channels, fd, nSamples); - } else { - ok = d->api->FillInterleavedOutputBuffer(2, QSpatialAudioEnginePrivate::bufferSize, fd); - if (!ok) { - qWarning() << " Reading failed!"; - break; - } - } - fd += nChannels*QSpatialAudioEnginePrivate::bufferSize; - frames -= QSpatialAudioEnginePrivate::bufferSize; - } - const int bytesProcessed = ((char *)fd - data); - m_pos += bytesProcessed; - return bytesProcessed; -} - - -QSpatialAudioEnginePrivate::QSpatialAudioEnginePrivate() -{ - device = QMediaDevices::defaultAudioOutput(); -} - -QSpatialAudioEnginePrivate::~QSpatialAudioEnginePrivate() -{ - delete api; -} - -void QSpatialAudioEnginePrivate::addSpatialSound(QSpatialAudioSoundSource *sound) -{ - QSpatialAudioSound *sd = QSpatialAudioSound::get(sound); - - sd->sourceId = api->CreateSoundObjectSource(vraudio::kBinauralHighQuality); - sources.append(sound); -} - -void QSpatialAudioEnginePrivate::removeSpatialSound(QSpatialAudioSoundSource *sound) -{ - QSpatialAudioSound *sd = QSpatialAudioSound::get(sound); - - api->DestroySource(sd->sourceId); - sd->sourceId = vraudio::ResonanceAudioApi::kInvalidSourceId; - sources.removeOne(sound); -} - -void QSpatialAudioEnginePrivate::addStereoSound(QSpatialAudioStereoSource *sound) -{ - QSpatialAudioSound *sd = QSpatialAudioSound::get(sound); - - sd->sourceId = api->CreateStereoSource(2); - stereoSources.append(sound); -} - -void QSpatialAudioEnginePrivate::removeStereoSound(QSpatialAudioStereoSource *sound) -{ - QSpatialAudioSound *sd = QSpatialAudioSound::get(sound); - - api->DestroySource(sd->sourceId); - sd->sourceId = vraudio::ResonanceAudioApi::kInvalidSourceId; - stereoSources.removeOne(sound); -} - -void QSpatialAudioEnginePrivate::addRoom(QSpatialAudioRoom *room) -{ - rooms.append(room); -} - -void QSpatialAudioEnginePrivate::removeRoom(QSpatialAudioRoom *room) -{ - rooms.removeOne(room); -} - -void QSpatialAudioEnginePrivate::updateRooms() -{ - if (!roomEffectsEnabled) - return; - - bool needUpdate = listenerPositionDirty; - listenerPositionDirty = false; - - bool roomDirty = false; - for (const auto &room : rooms) { - auto *rd = QSpatialAudioRoomPrivate::get(room); - if (rd->dirty) { - roomDirty = true; - rd->update(); - needUpdate = true; - } - } - - if (!needUpdate) - return; - - QVector3D listenerPos = listenerPosition(); - float roomVolume = float(qInf()); - QSpatialAudioRoom *room = nullptr; - // Find the smallest room that contains the listener and apply it's room effects - for (auto *r : qAsConst(rooms)) { - QVector3D dim2 = r->dimensions()/2.; - float vol = dim2.x()*dim2.y()*dim2.z(); - if (vol > roomVolume) - continue; - QVector3D dist = r->position() - listenerPos; - // transform into room coordinates - dist = r->rotation().rotatedVector(dist); - if (qAbs(dist.x()) <= dim2.x() && - qAbs(dist.y()) <= dim2.y() && - qAbs(dist.z()) <= dim2.z()) { - room = r; - roomVolume = vol; - } - } - if (room != currentRoom) - roomDirty = true; - currentRoom = room; - - if (!roomDirty) - return; - - // apply room to engine - if (!currentRoom) { - api->EnableRoomEffects(false); - return; - } - QSpatialAudioRoomPrivate *rp = QSpatialAudioRoomPrivate::get(room); - api->SetReflectionProperties(rp->reflections); - api->SetReverbProperties(rp->reverb); - - // update room effects for all sound sources - for (auto *s : qAsConst(sources)) { - auto *sp = QSpatialAudioSoundSourcePrivate::get(s); - sp->updateRoomEffects(); - } -} - -QVector3D QSpatialAudioEnginePrivate::listenerPosition() const -{ - return listener ? listener->position() : QVector3D(); -} - - -/*! - \class QSpatialAudioEngine - \inmodule QtMultimedia - \ingroup multimedia_spatialaudio - - \brief QSpatialAudioEngine manages a three dimensional sound field. - - You can use an instance of QSpatialAudioEngine to manage a sound field in - three dimensions. A sound field is defined by several QSpatialAudioSoundSource - objects that define a sound at a specified location in 3D space. You can also - add stereo overlays using QSpatialAudioStereoSource. - - You can use QSpatialAudioListener to define the position of the person listening - to the sound field relative to the sound sources. Sound sources will be less audible - if the listener is further away from source. They will also get mapped to the corresponding - loudspeakers depending on the direction between listener and source. - - QSpatialAudioEngine offers two output modes. The first mode renders the sound field to a set of - speakers, either a stereo speaker pair or a surround configuration. The second mode provides - an immersive 3D sound experience when using headphones. - - Perception of sound localization is driven mainly by two factors. The first factor is timing - differences of the sound waves between left and right ear. The second factor comes from various - ways how sounds coming from different direcations create different types of reflections from our - ears and heads. See https://en.wikipedia.org/wiki/Sound_localization for more details. - - The spatial audio engine emulates those timing differences and reflections through - Head related transfer functions (HRTF, see - https://en.wikipedia.org/wiki/Head-related_transfer_function). The functions used emulates those - effects for an average persons ears and head. It provides a good and immersive 3D sound localization - experience for most persons when using headphones. - - The engine is rather versatile allowing you to define amd emulate room properties and reverb settings emulating - different types of rooms. - - Sound sources can also be occluded dampening the sound coming from those sources. - -*/ - -/*! - Constructs a spatial audio engine with \a parent. - - The engine will operate with a sample rate given by \a sampleRate. Sound content that is - not provided at that sample rate will automatically get resampled to \a sampleRate when - being processed by the engine. The default sample rate is fine in most cases, but you can define - a different rate if most of your sound files are sampled with a different rate, and avoid some - CPU overhead for resampling. - */ -QSpatialAudioEngine::QSpatialAudioEngine(QObject *parent, int sampleRate) - : QObject(parent) - , d(new QSpatialAudioEnginePrivate) -{ - d->sampleRate = sampleRate; - d->api = vraudio::CreateResonanceAudioApi(2, QSpatialAudioEnginePrivate::bufferSize, d->sampleRate); -} - -/*! - Destroys the spatial audio engine. - */ -QSpatialAudioEngine::~QSpatialAudioEngine() -{ - stop(); - delete d; -} - -/*! \enum QSpatialAudioEngine::OutputMode - \value Normal Map the sounds to the loudspeaker configuration of the output device. - This is normally a stereo or surround speaker setup. - \value Headphone Use Headphone spatialization to create a 3D audio effect when listening - to the sound field through headphones -*/ - -/*! - \property QSpatialAudioEngine::outputMode - - Sets or retrieves the current output mode of the engine. - - \sa QSpatialAudioEngine::OutputMode - */ -void QSpatialAudioEngine::setOutputMode(OutputMode mode) -{ - if (d->outputMode == mode) - return; - d->outputMode = mode; - if (d->api) { - d->api->SetStereoSpeakerMode(mode == Normal); - } - emit outputModeChanged(); -} - -QSpatialAudioEngine::OutputMode QSpatialAudioEngine::outputMode() const -{ - return d->outputMode; -} - -/*! - Returns the sample rate the engine has been configured with. - */ -int QSpatialAudioEngine::sampleRate() const -{ - return d->sampleRate; -} - -/*! - \property QSpatialAudioEngine::outputDevice - - Sets or returns the device that is being used for playing the sound field. - */ -void QSpatialAudioEngine::setOutputDevice(const QAudioDevice &device) -{ - if (d->device == device) - return; - if (d->api) { - qWarning() << "Changing device on a running engine not implemented"; - return; - } - d->device = device; - emit outputDeviceChanged(); -} - -QAudioDevice QSpatialAudioEngine::outputDevice() const -{ - return d->device; -} - -/*! - \property QSpatialAudioEngine::masterVolume - - Sets or returns volume being used to render the sound field. - */ -void QSpatialAudioEngine::setMasterVolume(float volume) -{ - if (d->masterVolume == volume) - return; - d->masterVolume = volume; - d->api->SetMasterVolume(volume); - emit masterVolumeChanged(); -} - -float QSpatialAudioEngine::masterVolume() const -{ - return d->masterVolume; -} - -/*! - Starts the engine. - */ -void QSpatialAudioEngine::start() -{ - if (d->outputStream) - // already started - return; - - d->format.setChannelCount(2); - d->format.setSampleRate(d->sampleRate); - d->format.setSampleFormat(QAudioFormat::Int16); - - d->api->SetStereoSpeakerMode(d->outputMode == Normal); - d->api->SetMasterVolume(d->masterVolume); - - d->outputStream.reset(new QAudioOutputStream(d)); - d->outputStream->moveToThread(&d->audioThread); - d->audioThread.start(); - - QMetaObject::invokeMethod(d->outputStream.get(), "startOutput"); -} - -/*! - Stops the engine. - */ -void QSpatialAudioEngine::stop() -{ - QMetaObject::invokeMethod(d->outputStream.get(), "stopOutput", Qt::BlockingQueuedConnection); - d->outputStream.reset(); - d->audioThread.exit(0); - d->audioThread.wait(); - delete d->api; - d->api = nullptr; -} - -/*! - \property QSpatialAudioEngine::paused - - Pauses the spatial audio engine. - */ -void QSpatialAudioEngine::setPaused(bool paused) -{ - bool old = d->paused.fetchAndStoreRelaxed(paused); - if (old != paused) { - if (d->outputStream) - d->outputStream->setPaused(paused); - emit pausedChanged(); - } -} - -bool QSpatialAudioEngine::paused() const -{ - return d->paused.loadRelaxed(); -} - -/*! - Enables room effects such as echos and reverb. - - Enables room effects if \a enabled is true. - Room effects will only apply if you create one or more \l QSpatialAudioRoom objects - and the listener is inside at least one of the rooms. If the listener is inside - multiple rooms, the room with the smallest volume will be used. - */ -void QSpatialAudioEngine::setRoomEffectsEnabled(bool enabled) -{ - if (d->roomEffectsEnabled == enabled) - return; - d->roomEffectsEnabled = enabled; -} - -/*! - Returns true if room effects are enabled. - */ -bool QSpatialAudioEngine::roomEffectsEnabled() const -{ - return d->roomEffectsEnabled; -} - -/*! - \property QSpatialAudioEngine::distanceScale - - Defines the scale of the coordinate system being used by the spatial audio engine. - By default, all units are in centimeters, in line with the default units being - used by Qt Quick 3D. - - Set the distance scale to QSpatialAudioEngine::DistanceScaleMeter to get units in meters. -*/ -void QSpatialAudioEngine::setDistanceScale(float scale) -{ - // multiply with 100, to get the conversion to meters that resonance audio uses - scale /= 100.f; - if (scale <= 0.0f) { - qWarning() << "QSpatialAudioEngine: Invalid distance scale."; - return; - } - if (scale == d->distanceScale) - return; - d->distanceScale = scale; - emit distanceScaleChanged(); -} - -float QSpatialAudioEngine::distanceScale() const -{ - return d->distanceScale*100.f; -} - - -/*! \class QSpatialAudioSound - \internal - */ - -void QSpatialAudioSound::load() -{ - decoder.reset(new QAudioDecoder); - buffers.clear(); - currentBuffer = 0; - bufPos = 0; - m_playing = false; - m_loading = true; - auto *ep = QSpatialAudioEnginePrivate::get(engine); - QAudioFormat f = ep->format; - f.setSampleFormat(QAudioFormat::Float); - f.setChannelConfig(nchannels == 2 ? QAudioFormat::ChannelConfigStereo : QAudioFormat::ChannelConfigMono); - decoder->setAudioFormat(f); - decoder->setSource(url); - - connect(decoder.get(), &QAudioDecoder::bufferReady, this, &QSpatialAudioSound::bufferReady); - connect(decoder.get(), &QAudioDecoder::finished, this, &QSpatialAudioSound::finished); - decoder->start(); -} - -void QSpatialAudioSound::getBuffer(float *buf, int nframes, int channels) -{ - Q_ASSERT(channels == nchannels); - QMutexLocker l(&mutex); - if (!m_playing || currentBuffer >= buffers.size()) { - memset(buf, 0, nframes*sizeof(float)); - } else { - int frames = nframes; - float *ff = buf; - while (frames) { - const QAudioBuffer &b = buffers.at(currentBuffer); -// qDebug() << s << b.format().sampleRate() << b.format().channelCount() << b.format().sampleFormat(); - auto *f = b.constData<float>() + bufPos*nchannels; - int toCopy = qMin(b.frameCount() - bufPos, frames); - memcpy(ff, f, toCopy*sizeof(float)*nchannels); - ff += toCopy*nchannels; - frames -= toCopy; - bufPos += toCopy; - Q_ASSERT(bufPos <= b.frameCount()); - if (bufPos == b.frameCount()) { - ++currentBuffer; - bufPos = 0; - } - if (!m_loading) { - if (currentBuffer == buffers.size()) { - currentBuffer = 0; - ++m_currentLoop; - } - if (m_loops > 0 && m_currentLoop >= m_loops) { - m_playing = false; - m_currentLoop = 0; - } - } - } - Q_ASSERT(ff - buf == channels*nframes); - } -} - -void QSpatialAudioSound::bufferReady() -{ - QMutexLocker l(&mutex); - auto b = decoder->read(); -// qDebug() << "read buffer" << b.format() << b.startTime() << b.duration(); - buffers.append(b); - if (m_autoPlay) - m_playing = true; -} - -void QSpatialAudioSound::finished() -{ -// qDebug() << "finished"; - m_loading = false; -} - -QT_END_NAMESPACE - -#include "moc_qspatialaudioengine.cpp" -#include "qspatialaudioengine.moc" diff --git a/src/multimedia/spatial/qspatialaudioengine.h b/src/multimedia/spatial/qspatialaudioengine.h deleted file mode 100644 index f67ce5726..000000000 --- a/src/multimedia/spatial/qspatialaudioengine.h +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Spatial Audio module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL-NOGPL2$ -** 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 3 or (at your option) 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.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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSPATIALAUDIOENGINE_H -#define QSPATIALAUDIOENGINE_H - -#include <QtMultimedia/qtmultimediaglobal.h> -#include <QtCore/qobject.h> - -QT_BEGIN_NAMESPACE - -class QSpatialAudioEnginePrivate; -class QAudioDevice; - -class Q_MULTIMEDIA_EXPORT QSpatialAudioEngine : public QObject -{ - Q_OBJECT - Q_PROPERTY(OutputMode outputMode READ outputMode WRITE setOutputMode NOTIFY outputModeChanged) - Q_PROPERTY(QAudioDevice outputDevice READ outputDevice WRITE setOutputDevice NOTIFY outputDeviceChanged) - Q_PROPERTY(float masterVolume READ masterVolume WRITE setMasterVolume NOTIFY masterVolumeChanged) - Q_PROPERTY(bool paused READ paused WRITE setPaused NOTIFY pausedChanged) - Q_PROPERTY(float distanceScale READ distanceScale WRITE setDistanceScale NOTIFY distanceScaleChanged) -public: - explicit QSpatialAudioEngine(QObject *parent = nullptr, int sampleRate = 44100); - ~QSpatialAudioEngine(); - - enum OutputMode { - Normal, - Headphone - }; - Q_ENUM(OutputMode) - - void setOutputMode(OutputMode mode); - OutputMode outputMode() const; - - int sampleRate() const; - - void setOutputDevice(const QAudioDevice &device); - QAudioDevice outputDevice() const; - - void setMasterVolume(float volume); - float masterVolume() const; - - void start(); - void stop(); - - void setPaused(bool paused); - bool paused() const; - - void setRoomEffectsEnabled(bool enabled); - bool roomEffectsEnabled() const; - - static constexpr float DistanceScaleCentimeter = 1.f; - static constexpr float DistanceScaleMeter = 100.f; - - void setDistanceScale(float scale); - float distanceScale() const; - -Q_SIGNALS: - void outputModeChanged(); - void outputDeviceChanged(); - void masterVolumeChanged(); - void pausedChanged(); - void distanceScaleChanged(); - -public Q_SLOTS: - void pause() { setPaused(true); } - void resume() { setPaused(false); } - -private: - friend class QSpatialAudioEnginePrivate; - QSpatialAudioEnginePrivate *d; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/multimedia/spatial/qspatialaudioengine_p.h b/src/multimedia/spatial/qspatialaudioengine_p.h deleted file mode 100644 index 3163f0c86..000000000 --- a/src/multimedia/spatial/qspatialaudioengine_p.h +++ /dev/null @@ -1,179 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Spatial Audio module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL-NOGPL2$ -** 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 3 or (at your option) 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.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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSPATIALAUDIOENGINE_P_H -#define QSPATIALAUDIOENGINE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <qspatialaudioengine.h> -#include <qaudiodevice.h> -#include <qaudiodecoder.h> -#include <qthread.h> -#include <qmutex.h> -#include <qurl.h> -#include <qaudiobuffer.h> -#include <qvector3d.h> - -namespace vraudio { -class ResonanceAudioApi; -} - -QT_BEGIN_NAMESPACE - -class QSpatialAudioSoundSource; -class QSpatialAudioStereoSource; -class QAudioSink; -class QAudioOutputStream; -class QAmbisonicDecoder; -class QAudioDecoder; -class QSpatialAudioRoom; -class QSpatialAudioListener; - -class QSpatialAudioEnginePrivate -{ -public: - static QSpatialAudioEnginePrivate *get(QSpatialAudioEngine *engine) { return engine ? engine->d : nullptr; } - - static constexpr int bufferSize = 128; - - QSpatialAudioEnginePrivate(); - ~QSpatialAudioEnginePrivate(); - vraudio::ResonanceAudioApi *api = nullptr; - int sampleRate = 44100; - float masterVolume = 1.; - QSpatialAudioEngine::OutputMode outputMode = QSpatialAudioEngine::Normal; - bool roomEffectsEnabled = true; - - // Resonance Audio uses meters internally, while Qt Quick 3D and our API uses cm by default. - // To make things independent from the scale setting, we store all distances in meters internally - // and convert in the setters and getters. - float distanceScale = 0.01f; - - QMutex mutex; - QAudioFormat format; - QAudioDevice device; - QAtomicInteger<bool> paused = false; - - QThread audioThread; - std::unique_ptr<QAudioOutputStream> outputStream; - std::unique_ptr<QAmbisonicDecoder> ambisonicDecoder; - - QSpatialAudioListener *listener = nullptr; - QList<QSpatialAudioSoundSource *> sources; - QList<QSpatialAudioStereoSource *> stereoSources; - QList<QSpatialAudioRoom *> rooms; - mutable bool listenerPositionDirty = true; - QSpatialAudioRoom *currentRoom = nullptr; - - void addSpatialSound(QSpatialAudioSoundSource *sound); - void removeSpatialSound(QSpatialAudioSoundSource *sound); - void addStereoSound(QSpatialAudioStereoSource *sound); - void removeStereoSound(QSpatialAudioStereoSource *sound); - - void addRoom(QSpatialAudioRoom *room); - void removeRoom(QSpatialAudioRoom *room); - void updateRooms(); - - QVector3D listenerPosition() const; -}; - -class QSpatialAudioSound : public QObject -{ -public: - QSpatialAudioSound(QObject *parent, int nchannels = 2) - : QObject(parent) - , nchannels(nchannels) - {} - - template<typename T> - static QSpatialAudioSound *get(T *soundSource) { return soundSource ? soundSource->d : nullptr; } - - - QUrl url; - float volume = 1.; - int nchannels = 2; - std::unique_ptr<QAudioDecoder> decoder; - QSpatialAudioEngine *engine = nullptr; - - QMutex mutex; - int currentBuffer = 0; - int bufPos = 0; - int m_currentLoop = 0; - QList<QAudioBuffer> buffers; - int sourceId = -1; // kInvalidSourceId - - QAtomicInteger<bool> m_autoPlay = true; - QAtomicInteger<bool> m_playing = false; - QAtomicInt m_loops = 1; - bool m_loading = false; - - void play() { - m_playing = true; - } - void pause() { - m_playing = false; - } - void stop() { - QMutexLocker locker(&mutex); - m_playing = false; - currentBuffer = 0; - bufPos = 0; - m_currentLoop = 0; - } - - void load(); - void getBuffer(float *buf, int frames, int channels); - -private Q_SLOTS: - void bufferReady(); - void finished(); - -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/multimedia/spatial/qspatialaudiolistener.cpp b/src/multimedia/spatial/qspatialaudiolistener.cpp deleted file mode 100644 index c93e7a1e5..000000000 --- a/src/multimedia/spatial/qspatialaudiolistener.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Spatial Audio module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL-NOGPL2$ -** 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 3 or (at your option) 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.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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "qspatialaudiolistener.h" -#include "qspatialaudioengine_p.h" -#include "api/resonance_audio_api.h" -#include <qaudiosink.h> -#include <qurl.h> -#include <qdebug.h> -#include <qaudiodecoder.h> - -QT_BEGIN_NAMESPACE - -class QSpatialAudioListenerPrivate -{ -public: - QSpatialAudioEngine *engine = nullptr; - QVector3D pos; - QQuaternion rotation; -}; - -/*! - \class QSpatialAudioListener - \inmodule QtMultimedia - \ingroup multimedia_spatialaudio - - \brief Defines the position and orientation of the person listening to a sound field - defined by QSpatialAudioEngine. - - A QSpatialAudioEngine can have exactly one listener that defines the position and orientation - of the person listening to the sound field. - */ - -/*! - Creates a listener for the spatial audio engine for \a engine. - */ -QSpatialAudioListener::QSpatialAudioListener(QSpatialAudioEngine *engine) - : d(new QSpatialAudioListenerPrivate) -{ - setEngine(engine); -} - -/*! - Destroys the listener. - */ -QSpatialAudioListener::~QSpatialAudioListener() -{ - delete d; -} - -/*! - Sets the listener's position in 3D space to \a pos. Units are in centimeters - by default. - - \sa QSpatialAudioEngine::distanceScale - */ -void QSpatialAudioListener::setPosition(QVector3D pos) -{ - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - pos *= ep->distanceScale; - if (d->pos == pos) - return; - - d->pos = pos; - if (ep && ep->api) { - ep->api->SetHeadPosition(pos.x(), pos.y(), pos.z()); - ep->listenerPositionDirty = true; - } -} - -/*! - Returns the current position of the listener. - */ -QVector3D QSpatialAudioListener::position() const -{ - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - return d->pos/ep->distanceScale; -} - -/*! - Sets the listener's orientation in 3D space to \a q. - */ -void QSpatialAudioListener::setRotation(const QQuaternion &q) -{ - d->rotation = q; - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - if (ep && ep->api) - ep->api->SetHeadRotation(d->rotation.x(), d->rotation.y(), d->rotation.z(), d->rotation.scalar()); -} - -/*! - Returns the listener's orientation in 3D space. - */ -QQuaternion QSpatialAudioListener::rotation() const -{ - return d->rotation; -} - -/*! - \internal - */ -void QSpatialAudioListener::setEngine(QSpatialAudioEngine *engine) -{ - if (d->engine) { - auto *ed = QSpatialAudioEnginePrivate::get(d->engine); - ed->listener = nullptr; - } - d->engine = engine; - if (d->engine) { - auto *ed = QSpatialAudioEnginePrivate::get(d->engine); - if (ed->listener) { - qWarning() << "Ignoring attempt to add a second listener to the spatial audio engine."; - d->engine = nullptr; - return; - } - ed->listener = this; - } -} - -/*! - Returns the engine associated with this listener. - */ -QSpatialAudioEngine *QSpatialAudioListener::engine() const -{ - return d->engine; -} - -QT_END_NAMESPACE diff --git a/src/multimedia/spatial/qspatialaudiolistener.h b/src/multimedia/spatial/qspatialaudiolistener.h deleted file mode 100644 index 715223521..000000000 --- a/src/multimedia/spatial/qspatialaudiolistener.h +++ /dev/null @@ -1,73 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Spatial Audio module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL-NOGPL2$ -** 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 3 or (at your option) 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.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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef QSPATIALAUDIOLISTENER_H -#define QSPATIALAUDIOLISTENER_H - -#include <QtMultimedia/qtmultimediaglobal.h> -#include <QtCore/QObject> -#include <QtMultimedia/qaudioformat.h> -#include <QtGui/qvector3d.h> -#include <QtGui/qquaternion.h> - -QT_BEGIN_NAMESPACE - -class QSpatialAudioEngine; - -class QSpatialAudioListenerPrivate; -class Q_MULTIMEDIA_EXPORT QSpatialAudioListener : public QObject -{ -public: - explicit QSpatialAudioListener(QSpatialAudioEngine *engine); - ~QSpatialAudioListener(); - - QAudioFormat format() const; - - void setPosition(QVector3D pos); - QVector3D position() const; - void setRotation(const QQuaternion &q); - QQuaternion rotation() const; - - QSpatialAudioEngine *engine() const; - -private: - void setEngine(QSpatialAudioEngine *engine); - QSpatialAudioListenerPrivate *d = nullptr; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/multimedia/spatial/qspatialaudioroom.cpp b/src/multimedia/spatial/qspatialaudioroom.cpp deleted file mode 100644 index 9e091c43f..000000000 --- a/src/multimedia/spatial/qspatialaudioroom.cpp +++ /dev/null @@ -1,418 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Spatial Audio module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL-NOGPL2$ -** 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 3 or (at your option) 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.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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include <qspatialaudioroom_p.h> - -QT_BEGIN_NAMESPACE - -namespace { -inline QVector3D toVector(const float *f) -{ - return QVector3D(f[0], f[1], f[2]); -} - -inline void toFloats(const QVector3D &v, float *f) -{ - f[0] = v.x(); - f[1] = v.y(); - f[2] = v.z(); -} - -inline QQuaternion toQuaternion(const float *f) -{ - // resonance audio puts the scalar component last - return QQuaternion(f[3], f[0], f[1], f[2]); -} - -inline void toFloats(const QQuaternion &q, float *f) -{ - f[0] = q.x(); - f[1] = q.y(); - f[2] = q.z(); - f[3] = q.scalar(); -} - -// Default values for occlusion and dampening of different wall materials. -// These values are used as defaults if a wall is only defined by a material -// and define how sound passes through the wall. -// We define both occlusion and dampening constants to be able to tune the -// sound. Dampening only reduces the level of the sound without affecting its -// tone, while occlusion will dampen higher frequencies more than lower ones -struct { - float occlusion; - float dampening; -} occlusionAndDampening[] = { - { 0.f, 1.f }, // Transparent, - { 0.f, .1f }, // AcousticCeilingTiles, - { 2.f, .4f }, // BrickBare, - { 2.f, .4f }, // BrickPainted, - { 4.f, 1.f }, // ConcreteBlockCoarse, - { 4.f, 1.f }, // ConcreteBlockPainted, - { .7f, .7f }, // CurtainHeavy, - { .5f, .5f }, // FiberGlassInsulation, - { .2f, .3f }, // GlassThin, - { .5f, .2f }, // GlassThick, - { 7.f, 1.f }, // Grass, - { 4.f, 1.f }, // LinoleumOnConcrete, - { 4.f, 1.f }, // Marble, - { 0.f, .2f }, // Metal, - { 4.f, 1.f }, // ParquetOnConcrete, - { 2.f, .4f }, // PlasterRough, - { 2.f, .4f }, // PlasterSmooth, - { 1.5f, .2f }, // PlywoodPanel, - { 4.f, 1.f }, // PolishedConcreteOrTile, - { 4.f, 1.f }, // Sheetrock, - { 4.f, 1.f }, // WaterOrIceSurface, - { 1.f, .3f }, // WoodCeiling, - { 1.f, .3f }, // WoodPanel, - { 0.f, .0f }, // UniformMaterial, -}; - -} - -float QSpatialAudioRoomPrivate::wallOcclusion(QSpatialAudioRoom::Wall wall) const -{ - return m_wallOcclusion[wall] < 0 ? occlusionAndDampening[roomProperties.material_names[wall]].occlusion : m_wallOcclusion[wall]; -} - -float QSpatialAudioRoomPrivate::wallDampening(QSpatialAudioRoom::Wall wall) const -{ - return m_wallDampening[wall] < 0 ? occlusionAndDampening[roomProperties.material_names[wall]].dampening : m_wallDampening[wall]; -} - -void QSpatialAudioRoomPrivate::update() -{ - if (!dirty) - return; - reflections = vraudio::ComputeReflectionProperties(roomProperties); - reverb = vraudio::ComputeReverbProperties(roomProperties); - dirty = false; -} - - -/*! - \class QSpatialAudioRoom - \inmodule QtMultimedia - \ingroup multimedia_spatialaudio - - Defines a room for the spatial audio engine. - - If the listener is inside a room, first order sound reflections and reverb - matching the rooms properties will get applied to the sound field. - - A room is always square and defined by it's center position, it's orientation and dimensions. - Each of the 6 walls of the room can be made of different materials that will contribute - to the computed reflections and reverb that the listener will experience while being inside - the room. - - If multiple rooms cover the same position, the engine will use the room with the smallest - volume. - */ - -/*! - Constructs a QSpatialAudioRoom for \a engine. - */ -QSpatialAudioRoom::QSpatialAudioRoom(QSpatialAudioEngine *engine) - : d(new QSpatialAudioRoomPrivate) -{ - Q_ASSERT(engine); - d->engine = engine; - auto *ep = QSpatialAudioEnginePrivate::get(engine); - ep->addRoom(this); -} - -/*! - Destroys the room. - */ -QSpatialAudioRoom::~QSpatialAudioRoom() -{ - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - if (ep) - ep->removeRoom(this); - delete d; -} - -/*! - \enum QSpatialAudioRoom::Material - - Defines different materials that can be applied to the different walls of the room. - - \value Transparent The side of the room is open and won't contribute to reflections or reverb. - \value AcousticCeilingTiles Acoustic tiles that suppress most reflections and reverb. - \value BrickBare Bare brick wall. - \value BrickPainted Painted brick wall. - \value ConcreteBlockCoarse Raw concrete wall - \value ConcreteBlockPainted Painted concrete wall - \value CurtainHeavy Heavy curtain. Will mostly reflect low frequencies - \value FiberGlassInsulation Fiber glass insulation. Only reflects very low frequencies - \value GlassThin Thin glass wall - \value GlassThick Thick glass wall - \value Grass Grass - \value LinoleumOnConcrete Linoleum floor - \value Marble Marble floor - \value Metal Metal - \value ParquetOnConcrete Parquet wooden floor on concrete - \value PlasterRough Rough plaster - \value PlasterSmooth Smooth plaster - \value PlywoodPanel Plywodden panel - \value PolishedConcreteOrTile Polished concrete or tiles - \value Sheetrock Rock - \value WaterOrIceSurface Water or ice - \value WoodCeiling Wooden ceiling - \value WoodPanel Wooden panel - \value UniformMaterial Artificial material giving uniform reflections on all frequencies -*/ - -/*! - \enum QSpatialAudioRoom::Wall - - An enum defining the 6 walls of the room - - \value LeftWall Left wall (negative x) - \value RightWall Right wall (positive x) - \value BackWall Back wall (negative y) - \value FrontWall Front wall (positive y) - \value Floor Bottom wall (negative z) - \value Ceiling Top wall (positive z) -*/ - - -/*! - \property QSpatialAudioRoom::position - - Defines the position of the center of the room in 3D space. Units are in centimeters - by default. - - \sa dimensions, QSpatialAudioEngine::distanceScale - */ -void QSpatialAudioRoom::setPosition(QVector3D pos) -{ - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - pos *= ep->distanceScale; - if (toVector(d->roomProperties.position) == pos) - return; - toFloats(pos, d->roomProperties.position); - d->dirty = true; - emit positionChanged(); -} - -QVector3D QSpatialAudioRoom::position() const -{ - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - auto pos = toVector(d->roomProperties.position); - pos /= ep->distanceScale; - return pos; -} - -/*! - \property QSpatialAudioRoom::dimensions - - Defines the dimensions of the room in 3D space. Units are in centimeters - by default. - - \sa position, QSpatialAudioEngine::distanceScale - */ -void QSpatialAudioRoom::setDimensions(QVector3D dim) -{ - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - dim *= ep->distanceScale; - if (toVector(d->roomProperties.dimensions) == dim) - return; - toFloats(dim, d->roomProperties.dimensions); - d->dirty = true; - emit dimensionsChanged(); -} - -QVector3D QSpatialAudioRoom::dimensions() const -{ - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - auto dim = toVector(d->roomProperties.dimensions); - dim /= ep->distanceScale; - return dim; -} - -/*! - \property QSpatialAudioRoom::rotation - - Defines the orientation of the room in 3D space. - */ -void QSpatialAudioRoom::setRotation(const QQuaternion &q) -{ - if (toQuaternion(d->roomProperties.rotation) == q) - return; - toFloats(q, d->roomProperties.rotation); - d->dirty = true; - emit rotationChanged(); -} - -QQuaternion QSpatialAudioRoom::rotation() const -{ - return toQuaternion(d->roomProperties.rotation); -} - -/*! - Sets \a wall to \a material. - - Different wall materials have different reflection and reverb properties - that influence the sound of the room. - - \sa wallMaterial(), Material, QSpatialAudioRoom::Wall - */ -void QSpatialAudioRoom::setWallMaterial(Wall wall, Material material) -{ - static_assert(vraudio::kUniform == int(UniformMaterial)); - static_assert(vraudio::kTransparent == int(Transparent)); - - if (d->roomProperties.material_names[int(wall)] == int(material)) - return; - d->roomProperties.material_names[int(wall)] = vraudio::MaterialName(int(material)); - d->dirty = true; - emit wallsChanged(); -} - -/*! - returns the material being used for \a wall. - - \sa setWallMaterial(), Material, QSpatialAudioRoom::Wall - */ -QSpatialAudioRoom::Material QSpatialAudioRoom::wallMaterial(Wall wall) const -{ - return Material(d->roomProperties.material_names[int(wall)]); -} - -/*! - \property QSpatialAudioRoom::reflectionGain - - A gain factor for reflections generated in this room. A value - from 0 to 1 will dampen reflections, while a value larger than 1 - will apply a gain to reflections, making them louder. - - The default is 1, a factor of 0 disables reflections. Negative - values are mapped to 0. - */ -void QSpatialAudioRoom::setReflectionGain(float factor) -{ - if (factor < 0.) - factor = 0.; - if (d->roomProperties.reflection_scalar == factor) - return; - d->roomProperties.reflection_scalar = factor; - d->dirty = true; - reflectionGainChanged(); -} - -float QSpatialAudioRoom::reflectionGain() const -{ - return d->roomProperties.reflection_scalar; -} - -/*! - \property QSpatialAudioRoom::reverbGain - - A gain factor for reverb generated in this room. A value - from 0 to 1 will dampen reverb, while a value larger than 1 - will apply a gain to the reverb, making it louder. - - The default is 1, a factor of 0 disables reverb. Negative - values are mapped to 0. - */ -void QSpatialAudioRoom::setReverbGain(float factor) -{ - if (factor < 0) - factor = 0; - if (d->roomProperties.reverb_gain == factor) - return; - d->roomProperties.reverb_gain = factor; - d->dirty = true; - reverbGainChanged(); -} - -float QSpatialAudioRoom::reverbGain() const -{ - return d->roomProperties.reverb_gain; -} - -/*! - \property QSpatialAudioRoom::reverbTime - - A factor to be applies to all reverb timings generated for this room. - Larger values will lead to longer reverb timings, making the room sound - larger. - - The default is 1. Negative values are mapped to 0. - */ -void QSpatialAudioRoom::setReverbTime(float factor) -{ - if (factor < 0) - factor = 0; - if (d->roomProperties.reverb_time == factor) - return; - d->roomProperties.reverb_time = factor; - d->dirty = true; - reverbTimeChanged(); -} - -float QSpatialAudioRoom::reverbTime() const -{ - return d->roomProperties.reverb_time; -} - -/*! - \property QSpatialAudioRoom::reverbBrightness - - A brightness factor to be applied to the generated reverb. - A positive value will increase reverb for higher frequencies and - dampen lower frequencies, a negative value does the reverse. - - The default is 0. - */ -void QSpatialAudioRoom::setReverbBrightness(float factor) -{ - if (d->roomProperties.reverb_brightness == factor) - return; - d->roomProperties.reverb_brightness = factor; - d->dirty = true; - reverbBrightnessChanged(); -} - -float QSpatialAudioRoom::reverbBrightness() const -{ - return d->roomProperties.reverb_brightness; -} - -QT_END_NAMESPACE - -#include "moc_qspatialaudioroom.cpp" diff --git a/src/multimedia/spatial/qspatialaudioroom.h b/src/multimedia/spatial/qspatialaudioroom.h deleted file mode 100644 index a3bba8930..000000000 --- a/src/multimedia/spatial/qspatialaudioroom.h +++ /dev/null @@ -1,141 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Spatial Audio module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL-NOGPL2$ -** 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 3 or (at your option) 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.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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSPATIALAUDIOROOM_H -#define QSPATIALAUDIOROOM_H - -#include <QtMultimedia/qtmultimediaglobal.h> -#include <QtCore/qobject.h> -#include <QtGui/qvector3d.h> - -QT_BEGIN_NAMESPACE - -class QSpatialAudioEngine; -class QSpatialAudioRoomPrivate; - -class Q_MULTIMEDIA_EXPORT QSpatialAudioRoom : public QObject -{ - Q_OBJECT - Q_PROPERTY(QVector3D position READ position WRITE setPosition NOTIFY positionChanged) - Q_PROPERTY(QVector3D dimensions READ dimensions WRITE setDimensions NOTIFY dimensionsChanged) - Q_PROPERTY(QQuaternion rotation READ rotation WRITE setRotation NOTIFY rotationChanged) - Q_PROPERTY(float reflectionGain READ reflectionGain WRITE setReflectionGain NOTIFY reflectionGainChanged) - Q_PROPERTY(float reverbGain READ reverbGain WRITE setReverbGain NOTIFY reverbGainChanged) - Q_PROPERTY(float reverbTime READ reverbTime WRITE setReverbTime NOTIFY reverbTimeChanged) - Q_PROPERTY(float reverbBrightness READ reverbBrightness WRITE setReverbBrightness NOTIFY reverbBrightnessChanged) -public: - QSpatialAudioRoom(QSpatialAudioEngine *engine); - ~QSpatialAudioRoom(); - - enum Material { - Transparent, - AcousticCeilingTiles, - BrickBare, - BrickPainted, - ConcreteBlockCoarse, - ConcreteBlockPainted, - CurtainHeavy, - FiberGlassInsulation, - GlassThin, - GlassThick, - Grass, - LinoleumOnConcrete, - Marble, - Metal, - ParquetOnConcrete, - PlasterRough, - PlasterSmooth, - PlywoodPanel, - PolishedConcreteOrTile, - Sheetrock, - WaterOrIceSurface, - WoodCeiling, - WoodPanel, - UniformMaterial, - }; - - enum Wall { - LeftWall, - RightWall, - Floor, - Ceiling, - FrontWall, - BackWall - }; - - void setPosition(QVector3D pos); - QVector3D position() const; - - void setDimensions(QVector3D pos); - QVector3D dimensions() const; - - void setRotation(const QQuaternion &q); - QQuaternion rotation() const; - - void setWallMaterial(Wall wall, Material material); - Material wallMaterial(Wall wall) const; - - void setReflectionGain(float factor); - float reflectionGain() const; - - void setReverbGain(float factor); - float reverbGain() const; - - void setReverbTime(float factor); - float reverbTime() const; - - void setReverbBrightness(float factor); - float reverbBrightness() const; - -Q_SIGNALS: - void positionChanged(); - void dimensionsChanged(); - void rotationChanged(); - void wallsChanged(); - void reflectionGainChanged(); - void reverbGainChanged(); - void reverbTimeChanged(); - void reverbBrightnessChanged(); - -private: - friend class QSpatialAudioRoomPrivate; - QSpatialAudioRoomPrivate *d; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/multimedia/spatial/qspatialaudioroom_p.h b/src/multimedia/spatial/qspatialaudioroom_p.h deleted file mode 100644 index 668570eef..000000000 --- a/src/multimedia/spatial/qspatialaudioroom_p.h +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Spatial Audio module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL-NOGPL2$ -** 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 3 or (at your option) 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.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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef QSPATIALAUDIOROOM_P_H -#define QSPATIALAUDIOROOM_P_H - -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <qspatialaudioroom.h> -#include <qspatialaudioengine_p.h> -#include <QtGui/qquaternion.h> - -#include <resonance_audio_api_extensions.h> -#include "platforms/common/room_effects_utils.h" -#include "platforms/common/room_properties.h" - -QT_BEGIN_NAMESPACE - -class QSpatialAudioRoomPrivate -{ -public: - static QSpatialAudioRoomPrivate *get(const QSpatialAudioRoom *r) { return r->d; } - - QSpatialAudioEngine *engine = nullptr; - vraudio::RoomProperties roomProperties; - bool dirty = true; - - vraudio::ReverbProperties reverb; - vraudio::ReflectionProperties reflections; - - float m_wallOcclusion[6] = { -1.f, -1.f, -1.f, -1.f, -1.f, -1.f }; - float m_wallDampening[6] = { -1.f, -1.f, -1.f, -1.f, -1.f, -1.f }; - - float wallOcclusion(QSpatialAudioRoom::Wall wall) const; - float wallDampening(QSpatialAudioRoom::Wall wall) const; - - void update(); -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/multimedia/spatial/qspatialaudiosoundsource.cpp b/src/multimedia/spatial/qspatialaudiosoundsource.cpp deleted file mode 100644 index c86e6351b..000000000 --- a/src/multimedia/spatial/qspatialaudiosoundsource.cpp +++ /dev/null @@ -1,617 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Spatial Audio module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL-NOGPL2$ -** 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 3 or (at your option) 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.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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "qspatialaudioroom_p.h" -#include "qspatialaudiosoundsource_p.h" -#include "qspatialaudiolistener.h" -#include "qspatialaudioengine_p.h" -#include "qspatialaudioroom.h" -#include "api/resonance_audio_api.h" -#include <qaudiosink.h> -#include <qurl.h> -#include <qdebug.h> -#include <qaudiodecoder.h> - -QT_BEGIN_NAMESPACE - -/*! - \class QSpatialAudioSoundSource - \inmodule QtMultimedia - \ingroup multimedia_spatialaudio - - \brief A sound object in 3D space. - - QSpatialAudioSoundSource represents an audible object in 3D space. You can define - it's position and orientation in space, set the sound it is playing and define a - volume for the object. - - The object can have different attenuation behavior, emit sound mainly in one direction - or spherically, and behave as if occluded by some other object. - */ - -/*! - Creates a spatial sound source for \a engine. The object can be placed in - 3D space and will be louder the closer to the listener it is. - */ -QSpatialAudioSoundSource::QSpatialAudioSoundSource(QSpatialAudioEngine *engine) - : d(new QSpatialAudioSoundSourcePrivate(this)) -{ - setEngine(engine); -} - -/*! - Destroys the sound source. - */ -QSpatialAudioSoundSource::~QSpatialAudioSoundSource() -{ - setEngine(nullptr); -} - -/*! - \property QSpatialAudioSoundSource::position - - Defines the position of the sound source in 3D space. Units are in centimeters - by default. - - \sa QSpatialAudioEngine::distanceScale - */ -void QSpatialAudioSoundSource::setPosition(QVector3D pos) -{ - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - pos *= ep->distanceScale; - d->pos = pos; - if (ep) - ep->api->SetSourcePosition(d->sourceId, pos.x(), pos.y(), pos.z()); - d->updateRoomEffects(); - emit positionChanged(); -} - -QVector3D QSpatialAudioSoundSource::position() const -{ - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - return d->pos/ep->distanceScale; -} - -/*! - \property QSpatialAudioSoundSource::rotation - - Defines the orientation of the sound source in 3D space. - */ -void QSpatialAudioSoundSource::setRotation(const QQuaternion &q) -{ - d->rotation = q; - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - if (ep) - ep->api->SetSourceRotation(d->sourceId, q.x(), q.y(), q.z(), q.scalar()); - emit rotationChanged(); -} - -QQuaternion QSpatialAudioSoundSource::rotation() const -{ - return d->rotation; -} - -/*! - \property QSpatialAudioSoundSource::volume - - Defines the volume of the sound. - - Values between 0 and 1 will attenuate the sound, while values above 1 - provide an additional gain boost. - */ -void QSpatialAudioSoundSource::setVolume(float volume) -{ - if (d->volume == volume) - return; - d->volume = volume; - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - if (ep) - ep->api->SetSourceVolume(d->sourceId, d->volume*d->wallDampening); - emit volumeChanged(); -} - -float QSpatialAudioSoundSource::volume() const -{ - return d->volume; -} - -/*! - \enum QSpatialAudioSoundSource::DistanceModel - - Defines how the volume of the sound scales with distance to the listener. - - \value DistanceModel_Logarithmic Volume decreases logarithmically with distance. - \value DistanceModel_Linear Volume decreases linearly with distance. - \value DistanceModel_ManualAttenutation Attenuation is defined manually using the - \l manualAttenuation property. -*/ - -/*! - \property QSpatialAudioSoundSource::distanceModel - - Defines distance model for this sound source. The volume starts scaling down - from \l size to \l distanceCutoff. The volume is constant for distances smaller - than size and zero for distances larger than the cutoff distance. - - \sa QSpatialAudioSoundSource::DistanceModel - */ -void QSpatialAudioSoundSource::setDistanceModel(DistanceModel model) -{ - if (d->distanceModel == model) - return; - d->distanceModel = model; - - d->updateDistanceModel(); - emit distanceModelChanged(); -} - -void QSpatialAudioSoundSourcePrivate::updateDistanceModel() -{ - if (!engine || sourceId < 0) - return; - auto *ep = QSpatialAudioEnginePrivate::get(engine); - - vraudio::DistanceRolloffModel dm = vraudio::kLogarithmic; - switch (distanceModel) { - case QSpatialAudioSoundSource::DistanceModel_Linear: - dm = vraudio::kLinear; - break; - case QSpatialAudioSoundSource::DistanceModel_ManualAttenutation: - dm = vraudio::kNone; - break; - default: - break; - } - - ep->api->SetSourceDistanceModel(sourceId, dm, size, distanceCutoff); -} - -void QSpatialAudioSoundSourcePrivate::updateRoomEffects() -{ - if (!engine || sourceId < 0) - return; - auto *ep = QSpatialAudioEnginePrivate::get(engine); - if (!ep->currentRoom) - return; - auto *rp = QSpatialAudioRoomPrivate::get(ep->currentRoom); - - QVector3D roomDim2 = ep->currentRoom->dimensions()/2.; - QVector3D roomPos = ep->currentRoom->position(); - QQuaternion roomRot = ep->currentRoom->rotation(); - QVector3D dist = pos - roomPos; - // transform into room coordinates - dist = roomRot.rotatedVector(dist); - if (qAbs(dist.x()) <= roomDim2.x() && - qAbs(dist.y()) <= roomDim2.y() && - qAbs(dist.z()) <= roomDim2.z()) { - // Source is inside room, apply - ep->api->SetSourceRoomEffectsGain(sourceId, 1); - wallDampening = 1.; - wallOcclusion = 0.; - } else { - // ### calculate room occlusion and dampening - // This is a bit of heuristics on top of the heuristic dampening/occlusion numbers for walls - // - // We basically cast a ray from the listener through the walls. If walls have different characteristics - // and we get close to a corner, we try to use some averaging to avoid abrupt changes - auto relativeListenerPos = ep->listenerPosition() - roomPos; - relativeListenerPos = roomRot.rotatedVector(relativeListenerPos); - - auto direction = dist.normalized(); - enum { - X, Y, Z - }; - // Very rough approximation, use the size of the source plus twice the size of our head. - // One could probably improve upon this. - const float transitionDistance = size + 0.4; - QSpatialAudioRoom::Wall walls[3]; - walls[X] = direction.x() > 0 ? QSpatialAudioRoom::RightWall : QSpatialAudioRoom::LeftWall; - walls[Y] = direction.y() > 0 ? QSpatialAudioRoom::FrontWall : QSpatialAudioRoom::BackWall; - walls[Z] = direction.z() > 0 ? QSpatialAudioRoom::Ceiling : QSpatialAudioRoom::Floor; - float factors[3] = { 0., 0., 0. }; - bool foundWall = false; - if (direction.x() != 0) { - float sign = direction.x() > 0 ? 1.f : -1.f; - float dx = sign * roomDim2.x() - relativeListenerPos.x(); - QVector3D intersection = relativeListenerPos + direction*dx/direction.x(); - float dy = roomDim2.y() - qAbs(intersection.y()); - float dz = roomDim2.z() - qAbs(intersection.z()); - if (dy > 0 && dz > 0) { -// qDebug() << "Hit with wall X" << walls[0] << dy << dz; - // Ray is hitting this wall - factors[Y] = qMax(0.f, 1.f/3.f - dy/transitionDistance); - factors[Z] = qMax(0.f, 1.f/3.f - dz/transitionDistance); - factors[X] = 1.f - factors[Y] - factors[Z]; - foundWall = true; - } - } - if (!foundWall && direction.y() != 0) { - float sign = direction.y() > 0 ? 1.f : -1.f; - float dy = sign * roomDim2.y() - relativeListenerPos.y(); - QVector3D intersection = relativeListenerPos + direction*dy/direction.y(); - float dx = roomDim2.x() - qAbs(intersection.x()); - float dz = roomDim2.z() - qAbs(intersection.z()); - if (dx > 0 && dz > 0) { - // Ray is hitting this wall -// qDebug() << "Hit with wall Y" << walls[1] << dx << dy; - factors[X] = qMax(0.f, 1.f/3.f - dx/transitionDistance); - factors[Z] = qMax(0.f, 1.f/3.f - dz/transitionDistance); - factors[Y] = 1.f - factors[X] - factors[Z]; - foundWall = true; - } - } - if (!foundWall) { - Q_ASSERT(direction.z() != 0); - float sign = direction.z() > 0 ? 1.f : -1.f; - float dz = sign * roomDim2.z() - relativeListenerPos.z(); - QVector3D intersection = relativeListenerPos + direction*dz/direction.z(); - float dx = roomDim2.x() - qAbs(intersection.x()); - float dy = roomDim2.y() - qAbs(intersection.y()); - if (dx > 0 && dy > 0) { - // Ray is hitting this wall -// qDebug() << "Hit with wall Z" << walls[2]; - factors[X] = qMax(0.f, 1.f/3.f - dx/transitionDistance); - factors[Y] = qMax(0.f, 1.f/3.f - dy/transitionDistance); - factors[Z] = 1.f - factors[X] - factors[Y]; - foundWall = true; - } - } - wallDampening = 0; - wallOcclusion = 0; - for (int i = 0; i < 3; ++i) { - wallDampening += factors[i]*rp->wallDampening(walls[i]); - wallOcclusion += factors[i]*rp->wallOcclusion(walls[i]); - } - -// qDebug() << "intersection with wall" << walls[0] << walls[1] << walls[2] << factors[0] << factors[1] << factors[2] << wallDampening << wallOcclusion; - ep->api->SetSourceRoomEffectsGain(sourceId, 0); - } - ep->api->SetSoundObjectOcclusionIntensity(sourceId, occlusionIntensity + wallOcclusion); - ep->api->SetSourceVolume(sourceId, volume*wallDampening); -} - -QSpatialAudioSoundSource::DistanceModel QSpatialAudioSoundSource::distanceModel() const -{ - return d->distanceModel; -} - -/*! - \property QSpatialAudioSoundSource::size - - Defines the size of the sound source. If the listener is closer to the sound - object than the size, volume will stay constant. The size is also used to for - occlusion calculations, where large sources can be partially occluded by a wall. - */ -void QSpatialAudioSoundSource::setSize(float size) -{ - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - size *= ep->distanceScale; - if (d->size == size) - return; - d->size = size; - - d->updateDistanceModel(); - emit sizeChanged(); -} - -float QSpatialAudioSoundSource::size() const -{ - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - return d->size/ep->distanceScale; -} - -/*! - \property QSpatialAudioSoundSource::distanceCutoff - - Defines a distance beyond which sound coming from the source will cutoff. - If the listener is further away from the sound object than the cutoff - distance it won't be audible anymore. - */ -void QSpatialAudioSoundSource::setDistanceCutoff(float cutoff) -{ - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - cutoff *= ep->distanceScale; - if (d->distanceCutoff == cutoff) - return; - d->distanceCutoff = cutoff; - - d->updateDistanceModel(); - emit distanceCutoffChanged(); -} - -float QSpatialAudioSoundSource::distanceCutoff() const -{ - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - return d->distanceCutoff/ep->distanceScale; -} - -/*! - \property QSpatialAudioSoundSource::manualAttenuation - - Defines a manual attenuation factor if \l distanceModel is set to - QSpatialAudioSoundSource::DistanceModel_ManualAttenutation. - */ -void QSpatialAudioSoundSource::setManualAttenuation(float attenuation) -{ - if (d->manualAttenuation == attenuation) - return; - d->manualAttenuation = attenuation; - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - if (ep) - ep->api->SetSourceDistanceAttenuation(d->sourceId, d->manualAttenuation); - emit manualAttenuationChanged(); -} - -float QSpatialAudioSoundSource::manualAttenuation() const -{ - return d->manualAttenuation; -} - -/*! - \property QSpatialAudioSoundSource::occlusionIntensity - - Defines how much the object is occluded. 0 implies the object is - not occluded at all, 1 implies the sound source is fully occluded by - another object. - - A fully occluded object will still be audible, but especially higher - frequencies will be dampened. In addition, the object will still - participate in generating reverb and reflections in the room. - - Values larger than 1 are possible to further dampen the direct - sound coming from the source. - - The default is 0. - */ -void QSpatialAudioSoundSource::setOcclusionIntensity(float occlusion) -{ - if (d->occlusionIntensity == occlusion) - return; - d->occlusionIntensity = occlusion; - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - if (ep) - ep->api->SetSoundObjectOcclusionIntensity(d->sourceId, d->occlusionIntensity + d->wallOcclusion); - emit occlusionIntensityChanged(); -} - -float QSpatialAudioSoundSource::occlusionIntensity() const -{ - return d->occlusionIntensity; -} - -/*! - \property QSpatialAudioSoundSource::directivity - - Defines the directivity of the sound source. A value of 0 implies that the sound is - emitted equally in all directions, while a value of 1 implies that the source mainly - emits sound in the forward direction. - - Valid values are between 0 and 1, the default is 0. - */ -void QSpatialAudioSoundSource::setDirectivity(float alpha) -{ - alpha = qBound(0., alpha, 1.); - if (alpha == d->directivity) - return; - d->directivity = alpha; - - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - if (ep) - ep->api->SetSoundObjectDirectivity(d->sourceId, d->directivity, d->directivityOrder); - - emit directivityChanged(); -} - -float QSpatialAudioSoundSource::directivity() const -{ - return d->directivity; -} - -/*! - \property QSpatialAudioSoundSource::directivityOrder - - Defines the order of the directivity of the sound source. A higher order - implies a sharper localization of the sound cone. - - The minimum value and default for this property is 1. - */ -void QSpatialAudioSoundSource::setDirectivityOrder(float order) -{ - order = qMax(order, 1.); - if (order == d->directivityOrder) - return; - d->directivityOrder = order; - - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - if (ep) - ep->api->SetSoundObjectDirectivity(d->sourceId, d->directivity, d->directivityOrder); - - emit directivityChanged(); -} - -float QSpatialAudioSoundSource::directivityOrder() const -{ - return d->directivityOrder; -} - -/*! - \property QSpatialAudioSoundSource::nearFieldGain - - Defines the near field gain for the sound source. Valid values are between 0 and 1. - A near field gain of 1 will raise the volume of the sound signal by approx 20 dB for - distances very close to the listener. - */ -void QSpatialAudioSoundSource::setNearFieldGain(float gain) -{ - gain = qBound(0., gain, 1.); - if (gain == d->nearFieldGain) - return; - d->nearFieldGain = gain; - - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - if (ep) - ep->api->SetSoundObjectNearFieldEffectGain(d->sourceId, d->nearFieldGain/9.); - - emit nearFieldGainChanged(); - -} - -float QSpatialAudioSoundSource::nearFieldGain() const -{ - return d->nearFieldGain; -} - -/*! - \property QSpatialAudioSoundSource::source - - The source file for the sound to be played. - */ -void QSpatialAudioSoundSource::setSource(const QUrl &url) -{ - if (d->url == url) - return; - d->url = url; - - d->load(); - emit sourceChanged(); -} - -QUrl QSpatialAudioSoundSource::source() const -{ - return d->url; -} - -/*! - \property QSpatialAudioSoundSource::loops - - Determines how many times the sound is played before the player stops. - Set to QSpatialAudioSoundSource::Infinite to play the current sound in a loop forever. - - The default value is \c 1. - */ -int QSpatialAudioSoundSource::loops() const -{ - return d->m_loops.loadRelaxed(); -} - -void QSpatialAudioSoundSource::setLoops(int loops) -{ - int oldLoops = d->m_loops.fetchAndStoreRelaxed(loops); - if (oldLoops != loops) - emit loopsChanged(); -} - -/*! - \property QSpatialAudioSoundSource::autoPlay - - Determines whether the sound should automatically start playing when a source - gets specified. - - The default value is \c true. - */ -bool QSpatialAudioSoundSource::autoPlay() const -{ - return d->m_autoPlay.loadRelaxed(); -} - -void QSpatialAudioSoundSource::setAutoPlay(bool autoPlay) -{ - bool old = d->m_autoPlay.fetchAndStoreRelaxed(autoPlay); - if (old != autoPlay) - emit autoPlayChanged(); -} - -/*! - Starts playing back the sound. Does nothing if the sound is already playing. - */ -void QSpatialAudioSoundSource::play() -{ - d->play(); -} - -/*! - Pauses sound playback. Calling play() will continue playback. - */ -void QSpatialAudioSoundSource::pause() -{ - d->pause(); -} - -/*! - Stops sound playback and resets the current position and current loop count to 0. - Calling play() will start playback at the beginning of the sound file. - */ -void QSpatialAudioSoundSource::stop() -{ - d->stop(); -} - -/*! - \internal - */ -void QSpatialAudioSoundSource::setEngine(QSpatialAudioEngine *engine) -{ - if (d->engine == engine) - return; - auto *ep = QSpatialAudioEnginePrivate::get(engine); - - if (ep) - ep->removeSpatialSound(this); - d->engine = engine; - - ep = QSpatialAudioEnginePrivate::get(engine); - if (ep) { - ep->addSpatialSound(this); - ep->api->SetSourcePosition(d->sourceId, d->pos.x(), d->pos.y(), d->pos.z()); - ep->api->SetSourceRotation(d->sourceId, d->rotation.x(), d->rotation.y(), d->rotation.z(), d->rotation.scalar()); - ep->api->SetSourceVolume(d->sourceId, d->volume); - ep->api->SetSoundObjectDirectivity(d->sourceId, d->directivity, d->directivityOrder); - ep->api->SetSoundObjectNearFieldEffectGain(d->sourceId, d->nearFieldGain); - d->updateDistanceModel(); - } -} - -/*! - Returns the engine associated with this listener. - */ -QSpatialAudioEngine *QSpatialAudioSoundSource::engine() const -{ - return d->engine; -} - -QT_END_NAMESPACE - -#include "moc_qspatialaudiosoundsource.cpp" diff --git a/src/multimedia/spatial/qspatialaudiosoundsource.h b/src/multimedia/spatial/qspatialaudiosoundsource.h deleted file mode 100644 index cd0d8fe75..000000000 --- a/src/multimedia/spatial/qspatialaudiosoundsource.h +++ /dev/null @@ -1,161 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Spatial Audio module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL-NOGPL2$ -** 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 3 or (at your option) 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.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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef QSPATIALAUDIOSOURCE_H -#define QSPATIALAUDIOSOURCE_H - -#include <QtMultimedia/qtmultimediaglobal.h> -#include <QtCore/QObject> -#include <QtGui/qvector3d.h> -#include <QtGui/qquaternion.h> - -QT_BEGIN_NAMESPACE - -class QSpatialAudioEngine; -class QSpatialAudioSound; - -class QSpatialAudioSoundSourcePrivate; -class Q_MULTIMEDIA_EXPORT QSpatialAudioSoundSource : public QObject -{ - Q_OBJECT - Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) - Q_PROPERTY(QVector3D position READ position WRITE setPosition NOTIFY positionChanged) - Q_PROPERTY(QQuaternion rotation READ rotation WRITE setRotation NOTIFY rotationChanged) - Q_PROPERTY(float volume READ volume WRITE setVolume NOTIFY volumeChanged) - Q_PROPERTY(DistanceModel distanceModel READ distanceModel WRITE setDistanceModel NOTIFY distanceModelChanged) - Q_PROPERTY(float size READ size WRITE setSize NOTIFY sizeChanged) - Q_PROPERTY(float distanceCutoff READ distanceCutoff WRITE setDistanceCutoff NOTIFY distanceCutoffChanged) - Q_PROPERTY(float manualAttenuation READ manualAttenuation WRITE setManualAttenuation NOTIFY manualAttenuationChanged) - Q_PROPERTY(float occlusionIntensity READ occlusionIntensity WRITE setOcclusionIntensity NOTIFY occlusionIntensityChanged) - Q_PROPERTY(float directivity READ directivity WRITE setDirectivity NOTIFY directivityChanged) - Q_PROPERTY(float directivityOrder READ directivityOrder WRITE setDirectivityOrder NOTIFY directivityOrderChanged) - Q_PROPERTY(float nearFieldGain READ nearFieldGain WRITE setNearFieldGain NOTIFY nearFieldGainChanged) - Q_PROPERTY(int loops READ loops WRITE setLoops NOTIFY loopsChanged) - Q_PROPERTY(bool autoPlay READ autoPlay WRITE setAutoPlay NOTIFY autoPlayChanged) - -public: - explicit QSpatialAudioSoundSource(QSpatialAudioEngine *engine); - ~QSpatialAudioSoundSource(); - - void setSource(const QUrl &url); - QUrl source() const; - - enum Loops - { - Infinite = -1, - Once = 1 - }; - Q_ENUM(Loops) - - int loops() const; - void setLoops(int loops); - - bool autoPlay() const; - void setAutoPlay(bool autoPlay); - - void setPosition(QVector3D pos); - QVector3D position() const; - - void setRotation(const QQuaternion &q); - QQuaternion rotation() const; - - void setVolume(float volume); - float volume() const; - - enum DistanceModel { - DistanceModel_Logarithmic, - DistanceModel_Linear, - DistanceModel_ManualAttenutation - }; - Q_ENUM(DistanceModel); - - void setDistanceModel(DistanceModel model); - DistanceModel distanceModel() const; - - void setSize(float size); - float size() const; - - void setDistanceCutoff(float cutoff); - float distanceCutoff() const; - - void setManualAttenuation(float attenuation); - float manualAttenuation() const; - - void setOcclusionIntensity(float occlusion); - float occlusionIntensity() const; - - void setDirectivity(float alpha); - float directivity() const; - - void setDirectivityOrder(float alpha); - float directivityOrder() const; - - void setNearFieldGain(float gain); - float nearFieldGain() const; - - QSpatialAudioEngine *engine() const; - -Q_SIGNALS: - void sourceChanged(); - void loopsChanged(); - void autoPlayChanged(); - void positionChanged(); - void rotationChanged(); - void volumeChanged(); - void distanceModelChanged(); - void sizeChanged(); - void distanceCutoffChanged(); - void manualAttenuationChanged(); - void occlusionIntensityChanged(); - void directivityChanged(); - void directivityOrderChanged(); - void nearFieldGainChanged(); - -public Q_SLOTS: - void play(); - void pause(); - void stop(); - -private: - void setEngine(QSpatialAudioEngine *engine); - friend class QSpatialAudioSound; - friend class QSpatialAudioSoundSourcePrivate; - QSpatialAudioSoundSourcePrivate *d = nullptr; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/multimedia/spatial/qspatialaudiosoundsource_p.h b/src/multimedia/spatial/qspatialaudiosoundsource_p.h deleted file mode 100644 index 83bd2d232..000000000 --- a/src/multimedia/spatial/qspatialaudiosoundsource_p.h +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Spatial Audio module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL-NOGPL2$ -** 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 3 or (at your option) 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.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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSPATIALAUDIOSOUNDSOURCE_P_H -#define QSPATIALAUDIOSOUNDSOURCE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <qspatialaudiosoundsource.h> -#include <qspatialaudioengine_p.h> -#include <qurl.h> -#include <qvector3d.h> -#include <qquaternion.h> -#include <qaudiobuffer.h> -#include <qaudiodevice.h> -#include <qmutex.h> - -QT_BEGIN_NAMESPACE - -class QAudioDecoder; -class QSpatialAudioEnginePrivate; - -class QSpatialAudioSoundSourcePrivate : public QSpatialAudioSound -{ -public: - QSpatialAudioSoundSourcePrivate(QObject *parent) - : QSpatialAudioSound(parent, 1) - {} - - static QSpatialAudioSoundSourcePrivate *get(QSpatialAudioSoundSource *soundSource) - { return soundSource ? soundSource->d : nullptr; } - - QVector3D pos; - QQuaternion rotation; - QSpatialAudioSoundSource::DistanceModel distanceModel = QSpatialAudioSoundSource::DistanceModel_Logarithmic; - float size = .1f; - float distanceCutoff = 50.f; - float manualAttenuation = 0.f; - float occlusionIntensity = 0.f; - float directivity = 0.f; - float directivityOrder = 1.f; - float nearFieldGain = 0.f; - float wallDampening = 1.f; - float wallOcclusion = 0.f; - - void updateDistanceModel(); - void updateRoomEffects(); -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/multimedia/spatial/qspatialaudiostereosource.cpp b/src/multimedia/spatial/qspatialaudiostereosource.cpp deleted file mode 100644 index 61f3a47b2..000000000 --- a/src/multimedia/spatial/qspatialaudiostereosource.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Spatial Audio module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL-NOGPL2$ -** 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 3 or (at your option) 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.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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "qspatialaudiostereosource.h" -#include "qspatialaudiolistener.h" -#include "qspatialaudioengine_p.h" -#include "api/resonance_audio_api.h" -#include <qaudiosink.h> -#include <qurl.h> -#include <qdebug.h> -#include <qaudiodecoder.h> - -QT_BEGIN_NAMESPACE - -/*! - \class QSpatialAudioStereoSource - \inmodule QtMultimedia - \ingroup multimedia_spatialaudio - - \brief A stereo overlay sound. - - QSpatialAudioStereoSource represents a position and orientation independent sound. - It's commonly used for background sounds (e.g. music) that is supposed to be independent - of the listeners position and orientation. - */ - -/*! - Creates a stereo sound source for \a engine. - */ -QSpatialAudioStereoSource::QSpatialAudioStereoSource(QSpatialAudioEngine *engine) - : d(new QSpatialAudioSound(this)) -{ - setEngine(engine); -} - -QSpatialAudioStereoSource::~QSpatialAudioStereoSource() -{ - setEngine(nullptr); - delete d; -} - -/*! - \property QSpatialAudioStereoSource::volume - - Defines the volume of the sound. - - Values between 0 and 1 will attenuate the sound, while values above 1 - provide an additional gain boost. - */ -void QSpatialAudioStereoSource::setVolume(float volume) -{ - if (d->volume == volume) - return; - d->volume = volume; - auto *ep = QSpatialAudioEnginePrivate::get(d->engine); - if (ep) - ep->api->SetSourceVolume(d->sourceId, d->volume); - emit volumeChanged(); -} - -float QSpatialAudioStereoSource::volume() const -{ - return d->volume; -} - -void QSpatialAudioStereoSource::setSource(const QUrl &url) -{ - if (d->url == url) - return; - d->url = url; - - d->load(); - emit sourceChanged(); -} - -/*! - \property QSpatialAudioStereoSource::source - - The source file for the sound to be played. - */ -QUrl QSpatialAudioStereoSource::source() const -{ - return d->url; -} - -/*! - \property QSpatialAudioStereoSource::loops - - Determines how many times the sound is played before the player stops. - Set to QSpatialAudioSoundSource::Infinite to play the current sound in - a loop forever. - - The default value is \c 1. - */ -int QSpatialAudioStereoSource::loops() const -{ - return d->m_loops.loadRelaxed(); -} - -void QSpatialAudioStereoSource::setLoops(int loops) -{ - int oldLoops = d->m_loops.fetchAndStoreRelaxed(loops); - if (oldLoops != loops) - emit loopsChanged(); -} - -/*! - \property QSpatialAudioStereoSource::autoPlay - - Determines whether the sound should automatically start playing when a source - gets specified. - - The default value is \c true. - */ -bool QSpatialAudioStereoSource::autoPlay() const -{ - return d->m_autoPlay.loadRelaxed(); -} - -void QSpatialAudioStereoSource::setAutoPlay(bool autoPlay) -{ - bool old = d->m_autoPlay.fetchAndStoreRelaxed(autoPlay); - if (old != autoPlay) - emit autoPlayChanged(); -} - -/*! - Starts playing back the sound. Does nothing if the sound is already playing. - */ -void QSpatialAudioStereoSource::play() -{ - d->play(); -} - -/*! - Pauses sound playback. Calling play() will continue playback. - */ -void QSpatialAudioStereoSource::pause() -{ - d->pause(); -} - -/*! - Stops sound playback and resets the current position and current loop count to 0. - Calling play() will start playback at the beginning of the sound file. - */ -void QSpatialAudioStereoSource::stop() -{ - d->stop(); -} - -/*! - \internal - */ -void QSpatialAudioStereoSource::setEngine(QSpatialAudioEngine *engine) -{ - if (d->engine == engine) - return; - auto *ep = QSpatialAudioEnginePrivate::get(engine); - - if (ep) - ep->removeStereoSound(this); - d->engine = engine; - - ep = QSpatialAudioEnginePrivate::get(engine); - if (ep) { - ep->addStereoSound(this); - ep->api->SetSourceVolume(d->sourceId, d->volume); - } -} - -/*! - Returns the engine associated with this listener. - */ -QSpatialAudioEngine *QSpatialAudioStereoSource::engine() const -{ - return d->engine; -} - -QT_END_NAMESPACE - -#include "moc_qspatialaudiostereosource.cpp" diff --git a/src/multimedia/spatial/qspatialaudiostereosource.h b/src/multimedia/spatial/qspatialaudiostereosource.h deleted file mode 100644 index 402aee9f8..000000000 --- a/src/multimedia/spatial/qspatialaudiostereosource.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Spatial Audio module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL-NOGPL2$ -** 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 3 or (at your option) 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.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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef QSPATIALAUDIOSTEREOSOURCE_H -#define QSPATIALAUDIOSTEREOSOURCE_H - -#include <QtMultimedia/qtmultimediaglobal.h> -#include <QtCore/QUrl> -#include <QtCore/QObject> - -QT_BEGIN_NAMESPACE - -class QSpatialAudioEngine; -class QSpatialAudioSound; - -class QSpatialAudioStereoSourcePrivate; -class Q_MULTIMEDIA_EXPORT QSpatialAudioStereoSource : public QObject -{ - Q_OBJECT - Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) - Q_PROPERTY(float volume READ volume WRITE setVolume NOTIFY volumeChanged) - Q_PROPERTY(int loops READ loops WRITE setLoops NOTIFY loopsChanged) - Q_PROPERTY(bool autoPlay READ autoPlay WRITE setAutoPlay NOTIFY autoPlayChanged) - -public: - explicit QSpatialAudioStereoSource(QSpatialAudioEngine *engine); - ~QSpatialAudioStereoSource(); - - void setSource(const QUrl &url); - QUrl source() const; - - enum Loops - { - Infinite = -1, - Once = 1 - }; - Q_ENUM(Loops) - - int loops() const; - void setLoops(int loops); - - bool autoPlay() const; - void setAutoPlay(bool autoPlay); - - void setVolume(float volume); - float volume() const; - - QSpatialAudioEngine *engine() const; - -Q_SIGNALS: - void sourceChanged(); - void loopsChanged(); - void autoPlayChanged(); - void volumeChanged(); - -public Q_SLOTS: - void play(); - void pause(); - void stop(); - -private: - void setEngine(QSpatialAudioEngine *engine); - friend class QSpatialAudioSound; - QSpatialAudioSound *d = nullptr; -}; - -QT_END_NAMESPACE - -#endif |