Fix HRTF index calculations for B-Format coefficients
[openal-soft.git] / Alc / hrtf.c
blob3be30d95abacc8a77af716bcc1f76eee39921c16
1 /**
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.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <stdlib.h>
24 #include <ctype.h>
26 #include "AL/al.h"
27 #include "AL/alc.h"
28 #include "alMain.h"
29 #include "alSource.h"
30 #include "alu.h"
31 #include "hrtf.h"
33 #include "compat.h"
34 #include "almalloc.h"
37 /* Current data set limits defined by the makehrtf utility. */
38 #define MIN_IR_SIZE (8)
39 #define MAX_IR_SIZE (128)
40 #define MOD_IR_SIZE (8)
42 #define MIN_EV_COUNT (5)
43 #define MAX_EV_COUNT (128)
45 #define MIN_AZ_COUNT (1)
46 #define MAX_AZ_COUNT (128)
48 static const ALchar magicMarker00[8] = "MinPHR00";
49 static const ALchar magicMarker01[8] = "MinPHR01";
51 /* First value for pass-through coefficients (remaining are 0), used for omni-
52 * directional sounds. */
53 static const ALfloat PassthruCoeff = 32767.0f * 0.707106781187f/*sqrt(0.5)*/;
55 static struct Hrtf *LoadedHrtfs = NULL;
57 /* Calculate the elevation indices given the polar elevation in radians.
58 * This will return two indices between 0 and (evcount - 1) and an
59 * interpolation factor between 0.0 and 1.0.
61 static void CalcEvIndices(ALuint evcount, ALfloat ev, ALuint *evidx, ALfloat *evmu)
63 ev = (F_PI_2 + ev) * (evcount-1) / F_PI;
64 evidx[0] = fastf2u(ev);
65 evidx[1] = minu(evidx[0] + 1, evcount-1);
66 *evmu = ev - evidx[0];
69 /* Calculate the azimuth indices given the polar azimuth in radians. This
70 * will return two indices between 0 and (azcount - 1) and an interpolation
71 * factor between 0.0 and 1.0.
73 static void CalcAzIndices(ALuint azcount, ALfloat az, ALuint *azidx, ALfloat *azmu)
75 az = (F_TAU + az) * azcount / F_TAU;
76 azidx[0] = fastf2u(az) % azcount;
77 azidx[1] = (azidx[0] + 1) % azcount;
78 *azmu = az - floorf(az);
81 /* Calculates static HRIR coefficients and delays for the given polar
82 * elevation and azimuth in radians. Linear interpolation is used to
83 * increase the apparent resolution of the HRIR data set. The coefficients
84 * are also normalized and attenuated by the specified gain.
86 void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat spread, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays)
88 ALuint evidx[2], lidx[4], ridx[4];
89 ALfloat mu[3], blend[4];
90 ALfloat dirfact;
91 ALuint i;
93 dirfact = 1.0f - (spread / F_TAU);
95 /* Claculate elevation indices and interpolation factor. */
96 CalcEvIndices(Hrtf->evCount, elevation, evidx, &mu[2]);
98 for(i = 0;i < 2;i++)
100 ALuint azcount = Hrtf->azCount[evidx[i]];
101 ALuint evoffset = Hrtf->evOffset[evidx[i]];
102 ALuint azidx[2];
104 /* Calculate azimuth indices and interpolation factor for this elevation. */
105 CalcAzIndices(azcount, azimuth, azidx, &mu[i]);
107 /* Calculate a set of linear HRIR indices for left and right channels. */
108 lidx[i*2 + 0] = evoffset + azidx[0];
109 lidx[i*2 + 1] = evoffset + azidx[1];
110 ridx[i*2 + 0] = evoffset + ((azcount-azidx[0]) % azcount);
111 ridx[i*2 + 1] = evoffset + ((azcount-azidx[1]) % azcount);
114 /* Calculate 4 blending weights for 2D bilinear interpolation. */
115 blend[0] = (1.0f-mu[0]) * (1.0f-mu[2]);
116 blend[1] = ( mu[0]) * (1.0f-mu[2]);
117 blend[2] = (1.0f-mu[1]) * ( mu[2]);
118 blend[3] = ( mu[1]) * ( mu[2]);
120 /* Calculate the HRIR delays using linear interpolation. */
121 delays[0] = fastf2u((Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] +
122 Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3]) *
123 dirfact + 0.5f) << HRTFDELAY_BITS;
124 delays[1] = fastf2u((Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] +
125 Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3]) *
126 dirfact + 0.5f) << HRTFDELAY_BITS;
128 /* Calculate the sample offsets for the HRIR indices. */
129 lidx[0] *= Hrtf->irSize;
130 lidx[1] *= Hrtf->irSize;
131 lidx[2] *= Hrtf->irSize;
132 lidx[3] *= Hrtf->irSize;
133 ridx[0] *= Hrtf->irSize;
134 ridx[1] *= Hrtf->irSize;
135 ridx[2] *= Hrtf->irSize;
136 ridx[3] *= Hrtf->irSize;
138 /* Calculate the normalized and attenuated HRIR coefficients using linear
139 * interpolation when there is enough gain to warrant it. Zero the
140 * coefficients if gain is too low.
142 if(gain > 0.0001f)
144 ALfloat c;
146 i = 0;
147 c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
148 Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
149 coeffs[i][0] = lerp(PassthruCoeff, c, dirfact) * gain * (1.0f/32767.0f);
150 c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
151 Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
152 coeffs[i][1] = lerp(PassthruCoeff, c, dirfact) * gain * (1.0f/32767.0f);
154 for(i = 1;i < Hrtf->irSize;i++)
156 c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
157 Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
158 coeffs[i][0] = lerp(0.0f, c, dirfact) * gain * (1.0f/32767.0f);
159 c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
160 Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
161 coeffs[i][1] = lerp(0.0f, c, dirfact) * gain * (1.0f/32767.0f);
164 else
166 for(i = 0;i < Hrtf->irSize;i++)
168 coeffs[i][0] = 0.0f;
169 coeffs[i][1] = 0.0f;
175 ALuint BuildBFormatHrtf(const struct Hrtf *Hrtf, ALfloat (*coeffs)[HRIR_LENGTH][2], ALuint NumChannels)
177 static const struct {
178 ALfloat elevation;
179 ALfloat azimuth;
180 } CubePoints[8] = {
181 { DEG2RAD( 35.0f), DEG2RAD( -45.0f) },
182 { DEG2RAD( 35.0f), DEG2RAD( 45.0f) },
183 { DEG2RAD( 35.0f), DEG2RAD(-135.0f) },
184 { DEG2RAD( 35.0f), DEG2RAD( 135.0f) },
185 { DEG2RAD(-35.0f), DEG2RAD( -45.0f) },
186 { DEG2RAD(-35.0f), DEG2RAD( 45.0f) },
187 { DEG2RAD(-35.0f), DEG2RAD(-135.0f) },
188 { DEG2RAD(-35.0f), DEG2RAD( 135.0f) },
190 static const ALfloat CubeMatrix[8][MAX_AMBI_COEFFS] = {
191 { 0.25f, 0.14425f, 0.14425f, 0.14425f },
192 { 0.25f, -0.14425f, 0.14425f, 0.14425f },
193 { 0.25f, 0.14425f, 0.14425f, -0.14425f },
194 { 0.25f, -0.14425f, 0.14425f, -0.14425f },
195 { 0.25f, 0.14425f, -0.14425f, 0.14425f },
196 { 0.25f, -0.14425f, -0.14425f, 0.14425f },
197 { 0.25f, 0.14425f, -0.14425f, -0.14425f },
198 { 0.25f, -0.14425f, -0.14425f, -0.14425f },
200 ALuint lidx[8], ridx[8];
201 ALuint min_delay = HRTF_HISTORY_LENGTH;
202 ALuint max_length = 0;
203 ALuint i, j, c;
205 assert(NumChannels == 4);
207 for(c = 0;c < 8;c++)
209 ALuint evidx, azidx;
210 ALuint evoffset;
211 ALuint azcount;
213 /* Calculate elevation index. */
214 evidx = (ALuint)floorf((F_PI_2 + CubePoints[c].elevation) *
215 (Hrtf->evCount-1)/F_PI + 0.5f);
216 evidx = minu(evidx, Hrtf->evCount-1);
218 azcount = Hrtf->azCount[evidx];
219 evoffset = Hrtf->evOffset[evidx];
221 /* Calculate azimuth index for this elevation. */
222 azidx = (ALuint)floorf((F_TAU+CubePoints[c].azimuth) *
223 azcount/F_TAU + 0.5f) % azcount;
225 /* Calculate indices for left and right channels. */
226 lidx[c] = evoffset + azidx;
227 ridx[c] = evoffset + ((azcount-azidx) % azcount);
229 min_delay = minu(min_delay, minu(Hrtf->delays[lidx[c]], Hrtf->delays[ridx[c]]));
232 for(c = 0;c < 8;c++)
234 const ALshort *fir;
235 ALuint length;
236 ALuint delay;
238 fir = &Hrtf->coeffs[lidx[c] * Hrtf->irSize];
239 delay = Hrtf->delays[lidx[c]] - min_delay;
240 length = minu(delay + Hrtf->irSize, HRIR_LENGTH);
241 for(i = 0;i < NumChannels;++i)
243 ALuint k = 0;
244 for(j = delay;j < length;++j)
245 coeffs[i][j][0] += fir[k++]/32767.0f * CubeMatrix[c][i];
247 max_length = maxu(max_length, length);
249 fir = &Hrtf->coeffs[ridx[c] * Hrtf->irSize];
250 delay = Hrtf->delays[ridx[c]] - min_delay;
251 length = minu(delay + Hrtf->irSize, HRIR_LENGTH);
252 for(i = 0;i < NumChannels;++i)
254 ALuint k = 0;
255 for(j = delay;j < length;++j)
256 coeffs[i][j][1] += fir[k++]/32767.0f * CubeMatrix[c][i];
258 max_length = maxu(max_length, length);
260 TRACE("Skipped min delay: %u, new combined length: %u\n", min_delay, max_length);
262 return max_length;
266 static struct Hrtf *LoadHrtf00(FILE *f, const_al_string filename)
268 const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
269 struct Hrtf *Hrtf = NULL;
270 ALboolean failed = AL_FALSE;
271 ALuint rate = 0, irCount = 0;
272 ALushort irSize = 0;
273 ALubyte evCount = 0;
274 ALubyte *azCount = NULL;
275 ALushort *evOffset = NULL;
276 ALshort *coeffs = NULL;
277 ALubyte *delays = NULL;
278 ALuint i, j;
280 rate = fgetc(f);
281 rate |= fgetc(f)<<8;
282 rate |= fgetc(f)<<16;
283 rate |= fgetc(f)<<24;
285 irCount = fgetc(f);
286 irCount |= fgetc(f)<<8;
288 irSize = fgetc(f);
289 irSize |= fgetc(f)<<8;
291 evCount = fgetc(f);
293 if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
295 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
296 irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE);
297 failed = AL_TRUE;
299 if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT)
301 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
302 evCount, MIN_EV_COUNT, MAX_EV_COUNT);
303 failed = AL_TRUE;
306 if(failed)
307 return NULL;
309 azCount = malloc(sizeof(azCount[0])*evCount);
310 evOffset = malloc(sizeof(evOffset[0])*evCount);
311 if(azCount == NULL || evOffset == NULL)
313 ERR("Out of memory.\n");
314 failed = AL_TRUE;
317 if(!failed)
319 evOffset[0] = fgetc(f);
320 evOffset[0] |= fgetc(f)<<8;
321 for(i = 1;i < evCount;i++)
323 evOffset[i] = fgetc(f);
324 evOffset[i] |= fgetc(f)<<8;
325 if(evOffset[i] <= evOffset[i-1])
327 ERR("Invalid evOffset: evOffset[%d]=%d (last=%d)\n",
328 i, evOffset[i], evOffset[i-1]);
329 failed = AL_TRUE;
332 azCount[i-1] = evOffset[i] - evOffset[i-1];
333 if(azCount[i-1] < MIN_AZ_COUNT || azCount[i-1] > MAX_AZ_COUNT)
335 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
336 i-1, azCount[i-1], MIN_AZ_COUNT, MAX_AZ_COUNT);
337 failed = AL_TRUE;
340 if(irCount <= evOffset[i-1])
342 ERR("Invalid evOffset: evOffset[%d]=%d (irCount=%d)\n",
343 i-1, evOffset[i-1], irCount);
344 failed = AL_TRUE;
347 azCount[i-1] = irCount - evOffset[i-1];
348 if(azCount[i-1] < MIN_AZ_COUNT || azCount[i-1] > MAX_AZ_COUNT)
350 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
351 i-1, azCount[i-1], MIN_AZ_COUNT, MAX_AZ_COUNT);
352 failed = AL_TRUE;
356 if(!failed)
358 coeffs = malloc(sizeof(coeffs[0])*irSize*irCount);
359 delays = malloc(sizeof(delays[0])*irCount);
360 if(coeffs == NULL || delays == NULL)
362 ERR("Out of memory.\n");
363 failed = AL_TRUE;
367 if(!failed)
369 for(i = 0;i < irCount*irSize;i+=irSize)
371 for(j = 0;j < irSize;j++)
373 ALshort coeff;
374 coeff = fgetc(f);
375 coeff |= fgetc(f)<<8;
376 coeffs[i+j] = coeff;
379 for(i = 0;i < irCount;i++)
381 delays[i] = fgetc(f);
382 if(delays[i] > maxDelay)
384 ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i], maxDelay);
385 failed = AL_TRUE;
389 if(feof(f))
391 ERR("Premature end of data\n");
392 failed = AL_TRUE;
396 if(!failed)
398 size_t total = sizeof(struct Hrtf);
399 total += sizeof(azCount[0])*evCount;
400 total += sizeof(evOffset[0])*evCount;
401 total += sizeof(coeffs[0])*irSize*irCount;
402 total += sizeof(delays[0])*irCount;
403 total += al_string_length(filename)+1;
405 Hrtf = al_calloc(16, total);
406 if(Hrtf == NULL)
408 ERR("Out of memory.\n");
409 failed = AL_TRUE;
413 if(!failed)
415 Hrtf->sampleRate = rate;
416 Hrtf->irSize = irSize;
417 Hrtf->evCount = evCount;
418 Hrtf->azCount = ((ALubyte*)(Hrtf+1));
419 Hrtf->evOffset = ((ALushort*)(Hrtf->azCount + evCount));
420 Hrtf->coeffs = ((ALshort*)(Hrtf->evOffset + evCount));
421 Hrtf->delays = ((ALubyte*)(Hrtf->coeffs + irSize*irCount));
422 Hrtf->filename = ((char*)(Hrtf->delays + irCount));
423 Hrtf->next = NULL;
425 memcpy((void*)Hrtf->azCount, azCount, sizeof(azCount[0])*evCount);
426 memcpy((void*)Hrtf->evOffset, evOffset, sizeof(evOffset[0])*evCount);
427 memcpy((void*)Hrtf->coeffs, coeffs, sizeof(coeffs[0])*irSize*irCount);
428 memcpy((void*)Hrtf->delays, delays, sizeof(delays[0])*irCount);
429 memcpy((void*)Hrtf->filename, al_string_get_cstr(filename), al_string_length(filename)+1);
432 free(azCount);
433 free(evOffset);
434 free(coeffs);
435 free(delays);
436 return Hrtf;
439 static struct Hrtf *LoadHrtf01(FILE *f, const_al_string filename)
441 const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
442 struct Hrtf *Hrtf = NULL;
443 ALboolean failed = AL_FALSE;
444 ALuint rate = 0, irCount = 0;
445 ALubyte irSize = 0, evCount = 0;
446 ALubyte *azCount = NULL;
447 ALushort *evOffset = NULL;
448 ALshort *coeffs = NULL;
449 ALubyte *delays = NULL;
450 ALuint i, j;
452 rate = fgetc(f);
453 rate |= fgetc(f)<<8;
454 rate |= fgetc(f)<<16;
455 rate |= fgetc(f)<<24;
457 irSize = fgetc(f);
459 evCount = fgetc(f);
461 if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
463 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
464 irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE);
465 failed = AL_TRUE;
467 if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT)
469 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
470 evCount, MIN_EV_COUNT, MAX_EV_COUNT);
471 failed = AL_TRUE;
474 if(failed)
475 return NULL;
477 azCount = malloc(sizeof(azCount[0])*evCount);
478 evOffset = malloc(sizeof(evOffset[0])*evCount);
479 if(azCount == NULL || evOffset == NULL)
481 ERR("Out of memory.\n");
482 failed = AL_TRUE;
485 if(!failed)
487 for(i = 0;i < evCount;i++)
489 azCount[i] = fgetc(f);
490 if(azCount[i] < MIN_AZ_COUNT || azCount[i] > MAX_AZ_COUNT)
492 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
493 i, azCount[i], MIN_AZ_COUNT, MAX_AZ_COUNT);
494 failed = AL_TRUE;
499 if(!failed)
501 evOffset[0] = 0;
502 irCount = azCount[0];
503 for(i = 1;i < evCount;i++)
505 evOffset[i] = evOffset[i-1] + azCount[i-1];
506 irCount += azCount[i];
509 coeffs = malloc(sizeof(coeffs[0])*irSize*irCount);
510 delays = malloc(sizeof(delays[0])*irCount);
511 if(coeffs == NULL || delays == NULL)
513 ERR("Out of memory.\n");
514 failed = AL_TRUE;
518 if(!failed)
520 for(i = 0;i < irCount*irSize;i+=irSize)
522 for(j = 0;j < irSize;j++)
524 ALshort coeff;
525 coeff = fgetc(f);
526 coeff |= fgetc(f)<<8;
527 coeffs[i+j] = coeff;
530 for(i = 0;i < irCount;i++)
532 delays[i] = fgetc(f);
533 if(delays[i] > maxDelay)
535 ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i], maxDelay);
536 failed = AL_TRUE;
540 if(feof(f))
542 ERR("Premature end of data\n");
543 failed = AL_TRUE;
547 if(!failed)
549 size_t total = sizeof(struct Hrtf);
550 total += sizeof(azCount[0])*evCount;
551 total += sizeof(evOffset[0])*evCount;
552 total += sizeof(coeffs[0])*irSize*irCount;
553 total += sizeof(delays[0])*irCount;
554 total += al_string_length(filename)+1;
556 Hrtf = al_calloc(16, total);
557 if(Hrtf == NULL)
559 ERR("Out of memory.\n");
560 failed = AL_TRUE;
564 if(!failed)
566 Hrtf->sampleRate = rate;
567 Hrtf->irSize = irSize;
568 Hrtf->evCount = evCount;
569 Hrtf->azCount = ((ALubyte*)(Hrtf+1));
570 Hrtf->evOffset = ((ALushort*)(Hrtf->azCount + evCount));
571 Hrtf->coeffs = ((ALshort*)(Hrtf->evOffset + evCount));
572 Hrtf->delays = ((ALubyte*)(Hrtf->coeffs + irSize*irCount));
573 Hrtf->filename = ((char*)(Hrtf->delays + irCount));
574 Hrtf->next = NULL;
576 memcpy((void*)Hrtf->azCount, azCount, sizeof(azCount[0])*evCount);
577 memcpy((void*)Hrtf->evOffset, evOffset, sizeof(evOffset[0])*evCount);
578 memcpy((void*)Hrtf->coeffs, coeffs, sizeof(coeffs[0])*irSize*irCount);
579 memcpy((void*)Hrtf->delays, delays, sizeof(delays[0])*irCount);
580 memcpy((void*)Hrtf->filename, al_string_get_cstr(filename), al_string_length(filename)+1);
583 free(azCount);
584 free(evOffset);
585 free(coeffs);
586 free(delays);
587 return Hrtf;
590 static void AddFileEntry(vector_HrtfEntry *list, al_string *filename)
592 HrtfEntry entry = { AL_STRING_INIT_STATIC(), NULL };
593 struct Hrtf *hrtf = NULL;
594 const HrtfEntry *iter;
595 const char *name;
596 const char *ext;
597 ALchar magic[8];
598 FILE *f;
599 int i;
601 name = strrchr(al_string_get_cstr(*filename), '/');
602 if(!name) name = strrchr(al_string_get_cstr(*filename), '\\');
603 if(!name) name = al_string_get_cstr(*filename);
604 else ++name;
606 #define MATCH_FNAME(i) (al_string_cmp_cstr(*filename, (i)->hrtf->filename) == 0)
607 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_FNAME);
608 if(iter != VECTOR_END(*list))
610 TRACE("Skipping duplicate file entry %s\n", al_string_get_cstr(*filename));
611 goto done;
613 #undef MATCH_FNAME
615 entry.hrtf = LoadedHrtfs;
616 while(entry.hrtf)
618 if(al_string_cmp_cstr(*filename, entry.hrtf->filename) == 0)
620 TRACE("Skipping load of already-loaded file %s\n", al_string_get_cstr(*filename));
621 goto skip_load;
623 entry.hrtf = entry.hrtf->next;
626 TRACE("Loading %s...\n", al_string_get_cstr(*filename));
627 f = al_fopen(al_string_get_cstr(*filename), "rb");
628 if(f == NULL)
630 ERR("Could not open %s\n", al_string_get_cstr(*filename));
631 goto done;
634 if(fread(magic, 1, sizeof(magic), f) != sizeof(magic))
635 ERR("Failed to read header from %s\n", al_string_get_cstr(*filename));
636 else
638 if(memcmp(magic, magicMarker00, sizeof(magicMarker00)) == 0)
640 TRACE("Detected data set format v0\n");
641 hrtf = LoadHrtf00(f, *filename);
643 else if(memcmp(magic, magicMarker01, sizeof(magicMarker01)) == 0)
645 TRACE("Detected data set format v1\n");
646 hrtf = LoadHrtf01(f, *filename);
648 else
649 ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(*filename), magic);
651 fclose(f);
653 if(!hrtf)
655 ERR("Failed to load %s\n", al_string_get_cstr(*filename));
656 goto done;
659 hrtf->next = LoadedHrtfs;
660 LoadedHrtfs = hrtf;
661 TRACE("Loaded HRTF support for format: %s %uhz\n",
662 DevFmtChannelsString(DevFmtStereo), hrtf->sampleRate);
663 entry.hrtf = hrtf;
665 skip_load:
666 /* TODO: Get a human-readable name from the HRTF data (possibly coming in a
667 * format update). */
668 ext = strrchr(name, '.');
670 i = 0;
671 do {
672 if(!ext)
673 al_string_copy_cstr(&entry.name, name);
674 else
675 al_string_copy_range(&entry.name, name, ext);
676 if(i != 0)
678 char str[64];
679 snprintf(str, sizeof(str), " #%d", i+1);
680 al_string_append_cstr(&entry.name, str);
682 ++i;
684 #define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0)
685 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_NAME);
686 #undef MATCH_NAME
687 } while(iter != VECTOR_END(*list));
689 TRACE("Adding entry \"%s\" from file \"%s\"\n", al_string_get_cstr(entry.name),
690 al_string_get_cstr(*filename));
691 VECTOR_PUSH_BACK(*list, entry);
693 done:
694 al_string_deinit(filename);
698 /* Unfortunate that we have to duplicate LoadHrtf01 like this, to take a memory
699 * buffer for input instead of a FILE*, but there's no portable way to access a
700 * memory buffer through the standard FILE* I/O API (POSIX 2008 has fmemopen,
701 * and Windows doesn't seem to have anything).
703 static struct Hrtf *LoadBuiltInHrtf01(const ALubyte *data, size_t datalen, const_al_string filename)
705 const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
706 struct Hrtf *Hrtf = NULL;
707 ALboolean failed = AL_FALSE;
708 ALuint rate = 0, irCount = 0;
709 ALubyte irSize = 0, evCount = 0;
710 const ALubyte *azCount = NULL;
711 ALushort *evOffset = NULL;
712 ALshort *coeffs = NULL;
713 const ALubyte *delays = NULL;
714 ALuint i, j;
716 if(datalen < 6)
718 ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n",
719 al_string_get_cstr(filename), 6, datalen);
720 return NULL;
723 rate = *(data++);
724 rate |= *(data++)<<8;
725 rate |= *(data++)<<16;
726 rate |= *(data++)<<24;
727 datalen -= 4;
729 irSize = *(data++);
730 datalen -= 1;
732 evCount = *(data++);
733 datalen -= 1;
735 if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
737 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
738 irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE);
739 failed = AL_TRUE;
741 if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT)
743 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
744 evCount, MIN_EV_COUNT, MAX_EV_COUNT);
745 failed = AL_TRUE;
747 if(failed)
748 return NULL;
750 if(datalen < evCount)
752 ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n",
753 al_string_get_cstr(filename), evCount, datalen);
754 return NULL;
757 azCount = data;
758 data += evCount;
759 datalen -= evCount;
761 evOffset = malloc(sizeof(evOffset[0])*evCount);
762 if(azCount == NULL || evOffset == NULL)
764 ERR("Out of memory.\n");
765 failed = AL_TRUE;
768 if(!failed)
770 for(i = 0;i < evCount;i++)
772 if(azCount[i] < MIN_AZ_COUNT || azCount[i] > MAX_AZ_COUNT)
774 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
775 i, azCount[i], MIN_AZ_COUNT, MAX_AZ_COUNT);
776 failed = AL_TRUE;
781 if(!failed)
783 evOffset[0] = 0;
784 irCount = azCount[0];
785 for(i = 1;i < evCount;i++)
787 evOffset[i] = evOffset[i-1] + azCount[i-1];
788 irCount += azCount[i];
791 coeffs = malloc(sizeof(coeffs[0])*irSize*irCount);
792 if(coeffs == NULL)
794 ERR("Out of memory.\n");
795 failed = AL_TRUE;
799 if(!failed)
801 size_t reqsize = 2*irSize*irCount + irCount;
802 if(datalen < reqsize)
804 ERR("Unexpected end of %s data (req "SZFMT", rem "SZFMT"\n",
805 al_string_get_cstr(filename), reqsize, datalen);
806 failed = AL_TRUE;
810 if(!failed)
812 for(i = 0;i < irCount*irSize;i+=irSize)
814 for(j = 0;j < irSize;j++)
816 ALshort coeff;
817 coeff = *(data++);
818 coeff |= *(data++)<<8;
819 datalen -= 2;
820 coeffs[i+j] = coeff;
824 delays = data;
825 data += irCount;
826 datalen -= irCount;
827 for(i = 0;i < irCount;i++)
829 if(delays[i] > maxDelay)
831 ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i], maxDelay);
832 failed = AL_TRUE;
837 if(!failed)
839 size_t total = sizeof(struct Hrtf);
840 total += sizeof(azCount[0])*evCount;
841 total += sizeof(evOffset[0])*evCount;
842 total += sizeof(coeffs[0])*irSize*irCount;
843 total += sizeof(delays[0])*irCount;
844 total += al_string_length(filename)+1;
846 Hrtf = al_calloc(16, total);
847 if(Hrtf == NULL)
849 ERR("Out of memory.\n");
850 failed = AL_TRUE;
854 if(!failed)
856 Hrtf->sampleRate = rate;
857 Hrtf->irSize = irSize;
858 Hrtf->evCount = evCount;
859 Hrtf->azCount = ((ALubyte*)(Hrtf+1));
860 Hrtf->evOffset = ((ALushort*)(Hrtf->azCount + evCount));
861 Hrtf->coeffs = ((ALshort*)(Hrtf->evOffset + evCount));
862 Hrtf->delays = ((ALubyte*)(Hrtf->coeffs + irSize*irCount));
863 Hrtf->filename = ((char*)(Hrtf->delays + irCount));
864 Hrtf->next = NULL;
866 memcpy((void*)Hrtf->azCount, azCount, sizeof(azCount[0])*evCount);
867 memcpy((void*)Hrtf->evOffset, evOffset, sizeof(evOffset[0])*evCount);
868 memcpy((void*)Hrtf->coeffs, coeffs, sizeof(coeffs[0])*irSize*irCount);
869 memcpy((void*)Hrtf->delays, delays, sizeof(delays[0])*irCount);
870 memcpy((void*)Hrtf->filename, al_string_get_cstr(filename), al_string_length(filename)+1);
873 free(evOffset);
874 free(coeffs);
875 return Hrtf;
878 /* Another unfortunate duplication, this time of AddFileEntry to take a memory
879 * buffer for input instead of opening the given filename.
881 static void AddBuiltInEntry(vector_HrtfEntry *list, const ALubyte *data, size_t datalen, al_string *filename)
883 HrtfEntry entry = { AL_STRING_INIT_STATIC(), NULL };
884 struct Hrtf *hrtf = NULL;
885 const HrtfEntry *iter;
886 int i;
888 #define MATCH_FNAME(i) (al_string_cmp_cstr(*filename, (i)->hrtf->filename) == 0)
889 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_FNAME);
890 if(iter != VECTOR_END(*list))
892 TRACE("Skipping duplicate file entry %s\n", al_string_get_cstr(*filename));
893 goto done;
895 #undef MATCH_FNAME
897 entry.hrtf = LoadedHrtfs;
898 while(entry.hrtf)
900 if(al_string_cmp_cstr(*filename, entry.hrtf->filename) == 0)
902 TRACE("Skipping load of already-loaded file %s\n", al_string_get_cstr(*filename));
903 goto skip_load;
905 entry.hrtf = entry.hrtf->next;
908 TRACE("Loading %s...\n", al_string_get_cstr(*filename));
909 if(datalen < sizeof(magicMarker01))
911 ERR("%s data is too short ("SZFMT" bytes)\n", al_string_get_cstr(*filename), datalen);
912 goto done;
915 if(memcmp(data, magicMarker01, sizeof(magicMarker01)) == 0)
917 TRACE("Detected data set format v1\n");
918 hrtf = LoadBuiltInHrtf01(
919 data+sizeof(magicMarker01), datalen-sizeof(magicMarker01),
920 *filename
923 else
924 ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(*filename), data);
926 if(!hrtf)
928 ERR("Failed to load %s\n", al_string_get_cstr(*filename));
929 goto done;
932 hrtf->next = LoadedHrtfs;
933 LoadedHrtfs = hrtf;
934 TRACE("Loaded HRTF support for format: %s %uhz\n",
935 DevFmtChannelsString(DevFmtStereo), hrtf->sampleRate);
936 entry.hrtf = hrtf;
938 skip_load:
939 i = 0;
940 do {
941 al_string_copy(&entry.name, *filename);
942 if(i != 0)
944 char str[64];
945 snprintf(str, sizeof(str), " #%d", i+1);
946 al_string_append_cstr(&entry.name, str);
948 ++i;
950 #define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0)
951 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_NAME);
952 #undef MATCH_NAME
953 } while(iter != VECTOR_END(*list));
955 TRACE("Adding built-in entry \"%s\"\n", al_string_get_cstr(entry.name));
956 VECTOR_PUSH_BACK(*list, entry);
958 done:
959 al_string_deinit(filename);
963 #ifndef ALSOFT_EMBED_HRTF_DATA
964 #define IDR_DEFAULT_44100_MHR 0
965 #define IDR_DEFAULT_48000_MHR 1
967 static const ALubyte *GetResource(int UNUSED(name), size_t *size)
969 *size = 0;
970 return NULL;
973 #else
974 #include "hrtf_res.h"
976 #ifdef _WIN32
977 static const ALubyte *GetResource(int name, size_t *size)
979 HMODULE handle;
980 HGLOBAL res;
981 HRSRC rc;
983 GetModuleHandleExW(
984 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
985 (LPCWSTR)GetResource, &handle
987 rc = FindResourceW(handle, MAKEINTRESOURCEW(name), MAKEINTRESOURCEW(MHRTYPE));
988 res = LoadResource(handle, rc);
990 *size = SizeofResource(handle, rc);
991 return LockResource(res);
994 #else
996 extern const ALubyte _binary_default_44100_mhr_start[] HIDDEN_DECL;
997 extern const ALubyte _binary_default_44100_mhr_end[] HIDDEN_DECL;
998 extern const ALubyte _binary_default_44100_mhr_size[] HIDDEN_DECL;
1000 extern const ALubyte _binary_default_48000_mhr_start[] HIDDEN_DECL;
1001 extern const ALubyte _binary_default_48000_mhr_end[] HIDDEN_DECL;
1002 extern const ALubyte _binary_default_48000_mhr_size[] HIDDEN_DECL;
1004 static const ALubyte *GetResource(int name, size_t *size)
1006 if(name == IDR_DEFAULT_44100_MHR)
1008 /* Make sure all symbols are referenced, to ensure the compiler won't
1009 * ignore the declarations and lose the visibility attribute used to
1010 * hide them (would be nice if ld or objcopy could automatically mark
1011 * them as hidden when generating them, but apparently they can't).
1013 const void *volatile ptr =_binary_default_44100_mhr_size;
1014 (void)ptr;
1015 *size = _binary_default_44100_mhr_end - _binary_default_44100_mhr_start;
1016 return _binary_default_44100_mhr_start;
1018 if(name == IDR_DEFAULT_48000_MHR)
1020 const void *volatile ptr =_binary_default_48000_mhr_size;
1021 (void)ptr;
1022 *size = _binary_default_48000_mhr_end - _binary_default_48000_mhr_start;
1023 return _binary_default_48000_mhr_start;
1025 *size = 0;
1026 return NULL;
1028 #endif
1029 #endif
1031 vector_HrtfEntry EnumerateHrtf(const_al_string devname)
1033 vector_HrtfEntry list = VECTOR_INIT_STATIC();
1034 const char *defaulthrtf = "";
1035 const char *pathlist = "";
1036 bool usedefaults = true;
1038 if(ConfigValueStr(al_string_get_cstr(devname), NULL, "hrtf-paths", &pathlist))
1040 while(pathlist && *pathlist)
1042 const char *next, *end;
1044 while(isspace(*pathlist) || *pathlist == ',')
1045 pathlist++;
1046 if(*pathlist == '\0')
1047 continue;
1049 next = strchr(pathlist, ',');
1050 if(next)
1051 end = next++;
1052 else
1054 end = pathlist + strlen(pathlist);
1055 usedefaults = false;
1058 while(end != pathlist && isspace(*(end-1)))
1059 --end;
1060 if(end != pathlist)
1062 al_string pname = AL_STRING_INIT_STATIC();
1063 vector_al_string flist;
1065 al_string_append_range(&pname, pathlist, end);
1067 flist = SearchDataFiles(".mhr", al_string_get_cstr(pname));
1068 VECTOR_FOR_EACH_PARAMS(al_string, flist, AddFileEntry, &list);
1069 VECTOR_DEINIT(flist);
1071 al_string_deinit(&pname);
1074 pathlist = next;
1077 else if(ConfigValueExists(al_string_get_cstr(devname), NULL, "hrtf_tables"))
1078 ERR("The hrtf_tables option is deprecated, please use hrtf-paths instead.\n");
1080 if(usedefaults)
1082 vector_al_string flist;
1083 const ALubyte *rdata;
1084 size_t rsize;
1086 flist = SearchDataFiles(".mhr", "openal/hrtf");
1087 VECTOR_FOR_EACH_PARAMS(al_string, flist, AddFileEntry, &list);
1088 VECTOR_DEINIT(flist);
1090 rdata = GetResource(IDR_DEFAULT_44100_MHR, &rsize);
1091 if(rdata != NULL && rsize > 0)
1093 al_string ename = AL_STRING_INIT_STATIC();
1094 al_string_copy_cstr(&ename, "Built-In 44100hz");
1095 AddBuiltInEntry(&list, rdata, rsize, &ename);
1098 rdata = GetResource(IDR_DEFAULT_48000_MHR, &rsize);
1099 if(rdata != NULL && rsize > 0)
1101 al_string ename = AL_STRING_INIT_STATIC();
1102 al_string_copy_cstr(&ename, "Built-In 48000hz");
1103 AddBuiltInEntry(&list, rdata, rsize, &ename);
1107 if(VECTOR_SIZE(list) > 1 && ConfigValueStr(al_string_get_cstr(devname), NULL, "default-hrtf", &defaulthrtf))
1109 const HrtfEntry *iter;
1110 /* Find the preferred HRTF and move it to the front of the list. */
1111 #define FIND_ENTRY(i) (al_string_cmp_cstr((i)->name, defaulthrtf) == 0)
1112 VECTOR_FIND_IF(iter, const HrtfEntry, list, FIND_ENTRY);
1113 if(iter != VECTOR_END(list) && iter != VECTOR_BEGIN(list))
1115 HrtfEntry entry = *iter;
1116 memmove(&VECTOR_ELEM(list,1), &VECTOR_ELEM(list,0),
1117 (iter-VECTOR_BEGIN(list))*sizeof(HrtfEntry));
1118 VECTOR_ELEM(list,0) = entry;
1120 else
1121 WARN("Failed to find default HRTF \"%s\"\n", defaulthrtf);
1122 #undef FIND_ENTRY
1125 return list;
1128 void FreeHrtfList(vector_HrtfEntry *list)
1130 #define CLEAR_ENTRY(i) do { \
1131 al_string_deinit(&(i)->name); \
1132 } while(0)
1133 VECTOR_FOR_EACH(HrtfEntry, *list, CLEAR_ENTRY);
1134 VECTOR_DEINIT(*list);
1135 #undef CLEAR_ENTRY
1139 void FreeHrtfs(void)
1141 struct Hrtf *Hrtf = LoadedHrtfs;
1142 LoadedHrtfs = NULL;
1144 while(Hrtf != NULL)
1146 struct Hrtf *next = Hrtf->next;
1147 al_free(Hrtf);
1148 Hrtf = next;