2021-09-12 03:18:12 +00:00
|
|
|
#include <vector>
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
#include <AL/al.h>
|
|
|
|
|
|
|
|
#include <media-layer/audio.h>
|
|
|
|
#include <libreborn/libreborn.h>
|
|
|
|
|
|
|
|
#include "file.h"
|
|
|
|
#include "engine.h"
|
2022-07-08 19:00:01 +00:00
|
|
|
#include "api.h"
|
2021-09-12 03:18:12 +00:00
|
|
|
|
|
|
|
// Store Audio Sources
|
|
|
|
static std::vector<ALuint> &get_sources() {
|
|
|
|
static std::vector<ALuint> sources;
|
|
|
|
return sources;
|
|
|
|
}
|
|
|
|
|
2022-07-08 19:00:01 +00:00
|
|
|
// Store Idle Audio Sources
|
|
|
|
#define MAX_IDLE_SOURCES 50
|
|
|
|
static std::vector<ALuint> &get_idle_sources() {
|
|
|
|
static std::vector<ALuint> sources;
|
|
|
|
return sources;
|
|
|
|
}
|
|
|
|
|
2022-05-29 22:44:27 +00:00
|
|
|
// Error Checking
|
2022-03-12 01:02:38 +00:00
|
|
|
#define AL_ERROR_CHECK() AL_ERROR_CHECK_MANUAL(alGetError())
|
|
|
|
#define AL_ERROR_CHECK_MANUAL(val) \
|
2021-09-12 03:18:12 +00:00
|
|
|
{ \
|
2022-03-12 01:02:38 +00:00
|
|
|
ALenum __err = val; \
|
|
|
|
if (__err != AL_NO_ERROR) { \
|
|
|
|
ERR("OpenAL Error: %s", alGetString(__err)); \
|
2021-09-12 03:18:12 +00:00
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
2022-07-08 19:00:01 +00:00
|
|
|
// Delete Sources
|
|
|
|
void _media_audio_delete_sources() {
|
|
|
|
if (_media_audio_is_loaded()) {
|
|
|
|
for (ALuint source : get_idle_sources()) {
|
|
|
|
alDeleteSources(1, &source);
|
|
|
|
AL_ERROR_CHECK();
|
|
|
|
}
|
|
|
|
for (ALuint source : get_sources()) {
|
|
|
|
alDeleteSources(1, &source);
|
|
|
|
AL_ERROR_CHECK();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
get_idle_sources().clear();
|
|
|
|
get_sources().clear();
|
|
|
|
}
|
|
|
|
|
2021-09-12 03:18:12 +00:00
|
|
|
// Update Listener
|
|
|
|
void media_audio_update(float volume, float x, float y, float z, float yaw) {
|
2021-10-12 20:01:07 +00:00
|
|
|
// Check
|
|
|
|
if (_media_audio_is_loaded()) {
|
|
|
|
// Update Listener Volume
|
|
|
|
alListenerf(AL_GAIN, volume);
|
|
|
|
AL_ERROR_CHECK();
|
2021-09-12 03:18:12 +00:00
|
|
|
|
2021-10-12 20:01:07 +00:00
|
|
|
// Update Listener Position
|
|
|
|
alListener3f(AL_POSITION, x, y, z);
|
|
|
|
AL_ERROR_CHECK();
|
2021-09-12 03:18:12 +00:00
|
|
|
|
2021-10-12 20:01:07 +00:00
|
|
|
// Update Listener Orientation
|
|
|
|
float radian_yaw = yaw * (M_PI / 180);
|
|
|
|
ALfloat orientation[] = {-sinf(radian_yaw), 0.0f, cosf(radian_yaw), 0.0f, 1.0f, 0.0f};
|
|
|
|
alListenerfv(AL_ORIENTATION, orientation);
|
|
|
|
AL_ERROR_CHECK();
|
2021-09-12 03:18:12 +00:00
|
|
|
|
2021-10-12 20:01:07 +00:00
|
|
|
// Clear Finished Sources
|
|
|
|
std::vector<ALuint>::iterator it = get_sources().begin();
|
|
|
|
while (it != get_sources().end()) {
|
|
|
|
ALuint source = *it;
|
|
|
|
bool remove = false;
|
|
|
|
// Check
|
|
|
|
if (source && alIsSource(source)) {
|
|
|
|
// Is Valid Source
|
|
|
|
ALint source_state;
|
|
|
|
alGetSourcei(source, AL_SOURCE_STATE, &source_state);
|
2021-09-12 20:38:41 +00:00
|
|
|
AL_ERROR_CHECK();
|
2021-10-12 20:01:07 +00:00
|
|
|
if (source_state != AL_PLAYING) {
|
|
|
|
// Finished Playing
|
|
|
|
remove = true;
|
2022-07-08 19:00:01 +00:00
|
|
|
if (get_idle_sources().size() < MAX_IDLE_SOURCES) {
|
|
|
|
get_idle_sources().push_back(source);
|
|
|
|
} else {
|
|
|
|
alDeleteSources(1, &source);
|
|
|
|
AL_ERROR_CHECK();
|
|
|
|
}
|
2021-10-12 20:01:07 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Not A Source
|
|
|
|
remove = true;
|
|
|
|
}
|
|
|
|
// Remove If Needed
|
|
|
|
if (remove) {
|
|
|
|
it = get_sources().erase(it);
|
|
|
|
} else {
|
|
|
|
++it;
|
2021-09-12 20:38:41 +00:00
|
|
|
}
|
2021-09-12 03:18:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-29 22:44:27 +00:00
|
|
|
// Play
|
2021-09-12 03:18:12 +00:00
|
|
|
void media_audio_play(const char *source, const char *name, float x, float y, float z, float pitch, float volume, int is_ui) {
|
2021-10-12 20:01:07 +00:00
|
|
|
// Check
|
|
|
|
if (_media_audio_is_loaded()) {
|
|
|
|
// Load Sound
|
|
|
|
ALuint buffer = _media_audio_get_buffer(source, name);
|
|
|
|
if (volume > 0.0f && buffer) {
|
2022-07-08 19:00:01 +00:00
|
|
|
// Get Source
|
2021-10-12 20:01:07 +00:00
|
|
|
ALuint al_source;
|
2022-07-08 19:00:01 +00:00
|
|
|
if (get_idle_sources().size() > 0) {
|
|
|
|
// Use Idle Source
|
|
|
|
al_source = get_idle_sources().back();
|
|
|
|
get_idle_sources().pop_back();
|
|
|
|
} else {
|
|
|
|
// Create Source
|
|
|
|
alGenSources(1, &al_source);
|
|
|
|
// Special Out-Of-Memory Handling
|
|
|
|
{
|
|
|
|
ALenum err = alGetError();
|
|
|
|
if (err == AL_OUT_OF_MEMORY) {
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
AL_ERROR_CHECK_MANUAL(err);
|
|
|
|
}
|
2022-03-12 01:02:38 +00:00
|
|
|
}
|
|
|
|
}
|
2021-09-12 03:18:12 +00:00
|
|
|
|
2021-10-12 20:01:07 +00:00
|
|
|
// Set Properties
|
|
|
|
alSourcef(al_source, AL_PITCH, pitch);
|
|
|
|
AL_ERROR_CHECK();
|
|
|
|
alSourcef(al_source, AL_GAIN, volume);
|
|
|
|
AL_ERROR_CHECK();
|
|
|
|
alSource3f(al_source, AL_POSITION, x, y, z);
|
|
|
|
AL_ERROR_CHECK();
|
|
|
|
alSource3f(al_source, AL_VELOCITY, 0, 0, 0);
|
|
|
|
AL_ERROR_CHECK();
|
|
|
|
alSourcei(al_source, AL_LOOPING, AL_FALSE);
|
|
|
|
AL_ERROR_CHECK();
|
|
|
|
alSourcei(al_source, AL_SOURCE_RELATIVE, is_ui ? AL_TRUE : AL_FALSE);
|
|
|
|
AL_ERROR_CHECK();
|
2021-09-12 03:18:12 +00:00
|
|
|
|
2021-10-12 20:01:07 +00:00
|
|
|
// Set Attenuation
|
|
|
|
alSourcei(al_source, AL_DISTANCE_MODEL, AL_LINEAR_DISTANCE);
|
|
|
|
AL_ERROR_CHECK();
|
|
|
|
alSourcef(al_source, AL_MAX_DISTANCE, 16.0f);
|
|
|
|
AL_ERROR_CHECK();
|
|
|
|
alSourcef(al_source, AL_ROLLOFF_FACTOR, 1.0f);
|
|
|
|
AL_ERROR_CHECK();
|
|
|
|
alSourcef(al_source, AL_REFERENCE_DISTANCE, 0.0f);
|
|
|
|
AL_ERROR_CHECK();
|
2021-09-12 03:18:12 +00:00
|
|
|
|
2021-10-12 20:01:07 +00:00
|
|
|
// Set Buffer
|
|
|
|
alSourcei(al_source, AL_BUFFER, buffer);
|
|
|
|
AL_ERROR_CHECK();
|
2021-09-12 03:18:12 +00:00
|
|
|
|
2021-10-12 20:01:07 +00:00
|
|
|
// Play
|
|
|
|
alSourcePlay(al_source);
|
|
|
|
AL_ERROR_CHECK();
|
|
|
|
get_sources().push_back(al_source);
|
|
|
|
}
|
2021-09-12 03:18:12 +00:00
|
|
|
}
|
|
|
|
}
|