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
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];
93 dirfact
= 1.0f
- (spread
/ F_TAU
);
95 /* Claculate elevation indices and interpolation factor. */
96 CalcEvIndices(Hrtf
->evCount
, elevation
, evidx
, &mu
[2]);
100 ALuint azcount
= Hrtf
->azCount
[evidx
[i
]];
101 ALuint evoffset
= Hrtf
->evOffset
[evidx
[i
]];
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.
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
);
166 for(i
= 0;i
< Hrtf
->irSize
;i
++)
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;
183 ALubyte
*azCount
= NULL
;
184 ALushort
*evOffset
= NULL
;
185 ALshort
*coeffs
= NULL
;
186 ALubyte
*delays
= NULL
;
191 rate
|= fgetc(f
)<<16;
192 rate
|= fgetc(f
)<<24;
195 irCount
|= fgetc(f
)<<8;
198 irSize
|= fgetc(f
)<<8;
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
);
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
);
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");
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]);
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
);
249 if(irCount
<= evOffset
[i
-1])
251 ERR("Invalid evOffset: evOffset[%d]=%d (irCount=%d)\n",
252 i
-1, evOffset
[i
-1], irCount
);
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
);
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");
278 for(i
= 0;i
< irCount
*irSize
;i
+=irSize
)
280 for(j
= 0;j
< irSize
;j
++)
284 coeff
|= fgetc(f
)<<8;
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
);
300 ERR("Premature end of data\n");
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
);
317 ERR("Out of memory.\n");
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
));
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);
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
;
363 rate
|= fgetc(f
)<<16;
364 rate
|= fgetc(f
)<<24;
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
);
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
);
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");
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
);
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");
429 for(i
= 0;i
< irCount
*irSize
;i
+=irSize
)
431 for(j
= 0;j
< irSize
;j
++)
435 coeff
|= fgetc(f
)<<8;
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
);
451 ERR("Premature end of data\n");
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
);
468 ERR("Out of memory.\n");
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
));
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);
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
;
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
);
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
));
524 entry
.hrtf
= LoadedHrtfs
;
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
));
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");
539 ERR("Could not open %s\n", al_string_get_cstr(*filename
));
543 if(fread(magic
, 1, sizeof(magic
), f
) != sizeof(magic
))
544 ERR("Failed to read header from %s\n", al_string_get_cstr(*filename
));
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
);
558 ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(*filename
), magic
);
564 ERR("Failed to load %s\n", al_string_get_cstr(*filename
));
568 hrtf
->next
= LoadedHrtfs
;
570 TRACE("Loaded HRTF support for format: %s %uhz\n",
571 DevFmtChannelsString(DevFmtStereo
), hrtf
->sampleRate
);
575 /* TODO: Get a human-readable name from the HRTF data (possibly coming in a
577 ext
= strrchr(name
, '.');
582 al_string_copy_cstr(&entry
.name
, name
);
584 al_string_copy_range(&entry
.name
, name
, ext
);
588 snprintf(str
, sizeof(str
), " #%d", i
+1);
589 al_string_append_cstr(&entry
.name
, str
);
593 #define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0)
594 VECTOR_FIND_IF(iter
, const HrtfEntry
, *list
, 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
);
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
;
627 ERR("Unexpected end of %s data (req %d, rem "SZFMT
"\n",
628 al_string_get_cstr(filename
), 6, datalen
);
633 rate
|= *(data
++)<<8;
634 rate
|= *(data
++)<<16;
635 rate
|= *(data
++)<<24;
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
);
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
);
659 if(datalen
< evCount
)
661 ERR("Unexpected end of %s data (req %d, rem "SZFMT
"\n",
662 al_string_get_cstr(filename
), evCount
, datalen
);
670 evOffset
= malloc(sizeof(evOffset
[0])*evCount
);
671 if(azCount
== NULL
|| evOffset
== NULL
)
673 ERR("Out of memory.\n");
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
);
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
);
703 ERR("Out of memory.\n");
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
);
721 for(i
= 0;i
< irCount
*irSize
;i
+=irSize
)
723 for(j
= 0;j
< irSize
;j
++)
727 coeff
|= *(data
++)<<8;
736 for(i
= 0;i
< irCount
;i
++)
738 if(delays
[i
] > maxDelay
)
740 ERR("Invalid delays[%d]: %d (%d)\n", i
, delays
[i
], maxDelay
);
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
);
758 ERR("Out of memory.\n");
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
));
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);
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
;
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
));
806 entry
.hrtf
= LoadedHrtfs
;
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
));
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
);
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
),
833 ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(*filename
), data
);
837 ERR("Failed to load %s\n", al_string_get_cstr(*filename
));
841 hrtf
->next
= LoadedHrtfs
;
843 TRACE("Loaded HRTF support for format: %s %uhz\n",
844 DevFmtChannelsString(DevFmtStereo
), hrtf
->sampleRate
);
850 al_string_copy(&entry
.name
, *filename
);
854 snprintf(str
, sizeof(str
), " #%d", i
+1);
855 al_string_append_cstr(&entry
.name
, str
);
859 #define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0)
860 VECTOR_FIND_IF(iter
, const HrtfEntry
, *list
, 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
);
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
)
883 #include "hrtf_res.h"
886 static const ALubyte
*GetResource(int name
, size_t *size
)
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
);
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
;
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
;
931 *size
= _binary_default_48000_mhr_end
- _binary_default_48000_mhr_start
;
932 return _binary_default_48000_mhr_start
;
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
== ',')
955 if(*pathlist
== '\0')
958 next
= strchr(pathlist
, ',');
963 end
= pathlist
+ strlen(pathlist
);
967 while(end
!= pathlist
&& isspace(*(end
-1)))
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
);
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");
991 vector_al_string flist
;
992 const ALubyte
*rdata
;
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
;
1030 WARN("Failed to find default HRTF \"%s\"\n", defaulthrtf
);
1037 void FreeHrtfList(vector_HrtfEntry
*list
)
1039 #define CLEAR_ENTRY(i) do { \
1040 al_string_deinit(&(i)->name); \
1042 VECTOR_FOR_EACH(HrtfEntry
, *list
, CLEAR_ENTRY
);
1043 VECTOR_DEINIT(*list
);
1048 void FreeHrtfs(void)
1050 struct Hrtf
*Hrtf
= LoadedHrtfs
;
1055 struct Hrtf
*next
= Hrtf
->next
;