diff options
author | Chris Robinson <[email protected]> | 2021-04-25 18:08:08 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2021-04-25 18:08:08 -0700 |
commit | 2479483645bf719233fa5d39bc91682f12d71350 (patch) | |
tree | de4d9f11e4d4549adc6e7a43b9c4a1d630f91feb /alc | |
parent | 8d09d03ed363ab1735b1933588d8242ba85ddf10 (diff) |
Move bformatdec to core
Diffstat (limited to 'alc')
-rw-r--r-- | alc/alc.cpp | 4 | ||||
-rw-r--r-- | alc/alu.cpp | 4 | ||||
-rw-r--r-- | alc/bformatdec.cpp | 263 | ||||
-rw-r--r-- | alc/bformatdec.h | 71 | ||||
-rw-r--r-- | alc/front_stablizer.h | 36 | ||||
-rw-r--r-- | alc/panning.cpp | 4 |
6 files changed, 6 insertions, 376 deletions
diff --git a/alc/alc.cpp b/alc/alc.cpp index 8ba1c8a2..d06ca067 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -77,9 +77,9 @@ #include "alstring.h" #include "alu.h" #include "atomic.h" -#include "bformatdec.h" #include "core/ambidefs.h" #include "core/async_event.h" +#include "core/bformatdec.h" #include "core/bs2b.h" #include "core/cpu_caps.h" #include "core/devformat.h" @@ -89,11 +89,11 @@ #include "core/filters/nfc.h" #include "core/filters/splitter.h" #include "core/fpu_ctrl.h" +#include "core/front_stablizer.h" #include "core/hrtf.h" #include "core/logging.h" #include "core/uhjfilter.h" #include "effects/base.h" -#include "front_stablizer.h" #include "inprogext.h" #include "intrusive_ptr.h" #include "opthelpers.h" diff --git a/alc/alu.cpp b/alc/alu.cpp index a97bc18b..14ffd8b5 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -51,9 +51,9 @@ #include "alspan.h" #include "alstring.h" #include "atomic.h" -#include "bformatdec.h" #include "core/ambidefs.h" #include "core/async_event.h" +#include "core/bformatdec.h" #include "core/bs2b.h" #include "core/bsinc_tables.h" #include "core/cpu_caps.h" @@ -62,6 +62,7 @@ #include "core/filters/nfc.h" #include "core/filters/splitter.h" #include "core/fpu_ctrl.h" +#include "core/front_stablizer.h" #include "core/hrtf.h" #include "core/mastering.h" #include "core/mixer.h" @@ -69,7 +70,6 @@ #include "core/uhjfilter.h" #include "effects/base.h" #include "effectslot.h" -#include "front_stablizer.h" #include "inprogext.h" #include "math_defs.h" #include "opthelpers.h" diff --git a/alc/bformatdec.cpp b/alc/bformatdec.cpp deleted file mode 100644 index e29af045..00000000 --- a/alc/bformatdec.cpp +++ /dev/null @@ -1,263 +0,0 @@ - -#include "config.h" - -#include "bformatdec.h" - -#include <algorithm> -#include <array> -#include <cmath> -#include <utility> - -#include "almalloc.h" -#include "core/ambdec.h" -#include "core/filters/splitter.h" -#include "core/mixer.h" -#include "front_stablizer.h" -#include "math_defs.h" -#include "opthelpers.h" - - -namespace { - -inline auto& GetAmbiScales(AmbDecScale scaletype) noexcept -{ - if(scaletype == AmbDecScale::FuMa) return AmbiScale::FromFuMa(); - if(scaletype == AmbDecScale::SN3D) return AmbiScale::FromSN3D(); - return AmbiScale::FromN3D(); -} - -} // namespace - - -BFormatDec::BFormatDec(const AmbDecConf *conf, const bool allow_2band, const size_t inchans, - const uint srate, const uint (&chanmap)[MAX_OUTPUT_CHANNELS], - std::unique_ptr<FrontStablizer> stablizer) - : mStablizer{std::move(stablizer)}, mDualBand{allow_2band && (conf->FreqBands == 2)} - , mChannelDec{inchans} -{ - const bool periphonic{(conf->ChanMask&AmbiPeriphonicMask) != 0}; - auto&& coeff_scale = GetAmbiScales(conf->CoeffScale); - - if(!mDualBand) - { - for(size_t j{0},k{0};j < mChannelDec.size();++j) - { - const size_t acn{periphonic ? j : AmbiIndex::FromACN2D()[j]}; - if(!(conf->ChanMask&(1u<<acn))) continue; - const size_t order{AmbiIndex::OrderFromChannel()[acn]}; - const float gain{conf->HFOrderGain[order] / coeff_scale[acn]}; - for(size_t i{0u};i < conf->NumSpeakers;++i) - { - const size_t chanidx{chanmap[i]}; - mChannelDec[j].mGains.Single[chanidx] = conf->Matrix[i][k] * gain; - } - ++k; - } - } - else - { - mChannelDec[0].mXOver.init(conf->XOverFreq / static_cast<float>(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 j{0},k{0};j < mChannelDec.size();++j) - { - const size_t acn{periphonic ? j : AmbiIndex::FromACN2D()[j]}; - if(!(conf->ChanMask&(1u<<acn))) continue; - const size_t order{AmbiIndex::OrderFromChannel()[acn]}; - const float hfGain{conf->HFOrderGain[order] * ratio / coeff_scale[acn]}; - const float lfGain{conf->LFOrderGain[order] / ratio / coeff_scale[acn]}; - for(size_t i{0u};i < conf->NumSpeakers;++i) - { - 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 size_t inchans, const al::span<const ChannelDec> coeffs, - const al::span<const ChannelDec> coeffslf, std::unique_ptr<FrontStablizer> stablizer) - : mStablizer{std::move(stablizer)}, mDualBand{!coeffslf.empty()}, mChannelDec{inchans} -{ - if(!mDualBand) - { - for(size_t j{0};j < mChannelDec.size();++j) - { - float *outcoeffs{mChannelDec[j].mGains.Single}; - for(const ChannelDec &incoeffs : coeffs) - *(outcoeffs++) = incoeffs[j]; - } - } - else - { - for(size_t j{0};j < mChannelDec.size();++j) - { - float *outcoeffs{mChannelDec[j].mGains.Dual[sHFBand]}; - for(const ChannelDec &incoeffs : coeffs) - *(outcoeffs++) = incoeffs[j]; - - outcoeffs = mChannelDec[j].mGains.Dual[sLFBand]; - for(const ChannelDec &incoeffs : coeffslf) - *(outcoeffs++) = incoeffs[j]; - } - } -} - - -void BFormatDec::process(const al::span<FloatBufferLine> OutBuffer, - const FloatBufferLine *InSamples, const size_t SamplesToDo) -{ - ASSUME(SamplesToDo > 0); - - if(mDualBand) - { - const al::span<float> hfSamples{mSamples[sHFBand].data(), SamplesToDo}; - const al::span<float> lfSamples{mSamples[sLFBand].data(), SamplesToDo}; - for(auto &chandec : mChannelDec) - { - chandec.mXOver.process({InSamples->data(), SamplesToDo}, hfSamples.data(), - lfSamples.data()); - MixSamples(hfSamples, OutBuffer, chandec.mGains.Dual[sHFBand], - chandec.mGains.Dual[sHFBand], 0, 0); - MixSamples(lfSamples, OutBuffer, chandec.mGains.Dual[sLFBand], - chandec.mGains.Dual[sLFBand], 0, 0); - ++InSamples; - } - } - else - { - for(auto &chandec : mChannelDec) - { - MixSamples({InSamples->data(), SamplesToDo}, OutBuffer, chandec.mGains.Single, - chandec.mGains.Single, 0, 0); - ++InSamples; - } - } -} - -void BFormatDec::processStablize(const al::span<FloatBufferLine> OutBuffer, - const FloatBufferLine *InSamples, const size_t lidx, const size_t ridx, const size_t cidx, - const size_t SamplesToDo) -{ - ASSUME(SamplesToDo > 0); - - /* Move the existing direct L/R signal out so it doesn't get processed by - * the stablizer. Add a delay to it so it stays aligned with the stablizer - * delay. - */ - float *RESTRICT mid{al::assume_aligned<16>(mStablizer->MidDirect.data())}; - float *RESTRICT side{al::assume_aligned<16>(mStablizer->Side.data())}; - for(size_t i{0};i < SamplesToDo;++i) - { - mid[FrontStablizer::DelayLength+i] = OutBuffer[lidx][i] + OutBuffer[ridx][i]; - side[FrontStablizer::DelayLength+i] = OutBuffer[lidx][i] - OutBuffer[ridx][i]; - } - std::fill_n(OutBuffer[lidx].begin(), SamplesToDo, 0.0f); - std::fill_n(OutBuffer[ridx].begin(), SamplesToDo, 0.0f); - - /* Decode the B-Format input to OutBuffer. */ - process(OutBuffer, InSamples, SamplesToDo); - - /* Apply a delay to all channels, except the front-left and front-right, so - * they maintain correct timing. - */ - const size_t NumChannels{OutBuffer.size()}; - for(size_t i{0u};i < NumChannels;i++) - { - if(i == lidx || i == ridx) - continue; - - auto &DelayBuf = mStablizer->DelayBuf[i]; - auto buffer_end = OutBuffer[i].begin() + SamplesToDo; - if LIKELY(SamplesToDo >= FrontStablizer::DelayLength) - { - auto delay_end = std::rotate(OutBuffer[i].begin(), - buffer_end - FrontStablizer::DelayLength, buffer_end); - std::swap_ranges(OutBuffer[i].begin(), delay_end, DelayBuf.begin()); - } - else - { - auto delay_start = std::swap_ranges(OutBuffer[i].begin(), buffer_end, - DelayBuf.begin()); - std::rotate(DelayBuf.begin(), delay_start, DelayBuf.end()); - } - } - - /* Include the side signal for what was just decoded. */ - for(size_t i{0};i < SamplesToDo;++i) - side[FrontStablizer::DelayLength+i] += OutBuffer[lidx][i] - OutBuffer[ridx][i]; - - /* Combine the delayed mid signal with the decoded mid signal. Note that - * the samples are stored and combined in reverse, so the newest samples - * are at the front and the oldest at the back. - */ - al::span<float> tmpbuf{mStablizer->TempBuf.data(), SamplesToDo+FrontStablizer::DelayLength}; - auto tmpiter = tmpbuf.begin() + SamplesToDo; - std::copy(mStablizer->MidDelay.cbegin(), mStablizer->MidDelay.cend(), tmpiter); - for(size_t i{0};i < SamplesToDo;++i) - *--tmpiter = OutBuffer[lidx][i] + OutBuffer[ridx][i]; - /* Save the newest samples for next time. */ - std::copy_n(tmpbuf.cbegin(), mStablizer->MidDelay.size(), mStablizer->MidDelay.begin()); - - /* Apply an all-pass on the reversed signal, then reverse the samples to - * get the forward signal with a reversed phase shift. The future samples - * are included with the all-pass to reduce the error in the output - * samples (the smaller the delay, the more error is introduced). - */ - mStablizer->MidFilter.applyAllpass(tmpbuf); - tmpbuf = tmpbuf.subspan<FrontStablizer::DelayLength>(); - std::reverse(tmpbuf.begin(), tmpbuf.end()); - - /* Now apply the band-splitter, combining its phase shift with the reversed - * phase shift, restoring the original phase on the split signal. - */ - mStablizer->MidFilter.process(tmpbuf, mStablizer->MidHF.data(), mStablizer->MidLF.data()); - - /* This pans the separate low- and high-frequency signals between being on - * the center channel and the left+right channels. The low-frequency signal - * is panned 1/3rd toward center and the high-frequency signal is panned - * 1/4th toward center. These values can be tweaked. - */ - const float cos_lf{std::cos(1.0f/3.0f * (al::MathDefs<float>::Pi()*0.5f))}; - const float cos_hf{std::cos(1.0f/4.0f * (al::MathDefs<float>::Pi()*0.5f))}; - const float sin_lf{std::sin(1.0f/3.0f * (al::MathDefs<float>::Pi()*0.5f))}; - const float sin_hf{std::sin(1.0f/4.0f * (al::MathDefs<float>::Pi()*0.5f))}; - for(size_t i{0};i < SamplesToDo;i++) - { - const float m{mStablizer->MidLF[i]*cos_lf + mStablizer->MidHF[i]*cos_hf + mid[i]}; - const float c{mStablizer->MidLF[i]*sin_lf + mStablizer->MidHF[i]*sin_hf}; - const float s{side[i]}; - - /* The generated center channel signal adds to the existing signal, - * while the modified left and right channels replace. - */ - OutBuffer[lidx][i] = (m + s) * 0.5f; - OutBuffer[ridx][i] = (m - s) * 0.5f; - OutBuffer[cidx][i] += c * 0.5f; - } - /* Move the delayed mid/side samples to the front for next time. */ - auto mid_end = mStablizer->MidDirect.cbegin() + SamplesToDo; - std::copy(mid_end, mid_end+FrontStablizer::DelayLength, mStablizer->MidDirect.begin()); - auto side_end = mStablizer->Side.cbegin() + SamplesToDo; - std::copy(side_end, side_end+FrontStablizer::DelayLength, mStablizer->Side.begin()); -} - - -std::unique_ptr<BFormatDec> BFormatDec::Create(const AmbDecConf *conf, const bool allow_2band, - const size_t inchans, const uint srate, const uint (&chanmap)[MAX_OUTPUT_CHANNELS], - std::unique_ptr<FrontStablizer> stablizer) -{ - return std::unique_ptr<BFormatDec>{new(FamCount(inchans)) - BFormatDec{conf, allow_2band, inchans, srate, chanmap, std::move(stablizer)}}; -} -std::unique_ptr<BFormatDec> BFormatDec::Create(const size_t inchans, - const al::span<const ChannelDec> coeffs, const al::span<const ChannelDec> coeffslf, - std::unique_ptr<FrontStablizer> stablizer) -{ - return std::unique_ptr<BFormatDec>{new(FamCount(inchans)) - BFormatDec{inchans, coeffs, coeffslf, std::move(stablizer)}}; -} diff --git a/alc/bformatdec.h b/alc/bformatdec.h deleted file mode 100644 index bb39f709..00000000 --- a/alc/bformatdec.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef BFORMATDEC_H -#define BFORMATDEC_H - -#include <array> -#include <cstddef> -#include <memory> - -#include "almalloc.h" -#include "alspan.h" -#include "core/ambidefs.h" -#include "core/bufferline.h" -#include "core/devformat.h" -#include "core/filters/splitter.h" - -struct AmbDecConf; -struct FrontStablizer; - - -using ChannelDec = std::array<float,MaxAmbiChannels>; - -class BFormatDec { - static constexpr size_t sHFBand{0}; - static constexpr size_t sLFBand{1}; - static constexpr size_t sNumBands{2}; - - struct ChannelDecoder { - union MatrixU { - float Dual[sNumBands][MAX_OUTPUT_CHANNELS]; - float Single[MAX_OUTPUT_CHANNELS]; - } mGains{}; - - /* NOTE: BandSplitter filter is unused with single-band decoding. */ - BandSplitter mXOver; - }; - - alignas(16) std::array<FloatBufferLine,2> mSamples; - - const std::unique_ptr<FrontStablizer> mStablizer; - const bool mDualBand{false}; - - al::FlexArray<ChannelDecoder> mChannelDec; - -public: - BFormatDec(const AmbDecConf *conf, const bool allow_2band, const size_t inchans, - const uint srate, const uint (&chanmap)[MAX_OUTPUT_CHANNELS], - std::unique_ptr<FrontStablizer> stablizer); - BFormatDec(const size_t inchans, const al::span<const ChannelDec> coeffs, - const al::span<const ChannelDec> coeffslf, std::unique_ptr<FrontStablizer> stablizer); - - bool hasStablizer() const noexcept { return mStablizer != nullptr; }; - - /* Decodes the ambisonic input to the given output channels. */ - void process(const al::span<FloatBufferLine> OutBuffer, const FloatBufferLine *InSamples, - const size_t SamplesToDo); - - /* Decodes the ambisonic input to the given output channels with stablization. */ - void processStablize(const al::span<FloatBufferLine> OutBuffer, - const FloatBufferLine *InSamples, const size_t lidx, const size_t ridx, const size_t cidx, - const size_t SamplesToDo); - - static std::unique_ptr<BFormatDec> Create(const AmbDecConf *conf, const bool allow_2band, - const size_t inchans, const uint srate, const uint (&chanmap)[MAX_OUTPUT_CHANNELS], - std::unique_ptr<FrontStablizer> stablizer); - static std::unique_ptr<BFormatDec> Create(const size_t inchans, - const al::span<const ChannelDec> coeffs, const al::span<const ChannelDec> coeffslf, - std::unique_ptr<FrontStablizer> stablizer); - - DEF_FAM_NEWDEL(BFormatDec, mChannelDec) -}; - -#endif /* BFORMATDEC_H */ diff --git a/alc/front_stablizer.h b/alc/front_stablizer.h deleted file mode 100644 index 0fedeb50..00000000 --- a/alc/front_stablizer.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef ALC_FRONT_STABLIZER_H -#define ALC_FRONT_STABLIZER_H - -#include <array> -#include <memory> - -#include "almalloc.h" -#include "core/bufferline.h" -#include "core/filters/splitter.h" - - -struct FrontStablizer { - static constexpr size_t DelayLength{256u}; - - FrontStablizer(size_t numchans) : DelayBuf{numchans} { } - - alignas(16) std::array<float,BufferLineSize + DelayLength> Side{}; - alignas(16) std::array<float,BufferLineSize + DelayLength> MidDirect{}; - alignas(16) std::array<float,DelayLength> MidDelay{}; - - alignas(16) std::array<float,BufferLineSize + DelayLength> TempBuf{}; - - BandSplitter MidFilter; - alignas(16) FloatBufferLine MidLF{}; - alignas(16) FloatBufferLine MidHF{}; - - using DelayLine = std::array<float,DelayLength>; - al::FlexArray<DelayLine,16> DelayBuf; - - static std::unique_ptr<FrontStablizer> Create(size_t numchans) - { return std::unique_ptr<FrontStablizer>{new(FamCount(numchans)) FrontStablizer{numchans}}; } - - DEF_FAM_NEWDEL(FrontStablizer, DelayBuf) -}; - -#endif /* ALC_FRONT_STABLIZER_H */ diff --git a/alc/panning.cpp b/alc/panning.cpp index ce6ba29c..5e263111 100644 --- a/alc/panning.cpp +++ b/alc/panning.cpp @@ -47,15 +47,15 @@ #include "alspan.h" #include "alstring.h" #include "alu.h" -#include "bformatdec.h" #include "core/ambdec.h" #include "core/ambidefs.h" +#include "core/bformatdec.h" #include "core/bs2b.h" #include "core/devformat.h" +#include "core/front_stablizer.h" #include "core/hrtf.h" #include "core/logging.h" #include "core/uhjfilter.h" -#include "front_stablizer.h" #include "math_defs.h" #include "opthelpers.h" |