Don't inline the utf8 converters
[openal-soft.git] / alc / bformatdec.cpp
blob9fbe32b801d932f945a0a8554451a0c74327cd6a
2 #include "config.h"
4 #include "bformatdec.h"
6 #include <algorithm>
7 #include <array>
8 #include <cassert>
9 #include <cmath>
10 #include <iterator>
11 #include <numeric>
13 #include "AL/al.h"
15 #include "almalloc.h"
16 #include "alu.h"
17 #include "ambdec.h"
18 #include "filters/splitter.h"
19 #include "opthelpers.h"
22 namespace {
24 constexpr ALfloat Ambi3DDecoderHFScale[MAX_AMBI_ORDER+1] = {
25 1.00000000e+00f, 1.00000000e+00f
27 constexpr ALfloat Ambi3DDecoderHFScale2O[MAX_AMBI_ORDER+1] = {
28 7.45355990e-01f, 1.00000000e+00f
30 constexpr ALfloat Ambi3DDecoderHFScale3O[MAX_AMBI_ORDER+1] = {
31 5.89792205e-01f, 8.79693856e-01f
34 inline auto GetDecoderHFScales(ALuint order) noexcept -> const ALfloat(&)[MAX_AMBI_ORDER+1]
36 if(order >= 3) return Ambi3DDecoderHFScale3O;
37 if(order == 2) return Ambi3DDecoderHFScale2O;
38 return Ambi3DDecoderHFScale;
41 inline auto GetAmbiScales(AmbDecScale scaletype) noexcept -> const std::array<float,MAX_AMBI_CHANNELS>&
43 if(scaletype == AmbDecScale::FuMa) return AmbiScale::FromFuMa;
44 if(scaletype == AmbDecScale::SN3D) return AmbiScale::FromSN3D;
45 return AmbiScale::FromN3D;
48 } // namespace
51 BFormatDec::BFormatDec(const AmbDecConf *conf, const bool allow_2band, const ALuint inchans,
52 const ALuint srate, const ALuint (&chanmap)[MAX_OUTPUT_CHANNELS])
54 mDualBand = allow_2band && (conf->FreqBands == 2);
55 if(!mDualBand)
56 mSamples.resize(2);
57 else
59 ASSUME(inchans > 0);
60 mSamples.resize(inchans * 2);
61 mSamplesHF = mSamples.data();
62 mSamplesLF = mSamplesHF + inchans;
64 mNumChannels = inchans;
66 mEnabled = std::accumulate(std::begin(chanmap), std::begin(chanmap)+conf->Speakers.size(), 0u,
67 [](ALuint mask, const ALuint &chan) noexcept -> ALuint
68 { return mask | (1 << chan); }
71 const ALfloat xover_norm{conf->XOverFreq / static_cast<float>(srate)};
73 const bool periphonic{(conf->ChanMask&AMBI_PERIPHONIC_MASK) != 0};
74 const std::array<float,MAX_AMBI_CHANNELS> &coeff_scale = GetAmbiScales(conf->CoeffScale);
75 const size_t coeff_count{periphonic ? MAX_AMBI_CHANNELS : MAX_AMBI2D_CHANNELS};
77 if(!mDualBand)
79 for(size_t i{0u};i < conf->Speakers.size();i++)
81 ALfloat (&mtx)[MAX_AMBI_CHANNELS] = mMatrix.Single[chanmap[i]];
82 for(size_t j{0},k{0};j < coeff_count;j++)
84 const size_t l{periphonic ? j : AmbiIndex::From2D[j]};
85 if(!(conf->ChanMask&(1u<<l))) continue;
86 mtx[j] = conf->HFMatrix[i][k] / coeff_scale[l] *
87 ((l>=9) ? conf->HFOrderGain[3] :
88 (l>=4) ? conf->HFOrderGain[2] :
89 (l>=1) ? conf->HFOrderGain[1] : conf->HFOrderGain[0]);
90 ++k;
94 else
96 mXOver[0].init(xover_norm);
97 std::fill(std::begin(mXOver)+1, std::end(mXOver), mXOver[0]);
99 const float ratio{std::pow(10.0f, conf->XOverRatio / 40.0f)};
100 for(size_t i{0u};i < conf->Speakers.size();i++)
102 ALfloat (&mtx)[sNumBands][MAX_AMBI_CHANNELS] = mMatrix.Dual[chanmap[i]];
103 for(size_t j{0},k{0};j < coeff_count;j++)
105 const size_t l{periphonic ? j : AmbiIndex::From2D[j]};
106 if(!(conf->ChanMask&(1u<<l))) continue;
107 mtx[sHFBand][j] = conf->HFMatrix[i][k] / coeff_scale[l] *
108 ((l>=9) ? conf->HFOrderGain[3] :
109 (l>=4) ? conf->HFOrderGain[2] :
110 (l>=1) ? conf->HFOrderGain[1] : conf->HFOrderGain[0]) * ratio;
111 mtx[sLFBand][j] = conf->LFMatrix[i][k] / coeff_scale[l] *
112 ((l>=9) ? conf->LFOrderGain[3] :
113 (l>=4) ? conf->LFOrderGain[2] :
114 (l>=1) ? conf->LFOrderGain[1] : conf->LFOrderGain[0]) / ratio;
115 ++k;
121 BFormatDec::BFormatDec(const ALuint inchans, const ALsizei chancount,
122 const ChannelDec (&chancoeffs)[MAX_OUTPUT_CHANNELS],
123 const ALuint (&chanmap)[MAX_OUTPUT_CHANNELS])
125 mSamples.resize(2);
126 mNumChannels = inchans;
128 ASSUME(chancount > 0);
129 mEnabled = std::accumulate(std::begin(chanmap), std::begin(chanmap)+chancount, 0u,
130 [](ALuint mask, const ALuint &chan) noexcept -> ALuint
131 { return mask | (1 << chan); }
134 const ChannelDec *incoeffs{chancoeffs};
135 auto set_coeffs = [this,inchans,&incoeffs](const ALuint chanidx) noexcept -> void
137 ALfloat (&mtx)[MAX_AMBI_CHANNELS] = mMatrix.Single[chanidx];
138 const ALfloat (&coeffs)[MAX_AMBI_CHANNELS] = *(incoeffs++);
140 ASSUME(inchans > 0);
141 std::copy_n(std::begin(coeffs), inchans, std::begin(mtx));
143 std::for_each(chanmap, chanmap+chancount, set_coeffs);
147 void BFormatDec::process(const al::span<FloatBufferLine> OutBuffer,
148 const FloatBufferLine *InSamples, const size_t SamplesToDo)
150 ASSUME(SamplesToDo > 0);
152 if(mDualBand)
154 for(ALuint i{0};i < mNumChannels;i++)
155 mXOver[i].process(mSamplesHF[i].data(), mSamplesLF[i].data(), InSamples[i].data(),
156 SamplesToDo);
158 ALfloat (*mixmtx)[sNumBands][MAX_AMBI_CHANNELS]{mMatrix.Dual};
159 ALuint enabled{mEnabled};
160 for(FloatBufferLine &outbuf : OutBuffer)
162 if LIKELY(enabled&1)
164 const al::span<float> outspan{outbuf.data(), SamplesToDo};
165 MixRowSamples(outspan, {(*mixmtx)[sHFBand], mNumChannels}, mSamplesHF->data(),
166 mSamplesHF->size());
167 MixRowSamples(outspan, {(*mixmtx)[sLFBand], mNumChannels}, mSamplesLF->data(),
168 mSamplesLF->size());
170 ++mixmtx;
171 enabled >>= 1;
174 else
176 ALfloat (*mixmtx)[MAX_AMBI_CHANNELS]{mMatrix.Single};
177 ALuint enabled{mEnabled};
178 for(FloatBufferLine &outbuf : OutBuffer)
180 if LIKELY(enabled&1)
181 MixRowSamples({outbuf.data(), SamplesToDo}, {*mixmtx, mNumChannels},
182 InSamples->data(), InSamples->size());
183 ++mixmtx;
184 enabled >>= 1;
190 std::array<ALfloat,MAX_AMBI_ORDER+1> BFormatDec::GetHFOrderScales(const ALuint in_order, const ALuint out_order) noexcept
192 std::array<ALfloat,MAX_AMBI_ORDER+1> ret{};
194 assert(out_order >= in_order);
196 const ALfloat (&target)[MAX_AMBI_ORDER+1] = GetDecoderHFScales(out_order);
197 const ALfloat (&input)[MAX_AMBI_ORDER+1] = GetDecoderHFScales(in_order);
199 for(ALuint i{0};i < in_order+1;++i)
200 ret[i] = input[i] / target[i];
202 return ret;