From 6df048eac872e7ba87a347558881c8704a8ef3a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 4 Jun 2018 17:09:54 +0200 Subject: [PATCH] Audio: doc++ Compiling code snippets, reworked the totally confused scenegraph integration docs. --- doc/snippets/CMakeLists.txt | 15 +++++ doc/snippets/MagnumAudio-scenegraph.cpp | 83 +++++++++++++++++++++++++ doc/snippets/MagnumAudio.cpp | 49 +++++++++++++++ src/Magnum/Audio/Context.h | 24 +++---- src/Magnum/Audio/Listener.h | 73 +++++++++------------- src/Magnum/Audio/Playable.h | 41 ++++-------- src/Magnum/Audio/PlayableGroup.h | 48 ++++---------- 7 files changed, 211 insertions(+), 122 deletions(-) create mode 100644 doc/snippets/MagnumAudio-scenegraph.cpp create mode 100644 doc/snippets/MagnumAudio.cpp diff --git a/doc/snippets/CMakeLists.txt b/doc/snippets/CMakeLists.txt index 3bd9c70e5..523fdb599 100644 --- a/doc/snippets/CMakeLists.txt +++ b/doc/snippets/CMakeLists.txt @@ -44,6 +44,21 @@ add_library(snippets-Magnum STATIC target_link_libraries(snippets-Magnum PRIVATE Magnum) set_target_properties(snippets-Magnum PROPERTIES FOLDER "Magnum/doc/snippets") +if(WITH_AUDIO) + add_library(snippets-MagnumAudio STATIC MagnumAudio.cpp) + target_link_libraries(snippets-MagnumAudio PRIVATE MagnumAudio) + set_target_properties(snippets-MagnumAudio PROPERTIES FOLDER "Magnum/doc/snippets") + + if(WITH_SCENEGRAPH) + add_library(snippets-MagnumAudio-scenegraph STATIC + MagnumAudio-scenegraph.cpp) + target_link_libraries(snippets-MagnumAudio-scenegraph PRIVATE + MagnumAudio + MagnumSceneGraph) + set_target_properties(snippets-MagnumAudio-scenegraph PROPERTIES FOLDER "Magnum/doc/snippets") + endif() +endif() + if(WITH_GL) add_library(snippets-MagnumGL STATIC MagnumGL.cpp diff --git a/doc/snippets/MagnumAudio-scenegraph.cpp b/doc/snippets/MagnumAudio-scenegraph.cpp new file mode 100644 index 000000000..71ae14921 --- /dev/null +++ b/doc/snippets/MagnumAudio-scenegraph.cpp @@ -0,0 +1,83 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Magnum/Audio/Buffer.h" +#include "Magnum/Audio/Listener.h" +#include "Magnum/Audio/Playable.h" +#include "Magnum/Audio/PlayableGroup.h" + +#include "Magnum/SceneGraph/MatrixTransformation3D.h" +#include "Magnum/SceneGraph/Object.h" +#include "Magnum/SceneGraph/Scene.h" + +using namespace Magnum; + +int main() { + +{ +typedef SceneGraph::Object Object3D; +typedef SceneGraph::Scene Scene3D; + +/* [Listener-usage] */ +Scene3D scene; +Object3D object{&scene}; +Audio::Listener3D listener{object}; + +// ... + +// every frame, adapt the listener to changes in scene transformation +listener.update({}); +/* [Listener-usage] */ +} + +{ +typedef SceneGraph::Object Object3D; +typedef SceneGraph::Scene Scene3D; +Audio::PlayableGroup3D someOtherGroup; +/* [Playable-usage] */ +Scene3D scene; +Object3D object{&scene}; +Audio::Buffer buffer; + +// ... +Audio::Listener3D listener{scene}; +Audio::PlayableGroup3D group; + +/* Attach the playable to an object and configure its source */ +Audio::Playable3D playable{object, &group}; +playable.source() + .setBuffer(&buffer) + .setLooping(true) + .play(); + +// ... + +// every frame, adapt the listener and all playables to changes in scene +// transformation +listener.update({group, someOtherGroup}); +/* [Playable-usage] */ +} + +} diff --git a/doc/snippets/MagnumAudio.cpp b/doc/snippets/MagnumAudio.cpp new file mode 100644 index 000000000..95772958a --- /dev/null +++ b/doc/snippets/MagnumAudio.cpp @@ -0,0 +1,49 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Magnum/Audio/Context.h" +#include "Magnum/Audio/Extensions.h" + +using namespace Magnum; + +int main() { + +{ +/* [Context-isExtensionSupported] */ +if(Audio::Context::current().isExtensionSupported()) { + // amazing binaural audio +} else { + // probably left/right stereo only +} +/* [Context-isExtensionSupported] */ +} + +{ +/* [MAGNUM_ASSERT_AUDIO_EXTENSION_SUPPORTED] */ +MAGNUM_ASSERT_AUDIO_EXTENSION_SUPPORTED(Audio::Extensions::ALC::SOFTX::HRTF); +/* [MAGNUM_ASSERT_AUDIO_EXTENSION_SUPPORTED] */ +} + +} diff --git a/src/Magnum/Audio/Context.h b/src/Magnum/Audio/Context.h index 07ee1f18f..1f1c41b43 100644 --- a/src/Magnum/Audio/Context.h +++ b/src/Magnum/Audio/Context.h @@ -315,13 +315,7 @@ class MAGNUM_AUDIO_EXPORT Context { * Extensions usable with this function are listed in @ref Extensions * namespace in header @ref Extensions.h. Example usage: * - * @code{.cpp} - * if(Context::current().isExtensionSupported()) { - * // amazing binaural audio - * } else { - * // probably left/right stereo only - * } - * @endcode + * @snippet MagnumAudio.cpp Context-isExtensionSupported * * @see @ref isExtensionSupported(const Extension&) const, * @ref MAGNUM_ASSERT_AUDIO_EXTENSION_SUPPORTED() @@ -396,7 +390,8 @@ class MAGNUM_AUDIO_EXPORT Context::Configuration { * @brief Set sampling rate * @return Reference to self (for method chaining) * - * If set to `-1` (the default), system OpenAL configuration is used. + * If set to @cpp -1 @ce (the default), system OpenAL configuration is + * used. */ Configuration& setFrequency(Int hz) { _frequency = hz; @@ -429,7 +424,8 @@ class MAGNUM_AUDIO_EXPORT Context::Configuration { * @brief Set hint for how many mono sources to support * @return Reference to self (for method chaining) * - * If set to `-1` (the default), no hint will be given to OpenAL. + * If set to @cpp -1 @ce (the default), no hint will be given to + * OpenAL. */ Configuration& setMonoSourceCount(Int count) { _monoSources = count; @@ -443,7 +439,8 @@ class MAGNUM_AUDIO_EXPORT Context::Configuration { * @brief Set hint for how many stereo sources to support * @return Reference to self (for method chaining) * - * If set to `-1` (the default), no hint will be given to OpenAL. + * If set to @cpp -1 @ce (the default), no hint will be given to + * OpenAL. */ Configuration& setStereoSourceCount(Int count) { _stereoSources = count; @@ -457,7 +454,8 @@ class MAGNUM_AUDIO_EXPORT Context::Configuration { * @brief Set refresh rate * @return Reference to self (for method chaining) * - * If set to `-1` (the default), system OpenAL configuration is used. + * If set to @cpp -1 @ce (the default), system OpenAL configuration is + * used. */ Configuration& setRefreshRate(Int hz) { _refreshRate = hz; @@ -488,9 +486,7 @@ By default, if assertion fails, an message is printed to error output and the application aborts. If `CORRADE_NO_ASSERT` is defined, this macro does nothing. Example usage: -@code{.cpp} -MAGNUM_ASSERT_AUDIO_EXTENSION_SUPPORTED(Extensions::ALC::SOFTX::HRTF); -@endcode +@snippet MagnumAudio.cpp MAGNUM_ASSERT_AUDIO_EXTENSION_SUPPORTED @see @ref Magnum::Audio::Context::isExtensionSupported() "Audio::Context::isExtensionSupported()", @ref CORRADE_ASSERT(), @ref CORRADE_INTERNAL_ASSERT() diff --git a/src/Magnum/Audio/Listener.h b/src/Magnum/Audio/Listener.h index b463a5eef..9833092d0 100644 --- a/src/Magnum/Audio/Listener.h +++ b/src/Magnum/Audio/Listener.h @@ -41,47 +41,28 @@ namespace Magnum { namespace Audio { @brief Listener Feature which manages the position, orientation and gain of the OpenAL listener -for an @ref SceneGraph::Object. +for a @ref SceneGraph::Object. @section Audio-Listener-usage Usage -Minimal scene setup for a @ref Listener3D will require the following code: +The listener will be commonly used together with a bunch of @ref Playable +features, managed in one or more @ref PlayableGroup instances. In order to +reflect transformation changes affecting the scene, you need to call +@ref update() after each change (or simply every frame): -@code{.cpp} -Scene3D scene; -Object3D object{&scene}; -Listener3D listener{object}; +@snippet MagnumAudio-scenegraph.cpp Listener-usage -// ... every frame, update the listener to changes in object transformation: -listener.update({}); -@endcode - -For two dimensional scenes simply replace all `3D` with `2D`. - -@subsection Audio-Listener-usage-playablegroup Using Listener with PlayableGroup - -When using @ref PlayableGroup, you can update the listener and groups as -follows: - -@code{.cpp} -// ... -Listener3D listener{object}; -PlayableGroup3D group1, group2; - -// ... and every frame: -listener.update({group1, group2}); -@endcode +For two-dimensional scenes simply replace all `3D` with `2D`. See @ref Playable +for more info about how to set up and group audio sources. @section Audio-Listener-active-listener Active listener -There can only be at the most *one* active listener at a given time, i.e. the -one on which @ref Listener::update() was called last. This is because OpenAL +There can only be at most *one* active listener at a given time, i.e. the one +on which @ref Listener::update() was called last. This is because OpenAL only supports notion of one listener. Having multiple @ref Listener2D or @ref Listener3D instances can still be useful for conveniently switching between them for cinematics for example. -@ref AbstractObject::setClean() will not affect inactive listeners. - @section Audio-Listener-sound-transformation Sound transformation @ref Listener::setSoundTransformation() enables you to set a transformation @@ -91,10 +72,8 @@ into the three dimensional audio space or even scaling the audio scene to match a certain world scale. In the later case you might want to instead consider @ref Renderer::setSpeedOfSound(). -- @ref Listener2D -- @ref Listener3D - -@see @ref Audio::Renderer, @ref Playable, @ref PlayableGroup +@see @ref Listener2D, @ref Listener3D, @ref Renderer, @ref Playable, + @ref PlayableGroup */ template class Listener: public SceneGraph::AbstractFeature { public: @@ -102,10 +81,10 @@ template class Listener: public SceneGraph::AbstractFeat * @brief Constructor * @param object Object this listener belongs to * - * Creates a listener with a forward vector of @cpp {0.0f, 0.0f, -1.0f} @ce - * and up vector of @cpp {0.0f, 1.0f, 0.0f} @ce. These vectors cannot - * be changed, the listeners orientation and translation can be instead - * affected by @p object or via @ref Listener::setSoundTransformation(). + * Creates a listener with a default orientation (i.e., forward vector + * is @cpp {0.0f, 0.0f, -1.0f} @ce and up vector of @cpp {0.0f, 1.0f, 0.0f} @ce). + * You can change this orientation by transforming the object this + * listener is attached to or via @ref Listener::setSoundTransformation(). * @see @ref setGain() */ explicit Listener(SceneGraph::AbstractObject& object); @@ -119,9 +98,9 @@ template class Listener: public SceneGraph::AbstractFeat /** * @brief Set sound transformation - * @param soundTransformation Transformation for transforming from - * world to listener space * @return Reference to self (for method chaining) + * + * Global transformation for transforming from world to listener space. */ Listener& setSoundTransformation(const Matrix4& soundTransformation) { _soundTransformation = soundTransformation; @@ -133,10 +112,12 @@ template class Listener: public SceneGraph::AbstractFeat * @brief Update the listener * @param groups Groups to update * - * Makes this Listener the active listener and calls + * Makes this instance the active listener and calls * @ref SceneGraph::AbstractObject::setClean() on its parent object and - * all objects of the @ref Playable s in the group. Updates listene - * related configuration for @ref Renderer (position, orientation, gain). + * all objects of the @ref Playable "Playables" in the group to reflect + * transformation changes to spatial audio behavior. Also updates + * listener-related configuration for @ref Renderer (position, + * orientation, gain). */ void update(std::initializer_list>> groups); @@ -145,8 +126,10 @@ template class Listener: public SceneGraph::AbstractFeat /** * @brief Set listener gain - * @param gain Gain * @return Reference to self (for method chaining) + * + * Default is @cpp 1.0f @ce (i.e., not affecting the global gain in any + * way). */ Listener& setGain(Float gain); @@ -161,14 +144,14 @@ template class Listener: public SceneGraph::AbstractFeat }; /** - * @brief Listener for two dimensional float scenes + * @brief Listener for two-dimensional float scenes * * @see @ref Listener3D */ typedef Listener<2> Listener2D; /** - * @brief Listener for three dimensional float scenes + * @brief Listener for three-dimensional float scenes * * @see @ref Listener2D */ diff --git a/src/Magnum/Audio/Playable.h b/src/Magnum/Audio/Playable.h index 1683ddac3..ff14f0a9f 100644 --- a/src/Magnum/Audio/Playable.h +++ b/src/Magnum/Audio/Playable.h @@ -44,29 +44,14 @@ an @ref SceneGraph::Object. @section Audio-Playable-usage Usage -@code{.cpp} -Object3D object; -Source source; -Playable3D playable{object, source}; +Attach the instance to an existing object and set a filled buffer to it. In +order to reflect transformation changes from the scene in the spatial audio, +the playable should be added to some @ref PlayableGroup, which is periodically +updated from a currently active @link Listener @endlink: -// ... +@snippet MagnumAudio-scenegraph.cpp Playable-usage -object.translate(offset); - -// ... and every frame, update the sources positions by cleaning the object: -object.setClean(); -@endcode - -Position of the source will be updated to the translation of `object` when -@ref SceneGraph::Object::setClean() is called, which is done in -@ref Audio::Listener::update() or @ref Audio::PlayableGroup::setClean() for example. - -To manage multiple Playables at once, use @ref PlayableGroup. - -- @ref Playable2D -- @ref Playable3D - -@see @ref Source, @ref PlayableGroup, @ref Listener +@see @ref Playable2D, @ref Playable3D, @ref Source */ template class Playable: public SceneGraph::AbstractGroupedFeature, Float> { public: @@ -75,11 +60,11 @@ template class Playable: public SceneGraph::AbstractGrou * @param object Object this playable belongs to * @param group Group this playable belongs to * - * Creates playable with a source and a forward vector of @cpp {0.0f, -1.0f} @ce - * for 2D and @cpp {0.0f, 0.0f, -1.0f} @ce for 3D scenes. This forward - * vector cannot be changed, the sources orientation and translation - * can be instead affected by @p object or via - * @ref PlayableGroup::setSoundTransformation(). + * Creates playable with a source and a forward vector of + * @cpp {0.0f, -1.0f} @ce for 2D and @cpp {0.0f, 0.0f, -1.0f} @ce for + * 3D scenes. This forward vector cannot be changed, the sources + * orientation and translation can be instead affected by @p object or + * via @ref PlayableGroup::setSoundTransformation(). * @see @ref setGain(), @ref PlayableGroup::add() */ explicit Playable(SceneGraph::AbstractObject& object, PlayableGroup* group = nullptr); @@ -127,14 +112,14 @@ template class Playable: public SceneGraph::AbstractGrou }; /** - * @brief Playable for two dimensional float scenes + * @brief Playable for two-dimensional float scenes * * @see @ref Playable3D */ typedef Playable<2> Playable2D; /** - * @brief Playable for three dimensional float scenes + * @brief Playable for three-dimensional float scenes * * @see @ref Playable2D */ diff --git a/src/Magnum/Audio/PlayableGroup.h b/src/Magnum/Audio/PlayableGroup.h index 0b2038628..97c4369fd 100644 --- a/src/Magnum/Audio/PlayableGroup.h +++ b/src/Magnum/Audio/PlayableGroup.h @@ -41,34 +41,10 @@ namespace Magnum { namespace Audio { /** @brief PlayableGroup -Manages @ref Audio::Playable features and provides means of setting gain or -transformation of a group of Playables, aswell as the ability of playing, -pausing, stopping or cleaning all sources of all Playables. - -@section Audio-PlayableGroup-usage Usage - -@code{.cpp} -Object3D object; -Source source; -PlayableGroup3D group; -Playable3D playable{object, source, &group}; - -// ... - -object.translate(offset); - -// ... and every frame, update the sources positions: -group.setClean(); -@endcode - -For two dimensional scenes simply replace `3D` with `2D`. When using a -@ref Listener, prefer @ref Listener::update() over -@ref PlayableGroup::setClean(). - -- @ref PlayableGroup2D -- @ref PlayableGroup3D - -@see @ref Playable, @ref SceneGraph::FeatureGroup, @ref Listener +Manages a group of @ref Playable instances with an ability to control gain, +transformation or state for all of them at once. See @ref Playable and +@ref Listener documentation for more information. +@see @ref PlayableGroup2D, @ref PlayableGroup3D */ template class PlayableGroup: public SceneGraph::FeatureGroup, Float> { public: @@ -79,6 +55,7 @@ template class PlayableGroup: public SceneGraph::Feature /** * @brief Play all sound sources in this group * @return Reference to self (for method chaining) + * * @see @ref Source::play() */ PlayableGroup& play(); @@ -86,6 +63,7 @@ template class PlayableGroup: public SceneGraph::Feature /** * @brief Pause all sound sources in this group * @return Reference to self (for method chaining) + * * @see @ref Source::pause() */ PlayableGroup& pause(); @@ -93,6 +71,7 @@ template class PlayableGroup: public SceneGraph::Feature /** * @brief Stop all sound sources in this group * @return Reference to self (for method chaining) + * * @see @ref Source::stop() */ PlayableGroup& stop(); @@ -101,14 +80,13 @@ template class PlayableGroup: public SceneGraph::Feature Float gain() const { return _gain; } /** - * @brief Set gain for all sound sources of Playables in this group - * @param gain Gain + * @brief Set gain for all sound sources in this group * @return Reference to self (for method chaining) * - * Will calculate the sound sources gain relative to the gain of the - * Playable and this playable group. The sources gain is computed as - * @cpp sourceGain = playableGain*groupGain @ce. Default of the groups - * gain is @cpp 1.0f @ce. + * Will calculate source gain for each source relative to the gain of + * given @ref Playable and this playable group. The source gain is + * calculated as @cpp sourceGain = playableGain*groupGain @ce. Default + * group gain is @cpp 1.0f @ce. */ PlayableGroup& setGain(const Float gain); @@ -116,7 +94,7 @@ template class PlayableGroup: public SceneGraph::Feature const Matrix4& soundTransformation() const { return _soundTransform; } /** - * @brief Set transformation of the sounds in this group + * @brief Set transformation of all sound sources in this group * @return Reference to self (for method chaining) */ PlayableGroup& setSoundTransformation(const Matrix4& matrix);