diff --git a/include/Engine/Sound/EContinueSound.h b/include/Engine/Sound/EContinueSound.h index 2c624b0b..707d5c6b 100644 --- a/include/Engine/Sound/EContinueSound.h +++ b/include/Engine/Sound/EContinueSound.h @@ -6,7 +6,7 @@ namespace Events { - +// Continues to play a sound from where it was paused. struct ContinueSound : Event { EntityID EmitterID; diff --git a/include/Engine/Sound/EPauseSound.h b/include/Engine/Sound/EPauseSound.h index f9e2e6f0..33d57428 100644 --- a/include/Engine/Sound/EPauseSound.h +++ b/include/Engine/Sound/EPauseSound.h @@ -6,7 +6,7 @@ namespace Events { - +// Pauses a playing sound struct PauseSound : Event { EntityID EmitterID; diff --git a/include/Engine/Sound/EPlayBackgroundMusic.h b/include/Engine/Sound/EPlayBackgroundMusic.h index 4276ad4a..711954ee 100644 --- a/include/Engine/Sound/EPlayBackgroundMusic.h +++ b/include/Engine/Sound/EPlayBackgroundMusic.h @@ -7,7 +7,7 @@ namespace Events { - +// Play a sound that will be heared the same anywhere struct PlayBackgroundMusic : public Event { std::string FilePath = ""; diff --git a/include/Engine/Sound/EPlaySound.h b/include/Engine/Sound/EPlaySound.h deleted file mode 100644 index 9c9eab0a..00000000 --- a/include/Engine/Sound/EPlaySound.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef Events_PlaySound_h__ -#define Events_PlaySound_h__ - -#include "Core/EventBroker.h" -#include "Core/Entity.h" - -namespace Events -{ - - struct PlaySound : Event -{ - std::string FilePath; - EntityID EmitterID; -}; - -} - -#endif \ No newline at end of file diff --git a/include/Engine/Sound/EPlaySoundOnEntity.h b/include/Engine/Sound/EPlaySoundOnEntity.h index 39dea432..fb4b7a15 100644 --- a/include/Engine/Sound/EPlaySoundOnEntity.h +++ b/include/Engine/Sound/EPlaySoundOnEntity.h @@ -10,6 +10,7 @@ namespace Events // Plays a sound on an entity with a SoundEmitter component attached. // Sound behavior is thereby specified in the SoundEmitter component. +// ?(???)?? struct PlaySoundOnEntity : public Event { EntityID EmitterID = 0; diff --git a/include/Engine/Sound/EPlaySoundOnPosition.h b/include/Engine/Sound/EPlaySoundOnPosition.h index 324b8fae..9c6f8f26 100644 --- a/include/Engine/Sound/EPlaySoundOnPosition.h +++ b/include/Engine/Sound/EPlaySoundOnPosition.h @@ -8,7 +8,7 @@ namespace Events { -// Plays a sound on a given position +// Plays a sound on a given position. Idk if this would be useful. struct PlaySoundOnPosition : public Event { glm::vec3 Position = glm::vec3(0); diff --git a/include/Engine/Sound/ESetBGMGain.h b/include/Engine/Sound/ESetBGMGain.h index 4efe34ce..1be6aa24 100644 --- a/include/Engine/Sound/ESetBGMGain.h +++ b/include/Engine/Sound/ESetBGMGain.h @@ -5,7 +5,7 @@ namespace Events { - +// Set the "volume" for all background sounds struct SetBGMGain : public Event { float Gain; diff --git a/include/Engine/Sound/ESetSFXGain.h b/include/Engine/Sound/ESetSFXGain.h index cbc06e97..88465cc1 100644 --- a/include/Engine/Sound/ESetSFXGain.h +++ b/include/Engine/Sound/ESetSFXGain.h @@ -5,7 +5,7 @@ namespace Events { - +// Set the "volume" for all effect sounds struct SetSFXGain : public Event { float Gain; diff --git a/include/Engine/Sound/EStopSound.h b/include/Engine/Sound/EStopSound.h index b6cd37b8..62644fbe 100644 --- a/include/Engine/Sound/EStopSound.h +++ b/include/Engine/Sound/EStopSound.h @@ -6,7 +6,7 @@ namespace Events { - +// Stops a sound emitter, and will also delete it. struct StopSound : Event { EntityID EmitterID; diff --git a/include/Engine/Sound/SoundSystem.h b/include/Engine/Sound/SoundSystem.h index 43d670d0..ae30a682 100644 --- a/include/Engine/Sound/SoundSystem.h +++ b/include/Engine/Sound/SoundSystem.h @@ -12,7 +12,6 @@ #include "Core/EventBroker.h" #include "Rendering/RenderQueueFactory.h" // Absolute transform #include "Sound/Sound.h" -#include "Sound/EPlaySound.h" #include "Sound/EPlaySoundOnEntity.h" #include "Sound/EPlaySoundOnPosition.h" #include "Sound/EPlayBackgroundMusic.h" @@ -22,13 +21,17 @@ #include "Sound/ESetBGMGain.h" #include "Sound/ESetSFXGain.h" +enum class SoundType { + SFX, + BGM +}; struct Source { Source() { } Sound* SoundResource = nullptr; ALuint ALsource; - bool HasBeenPlayed = false; + SoundType Type; }; class SoundSystem @@ -42,15 +45,15 @@ public: private: // Help functions for working with OpenaAL void setListenerPos(glm::vec3 pos) { alListener3f(AL_POSITION, pos.x, pos.y, pos.z); }; - glm::vec3 listnerPos() { glm::vec3 pos; alGetListener3f(AL_POSITION, &pos.x, &pos.y, &pos.z); return pos; }; void setListenerVel(glm::vec3 vel) { alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z); }; - glm::vec3 listenerVel() { glm::vec3 vel; alGetListener3f(AL_VELOCITY, &vel.x, &vel.y, &vel.z); return vel; }; void setListenerOri(glm::vec3 ori); + glm::vec3 listnerPos() { glm::vec3 pos; alGetListener3f(AL_POSITION, &pos.x, &pos.y, &pos.z); return pos; }; + glm::vec3 listenerVel() { glm::vec3 vel; alGetListener3f(AL_VELOCITY, &vel.x, &vel.y, &vel.z); return vel; }; glm::vec3 listenerOri() { glm::vec3 ori; alGetListener3f(AL_ORIENTATION, &ori.x, &ori.y, &ori.z); return ori; }; void setSourcePos(ALuint source, glm::vec3 pos) { ALfloat spos[3] = { pos.x, pos.y, pos.z }; alSourcefv(source, AL_POSITION, spos); }; void setSourceVel(ALuint source, glm::vec3 vel) { ALfloat svel[3] = { vel.x, vel.y, vel.z }; alSourcefv(source, AL_VELOCITY, svel); }; - // Logic + // Logic void initOpenAL(); void updateEmitters(); void updateListener(); @@ -60,9 +63,9 @@ private: void playSound(Source* source); void stopSound(Source* source); void stopEmitters(); - bool isPlaying(ALuint source); + ALenum getSourceState(ALuint source); void setGain(Source* source, float gain); - void setSoundProperties(ALuint source, float gain, float pitch, bool loop, float maxDistance, float rollOffFactor, float referenceDistance); + void setSoundProperties(ALuint source, ComponentWrapper* soundComponent); // OpenAL system variables ALCdevice* m_ALCdevice = nullptr; @@ -72,25 +75,23 @@ private: World* m_World = nullptr; EventBroker* m_EventBroker = nullptr; std::unordered_map m_Sources; - float m_BGMVolumeChannel = 1.f; + float m_BGMVolumeChannel = 1.0f; float m_SFXVolumeChannel = 1.f; bool m_EditorEnabled = false; // Events - EventRelay m_EPlaySound; - bool OnPlaySound(const Events::PlaySound &e); EventRelay m_EPlaySoundOnEntity; bool OnPlaySoundOnEntity(const Events::PlaySoundOnEntity &e); EventRelay m_EPlaySoundOnPosition; bool OnPlaySoundOnPosition(const Events::PlaySoundOnPosition &e); + EventRelay m_EPlayBackgroundMusic; + bool OnPlayBackgroundMusic(const Events::PlayBackgroundMusic &e); EventRelay m_EPauseSound; bool OnPauseSound(const Events::PauseSound &e); EventRelay m_EStopSound; bool OnStopSound(const Events::StopSound &e); EventRelay m_EContinueSound; bool OnContinueSound(const Events::ContinueSound &e); - EventRelay m_EPlayBackgroundMusic; - bool OnPlayBackgroundMusic(const Events::PlayBackgroundMusic &e); EventRelay m_ESetBGMGain; bool OnSetBGMGain(const Events::SetBGMGain &e); // Not tested EventRelay m_ESetSFXGain; diff --git a/src/Engine/Sound/SoundSystem.cpp b/src/Engine/Sound/SoundSystem.cpp index b5c63d13..ced5f484 100644 --- a/src/Engine/Sound/SoundSystem.cpp +++ b/src/Engine/Sound/SoundSystem.cpp @@ -8,38 +8,24 @@ SoundSystem::SoundSystem(World* world, EventBroker* eventBroker, bool editorMode initOpenAL(); - alSpeedOfSound(340.29f); // Speed of sound + alSpeedOfSound(340.29f); alDistanceModel(AL_LINEAR_DISTANCE); alDopplerFactor(1); - EVENT_SUBSCRIBE_MEMBER(m_EPlaySound, &SoundSystem::OnPlaySound); EVENT_SUBSCRIBE_MEMBER(m_EPlaySoundOnEntity, &SoundSystem::OnPlaySoundOnEntity); EVENT_SUBSCRIBE_MEMBER(m_EPlaySoundOnPosition, &SoundSystem::OnPlaySoundOnPosition); + EVENT_SUBSCRIBE_MEMBER(m_EPlayBackgroundMusic, &SoundSystem::OnPlayBackgroundMusic); EVENT_SUBSCRIBE_MEMBER(m_EStopSound, &SoundSystem::OnStopSound); EVENT_SUBSCRIBE_MEMBER(m_EPauseSound, &SoundSystem::OnPauseSound); EVENT_SUBSCRIBE_MEMBER(m_EContinueSound, &SoundSystem::OnContinueSound); - EVENT_SUBSCRIBE_MEMBER(m_EPlayBackgroundMusic, &SoundSystem::OnPlayBackgroundMusic); - //EVENT_SUBSCRIBE_MEMBER(m_ESetBGMGain, &SoundSystem::SetBGMGain); - //EVENT_SUBSCRIBE_MEMBER(m_ESetSFXGain, &SoundSystem::OnSetSFXGain); -} - -void SoundSystem::initOpenAL() -{ - // Initialize OpenAL - m_ALCdevice = alcOpenDevice(nullptr); - if (m_ALCdevice != nullptr) { - m_ALCcontext = alcCreateContext(m_ALCdevice, nullptr); - alcMakeContextCurrent(m_ALCcontext); - } else { - LOG_ERROR("OpenAL failed to initialize."); - } + EVENT_SUBSCRIBE_MEMBER(m_ESetBGMGain, &SoundSystem::OnSetBGMGain); + EVENT_SUBSCRIBE_MEMBER(m_ESetSFXGain, &SoundSystem::OnSetSFXGain); } SoundSystem::~SoundSystem() { stopEmitters(); // Stopps emitters deleteInactiveEmitters(); // Deletes stopped emitters - // Delete entities std::unordered_map::iterator it; for (it = m_Sources.begin(); it != m_Sources.end(); it++) { @@ -49,58 +35,49 @@ SoundSystem::~SoundSystem() alcDestroyContext(m_ALCcontext); alcCloseDevice(m_ALCdevice); - delete m_ALCcontext; - delete m_ALCdevice; } void SoundSystem::stopEmitters() { std::unordered_map::iterator it; for (it = m_Sources.begin(); it != m_Sources.end(); it++) { - if (isPlaying((*it).second->ALsource)) { + if (getSourceState((*it).second->ALsource) == AL_PLAYING) { stopSound((*it).second); } } } void SoundSystem::Update() -{ - addNewEmitters(); - deleteInactiveEmitters(); +{ + addNewEmitters(); // can be optimized with "EEntityCreated" + deleteInactiveEmitters(); // can be optimized with "EEntityDeleted" updateEmitters(); updateListener(); } void SoundSystem::deleteInactiveEmitters() { - auto emitterComponents = m_World->GetComponents("SoundEmitter"); - for (auto it = emitterComponents->begin(); it != emitterComponents->end();) { - EntityID emitter = (*it).EntityID; - Source* source = m_Sources[emitter]; - if (isPlaying(source->ALsource) || !source->HasBeenPlayed) { // The sound is still playing, do not remove - it++; - continue; - } - else { - alDeleteBuffers(1, &source->ALsource); - alDeleteSources(1, &source->ALsource); - //delete m_Sources[emitter]->SoundResource; - m_Sources.erase(emitter); - m_World->DeleteEntity(emitter); - } - } - std::unordered_map::iterator it; for (it = m_Sources.begin(); it != m_Sources.end();) { if (m_World->ValidEntity((*it).first)) { - // Entity is valid, move on. - it++; - continue; + if (getSourceState(it->second->ALsource) != AL_STOPPED) { + // Nothing to see here, move along + it++; + continue; + } else { + // Sound has been stopped / finished playing + alDeleteBuffers(1, &it->second->ALsource); + alDeleteSources(1, &it->second->ALsource); + delete it->second->SoundResource; + m_World->DeleteEntity(it->first); + it = m_Sources.erase(it); + } } else { + // Entity has been removed stopSound((*it).second); - alDeleteBuffers(1, &m_Sources[(*it).first]->ALsource); - alDeleteSources(1, &m_Sources[(*it).first]->ALsource); - //delete m_Sources[emitter]->SoundResource; + alDeleteBuffers(1, &it->second->ALsource); + alDeleteSources(1, &it->second->ALsource); + delete it->second->SoundResource; it = m_Sources.erase(it); } } @@ -111,19 +88,10 @@ void SoundSystem::addNewEmitters() auto emitterComponents = m_World->GetComponents("SoundEmitter"); for (auto it = emitterComponents->begin(); it != emitterComponents->end(); it++) { EntityID emitter = (*it).EntityID; - std::unordered_map::iterator i; - i = m_Sources.find(emitter); - if (i == m_Sources.end()) { // Did not exist, add it + std::unordered_map::iterator source; + source = m_Sources.find(emitter); + if (source == m_Sources.end()) { // Did not exist, add it Source* source = createSource((std::string)(*it)["FilePath"]); - setSoundProperties( - source->ALsource, - (float)(double)(*it)["Gain"], - (float)(double)(*it)["Pitch"], - (bool)(*it)["Loop"], - (float)(double)(*it)["MaxDistance"], - (float)(double)(*it)["RollOffFactor"], - (float)(double)(*it)["ReferenceDistance"] - ); m_Sources[emitter] = source; } } @@ -131,45 +99,30 @@ void SoundSystem::addNewEmitters() void SoundSystem::updateEmitters() { - auto emitterComponents = m_World->GetComponents("SoundEmitter"); - for (auto it = emitterComponents->begin(); it != emitterComponents->end();) { - EntityID emitter = (*it).EntityID; - if (!m_World->ValidEntity(emitter)) { // Entity has been deleted - // Delete - } else { - std::unordered_map::iterator i; - i = m_Sources.find(emitter); - if (i != m_Sources.end()) { - // Get previous pos - glm::vec3 previousPos; - alGetSource3f(i->second->ALsource, AL_POSITION, &previousPos.x, &previousPos.y, &previousPos.z); - // Get next pos - glm::vec3 nextPos = RenderQueueFactory::AbsolutePosition(m_World, emitter); - // Calculate velocity - glm::vec3 velocity = nextPos - previousPos; - setSourcePos(i->second->ALsource, nextPos); - setSourceVel(i->second->ALsource, velocity); - setSoundProperties( - i->second->ALsource, - (float)(double)(*it)["Gain"], - (float)(double)(*it)["Pitch"], - (bool)(*it)["Loop"], - (float)(double)(*it)["MaxDistance"], - (float)(double)(*it)["RollOffFactor"], - (float)(double)(*it)["ReferenceDistance"] - ); + std::unordered_map::iterator it; + for (it = m_Sources.begin(); it != m_Sources.end(); it++) { + // Get previous pos + glm::vec3 previousPos; + alGetSource3f(it->second->ALsource, AL_POSITION, &previousPos.x, &previousPos.y, &previousPos.z); + // Get next pos + glm::vec3 nextPos = RenderQueueFactory::AbsolutePosition(m_World, it->first); + // Calculate velocity + glm::vec3 velocity = nextPos - previousPos; + setSourcePos(it->second->ALsource, nextPos); + setSourceVel(it->second->ALsource, velocity); + float gain; + (bool)(it->second->Type) ? gain = m_SFXVolumeChannel : gain = m_BGMVolumeChannel; + auto emitter = m_World->GetComponent(it->first, "SoundEmitter"); + setSoundProperties(it->second->ALsource, &emitter); - // To make an emitter play when spawned in editor mode - if (m_EditorEnabled) { - // Path changed - if (i->second->SoundResource->Path() != (std::string)(*it)["FilePath"]) { - i->second->SoundResource = ResourceManager::Load((std::string)(*it)["FilePath"]); - if (i->second->SoundResource->Buffer() != 0) { - playSound(i->second); - } - } + // To make an emitter play when spawned in editor mode + if (m_EditorEnabled) { + // Path changed + if (it->second->SoundResource->Path() != (std::string)emitter["FilePath"]) { + it->second->SoundResource = ResourceManager::Load((std::string)emitter["FilePath"]); + if (it->second->SoundResource->Buffer() != 0) { + playSound(it->second); } - it++; } } } @@ -207,7 +160,6 @@ void SoundSystem::playSound(Source* source) { alSourcei(source->ALsource, AL_BUFFER, source->SoundResource->Buffer()); alSourcePlay(source->ALsource); - source->HasBeenPlayed = true; } void SoundSystem::stopSound(Source* source) @@ -215,16 +167,10 @@ void SoundSystem::stopSound(Source* source) alSourceStop(source->ALsource); } -bool SoundSystem::OnPlaySound(const Events::PlaySound & e) -{ - Source* sauce = createSource(e.FilePath); - playSound(sauce); - return false; -} - bool SoundSystem::OnPlaySoundOnEntity(const Events::PlaySoundOnEntity & e) { Source* source = createSource(e.FilePath); + source->Type = SoundType::SFX; m_Sources[e.EmitterID] = source; playSound(source); return false; @@ -245,6 +191,7 @@ bool SoundSystem::OnPlaySoundOnPosition(const Events::PlaySoundOnPosition & e) (float&)(double)emitter["ReferenceDistance"] = e.ReferenceDistance; auto model = m_World->AttachComponent(emitterID, "Model"); (std::string&)model["Resource"] = "Models/Core/UnitCube.obj"; + source->Type = SoundType::SFX; m_Sources[emitterID] = source; playSound(source); return false; @@ -278,6 +225,7 @@ bool SoundSystem::OnPlayBackgroundMusic(const Events::PlayBackgroundMusic & e) (std::string&)emitter["FilePath"] = e.FilePath; m_World->AttachComponent(emitterChild, "Transform"); Source* source = createSource(e.FilePath); + source->Type = SoundType::BGM; m_Sources[emitterChild] = source; playSound(source); } @@ -312,11 +260,11 @@ void SoundSystem::setListenerOri(glm::vec3 ori) alListenerfv(AL_ORIENTATION, lOri); } -bool SoundSystem::isPlaying(ALuint source) +ALenum SoundSystem::getSourceState(ALuint source) { ALenum state; alGetSourcei(source, AL_SOURCE_STATE, &state); - return (state == AL_PLAYING); + return state; } void SoundSystem::setGain(Source * source, float gain) @@ -324,12 +272,24 @@ void SoundSystem::setGain(Source * source, float gain) alSourcef(source->ALsource, AL_GAIN, gain); } -void SoundSystem::setSoundProperties(ALuint source, float gain, float pitch, bool loop, float maxDistance, float rollOffFactor, float referenceDistance) +void SoundSystem::setSoundProperties(ALuint source, ComponentWrapper* soundComponent) { - alSourcef(source, AL_GAIN, gain * m_SFXVolumeChannel); - alSourcef(source, AL_PITCH, pitch); - alSourcei(source, AL_LOOPING, (int)loop); // YOLO - alSourcef(source, AL_MAX_DISTANCE, maxDistance); - alSourcef(source, AL_ROLLOFF_FACTOR, rollOffFactor); - alSourcef(source, AL_REFERENCE_DISTANCE, referenceDistance); + alSourcef(source, AL_GAIN, (float)(double)(*soundComponent)["Gain"]); + alSourcef(source, AL_PITCH, (float)(double)(*soundComponent)["Pitch"]); + alSourcei(source, AL_LOOPING, (int)(bool)(*soundComponent)["Loop"]); // YOLO + alSourcef(source, AL_MAX_DISTANCE, (float)(double)(*soundComponent)["MaxDistance"]); + alSourcef(source, AL_ROLLOFF_FACTOR, (float)(double)(*soundComponent)["RollOffFactor"]); + alSourcef(source, AL_REFERENCE_DISTANCE, (float)(double)(*soundComponent)["ReferenceDistance"]); } + +void SoundSystem::initOpenAL() +{ + // Initialize OpenAL + m_ALCdevice = alcOpenDevice(nullptr); + if (m_ALCdevice != nullptr) { + m_ALCcontext = alcCreateContext(m_ALCdevice, nullptr); + alcMakeContextCurrent(m_ALCcontext); + } else { + LOG_ERROR("OpenAL failed to initialize."); + } +} \ No newline at end of file diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 95846e52..640f77c0 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -144,7 +144,7 @@ bool Game::debugOnInputCommand(const Events::InputCommand & e) { if (e.Command == "PlaySound" && e.Value > 0) { Events::PlayBackgroundMusic e; - e.FilePath = "Audio/crosscounter.wav"; + e.FilePath = "Audio/5dollar.wav"; //e.emitterID = 18; // rofl m_EventBroker->Publish(e); }