chorus.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. /**
  2. * OpenAL cross platform audio library
  3. * Copyright (C) 2013 by Mike Gorchak
  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 <cmath>
  24. #include <cstdlib>
  25. #include <limits>
  26. #include <variant>
  27. #include <vector>
  28. #include "alc/effects/base.h"
  29. #include "alnumbers.h"
  30. #include "alnumeric.h"
  31. #include "alspan.h"
  32. #include "core/ambidefs.h"
  33. #include "core/bufferline.h"
  34. #include "core/context.h"
  35. #include "core/cubic_tables.h"
  36. #include "core/device.h"
  37. #include "core/effects/base.h"
  38. #include "core/effectslot.h"
  39. #include "core/mixer.h"
  40. #include "core/mixer/defs.h"
  41. #include "core/resampler_limits.h"
  42. #include "intrusive_ptr.h"
  43. #include "opthelpers.h"
  44. struct BufferStorage;
  45. namespace {
  46. using uint = unsigned int;
  47. constexpr auto inv_sqrt2 = static_cast<float>(1.0 / al::numbers::sqrt2);
  48. constexpr auto lcoeffs_pw = CalcDirectionCoeffs(std::array{-1.0f, 0.0f, 0.0f});
  49. constexpr auto rcoeffs_pw = CalcDirectionCoeffs(std::array{ 1.0f, 0.0f, 0.0f});
  50. constexpr auto lcoeffs_nrml = CalcDirectionCoeffs(std::array{-inv_sqrt2, 0.0f, inv_sqrt2});
  51. constexpr auto rcoeffs_nrml = CalcDirectionCoeffs(std::array{ inv_sqrt2, 0.0f, inv_sqrt2});
  52. struct ChorusState final : public EffectState {
  53. std::vector<float> mDelayBuffer;
  54. uint mOffset{0};
  55. uint mLfoOffset{0};
  56. uint mLfoRange{1};
  57. float mLfoScale{0.0f};
  58. uint mLfoDisp{0};
  59. /* Calculated delays to apply to the left and right outputs. */
  60. std::array<std::array<uint,BufferLineSize>,2> mModDelays{};
  61. /* Temp storage for the modulated left and right outputs. */
  62. alignas(16) std::array<FloatBufferLine,2> mBuffer{};
  63. /* Gains for left and right outputs. */
  64. struct OutGains {
  65. std::array<float,MaxAmbiChannels> Current{};
  66. std::array<float,MaxAmbiChannels> Target{};
  67. };
  68. std::array<OutGains,2> mGains;
  69. /* effect parameters */
  70. ChorusWaveform mWaveform{};
  71. int mDelay{0};
  72. float mDepth{0.0f};
  73. float mFeedback{0.0f};
  74. void calcTriangleDelays(const size_t todo);
  75. void calcSinusoidDelays(const size_t todo);
  76. void deviceUpdate(const DeviceBase *device, const float MaxDelay);
  77. void update(const ContextBase *context, const EffectSlot *slot, const ChorusWaveform waveform,
  78. const float delay, const float depth, const float feedback, const float rate,
  79. int phase, const EffectTarget target);
  80. void deviceUpdate(const DeviceBase *device, const BufferStorage*) final;
  81. void update(const ContextBase *context, const EffectSlot *slot, const EffectProps *props_,
  82. const EffectTarget target) final;
  83. void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn,
  84. const al::span<FloatBufferLine> samplesOut) final;
  85. };
  86. void ChorusState::deviceUpdate(const DeviceBase *Device, const BufferStorage*)
  87. {
  88. constexpr auto MaxDelay = std::max(ChorusMaxDelay, FlangerMaxDelay);
  89. const auto frequency = static_cast<float>(Device->Frequency);
  90. const size_t maxlen{NextPowerOf2(float2uint(MaxDelay*2.0f*frequency) + 1u)};
  91. if(maxlen != mDelayBuffer.size())
  92. decltype(mDelayBuffer)(maxlen).swap(mDelayBuffer);
  93. std::fill(mDelayBuffer.begin(), mDelayBuffer.end(), 0.0f);
  94. for(auto &e : mGains)
  95. {
  96. e.Current.fill(0.0f);
  97. e.Target.fill(0.0f);
  98. }
  99. }
  100. void ChorusState::update(const ContextBase *context, const EffectSlot *slot,
  101. const EffectProps *props_, const EffectTarget target)
  102. {
  103. static constexpr int mindelay{MaxResamplerEdge << gCubicTable.sTableBits};
  104. auto &props = std::get<ChorusProps>(*props_);
  105. /* The LFO depth is scaled to be relative to the sample delay. Clamp the
  106. * delay and depth to allow enough padding for resampling.
  107. */
  108. const DeviceBase *device{context->mDevice};
  109. const auto frequency = static_cast<float>(device->Frequency);
  110. mWaveform = props.Waveform;
  111. const auto stepscale = float{frequency * gCubicTable.sTableSteps};
  112. mDelay = std::max(float2int(std::round(props.Delay * stepscale)), mindelay);
  113. mDepth = std::min(static_cast<float>(mDelay) * props.Depth,
  114. static_cast<float>(mDelay - mindelay));
  115. mFeedback = props.Feedback;
  116. /* Gains for left and right sides */
  117. const bool ispairwise{device->mRenderMode == RenderMode::Pairwise};
  118. const auto lcoeffs = (!ispairwise) ? al::span{lcoeffs_nrml} : al::span{lcoeffs_pw};
  119. const auto rcoeffs = (!ispairwise) ? al::span{rcoeffs_nrml} : al::span{rcoeffs_pw};
  120. /* Attenuate the outputs by -3dB, since we duplicate a single mono input to
  121. * separate left/right outputs.
  122. */
  123. const auto gain = slot->Gain * (1.0f/al::numbers::sqrt2_v<float>);
  124. mOutTarget = target.Main->Buffer;
  125. ComputePanGains(target.Main, lcoeffs, gain, mGains[0].Target);
  126. ComputePanGains(target.Main, rcoeffs, gain, mGains[1].Target);
  127. if(!(props.Rate > 0.0f))
  128. {
  129. mLfoOffset = 0;
  130. mLfoRange = 1;
  131. mLfoScale = 0.0f;
  132. mLfoDisp = 0;
  133. }
  134. else
  135. {
  136. /* Calculate LFO coefficient (number of samples per cycle). Limit the
  137. * max range to avoid overflow when calculating the displacement.
  138. */
  139. static constexpr int range_limit{std::numeric_limits<int>::max()/360 - 180};
  140. const auto range = std::round(frequency / props.Rate);
  141. const uint lfo_range{float2uint(std::min(range, float{range_limit}))};
  142. mLfoOffset = mLfoOffset * lfo_range / mLfoRange;
  143. mLfoRange = lfo_range;
  144. switch(mWaveform)
  145. {
  146. case ChorusWaveform::Triangle:
  147. mLfoScale = 4.0f / static_cast<float>(mLfoRange);
  148. break;
  149. case ChorusWaveform::Sinusoid:
  150. mLfoScale = al::numbers::pi_v<float>*2.0f / static_cast<float>(mLfoRange);
  151. break;
  152. }
  153. /* Calculate lfo phase displacement */
  154. auto phase = props.Phase;
  155. if(phase < 0) phase += 360;
  156. mLfoDisp = (mLfoRange*static_cast<uint>(phase) + 180) / 360;
  157. }
  158. }
  159. void ChorusState::calcTriangleDelays(const size_t todo)
  160. {
  161. const uint lfo_range{mLfoRange};
  162. const float lfo_scale{mLfoScale};
  163. const float depth{mDepth};
  164. const int delay{mDelay};
  165. auto gen_lfo = [lfo_scale,depth,delay](const uint offset) -> uint
  166. {
  167. const float offset_norm{static_cast<float>(offset) * lfo_scale};
  168. return static_cast<uint>(fastf2i((1.0f-std::abs(2.0f-offset_norm)) * depth) + delay);
  169. };
  170. uint offset{mLfoOffset};
  171. ASSUME(lfo_range > offset);
  172. auto ldelays = mModDelays[0].begin();
  173. for(size_t i{0};i < todo;)
  174. {
  175. const size_t rem{std::min(todo-i, size_t{lfo_range-offset})};
  176. ldelays = std::generate_n(ldelays, rem, [&offset,gen_lfo] { return gen_lfo(offset++); });
  177. if(offset == lfo_range) offset = 0;
  178. i += rem;
  179. }
  180. offset = (mLfoOffset+mLfoDisp) % lfo_range;
  181. auto rdelays = mModDelays[1].begin();
  182. for(size_t i{0};i < todo;)
  183. {
  184. const size_t rem{std::min(todo-i, size_t{lfo_range-offset})};
  185. rdelays = std::generate_n(rdelays, rem, [&offset,gen_lfo] { return gen_lfo(offset++); });
  186. if(offset == lfo_range) offset = 0;
  187. i += rem;
  188. }
  189. mLfoOffset = static_cast<uint>(mLfoOffset+todo) % lfo_range;
  190. }
  191. void ChorusState::calcSinusoidDelays(const size_t todo)
  192. {
  193. const uint lfo_range{mLfoRange};
  194. const float lfo_scale{mLfoScale};
  195. const float depth{mDepth};
  196. const int delay{mDelay};
  197. auto gen_lfo = [lfo_scale,depth,delay](const uint offset) -> uint
  198. {
  199. const float offset_norm{static_cast<float>(offset) * lfo_scale};
  200. return static_cast<uint>(fastf2i(std::sin(offset_norm)*depth) + delay);
  201. };
  202. uint offset{mLfoOffset};
  203. ASSUME(lfo_range > offset);
  204. auto ldelays = mModDelays[0].begin();
  205. for(size_t i{0};i < todo;)
  206. {
  207. const size_t rem{std::min(todo-i, size_t{lfo_range-offset})};
  208. ldelays = std::generate_n(ldelays, rem, [&offset,gen_lfo] { return gen_lfo(offset++); });
  209. if(offset == lfo_range) offset = 0;
  210. i += rem;
  211. }
  212. offset = (mLfoOffset+mLfoDisp) % lfo_range;
  213. auto rdelays = mModDelays[1].begin();
  214. for(size_t i{0};i < todo;)
  215. {
  216. const size_t rem{std::min(todo-i, size_t{lfo_range-offset})};
  217. rdelays = std::generate_n(rdelays, rem, [&offset,gen_lfo] { return gen_lfo(offset++); });
  218. if(offset == lfo_range) offset = 0;
  219. i += rem;
  220. }
  221. mLfoOffset = static_cast<uint>(mLfoOffset+todo) % lfo_range;
  222. }
  223. void ChorusState::process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut)
  224. {
  225. const auto delaybuf = al::span{mDelayBuffer};
  226. const size_t bufmask{delaybuf.size()-1};
  227. const float feedback{mFeedback};
  228. const uint avgdelay{(static_cast<uint>(mDelay) + MixerFracHalf) >> MixerFracBits};
  229. uint offset{mOffset};
  230. if(mWaveform == ChorusWaveform::Sinusoid)
  231. calcSinusoidDelays(samplesToDo);
  232. else /*if(mWaveform == ChorusWaveform::Triangle)*/
  233. calcTriangleDelays(samplesToDo);
  234. const auto ldelays = al::span{mModDelays[0]};
  235. const auto rdelays = al::span{mModDelays[1]};
  236. const auto lbuffer = al::span{mBuffer[0]};
  237. const auto rbuffer = al::span{mBuffer[1]};
  238. for(size_t i{0u};i < samplesToDo;++i)
  239. {
  240. // Feed the buffer's input first (necessary for delays < 1).
  241. delaybuf[offset&bufmask] = samplesIn[0][i];
  242. // Tap for the left output.
  243. size_t delay{offset - (ldelays[i] >> gCubicTable.sTableBits)};
  244. size_t phase{ldelays[i] & gCubicTable.sTableMask};
  245. lbuffer[i] = delaybuf[(delay+1) & bufmask]*gCubicTable.getCoeff0(phase) +
  246. delaybuf[(delay ) & bufmask]*gCubicTable.getCoeff1(phase) +
  247. delaybuf[(delay-1) & bufmask]*gCubicTable.getCoeff2(phase) +
  248. delaybuf[(delay-2) & bufmask]*gCubicTable.getCoeff3(phase);
  249. // Tap for the right output.
  250. delay = offset - (rdelays[i] >> gCubicTable.sTableBits);
  251. phase = rdelays[i] & gCubicTable.sTableMask;
  252. rbuffer[i] = delaybuf[(delay+1) & bufmask]*gCubicTable.getCoeff0(phase) +
  253. delaybuf[(delay ) & bufmask]*gCubicTable.getCoeff1(phase) +
  254. delaybuf[(delay-1) & bufmask]*gCubicTable.getCoeff2(phase) +
  255. delaybuf[(delay-2) & bufmask]*gCubicTable.getCoeff3(phase);
  256. // Accumulate feedback from the average delay of the taps.
  257. delaybuf[offset&bufmask] += delaybuf[(offset-avgdelay) & bufmask] * feedback;
  258. ++offset;
  259. }
  260. MixSamples(lbuffer.first(samplesToDo), samplesOut, mGains[0].Current, mGains[0].Target,
  261. samplesToDo, 0);
  262. MixSamples(rbuffer.first(samplesToDo), samplesOut, mGains[1].Current, mGains[1].Target,
  263. samplesToDo, 0);
  264. mOffset = offset;
  265. }
  266. struct ChorusStateFactory final : public EffectStateFactory {
  267. al::intrusive_ptr<EffectState> create() override
  268. { return al::intrusive_ptr<EffectState>{new ChorusState{}}; }
  269. };
  270. } // namespace
  271. EffectStateFactory *ChorusStateFactory_getFactory()
  272. {
  273. static ChorusStateFactory ChorusFactory{};
  274. return &ChorusFactory;
  275. }