diff --git a/alc/bformatdec.cpp b/alc/bformatdec.cpp index 3001bfb4..3ef2fec0 100644 --- a/alc/bformatdec.cpp +++ b/alc/bformatdec.cpp @@ -50,67 +50,66 @@ inline auto GetAmbiScales(AmbDecScale scaletype) noexcept BFormatDec::BFormatDec(const AmbDecConf *conf, const bool allow_2band, const ALuint inchans, - const ALuint srate, const ALuint (&chanmap)[MAX_OUTPUT_CHANNELS]) + const ALuint srate, const ALuint (&chanmap)[MAX_OUTPUT_CHANNELS]) : mChannelDec{inchans} { mDualBand = allow_2band && (conf->FreqBands == 2); - mNumChannels = inchans; const bool periphonic{(conf->ChanMask&AMBI_PERIPHONIC_MASK) != 0}; const std::array &coeff_scale = GetAmbiScales(conf->CoeffScale); if(!mDualBand) { - for(size_t i{0u};i < conf->Speakers.size();i++) + for(size_t j{0},k{0};j < mChannelDec.size();++j) { - const size_t chanidx{chanmap[i]}; - for(size_t j{0},k{0};j < mNumChannels;j++) + const size_t acn{periphonic ? j : AmbiIndex::From2D[j]}; + if(!(conf->ChanMask&(1u<HFOrderGain[order] / coeff_scale[acn]}; + for(size_t i{0u};i < conf->Speakers.size();++i) { - const size_t acn{periphonic ? j : AmbiIndex::From2D[j]}; - if(!(conf->ChanMask&(1u<HFMatrix[i][k] / coeff_scale[acn] * - conf->HFOrderGain[AmbiIndex::OrderFromChannel[acn]]; - ++k; + const size_t chanidx{chanmap[i]}; + mChannelDec[j].mGains.Single[chanidx] = conf->HFMatrix[i][k] * gain; } + ++k; } } else { - mXOver[0].init(conf->XOverFreq / static_cast(srate)); - std::fill(std::begin(mXOver)+1, std::end(mXOver), mXOver[0]); + mChannelDec[0].mXOver.init(conf->XOverFreq / static_cast(srate)); + for(size_t j{1};j < mChannelDec.size();++j) + mChannelDec[j].mXOver = mChannelDec[0].mXOver; const float ratio{std::pow(10.0f, conf->XOverRatio / 40.0f)}; - for(size_t i{0u};i < conf->Speakers.size();i++) + for(size_t j{0},k{0};j < mChannelDec.size();++j) { - const size_t chanidx{chanmap[i]}; - for(size_t j{0},k{0};j < mNumChannels;j++) + const size_t acn{periphonic ? j : AmbiIndex::From2D[j]}; + if(!(conf->ChanMask&(1u<HFOrderGain[order] * ratio / coeff_scale[acn]}; + const float lfGain{conf->LFOrderGain[order] / ratio / coeff_scale[acn]}; + for(size_t i{0u};i < conf->Speakers.size();++i) { - const size_t acn{periphonic ? j : AmbiIndex::From2D[j]}; - if(!(conf->ChanMask&(1u<HFMatrix[i][k] / coeff_scale[acn] * - conf->HFOrderGain[AmbiIndex::OrderFromChannel[acn]] * ratio; - mMatrix.Dual[j][sLFBand][chanidx] = conf->LFMatrix[i][k] / coeff_scale[acn] * - conf->LFOrderGain[AmbiIndex::OrderFromChannel[acn]] / ratio; - ++k; + const size_t chanidx{chanmap[i]}; + mChannelDec[j].mGains.Dual[sHFBand][chanidx] = conf->HFMatrix[i][k] * hfGain; + mChannelDec[j].mGains.Dual[sLFBand][chanidx] = conf->LFMatrix[i][k] * lfGain; } + ++k; } } } BFormatDec::BFormatDec(const ALuint inchans, const ChannelDec (&chancoeffs)[MAX_OUTPUT_CHANNELS], - const al::span chanmap) + const al::span chanmap) : mChannelDec{inchans} { - mNumChannels = inchans; - - const ChannelDec *incoeffs{chancoeffs}; - auto set_coeffs = [this,inchans,&incoeffs](const ALuint chanidx) noexcept -> void + for(size_t j{0};j < mChannelDec.size();++j) { - const float (&coeffs)[MAX_AMBI_CHANNELS] = *(incoeffs++); - - ASSUME(inchans > 0); - for(size_t j{0};j < inchans;++j) - mMatrix.Single[j][chanidx] = coeffs[j]; - }; - std::for_each(chanmap.begin(), chanmap.end(), set_coeffs); + const ChannelDec *incoeffs{chancoeffs}; + for(const ALuint chanidx : chanmap) + { + mChannelDec[j].mGains.Single[chanidx] = (*incoeffs)[j]; + ++incoeffs; + } + } } @@ -123,23 +122,25 @@ void BFormatDec::process(const al::span OutBuffer, { const al::span hfSamples{mSamples[sHFBand].data(), SamplesToDo}; const al::span lfSamples{mSamples[sLFBand].data(), SamplesToDo}; - const size_t numchans{mNumChannels}; - for(size_t i{0};i < numchans;i++) + for(auto &chandec : mChannelDec) { - mXOver[i].process({InSamples[i].data(), SamplesToDo}, mSamples[sHFBand].data(), + chandec.mXOver.process({InSamples->data(), SamplesToDo}, mSamples[sHFBand].data(), mSamples[sLFBand].data()); - MixSamples(hfSamples, OutBuffer, mMatrix.Dual[i][sHFBand], mMatrix.Dual[i][sHFBand], - 0, 0); - MixSamples(lfSamples, OutBuffer, mMatrix.Dual[i][sLFBand], mMatrix.Dual[i][sLFBand], - 0, 0); + MixSamples(hfSamples, OutBuffer, chandec.mGains.Dual[sHFBand], + chandec.mGains.Dual[sHFBand], 0, 0); + MixSamples(hfSamples, OutBuffer, chandec.mGains.Dual[sLFBand], + chandec.mGains.Dual[sLFBand], 0, 0); + ++InSamples; } } else { - const size_t numchans{mNumChannels}; - for(size_t i{0};i < numchans;i++) - MixSamples({InSamples[i].data(), SamplesToDo}, OutBuffer, mMatrix.Single[i], - mMatrix.Single[i], 0, 0); + for(auto &chandec : mChannelDec) + { + MixSamples({InSamples->data(), SamplesToDo}, OutBuffer, chandec.mGains.Single, + chandec.mGains.Single, 0, 0); + ++InSamples; + } } } diff --git a/alc/bformatdec.h b/alc/bformatdec.h index fe4b8263..d3380616 100644 --- a/alc/bformatdec.h +++ b/alc/bformatdec.h @@ -24,21 +24,22 @@ class BFormatDec { static constexpr size_t sLFBand{1}; static constexpr size_t sNumBands{2}; - bool mDualBand{false}; + struct ChannelDecoder { + union MatrixU { + float Dual[sNumBands][MAX_OUTPUT_CHANNELS]; + float Single[MAX_OUTPUT_CHANNELS]; + } mGains{}; - ALuint mNumChannels{0u}; - union MatrixU { - float Dual[MAX_AMBI_CHANNELS][sNumBands][MAX_OUTPUT_CHANNELS]; - float Single[MAX_AMBI_CHANNELS][MAX_OUTPUT_CHANNELS]; - } mMatrix{}; - - /* NOTE: BandSplitter filters and temp samples are unused with single-band - * decoding. - */ - BandSplitter mXOver[MAX_AMBI_CHANNELS]; + /* NOTE: BandSplitter filter is unused with single-band decoding. */ + BandSplitter mXOver; + }; alignas(16) std::array mSamples; + bool mDualBand{false}; + + al::FlexArray mChannelDec; + public: BFormatDec(const AmbDecConf *conf, const bool allow_2band, const ALuint inchans, const ALuint srate, const ALuint (&chanmap)[MAX_OUTPUT_CHANNELS]); @@ -53,7 +54,7 @@ public: static std::array GetHFOrderScales(const ALuint in_order, const ALuint out_order) noexcept; - DEF_NEWDEL(BFormatDec) + DEF_FAM_NEWDEL(BFormatDec, mChannelDec) }; #endif /* BFORMATDEC_H */ diff --git a/alc/panning.cpp b/alc/panning.cpp index a74e5c30..d6f426f3 100644 --- a/alc/panning.cpp +++ b/alc/panning.cpp @@ -464,8 +464,8 @@ void InitPanning(ALCdevice *device) (coeffcount > 5) ? "third" : (coeffcount > 3) ? "second" : "first", ""); - device->AmbiDecoder = al::make_unique(coeffcount, chancoeffs, - al::span{idxmap, chanmap.size()}); + device->AmbiDecoder.reset(new(FamCount{coeffcount}) BFormatDec{coeffcount, chancoeffs, + al::span{idxmap, chanmap.size()}}); } } @@ -505,8 +505,8 @@ void InitCustomPanning(ALCdevice *device, bool hqdec, const AmbDecConf *conf, (conf->ChanMask > AMBI_1ORDER_MASK) ? "second" : "first", (conf->ChanMask&AMBI_PERIPHONIC_MASK) ? " periphonic" : "" ); - device->AmbiDecoder = al::make_unique(conf, hqdec, count, device->Frequency, - speakermap); + device->AmbiDecoder.reset(new(FamCount{count}) BFormatDec{conf, hqdec, count, + device->Frequency, speakermap}); auto accum_spkr_dist = std::bind(std::plus{}, _1, std::bind(std::mem_fn(&AmbDecConf::SpeakerConf::Distance), _2));