From 83238973ed08225adf03e76b6933e0c209f93fd9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 14 May 2022 21:23:03 -0700 Subject: [PATCH] Use virtual functions for the decoder --- alc/alu.cpp | 2 +- core/uhjfilter.cpp | 2 +- core/uhjfilter.h | 46 +++++++++++++++++++++++++++++++--------------- core/voice.cpp | 15 +++++---------- core/voice.h | 3 +-- 5 files changed, 39 insertions(+), 29 deletions(-) diff --git a/alc/alu.cpp b/alc/alu.cpp index c7fb5f57..487ce4c8 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -765,7 +765,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con voice->mFlags.reset(VoiceHasHrtf).reset(VoiceHasNfc); if(auto *decoder{voice->mDecoder.get()}) - decoder->mWidthControl = minf(props->EnhWidth, 0.7f); + decoder->setWidth(minf(props->EnhWidth, 0.7f)); if(IsAmbisonic(voice->mFmtChannels)) { diff --git a/core/uhjfilter.cpp b/core/uhjfilter.cpp index 7fb23131..6cdc2944 100644 --- a/core/uhjfilter.cpp +++ b/core/uhjfilter.cpp @@ -174,7 +174,7 @@ void UhjDecoder::decode(const al::span samples, const size_t samplesToDo * where j is a +90 degree phase shift. w is a variable control for the * resulting stereo width, with the range 0 <= w <= 0.7. */ -void UhjDecoder::decodeStereo(const al::span samples, const size_t samplesToDo, +void UhjStereoDecoder::decode(const al::span samples, const size_t samplesToDo, const size_t forwardSamples) { ASSUME(samplesToDo > 0); diff --git a/core/uhjfilter.h b/core/uhjfilter.h index 8f2736bf..73be7d17 100644 --- a/core/uhjfilter.h +++ b/core/uhjfilter.h @@ -9,6 +9,16 @@ #include "resampler_limits.h" +struct DecoderBase { + virtual ~DecoderBase() = default; + + virtual void setWidth(float width) noexcept = 0; + + virtual void decode(const al::span samples, const size_t samplesToDo, + const size_t forwardSamples) = 0; +}; + + struct UhjFilterBase { /* The filter delay is half it's effective size, so a delay of 128 has a * FIR length of 256. @@ -38,7 +48,7 @@ struct UhjEncoder : public UhjFilterBase { }; -struct UhjDecoder : public UhjFilterBase { +struct UhjDecoder : public DecoderBase, public UhjFilterBase { alignas(16) std::array mS{}; alignas(16) std::array mD{}; alignas(16) std::array mT{}; @@ -48,13 +58,7 @@ struct UhjDecoder : public UhjFilterBase { alignas(16) std::array mTemp{}; - float mCurrentWidth{-1.0f}; - - /** - * The width factor for Super Stereo processing. Can be changed in between - * calls to decodeStereo, with valid values being between 0...0.7. - */ - float mWidthControl{0.593f}; + void setWidth(float) noexcept override { } /** * Decodes a 3- or 4-channel UHJ signal into a B-Format signal with FuMa @@ -65,7 +69,22 @@ struct UhjDecoder : public UhjFilterBase { * B-Format decoder, as it needs different shelf filters. */ void decode(const al::span samples, const size_t samplesToDo, - const size_t forwardSamples); + const size_t forwardSamples) override; + + DEF_NEWDEL(UhjDecoder) +}; + +struct UhjStereoDecoder : public UhjDecoder { + float mCurrentWidth{-1.0f}; + + /** + * The width factor for Super Stereo processing. Can be changed in between + * calls to decodeStereo, with valid values being between 0...0.7. + */ + float mWidthControl{0.593f}; + + void setWidth(float width) noexcept override + { mWidthControl = width; } /** * Applies Super Stereo processing on a stereo signal to create a B-Format @@ -73,13 +92,10 @@ struct UhjDecoder : public UhjFilterBase { * should contain 3 channels, the first two being the left and right stereo * channels, and the third left empty. */ - void decodeStereo(const al::span samples, const size_t samplesToDo, - const size_t forwardSamples); - - using DecoderFunc = void (UhjDecoder::*)(const al::span samples, - const size_t samplesToDo, const size_t forwardSamples); + void decode(const al::span samples, const size_t samplesToDo, + const size_t forwardSamples) override; - DEF_NEWDEL(UhjDecoder) + DEF_NEWDEL(UhjStereoDecoder) }; #endif /* CORE_UHJFILTER_H */ diff --git a/core/voice.cpp b/core/voice.cpp index e269c4a9..48a2de51 100644 --- a/core/voice.cpp +++ b/core/voice.cpp @@ -637,8 +637,8 @@ void Voice::mix(const State vstate, ContextBase *Context, const uint SamplesToDo if(mDecoder) { SrcBufferSize = SrcBufferSize - PostPadding + MaxResamplerEdge; - ((*mDecoder).*mDecoderFunc)(MixingSamples, SrcBufferSize, - srcOffset * likely(vstate == Playing)); + mDecoder->decode(MixingSamples, SrcBufferSize, + likely(vstate == Playing) ? srcOffset : 0.0f); } /* Store the last source samples used for next time. */ if(likely(vstate == Playing)) @@ -853,17 +853,12 @@ void Voice::prepare(DeviceBase *device) mPrevSamples.reserve(maxu(2, num_channels)); mPrevSamples.resize(num_channels); - if(IsUHJ(mFmtChannels)) - { + if(mFmtChannels == FmtSuperStereo) + mDecoder = std::make_unique(); + else if(IsUHJ(mFmtChannels)) mDecoder = std::make_unique(); - mDecoderFunc = (mFmtChannels == FmtSuperStereo) ? &UhjDecoder::decodeStereo - : &UhjDecoder::decode; - } else - { mDecoder = nullptr; - mDecoderFunc = nullptr; - } /* Clear the stepping value explicitly so the mixer knows not to mix this * until the update gets applied. diff --git a/core/voice.h b/core/voice.h index 70b80841..3cf10d22 100644 --- a/core/voice.h +++ b/core/voice.h @@ -219,8 +219,7 @@ struct Voice { AmbiScaling mAmbiScaling; uint mAmbiOrder; - std::unique_ptr mDecoder; - UhjDecoder::DecoderFunc mDecoderFunc{}; + std::unique_ptr mDecoder; /** Current target parameters used for mixing. */ uint mStep{0}; -- 2.11.4.GIT