makemhr.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #ifndef MAKEMHR_H
  2. #define MAKEMHR_H
  3. #include <algorithm>
  4. #include <array>
  5. #include <complex>
  6. #include <vector>
  7. #include "alcomplex.h"
  8. #include "alspan.h"
  9. #include "polyphase_resampler.h"
  10. // The maximum path length used when processing filenames.
  11. inline constexpr auto MAX_PATH_LEN = 256u;
  12. // The limit to the number of 'distances' listed in the data set definition.
  13. // Must be less than 256
  14. inline constexpr auto MAX_FD_COUNT = 16u;
  15. // The limits to the number of 'elevations' listed in the data set definition.
  16. // Must be less than 256.
  17. inline constexpr auto MIN_EV_COUNT = 5u;
  18. inline constexpr auto MAX_EV_COUNT = 181u;
  19. // The limits for each of the 'azimuths' listed in the data set definition.
  20. // Must be less than 256.
  21. inline constexpr auto MIN_AZ_COUNT = 1u;
  22. inline constexpr auto MAX_AZ_COUNT = 255u;
  23. // The limits for the 'distance' from source to listener for each field in
  24. // the definition file.
  25. inline constexpr auto MIN_DISTANCE = 0.05;
  26. inline constexpr auto MAX_DISTANCE = 2.50;
  27. // The limits for the sample 'rate' metric in the data set definition and for
  28. // resampling.
  29. inline constexpr auto MIN_RATE = 32000u;
  30. inline constexpr auto MAX_RATE = 96000u;
  31. // The limits for the HRIR 'points' metric in the data set definition.
  32. inline constexpr auto MIN_POINTS = 16u;
  33. inline constexpr auto MAX_POINTS = 8192u;
  34. using uint = unsigned int;
  35. /* Complex double type. */
  36. using complex_d = std::complex<double>;
  37. enum ChannelModeT : bool {
  38. CM_AllowStereo = false,
  39. CM_ForceMono = true
  40. };
  41. // Sample and channel type enum values.
  42. enum SampleTypeT {
  43. ST_S16 = 0,
  44. ST_S24 = 1
  45. };
  46. // Certain iterations rely on these integer enum values.
  47. enum ChannelTypeT {
  48. CT_NONE = -1,
  49. CT_MONO = 0,
  50. CT_STEREO = 1
  51. };
  52. // Structured HRIR storage for stereo azimuth pairs, elevations, and fields.
  53. struct HrirAzT {
  54. double mAzimuth{0.0};
  55. uint mIndex{0u};
  56. std::array<double,2> mDelays{};
  57. std::array<al::span<double>,2> mIrs{};
  58. };
  59. struct HrirEvT {
  60. double mElevation{0.0};
  61. al::span<HrirAzT> mAzs;
  62. };
  63. struct HrirFdT {
  64. double mDistance{0.0};
  65. uint mEvStart{0u};
  66. al::span<HrirEvT> mEvs;
  67. };
  68. // The HRIR metrics and data set used when loading, processing, and storing
  69. // the resulting HRTF.
  70. struct HrirDataT {
  71. uint mIrRate{0u};
  72. SampleTypeT mSampleType{ST_S24};
  73. ChannelTypeT mChannelType{CT_NONE};
  74. uint mIrPoints{0u};
  75. uint mFftSize{0u};
  76. uint mIrSize{0u};
  77. double mRadius{0.0};
  78. uint mIrCount{0u};
  79. std::vector<double> mHrirsBase;
  80. std::vector<HrirEvT> mEvsBase;
  81. std::vector<HrirAzT> mAzsBase;
  82. std::vector<HrirFdT> mFds;
  83. /* GCC warns when it tries to inline this. */
  84. ~HrirDataT();
  85. };
  86. bool PrepareHrirData(const al::span<const double> distances,
  87. const al::span<const uint,MAX_FD_COUNT> evCounts,
  88. const al::span<const std::array<uint,MAX_EV_COUNT>,MAX_FD_COUNT> azCounts, HrirDataT *hData);
  89. /* Calculate the magnitude response of the given input. This is used in
  90. * place of phase decomposition, since the phase residuals are discarded for
  91. * minimum phase reconstruction. The mirrored half of the response is also
  92. * discarded.
  93. */
  94. inline void MagnitudeResponse(const al::span<const complex_d> in, const al::span<double> out)
  95. {
  96. static constexpr double Epsilon{1e-9};
  97. for(size_t i{0};i < out.size();++i)
  98. out[i] = std::max(std::abs(in[i]), Epsilon);
  99. }
  100. // Performs a forward FFT.
  101. inline void FftForward(const uint n, complex_d *inout)
  102. { forward_fft(al::span{inout, n}); }
  103. // Performs an inverse FFT, scaling the result by the number of elements.
  104. inline void FftInverse(const uint n, complex_d *inout)
  105. {
  106. const auto values = al::span{inout, n};
  107. inverse_fft(values);
  108. const double f{1.0 / n};
  109. std::for_each(values.begin(), values.end(), [f](complex_d &value) { value *= f; });
  110. }
  111. // Performs linear interpolation.
  112. inline double Lerp(const double a, const double b, const double f)
  113. { return a + f * (b - a); }
  114. #endif /* MAKEMHR_H */