Overte C++ Documentation
AudioHRTF.h
1 //
2 // AudioHRTF.h
3 // libraries/audio/src
4 //
5 // Created by Ken Cooke on 1/17/16.
6 // Copyright 2016 High Fidelity, Inc.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 
12 #ifndef hifi_AudioHRTF_h
13 #define hifi_AudioHRTF_h
14 
15 #include <stdint.h>
16 #include <string.h>
17 #include <algorithm>
18 
19 #include "AudioHelpers.h"
20 
21 static const int HRTF_AZIMUTHS = 72; // 360 / 5-degree steps
22 static const int HRTF_TAPS = 64; // minimum-phase FIR coefficients
23 static const int HRTF_TABLES = 25; // number of HRTF subjects
24 
25 static const int HRTF_DELAY = 24; // max ITD in samples (1.0ms at 24KHz)
26 static const int HRTF_BLOCK = 240; // block processing size
27 
28 static const float HRTF_GAIN = 1.0f; // HRTF global gain adjustment
29 
30 // Near-field HRTF
31 static const float HRTF_AZIMUTH_REF = 2.0f; // IRCAM Listen HRTF was recorded at 2 meters
32 static const float HRTF_NEARFIELD_MAX = 1.0f; // distance in meters
33 static const float HRTF_NEARFIELD_MIN = 0.125f; // distance in meters
34 static const float HRTF_HEAD_RADIUS = 0.0875f; // average human head in meters
35 
36 // Distance attenuation
37 static const float ATTN_DISTANCE_REF = 2.0f; // distance where attn is 0dB
38 static const float ATTN_GAIN_MAX = 16.0f; // max gain allowed by distance attn (+24dB)
39 
40 // Distance filter
41 static const float LPF_DISTANCE_REF = 256.0f; // approximation of sound propogation in air
42 
43 class AudioHRTF {
44 
45 public:
46  AudioHRTF() {};
47 
48  //
49  // input: mono source
50  // output: interleaved stereo mix buffer (accumulates into existing output)
51  // index: HRTF subject index
52  // azimuth: clockwise panning angle in radians
53  // distance: source distance in meters
54  // gain: gain factor for distance attenuation
55  // numFrames: must be HRTF_BLOCK in this version
56  // lpfDistance: distance filter adjustment (distance to 1kHz lowpass in meters)
57  //
58  void render(int16_t* input, float* output, int index, float azimuth, float distance, float gain, int numFrames,
59  float lpfDistance = LPF_DISTANCE_REF);
60 
61  //
62  // Non-spatialized direct mix (accumulates into existing output)
63  //
64  void mixMono(int16_t* input, float* output, float gain, int numFrames);
65  void mixStereo(int16_t* input, float* output, float gain, int numFrames);
66 
67  //
68  // Fast path when input is known to be silent and state as been flushed
69  //
70  void setParameterHistory(float azimuth, float distance, float gain, float lpfDistance = LPF_DISTANCE_REF) {
71  // new parameters become old
72  _azimuthState = azimuth;
73  _distanceState = distance;
74  _gainState = gain;
75 
76  _lpfState = 0.5f * fastLog2f(std::max(distance, 1.0f)) / fastLog2f(std::max(lpfDistance, 2.0f));
77  _lpfState = std::min(std::max(_lpfState, 0.0f), 1.0f);
78  }
79 
80  //
81  // HRTF local gain adjustment in amplitude (1.0 == unity)
82  //
83  void setGainAdjustment(float gain) { _gainAdjust = HRTF_GAIN * gain; };
84  float getGainAdjustment() { return _gainAdjust; }
85 
86  // clear internal state, but retain settings
87  void reset() {
88  if (!_resetState) {
89  // FIR history
90  memset(_firState, 0, sizeof(_firState));
91 
92  // integer delay history
93  memset(_delayState, 0, sizeof(_delayState));
94 
95  // biquad history
96  memset(_bqState, 0, sizeof(_bqState));
97 
98  // parameter history
99  _azimuthState = 0.0f;
100  _distanceState = 0.0f;
101  _gainState = 0.0f;
102  _lpfState = 0.0f;
103 
104  // _gainAdjust is retained
105 
106  _resetState = true;
107  }
108  }
109 
110 private:
111  AudioHRTF(const AudioHRTF&) = delete;
112  AudioHRTF& operator=(const AudioHRTF&) = delete;
113 
114  // SIMD channel assignmentS
115  enum Channel {
116  L0, R0,
117  L1, R1,
118  L2, R2,
119  L3, R3
120  };
121 
122  // For best cache utilization when processing thousands of instances, only
123  // the minimum persistant state is stored here. No coefs or work buffers.
124 
125  // FIR history
126  float _firState[HRTF_TAPS] = {};
127 
128  // integer delay history
129  float _delayState[4][HRTF_DELAY] = {};
130 
131  // biquad history
132  float _bqState[3][8] = {};
133 
134  // parameter history
135  float _azimuthState = 0.0f;
136  float _distanceState = 0.0f;
137  float _gainState = 0.0f;
138  float _lpfState = 0.0f;
139 
140  // global and local gain adjustment
141  float _gainAdjust = HRTF_GAIN;
142 
143  bool _resetState = true;
144 };
145 
146 #endif // AudioHRTF_h