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 ALuint
BuildBFormatHrtf(const struct Hrtf
*Hrtf
, ALfloat (*coeffs
)[HRIR_LENGTH
][2], ALuint NumChannels
)
177 static const struct {
181 { DEG2RAD( 35.0f
), DEG2RAD( -45.0f
) },
182 { DEG2RAD( 35.0f
), DEG2RAD( 45.0f
) },
183 { DEG2RAD( 35.0f
), DEG2RAD(-135.0f
) },
184 { DEG2RAD( 35.0f
), DEG2RAD( 135.0f
) },
185 { DEG2RAD(-35.0f
), DEG2RAD( -45.0f
) },
186 { DEG2RAD(-35.0f
), DEG2RAD( 45.0f
) },
187 { DEG2RAD(-35.0f
), DEG2RAD(-135.0f
) },
188 { DEG2RAD(-35.0f
), DEG2RAD( 135.0f
) },
190 static const ALfloat CubeMatrix
[8][MAX_AMBI_COEFFS
] = {
191 { 0.25f
, 0.14425f
, 0.14425f
, 0.14425f
},
192 { 0.25f
, -0.14425f
, 0.14425f
, 0.14425f
},
193 { 0.25f
, 0.14425f
, 0.14425f
, -0.14425f
},
194 { 0.25f
, -0.14425f
, 0.14425f
, -0.14425f
},
195 { 0.25f
, 0.14425f
, -0.14425f
, 0.14425f
},
196 { 0.25f
, -0.14425f
, -0.14425f
, 0.14425f
},
197 { 0.25f
, 0.14425f
, -0.14425f
, -0.14425f
},
198 { 0.25f
, -0.14425f
, -0.14425f
, -0.14425f
},
200 ALuint lidx
[8], ridx
[8];
201 ALuint min_delay
= HRTF_HISTORY_LENGTH
;
202 ALuint max_length
= 0;
205 assert(NumChannels
== 4);
213 /* Calculate elevation index. */
214 evidx
= (ALuint
)floorf((F_PI_2
+ CubePoints
[c
].elevation
) *
215 (Hrtf
->evCount
-1)/F_PI
+ 0.5f
);
216 evidx
= minu(evidx
, Hrtf
->evCount
-1);
218 azcount
= Hrtf
->azCount
[evidx
];
219 evoffset
= Hrtf
->evOffset
[evidx
];
221 /* Calculate azimuth index for this elevation. */
222 azidx
= (ALuint
)floorf((F_TAU
+CubePoints
[c
].azimuth
) *
223 azcount
/F_TAU
+ 0.5f
) % azcount
;
225 /* Calculate indices for left and right channels. */
226 lidx
[c
] = evoffset
+ azidx
;
227 ridx
[c
] = evoffset
+ ((azcount
-azidx
) % azcount
);
229 min_delay
= minu(min_delay
, minu(Hrtf
->delays
[lidx
[c
]], Hrtf
->delays
[ridx
[c
]]));
238 fir
= &Hrtf
->coeffs
[lidx
[c
] * Hrtf
->irSize
];
239 delay
= Hrtf
->delays
[lidx
[c
]] - min_delay
;
240 length
= minu(delay
+ Hrtf
->irSize
, HRIR_LENGTH
);
241 for(i
= 0;i
< NumChannels
;++i
)
244 for(j
= delay
;j
< length
;++j
)
245 coeffs
[i
][j
][0] += fir
[k
++]/32767.0f
* CubeMatrix
[c
][i
];
247 max_length
= maxu(max_length
, length
);
249 fir
= &Hrtf
->coeffs
[ridx
[c
] * Hrtf
->irSize
];
250 delay
= Hrtf
->delays
[ridx
[c
]] - min_delay
;
251 length
= minu(delay
+ Hrtf
->irSize
, HRIR_LENGTH
);
252 for(i
= 0;i
< NumChannels
;++i
)
255 for(j
= delay
;j
< length
;++j
)
256 coeffs
[i
][j
][1] += fir
[k
++]/32767.0f
* CubeMatrix
[c
][i
];
258 max_length
= maxu(max_length
, length
);
260 TRACE("Skipped min delay: %u, new combined length: %u\n", min_delay
, max_length
);
266 static struct Hrtf
*LoadHrtf00(FILE *f
, const_al_string filename
)
268 const ALubyte maxDelay
= HRTF_HISTORY_LENGTH
-1;
269 struct Hrtf
*Hrtf
= NULL
;
270 ALboolean failed
= AL_FALSE
;
271 ALuint rate
= 0, irCount
= 0;
274 ALubyte
*azCount
= NULL
;
275 ALushort
*evOffset
= NULL
;
276 ALshort
*coeffs
= NULL
;
277 ALubyte
*delays
= NULL
;
282 rate
|= fgetc(f
)<<16;
283 rate
|= fgetc(f
)<<24;
286 irCount
|= fgetc(f
)<<8;
289 irSize
|= fgetc(f
)<<8;
293 if(irSize
< MIN_IR_SIZE
|| irSize
> MAX_IR_SIZE
|| (irSize
%MOD_IR_SIZE
))
295 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
296 irSize
, MIN_IR_SIZE
, MAX_IR_SIZE
, MOD_IR_SIZE
);
299 if(evCount
< MIN_EV_COUNT
|| evCount
> MAX_EV_COUNT
)
301 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
302 evCount
, MIN_EV_COUNT
, MAX_EV_COUNT
);
309 azCount
= malloc(sizeof(azCount
[0])*evCount
);
310 evOffset
= malloc(sizeof(evOffset
[0])*evCount
);
311 if(azCount
== NULL
|| evOffset
== NULL
)
313 ERR("Out of memory.\n");
319 evOffset
[0] = fgetc(f
);
320 evOffset
[0] |= fgetc(f
)<<8;
321 for(i
= 1;i
< evCount
;i
++)
323 evOffset
[i
] = fgetc(f
);
324 evOffset
[i
] |= fgetc(f
)<<8;
325 if(evOffset
[i
] <= evOffset
[i
-1])
327 ERR("Invalid evOffset: evOffset[%d]=%d (last=%d)\n",
328 i
, evOffset
[i
], evOffset
[i
-1]);
332 azCount
[i
-1] = evOffset
[i
] - evOffset
[i
-1];
333 if(azCount
[i
-1] < MIN_AZ_COUNT
|| azCount
[i
-1] > MAX_AZ_COUNT
)
335 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
336 i
-1, azCount
[i
-1], MIN_AZ_COUNT
, MAX_AZ_COUNT
);
340 if(irCount
<= evOffset
[i
-1])
342 ERR("Invalid evOffset: evOffset[%d]=%d (irCount=%d)\n",
343 i
-1, evOffset
[i
-1], irCount
);
347 azCount
[i
-1] = irCount
- evOffset
[i
-1];
348 if(azCount
[i
-1] < MIN_AZ_COUNT
|| azCount
[i
-1] > MAX_AZ_COUNT
)
350 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
351 i
-1, azCount
[i
-1], MIN_AZ_COUNT
, MAX_AZ_COUNT
);
358 coeffs
= malloc(sizeof(coeffs
[0])*irSize
*irCount
);
359 delays
= malloc(sizeof(delays
[0])*irCount
);
360 if(coeffs
== NULL
|| delays
== NULL
)
362 ERR("Out of memory.\n");
369 for(i
= 0;i
< irCount
*irSize
;i
+=irSize
)
371 for(j
= 0;j
< irSize
;j
++)
375 coeff
|= fgetc(f
)<<8;
379 for(i
= 0;i
< irCount
;i
++)
381 delays
[i
] = fgetc(f
);
382 if(delays
[i
] > maxDelay
)
384 ERR("Invalid delays[%d]: %d (%d)\n", i
, delays
[i
], maxDelay
);
391 ERR("Premature end of data\n");
398 size_t total
= sizeof(struct Hrtf
);
399 total
+= sizeof(azCount
[0])*evCount
;
400 total
+= sizeof(evOffset
[0])*evCount
;
401 total
+= sizeof(coeffs
[0])*irSize
*irCount
;
402 total
+= sizeof(delays
[0])*irCount
;
403 total
+= al_string_length(filename
)+1;
405 Hrtf
= al_calloc(16, total
);
408 ERR("Out of memory.\n");
415 Hrtf
->sampleRate
= rate
;
416 Hrtf
->irSize
= irSize
;
417 Hrtf
->evCount
= evCount
;
418 Hrtf
->azCount
= ((ALubyte
*)(Hrtf
+1));
419 Hrtf
->evOffset
= ((ALushort
*)(Hrtf
->azCount
+ evCount
));
420 Hrtf
->coeffs
= ((ALshort
*)(Hrtf
->evOffset
+ evCount
));
421 Hrtf
->delays
= ((ALubyte
*)(Hrtf
->coeffs
+ irSize
*irCount
));
422 Hrtf
->filename
= ((char*)(Hrtf
->delays
+ irCount
));
425 memcpy((void*)Hrtf
->azCount
, azCount
, sizeof(azCount
[0])*evCount
);
426 memcpy((void*)Hrtf
->evOffset
, evOffset
, sizeof(evOffset
[0])*evCount
);
427 memcpy((void*)Hrtf
->coeffs
, coeffs
, sizeof(coeffs
[0])*irSize
*irCount
);
428 memcpy((void*)Hrtf
->delays
, delays
, sizeof(delays
[0])*irCount
);
429 memcpy((void*)Hrtf
->filename
, al_string_get_cstr(filename
), al_string_length(filename
)+1);
439 static struct Hrtf
*LoadHrtf01(FILE *f
, const_al_string filename
)
441 const ALubyte maxDelay
= HRTF_HISTORY_LENGTH
-1;
442 struct Hrtf
*Hrtf
= NULL
;
443 ALboolean failed
= AL_FALSE
;
444 ALuint rate
= 0, irCount
= 0;
445 ALubyte irSize
= 0, evCount
= 0;
446 ALubyte
*azCount
= NULL
;
447 ALushort
*evOffset
= NULL
;
448 ALshort
*coeffs
= NULL
;
449 ALubyte
*delays
= NULL
;
454 rate
|= fgetc(f
)<<16;
455 rate
|= fgetc(f
)<<24;
461 if(irSize
< MIN_IR_SIZE
|| irSize
> MAX_IR_SIZE
|| (irSize
%MOD_IR_SIZE
))
463 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
464 irSize
, MIN_IR_SIZE
, MAX_IR_SIZE
, MOD_IR_SIZE
);
467 if(evCount
< MIN_EV_COUNT
|| evCount
> MAX_EV_COUNT
)
469 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
470 evCount
, MIN_EV_COUNT
, MAX_EV_COUNT
);
477 azCount
= malloc(sizeof(azCount
[0])*evCount
);
478 evOffset
= malloc(sizeof(evOffset
[0])*evCount
);
479 if(azCount
== NULL
|| evOffset
== NULL
)
481 ERR("Out of memory.\n");
487 for(i
= 0;i
< evCount
;i
++)
489 azCount
[i
] = fgetc(f
);
490 if(azCount
[i
] < MIN_AZ_COUNT
|| azCount
[i
] > MAX_AZ_COUNT
)
492 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
493 i
, azCount
[i
], MIN_AZ_COUNT
, MAX_AZ_COUNT
);
502 irCount
= azCount
[0];
503 for(i
= 1;i
< evCount
;i
++)
505 evOffset
[i
] = evOffset
[i
-1] + azCount
[i
-1];
506 irCount
+= azCount
[i
];
509 coeffs
= malloc(sizeof(coeffs
[0])*irSize
*irCount
);
510 delays
= malloc(sizeof(delays
[0])*irCount
);
511 if(coeffs
== NULL
|| delays
== NULL
)
513 ERR("Out of memory.\n");
520 for(i
= 0;i
< irCount
*irSize
;i
+=irSize
)
522 for(j
= 0;j
< irSize
;j
++)
526 coeff
|= fgetc(f
)<<8;
530 for(i
= 0;i
< irCount
;i
++)
532 delays
[i
] = fgetc(f
);
533 if(delays
[i
] > maxDelay
)
535 ERR("Invalid delays[%d]: %d (%d)\n", i
, delays
[i
], maxDelay
);
542 ERR("Premature end of data\n");
549 size_t total
= sizeof(struct Hrtf
);
550 total
+= sizeof(azCount
[0])*evCount
;
551 total
+= sizeof(evOffset
[0])*evCount
;
552 total
+= sizeof(coeffs
[0])*irSize
*irCount
;
553 total
+= sizeof(delays
[0])*irCount
;
554 total
+= al_string_length(filename
)+1;
556 Hrtf
= al_calloc(16, total
);
559 ERR("Out of memory.\n");
566 Hrtf
->sampleRate
= rate
;
567 Hrtf
->irSize
= irSize
;
568 Hrtf
->evCount
= evCount
;
569 Hrtf
->azCount
= ((ALubyte
*)(Hrtf
+1));
570 Hrtf
->evOffset
= ((ALushort
*)(Hrtf
->azCount
+ evCount
));
571 Hrtf
->coeffs
= ((ALshort
*)(Hrtf
->evOffset
+ evCount
));
572 Hrtf
->delays
= ((ALubyte
*)(Hrtf
->coeffs
+ irSize
*irCount
));
573 Hrtf
->filename
= ((char*)(Hrtf
->delays
+ irCount
));
576 memcpy((void*)Hrtf
->azCount
, azCount
, sizeof(azCount
[0])*evCount
);
577 memcpy((void*)Hrtf
->evOffset
, evOffset
, sizeof(evOffset
[0])*evCount
);
578 memcpy((void*)Hrtf
->coeffs
, coeffs
, sizeof(coeffs
[0])*irSize
*irCount
);
579 memcpy((void*)Hrtf
->delays
, delays
, sizeof(delays
[0])*irCount
);
580 memcpy((void*)Hrtf
->filename
, al_string_get_cstr(filename
), al_string_length(filename
)+1);
590 static void AddFileEntry(vector_HrtfEntry
*list
, al_string
*filename
)
592 HrtfEntry entry
= { AL_STRING_INIT_STATIC(), NULL
};
593 struct Hrtf
*hrtf
= NULL
;
594 const HrtfEntry
*iter
;
601 name
= strrchr(al_string_get_cstr(*filename
), '/');
602 if(!name
) name
= strrchr(al_string_get_cstr(*filename
), '\\');
603 if(!name
) name
= al_string_get_cstr(*filename
);
606 #define MATCH_FNAME(i) (al_string_cmp_cstr(*filename, (i)->hrtf->filename) == 0)
607 VECTOR_FIND_IF(iter
, const HrtfEntry
, *list
, MATCH_FNAME
);
608 if(iter
!= VECTOR_END(*list
))
610 TRACE("Skipping duplicate file entry %s\n", al_string_get_cstr(*filename
));
615 entry
.hrtf
= LoadedHrtfs
;
618 if(al_string_cmp_cstr(*filename
, entry
.hrtf
->filename
) == 0)
620 TRACE("Skipping load of already-loaded file %s\n", al_string_get_cstr(*filename
));
623 entry
.hrtf
= entry
.hrtf
->next
;
626 TRACE("Loading %s...\n", al_string_get_cstr(*filename
));
627 f
= al_fopen(al_string_get_cstr(*filename
), "rb");
630 ERR("Could not open %s\n", al_string_get_cstr(*filename
));
634 if(fread(magic
, 1, sizeof(magic
), f
) != sizeof(magic
))
635 ERR("Failed to read header from %s\n", al_string_get_cstr(*filename
));
638 if(memcmp(magic
, magicMarker00
, sizeof(magicMarker00
)) == 0)
640 TRACE("Detected data set format v0\n");
641 hrtf
= LoadHrtf00(f
, *filename
);
643 else if(memcmp(magic
, magicMarker01
, sizeof(magicMarker01
)) == 0)
645 TRACE("Detected data set format v1\n");
646 hrtf
= LoadHrtf01(f
, *filename
);
649 ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(*filename
), magic
);
655 ERR("Failed to load %s\n", al_string_get_cstr(*filename
));
659 hrtf
->next
= LoadedHrtfs
;
661 TRACE("Loaded HRTF support for format: %s %uhz\n",
662 DevFmtChannelsString(DevFmtStereo
), hrtf
->sampleRate
);
666 /* TODO: Get a human-readable name from the HRTF data (possibly coming in a
668 ext
= strrchr(name
, '.');
673 al_string_copy_cstr(&entry
.name
, name
);
675 al_string_copy_range(&entry
.name
, name
, ext
);
679 snprintf(str
, sizeof(str
), " #%d", i
+1);
680 al_string_append_cstr(&entry
.name
, str
);
684 #define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0)
685 VECTOR_FIND_IF(iter
, const HrtfEntry
, *list
, MATCH_NAME
);
687 } while(iter
!= VECTOR_END(*list
));
689 TRACE("Adding entry \"%s\" from file \"%s\"\n", al_string_get_cstr(entry
.name
),
690 al_string_get_cstr(*filename
));
691 VECTOR_PUSH_BACK(*list
, entry
);
694 al_string_deinit(filename
);
698 /* Unfortunate that we have to duplicate LoadHrtf01 like this, to take a memory
699 * buffer for input instead of a FILE*, but there's no portable way to access a
700 * memory buffer through the standard FILE* I/O API (POSIX 2008 has fmemopen,
701 * and Windows doesn't seem to have anything).
703 static struct Hrtf
*LoadBuiltInHrtf01(const ALubyte
*data
, size_t datalen
, const_al_string filename
)
705 const ALubyte maxDelay
= HRTF_HISTORY_LENGTH
-1;
706 struct Hrtf
*Hrtf
= NULL
;
707 ALboolean failed
= AL_FALSE
;
708 ALuint rate
= 0, irCount
= 0;
709 ALubyte irSize
= 0, evCount
= 0;
710 const ALubyte
*azCount
= NULL
;
711 ALushort
*evOffset
= NULL
;
712 ALshort
*coeffs
= NULL
;
713 const ALubyte
*delays
= NULL
;
718 ERR("Unexpected end of %s data (req %d, rem "SZFMT
"\n",
719 al_string_get_cstr(filename
), 6, datalen
);
724 rate
|= *(data
++)<<8;
725 rate
|= *(data
++)<<16;
726 rate
|= *(data
++)<<24;
735 if(irSize
< MIN_IR_SIZE
|| irSize
> MAX_IR_SIZE
|| (irSize
%MOD_IR_SIZE
))
737 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
738 irSize
, MIN_IR_SIZE
, MAX_IR_SIZE
, MOD_IR_SIZE
);
741 if(evCount
< MIN_EV_COUNT
|| evCount
> MAX_EV_COUNT
)
743 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
744 evCount
, MIN_EV_COUNT
, MAX_EV_COUNT
);
750 if(datalen
< evCount
)
752 ERR("Unexpected end of %s data (req %d, rem "SZFMT
"\n",
753 al_string_get_cstr(filename
), evCount
, datalen
);
761 evOffset
= malloc(sizeof(evOffset
[0])*evCount
);
762 if(azCount
== NULL
|| evOffset
== NULL
)
764 ERR("Out of memory.\n");
770 for(i
= 0;i
< evCount
;i
++)
772 if(azCount
[i
] < MIN_AZ_COUNT
|| azCount
[i
] > MAX_AZ_COUNT
)
774 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
775 i
, azCount
[i
], MIN_AZ_COUNT
, MAX_AZ_COUNT
);
784 irCount
= azCount
[0];
785 for(i
= 1;i
< evCount
;i
++)
787 evOffset
[i
] = evOffset
[i
-1] + azCount
[i
-1];
788 irCount
+= azCount
[i
];
791 coeffs
= malloc(sizeof(coeffs
[0])*irSize
*irCount
);
794 ERR("Out of memory.\n");
801 size_t reqsize
= 2*irSize
*irCount
+ irCount
;
802 if(datalen
< reqsize
)
804 ERR("Unexpected end of %s data (req "SZFMT
", rem "SZFMT
"\n",
805 al_string_get_cstr(filename
), reqsize
, datalen
);
812 for(i
= 0;i
< irCount
*irSize
;i
+=irSize
)
814 for(j
= 0;j
< irSize
;j
++)
818 coeff
|= *(data
++)<<8;
827 for(i
= 0;i
< irCount
;i
++)
829 if(delays
[i
] > maxDelay
)
831 ERR("Invalid delays[%d]: %d (%d)\n", i
, delays
[i
], maxDelay
);
839 size_t total
= sizeof(struct Hrtf
);
840 total
+= sizeof(azCount
[0])*evCount
;
841 total
+= sizeof(evOffset
[0])*evCount
;
842 total
+= sizeof(coeffs
[0])*irSize
*irCount
;
843 total
+= sizeof(delays
[0])*irCount
;
844 total
+= al_string_length(filename
)+1;
846 Hrtf
= al_calloc(16, total
);
849 ERR("Out of memory.\n");
856 Hrtf
->sampleRate
= rate
;
857 Hrtf
->irSize
= irSize
;
858 Hrtf
->evCount
= evCount
;
859 Hrtf
->azCount
= ((ALubyte
*)(Hrtf
+1));
860 Hrtf
->evOffset
= ((ALushort
*)(Hrtf
->azCount
+ evCount
));
861 Hrtf
->coeffs
= ((ALshort
*)(Hrtf
->evOffset
+ evCount
));
862 Hrtf
->delays
= ((ALubyte
*)(Hrtf
->coeffs
+ irSize
*irCount
));
863 Hrtf
->filename
= ((char*)(Hrtf
->delays
+ irCount
));
866 memcpy((void*)Hrtf
->azCount
, azCount
, sizeof(azCount
[0])*evCount
);
867 memcpy((void*)Hrtf
->evOffset
, evOffset
, sizeof(evOffset
[0])*evCount
);
868 memcpy((void*)Hrtf
->coeffs
, coeffs
, sizeof(coeffs
[0])*irSize
*irCount
);
869 memcpy((void*)Hrtf
->delays
, delays
, sizeof(delays
[0])*irCount
);
870 memcpy((void*)Hrtf
->filename
, al_string_get_cstr(filename
), al_string_length(filename
)+1);
878 /* Another unfortunate duplication, this time of AddFileEntry to take a memory
879 * buffer for input instead of opening the given filename.
881 static void AddBuiltInEntry(vector_HrtfEntry
*list
, const ALubyte
*data
, size_t datalen
, al_string
*filename
)
883 HrtfEntry entry
= { AL_STRING_INIT_STATIC(), NULL
};
884 struct Hrtf
*hrtf
= NULL
;
885 const HrtfEntry
*iter
;
888 #define MATCH_FNAME(i) (al_string_cmp_cstr(*filename, (i)->hrtf->filename) == 0)
889 VECTOR_FIND_IF(iter
, const HrtfEntry
, *list
, MATCH_FNAME
);
890 if(iter
!= VECTOR_END(*list
))
892 TRACE("Skipping duplicate file entry %s\n", al_string_get_cstr(*filename
));
897 entry
.hrtf
= LoadedHrtfs
;
900 if(al_string_cmp_cstr(*filename
, entry
.hrtf
->filename
) == 0)
902 TRACE("Skipping load of already-loaded file %s\n", al_string_get_cstr(*filename
));
905 entry
.hrtf
= entry
.hrtf
->next
;
908 TRACE("Loading %s...\n", al_string_get_cstr(*filename
));
909 if(datalen
< sizeof(magicMarker01
))
911 ERR("%s data is too short ("SZFMT
" bytes)\n", al_string_get_cstr(*filename
), datalen
);
915 if(memcmp(data
, magicMarker01
, sizeof(magicMarker01
)) == 0)
917 TRACE("Detected data set format v1\n");
918 hrtf
= LoadBuiltInHrtf01(
919 data
+sizeof(magicMarker01
), datalen
-sizeof(magicMarker01
),
924 ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(*filename
), data
);
928 ERR("Failed to load %s\n", al_string_get_cstr(*filename
));
932 hrtf
->next
= LoadedHrtfs
;
934 TRACE("Loaded HRTF support for format: %s %uhz\n",
935 DevFmtChannelsString(DevFmtStereo
), hrtf
->sampleRate
);
941 al_string_copy(&entry
.name
, *filename
);
945 snprintf(str
, sizeof(str
), " #%d", i
+1);
946 al_string_append_cstr(&entry
.name
, str
);
950 #define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0)
951 VECTOR_FIND_IF(iter
, const HrtfEntry
, *list
, MATCH_NAME
);
953 } while(iter
!= VECTOR_END(*list
));
955 TRACE("Adding built-in entry \"%s\"\n", al_string_get_cstr(entry
.name
));
956 VECTOR_PUSH_BACK(*list
, entry
);
959 al_string_deinit(filename
);
963 #ifndef ALSOFT_EMBED_HRTF_DATA
964 #define IDR_DEFAULT_44100_MHR 0
965 #define IDR_DEFAULT_48000_MHR 1
967 static const ALubyte
*GetResource(int UNUSED(name
), size_t *size
)
974 #include "hrtf_res.h"
977 static const ALubyte
*GetResource(int name
, size_t *size
)
984 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
985 (LPCWSTR
)GetResource
, &handle
987 rc
= FindResourceW(handle
, MAKEINTRESOURCEW(name
), MAKEINTRESOURCEW(MHRTYPE
));
988 res
= LoadResource(handle
, rc
);
990 *size
= SizeofResource(handle
, rc
);
991 return LockResource(res
);
996 extern const ALubyte _binary_default_44100_mhr_start
[] HIDDEN_DECL
;
997 extern const ALubyte _binary_default_44100_mhr_end
[] HIDDEN_DECL
;
998 extern const ALubyte _binary_default_44100_mhr_size
[] HIDDEN_DECL
;
1000 extern const ALubyte _binary_default_48000_mhr_start
[] HIDDEN_DECL
;
1001 extern const ALubyte _binary_default_48000_mhr_end
[] HIDDEN_DECL
;
1002 extern const ALubyte _binary_default_48000_mhr_size
[] HIDDEN_DECL
;
1004 static const ALubyte
*GetResource(int name
, size_t *size
)
1006 if(name
== IDR_DEFAULT_44100_MHR
)
1008 /* Make sure all symbols are referenced, to ensure the compiler won't
1009 * ignore the declarations and lose the visibility attribute used to
1010 * hide them (would be nice if ld or objcopy could automatically mark
1011 * them as hidden when generating them, but apparently they can't).
1013 const void *volatile ptr
=_binary_default_44100_mhr_size
;
1015 *size
= _binary_default_44100_mhr_end
- _binary_default_44100_mhr_start
;
1016 return _binary_default_44100_mhr_start
;
1018 if(name
== IDR_DEFAULT_48000_MHR
)
1020 const void *volatile ptr
=_binary_default_48000_mhr_size
;
1022 *size
= _binary_default_48000_mhr_end
- _binary_default_48000_mhr_start
;
1023 return _binary_default_48000_mhr_start
;
1031 vector_HrtfEntry
EnumerateHrtf(const_al_string devname
)
1033 vector_HrtfEntry list
= VECTOR_INIT_STATIC();
1034 const char *defaulthrtf
= "";
1035 const char *pathlist
= "";
1036 bool usedefaults
= true;
1038 if(ConfigValueStr(al_string_get_cstr(devname
), NULL
, "hrtf-paths", &pathlist
))
1040 while(pathlist
&& *pathlist
)
1042 const char *next
, *end
;
1044 while(isspace(*pathlist
) || *pathlist
== ',')
1046 if(*pathlist
== '\0')
1049 next
= strchr(pathlist
, ',');
1054 end
= pathlist
+ strlen(pathlist
);
1055 usedefaults
= false;
1058 while(end
!= pathlist
&& isspace(*(end
-1)))
1062 al_string pname
= AL_STRING_INIT_STATIC();
1063 vector_al_string flist
;
1065 al_string_append_range(&pname
, pathlist
, end
);
1067 flist
= SearchDataFiles(".mhr", al_string_get_cstr(pname
));
1068 VECTOR_FOR_EACH_PARAMS(al_string
, flist
, AddFileEntry
, &list
);
1069 VECTOR_DEINIT(flist
);
1071 al_string_deinit(&pname
);
1077 else if(ConfigValueExists(al_string_get_cstr(devname
), NULL
, "hrtf_tables"))
1078 ERR("The hrtf_tables option is deprecated, please use hrtf-paths instead.\n");
1082 vector_al_string flist
;
1083 const ALubyte
*rdata
;
1086 flist
= SearchDataFiles(".mhr", "openal/hrtf");
1087 VECTOR_FOR_EACH_PARAMS(al_string
, flist
, AddFileEntry
, &list
);
1088 VECTOR_DEINIT(flist
);
1090 rdata
= GetResource(IDR_DEFAULT_44100_MHR
, &rsize
);
1091 if(rdata
!= NULL
&& rsize
> 0)
1093 al_string ename
= AL_STRING_INIT_STATIC();
1094 al_string_copy_cstr(&ename
, "Built-In 44100hz");
1095 AddBuiltInEntry(&list
, rdata
, rsize
, &ename
);
1098 rdata
= GetResource(IDR_DEFAULT_48000_MHR
, &rsize
);
1099 if(rdata
!= NULL
&& rsize
> 0)
1101 al_string ename
= AL_STRING_INIT_STATIC();
1102 al_string_copy_cstr(&ename
, "Built-In 48000hz");
1103 AddBuiltInEntry(&list
, rdata
, rsize
, &ename
);
1107 if(VECTOR_SIZE(list
) > 1 && ConfigValueStr(al_string_get_cstr(devname
), NULL
, "default-hrtf", &defaulthrtf
))
1109 const HrtfEntry
*iter
;
1110 /* Find the preferred HRTF and move it to the front of the list. */
1111 #define FIND_ENTRY(i) (al_string_cmp_cstr((i)->name, defaulthrtf) == 0)
1112 VECTOR_FIND_IF(iter
, const HrtfEntry
, list
, FIND_ENTRY
);
1113 if(iter
!= VECTOR_END(list
) && iter
!= VECTOR_BEGIN(list
))
1115 HrtfEntry entry
= *iter
;
1116 memmove(&VECTOR_ELEM(list
,1), &VECTOR_ELEM(list
,0),
1117 (iter
-VECTOR_BEGIN(list
))*sizeof(HrtfEntry
));
1118 VECTOR_ELEM(list
,0) = entry
;
1121 WARN("Failed to find default HRTF \"%s\"\n", defaulthrtf
);
1128 void FreeHrtfList(vector_HrtfEntry
*list
)
1130 #define CLEAR_ENTRY(i) do { \
1131 al_string_deinit(&(i)->name); \
1133 VECTOR_FOR_EACH(HrtfEntry
, *list
, CLEAR_ENTRY
);
1134 VECTOR_DEINIT(*list
);
1139 void FreeHrtfs(void)
1141 struct Hrtf
*Hrtf
= LoadedHrtfs
;
1146 struct Hrtf
*next
= Hrtf
->next
;