add effects extension support

This commit is contained in:
MihailRis 2025-02-18 23:15:56 +03:00
parent 3637855581
commit 923c694ab4
2 changed files with 134 additions and 7 deletions

View file

@ -40,6 +40,20 @@ static bool check_alc_errors(ALCdevice* device, const char* context) {
return true;
}
static LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti = nullptr;
static LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots = nullptr;
static LPALGENEFFECTS alGenEffects = nullptr;
static LPALDELETEEFFECTS alDeleteEffects = nullptr;
static LPALISEFFECT alIsEffect = nullptr;
static LPALEFFECTI alEffecti = nullptr;
static LPALEFFECTF alEffectf = nullptr;
static LPALGENFILTERS alGenFilters = nullptr;
static LPALDELETEFILTERS alDeleteFilters = nullptr;
static LPALISFILTER alIsFilter = nullptr;
static LPALFILTERI alFilteri = nullptr;
static LPALFILTERF alFilterf = nullptr;
ALSound::ALSound(
ALAudio* al, uint buffer, const std::shared_ptr<PCM>& pcm, bool keepPCM
)
@ -382,6 +396,10 @@ void ALSpeaker::play() {
AL_GAIN,
volume * p_channel->getVolume()
));
if (al->useEffects) {
AL_CHECK(alSource3i(source, AL_AUXILIARY_SEND_FILTER, al->effectSlots[0], 0, al->filters[0]));
//AL_CHECK(alSourcei(source, AL_DIRECT_FILTER, al->filters[0]));
}
AL_CHECK(alSourcePlay(source));
}
@ -455,15 +473,14 @@ int ALSpeaker::getPriority() const {
return priority;
}
bool ALSpeaker::isManuallyStopped() const {
return manuallyStopped;
}
static bool alc_enumeration_ext = false;
ALAudio::ALAudio(ALCdevice* device, ALCcontext* context)
: device(device), context(context) {
ALAudio::ALAudio(ALCdevice* device, ALCcontext* context, bool useEffects)
: device(device), context(context), useEffects(useEffects) {
ALCint size;
alcGetIntegerv(device, ALC_ATTRIBUTES_SIZE, 1, &size);
std::vector<ALCint> attrs(size);
@ -487,6 +504,11 @@ ALAudio::ALAudio(ALCdevice* device, ALCcontext* context)
}
alDopplerFactor(1.0 / 3.0);
alGetError();
if (useEffects) {
initEffects();
}
}
ALAudio::~ALAudio() {
@ -513,6 +535,58 @@ ALAudio::~ALAudio() {
context = nullptr;
}
void ALAudio::initEffects() {
for (uint i = 0; i < effectSlots.size(); i++) {
alGenAuxiliaryEffectSlots(1, &effectSlots[i]);
if (alGetError() != AL_NO_ERROR) {
logger.error() << "could not to create aux effect slot #" << i;
useEffects = false;
return;
}
}
for (uint i = 0; i < effects.size(); i++) {
alGenEffects(1, &effects[i]);
if (alGetError() != AL_NO_ERROR || !alIsEffect(effects[i])) {
logger.error() << "could not to create effect #" << i;
useEffects = false;
return;
}
}
for (uint i = 0; i < filters.size(); i++) {
alGenFilters(1, &filters[i]);
if (alGetError() != AL_NO_ERROR || !alIsFilter(filters[i])) {
logger.error() << "could not to create filter #" << i;
useEffects = false;
return;
}
}
// Create reverb effect
alEffecti(effects[0], AL_EFFECT_TYPE, AL_EFFECT_REVERB);
if (alGetError() != AL_NO_ERROR) {
logger.error() << "reverb effect is not supported";
useEffects = false;
return;
}
alEffectf(effects[0], AL_REVERB_DECAY_TIME, 1.0f);
// Create lowpass filter
alFilteri(filters[0], AL_FILTER_TYPE, AL_FILTER_LOWPASS);
if (alGetError() != AL_NO_ERROR) {
logger.error() << "lowpass filter is not supported";
useEffects = false;
return;
}
alFilterf(filters[0], AL_LOWPASS_GAIN, 1.0f);
alFilterf(filters[0], AL_LOWPASS_GAINHF, 0.1f);
// Attach effect to aux effect slot
alAuxiliaryEffectSloti(effectSlots[0], AL_EFFECTSLOT_EFFECT, effects[0]);
if (alGetError() == AL_NO_ERROR) {
logger.info() << "successfully loaded effect into effect slot";
}
}
std::unique_ptr<Sound> ALAudio::createSound(
std::shared_ptr<PCM> pcm, bool keepPCM
) {
@ -592,19 +666,62 @@ std::unique_ptr<InputDevice> ALAudio::openInputDevice(
);
}
template<typename T>
static bool get_proc_address(const char* name, T& ptr) {
ptr = (T) alGetProcAddress(name);
return ptr != nullptr;
}
std::unique_ptr<ALAudio> ALAudio::create() {
alc_enumeration_ext = alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT");
ALCdevice* device = alcOpenDevice(nullptr);
if (device == nullptr) return nullptr;
if (device == nullptr) {
return nullptr;
}
bool effects = true;
ALint attribs[4] {};
if (alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_TRUE) {
logger.info() << "AL effects extension present";
attribs[0] = ALC_MAX_AUXILIARY_SENDS;
attribs[1] = 4;
} else {
logger.warning() << "AL effects extension is not supported";
effects = false;
}
ALCcontext* context = alcCreateContext(device, nullptr);
if (!alcMakeContextCurrent(context)) {
alcCloseDevice(device);
return nullptr;
}
AL_CHECK();
ALCint sends = 0;
alcGetIntegerv(device, ALC_MAX_AUXILIARY_SENDS, 1, &sends);
logger.info() << "device supports " << sends << " aux sends per source";
if (effects) {
bool ok = get_proc_address("alAuxiliaryEffectSloti", alAuxiliaryEffectSloti)
&& get_proc_address("alGenAuxiliaryEffectSlots", alGenAuxiliaryEffectSlots)
&& get_proc_address("alGenEffects", alGenEffects)
&& get_proc_address("alDeleteEffects", alDeleteEffects)
&& get_proc_address("alIsEffect", alIsEffect)
&& get_proc_address("alEffecti", alEffecti)
&& get_proc_address("alEffectf", alEffectf)
&& get_proc_address("alGenFilters", alGenFilters)
&& get_proc_address("alDeleteFilters", alDeleteFilters)
&& get_proc_address("alIsFilter", alIsFilter)
&& get_proc_address("alFilteri", alFilteri)
&& get_proc_address("alFilterf", alFilterf)
;
if (!ok) {
logger.error() << "could not get effects extension function pointers";
effects = false;
}
}
logger.info() << "initialized";
return std::make_unique<ALAudio>(device, context);
return std::make_unique<ALAudio>(device, context, effects);
}
uint ALAudio::getFreeSource() {

View file

@ -3,6 +3,7 @@
#include <glm/glm.hpp>
#include <queue>
#include <string>
#include <array>
#include <unordered_map>
#include <vector>
@ -12,9 +13,11 @@
#ifdef __APPLE__
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#include <OpenAL/alext.h>
#else
#include <AL/al.h>
#include <AL/alc.h>
#include <AL/alext.h>
#endif
namespace audio {
@ -176,10 +179,17 @@ namespace audio {
std::vector<uint> allbuffers;
std::vector<uint> freebuffers;
uint maxSources = 256;
void initEffects();
public:
ALAudio(ALCdevice* device, ALCcontext* context);
std::array<uint, 2> effectSlots;
std::array<uint, 2> effects;
std::array<uint, 1> filters;
bool useEffects;
ALAudio(ALCdevice* device, ALCcontext* context, bool effects);
~ALAudio();
uint getFreeSource();