4 #include "bformatdec.h"
18 #include "filters/splitter.h"
19 #include "opthelpers.h"
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
;
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);
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
};
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]);
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
;
121 BFormatDec::BFormatDec(const ALuint inchans
, const ALsizei chancount
,
122 const ChannelDec (&chancoeffs
)[MAX_OUTPUT_CHANNELS
],
123 const ALuint (&chanmap
)[MAX_OUTPUT_CHANNELS
])
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
++);
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);
154 for(ALuint i
{0};i
< mNumChannels
;i
++)
155 mXOver
[i
].process(mSamplesHF
[i
].data(), mSamplesLF
[i
].data(), InSamples
[i
].data(),
158 ALfloat (*mixmtx
)[sNumBands
][MAX_AMBI_CHANNELS
]{mMatrix
.Dual
};
159 ALuint enabled
{mEnabled
};
160 for(FloatBufferLine
&outbuf
: OutBuffer
)
164 const al::span
<float> outspan
{outbuf
.data(), SamplesToDo
};
165 MixRowSamples(outspan
, {(*mixmtx
)[sHFBand
], mNumChannels
}, mSamplesHF
->data(),
167 MixRowSamples(outspan
, {(*mixmtx
)[sLFBand
], mNumChannels
}, mSamplesLF
->data(),
176 ALfloat (*mixmtx
)[MAX_AMBI_CHANNELS
]{mMatrix
.Single
};
177 ALuint enabled
{mEnabled
};
178 for(FloatBufferLine
&outbuf
: OutBuffer
)
181 MixRowSamples({outbuf
.data(), SamplesToDo
}, {*mixmtx
, mNumChannels
},
182 InSamples
->data(), InSamples
->size());
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
];