makemhr.h 3.8 KB

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