From f3eeedc91a04ca0651e0fe78a2119e7e3e38e391 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 25 Sep 2024 17:36:31 +0200 Subject: WIP Audio API + facade --- src/crepe/api/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/crepe/api/CMakeLists.txt (limited to 'src/crepe/api/CMakeLists.txt') diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt new file mode 100644 index 0000000..94617a4 --- /dev/null +++ b/src/crepe/api/CMakeLists.txt @@ -0,0 +1,4 @@ +target_sources(crepe PUBLIC + AudioSource.cpp +) + -- cgit v1.2.3 From 3cb7227c3c9678141ff74915331b706265c380cb Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sat, 28 Sep 2024 17:07:56 +0200 Subject: more WIP audio facade --- src/CMakeLists.txt | 15 +++++++++--- src/crepe/CMakeLists.txt | 6 +++++ src/crepe/Sound.cpp | 19 ++++++++++++++-- src/crepe/Sound.h | 54 ++++++++++++++++++++++++++++++++++++++------ src/crepe/SoundSystem.cpp | 25 ++++++++++++++++++++ src/crepe/SoundSystem.h | 27 ++++++++++++++++++++++ src/crepe/api/CMakeLists.txt | 9 +++++++- src/crepe/api/Resource.cpp | 12 ++++++++++ src/crepe/api/Resource.h | 11 ++++++--- src/dummy_audio.cpp | 37 ++++++++++++++++++++++++++++++ test/CMakeLists.txt | 2 +- 11 files changed, 200 insertions(+), 17 deletions(-) create mode 100644 src/crepe/SoundSystem.cpp create mode 100644 src/crepe/SoundSystem.h create mode 100644 src/crepe/api/Resource.cpp create mode 100644 src/dummy_audio.cpp (limited to 'src/crepe/api/CMakeLists.txt') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cc71435..232d330 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,13 +15,22 @@ project(crepe C CXX) add_library(crepe SHARED) target_include_directories(crepe - SYSTEM INTERFACE . + PUBLIC SYSTEM INTERFACE . ) -# NOTE: all libraries *must* be linked as PRIVATE +# TODO: libraries should be linked as PRIVATE target_link_libraries(crepe - PRIVATE soloud + PUBLIC soloud ) add_subdirectory(crepe) +install( + TARGETS crepe + FILE_SET HEADERS DESTINATION include/crepe +) + + +add_executable(dummy_audio dummy_audio.cpp) +target_link_libraries(dummy_audio PUBLIC crepe) + diff --git a/src/crepe/CMakeLists.txt b/src/crepe/CMakeLists.txt index aa64262..13d9be5 100644 --- a/src/crepe/CMakeLists.txt +++ b/src/crepe/CMakeLists.txt @@ -1,5 +1,11 @@ target_sources(crepe PUBLIC Sound.cpp + SoundSystem.cpp +) + +target_sources(crepe PUBLIC FILE_SET HEADERS FILES + Sound.h + SoundSystem.h ) add_subdirectory(api) diff --git a/src/crepe/Sound.cpp b/src/crepe/Sound.cpp index f45a697..d48393c 100644 --- a/src/crepe/Sound.cpp +++ b/src/crepe/Sound.cpp @@ -1,9 +1,24 @@ #include "Sound.h" +#include "SoundSystem.h" using namespace crepe; -Sound::Sound(std::unique_ptr res) { - _res = std::move(res); +Sound::Sound(std::unique_ptr res, SoundSystem & system) : system(system) { + this->res = std::move(res); } +void Sound::play() { + if (this->system.engine.getPause(this->handle)) { + // resume if paused + this->system.engine.setPause(this->handle, false); + } else { + // or start new sound + this->handle = this->system.engine.play(this->sample); + } +} + +void Sound::pause() { + if (this->system.engine.getPause(this->handle)) return; + this->system.engine.setPause(this->handle, true); +} diff --git a/src/crepe/Sound.h b/src/crepe/Sound.h index ac4b7f4..71fe390 100644 --- a/src/crepe/Sound.h +++ b/src/crepe/Sound.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include @@ -8,22 +9,61 @@ namespace crepe { -class Sound { -public: - Sound(std::unique_ptr res); - virtual ~Sound() = default; +class SoundSystem; +class Sound { public: + /** + * \brief Pause this sample + * + * Pauses this sound if it is playing, or does nothing if it is already + * paused. The playhead position is saved, such that calling \c play() after + * this function makes the sound resume. + */ void pause(); + /** + * \brief Play this sample + * + * Resume playback if this sound is paused, or start from the beginning of + * the sample. + * + * \note This class only saves a reference to the most recent 'voice' of this + * sound. Calling \c play() while the sound is already playing causes + * multiple instances of the sample to play simultaniously. The sample + * started last is the one that is controlled afterwards. + */ void play(); + /** + * \brief Reset playhead position + * + * Resets the playhead position so that calling \c play() after this function + * makes it play from the start of the sample. If the sound is not paused + * before calling this function, this function will stop playback. + */ void rewind(); + /** + * \brief Set playback volume / gain + * + * \param volume Volume (0 = muted, 1 = full volume) + */ void set_volume(float volume); + /** + * \brief Set looping behavior for this sample + * + * \param looping Looping behavior (false = one-shot, true = loop) + */ void set_looping(bool looping); private: - std::unique_ptr _res; - SoLoud::handle _handle; - bool _paused; + Sound(std::unique_ptr res, SoundSystem & system); + SoundSystem & system; + friend class SoundSystem; + +private: + std::unique_ptr res; + SoLoud::Wav sample; + SoLoud::handle handle; + bool paused; }; } diff --git a/src/crepe/SoundSystem.cpp b/src/crepe/SoundSystem.cpp new file mode 100644 index 0000000..30b0157 --- /dev/null +++ b/src/crepe/SoundSystem.cpp @@ -0,0 +1,25 @@ +#include "SoundSystem.h" +#include + +using namespace crepe; + +SoundSystem SoundSystem::instance { }; + +std::unique_ptr SoundSystem::sound(const std::string & src) { + auto res = std::make_unique(src); + return SoundSystem::sound(std::move(res)); +} + +std::unique_ptr SoundSystem::sound(std::unique_ptr res) { + Sound * out = new Sound(std::move(res), SoundSystem::instance); + return std::unique_ptr(out); +} + +SoundSystem::SoundSystem() { + engine.init(); +} + +SoundSystem::~SoundSystem() { + engine.deinit(); +} + diff --git a/src/crepe/SoundSystem.h b/src/crepe/SoundSystem.h new file mode 100644 index 0000000..23bb00a --- /dev/null +++ b/src/crepe/SoundSystem.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +#include + +#include "Sound.h" + +namespace crepe { + +class SoundSystem { +public: + static std::unique_ptr sound(const std::string & res); + static std::unique_ptr sound(std::unique_ptr res); + +private: + SoundSystem(); + virtual ~SoundSystem(); + static SoundSystem instance; + +private: + SoLoud::Soloud engine; + friend class Sound; +}; + +} + diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index 94617a4..feb03ef 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -1,4 +1,11 @@ target_sources(crepe PUBLIC - AudioSource.cpp + # AudioSource.cpp + Resource.cpp +) + +target_sources(crepe PUBLIC FILE_SET HEADERS FILES + AudioSource.h + Component.h + Resource.h ) diff --git a/src/crepe/api/Resource.cpp b/src/crepe/api/Resource.cpp new file mode 100644 index 0000000..a38900b --- /dev/null +++ b/src/crepe/api/Resource.cpp @@ -0,0 +1,12 @@ +#include "Resource.h" + +using namespace crepe::api; + +Resource::Resource(const std::string & src) : src(src) { + this->file = std::ifstream(src, std::ios::in | std::ios::binary); +} + +const std::istream & Resource::read() { + return this->file; +} + diff --git a/src/crepe/api/Resource.h b/src/crepe/api/Resource.h index 620a10e..2260b1a 100644 --- a/src/crepe/api/Resource.h +++ b/src/crepe/api/Resource.h @@ -1,16 +1,21 @@ #pragma once #include +#include +#include namespace crepe::api { class Resource { public: - Resource(const std::string & source); - virtual ~Resource(); + Resource(const std::string & src); + +public: + const std::istream & read(); private: - std::string _source; + std::string src; + std::ifstream file; }; } diff --git a/src/dummy_audio.cpp b/src/dummy_audio.cpp new file mode 100644 index 0000000..5e0000e --- /dev/null +++ b/src/dummy_audio.cpp @@ -0,0 +1,37 @@ +#include "crepe/SoundSystem.h" + +#include +#include + +using namespace crepe; +using namespace std; +using namespace std::chrono_literals; + +int main() { + auto bgm = SoundSystem::sound("../mwe/audio/bgm.ogg"); + auto sfx1 = SoundSystem::sound("../mwe/audio/sfx1.wav"); + auto sfx2 = SoundSystem::sound("../mwe/audio/sfx2.wav"); + auto sfx3 = SoundSystem::sound("../mwe/audio/sfx3.wav"); + + bgm->play(); + + // play each sample sequentially + this_thread::sleep_for(500ms); + sfx1->play(); + this_thread::sleep_for(500ms); + sfx2->play(); + bgm->pause(); + this_thread::sleep_for(500ms); + sfx3->play(); + bgm->play(); + this_thread::sleep_for(500ms); + + // play all samples simultaniously + sfx1->play(); + sfx2->play(); + sfx3->play(); + this_thread::sleep_for(1000ms); + + return 0; +} + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d103b9a..f015570 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -13,7 +13,7 @@ add_subdirectory(../src crepe) add_executable(test dummy.cpp - audio.cpp + # audio.cpp ) target_link_libraries(test -- cgit v1.2.3 From 202a9ec288ded78771e1f7e4c711a7612b201b9d Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sat, 5 Oct 2024 14:20:45 +0200 Subject: rename Resource to Asset --- src/crepe/Sound.cpp | 6 +++--- src/crepe/Sound.h | 6 +++--- src/crepe/api/Asset.cpp | 14 ++++++++++++++ src/crepe/api/Asset.h | 24 ++++++++++++++++++++++++ src/crepe/api/AudioSource.cpp | 2 +- src/crepe/api/AudioSource.h | 6 +++--- src/crepe/api/CMakeLists.txt | 4 ++-- src/crepe/api/Resource.cpp | 14 -------------- src/crepe/api/Resource.h | 24 ------------------------ src/test/audio.cpp | 4 ++-- 10 files changed, 52 insertions(+), 52 deletions(-) create mode 100644 src/crepe/api/Asset.cpp create mode 100644 src/crepe/api/Asset.h delete mode 100644 src/crepe/api/Resource.cpp delete mode 100644 src/crepe/api/Resource.h (limited to 'src/crepe/api/CMakeLists.txt') diff --git a/src/crepe/Sound.cpp b/src/crepe/Sound.cpp index 1758282..c6e87d5 100644 --- a/src/crepe/Sound.cpp +++ b/src/crepe/Sound.cpp @@ -5,17 +5,17 @@ using namespace crepe; -Sound::Sound(std::unique_ptr res) { +Sound::Sound(std::unique_ptr res) { dbg_trace(); this->load(std::move(res)); } Sound::Sound(const char * src) { dbg_trace(); - this->load(std::make_unique(src)); + this->load(std::make_unique(src)); } -void Sound::load(std::unique_ptr res) { +void Sound::load(std::unique_ptr res) { this->sample.load(res->canonical()); } diff --git a/src/crepe/Sound.h b/src/crepe/Sound.h index ac93991..339dd7c 100644 --- a/src/crepe/Sound.h +++ b/src/crepe/Sound.h @@ -5,7 +5,7 @@ #include -#include "api/Resource.h" +#include "api/Asset.h" namespace crepe { @@ -66,10 +66,10 @@ public: public: Sound(const char * src); - Sound(std::unique_ptr res); + Sound(std::unique_ptr res); private: - void load(std::unique_ptr res); + void load(std::unique_ptr res); private: SoLoud::Wav sample; diff --git a/src/crepe/api/Asset.cpp b/src/crepe/api/Asset.cpp new file mode 100644 index 0000000..92ee50e --- /dev/null +++ b/src/crepe/api/Asset.cpp @@ -0,0 +1,14 @@ +#include + +#include "Asset.h" + +using namespace crepe::api; + +Asset::Asset(const std::string & src) { + this->src = std::filesystem::canonical(src); + this->file = std::ifstream(this->src, std::ios::in | std::ios::binary); +} + +const std::istream & Asset::read() { return this->file; } + +const char * Asset::canonical() { return this->src.c_str(); } diff --git a/src/crepe/api/Asset.h b/src/crepe/api/Asset.h new file mode 100644 index 0000000..259c696 --- /dev/null +++ b/src/crepe/api/Asset.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include + +namespace crepe::api { + +class Asset { +public: + Asset(const std::string & src); + +public: + //! Get an input stream to the contents of this resource + const std::istream & read(); + //! Get the canonical path to this resource + const char * canonical(); + +private: + std::string src; + std::ifstream file; +}; + +} // namespace crepe::api diff --git a/src/crepe/api/AudioSource.cpp b/src/crepe/api/AudioSource.cpp index 4d1b093..656fc46 100644 --- a/src/crepe/api/AudioSource.cpp +++ b/src/crepe/api/AudioSource.cpp @@ -5,7 +5,7 @@ using namespace crepe::api; -AudioSource::AudioSource(std::unique_ptr audio_clip) { +AudioSource::AudioSource(std::unique_ptr audio_clip) { this->_sound = std::make_unique(std::move(audio_clip)); } diff --git a/src/crepe/api/AudioSource.h b/src/crepe/api/AudioSource.h index 4300c48..9dfaf46 100644 --- a/src/crepe/api/AudioSource.h +++ b/src/crepe/api/AudioSource.h @@ -3,7 +3,7 @@ #include #include "Component.h" -#include "Resource.h" +#include "Asset.h" namespace crepe { class Sound; @@ -14,7 +14,7 @@ namespace crepe::api { //! Audio source component class AudioSource : Component { public: - AudioSource(std::unique_ptr audio_clip); + AudioSource(std::unique_ptr audio_clip); virtual ~AudioSource() = default; public: @@ -26,7 +26,7 @@ public: public: //! Sample file location - std::unique_ptr audio_clip; + std::unique_ptr audio_clip; //! TODO: ????? bool play_on_awake; //! Repeat the current audio clip during playback diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index feb03ef..54c7fdc 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -1,11 +1,11 @@ target_sources(crepe PUBLIC # AudioSource.cpp - Resource.cpp + Asset.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES AudioSource.h Component.h - Resource.h + Asset.h ) diff --git a/src/crepe/api/Resource.cpp b/src/crepe/api/Resource.cpp deleted file mode 100644 index 1a647ce..0000000 --- a/src/crepe/api/Resource.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include - -#include "Resource.h" - -using namespace crepe::api; - -Resource::Resource(const std::string & src) { - this->src = std::filesystem::canonical(src); - this->file = std::ifstream(this->src, std::ios::in | std::ios::binary); -} - -const std::istream & Resource::read() { return this->file; } - -const char * Resource::canonical() { return this->src.c_str(); } diff --git a/src/crepe/api/Resource.h b/src/crepe/api/Resource.h deleted file mode 100644 index f2b2a0e..0000000 --- a/src/crepe/api/Resource.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace crepe::api { - -class Resource { -public: - Resource(const std::string & src); - -public: - //! Get an input stream to the contents of this resource - const std::istream & read(); - //! Get the canonical path to this resource - const char * canonical(); - -private: - std::string src; - std::ifstream file; -}; - -} // namespace crepe::api diff --git a/src/test/audio.cpp b/src/test/audio.cpp index 5bb2607..1d84551 100644 --- a/src/test/audio.cpp +++ b/src/test/audio.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include @@ -15,7 +15,7 @@ using namespace crepe::api; // TODO: mock internal audio class TEST(audio, play) { - auto res = std::make_unique("../mwe/audio/bgm.ogg"); + auto res = std::make_unique("../mwe/audio/bgm.ogg"); auto bgm = AudioSource(std::move(res)); bgm.play(); -- cgit v1.2.3 From b99e38badb82c5cc79771a77c5f6ea180c67ee4f Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sat, 5 Oct 2024 14:24:39 +0200 Subject: move Asset from crepe::api to crepe --- src/crepe/Asset.cpp | 14 ++++++++++++++ src/crepe/Asset.h | 24 ++++++++++++++++++++++++ src/crepe/CMakeLists.txt | 2 ++ src/crepe/Sound.cpp | 6 +++--- src/crepe/Sound.h | 6 +++--- src/crepe/api/Asset.cpp | 14 -------------- src/crepe/api/Asset.h | 24 ------------------------ src/crepe/api/CMakeLists.txt | 2 -- 8 files changed, 46 insertions(+), 46 deletions(-) create mode 100644 src/crepe/Asset.cpp create mode 100644 src/crepe/Asset.h delete mode 100644 src/crepe/api/Asset.cpp delete mode 100644 src/crepe/api/Asset.h (limited to 'src/crepe/api/CMakeLists.txt') diff --git a/src/crepe/Asset.cpp b/src/crepe/Asset.cpp new file mode 100644 index 0000000..15ddc27 --- /dev/null +++ b/src/crepe/Asset.cpp @@ -0,0 +1,14 @@ +#include + +#include "Asset.h" + +using namespace crepe; + +Asset::Asset(const std::string & src) { + this->src = std::filesystem::canonical(src); + this->file = std::ifstream(this->src, std::ios::in | std::ios::binary); +} + +const std::istream & Asset::read() { return this->file; } + +const char * Asset::canonical() { return this->src.c_str(); } diff --git a/src/crepe/Asset.h b/src/crepe/Asset.h new file mode 100644 index 0000000..736ba44 --- /dev/null +++ b/src/crepe/Asset.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include + +namespace crepe { + +class Asset { +public: + Asset(const std::string & src); + +public: + //! Get an input stream to the contents of this resource + const std::istream & read(); + //! Get the canonical path to this resource + const char * canonical(); + +private: + std::string src; + std::ifstream file; +}; + +} // namespace crepe diff --git a/src/crepe/CMakeLists.txt b/src/crepe/CMakeLists.txt index 3a60840..208ba1f 100644 --- a/src/crepe/CMakeLists.txt +++ b/src/crepe/CMakeLists.txt @@ -1,9 +1,11 @@ target_sources(crepe PUBLIC + Asset.cpp Sound.cpp SoundContext.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES + Asset.h Sound.h SoundContext.h ) diff --git a/src/crepe/Sound.cpp b/src/crepe/Sound.cpp index c6e87d5..73ad69c 100644 --- a/src/crepe/Sound.cpp +++ b/src/crepe/Sound.cpp @@ -5,17 +5,17 @@ using namespace crepe; -Sound::Sound(std::unique_ptr res) { +Sound::Sound(std::unique_ptr res) { dbg_trace(); this->load(std::move(res)); } Sound::Sound(const char * src) { dbg_trace(); - this->load(std::make_unique(src)); + this->load(std::make_unique(src)); } -void Sound::load(std::unique_ptr res) { +void Sound::load(std::unique_ptr res) { this->sample.load(res->canonical()); } diff --git a/src/crepe/Sound.h b/src/crepe/Sound.h index 339dd7c..1ac20a7 100644 --- a/src/crepe/Sound.h +++ b/src/crepe/Sound.h @@ -5,7 +5,7 @@ #include -#include "api/Asset.h" +#include "Asset.h" namespace crepe { @@ -66,10 +66,10 @@ public: public: Sound(const char * src); - Sound(std::unique_ptr res); + Sound(std::unique_ptr res); private: - void load(std::unique_ptr res); + void load(std::unique_ptr res); private: SoLoud::Wav sample; diff --git a/src/crepe/api/Asset.cpp b/src/crepe/api/Asset.cpp deleted file mode 100644 index 92ee50e..0000000 --- a/src/crepe/api/Asset.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include - -#include "Asset.h" - -using namespace crepe::api; - -Asset::Asset(const std::string & src) { - this->src = std::filesystem::canonical(src); - this->file = std::ifstream(this->src, std::ios::in | std::ios::binary); -} - -const std::istream & Asset::read() { return this->file; } - -const char * Asset::canonical() { return this->src.c_str(); } diff --git a/src/crepe/api/Asset.h b/src/crepe/api/Asset.h deleted file mode 100644 index 259c696..0000000 --- a/src/crepe/api/Asset.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace crepe::api { - -class Asset { -public: - Asset(const std::string & src); - -public: - //! Get an input stream to the contents of this resource - const std::istream & read(); - //! Get the canonical path to this resource - const char * canonical(); - -private: - std::string src; - std::ifstream file; -}; - -} // namespace crepe::api diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index 54c7fdc..9548594 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -1,11 +1,9 @@ target_sources(crepe PUBLIC # AudioSource.cpp - Asset.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES AudioSource.h Component.h - Asset.h ) -- cgit v1.2.3