diff options
author | Lars Knoll <lars.knoll@qt.io> | 2022-04-25 19:56:56 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2022-05-11 08:23:57 +0200 |
commit | c6749ee963b68ed2b9f6afc70bcd07695734c3f2 (patch) | |
tree | 7302d07ef4b855bfef0cd241627bf73cda190e07 /examples/multimedia | |
parent | e610585d68b3ec6d655335fbf29eaafc94a6fbf8 (diff) |
Add example for spatial audio
A simple widget based example that lets you pan one sound
source around in space.
Change-Id: I09e66fd217a136ef5bacaf7c3bb46af462993736
Reviewed-by: Rafael Roquetto <rafael.roquetto@qt.io>
Diffstat (limited to 'examples/multimedia')
-rw-r--r-- | examples/multimedia/CMakeLists.txt | 1 | ||||
-rw-r--r-- | examples/multimedia/spatialaudio/CMakeLists.txt | 33 | ||||
-rw-r--r-- | examples/multimedia/spatialaudio/main.cpp | 161 |
3 files changed, 195 insertions, 0 deletions
diff --git a/examples/multimedia/CMakeLists.txt b/examples/multimedia/CMakeLists.txt index 6123c7994..44b701120 100644 --- a/examples/multimedia/CMakeLists.txt +++ b/examples/multimedia/CMakeLists.txt @@ -10,6 +10,7 @@ if(TARGET Qt::Widgets) endif() qt_internal_add_example(audiosource) qt_internal_add_example(audiooutput) + qt_internal_add_example(spatialaudio) endif() if(TARGET Qt::Quick) qt_internal_add_example(declarative-camera) diff --git a/examples/multimedia/spatialaudio/CMakeLists.txt b/examples/multimedia/spatialaudio/CMakeLists.txt new file mode 100644 index 000000000..9e6649fc8 --- /dev/null +++ b/examples/multimedia/spatialaudio/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.16) +project(audiodecoder LANGUAGES CXX) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/multimedia/spatialaudio") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Multimedia Widgets) + +qt_add_executable(spatialaudio + main.cpp +) + +set_target_properties(spatialaudio PROPERTIES + WIN32_EXECUTABLE FALSE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(spatialaudio PUBLIC + Qt::Core + Qt::Multimedia + Qt::Widgets +) + +install(TARGETS spatialaudio + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/multimedia/spatialaudio/main.cpp b/examples/multimedia/spatialaudio/main.cpp new file mode 100644 index 000000000..a0f1e52b5 --- /dev/null +++ b/examples/multimedia/spatialaudio/main.cpp @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QtWidgets/QtWidgets> +#include <QtMultimedia/QtMultimedia> + +class AudioWidget : public QWidget +{ +public: + AudioWidget() + : QWidget() + { + setWindowTitle(tr("Spatial Audio test application")); + + setMinimumSize(400, 300); + auto *grid = new QGridLayout(this); + fileEdit = new QLineEdit; + fileDialogButton = new QPushButton(tr("Open Filedialog")); + grid->addWidget(fileEdit, 0, 0); + grid->addWidget(fileDialogButton, 0, 1); + + azimuth = new QSlider(Qt::Horizontal); + azimuth->setRange(-180, 180); + grid->addWidget(new QLabel("Azimuth:"), 1, 0); + grid->addWidget(azimuth, 1, 1); + elevation = new QSlider(Qt::Horizontal); + elevation->setRange(-90, 90); + grid->addWidget(new QLabel("Elevation:"), 2, 0); + grid->addWidget(elevation, 2, 1); + distance = new QSlider(Qt::Horizontal); + distance->setRange(0, 100); + grid->addWidget(new QLabel("Distance:"), 3, 0); + grid->addWidget(distance, 3, 1); + occlusion = new QSlider(Qt::Horizontal); + occlusion->setRange(0, 1000); + grid->addWidget(new QLabel("Occlusion:"), 4, 0); + grid->addWidget(occlusion, 4, 1); + + useHeadphone = new QCheckBox(tr("Use headphone spatialization")); + grid->addWidget(useHeadphone, 5, 1, 1, 2); + + connect(azimuth, &QSlider::valueChanged, this, &AudioWidget::newPosition); + connect(elevation, &QSlider::valueChanged, this, &AudioWidget::newPosition); + connect(distance, &QSlider::valueChanged, this, &AudioWidget::newPosition); + connect(occlusion, &QSlider::valueChanged, this, &AudioWidget::newOcclusion); + connect(useHeadphone, &QCheckBox::stateChanged, this, &AudioWidget::useHeadphoneChanged); + connect(fileEdit, &QLineEdit::textChanged, this, &AudioWidget::fileChanged); + connect(fileDialogButton, &QPushButton::clicked, this, &AudioWidget::openFileDialog); + + listener = new QSpatialAudioListener(&engine); + listener->setPosition({}); + listener->setRotation({}); + engine.start(); + + sound = new QSpatialAudioSoundSource(&engine); + + distance->setValue(1); + } + void setFile(const QString &file) { fileEdit->setText(file); } +private slots: + void newPosition() + { + float az = azimuth->value()/180.*M_PI; + float el = elevation->value()/180.*M_PI; + float d = distance->value()/10.; + + float x = d*sin(az)*cos(el); + float y = d*cos(az)*cos(el); + float z = d*sin(el); + sound->setPosition({x, y, z}); + } + void newOcclusion() + { + sound->setOcclusionIntensity(occlusion->value()/100.); + } + void useHeadphoneChanged(int state) + { + engine.setOutputMode(state ? QSpatialAudioEngine::Headphone : QSpatialAudioEngine::Stereo); + } + void fileChanged(const QString &file) + { + sound->setSource(QUrl::fromLocalFile(file)); + } + void openFileDialog() + { + auto file = QFileDialog::getOpenFileName(this); + fileEdit->setText(file); + } + + QLineEdit *fileEdit = nullptr; + QPushButton *fileDialogButton = nullptr; + QSlider *azimuth = nullptr; + QSlider *elevation = nullptr; + QSlider *distance = nullptr; + QSlider *occlusion = nullptr; + QCheckBox *useHeadphone = nullptr; + + QSpatialAudioEngine engine; + QSpatialAudioListener *listener = nullptr; + QSpatialAudioSoundSource *sound = nullptr; +}; + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + AudioWidget *w = new AudioWidget; + w->show(); + if (argc > 1) { + auto file = QString::fromUtf8(argv[1]); + w->setFile(file); + } + + return app.exec(); +} |