Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EFX environment and reverb effect. Closes #697. #702

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions rwengine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ set(RWENGINE_SOURCES
src/audio/SoundManager.hpp
src/audio/SoundSource.cpp
src/audio/SoundSource.hpp
src/audio/EffectSlot.hpp
src/audio/EffectSlot.cpp
src/audio/SoundEffect.cpp
src/audio/SoundEffect.hpp
src/audio/ReverbEffect.cpp
src/audio/ReverbEffect.hpp
src/audio/OpenAlExtensions.hpp
src/audio/OpenAlExtensions.cpp

src/core/Logger.cpp
src/core/Logger.hpp
Expand Down
37 changes: 37 additions & 0 deletions rwengine/src/audio/EffectSlot.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include "EffectSlot.hpp"
#include "SoundEffect.hpp"
#include "OpenAlExtensions.hpp"

EffectSlot::EffectSlot() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using an initialization list

alGenAuxiliaryEffectSlots(1, &slotId);

created = alGetError() == AL_NO_ERROR;
}

EffectSlot::~EffectSlot() {
alDeleteAuxiliaryEffectSlots(1, &slotId);
}

bool EffectSlot::attachEffect(std::shared_ptr<SoundEffect> effect) {
alAuxiliaryEffectSloti(slotId, AL_EFFECTSLOT_EFFECT, effect->getId());

if (alGetError() != AL_NO_ERROR) {
return false;
}

this->effect = std::move(effect);

return true;
}

bool EffectSlot::detachEffect() {
alAuxiliaryEffectSloti(slotId, AL_EFFECTSLOT_EFFECT, 0);
this->effect = nullptr;

return alGetError() == AL_NO_ERROR;
}

void EffectSlot::setGain(float gain) {
this->gain = gain;
alAuxiliaryEffectSlotf(slotId, AL_EFFECTSLOT_GAIN, gain);
}
62 changes: 62 additions & 0 deletions rwengine/src/audio/EffectSlot.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#ifndef EFFECTSLOT_H
#define EFFECTSLOT_H

#include <al.h>

#include <memory>

class SoundEffect;

/**
* Effect slot.
*
* Many sound sources can be attached to one slot.
* Different effects can be binded to this (e.g reverb, delay).
*/
class EffectSlot {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have problems with understanding connection between this class and SoundEffect. I mean where is EffectSlot created, used, deleted. Because instances of EffectSlot and SoundEffect are in relation 1 to 1. I think solution when one of them contains/owns instances of second would be good enough.

public:
EffectSlot();
~EffectSlot();

/**
* Attach effect to this slot.
*
* @param sound effect (e.g reverb, delay)
* @return true if effect attached successfully, false otherwise
*/
bool attachEffect(std::shared_ptr<SoundEffect> effect);

/**
* Detach current effect from this slot.
* @return true if effect detached successfully, false otherwise
*/
bool detachEffect();

void setGain(float gain);

ALuint getSlotId() const {
return slotId;
}

int getSlotNumber() const {
return slotNumber;
}

private:
/**
* Effect binded to this slot
*/
std::shared_ptr<SoundEffect> effect;

ALuint slotId;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or you can set members to defaults right here

/**
* This is flag of successfull slot creation
*/
bool created;
float gain = 1.0f;

/// OpenAL aux slot
int slotNumber = 0;
};

#endif // EFFECTSLOT_H
25 changes: 25 additions & 0 deletions rwengine/src/audio/OpenAlExtensions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "OpenAlExtensions.hpp"

LPALGENEFFECTS alGenEffects = nullptr;
LPALDELETEEFFECTS alDeleteEffects = nullptr;
LPALEFFECTI alEffecti = nullptr;
LPALEFFECTF alEffectf = nullptr;

// Auxiliary slot object
LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots = nullptr;
LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots = nullptr;
LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti = nullptr;
LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf = nullptr;

