Use virtual functions for the decoder
This commit is contained in:
parent
0a57ebdd49
commit
83238973ed
@ -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))
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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.
|
||||
|
@ -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};
|
||||
|
Loading…
x
Reference in New Issue
Block a user