From ae65ef53fc8b70ebee3b43bb06ecd091aaae2a26 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Thu, 17 Jul 2008 14:19:18 +0000 Subject: engine sounds --- src/audio/audio.cc | 41 ++++++++++++++++++++++++++++++++++++ src/audio/audio.h | 13 ++++++++++++ src/audio/sources.cc | 26 +++++++++++++++++++++++ src/audio/sources.h | 4 ++++ src/client/client.cc | 6 ++++++ src/client/client.h | 4 ++++ src/client/view.cc | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ src/core/application.cc | 6 ++++++ src/core/application.h | 3 +++ src/core/clientstate.cc | 18 +++++++++++++++- src/core/clientstate.h | 5 +++++ 11 files changed, 180 insertions(+), 1 deletion(-) diff --git a/src/audio/audio.cc b/src/audio/audio.cc index 1895d21..ff0918d 100644 --- a/src/audio/audio.cc +++ b/src/audio/audio.cc @@ -91,4 +91,45 @@ void play(const char *name) } } +void update_source(size_t source_index, math::Vector3f const & location, math::Vector3f const & velocity, float pitch, float gain) +{ + ALuint source = Sources::source(source_index); + alSourcefv(source, AL_POSITION, location.ptr()); + //alSourcefv(source, AL_VELOCITY, velocity.ptr()); + alSourcef(source, AL_PITCH, pitch); + alSourcef(source, AL_GAIN, gain); +} + +void loop( size_t source_index, const char *name, float pitch, float gain) +{ + if (!audio_context) + return; + + ALuint source = Sources::source(source_index); + Buffers::bind(source, Buffers::load(std::string(name))); + + alSourcef(source, AL_PITCH, pitch); + alSourcef(source, AL_GAIN, gain); + + alSourcei(source, AL_LOOPING, AL_TRUE); + alSourceRewind(source); + alSourcePlay(source); +} + +void update_listener(math::Vector3f const &location, math::Axis const &axis, float speed) +{ + alListenerfv(AL_POSITION, location.ptr()); + + math::Vector3f velocity(axis.forward()); + velocity = velocity * speed; + //alListenerfv(AL_VELOCITY, velocity.ptr()); + + ALfloat orientation[6]; + for (size_t i =0; i <3; i++) { + orientation[i] = axis.forward()[i]; + orientation[i+3] = axis.up()[i]; + } + alListenerfv(AL_ORIENTATION, orientation); +} + } diff --git a/src/audio/audio.h b/src/audio/audio.h index bf97a4a..629ae88 100644 --- a/src/audio/audio.h +++ b/src/audio/audio.h @@ -7,6 +7,8 @@ #ifndef __INCLUDED_AUDIO_AUDIO_H__ #define __INCLUDED_AUDIO_AUDIO_H__ +#include + #ifdef _WIN32 #include #endif @@ -14,6 +16,9 @@ #include "AL/al.h" #include "AL/alc.h" +#include "math/vector3f.h" +#include "math/axis.h" + /// functions to handle audio namespace audio { @@ -30,6 +35,14 @@ void load(const char *name); /// play a previously loaded audio sample void play(const char *name); +/// play a looping sound on a specified source +void loop( size_t source_index, const char *name, float pitch=1.0f, float gain=1.0f); + +/// update source parameters +void update_source(size_t source_index, math::Vector3f const & location, math::Vector3f const & velocity, float pitch=1.0f, float gain=1.0f); + +/// update listener parameters +void update_listener(math::Vector3f const &location, math::Axis const &axis, float speed); } #endif // __INCLUDED_AUDIO_AUDIO_H__ diff --git a/src/audio/sources.cc b/src/audio/sources.cc index 2c67304..3a6b3fc 100644 --- a/src/audio/sources.cc +++ b/src/audio/sources.cc @@ -53,4 +53,30 @@ void Sources::clear() } +size_t Sources::get() +{ + for (size_t i= MAXUISOURCES; i < MAXSOURCES; i++) { + if (source_available[i]) { + source_available[i] = false; + alSourcef(sources[i], AL_PITCH, 1.0); + alSourcef(sources[i], AL_GAIN, 1.0); + //con_debug << "reserved source " << i << std::endl; + return i; + } + } + return 0; +} + +void Sources::remove(size_t index) +{ + if ( (index < MAXUISOURCES ) || (MAXSOURCES <= index)) + return; + + source_available[index] = true; + alSourcef(sources[index], AL_GAIN, 0); + alSourceRewind(sources[index]); + + //con_debug << "removed source " << index << std::endl; +} + } diff --git a/src/audio/sources.h b/src/audio/sources.h index 302d5d5..078c424 100644 --- a/src/audio/sources.h +++ b/src/audio/sources.h @@ -27,6 +27,10 @@ public: static inline bool available(size_t index) { return source_available[index]; } static inline ALuint source(size_t index) { return sources[index]; } + + static size_t get(); + static void remove(size_t index); + private: static void clear(); diff --git a/src/client/client.cc b/src/client/client.cc index a3219e6..2f60fce 100644 --- a/src/client/client.cc +++ b/src/client/client.cc @@ -11,6 +11,7 @@ #include #include "audio/audio.h" +#include "audio/sources.h" #include "client/chat.h" #include "client/client.h" #include "client/video.h" @@ -165,6 +166,11 @@ void Client::notify_sound(const char * name) audio::play(name); } +void Client::notify_remove_sound(size_t source) +{ + audio::Sources::remove(source); +} + void Client::notify_message(std::string const & message) { con_print << message << std::endl; diff --git a/src/client/client.h b/src/client/client.h index 8bd6d45..9b60671 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -33,6 +33,10 @@ public: /// text notifications from the core virtual void notify_message(std::string const & message); + + /// remove sound source notification + virtual void notify_remove_sound(size_t source); + }; diff --git a/src/client/view.cc b/src/client/view.cc index 63718e1..7038a47 100644 --- a/src/client/view.cc +++ b/src/client/view.cc @@ -11,6 +11,8 @@ #include #include +#include "audio/audio.h" +#include "audio/sources.h" #include "client/client.h" #include "client/chat.h" #include "client/console.h" @@ -34,6 +36,7 @@ core::Cvar *draw_stats = 0; core::Cvar *draw_location = 0; core::Cvar *draw_radar = 0; +core::Cvar *snd_engines = 0; core::Cvar *cl_crosshaircolor = 0; namespace view @@ -57,6 +60,9 @@ void init() cl_crosshaircolor = core::Cvar::get("cl_crosshaircolor", "1 1 1", core::Cvar::Archive); cl_crosshaircolor->set_info("[r g b] crosshairs color"); + + snd_engines = core::Cvar::get("snd_engines", "0", core::Cvar::Archive); + snd_engines->set_info("[bool] enable or disable engine sounds"); } void shutdown() @@ -282,6 +288,47 @@ void reset() } +// render ingame sounds +void render_sound() +{ + if (!(snd_engines && snd_engines->value())) + return; + + float speed = 0; + if (core::localcontrol()) { + speed = core::localcontrol()->speed(); + } + + audio::update_listener(render::Camera::eye(), render::Camera::axis(), speed); + + for (std::map::iterator it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { + core::Entity *entity = (*it).second; + core::ClientState *state = entity->state(); + + if ((entity->type() == core::Entity::Controlable)) { + core::EntityControlable *entitycontrolable = (core::EntityControlable *) entity; + + if (entity->model() && state->detailvisible() && entitycontrolable->thrust() > 0 ) { + + float speed = entitycontrolable->speed(); + float pitch = 0.2f + entitycontrolable->thrust() * 0.8f; + + if (!state->state_enginesound) { + if ((state->state_enginesound = audio::Sources::get()) > 0 ) + audio::loop(state->state_enginesound, "engines/loop01", pitch, 0); + } + + if (state->state_enginesound) { + audio::update_source(state->state_enginesound, + state->location() - state->axis().forward() * entity->model()->maxbbox().y , state->axis().forward() * speed, pitch); + } + } else { + entity->state()->clearsound(); + } + } + } +} + void frame(float seconds) { using namespace render; @@ -300,6 +347,8 @@ void frame(float seconds) if (core::application()->connected() && core::game()->serverframetime()) { render::draw(seconds); // draw the world + + render_sound(); } // switch to ortographic projection to draw the GUI @@ -317,8 +366,14 @@ void frame(float seconds) if (!core::application()->connected()) { // draw the loader bitmap draw_loader(); + + // force console on if not connected + if (!console()->visible()) + console()->toggle(); } + gl::enable(GL_BLEND); + // draw text elements if (draw_ui->value()) { diff --git a/src/core/application.cc b/src/core/application.cc index f8c563c..f92a0fe 100644 --- a/src/core/application.cc +++ b/src/core/application.cc @@ -411,6 +411,12 @@ void Application::notify_sound(const char *name) // Dedicated servers don't need sounds } +void Application::notify_remove_sound(size_t source) +{ + // the default implementation does nothing. + // Dedicated servers don't need sounds +} + void Application::notify_message(std::string const & message) { con_print << message << std::endl; diff --git a/src/core/application.h b/src/core/application.h index aad3ac9..8f69720 100644 --- a/src/core/application.h +++ b/src/core/application.h @@ -64,6 +64,9 @@ public: /// text notifications from the core to the application virtual void notify_message(std::string const & message); + /// remove sound source notification + virtual void notify_remove_sound(size_t source); + /*----- static --------------------------------------------------- */ /// a pointer to the current application instance diff --git a/src/core/clientstate.cc b/src/core/clientstate.cc index cc9c79e..503a71f 100644 --- a/src/core/clientstate.cc +++ b/src/core/clientstate.cc @@ -5,6 +5,7 @@ */ #include "core/clientstate.h" +#include "core/application.h" namespace core { @@ -14,6 +15,8 @@ ClientState::ClientState() state_detailvisible = false; state_targetable = false; + state_enginesound = 0; + for (size_t i = 0; i < 3; i++) state_screenlocation[i] = 0; @@ -25,11 +28,24 @@ ClientState::ClientState(Entity *entity) state_visible = false; state_detailvisible = false; state_fuzz = math::randomf(); + + state_enginesound = 0; + assign(entity); } ClientState::~ClientState() -{} +{ + clearsound(); +} + +void ClientState::clearsound() +{ + if (state_enginesound) { + application()->notify_remove_sound(state_enginesound); + state_enginesound = 0; + } +} void ClientState::assign(Entity * entity) { diff --git a/src/core/clientstate.h b/src/core/clientstate.h index 6cd283d..87dd1d7 100644 --- a/src/core/clientstate.h +++ b/src/core/clientstate.h @@ -49,6 +49,9 @@ public: /// assign the content of an entity void assign(Entity *entity); + /// clear attached sounds + void clearsound(); + math::Vector3f state_location; math::Axis state_axis; @@ -62,6 +65,8 @@ public: bool state_targetable; float state_fuzz; + + size_t state_enginesound; }; } -- cgit v1.2.3