dedicated.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /**
  2. * OpenAL cross platform audio library
  3. * Copyright (C) 2011 by Chris Robinson.
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Library General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Library General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Library General Public
  15. * License along with this library; if not, write to the
  16. * Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. * Or go to http://www.gnu.org/copyleft/lgpl.html
  19. */
  20. #include "config.h"
  21. #include <algorithm>
  22. #include <array>
  23. #include <cstdlib>
  24. #include <variant>
  25. #include "alc/effects/base.h"
  26. #include "alspan.h"
  27. #include "core/bufferline.h"
  28. #include "core/devformat.h"
  29. #include "core/device.h"
  30. #include "core/effects/base.h"
  31. #include "core/effectslot.h"
  32. #include "core/mixer.h"
  33. #include "intrusive_ptr.h"
  34. struct BufferStorage;
  35. struct ContextBase;
  36. namespace {
  37. using uint = unsigned int;
  38. struct DedicatedState final : public EffectState {
  39. /* The "dedicated" effect can output to the real output, so should have
  40. * gains for all possible output channels and not just the main ambisonic
  41. * buffer.
  42. */
  43. std::array<float,MaxOutputChannels> mCurrentGains{};
  44. std::array<float,MaxOutputChannels> mTargetGains{};
  45. void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) final;
  46. void update(const ContextBase *context, const EffectSlot *slot, const EffectProps *props_,
  47. const EffectTarget target) final;
  48. void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn,
  49. const al::span<FloatBufferLine> samplesOut) final;
  50. };
  51. void DedicatedState::deviceUpdate(const DeviceBase*, const BufferStorage*)
  52. {
  53. std::fill(mCurrentGains.begin(), mCurrentGains.end(), 0.0f);
  54. }
  55. void DedicatedState::update(const ContextBase*, const EffectSlot *slot,
  56. const EffectProps *props_, const EffectTarget target)
  57. {
  58. std::fill(mTargetGains.begin(), mTargetGains.end(), 0.0f);
  59. auto &props = std::get<DedicatedProps>(*props_);
  60. const float Gain{slot->Gain * props.Gain};
  61. if(props.Target == DedicatedProps::Dialog)
  62. {
  63. /* Dialog goes to the front-center speaker if it exists, otherwise it
  64. * plays from the front-center location.
  65. */
  66. const size_t idx{target.RealOut ? target.RealOut->ChannelIndex[FrontCenter]
  67. : InvalidChannelIndex};
  68. if(idx != InvalidChannelIndex)
  69. {
  70. mOutTarget = target.RealOut->Buffer;
  71. mTargetGains[idx] = Gain;
  72. }
  73. else
  74. {
  75. static constexpr auto coeffs = CalcDirectionCoeffs(std::array{0.0f, 0.0f, -1.0f});
  76. mOutTarget = target.Main->Buffer;
  77. ComputePanGains(target.Main, coeffs, Gain, mTargetGains);
  78. }
  79. }
  80. else if(props.Target == DedicatedProps::Lfe)
  81. {
  82. const size_t idx{target.RealOut ? target.RealOut->ChannelIndex[LFE] : InvalidChannelIndex};
  83. if(idx != InvalidChannelIndex)
  84. {
  85. mOutTarget = target.RealOut->Buffer;
  86. mTargetGains[idx] = Gain;
  87. }
  88. }
  89. }
  90. void DedicatedState::process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut)
  91. {
  92. MixSamples(al::span{samplesIn[0]}.first(samplesToDo), samplesOut, mCurrentGains, mTargetGains,
  93. samplesToDo, 0);
  94. }
  95. struct DedicatedStateFactory final : public EffectStateFactory {
  96. al::intrusive_ptr<EffectState> create() override
  97. { return al::intrusive_ptr<EffectState>{new DedicatedState{}}; }
  98. };
  99. } // namespace
  100. EffectStateFactory *DedicatedStateFactory_getFactory()
  101. {
  102. static DedicatedStateFactory DedicatedFactory{};
  103. return &DedicatedFactory;
  104. }