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
31 /* External HRTF file format (LE byte order):
33 * ALchar magic[8] = "MinPHR00";
36 * ALushort hrirCount; // Required value: 828
37 * ALushort hrirSize; // Required value: 32
38 * ALubyte evCount; // Required value: 19
40 * ALushort evOffset[evCount]; // Required values:
41 * { 0, 1, 13, 37, 73, 118, 174, 234, 306, 378, 450, 522, 594, 654, 710, 755, 791, 815, 827 }
43 * ALshort coefficients[hrirCount][hrirSize];
44 * ALubyte delays[hrirCount]; // Element values must not exceed 127
47 static const ALchar magicMarker
[8] = "MinPHR00";
49 #define HRIR_COUNT 828
52 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 };
53 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 };
56 static const struct Hrtf
{
58 ALshort coeffs
[HRIR_COUNT
][HRIR_LENGTH
];
59 ALubyte delays
[HRIR_COUNT
];
62 #include "hrtf_tables.inc"
65 static struct Hrtf
*LoadedHrtfs
= NULL
;
66 static ALuint NumLoadedHrtfs
= 0;
69 // Calculate the elevation indices given the polar elevation in radians.
70 // This will return two indices between 0 and (ELEV_COUNT-1) and an
71 // interpolation factor between 0.0 and 1.0.
72 static void CalcEvIndices(ALfloat ev
, ALuint
*evidx
, ALfloat
*evmu
)
74 ev
= (F_PI_2
+ ev
) * (ELEV_COUNT
-1) / F_PI
;
75 evidx
[0] = fastf2u(ev
);
76 evidx
[1] = minu(evidx
[0] + 1, ELEV_COUNT
-1);
77 *evmu
= ev
- evidx
[0];
80 // Calculate the azimuth indices given the polar azimuth in radians. This
81 // will return two indices between 0 and (azCount [ei] - 1) and an
82 // interpolation factor between 0.0 and 1.0.
83 static void CalcAzIndices(ALuint evidx
, ALfloat az
, ALuint
*azidx
, ALfloat
*azmu
)
85 az
= (F_PI
*2.0f
+ az
) * azCount
[evidx
] / (F_PI
*2.0f
);
86 azidx
[0] = fastf2u(az
) % azCount
[evidx
];
87 azidx
[1] = (azidx
[0] + 1) % azCount
[evidx
];
88 *azmu
= az
- aluFloor(az
);
91 // Calculates the normalized HRTF transition factor (delta) from the changes
92 // in gain and listener to source angle between updates. The result is a
93 // normalized delta factor than can be used to calculate moving HRIR stepping
95 ALfloat
CalcHrtfDelta(ALfloat oldGain
, ALfloat newGain
, const ALfloat olddir
[3], const ALfloat newdir
[3])
97 ALfloat gainChange
, angleChange
;
99 // Calculate the normalized dB gain change.
100 newGain
= maxf(newGain
, 0.0001f
);
101 oldGain
= maxf(oldGain
, 0.0001f
);
102 gainChange
= aluFabs(aluLog10(newGain
/ oldGain
) / aluLog10(0.0001f
));
104 // Calculate the normalized listener to source angle change when there is
105 // enough gain to notice it.
107 if(gainChange
> 0.0001f
|| newGain
> 0.0001f
)
109 // No angle change when the directions are equal or degenerate (when
110 // both have zero length).
111 if(newdir
[0]-olddir
[0] || newdir
[1]-olddir
[1] || newdir
[2]-olddir
[2])
112 angleChange
= aluAcos(olddir
[0]*newdir
[0] +
113 olddir
[1]*newdir
[1] +
114 olddir
[2]*newdir
[2]) / F_PI
;
118 // Use the largest of the two changes for the delta factor, and apply a
119 // significance shaping function to it.
120 return clampf(angleChange
*2.0f
, gainChange
*2.0f
, 1.0f
);
123 // Calculates static HRIR coefficients and delays for the given polar
124 // elevation and azimuth in radians. Linear interpolation is used to
125 // increase the apparent resolution of the HRIR dataset. The coefficients
126 // are also normalized and attenuated by the specified gain.
127 void GetLerpedHrtfCoeffs(const struct Hrtf
*Hrtf
, ALfloat elevation
, ALfloat azimuth
, ALfloat gain
, ALfloat (*coeffs
)[2], ALuint
*delays
)
129 ALuint evidx
[2], azidx
[2];
131 ALuint lidx
[4], ridx
[4];
134 // Claculate elevation indices and interpolation factor.
135 CalcEvIndices(elevation
, evidx
, &mu
[2]);
137 // Calculate azimuth indices and interpolation factor for the first
139 CalcAzIndices(evidx
[0], azimuth
, azidx
, &mu
[0]);
141 // Calculate the first set of linear HRIR indices for left and right
143 lidx
[0] = evOffset
[evidx
[0]] + azidx
[0];
144 lidx
[1] = evOffset
[evidx
[0]] + azidx
[1];
145 ridx
[0] = evOffset
[evidx
[0]] + ((azCount
[evidx
[0]]-azidx
[0]) % azCount
[evidx
[0]]);
146 ridx
[1] = evOffset
[evidx
[0]] + ((azCount
[evidx
[0]]-azidx
[1]) % azCount
[evidx
[0]]);
148 // Calculate azimuth indices and interpolation factor for the second
150 CalcAzIndices(evidx
[1], azimuth
, azidx
, &mu
[1]);
152 // Calculate the second set of linear HRIR indices for left and right
154 lidx
[2] = evOffset
[evidx
[1]] + azidx
[0];
155 lidx
[3] = evOffset
[evidx
[1]] + azidx
[1];
156 ridx
[2] = evOffset
[evidx
[1]] + ((azCount
[evidx
[1]]-azidx
[0]) % azCount
[evidx
[1]]);
157 ridx
[3] = evOffset
[evidx
[1]] + ((azCount
[evidx
[1]]-azidx
[1]) % azCount
[evidx
[1]]);
159 // Calculate the normalized and attenuated HRIR coefficients using linear
160 // interpolation when there is enough gain to warrant it. Zero the
161 // coefficients if gain is too low.
164 gain
*= 1.0f
/32767.0f
;
165 for(i
= 0;i
< HRIR_LENGTH
;i
++)
167 coeffs
[i
][0] = lerp(lerp(Hrtf
->coeffs
[lidx
[0]][i
], Hrtf
->coeffs
[lidx
[1]][i
], mu
[0]),
168 lerp(Hrtf
->coeffs
[lidx
[2]][i
], Hrtf
->coeffs
[lidx
[3]][i
], mu
[1]),
170 coeffs
[i
][1] = lerp(lerp(Hrtf
->coeffs
[ridx
[0]][i
], Hrtf
->coeffs
[ridx
[1]][i
], mu
[0]),
171 lerp(Hrtf
->coeffs
[ridx
[2]][i
], Hrtf
->coeffs
[ridx
[3]][i
], mu
[1]),
177 for(i
= 0;i
< HRIR_LENGTH
;i
++)
184 // Calculate the HRIR delays using linear interpolation.
185 delays
[0] = fastf2u(lerp(lerp(Hrtf
->delays
[lidx
[0]], Hrtf
->delays
[lidx
[1]], mu
[0]),
186 lerp(Hrtf
->delays
[lidx
[2]], Hrtf
->delays
[lidx
[3]], mu
[1]),
188 delays
[1] = fastf2u(lerp(lerp(Hrtf
->delays
[ridx
[0]], Hrtf
->delays
[ridx
[1]], mu
[0]),
189 lerp(Hrtf
->delays
[ridx
[2]], Hrtf
->delays
[ridx
[3]], mu
[1]),
193 // Calculates the moving HRIR target coefficients, target delays, and
194 // stepping values for the given polar elevation and azimuth in radians.
195 // Linear interpolation is used to increase the apparent resolution of the
196 // HRIR dataset. The coefficients are also normalized and attenuated by the
197 // specified gain. Stepping resolution and count is determined using the
198 // given delta factor between 0.0 and 1.0.
199 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
)
201 ALuint evidx
[2], azidx
[2];
202 ALuint lidx
[4], ridx
[4];
208 // Claculate elevation indices and interpolation factor.
209 CalcEvIndices(elevation
, evidx
, &mu
[2]);
211 // Calculate azimuth indices and interpolation factor for the first
213 CalcAzIndices(evidx
[0], azimuth
, azidx
, &mu
[0]);
215 // Calculate the first set of linear HRIR indices for left and right
217 lidx
[0] = evOffset
[evidx
[0]] + azidx
[0];
218 lidx
[1] = evOffset
[evidx
[0]] + azidx
[1];
219 ridx
[0] = evOffset
[evidx
[0]] + ((azCount
[evidx
[0]]-azidx
[0]) % azCount
[evidx
[0]]);
220 ridx
[1] = evOffset
[evidx
[0]] + ((azCount
[evidx
[0]]-azidx
[1]) % azCount
[evidx
[0]]);
222 // Calculate azimuth indices and interpolation factor for the second
224 CalcAzIndices(evidx
[1], azimuth
, azidx
, &mu
[1]);
226 // Calculate the second set of linear HRIR indices for left and right
228 lidx
[2] = evOffset
[evidx
[1]] + azidx
[0];
229 lidx
[3] = evOffset
[evidx
[1]] + azidx
[1];
230 ridx
[2] = evOffset
[evidx
[1]] + ((azCount
[evidx
[1]]-azidx
[0]) % azCount
[evidx
[1]]);
231 ridx
[3] = evOffset
[evidx
[1]] + ((azCount
[evidx
[1]]-azidx
[1]) % azCount
[evidx
[1]]);
233 // Calculate the stepping parameters.
234 delta
= maxf(aluFloor(delta
*(Hrtf
->sampleRate
*0.015f
) + 0.5f
), 1.0f
);
237 // Calculate the normalized and attenuated target HRIR coefficients using
238 // linear interpolation when there is enough gain to warrant it. Zero
239 // the target coefficients if gain is too low. Then calculate the
240 // coefficient stepping values using the target and previous running
244 gain
*= 1.0f
/32767.0f
;
245 for(i
= 0;i
< HRIR_LENGTH
;i
++)
247 left
= coeffs
[i
][0] - (coeffStep
[i
][0] * counter
);
248 right
= coeffs
[i
][1] - (coeffStep
[i
][1] * counter
);
250 coeffs
[i
][0] = lerp(lerp(Hrtf
->coeffs
[lidx
[0]][i
], Hrtf
->coeffs
[lidx
[1]][i
], mu
[0]),
251 lerp(Hrtf
->coeffs
[lidx
[2]][i
], Hrtf
->coeffs
[lidx
[3]][i
], mu
[1]),
253 coeffs
[i
][1] = lerp(lerp(Hrtf
->coeffs
[ridx
[0]][i
], Hrtf
->coeffs
[ridx
[1]][i
], mu
[0]),
254 lerp(Hrtf
->coeffs
[ridx
[2]][i
], Hrtf
->coeffs
[ridx
[3]][i
], mu
[1]),
257 coeffStep
[i
][0] = step
* (coeffs
[i
][0] - left
);
258 coeffStep
[i
][1] = step
* (coeffs
[i
][1] - right
);
263 for(i
= 0;i
< HRIR_LENGTH
;i
++)
265 left
= coeffs
[i
][0] - (coeffStep
[i
][0] * counter
);
266 right
= coeffs
[i
][1] - (coeffStep
[i
][1] * counter
);
271 coeffStep
[i
][0] = step
* -left
;
272 coeffStep
[i
][1] = step
* -right
;
276 // Calculate the HRIR delays using linear interpolation. Then calculate
277 // the delay stepping values using the target and previous running
279 left
= (ALfloat
)(delays
[0] - (delayStep
[0] * counter
));
280 right
= (ALfloat
)(delays
[1] - (delayStep
[1] * counter
));
282 delays
[0] = fastf2u(lerp(lerp(Hrtf
->delays
[lidx
[0]], Hrtf
->delays
[lidx
[1]], mu
[0]),
283 lerp(Hrtf
->delays
[lidx
[2]], Hrtf
->delays
[lidx
[3]], mu
[1]),
285 delays
[1] = fastf2u(lerp(lerp(Hrtf
->delays
[ridx
[0]], Hrtf
->delays
[ridx
[1]], mu
[0]),
286 lerp(Hrtf
->delays
[ridx
[2]], Hrtf
->delays
[ridx
[3]], mu
[1]),
289 delayStep
[0] = fastf2i(step
* (delays
[0] - left
));
290 delayStep
[1] = fastf2i(step
* (delays
[1] - right
));
292 // The stepping count is the number of samples necessary for the HRIR to
293 // complete its transition. The mixer will only apply stepping for this
295 return fastf2u(delta
);
298 const struct Hrtf
*GetHrtf(ALCdevice
*device
)
300 if(device
->FmtChans
== DevFmtStereo
)
303 for(i
= 0;i
< NumLoadedHrtfs
;i
++)
305 if(device
->Frequency
== LoadedHrtfs
[i
].sampleRate
)
306 return &LoadedHrtfs
[i
];
308 if(device
->Frequency
== DefaultHrtf
.sampleRate
)
311 ERR("Incompatible format: %s %uhz\n",
312 DevFmtChannelsString(device
->FmtChans
), device
->Frequency
);
318 char *fnamelist
=NULL
, *next
=NULL
;
321 if(ConfigValueStr(NULL
, "hrtf_tables", &val
))
322 next
= fnamelist
= strdup(val
);
325 const ALubyte maxDelay
= SRC_HISTORY_LENGTH
-1;
334 next
= strchr(fname
, ',');
346 while(isspace(*next
) || *next
== ',')
352 TRACE("Loading %s\n", fname
);
353 f
= fopen(fname
, "rb");
356 ERR("Could not open %s\n", fname
);
361 if(fread(magic
, 1, sizeof(magicMarker
), f
) != sizeof(magicMarker
))
363 ERR("Failed to read magic marker\n");
366 else if(memcmp(magic
, magicMarker
, sizeof(magicMarker
)) != 0)
369 ERR("Invalid magic marker: \"%s\"\n", magic
);
375 ALushort hrirCount
, hrirSize
;
378 newdata
.sampleRate
= fgetc(f
);
379 newdata
.sampleRate
|= fgetc(f
)<<8;
380 newdata
.sampleRate
|= fgetc(f
)<<16;
381 newdata
.sampleRate
|= fgetc(f
)<<24;
383 hrirCount
= fgetc(f
);
384 hrirCount
|= fgetc(f
)<<8;
387 hrirSize
|= fgetc(f
)<<8;
391 if(hrirCount
!= HRIR_COUNT
|| hrirSize
!= HRIR_LENGTH
|| evCount
!= ELEV_COUNT
)
393 ERR("Unsupported value: hrirCount=%d (%d), hrirSize=%d (%d), evCount=%d (%d)\n",
394 hrirCount
, HRIR_COUNT
, hrirSize
, HRIR_LENGTH
, evCount
, ELEV_COUNT
);
401 for(i
= 0;i
< HRIR_COUNT
;i
++)
405 offset
|= fgetc(f
)<<8;
406 if(offset
!= evOffset
[i
])
408 ERR("Unsupported evOffset[%d] value: %d (%d)\n", i
, offset
, evOffset
[i
]);
416 for(i
= 0;i
< HRIR_COUNT
;i
++)
418 for(j
= 0;j
< HRIR_LENGTH
;j
++)
422 coeff
|= fgetc(f
)<<8;
423 newdata
.coeffs
[i
][j
] = coeff
;
426 for(i
= 0;i
< HRIR_COUNT
;i
++)
430 newdata
.delays
[i
] = delay
;
433 ERR("Invalid delay[%d]: %d (%d)\n", i
, delay
, maxDelay
);
440 ERR("Premature end of data\n");
450 void *temp
= realloc(LoadedHrtfs
, (NumLoadedHrtfs
+1)*sizeof(LoadedHrtfs
[0]));
454 TRACE("Loaded HRTF support for format: %s %uhz\n",
455 DevFmtChannelsString(DevFmtStereo
), newdata
.sampleRate
);
456 LoadedHrtfs
[NumLoadedHrtfs
++] = newdata
;
460 ERR("Failed to load %s\n", fname
);