bformatdec.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #include "config.h"
  2. #include "bformatdec.h"
  3. #include <algorithm>
  4. #include <array>
  5. #include <cmath>
  6. #include <functional>
  7. #include <utility>
  8. #include "alnumbers.h"
  9. #include "bufferline.h"
  10. #include "filters/splitter.h"
  11. #include "flexarray.h"
  12. #include "front_stablizer.h"
  13. #include "mixer.h"
  14. #include "opthelpers.h"
  15. namespace {
  16. template<typename... Ts>
  17. struct overloaded : Ts... { using Ts::operator()...; };
  18. template<typename... Ts>
  19. overloaded(Ts...) -> overloaded<Ts...>;
  20. } // namespace
  21. BFormatDec::BFormatDec(const size_t inchans, const al::span<const ChannelDec> coeffs,
  22. const al::span<const ChannelDec> coeffslf, const float xover_f0norm,
  23. std::unique_ptr<FrontStablizer> stablizer)
  24. : mStablizer{std::move(stablizer)}
  25. {
  26. if(coeffslf.empty())
  27. {
  28. auto &decoder = mChannelDec.emplace<std::vector<ChannelDecoderSingle>>(inchans);
  29. for(size_t j{0};j < decoder.size();++j)
  30. {
  31. std::transform(coeffs.cbegin(), coeffs.cend(), decoder[j].mGains.begin(),
  32. [j](const ChannelDec &incoeffs) { return incoeffs[j]; });
  33. }
  34. }
  35. else
  36. {
  37. auto &decoder = mChannelDec.emplace<std::vector<ChannelDecoderDual>>(inchans);
  38. decoder[0].mXOver.init(xover_f0norm);
  39. for(size_t j{1};j < decoder.size();++j)
  40. decoder[j].mXOver = decoder[0].mXOver;
  41. for(size_t j{0};j < decoder.size();++j)
  42. {
  43. std::transform(coeffs.cbegin(), coeffs.cend(), decoder[j].mGains[sHFBand].begin(),
  44. [j](const ChannelDec &incoeffs) { return incoeffs[j]; });
  45. std::transform(coeffslf.cbegin(), coeffslf.cend(), decoder[j].mGains[sLFBand].begin(),
  46. [j](const ChannelDec &incoeffs) { return incoeffs[j]; });
  47. }
  48. }
  49. }
  50. void BFormatDec::process(const al::span<FloatBufferLine> OutBuffer,
  51. const al::span<const FloatBufferLine> InSamples, const size_t SamplesToDo)
  52. {
  53. ASSUME(SamplesToDo > 0);
  54. auto decode_dualband = [=](std::vector<ChannelDecoderDual> &decoder)
  55. {
  56. auto input = InSamples.cbegin();
  57. const auto hfSamples = al::span<float>{mSamples[sHFBand]}.first(SamplesToDo);
  58. const auto lfSamples = al::span<float>{mSamples[sLFBand]}.first(SamplesToDo);
  59. for(auto &chandec : decoder)
  60. {
  61. chandec.mXOver.process(al::span{*input++}.first(SamplesToDo), hfSamples, lfSamples);
  62. MixSamples(hfSamples, OutBuffer, chandec.mGains[sHFBand], chandec.mGains[sHFBand],0,0);
  63. MixSamples(lfSamples, OutBuffer, chandec.mGains[sLFBand], chandec.mGains[sLFBand],0,0);
  64. }
  65. };
  66. auto decode_singleband = [=](std::vector<ChannelDecoderSingle> &decoder)
  67. {
  68. auto input = InSamples.cbegin();
  69. for(auto &chandec : decoder)
  70. {
  71. MixSamples(al::span{*input++}.first(SamplesToDo), OutBuffer, chandec.mGains,
  72. chandec.mGains, 0, 0);
  73. }
  74. };
  75. std::visit(overloaded{decode_dualband, decode_singleband}, mChannelDec);
  76. }
  77. void BFormatDec::processStablize(const al::span<FloatBufferLine> OutBuffer,
  78. const al::span<const FloatBufferLine> InSamples, const size_t lidx, const size_t ridx,
  79. const size_t cidx, const size_t SamplesToDo)
  80. {
  81. ASSUME(SamplesToDo > 0);
  82. /* Move the existing direct L/R signal out so it doesn't get processed by
  83. * the stablizer.
  84. */
  85. const auto leftout = al::span<float>{OutBuffer[lidx]}.first(SamplesToDo);
  86. const auto rightout = al::span<float>{OutBuffer[ridx]}.first(SamplesToDo);
  87. const auto mid = al::span{mStablizer->MidDirect}.first(SamplesToDo);
  88. const auto side = al::span{mStablizer->Side}.first(SamplesToDo);
  89. std::transform(leftout.cbegin(), leftout.cend(), rightout.cbegin(), mid.begin(),std::plus{});
  90. std::transform(leftout.cbegin(), leftout.cend(), rightout.cbegin(), side.begin(),std::minus{});
  91. std::fill_n(leftout.begin(), leftout.size(), 0.0f);
  92. std::fill_n(rightout.begin(), rightout.size(), 0.0f);
  93. /* Decode the B-Format input to OutBuffer. */
  94. process(OutBuffer, InSamples, SamplesToDo);
  95. /* Include the decoded side signal with the direct side signal. */
  96. for(size_t i{0};i < SamplesToDo;++i)
  97. side[i] += leftout[i] - rightout[i];
  98. /* Get the decoded mid signal and band-split it. */
  99. const auto tmpsamples = al::span{mStablizer->Temp}.first(SamplesToDo);
  100. std::transform(leftout.cbegin(), leftout.cend(), rightout.cbegin(), tmpsamples.begin(),
  101. std::plus{});
  102. mStablizer->MidFilter.process(tmpsamples, mStablizer->MidHF, mStablizer->MidLF);
  103. /* Apply an all-pass to all channels to match the band-splitter's phase
  104. * shift. This is to keep the phase synchronized between the existing
  105. * signal and the split mid signal.
  106. */
  107. const size_t NumChannels{OutBuffer.size()};
  108. for(size_t i{0u};i < NumChannels;i++)
  109. {
  110. /* Skip the left and right channels, which are going to get overwritten,
  111. * and substitute the direct mid signal and direct+decoded side signal.
  112. */
  113. if(i == lidx)
  114. mStablizer->ChannelFilters[i].processAllPass(mid);
  115. else if(i == ridx)
  116. mStablizer->ChannelFilters[i].processAllPass(side);
  117. else
  118. mStablizer->ChannelFilters[i].processAllPass({OutBuffer[i].data(), SamplesToDo});
  119. }
  120. /* This pans the separate low- and high-frequency signals between being on
  121. * the center channel and the left+right channels. The low-frequency signal
  122. * is panned 1/3rd toward center and the high-frequency signal is panned
  123. * 1/4th toward center. These values can be tweaked.
  124. */
  125. const float cos_lf{std::cos(1.0f/3.0f * (al::numbers::pi_v<float>*0.5f))};
  126. const float cos_hf{std::cos(1.0f/4.0f * (al::numbers::pi_v<float>*0.5f))};
  127. const float sin_lf{std::sin(1.0f/3.0f * (al::numbers::pi_v<float>*0.5f))};
  128. const float sin_hf{std::sin(1.0f/4.0f * (al::numbers::pi_v<float>*0.5f))};
  129. const auto centerout = al::span<float>{OutBuffer[cidx]}.first(SamplesToDo);
  130. for(size_t i{0};i < SamplesToDo;i++)
  131. {
  132. /* Add the direct mid signal to the processed mid signal so it can be
  133. * properly combined with the direct+decoded side signal.
  134. */
  135. const float m{mStablizer->MidLF[i]*cos_lf + mStablizer->MidHF[i]*cos_hf + mid[i]};
  136. const float c{mStablizer->MidLF[i]*sin_lf + mStablizer->MidHF[i]*sin_hf};
  137. const float s{side[i]};
  138. /* The generated center channel signal adds to the existing signal,
  139. * while the modified left and right channels replace.
  140. */
  141. leftout[i] = (m + s) * 0.5f;
  142. rightout[i] = (m - s) * 0.5f;
  143. centerout[i] += c * 0.5f;
  144. }
  145. }
  146. std::unique_ptr<BFormatDec> BFormatDec::Create(const size_t inchans,
  147. const al::span<const ChannelDec> coeffs, const al::span<const ChannelDec> coeffslf,
  148. const float xover_f0norm, std::unique_ptr<FrontStablizer> stablizer)
  149. {
  150. return std::make_unique<BFormatDec>(inchans, coeffs, coeffslf, xover_f0norm,
  151. std::move(stablizer));
  152. }