From ab0b4923c4f49e7a28f6d17e994d3e013ca344bb Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Thu, 14 Nov 2024 18:04:03 +0100 Subject: more WIP audio system + utilities --- src/crepe/CMakeLists.txt | 2 ++ src/crepe/Resource.cpp | 6 ++++ src/crepe/Resource.h | 12 ++----- src/crepe/api/ResourceManager.cpp | 13 ++++++++ src/crepe/api/ResourceManager.h | 13 ++++---- src/crepe/facade/Sound.cpp | 22 ++++++------- src/crepe/facade/Sound.h | 7 ++-- src/crepe/util/CMakeLists.txt | 2 ++ src/crepe/util/OptionalRef.h | 41 ++++++++++++++++++++++++ src/crepe/util/OptionalRef.hpp | 67 +++++++++++++++++++++++++++++++++++++++ src/test/AssetTest.cpp | 2 +- src/test/CMakeLists.txt | 2 ++ src/test/OptionalRefTest.cpp | 16 ++++++++++ src/test/ResourceManagerTest.cpp | 21 ++++++++++++ 14 files changed, 194 insertions(+), 32 deletions(-) create mode 100644 src/crepe/Resource.cpp create mode 100644 src/crepe/util/OptionalRef.h create mode 100644 src/crepe/util/OptionalRef.hpp create mode 100644 src/test/OptionalRefTest.cpp create mode 100644 src/test/ResourceManagerTest.cpp diff --git a/src/crepe/CMakeLists.txt b/src/crepe/CMakeLists.txt index 05f86d7..d72d4a0 100644 --- a/src/crepe/CMakeLists.txt +++ b/src/crepe/CMakeLists.txt @@ -4,6 +4,7 @@ target_sources(crepe PUBLIC Component.cpp Collider.cpp Exception.cpp + Resource.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -15,6 +16,7 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES ValueBroker.hpp Exception.h Exception.hpp + Resource.h ) add_subdirectory(api) diff --git a/src/crepe/Resource.cpp b/src/crepe/Resource.cpp new file mode 100644 index 0000000..e254695 --- /dev/null +++ b/src/crepe/Resource.cpp @@ -0,0 +1,6 @@ +#include "Resource.h" + +using namespace crepe; + +Resource::Resource(const Asset & asset) { } + diff --git a/src/crepe/Resource.h b/src/crepe/Resource.h index dcf3dbd..95b4d06 100644 --- a/src/crepe/Resource.h +++ b/src/crepe/Resource.h @@ -12,16 +12,10 @@ class Asset; * resource (e.g. textures, sounds). */ class Resource { +public: + Resource(const Asset & src); + private: - /** - * \brief Prototype pattern clone function. - * - * \param src Source file of new resource (abstraction for file saved on - * disk) - * - * \returns New instance of concrete resource - */ - virtual std::unique_ptr clone(const Asset & src) const = 0; /** * The resource manager uses \c clone to create new instances of the concrete * resource class. This may be used to inherit references to classes that diff --git a/src/crepe/api/ResourceManager.cpp b/src/crepe/api/ResourceManager.cpp index 17fbd9b..6eb4afd 100644 --- a/src/crepe/api/ResourceManager.cpp +++ b/src/crepe/api/ResourceManager.cpp @@ -2,6 +2,9 @@ #include "ResourceManager.h" +// default resource cache functions +#include "../facade/Sound.h" + using namespace crepe; ResourceManager & ResourceManager::get_instance() { @@ -11,3 +14,13 @@ ResourceManager & ResourceManager::get_instance() { ResourceManager::~ResourceManager() { dbg_trace(); } ResourceManager::ResourceManager() { dbg_trace(); } + +void ResourceManager::clear() { + this->resources.clear(); +} + +template <> +Sound & ResourceManager::cache(const Asset & asset) { + return this->cache(asset); +} + diff --git a/src/crepe/api/ResourceManager.h b/src/crepe/api/ResourceManager.h index a69a9fa..468af16 100644 --- a/src/crepe/api/ResourceManager.h +++ b/src/crepe/api/ResourceManager.h @@ -51,22 +51,23 @@ public: * it is already cached. * \tparam T The type of asset to cache (e.g., texture, sound, etc.). * - * \return A shared pointer to the cached asset. + * \return A reference to the resource * * This template function caches the asset at the given file path. If the - * asset is already cached and `reload` is false, the existing cached version - * will be returned. Otherwise, the asset will be reloaded and added to the + * asset is already cached, the existing instance will be returned. + * Otherwise, the concrete resource will be instantiated and added to the * cache. */ template T & cache(const Asset & asset); - /** - * \brief Clear the resource cache - */ + //! Clear the resource cache void clear(); }; +template <> +Sound & ResourceManager::cache(const Asset & asset); + } // namespace crepe #include "ResourceManager.hpp" diff --git a/src/crepe/facade/Sound.cpp b/src/crepe/facade/Sound.cpp index 726f11f..4eefcda 100644 --- a/src/crepe/facade/Sound.cpp +++ b/src/crepe/facade/Sound.cpp @@ -1,5 +1,3 @@ -#include - #include "../api/Asset.h" #include "../util/Log.h" @@ -9,16 +7,13 @@ using namespace crepe; using namespace std; -Sound::Sound(SoundContext & ctx) : context(ctx) { dbg_trace(); } - -unique_ptr Sound::clone(const Asset & src) const { - auto instance = make_unique(*this); - instance->sample.load(src.get_path().c_str()); - return instance; +Sound::Sound(const Asset & src) : Resource(src) { + this->sample.load(src.get_path().c_str()); + dbg_trace(); } void Sound::play() { - SoundContext & ctx = this->context; + SoundContext & ctx = this->context.get(); if (ctx.engine.getPause(this->handle)) { // resume if paused ctx.engine.setPause(this->handle, false); @@ -30,13 +25,13 @@ void Sound::play() { } void Sound::pause() { - SoundContext & ctx = this->context; + SoundContext & ctx = this->context.get(); if (ctx.engine.getPause(this->handle)) return; ctx.engine.setPause(this->handle, true); } void Sound::rewind() { - SoundContext & ctx = this->context; + SoundContext & ctx = this->context.get(); if (!ctx.engine.isValidVoiceHandle(this->handle)) return; ctx.engine.seek(this->handle, 0); } @@ -44,7 +39,7 @@ void Sound::rewind() { void Sound::set_volume(float volume) { this->volume = volume; - SoundContext & ctx = this->context; + SoundContext & ctx = this->context.get(); if (!ctx.engine.isValidVoiceHandle(this->handle)) return; ctx.engine.setVolume(this->handle, this->volume); } @@ -52,7 +47,8 @@ void Sound::set_volume(float volume) { void Sound::set_looping(bool looping) { this->looping = looping; - SoundContext & ctx = this->context; + SoundContext & ctx = this->context.get(); if (!ctx.engine.isValidVoiceHandle(this->handle)) return; ctx.engine.setLooping(this->handle, this->looping); } + diff --git a/src/crepe/facade/Sound.h b/src/crepe/facade/Sound.h index 8342b46..6f8462a 100644 --- a/src/crepe/facade/Sound.h +++ b/src/crepe/facade/Sound.h @@ -4,6 +4,7 @@ #include #include +#include "../util/OptionalRef.h" #include "../Resource.h" namespace crepe { @@ -18,6 +19,7 @@ class SoundContext; */ class Sound : public Resource { public: + Sound(const Asset & src); /** * \brief Pause this sample * @@ -72,13 +74,12 @@ public: bool get_looping() const { return this->looping; } public: - Sound(SoundContext & ctx); - std::unique_ptr clone(const Asset & src) const override; + void set_context(SoundContext & ctx); private: SoLoud::Wav sample; SoLoud::handle handle; - SoundContext & context; + OptionalRef context; float volume = 1.0f; bool looping = false; diff --git a/src/crepe/util/CMakeLists.txt b/src/crepe/util/CMakeLists.txt index 4be738a..94ed906 100644 --- a/src/crepe/util/CMakeLists.txt +++ b/src/crepe/util/CMakeLists.txt @@ -9,5 +9,7 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES Log.hpp Proxy.h Proxy.hpp + OptionalRef.h + OptionalRef.hpp ) diff --git a/src/crepe/util/OptionalRef.h b/src/crepe/util/OptionalRef.h new file mode 100644 index 0000000..1ad3a6d --- /dev/null +++ b/src/crepe/util/OptionalRef.h @@ -0,0 +1,41 @@ +#pragma once + +namespace crepe { + +/** + * \brief Optional reference utility + * + * This class doesn't need to know the full definition of \c T to be used. + * + * \tparam T Value type + */ +template +class OptionalRef { +public: + OptionalRef() = default; + OptionalRef(T &); + OptionalRef & operator=(T &); + explicit operator bool() const noexcept; + + void set(T &) noexcept; + T & get() const; + void clear() noexcept; + + OptionalRef(const OptionalRef &); + OptionalRef(OptionalRef &&); + OptionalRef & operator=(const OptionalRef &); + OptionalRef & operator=(OptionalRef &&); + +private: + /** + * \brief Reference to the value of type \c T + * + * \note This raw pointer is *not* managed, and only used as a reference! + */ + T * ref = nullptr; +}; + +} + +#include "OptionalRef.hpp" + diff --git a/src/crepe/util/OptionalRef.hpp b/src/crepe/util/OptionalRef.hpp new file mode 100644 index 0000000..e603a25 --- /dev/null +++ b/src/crepe/util/OptionalRef.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include + +#include "OptionalRef.h" + +namespace crepe { + +template +OptionalRef::OptionalRef(T & ref) { + this->set(ref); +} + +template +OptionalRef::OptionalRef(const OptionalRef & other) { + this->ref = other.ref; +} + +template +OptionalRef::OptionalRef(OptionalRef && other) { + this->ref = other.ref; + other.clear(); +} + +template +OptionalRef & OptionalRef::operator=(const OptionalRef & other) { + this->ref = other.ref; + return *this; +} + +template +OptionalRef & OptionalRef::operator=(OptionalRef && other) { + this->ref = other.ref; + other.clear(); + return *this; +} + +template +T & OptionalRef::get() const { + if (this->ref == nullptr) + throw std::runtime_error("OptionalRef: attempt to dereference nullptr"); + return *this->ref; +} + +template +void OptionalRef::set(T & ref) noexcept { + this->ref = &ref; +} + +template +void OptionalRef::clear() noexcept { + this->ref = nullptr; +} + +template +OptionalRef & OptionalRef::operator=(T & ref) { + this->set(ref); + return *this; +} + +template +OptionalRef::operator bool() const noexcept { + return this->ref == nullptr; +} + +} + diff --git a/src/test/AssetTest.cpp b/src/test/AssetTest.cpp index 324a3f1..563a253 100644 --- a/src/test/AssetTest.cpp +++ b/src/test/AssetTest.cpp @@ -1,7 +1,7 @@ -#include "api/Config.h" #include #include +#include using namespace std; using namespace crepe; diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 5ea90f7..437c296 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -5,5 +5,7 @@ target_sources(test_main PUBLIC ParticleTest.cpp AudioTest.cpp AssetTest.cpp + ResourceManagerTest.cpp + OptionalRefTest.cpp ) diff --git a/src/test/OptionalRefTest.cpp b/src/test/OptionalRefTest.cpp new file mode 100644 index 0000000..65bd816 --- /dev/null +++ b/src/test/OptionalRefTest.cpp @@ -0,0 +1,16 @@ +#include + +#include + +using namespace std; +using namespace crepe; +using namespace testing; + +TEST(OptionalRefTest, Explicit) { + string value = "foo"; + OptionalRef ref; + + EXPECT_FALSE(bool(ref)); + ASSERT_THROW(ref.get(), runtime_error); +} + diff --git a/src/test/ResourceManagerTest.cpp b/src/test/ResourceManagerTest.cpp new file mode 100644 index 0000000..42b6b5d --- /dev/null +++ b/src/test/ResourceManagerTest.cpp @@ -0,0 +1,21 @@ +#include + +#include + +using namespace std; +using namespace crepe; +using namespace testing; + +class ResourceManagerTest : public Test { +public: + ResourceManager & manager = ResourceManager::get_instance(); + + void SetUp() override { + this->manager.clear(); + } +}; + +TEST_F(ResourceManagerTest, Main) { + Sound & sound = this->manager.cache("mwe/audio/sfx1.wav"); +} + -- cgit v1.2.3