diff options
| author | Loek Le Blansch <loek@pipeframe.xyz> | 2024-11-14 18:04:03 +0100 | 
|---|---|---|
| committer | Loek Le Blansch <loek@pipeframe.xyz> | 2024-11-14 18:04:03 +0100 | 
| commit | ab0b4923c4f49e7a28f6d17e994d3e013ca344bb (patch) | |
| tree | b385693017be292b8f4862e88b912dba7c6be619 | |
| parent | 213f947d0907858cace470736c15f87caa934591 (diff) | |
more WIP audio system + utilities
| -rw-r--r-- | src/crepe/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/crepe/Resource.cpp | 6 | ||||
| -rw-r--r-- | src/crepe/Resource.h | 12 | ||||
| -rw-r--r-- | src/crepe/api/ResourceManager.cpp | 13 | ||||
| -rw-r--r-- | src/crepe/api/ResourceManager.h | 13 | ||||
| -rw-r--r-- | src/crepe/facade/Sound.cpp | 22 | ||||
| -rw-r--r-- | src/crepe/facade/Sound.h | 7 | ||||
| -rw-r--r-- | src/crepe/util/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/crepe/util/OptionalRef.h | 41 | ||||
| -rw-r--r-- | src/crepe/util/OptionalRef.hpp | 67 | ||||
| -rw-r--r-- | src/test/AssetTest.cpp | 2 | ||||
| -rw-r--r-- | src/test/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/test/OptionalRefTest.cpp | 16 | ||||
| -rw-r--r-- | src/test/ResourceManagerTest.cpp | 21 | 
14 files changed, 194 insertions, 32 deletions
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,17 +12,11 @@ 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<Resource> 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  	 * would otherwise need to be implemented as singletons. 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<Sound>(const Asset & asset) { +	return this->cache<Sound>(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 <typename T>  	T & cache(const Asset & asset); -	/** -	 * \brief Clear the resource cache -	 */ +	//! Clear the resource cache  	void clear();  }; +template <> +Sound & ResourceManager::cache<Sound>(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 <memory> -  #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<Resource> Sound::clone(const Asset & src) const { -	auto instance = make_unique<Sound>(*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 <soloud/soloud.h>  #include <soloud/soloud_wav.h> +#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<Resource> clone(const Asset & src) const override; +	void set_context(SoundContext & ctx);  private:  	SoLoud::Wav sample;  	SoLoud::handle handle; -	SoundContext & context; +	OptionalRef<SoundContext> 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 <typename T> +class OptionalRef { +public: +	OptionalRef() = default; +	OptionalRef(T &); +  OptionalRef<T> & operator=(T &); +	explicit operator bool() const noexcept; + +	void set(T &) noexcept; +	T & get() const; +	void clear() noexcept; + +  OptionalRef(const OptionalRef<T> &); +  OptionalRef(OptionalRef<T> &&); +  OptionalRef<T> & operator=(const OptionalRef<T> &); +  OptionalRef<T> & operator=(OptionalRef<T> &&); + +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 <stdexcept> + +#include "OptionalRef.h" + +namespace crepe { + +template <typename T> +OptionalRef<T>::OptionalRef(T & ref) { +	this->set(ref); +} + +template <typename T> +OptionalRef<T>::OptionalRef(const OptionalRef<T> & other) { +	this->ref = other.ref; +} + +template <typename T> +OptionalRef<T>::OptionalRef(OptionalRef<T> && other) { +	this->ref = other.ref; +	other.clear(); +} + +template <typename T> +OptionalRef<T> & OptionalRef<T>::operator=(const OptionalRef<T> & other) { +	this->ref = other.ref; +	return *this; +} + +template <typename T> +OptionalRef<T> & OptionalRef<T>::operator=(OptionalRef<T> && other) { +	this->ref = other.ref; +	other.clear(); +	return *this; +} + +template <typename T> +T & OptionalRef<T>::get() const { +	if (this->ref == nullptr) +		throw std::runtime_error("OptionalRef: attempt to dereference nullptr"); +	return *this->ref; +} + +template <typename T> +void OptionalRef<T>::set(T & ref) noexcept { +	this->ref = &ref; +} + +template <typename T> +void OptionalRef<T>::clear() noexcept { +	this->ref = nullptr; +} + +template <typename T> +OptionalRef<T> & OptionalRef<T>::operator=(T & ref) { +	this->set(ref); +	return *this; +} + +template <typename T> +OptionalRef<T>::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 <gtest/gtest.h>  #include <crepe/api/Asset.h> +#include <crepe/api/Config.h>  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 <gtest/gtest.h> + +#include <crepe/util/OptionalRef.h> + +using namespace std; +using namespace crepe; +using namespace testing; + +TEST(OptionalRefTest, Explicit) { +	string value = "foo"; +	OptionalRef<string> 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 <gtest/gtest.h> + +#include <crepe/api/ResourceManager.h> + +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<Sound>("mwe/audio/sfx1.wav"); +} +  |