Use virtual functions for the decoder

This commit is contained in:
Chris Robinson 2022-05-14 21:23:03 -07:00
parent 0a57ebdd49
commit 83238973ed
5 changed files with 39 additions and 29 deletions

View File

@ -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))
{

View File

@ -174,7 +174,7 @@ void UhjDecoder::decode(const al::span<float*> 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<float*> samples, const size_t samplesToDo,
void UhjStereoDecoder::decode(const al::span<float*> samples, const size_t samplesToDo,
const size_t forwardSamples)
{
ASSUME(samplesToDo > 0);

View File

@ -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<float*> 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<float,BufferLineSize+MaxResamplerEdge+sFilterDelay> mS{};
alignas(16) std::array<float,BufferLineSize+MaxResamplerEdge+sFilterDelay> mD{};
alignas(16) std::array<float,BufferLineSize+MaxResamplerEdge+sFilterDelay> mT{};
@ -48,13 +58,7 @@ struct UhjDecoder : public UhjFilterBase {
alignas(16) std::array<float,BufferLineSize+MaxResamplerEdge + sFilterDelay*2> 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<float*> 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<float*> samples, const size_t samplesToDo,
const size_t forwardSamples);
void decode(const al::span<float*> samples, const size_t samplesToDo,
const size_t forwardSamples) override;
using DecoderFunc = void (UhjDecoder::*)(const al::span<float*> samples,
const size_t samplesToDo, const size_t forwardSamples);
DEF_NEWDEL(UhjDecoder)
DEF_NEWDEL(UhjStereoDecoder)
};
#endif /* CORE_UHJFILTER_H */

View File

@ -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<UhjStereoDecoder>();
else if(IsUHJ(mFmtChannels))
mDecoder = std::make_unique<UhjDecoder>();
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.

View File

@ -219,8 +219,7 @@ struct Voice {
AmbiScaling mAmbiScaling;
uint mAmbiOrder;
std::unique_ptr<UhjDecoder> mDecoder;
UhjDecoder::DecoderFunc mDecoderFunc{};
std::unique_ptr<DecoderBase> mDecoder;
/** Current target parameters used for mixing. */
uint mStep{0};