diff --git a/src/audio/AL/ALAudio.cpp b/src/audio/AL/ALAudio.cpp index 8f48c4aea..555336e93 100644 --- a/src/audio/AL/ALAudio.cpp +++ b/src/audio/AL/ALAudio.cpp @@ -780,15 +780,18 @@ void ALAudio::setListener( AL_CHECK(alListenerf(AL_GAIN, get_channel(0)->getVolume())); } -void ALAudio::update(double delta) { +void ALAudio::update(double) { +} + +void ALAudio::setAcoustics(Acoustics acoustics) { if (!useEffects) { return; } int reverbEffect = effects[REVERB_EFFECT]; - AL_CHECK(alEffectf(reverbEffect, AL_REVERB_DECAY_TIME, 1.0f)); - AL_CHECK(alEffectf(reverbEffect, AL_REVERB_ROOM_ROLLOFF_FACTOR, 0.07f)); - AL_CHECK(alEffectf(reverbEffect, AL_REVERB_GAIN, 0.0f)); - AL_CHECK(alEffectf(reverbEffect, AL_REVERB_GAINHF, 0.0f)); - AL_CHECK(alEffectf(reverbEffect, AL_REVERB_REFLECTIONS_GAIN, 0.0f)); + AL_CHECK(alEffectf(reverbEffect, AL_REVERB_DECAY_TIME, std::max(0.1f, acoustics.reverbDecayTime))); + AL_CHECK(alEffectf(reverbEffect, AL_REVERB_ROOM_ROLLOFF_FACTOR, 0.14f)); + // AL_CHECK(alEffectf(reverbEffect, AL_REVERB_GAIN, 0.0f)); + // AL_CHECK(alEffectf(reverbEffect, AL_REVERB_GAINHF, 0.0f)); + AL_CHECK(alEffectf(reverbEffect, AL_REVERB_REFLECTIONS_GAIN, 0.5f)); alAuxiliaryEffectSloti(effectSlots[0], AL_EFFECTSLOT_EFFECT, reverbEffect); } diff --git a/src/audio/AL/ALAudio.hpp b/src/audio/AL/ALAudio.hpp index e01967d33..c2cba3961 100644 --- a/src/audio/AL/ALAudio.hpp +++ b/src/audio/AL/ALAudio.hpp @@ -226,6 +226,8 @@ namespace audio { void update(double delta) override; + void setAcoustics(Acoustics acoustics) override; + bool isDummy() const override { return false; } diff --git a/src/audio/NoAudio.hpp b/src/audio/NoAudio.hpp index 0da1b4d63..c97794f36 100644 --- a/src/audio/NoAudio.hpp +++ b/src/audio/NoAudio.hpp @@ -104,6 +104,9 @@ namespace audio { void update(double delta) override { } + void setAcoustics(Acoustics) override { + } + bool isDummy() const override { return true; } diff --git a/src/audio/audio.cpp b/src/audio/audio.cpp index dc0e57463..a45a876f6 100644 --- a/src/audio/audio.cpp +++ b/src/audio/audio.cpp @@ -496,6 +496,10 @@ void audio::update(double delta) { } } +void audio::set_acoustics(Acoustics acoustics) { + backend->setAcoustics(std::move(acoustics)); +} + void audio::reset_channel(int index) { auto channel = get_channel(index); if (channel == nullptr) { diff --git a/src/audio/audio.hpp b/src/audio/audio.hpp index 642b9235d..365f6bce9 100644 --- a/src/audio/audio.hpp +++ b/src/audio/audio.hpp @@ -7,6 +7,7 @@ #include "typedefs.hpp" #include "settings.hpp" #include "io/fwd.hpp" +#include "effects.hpp" namespace audio { /// @brief playing speaker uid @@ -394,6 +395,7 @@ namespace audio { virtual std::vector getInputDeviceNames() = 0; virtual std::vector getOutputDeviceNames() = 0; virtual void update(double delta) = 0; + virtual void setAcoustics(Acoustics acoustics) = 0; /// @brief Check if backend is an abstraction that does not internally /// work with actual audio data or play anything @@ -580,6 +582,8 @@ namespace audio { /// @param delta time elapsed since the last update (seconds) void update(double delta); + void set_acoustics(Acoustics acoustics); + /// @brief Stop all playing audio in channel, reset channel state void reset_channel(int channel); diff --git a/src/audio/effects.hpp b/src/audio/effects.hpp index 01d2eedd5..e292621d3 100644 --- a/src/audio/effects.hpp +++ b/src/audio/effects.hpp @@ -26,4 +26,8 @@ namespace audio { protected: const Effect* effect = nullptr; }; + + struct Acoustics { + float reverbDecayTime; + }; } diff --git a/src/graphics/render/Decorator.cpp b/src/graphics/render/Decorator.cpp index 420f6d0dc..77aaa5cda 100644 --- a/src/graphics/render/Decorator.cpp +++ b/src/graphics/render/Decorator.cpp @@ -23,9 +23,12 @@ #include "io/io.hpp" #include "audio/audio.hpp" #include "maths/util.hpp" +#include "debug/Logger.hpp" namespace fs = std::filesystem; +static debug::Logger logger("decorator"); + /// @brief Not greater than 64 for this BIG_PRIME value inline constexpr int UPDATE_AREA_DIAMETER = 32; /// @brief Number of blocks in the volume @@ -70,19 +73,56 @@ Decorator::Decorator( void Decorator::addParticles(const Block& def, const glm::ivec3& pos) { const auto& found = blockEmitters.find(pos); - if (found == blockEmitters.end()) { - auto treg = util::get_texture_region( - assets, def.particles->texture, "" - ); - blockEmitters[pos] = renderer.particles->add(std::make_unique( - level, - glm::vec3{pos.x + 0.5, pos.y + 0.5, pos.z + 0.5}, - *def.particles, - treg.texture, - treg.region, - -1 - )); + if (found != blockEmitters.end()) { + return; } + auto treg = util::get_texture_region( + assets, def.particles->texture, "" + ); + blockEmitters[pos] = renderer.particles->add(std::make_unique( + level, + glm::vec3{pos.x + 0.5, pos.y + 0.5, pos.z + 0.5}, + *def.particles, + treg.texture, + treg.region, + -1 + )); +} + +void Decorator::updateAcoustics(const Camera& camera) { + audio::Acoustics acoustics {}; + util::PseudoRandom random(0x34621B361); + + auto& chunks = *player.chunks; + const auto& start = camera.position; + float rayLength = 40.0f; + + int rays = 100; + int hit = 0; + float averageDistance = 0.0f; + for (int i = 0; i < rays; i++) { + glm::vec3 dir { + random.randFloat() - 0.5f, + random.randFloat() - 0.5f, + random.randFloat() - 0.5f, + }; + dir = glm::normalize(dir); + auto end = chunks.rayCastToObstacle(start, dir, rayLength); + auto distance = glm::distance(start, end); + if (distance >= rayLength * 0.98f) { + continue; + } + hit++; + averageDistance += distance * 0.2f; + } + float decayTime = (averageDistance / hit) * ((hit / static_cast(rays)) - 0.6f) * 1.6f; + decayTime *= 2.5f; + decayTime *= decayTime; + logger.info() << "rays hit " << hit << "/" << rays << " decay-time: " << decayTime; + + + acoustics.reverbDecayTime = decayTime; + audio::set_acoustics(std::move(acoustics)); } void Decorator::updateRandom( @@ -283,4 +323,5 @@ void Decorator::update( } updateBlockEmitters(camera); updateTextNotes(); + updateAcoustics(camera); } diff --git a/src/graphics/render/Decorator.hpp b/src/graphics/render/Decorator.hpp index 181fdcb5d..4fe52c50a 100644 --- a/src/graphics/render/Decorator.hpp +++ b/src/graphics/render/Decorator.hpp @@ -48,6 +48,7 @@ class Decorator { void updateBlockEmitters(const Camera& camera); void updateTextNotes(); void addParticles(const Block& def, const glm::ivec3& pos); + void updateAcoustics(const Camera& camera); public: Decorator( Engine& engine,