diff options
author | Chris Robinson <[email protected]> | 2019-10-02 16:53:23 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2019-10-02 16:53:23 -0700 |
commit | 64e2c377d865d67efdac675c355e7b1a6b4166e6 (patch) | |
tree | 574d85a15e26c6041da98b23d4c00ab264f481aa /alc | |
parent | d639935e1975db4276f6ee8c3622684cefa6b269 (diff) |
Move ALvoice from alu.h to a separate header
Diffstat (limited to 'alc')
-rw-r--r-- | alc/alcontext.h | 1 | ||||
-rw-r--r-- | alc/alu.cpp | 44 | ||||
-rw-r--r-- | alc/alu.h | 287 | ||||
-rw-r--r-- | alc/converter.h | 1 | ||||
-rw-r--r-- | alc/mixer/defs.h | 16 | ||||
-rw-r--r-- | alc/mixer/hrtfbase.h | 1 | ||||
-rw-r--r-- | alc/voice.cpp | 34 | ||||
-rw-r--r-- | alc/voice.h | 293 |
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(); } @@ -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 */ |