bformatdec.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. #include "config.h"
  2. #include "bformatdec.h"
  3. #include <algorithm>
  4. #include <array>
  5. #include <cassert>
  6. #include <cmath>
  7. #include <iterator>
  8. #include <numeric>
  9. #include "almalloc.h"
  10. #include "alu.h"
  11. #include "core/ambdec.h"
  12. #include "core/filters/splitter.h"
  13. #include "front_stablizer.h"
  14. #include "math_defs.h"
  15. #include "opthelpers.h"
  16. namespace {
  17. constexpr std::array<float,MaxAmbiOrder+1> Ambi3DDecoderHFScale{{
  18. 1.00000000e+00f, 1.00000000e+00f
  19. }};
  20. constexpr std::array<float,MaxAmbiOrder+1> Ambi3DDecoderHFScale2O{{
  21. 7.45355990e-01f, 1.00000000e+00f, 1.00000000e+00f
  22. }};
  23. constexpr std::array<float,MaxAmbiOrder+1> Ambi3DDecoderHFScale3O{{
  24. 5.89792205e-01f, 8.79693856e-01f, 1.00000000e+00f, 1.00000000e+00f
  25. }};
  26. inline auto& GetDecoderHFScales(uint order) noexcept
  27. {
  28. if(order >= 3) return Ambi3DDecoderHFScale3O;
  29. if(order == 2) return Ambi3DDecoderHFScale2O;
  30. return Ambi3DDecoderHFScale;
  31. }
  32. inline auto& GetAmbiScales(AmbDecScale scaletype) noexcept
  33. {
  34. if(scaletype == AmbDecScale::FuMa) return AmbiScale::FromFuMa();
  35. if(scaletype == AmbDecScale::SN3D) return AmbiScale::FromSN3D();
  36. return AmbiScale::FromN3D();
  37. }
  38. } // namespace
  39. BFormatDec::BFormatDec(const AmbDecConf *conf, const bool allow_2band, const size_t inchans,
  40. const uint srate, const uint (&chanmap)[MAX_OUTPUT_CHANNELS],
  41. std::unique_ptr<FrontStablizer> stablizer)
  42. : mStablizer{std::move(stablizer)}, mDualBand{allow_2band && (conf->FreqBands == 2)}
  43. , mChannelDec{inchans}
  44. {
  45. const bool periphonic{(conf->ChanMask&AmbiPeriphonicMask) != 0};
  46. auto&& coeff_scale = GetAmbiScales(conf->CoeffScale);
  47. if(!mDualBand)
  48. {
  49. for(size_t j{0},k{0};j < mChannelDec.size();++j)
  50. {
  51. const size_t acn{periphonic ? j : AmbiIndex::FromACN2D()[j]};
  52. if(!(conf->ChanMask&(1u<<acn))) continue;
  53. const size_t order{AmbiIndex::OrderFromChannel()[acn]};
  54. const float gain{conf->HFOrderGain[order] / coeff_scale[acn]};
  55. for(size_t i{0u};i < conf->NumSpeakers;++i)
  56. {
  57. const size_t chanidx{chanmap[i]};
  58. mChannelDec[j].mGains.Single[chanidx] = conf->Matrix[i][k] * gain;
  59. }
  60. ++k;
  61. }
  62. }
  63. else
  64. {
  65. mChannelDec[0].mXOver.init(conf->XOverFreq / static_cast<float>(srate));
  66. for(size_t j{1};j < mChannelDec.size();++j)
  67. mChannelDec[j].mXOver = mChannelDec[0].mXOver;
  68. const float ratio{std::pow(10.0f, conf->XOverRatio / 40.0f)};
  69. for(size_t j{0},k{0};j < mChannelDec.size();++j)
  70. {
  71. const size_t acn{periphonic ? j : AmbiIndex::FromACN2D()[j]};
  72. if(!(conf->ChanMask&(1u<<acn))) continue;
  73. const size_t order{AmbiIndex::OrderFromChannel()[acn]};
  74. const float hfGain{conf->HFOrderGain[order] * ratio / coeff_scale[acn]};
  75. const float lfGain{conf->LFOrderGain[order] / ratio / coeff_scale[acn]};
  76. for(size_t i{0u};i < conf->NumSpeakers;++i)
  77. {
  78. const size_t chanidx{chanmap[i]};
  79. mChannelDec[j].mGains.Dual[sHFBand][chanidx] = conf->HFMatrix[i][k] * hfGain;
  80. mChannelDec[j].mGains.Dual[sLFBand][chanidx] = conf->LFMatrix[i][k] * lfGain;
  81. }
  82. ++k;
  83. }
  84. }
  85. }
  86. BFormatDec::BFormatDec(const size_t inchans, const al::span<const ChannelDec> coeffs,
  87. const al::span<const ChannelDec> coeffslf, std::unique_ptr<FrontStablizer> stablizer)
  88. : mStablizer{std::move(stablizer)}, mDualBand{!coeffslf.empty()}, mChannelDec{inchans}
  89. {
  90. if(!mDualBand)
  91. {
  92. for(size_t j{0};j < mChannelDec.size();++j)
  93. {
  94. float *outcoeffs{mChannelDec[j].mGains.Single};
  95. for(const ChannelDec &incoeffs : coeffs)
  96. *(outcoeffs++) = incoeffs[j];
  97. }
  98. }
  99. else
  100. {
  101. for(size_t j{0};j < mChannelDec.size();++j)
  102. {
  103. float *outcoeffs{mChannelDec[j].mGains.Dual[sHFBand]};
  104. for(const ChannelDec &incoeffs : coeffs)
  105. *(outcoeffs++) = incoeffs[j];
  106. outcoeffs = mChannelDec[j].mGains.Dual[sLFBand];
  107. for(const ChannelDec &incoeffs : coeffslf)
  108. *(outcoeffs++) = incoeffs[j];
  109. }
  110. }
  111. }
  112. void BFormatDec::process(const al::span<FloatBufferLine> OutBuffer,
  113. const FloatBufferLine *InSamples, const size_t SamplesToDo)
  114. {
  115. ASSUME(SamplesToDo > 0);
  116. if(mDualBand)
  117. {
  118. const al::span<float> hfSamples{mSamples[sHFBand].data(), SamplesToDo};
  119. const al::span<float> lfSamples{mSamples[sLFBand].data(), SamplesToDo};
  120. for(auto &chandec : mChannelDec)
  121. {
  122. chandec.mXOver.process({InSamples->data(), SamplesToDo}, hfSamples.data(),
  123. lfSamples.data());
  124. MixSamples(hfSamples, OutBuffer, chandec.mGains.Dual[sHFBand],
  125. chandec.mGains.Dual[sHFBand], 0, 0);
  126. MixSamples(lfSamples, OutBuffer, chandec.mGains.Dual[sLFBand],
  127. chandec.mGains.Dual[sLFBand], 0, 0);
  128. ++InSamples;
  129. }
  130. }
  131. else
  132. {
  133. for(auto &chandec : mChannelDec)
  134. {
  135. MixSamples({InSamples->data(), SamplesToDo}, OutBuffer, chandec.mGains.Single,
  136. chandec.mGains.Single, 0, 0);
  137. ++InSamples;
  138. }
  139. }
  140. }
  141. void BFormatDec::processStablize(const al::span<FloatBufferLine> OutBuffer,
  142. const FloatBufferLine *InSamples, const size_t lidx, const size_t ridx, const size_t cidx,
  143. const size_t SamplesToDo)
  144. {
  145. ASSUME(SamplesToDo > 0);
  146. /* Move the existing direct L/R signal out so it doesn't get processed by
  147. * the stablizer. Add a delay to it so it stays aligned with the stablizer
  148. * delay.
  149. */
  150. float *RESTRICT mid{al::assume_aligned<16>(mStablizer->MidDirect.data())};
  151. float *RESTRICT side{al::assume_aligned<16>(mStablizer->Side.data())};
  152. for(size_t i{0};i < SamplesToDo;++i)
  153. {
  154. mid[FrontStablizer::DelayLength+i] = OutBuffer[lidx][i] + OutBuffer[ridx][i];
  155. side[FrontStablizer::DelayLength+i] = OutBuffer[lidx][i] - OutBuffer[ridx][i];
  156. }
  157. std::fill_n(OutBuffer[lidx].begin(), SamplesToDo, 0.0f);
  158. std::fill_n(OutBuffer[ridx].begin(), SamplesToDo, 0.0f);
  159. /* Decode the B-Format input to OutBuffer. */
  160. process(OutBuffer, InSamples, SamplesToDo);
  161. /* Apply a delay to all channels, except the front-left and front-right, so
  162. * they maintain correct timing.
  163. */
  164. const size_t NumChannels{OutBuffer.size()};
  165. for(size_t i{0u};i < NumChannels;i++)
  166. {
  167. if(i == lidx || i == ridx)
  168. continue;
  169. auto &DelayBuf = mStablizer->DelayBuf[i];
  170. auto buffer_end = OutBuffer[i].begin() + SamplesToDo;
  171. if LIKELY(SamplesToDo >= FrontStablizer::DelayLength)
  172. {
  173. auto delay_end = std::rotate(OutBuffer[i].begin(),
  174. buffer_end - FrontStablizer::DelayLength, buffer_end);
  175. std::swap_ranges(OutBuffer[i].begin(), delay_end, DelayBuf.begin());
  176. }
  177. else
  178. {
  179. auto delay_start = std::swap_ranges(OutBuffer[i].begin(), buffer_end,
  180. DelayBuf.begin());
  181. std::rotate(DelayBuf.begin(), delay_start, DelayBuf.end());
  182. }
  183. }
  184. /* Include the side signal for what was just decoded. */
  185. for(size_t i{0};i < SamplesToDo;++i)
  186. side[FrontStablizer::DelayLength+i] += OutBuffer[lidx][i] - OutBuffer[ridx][i];
  187. /* Combine the delayed mid signal with the decoded mid signal. Note that
  188. * the samples are stored and combined in reverse, so the newest samples
  189. * are at the front and the oldest at the back.
  190. */
  191. al::span<float> tmpbuf{mStablizer->TempBuf.data(), SamplesToDo+FrontStablizer::DelayLength};
  192. auto tmpiter = tmpbuf.begin() + SamplesToDo;
  193. std::copy(mStablizer->MidDelay.cbegin(), mStablizer->MidDelay.cend(), tmpiter);
  194. for(size_t i{0};i < SamplesToDo;++i)
  195. *--tmpiter = OutBuffer[lidx][i] + OutBuffer[ridx][i];
  196. /* Save the newest samples for next time. */
  197. std::copy_n(tmpbuf.cbegin(), mStablizer->MidDelay.size(), mStablizer->MidDelay.begin());
  198. /* Apply an all-pass on the reversed signal, then reverse the samples to
  199. * get the forward signal with a reversed phase shift. The future samples
  200. * are included with the all-pass to reduce the error in the output
  201. * samples (the smaller the delay, the more error is introduced).
  202. */
  203. mStablizer->MidFilter.applyAllpass(tmpbuf);
  204. tmpbuf = tmpbuf.subspan<FrontStablizer::DelayLength>();
  205. std::reverse(tmpbuf.begin(), tmpbuf.end());
  206. /* Now apply the band-splitter, combining its phase shift with the reversed
  207. * phase shift, restoring the original phase on the split signal.
  208. */
  209. mStablizer->MidFilter.process(tmpbuf, mStablizer->MidHF.data(), mStablizer->MidLF.data());
  210. /* This pans the separate low- and high-frequency signals between being on
  211. * the center channel and the left+right channels. The low-frequency signal
  212. * is panned 1/3rd toward center and the high-frequency signal is panned
  213. * 1/4th toward center. These values can be tweaked.
  214. */
  215. const float cos_lf{std::cos(1.0f/3.0f * (al::MathDefs<float>::Pi()*0.5f))};
  216. const float cos_hf{std::cos(1.0f/4.0f * (al::MathDefs<float>::Pi()*0.5f))};
  217. const float sin_lf{std::sin(1.0f/3.0f * (al::MathDefs<float>::Pi()*0.5f))};
  218. const float sin_hf{std::sin(1.0f/4.0f * (al::MathDefs<float>::Pi()*0.5f))};
  219. for(size_t i{0};i < SamplesToDo;i++)
  220. {
  221. const float m{mStablizer->MidLF[i]*cos_lf + mStablizer->MidHF[i]*cos_hf + mid[i]};
  222. const float c{mStablizer->MidLF[i]*sin_lf + mStablizer->MidHF[i]*sin_hf};
  223. const float s{side[i]};
  224. /* The generated center channel signal adds to the existing signal,
  225. * while the modified left and right channels replace.
  226. */
  227. OutBuffer[lidx][i] = (m + s) * 0.5f;
  228. OutBuffer[ridx][i] = (m - s) * 0.5f;
  229. OutBuffer[cidx][i] += c * 0.5f;
  230. }
  231. /* Move the delayed mid/side samples to the front for next time. */
  232. auto mid_end = mStablizer->MidDirect.cbegin() + SamplesToDo;
  233. std::copy(mid_end, mid_end+FrontStablizer::DelayLength, mStablizer->MidDirect.begin());
  234. auto side_end = mStablizer->Side.cbegin() + SamplesToDo;
  235. std::copy(side_end, side_end+FrontStablizer::DelayLength, mStablizer->Side.begin());
  236. }
  237. auto BFormatDec::GetHFOrderScales(const uint in_order, const uint out_order) noexcept
  238. -> std::array<float,MaxAmbiOrder+1>
  239. {
  240. std::array<float,MaxAmbiOrder+1> ret{};
  241. assert(out_order >= in_order);
  242. const auto &target = GetDecoderHFScales(out_order);
  243. const auto &input = GetDecoderHFScales(in_order);
  244. for(size_t i{0};i < in_order+1;++i)
  245. ret[i] = input[i] / target[i];
  246. return ret;
  247. }
  248. std::unique_ptr<BFormatDec> BFormatDec::Create(const AmbDecConf *conf, const bool allow_2band,
  249. const size_t inchans, const uint srate, const uint (&chanmap)[MAX_OUTPUT_CHANNELS],
  250. std::unique_ptr<FrontStablizer> stablizer)
  251. {
  252. return std::unique_ptr<BFormatDec>{new(FamCount(inchans))
  253. BFormatDec{conf, allow_2band, inchans, srate, chanmap, std::move(stablizer)}};
  254. }
  255. std::unique_ptr<BFormatDec> BFormatDec::Create(const size_t inchans,
  256. const al::span<const ChannelDec> coeffs, const al::span<const ChannelDec> coeffslf,
  257. std::unique_ptr<FrontStablizer> stablizer)
  258. {
  259. return std::unique_ptr<BFormatDec>{new(FamCount(inchans))
  260. BFormatDec{inchans, coeffs, coeffslf, std::move(stablizer)}};
  261. }