Remove the last use of ALfilterState_processSingle
[openal-soft.git] / Alc / hrtf.c
blob9e927e4f9339e729507f37f86f97a4d01e2db87a
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 static struct Hrtf *LoadHrtf00(FILE *f, const_al_string filename)
177 const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
178 struct Hrtf *Hrtf = NULL;
179 ALboolean failed = AL_FALSE;
180 ALuint rate = 0, irCount = 0;
181 ALushort irSize = 0;
182 ALubyte evCount = 0;
183 ALubyte *azCount = NULL;
184 ALushort *evOffset = NULL;
185 ALshort *coeffs = NULL;
186 ALubyte *delays = NULL;
187 ALuint i, j;
189 rate = fgetc(f);
190 rate |= fgetc(f)<<8;
191 rate |= fgetc(f)<<16;
192 rate |= fgetc(f)<<24;
194 irCount = fgetc(f);
195 irCount |= fgetc(f)<<8;
197 irSize = fgetc(f);
198 irSize |= fgetc(f)<<8;
200 evCount = fgetc(f);
202 if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
204 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
205 irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE);
206 failed = AL_TRUE;
208 if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT)
210 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
211 evCount, MIN_EV_COUNT, MAX_EV_COUNT);
212 failed = AL_TRUE;
215 if(failed)
216 return NULL;
218 azCount = malloc(sizeof(azCount[0])*evCount);
219 evOffset = malloc(sizeof(evOffset[0])*evCount);
220 if(azCount == NULL || evOffset == NULL)
222 ERR("Out of memory.\n");
223 failed = AL_TRUE;
226 if(!failed)
228 evOffset[0] = fgetc(f);
229 evOffset[0] |= fgetc(f)<<8;
230 for(i = 1;i < evCount;i++)
232 evOffset[i] = fgetc(f);
233 evOffset[i] |= fgetc(f)<<8;
234 if(evOffset[i] <= evOffset[i-1])
236 ERR("Invalid evOffset: evOffset[%d]=%d (last=%d)\n",
237 i, evOffset[i], evOffset[i-1]);
238 failed = AL_TRUE;
241 azCount[i-1] = evOffset[i] - evOffset[i-1];
242 if(azCount[i-1] < MIN_AZ_COUNT || azCount[i-1] > MAX_AZ_COUNT)
244 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
245 i-1, azCount[i-1], MIN_AZ_COUNT, MAX_AZ_COUNT);
246 failed = AL_TRUE;
249 if(irCount <= evOffset[i-1])
251 ERR("Invalid evOffset: evOffset[%d]=%d (irCount=%d)\n",
252 i-1, evOffset[i-1], irCount);
253 failed = AL_TRUE;
256 azCount[i-1] = irCount - evOffset[i-1];
257 if(azCount[i-1] < MIN_AZ_COUNT || azCount[i-1] > MAX_AZ_COUNT)
259 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
260 i-1, azCount[i-1], MIN_AZ_COUNT, MAX_AZ_COUNT);
261 failed = AL_TRUE;
265 if(!failed)
267 coeffs = malloc(sizeof(coeffs[0])*irSize*irCount);
268 delays = malloc(sizeof(delays[0])*irCount);
269 if(coeffs == NULL || delays == NULL)
271 ERR("Out of memory.\n");
272 failed = AL_TRUE;
276 if(!failed)
278 for(i = 0;i < irCount*irSize;i+=irSize)
280 for(j = 0;j < irSize;j++)
282 ALshort coeff;
283 coeff = fgetc(f);
284 coeff |= fgetc(f)<<8;
285 coeffs[i+j] = coeff;
288 for(i = 0;i < irCount;i++)
290 delays[i] = fgetc(f);
291 if(delays[i] > maxDelay)
293 ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i], maxDelay);
294 failed = AL_TRUE;
298 if(feof(f))
300 ERR("Premature end of data\n");
301 failed = AL_TRUE;
305 if(!failed)
307 size_t total = sizeof(struct Hrtf);
308 total += sizeof(azCount[0])*evCount;
309 total += sizeof(evOffset[0])*evCount;
310 total += sizeof(coeffs[0])*irSize*irCount;
311 total += sizeof(delays[0])*irCount;
312 total += al_string_length(filename)+1;
314 Hrtf = al_calloc(16, total);
315 if(Hrtf == NULL)
317 ERR("Out of memory.\n");
318 failed = AL_TRUE;
322 if(!failed)
324 Hrtf->sampleRate = rate;
325 Hrtf->irSize = irSize;
326 Hrtf->evCount = evCount;
327 Hrtf->azCount = ((ALubyte*)(Hrtf+1));
328 Hrtf->evOffset = ((ALushort*)(Hrtf->azCount + evCount));
329 Hrtf->coeffs = ((ALshort*)(Hrtf->evOffset + evCount));
330 Hrtf->delays = ((ALubyte*)(Hrtf->coeffs + irSize*irCount));
331 Hrtf->filename = ((char*)(Hrtf->delays + irCount));
332 Hrtf->next = NULL;
334 memcpy((void*)Hrtf->azCount, azCount, sizeof(azCount[0])*evCount);
335 memcpy((void*)Hrtf->evOffset, evOffset, sizeof(evOffset[0])*evCount);
336 memcpy((void*)Hrtf->coeffs, coeffs, sizeof(coeffs[0])*irSize*irCount);
337 memcpy((void*)Hrtf->delays, delays, sizeof(delays[0])*irCount);
338 memcpy((void*)Hrtf->filename, al_string_get_cstr(filename), al_string_length(filename)+1);
341 free(azCount);
342 free(evOffset);
343 free(coeffs);
344 free(delays);
345 return Hrtf;
348 static struct Hrtf *LoadHrtf01(FILE *f, const_al_string filename)
350 const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
351 struct Hrtf *Hrtf = NULL;
352 ALboolean failed = AL_FALSE;
353 ALuint rate = 0, irCount = 0;
354 ALubyte irSize = 0, evCount = 0;
355 ALubyte *azCount = NULL;
356 ALushort *evOffset = NULL;
357 ALshort *coeffs = NULL;
358 ALubyte *delays = NULL;
359 ALuint i, j;
361 rate = fgetc(f);
362 rate |= fgetc(f)<<8;
363 rate |= fgetc(f)<<16;
364 rate |= fgetc(f)<<24;
366 irSize = fgetc(f);
368 evCount = fgetc(f);
370 if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
372 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
373 irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE);
374 failed = AL_TRUE;
376 if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT)
378 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
379 evCount, MIN_EV_COUNT, MAX_EV_COUNT);
380 failed = AL_TRUE;
383 if(failed)
384 return NULL;
386 azCount = malloc(sizeof(azCount[0])*evCount);
387 evOffset = malloc(sizeof(evOffset[0])*evCount);
388 if(azCount == NULL || evOffset == NULL)
390 ERR("Out of memory.\n");
391 failed = AL_TRUE;
394 if(!failed)
396 for(i = 0;i < evCount;i++)
398 azCount[i] = fgetc(f);
399 if(azCount[i] < MIN_AZ_COUNT || azCount[i] > MAX_AZ_COUNT)
401 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
402 i, azCount[i], MIN_AZ_COUNT, MAX_AZ_COUNT);
403 failed = AL_TRUE;
408 if(!failed)
410 evOffset[0] = 0;
411 irCount = azCount[0];
412 for(i = 1;i < evCount;i++)
414 evOffset[i] = evOffset[i-1] + azCount[i-1];
415 irCount += azCount[i];
418 coeffs = malloc(sizeof(coeffs[0])*irSize*irCount);
419 delays = malloc(sizeof(delays[0])*irCount);
420 if(coeffs == NULL || delays == NULL)
422 ERR("Out of memory.\n");
423 failed = AL_TRUE;
427 if(!failed)
429 for(i = 0;i < irCount*irSize;i+=irSize)
431 for(j = 0;j < irSize;j++)
433 ALshort coeff;
434 coeff = fgetc(f);
435 coeff |= fgetc(f)<<8;
436 coeffs[i+j] = coeff;
439 for(i = 0;i < irCount;i++)
441 delays[i] = fgetc(f);
442 if(delays[i] > maxDelay)
444 ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i], maxDelay);
445 failed = AL_TRUE;
449 if(feof(f))
451 ERR("Premature end of data\n");
452 failed = AL_TRUE;
456 if(!failed)
458 size_t total = sizeof(struct Hrtf);
459 total += sizeof(azCount[0])*evCount;
460 total += sizeof(evOffset[0])*evCount;
461 total += sizeof(coeffs[0])*irSize*irCount;
462 total += sizeof(delays[0])*irCount;
463 total += al_string_length(filename)+1;
465 Hrtf = al_calloc(16, total);
466 if(Hrtf == NULL)
468 ERR("Out of memory.\n");
469 failed = AL_TRUE;
473 if(!failed)
475 Hrtf->sampleRate = rate;
476 Hrtf->irSize = irSize;
477 Hrtf->evCount = evCount;
478 Hrtf->azCount = ((ALubyte*)(Hrtf+1));
479 Hrtf->evOffset = ((ALushort*)(Hrtf->azCount + evCount));
480 Hrtf->coeffs = ((ALshort*)(Hrtf->evOffset + evCount));
481 Hrtf->delays = ((ALubyte*)(Hrtf->coeffs + irSize*irCount));
482 Hrtf->filename = ((char*)(Hrtf->delays + irCount));
483 Hrtf->next = NULL;
485 memcpy((void*)Hrtf->azCount, azCount, sizeof(azCount[0])*evCount);
486 memcpy((void*)Hrtf->evOffset, evOffset, sizeof(evOffset[0])*evCount);
487 memcpy((void*)Hrtf->coeffs, coeffs, sizeof(coeffs[0])*irSize*irCount);
488 memcpy((void*)Hrtf->delays, delays, sizeof(delays[0])*irCount);
489 memcpy((void*)Hrtf->filename, al_string_get_cstr(filename), al_string_length(filename)+1);
492 free(azCount);
493 free(evOffset);
494 free(coeffs);
495 free(delays);
496 return Hrtf;
499 static void AddFileEntry(vector_HrtfEntry *list, al_string *filename)
501 HrtfEntry entry = { AL_STRING_INIT_STATIC(), NULL };
502 struct Hrtf *hrtf = NULL;
503 const HrtfEntry *iter;
504 const char *name;
505 const char *ext;
506 ALchar magic[8];
507 FILE *f;
508 int i;
510 name = strrchr(al_string_get_cstr(*filename), '/');
511 if(!name) name = strrchr(al_string_get_cstr(*filename), '\\');
512 if(!name) name = al_string_get_cstr(*filename);
513 else ++name;
515 #define MATCH_FNAME(i) (al_string_cmp_cstr(*filename, (i)->hrtf->filename) == 0)
516 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_FNAME);
517 if(iter != VECTOR_END(*list))
519 TRACE("Skipping duplicate file entry %s\n", al_string_get_cstr(*filename));
520 goto done;
522 #undef MATCH_FNAME
524 entry.hrtf = LoadedHrtfs;
525 while(entry.hrtf)
527 if(al_string_cmp_cstr(*filename, entry.hrtf->filename) == 0)
529 TRACE("Skipping load of already-loaded file %s\n", al_string_get_cstr(*filename));
530 goto skip_load;
532 entry.hrtf = entry.hrtf->next;
535 TRACE("Loading %s...\n", al_string_get_cstr(*filename));
536 f = al_fopen(al_string_get_cstr(*filename), "rb");
537 if(f == NULL)
539 ERR("Could not open %s\n", al_string_get_cstr(*filename));
540 goto done;
543 if(fread(magic, 1, sizeof(magic), f) != sizeof(magic))
544 ERR("Failed to read header from %s\n", al_string_get_cstr(*filename));
545 else
547 if(memcmp(magic, magicMarker00, sizeof(magicMarker00)) == 0)
549 TRACE("Detected data set format v0\n");
550 hrtf = LoadHrtf00(f, *filename);
552 else if(memcmp(magic, magicMarker01, sizeof(magicMarker01)) == 0)
554 TRACE("Detected data set format v1\n");
555 hrtf = LoadHrtf01(f, *filename);
557 else
558 ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(*filename), magic);
560 fclose(f);
562 if(!hrtf)
564 ERR("Failed to load %s\n", al_string_get_cstr(*filename));
565 goto done;
568 hrtf->next = LoadedHrtfs;
569 LoadedHrtfs = hrtf;
570 TRACE("Loaded HRTF support for format: %s %uhz\n",
571 DevFmtChannelsString(DevFmtStereo), hrtf->sampleRate);
572 entry.hrtf = hrtf;
574 skip_load:
575 /* TODO: Get a human-readable name from the HRTF data (possibly coming in a
576 * format update). */
577 ext = strrchr(name, '.');
579 i = 0;
580 do {
581 if(!ext)
582 al_string_copy_cstr(&entry.name, name);
583 else
584 al_string_copy_range(&entry.name, name, ext);
585 if(i != 0)
587 char str[64];
588 snprintf(str, sizeof(str), " #%d", i+1);
589 al_string_append_cstr(&entry.name, str);
591 ++i;
593 #define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0)
594 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_NAME);
595 #undef MATCH_NAME
596 } while(iter != VECTOR_END(*list));
598 TRACE("Adding entry \"%s\" from file \"%s\"\n", al_string_get_cstr(entry.name),
599 al_string_get_cstr(*filename));
600 VECTOR_PUSH_BACK(*list, entry);
602 done:
603 al_string_deinit(filename);
607 /* Unfortunate that we have to duplicate LoadHrtf01 like this, to take a memory
608 * buffer for input instead of a FILE*, but there's no portable way to access a
609 * memory buffer through the standard FILE* I/O API (POSIX 2008 has fmemopen,
610 * and Windows doesn't seem to have anything).
612 static struct Hrtf *LoadBuiltInHrtf01(const ALubyte *data, size_t datalen, const_al_string filename)
614 const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
615 struct Hrtf *Hrtf = NULL;
616 ALboolean failed = AL_FALSE;
617 ALuint rate = 0, irCount = 0;
618 ALubyte irSize = 0, evCount = 0;
619 const ALubyte *azCount = NULL;
620 ALushort *evOffset = NULL;
621 ALshort *coeffs = NULL;
622 const ALubyte *delays = NULL;
623 ALuint i, j;
625 if(datalen < 6)
627 ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n",
628 al_string_get_cstr(filename), 6, datalen);
629 return NULL;
632 rate = *(data++);
633 rate |= *(data++)<<8;
634 rate |= *(data++)<<16;
635 rate |= *(data++)<<24;
636 datalen -= 4;
638 irSize = *(data++);
639 datalen -= 1;
641 evCount = *(data++);
642 datalen -= 1;
644 if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
646 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
647 irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE);
648 failed = AL_TRUE;
650 if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT)
652 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
653 evCount, MIN_EV_COUNT, MAX_EV_COUNT);
654 failed = AL_TRUE;
656 if(failed)
657 return NULL;
659 if(datalen < evCount)
661 ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n",
662 al_string_get_cstr(filename), evCount, datalen);
663 return NULL;
666 azCount = data;
667 data += evCount;
668 datalen -= evCount;
670 evOffset = malloc(sizeof(evOffset[0])*evCount);
671 if(azCount == NULL || evOffset == NULL)
673 ERR("Out of memory.\n");
674 failed = AL_TRUE;
677 if(!failed)
679 for(i = 0;i < evCount;i++)
681 if(azCount[i] < MIN_AZ_COUNT || azCount[i] > MAX_AZ_COUNT)
683 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
684 i, azCount[i], MIN_AZ_COUNT, MAX_AZ_COUNT);
685 failed = AL_TRUE;
690 if(!failed)
692 evOffset[0] = 0;
693 irCount = azCount[0];
694 for(i = 1;i < evCount;i++)
696 evOffset[i] = evOffset[i-1] + azCount[i-1];
697 irCount += azCount[i];
700 coeffs = malloc(sizeof(coeffs[0])*irSize*irCount);
701 if(coeffs == NULL)
703 ERR("Out of memory.\n");
704 failed = AL_TRUE;
708 if(!failed)
710 size_t reqsize = 2*irSize*irCount + irCount;
711 if(datalen < reqsize)
713 ERR("Unexpected end of %s data (req "SZFMT", rem "SZFMT"\n",
714 al_string_get_cstr(filename), reqsize, datalen);
715 failed = AL_TRUE;
719 if(!failed)
721 for(i = 0;i < irCount*irSize;i+=irSize)
723 for(j = 0;j < irSize;j++)
725 ALshort coeff;
726 coeff = *(data++);
727 coeff |= *(data++)<<8;
728 datalen -= 2;
729 coeffs[i+j] = coeff;
733 delays = data;
734 data += irCount;
735 datalen -= irCount;
736 for(i = 0;i < irCount;i++)
738 if(delays[i] > maxDelay)
740 ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i], maxDelay);
741 failed = AL_TRUE;
746 if(!failed)
748 size_t total = sizeof(struct Hrtf);
749 total += sizeof(azCount[0])*evCount;
750 total += sizeof(evOffset[0])*evCount;
751 total += sizeof(coeffs[0])*irSize*irCount;
752 total += sizeof(delays[0])*irCount;
753 total += al_string_length(filename)+1;
755 Hrtf = al_calloc(16, total);
756 if(Hrtf == NULL)
758 ERR("Out of memory.\n");
759 failed = AL_TRUE;
763 if(!failed)
765 Hrtf->sampleRate = rate;
766 Hrtf->irSize = irSize;
767 Hrtf->evCount = evCount;
768 Hrtf->azCount = ((ALubyte*)(Hrtf+1));
769 Hrtf->evOffset = ((ALushort*)(Hrtf->azCount + evCount));
770 Hrtf->coeffs = ((ALshort*)(Hrtf->evOffset + evCount));
771 Hrtf->delays = ((ALubyte*)(Hrtf->coeffs + irSize*irCount));
772 Hrtf->filename = ((char*)(Hrtf->delays + irCount));
773 Hrtf->next = NULL;
775 memcpy((void*)Hrtf->azCount, azCount, sizeof(azCount[0])*evCount);
776 memcpy((void*)Hrtf->evOffset, evOffset, sizeof(evOffset[0])*evCount);
777 memcpy((void*)Hrtf->coeffs, coeffs, sizeof(coeffs[0])*irSize*irCount);
778 memcpy((void*)Hrtf->delays, delays, sizeof(delays[0])*irCount);
779 memcpy((void*)Hrtf->filename, al_string_get_cstr(filename), al_string_length(filename)+1);
782 free(evOffset);
783 free(coeffs);
784 return Hrtf;
787 /* Another unfortunate duplication, this time of AddFileEntry to take a memory
788 * buffer for input instead of opening the given filename.
790 static void AddBuiltInEntry(vector_HrtfEntry *list, const ALubyte *data, size_t datalen, al_string *filename)
792 HrtfEntry entry = { AL_STRING_INIT_STATIC(), NULL };
793 struct Hrtf *hrtf = NULL;
794 const HrtfEntry *iter;
795 int i;
797 #define MATCH_FNAME(i) (al_string_cmp_cstr(*filename, (i)->hrtf->filename) == 0)
798 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_FNAME);
799 if(iter != VECTOR_END(*list))
801 TRACE("Skipping duplicate file entry %s\n", al_string_get_cstr(*filename));
802 goto done;
804 #undef MATCH_FNAME
806 entry.hrtf = LoadedHrtfs;
807 while(entry.hrtf)
809 if(al_string_cmp_cstr(*filename, entry.hrtf->filename) == 0)
811 TRACE("Skipping load of already-loaded file %s\n", al_string_get_cstr(*filename));
812 goto skip_load;
814 entry.hrtf = entry.hrtf->next;
817 TRACE("Loading %s...\n", al_string_get_cstr(*filename));
818 if(datalen < sizeof(magicMarker01))
820 ERR("%s data is too short ("SZFMT" bytes)\n", al_string_get_cstr(*filename), datalen);
821 goto done;
824 if(memcmp(data, magicMarker01, sizeof(magicMarker01)) == 0)
826 TRACE("Detected data set format v1\n");
827 hrtf = LoadBuiltInHrtf01(
828 data+sizeof(magicMarker01), datalen-sizeof(magicMarker01),
829 *filename
832 else
833 ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(*filename), data);
835 if(!hrtf)
837 ERR("Failed to load %s\n", al_string_get_cstr(*filename));
838 goto done;
841 hrtf->next = LoadedHrtfs;
842 LoadedHrtfs = hrtf;
843 TRACE("Loaded HRTF support for format: %s %uhz\n",
844 DevFmtChannelsString(DevFmtStereo), hrtf->sampleRate);
845 entry.hrtf = hrtf;
847 skip_load:
848 i = 0;
849 do {
850 al_string_copy(&entry.name, *filename);
851 if(i != 0)
853 char str[64];
854 snprintf(str, sizeof(str), " #%d", i+1);
855 al_string_append_cstr(&entry.name, str);
857 ++i;
859 #define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0)
860 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_NAME);
861 #undef MATCH_NAME
862 } while(iter != VECTOR_END(*list));
864 TRACE("Adding built-in entry \"%s\"\n", al_string_get_cstr(entry.name));
865 VECTOR_PUSH_BACK(*list, entry);
867 done:
868 al_string_deinit(filename);
872 #ifndef ALSOFT_EMBED_HRTF_DATA
873 #define IDR_DEFAULT_44100_MHR 0
874 #define IDR_DEFAULT_48000_MHR 1
876 static const ALubyte *GetResource(int UNUSED(name), size_t *size)
878 *size = 0;
879 return NULL;
882 #else
883 #include "hrtf_res.h"
885 #ifdef _WIN32
886 static const ALubyte *GetResource(int name, size_t *size)
888 HMODULE handle;
889 HGLOBAL res;
890 HRSRC rc;
892 GetModuleHandleExW(
893 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
894 (LPCWSTR)GetResource, &handle
896 rc = FindResourceW(handle, MAKEINTRESOURCEW(name), MAKEINTRESOURCEW(MHRTYPE));
897 res = LoadResource(handle, rc);
899 *size = SizeofResource(handle, rc);
900 return LockResource(res);
903 #else
905 extern const ALubyte _binary_default_44100_mhr_start[] HIDDEN_DECL;
906 extern const ALubyte _binary_default_44100_mhr_end[] HIDDEN_DECL;
907 extern const ALubyte _binary_default_44100_mhr_size[] HIDDEN_DECL;
909 extern const ALubyte _binary_default_48000_mhr_start[] HIDDEN_DECL;
910 extern const ALubyte _binary_default_48000_mhr_end[] HIDDEN_DECL;
911 extern const ALubyte _binary_default_48000_mhr_size[] HIDDEN_DECL;
913 static const ALubyte *GetResource(int name, size_t *size)
915 if(name == IDR_DEFAULT_44100_MHR)
917 /* Make sure all symbols are referenced, to ensure the compiler won't
918 * ignore the declarations and lose the visibility attribute used to
919 * hide them (would be nice if ld or objcopy could automatically mark
920 * them as hidden when generating them, but apparently they can't).
922 const void *volatile ptr =_binary_default_44100_mhr_size;
923 (void)ptr;
924 *size = _binary_default_44100_mhr_end - _binary_default_44100_mhr_start;
925 return _binary_default_44100_mhr_start;
927 if(name == IDR_DEFAULT_48000_MHR)
929 const void *volatile ptr =_binary_default_48000_mhr_size;
930 (void)ptr;
931 *size = _binary_default_48000_mhr_end - _binary_default_48000_mhr_start;
932 return _binary_default_48000_mhr_start;
934 *size = 0;
935 return NULL;
937 #endif
938 #endif
940 vector_HrtfEntry EnumerateHrtf(const_al_string devname)
942 vector_HrtfEntry list = VECTOR_INIT_STATIC();
943 const char *defaulthrtf = "";
944 const char *pathlist = "";
945 bool usedefaults = true;
947 if(ConfigValueStr(al_string_get_cstr(devname), NULL, "hrtf-paths", &pathlist))
949 while(pathlist && *pathlist)
951 const char *next, *end;
953 while(isspace(*pathlist) || *pathlist == ',')
954 pathlist++;
955 if(*pathlist == '\0')
956 continue;
958 next = strchr(pathlist, ',');
959 if(next)
960 end = next++;
961 else
963 end = pathlist + strlen(pathlist);
964 usedefaults = false;
967 while(end != pathlist && isspace(*(end-1)))
968 --end;
969 if(end != pathlist)
971 al_string pname = AL_STRING_INIT_STATIC();
972 vector_al_string flist;
974 al_string_append_range(&pname, pathlist, end);
976 flist = SearchDataFiles(".mhr", al_string_get_cstr(pname));
977 VECTOR_FOR_EACH_PARAMS(al_string, flist, AddFileEntry, &list);
978 VECTOR_DEINIT(flist);
980 al_string_deinit(&pname);
983 pathlist = next;
986 else if(ConfigValueExists(al_string_get_cstr(devname), NULL, "hrtf_tables"))
987 ERR("The hrtf_tables option is deprecated, please use hrtf-paths instead.\n");
989 if(usedefaults)
991 vector_al_string flist;
992 const ALubyte *rdata;
993 size_t rsize;
995 flist = SearchDataFiles(".mhr", "openal/hrtf");
996 VECTOR_FOR_EACH_PARAMS(al_string, flist, AddFileEntry, &list);
997 VECTOR_DEINIT(flist);
999 rdata = GetResource(IDR_DEFAULT_44100_MHR, &rsize);
1000 if(rdata != NULL && rsize > 0)
1002 al_string ename = AL_STRING_INIT_STATIC();
1003 al_string_copy_cstr(&ename, "Built-In 44100hz");
1004 AddBuiltInEntry(&list, rdata, rsize, &ename);
1007 rdata = GetResource(IDR_DEFAULT_48000_MHR, &rsize);
1008 if(rdata != NULL && rsize > 0)
1010 al_string ename = AL_STRING_INIT_STATIC();
1011 al_string_copy_cstr(&ename, "Built-In 48000hz");
1012 AddBuiltInEntry(&list, rdata, rsize, &ename);
1016 if(VECTOR_SIZE(list) > 1 && ConfigValueStr(al_string_get_cstr(devname), NULL, "default-hrtf", &defaulthrtf))
1018 const HrtfEntry *iter;
1019 /* Find the preferred HRTF and move it to the front of the list. */
1020 #define FIND_ENTRY(i) (al_string_cmp_cstr((i)->name, defaulthrtf) == 0)
1021 VECTOR_FIND_IF(iter, const HrtfEntry, list, FIND_ENTRY);
1022 if(iter != VECTOR_END(list) && iter != VECTOR_BEGIN(list))
1024 HrtfEntry entry = *iter;
1025 memmove(&VECTOR_ELEM(list,1), &VECTOR_ELEM(list,0),
1026 (iter-VECTOR_BEGIN(list))*sizeof(HrtfEntry));
1027 VECTOR_ELEM(list,0) = entry;
1029 else
1030 WARN("Failed to find default HRTF \"%s\"\n", defaulthrtf);
1031 #undef FIND_ENTRY
1034 return list;
1037 void FreeHrtfList(vector_HrtfEntry *list)
1039 #define CLEAR_ENTRY(i) do { \
1040 al_string_deinit(&(i)->name); \
1041 } while(0)
1042 VECTOR_FOR_EACH(HrtfEntry, *list, CLEAR_ENTRY);
1043 VECTOR_DEINIT(*list);
1044 #undef CLEAR_ENTRY
1048 void FreeHrtfs(void)
1050 struct Hrtf *Hrtf = LoadedHrtfs;
1051 LoadedHrtfs = NULL;
1053 while(Hrtf != NULL)
1055 struct Hrtf *next = Hrtf->next;
1056 al_free(Hrtf);
1057 Hrtf = next;