]> git.localhorst.tv Git - blank.git/blobdiff - src/audio/audio.cpp
tests for TokenStreamReader
[blank.git] / src / audio / audio.cpp
index eed5dac170e514999074ca7948ec803c90328c1a..c7ed554ee8304e880fb8ce2f2587437b76d27b1d 100644 (file)
@@ -1,6 +1,10 @@
 #include "ALError.hpp"
 #include "Audio.hpp"
 #include "Sound.hpp"
+#include "SoundBank.hpp"
+
+#include "../app/Assets.hpp"
+#include "../shared/ResourceIndex.hpp"
 
 #include <algorithm>
 #include <alut.h>
@@ -48,7 +52,8 @@ ALError::ALError(ALenum num, const std::string &msg)
 }
 
 
-Audio::Audio() {
+Audio::Audio()
+: last_free(0) {
        alGenSources(NUM_SRC, source);
        ALenum err = alGetError();
        if (err != AL_NO_ERROR) {
@@ -92,14 +97,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];
+       CoarseTimer &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 = CoarseTimer(sound.Duration());
+       t.Start();
 }
 
 void Audio::StopAll() noexcept {
@@ -109,14 +123,36 @@ 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;
+               }
+       }
+}
 
-Sound::Sound()
-: handle(AL_NONE) {
-       alGenBuffers(1, &handle);
-       ALenum err = alGetError();
-       if (err != AL_NO_ERROR) {
-               throw ALError(err, "alGenBuffers");
+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)
+, duration(0) {
+
 }
 
 Sound::Sound(const char *file)
@@ -124,6 +160,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() {
@@ -132,18 +176,19 @@ Sound::~Sound() {
                ALenum err = alGetError();
                if (err != AL_NO_ERROR) {
                        std::cerr << "warning: alDeleteBuffers failed with " << al_error_string(err) << std::endl;
-                       //throw ALError(err, "alDeleteBuffers");
                }
        }
 }
 
 Sound::Sound(Sound &&other)
-: handle(other.handle) {
+: handle(other.handle)
+, duration(other.duration) {
        other.handle = AL_NONE;
 }
 
 Sound &Sound::operator =(Sound &&other) {
        std::swap(handle, other.handle);
+       std::swap(duration, other.duration);
        return *this;
 }
 
@@ -151,4 +196,18 @@ void Sound::Bind(ALuint src) const {
        alSourcei(src, AL_BUFFER, handle);
 }
 
+
+SoundBank::SoundBank()
+: sounds() {
+
+}
+
+void SoundBank::Load(const AssetLoader &loader, const ResourceIndex &index) {
+       sounds.clear();
+       sounds.resize(index.Size());
+       for (const auto &entry : index.Entries()) {
+               sounds[entry.second] = loader.LoadSound(entry.first);
+       }
+}
+
 }