From: Daniel Karbach Date: Fri, 14 Aug 2015 09:39:39 +0000 (+0200) Subject: the sound thing X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=045a6ec084bf1fb4df3c6ade4a88932cf61bed23;p=blank.git the sound thing --- diff --git a/TODO b/TODO index 9bd2aaa..b77cdae 100644 --- a/TODO +++ b/TODO @@ -21,11 +21,6 @@ command line usefull for development and later on world administration -audio - - do the sources thing right™ - (or at least in a way that it doesn't error out on shutdown :P ) - persistence merge IO counters, so number of operations per frame is kept diff --git a/src/app/IntervalTimer.hpp b/src/app/IntervalTimer.hpp index bcf1bae..06caa5e 100644 --- a/src/app/IntervalTimer.hpp +++ b/src/app/IntervalTimer.hpp @@ -13,7 +13,7 @@ class IntervalTimer { public: /// Create a timer that hits every interval_ms milliseconds. /// Initial state is stopped. - explicit IntervalTimer(int interval_ms) noexcept + explicit IntervalTimer(int interval_ms = 0) noexcept : intv(interval_ms) { } void Start() noexcept { @@ -35,7 +35,7 @@ public: return Running() && value % intv < last_dt; } bool HitOnce() const noexcept { - return value >= intv; + return Running() && value >= intv; } int Elapsed() const noexcept { return value; diff --git a/src/app/app.cpp b/src/app/app.cpp index 8f3801c..a6acade 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -129,6 +129,7 @@ void Application::Handle(const SDL_WindowEvent &event) { void Application::Update(int dt) { env.counter.EnterUpdate(); + env.audio.Update(dt); if (HasState()) { GetState().Update(dt); } diff --git a/src/audio/Audio.hpp b/src/audio/Audio.hpp index fe5364d..bfd6d47 100644 --- a/src/audio/Audio.hpp +++ b/src/audio/Audio.hpp @@ -1,6 +1,8 @@ #ifndef BLANK_AUDIO_AUDIO_HPP_ #define BLANK_AUDIO_AUDIO_HPP_ +#include "../app/IntervalTimer.hpp" + #include #include @@ -32,9 +34,16 @@ public: void StopAll() noexcept; + void Update(int dt) noexcept; + +private: + int NextFree() noexcept; + private: - static constexpr std::size_t NUM_SRC = 1; + static constexpr std::size_t NUM_SRC = 16; ALuint source[NUM_SRC]; + IntervalTimer timer[NUM_SRC]; + int last_free; }; diff --git a/src/audio/Sound.hpp b/src/audio/Sound.hpp index abbb27b..abd3178 100644 --- a/src/audio/Sound.hpp +++ b/src/audio/Sound.hpp @@ -22,8 +22,12 @@ public: public: void Bind(ALuint src) const; + /// full duration in milliseconds + int Duration() const noexcept { return duration; } + private: ALuint handle; + int duration; }; diff --git a/src/audio/audio.cpp b/src/audio/audio.cpp index eed5dac..426745f 100644 --- a/src/audio/audio.cpp +++ b/src/audio/audio.cpp @@ -92,14 +92,23 @@ void Audio::Play( const glm::vec3 &vel, const glm::vec3 &dir ) noexcept { - // TODO: find next free source - ALuint src = source[0]; + int i = NextFree(); + if (i < 0) { + std::cerr << "unable to find free audio source" << std::endl; + return; + } + + ALuint src = source[i]; + IntervalTimer &t = timer[i]; sound.Bind(src); alSourcefv(src, AL_POSITION, glm::value_ptr(pos)); alSourcefv(src, AL_VELOCITY, glm::value_ptr(vel)); alSourcefv(src, AL_DIRECTION, glm::value_ptr(dir)); alSourcePlay(src); + + t = IntervalTimer(sound.Duration()); + t.Start(); } void Audio::StopAll() noexcept { @@ -109,9 +118,35 @@ void Audio::StopAll() noexcept { } } +void Audio::Update(int dt) noexcept { + for (std::size_t i = 0; i < NUM_SRC; ++i) { + timer[i].Update(dt); + if (timer[i].HitOnce()) { + timer[i].Stop(); + alSourceStop(source[i]); + alSourcei(source[i], AL_BUFFER, AL_NONE); + last_free = i; + } + } +} + +int Audio::NextFree() noexcept { + if (!timer[last_free].Running()) { + return last_free; + } + for (int i = (last_free + 1) % NUM_SRC; i != last_free; i = (i + 1) % NUM_SRC) { + if (!timer[i].Running()) { + last_free = i; + return i; + } + } + return -1; +} + Sound::Sound() -: handle(AL_NONE) { +: handle(AL_NONE) +, duration(0) { alGenBuffers(1, &handle); ALenum err = alGetError(); if (err != AL_NO_ERROR) { @@ -124,6 +159,14 @@ Sound::Sound(const char *file) if (handle == AL_NONE) { throw ALError(alGetError(), "alutCreateBufferFromFile"); } + + ALint size, channels, bits, freq; + alGetBufferi(handle, AL_SIZE, &size); + alGetBufferi(handle, AL_CHANNELS, &channels); + alGetBufferi(handle, AL_BITS, &bits); + alGetBufferi(handle, AL_FREQUENCY, &freq); + + duration = size * 8 * 1000 / (channels * bits * freq); } Sound::~Sound() {