diff --git a/core/include/cubos/core/al/audio_context.hpp b/core/include/cubos/core/al/audio_context.hpp index 31375c033f..b6cef973cd 100644 --- a/core/include/cubos/core/al/audio_context.hpp +++ b/core/include/cubos/core/al/audio_context.hpp @@ -148,6 +148,12 @@ namespace cubos::core::al /// @brief Plays the source. virtual void play() = 0; + /// @brief Stops the source, restarting buffer to position 0. + virtual void stop() = 0; + + /// @brief Pauses the source, allowing to be played from the moment it was paused. + virtual void pause() = 0; + protected: Source() = default; }; @@ -188,8 +194,9 @@ namespace cubos::core::al /// @return Handle of the new source. virtual std::shared_ptr createSource() = 0; - /// @brief Creates a new audio listener. - /// @return Handle of the new listener. + /// @brief Gets the listener with the specific index. + /// @param index Index of the listener. + /// @return Handle of the listener. virtual std::shared_ptr listener(size_t index) = 0; protected: diff --git a/core/src/al/miniaudio_context.cpp b/core/src/al/miniaudio_context.cpp index f5a87a90bf..a77177392b 100644 --- a/core/src/al/miniaudio_context.cpp +++ b/core/src/al/miniaudio_context.cpp @@ -180,6 +180,25 @@ class MiniaudioSource : public impl::Source } } + void stop() override + { + if (ma_sound_stop(&mSound) != MA_SUCCESS) + { + CUBOS_ERROR("Failed to stop sound"); + return; + } + ma_sound_seek_to_pcm_frame(&mSound, 0); + } + + void pause() override + { + if (ma_sound_stop(&mSound) != MA_SUCCESS) + { + CUBOS_ERROR("Failed to pause sound"); + return; + } + } + private: ma_sound mSound; ma_engine& mEngine; @@ -188,7 +207,7 @@ class MiniaudioSource : public impl::Source class MiniaudioDevice : public impl::AudioDevice { public: - MiniaudioDevice(ma_context& context, const std::string& deviceName, ma_uint32 listenerCount) + MiniaudioDevice(ma_context& context, const std::string& specifier, ma_uint32 listenerCount) : mContext(context) { ma_device_info* pPlaybackDeviceInfos; @@ -202,6 +221,12 @@ class MiniaudioDevice : public impl::AudioDevice return; } + std::string deviceName{specifier}; + if (deviceName == "") + { + deviceName = pPlaybackDeviceInfos[0].name; + } + ma_device_id* deviceId = nullptr; for (ma_uint32 i = 0; i < playbackDeviceCount; i++) { diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 9a40651a12..a8e61cc074 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -39,6 +39,15 @@ set(CUBOS_ENGINE_SOURCE "src/utils/free_camera/plugin.cpp" "src/utils/free_camera/controller.cpp" + "src/audio/plugin.cpp" + "src/audio/source.cpp" + "src/audio/source_impl.cpp" + "src/audio/listener.cpp" + "src/audio/listener_impl.cpp" + "src/audio/pause.cpp" + "src/audio/play.cpp" + "src/audio/stop.cpp" + "src/audio/audio.cpp" "src/audio/bridge.cpp" diff --git a/engine/include/cubos/engine/audio/listener.hpp b/engine/include/cubos/engine/audio/listener.hpp new file mode 100644 index 0000000000..d628e1091d --- /dev/null +++ b/engine/include/cubos/engine/audio/listener.hpp @@ -0,0 +1,24 @@ +/// @file +/// @brief Component @ref cubos::engine::AudioListener. +/// @ingroup audio-plugin + +#pragma once + +#include + +#include +#include + +#include + +namespace cubos::engine +{ + /// @brief Component which adds an AudioListener to the entitiy + /// @ingroup audio-plugin + struct CUBOS_ENGINE_API AudioListener + { + CUBOS_REFLECT; + + bool active{false}; + }; +} // namespace cubos::engine diff --git a/engine/include/cubos/engine/audio/pause.hpp b/engine/include/cubos/engine/audio/pause.hpp new file mode 100644 index 0000000000..7ac9d1d8b8 --- /dev/null +++ b/engine/include/cubos/engine/audio/pause.hpp @@ -0,0 +1,22 @@ +/// @file +/// @brief Component @ref cubos::engine::AudioPause. +/// @ingroup audio-plugin + +#pragma once + +#include + +#include + +#include +#include + +namespace cubos::engine +{ + /// @brief Component which adds an AudioSource to the entitiy + /// @ingroup audio-plugin + struct CUBOS_ENGINE_API AudioPause + { + CUBOS_REFLECT; + }; +} // namespace cubos::engine diff --git a/engine/include/cubos/engine/audio/play.hpp b/engine/include/cubos/engine/audio/play.hpp new file mode 100644 index 0000000000..d4a7d64595 --- /dev/null +++ b/engine/include/cubos/engine/audio/play.hpp @@ -0,0 +1,22 @@ +/// @file +/// @brief Component @ref cubos::engine::AudioPlay. +/// @ingroup audio-plugin + +#pragma once + +#include + +#include + +#include +#include + +namespace cubos::engine +{ + /// @brief Component which adds an AudioSource to the entitiy + /// @ingroup audio-plugin + struct CUBOS_ENGINE_API AudioPlay + { + CUBOS_REFLECT; + }; +} // namespace cubos::engine diff --git a/engine/include/cubos/engine/audio/plugin.hpp b/engine/include/cubos/engine/audio/plugin.hpp new file mode 100644 index 0000000000..8a29f2463b --- /dev/null +++ b/engine/include/cubos/engine/audio/plugin.hpp @@ -0,0 +1,40 @@ +/// @dir +/// @brief @ref audio-plugin plugin directory. + +/// @file +/// @brief Plugin entry point. +/// @ingroup audio-plugin + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace cubos::engine +{ + /// @defgroup audio-plugin Audio + /// @ingroup engine + /// @brief Adds audio to @b Cubos + /// + /// ## Settings + /// - `audio.listener.count` - number of listeners per audio device (default: `4`). + /// + /// ## Dependencies + /// - @ref settings-plugin + + /// @brief Initializes the audio context (after @ref settingsTag). + CUBOS_ENGINE_API extern Tag audioInitTag; + + /// @brief Initializes the audio state (after @ref audioInitTag). + CUBOS_ENGINE_API extern Tag audioStateInitTag; + + /// @brief Plugin entry function. + /// @param cubos @b Cubos main class. + /// @ingroup assets-plugin + CUBOS_ENGINE_API void audioPlugin(Cubos& cubos); +} // namespace cubos::engine diff --git a/engine/include/cubos/engine/audio/source.hpp b/engine/include/cubos/engine/audio/source.hpp new file mode 100644 index 0000000000..15974c709b --- /dev/null +++ b/engine/include/cubos/engine/audio/source.hpp @@ -0,0 +1,41 @@ +/// @file +/// @brief Component @ref cubos::engine::AudioSource. +/// @ingroup audio-plugin + +#pragma once + +#include + +#include +#include + +#include +#include +#include + +namespace cubos::engine +{ + /// @brief Component which adds an AudioSource to the entitiy + /// @ingroup audio-plugin + struct CUBOS_ENGINE_API AudioSource + { + CUBOS_REFLECT; + + bool playing{false}; + bool looping{false}; + bool stop{false}; + + float gain; + float pitch; + float maxDistance; + float minDistance; + + float innerConeAngle; + float outerConeAngle; + float outerConeGain; + + glm::vec3 coneDirection; + + Asset