bformatdec.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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 "AL/al.h"
  10. #include "almalloc.h"
  11. #include "alu.h"
  12. #include "ambdec.h"
  13. #include "filters/splitter.h"
  14. #include "opthelpers.h"
  15. namespace {
  16. constexpr ALfloat Ambi3DDecoderHFScale[MAX_AMBI_ORDER+1] = {
  17. 1.00000000e+00f, 1.00000000e+00f
  18. };
  19. constexpr ALfloat Ambi3DDecoderHFScale2O[MAX_AMBI_ORDER+1] = {
  20. 7.45355990e-01f, 1.00000000e+00f
  21. };
  22. constexpr ALfloat Ambi3DDecoderHFScale3O[MAX_AMBI_ORDER+1] = {
  23. 5.89792205e-01f, 8.79693856e-01f
  24. };
  25. inline auto GetDecoderHFScales(ALuint order) noexcept -> const ALfloat(&)[MAX_AMBI_ORDER+1]
  26. {
  27. if(order >= 3) return Ambi3DDecoderHFScale3O;
  28. if(order == 2) return Ambi3DDecoderHFScale2O;
  29. return Ambi3DDecoderHFScale;
  30. }
  31. inline auto GetAmbiScales(AmbDecScale scaletype) noexcept -> const std::array<float,MAX_AMBI_CHANNELS>&
  32. {
  33. if(scaletype == AmbDecScale::FuMa) return AmbiScale::FromFuMa;
  34. if(scaletype == AmbDecScale::SN3D) return AmbiScale::FromSN3D;
  35. return AmbiScale::FromN3D;
  36. }
  37. } // namespace
  38. BFormatDec::BFormatDec(const AmbDecConf *conf, const bool allow_2band, const ALuint inchans,
  39. const ALuint srate, const ALuint (&chanmap)[MAX_OUTPUT_CHANNELS])
  40. {
  41. mDualBand = allow_2band && (conf->FreqBands == 2);
  42. if(!mDualBand)
  43. mSamples.resize(2);
  44. else
  45. {
  46. ASSUME(inchans > 0);
  47. mSamples.resize(inchans * 2);
  48. mSamplesHF = mSamples.data();
  49. mSamplesLF = mSamplesHF + inchans;
  50. }
  51. mNumChannels = inchans;
  52. mEnabled = std::accumulate(std::begin(chanmap), std::begin(chanmap)+conf->Speakers.size(), 0u,
  53. [](ALuint mask, const ALuint &chan) noexcept -> ALuint
  54. { return mask | (1 << chan); }
  55. );
  56. const ALfloat xover_norm{conf->XOverFreq / static_cast<float>(srate)};
  57. const bool periphonic{(conf->ChanMask&AMBI_PERIPHONIC_MASK) != 0};
  58. const std::array<float,MAX_AMBI_CHANNELS> &coeff_scale = GetAmbiScales(conf->CoeffScale);
  59. const size_t coeff_count{periphonic ? MAX_AMBI_CHANNELS : MAX_AMBI2D_CHANNELS};
  60. if(!mDualBand)
  61. {
  62. for(size_t i{0u};i < conf->Speakers.size();i++)
  63. {
  64. ALfloat (&mtx)[MAX_AMBI_CHANNELS] = mMatrix.Single[chanmap[i]];
  65. for(size_t j{0},k{0};j < coeff_count;j++)
  66. {
  67. const size_t l{periphonic ? j : AmbiIndex::From2D[j]};
  68. if(!(conf->ChanMask&(1u<<l))) continue;
  69. mtx[j] = conf->HFMatrix[i][k] / coeff_scale[l] *
  70. ((l>=9) ? conf->HFOrderGain[3] :
  71. (l>=4) ? conf->HFOrderGain[2] :
  72. (l>=1) ? conf->HFOrderGain[1] : conf->HFOrderGain[0]);
  73. ++k;
  74. }
  75. }
  76. }
  77. else
  78. {
  79. mXOver[0].init(xover_norm);
  80. std::fill(std::begin(mXOver)+1, std::end(mXOver), mXOver[0]);
  81. const float ratio{std::pow(10.0f, conf->XOverRatio / 40.0f)};
  82. for(size_t i{0u};i < conf->Speakers.size();i++)
  83. {
  84. ALfloat (&mtx)[sNumBands][MAX_AMBI_CHANNELS] = mMatrix.Dual[chanmap[i]];
  85. for(size_t j{0},k{0};j < coeff_count;j++)
  86. {
  87. const size_t l{periphonic ? j : AmbiIndex::From2D[j]};
  88. if(!(conf->ChanMask&(1u<<l))) continue;
  89. mtx[sHFBand][j] = conf->HFMatrix[i][k] / coeff_scale[l] *
  90. ((l>=9) ? conf->HFOrderGain[3] :
  91. (l>=4) ? conf->HFOrderGain[2] :
  92. (l>=1) ? conf->HFOrderGain[1] : conf->HFOrderGain[0]) * ratio;
  93. mtx[sLFBand][j] = conf->LFMatrix[i][k] / coeff_scale[l] *
  94. ((l>=9) ? conf->LFOrderGain[3] :
  95. (l>=4) ? conf->LFOrderGain[2] :
  96. (l>=1) ? conf->LFOrderGain[1] : conf->LFOrderGain[0]) / ratio;
  97. ++k;
  98. }
  99. }
  100. }
  101. }
  102. BFormatDec::BFormatDec(const ALuint inchans, const ALsizei chancount,
  103. const ChannelDec (&chancoeffs)[MAX_OUTPUT_CHANNELS],
  104. const ALuint (&chanmap)[MAX_OUTPUT_CHANNELS])
  105. {
  106. mSamples.resize(2);
  107. mNumChannels = inchans;
  108. ASSUME(chancount > 0);
  109. mEnabled = std::accumulate(std::begin(chanmap), std::begin(chanmap)+chancount, 0u,
  110. [](ALuint mask, const ALuint &chan) noexcept -> ALuint
  111. { return mask | (1 << chan); }
  112. );
  113. const ChannelDec *incoeffs{chancoeffs};
  114. auto set_coeffs = [this,inchans,&incoeffs](const ALuint chanidx) noexcept -> void
  115. {
  116. ALfloat (&mtx)[MAX_AMBI_CHANNELS] = mMatrix.Single[chanidx];
  117. const ALfloat (&coeffs)[MAX_AMBI_CHANNELS] = *(incoeffs++);
  118. ASSUME(inchans > 0);
  119. std::copy_n(std::begin(coeffs), inchans, std::begin(mtx));
  120. };
  121. std::for_each(chanmap, chanmap+chancount, set_coeffs);
  122. }
  123. void BFormatDec::process(const al::span<FloatBufferLine> OutBuffer,
  124. const FloatBufferLine *InSamples, const size_t SamplesToDo)
  125. {
  126. ASSUME(SamplesToDo > 0);
  127. if(mDualBand)
  128. {
  129. for(ALuint i{0};i < mNumChannels;i++)
  130. mXOver[i].process(mSamplesHF[i].data(), mSamplesLF[i].data(), InSamples[i].data(),
  131. SamplesToDo);
  132. ALfloat (*mixmtx)[sNumBands][MAX_AMBI_CHANNELS]{mMatrix.Dual};
  133. ALuint enabled{mEnabled};
  134. for(FloatBufferLine &outbuf : OutBuffer)
  135. {
  136. if LIKELY(enabled&1)
  137. {
  138. const al::span<float> outspan{outbuf.data(), SamplesToDo};
  139. MixRowSamples(outspan, {(*mixmtx)[sHFBand], mNumChannels}, mSamplesHF->data(),
  140. mSamplesHF->size());
  141. MixRowSamples(outspan, {(*mixmtx)[sLFBand], mNumChannels}, mSamplesLF->data(),
  142. mSamplesLF->size());
  143. }
  144. ++mixmtx;
  145. enabled >>= 1;
  146. }
  147. }
  148. else
  149. {
  150. ALfloat (*mixmtx)[MAX_AMBI_CHANNELS]{mMatrix.Single};
  151. ALuint enabled{mEnabled};
  152. for(FloatBufferLine &outbuf : OutBuffer)
  153. {
  154. if LIKELY(enabled&1)
  155. MixRowSamples({outbuf.data(), SamplesToDo}, {*mixmtx, mNumChannels},
  156. InSamples->data(), InSamples->size());
  157. ++mixmtx;
  158. enabled >>= 1;
  159. }
  160. }
  161. }
  162. std::array<ALfloat,MAX_AMBI_ORDER+1> BFormatDec::GetHFOrderScales(const ALuint in_order, const ALuint out_order) noexcept
  163. {
  164. std::array<ALfloat,MAX_AMBI_ORDER+1> ret{};
  165. assert(out_order >= in_order);
  166. const ALfloat (&target)[MAX_AMBI_ORDER+1] = GetDecoderHFScales(out_order);
  167. const ALfloat (&input)[MAX_AMBI_ORDER+1] = GetDecoderHFScales(in_order);
  168. for(ALuint i{0};i < in_order+1;++i)
  169. ret[i] = input[i] / target[i];
  170. return ret;
  171. }