Diggler/Audio.cpp

149 lines
3.8 KiB
C++

#include "Audio.hpp"
#include <AL/al.h>
#include <AL/alext.h>
#include "Game.hpp"
#include "Sound.hpp"
#include "GlobalProperties.hpp"
#define AUDIO_GC_DEBUG 0
namespace Diggler {
Audio::Audio(Game* G) : G(G), sounds(m_sounds) {
if (!GlobalProperties::IsSoundEnabled)
return;
int alMajor, alMinor;
alcGetIntegerv(nullptr, ALC_MAJOR_VERSION, 1, &alMajor);
alcGetIntegerv(nullptr, ALC_MINOR_VERSION, 1, &alMinor);
getDebugStream() << "OpenAL v" << alMajor << '.' << alMinor << std::endl;
ALboolean enumeration = alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT");
if (enumeration == AL_FALSE)
; // enumeration not supported
else {
const ALCchar *devices = alcGetString(nullptr, ALC_DEVICE_SPECIFIER);
const ALCchar *device = devices, *next = devices + 1;
size_t len = 0;
while (device && *device != '\0' && next && *next != '\0') {
len = strlen(device);
device += (len + 1);
next += (len + 2);
}
}
const ALCchar *deviceName = nullptr;
m_audioDevice = alcOpenDevice(deviceName);
if (!m_audioDevice) {
getDebugStream() << "Failed opening AL device '" << deviceName << "': " << alcGetError(m_audioDevice) << std::endl;
GlobalProperties::IsSoundEnabled = false;
}
deviceName = alcGetString(m_audioDevice, ALC_DEVICE_SPECIFIER);
getDebugStream() << "Using device '" << deviceName << '\'' << std::endl;
ALCint attrs[] = {
0, 0
};
m_audioContext = alcCreateContext(m_audioDevice, attrs);
if (!alcMakeContextCurrent(m_audioContext)) {
getDebugStream() << "Failed setting context on AL device '" << deviceName << "': " << alcGetError(m_audioDevice) << std::endl;
alcCloseDevice(m_audioDevice);
GlobalProperties::IsSoundEnabled = false;
}
}
Audio::~Audio() {
if (!GlobalProperties::IsSoundEnabled)
return;
alcMakeContextCurrent(nullptr);
alcDestroyContext(m_audioContext);
alcCloseDevice(m_audioDevice);
}
static ALfloat float3data[3], plrOrient[6];
void Audio::updateAngle() {
const glm::vec3 &at = G->LP->camera.getLookAt(),
&up = G->LP->camera.getUp();
plrOrient[0] = at.x;
plrOrient[1] = at.y;
plrOrient[2] = at.z;
plrOrient[3] = up.x;
plrOrient[4] = up.y;
plrOrient[5] = up.z;
alListenerfv(AL_ORIENTATION, plrOrient);
}
void Audio::updatePos() {
float3data[0] = G->LP->position.x;
float3data[1] = G->LP->position.y;
float3data[2] = G->LP->position.z;
alListenerfv(AL_POSITION, float3data);
float3data[0] = G->LP->velocity.x;
float3data[1] = G->LP->velocity.y;
float3data[2] = G->LP->velocity.z;
alListenerfv(AL_VELOCITY, float3data);
}
void Audio::update() {
updatePos();
updateAngle();
}
void Audio::loadSoundAssets() {
std::string soundsDir = getAssetsDirectory() + "sounds/";
for (const std::string &fn : fs::getFiles(soundsDir)) {
if (fn.length() >= 4 && fn.substr(fn.length()-4) == ".ogg") {
addSound(fn.substr(0, fn.length()-4), soundsDir+fn);
}
}
}
void Audio::addSound(const std::string& name, const std::string& path) {
m_sounds.emplace(std::piecewise_construct,
std::forward_as_tuple(name), std::forward_as_tuple()).first->second.loadOgg(path);
}
void Audio::playSound(const std::string &name) {
playSound(m_sounds.at(name));
}
void Audio::playSound(const SoundBuffer &buf) {
m_playing.emplace_back(&buf);
m_playing.back().play();
gc();
}
void Audio::playSound(const std::string &name, const glm::vec3 &pos) {
playSound(m_sounds.at(name), pos);
}
void Audio::playSound(const SoundBuffer &buf, const glm::vec3& pos) {
m_playing.emplace_back(&buf, false, pos);
m_playing.back().play();
gc();
}
/// Garbage Collects the sound sources
void Audio::gc() {
#if AUDIO_GC_DEBUG
uint freed = 0;
#endif
std::list<Sound>::const_iterator it = m_playing.begin();
while (it != m_playing.end()) {
if (!it->isPlaying()) {
it = m_playing.erase(it);
#if AUDIO_GC_DEBUG
freed++;
#endif
} else {
++it;
}
}
#if AUDIO_GC_DEBUG
getDebugStream() << "GC'd " << freed << " sources" << std::endl;
#endif
}
}