2007-12-18 01:43:19 +00:00
|
|
|
#ifndef _AL_AUXEFFECTSLOT_H_
|
|
|
|
#define _AL_AUXEFFECTSLOT_H_
|
|
|
|
|
2012-09-14 09:42:36 +00:00
|
|
|
#include "alMain.h"
|
2008-07-26 02:31:12 +00:00
|
|
|
#include "alEffect.h"
|
2007-12-18 01:43:19 +00:00
|
|
|
|
2014-04-19 09:11:04 +00:00
|
|
|
#include "align.h"
|
|
|
|
|
2007-12-18 01:43:19 +00:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2013-10-07 12:41:41 +00:00
|
|
|
struct ALeffectStateVtable;
|
|
|
|
struct ALeffectslot;
|
2013-05-21 19:47:18 +00:00
|
|
|
|
2013-10-07 12:41:41 +00:00
|
|
|
typedef struct ALeffectState {
|
|
|
|
const struct ALeffectStateVtable *vtbl;
|
2016-03-17 17:10:26 +00:00
|
|
|
|
|
|
|
ALfloat (*OutBuffer)[BUFFERSIZE];
|
|
|
|
ALuint OutChannels;
|
2013-10-07 12:41:41 +00:00
|
|
|
} ALeffectState;
|
2013-05-21 11:18:02 +00:00
|
|
|
|
2016-05-13 01:26:33 +00:00
|
|
|
void ALeffectState_Destruct(ALeffectState *state);
|
|
|
|
|
2013-05-21 11:18:02 +00:00
|
|
|
struct ALeffectStateVtable {
|
2013-10-30 03:08:03 +00:00
|
|
|
void (*const Destruct)(ALeffectState *state);
|
2013-05-29 18:17:45 +00:00
|
|
|
|
|
|
|
ALboolean (*const deviceUpdate)(ALeffectState *state, ALCdevice *device);
|
2016-05-14 01:28:01 +00:00
|
|
|
void (*const update)(ALeffectState *state, const ALCdevice *device, const struct ALeffectslot *slot, const union ALeffectProps *props);
|
2016-01-27 16:16:47 +00:00
|
|
|
void (*const process)(ALeffectState *state, ALuint samplesToDo, const ALfloat (*restrict samplesIn)[BUFFERSIZE], ALfloat (*restrict samplesOut)[BUFFERSIZE], ALuint numChannels);
|
2013-05-26 04:04:00 +00:00
|
|
|
|
2014-03-22 06:56:18 +00:00
|
|
|
void (*const Delete)(void *ptr);
|
2013-05-21 11:18:02 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#define DEFINE_ALEFFECTSTATE_VTABLE(T) \
|
2013-10-30 03:08:03 +00:00
|
|
|
DECLARE_THUNK(T, ALeffectState, void, Destruct) \
|
|
|
|
DECLARE_THUNK1(T, ALeffectState, ALboolean, deviceUpdate, ALCdevice*) \
|
2016-05-14 01:28:01 +00:00
|
|
|
DECLARE_THUNK3(T, ALeffectState, void, update, const ALCdevice*, const ALeffectslot*, const ALeffectProps*) \
|
2016-01-27 16:16:47 +00:00
|
|
|
DECLARE_THUNK4(T, ALeffectState, void, process, ALuint, const ALfloatBUFFERSIZE*restrict, ALfloatBUFFERSIZE*restrict, ALuint) \
|
2014-03-22 06:56:18 +00:00
|
|
|
static void T##_ALeffectState_Delete(void *ptr) \
|
2014-04-19 09:38:32 +00:00
|
|
|
{ return T##_Delete(STATIC_UPCAST(T, ALeffectState, (ALeffectState*)ptr)); } \
|
2013-05-21 12:02:25 +00:00
|
|
|
\
|
2013-05-21 11:18:02 +00:00
|
|
|
static const struct ALeffectStateVtable T##_ALeffectState_vtable = { \
|
2013-05-21 20:02:56 +00:00
|
|
|
T##_ALeffectState_Destruct, \
|
2013-05-29 18:17:45 +00:00
|
|
|
\
|
|
|
|
T##_ALeffectState_deviceUpdate, \
|
|
|
|
T##_ALeffectState_update, \
|
|
|
|
T##_ALeffectState_process, \
|
|
|
|
\
|
2013-05-26 04:04:00 +00:00
|
|
|
T##_ALeffectState_Delete, \
|
2013-05-21 11:18:02 +00:00
|
|
|
}
|
|
|
|
|
2013-05-21 19:47:18 +00:00
|
|
|
|
2013-10-07 12:41:41 +00:00
|
|
|
struct ALeffectStateFactoryVtable;
|
2013-05-21 19:47:18 +00:00
|
|
|
|
2013-10-07 12:41:41 +00:00
|
|
|
typedef struct ALeffectStateFactory {
|
2013-05-21 19:47:18 +00:00
|
|
|
const struct ALeffectStateFactoryVtable *vtbl;
|
2013-10-07 12:41:41 +00:00
|
|
|
} ALeffectStateFactory;
|
|
|
|
|
|
|
|
struct ALeffectStateFactoryVtable {
|
|
|
|
ALeffectState *(*const create)(ALeffectStateFactory *factory);
|
2013-05-21 19:47:18 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#define DEFINE_ALEFFECTSTATEFACTORY_VTABLE(T) \
|
2013-10-30 03:08:03 +00:00
|
|
|
DECLARE_THUNK(T, ALeffectStateFactory, ALeffectState*, create) \
|
2013-05-21 19:47:18 +00:00
|
|
|
\
|
|
|
|
static const struct ALeffectStateFactoryVtable T##_ALeffectStateFactory_vtable = { \
|
|
|
|
T##_ALeffectStateFactory_create, \
|
|
|
|
}
|
2012-09-14 09:42:36 +00:00
|
|
|
|
2009-05-29 20:30:50 +00:00
|
|
|
|
2016-01-28 08:02:46 +00:00
|
|
|
#define MAX_EFFECT_CHANNELS (4)
|
|
|
|
|
|
|
|
|
2016-05-13 01:26:33 +00:00
|
|
|
struct ALeffectslotProps {
|
|
|
|
ATOMIC(ALfloat) Gain;
|
|
|
|
ATOMIC(ALboolean) AuxSendAuto;
|
|
|
|
|
|
|
|
ATOMIC(ALenum) Type;
|
|
|
|
ALeffectProps Props;
|
|
|
|
|
2016-05-13 02:05:06 +00:00
|
|
|
/* Flag indicates if State should be updated. */
|
|
|
|
ATOMIC(ALboolean) UpdateState;
|
2016-05-13 01:26:33 +00:00
|
|
|
ATOMIC(ALeffectState*) State;
|
|
|
|
|
|
|
|
ATOMIC(struct ALeffectslotProps*) next;
|
|
|
|
};
|
|
|
|
|
2007-12-18 22:22:59 +00:00
|
|
|
|
2016-05-13 01:26:33 +00:00
|
|
|
typedef struct ALeffectslot {
|
2011-09-11 09:01:31 +00:00
|
|
|
volatile ALfloat Gain;
|
|
|
|
volatile ALboolean AuxSendAuto;
|
2007-12-18 23:47:24 +00:00
|
|
|
|
2016-05-13 01:26:33 +00:00
|
|
|
struct {
|
|
|
|
ALenum Type;
|
|
|
|
ALeffectProps Props;
|
|
|
|
|
|
|
|
ALeffectState *State;
|
|
|
|
} Effect;
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
|
2011-08-30 06:05:47 +00:00
|
|
|
RefCount ref;
|
2008-01-16 21:20:09 +00:00
|
|
|
|
2016-05-13 01:26:33 +00:00
|
|
|
ATOMIC(struct ALeffectslotProps*) Update;
|
|
|
|
ATOMIC(struct ALeffectslotProps*) FreeList;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
ALfloat Gain;
|
|
|
|
ALboolean AuxSendAuto;
|
|
|
|
|
|
|
|
ALenum EffectType;
|
|
|
|
ALeffectState *EffectState;
|
|
|
|
|
|
|
|
ALfloat RoomRolloff; /* Added to the source's room rolloff, not multiplied. */
|
|
|
|
ALfloat DecayTime;
|
|
|
|
ALfloat AirAbsorptionGainHF;
|
|
|
|
} Params;
|
|
|
|
|
2012-04-20 05:28:01 +00:00
|
|
|
/* Self ID */
|
|
|
|
ALuint id;
|
2016-01-28 08:02:46 +00:00
|
|
|
|
|
|
|
ALuint NumChannels;
|
2016-04-15 04:50:36 +00:00
|
|
|
BFChannelConfig ChanMap[MAX_EFFECT_CHANNELS];
|
2016-01-28 08:02:46 +00:00
|
|
|
/* Wet buffer configuration is ACN channel order with N3D scaling:
|
|
|
|
* * Channel 0 is the unattenuated mono signal.
|
|
|
|
* * Channel 1 is OpenAL -X
|
|
|
|
* * Channel 2 is OpenAL Y
|
|
|
|
* * Channel 3 is OpenAL -Z
|
|
|
|
* Consequently, effects that only want to work with mono input can use
|
|
|
|
* channel 0 by itself. Effects that want multichannel can process the
|
2016-04-15 17:50:46 +00:00
|
|
|
* ambisonics signal and make a B-Format pan (ComputeFirstOrderGains) for
|
|
|
|
* first-order device output (FOAOut).
|
2016-01-28 08:02:46 +00:00
|
|
|
*/
|
|
|
|
alignas(16) ALfloat WetBuffer[MAX_EFFECT_CHANNELS][BUFFERSIZE];
|
2013-10-07 12:41:41 +00:00
|
|
|
} ALeffectslot;
|
2007-12-18 01:43:19 +00:00
|
|
|
|
2013-11-04 21:51:19 +00:00
|
|
|
inline struct ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id)
|
|
|
|
{ return (struct ALeffectslot*)LookupUIntMapKey(&context->EffectSlotMap, id); }
|
|
|
|
inline struct ALeffectslot *RemoveEffectSlot(ALCcontext *context, ALuint id)
|
|
|
|
{ return (struct ALeffectslot*)RemoveUIntMapKey(&context->EffectSlotMap, id); }
|
2007-12-18 01:43:19 +00:00
|
|
|
|
2012-01-21 00:23:15 +00:00
|
|
|
ALenum InitEffectSlot(ALeffectslot *slot);
|
2016-05-13 01:26:33 +00:00
|
|
|
void DeinitEffectSlot(ALeffectslot *slot);
|
2016-05-13 02:05:06 +00:00
|
|
|
void UpdateEffectSlotProps(ALeffectslot *slot, ALboolean withstate);
|
2008-01-16 00:22:39 +00:00
|
|
|
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context);
|
2007-12-18 01:43:19 +00:00
|
|
|
|
2009-05-29 20:30:50 +00:00
|
|
|
|
2013-05-24 01:50:07 +00:00
|
|
|
ALeffectStateFactory *ALnullStateFactory_getFactory(void);
|
2013-05-21 19:47:18 +00:00
|
|
|
ALeffectStateFactory *ALreverbStateFactory_getFactory(void);
|
2013-10-03 10:32:54 +00:00
|
|
|
ALeffectStateFactory *ALautowahStateFactory_getFactory(void);
|
2013-05-21 19:47:18 +00:00
|
|
|
ALeffectStateFactory *ALchorusStateFactory_getFactory(void);
|
2013-10-03 14:55:12 +00:00
|
|
|
ALeffectStateFactory *ALcompressorStateFactory_getFactory(void);
|
2013-05-21 19:47:18 +00:00
|
|
|
ALeffectStateFactory *ALdistortionStateFactory_getFactory(void);
|
|
|
|
ALeffectStateFactory *ALechoStateFactory_getFactory(void);
|
|
|
|
ALeffectStateFactory *ALequalizerStateFactory_getFactory(void);
|
|
|
|
ALeffectStateFactory *ALflangerStateFactory_getFactory(void);
|
|
|
|
ALeffectStateFactory *ALmodulatorStateFactory_getFactory(void);
|
|
|
|
|
|
|
|
ALeffectStateFactory *ALdedicatedStateFactory_getFactory(void);
|
|
|
|
|
2009-05-29 20:30:50 +00:00
|
|
|
|
2012-03-13 21:58:34 +00:00
|
|
|
ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *effect);
|
2009-05-29 20:30:50 +00:00
|
|
|
|
2013-05-21 19:47:18 +00:00
|
|
|
void InitEffectFactoryMap(void);
|
|
|
|
void DeinitEffectFactoryMap(void);
|
|
|
|
|
2007-12-18 01:43:19 +00:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|