From d7fa9eb70f7eee0406df4ca2a89cfe5b28c2d111 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 10 Apr 2014 07:39:44 +0200 Subject: [PATCH] Sound! --- deploy.bat | 1 + src/Components/SoundEmitter.h | 10 +- src/GameWorld.cpp | 19 +- src/GameWorld.h | 2 +- src/Systems/SoundSystem.cpp | 213 ++++++++++++++++++ src/Systems/SoundSystem.h | 46 ++++ vs12/Returngeance/Returngeance.vcxproj | 2 + .../Returngeance/Returngeance.vcxproj.filters | 6 + 8 files changed, 287 insertions(+), 12 deletions(-) create mode 100755 src/Systems/SoundSystem.cpp create mode 100755 src/Systems/SoundSystem.h diff --git a/deploy.bat b/deploy.bat index 6d57b2c..1c29099 100755 --- a/deploy.bat +++ b/deploy.bat @@ -11,6 +11,7 @@ ECHO Deploying %Configuration% :: Asset folders MKLINK "%ConfigPath%\Models\" "assets\Models" /J MKLINK "%ConfigPath%\Textures\" "assets\Textures\" /J +MKLINK "%ConfigPath%\Sounds\" "assets\Sounds\" /J :: Shaders MKLINK "%ConfigPath%\Shaders\" "src\Shaders\" /J :: DLLs diff --git a/src/Components/SoundEmitter.h b/src/Components/SoundEmitter.h index 8e471d5..f7dfa14 100755 --- a/src/Components/SoundEmitter.h +++ b/src/Components/SoundEmitter.h @@ -10,11 +10,11 @@ namespace Components struct SoundEmitter : Component { - float Gain; - float MaxDistance; - float ReferenceDistance; - float Pitch; - bool Loop; + float Gain = 1.f; + float MaxDistance = 1.f; + float ReferenceDistance = 1.f; + float Pitch = 1.f; + bool Loop = false; std::string Path; }; diff --git a/src/GameWorld.cpp b/src/GameWorld.cpp index 683f6a9..e329e12 100755 --- a/src/GameWorld.cpp +++ b/src/GameWorld.cpp @@ -23,7 +23,7 @@ void GameWorld::Initialize() transform->Scale = glm::vec3(1000.0f); transform->Orientation = glm::quat(glm::vec3(0.0f, 0.0f, glm::pi() / 20.f)); auto model = AddComponent(terrain, "Model"); - model->ModelFile = "Models/PhysicsTest/Plane.obj"; + model->ModelFile = "Models/Placeholders/PhysicsTest/Plane.obj"; auto physics = AddComponent(terrain, "Physics"); auto Box = AddComponent(terrain, "BoxShape"); Box->Width = 0.5f; @@ -44,7 +44,7 @@ void GameWorld::Initialize() transform->Position = glm::vec3(0, 10+i, 0); transform->Orientation = glm::quat(glm::vec3(0.0f, 0.0f, 0.0f)); auto model = AddComponent(entity, "Model"); - model->ModelFile = "Models/PhysicsTest/ArrowCube.obj"; + model->ModelFile = "Models/Placeholders/PhysicsTest/ArrowCube.obj"; auto physics = AddComponent(entity, "Physics"); physics->Mass = 10; @@ -62,7 +62,7 @@ void GameWorld::Initialize() transform->Position = glm::vec3(-5.f, 10+i, 0); transform->Orientation = glm::quat(glm::vec3(0.0f, 0.0f, 0.0f)); auto model = AddComponent(entity1, "Model"); - model->ModelFile = "Models/PhysicsTest/ArrowCube.obj"; + model->ModelFile = "Models/Placeholders/PhysicsTest/ArrowCube.obj"; auto physics = AddComponent(entity1, "Physics"); physics->Mass = 0; @@ -90,7 +90,14 @@ void GameWorld::Initialize() } - + { + auto entity = CreateEntity(); + AddComponent(entity, "Transform"); + auto emitter = AddComponent(entity, "SoundEmitter"); + emitter->Path = "Sounds/korvring.wav"; + emitter->Loop = true; + GetSystem("SoundSystem")->PlaySound(emitter); + } } @@ -135,7 +142,7 @@ void GameWorld::RegisterSystems() ////m_SystemFactory.Register("ParticleSystem", [this]() { return new Systems::ParticleSystem(this); }); //m_SystemFactory.Register("PlayerSystem", [this]() { return new Systems::PlayerSystem(this); }); m_SystemFactory.Register("FreeSteeringSystem", [this]() { return new Systems::FreeSteeringSystem(this); }); - //m_SystemFactory.Register("SoundSystem", [this]() { return new Systems::SoundSystem(this); }); + m_SystemFactory.Register("SoundSystem", [this]() { return new Systems::SoundSystem(this); }); m_SystemFactory.Register("PhysicsSystem", [this]() { return new Systems::PhysicsSystem(this); }); @@ -153,7 +160,7 @@ void GameWorld::AddSystems() ////AddSystem("ParticleSystem"); //AddSystem("PlayerSystem"); AddSystem("FreeSteeringSystem"); - //AddSystem("SoundSystem"); + AddSystem("SoundSystem"); AddSystem("PhysicsSystem"); diff --git a/src/GameWorld.h b/src/GameWorld.h index 0061f0c..0adfec3 100755 --- a/src/GameWorld.h +++ b/src/GameWorld.h @@ -12,7 +12,7 @@ //#include "Systems/PlayerSystem.h" #include "Systems/FreeSteeringSystem.h" #include "Systems/RenderSystem.h" -//#include "Systems/SoundSystem.h" +#include "Systems/SoundSystem.h" #include "Systems/PhysicsSystem.h" #include "Components/Bounds.h" diff --git a/src/Systems/SoundSystem.cpp b/src/Systems/SoundSystem.cpp new file mode 100755 index 0000000..ce53256 --- /dev/null +++ b/src/Systems/SoundSystem.cpp @@ -0,0 +1,213 @@ +#include "PrecompiledHeader.h" +#include "SoundSystem.h" +#include "World.h" + +Systems::SoundSystem::SoundSystem(World* world) + : System(world) +{ + //initialize OpenAL + ALCdevice* Device = alcOpenDevice(NULL); + ALCcontext* context; + if(Device) + { + context = alcCreateContext(Device, NULL); + alcMakeContextCurrent(context); + } + else + { + LOG_ERROR("OMG OPEN AL FAIL"); + } + + alGetError(); + + alSpeedOfSound(340.29f); // Speed of sound + alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); +} + +void Systems::SoundSystem::Update(double dt) +{ + +} + +void Systems::SoundSystem::UpdateEntity(double dt, EntityID entity, EntityID parent) +{ + auto transformComponent = m_World->GetComponent(entity, "Transform"); + if (transformComponent == nullptr) + return; + + auto entityName = m_World->GetProperty(entity, "Name"); + if (entityName == "Camera") + { + glm::vec3 playerPos = transformComponent->Position; + ALfloat listenerPos[3] = { playerPos.x, playerPos.y, -playerPos.z }; + + glm::vec3 playerVel = transformComponent->Velocity; + ALfloat listenerVel[3] = { playerVel.x, playerVel.y, -playerVel.z }; + + glm::fquat playerQuatOri = transformComponent->Orientation; + glm::vec3 playerOriFW = glm::rotate(playerQuatOri, glm::vec3(0, 0, -1)); + glm::vec3 playerOriUP = glm::rotate(playerQuatOri, glm::vec3(0, 1, 0)); + ALfloat listenerOri[6] = { playerOriFW.x, playerOriFW.y, playerOriFW.z, playerOriUP.x, playerOriUP.y, playerOriUP.z }; + + //Listener + alListenerfv(AL_POSITION, listenerPos); + alListenerfv(AL_VELOCITY, listenerVel); + alListenerfv(AL_ORIENTATION, listenerOri); + } + + auto soundEmitter = m_World->GetComponent(entity, "SoundEmitter"); + if(soundEmitter != nullptr) + { + ALuint source = m_Sources[soundEmitter]; + alSourcef(source, AL_GAIN, soundEmitter->Gain); + //alSourcef(source, AL_MAX_DISTANCE, soundEmitter->MaxDistance); + alSourcef(source, AL_REFERENCE_DISTANCE, soundEmitter->ReferenceDistance); + alSourcef(source, AL_PITCH, soundEmitter->Pitch); + alSourcei(source, AL_LOOPING, soundEmitter->Loop); + + glm::vec3 emitterPos = transformComponent->Position; + ALfloat sourcePos[3] = { emitterPos.x, emitterPos.y, -emitterPos.z }; + + glm::vec3 emitterVel= transformComponent->Velocity; + ALfloat sourceVel[3] = { emitterVel.x, emitterVel.y, -emitterVel.z }; + + alSourcefv(source, AL_POSITION, sourcePos); + alSourcefv(source, AL_VELOCITY, sourceVel); + } +} + +void Systems::SoundSystem::PlaySound(Components::SoundEmitter* emitter, std::string fileName) +{ + if (m_Sources.find(emitter) == m_Sources.end()) + return; + + ALuint buffer = LoadFile(fileName); + if (buffer == 0) + return; + ALuint source = m_Sources[emitter]; + alSourcei(source, AL_BUFFER, buffer); + alSourcePlay(m_Sources[emitter]); +} + +void Systems::SoundSystem::PlaySound(std::shared_ptr emitter) +{ + ALuint buffer = LoadFile(emitter->Path); + ALuint source = m_Sources[emitter.get()]; + alSourcei(source, AL_BUFFER, buffer); + alSourcePlay(m_Sources[emitter.get()]); +} + +void Systems::SoundSystem::StopSound(std::shared_ptr emitter) +{ + alSourceStop(m_Sources[emitter.get()]); +} + +void Systems::SoundSystem::OnComponentCreated(std::string type, std::shared_ptr component) +{ + if(type == "SoundEmitter") { + ALuint source = CreateSource(); + m_Sources[component.get()] = source; + } +} + +void Systems::SoundSystem::OnComponentRemoved(std::string type, Component* component) +{ + if(type == "SoundEmitter") { + if (m_Sources.find(component) != m_Sources.end()) { + ALuint source = m_Sources[component]; + alDeleteSources(1, &source); + } + } +} + +ALuint Systems::SoundSystem::LoadFile(std::string path) +{ + if (m_BufferCache.find(path) != m_BufferCache.end()) + return m_BufferCache[path]; + + FILE *fp = NULL; + fp = fopen(path.c_str(), "rb"); + + if (fp == NULL) { + LOG_ERROR("Failed to load sound file \"%s\"", path.c_str()); + return 0; + } + + //CHECK FOR VALID WAVE-FILE + fread(type, sizeof(char), 4, fp); + if(type[0]!='R' || type[1]!='I' || type[2]!='F' || type[3]!='F') { + LOG_ERROR("ERROR: No RIFF in WAVE-file"); + return 0; + } + + fread(&size, sizeof(unsigned long), 1, fp); + fread(type, sizeof(char), 4, fp); + if(type[0]!='W' || type[1]!='A' || type[2]!='V' || type[3]!='E') { + LOG_ERROR("ERROR: Not WAVE-file"); + return 0; + } + + fread(type, sizeof(char), 4, fp); + if(type[0]!='f' || type[1]!='m' || type[2]!='t' || type[3]!=' ') { + LOG_ERROR("ERROR: No fmt in WAVE-file"); + return 0; + } + + //READ THE DATA FROM WAVE-FILE + fread(&chunkSize, sizeof(unsigned long), 1, fp); + fread(&formatType, sizeof(short), 1, fp); + fread(&channels, sizeof(short), 1, fp); + fread(&sampleRate, sizeof(unsigned long), 1, fp); + fread(&avgBytesPerSec, sizeof(unsigned long), 1, fp); + fread(&bytesPerSample, sizeof(short), 1, fp); + fread(&bitsPerSample, sizeof(short), 1, fp); + + fread(type, sizeof(char), 4, fp); + if(type[0]!='d' || type[1]!='a' || type[2]!='t' || type[3]!='a') + { + LOG_ERROR("ERROR: WAVE-file Missing data"); + return 0; + } + + fread(&dataSize, sizeof(unsigned long), 1, fp); + + unsigned char* buf = new unsigned char[dataSize]; + fread(buf, sizeof(unsigned char), dataSize, fp); + fclose(fp); + + // Create buffer + ALuint format = 0; + if(bitsPerSample == 8) + { + if(channels == 1) + format = AL_FORMAT_MONO8; + else if(channels == 2) + format = AL_FORMAT_STEREO8; + } + if(bitsPerSample == 16) + { + if (channels == 1) + format = AL_FORMAT_MONO16; + else if (channels == 2) + format = AL_FORMAT_STEREO16; + } + + ALuint buffer; + alGenBuffers(1, &buffer); + alBufferData(buffer, format, buf, dataSize, sampleRate); + delete[] buf; + + m_BufferCache[path] = buffer; + return buffer; +} + +ALuint Systems::SoundSystem::CreateSource() +{ + ALuint source; + alGenSources((ALuint)1, &source); + + alDopplerFactor(1); // Numbers greater than 1 will increase Doppler effect, numbers lower than 1 will decrease the Doppler effect + alDopplerVelocity(350.f); // Defines the velocity of the sound + + return source; +} \ No newline at end of file diff --git a/src/Systems/SoundSystem.h b/src/Systems/SoundSystem.h new file mode 100755 index 0000000..33b51d9 --- /dev/null +++ b/src/Systems/SoundSystem.h @@ -0,0 +1,46 @@ +#ifndef SoundEmitter_h__ +#define SoundEmitter_h__ + +#include "System.h" +#include "Components/Transform.h" +#include "Components/SoundEmitter.h" +#include +#include +#include + +namespace Systems +{ + +class SoundSystem : public System +{ +public: + SoundSystem(World* world); + + void Update(double dt) override; + void UpdateEntity(double dt, EntityID entity, EntityID parent) override; + void OnComponentCreated(std::string type, std::shared_ptr component) override; + void OnComponentRemoved(std::string type, Component* component) override; + void PlaySound(Components::SoundEmitter* emitter, std::string path); // Use if you want to play a temporary .wav file not from component + void PlaySound(std::shared_ptr emitter); // Use if you want to play .wav file from component // imon no hate plx T.T + void StopSound(std::shared_ptr emitter); + +private: + ALuint LoadFile(std::string fileName); + ALuint CreateSource(); + + //File-info + char type[4]; + unsigned long size, chunkSize; + short formatType, channels; + unsigned long sampleRate, avgBytesPerSec; + short bytesPerSample, bitsPerSample; + unsigned long dataSize; + + + std::map m_Sources; + std::map m_BufferCache; // string = fileName +}; + +} +#endif // !SoundEmitter_h__ + diff --git a/vs12/Returngeance/Returngeance.vcxproj b/vs12/Returngeance/Returngeance.vcxproj index 31927eb..81e3b0e 100755 --- a/vs12/Returngeance/Returngeance.vcxproj +++ b/vs12/Returngeance/Returngeance.vcxproj @@ -104,6 +104,7 @@ + @@ -153,6 +154,7 @@ + diff --git a/vs12/Returngeance/Returngeance.vcxproj.filters b/vs12/Returngeance/Returngeance.vcxproj.filters index cc54cba..0c5d439 100755 --- a/vs12/Returngeance/Returngeance.vcxproj.filters +++ b/vs12/Returngeance/Returngeance.vcxproj.filters @@ -31,6 +31,9 @@ Systems + + Systems + @@ -160,6 +163,9 @@ Components + + Systems +