Remove the separate surround51rear decoder option
[openal-soft.git] / Alc / hrtf.c
blobd79168e1eff89b144d58bee0cc7555142ddd192c
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 and attenuated by
81 * the specified gain.
83 void GetHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat spread, ALfloat gain, ALfloat (*coeffs)[2], ALsizei *delays)
85 ALsizei evidx, azidx, lidx, ridx;
86 ALsizei azcount, evoffset;
87 ALfloat dirfact;
88 ALsizei i;
90 dirfact = 1.0f - (spread / F_TAU);
92 /* Claculate elevation index. */
93 evidx = CalcEvIndex(Hrtf->evCount, elevation);
94 azcount = Hrtf->azCount[evidx];
95 evoffset = Hrtf->evOffset[evidx];
97 /* Calculate azimuth index. */
98 azidx = CalcAzIndex(Hrtf->azCount[evidx], azimuth);
100 /* Calculate the HRIR indices for left and right channels. */
101 lidx = evoffset + azidx;
102 ridx = evoffset + ((azcount-azidx) % azcount);
104 /* Calculate the HRIR delays. */
105 delays[0] = fastf2i(Hrtf->delays[lidx]*dirfact + 0.5f) << HRTFDELAY_BITS;
106 delays[1] = fastf2i(Hrtf->delays[ridx]*dirfact + 0.5f) << HRTFDELAY_BITS;
108 /* Calculate the sample offsets for the HRIR indices. */
109 lidx *= Hrtf->irSize;
110 ridx *= Hrtf->irSize;
112 /* Calculate the normalized and attenuated HRIR coefficients. Zero the
113 * coefficients if gain is too low.
115 if(gain > 0.0001f)
117 gain /= 32767.0f;
119 i = 0;
120 coeffs[i][0] = lerp(PassthruCoeff, Hrtf->coeffs[lidx+i], dirfact)*gain;
121 coeffs[i][1] = lerp(PassthruCoeff, Hrtf->coeffs[ridx+i], dirfact)*gain;
122 for(i = 1;i < Hrtf->irSize;i++)
124 coeffs[i][0] = Hrtf->coeffs[lidx+i]*gain * dirfact;
125 coeffs[i][1] = Hrtf->coeffs[ridx+i]*gain * dirfact;
128 else
130 for(i = 0;i < Hrtf->irSize;i++)
132 coeffs[i][0] = 0.0f;
133 coeffs[i][1] = 0.0f;
139 ALsizei BuildBFormatHrtf(const struct Hrtf *Hrtf, ALfloat (*coeffs)[HRIR_LENGTH][2], ALsizei NumChannels, const ALfloat (*restrict AmbiPoints)[2], const ALfloat (*restrict AmbiMatrix)[2][MAX_AMBI_COEFFS], ALsizei AmbiCount)
141 /* Set this to 2 for dual-band HRTF processing. May require a higher quality
142 * band-splitter, or better calculation of the new IR length to deal with the
143 * tail generated by the filter.
145 #define NUM_BANDS 2
146 BandSplitter splitter;
147 ALsizei lidx[HRTF_AMBI_MAX_CHANNELS], ridx[HRTF_AMBI_MAX_CHANNELS];
148 ALsizei min_delay = HRTF_HISTORY_LENGTH;
149 ALfloat temps[3][HRIR_LENGTH];
150 ALsizei max_length = 0;
151 ALsizei i, j, c, b;
153 for(c = 0;c < AmbiCount;c++)
155 ALuint evidx, azidx;
156 ALuint evoffset;
157 ALuint azcount;
159 /* Calculate elevation index. */
160 evidx = (ALsizei)floorf((F_PI_2 + AmbiPoints[c][0]) *
161 (Hrtf->evCount-1)/F_PI + 0.5f);
162 evidx = mini(evidx, Hrtf->evCount-1);
164 azcount = Hrtf->azCount[evidx];
165 evoffset = Hrtf->evOffset[evidx];
167 /* Calculate azimuth index for this elevation. */
168 azidx = (ALsizei)floorf((F_TAU+AmbiPoints[c][1]) *
169 azcount/F_TAU + 0.5f) % azcount;
171 /* Calculate indices for left and right channels. */
172 lidx[c] = evoffset + azidx;
173 ridx[c] = evoffset + ((azcount-azidx) % azcount);
175 min_delay = mini(min_delay, mini(Hrtf->delays[lidx[c]], Hrtf->delays[ridx[c]]));
178 memset(temps, 0, sizeof(temps));
179 bandsplit_init(&splitter, 400.0f / (ALfloat)Hrtf->sampleRate);
180 for(c = 0;c < AmbiCount;c++)
182 const ALshort *fir;
183 ALsizei delay;
185 /* Convert the left FIR from shorts to float */
186 fir = &Hrtf->coeffs[lidx[c] * Hrtf->irSize];
187 if(NUM_BANDS == 1)
189 for(i = 0;i < Hrtf->irSize;i++)
190 temps[0][i] = fir[i] / 32767.0f;
192 else
194 /* Band-split left HRIR into low and high frequency responses. */
195 bandsplit_clear(&splitter);
196 for(i = 0;i < Hrtf->irSize;i++)
197 temps[2][i] = fir[i] / 32767.0f;
198 bandsplit_process(&splitter, temps[0], temps[1], temps[2], HRIR_LENGTH);
201 /* Add to the left output coefficients with the specified delay. */
202 delay = Hrtf->delays[lidx[c]] - min_delay;
203 for(i = 0;i < NumChannels;++i)
205 for(b = 0;b < NUM_BANDS;b++)
207 ALsizei k = 0;
208 for(j = delay;j < HRIR_LENGTH;++j)
209 coeffs[i][j][0] += temps[b][k++] * AmbiMatrix[c][b][i];
212 max_length = maxi(max_length, mini(delay + Hrtf->irSize, HRIR_LENGTH));
214 /* Convert the right FIR from shorts to float */
215 fir = &Hrtf->coeffs[ridx[c] * Hrtf->irSize];
216 if(NUM_BANDS == 1)
218 for(i = 0;i < Hrtf->irSize;i++)
219 temps[0][i] = fir[i] / 32767.0f;
221 else
223 /* Band-split right HRIR into low and high frequency responses. */
224 bandsplit_clear(&splitter);
225 for(i = 0;i < Hrtf->irSize;i++)
226 temps[2][i] = fir[i] / 32767.0f;
227 bandsplit_process(&splitter, temps[0], temps[1], temps[2], HRIR_LENGTH);
230 /* Add to the right output coefficients with the specified delay. */
231 delay = Hrtf->delays[ridx[c]] - min_delay;
232 for(i = 0;i < NumChannels;++i)
234 for(b = 0;b < NUM_BANDS;b++)
236 ALuint k = 0;
237 for(j = delay;j < HRIR_LENGTH;++j)
238 coeffs[i][j][1] += temps[b][k++] * AmbiMatrix[c][b][i];
241 max_length = maxi(max_length, mini(delay + Hrtf->irSize, HRIR_LENGTH));
243 TRACE("Skipped min delay: %d, new combined length: %d\n", min_delay, max_length);
245 return max_length;
246 #undef NUM_BANDS
250 static struct Hrtf *LoadHrtf00(const ALubyte *data, size_t datalen, const_al_string filename)
252 const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
253 struct Hrtf *Hrtf = NULL;
254 ALboolean failed = AL_FALSE;
255 ALuint rate = 0, irCount = 0;
256 ALushort irSize = 0;
257 ALubyte evCount = 0;
258 ALubyte *azCount = NULL;
259 ALushort *evOffset = NULL;
260 ALshort *coeffs = NULL;
261 const ALubyte *delays = NULL;
262 ALuint i, j;
264 if(datalen < 9)
266 ERR("Unexpected end of %s data (req %d, rem "SZFMT")\n",
267 al_string_get_cstr(filename), 9, datalen);
268 return NULL;
271 rate = *(data++);
272 rate |= *(data++)<<8;
273 rate |= *(data++)<<16;
274 rate |= *(data++)<<24;
275 datalen -= 4;
277 irCount = *(data++);
278 irCount |= *(data++)<<8;
279 datalen -= 2;
281 irSize = *(data++);
282 irSize |= *(data++)<<8;
283 datalen -= 2;
285 evCount = *(data++);
286 datalen -= 1;
288 if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
290 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
291 irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE);
292 failed = AL_TRUE;
294 if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT)
296 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
297 evCount, MIN_EV_COUNT, MAX_EV_COUNT);
298 failed = AL_TRUE;
300 if(failed)
301 return NULL;
303 if(datalen < evCount*2)
305 ERR("Unexpected end of %s data (req %d, rem "SZFMT")\n",
306 al_string_get_cstr(filename), evCount*2, datalen);
307 return NULL;
310 azCount = malloc(sizeof(azCount[0])*evCount);
311 evOffset = malloc(sizeof(evOffset[0])*evCount);
312 if(azCount == NULL || evOffset == NULL)
314 ERR("Out of memory.\n");
315 failed = AL_TRUE;
318 if(!failed)
320 evOffset[0] = *(data++);
321 evOffset[0] |= *(data++)<<8;
322 datalen -= 2;
323 for(i = 1;i < evCount;i++)
325 evOffset[i] = *(data++);
326 evOffset[i] |= *(data++)<<8;
327 datalen -= 2;
328 if(evOffset[i] <= evOffset[i-1])
330 ERR("Invalid evOffset: evOffset[%d]=%d (last=%d)\n",
331 i, evOffset[i], evOffset[i-1]);
332 failed = AL_TRUE;
335 azCount[i-1] = evOffset[i] - evOffset[i-1];
336 if(azCount[i-1] < MIN_AZ_COUNT || azCount[i-1] > MAX_AZ_COUNT)
338 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
339 i-1, azCount[i-1], MIN_AZ_COUNT, MAX_AZ_COUNT);
340 failed = AL_TRUE;
343 if(irCount <= evOffset[i-1])
345 ERR("Invalid evOffset: evOffset[%d]=%d (irCount=%d)\n",
346 i-1, evOffset[i-1], irCount);
347 failed = AL_TRUE;
350 azCount[i-1] = irCount - evOffset[i-1];
351 if(azCount[i-1] < MIN_AZ_COUNT || azCount[i-1] > MAX_AZ_COUNT)
353 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
354 i-1, azCount[i-1], MIN_AZ_COUNT, MAX_AZ_COUNT);
355 failed = AL_TRUE;
359 if(!failed)
361 coeffs = malloc(sizeof(coeffs[0])*irSize*irCount);
362 if(coeffs == NULL)
364 ERR("Out of memory.\n");
365 failed = AL_TRUE;
369 if(!failed)
371 size_t reqsize = 2*irSize*irCount + irCount;
372 if(datalen < reqsize)
374 ERR("Unexpected end of %s data (req "SZFMT", rem "SZFMT")\n",
375 al_string_get_cstr(filename), reqsize, datalen);
376 failed = AL_TRUE;
380 if(!failed)
382 for(i = 0;i < irCount*irSize;i+=irSize)
384 for(j = 0;j < irSize;j++)
386 coeffs[i+j] = *(data++);
387 coeffs[i+j] |= *(data++)<<8;
388 datalen -= 2;
392 delays = data;
393 data += irCount;
394 datalen -= irCount;
395 for(i = 0;i < irCount;i++)
397 if(delays[i] > maxDelay)
399 ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i], maxDelay);
400 failed = AL_TRUE;
405 if(!failed)
407 size_t total = sizeof(struct Hrtf);
408 total += sizeof(azCount[0])*evCount;
409 total = (total+1)&~1; /* Align for (u)short fields */
410 total += sizeof(evOffset[0])*evCount;
411 total += sizeof(coeffs[0])*irSize*irCount;
412 total += sizeof(delays[0])*irCount;
413 total += al_string_length(filename)+1;
415 Hrtf = al_calloc(16, total);
416 if(Hrtf == NULL)
418 ERR("Out of memory.\n");
419 failed = AL_TRUE;
423 if(!failed)
425 char *base = (char*)Hrtf;
426 uintptr_t offset = sizeof(*Hrtf);
428 Hrtf->sampleRate = rate;
429 Hrtf->irSize = irSize;
430 Hrtf->evCount = evCount;
431 Hrtf->azCount = ((ALubyte*)(base + offset)); offset += evCount*sizeof(Hrtf->azCount[0]);
432 offset = (offset+1)&~1; /* Align for (u)short fields */
433 Hrtf->evOffset = ((ALushort*)(base + offset)); offset += evCount*sizeof(Hrtf->evOffset[0]);
434 Hrtf->coeffs = ((ALshort*)(base + offset)); offset += irSize*irCount*sizeof(Hrtf->coeffs[0]);
435 Hrtf->delays = ((ALubyte*)(base + offset)); offset += irCount*sizeof(Hrtf->delays[0]);
436 Hrtf->filename = ((char*)(base + offset));
437 Hrtf->next = NULL;
439 memcpy((void*)Hrtf->azCount, azCount, sizeof(azCount[0])*evCount);
440 memcpy((void*)Hrtf->evOffset, evOffset, sizeof(evOffset[0])*evCount);
441 memcpy((void*)Hrtf->coeffs, coeffs, sizeof(coeffs[0])*irSize*irCount);
442 memcpy((void*)Hrtf->delays, delays, sizeof(delays[0])*irCount);
443 memcpy((void*)Hrtf->filename, al_string_get_cstr(filename), al_string_length(filename)+1);
446 free(azCount);
447 free(evOffset);
448 free(coeffs);
449 return Hrtf;
452 static struct Hrtf *LoadHrtf01(const ALubyte *data, size_t datalen, const_al_string filename)
454 const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
455 struct Hrtf *Hrtf = NULL;
456 ALboolean failed = AL_FALSE;
457 ALuint rate = 0, irCount = 0;
458 ALubyte irSize = 0, evCount = 0;
459 const ALubyte *azCount = NULL;
460 ALushort *evOffset = NULL;
461 ALshort *coeffs = NULL;
462 const ALubyte *delays = NULL;
463 ALuint i, j;
465 if(datalen < 6)
467 ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n",
468 al_string_get_cstr(filename), 6, datalen);
469 return NULL;
472 rate = *(data++);
473 rate |= *(data++)<<8;
474 rate |= *(data++)<<16;
475 rate |= *(data++)<<24;
476 datalen -= 4;
478 irSize = *(data++);
479 datalen -= 1;
481 evCount = *(data++);
482 datalen -= 1;
484 if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
486 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
487 irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE);
488 failed = AL_TRUE;
490 if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT)
492 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
493 evCount, MIN_EV_COUNT, MAX_EV_COUNT);
494 failed = AL_TRUE;
496 if(failed)
497 return NULL;
499 if(datalen < evCount)
501 ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n",
502 al_string_get_cstr(filename), evCount, datalen);
503 return NULL;
506 azCount = data;
507 data += evCount;
508 datalen -= evCount;
510 evOffset = malloc(sizeof(evOffset[0])*evCount);
511 if(azCount == NULL || evOffset == NULL)
513 ERR("Out of memory.\n");
514 failed = AL_TRUE;
517 if(!failed)
519 for(i = 0;i < evCount;i++)
521 if(azCount[i] < MIN_AZ_COUNT || azCount[i] > MAX_AZ_COUNT)
523 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
524 i, azCount[i], MIN_AZ_COUNT, MAX_AZ_COUNT);
525 failed = AL_TRUE;
530 if(!failed)
532 evOffset[0] = 0;
533 irCount = azCount[0];
534 for(i = 1;i < evCount;i++)
536 evOffset[i] = evOffset[i-1] + azCount[i-1];
537 irCount += azCount[i];
540 coeffs = malloc(sizeof(coeffs[0])*irSize*irCount);
541 if(coeffs == NULL)
543 ERR("Out of memory.\n");
544 failed = AL_TRUE;
548 if(!failed)
550 size_t reqsize = 2*irSize*irCount + irCount;
551 if(datalen < reqsize)
553 ERR("Unexpected end of %s data (req "SZFMT", rem "SZFMT"\n",
554 al_string_get_cstr(filename), reqsize, datalen);
555 failed = AL_TRUE;
559 if(!failed)
561 for(i = 0;i < irCount*irSize;i+=irSize)
563 for(j = 0;j < irSize;j++)
565 ALshort coeff;
566 coeff = *(data++);
567 coeff |= *(data++)<<8;
568 datalen -= 2;
569 coeffs[i+j] = coeff;
573 delays = data;
574 data += irCount;
575 datalen -= irCount;
576 for(i = 0;i < irCount;i++)
578 if(delays[i] > maxDelay)
580 ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i], maxDelay);
581 failed = AL_TRUE;
586 if(!failed)
588 size_t total = sizeof(struct Hrtf);
589 total += sizeof(azCount[0])*evCount;
590 total = (total+1)&~1; /* Align for (u)short fields */
591 total += sizeof(evOffset[0])*evCount;
592 total += sizeof(coeffs[0])*irSize*irCount;
593 total += sizeof(delays[0])*irCount;
594 total += al_string_length(filename)+1;
596 Hrtf = al_calloc(16, total);
597 if(Hrtf == NULL)
599 ERR("Out of memory.\n");
600 failed = AL_TRUE;
604 if(!failed)
606 char *base = (char*)Hrtf;
607 uintptr_t offset = sizeof(*Hrtf);
609 Hrtf->sampleRate = rate;
610 Hrtf->irSize = irSize;
611 Hrtf->evCount = evCount;
612 Hrtf->azCount = ((ALubyte*)(base + offset)); offset += evCount*sizeof(Hrtf->azCount[0]);
613 offset = (offset+1)&~1; /* Align for (u)short fields */
614 Hrtf->evOffset = ((ALushort*)(base + offset)); offset += evCount*sizeof(Hrtf->evOffset[0]);
615 Hrtf->coeffs = ((ALshort*)(base + offset)); offset += irSize*irCount*sizeof(Hrtf->coeffs[0]);
616 Hrtf->delays = ((ALubyte*)(base + offset)); offset += irCount*sizeof(Hrtf->delays[0]);
617 Hrtf->filename = ((char*)(base + offset));
618 Hrtf->next = NULL;
620 memcpy((void*)Hrtf->azCount, azCount, sizeof(azCount[0])*evCount);
621 memcpy((void*)Hrtf->evOffset, evOffset, sizeof(evOffset[0])*evCount);
622 memcpy((void*)Hrtf->coeffs, coeffs, sizeof(coeffs[0])*irSize*irCount);
623 memcpy((void*)Hrtf->delays, delays, sizeof(delays[0])*irCount);
624 memcpy((void*)Hrtf->filename, al_string_get_cstr(filename), al_string_length(filename)+1);
627 free(evOffset);
628 free(coeffs);
629 return Hrtf;
632 static void AddFileEntry(vector_HrtfEntry *list, al_string *filename)
634 HrtfEntry entry = { AL_STRING_INIT_STATIC(), NULL };
635 struct Hrtf *hrtf = NULL;
636 const HrtfEntry *iter;
637 struct FileMapping fmap;
638 const char *name;
639 const char *ext;
640 int i;
642 #define MATCH_FNAME(i) (al_string_cmp_cstr(*filename, (i)->hrtf->filename) == 0)
643 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_FNAME);
644 if(iter != VECTOR_END(*list))
646 TRACE("Skipping duplicate file entry %s\n", al_string_get_cstr(*filename));
647 goto done;
649 #undef MATCH_FNAME
651 entry.hrtf = LoadedHrtfs;
652 while(entry.hrtf)
654 if(al_string_cmp_cstr(*filename, entry.hrtf->filename) == 0)
656 TRACE("Skipping load of already-loaded file %s\n", al_string_get_cstr(*filename));
657 goto skip_load;
659 entry.hrtf = entry.hrtf->next;
662 TRACE("Loading %s...\n", al_string_get_cstr(*filename));
663 fmap = MapFileToMem(al_string_get_cstr(*filename));
664 if(fmap.ptr == NULL)
666 ERR("Could not open %s\n", al_string_get_cstr(*filename));
667 goto done;
670 if(fmap.len < sizeof(magicMarker01))
671 ERR("%s data is too short ("SZFMT" bytes)\n", al_string_get_cstr(*filename), fmap.len);
672 else if(memcmp(fmap.ptr, magicMarker01, sizeof(magicMarker01)) == 0)
674 TRACE("Detected data set format v1\n");
675 hrtf = LoadHrtf01((const ALubyte*)fmap.ptr+sizeof(magicMarker01),
676 fmap.len-sizeof(magicMarker01), *filename
679 else if(memcmp(fmap.ptr, magicMarker00, sizeof(magicMarker00)) == 0)
681 TRACE("Detected data set format v0\n");
682 hrtf = LoadHrtf00((const ALubyte*)fmap.ptr+sizeof(magicMarker00),
683 fmap.len-sizeof(magicMarker00), *filename
686 else
687 ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(*filename), (const char*)fmap.ptr);
688 UnmapFileMem(&fmap);
690 if(!hrtf)
692 ERR("Failed to load %s\n", al_string_get_cstr(*filename));
693 goto done;
696 hrtf->next = LoadedHrtfs;
697 LoadedHrtfs = hrtf;
698 TRACE("Loaded HRTF support for format: %s %uhz\n",
699 DevFmtChannelsString(DevFmtStereo), hrtf->sampleRate);
700 entry.hrtf = hrtf;
702 skip_load:
703 /* TODO: Get a human-readable name from the HRTF data (possibly coming in a
704 * format update). */
705 name = strrchr(al_string_get_cstr(*filename), '/');
706 if(!name) name = strrchr(al_string_get_cstr(*filename), '\\');
707 if(!name) name = al_string_get_cstr(*filename);
708 else ++name;
710 ext = strrchr(name, '.');
712 i = 0;
713 do {
714 if(!ext)
715 al_string_copy_cstr(&entry.name, name);
716 else
717 al_string_copy_range(&entry.name, name, ext);
718 if(i != 0)
720 char str[64];
721 snprintf(str, sizeof(str), " #%d", i+1);
722 al_string_append_cstr(&entry.name, str);
724 ++i;
726 #define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0)
727 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_NAME);
728 #undef MATCH_NAME
729 } while(iter != VECTOR_END(*list));
731 TRACE("Adding entry \"%s\" from file \"%s\"\n", al_string_get_cstr(entry.name),
732 al_string_get_cstr(*filename));
733 VECTOR_PUSH_BACK(*list, entry);
735 done:
736 al_string_deinit(filename);
739 /* Unfortunate that we have to duplicate AddFileEntry to take a memory buffer
740 * for input instead of opening the given filename.
742 static void AddBuiltInEntry(vector_HrtfEntry *list, const ALubyte *data, size_t datalen, al_string *filename)
744 HrtfEntry entry = { AL_STRING_INIT_STATIC(), NULL };
745 struct Hrtf *hrtf = NULL;
746 const HrtfEntry *iter;
747 int i;
749 #define MATCH_FNAME(i) (al_string_cmp_cstr(*filename, (i)->hrtf->filename) == 0)
750 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_FNAME);
751 if(iter != VECTOR_END(*list))
753 TRACE("Skipping duplicate file entry %s\n", al_string_get_cstr(*filename));
754 goto done;
756 #undef MATCH_FNAME
758 entry.hrtf = LoadedHrtfs;
759 while(entry.hrtf)
761 if(al_string_cmp_cstr(*filename, entry.hrtf->filename) == 0)
763 TRACE("Skipping load of already-loaded file %s\n", al_string_get_cstr(*filename));
764 goto skip_load;
766 entry.hrtf = entry.hrtf->next;
769 TRACE("Loading %s...\n", al_string_get_cstr(*filename));
770 if(datalen < sizeof(magicMarker01))
772 ERR("%s data is too short ("SZFMT" bytes)\n", al_string_get_cstr(*filename), datalen);
773 goto done;
776 if(memcmp(data, magicMarker01, sizeof(magicMarker01)) == 0)
778 TRACE("Detected data set format v1\n");
779 hrtf = LoadHrtf01(data+sizeof(magicMarker01),
780 datalen-sizeof(magicMarker01), *filename
783 else if(memcmp(data, magicMarker00, sizeof(magicMarker00)) == 0)
785 TRACE("Detected data set format v0\n");
786 hrtf = LoadHrtf00(data+sizeof(magicMarker00),
787 datalen-sizeof(magicMarker00), *filename
790 else
791 ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(*filename), data);
793 if(!hrtf)
795 ERR("Failed to load %s\n", al_string_get_cstr(*filename));
796 goto done;
799 hrtf->next = LoadedHrtfs;
800 LoadedHrtfs = hrtf;
801 TRACE("Loaded HRTF support for format: %s %uhz\n",
802 DevFmtChannelsString(DevFmtStereo), hrtf->sampleRate);
803 entry.hrtf = hrtf;
805 skip_load:
806 i = 0;
807 do {
808 al_string_copy(&entry.name, *filename);
809 if(i != 0)
811 char str[64];
812 snprintf(str, sizeof(str), " #%d", i+1);
813 al_string_append_cstr(&entry.name, str);
815 ++i;
817 #define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0)
818 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_NAME);
819 #undef MATCH_NAME
820 } while(iter != VECTOR_END(*list));
822 TRACE("Adding built-in entry \"%s\"\n", al_string_get_cstr(entry.name));
823 VECTOR_PUSH_BACK(*list, entry);
825 done:
826 al_string_deinit(filename);
830 #ifndef ALSOFT_EMBED_HRTF_DATA
831 #define IDR_DEFAULT_44100_MHR 1
832 #define IDR_DEFAULT_48000_MHR 2
834 static const ALubyte *GetResource(int UNUSED(name), size_t *size)
836 *size = 0;
837 return NULL;
840 #else
841 #include "hrtf_res.h"
843 #ifdef _WIN32
844 static const ALubyte *GetResource(int name, size_t *size)
846 HMODULE handle;
847 HGLOBAL res;
848 HRSRC rc;
850 GetModuleHandleExW(
851 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
852 (LPCWSTR)GetResource, &handle
854 rc = FindResourceW(handle, MAKEINTRESOURCEW(name), MAKEINTRESOURCEW(MHRTYPE));
855 res = LoadResource(handle, rc);
857 *size = SizeofResource(handle, rc);
858 return LockResource(res);
861 #elif defined(__APPLE__)
863 #include <Availability.h>
864 #include <mach-o/getsect.h>
865 #include <mach-o/ldsyms.h>
867 static const ALubyte *GetResource(int name, size_t *size)
869 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1070)
870 /* NOTE: OSX 10.7 and up need to call getsectiondata(&_mh_dylib_header, ...). However, that
871 * call requires 10.7.
873 if(name == IDR_DEFAULT_44100_MHR)
874 return getsectiondata(&_mh_dylib_header, "binary", "default_44100", size);
875 if(name == IDR_DEFAULT_48000_MHR)
876 return getsectiondata(&_mh_dylib_header, "binary", "default_48000", size);
877 #else
878 if(name == IDR_DEFAULT_44100_MHR)
879 return getsectdata("binary", "default_44100", size);
880 if(name == IDR_DEFAULT_48000_MHR)
881 return getsectdata("binary", "default_48000", size);
882 #endif
883 *size = 0;
884 return NULL;
887 #else
889 extern const ALubyte _binary_default_44100_mhr_start[] HIDDEN_DECL;
890 extern const ALubyte _binary_default_44100_mhr_end[] HIDDEN_DECL;
891 extern const ALubyte _binary_default_44100_mhr_size[] HIDDEN_DECL;
893 extern const ALubyte _binary_default_48000_mhr_start[] HIDDEN_DECL;
894 extern const ALubyte _binary_default_48000_mhr_end[] HIDDEN_DECL;
895 extern const ALubyte _binary_default_48000_mhr_size[] HIDDEN_DECL;
897 static const ALubyte *GetResource(int name, size_t *size)
899 if(name == IDR_DEFAULT_44100_MHR)
901 /* Make sure all symbols are referenced, to ensure the compiler won't
902 * ignore the declarations and lose the visibility attribute used to
903 * hide them (would be nice if ld or objcopy could automatically mark
904 * them as hidden when generating them, but apparently they can't).
906 const void *volatile ptr =_binary_default_44100_mhr_size;
907 (void)ptr;
908 *size = _binary_default_44100_mhr_end - _binary_default_44100_mhr_start;
909 return _binary_default_44100_mhr_start;
911 if(name == IDR_DEFAULT_48000_MHR)
913 const void *volatile ptr =_binary_default_48000_mhr_size;
914 (void)ptr;
915 *size = _binary_default_48000_mhr_end - _binary_default_48000_mhr_start;
916 return _binary_default_48000_mhr_start;
918 *size = 0;
919 return NULL;
921 #endif
922 #endif
924 vector_HrtfEntry EnumerateHrtf(const_al_string devname)
926 vector_HrtfEntry list = VECTOR_INIT_STATIC();
927 const char *defaulthrtf = "";
928 const char *pathlist = "";
929 bool usedefaults = true;
931 if(ConfigValueStr(al_string_get_cstr(devname), NULL, "hrtf-paths", &pathlist))
933 while(pathlist && *pathlist)
935 const char *next, *end;
937 while(isspace(*pathlist) || *pathlist == ',')
938 pathlist++;
939 if(*pathlist == '\0')
940 continue;
942 next = strchr(pathlist, ',');
943 if(next)
944 end = next++;
945 else
947 end = pathlist + strlen(pathlist);
948 usedefaults = false;
951 while(end != pathlist && isspace(*(end-1)))
952 --end;
953 if(end != pathlist)
955 al_string pname = AL_STRING_INIT_STATIC();
956 vector_al_string flist;
958 al_string_append_range(&pname, pathlist, end);
960 flist = SearchDataFiles(".mhr", al_string_get_cstr(pname));
961 VECTOR_FOR_EACH_PARAMS(al_string, flist, AddFileEntry, &list);
962 VECTOR_DEINIT(flist);
964 al_string_deinit(&pname);
967 pathlist = next;
970 else if(ConfigValueExists(al_string_get_cstr(devname), NULL, "hrtf_tables"))
971 ERR("The hrtf_tables option is deprecated, please use hrtf-paths instead.\n");
973 if(usedefaults)
975 vector_al_string flist;
976 const ALubyte *rdata;
977 size_t rsize;
979 flist = SearchDataFiles(".mhr", "openal/hrtf");
980 VECTOR_FOR_EACH_PARAMS(al_string, flist, AddFileEntry, &list);
981 VECTOR_DEINIT(flist);
983 rdata = GetResource(IDR_DEFAULT_44100_MHR, &rsize);
984 if(rdata != NULL && rsize > 0)
986 al_string ename = AL_STRING_INIT_STATIC();
987 al_string_copy_cstr(&ename, "Built-In 44100hz");
988 AddBuiltInEntry(&list, rdata, rsize, &ename);
991 rdata = GetResource(IDR_DEFAULT_48000_MHR, &rsize);
992 if(rdata != NULL && rsize > 0)
994 al_string ename = AL_STRING_INIT_STATIC();
995 al_string_copy_cstr(&ename, "Built-In 48000hz");
996 AddBuiltInEntry(&list, rdata, rsize, &ename);
1000 if(VECTOR_SIZE(list) > 1 && ConfigValueStr(al_string_get_cstr(devname), NULL, "default-hrtf", &defaulthrtf))
1002 const HrtfEntry *iter;
1003 /* Find the preferred HRTF and move it to the front of the list. */
1004 #define FIND_ENTRY(i) (al_string_cmp_cstr((i)->name, defaulthrtf) == 0)
1005 VECTOR_FIND_IF(iter, const HrtfEntry, list, FIND_ENTRY);
1006 #undef FIND_ENTRY
1007 if(iter == VECTOR_END(list))
1008 WARN("Failed to find default HRTF \"%s\"\n", defaulthrtf);
1009 else if(iter != VECTOR_BEGIN(list))
1011 HrtfEntry entry = *iter;
1012 memmove(&VECTOR_ELEM(list,1), &VECTOR_ELEM(list,0),
1013 (iter-VECTOR_BEGIN(list))*sizeof(HrtfEntry));
1014 VECTOR_ELEM(list,0) = entry;
1018 return list;
1021 void FreeHrtfList(vector_HrtfEntry *list)
1023 #define CLEAR_ENTRY(i) do { \
1024 al_string_deinit(&(i)->name); \
1025 } while(0)
1026 VECTOR_FOR_EACH(HrtfEntry, *list, CLEAR_ENTRY);
1027 VECTOR_DEINIT(*list);
1028 #undef CLEAR_ENTRY
1032 void FreeHrtfs(void)
1034 struct Hrtf *Hrtf = LoadedHrtfs;
1035 LoadedHrtfs = NULL;
1037 while(Hrtf != NULL)
1039 struct Hrtf *next = Hrtf->next;
1040 al_free(Hrtf);
1041 Hrtf = next;