2 * OpenAL cross platform audio library
3 * Copyright (C) 2011 by Chris Robinson
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
28 /* External HRTF file format (LE byte order):
30 * ALchar magic[8] = "MinPHR00";
33 * ALushort hrirCount; // Required value: 828
34 * ALushort hrirSize; // Required value: 32
35 * ALubyte evCount; // Required value: 19
37 * ALushort evOffset[evCount]; // Required values:
38 * { 0, 1, 13, 37, 73, 118, 174, 234, 306, 378, 450, 522, 594, 654, 710, 755, 791, 815, 827 }
40 * ALshort coefficients[hrirCount][hrirSize];
41 * ALubyte delays[hrirCount]; // Element values must not exceed 127
44 static const ALchar magicMarker
[8] = "MinPHR00";
46 #define HRIR_COUNT 828
49 static const ALushort evOffset
[ELEV_COUNT
] = { 0, 1, 13, 37, 73, 118, 174, 234, 306, 378, 450, 522, 594, 654, 710, 755, 791, 815, 827 };
50 static const ALubyte azCount
[ELEV_COUNT
] = { 1, 12, 24, 36, 45, 56, 60, 72, 72, 72, 72, 72, 60, 56, 45, 36, 24, 12, 1 };
54 ALshort coeffs
[HRIR_COUNT
][HRIR_LENGTH
];
55 ALubyte delays
[HRIR_COUNT
];
58 #include "hrtf_tables.inc"
61 // Calculate the elevation indices given the polar elevation in radians.
62 // This will return two indices between 0 and (ELEV_COUNT-1) and an
63 // interpolation factor between 0.0 and 1.0.
64 static void CalcEvIndices(ALfloat ev
, ALuint
*evidx
, ALfloat
*evmu
)
66 ev
= (M_PI
/2.0f
+ ev
) * (ELEV_COUNT
-1) / M_PI
;
67 evidx
[0] = (ALuint
)ev
;
68 evidx
[1] = minu(evidx
[0] + 1, ELEV_COUNT
-1);
69 *evmu
= ev
- evidx
[0];
72 // Calculate the azimuth indices given the polar azimuth in radians. This
73 // will return two indices between 0 and (azCount [ei] - 1) and an
74 // interpolation factor between 0.0 and 1.0.
75 static void CalcAzIndices(ALuint evidx
, ALfloat az
, ALuint
*azidx
, ALfloat
*azmu
)
77 az
= (M_PI
*2.0f
+ az
) * azCount
[evidx
] / (M_PI
*2.0f
);
78 azidx
[0] = (ALuint
)az
% azCount
[evidx
];
79 azidx
[1] = (azidx
[0] + 1) % azCount
[evidx
];
80 *azmu
= az
- floor(az
);
83 // Calculates the normalized HRTF transition factor (delta) from the changes
84 // in gain and listener to source angle between updates. The result is a
85 // normalized delta factor than can be used to calculate moving HRIR stepping
87 ALfloat
CalcHrtfDelta(ALfloat oldGain
, ALfloat newGain
, const ALfloat olddir
[3], const ALfloat newdir
[3])
89 ALfloat gainChange
, angleChange
;
91 // Calculate the normalized dB gain change.
92 newGain
= maxf(newGain
, 0.0001f
);
93 oldGain
= maxf(oldGain
, 0.0001f
);
94 gainChange
= aluFabs(log10(newGain
/ oldGain
) / log10(0.0001f
));
96 // Calculate the normalized listener to source angle change when there is
97 // enough gain to notice it.
99 if(gainChange
> 0.0001f
|| newGain
> 0.0001f
)
101 // No angle change when the directions are equal or degenerate (when
102 // both have zero length).
103 if(newdir
[0]-olddir
[0] || newdir
[1]-olddir
[1] || newdir
[2]-olddir
[2])
104 angleChange
= aluAcos(olddir
[0]*newdir
[0] +
105 olddir
[1]*newdir
[1] +
106 olddir
[2]*newdir
[2]) / M_PI
;
110 // Use the largest of the two changes for the delta factor, and apply a
111 // significance shaping function to it.
112 return clampf(angleChange
*2.0f
, gainChange
*2.0f
, 1.0f
);
115 // Calculates static HRIR coefficients and delays for the given polar
116 // elevation and azimuth in radians. Linear interpolation is used to
117 // increase the apparent resolution of the HRIR dataset. The coefficients
118 // are also normalized and attenuated by the specified gain.
119 void GetLerpedHrtfCoeffs(const struct Hrtf
*Hrtf
, ALfloat elevation
, ALfloat azimuth
, ALfloat gain
, ALfloat (*coeffs
)[2], ALuint
*delays
)
121 ALuint evidx
[2], azidx
[2];
123 ALuint lidx
[4], ridx
[4];
126 // Claculate elevation indices and interpolation factor.
127 CalcEvIndices(elevation
, evidx
, &mu
[2]);
129 // Calculate azimuth indices and interpolation factor for the first
131 CalcAzIndices(evidx
[0], azimuth
, azidx
, &mu
[0]);
133 // Calculate the first set of linear HRIR indices for left and right
135 lidx
[0] = evOffset
[evidx
[0]] + azidx
[0];
136 lidx
[1] = evOffset
[evidx
[0]] + azidx
[1];
137 ridx
[0] = evOffset
[evidx
[0]] + ((azCount
[evidx
[0]]-azidx
[0]) % azCount
[evidx
[0]]);
138 ridx
[1] = evOffset
[evidx
[0]] + ((azCount
[evidx
[0]]-azidx
[1]) % azCount
[evidx
[0]]);
140 // Calculate azimuth indices and interpolation factor for the second
142 CalcAzIndices(evidx
[1], azimuth
, azidx
, &mu
[1]);
144 // Calculate the second set of linear HRIR indices for left and right
146 lidx
[2] = evOffset
[evidx
[1]] + azidx
[0];
147 lidx
[3] = evOffset
[evidx
[1]] + azidx
[1];
148 ridx
[2] = evOffset
[evidx
[1]] + ((azCount
[evidx
[1]]-azidx
[0]) % azCount
[evidx
[1]]);
149 ridx
[3] = evOffset
[evidx
[1]] + ((azCount
[evidx
[1]]-azidx
[1]) % azCount
[evidx
[1]]);
151 // Calculate the normalized and attenuated HRIR coefficients using linear
152 // interpolation when there is enough gain to warrant it. Zero the
153 // coefficients if gain is too low.
156 ALdouble scale
= gain
* (1.0/32767.0);
157 for(i
= 0;i
< HRIR_LENGTH
;i
++)
159 coeffs
[i
][0] = lerp(lerp(Hrtf
->coeffs
[lidx
[0]][i
], Hrtf
->coeffs
[lidx
[1]][i
], mu
[0]),
160 lerp(Hrtf
->coeffs
[lidx
[2]][i
], Hrtf
->coeffs
[lidx
[3]][i
], mu
[1]),
162 coeffs
[i
][1] = lerp(lerp(Hrtf
->coeffs
[ridx
[0]][i
], Hrtf
->coeffs
[ridx
[1]][i
], mu
[0]),
163 lerp(Hrtf
->coeffs
[ridx
[2]][i
], Hrtf
->coeffs
[ridx
[3]][i
], mu
[1]),
169 for(i
= 0;i
< HRIR_LENGTH
;i
++)
176 // Calculate the HRIR delays using linear interpolation.
177 delays
[0] = (ALuint
)(lerp(lerp(Hrtf
->delays
[lidx
[0]], Hrtf
->delays
[lidx
[1]], mu
[0]),
178 lerp(Hrtf
->delays
[lidx
[2]], Hrtf
->delays
[lidx
[3]], mu
[1]),
180 delays
[1] = (ALuint
)(lerp(lerp(Hrtf
->delays
[ridx
[0]], Hrtf
->delays
[ridx
[1]], mu
[0]),
181 lerp(Hrtf
->delays
[ridx
[2]], Hrtf
->delays
[ridx
[3]], mu
[1]),
185 // Calculates the moving HRIR target coefficients, target delays, and
186 // stepping values for the given polar elevation and azimuth in radians.
187 // Linear interpolation is used to increase the apparent resolution of the
188 // HRIR dataset. The coefficients are also normalized and attenuated by the
189 // specified gain. Stepping resolution and count is determined using the
190 // given delta factor between 0.0 and 1.0.
191 ALuint
GetMovingHrtfCoeffs(const struct Hrtf
*Hrtf
, ALfloat elevation
, ALfloat azimuth
, ALfloat gain
, ALfloat delta
, ALint counter
, ALfloat (*coeffs
)[2], ALuint
*delays
, ALfloat (*coeffStep
)[2], ALint
*delayStep
)
193 ALuint evidx
[2], azidx
[2];
194 ALuint lidx
[4], ridx
[4];
200 // Claculate elevation indices and interpolation factor.
201 CalcEvIndices(elevation
, evidx
, &mu
[2]);
203 // Calculate azimuth indices and interpolation factor for the first
205 CalcAzIndices(evidx
[0], azimuth
, azidx
, &mu
[0]);
207 // Calculate the first set of linear HRIR indices for left and right
209 lidx
[0] = evOffset
[evidx
[0]] + azidx
[0];
210 lidx
[1] = evOffset
[evidx
[0]] + azidx
[1];
211 ridx
[0] = evOffset
[evidx
[0]] + ((azCount
[evidx
[0]]-azidx
[0]) % azCount
[evidx
[0]]);
212 ridx
[1] = evOffset
[evidx
[0]] + ((azCount
[evidx
[0]]-azidx
[1]) % azCount
[evidx
[0]]);
214 // Calculate azimuth indices and interpolation factor for the second
216 CalcAzIndices(evidx
[1], azimuth
, azidx
, &mu
[1]);
218 // Calculate the second set of linear HRIR indices for left and right
220 lidx
[2] = evOffset
[evidx
[1]] + azidx
[0];
221 lidx
[3] = evOffset
[evidx
[1]] + azidx
[1];
222 ridx
[2] = evOffset
[evidx
[1]] + ((azCount
[evidx
[1]]-azidx
[0]) % azCount
[evidx
[1]]);
223 ridx
[3] = evOffset
[evidx
[1]] + ((azCount
[evidx
[1]]-azidx
[1]) % azCount
[evidx
[1]]);
225 // Calculate the stepping parameters.
226 delta
= maxf(floor(delta
*(Hrtf
->sampleRate
*0.015f
) + 0.5), 1.0f
);
229 // Calculate the normalized and attenuated target HRIR coefficients using
230 // linear interpolation when there is enough gain to warrant it. Zero
231 // the target coefficients if gain is too low. Then calculate the
232 // coefficient stepping values using the target and previous running
236 ALdouble scale
= gain
* (1.0/32767.0);
237 for(i
= 0;i
< HRIR_LENGTH
;i
++)
239 left
= coeffs
[i
][0] - (coeffStep
[i
][0] * counter
);
240 right
= coeffs
[i
][1] - (coeffStep
[i
][1] * counter
);
242 coeffs
[i
][0] = lerp(lerp(Hrtf
->coeffs
[lidx
[0]][i
], Hrtf
->coeffs
[lidx
[1]][i
], mu
[0]),
243 lerp(Hrtf
->coeffs
[lidx
[2]][i
], Hrtf
->coeffs
[lidx
[3]][i
], mu
[1]),
245 coeffs
[i
][1] = lerp(lerp(Hrtf
->coeffs
[ridx
[0]][i
], Hrtf
->coeffs
[ridx
[1]][i
], mu
[0]),
246 lerp(Hrtf
->coeffs
[ridx
[2]][i
], Hrtf
->coeffs
[ridx
[3]][i
], mu
[1]),
249 coeffStep
[i
][0] = step
* (coeffs
[i
][0] - left
);
250 coeffStep
[i
][1] = step
* (coeffs
[i
][1] - right
);
255 for(i
= 0;i
< HRIR_LENGTH
;i
++)
257 left
= coeffs
[i
][0] - (coeffStep
[i
][0] * counter
);
258 right
= coeffs
[i
][1] - (coeffStep
[i
][1] * counter
);
263 coeffStep
[i
][0] = step
* -left
;
264 coeffStep
[i
][1] = step
* -right
;
268 // Calculate the HRIR delays using linear interpolation. Then calculate
269 // the delay stepping values using the target and previous running
271 left
= delays
[0] - (delayStep
[0] * counter
);
272 right
= delays
[1] - (delayStep
[1] * counter
);
274 delays
[0] = (ALuint
)(lerp(lerp(Hrtf
->delays
[lidx
[0]], Hrtf
->delays
[lidx
[1]], mu
[0]),
275 lerp(Hrtf
->delays
[lidx
[2]], Hrtf
->delays
[lidx
[3]], mu
[1]),
277 delays
[1] = (ALuint
)(lerp(lerp(Hrtf
->delays
[ridx
[0]], Hrtf
->delays
[ridx
[1]], mu
[0]),
278 lerp(Hrtf
->delays
[ridx
[2]], Hrtf
->delays
[ridx
[3]], mu
[1]),
281 delayStep
[0] = (ALint
)(step
* (delays
[0] - left
));
282 delayStep
[1] = (ALint
)(step
* (delays
[1] - right
));
284 // The stepping count is the number of samples necessary for the HRIR to
285 // complete its transition. The mixer will only apply stepping for this
287 return (ALuint
)delta
;
290 const struct Hrtf
*GetHrtf(ALCdevice
*device
)
292 if(device
->FmtChans
== DevFmtStereo
&& device
->Frequency
== LoadedHrtf
.sampleRate
)
294 ERR("Incompatible format: %s %uhz\n",
295 DevFmtChannelsString(device
->FmtChans
), device
->Frequency
);
304 fname
= GetConfigValue(NULL
, "hrtf_tables", "");
307 f
= fopen(fname
, "rb");
309 ERR("Could not open %s\n", fname
);
313 const ALubyte maxDelay
= SRC_HISTORY_LENGTH
-1;
314 ALboolean failed
= AL_FALSE
;
319 if(fread(magic
, 1, sizeof(magicMarker
), f
) != sizeof(magicMarker
))
321 ERR("Failed to read magic marker\n");
324 else if(memcmp(magic
, magicMarker
, sizeof(magicMarker
)) != 0)
327 ERR("Invalid magic marker: \"%s\"\n", magic
);
333 ALushort hrirCount
, hrirSize
;
336 newdata
.sampleRate
= fgetc(f
);
337 newdata
.sampleRate
|= fgetc(f
)<<8;
338 newdata
.sampleRate
|= fgetc(f
)<<16;
339 newdata
.sampleRate
|= fgetc(f
)<<24;
341 hrirCount
= fgetc(f
);
342 hrirCount
|= fgetc(f
)<<8;
345 hrirSize
|= fgetc(f
)<<8;
349 if(hrirCount
!= HRIR_COUNT
|| hrirSize
!= HRIR_LENGTH
|| evCount
!= ELEV_COUNT
)
351 ERR("Unsupported value: hrirCount=%d (%d), hrirSize=%d (%d), evCount=%d (%d)\n",
352 hrirCount
, HRIR_COUNT
, hrirSize
, HRIR_LENGTH
, evCount
, ELEV_COUNT
);
359 for(i
= 0;i
< HRIR_COUNT
;i
++)
363 offset
|= fgetc(f
)<<8;
364 if(offset
!= evOffset
[i
])
366 ERR("Unsupported evOffset[%d] value: %d (%d)\n", i
, offset
, evOffset
[i
]);
374 for(i
= 0;i
< HRIR_COUNT
;i
++)
376 for(j
= 0;j
< HRIR_LENGTH
;j
++)
380 coeff
|= fgetc(f
)<<8;
381 newdata
.coeffs
[i
][j
] = coeff
;
384 for(i
= 0;i
< HRIR_COUNT
;i
++)
388 newdata
.delays
[i
] = delay
;
391 ERR("Invalid delay[%d]: %d (%d)\n", i
, delay
, maxDelay
);
398 ERR("Premature end of data\n");
407 LoadedHrtf
= newdata
;
409 ERR("Failed to load %s\n", fname
);
411 TRACE("HRTF support for format: %s %uhz\n",
412 DevFmtChannelsString(DevFmtStereo
), LoadedHrtf
.sampleRate
);