aboutsummaryrefslogtreecommitdiffstats
path: root/alc/hrtf.h
diff options
context:
space:
mode:
Diffstat (limited to 'alc/hrtf.h')
-rw-r--r--alc/hrtf.h124
1 files changed, 124 insertions, 0 deletions
diff --git a/alc/hrtf.h b/alc/hrtf.h
new file mode 100644
index 00000000..6c41cb82
--- /dev/null
+++ b/alc/hrtf.h
@@ -0,0 +1,124 @@
+#ifndef ALC_HRTF_H
+#define ALC_HRTF_H
+
+#include <array>
+#include <cstddef>
+#include <memory>
+#include <string>
+
+#include "AL/al.h"
+
+#include "almalloc.h"
+#include "ambidefs.h"
+#include "atomic.h"
+#include "vector.h"
+
+
+struct HrtfHandle;
+
+#define HRTF_HISTORY_BITS (6)
+#define HRTF_HISTORY_LENGTH (1<<HRTF_HISTORY_BITS)
+#define HRTF_HISTORY_MASK (HRTF_HISTORY_LENGTH-1)
+
+#define HRIR_BITS (7)
+#define HRIR_LENGTH (1<<HRIR_BITS)
+#define HRIR_MASK (HRIR_LENGTH-1)
+
+
+struct HrtfEntry {
+ RefCount ref;
+
+ ALuint sampleRate;
+ ALsizei irSize;
+
+ struct Field {
+ ALfloat distance;
+ ALubyte evCount;
+ };
+ /* NOTE: Fields are stored *backwards*. field[0] is the farthest field, and
+ * field[fdCount-1] is the nearest.
+ */
+ ALsizei fdCount;
+ const Field *field;
+
+ struct Elevation {
+ ALushort azCount;
+ ALushort irOffset;
+ };
+ Elevation *elev;
+ const ALfloat (*coeffs)[2];
+ const ALubyte (*delays)[2];
+
+ void IncRef();
+ void DecRef();
+
+ DEF_PLACE_NEWDEL()
+};
+
+struct EnumeratedHrtf {
+ std::string name;
+
+ HrtfHandle *hrtf;
+};
+
+
+using float2 = std::array<float,2>;
+
+template<typename T>
+using HrirArray = std::array<std::array<T,2>,HRIR_LENGTH>;
+
+struct HrtfState {
+ alignas(16) std::array<ALfloat,HRTF_HISTORY_LENGTH> History;
+ alignas(16) HrirArray<ALfloat> Values;
+};
+
+struct HrtfFilter {
+ alignas(16) HrirArray<ALfloat> Coeffs;
+ ALsizei Delay[2];
+ ALfloat Gain;
+};
+
+struct DirectHrtfState {
+ /* HRTF filter state for dry buffer content */
+ ALsizei IrSize{0};
+ struct ChanData {
+ alignas(16) HrirArray<ALfloat> Values;
+ alignas(16) HrirArray<ALfloat> Coeffs;
+ };
+ al::FlexArray<ChanData> Chan;
+
+ DirectHrtfState(size_t numchans) : Chan{numchans} { }
+ DirectHrtfState(const DirectHrtfState&) = delete;
+ DirectHrtfState& operator=(const DirectHrtfState&) = delete;
+
+ static std::unique_ptr<DirectHrtfState> Create(size_t num_chans);
+ static constexpr size_t Sizeof(size_t numchans) noexcept
+ { return al::FlexArray<ChanData>::Sizeof(numchans, offsetof(DirectHrtfState, Chan)); }
+
+ DEF_PLACE_NEWDEL()
+};
+
+struct AngularPoint {
+ ALfloat Elev;
+ ALfloat Azim;
+};
+
+
+al::vector<EnumeratedHrtf> EnumerateHrtf(const char *devname);
+HrtfEntry *GetLoadedHrtf(HrtfHandle *handle);
+
+void GetHrtfCoeffs(const HrtfEntry *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat distance,
+ ALfloat spread, HrirArray<ALfloat> &coeffs, ALsizei (&delays)[2]);
+
+/**
+ * Produces HRTF filter coefficients for decoding B-Format, given a set of
+ * virtual speaker positions, a matching decoding matrix, and per-order high-
+ * frequency gains for the decoder. The calculated impulse responses are
+ * ordered and scaled according to the matrix input. Note the specified virtual
+ * positions should be in degrees, not radians!
+ */
+void BuildBFormatHrtf(const HrtfEntry *Hrtf, DirectHrtfState *state, const ALuint NumChannels,
+ const AngularPoint *AmbiPoints, const ALfloat (*RESTRICT AmbiMatrix)[MAX_AMBI_CHANNELS],
+ const size_t AmbiCount, const ALfloat *RESTRICT AmbiOrderHFGain);
+
+#endif /* ALC_HRTF_H */