🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

192 lines
7.4 KiB

  1. #include "config.h"
  2. #include "bformatdec.h"
  3. #include <algorithm>
  4. #include <array>
  5. #include <cmath>
  6. #include <utility>
  7. #include "almalloc.h"
  8. #include "alnumbers.h"
  9. #include "filters/splitter.h"
  10. #include "front_stablizer.h"
  11. #include "mixer.h"
  12. #include "opthelpers.h"
  13. BFormatDec::BFormatDec(const size_t inchans, const al::span<const ChannelDec> coeffs,
  14. const al::span<const ChannelDec> coeffslf, const float xover_f0norm,
  15. std::unique_ptr<FrontStablizer> stablizer)
  16. : mStablizer{std::move(stablizer)}, mDualBand{!coeffslf.empty()}, mChannelDec{inchans}
  17. {
  18. if(!mDualBand)
  19. {
  20. for(size_t j{0};j < mChannelDec.size();++j)
  21. {
  22. float *outcoeffs{mChannelDec[j].mGains.Single};
  23. for(const ChannelDec &incoeffs : coeffs)
  24. *(outcoeffs++) = incoeffs[j];
  25. }
  26. }
  27. else
  28. {
  29. mChannelDec[0].mXOver.init(xover_f0norm);
  30. for(size_t j{1};j < mChannelDec.size();++j)
  31. mChannelDec[j].mXOver = mChannelDec[0].mXOver;
  32. for(size_t j{0};j < mChannelDec.size();++j)
  33. {
  34. float *outcoeffs{mChannelDec[j].mGains.Dual[sHFBand]};
  35. for(const ChannelDec &incoeffs : coeffs)
  36. *(outcoeffs++) = incoeffs[j];
  37. outcoeffs = mChannelDec[j].mGains.Dual[sLFBand];
  38. for(const ChannelDec &incoeffs : coeffslf)
  39. *(outcoeffs++) = incoeffs[j];
  40. }
  41. }
  42. }
  43. void BFormatDec::process(const al::span<FloatBufferLine> OutBuffer,
  44. const FloatBufferLine *InSamples, const size_t SamplesToDo)
  45. {
  46. ASSUME(SamplesToDo > 0);
  47. if(mDualBand)
  48. {
  49. const al::span<float> hfSamples{mSamples[sHFBand].data(), SamplesToDo};
  50. const al::span<float> lfSamples{mSamples[sLFBand].data(), SamplesToDo};
  51. for(auto &chandec : mChannelDec)
  52. {
  53. chandec.mXOver.process({InSamples->data(), SamplesToDo}, hfSamples.data(),
  54. lfSamples.data());
  55. MixSamples(hfSamples, OutBuffer, chandec.mGains.Dual[sHFBand],
  56. chandec.mGains.Dual[sHFBand], 0, 0);
  57. MixSamples(lfSamples, OutBuffer, chandec.mGains.Dual[sLFBand],
  58. chandec.mGains.Dual[sLFBand], 0, 0);
  59. ++InSamples;
  60. }
  61. }
  62. else
  63. {
  64. for(auto &chandec : mChannelDec)
  65. {
  66. MixSamples({InSamples->data(), SamplesToDo}, OutBuffer, chandec.mGains.Single,
  67. chandec.mGains.Single, 0, 0);
  68. ++InSamples;
  69. }
  70. }
  71. }
  72. void BFormatDec::processStablize(const al::span<FloatBufferLine> OutBuffer,
  73. const FloatBufferLine *InSamples, const size_t lidx, const size_t ridx, const size_t cidx,
  74. const size_t SamplesToDo)
  75. {
  76. ASSUME(SamplesToDo > 0);
  77. /* Move the existing direct L/R signal out so it doesn't get processed by
  78. * the stablizer. Add a delay to it so it stays aligned with the stablizer
  79. * delay.
  80. */
  81. float *RESTRICT mid{al::assume_aligned<16>(mStablizer->MidDirect.data())};
  82. float *RESTRICT side{al::assume_aligned<16>(mStablizer->Side.data())};
  83. for(size_t i{0};i < SamplesToDo;++i)
  84. {
  85. mid[FrontStablizer::DelayLength+i] = OutBuffer[lidx][i] + OutBuffer[ridx][i];
  86. side[FrontStablizer::DelayLength+i] = OutBuffer[lidx][i] - OutBuffer[ridx][i];
  87. }
  88. std::fill_n(OutBuffer[lidx].begin(), SamplesToDo, 0.0f);
  89. std::fill_n(OutBuffer[ridx].begin(), SamplesToDo, 0.0f);
  90. /* Decode the B-Format input to OutBuffer. */
  91. process(OutBuffer, InSamples, SamplesToDo);
  92. /* Apply a delay to all channels, except the front-left and front-right, so
  93. * they maintain correct timing.
  94. */
  95. const size_t NumChannels{OutBuffer.size()};
  96. for(size_t i{0u};i < NumChannels;i++)
  97. {
  98. if(i == lidx || i == ridx)
  99. continue;
  100. auto &DelayBuf = mStablizer->DelayBuf[i];
  101. auto buffer_end = OutBuffer[i].begin() + SamplesToDo;
  102. if LIKELY(SamplesToDo >= FrontStablizer::DelayLength)
  103. {
  104. auto delay_end = std::rotate(OutBuffer[i].begin(),
  105. buffer_end - FrontStablizer::DelayLength, buffer_end);
  106. std::swap_ranges(OutBuffer[i].begin(), delay_end, DelayBuf.begin());
  107. }
  108. else
  109. {
  110. auto delay_start = std::swap_ranges(OutBuffer[i].begin(), buffer_end,
  111. DelayBuf.begin());
  112. std::rotate(DelayBuf.begin(), delay_start, DelayBuf.end());
  113. }
  114. }
  115. /* Include the side signal for what was just decoded. */
  116. for(size_t i{0};i < SamplesToDo;++i)
  117. side[FrontStablizer::DelayLength+i] += OutBuffer[lidx][i] - OutBuffer[ridx][i];
  118. /* Combine the delayed mid signal with the decoded mid signal. */
  119. float *tmpbuf{mStablizer->TempBuf.data()};
  120. auto tmpiter = std::copy(mStablizer->MidDelay.cbegin(), mStablizer->MidDelay.cend(), tmpbuf);
  121. for(size_t i{0};i < SamplesToDo;++i,++tmpiter)
  122. *tmpiter = OutBuffer[lidx][i] + OutBuffer[ridx][i];
  123. /* Save the newest samples for next time. */
  124. std::copy_n(tmpbuf+SamplesToDo, mStablizer->MidDelay.size(), mStablizer->MidDelay.begin());
  125. /* Apply an all-pass on the signal in reverse. The future samples are
  126. * included with the all-pass to reduce the error in the output samples
  127. * (the smaller the delay, the more error is introduced).
  128. */
  129. mStablizer->MidFilter.applyAllpassRev({tmpbuf, SamplesToDo+FrontStablizer::DelayLength});
  130. /* Now apply the band-splitter, combining its phase shift with the reversed
  131. * phase shift, restoring the original phase on the split signal.
  132. */
  133. mStablizer->MidFilter.process({tmpbuf, SamplesToDo}, mStablizer->MidHF.data(),
  134. mStablizer->MidLF.data());
  135. /* This pans the separate low- and high-frequency signals between being on
  136. * the center channel and the left+right channels. The low-frequency signal
  137. * is panned 1/3rd toward center and the high-frequency signal is panned
  138. * 1/4th toward center. These values can be tweaked.
  139. */
  140. const float cos_lf{std::cos(1.0f/3.0f * (al::numbers::pi_v<float>*0.5f))};
  141. const float cos_hf{std::cos(1.0f/4.0f * (al::numbers::pi_v<float>*0.5f))};
  142. const float sin_lf{std::sin(1.0f/3.0f * (al::numbers::pi_v<float>*0.5f))};
  143. const float sin_hf{std::sin(1.0f/4.0f * (al::numbers::pi_v<float>*0.5f))};
  144. for(size_t i{0};i < SamplesToDo;i++)
  145. {
  146. const float m{mStablizer->MidLF[i]*cos_lf + mStablizer->MidHF[i]*cos_hf + mid[i]};
  147. const float c{mStablizer->MidLF[i]*sin_lf + mStablizer->MidHF[i]*sin_hf};
  148. const float s{side[i]};
  149. /* The generated center channel signal adds to the existing signal,
  150. * while the modified left and right channels replace.
  151. */
  152. OutBuffer[lidx][i] = (m + s) * 0.5f;
  153. OutBuffer[ridx][i] = (m - s) * 0.5f;
  154. OutBuffer[cidx][i] += c * 0.5f;
  155. }
  156. /* Move the delayed mid/side samples to the front for next time. */
  157. auto mid_end = mStablizer->MidDirect.cbegin() + SamplesToDo;
  158. std::copy(mid_end, mid_end+FrontStablizer::DelayLength, mStablizer->MidDirect.begin());
  159. auto side_end = mStablizer->Side.cbegin() + SamplesToDo;
  160. std::copy(side_end, side_end+FrontStablizer::DelayLength, mStablizer->Side.begin());
  161. }
  162. std::unique_ptr<BFormatDec> BFormatDec::Create(const size_t inchans,
  163. const al::span<const ChannelDec> coeffs, const al::span<const ChannelDec> coeffslf,
  164. const float xover_f0norm, std::unique_ptr<FrontStablizer> stablizer)
  165. {
  166. return std::make_unique<BFormatDec>(inchans, coeffs, coeffslf, xover_f0norm,
  167. std::move(stablizer));
  168. }