🛠️🐜 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.

101 lines
3.0 KiB

  1. #ifndef CORE_MIXER_H
  2. #define CORE_MIXER_H
  3. #include <array>
  4. #include <cmath>
  5. #include <stddef.h>
  6. #include <type_traits>
  7. #include "alspan.h"
  8. #include "ambidefs.h"
  9. #include "bufferline.h"
  10. #include "devformat.h"
  11. struct MixParams;
  12. using MixerFunc = void(*)(const al::span<const float> InSamples,
  13. const al::span<FloatBufferLine> OutBuffer, float *CurrentGains, const float *TargetGains,
  14. const size_t Counter, const size_t OutPos);
  15. extern MixerFunc MixSamples;
  16. /**
  17. * Calculates ambisonic encoder coefficients using the X, Y, and Z direction
  18. * components, which must represent a normalized (unit length) vector, and the
  19. * spread is the angular width of the sound (0...tau).
  20. *
  21. * NOTE: The components use ambisonic coordinates. As a result:
  22. *
  23. * Ambisonic Y = OpenAL -X
  24. * Ambisonic Z = OpenAL Y
  25. * Ambisonic X = OpenAL -Z
  26. *
  27. * The components are ordered such that OpenAL's X, Y, and Z are the first,
  28. * second, and third parameters respectively -- simply negate X and Z.
  29. */
  30. std::array<float,MaxAmbiChannels> CalcAmbiCoeffs(const float y, const float z, const float x,
  31. const float spread);
  32. /**
  33. * CalcDirectionCoeffs
  34. *
  35. * Calculates ambisonic coefficients based on an OpenAL direction vector. The
  36. * vector must be normalized (unit length), and the spread is the angular width
  37. * of the sound (0...tau).
  38. */
  39. inline std::array<float,MaxAmbiChannels> CalcDirectionCoeffs(const float (&dir)[3],
  40. const float spread)
  41. {
  42. /* Convert from OpenAL coords to Ambisonics. */
  43. return CalcAmbiCoeffs(-dir[0], dir[1], -dir[2], spread);
  44. }
  45. /**
  46. * CalcAngleCoeffs
  47. *
  48. * Calculates ambisonic coefficients based on azimuth and elevation. The
  49. * azimuth and elevation parameters are in radians, going right and up
  50. * respectively.
  51. */
  52. inline std::array<float,MaxAmbiChannels> CalcAngleCoeffs(const float azimuth,
  53. const float elevation, const float spread)
  54. {
  55. const float x{-std::sin(azimuth) * std::cos(elevation)};
  56. const float y{ std::sin(elevation)};
  57. const float z{ std::cos(azimuth) * std::cos(elevation)};
  58. return CalcAmbiCoeffs(x, y, z, spread);
  59. }
  60. /**
  61. * ComputePanGains
  62. *
  63. * Computes panning gains using the given channel decoder coefficients and the
  64. * pre-calculated direction or angle coefficients. For B-Format sources, the
  65. * coeffs are a 'slice' of a transform matrix for the input channel, used to
  66. * scale and orient the sound samples.
  67. */
  68. void ComputePanGains(const MixParams *mix, const float*RESTRICT coeffs, const float ingain,
  69. const al::span<float,MAX_OUTPUT_CHANNELS> gains);
  70. /** Helper to set an identity/pass-through panning for ambisonic mixing (3D input). */
  71. template<typename T, typename I, typename F>
  72. auto SetAmbiPanIdentity(T iter, I count, F func) -> std::enable_if_t<std::is_integral<I>::value>
  73. {
  74. if(count < 1) return;
  75. std::array<float,MaxAmbiChannels> coeffs{{1.0f}};
  76. func(*iter, coeffs);
  77. ++iter;
  78. for(I i{1};i < count;++i,++iter)
  79. {
  80. coeffs[i-1] = 0.0f;
  81. coeffs[i ] = 1.0f;
  82. func(*iter, coeffs);
  83. }
  84. }
  85. #endif /* CORE_MIXER_H */