diff options
-rw-r--r-- | CMakeLists.txt | 8 | ||||
-rw-r--r-- | al/event.cpp | 2 | ||||
-rw-r--r-- | al/source.cpp | 2 | ||||
-rw-r--r-- | alc/alc.cpp | 2 | ||||
-rw-r--r-- | alc/alcontext.h | 141 | ||||
-rw-r--r-- | alc/alu.cpp | 4 | ||||
-rw-r--r-- | alc/alu.h | 10 | ||||
-rw-r--r-- | alc/voice.cpp | 10 | ||||
-rw-r--r-- | alc/voice.h | 8 | ||||
-rw-r--r-- | core/context.cpp | 5 | ||||
-rw-r--r-- | core/context.h | 171 | ||||
-rw-r--r-- | core/voice_change.h (renamed from alc/voice_change.h) | 0 |
12 files changed, 199 insertions, 164 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a1f6a09..ef4ef720 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -655,6 +655,8 @@ set(CORE_OBJS core/bsinc_tables.cpp core/bsinc_tables.h core/bufferline.h + core/context.cpp + core/context.h core/converter.cpp core/converter.h core/cpu_caps.cpp @@ -689,7 +691,8 @@ set(CORE_OBJS core/resampler_limits.h core/uhjfilter.cpp core/uhjfilter.h - core/uiddefs.cpp) + core/uiddefs.cpp + core/voice_change.h) set(HAVE_RTKIT 0) option(ALSOFT_REQUIRE_RTKIT "Require RTKit/D-Bus support" FALSE) @@ -784,8 +787,7 @@ set(ALC_OBJS alc/inprogext.h alc/panning.cpp alc/voice.cpp - alc/voice.h - alc/voice_change.h) + alc/voice.h) # Include SIMD mixers set(CPU_EXTS "Default") diff --git a/al/event.cpp b/al/event.cpp index 0bba4280..843a90e1 100644 --- a/al/event.cpp +++ b/al/event.cpp @@ -23,12 +23,12 @@ #include "core/async_event.h" #include "core/except.h" #include "core/logging.h" +#include "core/voice_change.h" #include "effects/base.h" #include "inprogext.h" #include "opthelpers.h" #include "ringbuffer.h" #include "threads.h" -#include "voice_change.h" static int EventThread(ALCcontext *context) diff --git a/al/source.cpp b/al/source.cpp index 27eeff9c..ca234a05 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -63,6 +63,7 @@ #include "core/filters/nfc.h" #include "core/filters/splitter.h" #include "core/logging.h" +#include "core/voice_change.h" #include "event.h" #include "filter.h" #include "inprogext.h" @@ -70,7 +71,6 @@ #include "opthelpers.h" #include "ringbuffer.h" #include "threads.h" -#include "voice_change.h" namespace { diff --git a/alc/alc.cpp b/alc/alc.cpp index 47b77758..858fe278 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -93,6 +93,7 @@ #include "core/hrtf.h" #include "core/logging.h" #include "core/uhjfilter.h" +#include "core/voice_change.h" #include "effects/base.h" #include "inprogext.h" #include "intrusive_ptr.h" @@ -103,7 +104,6 @@ #include "threads.h" #include "vecmat.h" #include "vector.h" -#include "voice_change.h" #include "backends/base.h" #include "backends/null.h" diff --git a/alc/alcontext.h b/alc/alcontext.h index 075e6a55..2b38dd70 100644 --- a/alc/alcontext.h +++ b/alc/alcontext.h @@ -19,6 +19,7 @@ #include "alu.h" #include "atomic.h" #include "core/bufferline.h" +#include "core/context.h" #include "inprogext.h" #include "intrusive_ptr.h" #include "threads.h" @@ -38,146 +39,6 @@ struct VoicePropsItem; using uint = unsigned int; -enum class DistanceModel : unsigned char { - Disable, - Inverse, InverseClamped, - Linear, LinearClamped, - Exponent, ExponentClamped, - - Default = InverseClamped -}; - - -struct WetBuffer { - bool mInUse; - al::FlexArray<FloatBufferLine, 16> mBuffer; - - WetBuffer(size_t count) : mBuffer{count} { } - - DEF_FAM_NEWDEL(WetBuffer, mBuffer) -}; -using WetBufferPtr = std::unique_ptr<WetBuffer>; - - -struct ContextProps { - float DopplerFactor; - float DopplerVelocity; - float SpeedOfSound; - bool SourceDistanceModel; - DistanceModel mDistanceModel; - - std::atomic<ContextProps*> next; - - DEF_NEWDEL(ContextProps) -}; - -struct ListenerProps { - std::array<float,3> Position; - std::array<float,3> Velocity; - std::array<float,3> OrientAt; - std::array<float,3> OrientUp; - float Gain; - float MetersPerUnit; - - std::atomic<ListenerProps*> next; - - DEF_NEWDEL(ListenerProps) -}; - -struct ContextParams { - /* Pointer to the most recent property values that are awaiting an update. */ - std::atomic<ContextProps*> ContextUpdate{nullptr}; - std::atomic<ListenerProps*> ListenerUpdate{nullptr}; - - alu::Matrix Matrix{alu::Matrix::Identity()}; - alu::Vector Velocity{}; - - float Gain{1.0f}; - float MetersPerUnit{1.0f}; - - float DopplerFactor{1.0f}; - float SpeedOfSound{343.3f}; /* in units per sec! */ - - bool SourceDistanceModel{false}; - DistanceModel mDistanceModel{}; -}; - -struct ContextBase { - DeviceBase *const mDevice; - - /* Counter for the pre-mixing updates, in 31.1 fixed point (lowest bit - * indicates if updates are currently happening). - */ - RefCount mUpdateCount{0u}; - std::atomic<bool> mHoldUpdates{false}; - std::atomic<bool> mStopVoicesOnDisconnect{true}; - - float mGainBoost{1.0f}; - - /* Linked lists of unused property containers, free to use for future - * updates. - */ - std::atomic<ContextProps*> mFreeContextProps{nullptr}; - std::atomic<ListenerProps*> mFreeListenerProps{nullptr}; - std::atomic<VoicePropsItem*> mFreeVoiceProps{nullptr}; - std::atomic<EffectSlotProps*> mFreeEffectslotProps{nullptr}; - - /* The voice change tail is the beginning of the "free" elements, up to and - * *excluding* the current. If tail==current, there's no free elements and - * new ones need to be allocated. The current voice change is the element - * last processed, and any after are pending. - */ - VoiceChange *mVoiceChangeTail{}; - std::atomic<VoiceChange*> mCurrentVoiceChange{}; - - void allocVoiceChanges(size_t addcount); - - - ContextParams mParams; - - using VoiceArray = al::FlexArray<Voice*>; - std::atomic<VoiceArray*> mVoices{}; - std::atomic<size_t> mActiveVoiceCount{}; - - void allocVoices(size_t addcount); - al::span<Voice*> getVoicesSpan() const noexcept - { - return {mVoices.load(std::memory_order_relaxed)->data(), - mActiveVoiceCount.load(std::memory_order_relaxed)}; - } - al::span<Voice*> getVoicesSpanAcquired() const noexcept - { - return {mVoices.load(std::memory_order_acquire)->data(), - mActiveVoiceCount.load(std::memory_order_acquire)}; - } - - - using EffectSlotArray = al::FlexArray<EffectSlot*>; - std::atomic<EffectSlotArray*> mActiveAuxSlots{nullptr}; - - std::thread mEventThread; - al::semaphore mEventSem; - std::unique_ptr<RingBuffer> mAsyncEvents; - std::atomic<uint> mEnabledEvts{0u}; - - /* Asynchronous voice change actions are processed as a linked list of - * VoiceChange objects by the mixer, which is atomically appended to. - * However, to avoid allocating each object individually, they're allocated - * in clusters that are stored in a vector for easy automatic cleanup. - */ - using VoiceChangeCluster = std::unique_ptr<VoiceChange[]>; - al::vector<VoiceChangeCluster> mVoiceChangeClusters; - - using VoiceCluster = std::unique_ptr<Voice[]>; - al::vector<VoiceCluster> mVoiceClusters; - - - ContextBase(DeviceBase *device); - ContextBase(const ContextBase&) = delete; - ContextBase& operator=(const ContextBase&) = delete; - ~ContextBase(); -}; - struct SourceSubList { uint64_t FreeMask{~0_u64}; ALsource *Sources{nullptr}; /* 64 */ diff --git a/alc/alu.cpp b/alc/alu.cpp index d7f4410f..250d4ee4 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -39,7 +39,6 @@ #include <stdint.h> #include <utility> -#include "alcontext.h" #include "almalloc.h" #include "alnumeric.h" #include "alspan.h" @@ -53,6 +52,7 @@ #include "core/bsinc_defs.h" #include "core/bsinc_tables.h" #include "core/bufferline.h" +#include "core/context.h" #include "core/cpu_caps.h" #include "core/devformat.h" #include "core/device.h" @@ -66,6 +66,7 @@ #include "core/mixer/hrtfdefs.h" #include "core/resampler_limits.h" #include "core/uhjfilter.h" +#include "core/voice_change.h" #include "effects/base.h" #include "effectslot.h" #include "intrusive_ptr.h" @@ -77,7 +78,6 @@ #include "vecmat.h" #include "vector.h" #include "voice.h" -#include "voice_change.h" struct CTag; #ifdef HAVE_SSE @@ -1,21 +1,13 @@ #ifndef ALU_H #define ALU_H -#include <string> - -#include "aloptional.h" - struct ALCcontext; struct ALCdevice; struct EffectSlot; -#define MAX_SENDS 6 - - constexpr float GainMixMax{1000.0f}; /* +60dB */ -constexpr float SpeedOfSoundMetersPerSec{343.3f}; constexpr float AirAbsorbGainHF{0.99426f}; /* -0.05dB */ @@ -27,8 +19,6 @@ enum HrtfRequestMode { void aluInit(void); -void aluInitMixer(al::optional<std::string> resampler); - /* aluInitRenderer * * Set up the appropriate panning method and mixing method given the device diff --git a/alc/voice.cpp b/alc/voice.cpp index 6abfcf59..686f4c9b 100644 --- a/alc/voice.cpp +++ b/alc/voice.cpp @@ -22,8 +22,6 @@ #include "voice.h" -#include <stdlib.h> - #include <algorithm> #include <array> #include <atomic> @@ -32,19 +30,19 @@ #include <iterator> #include <memory> #include <new> +#include <stdlib.h> #include <utility> #include <vector> #include "albyte.h" -#include "alcontext.h" #include "alnumeric.h" #include "aloptional.h" #include "alspan.h" #include "alstring.h" -#include "alu.h" #include "buffer_storage.h" #include "core/ambidefs.h" #include "core/async_event.h" +#include "core/context.h" #include "core/cpu_caps.h" #include "core/devformat.h" #include "core/device.h" @@ -57,10 +55,10 @@ #include "core/mixer/defs.h" #include "core/mixer/hrtfdefs.h" #include "core/resampler_limits.h" +#include "core/voice_change.h" #include "opthelpers.h" #include "ringbuffer.h" #include "vector.h" -#include "voice_change.h" struct CTag; #ifdef HAVE_SSE @@ -78,6 +76,8 @@ Resampler ResamplerDefault{Resampler::Linear}; namespace { +using uint = unsigned int; + using HrtfMixerFunc = void(*)(const float *InSamples, float2 *AccumSamples, const uint IrSize, const MixHrtfFilter *hrtfparams, const size_t BufferSize); using HrtfMixerBlendFunc = void(*)(const float *InSamples, float2 *AccumSamples, diff --git a/alc/voice.h b/alc/voice.h index dfeffec1..937294e3 100644 --- a/alc/voice.h +++ b/alc/voice.h @@ -6,11 +6,12 @@ #include <array> #include <atomic> #include <memory> +#include <string> #include "albyte.h" #include "almalloc.h" +#include "aloptional.h" #include "alspan.h" -#include "alu.h" #include "buffer_storage.h" #include "core/bufferline.h" #include "core/devformat.h" @@ -31,6 +32,9 @@ enum class DistanceModel : unsigned char; using uint = unsigned int; +#define MAX_SENDS 6 + + enum class SpatializeMode : unsigned char { Off, On, @@ -262,4 +266,6 @@ struct Voice { extern Resampler ResamplerDefault; +void aluInitMixer(al::optional<std::string> resampler); + #endif /* VOICE_H */ diff --git a/core/context.cpp b/core/context.cpp new file mode 100644 index 00000000..f1c310aa --- /dev/null +++ b/core/context.cpp @@ -0,0 +1,5 @@ + +#include "config.h" + +#include "context.h" + diff --git a/core/context.h b/core/context.h new file mode 100644 index 00000000..bf439053 --- /dev/null +++ b/core/context.h @@ -0,0 +1,171 @@ +#ifndef CORE_CONTEXT_H +#define CORE_CONTEXT_H + +#include <array> +#include <atomic> +#include <cstddef> +#include <memory> +#include <thread> + +#include "almalloc.h" +#include "alspan.h" +#include "atomic.h" +#include "core/bufferline.h" +#include "threads.h" +#include "vecmat.h" +#include "vector.h" + +struct DeviceBase; +struct EffectSlot; +struct EffectSlotProps; +struct RingBuffer; +struct Voice; +struct VoiceChange; +struct VoicePropsItem; + +using uint = unsigned int; + + +constexpr float SpeedOfSoundMetersPerSec{343.3f}; + +enum class DistanceModel : unsigned char { + Disable, + Inverse, InverseClamped, + Linear, LinearClamped, + Exponent, ExponentClamped, + + Default = InverseClamped +}; + + +struct WetBuffer { + bool mInUse; + al::FlexArray<FloatBufferLine, 16> mBuffer; + + WetBuffer(size_t count) : mBuffer{count} { } + + DEF_FAM_NEWDEL(WetBuffer, mBuffer) +}; +using WetBufferPtr = std::unique_ptr<WetBuffer>; + + +struct ContextProps { + float DopplerFactor; + float DopplerVelocity; + float SpeedOfSound; + bool SourceDistanceModel; + DistanceModel mDistanceModel; + + std::atomic<ContextProps*> next; + + DEF_NEWDEL(ContextProps) +}; + +struct ListenerProps { + std::array<float,3> Position; + std::array<float,3> Velocity; + std::array<float,3> OrientAt; + std::array<float,3> OrientUp; + float Gain; + float MetersPerUnit; + + std::atomic<ListenerProps*> next; + + DEF_NEWDEL(ListenerProps) +}; + +struct ContextParams { + /* Pointer to the most recent property values that are awaiting an update. */ + std::atomic<ContextProps*> ContextUpdate{nullptr}; + std::atomic<ListenerProps*> ListenerUpdate{nullptr}; + + alu::Matrix Matrix{alu::Matrix::Identity()}; + alu::Vector Velocity{}; + + float Gain{1.0f}; + float MetersPerUnit{1.0f}; + + float DopplerFactor{1.0f}; + float SpeedOfSound{343.3f}; /* in units per sec! */ + + bool SourceDistanceModel{false}; + DistanceModel mDistanceModel{}; +}; + +struct ContextBase { + DeviceBase *const mDevice; + + /* Counter for the pre-mixing updates, in 31.1 fixed point (lowest bit + * indicates if updates are currently happening). + */ + RefCount mUpdateCount{0u}; + std::atomic<bool> mHoldUpdates{false}; + std::atomic<bool> mStopVoicesOnDisconnect{true}; + + float mGainBoost{1.0f}; + + /* Linked lists of unused property containers, free to use for future + * updates. + */ + std::atomic<ContextProps*> mFreeContextProps{nullptr}; + std::atomic<ListenerProps*> mFreeListenerProps{nullptr}; + std::atomic<VoicePropsItem*> mFreeVoiceProps{nullptr}; + std::atomic<EffectSlotProps*> mFreeEffectslotProps{nullptr}; + + /* The voice change tail is the beginning of the "free" elements, up to and + * *excluding* the current. If tail==current, there's no free elements and + * new ones need to be allocated. The current voice change is the element + * last processed, and any after are pending. + */ + VoiceChange *mVoiceChangeTail{}; + std::atomic<VoiceChange*> mCurrentVoiceChange{}; + + void allocVoiceChanges(size_t addcount); + + + ContextParams mParams; + + using VoiceArray = al::FlexArray<Voice*>; + std::atomic<VoiceArray*> mVoices{}; + std::atomic<size_t> mActiveVoiceCount{}; + + void allocVoices(size_t addcount); + al::span<Voice*> getVoicesSpan() const noexcept + { + return {mVoices.load(std::memory_order_relaxed)->data(), + mActiveVoiceCount.load(std::memory_order_relaxed)}; + } + al::span<Voice*> getVoicesSpanAcquired() const noexcept + { + return {mVoices.load(std::memory_order_acquire)->data(), + mActiveVoiceCount.load(std::memory_order_acquire)}; + } + + + using EffectSlotArray = al::FlexArray<EffectSlot*>; + std::atomic<EffectSlotArray*> mActiveAuxSlots{nullptr}; + + std::thread mEventThread; + al::semaphore mEventSem; + std::unique_ptr<RingBuffer> mAsyncEvents; + std::atomic<uint> mEnabledEvts{0u}; + + /* Asynchronous voice change actions are processed as a linked list of + * VoiceChange objects by the mixer, which is atomically appended to. + * However, to avoid allocating each object individually, they're allocated + * in clusters that are stored in a vector for easy automatic cleanup. + */ + using VoiceChangeCluster = std::unique_ptr<VoiceChange[]>; + al::vector<VoiceChangeCluster> mVoiceChangeClusters; + + using VoiceCluster = std::unique_ptr<Voice[]>; + al::vector<VoiceCluster> mVoiceClusters; + + + ContextBase(DeviceBase *device); + ContextBase(const ContextBase&) = delete; + ContextBase& operator=(const ContextBase&) = delete; + ~ContextBase(); +}; + +#endif /* CORE_CONTEXT_H */ diff --git a/alc/voice_change.h b/core/voice_change.h index ddc6186f..ddc6186f 100644 --- a/alc/voice_change.h +++ b/core/voice_change.h |