void initEfxFunctionPointers() {
alGenEffects = reinterpret_cast<LPALGENEFFECTS>(alGetProcAddress("alGenEffects"));
alDeleteEffects = reinterpret_cast<LPALDELETEEFFECTS>(alGetProcAddress("alDeleteEffects"));
alEffecti = reinterpret_cast<LPALEFFECTI>(alGetProcAddress("alEffecti"));
alEffectf = reinterpret_cast<LPALEFFECTF>(alGetProcAddress("alEffectf"));

// aux slot
alGenAuxiliaryEffectSlots = reinterpret_cast<LPALGENAUXILIARYEFFECTSLOTS>(alGetProcAddress("alGenAuxiliaryEffectSlots"));
alDeleteAuxiliaryEffectSlots = reinterpret_cast<LPALDELETEAUXILIARYEFFECTSLOTS>(alGetProcAddress("alDeleteAuxiliaryEffectSlots"));
alAuxiliaryEffectSloti = reinterpret_cast<LPALAUXILIARYEFFECTSLOTI>(alGetProcAddress("alAuxiliaryEffectSloti"));
alAuxiliaryEffectSlotf = reinterpret_cast<LPALAUXILIARYEFFECTSLOTF>(alGetProcAddress("alAuxiliaryEffectSlotf"));
}
26 changes: 26 additions & 0 deletions rwengine/src/audio/OpenAlExtensions.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef OPENALEXTENSIONS_HPP
#define OPENALEXTENSIONS_HPP

#include <efx.h>

/**
* Functions to access OpenAL EFX extension
*/

extern LPALGENEFFECTS alGenEffects;
extern LPALDELETEEFFECTS alDeleteEffects;
extern LPALEFFECTI alEffecti;
extern LPALEFFECTF alEffectf;

// Aux slot
extern LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots;
extern LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots;
extern LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti;
extern LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf;

/**
* Initialize function pointers
*/
void initEfxFunctionPointers();

#endif // OPENALEXTENSIONS_HPP
44 changes: 44 additions & 0 deletions rwengine/src/audio/ReverbEffect.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "ReverbEffect.hpp"
#include "OpenAlExtensions.hpp"
#include <efx.h>

ReverbEffect::ReverbEffect() : SoundEffect (AL_EFFECT_REVERB) {

}


void ReverbEffect::setDensity(float d) {
alEffectf(id, AL_REVERB_DENSITY, d);
}

void ReverbEffect::setDiffusion(float d) {
alEffectf(id, AL_REVERB_DIFFUSION, d);
}

void ReverbEffect::setGain(float g) {
alEffectf(id, AL_REVERB_GAIN, g);
}

void ReverbEffect::setGainHf(float g) {
alEffectf(id, AL_REVERB_GAINHF, g);
}

void ReverbEffect::setDecayTime(float t) {
alEffectf(id, AL_REVERB_DECAY_TIME, t);
}

void ReverbEffect::setLateReverbGain(float g) {
alEffectf(id, AL_REVERB_LATE_REVERB_GAIN, g);
}

void ReverbEffect::setLateReverbDelay(float t) {
alEffectf(id, AL_REVERB_LATE_REVERB_DELAY, t);
}

void ReverbEffect::setAirAbsorptionGainHf(float g) {
alEffectf(id, AL_REVERB_AIR_ABSORPTION_GAINHF, g);
}

void ReverbEffect::setDecayHfLimit(bool flag) {
alEffecti(id, AL_REVERB_DECAY_HFLIMIT, flag ? AL_TRUE : AL_FALSE);
}
22 changes: 22 additions & 0 deletions rwengine/src/audio/ReverbEffect.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef REVERBEFFECT_H
#define REVERBEFFECT_H

#include "SoundEffect.hpp"

class ReverbEffect : public SoundEffect {

public:
ReverbEffect();

void setDensity(float density = 1.0f);
void setDiffusion(float diffusion = 0.3f);
void setGain(float gain = 0.92f);
void setGainHf(float gainHf = 0.89f);
void setDecayTime(float decayTime = 5.49f);
void setLateReverbGain(float lateReverbGain = 1.26f );
void setLateReverbDelay(float lateReverbDelay = 0.011f);
void setAirAbsorptionGainHf(float absorptionGainHf = 0.994f);
void setDecayHfLimit(bool decayHfLimit = true);
};

#endif // REVERBEFFECT_H
13 changes: 13 additions & 0 deletions rwengine/src/audio/Sound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

#include "audio/SoundBuffer.hpp"

Sound::~Sound()
{
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting. Use clang-format with our config file.

if (effect != nullptr) {
buffer->disableEffect(effect);
}
}

