Rename al_string_* functions to alstr_*
[openal-soft.git] / Alc / hrtf.c
blob4634e6eb470508ee9a752ca7fd9e427a547de294
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 "bformatdec.h"
32 #include "hrtf.h"
34 #include "compat.h"
35 #include "almalloc.h"
38 /* Current data set limits defined by the makehrtf utility. */
39 #define MIN_IR_SIZE (8)
40 #define MAX_IR_SIZE (128)
41 #define MOD_IR_SIZE (8)
43 #define MIN_EV_COUNT (5)
44 #define MAX_EV_COUNT (128)
46 #define MIN_AZ_COUNT (1)
47 #define MAX_AZ_COUNT (128)
49 static const ALchar magicMarker00[8] = "MinPHR00";
50 static const ALchar magicMarker01[8] = "MinPHR01";
52 /* First value for pass-through coefficients (remaining are 0), used for omni-
53 * directional sounds. */
54 static const ALfloat PassthruCoeff = 0.707106781187f/*sqrt(0.5)*/;
56 static struct Hrtf *LoadedHrtfs = NULL;
59 /* Calculate the elevation index given the polar elevation in radians. This
60 * will return an index between 0 and (evcount - 1). Assumes the FPU is in
61 * round-to-zero mode.
63 static ALsizei CalcEvIndex(ALsizei evcount, ALfloat ev)
65 ev = (F_PI_2 + ev) * (evcount-1) / F_PI;
66 return mini(fastf2i(ev + 0.5f), evcount-1);
69 /* Calculate the azimuth index given the polar azimuth in radians. This will
70 * return an index between 0 and (azcount - 1). Assumes the FPU is in round-to-
71 * zero mode.
73 static ALsizei CalcAzIndex(ALsizei azcount, ALfloat az)
75 az = (F_TAU + az) * azcount / F_TAU;
76 return fastf2i(az + 0.5f) % azcount;
79 /* Calculates static HRIR coefficients and delays for the given polar elevation
80 * and azimuth in radians. The coefficients are normalized.
82 void GetHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat spread, ALfloat (*coeffs)[2], ALsizei *delays)
84 ALsizei evidx, azidx, lidx, ridx;
85 ALsizei azcount, evoffset;
86 ALfloat dirfact;
87 ALsizei i;
89 dirfact = 1.0f - (spread / F_TAU);
91 /* Claculate elevation index. */
92 evidx = CalcEvIndex(Hrtf->evCount, elevation);
93 azcount = Hrtf->azCount[evidx];
94 evoffset = Hrtf->evOffset[evidx];
96 /* Calculate azimuth index. */
97 azidx = CalcAzIndex(Hrtf->azCount[evidx], azimuth);
99 /* Calculate the HRIR indices for left and right channels. */
100 lidx = evoffset + azidx;
101 ridx = evoffset + ((azcount-azidx) % azcount);
103 /* Calculate the HRIR delays. */
104 delays[0] = fastf2i(Hrtf->delays[lidx]*dirfact + 0.5f);
105 delays[1] = fastf2i(Hrtf->delays[ridx]*dirfact + 0.5f);
107 /* Calculate the sample offsets for the HRIR indices. */
108 lidx *= Hrtf->irSize;
109 ridx *= Hrtf->irSize;
111 /* Calculate the normalized and attenuated HRIR coefficients. */
112 i = 0;
113 coeffs[i][0] = lerp(PassthruCoeff, Hrtf->coeffs[lidx+i], dirfact);
114 coeffs[i][1] = lerp(PassthruCoeff, Hrtf->coeffs[ridx+i], dirfact);
115 for(i = 1;i < Hrtf->irSize;i++)
117 coeffs[i][0] = Hrtf->coeffs[lidx+i] * dirfact;
118 coeffs[i][1] = Hrtf->coeffs[ridx+i] * dirfact;
123 ALsizei BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, ALsizei NumChannels, const ALfloat (*restrict AmbiPoints)[2], const ALfloat (*restrict AmbiMatrix)[2][MAX_AMBI_COEFFS], ALsizei AmbiCount)
125 /* Set this to 2 for dual-band HRTF processing. May require a higher quality
126 * band-splitter, or better calculation of the new IR length to deal with the
127 * tail generated by the filter.
129 #define NUM_BANDS 2
130 BandSplitter splitter;
131 ALsizei lidx[HRTF_AMBI_MAX_CHANNELS], ridx[HRTF_AMBI_MAX_CHANNELS];
132 ALsizei min_delay = HRTF_HISTORY_LENGTH;
133 ALfloat temps[3][HRIR_LENGTH];
134 ALsizei max_length = 0;
135 ALsizei i, c, b;
137 for(c = 0;c < AmbiCount;c++)
139 ALuint evidx, azidx;
140 ALuint evoffset;
141 ALuint azcount;
143 /* Calculate elevation index. */
144 evidx = (ALsizei)floorf((F_PI_2 + AmbiPoints[c][0]) *
145 (Hrtf->evCount-1)/F_PI + 0.5f);
146 evidx = mini(evidx, Hrtf->evCount-1);
148 azcount = Hrtf->azCount[evidx];
149 evoffset = Hrtf->evOffset[evidx];
151 /* Calculate azimuth index for this elevation. */
152 azidx = (ALsizei)floorf((F_TAU+AmbiPoints[c][1]) *
153 azcount/F_TAU + 0.5f) % azcount;
155 /* Calculate indices for left and right channels. */
156 lidx[c] = evoffset + azidx;
157 ridx[c] = evoffset + ((azcount-azidx) % azcount);
159 min_delay = mini(min_delay, mini(Hrtf->delays[lidx[c]], Hrtf->delays[ridx[c]]));
162 memset(temps, 0, sizeof(temps));
163 bandsplit_init(&splitter, 400.0f / (ALfloat)Hrtf->sampleRate);
164 for(c = 0;c < AmbiCount;c++)
166 const ALfloat *fir;
167 ALsizei delay;
169 /* Add to the left output coefficients with the specified delay. */
170 fir = &Hrtf->coeffs[lidx[c] * Hrtf->irSize];
171 delay = Hrtf->delays[lidx[c]] - min_delay;
172 if(NUM_BANDS == 1)
174 for(i = 0;i < NumChannels;++i)
176 ALsizei j = delay, k = 0;
177 while(j < HRIR_LENGTH && k < Hrtf->irSize)
178 state->Chan[i].Coeffs[j++][0] += fir[k++] * AmbiMatrix[c][0][i];
181 else
183 /* Band-split left HRIR into low and high frequency responses. */
184 bandsplit_clear(&splitter);
185 for(i = 0;i < Hrtf->irSize;i++)
186 temps[2][i] = fir[i];
187 bandsplit_process(&splitter, temps[0], temps[1], temps[2], HRIR_LENGTH);
189 for(i = 0;i < NumChannels;++i)
191 for(b = 0;b < NUM_BANDS;b++)
193 ALsizei j = delay, k = 0;
194 while(j < HRIR_LENGTH)
195 state->Chan[i].Coeffs[j++][0] += temps[b][k++] * AmbiMatrix[c][b][i];
199 max_length = maxi(max_length, mini(delay + Hrtf->irSize, HRIR_LENGTH));
201 /* Add to the right output coefficients with the specified delay. */
202 fir = &Hrtf->coeffs[ridx[c] * Hrtf->irSize];
203 delay = Hrtf->delays[ridx[c]] - min_delay;
204 if(NUM_BANDS == 1)
206 for(i = 0;i < NumChannels;++i)
208 ALsizei j = delay, k = 0;
209 while(j < HRIR_LENGTH && k < Hrtf->irSize)
210 state->Chan[i].Coeffs[j++][1] += fir[k++] * AmbiMatrix[c][0][i];
213 else
215 /* Band-split right HRIR into low and high frequency responses. */
216 bandsplit_clear(&splitter);
217 for(i = 0;i < Hrtf->irSize;i++)
218 temps[2][i] = fir[i];
219 bandsplit_process(&splitter, temps[0], temps[1], temps[2], HRIR_LENGTH);
221 for(i = 0;i < NumChannels;++i)
223 for(b = 0;b < NUM_BANDS;b++)
225 ALsizei j = delay, k = 0;
226 while(j < HRIR_LENGTH)
227 state->Chan[i].Coeffs[j++][1] += temps[b][k++] * AmbiMatrix[c][b][i];
231 max_length = maxi(max_length, mini(delay + Hrtf->irSize, HRIR_LENGTH));
233 TRACE("Skipped min delay: %d, new combined length: %d\n", min_delay, max_length);
235 return max_length;
236 #undef NUM_BANDS
240 static struct Hrtf *CreateHrtfStore(ALuint rate, ALsizei irSize, ALsizei evCount, ALsizei irCount,
241 const ALubyte *azCount, const ALushort *evOffset,
242 const ALshort *coeffs, const ALubyte *delays,
243 const_al_string filename)
245 struct Hrtf *Hrtf;
246 size_t total;
248 total = sizeof(struct Hrtf);
249 total += sizeof(Hrtf->azCount[0])*evCount;
250 total = RoundUp(total, sizeof(ALushort)); /* Align for ushort fields */
251 total += sizeof(Hrtf->evOffset[0])*evCount;
252 total = RoundUp(total, sizeof(ALfloat)); /* Align for float fields */
253 total += sizeof(Hrtf->coeffs[0])*irSize*irCount;
254 total += sizeof(Hrtf->delays[0])*irCount;
255 total += alstr_length(filename)+1;
257 Hrtf = al_calloc(16, total);
258 if(Hrtf == NULL)
259 ERR("Out of memory.\n");
260 else
262 uintptr_t offset = sizeof(struct Hrtf);
263 char *base = (char*)Hrtf;
264 ALushort *_evOffset;
265 ALubyte *_azCount;
266 ALubyte *_delays;
267 ALfloat *_coeffs;
268 char *_name;
269 ALsizei i;
271 Hrtf->sampleRate = rate;
272 Hrtf->irSize = irSize;
273 Hrtf->evCount = evCount;
275 /* Set up pointers to storage following the main HRTF struct. */
276 _azCount = (ALubyte*)(base + offset); Hrtf->azCount = _azCount;
277 offset += sizeof(_azCount[0])*evCount;
279 offset = RoundUp(offset, sizeof(ALushort)); /* Align for ushort fields */
280 _evOffset = (ALushort*)(base + offset); Hrtf->evOffset = _evOffset;
281 offset += sizeof(_evOffset[0])*evCount;
283 offset = RoundUp(offset, sizeof(ALfloat)); /* Align for float fields */
284 _coeffs = (ALfloat*)(base + offset); Hrtf->coeffs = _coeffs;
285 offset += sizeof(_coeffs[0])*irSize*irCount;
287 _delays = (ALubyte*)(base + offset); Hrtf->delays = _delays;
288 offset += sizeof(_delays[0])*irCount;
290 _name = (char*)(base + offset); Hrtf->filename = _name;
291 offset += sizeof(_name[0])*(alstr_length(filename)+1);
293 Hrtf->next = NULL;
295 /* Copy input data to storage. */
296 for(i = 0;i < evCount;i++) _azCount[i] = azCount[i];
297 for(i = 0;i < evCount;i++) _evOffset[i] = evOffset[i];
298 for(i = 0;i < irSize*irCount;i++)
299 _coeffs[i] = coeffs[i] / 32768.0f;
300 for(i = 0;i < irCount;i++) _delays[i] = delays[i];
301 for(i = 0;i < (ALsizei)alstr_length(filename);i++)
302 _name[i] = VECTOR_ELEM(filename, i);
303 _name[i] = '\0';
305 assert(offset == total);
308 return Hrtf;
311 static struct Hrtf *LoadHrtf00(const ALubyte *data, size_t datalen, const_al_string filename)
313 const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
314 struct Hrtf *Hrtf = NULL;
315 ALboolean failed = AL_FALSE;
316 ALuint rate = 0, irCount = 0;
317 ALushort irSize = 0;
318 ALubyte evCount = 0;
319 ALubyte *azCount = NULL;
320 ALushort *evOffset = NULL;
321 ALshort *coeffs = NULL;
322 const ALubyte *delays = NULL;
323 ALuint i, j;
325 if(datalen < 9)
327 ERR("Unexpected end of %s data (req %d, rem "SZFMT")\n",
328 alstr_get_cstr(filename), 9, datalen);
329 return NULL;
332 rate = *(data++);
333 rate |= *(data++)<<8;
334 rate |= *(data++)<<16;
335 rate |= *(data++)<<24;
336 datalen -= 4;
338 irCount = *(data++);
339 irCount |= *(data++)<<8;
340 datalen -= 2;
342 irSize = *(data++);
343 irSize |= *(data++)<<8;
344 datalen -= 2;
346 evCount = *(data++);
347 datalen -= 1;
349 if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
351 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
352 irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE);
353 failed = AL_TRUE;
355 if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT)
357 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
358 evCount, MIN_EV_COUNT, MAX_EV_COUNT);
359 failed = AL_TRUE;
361 if(failed)
362 return NULL;
364 if(datalen < evCount*2)
366 ERR("Unexpected end of %s data (req %d, rem "SZFMT")\n",
367 alstr_get_cstr(filename), evCount*2, datalen);
368 return NULL;
371 azCount = malloc(sizeof(azCount[0])*evCount);
372 evOffset = malloc(sizeof(evOffset[0])*evCount);
373 if(azCount == NULL || evOffset == NULL)
375 ERR("Out of memory.\n");
376 failed = AL_TRUE;
379 if(!failed)
381 evOffset[0] = *(data++);
382 evOffset[0] |= *(data++)<<8;
383 datalen -= 2;
384 for(i = 1;i < evCount;i++)
386 evOffset[i] = *(data++);
387 evOffset[i] |= *(data++)<<8;
388 datalen -= 2;
389 if(evOffset[i] <= evOffset[i-1])
391 ERR("Invalid evOffset: evOffset[%d]=%d (last=%d)\n",
392 i, evOffset[i], evOffset[i-1]);
393 failed = AL_TRUE;
396 azCount[i-1] = evOffset[i] - evOffset[i-1];
397 if(azCount[i-1] < MIN_AZ_COUNT || azCount[i-1] > MAX_AZ_COUNT)
399 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
400 i-1, azCount[i-1], MIN_AZ_COUNT, MAX_AZ_COUNT);
401 failed = AL_TRUE;
404 if(irCount <= evOffset[i-1])
406 ERR("Invalid evOffset: evOffset[%d]=%d (irCount=%d)\n",
407 i-1, evOffset[i-1], irCount);
408 failed = AL_TRUE;
411 azCount[i-1] = irCount - evOffset[i-1];
412 if(azCount[i-1] < MIN_AZ_COUNT || azCount[i-1] > MAX_AZ_COUNT)
414 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
415 i-1, azCount[i-1], MIN_AZ_COUNT, MAX_AZ_COUNT);
416 failed = AL_TRUE;
420 if(!failed)
422 coeffs = malloc(sizeof(coeffs[0])*irSize*irCount);
423 if(coeffs == NULL)
425 ERR("Out of memory.\n");
426 failed = AL_TRUE;
430 if(!failed)
432 size_t reqsize = 2*irSize*irCount + irCount;
433 if(datalen < reqsize)
435 ERR("Unexpected end of %s data (req "SZFMT", rem "SZFMT")\n",
436 alstr_get_cstr(filename), reqsize, datalen);
437 failed = AL_TRUE;
441 if(!failed)
443 for(i = 0;i < irCount*irSize;i+=irSize)
445 for(j = 0;j < irSize;j++)
447 coeffs[i+j] = *(data++);
448 coeffs[i+j] |= *(data++)<<8;
449 datalen -= 2;
453 delays = data;
454 data += irCount;
455 datalen -= irCount;
456 for(i = 0;i < irCount;i++)
458 if(delays[i] > maxDelay)
460 ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i], maxDelay);
461 failed = AL_TRUE;
466 if(!failed)
467 Hrtf = CreateHrtfStore(rate, irSize, evCount, irCount, azCount,
468 evOffset, coeffs, delays, filename);
470 free(azCount);
471 free(evOffset);
472 free(coeffs);
473 return Hrtf;
476 static struct Hrtf *LoadHrtf01(const ALubyte *data, size_t datalen, const_al_string filename)
478 const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
479 struct Hrtf *Hrtf = NULL;
480 ALboolean failed = AL_FALSE;
481 ALuint rate = 0, irCount = 0;
482 ALubyte irSize = 0, evCount = 0;
483 const ALubyte *azCount = NULL;
484 ALushort *evOffset = NULL;
485 ALshort *coeffs = NULL;
486 const ALubyte *delays = NULL;
487 ALuint i, j;
489 if(datalen < 6)
491 ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n",
492 alstr_get_cstr(filename), 6, datalen);
493 return NULL;
496 rate = *(data++);
497 rate |= *(data++)<<8;
498 rate |= *(data++)<<16;
499 rate |= *(data++)<<24;
500 datalen -= 4;
502 irSize = *(data++);
503 datalen -= 1;
505 evCount = *(data++);
506 datalen -= 1;
508 if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
510 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
511 irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE);
512 failed = AL_TRUE;
514 if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT)
516 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
517 evCount, MIN_EV_COUNT, MAX_EV_COUNT);
518 failed = AL_TRUE;
520 if(failed)
521 return NULL;
523 if(datalen < evCount)
525 ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n",
526 alstr_get_cstr(filename), evCount, datalen);
527 return NULL;
530 azCount = data;
531 data += evCount;
532 datalen -= evCount;
534 evOffset = malloc(sizeof(evOffset[0])*evCount);
535 if(azCount == NULL || evOffset == NULL)
537 ERR("Out of memory.\n");
538 failed = AL_TRUE;
541 if(!failed)
543 for(i = 0;i < evCount;i++)
545 if(azCount[i] < MIN_AZ_COUNT || azCount[i] > MAX_AZ_COUNT)
547 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
548 i, azCount[i], MIN_AZ_COUNT, MAX_AZ_COUNT);
549 failed = AL_TRUE;
554 if(!failed)
556 evOffset[0] = 0;
557 irCount = azCount[0];
558 for(i = 1;i < evCount;i++)
560 evOffset[i] = evOffset[i-1] + azCount[i-1];
561 irCount += azCount[i];
564 coeffs = malloc(sizeof(coeffs[0])*irSize*irCount);
565 if(coeffs == NULL)
567 ERR("Out of memory.\n");
568 failed = AL_TRUE;
572 if(!failed)
574 size_t reqsize = 2*irSize*irCount + irCount;
575 if(datalen < reqsize)
577 ERR("Unexpected end of %s data (req "SZFMT", rem "SZFMT"\n",
578 alstr_get_cstr(filename), reqsize, datalen);
579 failed = AL_TRUE;
583 if(!failed)
585 for(i = 0;i < irCount*irSize;i+=irSize)
587 for(j = 0;j < irSize;j++)
589 ALshort coeff;
590 coeff = *(data++);
591 coeff |= *(data++)<<8;
592 datalen -= 2;
593 coeffs[i+j] = coeff;
597 delays = data;
598 data += irCount;
599 datalen -= irCount;
600 for(i = 0;i < irCount;i++)
602 if(delays[i] > maxDelay)
604 ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i], maxDelay);
605 failed = AL_TRUE;
610 if(!failed)
611 Hrtf = CreateHrtfStore(rate, irSize, evCount, irCount, azCount,
612 evOffset, coeffs, delays, filename);
614 free(evOffset);
615 free(coeffs);
616 return Hrtf;
619 static void AddFileEntry(vector_HrtfEntry *list, const_al_string filename)
621 HrtfEntry entry = { AL_STRING_INIT_STATIC(), NULL };
622 struct Hrtf *hrtf = NULL;
623 const HrtfEntry *iter;
624 struct FileMapping fmap;
625 const char *name;
626 const char *ext;
627 int i;
629 #define MATCH_FNAME(i) (alstr_cmp_cstr(filename, (i)->hrtf->filename) == 0)
630 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_FNAME);
631 if(iter != VECTOR_END(*list))
633 TRACE("Skipping duplicate file entry %s\n", alstr_get_cstr(filename));
634 return;
636 #undef MATCH_FNAME
638 entry.hrtf = LoadedHrtfs;
639 while(entry.hrtf)
641 if(alstr_cmp_cstr(filename, entry.hrtf->filename) == 0)
643 TRACE("Skipping load of already-loaded file %s\n", alstr_get_cstr(filename));
644 goto skip_load;
646 entry.hrtf = entry.hrtf->next;
649 TRACE("Loading %s...\n", alstr_get_cstr(filename));
650 fmap = MapFileToMem(alstr_get_cstr(filename));
651 if(fmap.ptr == NULL)
653 ERR("Could not open %s\n", alstr_get_cstr(filename));
654 return;
657 if(fmap.len < sizeof(magicMarker01))
658 ERR("%s data is too short ("SZFMT" bytes)\n", alstr_get_cstr(filename), fmap.len);
659 else if(memcmp(fmap.ptr, magicMarker01, sizeof(magicMarker01)) == 0)
661 TRACE("Detected data set format v1\n");
662 hrtf = LoadHrtf01((const ALubyte*)fmap.ptr+sizeof(magicMarker01),
663 fmap.len-sizeof(magicMarker01), filename
666 else if(memcmp(fmap.ptr, magicMarker00, sizeof(magicMarker00)) == 0)
668 TRACE("Detected data set format v0\n");
669 hrtf = LoadHrtf00((const ALubyte*)fmap.ptr+sizeof(magicMarker00),
670 fmap.len-sizeof(magicMarker00), filename
673 else
674 ERR("Invalid header in %s: \"%.8s\"\n", alstr_get_cstr(filename), (const char*)fmap.ptr);
675 UnmapFileMem(&fmap);
677 if(!hrtf)
679 ERR("Failed to load %s\n", alstr_get_cstr(filename));
680 return;
683 hrtf->next = LoadedHrtfs;
684 LoadedHrtfs = hrtf;
685 TRACE("Loaded HRTF support for format: %s %uhz\n",
686 DevFmtChannelsString(DevFmtStereo), hrtf->sampleRate);
687 entry.hrtf = hrtf;
689 skip_load:
690 /* TODO: Get a human-readable name from the HRTF data (possibly coming in a
691 * format update). */
692 name = strrchr(alstr_get_cstr(filename), '/');
693 if(!name) name = strrchr(alstr_get_cstr(filename), '\\');
694 if(!name) name = alstr_get_cstr(filename);
695 else ++name;
697 ext = strrchr(name, '.');
699 i = 0;
700 do {
701 if(!ext)
702 alstr_copy_cstr(&entry.name, name);
703 else
704 alstr_copy_range(&entry.name, name, ext);
705 if(i != 0)
707 char str[64];
708 snprintf(str, sizeof(str), " #%d", i+1);
709 alstr_append_cstr(&entry.name, str);
711 ++i;
713 #define MATCH_NAME(i) (alstr_cmp(entry.name, (i)->name) == 0)
714 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_NAME);
715 #undef MATCH_NAME
716 } while(iter != VECTOR_END(*list));
718 TRACE("Adding entry \"%s\" from file \"%s\"\n", alstr_get_cstr(entry.name),
719 alstr_get_cstr(filename));
720 VECTOR_PUSH_BACK(*list, entry);
723 /* Unfortunate that we have to duplicate AddFileEntry to take a memory buffer
724 * for input instead of opening the given filename.
726 static void AddBuiltInEntry(vector_HrtfEntry *list, const ALubyte *data, size_t datalen, const_al_string filename)
728 HrtfEntry entry = { AL_STRING_INIT_STATIC(), NULL };
729 struct Hrtf *hrtf = NULL;
730 const HrtfEntry *iter;
731 int i;
733 #define MATCH_FNAME(i) (alstr_cmp_cstr(filename, (i)->hrtf->filename) == 0)
734 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_FNAME);
735 if(iter != VECTOR_END(*list))
737 TRACE("Skipping duplicate file entry %s\n", alstr_get_cstr(filename));
738 return;
740 #undef MATCH_FNAME
742 entry.hrtf = LoadedHrtfs;
743 while(entry.hrtf)
745 if(alstr_cmp_cstr(filename, entry.hrtf->filename) == 0)
747 TRACE("Skipping load of already-loaded file %s\n", alstr_get_cstr(filename));
748 goto skip_load;
750 entry.hrtf = entry.hrtf->next;
753 TRACE("Loading %s...\n", alstr_get_cstr(filename));
754 if(datalen < sizeof(magicMarker01))
756 ERR("%s data is too short ("SZFMT" bytes)\n", alstr_get_cstr(filename), datalen);
757 return;
760 if(memcmp(data, magicMarker01, sizeof(magicMarker01)) == 0)
762 TRACE("Detected data set format v1\n");
763 hrtf = LoadHrtf01(data+sizeof(magicMarker01),
764 datalen-sizeof(magicMarker01), filename
767 else if(memcmp(data, magicMarker00, sizeof(magicMarker00)) == 0)
769 TRACE("Detected data set format v0\n");
770 hrtf = LoadHrtf00(data+sizeof(magicMarker00),
771 datalen-sizeof(magicMarker00), filename
774 else
775 ERR("Invalid header in %s: \"%.8s\"\n", alstr_get_cstr(filename), data);
777 if(!hrtf)
779 ERR("Failed to load %s\n", alstr_get_cstr(filename));
780 return;
783 hrtf->next = LoadedHrtfs;
784 LoadedHrtfs = hrtf;
785 TRACE("Loaded HRTF support for format: %s %uhz\n",
786 DevFmtChannelsString(DevFmtStereo), hrtf->sampleRate);
787 entry.hrtf = hrtf;
789 skip_load:
790 i = 0;
791 do {
792 alstr_copy(&entry.name, filename);
793 if(i != 0)
795 char str[64];
796 snprintf(str, sizeof(str), " #%d", i+1);
797 alstr_append_cstr(&entry.name, str);
799 ++i;
801 #define MATCH_NAME(i) (alstr_cmp(entry.name, (i)->name) == 0)
802 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_NAME);
803 #undef MATCH_NAME
804 } while(iter != VECTOR_END(*list));
806 TRACE("Adding built-in entry \"%s\"\n", alstr_get_cstr(entry.name));
807 VECTOR_PUSH_BACK(*list, entry);
811 #ifndef ALSOFT_EMBED_HRTF_DATA
812 #define IDR_DEFAULT_44100_MHR 1
813 #define IDR_DEFAULT_48000_MHR 2
815 static const ALubyte *GetResource(int UNUSED(name), size_t *size)
817 *size = 0;
818 return NULL;
821 #else
822 #include "hrtf_res.h"
824 #ifdef _WIN32
825 static const ALubyte *GetResource(int name, size_t *size)
827 HMODULE handle;
828 HGLOBAL res;
829 HRSRC rc;
831 GetModuleHandleExW(
832 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
833 (LPCWSTR)GetResource, &handle
835 rc = FindResourceW(handle, MAKEINTRESOURCEW(name), MAKEINTRESOURCEW(MHRTYPE));
836 res = LoadResource(handle, rc);
838 *size = SizeofResource(handle, rc);
839 return LockResource(res);
842 #elif defined(__APPLE__)
844 #include <Availability.h>
845 #include <mach-o/getsect.h>
846 #include <mach-o/ldsyms.h>
848 static const ALubyte *GetResource(int name, size_t *size)
850 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1070)
851 /* NOTE: OSX 10.7 and up need to call getsectiondata(&_mh_dylib_header, ...). However, that
852 * call requires 10.7.
854 if(name == IDR_DEFAULT_44100_MHR)
855 return getsectiondata(&_mh_dylib_header, "binary", "default_44100", size);
856 if(name == IDR_DEFAULT_48000_MHR)
857 return getsectiondata(&_mh_dylib_header, "binary", "default_48000", size);
858 #else
859 if(name == IDR_DEFAULT_44100_MHR)
860 return getsectdata("binary", "default_44100", size);
861 if(name == IDR_DEFAULT_48000_MHR)
862 return getsectdata("binary", "default_48000", size);
863 #endif
864 *size = 0;
865 return NULL;
868 #else
870 extern const ALubyte _binary_default_44100_mhr_start[] HIDDEN_DECL;
871 extern const ALubyte _binary_default_44100_mhr_end[] HIDDEN_DECL;
872 extern const ALubyte _binary_default_44100_mhr_size[] HIDDEN_DECL;
874 extern const ALubyte _binary_default_48000_mhr_start[] HIDDEN_DECL;
875 extern const ALubyte _binary_default_48000_mhr_end[] HIDDEN_DECL;
876 extern const ALubyte _binary_default_48000_mhr_size[] HIDDEN_DECL;
878 static const ALubyte *GetResource(int name, size_t *size)
880 if(name == IDR_DEFAULT_44100_MHR)
882 /* Make sure all symbols are referenced, to ensure the compiler won't
883 * ignore the declarations and lose the visibility attribute used to
884 * hide them (would be nice if ld or objcopy could automatically mark
885 * them as hidden when generating them, but apparently they can't).
887 const void *volatile ptr =_binary_default_44100_mhr_size;
888 (void)ptr;
889 *size = _binary_default_44100_mhr_end - _binary_default_44100_mhr_start;
890 return _binary_default_44100_mhr_start;
892 if(name == IDR_DEFAULT_48000_MHR)
894 const void *volatile ptr =_binary_default_48000_mhr_size;
895 (void)ptr;
896 *size = _binary_default_48000_mhr_end - _binary_default_48000_mhr_start;
897 return _binary_default_48000_mhr_start;
899 *size = 0;
900 return NULL;
902 #endif
903 #endif
905 vector_HrtfEntry EnumerateHrtf(const_al_string devname)
907 vector_HrtfEntry list = VECTOR_INIT_STATIC();
908 const char *defaulthrtf = "";
909 const char *pathlist = "";
910 bool usedefaults = true;
912 if(ConfigValueStr(alstr_get_cstr(devname), NULL, "hrtf-paths", &pathlist))
914 al_string pname = AL_STRING_INIT_STATIC();
915 while(pathlist && *pathlist)
917 const char *next, *end;
919 while(isspace(*pathlist) || *pathlist == ',')
920 pathlist++;
921 if(*pathlist == '\0')
922 continue;
924 next = strchr(pathlist, ',');
925 if(next)
926 end = next++;
927 else
929 end = pathlist + strlen(pathlist);
930 usedefaults = false;
933 while(end != pathlist && isspace(*(end-1)))
934 --end;
935 if(end != pathlist)
937 vector_al_string flist;
938 size_t i;
940 alstr_append_range(&pname, pathlist, end);
942 flist = SearchDataFiles(".mhr", alstr_get_cstr(pname));
943 for(i = 0;i < VECTOR_SIZE(flist);i++)
944 AddFileEntry(&list, VECTOR_ELEM(flist, i));
945 VECTOR_FOR_EACH(al_string, flist, alstr_reset);
946 VECTOR_DEINIT(flist);
949 pathlist = next;
952 alstr_reset(&pname);
954 else if(ConfigValueExists(alstr_get_cstr(devname), NULL, "hrtf_tables"))
955 ERR("The hrtf_tables option is deprecated, please use hrtf-paths instead.\n");
957 if(usedefaults)
959 al_string ename = AL_STRING_INIT_STATIC();
960 vector_al_string flist;
961 const ALubyte *rdata;
962 size_t rsize, i;
964 flist = SearchDataFiles(".mhr", "openal/hrtf");
965 for(i = 0;i < VECTOR_SIZE(flist);i++)
966 AddFileEntry(&list, VECTOR_ELEM(flist, i));
967 VECTOR_FOR_EACH(al_string, flist, alstr_reset);
968 VECTOR_DEINIT(flist);
970 rdata = GetResource(IDR_DEFAULT_44100_MHR, &rsize);
971 if(rdata != NULL && rsize > 0)
973 alstr_copy_cstr(&ename, "Built-In 44100hz");
974 AddBuiltInEntry(&list, rdata, rsize, ename);
977 rdata = GetResource(IDR_DEFAULT_48000_MHR, &rsize);
978 if(rdata != NULL && rsize > 0)
980 alstr_copy_cstr(&ename, "Built-In 48000hz");
981 AddBuiltInEntry(&list, rdata, rsize, ename);
983 alstr_reset(&ename);
986 if(VECTOR_SIZE(list) > 1 && ConfigValueStr(alstr_get_cstr(devname), NULL, "default-hrtf", &defaulthrtf))
988 const HrtfEntry *iter;
989 /* Find the preferred HRTF and move it to the front of the list. */
990 #define FIND_ENTRY(i) (alstr_cmp_cstr((i)->name, defaulthrtf) == 0)
991 VECTOR_FIND_IF(iter, const HrtfEntry, list, FIND_ENTRY);
992 #undef FIND_ENTRY
993 if(iter == VECTOR_END(list))
994 WARN("Failed to find default HRTF \"%s\"\n", defaulthrtf);
995 else if(iter != VECTOR_BEGIN(list))
997 HrtfEntry entry = *iter;
998 memmove(&VECTOR_ELEM(list,1), &VECTOR_ELEM(list,0),
999 (iter-VECTOR_BEGIN(list))*sizeof(HrtfEntry));
1000 VECTOR_ELEM(list,0) = entry;
1004 return list;
1007 void FreeHrtfList(vector_HrtfEntry *list)
1009 #define CLEAR_ENTRY(i) alstr_reset(&(i)->name)
1010 VECTOR_FOR_EACH(HrtfEntry, *list, CLEAR_ENTRY);
1011 VECTOR_DEINIT(*list);
1012 #undef CLEAR_ENTRY
1016 void FreeHrtfs(void)
1018 struct Hrtf *Hrtf = LoadedHrtfs;
1019 LoadedHrtfs = NULL;
1021 while(Hrtf != NULL)
1023 struct Hrtf *next = Hrtf->next;
1024 al_free(Hrtf);
1025 Hrtf = next;