Avoid using ATOMIC macros
[openal-soft.git] / Alc / hrtf.cpp
blob034d5a49b3565293c6a45987db6300f7163f69ba
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 <mutex>
27 #include <array>
28 #include <vector>
29 #include <memory>
30 #include <istream>
31 #include <algorithm>
33 #include "AL/al.h"
34 #include "AL/alc.h"
35 #include "alMain.h"
36 #include "alSource.h"
37 #include "alu.h"
38 #include "hrtf.h"
39 #include "alconfig.h"
40 #include "filters/splitter.h"
42 #include "compat.h"
43 #include "almalloc.h"
46 struct HrtfEntry {
47 struct HrtfEntry *next;
48 struct Hrtf *handle;
49 char filename[];
52 namespace {
54 /* Current data set limits defined by the makehrtf utility. */
55 #define MIN_IR_SIZE (8)
56 #define MAX_IR_SIZE (512)
57 #define MOD_IR_SIZE (8)
59 #define MIN_FD_COUNT (1)
60 #define MAX_FD_COUNT (16)
62 #define MIN_FD_DISTANCE (50)
63 #define MAX_FD_DISTANCE (2500)
65 #define MIN_EV_COUNT (5)
66 #define MAX_EV_COUNT (128)
68 #define MIN_AZ_COUNT (1)
69 #define MAX_AZ_COUNT (128)
71 #define MAX_HRIR_DELAY (HRTF_HISTORY_LENGTH-1)
73 constexpr ALchar magicMarker00[8]{'M','i','n','P','H','R','0','0'};
74 constexpr ALchar magicMarker01[8]{'M','i','n','P','H','R','0','1'};
75 constexpr ALchar magicMarker02[8]{'M','i','n','P','H','R','0','2'};
77 /* First value for pass-through coefficients (remaining are 0), used for omni-
78 * directional sounds. */
79 constexpr ALfloat PassthruCoeff{0.707106781187f/*sqrt(0.5)*/};
81 std::mutex LoadedHrtfLock;
82 HrtfEntry *LoadedHrtfs{nullptr};
85 class databuf final : public std::streambuf {
86 int_type underflow() override
87 { return traits_type::eof(); }
89 pos_type seekoff(off_type offset, std::ios_base::seekdir whence, std::ios_base::openmode mode) override
91 if((mode&std::ios_base::out) || !(mode&std::ios_base::in))
92 return traits_type::eof();
94 char_type *cur;
95 switch(whence)
97 case std::ios_base::beg:
98 if(offset < 0 || offset > egptr()-eback())
99 return traits_type::eof();
100 cur = eback() + offset;
101 break;
103 case std::ios_base::cur:
104 if((offset >= 0 && offset > egptr()-gptr()) ||
105 (offset < 0 && -offset > gptr()-eback()))
106 return traits_type::eof();
107 cur = gptr() + offset;
108 break;
110 case std::ios_base::end:
111 if(offset > 0 || -offset > egptr()-eback())
112 return traits_type::eof();
113 cur = egptr() + offset;
114 break;
116 default:
117 return traits_type::eof();
120 setg(eback(), cur, egptr());
121 return cur - eback();
124 pos_type seekpos(pos_type pos, std::ios_base::openmode mode) override
126 // Simplified version of seekoff
127 if((mode&std::ios_base::out) || !(mode&std::ios_base::in))
128 return traits_type::eof();
130 if(pos < 0 || pos > egptr()-eback())
131 return traits_type::eof();
133 setg(eback(), eback() + pos, egptr());
134 return pos;
137 public:
138 databuf(const char_type *start, const char_type *end) noexcept
140 setg(const_cast<char_type*>(start), const_cast<char_type*>(start),
141 const_cast<char_type*>(end));
145 class idstream final : public std::istream {
146 databuf mStreamBuf;
148 public:
149 idstream(const char *start, const char *end)
150 : std::istream{nullptr}, mStreamBuf{start, end}
151 { init(&mStreamBuf); }
155 /* Calculate the elevation index given the polar elevation in radians. This
156 * will return an index between 0 and (evcount - 1).
158 ALsizei CalcEvIndex(ALsizei evcount, ALfloat ev, ALfloat *mu)
160 ev = (F_PI_2+ev) * (evcount-1) / F_PI;
161 ALsizei idx{float2int(ev)};
163 *mu = ev - idx;
164 return mini(idx, evcount-1);
167 /* Calculate the azimuth index given the polar azimuth in radians. This will
168 * return an index between 0 and (azcount - 1).
170 ALsizei CalcAzIndex(ALsizei azcount, ALfloat az, ALfloat *mu)
172 az = (F_TAU+az) * azcount / F_TAU;
173 ALsizei idx{float2int(az)};
175 *mu = az - idx;
176 return idx % azcount;
179 } // namespace
182 /* Calculates static HRIR coefficients and delays for the given polar elevation
183 * and azimuth in radians. The coefficients are normalized.
185 void GetHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat spread,
186 ALfloat (*RESTRICT coeffs)[2], ALsizei *delays)
188 ALfloat dirfact{1.0f - (spread / F_TAU)};
190 /* Claculate the lower elevation index. */
191 ALfloat emu;
192 ALsizei evidx{CalcEvIndex(Hrtf->evCount, elevation, &emu)};
193 ALsizei evoffset{Hrtf->evOffset[evidx]};
195 /* Calculate lower azimuth index. */
196 ALfloat amu[2];
197 ALsizei azidx{CalcAzIndex(Hrtf->azCount[evidx], azimuth, &amu[0])};
199 /* Calculate the lower HRIR indices. */
200 ALsizei idx[4]{
201 evoffset + azidx,
202 evoffset + ((azidx+1) % Hrtf->azCount[evidx])
204 if(evidx < Hrtf->evCount-1)
206 /* Increment elevation to the next (upper) index. */
207 evidx++;
208 evoffset = Hrtf->evOffset[evidx];
210 /* Calculate upper azimuth index. */
211 azidx = CalcAzIndex(Hrtf->azCount[evidx], azimuth, &amu[1]);
213 /* Calculate the upper HRIR indices. */
214 idx[2] = evoffset + azidx;
215 idx[3] = evoffset + ((azidx+1) % Hrtf->azCount[evidx]);
217 else
219 /* If the lower elevation is the top index, the upper elevation is the
220 * same as the lower.
222 amu[1] = amu[0];
223 idx[2] = idx[0];
224 idx[3] = idx[1];
227 /* Calculate bilinear blending weights, attenuated according to the
228 * directional panning factor.
230 ALfloat blend[4]{
231 (1.0f-emu) * (1.0f-amu[0]) * dirfact,
232 (1.0f-emu) * ( amu[0]) * dirfact,
233 ( emu) * (1.0f-amu[1]) * dirfact,
234 ( emu) * ( amu[1]) * dirfact
237 /* Calculate the blended HRIR delays. */
238 delays[0] = fastf2i(
239 Hrtf->delays[idx[0]][0]*blend[0] + Hrtf->delays[idx[1]][0]*blend[1] +
240 Hrtf->delays[idx[2]][0]*blend[2] + Hrtf->delays[idx[3]][0]*blend[3]
242 delays[1] = fastf2i(
243 Hrtf->delays[idx[0]][1]*blend[0] + Hrtf->delays[idx[1]][1]*blend[1] +
244 Hrtf->delays[idx[2]][1]*blend[2] + Hrtf->delays[idx[3]][1]*blend[3]
247 /* Calculate the sample offsets for the HRIR indices. */
248 idx[0] *= Hrtf->irSize;
249 idx[1] *= Hrtf->irSize;
250 idx[2] *= Hrtf->irSize;
251 idx[3] *= Hrtf->irSize;
253 ASSUME(Hrtf->irSize >= MIN_IR_SIZE && (Hrtf->irSize%MOD_IR_SIZE) == 0);
255 /* Calculate the blended HRIR coefficients. */
256 coeffs[0][0] = PassthruCoeff * (1.0f-dirfact);
257 coeffs[0][1] = PassthruCoeff * (1.0f-dirfact);
258 for(ALsizei i{1};i < Hrtf->irSize;i++)
260 coeffs[i][0] = 0.0f;
261 coeffs[i][1] = 0.0f;
263 for(ALsizei c{0};c < 4;c++)
265 const ALfloat (*RESTRICT srccoeffs)[2] = Hrtf->coeffs + idx[c];
266 for(ALsizei i{0};i < Hrtf->irSize;i++)
268 coeffs[i][0] += srccoeffs[i][0] * blend[c];
269 coeffs[i][1] += srccoeffs[i][1] * blend[c];
275 void BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, ALsizei NumChannels, const struct AngularPoint *AmbiPoints, const ALfloat (*RESTRICT AmbiMatrix)[MAX_AMBI_COEFFS], ALsizei AmbiCount, const ALfloat *RESTRICT AmbiOrderHFGain)
277 /* Set this to 2 for dual-band HRTF processing. May require a higher quality
278 * band-splitter, or better calculation of the new IR length to deal with the
279 * tail generated by the filter.
281 #define NUM_BANDS 2
282 ALsizei min_delay{HRTF_HISTORY_LENGTH};
283 ALsizei max_delay{0};
284 std::vector<ALsizei> idx(AmbiCount);
285 for(ALsizei c{0};c < AmbiCount;c++)
287 ALuint evidx, azidx;
288 ALuint evoffset;
289 ALuint azcount;
291 /* Calculate elevation index. */
292 evidx = (ALsizei)((F_PI_2+AmbiPoints[c].Elev) * (Hrtf->evCount-1) / F_PI + 0.5f);
293 evidx = clampi(evidx, 0, Hrtf->evCount-1);
295 azcount = Hrtf->azCount[evidx];
296 evoffset = Hrtf->evOffset[evidx];
298 /* Calculate azimuth index for this elevation. */
299 azidx = (ALsizei)((F_TAU+AmbiPoints[c].Azim) * azcount / F_TAU + 0.5f) % azcount;
301 /* Calculate indices for left and right channels. */
302 idx[c] = evoffset + azidx;
304 min_delay = mini(min_delay, mini(Hrtf->delays[idx[c]][0], Hrtf->delays[idx[c]][1]));
305 max_delay = maxi(max_delay, maxi(Hrtf->delays[idx[c]][0], Hrtf->delays[idx[c]][1]));
308 std::vector<std::array<std::array<ALdouble,2>,HRIR_LENGTH>> tmpres(NumChannels);
309 ALfloat temps[3][HRIR_LENGTH]{};
311 BandSplitter splitter;
312 bandsplit_init(&splitter, 400.0f / (ALfloat)Hrtf->sampleRate);
313 for(ALsizei c{0};c < AmbiCount;++c)
315 const ALfloat (*fir)[2] = &Hrtf->coeffs[idx[c] * Hrtf->irSize];
316 ALsizei ldelay = Hrtf->delays[idx[c]][0] - min_delay;
317 ALsizei rdelay = Hrtf->delays[idx[c]][1] - min_delay;
319 if(NUM_BANDS == 1)
321 for(ALsizei i{0};i < NumChannels;++i)
323 ALdouble mult = (ALdouble)AmbiOrderHFGain[(ALsizei)sqrt(i)] * AmbiMatrix[c][i];
324 ALsizei lidx = ldelay, ridx = rdelay;
325 ALsizei j = 0;
326 while(lidx < HRIR_LENGTH && ridx < HRIR_LENGTH && j < Hrtf->irSize)
328 tmpres[i][lidx++][0] += fir[j][0] * mult;
329 tmpres[i][ridx++][1] += fir[j][1] * mult;
330 j++;
334 else
336 /* Band-split left HRIR into low and high frequency responses. */
337 bandsplit_clear(&splitter);
338 for(ALsizei i{0};i < Hrtf->irSize;++i)
339 temps[2][i] = fir[i][0];
340 bandsplit_process(&splitter, temps[0], temps[1], temps[2], HRIR_LENGTH);
342 /* Apply left ear response with delay. */
343 for(ALsizei i{0};i < NumChannels;++i)
345 ALdouble hfgain = AmbiOrderHFGain[(ALsizei)sqrt(i)];
346 for(ALsizei b{0};b < NUM_BANDS;++b)
348 ALdouble mult = AmbiMatrix[c][i] * ((b==0) ? hfgain : 1.0);
349 ALsizei lidx = ldelay;
350 ALsizei j = 0;
351 while(lidx < HRIR_LENGTH)
352 tmpres[i][lidx++][0] += temps[b][j++] * mult;
356 /* Band-split right HRIR into low and high frequency responses. */
357 bandsplit_clear(&splitter);
358 for(ALsizei i{0};i < Hrtf->irSize;++i)
359 temps[2][i] = fir[i][1];
360 bandsplit_process(&splitter, temps[0], temps[1], temps[2], HRIR_LENGTH);
362 /* Apply right ear response with delay. */
363 for(ALsizei i{0};i < NumChannels;++i)
365 ALdouble hfgain = AmbiOrderHFGain[(ALsizei)sqrt(i)];
366 for(ALsizei b{0};b < NUM_BANDS;++b)
368 ALdouble mult = AmbiMatrix[c][i] * ((b==0) ? hfgain : 1.0);
369 ALsizei ridx = rdelay;
370 ALsizei j = 0;
371 while(ridx < HRIR_LENGTH)
372 tmpres[i][ridx++][1] += temps[b][j++] * mult;
378 for(ALsizei i{0};i < NumChannels;++i)
380 for(ALsizei idx{0};idx < HRIR_LENGTH;idx++)
382 state->Chan[i].Coeffs[idx][0] = (ALfloat)tmpres[i][idx][0];
383 state->Chan[i].Coeffs[idx][1] = (ALfloat)tmpres[i][idx][1];
386 tmpres.clear();
387 idx.clear();
389 ALsizei max_length;
390 if(NUM_BANDS == 1)
391 max_length = mini(max_delay-min_delay + Hrtf->irSize, HRIR_LENGTH);
392 else
394 /* Increase the IR size by 2/3rds to account for the tail generated by
395 * the band-split filter.
397 const ALsizei irsize = mini(Hrtf->irSize*5/3, HRIR_LENGTH);
398 max_length = mini(max_delay-min_delay + irsize, HRIR_LENGTH);
400 /* Round up to the next IR size multiple. */
401 max_length += MOD_IR_SIZE-1;
402 max_length -= max_length%MOD_IR_SIZE;
404 TRACE("Skipped delay: %d, max delay: %d, new FIR length: %d\n",
405 min_delay, max_delay-min_delay, max_length);
406 state->IrSize = max_length;
407 #undef NUM_BANDS
411 namespace {
413 struct Hrtf *CreateHrtfStore(ALuint rate, ALsizei irSize, ALfloat distance, ALsizei evCount,
414 ALsizei irCount, const ALubyte *azCount, const ALushort *evOffset, const ALfloat (*coeffs)[2],
415 const ALubyte (*delays)[2], const char *filename)
417 struct Hrtf *Hrtf;
418 size_t total;
420 total = sizeof(struct Hrtf);
421 total += sizeof(Hrtf->azCount[0])*evCount;
422 total = RoundUp(total, sizeof(ALushort)); /* Align for ushort fields */
423 total += sizeof(Hrtf->evOffset[0])*evCount;
424 total = RoundUp(total, 16); /* Align for coefficients using SIMD */
425 total += sizeof(Hrtf->coeffs[0])*irSize*irCount;
426 total += sizeof(Hrtf->delays[0])*irCount;
428 Hrtf = static_cast<struct Hrtf*>(al_calloc(16, total));
429 if(Hrtf == nullptr)
430 ERR("Out of memory allocating storage for %s.\n", filename);
431 else
433 uintptr_t offset = sizeof(struct Hrtf);
434 char *base = (char*)Hrtf;
435 ALushort *_evOffset;
436 ALubyte *_azCount;
437 ALubyte (*_delays)[2];
438 ALfloat (*_coeffs)[2];
439 ALsizei i;
441 InitRef(&Hrtf->ref, 0);
442 Hrtf->sampleRate = rate;
443 Hrtf->irSize = irSize;
444 Hrtf->distance = distance;
445 Hrtf->evCount = evCount;
447 /* Set up pointers to storage following the main HRTF struct. */
448 _azCount = reinterpret_cast<ALubyte*>(base + offset);
449 offset += sizeof(_azCount[0])*evCount;
451 offset = RoundUp(offset, sizeof(ALushort)); /* Align for ushort fields */
452 _evOffset = reinterpret_cast<ALushort*>(base + offset);
453 offset += sizeof(_evOffset[0])*evCount;
455 offset = RoundUp(offset, 16); /* Align for coefficients using SIMD */
456 _coeffs = reinterpret_cast<ALfloat(*)[2]>(base + offset);
457 offset += sizeof(_coeffs[0])*irSize*irCount;
459 _delays = reinterpret_cast<ALubyte(*)[2]>(base + offset);
460 offset += sizeof(_delays[0])*irCount;
462 assert(offset == total);
464 /* Copy input data to storage. */
465 for(i = 0;i < evCount;i++) _azCount[i] = azCount[i];
466 for(i = 0;i < evCount;i++) _evOffset[i] = evOffset[i];
467 for(i = 0;i < irSize*irCount;i++)
469 _coeffs[i][0] = coeffs[i][0];
470 _coeffs[i][1] = coeffs[i][1];
472 for(i = 0;i < irCount;i++)
474 _delays[i][0] = delays[i][0];
475 _delays[i][1] = delays[i][1];
478 /* Finally, assign the storage pointers. */
479 Hrtf->azCount = _azCount;
480 Hrtf->evOffset = _evOffset;
481 Hrtf->coeffs = _coeffs;
482 Hrtf->delays = _delays;
485 return Hrtf;
488 ALubyte GetLE_ALubyte(std::istream &data)
490 return static_cast<ALubyte>(data.get());
493 ALshort GetLE_ALshort(std::istream &data)
495 int ret = data.get();
496 ret |= data.get() << 8;
497 return static_cast<ALshort>((ret^32768) - 32768);
500 ALushort GetLE_ALushort(std::istream &data)
502 int ret = data.get();
503 ret |= data.get() << 8;
504 return static_cast<ALushort>(ret);
507 ALint GetLE_ALint24(std::istream &data)
509 int ret = data.get();
510 ret |= data.get() << 8;
511 ret |= data.get() << 16;
512 return (ret^8388608) - 8388608;
515 ALuint GetLE_ALuint(std::istream &data)
517 int ret = data.get();
518 ret |= data.get() << 8;
519 ret |= data.get() << 16;
520 ret |= data.get() << 24;
521 return ret;
524 struct Hrtf *LoadHrtf00(std::istream &data, const char *filename)
526 ALuint rate{GetLE_ALuint(data)};
527 ALushort irCount{GetLE_ALushort(data)};
528 ALushort irSize{GetLE_ALushort(data)};
529 ALubyte evCount{GetLE_ALubyte(data)};
530 if(!data || data.eof())
532 ERR("Failed reading %s\n", filename);
533 return nullptr;
536 ALboolean failed{AL_FALSE};
537 if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
539 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
540 irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE);
541 failed = AL_TRUE;
543 if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT)
545 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
546 evCount, MIN_EV_COUNT, MAX_EV_COUNT);
547 failed = AL_TRUE;
549 if(failed)
550 return nullptr;
552 std::vector<ALushort> evOffset(evCount);
553 for(auto &val : evOffset)
554 val = GetLE_ALushort(data);
555 if(!data || data.eof())
557 ERR("Failed reading %s\n", filename);
558 return nullptr;
560 for(ALsizei i{1};i < evCount;i++)
562 if(evOffset[i] <= evOffset[i-1])
564 ERR("Invalid evOffset: evOffset[%d]=%d (last=%d)\n",
565 i, evOffset[i], evOffset[i-1]);
566 failed = AL_TRUE;
569 if(irCount <= evOffset.back())
571 ERR("Invalid evOffset: evOffset[" SZFMT "]=%d (irCount=%d)\n",
572 evOffset.size()-1, evOffset.back(), irCount);
573 failed = AL_TRUE;
575 if(failed)
576 return nullptr;
578 std::vector<ALubyte> azCount(evCount);
579 for(ALsizei i{1};i < evCount;i++)
581 azCount[i-1] = evOffset[i] - evOffset[i-1];
582 if(azCount[i-1] < MIN_AZ_COUNT || azCount[i-1] > MAX_AZ_COUNT)
584 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
585 i-1, azCount[i-1], MIN_AZ_COUNT, MAX_AZ_COUNT);
586 failed = AL_TRUE;
589 azCount.back() = irCount - evOffset.back();
590 if(azCount.back() < MIN_AZ_COUNT || azCount.back() > MAX_AZ_COUNT)
592 ERR("Unsupported azimuth count: azCount[" SZFMT "]=%d (%d to %d)\n",
593 azCount.size()-1, azCount.back(), MIN_AZ_COUNT, MAX_AZ_COUNT);
594 failed = AL_TRUE;
596 if(failed)
597 return nullptr;
599 std::vector<std::array<ALfloat,2>> coeffs(irSize*irCount);
600 std::vector<std::array<ALubyte,2>> delays(irCount);
601 for(auto &val : coeffs)
602 val[0] = GetLE_ALshort(data) / 32768.0f;
603 for(auto &val : delays)
604 val[0] = GetLE_ALubyte(data);
605 if(!data || data.eof())
607 ERR("Failed reading %s\n", filename);
608 return nullptr;
610 for(ALsizei i{0};i < irCount;i++)
612 if(delays[i][0] > MAX_HRIR_DELAY)
614 ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i][0], MAX_HRIR_DELAY);
615 failed = AL_TRUE;
618 if(failed)
619 return nullptr;
621 /* Mirror the left ear responses to the right ear. */
622 for(ALsizei i{0};i < evCount;i++)
624 ALushort evoffset = evOffset[i];
625 ALubyte azcount = azCount[i];
626 for(ALsizei j{0};j < azcount;j++)
628 ALsizei lidx = evoffset + j;
629 ALsizei ridx = evoffset + ((azcount-j) % azcount);
631 for(ALsizei k{0};k < irSize;k++)
632 coeffs[ridx*irSize + k][1] = coeffs[lidx*irSize + k][0];
633 delays[ridx][1] = delays[lidx][0];
637 return CreateHrtfStore(rate, irSize, 0.0f, evCount, irCount, azCount.data(),
638 evOffset.data(), &reinterpret_cast<ALfloat(&)[2]>(coeffs[0]),
639 &reinterpret_cast<ALubyte(&)[2]>(delays[0]), filename);
642 struct Hrtf *LoadHrtf01(std::istream &data, const char *filename)
644 ALuint rate{GetLE_ALuint(data)};
645 ALushort irSize{GetLE_ALubyte(data)};
646 ALubyte evCount{GetLE_ALubyte(data)};
647 if(!data || data.eof())
649 ERR("Failed reading %s\n", filename);
650 return nullptr;
653 ALboolean failed{AL_FALSE};
654 if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
656 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
657 irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE);
658 failed = AL_TRUE;
660 if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT)
662 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
663 evCount, MIN_EV_COUNT, MAX_EV_COUNT);
664 failed = AL_TRUE;
666 if(failed)
667 return nullptr;
669 std::vector<ALubyte> azCount(evCount);
670 data.read(reinterpret_cast<char*>(azCount.data()), evCount);
671 if(!data || data.eof() || data.gcount() < evCount)
673 ERR("Failed reading %s\n", filename);
674 return nullptr;
676 for(ALsizei i{0};i < evCount;++i)
678 if(azCount[i] < MIN_AZ_COUNT || azCount[i] > MAX_AZ_COUNT)
680 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
681 i, azCount[i], MIN_AZ_COUNT, MAX_AZ_COUNT);
682 failed = AL_TRUE;
685 if(failed)
686 return nullptr;
688 std::vector<ALushort> evOffset(evCount);
689 evOffset[0] = 0;
690 ALushort irCount{azCount[0]};
691 for(ALsizei i{1};i < evCount;i++)
693 evOffset[i] = evOffset[i-1] + azCount[i-1];
694 irCount += azCount[i];
697 std::vector<std::array<ALfloat,2>> coeffs(irSize*irCount);
698 std::vector<std::array<ALubyte,2>> delays(irCount);
699 for(auto &val : coeffs)
700 val[0] = GetLE_ALshort(data) / 32768.0f;
701 for(auto &val : delays)
702 val[0] = GetLE_ALubyte(data);
703 if(!data || data.eof())
705 ERR("Failed reading %s\n", filename);
706 return nullptr;
708 for(ALsizei i{0};i < irCount;i++)
710 if(delays[i][0] > MAX_HRIR_DELAY)
712 ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i][0], MAX_HRIR_DELAY);
713 failed = AL_TRUE;
716 if(failed)
717 return nullptr;
719 /* Mirror the left ear responses to the right ear. */
720 for(ALsizei i{0};i < evCount;i++)
722 ALushort evoffset = evOffset[i];
723 ALubyte azcount = azCount[i];
724 for(ALsizei j{0};j < azcount;j++)
726 ALsizei lidx = evoffset + j;
727 ALsizei ridx = evoffset + ((azcount-j) % azcount);
729 for(ALsizei k{0};k < irSize;k++)
730 coeffs[ridx*irSize + k][1] = coeffs[lidx*irSize + k][0];
731 delays[ridx][1] = delays[lidx][0];
735 return CreateHrtfStore(rate, irSize, 0.0f, evCount, irCount, azCount.data(),
736 evOffset.data(), &reinterpret_cast<ALfloat(&)[2]>(coeffs[0]),
737 &reinterpret_cast<ALubyte(&)[2]>(delays[0]), filename);
740 #define SAMPLETYPE_S16 0
741 #define SAMPLETYPE_S24 1
743 #define CHANTYPE_LEFTONLY 0
744 #define CHANTYPE_LEFTRIGHT 1
746 struct Hrtf *LoadHrtf02(std::istream &data, const char *filename)
748 ALuint rate{GetLE_ALuint(data)};
749 ALubyte sampleType{GetLE_ALubyte(data)};
750 ALubyte channelType{GetLE_ALubyte(data)};
751 ALushort irSize{GetLE_ALubyte(data)};
752 ALubyte fdCount{GetLE_ALubyte(data)};
753 if(!data || data.eof())
755 ERR("Failed reading %s\n", filename);
756 return nullptr;
759 ALboolean failed{AL_FALSE};
760 if(sampleType > SAMPLETYPE_S24)
762 ERR("Unsupported sample type: %d\n", sampleType);
763 failed = AL_TRUE;
765 if(channelType > CHANTYPE_LEFTRIGHT)
767 ERR("Unsupported channel type: %d\n", channelType);
768 failed = AL_TRUE;
771 if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
773 ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
774 irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE);
775 failed = AL_TRUE;
777 if(fdCount != 1)
779 ERR("Multiple field-depths not supported: fdCount=%d (%d to %d)\n",
780 fdCount, MIN_FD_COUNT, MAX_FD_COUNT);
781 failed = AL_TRUE;
783 if(failed)
784 return nullptr;
786 ALushort distance{};
787 ALubyte evCount{};
788 std::vector<ALubyte> azCount;
789 for(ALsizei i{0};i < fdCount;i++)
791 distance = GetLE_ALushort(data);
792 evCount = GetLE_ALubyte(data);
793 if(!data || data.eof())
795 ERR("Failed reading %s\n", filename);
796 return nullptr;
799 if(distance < MIN_FD_DISTANCE || distance > MAX_FD_DISTANCE)
801 ERR("Unsupported field distance: distance=%d (%dmm to %dmm)\n",
802 distance, MIN_FD_DISTANCE, MAX_FD_DISTANCE);
803 failed = AL_TRUE;
805 if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT)
807 ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
808 evCount, MIN_EV_COUNT, MAX_EV_COUNT);
809 failed = AL_TRUE;
811 if(failed)
812 return nullptr;
814 azCount.resize(evCount);
815 data.read(reinterpret_cast<char*>(azCount.data()), evCount);
816 if(!data || data.eof() || data.gcount() < evCount)
818 ERR("Failed reading %s\n", filename);
819 return nullptr;
822 for(ALsizei j{0};j < evCount;j++)
824 if(azCount[j] < MIN_AZ_COUNT || azCount[j] > MAX_AZ_COUNT)
826 ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
827 j, azCount[j], MIN_AZ_COUNT, MAX_AZ_COUNT);
828 failed = AL_TRUE;
831 if(failed)
832 return nullptr;
835 std::vector<ALushort> evOffset(evCount);
836 evOffset[0] = 0;
837 ALushort irCount{azCount[0]};
838 for(ALsizei i{1};i < evCount;++i)
840 evOffset[i] = evOffset[i-1] + azCount[i-1];
841 irCount += azCount[i];
844 std::vector<std::array<ALfloat,2>> coeffs(irSize*irCount);
845 std::vector<std::array<ALubyte,2>> delays(irCount);
846 if(channelType == CHANTYPE_LEFTONLY)
848 if(sampleType == SAMPLETYPE_S16)
850 for(auto &val : coeffs)
851 val[0] = GetLE_ALshort(data) / 32768.0f;
853 else if(sampleType == SAMPLETYPE_S24)
855 for(auto &val : coeffs)
856 val[0] = GetLE_ALint24(data) / 8388608.0f;
858 for(auto &val : delays)
859 val[0] = GetLE_ALubyte(data);
860 if(!data || data.eof())
862 ERR("Failed reading %s\n", filename);
863 return nullptr;
865 for(ALsizei i{0};i < irCount;++i)
867 if(delays[i][0] > MAX_HRIR_DELAY)
869 ERR("Invalid delays[%d][0]: %d (%d)\n", i, delays[i][0], MAX_HRIR_DELAY);
870 failed = AL_TRUE;
874 else if(channelType == CHANTYPE_LEFTRIGHT)
876 if(sampleType == SAMPLETYPE_S16)
878 for(auto &val : coeffs)
880 val[0] = GetLE_ALshort(data) / 32768.0f;
881 val[1] = GetLE_ALshort(data) / 32768.0f;
884 else if(sampleType == SAMPLETYPE_S24)
886 for(auto &val : coeffs)
888 val[0] = GetLE_ALint24(data) / 8388608.0f;
889 val[1] = GetLE_ALint24(data) / 8388608.0f;
892 for(auto &val : delays)
894 val[0] = GetLE_ALubyte(data);
895 val[1] = GetLE_ALubyte(data);
897 if(!data || data.eof())
899 ERR("Failed reading %s\n", filename);
900 return nullptr;
903 for(ALsizei i{0};i < irCount;++i)
905 if(delays[i][0] > MAX_HRIR_DELAY)
907 ERR("Invalid delays[%d][0]: %d (%d)\n", i, delays[i][0], MAX_HRIR_DELAY);
908 failed = AL_TRUE;
910 if(delays[i][1] > MAX_HRIR_DELAY)
912 ERR("Invalid delays[%d][1]: %d (%d)\n", i, delays[i][1], MAX_HRIR_DELAY);
913 failed = AL_TRUE;
917 if(failed)
918 return nullptr;
920 if(channelType == CHANTYPE_LEFTONLY)
922 /* Mirror the left ear responses to the right ear. */
923 for(ALsizei i{0};i < evCount;i++)
925 ALushort evoffset = evOffset[i];
926 ALubyte azcount = azCount[i];
927 for(ALsizei j{0};j < azcount;j++)
929 ALsizei lidx = evoffset + j;
930 ALsizei ridx = evoffset + ((azcount-j) % azcount);
932 for(ALsizei k{0};k < irSize;k++)
933 coeffs[ridx*irSize + k][1] = coeffs[lidx*irSize + k][0];
934 delays[ridx][1] = delays[lidx][0];
939 return CreateHrtfStore(rate, irSize,
940 (ALfloat)distance / 1000.0f, evCount, irCount, azCount.data(), evOffset.data(),
941 &reinterpret_cast<ALfloat(&)[2]>(coeffs[0]),
942 &reinterpret_cast<ALubyte(&)[2]>(delays[0]), filename
947 bool checkName(al::vector<EnumeratedHrtf> &list, const std::string &name)
949 return std::find_if(list.cbegin(), list.cend(),
950 [&name](const EnumeratedHrtf &entry)
951 { return name == entry.name; }
952 ) != list.cend();
955 void AddFileEntry(al::vector<EnumeratedHrtf> &list, const std::string &filename)
957 /* Check if this file has already been loaded globally. */
958 HrtfEntry *loaded_entry{LoadedHrtfs};
959 while(loaded_entry)
961 if(filename == loaded_entry->filename)
963 /* Check if this entry has already been added to the list. */
964 auto iter = std::find_if(list.cbegin(), list.cend(),
965 [loaded_entry](const EnumeratedHrtf &entry) -> bool
966 { return loaded_entry == entry.hrtf; }
968 if(iter != list.cend())
970 TRACE("Skipping duplicate file entry %s\n", filename.c_str());
971 return;
974 break;
976 loaded_entry = loaded_entry->next;
979 if(!loaded_entry)
981 TRACE("Got new file \"%s\"\n", filename.c_str());
983 loaded_entry = static_cast<HrtfEntry*>(al_calloc(DEF_ALIGN,
984 FAM_SIZE(struct HrtfEntry, filename, filename.length()+1)
986 loaded_entry->next = LoadedHrtfs;
987 loaded_entry->handle = nullptr;
988 strcpy(loaded_entry->filename, filename.c_str());
989 LoadedHrtfs = loaded_entry;
992 /* TODO: Get a human-readable name from the HRTF data (possibly coming in a
993 * format update). */
994 size_t namepos = filename.find_last_of('/')+1;
995 if(!namepos) namepos = filename.find_last_of('\\')+1;
997 size_t extpos{filename.find_last_of('.')};
998 if(extpos <= namepos) extpos = std::string::npos;
1000 const std::string basename{(extpos == std::string::npos) ?
1001 filename.substr(namepos) : filename.substr(namepos, extpos-namepos)};
1002 std::string newname{basename};
1003 int count{1};
1004 while(checkName(list, newname))
1006 newname = basename;
1007 newname += " #";
1008 newname += std::to_string(++count);
1010 list.emplace_back(EnumeratedHrtf{newname, loaded_entry});
1011 const EnumeratedHrtf &entry = list.back();
1013 TRACE("Adding file entry \"%s\"\n", entry.name.c_str());
1016 /* Unfortunate that we have to duplicate AddFileEntry to take a memory buffer
1017 * for input instead of opening the given filename.
1019 void AddBuiltInEntry(al::vector<EnumeratedHrtf> &list, const std::string &filename, ALuint residx)
1021 HrtfEntry *loaded_entry{LoadedHrtfs};
1022 while(loaded_entry)
1024 if(filename == loaded_entry->filename)
1026 /* Check if this entry has already been added to the list. */
1027 auto iter = std::find_if(list.cbegin(), list.cend(),
1028 [loaded_entry](const EnumeratedHrtf &entry) -> bool
1029 { return loaded_entry == entry.hrtf; }
1031 if(iter != list.cend())
1033 TRACE("Skipping duplicate file entry %s\n", filename.c_str());
1034 return;
1037 break;
1039 loaded_entry = loaded_entry->next;
1042 if(!loaded_entry)
1044 size_t namelen = filename.length()+32;
1046 TRACE("Got new file \"%s\"\n", filename.c_str());
1048 loaded_entry = static_cast<HrtfEntry*>(al_calloc(DEF_ALIGN,
1049 FAM_SIZE(struct HrtfEntry, filename, namelen)
1051 loaded_entry->next = LoadedHrtfs;
1052 loaded_entry->handle = nullptr;
1053 snprintf(loaded_entry->filename, namelen, "!%u_%s",
1054 residx, filename.c_str());
1055 LoadedHrtfs = loaded_entry;
1058 /* TODO: Get a human-readable name from the HRTF data (possibly coming in a
1059 * format update). */
1061 std::string newname{filename};
1062 int count{1};
1063 while(checkName(list, newname))
1065 newname = filename;
1066 newname += " #";
1067 newname += std::to_string(++count);
1069 list.emplace_back(EnumeratedHrtf{newname, loaded_entry});
1070 const EnumeratedHrtf &entry = list.back();
1072 TRACE("Adding built-in entry \"%s\"\n", entry.name.c_str());
1076 #define IDR_DEFAULT_44100_MHR 1
1077 #define IDR_DEFAULT_48000_MHR 2
1079 struct ResData { const char *data; size_t size; };
1080 #ifndef ALSOFT_EMBED_HRTF_DATA
1082 ResData GetResource(int UNUSED(name))
1083 { return {nullptr, 0u}; }
1085 #else
1087 #include "default-44100.mhr.h"
1088 #include "default-48000.mhr.h"
1090 ResData GetResource(int name)
1092 if(name == IDR_DEFAULT_44100_MHR)
1093 return {reinterpret_cast<const char*>(hrtf_default_44100), sizeof(hrtf_default_44100)};
1094 if(name == IDR_DEFAULT_48000_MHR)
1095 return {reinterpret_cast<const char*>(hrtf_default_48000), sizeof(hrtf_default_48000)};
1096 return {nullptr, 0u};
1098 #endif
1100 } // namespace
1103 al::vector<EnumeratedHrtf> EnumerateHrtf(const char *devname)
1105 al::vector<EnumeratedHrtf> list;
1107 bool usedefaults{true};
1108 const char *pathlist{""};
1109 if(ConfigValueStr(devname, nullptr, "hrtf-paths", &pathlist))
1111 while(pathlist && *pathlist)
1113 const char *next, *end;
1115 while(isspace(*pathlist) || *pathlist == ',')
1116 pathlist++;
1117 if(*pathlist == '\0')
1118 continue;
1120 next = strchr(pathlist, ',');
1121 if(next)
1122 end = next++;
1123 else
1125 end = pathlist + strlen(pathlist);
1126 usedefaults = false;
1129 while(end != pathlist && isspace(*(end-1)))
1130 --end;
1131 if(end != pathlist)
1133 const std::string pname{pathlist, end};
1134 for(const auto &fname : SearchDataFiles(".mhr", pname.c_str()))
1135 AddFileEntry(list, fname);
1138 pathlist = next;
1141 else if(ConfigValueExists(devname, nullptr, "hrtf_tables"))
1142 ERR("The hrtf_tables option is deprecated, please use hrtf-paths instead.\n");
1144 if(usedefaults)
1146 for(const auto &fname : SearchDataFiles(".mhr", "openal/hrtf"))
1147 AddFileEntry(list, fname);
1149 ResData res{GetResource(IDR_DEFAULT_44100_MHR)};
1150 if(res.data != nullptr && res.size > 0)
1151 AddBuiltInEntry(list, "Built-In 44100hz", IDR_DEFAULT_44100_MHR);
1153 res = GetResource(IDR_DEFAULT_48000_MHR);
1154 if(res.data != nullptr && res.size > 0)
1155 AddBuiltInEntry(list, "Built-In 48000hz", IDR_DEFAULT_48000_MHR);
1158 const char *defaulthrtf{""};
1159 if(!list.empty() && ConfigValueStr(devname, nullptr, "default-hrtf", &defaulthrtf))
1161 auto iter = std::find_if(list.begin(), list.end(),
1162 [defaulthrtf](const EnumeratedHrtf &entry) -> bool
1163 { return entry.name == defaulthrtf; }
1165 if(iter == list.end())
1166 WARN("Failed to find default HRTF \"%s\"\n", defaulthrtf);
1167 else if(iter != list.begin())
1169 EnumeratedHrtf entry{*iter};
1170 list.erase(iter);
1171 list.insert(list.begin(), entry);
1175 return list;
1178 struct Hrtf *GetLoadedHrtf(struct HrtfEntry *entry)
1180 std::lock_guard<std::mutex> _{LoadedHrtfLock};
1182 if(entry->handle)
1184 Hrtf *hrtf{entry->handle};
1185 Hrtf_IncRef(hrtf);
1186 return hrtf;
1189 std::unique_ptr<std::istream> stream;
1190 const char *name{""};
1191 ALuint residx{};
1192 char ch{};
1193 if(sscanf(entry->filename, "!%u%c", &residx, &ch) == 2 && ch == '_')
1195 name = strchr(entry->filename, ch)+1;
1197 TRACE("Loading %s...\n", name);
1198 ResData res{GetResource(residx)};
1199 if(!res.data || res.size == 0)
1201 ERR("Could not get resource %u, %s\n", residx, name);
1202 return nullptr;
1204 stream.reset(new idstream{res.data, res.data+res.size});
1206 else
1208 name = entry->filename;
1210 TRACE("Loading %s...\n", entry->filename);
1211 std::unique_ptr<al::ifstream> fstr{new al::ifstream{entry->filename, std::ios::binary}};
1212 if(!fstr->is_open())
1214 ERR("Could not open %s\n", entry->filename);
1215 return nullptr;
1217 stream = std::move(fstr);
1220 Hrtf *hrtf{};
1221 char magic[sizeof(magicMarker02)];
1222 stream->read(magic, sizeof(magic));
1223 if(stream->gcount() < static_cast<std::streamsize>(sizeof(magicMarker02)))
1224 ERR("%s data is too short (" SZFMT " bytes)\n", name, stream->gcount());
1225 else if(memcmp(magic, magicMarker02, sizeof(magicMarker02)) == 0)
1227 TRACE("Detected data set format v2\n");
1228 hrtf = LoadHrtf02(*stream, name);
1230 else if(memcmp(magic, magicMarker01, sizeof(magicMarker01)) == 0)
1232 TRACE("Detected data set format v1\n");
1233 hrtf = LoadHrtf01(*stream, name);
1235 else if(memcmp(magic, magicMarker00, sizeof(magicMarker00)) == 0)
1237 TRACE("Detected data set format v0\n");
1238 hrtf = LoadHrtf00(*stream, name);
1240 else
1241 ERR("Invalid header in %s: \"%.8s\"\n", name, magic);
1242 stream.reset();
1244 if(!hrtf)
1245 ERR("Failed to load %s\n", name);
1246 else
1248 entry->handle = hrtf;
1249 Hrtf_IncRef(hrtf);
1250 TRACE("Loaded HRTF support for format: %s %uhz\n",
1251 DevFmtChannelsString(DevFmtStereo), hrtf->sampleRate);
1254 return hrtf;
1258 void Hrtf_IncRef(struct Hrtf *hrtf)
1260 auto ref = IncrementRef(&hrtf->ref);
1261 TRACEREF("%p increasing refcount to %u\n", hrtf, ref);
1264 void Hrtf_DecRef(struct Hrtf *hrtf)
1266 auto ref = DecrementRef(&hrtf->ref);
1267 TRACEREF("%p decreasing refcount to %u\n", hrtf, ref);
1268 if(ref == 0)
1270 std::lock_guard<std::mutex> _{LoadedHrtfLock};
1272 struct HrtfEntry *Hrtf{LoadedHrtfs};
1273 while(Hrtf != nullptr)
1275 /* Need to double-check that it's still unused, as another device
1276 * could've reacquired this HRTF after its reference went to 0 and
1277 * before the lock was taken.
1279 if(hrtf == Hrtf->handle && ReadRef(&hrtf->ref) == 0)
1281 al_free(Hrtf->handle);
1282 Hrtf->handle = nullptr;
1283 TRACE("Unloaded unused HRTF %s\n", Hrtf->filename);
1285 Hrtf = Hrtf->next;
1291 void FreeHrtfs(void)
1293 struct HrtfEntry *Hrtf{LoadedHrtfs};
1294 LoadedHrtfs = nullptr;
1296 while(Hrtf != nullptr)
1298 struct HrtfEntry *next{Hrtf->next};
1299 al_free(Hrtf->handle);
1300 al_free(Hrtf);
1301 Hrtf = next;