aboutsummaryrefslogtreecommitdiffstats
path: root/alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2019-10-02 16:53:23 -0700
committerChris Robinson <[email protected]>2019-10-02 16:53:23 -0700
commit64e2c377d865d67efdac675c355e7b1a6b4166e6 (patch)
tree574d85a15e26c6041da98b23d4c00ab264f481aa /alc
parentd639935e1975db4276f6ee8c3622684cefa6b269 (diff)
Move ALvoice from alu.h to a separate header
Diffstat (limited to 'alc')
-rw-r--r--alc/alcontext.h1
-rw-r--r--alc/alu.cpp44
-rw-r--r--alc/alu.h287
-rw-r--r--alc/converter.h1
-rw-r--r--alc/mixer/defs.h16
-rw-r--r--alc/mixer/hrtfbase.h1
-rw-r--r--alc/voice.cpp34
-rw-r--r--alc/voice.h293
8 files changed, 351 insertions, 326 deletions
diff --git a/alc/alcontext.h b/alc/alcontext.h
index dd622654..ba3942f5 100644
--- a/alc/alcontext.h
+++ b/alc/alcontext.h
@@ -22,6 +22,7 @@
#include "logging.h"
#include "threads.h"
#include "vector.h"
+#include "voice.h"
struct ALeffectslot;
struct ALeffectslotProps;
diff --git a/alc/alu.cpp b/alc/alu.cpp
index 21eea1db..6d3e5549 100644
--- a/alc/alu.cpp
+++ b/alc/alu.cpp
@@ -25,14 +25,12 @@
#include <algorithm>
#include <array>
#include <atomic>
-#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
-#include <cstring>
#include <functional>
#include <iterator>
#include <limits>
@@ -78,6 +76,7 @@
#include "threads.h"
#include "uhjfilter.h"
#include "vecmat.h"
+#include "voice.h"
#include "bsinc_inc.h"
@@ -122,21 +121,50 @@ const ALfloat ConeScale{InitConeScale()};
/* Localized Z scalar for mono sources */
const ALfloat ZScale{InitZScale()};
+MixerFunc MixSamples{Mix_<CTag>};
+RowMixerFunc MixRowSamples{MixRow_<CTag>};
namespace {
-void ClearArray(ALfloat (&f)[MAX_OUTPUT_CHANNELS])
-{
- std::fill(std::begin(f), std::end(f), 0.0f);
-}
-
struct ChanMap {
Channel channel;
ALfloat angle;
ALfloat elevation;
};
+void ClearArray(ALfloat (&f)[MAX_OUTPUT_CHANNELS])
+{
+ std::fill(std::begin(f), std::end(f), 0.0f);
+}
+
HrtfDirectMixerFunc MixDirectHrtf = MixDirectHrtf_<CTag>;
+
+inline MixerFunc SelectMixer()
+{
+#ifdef HAVE_NEON
+ if((CPUCapFlags&CPU_CAP_NEON))
+ return Mix_<NEONTag>;
+#endif
+#ifdef HAVE_SSE
+ if((CPUCapFlags&CPU_CAP_SSE))
+ return Mix_<SSETag>;
+#endif
+ return Mix_<CTag>;
+}
+
+inline RowMixerFunc SelectRowMixer()
+{
+#ifdef HAVE_NEON
+ if((CPUCapFlags&CPU_CAP_NEON))
+ return MixRow_<NEONTag>;
+#endif
+#ifdef HAVE_SSE
+ if((CPUCapFlags&CPU_CAP_SSE))
+ return MixRow_<SSETag>;
+#endif
+ return MixRow_<CTag>;
+}
+
inline HrtfDirectMixerFunc SelectHrtfMixer(void)
{
#ifdef HAVE_NEON
@@ -232,6 +260,8 @@ inline ResamplerFunc SelectResampler(Resampler resampler, ALuint increment)
void aluInit(void)
{
+ MixSamples = SelectMixer();
+ MixRowSamples = SelectRowMixer();
MixDirectHrtf = SelectHrtfMixer();
}
diff --git a/alc/alu.h b/alc/alu.h
index 90a28654..e10bd7ab 100644
--- a/alc/alu.h
+++ b/alc/alu.h
@@ -25,9 +25,9 @@
struct ALbufferlistitem;
struct ALeffectslot;
-
enum class DistanceModel;
+
#define MAX_PITCH 255
#define MAX_SENDS 16
@@ -35,283 +35,6 @@ enum class DistanceModel;
#define DITHER_RNG_SEED 22222
-enum SpatializeMode {
- SpatializeOff = AL_FALSE,
- SpatializeOn = AL_TRUE,
- SpatializeAuto = AL_AUTO_SOFT
-};
-
-enum class Resampler {
- Point,
- Linear,
- Cubic,
- FastBSinc12,
- BSinc12,
- FastBSinc24,
- BSinc24,
-
- Max = BSinc24
-};
-extern Resampler ResamplerDefault;
-
-/* The number of distinct scale and phase intervals within the bsinc filter
- * table.
- */
-#define BSINC_SCALE_BITS 4
-#define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
-#define BSINC_PHASE_BITS 5
-#define BSINC_PHASE_COUNT (1<<BSINC_PHASE_BITS)
-
-/* Interpolator state. Kind of a misnomer since the interpolator itself is
- * stateless. This just keeps it from having to recompute scale-related
- * mappings for every sample.
- */
-struct BsincState {
- ALfloat sf; /* Scale interpolation factor. */
- ALuint m; /* Coefficient count. */
- ALuint l; /* Left coefficient offset. */
- /* Filter coefficients, followed by the scale, phase, and scale-phase
- * delta coefficients. Starting at phase index 0, each subsequent phase
- * index follows contiguously.
- */
- const ALfloat *filter;
-};
-
-union InterpState {
- BsincState bsinc;
-};
-
-using ResamplerFunc = const ALfloat*(*)(const InterpState *state, const ALfloat *RESTRICT src,
- ALuint frac, ALuint increment, const al::span<float> dst);
-
-
-enum {
- AF_None = 0,
- AF_LowPass = 1,
- AF_HighPass = 2,
- AF_BandPass = AF_LowPass | AF_HighPass
-};
-
-
-struct MixHrtfFilter {
- const HrirArray *Coeffs;
- ALsizei Delay[2];
- ALfloat Gain;
- ALfloat GainStep;
-};
-
-
-struct DirectParams {
- BiquadFilter LowPass;
- BiquadFilter HighPass;
-
- NfcFilter NFCtrlFilter;
-
- struct {
- HrtfFilter Old;
- HrtfFilter Target;
- HrtfState State;
- } Hrtf;
-
- struct {
- ALfloat Current[MAX_OUTPUT_CHANNELS];
- ALfloat Target[MAX_OUTPUT_CHANNELS];
- } Gains;
-};
-
-struct SendParams {
- BiquadFilter LowPass;
- BiquadFilter HighPass;
-
- struct {
- ALfloat Current[MAX_OUTPUT_CHANNELS];
- ALfloat Target[MAX_OUTPUT_CHANNELS];
- } Gains;
-};
-
-
-struct ALvoicePropsBase {
- ALfloat Pitch;
- ALfloat Gain;
- ALfloat OuterGain;
- ALfloat MinGain;
- ALfloat MaxGain;
- ALfloat InnerAngle;
- ALfloat OuterAngle;
- ALfloat RefDistance;
- ALfloat MaxDistance;
- ALfloat RolloffFactor;
- std::array<ALfloat,3> Position;
- std::array<ALfloat,3> Velocity;
- std::array<ALfloat,3> Direction;
- std::array<ALfloat,3> OrientAt;
- std::array<ALfloat,3> OrientUp;
- ALboolean HeadRelative;
- DistanceModel mDistanceModel;
- Resampler mResampler;
- ALboolean DirectChannels;
- SpatializeMode mSpatializeMode;
-
- ALboolean DryGainHFAuto;
- ALboolean WetGainAuto;
- ALboolean WetGainHFAuto;
- ALfloat OuterGainHF;
-
- ALfloat AirAbsorptionFactor;
- ALfloat RoomRolloffFactor;
- ALfloat DopplerFactor;
-
- std::array<ALfloat,2> StereoPan;
-
- ALfloat Radius;
-
- /** Direct filter and auxiliary send info. */
- struct {
- ALfloat Gain;
- ALfloat GainHF;
- ALfloat HFReference;
- ALfloat GainLF;
- ALfloat LFReference;
- } Direct;
- struct SendData {
- ALeffectslot *Slot;
- ALfloat Gain;
- ALfloat GainHF;
- ALfloat HFReference;
- ALfloat GainLF;
- ALfloat LFReference;
- } Send[MAX_SENDS];
-};
-
-struct ALvoiceProps : public ALvoicePropsBase {
- std::atomic<ALvoiceProps*> next{nullptr};
-
- DEF_NEWDEL(ALvoiceProps)
-};
-
-#define VOICE_IS_STATIC (1u<<0)
-#define VOICE_IS_FADING (1u<<1) /* Fading sources use gain stepping for smooth transitions. */
-#define VOICE_IS_AMBISONIC (1u<<2) /* Voice needs HF scaling for ambisonic upsampling. */
-#define VOICE_HAS_HRTF (1u<<3)
-#define VOICE_HAS_NFC (1u<<4)
-
-struct ALvoice {
- enum State {
- Stopped = 0,
- Playing = 1,
- Stopping = 2
- };
-
- std::atomic<ALvoiceProps*> mUpdate{nullptr};
-
- std::atomic<ALuint> mSourceID{0u};
- std::atomic<State> mPlayState{Stopped};
-
- ALvoicePropsBase mProps;
-
- /**
- * Source offset in samples, relative to the currently playing buffer, NOT
- * the whole queue.
- */
- std::atomic<ALuint> mPosition;
- /** Fractional (fixed-point) offset to the next sample. */
- std::atomic<ALuint> mPositionFrac;
-
- /* Current buffer queue item being played. */
- std::atomic<ALbufferlistitem*> mCurrentBuffer;
-
- /* Buffer queue item to loop to at end of queue (will be NULL for non-
- * looping voices).
- */
- std::atomic<ALbufferlistitem*> mLoopBuffer;
-
- /* Properties for the attached buffer(s). */
- FmtChannels mFmtChannels;
- ALuint mFrequency;
- ALuint mNumChannels;
- ALuint mSampleSize;
-
- /** Current target parameters used for mixing. */
- ALuint mStep;
-
- ResamplerFunc mResampler;
-
- InterpState mResampleState;
-
- ALuint mFlags;
-
- struct DirectData {
- int FilterType;
- al::span<FloatBufferLine> Buffer;
- };
- DirectData mDirect;
-
- struct SendData {
- int FilterType;
- al::span<FloatBufferLine> Buffer;
- };
- std::array<SendData,MAX_SENDS> mSend;
-
- struct ChannelData {
- alignas(16) std::array<ALfloat,MAX_RESAMPLER_PADDING> mPrevSamples;
-
- ALfloat mAmbiScale;
- BandSplitter mAmbiSplitter;
-
- DirectParams mDryParams;
- std::array<SendParams,MAX_SENDS> mWetParams;
- };
- std::array<ChannelData,MAX_INPUT_CHANNELS> mChans;
-
- ALvoice() = default;
- ALvoice(const ALvoice&) = delete;
- ALvoice(ALvoice&& rhs) noexcept { *this = std::move(rhs); }
- ~ALvoice() { delete mUpdate.exchange(nullptr, std::memory_order_acq_rel); }
- ALvoice& operator=(const ALvoice&) = delete;
- ALvoice& operator=(ALvoice&& rhs) noexcept
- {
- ALvoiceProps *old_update{mUpdate.load(std::memory_order_relaxed)};
- mUpdate.store(rhs.mUpdate.exchange(old_update, std::memory_order_relaxed),
- std::memory_order_relaxed);
-
- mSourceID.store(rhs.mSourceID.load(std::memory_order_relaxed), std::memory_order_relaxed);
- mPlayState.store(rhs.mPlayState.load(std::memory_order_relaxed),
- std::memory_order_relaxed);
-
- mProps = rhs.mProps;
-
- mPosition.store(rhs.mPosition.load(std::memory_order_relaxed), std::memory_order_relaxed);
- mPositionFrac.store(rhs.mPositionFrac.load(std::memory_order_relaxed),
- std::memory_order_relaxed);
-
- mCurrentBuffer.store(rhs.mCurrentBuffer.load(std::memory_order_relaxed),
- std::memory_order_relaxed);
- mLoopBuffer.store(rhs.mLoopBuffer.load(std::memory_order_relaxed),
- std::memory_order_relaxed);
-
- mFmtChannels = rhs.mFmtChannels;
- mFrequency = rhs.mFrequency;
- mNumChannels = rhs.mNumChannels;
- mSampleSize = rhs.mSampleSize;
-
- mStep = rhs.mStep;
- mResampler = rhs.mResampler;
-
- mResampleState = rhs.mResampleState;
-
- mFlags = rhs.mFlags;
-
- mDirect = rhs.mDirect;
- mSend = rhs.mSend;
- mChans = rhs.mChans;
-
- return *this;
- }
-
- void mix(ALvoice::State vstate, ALCcontext *Context, const ALuint SamplesToDo);
-};
-
-
using MixerFunc = void(*)(const al::span<const float> InSamples,
const al::span<FloatBufferLine> OutBuffer, float *CurrentGains, const float *TargetGains,
const size_t Counter, const size_t OutPos);
@@ -321,6 +44,9 @@ using HrtfDirectMixerFunc = void(*)(FloatBufferLine &LeftOut, FloatBufferLine &R
const al::span<const FloatBufferLine> InSamples, float2 *AccumSamples, DirectHrtfState *State,
const size_t BufferSize);
+extern MixerFunc MixSamples;
+extern RowMixerFunc MixRowSamples;
+
#define GAIN_MIX_MAX (1000.0f) /* +60dB */
@@ -369,8 +95,6 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, HrtfRequestMode hrtf_appr
void aluInitEffectPanning(ALeffectslot *slot, ALCdevice *device);
-ResamplerFunc PrepareResampler(Resampler resampler, ALuint increment, InterpState *state);
-
/**
* Calculates ambisonic encoder coefficients using the X, Y, and Z direction
* components, which must represent a normalized (unit length) vector, and the
@@ -441,9 +165,6 @@ void aluMixData(ALCdevice *device, ALvoid *OutBuffer, const ALuint NumSamples);
/* Caller must lock the device state, and the mixer must not be running. */
void aluHandleDisconnect(ALCdevice *device, const char *msg, ...) DECL_FORMAT(printf, 2, 3);
-extern MixerFunc MixSamples;
-extern RowMixerFunc MixRowSamples;
-
extern const ALfloat ConeScale;
extern const ALfloat ZScale;
diff --git a/alc/converter.h b/alc/converter.h
index d8fe7ba9..5842df07 100644
--- a/alc/converter.h
+++ b/alc/converter.h
@@ -11,6 +11,7 @@
#include "alnumeric.h"
#include "alu.h"
#include "devformat.h"
+#include "voice.h"
struct SampleConverter {
diff --git a/alc/mixer/defs.h b/alc/mixer/defs.h
index ce572973..b72b2526 100644
--- a/alc/mixer/defs.h
+++ b/alc/mixer/defs.h
@@ -5,9 +5,11 @@
#include "alcmain.h"
#include "alspan.h"
-#include "alu.h"
#include "hrtf.h"
+union InterpState;
+struct MixHrtfFilter;
+
enum InstSetType {
CTag,
@@ -39,11 +41,17 @@ void MixRow_(const al::span<float> OutBuffer, const al::span<const float> Gains,
const float *InSamples, const size_t InStride);
template<InstSetType InstTag>
-void MixHrtf_(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, const ALfloat *InSamples, float2 *AccumSamples, const size_t OutPos, const ALuint IrSize, MixHrtfFilter *hrtfparams, const size_t BufferSize);
+void MixHrtf_(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, const ALfloat *InSamples,
+ float2 *AccumSamples, const size_t OutPos, const ALuint IrSize, MixHrtfFilter *hrtfparams,
+ const size_t BufferSize);
template<InstSetType InstTag>
-void MixHrtfBlend_(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, const ALfloat *InSamples, float2 *AccumSamples, const size_t OutPos, const ALuint IrSize, const HrtfFilter *oldparams, MixHrtfFilter *newparams, const size_t BufferSize);
+void MixHrtfBlend_(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, const ALfloat *InSamples,
+ float2 *AccumSamples, const size_t OutPos, const ALuint IrSize, const HrtfFilter *oldparams,
+ MixHrtfFilter *newparams, const size_t BufferSize);
template<InstSetType InstTag>
-void MixDirectHrtf_(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, const al::span<const FloatBufferLine> InSamples, float2 *AccumSamples, DirectHrtfState *State, const size_t BufferSize);
+void MixDirectHrtf_(FloatBufferLine &LeftOut, FloatBufferLine &RightOut,
+ const al::span<const FloatBufferLine> InSamples, float2 *AccumSamples, DirectHrtfState *State,
+ const size_t BufferSize);
/* Vectorized resampler helpers */
inline void InitPosArrays(ALuint frac, ALuint increment, ALuint *frac_arr, ALuint *pos_arr,
diff --git a/alc/mixer/hrtfbase.h b/alc/mixer/hrtfbase.h
index d2432e90..af45a128 100644
--- a/alc/mixer/hrtfbase.h
+++ b/alc/mixer/hrtfbase.h
@@ -6,6 +6,7 @@
#include "alu.h"
#include "../hrtf.h"
#include "opthelpers.h"
+#include "voice.h"
using ApplyCoeffsT = void(size_t Offset, float2 *RESTRICT Values, const ALuint irSize,
diff --git a/alc/voice.cpp b/alc/voice.cpp
index a828e21f..59360e4e 100644
--- a/alc/voice.cpp
+++ b/alc/voice.cpp
@@ -20,6 +20,8 @@
#include "config.h"
+#include "voice.h"
+
#include <algorithm>
#include <array>
#include <atomic>
@@ -30,7 +32,6 @@
#include <iterator>
#include <memory>
#include <new>
-#include <string>
#include <utility>
#include "AL/al.h"
@@ -69,9 +70,6 @@ static_assert((INT_MAX>>FRACTIONBITS)/MAX_PITCH > BUFFERSIZE,
Resampler ResamplerDefault{Resampler::Linear};
-MixerFunc MixSamples = Mix_<CTag>;
-RowMixerFunc MixRowSamples = MixRow_<CTag>;
-
namespace {
using HrtfMixerFunc = void(*)(FloatBufferLine &LeftOut, FloatBufferLine &RightOut,
@@ -84,32 +82,6 @@ using HrtfMixerBlendFunc = void(*)(FloatBufferLine &LeftOut, FloatBufferLine &Ri
HrtfMixerFunc MixHrtfSamples = MixHrtf_<CTag>;
HrtfMixerBlendFunc MixHrtfBlendSamples = MixHrtfBlend_<CTag>;
-inline MixerFunc SelectMixer()
-{
-#ifdef HAVE_NEON
- if((CPUCapFlags&CPU_CAP_NEON))
- return Mix_<NEONTag>;
-#endif
-#ifdef HAVE_SSE
- if((CPUCapFlags&CPU_CAP_SSE))
- return Mix_<SSETag>;
-#endif
- return Mix_<CTag>;
-}
-
-inline RowMixerFunc SelectRowMixer()
-{
-#ifdef HAVE_NEON
- if((CPUCapFlags&CPU_CAP_NEON))
- return MixRow_<NEONTag>;
-#endif
-#ifdef HAVE_SSE
- if((CPUCapFlags&CPU_CAP_SSE))
- return MixRow_<SSETag>;
-#endif
- return MixRow_<CTag>;
-}
-
inline HrtfMixerFunc SelectHrtfMixer()
{
#ifdef HAVE_NEON
@@ -180,8 +152,6 @@ void aluInitMixer()
MixHrtfBlendSamples = SelectHrtfBlendMixer();
MixHrtfSamples = SelectHrtfMixer();
- MixSamples = SelectMixer();
- MixRowSamples = SelectRowMixer();
}
diff --git a/alc/voice.h b/alc/voice.h
new file mode 100644
index 00000000..c4bea635
--- /dev/null
+++ b/alc/voice.h
@@ -0,0 +1,293 @@
+#ifndef VOICE_H
+#define VOICE_H
+
+#include "AL/al.h"
+#include "AL/alext.h"
+
+#include "alspan.h"
+#include "alu.h"
+#include "filters/biquad.h"
+#include "filters/nfc.h"
+#include "filters/splitter.h"
+#include "hrtf.h"
+
+
+enum SpatializeMode {
+ SpatializeOff = AL_FALSE,
+ SpatializeOn = AL_TRUE,
+ SpatializeAuto = AL_AUTO_SOFT
+};
+
+enum class Resampler {
+ Point,
+ Linear,
+ Cubic,
+ FastBSinc12,
+ BSinc12,
+ FastBSinc24,
+ BSinc24,
+
+ Max = BSinc24
+};
+extern Resampler ResamplerDefault;
+
+/* The number of distinct scale and phase intervals within the bsinc filter
+ * table.
+ */
+#define BSINC_SCALE_BITS 4
+#define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
+#define BSINC_PHASE_BITS 5
+#define BSINC_PHASE_COUNT (1<<BSINC_PHASE_BITS)
+
+/* Interpolator state. Kind of a misnomer since the interpolator itself is
+ * stateless. This just keeps it from having to recompute scale-related
+ * mappings for every sample.
+ */
+struct BsincState {
+ float sf; /* Scale interpolation factor. */
+ ALuint m; /* Coefficient count. */
+ ALuint l; /* Left coefficient offset. */
+ /* Filter coefficients, followed by the scale, phase, and scale-phase
+ * delta coefficients. Starting at phase index 0, each subsequent phase
+ * index follows contiguously.
+ */
+ const float *filter;
+};
+
+union InterpState {
+ BsincState bsinc;
+};
+
+using ResamplerFunc = const float*(*)(const InterpState *state, const float *RESTRICT src,
+ ALuint frac, ALuint increment, const al::span<float> dst);
+
+ResamplerFunc PrepareResampler(Resampler resampler, ALuint increment, InterpState *state);
+
+
+enum {
+ AF_None = 0,
+ AF_LowPass = 1,
+ AF_HighPass = 2,
+ AF_BandPass = AF_LowPass | AF_HighPass
+};
+
+
+struct MixHrtfFilter {
+ const HrirArray *Coeffs;
+ ALsizei Delay[2];
+ float Gain;
+ float GainStep;
+};
+
+
+struct DirectParams {
+ BiquadFilter LowPass;
+ BiquadFilter HighPass;
+
+ NfcFilter NFCtrlFilter;
+
+ struct {
+ HrtfFilter Old;
+ HrtfFilter Target;
+ HrtfState State;
+ } Hrtf;
+
+ struct {
+ float Current[MAX_OUTPUT_CHANNELS];
+ float Target[MAX_OUTPUT_CHANNELS];
+ } Gains;
+};
+
+struct SendParams {
+ BiquadFilter LowPass;
+ BiquadFilter HighPass;
+
+ struct {
+ float Current[MAX_OUTPUT_CHANNELS];
+ float Target[MAX_OUTPUT_CHANNELS];
+ } Gains;
+};
+
+
+struct ALvoicePropsBase {
+ float Pitch;
+ float Gain;
+ float OuterGain;
+ float MinGain;
+ float MaxGain;
+ float InnerAngle;
+ float OuterAngle;
+ float RefDistance;
+ float MaxDistance;
+ float RolloffFactor;
+ std::array<float,3> Position;
+ std::array<float,3> Velocity;
+ std::array<float,3> Direction;
+ std::array<float,3> OrientAt;
+ std::array<float,3> OrientUp;
+ bool HeadRelative;
+ DistanceModel mDistanceModel;
+ Resampler mResampler;
+ bool DirectChannels;
+ SpatializeMode mSpatializeMode;
+
+ bool DryGainHFAuto;
+ bool WetGainAuto;
+ bool WetGainHFAuto;
+ float OuterGainHF;
+
+ float AirAbsorptionFactor;
+ float RoomRolloffFactor;
+ float DopplerFactor;
+
+ std::array<float,2> StereoPan;
+
+ float Radius;
+
+ /** Direct filter and auxiliary send info. */
+ struct {
+ float Gain;
+ float GainHF;
+ float HFReference;
+ float GainLF;
+ float LFReference;
+ } Direct;
+ struct SendData {
+ ALeffectslot *Slot;
+ float Gain;
+ float GainHF;
+ float HFReference;
+ float GainLF;
+ float LFReference;
+ } Send[MAX_SENDS];
+};
+
+struct ALvoiceProps : public ALvoicePropsBase {
+ std::atomic<ALvoiceProps*> next{nullptr};
+
+ DEF_NEWDEL(ALvoiceProps)
+};
+
+#define VOICE_IS_STATIC (1u<<0)
+#define VOICE_IS_FADING (1u<<1) /* Fading sources use gain stepping for smooth transitions. */
+#define VOICE_IS_AMBISONIC (1u<<2) /* Voice needs HF scaling for ambisonic upsampling. */
+#define VOICE_HAS_HRTF (1u<<3)
+#define VOICE_HAS_NFC (1u<<4)
+
+struct ALvoice {
+ enum State {
+ Stopped = 0,
+ Playing = 1,
+ Stopping = 2
+ };
+
+ std::atomic<ALvoiceProps*> mUpdate{nullptr};
+
+ std::atomic<ALuint> mSourceID{0u};
+ std::atomic<State> mPlayState{Stopped};
+
+ ALvoicePropsBase mProps;
+
+ /**
+ * Source offset in samples, relative to the currently playing buffer, NOT
+ * the whole queue.
+ */
+ std::atomic<ALuint> mPosition;
+ /** Fractional (fixed-point) offset to the next sample. */
+ std::atomic<ALuint> mPositionFrac;
+
+ /* Current buffer queue item being played. */
+ std::atomic<ALbufferlistitem*> mCurrentBuffer;
+
+ /* Buffer queue item to loop to at end of queue (will be NULL for non-
+ * looping voices).
+ */
+ std::atomic<ALbufferlistitem*> mLoopBuffer;
+
+ /* Properties for the attached buffer(s). */
+ FmtChannels mFmtChannels;
+ ALuint mFrequency;
+ ALuint mNumChannels;
+ ALuint mSampleSize;
+
+ /** Current target parameters used for mixing. */
+ ALuint mStep;
+
+ ResamplerFunc mResampler;
+
+ InterpState mResampleState;
+
+ ALuint mFlags;
+
+ struct DirectData {
+ int FilterType;
+ al::span<FloatBufferLine> Buffer;
+ };
+ DirectData mDirect;
+
+ struct SendData {
+ int FilterType;
+ al::span<FloatBufferLine> Buffer;
+ };
+ std::array<SendData,MAX_SENDS> mSend;
+
+ struct ChannelData {
+ alignas(16) std::array<ALfloat,MAX_RESAMPLER_PADDING> mPrevSamples;
+
+ ALfloat mAmbiScale;
+ BandSplitter mAmbiSplitter;
+
+ DirectParams mDryParams;
+ std::array<SendParams,MAX_SENDS> mWetParams;
+ };
+ std::array<ChannelData,MAX_INPUT_CHANNELS> mChans;
+
+ ALvoice() = default;
+ ALvoice(const ALvoice&) = delete;
+ ALvoice(ALvoice&& rhs) noexcept { *this = std::move(rhs); }
+ ~ALvoice() { delete mUpdate.exchange(nullptr, std::memory_order_acq_rel); }
+ ALvoice& operator=(const ALvoice&) = delete;
+ ALvoice& operator=(ALvoice&& rhs) noexcept
+ {
+ ALvoiceProps *old_update{mUpdate.load(std::memory_order_relaxed)};
+ mUpdate.store(rhs.mUpdate.exchange(old_update, std::memory_order_relaxed),
+ std::memory_order_relaxed);
+
+ mSourceID.store(rhs.mSourceID.load(std::memory_order_relaxed), std::memory_order_relaxed);
+ mPlayState.store(rhs.mPlayState.load(std::memory_order_relaxed),
+ std::memory_order_relaxed);
+
+ mProps = rhs.mProps;
+
+ mPosition.store(rhs.mPosition.load(std::memory_order_relaxed), std::memory_order_relaxed);
+ mPositionFrac.store(rhs.mPositionFrac.load(std::memory_order_relaxed),
+ std::memory_order_relaxed);
+
+ mCurrentBuffer.store(rhs.mCurrentBuffer.load(std::memory_order_relaxed),
+ std::memory_order_relaxed);
+ mLoopBuffer.store(rhs.mLoopBuffer.load(std::memory_order_relaxed),
+ std::memory_order_relaxed);
+
+ mFmtChannels = rhs.mFmtChannels;
+ mFrequency = rhs.mFrequency;
+ mNumChannels = rhs.mNumChannels;
+ mSampleSize = rhs.mSampleSize;
+
+ mStep = rhs.mStep;
+ mResampler = rhs.mResampler;
+
+ mResampleState = rhs.mResampleState;
+
+ mFlags = rhs.mFlags;
+
+ mDirect = rhs.mDirect;
+ mSend = rhs.mSend;
+ mChans = rhs.mChans;
+
+ return *this;
+ }
+
+ void mix(ALvoice::State vstate, ALCcontext *Context, const ALuint SamplesToDo);
+};
+
+#endif /* VOICE_H */