Add some helper wrappers to mmap files
[openal-soft.git] / Alc / hrtf.c
blobd0511083335f56a45f2994fe43b5abde36b8b8d0
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;
58 /* Calculate the elevation indices given the polar elevation in radians.
59 * This will return two indices between 0 and (evcount - 1) and an
60 * interpolation factor between 0.0 and 1.0.
62 static void CalcEvIndices(ALuint evcount, ALfloat ev, ALuint *evidx, ALfloat *evmu)
64 ev = (F_PI_2 + ev) * (evcount-1) / F_PI;
65 evidx[0] = fastf2u(ev);
66 evidx[1] = minu(evidx[0] + 1, evcount-1);
67 *evmu = ev - evidx[0];
70 /* Calculate the azimuth indices given the polar azimuth in radians. This
71 * will return two indices between 0 and (azcount - 1) and an interpolation
72 * factor between 0.0 and 1.0.
74 static void CalcAzIndices(ALuint azcount, ALfloat az, ALuint *azidx, ALfloat *azmu)
76 az = (F_TAU + az) * azcount / F_TAU;
77 azidx[0] = fastf2u(az) % azcount;
78 azidx[1] = (azidx[0] + 1) % azcount;
79 *azmu = az - floorf(az);
82 /* Calculates static HRIR coefficients and delays for the given polar
83 * elevation and azimuth in radians. Linear interpolation is used to
84 * increase the apparent resolution of the HRIR data set. The coefficients
85 * are also normalized and attenuated by the specified gain.
87 void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat spread, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays)
89 ALuint evidx[2], lidx[4], ridx[4];
90 ALfloat mu[3], blend[4];
91 ALfloat dirfact;
92 ALuint i;
94 dirfact = 1.0f - (spread / F_TAU);
96 /* Claculate elevation indices and interpolation factor. */
97 CalcEvIndices(Hrtf->evCount, elevation, evidx, &mu[2]);
99 for(i = 0;i < 2;i++)
101 ALuint azcount = Hrtf->azCount[evidx[i]];
102 ALuint evoffset = Hrtf->evOffset[evidx[i]];
103 ALuint azidx[2];
105 /* Calculate azimuth indices and interpolation factor for this elevation. */
106 CalcAzIndices(azcount, azimuth, azidx, &mu[i]);
108 /* Calculate a set of linear HRIR indices for left and right channels. */
109 lidx[i*2 + 0] = evoffset + azidx[0];
110 lidx[i*2 + 1] = evoffset + azidx[1];
111 ridx[i*2 + 0] = evoffset + ((azcount-azidx[0]) % azcount);
112 ridx[i*2 + 1] = evoffset + ((azcount-azidx[1]) % azcount);
115 /* Calculate 4 blending weights for 2D bilinear interpolation. */
116 blend[0] = (1.0f-mu[0]) * (1.0f-mu[2]);
117 blend[1] = ( mu[0]) * (1.0f-mu[2]);
118 blend[2] = (1.0f-mu[1]) * ( mu[2]);
119 blend[3] = ( mu[1]) * ( mu[2]);
121 /* Calculate the HRIR delays using linear interpolation. */
122 delays[0] = fastf2u((Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] +
123 Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3]) *
124 dirfact + 0.5f) << HRTFDELAY_BITS;
125 delays[1] = fastf2u((Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] +
126 Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3]) *
127 dirfact + 0.5f) << HRTFDELAY_BITS;
129 /* Calculate the sample offsets for the HRIR indices. */
130 lidx[0] *= Hrtf->irSize;
131 lidx[1] *= Hrtf->irSize;
132 lidx[2] *= Hrtf->irSize;
133 lidx[3] *= Hrtf->irSize;
134 ridx[0] *= Hrtf->irSize;
135 ridx[1] *= Hrtf->irSize;
136 ridx[2] *= Hrtf->irSize;
137 ridx[3] *= Hrtf->irSize;
139 /* Calculate the normalized and attenuated HRIR coefficients using linear
140 * interpolation when there is enough gain to warrant it. Zero the
141 * coefficients if gain is too low.
143 if(gain > 0.0001f)
145 ALfloat c;
147 i = 0;
148 c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
149 Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
150 coeffs[i][0] = lerp(PassthruCoeff, c, dirfact) * gain * (1.0f/32767.0f);
151 c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
152 Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
153 coeffs[i][1] = lerp(PassthruCoeff, c, dirfact) * gain * (1.0f/32767.0f);
155 for(i = 1;i < Hrtf->irSize;i++)
157 c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
158 Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
159 coeffs[i][0] = lerp(0.0f, c, dirfact) * gain * (1.0f/32767.0f);
160 c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
161 Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
162 coeffs[i][1] = lerp(0.0f, c, dirfact) * gain * (1.0f/32767.0f);
165 else
167 for(i = 0;i < Hrtf->irSize;i++)
169 coeffs[i][0] = 0.0f;
170 coeffs[i][1] = 0.0f;
176 ALuint BuildBFormatHrtf(const struct Hrtf *Hrtf, ALfloat (*coeffs)[HRIR_LENGTH][2], ALuint NumChannels)
178 static const struct {
179 ALfloat elevation;
180 ALfloat azimuth;
181 } CubePoints[8] = {
182 { DEG2RAD( 35.0f), DEG2RAD( -45.0f) },
183 { DEG2RAD( 35.0f), DEG2RAD( 45.0f) },
184 { DEG2RAD( 35.0f), DEG2RAD(-135.0f) },
185 { DEG2RAD( 35.0f), DEG2RAD( 135.0f) },
186 { DEG2RAD(-35.0f), DEG2RAD( -45.0f) },
187 { DEG2RAD(-35.0f), DEG2RAD( 45.0f) },
188 { DEG2RAD(-35.0f), DEG2RAD(-135.0f) },
189 { DEG2RAD(-35.0f), DEG2RAD( 135.0f) },
191 static const ALfloat CubeMatrix[8][2][MAX_AMBI_COEFFS] = {
192 { { 0.25f, 0.14425f, 0.14425f, 0.14425f }, { 0.125f, 0.125f, 0.125f, 0.125f } },
193 { { 0.25f, -0.14425f, 0.14425f, 0.14425f }, { 0.125f, -0.125f, 0.125f, 0.125f } },
194 { { 0.25f, 0.14425f, 0.14425f, -0.14425f }, { 0.125f, 0.125f, 0.125f, -0.125f } },
195 { { 0.25f, -0.14425f, 0.14425f, -0.14425f }, { 0.125f, -0.125f, 0.125f, -0.125f } },
196 { { 0.25f, 0.14425f, -0.14425f, 0.14425f }, { 0.125f, 0.125f, -0.125f, 0.125f } },
197 { { 0.25f, -0.14425f, -0.14425f, 0.14425f }, { 0.125f, -0.125f, -0.125f, 0.125f } },
198 { { 0.25f, 0.14425f, -0.14425f, -0.14425f }, { 0.125f, 0.125f, -0.125f, -0.125f } },
199 { { 0.25f, -0.14425f, -0.14425f, -0.14425f }, { 0.125f, -0.125f, -0.125f, -0.125f } },
201 /* Change this to 2 for dual-band HRTF processing. May require a higher quality
202 * band-splitter, or better calculation of the new IR length to deal with the
203 * tail generated by the filter.
205 #define NUM_BANDS 1
206 BandSplitter splitter;
207 ALfloat temps[3][HRIR_LENGTH];
208 ALuint lidx[8], ridx[8];
209 ALuint min_delay = HRTF_HISTORY_LENGTH;
210 ALuint max_length = 0;
211 ALuint i, j, c, b;
213 assert(NumChannels == 4);
215 for(c = 0;c < 8;c++)
217 ALuint evidx, azidx;
218 ALuint evoffset;
219 ALuint azcount;
221 /* Calculate elevation index. */
222 evidx = (ALuint)floorf((F_PI_2 + CubePoints[c].elevation) *
223 (Hrtf->evCount-1)/F_PI + 0.5f);
224 evidx = minu(evidx, Hrtf->evCount-1);
226 azcount = Hrtf->azCount[evidx];
227 evoffset = Hrtf->evOffset[evidx];
229 /* Calculate azimuth index for this elevation. */
230 azidx = (ALuint)floorf((F_TAU+CubePoints[c].azimuth) *
231 azcount/F_TAU + 0.5f) % azcount;
233 /* Calculate indices for left and right channels. */
234 lidx[c] = evoffset + azidx;
235 ridx[c] = evoffset + ((azcount-azidx) % azcount);
237 min_delay = minu(min_delay, minu(Hrtf->delays[lidx[c]], Hrtf->delays[ridx[c]]));
240 memset(temps, 0, sizeof(temps));
241 bandsplit_init(&splitter, 400.0f / (ALfloat)Hrtf->sampleRate);
242 for(c = 0;c < 8;c++)
244 const ALshort *fir;
245 ALuint delay;
247 /* Convert the left FIR from shorts to float */
248 fir = &Hrtf->coeffs[lidx[c] * Hrtf->irSize];
249 if(NUM_BANDS == 1)
251 for(i = 0;i < Hrtf->irSize;i++)
252 temps[0][i] = fir[i] / 32767.0f;
254 else
256 /* Band-split left HRIR into low and high frequency responses. */
257 bandsplit_clear(&splitter);
258 for(i = 0;i < Hrtf->irSize;i++)
259 temps[2][i] = fir[i] / 32767.0f;
260 bandsplit_process(&splitter, temps[0], temps[1], temps[2], HRIR_LENGTH);
263 /* Add to the left output coefficients with the specified delay. */
264 delay = Hrtf->delays[lidx[c]] - min_delay;
265 for(i = 0;i < NumChannels;++i)
267 for(b = 0;b < NUM_BANDS;b++)
269 ALuint k = 0;
270 for(j = delay;j < HRIR_LENGTH;++j)
271 coeffs[i][j][0] += temps[b][k++] * CubeMatrix[c][b][i];
274 max_length = maxu(max_length, minu(delay + Hrtf->irSize, HRIR_LENGTH));
276 /* Convert the right FIR from shorts to float */
277 fir = &Hrtf->coeffs[ridx[c] * Hrtf->irSize];
278 if(NUM_BANDS == 1)
280 for(i = 0;i < Hrtf->irSize;i++)
281 temps[0][i] = fir[i] / 32767.0f;
283 else
285 /* Band-split right HRIR into low and high frequency responses. */
286 bandsplit_clear(&splitter);
287 for(i = 0;i < Hrtf->irSize;i++)
288 temps[2][i] = fir[i] / 32767.0f;
289 bandsplit_process(&splitter, temps[0], temps[1], temps[2], HRIR_LENGTH);
292 /* Add to the right output coefficients with the specified delay. */
293 delay = Hrtf->delays[ridx[c]] - min_delay;
294 for(i = 0;i < NumChannels;++i)
296 for(b = 0;b < NUM_BANDS;b++)
298 ALuint k = 0;
299 for(j = delay;j < HRIR_LENGTH;++j)
300 coeffs[i][j][1] += temps[b][k++] * CubeMatrix[c][b][i];
303 max_length = maxu(max_length, minu(delay + Hrtf->irSize, HRIR_LENGTH));
305 TRACE("Skipped min delay: %u, new combined length: %u\n", min_delay, max_length);
306 #undef NUM_BANDS
308 return max_length;
312 static struct Hrtf *LoadHrtf00(FILE *f, const_al_string filename)
314 const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
315 struct Hrtf *Hrtf = NULL;
316 ALboolean failed = AL_FALSE;
317 ALuint rate = 0, irCount = 0;
318 ALushort irSize = 0;
319 ALubyte evCount = 0;
320 ALubyte *azCount = NULL;
321 ALushort *evOffset = NULL;
322 ALshort *coeffs = NULL;
323 ALubyte *delays = NULL;
324 ALuint i, j;
326 rate = fgetc(f);
327 rate |= fgetc(f)<<8;
328 rate |= fgetc(f)<<16;
329 rate |= fgetc(f)<<24;
331 irCount = fgetc(f);
332 irCount |= fgetc(f)<<8;
334 irSize = fgetc(f);
335 irSize |= fgetc(f)<<8;
337 evCount = fgetc(f);
339 if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
341 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
342 irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE);
343 failed = AL_TRUE;
345 if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT)
347 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
348 evCount, MIN_EV_COUNT, MAX_EV_COUNT);
349 failed = AL_TRUE;
352 if(failed)
353 return NULL;
355 azCount = malloc(sizeof(azCount[0])*evCount);
356 evOffset = malloc(sizeof(evOffset[0])*evCount);
357 if(azCount == NULL || evOffset == NULL)
359 ERR("Out of memory.\n");
360 failed = AL_TRUE;
363 if(!failed)
365 evOffset[0] = fgetc(f);
366 evOffset[0] |= fgetc(f)<<8;
367 for(i = 1;i < evCount;i++)
369 evOffset[i] = fgetc(f);
370 evOffset[i] |= fgetc(f)<<8;
371 if(evOffset[i] <= evOffset[i-1])
373 ERR("Invalid evOffset: evOffset[%d]=%d (last=%d)\n",
374 i, evOffset[i], evOffset[i-1]);
375 failed = AL_TRUE;
378 azCount[i-1] = evOffset[i] - evOffset[i-1];
379 if(azCount[i-1] < MIN_AZ_COUNT || azCount[i-1] > MAX_AZ_COUNT)
381 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
382 i-1, azCount[i-1], MIN_AZ_COUNT, MAX_AZ_COUNT);
383 failed = AL_TRUE;
386 if(irCount <= evOffset[i-1])
388 ERR("Invalid evOffset: evOffset[%d]=%d (irCount=%d)\n",
389 i-1, evOffset[i-1], irCount);
390 failed = AL_TRUE;
393 azCount[i-1] = irCount - evOffset[i-1];
394 if(azCount[i-1] < MIN_AZ_COUNT || azCount[i-1] > MAX_AZ_COUNT)
396 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
397 i-1, azCount[i-1], MIN_AZ_COUNT, MAX_AZ_COUNT);
398 failed = AL_TRUE;
402 if(!failed)
404 coeffs = malloc(sizeof(coeffs[0])*irSize*irCount);
405 delays = malloc(sizeof(delays[0])*irCount);
406 if(coeffs == NULL || delays == NULL)
408 ERR("Out of memory.\n");
409 failed = AL_TRUE;
413 if(!failed)
415 for(i = 0;i < irCount*irSize;i+=irSize)
417 for(j = 0;j < irSize;j++)
419 ALshort coeff;
420 coeff = fgetc(f);
421 coeff |= fgetc(f)<<8;
422 coeffs[i+j] = coeff;
425 for(i = 0;i < irCount;i++)
427 delays[i] = fgetc(f);
428 if(delays[i] > maxDelay)
430 ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i], maxDelay);
431 failed = AL_TRUE;
435 if(feof(f))
437 ERR("Premature end of data\n");
438 failed = AL_TRUE;
442 if(!failed)
444 size_t total = sizeof(struct Hrtf);
445 total += sizeof(azCount[0])*evCount;
446 total += sizeof(evOffset[0])*evCount;
447 total += sizeof(coeffs[0])*irSize*irCount;
448 total += sizeof(delays[0])*irCount;
449 total += al_string_length(filename)+1;
451 Hrtf = al_calloc(16, total);
452 if(Hrtf == NULL)
454 ERR("Out of memory.\n");
455 failed = AL_TRUE;
459 if(!failed)
461 Hrtf->sampleRate = rate;
462 Hrtf->irSize = irSize;
463 Hrtf->evCount = evCount;
464 Hrtf->azCount = ((ALubyte*)(Hrtf+1));
465 Hrtf->evOffset = ((ALushort*)(Hrtf->azCount + evCount));
466 Hrtf->coeffs = ((ALshort*)(Hrtf->evOffset + evCount));
467 Hrtf->delays = ((ALubyte*)(Hrtf->coeffs + irSize*irCount));
468 Hrtf->filename = ((char*)(Hrtf->delays + irCount));
469 Hrtf->next = NULL;
471 memcpy((void*)Hrtf->azCount, azCount, sizeof(azCount[0])*evCount);
472 memcpy((void*)Hrtf->evOffset, evOffset, sizeof(evOffset[0])*evCount);
473 memcpy((void*)Hrtf->coeffs, coeffs, sizeof(coeffs[0])*irSize*irCount);
474 memcpy((void*)Hrtf->delays, delays, sizeof(delays[0])*irCount);
475 memcpy((void*)Hrtf->filename, al_string_get_cstr(filename), al_string_length(filename)+1);
478 free(azCount);
479 free(evOffset);
480 free(coeffs);
481 free(delays);
482 return Hrtf;
485 static struct Hrtf *LoadHrtf01(FILE *f, const_al_string filename)
487 const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
488 struct Hrtf *Hrtf = NULL;
489 ALboolean failed = AL_FALSE;
490 ALuint rate = 0, irCount = 0;
491 ALubyte irSize = 0, evCount = 0;
492 ALubyte *azCount = NULL;
493 ALushort *evOffset = NULL;
494 ALshort *coeffs = NULL;
495 ALubyte *delays = NULL;
496 ALuint i, j;
498 rate = fgetc(f);
499 rate |= fgetc(f)<<8;
500 rate |= fgetc(f)<<16;
501 rate |= fgetc(f)<<24;
503 irSize = fgetc(f);
505 evCount = fgetc(f);
507 if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
509 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
510 irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE);
511 failed = AL_TRUE;
513 if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT)
515 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
516 evCount, MIN_EV_COUNT, MAX_EV_COUNT);
517 failed = AL_TRUE;
520 if(failed)
521 return NULL;
523 azCount = malloc(sizeof(azCount[0])*evCount);
524 evOffset = malloc(sizeof(evOffset[0])*evCount);
525 if(azCount == NULL || evOffset == NULL)
527 ERR("Out of memory.\n");
528 failed = AL_TRUE;
531 if(!failed)
533 for(i = 0;i < evCount;i++)
535 azCount[i] = fgetc(f);
536 if(azCount[i] < MIN_AZ_COUNT || azCount[i] > MAX_AZ_COUNT)
538 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
539 i, azCount[i], MIN_AZ_COUNT, MAX_AZ_COUNT);
540 failed = AL_TRUE;
545 if(!failed)
547 evOffset[0] = 0;
548 irCount = azCount[0];
549 for(i = 1;i < evCount;i++)
551 evOffset[i] = evOffset[i-1] + azCount[i-1];
552 irCount += azCount[i];
555 coeffs = malloc(sizeof(coeffs[0])*irSize*irCount);
556 delays = malloc(sizeof(delays[0])*irCount);
557 if(coeffs == NULL || delays == NULL)
559 ERR("Out of memory.\n");
560 failed = AL_TRUE;
564 if(!failed)
566 for(i = 0;i < irCount*irSize;i+=irSize)
568 for(j = 0;j < irSize;j++)
570 ALshort coeff;
571 coeff = fgetc(f);
572 coeff |= fgetc(f)<<8;
573 coeffs[i+j] = coeff;
576 for(i = 0;i < irCount;i++)
578 delays[i] = fgetc(f);
579 if(delays[i] > maxDelay)
581 ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i], maxDelay);
582 failed = AL_TRUE;
586 if(feof(f))
588 ERR("Premature end of data\n");
589 failed = AL_TRUE;
593 if(!failed)
595 size_t total = sizeof(struct Hrtf);
596 total += sizeof(azCount[0])*evCount;
597 total += sizeof(evOffset[0])*evCount;
598 total += sizeof(coeffs[0])*irSize*irCount;
599 total += sizeof(delays[0])*irCount;
600 total += al_string_length(filename)+1;
602 Hrtf = al_calloc(16, total);
603 if(Hrtf == NULL)
605 ERR("Out of memory.\n");
606 failed = AL_TRUE;
610 if(!failed)
612 Hrtf->sampleRate = rate;
613 Hrtf->irSize = irSize;
614 Hrtf->evCount = evCount;
615 Hrtf->azCount = ((ALubyte*)(Hrtf+1));
616 Hrtf->evOffset = ((ALushort*)(Hrtf->azCount + evCount));
617 Hrtf->coeffs = ((ALshort*)(Hrtf->evOffset + evCount));
618 Hrtf->delays = ((ALubyte*)(Hrtf->coeffs + irSize*irCount));
619 Hrtf->filename = ((char*)(Hrtf->delays + irCount));
620 Hrtf->next = NULL;
622 memcpy((void*)Hrtf->azCount, azCount, sizeof(azCount[0])*evCount);
623 memcpy((void*)Hrtf->evOffset, evOffset, sizeof(evOffset[0])*evCount);
624 memcpy((void*)Hrtf->coeffs, coeffs, sizeof(coeffs[0])*irSize*irCount);
625 memcpy((void*)Hrtf->delays, delays, sizeof(delays[0])*irCount);
626 memcpy((void*)Hrtf->filename, al_string_get_cstr(filename), al_string_length(filename)+1);
629 free(azCount);
630 free(evOffset);
631 free(coeffs);
632 free(delays);
633 return Hrtf;
636 static void AddFileEntry(vector_HrtfEntry *list, al_string *filename)
638 HrtfEntry entry = { AL_STRING_INIT_STATIC(), NULL };
639 struct Hrtf *hrtf = NULL;
640 const HrtfEntry *iter;
641 const char *name;
642 const char *ext;
643 ALchar magic[8];
644 FILE *f;
645 int i;
647 name = strrchr(al_string_get_cstr(*filename), '/');
648 if(!name) name = strrchr(al_string_get_cstr(*filename), '\\');
649 if(!name) name = al_string_get_cstr(*filename);
650 else ++name;
652 #define MATCH_FNAME(i) (al_string_cmp_cstr(*filename, (i)->hrtf->filename) == 0)
653 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_FNAME);
654 if(iter != VECTOR_END(*list))
656 TRACE("Skipping duplicate file entry %s\n", al_string_get_cstr(*filename));
657 goto done;
659 #undef MATCH_FNAME
661 entry.hrtf = LoadedHrtfs;
662 while(entry.hrtf)
664 if(al_string_cmp_cstr(*filename, entry.hrtf->filename) == 0)
666 TRACE("Skipping load of already-loaded file %s\n", al_string_get_cstr(*filename));
667 goto skip_load;
669 entry.hrtf = entry.hrtf->next;
672 TRACE("Loading %s...\n", al_string_get_cstr(*filename));
673 f = al_fopen(al_string_get_cstr(*filename), "rb");
674 if(f == NULL)
676 ERR("Could not open %s\n", al_string_get_cstr(*filename));
677 goto done;
680 if(fread(magic, 1, sizeof(magic), f) != sizeof(magic))
681 ERR("Failed to read header from %s\n", al_string_get_cstr(*filename));
682 else
684 if(memcmp(magic, magicMarker00, sizeof(magicMarker00)) == 0)
686 TRACE("Detected data set format v0\n");
687 hrtf = LoadHrtf00(f, *filename);
689 else if(memcmp(magic, magicMarker01, sizeof(magicMarker01)) == 0)
691 TRACE("Detected data set format v1\n");
692 hrtf = LoadHrtf01(f, *filename);
694 else
695 ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(*filename), magic);
697 fclose(f);
699 if(!hrtf)
701 ERR("Failed to load %s\n", al_string_get_cstr(*filename));
702 goto done;
705 hrtf->next = LoadedHrtfs;
706 LoadedHrtfs = hrtf;
707 TRACE("Loaded HRTF support for format: %s %uhz\n",
708 DevFmtChannelsString(DevFmtStereo), hrtf->sampleRate);
709 entry.hrtf = hrtf;
711 skip_load:
712 /* TODO: Get a human-readable name from the HRTF data (possibly coming in a
713 * format update). */
714 ext = strrchr(name, '.');
716 i = 0;
717 do {
718 if(!ext)
719 al_string_copy_cstr(&entry.name, name);
720 else
721 al_string_copy_range(&entry.name, name, ext);
722 if(i != 0)
724 char str[64];
725 snprintf(str, sizeof(str), " #%d", i+1);
726 al_string_append_cstr(&entry.name, str);
728 ++i;
730 #define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0)
731 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_NAME);
732 #undef MATCH_NAME
733 } while(iter != VECTOR_END(*list));
735 TRACE("Adding entry \"%s\" from file \"%s\"\n", al_string_get_cstr(entry.name),
736 al_string_get_cstr(*filename));
737 VECTOR_PUSH_BACK(*list, entry);
739 done:
740 al_string_deinit(filename);
744 /* Unfortunate that we have to duplicate LoadHrtf01 like this, to take a memory
745 * buffer for input instead of a FILE*, but there's no portable way to access a
746 * memory buffer through the standard FILE* I/O API (POSIX 2008 has fmemopen,
747 * and Windows doesn't seem to have anything).
749 static struct Hrtf *LoadBuiltInHrtf01(const ALubyte *data, size_t datalen, const_al_string filename)
751 const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
752 struct Hrtf *Hrtf = NULL;
753 ALboolean failed = AL_FALSE;
754 ALuint rate = 0, irCount = 0;
755 ALubyte irSize = 0, evCount = 0;
756 const ALubyte *azCount = NULL;
757 ALushort *evOffset = NULL;
758 ALshort *coeffs = NULL;
759 const ALubyte *delays = NULL;
760 ALuint i, j;
762 if(datalen < 6)
764 ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n",
765 al_string_get_cstr(filename), 6, datalen);
766 return NULL;
769 rate = *(data++);
770 rate |= *(data++)<<8;
771 rate |= *(data++)<<16;
772 rate |= *(data++)<<24;
773 datalen -= 4;
775 irSize = *(data++);
776 datalen -= 1;
778 evCount = *(data++);
779 datalen -= 1;
781 if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
783 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
784 irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE);
785 failed = AL_TRUE;
787 if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT)
789 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
790 evCount, MIN_EV_COUNT, MAX_EV_COUNT);
791 failed = AL_TRUE;
793 if(failed)
794 return NULL;
796 if(datalen < evCount)
798 ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n",
799 al_string_get_cstr(filename), evCount, datalen);
800 return NULL;
803 azCount = data;
804 data += evCount;
805 datalen -= evCount;
807 evOffset = malloc(sizeof(evOffset[0])*evCount);
808 if(azCount == NULL || evOffset == NULL)
810 ERR("Out of memory.\n");
811 failed = AL_TRUE;
814 if(!failed)
816 for(i = 0;i < evCount;i++)
818 if(azCount[i] < MIN_AZ_COUNT || azCount[i] > MAX_AZ_COUNT)
820 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
821 i, azCount[i], MIN_AZ_COUNT, MAX_AZ_COUNT);
822 failed = AL_TRUE;
827 if(!failed)
829 evOffset[0] = 0;
830 irCount = azCount[0];
831 for(i = 1;i < evCount;i++)
833 evOffset[i] = evOffset[i-1] + azCount[i-1];
834 irCount += azCount[i];
837 coeffs = malloc(sizeof(coeffs[0])*irSize*irCount);
838 if(coeffs == NULL)
840 ERR("Out of memory.\n");
841 failed = AL_TRUE;
845 if(!failed)
847 size_t reqsize = 2*irSize*irCount + irCount;
848 if(datalen < reqsize)
850 ERR("Unexpected end of %s data (req "SZFMT", rem "SZFMT"\n",
851 al_string_get_cstr(filename), reqsize, datalen);
852 failed = AL_TRUE;
856 if(!failed)
858 for(i = 0;i < irCount*irSize;i+=irSize)
860 for(j = 0;j < irSize;j++)
862 ALshort coeff;
863 coeff = *(data++);
864 coeff |= *(data++)<<8;
865 datalen -= 2;
866 coeffs[i+j] = coeff;
870 delays = data;
871 data += irCount;
872 datalen -= irCount;
873 for(i = 0;i < irCount;i++)
875 if(delays[i] > maxDelay)
877 ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i], maxDelay);
878 failed = AL_TRUE;
883 if(!failed)
885 size_t total = sizeof(struct Hrtf);
886 total += sizeof(azCount[0])*evCount;
887 total += sizeof(evOffset[0])*evCount;
888 total += sizeof(coeffs[0])*irSize*irCount;
889 total += sizeof(delays[0])*irCount;
890 total += al_string_length(filename)+1;
892 Hrtf = al_calloc(16, total);
893 if(Hrtf == NULL)
895 ERR("Out of memory.\n");
896 failed = AL_TRUE;
900 if(!failed)
902 Hrtf->sampleRate = rate;
903 Hrtf->irSize = irSize;
904 Hrtf->evCount = evCount;
905 Hrtf->azCount = ((ALubyte*)(Hrtf+1));
906 Hrtf->evOffset = ((ALushort*)(Hrtf->azCount + evCount));
907 Hrtf->coeffs = ((ALshort*)(Hrtf->evOffset + evCount));
908 Hrtf->delays = ((ALubyte*)(Hrtf->coeffs + irSize*irCount));
909 Hrtf->filename = ((char*)(Hrtf->delays + irCount));
910 Hrtf->next = NULL;
912 memcpy((void*)Hrtf->azCount, azCount, sizeof(azCount[0])*evCount);
913 memcpy((void*)Hrtf->evOffset, evOffset, sizeof(evOffset[0])*evCount);
914 memcpy((void*)Hrtf->coeffs, coeffs, sizeof(coeffs[0])*irSize*irCount);
915 memcpy((void*)Hrtf->delays, delays, sizeof(delays[0])*irCount);
916 memcpy((void*)Hrtf->filename, al_string_get_cstr(filename), al_string_length(filename)+1);
919 free(evOffset);
920 free(coeffs);
921 return Hrtf;
924 /* Another unfortunate duplication, this time of AddFileEntry to take a memory
925 * buffer for input instead of opening the given filename.
927 static void AddBuiltInEntry(vector_HrtfEntry *list, const ALubyte *data, size_t datalen, al_string *filename)
929 HrtfEntry entry = { AL_STRING_INIT_STATIC(), NULL };
930 struct Hrtf *hrtf = NULL;
931 const HrtfEntry *iter;
932 int i;
934 #define MATCH_FNAME(i) (al_string_cmp_cstr(*filename, (i)->hrtf->filename) == 0)
935 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_FNAME);
936 if(iter != VECTOR_END(*list))
938 TRACE("Skipping duplicate file entry %s\n", al_string_get_cstr(*filename));
939 goto done;
941 #undef MATCH_FNAME
943 entry.hrtf = LoadedHrtfs;
944 while(entry.hrtf)
946 if(al_string_cmp_cstr(*filename, entry.hrtf->filename) == 0)
948 TRACE("Skipping load of already-loaded file %s\n", al_string_get_cstr(*filename));
949 goto skip_load;
951 entry.hrtf = entry.hrtf->next;
954 TRACE("Loading %s...\n", al_string_get_cstr(*filename));
955 if(datalen < sizeof(magicMarker01))
957 ERR("%s data is too short ("SZFMT" bytes)\n", al_string_get_cstr(*filename), datalen);
958 goto done;
961 if(memcmp(data, magicMarker01, sizeof(magicMarker01)) == 0)
963 TRACE("Detected data set format v1\n");
964 hrtf = LoadBuiltInHrtf01(
965 data+sizeof(magicMarker01), datalen-sizeof(magicMarker01),
966 *filename
969 else
970 ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(*filename), data);
972 if(!hrtf)
974 ERR("Failed to load %s\n", al_string_get_cstr(*filename));
975 goto done;
978 hrtf->next = LoadedHrtfs;
979 LoadedHrtfs = hrtf;
980 TRACE("Loaded HRTF support for format: %s %uhz\n",
981 DevFmtChannelsString(DevFmtStereo), hrtf->sampleRate);
982 entry.hrtf = hrtf;
984 skip_load:
985 i = 0;
986 do {
987 al_string_copy(&entry.name, *filename);
988 if(i != 0)
990 char str[64];
991 snprintf(str, sizeof(str), " #%d", i+1);
992 al_string_append_cstr(&entry.name, str);
994 ++i;
996 #define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0)
997 VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_NAME);
998 #undef MATCH_NAME
999 } while(iter != VECTOR_END(*list));
1001 TRACE("Adding built-in entry \"%s\"\n", al_string_get_cstr(entry.name));
1002 VECTOR_PUSH_BACK(*list, entry);
1004 done:
1005 al_string_deinit(filename);
1009 #ifndef ALSOFT_EMBED_HRTF_DATA
1010 #define IDR_DEFAULT_44100_MHR 0
1011 #define IDR_DEFAULT_48000_MHR 1
1013 static const ALubyte *GetResource(int UNUSED(name), size_t *size)
1015 *size = 0;
1016 return NULL;
1019 #else
1020 #include "hrtf_res.h"
1022 #ifdef _WIN32
1023 static const ALubyte *GetResource(int name, size_t *size)
1025 HMODULE handle;
1026 HGLOBAL res;
1027 HRSRC rc;
1029 GetModuleHandleExW(
1030 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
1031 (LPCWSTR)GetResource, &handle
1033 rc = FindResourceW(handle, MAKEINTRESOURCEW(name), MAKEINTRESOURCEW(MHRTYPE));
1034 res = LoadResource(handle, rc);
1036 *size = SizeofResource(handle, rc);
1037 return LockResource(res);
1040 #else
1042 extern const ALubyte _binary_default_44100_mhr_start[] HIDDEN_DECL;
1043 extern const ALubyte _binary_default_44100_mhr_end[] HIDDEN_DECL;
1044 extern const ALubyte _binary_default_44100_mhr_size[] HIDDEN_DECL;
1046 extern const ALubyte _binary_default_48000_mhr_start[] HIDDEN_DECL;
1047 extern const ALubyte _binary_default_48000_mhr_end[] HIDDEN_DECL;
1048 extern const ALubyte _binary_default_48000_mhr_size[] HIDDEN_DECL;
1050 static const ALubyte *GetResource(int name, size_t *size)
1052 if(name == IDR_DEFAULT_44100_MHR)
1054 /* Make sure all symbols are referenced, to ensure the compiler won't
1055 * ignore the declarations and lose the visibility attribute used to
1056 * hide them (would be nice if ld or objcopy could automatically mark
1057 * them as hidden when generating them, but apparently they can't).
1059 const void *volatile ptr =_binary_default_44100_mhr_size;
1060 (void)ptr;
1061 *size = _binary_default_44100_mhr_end - _binary_default_44100_mhr_start;
1062 return _binary_default_44100_mhr_start;
1064 if(name == IDR_DEFAULT_48000_MHR)
1066 const void *volatile ptr =_binary_default_48000_mhr_size;
1067 (void)ptr;
1068 *size = _binary_default_48000_mhr_end - _binary_default_48000_mhr_start;
1069 return _binary_default_48000_mhr_start;
1071 *size = 0;
1072 return NULL;
1074 #endif
1075 #endif
1077 vector_HrtfEntry EnumerateHrtf(const_al_string devname)
1079 vector_HrtfEntry list = VECTOR_INIT_STATIC();
1080 const char *defaulthrtf = "";
1081 const char *pathlist = "";
1082 bool usedefaults = true;
1084 if(ConfigValueStr(al_string_get_cstr(devname), NULL, "hrtf-paths", &pathlist))
1086 while(pathlist && *pathlist)
1088 const char *next, *end;
1090 while(isspace(*pathlist) || *pathlist == ',')
1091 pathlist++;
1092 if(*pathlist == '\0')
1093 continue;
1095 next = strchr(pathlist, ',');
1096 if(next)
1097 end = next++;
1098 else
1100 end = pathlist + strlen(pathlist);
1101 usedefaults = false;
1104 while(end != pathlist && isspace(*(end-1)))
1105 --end;
1106 if(end != pathlist)
1108 al_string pname = AL_STRING_INIT_STATIC();
1109 vector_al_string flist;
1111 al_string_append_range(&pname, pathlist, end);
1113 flist = SearchDataFiles(".mhr", al_string_get_cstr(pname));
1114 VECTOR_FOR_EACH_PARAMS(al_string, flist, AddFileEntry, &list);
1115 VECTOR_DEINIT(flist);
1117 al_string_deinit(&pname);
1120 pathlist = next;
1123 else if(ConfigValueExists(al_string_get_cstr(devname), NULL, "hrtf_tables"))
1124 ERR("The hrtf_tables option is deprecated, please use hrtf-paths instead.\n");
1126 if(usedefaults)
1128 vector_al_string flist;
1129 const ALubyte *rdata;
1130 size_t rsize;
1132 flist = SearchDataFiles(".mhr", "openal/hrtf");
1133 VECTOR_FOR_EACH_PARAMS(al_string, flist, AddFileEntry, &list);
1134 VECTOR_DEINIT(flist);
1136 rdata = GetResource(IDR_DEFAULT_44100_MHR, &rsize);
1137 if(rdata != NULL && rsize > 0)
1139 al_string ename = AL_STRING_INIT_STATIC();
1140 al_string_copy_cstr(&ename, "Built-In 44100hz");
1141 AddBuiltInEntry(&list, rdata, rsize, &ename);
1144 rdata = GetResource(IDR_DEFAULT_48000_MHR, &rsize);
1145 if(rdata != NULL && rsize > 0)
1147 al_string ename = AL_STRING_INIT_STATIC();
1148 al_string_copy_cstr(&ename, "Built-In 48000hz");
1149 AddBuiltInEntry(&list, rdata, rsize, &ename);
1153 if(VECTOR_SIZE(list) > 1 && ConfigValueStr(al_string_get_cstr(devname), NULL, "default-hrtf", &defaulthrtf))
1155 const HrtfEntry *iter;
1156 /* Find the preferred HRTF and move it to the front of the list. */
1157 #define FIND_ENTRY(i) (al_string_cmp_cstr((i)->name, defaulthrtf) == 0)
1158 VECTOR_FIND_IF(iter, const HrtfEntry, list, FIND_ENTRY);
1159 if(iter != VECTOR_END(list) && iter != VECTOR_BEGIN(list))
1161 HrtfEntry entry = *iter;
1162 memmove(&VECTOR_ELEM(list,1), &VECTOR_ELEM(list,0),
1163 (iter-VECTOR_BEGIN(list))*sizeof(HrtfEntry));
1164 VECTOR_ELEM(list,0) = entry;
1166 else
1167 WARN("Failed to find default HRTF \"%s\"\n", defaulthrtf);
1168 #undef FIND_ENTRY
1171 return list;
1174 void FreeHrtfList(vector_HrtfEntry *list)
1176 #define CLEAR_ENTRY(i) do { \
1177 al_string_deinit(&(i)->name); \
1178 } while(0)
1179 VECTOR_FOR_EACH(HrtfEntry, *list, CLEAR_ENTRY);
1180 VECTOR_DEINIT(*list);
1181 #undef CLEAR_ENTRY
1185 void FreeHrtfs(void)
1187 struct Hrtf *Hrtf = LoadedHrtfs;
1188 LoadedHrtfs = NULL;
1190 while(Hrtf != NULL)
1192 struct Hrtf *next = Hrtf->next;
1193 al_free(Hrtf);
1194 Hrtf = next;