mirror of
https://github.com/MihailRis/voxelcore.git
synced 2026-10-12 14:31:50 +00:00
add effects extension support
This commit is contained in:
parent
3637855581
commit
923c694ab4
2 changed files with 134 additions and 7 deletions
|
|
@ -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() {
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue