Pass a span of pointers to the UHJ/SuperStereo decoder

This commit is contained in:
Chris Robinson 2022-01-01 00:10:21 -08:00
parent 1337f050dd
commit a271484e7c
4 changed files with 29 additions and 23 deletions

View File

@ -183,8 +183,9 @@ struct DeviceBase {
/* Temp storage used for mixer processing. */ /* Temp storage used for mixer processing. */
static constexpr size_t MixerLineSize{BufferLineSize + MaxResamplerPadding + static constexpr size_t MixerLineSize{BufferLineSize + MaxResamplerPadding +
UhjDecoder::sFilterDelay}; UhjDecoder::sFilterDelay};
static constexpr size_t MixerChannelsMax{16};
using MixerBufferLine = std::array<float,MixerLineSize>; using MixerBufferLine = std::array<float,MixerLineSize>;
alignas(16) std::array<MixerBufferLine,16> mSampleData; alignas(16) std::array<MixerBufferLine,MixerChannelsMax> mSampleData;
alignas(16) float ResampledData[BufferLineSize]; alignas(16) float ResampledData[BufferLineSize];
alignas(16) float FilteredData[BufferLineSize]; alignas(16) float FilteredData[BufferLineSize];

View File

@ -101,15 +101,15 @@ void UhjEncoder::encode(float *LeftOut, float *RightOut, const FloatBufferLine *
* where j is a +90 degree phase shift. 3-channel UHJ excludes Q, while 2- * where j is a +90 degree phase shift. 3-channel UHJ excludes Q, while 2-
* channel excludes Q and T. * channel excludes Q and T.
*/ */
void UhjDecoder::decode(const al::span<BufferLine> samples, const size_t offset, void UhjDecoder::decode(const al::span<float*> samples, const size_t samplesToDo,
const size_t samplesToDo, const size_t forwardSamples) const size_t forwardSamples)
{ {
ASSUME(samplesToDo > 0); ASSUME(samplesToDo > 0);
{ {
const float *RESTRICT left{samples[0].data() + offset}; const float *RESTRICT left{al::assume_aligned<16>(samples[0])};
const float *RESTRICT right{samples[1].data() + offset}; const float *RESTRICT right{al::assume_aligned<16>(samples[1])};
const float *RESTRICT t{samples[2].data() + offset}; const float *RESTRICT t{al::assume_aligned<16>(samples[2])};
/* S = Left + Right */ /* S = Left + Right */
for(size_t i{0};i < samplesToDo+sFilterDelay;++i) for(size_t i{0};i < samplesToDo+sFilterDelay;++i)
@ -124,9 +124,9 @@ void UhjDecoder::decode(const al::span<BufferLine> samples, const size_t offset,
mT[i] = t[i]; mT[i] = t[i];
} }
float *RESTRICT woutput{samples[0].data() + offset}; float *RESTRICT woutput{al::assume_aligned<16>(samples[0])};
float *RESTRICT xoutput{samples[1].data() + offset}; float *RESTRICT xoutput{al::assume_aligned<16>(samples[1])};
float *RESTRICT youtput{samples[2].data() + offset}; float *RESTRICT youtput{al::assume_aligned<16>(samples[2])};
/* Precompute j(0.828331*D + 0.767820*T) and store in xoutput. */ /* Precompute j(0.828331*D + 0.767820*T) and store in xoutput. */
auto tmpiter = std::copy(mDTHistory.cbegin(), mDTHistory.cend(), mTemp.begin()); auto tmpiter = std::copy(mDTHistory.cbegin(), mDTHistory.cend(), mTemp.begin());
@ -154,7 +154,7 @@ void UhjDecoder::decode(const al::span<BufferLine> samples, const size_t offset,
if(samples.size() > 3) if(samples.size() > 3)
{ {
float *RESTRICT zoutput{samples[3].data() + offset}; float *RESTRICT zoutput{al::assume_aligned<16>(samples[3])};
/* Z = 1.023332*Q */ /* Z = 1.023332*Q */
for(size_t i{0};i < samplesToDo;++i) for(size_t i{0};i < samplesToDo;++i)
zoutput[i] = 1.023332f*zoutput[i]; zoutput[i] = 1.023332f*zoutput[i];
@ -174,14 +174,14 @@ void UhjDecoder::decode(const al::span<BufferLine> samples, const size_t offset,
* where j is a +90 degree phase shift. w is a variable control for the * 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. * resulting stereo width, with the range 0 <= w <= 0.7.
*/ */
void UhjDecoder::decodeStereo(const al::span<BufferLine> samples, const size_t offset, void UhjDecoder::decodeStereo(const al::span<float*> samples, const size_t samplesToDo,
const size_t samplesToDo, const size_t forwardSamples) const size_t forwardSamples)
{ {
ASSUME(samplesToDo > 0); ASSUME(samplesToDo > 0);
{ {
const float *RESTRICT left{samples[0].data() + offset}; const float *RESTRICT left{al::assume_aligned<16>(samples[0])};
const float *RESTRICT right{samples[1].data() + offset}; const float *RESTRICT right{al::assume_aligned<16>(samples[1])};
for(size_t i{0};i < samplesToDo+sFilterDelay;++i) for(size_t i{0};i < samplesToDo+sFilterDelay;++i)
mS[i] = left[i] + right[i]; mS[i] = left[i] + right[i];
@ -212,9 +212,9 @@ void UhjDecoder::decodeStereo(const al::span<BufferLine> samples, const size_t o
mCurrentWidth = wtarget; mCurrentWidth = wtarget;
} }
float *RESTRICT woutput{samples[0].data() + offset}; float *RESTRICT woutput{al::assume_aligned<16>(samples[0])};
float *RESTRICT xoutput{samples[1].data() + offset}; float *RESTRICT xoutput{al::assume_aligned<16>(samples[1])};
float *RESTRICT youtput{samples[2].data() + offset}; float *RESTRICT youtput{al::assume_aligned<16>(samples[2])};
/* Precompute j*D and store in xoutput. */ /* Precompute j*D and store in xoutput. */
auto tmpiter = std::copy(mDTHistory.cbegin(), mDTHistory.cend(), mTemp.begin()); auto tmpiter = std::copy(mDTHistory.cbegin(), mDTHistory.cend(), mTemp.begin());

View File

@ -66,7 +66,7 @@ struct UhjDecoder : public UhjFilterBase {
* reconstructed from 2-channel UHJ should not be run through a normal * reconstructed from 2-channel UHJ should not be run through a normal
* B-Format decoder, as it needs different shelf filters. * B-Format decoder, as it needs different shelf filters.
*/ */
void decode(const al::span<BufferLine> samples, const size_t offset, const size_t samplesToDo, void decode(const al::span<float*> samples, const size_t samplesToDo,
const size_t forwardSamples); const size_t forwardSamples);
/** /**
@ -75,11 +75,11 @@ struct UhjDecoder : public UhjFilterBase {
* should contain 3 channels, the first two being the left and right stereo * should contain 3 channels, the first two being the left and right stereo
* channels, and the third left empty. * channels, and the third left empty.
*/ */
void decodeStereo(const al::span<BufferLine> samples, const size_t offset, void decodeStereo(const al::span<float*> samples, const size_t samplesToDo,
const size_t samplesToDo, const size_t forwardSamples); const size_t forwardSamples);
using DecoderFunc = void (UhjDecoder::*)(const al::span<BufferLine> samples, using DecoderFunc = void (UhjDecoder::*)(const al::span<float*> samples,
const size_t offset, const size_t samplesToDo, const size_t forwardSamples); const size_t samplesToDo, const size_t forwardSamples);
DEF_NEWDEL(UhjDecoder) DEF_NEWDEL(UhjDecoder)
}; };

View File

@ -53,6 +53,7 @@ struct CopyTag;
static_assert(!(sizeof(DeviceBase::MixerBufferLine)&15), static_assert(!(sizeof(DeviceBase::MixerBufferLine)&15),
"DeviceBase::MixerBufferLine must be a multiple of 16 bytes"); "DeviceBase::MixerBufferLine must be a multiple of 16 bytes");
static_assert(!(MaxResamplerEdge&3), "MaxResamplerEdge is not a multiple of 4");
Resampler ResamplerDefault{Resampler::Linear}; Resampler ResamplerDefault{Resampler::Linear};
@ -627,9 +628,13 @@ void Voice::mix(const State vstate, ContextBase *Context, const uint SamplesToDo
if(mDecoder) if(mDecoder)
{ {
std::array<float*,DeviceBase::MixerChannelsMax> chanptrs;
std::transform(MixingSamples.begin(), MixingSamples.end(), chanptrs.begin(),
[](DeviceBase::MixerBufferLine &bufline) noexcept -> float*
{ return bufline.data() + MaxResamplerEdge; });
const size_t srcOffset{(increment*DstBufferSize + DataPosFrac)>>MixerFracBits}; const size_t srcOffset{(increment*DstBufferSize + DataPosFrac)>>MixerFracBits};
SrcBufferSize = SrcBufferSize - PostPadding + MaxResamplerEdge; SrcBufferSize = SrcBufferSize - PostPadding + MaxResamplerEdge;
((*mDecoder).*mDecoderFunc)(MixingSamples, MaxResamplerEdge, SrcBufferSize, ((*mDecoder).*mDecoderFunc)({chanptrs.data(), MixingSamples.size()}, SrcBufferSize,
srcOffset * likely(vstate == Playing)); srcOffset * likely(vstate == Playing));
} }
} }