From 64e2c377d865d67efdac675c355e7b1a6b4166e6 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 2 Oct 2019 16:53:23 -0700 Subject: Move ALvoice from alu.h to a separate header --- CMakeLists.txt | 1 + alc/alcontext.h | 1 + alc/alu.cpp | 44 ++++++-- alc/alu.h | 287 +------------------------------------------------ alc/converter.h | 1 + alc/mixer/defs.h | 16 ++- alc/mixer/hrtfbase.h | 1 + alc/voice.cpp | 34 +----- alc/voice.h | 293 +++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 352 insertions(+), 326 deletions(-) create mode 100644 alc/voice.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 46fb692a..03c60162 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -632,6 +632,7 @@ SET(ALC_OBJS alc/uhjfilter.h alc/uiddefs.cpp alc/voice.cpp + alc/voice.h alc/mixer/defs.h alc/mixer/hrtfbase.h alc/mixer/mixer_c.cpp 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 #include #include -#include #include #include #include #include #include #include -#include #include #include #include @@ -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_}; +RowMixerFunc MixRowSamples{MixRow_}; 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_; + +inline MixerFunc SelectMixer() +{ +#ifdef HAVE_NEON + if((CPUCapFlags&CPU_CAP_NEON)) + return Mix_; +#endif +#ifdef HAVE_SSE + if((CPUCapFlags&CPU_CAP_SSE)) + return Mix_; +#endif + return Mix_; +} + +inline RowMixerFunc SelectRowMixer() +{ +#ifdef HAVE_NEON + if((CPUCapFlags&CPU_CAP_NEON)) + return MixRow_; +#endif +#ifdef HAVE_SSE + if((CPUCapFlags&CPU_CAP_SSE)) + return MixRow_; +#endif + return MixRow_; +} + 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< 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 Position; - std::array Velocity; - std::array Direction; - std::array OrientAt; - std::array 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 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 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 mUpdate{nullptr}; - - std::atomic mSourceID{0u}; - std::atomic mPlayState{Stopped}; - - ALvoicePropsBase mProps; - - /** - * Source offset in samples, relative to the currently playing buffer, NOT - * the whole queue. - */ - std::atomic mPosition; - /** Fractional (fixed-point) offset to the next sample. */ - std::atomic mPositionFrac; - - /* Current buffer queue item being played. */ - std::atomic mCurrentBuffer; - - /* Buffer queue item to loop to at end of queue (will be NULL for non- - * looping voices). - */ - std::atomic 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 Buffer; - }; - DirectData mDirect; - - struct SendData { - int FilterType; - al::span Buffer; - }; - std::array mSend; - - struct ChannelData { - alignas(16) std::array mPrevSamples; - - ALfloat mAmbiScale; - BandSplitter mAmbiSplitter; - - DirectParams mDryParams; - std::array mWetParams; - }; - std::array 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 InSamples, const al::span 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 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 OutBuffer, const al::span Gains, const float *InSamples, const size_t InStride); template -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 -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 -void MixDirectHrtf_(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, const al::span InSamples, float2 *AccumSamples, DirectHrtfState *State, const size_t BufferSize); +void MixDirectHrtf_(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, + const al::span 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 #include #include @@ -30,7 +32,6 @@ #include #include #include -#include #include #include "AL/al.h" @@ -69,9 +70,6 @@ static_assert((INT_MAX>>FRACTIONBITS)/MAX_PITCH > BUFFERSIZE, Resampler ResamplerDefault{Resampler::Linear}; -MixerFunc MixSamples = Mix_; -RowMixerFunc MixRowSamples = MixRow_; - namespace { using HrtfMixerFunc = void(*)(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, @@ -84,32 +82,6 @@ using HrtfMixerBlendFunc = void(*)(FloatBufferLine &LeftOut, FloatBufferLine &Ri HrtfMixerFunc MixHrtfSamples = MixHrtf_; HrtfMixerBlendFunc MixHrtfBlendSamples = MixHrtfBlend_; -inline MixerFunc SelectMixer() -{ -#ifdef HAVE_NEON - if((CPUCapFlags&CPU_CAP_NEON)) - return Mix_; -#endif -#ifdef HAVE_SSE - if((CPUCapFlags&CPU_CAP_SSE)) - return Mix_; -#endif - return Mix_; -} - -inline RowMixerFunc SelectRowMixer() -{ -#ifdef HAVE_NEON - if((CPUCapFlags&CPU_CAP_NEON)) - return MixRow_; -#endif -#ifdef HAVE_SSE - if((CPUCapFlags&CPU_CAP_SSE)) - return MixRow_; -#endif - return MixRow_; -} - 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< 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 Position; + std::array Velocity; + std::array Direction; + std::array OrientAt; + std::array 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 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 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 mUpdate{nullptr}; + + std::atomic mSourceID{0u}; + std::atomic mPlayState{Stopped}; + + ALvoicePropsBase mProps; + + /** + * Source offset in samples, relative to the currently playing buffer, NOT + * the whole queue. + */ + std::atomic mPosition; + /** Fractional (fixed-point) offset to the next sample. */ + std::atomic mPositionFrac; + + /* Current buffer queue item being played. */ + std::atomic mCurrentBuffer; + + /* Buffer queue item to loop to at end of queue (will be NULL for non- + * looping voices). + */ + std::atomic 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 Buffer; + }; + DirectData mDirect; + + struct SendData { + int FilterType; + al::span Buffer; + }; + std::array mSend; + + struct ChannelData { + alignas(16) std::array mPrevSamples; + + ALfloat mAmbiScale; + BandSplitter mAmbiSplitter; + + DirectParams mDryParams; + std::array mWetParams; + }; + std::array 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 */ -- cgit v1.2.3