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; 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( ALSound::ALSound(
ALAudio* al, uint buffer, const std::shared_ptr<PCM>& pcm, bool keepPCM ALAudio* al, uint buffer, const std::shared_ptr<PCM>& pcm, bool keepPCM
) )
@ -382,6 +396,10 @@ void ALSpeaker::play() {
AL_GAIN, AL_GAIN,
volume * p_channel->getVolume() 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)); AL_CHECK(alSourcePlay(source));
} }
@ -455,15 +473,14 @@ int ALSpeaker::getPriority() const {
return priority; return priority;
} }
bool ALSpeaker::isManuallyStopped() const { bool ALSpeaker::isManuallyStopped() const {
return manuallyStopped; return manuallyStopped;
} }
static bool alc_enumeration_ext = false; static bool alc_enumeration_ext = false;
ALAudio::ALAudio(ALCdevice* device, ALCcontext* context) ALAudio::ALAudio(ALCdevice* device, ALCcontext* context, bool useEffects)
: device(device), context(context) { : device(device), context(context), useEffects(useEffects) {
ALCint size; ALCint size;
alcGetIntegerv(device, ALC_ATTRIBUTES_SIZE, 1, &size); alcGetIntegerv(device, ALC_ATTRIBUTES_SIZE, 1, &size);
std::vector<ALCint> attrs(size); std::vector<ALCint> attrs(size);
@ -487,6 +504,11 @@ ALAudio::ALAudio(ALCdevice* device, ALCcontext* context)
} }
alDopplerFactor(1.0 / 3.0); alDopplerFactor(1.0 / 3.0);
alGetError();
if (useEffects) {
initEffects();
}
} }
ALAudio::~ALAudio() { ALAudio::~ALAudio() {
@ -513,6 +535,58 @@ ALAudio::~ALAudio() {
context = nullptr; 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::unique_ptr<Sound> ALAudio::createSound(
std::shared_ptr<PCM> pcm, bool keepPCM 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() { std::unique_ptr<ALAudio> ALAudio::create() {
alc_enumeration_ext = alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT"); alc_enumeration_ext = alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT");
ALCdevice* device = alcOpenDevice(nullptr); 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); ALCcontext* context = alcCreateContext(device, nullptr);
if (!alcMakeContextCurrent(context)) { if (!alcMakeContextCurrent(context)) {
alcCloseDevice(device); alcCloseDevice(device);
return nullptr; return nullptr;
} }
AL_CHECK(); 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"; logger.info() << "initialized";
return std::make_unique<ALAudio>(device, context); return std::make_unique<ALAudio>(device, context, effects);
} }
uint ALAudio::getFreeSource() { uint ALAudio::getFreeSource() {

View file

@ -3,6 +3,7 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <queue> #include <queue>
#include <string> #include <string>
#include <array>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
@ -12,9 +13,11 @@
#ifdef __APPLE__ #ifdef __APPLE__
#include <OpenAL/al.h> #include <OpenAL/al.h>
#include <OpenAL/alc.h> #include <OpenAL/alc.h>
#include <OpenAL/alext.h>
#else #else
#include <AL/al.h> #include <AL/al.h>
#include <AL/alc.h> #include <AL/alc.h>
#include <AL/alext.h>
#endif #endif
namespace audio { namespace audio {
@ -176,10 +179,17 @@ namespace audio {
std::vector<uint> allbuffers; std::vector<uint> allbuffers;
std::vector<uint> freebuffers; std::vector<uint> freebuffers;
uint maxSources = 256; uint maxSources = 256;
void initEffects();
public: 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(); ~ALAudio();
uint getFreeSource(); uint getFreeSource();