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
31 #include "bformatdec.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];
94 dirfact
= 1.0f
- (spread
/ F_TAU
);
96 /* Claculate elevation indices and interpolation factor. */
97 CalcEvIndices(Hrtf
->evCount
, elevation
, evidx
, &mu
[2]);
101 ALuint azcount
= Hrtf
->azCount
[evidx
[i
]];
102 ALuint evoffset
= Hrtf
->evOffset
[evidx
[i
]];
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.
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
);
167 for(i
= 0;i
< Hrtf
->irSize
;i
++)
176 ALuint
BuildBFormatHrtf(const struct Hrtf
*Hrtf
, ALfloat (*coeffs
)[HRIR_LENGTH
][2], ALuint NumChannels
)
178 static const struct {
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.
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;
213 assert(NumChannels
== 4);
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
);
247 /* Convert the left FIR from shorts to float */
248 fir
= &Hrtf
->coeffs
[lidx
[c
] * Hrtf
->irSize
];
251 for(i
= 0;i
< Hrtf
->irSize
;i
++)
252 temps
[0][i
] = fir
[i
] / 32767.0f
;
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
++)
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
];
280 for(i
= 0;i
< Hrtf
->irSize
;i
++)
281 temps
[0][i
] = fir
[i
] / 32767.0f
;
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
++)
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
);
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;
320 ALubyte
*azCount
= NULL
;
321 ALushort
*evOffset
= NULL
;
322 ALshort
*coeffs
= NULL
;
323 ALubyte
*delays
= NULL
;
328 rate
|= fgetc(f
)<<16;
329 rate
|= fgetc(f
)<<24;
332 irCount
|= fgetc(f
)<<8;
335 irSize
|= fgetc(f
)<<8;
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
);
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
);
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");
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]);
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
);
386 if(irCount
<= evOffset
[i
-1])
388 ERR("Invalid evOffset: evOffset[%d]=%d (irCount=%d)\n",
389 i
-1, evOffset
[i
-1], irCount
);
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
);
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");
415 for(i
= 0;i
< irCount
*irSize
;i
+=irSize
)
417 for(j
= 0;j
< irSize
;j
++)
421 coeff
|= fgetc(f
)<<8;
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
);
437 ERR("Premature end of data\n");
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
);
454 ERR("Out of memory.\n");
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
));
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);
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
;
500 rate
|= fgetc(f
)<<16;
501 rate
|= fgetc(f
)<<24;
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
);
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
);
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");
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
);
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");
566 for(i
= 0;i
< irCount
*irSize
;i
+=irSize
)
568 for(j
= 0;j
< irSize
;j
++)
572 coeff
|= fgetc(f
)<<8;
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
);
588 ERR("Premature end of data\n");
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
);
605 ERR("Out of memory.\n");
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
));
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);
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
;
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
);
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
));
661 entry
.hrtf
= LoadedHrtfs
;
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
));
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");
676 ERR("Could not open %s\n", al_string_get_cstr(*filename
));
680 if(fread(magic
, 1, sizeof(magic
), f
) != sizeof(magic
))
681 ERR("Failed to read header from %s\n", al_string_get_cstr(*filename
));
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
);
695 ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(*filename
), magic
);
701 ERR("Failed to load %s\n", al_string_get_cstr(*filename
));
705 hrtf
->next
= LoadedHrtfs
;
707 TRACE("Loaded HRTF support for format: %s %uhz\n",
708 DevFmtChannelsString(DevFmtStereo
), hrtf
->sampleRate
);
712 /* TODO: Get a human-readable name from the HRTF data (possibly coming in a
714 ext
= strrchr(name
, '.');
719 al_string_copy_cstr(&entry
.name
, name
);
721 al_string_copy_range(&entry
.name
, name
, ext
);
725 snprintf(str
, sizeof(str
), " #%d", i
+1);
726 al_string_append_cstr(&entry
.name
, str
);
730 #define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0)
731 VECTOR_FIND_IF(iter
, const HrtfEntry
, *list
, 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
);
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
;
764 ERR("Unexpected end of %s data (req %d, rem "SZFMT
"\n",
765 al_string_get_cstr(filename
), 6, datalen
);
770 rate
|= *(data
++)<<8;
771 rate
|= *(data
++)<<16;
772 rate
|= *(data
++)<<24;
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
);
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
);
796 if(datalen
< evCount
)
798 ERR("Unexpected end of %s data (req %d, rem "SZFMT
"\n",
799 al_string_get_cstr(filename
), evCount
, datalen
);
807 evOffset
= malloc(sizeof(evOffset
[0])*evCount
);
808 if(azCount
== NULL
|| evOffset
== NULL
)
810 ERR("Out of memory.\n");
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
);
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
);
840 ERR("Out of memory.\n");
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
);
858 for(i
= 0;i
< irCount
*irSize
;i
+=irSize
)
860 for(j
= 0;j
< irSize
;j
++)
864 coeff
|= *(data
++)<<8;
873 for(i
= 0;i
< irCount
;i
++)
875 if(delays
[i
] > maxDelay
)
877 ERR("Invalid delays[%d]: %d (%d)\n", i
, delays
[i
], maxDelay
);
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
);
895 ERR("Out of memory.\n");
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
));
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);
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
;
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
));
943 entry
.hrtf
= LoadedHrtfs
;
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
));
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
);
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
),
970 ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(*filename
), data
);
974 ERR("Failed to load %s\n", al_string_get_cstr(*filename
));
978 hrtf
->next
= LoadedHrtfs
;
980 TRACE("Loaded HRTF support for format: %s %uhz\n",
981 DevFmtChannelsString(DevFmtStereo
), hrtf
->sampleRate
);
987 al_string_copy(&entry
.name
, *filename
);
991 snprintf(str
, sizeof(str
), " #%d", i
+1);
992 al_string_append_cstr(&entry
.name
, str
);
996 #define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0)
997 VECTOR_FIND_IF(iter
, const HrtfEntry
, *list
, 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
);
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
)
1020 #include "hrtf_res.h"
1023 static const ALubyte
*GetResource(int name
, size_t *size
)
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
);
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
;
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
;
1068 *size
= _binary_default_48000_mhr_end
- _binary_default_48000_mhr_start
;
1069 return _binary_default_48000_mhr_start
;
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
== ',')
1092 if(*pathlist
== '\0')
1095 next
= strchr(pathlist
, ',');
1100 end
= pathlist
+ strlen(pathlist
);
1101 usedefaults
= false;
1104 while(end
!= pathlist
&& isspace(*(end
-1)))
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
);
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");
1128 vector_al_string flist
;
1129 const ALubyte
*rdata
;
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
;
1167 WARN("Failed to find default HRTF \"%s\"\n", defaulthrtf
);
1174 void FreeHrtfList(vector_HrtfEntry
*list
)
1176 #define CLEAR_ENTRY(i) do { \
1177 al_string_deinit(&(i)->name); \
1179 VECTOR_FOR_EACH(HrtfEntry
, *list
, CLEAR_ENTRY
);
1180 VECTOR_DEINIT(*list
);
1185 void FreeHrtfs(void)
1187 struct Hrtf
*Hrtf
= LoadedHrtfs
;
1192 struct Hrtf
*next
= Hrtf
->next
;