bool Sound::isPlaying() const {
return buffer->isPlaying();
}
Expand Down Expand Up @@ -46,6 +53,12 @@ void Sound::setMaxDistance(float maxDist) {
buffer->setMaxDistance(maxDist);
}

void Sound::enableEffect(std::shared_ptr<SoundEffect> effect)
{
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also

this->effect = std::move(effect);
buffer->enableEffect(this->effect);
}

size_t Sound::getScriptObjectID() const {
return id;
}
9 changes: 8 additions & 1 deletion rwengine/src/audio/Sound.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#ifndef _RWENGINE_SOUND_HPP_
#define _RWENGINE_SOUND_HPP_

#include <audio/SoundEffect.hpp>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

forward declaration


#include <glm/vec3.hpp>

#include <memory>
#include <optional>

class SoundSource;
struct SoundBuffer;
Expand All @@ -18,8 +21,10 @@ struct Sound {
std::shared_ptr<SoundSource> source;
std::unique_ptr<SoundBuffer> buffer;

std::shared_ptr<SoundEffect> effect;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

raw ptr is enough


Sound() = default;
~Sound() = default;
~Sound();

bool isPlaying() const;

Expand All @@ -42,6 +47,8 @@ struct Sound {

void setMaxDistance(float maxDist);

void enableEffect(std::shared_ptr<SoundEffect> effect);

size_t getScriptObjectID() const;
};
#endif
10 changes: 10 additions & 0 deletions rwengine/src/audio/SoundBuffer.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#include "audio/SoundBuffer.hpp"

#include <rw/types.hpp>
#include <efx.h>

#include "audio/alCheck.hpp"
#include "audio/SoundSource.hpp"
#include "audio/SoundEffect.hpp"

SoundBuffer::SoundBuffer() {
alCheck(alGenSources(1, &source));
Expand Down Expand Up @@ -83,3 +85,11 @@ void SoundBuffer::setGain(float gain) {
void SoundBuffer::setMaxDistance(float maxDist) {
alCheck(alSourcef(source, AL_MAX_DISTANCE, maxDist));
}

void SoundBuffer::enableEffect(std::shared_ptr<SoundEffect> effect) {
alCheck(alSource3i(source, AL_AUXILIARY_SEND_FILTER, (ALint) effect->getSlotId(), effect->getSlotNumber(), AL_FILTER_NULL));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

formatting

}

void SoundBuffer::disableEffect(std::shared_ptr<SoundEffect> effect) {
alCheck(alSource3i (source, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, effect->getSlotNumber(), AL_FILTER_NULL));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also

}
6 changes: 6 additions & 0 deletions rwengine/src/audio/SoundBuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
#include <al.h>
#include <glm/vec3.hpp>

#include <memory>

class SoundEffect;
class SoundSource;

/// OpenAL tool for playing
Expand All @@ -27,6 +30,9 @@ struct SoundBuffer {
void setGain(float gain);
void setMaxDistance(float maxDist);

void enableEffect(std::shared_ptr<SoundEffect> effect);
void disableEffect(std::shared_ptr<SoundEffect> effect);

ALuint source;
ALuint buffer;
};
Expand Down
47 changes: 47 additions & 0 deletions rwengine/src/audio/SoundEffect.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "SoundEffect.hpp"
#include "OpenAlExtensions.hpp"

SoundEffect::SoundEffect(ALint type) {
// reset error
alGetError();

alGenEffects(1, &id);

created = alGetError() == AL_NO_ERROR;
if (!created) {
return;
}

alEffecti(id, AL_EFFECT_TYPE, type);

created = alGetError() == AL_NO_ERROR;
if (!created) {
return;
}

alGenAuxiliaryEffectSlots(1, &slotId);

created = alGetError() == AL_NO_ERROR;
if (!created) {
return;
}

alAuxiliaryEffectSloti(slotId, AL_EFFECTSLOT_EFFECT, (ALint) id);

created = alGetError() == AL_NO_ERROR;
if (!created) {
return;
}

created = alGetError() == AL_NO_ERROR;
}

SoundEffect::~SoundEffect() {
alDeleteEffects(1, &id);
alDeleteAuxiliaryEffectSlots(1, &slotId);
}

void SoundEffect::setGain(float gain) {
this->gain = gain;
alAuxiliaryEffectSlotf(slotId, AL_EFFECTSLOT_GAIN, gain);
}
Loading