Use a loop to apply NFC filters
[openal-soft.git] / Alc / hrtf.c
blob91895cb977af874dc3f9ffa55a003cab2f2b7e62
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 = 32767.0f * 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) * (1.0f/32767.0f);
114 coeffs[i][1] = lerp(PassthruCoeff, Hrtf->coeffs[ridx+i], dirfact) * (1.0f/32767.0f);
115 for(i = 1;i < Hrtf->irSize;i++)
117 coeffs[i][0] = Hrtf->coeffs[lidx+i]*(1.0f/32767.0f) * dirfact;
118 coeffs[i][1] = Hrtf->coeffs[ridx+i]*(1.0f/32767.0f) * 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, j, 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 ALshort *fir;
167 ALsizei delay;
169 /* Convert the left FIR from shorts to float */
170 fir = &Hrtf->coeffs[lidx[c] * Hrtf->irSize];
171 if(NUM_BANDS == 1)
173 for(i = 0;i < Hrtf->irSize;i++)
174 temps[0][i] = fir[i] / 32767.0f;
176 else
178 /* Band-split left HRIR into low and high frequency responses. */
179 bandsplit_clear(&splitter);
180 for(i = 0;i < Hrtf->irSize;i++)
181 temps[2][i] = fir[i] / 32767.0f;
182 bandsplit_process(&splitter, temps[0], temps[1], temps[2], HRIR_LENGTH);
185 /* Add to the left output coefficients with the specified delay. */
186 delay = Hrtf->delays[lidx[c]] - min_delay;
187 for(i = 0;i < NumChannels;++i)
189 for(b = 0;b < NUM_BANDS;b++)
191 ALsizei k = 0;
192 for(j = delay;j < HRIR_LENGTH;++j)
193 state->Chan[i].Coeffs[j][0] += temps[b][k++] * AmbiMatrix[c][b][i];
196 max_length = maxi(max_length, mini(delay + Hrtf->irSize, HRIR_LENGTH));
198 /* Convert the right FIR from shorts to float */
199 fir = &Hrtf->coeffs[ridx[c] * Hrtf->irSize];
200 if(NUM_BANDS == 1)
202 for(i = 0;i < Hrtf->irSize;i++)
203 temps[0][i] = fir[i] / 32767.0f;
205 else
207 /* Band-split right HRIR into low and high frequency responses. */
208 bandsplit_clear(&splitter);
209 for(i = 0;i < Hrtf->irSize;i++)
210 temps[2][i] = fir[i] / 32767.0f;
211 bandsplit_process(&splitter, temps[0], temps[1], temps[2], HRIR_LENGTH);
214 /* Add to the right output coefficients with the specified delay. */
215 delay = Hrtf->delays[ridx[c]] - min_delay;
216 for(i = 0;i < NumChannels;++i)
218 for(b = 0;b < NUM_BANDS;b++)
220 ALuint k = 0;
221 for(j = delay;j < HRIR_LENGTH;++j)
222 state->Chan[i].Coeffs[j][1] += temps[b][k++] * AmbiMatrix[c][b][i];
225 max_length = maxi(max_length, mini(delay + Hrtf->irSize, HRIR_LENGTH));
227 TRACE("Skipped min delay: %d, new combined length: %d\n", min_delay, max_length);
229 return max_length;
230 #undef NUM_BANDS
234 static struct Hrtf *LoadHrtf00(const ALubyte *data, size_t datalen, const_al_string filename)
236 const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
237 struct Hrtf *Hrtf = NULL;
238 ALboolean failed = AL_FALSE;
239 ALuint rate = 0, irCount = 0;
240 ALushort irSize = 0;
241 ALubyte evCount = 0;
242 ALubyte *azCount = NULL;
243 ALushort *evOffset = NULL;
244 ALshort *coeffs = NULL;
245 const ALubyte *delays = NULL;
246 ALuint i, j;
248 if(datalen < 9)
250 ERR("Unexpected end of %s data (req %d, rem "SZFMT")\n",
251 al_string_get_cstr(filename), 9, datalen);
252 return NULL;
255 rate = *(data++);
256 rate |= *(data++)<<8;
257 rate |= *(data++)<<16;
258 rate |= *(data++)<<24;
259 datalen -= 4;
261 irCount = *(data++);
262 irCount |= *(data++)<<8;
263 datalen -= 2;
265 irSize = *(data++);
266 irSize |= *(data++)<<8;
267 datalen -= 2;
269 evCount = *(data++);
270 datalen -= 1;
272 if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
274 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
275 irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE);
276 failed = AL_TRUE;
278 if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT)
280 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
281 evCount, MIN_EV_COUNT, MAX_EV_COUNT);
282 failed = AL_TRUE;
284 if(failed)
285 return NULL;
287 if(datalen < evCount*2)
289 ERR("Unexpected end of %s data (req %d, rem "SZFMT")\n",
290 al_string_get_cstr(filename), evCount*2, datalen);
291 return NULL;
294 azCount = malloc(sizeof(azCount[0])*evCount);
295 evOffset = malloc(sizeof(evOffset[0])*evCount);
296 if(azCount == NULL || evOffset == NULL)
298 ERR("Out of memory.\n");
299 failed = AL_TRUE;
302 if(!failed)
304 evOffset[0] = *(data++);
305 evOffset[0] |= *(data++)<<8;
306 datalen -= 2;
307 for(i = 1;i < evCount;i++)
309 evOffset[i] = *(data++);
310 evOffset[i] |= *(data++)<<8;
311 datalen -= 2;
312 if(evOffset[i] <= evOffset[i-1])
314 ERR("Invalid evOffset: evOffset[%d]=%d (last=%d)\n",
315 i, evOffset[i], evOffset[i-1]);
316 failed = AL_TRUE;
319 azCount[i-1] = evOffset[i] - evOffset[i-1];
320 if(azCount[i-1] < MIN_AZ_COUNT || azCount[i-1] > MAX_AZ_COUNT)
322 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
323 i-1, azCount[i-1], MIN_AZ_COUNT, MAX_AZ_COUNT);
324 failed = AL_TRUE;
327 if(irCount <= evOffset[i-1])
329 ERR("Invalid evOffset: evOffset[%d]=%d (irCount=%d)\n",
330 i-1, evOffset[i-1], irCount);
331 failed = AL_TRUE;
334 azCount[i-1] = irCount - evOffset[i-1];
335 if(azCount[i-1] < MIN_AZ_COUNT || azCount[i-1] > MAX_AZ_COUNT)
337 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
338 i-1, azCount[i-1], MIN_AZ_COUNT, MAX_AZ_COUNT);
339 failed = AL_TRUE;
343 if(!failed)
345 coeffs = malloc(sizeof(coeffs[0])*irSize*irCount);
346 if(coeffs == NULL)
348 ERR("Out of memory.\n");
349 failed = AL_TRUE;
353 if(!failed)
355 size_t reqsize = 2*irSize*irCount + irCount;
356 if(datalen < reqsize)
358 ERR("Unexpected end of %s data (req "SZFMT", rem "SZFMT")\n",
359 al_string_get_cstr(filename), reqsize, datalen);
360 failed = AL_TRUE;
364 if(!failed)
366 for(i = 0;i < irCount*irSize;i+=irSize)
368 for(j = 0;j < irSize;j++)
370 coeffs[i+j] = *(data++);
371 coeffs[i+j] |= *(data++)<<8;
372 datalen -= 2;
376 delays = data;
377 data += irCount;
378 datalen -= irCount;
379 for(i = 0;i < irCount;i++)
381 if(delays[i] > maxDelay)
383 ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i], maxDelay);
384 failed = AL_TRUE;
389 if(!failed)
391 size_t total = sizeof(struct Hrtf);
392 total += sizeof(azCount[0])*evCount;
393 total = (total+1)&~1; /* Align for (u)short fields */
394 total += sizeof(evOffset[0])*evCount;
395 total += sizeof(coeffs[0])*irSize*irCount;
396 total += sizeof(delays[0])*irCount;
397 total += al_string_length(filename)+1;
399 Hrtf = al_calloc(16, total);
400 if(Hrtf == NULL)
402 ERR("Out of memory.\n");
403 failed = AL_TRUE;
407 if(!failed)
409 char *base = (char*)Hrtf;
410 uintptr_t offset = sizeof(*Hrtf);
412 Hrtf->sampleRate = rate;
413 Hrtf->irSize = irSize;
414 Hrtf->evCount = evCount;
415 Hrtf->azCount = ((ALubyte*)(base + offset)); offset += evCount*sizeof(Hrtf->azCount[0]);
416 offset = (offset+1)&~1; /* Align for (u)short fields */
417 Hrtf->evOffset = ((ALushort*)(base + offset)); offset += evCount*sizeof(Hrtf->evOffset[0]);
418 Hrtf->coeffs = ((ALshort*)(base + offset)); offset += irSize*irCount*sizeof(Hrtf->coeffs[0]);
419 Hrtf->delays = ((ALubyte*)(base + offset)); offset += irCount*sizeof(Hrtf->delays[0]);
420 Hrtf->filename = ((char*)(base + offset));
421 Hrtf->next = NULL;
423 memcpy((void*)Hrtf->azCount, azCount, sizeof(azCount[0])*evCount);
424 memcpy((void*)Hrtf->evOffset, evOffset, sizeof(evOffset[0])*evCount);
425 memcpy((void*)Hrtf->coeffs, coeffs, sizeof(coeffs[0])*irSize*irCount);
426 memcpy((void*)Hrtf->delays, delays, sizeof(delays[0])*irCount);
427 memcpy((void*)Hrtf->filename, al_string_get_cstr(filename), al_string_length(filename)+1);
430 free(azCount);
431 free(evOffset);
432 free(coeffs);
433 return Hrtf;
436 static struct Hrtf *LoadHrtf01(const ALubyte *data, size_t datalen, const_al_string filename)
438 const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
439 struct Hrtf *Hrtf = NULL;
440 ALboolean failed = AL_FALSE;
441 ALuint rate = 0, irCount = 0;
442 ALubyte irSize = 0, evCount = 0;
443 const ALubyte *azCount = NULL;
444 ALushort *evOffset = NULL;
445 ALshort *coeffs = NULL;
446 const ALubyte *delays = NULL;
447 ALuint i, j;
449 if(datalen < 6)
451 ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n",
452 al_string_get_cstr(filename), 6, datalen);
453 return NULL;
456 rate = *(data++);
457 rate |= *(data++)<<8;
458 rate |= *(data++)<<16;
459 rate |= *(data++)<<24;
460 datalen -= 4;
462 irSize = *(data++);
463 datalen -= 1;
465 evCount = *(data++);
466 datalen -= 1;
468 if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
470 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
471 irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE);
472 failed = AL_TRUE;
474 if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT)
476 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
477 evCount, MIN_EV_COUNT, MAX_EV_COUNT);
478 failed = AL_TRUE;
480 if(failed)
481 return NULL;
483 if(datalen < evCount)
485 ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n",
486 al_string_get_cstr(filename), evCount, datalen);
487 return NULL;
490 azCount = data;
491 data += evCount;
492 datalen -= evCount;
494 evOffset = malloc(sizeof(evOffset[0])*evCount);
495 if(azCount == NULL || evOffset == NULL)
497 ERR("Out of memory.\n");
498 failed = AL_TRUE;
501 if(!failed)
503 for(i = 0;i < evCount;i++)
505 if(azCount[i] < MIN_AZ_COUNT || azCount[i] > MAX_AZ_COUNT)
507 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
508 i, azCount[i], MIN_AZ_COUNT, MAX_AZ_COUNT);
509 failed = AL_TRUE;
514 if(!failed)
516 evOffset[0] = 0;
517 irCount = azCount[0];
518 for(i = 1;i < evCount;i++)
520 evOffset[i] = evOffset[i-1] + azCount[i-1];
521 irCount += azCount[i];
524 coeffs = malloc(sizeof(coeffs[0])*irSize*irCount);
525 if(coeffs == NULL)
527 ERR("Out of memory.\n");
528 failed = AL_TRUE;
532 if(!failed)
534 size_t reqsize = 2*irSize*irCount + irCount;
535 if(datalen < reqsize)
537 ERR("Unexpected end of %s data (req "SZFMT", rem "SZFMT"\n",
538 al_string_get_cstr(filename), reqsize, datalen);
539 failed = AL_TRUE;
543 if(!failed)
545 for(i = 0;i < irCount*irSize;i+=irSize)
547 for(j = 0;j < irSize;j++)
549 ALshort coeff;
550 coeff = *(data++);
551 coeff |= *(data++)<<8;
552 datalen -= 2;
553 coeffs[i+j] = coeff;
557 delays = data;
558 data += irCount;
559 datalen -= irCount;
560 for(i = 0;i < irCount;i++)
562 if(delays[i] > maxDelay)
564 ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i], maxDelay);
565 failed = AL_TRUE;
570 if(!failed)
572 size_t total = sizeof(struct Hrtf);
573 total += sizeof(azCount[0])*evCount;
574 total = (total+1)&~1; /* Align for (u)short fields */
575 total += sizeof(evOffset[0])*evCount;
576 total += sizeof(coeffs[0])*irSize*irCount;
577 total += sizeof(delays[0])*irCount;
578 total += al_string_length(filename)+1;
580 Hrtf = al_calloc(16, total);
581 if(Hrtf == NULL)
583 ERR("Out of memory.\n");
584 failed = AL_TRUE;
588 if(!failed)
590 char *base = (char*)Hrtf;
591 uintptr_t offset = sizeof(*Hrtf);
593 Hrtf->sampleRate = rate;
594 Hrtf->irSize = irSize;
595 Hrtf->evCount = evCount;
596 Hrtf->azCount = ((ALubyte*)(base + offset)); offset += evCount*sizeof(Hrtf->azCount[0]);
597 offset = (offset+1)&~1; /* Align for (u)short fields */
598 Hrtf->evOffset = ((ALushort*)(base + offset)); offset += evCount*sizeof(Hrtf->evOffset[0]);
599 Hrtf->coeffs = ((ALshort*)(base + offset)); offset += irSize*irCount*sizeof(Hrtf->coeffs[0]);
600 Hrtf->delays = ((ALubyte*)(base + offset)); offset += irCount*sizeof(Hrtf->delays[0]);
601 Hrtf->filename = ((char*)(base + offset));
602 Hrtf->next = NULL;
604 memcpy((void*)Hrtf->azCount, azCount, sizeof(azCount[0])*evCount);
605 memcpy((void*)Hrtf->evOffset, evOffset, sizeof(evOffset[0])*evCount);
606 memcpy((void*)Hrtf->coeffs, coeffs, sizeof(coeffs[0])*irSize*irCount);
607 memcpy((void*)Hrtf->delays, delays, sizeof(delays[0])*irCount);
608 memcpy((void*)Hrtf->filename, al_string_get_cstr(filename), al_string_length(filename)+1);
611 free(evOffset);
612 free(coeffs);
613 return Hrtf;
616 static void AddFileEntry(vector_HrtfEntry *list, al_string *filename)
618 HrtfEntry entry = { AL_STRING_INIT_STATIC(), NULL };
619 struct Hrtf *hrtf = NULL;
620 const HrtfEntry *iter;
621 struct FileMapping fmap;
622 const char *name;
623 const char *ext;
624 int i;
626 #define MATCH_FNAME(i) (al_string_cmp_cstr(*filename, (i)->hrtf->filename) == 0)
627 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_FNAME);
628 if(iter != VECTOR_END(*list))
630 TRACE("Skipping duplicate file entry %s\n", al_string_get_cstr(*filename));
631 goto done;
633 #undef MATCH_FNAME
635 entry.hrtf = LoadedHrtfs;
636 while(entry.hrtf)
638 if(al_string_cmp_cstr(*filename, entry.hrtf->filename) == 0)
640 TRACE("Skipping load of already-loaded file %s\n", al_string_get_cstr(*filename));
641 goto skip_load;
643 entry.hrtf = entry.hrtf->next;
646 TRACE("Loading %s...\n", al_string_get_cstr(*filename));
647 fmap = MapFileToMem(al_string_get_cstr(*filename));
648 if(fmap.ptr == NULL)
650 ERR("Could not open %s\n", al_string_get_cstr(*filename));
651 goto done;
654 if(fmap.len < sizeof(magicMarker01))
655 ERR("%s data is too short ("SZFMT" bytes)\n", al_string_get_cstr(*filename), fmap.len);
656 else if(memcmp(fmap.ptr, magicMarker01, sizeof(magicMarker01)) == 0)
658 TRACE("Detected data set format v1\n");
659 hrtf = LoadHrtf01((const ALubyte*)fmap.ptr+sizeof(magicMarker01),
660 fmap.len-sizeof(magicMarker01), *filename
663 else if(memcmp(fmap.ptr, magicMarker00, sizeof(magicMarker00)) == 0)
665 TRACE("Detected data set format v0\n");
666 hrtf = LoadHrtf00((const ALubyte*)fmap.ptr+sizeof(magicMarker00),
667 fmap.len-sizeof(magicMarker00), *filename
670 else
671 ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(*filename), (const char*)fmap.ptr);
672 UnmapFileMem(&fmap);
674 if(!hrtf)
676 ERR("Failed to load %s\n", al_string_get_cstr(*filename));
677 goto done;
680 hrtf->next = LoadedHrtfs;
681 LoadedHrtfs = hrtf;
682 TRACE("Loaded HRTF support for format: %s %uhz\n",
683 DevFmtChannelsString(DevFmtStereo), hrtf->sampleRate);
684 entry.hrtf = hrtf;
686 skip_load:
687 /* TODO: Get a human-readable name from the HRTF data (possibly coming in a
688 * format update). */
689 name = strrchr(al_string_get_cstr(*filename), '/');
690 if(!name) name = strrchr(al_string_get_cstr(*filename), '\\');
691 if(!name) name = al_string_get_cstr(*filename);
692 else ++name;
694 ext = strrchr(name, '.');
696 i = 0;
697 do {
698 if(!ext)
699 al_string_copy_cstr(&entry.name, name);
700 else
701 al_string_copy_range(&entry.name, name, ext);
702 if(i != 0)
704 char str[64];
705 snprintf(str, sizeof(str), " #%d", i+1);
706 al_string_append_cstr(&entry.name, str);
708 ++i;
710 #define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0)
711 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_NAME);
712 #undef MATCH_NAME
713 } while(iter != VECTOR_END(*list));
715 TRACE("Adding entry \"%s\" from file \"%s\"\n", al_string_get_cstr(entry.name),
716 al_string_get_cstr(*filename));
717 VECTOR_PUSH_BACK(*list, entry);
719 done:
720 al_string_deinit(filename);
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, 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) (al_string_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", al_string_get_cstr(*filename));
738 goto done;
740 #undef MATCH_FNAME
742 entry.hrtf = LoadedHrtfs;
743 while(entry.hrtf)
745 if(al_string_cmp_cstr(*filename, entry.hrtf->filename) == 0)
747 TRACE("Skipping load of already-loaded file %s\n", al_string_get_cstr(*filename));
748 goto skip_load;
750 entry.hrtf = entry.hrtf->next;
753 TRACE("Loading %s...\n", al_string_get_cstr(*filename));
754 if(datalen < sizeof(magicMarker01))
756 ERR("%s data is too short ("SZFMT" bytes)\n", al_string_get_cstr(*filename), datalen);
757 goto done;
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", al_string_get_cstr(*filename), data);
777 if(!hrtf)
779 ERR("Failed to load %s\n", al_string_get_cstr(*filename));
780 goto done;
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 al_string_copy(&entry.name, *filename);
793 if(i != 0)
795 char str[64];
796 snprintf(str, sizeof(str), " #%d", i+1);
797 al_string_append_cstr(&entry.name, str);
799 ++i;
801 #define MATCH_NAME(i) (al_string_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", al_string_get_cstr(entry.name));
807 VECTOR_PUSH_BACK(*list, entry);
809 done:
810 al_string_deinit(filename);
814 #ifndef ALSOFT_EMBED_HRTF_DATA
815 #define IDR_DEFAULT_44100_MHR 1
816 #define IDR_DEFAULT_48000_MHR 2
818 static const ALubyte *GetResource(int UNUSED(name), size_t *size)
820 *size = 0;
821 return NULL;
824 #else
825 #include "hrtf_res.h"
827 #ifdef _WIN32
828 static const ALubyte *GetResource(int name, size_t *size)
830 HMODULE handle;
831 HGLOBAL res;
832 HRSRC rc;
834 GetModuleHandleExW(
835 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
836 (LPCWSTR)GetResource, &handle
838 rc = FindResourceW(handle, MAKEINTRESOURCEW(name), MAKEINTRESOURCEW(MHRTYPE));
839 res = LoadResource(handle, rc);
841 *size = SizeofResource(handle, rc);
842 return LockResource(res);
845 #elif defined(__APPLE__)
847 #include <Availability.h>
848 #include <mach-o/getsect.h>
849 #include <mach-o/ldsyms.h>
851 static const ALubyte *GetResource(int name, size_t *size)
853 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1070)
854 /* NOTE: OSX 10.7 and up need to call getsectiondata(&_mh_dylib_header, ...). However, that
855 * call requires 10.7.
857 if(name == IDR_DEFAULT_44100_MHR)
858 return getsectiondata(&_mh_dylib_header, "binary", "default_44100", size);
859 if(name == IDR_DEFAULT_48000_MHR)
860 return getsectiondata(&_mh_dylib_header, "binary", "default_48000", size);
861 #else
862 if(name == IDR_DEFAULT_44100_MHR)
863 return getsectdata("binary", "default_44100", size);
864 if(name == IDR_DEFAULT_48000_MHR)
865 return getsectdata("binary", "default_48000", size);
866 #endif
867 *size = 0;
868 return NULL;
871 #else
873 extern const ALubyte _binary_default_44100_mhr_start[] HIDDEN_DECL;
874 extern const ALubyte _binary_default_44100_mhr_end[] HIDDEN_DECL;
875 extern const ALubyte _binary_default_44100_mhr_size[] HIDDEN_DECL;
877 extern const ALubyte _binary_default_48000_mhr_start[] HIDDEN_DECL;
878 extern const ALubyte _binary_default_48000_mhr_end[] HIDDEN_DECL;
879 extern const ALubyte _binary_default_48000_mhr_size[] HIDDEN_DECL;
881 static const ALubyte *GetResource(int name, size_t *size)
883 if(name == IDR_DEFAULT_44100_MHR)
885 /* Make sure all symbols are referenced, to ensure the compiler won't
886 * ignore the declarations and lose the visibility attribute used to
887 * hide them (would be nice if ld or objcopy could automatically mark
888 * them as hidden when generating them, but apparently they can't).
890 const void *volatile ptr =_binary_default_44100_mhr_size;
891 (void)ptr;
892 *size = _binary_default_44100_mhr_end - _binary_default_44100_mhr_start;
893 return _binary_default_44100_mhr_start;
895 if(name == IDR_DEFAULT_48000_MHR)
897 const void *volatile ptr =_binary_default_48000_mhr_size;
898 (void)ptr;
899 *size = _binary_default_48000_mhr_end - _binary_default_48000_mhr_start;
900 return _binary_default_48000_mhr_start;
902 *size = 0;
903 return NULL;
905 #endif
906 #endif
908 vector_HrtfEntry EnumerateHrtf(const_al_string devname)
910 vector_HrtfEntry list = VECTOR_INIT_STATIC();
911 const char *defaulthrtf = "";
912 const char *pathlist = "";
913 bool usedefaults = true;
915 if(ConfigValueStr(al_string_get_cstr(devname), NULL, "hrtf-paths", &pathlist))
917 while(pathlist && *pathlist)
919 const char *next, *end;
921 while(isspace(*pathlist) || *pathlist == ',')
922 pathlist++;
923 if(*pathlist == '\0')
924 continue;
926 next = strchr(pathlist, ',');
927 if(next)
928 end = next++;
929 else
931 end = pathlist + strlen(pathlist);
932 usedefaults = false;
935 while(end != pathlist && isspace(*(end-1)))
936 --end;
937 if(end != pathlist)
939 al_string pname = AL_STRING_INIT_STATIC();
940 vector_al_string flist;
942 al_string_append_range(&pname, pathlist, end);
944 flist = SearchDataFiles(".mhr", al_string_get_cstr(pname));
945 VECTOR_FOR_EACH_PARAMS(al_string, flist, AddFileEntry, &list);
946 VECTOR_DEINIT(flist);
948 al_string_deinit(&pname);
951 pathlist = next;
954 else if(ConfigValueExists(al_string_get_cstr(devname), NULL, "hrtf_tables"))
955 ERR("The hrtf_tables option is deprecated, please use hrtf-paths instead.\n");
957 if(usedefaults)
959 vector_al_string flist;
960 const ALubyte *rdata;
961 size_t rsize;
963 flist = SearchDataFiles(".mhr", "openal/hrtf");
964 VECTOR_FOR_EACH_PARAMS(al_string, flist, AddFileEntry, &list);
965 VECTOR_DEINIT(flist);
967 rdata = GetResource(IDR_DEFAULT_44100_MHR, &rsize);
968 if(rdata != NULL && rsize > 0)
970 al_string ename = AL_STRING_INIT_STATIC();
971 al_string_copy_cstr(&ename, "Built-In 44100hz");
972 AddBuiltInEntry(&list, rdata, rsize, &ename);
975 rdata = GetResource(IDR_DEFAULT_48000_MHR, &rsize);
976 if(rdata != NULL && rsize > 0)
978 al_string ename = AL_STRING_INIT_STATIC();
979 al_string_copy_cstr(&ename, "Built-In 48000hz");
980 AddBuiltInEntry(&list, rdata, rsize, &ename);
984 if(VECTOR_SIZE(list) > 1 && ConfigValueStr(al_string_get_cstr(devname), NULL, "default-hrtf", &defaulthrtf))
986 const HrtfEntry *iter;
987 /* Find the preferred HRTF and move it to the front of the list. */
988 #define FIND_ENTRY(i) (al_string_cmp_cstr((i)->name, defaulthrtf) == 0)
989 VECTOR_FIND_IF(iter, const HrtfEntry, list, FIND_ENTRY);
990 #undef FIND_ENTRY
991 if(iter == VECTOR_END(list))
992 WARN("Failed to find default HRTF \"%s\"\n", defaulthrtf);
993 else if(iter != VECTOR_BEGIN(list))
995 HrtfEntry entry = *iter;
996 memmove(&VECTOR_ELEM(list,1), &VECTOR_ELEM(list,0),
997 (iter-VECTOR_BEGIN(list))*sizeof(HrtfEntry));
998 VECTOR_ELEM(list,0) = entry;
1002 return list;
1005 void FreeHrtfList(vector_HrtfEntry *list)
1007 #define CLEAR_ENTRY(i) do { \
1008 al_string_deinit(&(i)->name); \
1009 } while(0)
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;