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