🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1681 lines
59 KiB

  1. /*
  2. * HRTF utility for producing and demonstrating the process of creating an
  3. * OpenAL Soft compatible HRIR data set.
  4. *
  5. * Copyright (C) 2011-2019 Christopher Fitzgerald
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program; if not, write to the Free Software Foundation, Inc.,
  19. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20. *
  21. * Or visit: http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  22. *
  23. * --------------------------------------------------------------------------
  24. *
  25. * A big thanks goes out to all those whose work done in the field of
  26. * binaural sound synthesis using measured HRTFs makes this utility and the
  27. * OpenAL Soft implementation possible.
  28. *
  29. * The algorithm for diffuse-field equalization was adapted from the work
  30. * done by Rio Emmanuel and Larcher Veronique of IRCAM and Bill Gardner of
  31. * MIT Media Laboratory. It operates as follows:
  32. *
  33. * 1. Take the FFT of each HRIR and only keep the magnitude responses.
  34. * 2. Calculate the diffuse-field power-average of all HRIRs weighted by
  35. * their contribution to the total surface area covered by their
  36. * measurement. This has since been modified to use coverage volume for
  37. * multi-field HRIR data sets.
  38. * 3. Take the diffuse-field average and limit its magnitude range.
  39. * 4. Equalize the responses by using the inverse of the diffuse-field
  40. * average.
  41. * 5. Reconstruct the minimum-phase responses.
  42. * 5. Zero the DC component.
  43. * 6. IFFT the result and truncate to the desired-length minimum-phase FIR.
  44. *
  45. * The spherical head algorithm for calculating propagation delay was adapted
  46. * from the paper:
  47. *
  48. * Modeling Interaural Time Difference Assuming a Spherical Head
  49. * Joel David Miller
  50. * Music 150, Musical Acoustics, Stanford University
  51. * December 2, 2001
  52. *
  53. * The formulae for calculating the Kaiser window metrics are from the
  54. * the textbook:
  55. *
  56. * Discrete-Time Signal Processing
  57. * Alan V. Oppenheim and Ronald W. Schafer
  58. * Prentice-Hall Signal Processing Series
  59. * 1999
  60. */
  61. #define _UNICODE
  62. #include "config.h"
  63. #include "makemhr.h"
  64. #include <algorithm>
  65. #include <atomic>
  66. #include <chrono>
  67. #include <cmath>
  68. #include <complex>
  69. #include <cstdint>
  70. #include <cstdio>
  71. #include <cstdlib>
  72. #include <cstring>
  73. #include <functional>
  74. #include <iostream>
  75. #include <limits>
  76. #include <memory>
  77. #include <numeric>
  78. #include <thread>
  79. #include <utility>
  80. #include <vector>
  81. #ifdef HAVE_GETOPT
  82. #include <unistd.h>
  83. #else
  84. #include "../getopt.h"
  85. #endif
  86. #include "alfstream.h"
  87. #include "alspan.h"
  88. #include "alstring.h"
  89. #include "loaddef.h"
  90. #include "loadsofa.h"
  91. #include "win_main_utf8.h"
  92. namespace {
  93. using namespace std::placeholders;
  94. } // namespace
  95. #ifndef M_PI
  96. #define M_PI (3.14159265358979323846)
  97. #endif
  98. // Head model used for calculating the impulse delays.
  99. enum HeadModelT {
  100. HM_NONE,
  101. HM_DATASET, // Measure the onset from the dataset.
  102. HM_SPHERE // Calculate the onset using a spherical head model.
  103. };
  104. // The epsilon used to maintain signal stability.
  105. #define EPSILON (1e-9)
  106. // The limits to the FFT window size override on the command line.
  107. #define MIN_FFTSIZE (65536)
  108. #define MAX_FFTSIZE (131072)
  109. // The limits to the equalization range limit on the command line.
  110. #define MIN_LIMIT (2.0)
  111. #define MAX_LIMIT (120.0)
  112. // The limits to the truncation window size on the command line.
  113. #define MIN_TRUNCSIZE (16)
  114. #define MAX_TRUNCSIZE (128)
  115. // The limits to the custom head radius on the command line.
  116. #define MIN_CUSTOM_RADIUS (0.05)
  117. #define MAX_CUSTOM_RADIUS (0.15)
  118. // The defaults for the command line options.
  119. #define DEFAULT_FFTSIZE (65536)
  120. #define DEFAULT_EQUALIZE (1)
  121. #define DEFAULT_SURFACE (1)
  122. #define DEFAULT_LIMIT (24.0)
  123. #define DEFAULT_TRUNCSIZE (32)
  124. #define DEFAULT_HEAD_MODEL (HM_DATASET)
  125. #define DEFAULT_CUSTOM_RADIUS (0.0)
  126. // The maximum propagation delay value supported by OpenAL Soft.
  127. #define MAX_HRTD (63.0)
  128. // The OpenAL Soft HRTF format marker. It stands for minimum-phase head
  129. // response protocol 03.
  130. #define MHR_FORMAT ("MinPHR03")
  131. /* Channel index enums. Mono uses LeftChannel only. */
  132. enum ChannelIndex : uint {
  133. LeftChannel = 0u,
  134. RightChannel = 1u
  135. };
  136. /* Performs a string substitution. Any case-insensitive occurrences of the
  137. * pattern string are replaced with the replacement string. The result is
  138. * truncated if necessary.
  139. */
  140. static std::string StrSubst(al::span<const char> in, const al::span<const char> pat,
  141. const al::span<const char> rep)
  142. {
  143. std::string ret;
  144. ret.reserve(in.size() + pat.size());
  145. while(in.size() >= pat.size())
  146. {
  147. if(al::strncasecmp(in.data(), pat.data(), pat.size()) == 0)
  148. {
  149. in = in.subspan(pat.size());
  150. ret.append(rep.data(), rep.size());
  151. }
  152. else
  153. {
  154. size_t endpos{1};
  155. while(endpos < in.size() && in[endpos] != pat.front())
  156. ++endpos;
  157. ret.append(in.data(), endpos);
  158. in = in.subspan(endpos);
  159. }
  160. }
  161. ret.append(in.data(), in.size());
  162. return ret;
  163. }
  164. /*********************
  165. *** Math routines ***
  166. *********************/
  167. // Simple clamp routine.
  168. static double Clamp(const double val, const double lower, const double upper)
  169. {
  170. return std::min(std::max(val, lower), upper);
  171. }
  172. static inline uint dither_rng(uint *seed)
  173. {
  174. *seed = *seed * 96314165 + 907633515;
  175. return *seed;
  176. }
  177. // Performs a triangular probability density function dither. The input samples
  178. // should be normalized (-1 to +1).
  179. static void TpdfDither(double *RESTRICT out, const double *RESTRICT in, const double scale,
  180. const uint count, const uint step, uint *seed)
  181. {
  182. static constexpr double PRNG_SCALE = 1.0 / std::numeric_limits<uint>::max();
  183. for(uint i{0};i < count;i++)
  184. {
  185. uint prn0{dither_rng(seed)};
  186. uint prn1{dither_rng(seed)};
  187. *out = std::round(*(in++)*scale + (prn0*PRNG_SCALE - prn1*PRNG_SCALE));
  188. out += step;
  189. }
  190. }
  191. /* Fast Fourier transform routines. The number of points must be a power of
  192. * two.
  193. */
  194. // Performs bit-reversal ordering.
  195. static void FftArrange(const uint n, complex_d *inout)
  196. {
  197. // Handle in-place arrangement.
  198. uint rk{0u};
  199. for(uint k{0u};k < n;k++)
  200. {
  201. if(rk > k)
  202. std::swap(inout[rk], inout[k]);
  203. uint m{n};
  204. while(rk&(m >>= 1))
  205. rk &= ~m;
  206. rk |= m;
  207. }
  208. }
  209. // Performs the summation.
  210. static void FftSummation(const uint n, const double s, complex_d *cplx)
  211. {
  212. double pi;
  213. uint m, m2;
  214. uint i, k, mk;
  215. pi = s * M_PI;
  216. for(m = 1, m2 = 2;m < n; m <<= 1, m2 <<= 1)
  217. {
  218. // v = Complex (-2.0 * sin (0.5 * pi / m) * sin (0.5 * pi / m), -sin (pi / m))
  219. double sm = std::sin(0.5 * pi / m);
  220. auto v = complex_d{-2.0*sm*sm, -std::sin(pi / m)};
  221. auto w = complex_d{1.0, 0.0};
  222. for(i = 0;i < m;i++)
  223. {
  224. for(k = i;k < n;k += m2)
  225. {
  226. mk = k + m;
  227. auto t = w * cplx[mk];
  228. cplx[mk] = cplx[k] - t;
  229. cplx[k] = cplx[k] + t;
  230. }
  231. w += v*w;
  232. }
  233. }
  234. }
  235. // Performs a forward FFT.
  236. void FftForward(const uint n, complex_d *inout)
  237. {
  238. FftArrange(n, inout);
  239. FftSummation(n, 1.0, inout);
  240. }
  241. // Performs an inverse FFT.
  242. void FftInverse(const uint n, complex_d *inout)
  243. {
  244. FftArrange(n, inout);
  245. FftSummation(n, -1.0, inout);
  246. double f{1.0 / n};
  247. for(uint i{0};i < n;i++)
  248. inout[i] *= f;
  249. }
  250. /* Calculate the complex helical sequence (or discrete-time analytical signal)
  251. * of the given input using the Hilbert transform. Given the natural logarithm
  252. * of a signal's magnitude response, the imaginary components can be used as
  253. * the angles for minimum-phase reconstruction.
  254. */
  255. static void Hilbert(const uint n, complex_d *inout)
  256. {
  257. uint i;
  258. // Handle in-place operation.
  259. for(i = 0;i < n;i++)
  260. inout[i].imag(0.0);
  261. FftInverse(n, inout);
  262. for(i = 1;i < (n+1)/2;i++)
  263. inout[i] *= 2.0;
  264. /* Increment i if n is even. */
  265. i += (n&1)^1;
  266. for(;i < n;i++)
  267. inout[i] = complex_d{0.0, 0.0};
  268. FftForward(n, inout);
  269. }
  270. /* Calculate the magnitude response of the given input. This is used in
  271. * place of phase decomposition, since the phase residuals are discarded for
  272. * minimum phase reconstruction. The mirrored half of the response is also
  273. * discarded.
  274. */
  275. void MagnitudeResponse(const uint n, const complex_d *in, double *out)
  276. {
  277. const uint m = 1 + (n / 2);
  278. uint i;
  279. for(i = 0;i < m;i++)
  280. out[i] = std::max(std::abs(in[i]), EPSILON);
  281. }
  282. /* Apply a range limit (in dB) to the given magnitude response. This is used
  283. * to adjust the effects of the diffuse-field average on the equalization
  284. * process.
  285. */
  286. static void LimitMagnitudeResponse(const uint n, const uint m, const double limit, const double *in, double *out)
  287. {
  288. double halfLim;
  289. uint i, lower, upper;
  290. double ave;
  291. halfLim = limit / 2.0;
  292. // Convert the response to dB.
  293. for(i = 0;i < m;i++)
  294. out[i] = 20.0 * std::log10(in[i]);
  295. // Use six octaves to calculate the average magnitude of the signal.
  296. lower = (static_cast<uint>(std::ceil(n / std::pow(2.0, 8.0)))) - 1;
  297. upper = (static_cast<uint>(std::floor(n / std::pow(2.0, 2.0)))) - 1;
  298. ave = 0.0;
  299. for(i = lower;i <= upper;i++)
  300. ave += out[i];
  301. ave /= upper - lower + 1;
  302. // Keep the response within range of the average magnitude.
  303. for(i = 0;i < m;i++)
  304. out[i] = Clamp(out[i], ave - halfLim, ave + halfLim);
  305. // Convert the response back to linear magnitude.
  306. for(i = 0;i < m;i++)
  307. out[i] = std::pow(10.0, out[i] / 20.0);
  308. }
  309. /* Reconstructs the minimum-phase component for the given magnitude response
  310. * of a signal. This is equivalent to phase recomposition, sans the missing
  311. * residuals (which were discarded). The mirrored half of the response is
  312. * reconstructed.
  313. */
  314. static void MinimumPhase(const uint n, double *mags, complex_d *out)
  315. {
  316. const uint m{(n/2) + 1};
  317. uint i;
  318. for(i = 0;i < m;i++)
  319. out[i] = std::log(mags[i]);
  320. for(;i < n;i++)
  321. {
  322. mags[i] = mags[n - i];
  323. out[i] = out[n - i];
  324. }
  325. Hilbert(n, out);
  326. // Remove any DC offset the filter has.
  327. mags[0] = EPSILON;
  328. for(i = 0;i < n;i++)
  329. {
  330. auto a = std::exp(complex_d{0.0, out[i].imag()});
  331. out[i] = a * mags[i];
  332. }
  333. }
  334. /***************************
  335. *** File storage output ***
  336. ***************************/
  337. // Write an ASCII string to a file.
  338. static int WriteAscii(const char *out, FILE *fp, const char *filename)
  339. {
  340. size_t len;
  341. len = strlen(out);
  342. if(fwrite(out, 1, len, fp) != len)
  343. {
  344. fclose(fp);
  345. fprintf(stderr, "\nError: Bad write to file '%s'.\n", filename);
  346. return 0;
  347. }
  348. return 1;
  349. }
  350. // Write a binary value of the given byte order and byte size to a file,
  351. // loading it from a 32-bit unsigned integer.
  352. static int WriteBin4(const uint bytes, const uint32_t in, FILE *fp, const char *filename)
  353. {
  354. uint8_t out[4];
  355. uint i;
  356. for(i = 0;i < bytes;i++)
  357. out[i] = (in>>(i*8)) & 0x000000FF;
  358. if(fwrite(out, 1, bytes, fp) != bytes)
  359. {
  360. fprintf(stderr, "\nError: Bad write to file '%s'.\n", filename);
  361. return 0;
  362. }
  363. return 1;
  364. }
  365. // Store the OpenAL Soft HRTF data set.
  366. static int StoreMhr(const HrirDataT *hData, const char *filename)
  367. {
  368. const uint channels{(hData->mChannelType == CT_STEREO) ? 2u : 1u};
  369. const uint n{hData->mIrPoints};
  370. uint dither_seed{22222};
  371. uint fi, ei, ai, i;
  372. FILE *fp;
  373. if((fp=fopen(filename, "wb")) == nullptr)
  374. {
  375. fprintf(stderr, "\nError: Could not open MHR file '%s'.\n", filename);
  376. return 0;
  377. }
  378. if(!WriteAscii(MHR_FORMAT, fp, filename))
  379. return 0;
  380. if(!WriteBin4(4, hData->mIrRate, fp, filename))
  381. return 0;
  382. if(!WriteBin4(1, static_cast<uint32_t>(hData->mChannelType), fp, filename))
  383. return 0;
  384. if(!WriteBin4(1, hData->mIrPoints, fp, filename))
  385. return 0;
  386. if(!WriteBin4(1, hData->mFdCount, fp, filename))
  387. return 0;
  388. for(fi = hData->mFdCount-1;fi < hData->mFdCount;fi--)
  389. {
  390. auto fdist = static_cast<uint32_t>(std::round(1000.0 * hData->mFds[fi].mDistance));
  391. if(!WriteBin4(2, fdist, fp, filename))
  392. return 0;
  393. if(!WriteBin4(1, hData->mFds[fi].mEvCount, fp, filename))
  394. return 0;
  395. for(ei = 0;ei < hData->mFds[fi].mEvCount;ei++)
  396. {
  397. if(!WriteBin4(1, hData->mFds[fi].mEvs[ei].mAzCount, fp, filename))
  398. return 0;
  399. }
  400. }
  401. for(fi = hData->mFdCount-1;fi < hData->mFdCount;fi--)
  402. {
  403. constexpr double scale{8388607.0};
  404. constexpr uint bps{3u};
  405. for(ei = 0;ei < hData->mFds[fi].mEvCount;ei++)
  406. {
  407. for(ai = 0;ai < hData->mFds[fi].mEvs[ei].mAzCount;ai++)
  408. {
  409. HrirAzT *azd = &hData->mFds[fi].mEvs[ei].mAzs[ai];
  410. double out[2 * MAX_TRUNCSIZE];
  411. TpdfDither(out, azd->mIrs[0], scale, n, channels, &dither_seed);
  412. if(hData->mChannelType == CT_STEREO)
  413. TpdfDither(out+1, azd->mIrs[1], scale, n, channels, &dither_seed);
  414. for(i = 0;i < (channels * n);i++)
  415. {
  416. const auto v = static_cast<int>(Clamp(out[i], -scale-1.0, scale));
  417. if(!WriteBin4(bps, static_cast<uint32_t>(v), fp, filename))
  418. return 0;
  419. }
  420. }
  421. }
  422. }
  423. for(fi = hData->mFdCount-1;fi < hData->mFdCount;fi--)
  424. {
  425. /* Delay storage has 2 bits of extra precision. */
  426. constexpr double DelayPrecScale{4.0};
  427. for(ei = 0;ei < hData->mFds[fi].mEvCount;ei++)
  428. {
  429. for(ai = 0;ai < hData->mFds[fi].mEvs[ei].mAzCount;ai++)
  430. {
  431. const HrirAzT &azd = hData->mFds[fi].mEvs[ei].mAzs[ai];
  432. auto v = static_cast<uint>(std::round(azd.mDelays[0]*DelayPrecScale));
  433. if(!WriteBin4(1, v, fp, filename)) return 0;
  434. if(hData->mChannelType == CT_STEREO)
  435. {
  436. v = static_cast<uint>(std::round(azd.mDelays[1]*DelayPrecScale));
  437. if(!WriteBin4(1, v, fp, filename)) return 0;
  438. }
  439. }
  440. }
  441. }
  442. fclose(fp);
  443. return 1;
  444. }
  445. /***********************
  446. *** HRTF processing ***
  447. ***********************/
  448. /* Balances the maximum HRIR magnitudes of multi-field data sets by
  449. * independently normalizing each field in relation to the overall maximum.
  450. * This is done to ignore distance attenuation.
  451. */
  452. static void BalanceFieldMagnitudes(const HrirDataT *hData, const uint channels, const uint m)
  453. {
  454. double maxMags[MAX_FD_COUNT];
  455. uint fi, ei, ai, ti, i;
  456. double maxMag{0.0};
  457. for(fi = 0;fi < hData->mFdCount;fi++)
  458. {
  459. maxMags[fi] = 0.0;
  460. for(ei = hData->mFds[fi].mEvStart;ei < hData->mFds[fi].mEvCount;ei++)
  461. {
  462. for(ai = 0;ai < hData->mFds[fi].mEvs[ei].mAzCount;ai++)
  463. {
  464. HrirAzT *azd = &hData->mFds[fi].mEvs[ei].mAzs[ai];
  465. for(ti = 0;ti < channels;ti++)
  466. {
  467. for(i = 0;i < m;i++)
  468. maxMags[fi] = std::max(azd->mIrs[ti][i], maxMags[fi]);
  469. }
  470. }
  471. }
  472. maxMag = std::max(maxMags[fi], maxMag);
  473. }
  474. for(fi = 0;fi < hData->mFdCount;fi++)
  475. {
  476. const double magFactor{maxMag / maxMags[fi]};
  477. for(ei = hData->mFds[fi].mEvStart;ei < hData->mFds[fi].mEvCount;ei++)
  478. {
  479. for(ai = 0;ai < hData->mFds[fi].mEvs[ei].mAzCount;ai++)
  480. {
  481. HrirAzT *azd = &hData->mFds[fi].mEvs[ei].mAzs[ai];
  482. for(ti = 0;ti < channels;ti++)
  483. {
  484. for(i = 0;i < m;i++)
  485. azd->mIrs[ti][i] *= magFactor;
  486. }
  487. }
  488. }
  489. }
  490. }
  491. /* Calculate the contribution of each HRIR to the diffuse-field average based
  492. * on its coverage volume. All volumes are centered at the spherical HRIR
  493. * coordinates and measured by extruded solid angle.
  494. */
  495. static void CalculateDfWeights(const HrirDataT *hData, double *weights)
  496. {
  497. double sum, innerRa, outerRa, evs, ev, upperEv, lowerEv;
  498. double solidAngle, solidVolume;
  499. uint fi, ei;
  500. sum = 0.0;
  501. // The head radius acts as the limit for the inner radius.
  502. innerRa = hData->mRadius;
  503. for(fi = 0;fi < hData->mFdCount;fi++)
  504. {
  505. // Each volume ends half way between progressive field measurements.
  506. if((fi + 1) < hData->mFdCount)
  507. outerRa = 0.5f * (hData->mFds[fi].mDistance + hData->mFds[fi + 1].mDistance);
  508. // The final volume has its limit extended to some practical value.
  509. // This is done to emphasize the far-field responses in the average.
  510. else
  511. outerRa = 10.0f;
  512. evs = M_PI / 2.0 / (hData->mFds[fi].mEvCount - 1);
  513. for(ei = hData->mFds[fi].mEvStart;ei < hData->mFds[fi].mEvCount;ei++)
  514. {
  515. // For each elevation, calculate the upper and lower limits of
  516. // the patch band.
  517. ev = hData->mFds[fi].mEvs[ei].mElevation;
  518. lowerEv = std::max(-M_PI / 2.0, ev - evs);
  519. upperEv = std::min(M_PI / 2.0, ev + evs);
  520. // Calculate the surface area of the patch band.
  521. solidAngle = 2.0 * M_PI * (std::sin(upperEv) - std::sin(lowerEv));
  522. // Then the volume of the extruded patch band.
  523. solidVolume = solidAngle * (std::pow(outerRa, 3.0) - std::pow(innerRa, 3.0)) / 3.0;
  524. // Each weight is the volume of one extruded patch.
  525. weights[(fi * MAX_EV_COUNT) + ei] = solidVolume / hData->mFds[fi].mEvs[ei].mAzCount;
  526. // Sum the total coverage volume of the HRIRs for all fields.
  527. sum += solidAngle;
  528. }
  529. innerRa = outerRa;
  530. }
  531. for(fi = 0;fi < hData->mFdCount;fi++)
  532. {
  533. // Normalize the weights given the total surface coverage for all
  534. // fields.
  535. for(ei = hData->mFds[fi].mEvStart;ei < hData->mFds[fi].mEvCount;ei++)
  536. weights[(fi * MAX_EV_COUNT) + ei] /= sum;
  537. }
  538. }
  539. /* Calculate the diffuse-field average from the given magnitude responses of
  540. * the HRIR set. Weighting can be applied to compensate for the varying
  541. * coverage of each HRIR. The final average can then be limited by the
  542. * specified magnitude range (in positive dB; 0.0 to skip).
  543. */
  544. static void CalculateDiffuseFieldAverage(const HrirDataT *hData, const uint channels, const uint m, const int weighted, const double limit, double *dfa)
  545. {
  546. std::vector<double> weights(hData->mFdCount * MAX_EV_COUNT);
  547. uint count, ti, fi, ei, i, ai;
  548. if(weighted)
  549. {
  550. // Use coverage weighting to calculate the average.
  551. CalculateDfWeights(hData, weights.data());
  552. }
  553. else
  554. {
  555. double weight;
  556. // If coverage weighting is not used, the weights still need to be
  557. // averaged by the number of existing HRIRs.
  558. count = hData->mIrCount;
  559. for(fi = 0;fi < hData->mFdCount;fi++)
  560. {
  561. for(ei = 0;ei < hData->mFds[fi].mEvStart;ei++)
  562. count -= hData->mFds[fi].mEvs[ei].mAzCount;
  563. }
  564. weight = 1.0 / count;
  565. for(fi = 0;fi < hData->mFdCount;fi++)
  566. {
  567. for(ei = hData->mFds[fi].mEvStart;ei < hData->mFds[fi].mEvCount;ei++)
  568. weights[(fi * MAX_EV_COUNT) + ei] = weight;
  569. }
  570. }
  571. for(ti = 0;ti < channels;ti++)
  572. {
  573. for(i = 0;i < m;i++)
  574. dfa[(ti * m) + i] = 0.0;
  575. for(fi = 0;fi < hData->mFdCount;fi++)
  576. {
  577. for(ei = hData->mFds[fi].mEvStart;ei < hData->mFds[fi].mEvCount;ei++)
  578. {
  579. for(ai = 0;ai < hData->mFds[fi].mEvs[ei].mAzCount;ai++)
  580. {
  581. HrirAzT *azd = &hData->mFds[fi].mEvs[ei].mAzs[ai];
  582. // Get the weight for this HRIR's contribution.
  583. double weight = weights[(fi * MAX_EV_COUNT) + ei];
  584. // Add this HRIR's weighted power average to the total.
  585. for(i = 0;i < m;i++)
  586. dfa[(ti * m) + i] += weight * azd->mIrs[ti][i] * azd->mIrs[ti][i];
  587. }
  588. }
  589. }
  590. // Finish the average calculation and keep it from being too small.
  591. for(i = 0;i < m;i++)
  592. dfa[(ti * m) + i] = std::max(sqrt(dfa[(ti * m) + i]), EPSILON);
  593. // Apply a limit to the magnitude range of the diffuse-field average
  594. // if desired.
  595. if(limit > 0.0)
  596. LimitMagnitudeResponse(hData->mFftSize, m, limit, &dfa[ti * m], &dfa[ti * m]);
  597. }
  598. }
  599. // Perform diffuse-field equalization on the magnitude responses of the HRIR
  600. // set using the given average response.
  601. static void DiffuseFieldEqualize(const uint channels, const uint m, const double *dfa, const HrirDataT *hData)
  602. {
  603. uint ti, fi, ei, ai, i;
  604. for(fi = 0;fi < hData->mFdCount;fi++)
  605. {
  606. for(ei = hData->mFds[fi].mEvStart;ei < hData->mFds[fi].mEvCount;ei++)
  607. {
  608. for(ai = 0;ai < hData->mFds[fi].mEvs[ei].mAzCount;ai++)
  609. {
  610. HrirAzT *azd = &hData->mFds[fi].mEvs[ei].mAzs[ai];
  611. for(ti = 0;ti < channels;ti++)
  612. {
  613. for(i = 0;i < m;i++)
  614. azd->mIrs[ti][i] /= dfa[(ti * m) + i];
  615. }
  616. }
  617. }
  618. }
  619. }
  620. // Resamples the HRIRs for use at the given sampling rate.
  621. static void ResampleHrirs(const uint rate, HrirDataT *hData)
  622. {
  623. struct Resampler {
  624. const double scale;
  625. const size_t m;
  626. /* Resampling from a lower rate to a higher rate. This likely only
  627. * works properly when 1 <= scale <= 2.
  628. */
  629. void upsample(double *resampled, const double *ir) const
  630. {
  631. std::fill_n(resampled, m, 0.0);
  632. resampled[0] = ir[0];
  633. for(size_t in{1};in < m;++in)
  634. {
  635. const auto offset = static_cast<double>(in) / scale;
  636. const auto out = static_cast<size_t>(offset);
  637. const double a{offset - static_cast<double>(out)};
  638. if(out == m-1)
  639. resampled[out] += ir[in]*(1.0-a);
  640. else
  641. {
  642. resampled[out ] += ir[in]*(1.0-a);
  643. resampled[out+1] += ir[in]*a;
  644. }
  645. }
  646. }
  647. /* Resampling from a higher rate to a lower rate. This likely only
  648. * works properly when 0.5 <= scale <= 1.0.
  649. */
  650. void downsample(double *resampled, const double *ir) const
  651. {
  652. resampled[0] = ir[0];
  653. for(size_t out{1};out < m;++out)
  654. {
  655. const auto offset = static_cast<double>(out) * scale;
  656. const auto in = static_cast<size_t>(offset);
  657. const double a{offset - static_cast<double>(in)};
  658. if(in == m-1)
  659. resampled[out] = ir[in]*(1.0-a);
  660. else
  661. resampled[out] = ir[in]*(1.0-a) + ir[in+1]*a;
  662. }
  663. }
  664. };
  665. while(rate > hData->mIrRate*2)
  666. ResampleHrirs(hData->mIrRate*2, hData);
  667. while(rate < (hData->mIrRate+1)/2)
  668. ResampleHrirs((hData->mIrRate+1)/2, hData);
  669. const auto scale = static_cast<double>(rate) / hData->mIrRate;
  670. const size_t m{hData->mFftSize/2u + 1u};
  671. auto resampled = std::vector<double>(m);
  672. const Resampler resampler{scale, m};
  673. auto do_resample = std::bind(
  674. std::mem_fn((scale > 1.0) ? &Resampler::upsample : &Resampler::downsample), &resampler,
  675. _1, _2);
  676. const uint channels{(hData->mChannelType == CT_STEREO) ? 2u : 1u};
  677. for(uint fi{0};fi < hData->mFdCount;++fi)
  678. {
  679. for(uint ei{hData->mFds[fi].mEvStart};ei < hData->mFds[fi].mEvCount;++ei)
  680. {
  681. for(uint ai{0};ai < hData->mFds[fi].mEvs[ei].mAzCount;++ai)
  682. {
  683. HrirAzT *azd = &hData->mFds[fi].mEvs[ei].mAzs[ai];
  684. for(uint ti{0};ti < channels;++ti)
  685. {
  686. do_resample(resampled.data(), azd->mIrs[ti]);
  687. /* This should probably be rescaled according to the scale,
  688. * however it'll all be normalized in the end so a constant
  689. * scalar is fine to leave.
  690. */
  691. std::transform(resampled.cbegin(), resampled.cend(), azd->mIrs[ti],
  692. [](const double d) { return std::max(d, EPSILON); });
  693. }
  694. }
  695. }
  696. }
  697. hData->mIrRate = rate;
  698. }
  699. /* Given field and elevation indices and an azimuth, calculate the indices of
  700. * the two HRIRs that bound the coordinate along with a factor for
  701. * calculating the continuous HRIR using interpolation.
  702. */
  703. static void CalcAzIndices(const HrirFdT &field, const uint ei, const double az, uint *a0, uint *a1, double *af)
  704. {
  705. double f{(2.0*M_PI + az) * field.mEvs[ei].mAzCount / (2.0*M_PI)};
  706. uint i{static_cast<uint>(f) % field.mEvs[ei].mAzCount};
  707. f -= std::floor(f);
  708. *a0 = i;
  709. *a1 = (i + 1) % field.mEvs[ei].mAzCount;
  710. *af = f;
  711. }
  712. /* Synthesize any missing onset timings at the bottom elevations of each field.
  713. * This just mirrors some top elevations for the bottom, and blends the
  714. * remaining elevations (not an accurate model).
  715. */
  716. static void SynthesizeOnsets(HrirDataT *hData)
  717. {
  718. const uint channels{(hData->mChannelType == CT_STEREO) ? 2u : 1u};
  719. auto proc_field = [channels](HrirFdT &field) -> void
  720. {
  721. /* Get the starting elevation from the measurements, and use it as the
  722. * upper elevation limit for what needs to be calculated.
  723. */
  724. const uint upperElevReal{field.mEvStart};
  725. if(upperElevReal <= 0) return;
  726. /* Get the lowest half of the missing elevations' delays by mirroring
  727. * the top elevation delays. The responses are on a spherical grid
  728. * centered between the ears, so these should align.
  729. */
  730. uint ei{};
  731. if(channels > 1)
  732. {
  733. /* Take the polar opposite position of the desired measurement and
  734. * swap the ears.
  735. */
  736. field.mEvs[0].mAzs[0].mDelays[0] = field.mEvs[field.mEvCount-1].mAzs[0].mDelays[1];
  737. field.mEvs[0].mAzs[0].mDelays[1] = field.mEvs[field.mEvCount-1].mAzs[0].mDelays[0];
  738. for(ei = 1u;ei < (upperElevReal+1)/2;++ei)
  739. {
  740. const uint topElev{field.mEvCount-ei-1};
  741. for(uint ai{0u};ai < field.mEvs[ei].mAzCount;ai++)
  742. {
  743. uint a0, a1;
  744. double af;
  745. /* Rotate this current azimuth by a half-circle, and lookup
  746. * the mirrored elevation to find the indices for the polar
  747. * opposite position (may need blending).
  748. */
  749. const double az{field.mEvs[ei].mAzs[ai].mAzimuth + M_PI};
  750. CalcAzIndices(field, topElev, az, &a0, &a1, &af);
  751. /* Blend the delays, and again, swap the ears. */
  752. field.mEvs[ei].mAzs[ai].mDelays[0] = Lerp(
  753. field.mEvs[topElev].mAzs[a0].mDelays[1],
  754. field.mEvs[topElev].mAzs[a1].mDelays[1], af);
  755. field.mEvs[ei].mAzs[ai].mDelays[1] = Lerp(
  756. field.mEvs[topElev].mAzs[a0].mDelays[0],
  757. field.mEvs[topElev].mAzs[a1].mDelays[0], af);
  758. }
  759. }
  760. }
  761. else
  762. {
  763. field.mEvs[0].mAzs[0].mDelays[0] = field.mEvs[field.mEvCount-1].mAzs[0].mDelays[0];
  764. for(ei = 1u;ei < (upperElevReal+1)/2;++ei)
  765. {
  766. const uint topElev{field.mEvCount-ei-1};
  767. for(uint ai{0u};ai < field.mEvs[ei].mAzCount;ai++)
  768. {
  769. uint a0, a1;
  770. double af;
  771. /* For mono data sets, mirror the azimuth front<->back
  772. * since the other ear is a mirror of what we have (e.g.
  773. * the left ear's back-left is simulated with the right
  774. * ear's front-right, which uses the left ear's front-left
  775. * measurement).
  776. */
  777. double az{field.mEvs[ei].mAzs[ai].mAzimuth};
  778. if(az <= M_PI) az = M_PI - az;
  779. else az = (M_PI*2.0)-az + M_PI;
  780. CalcAzIndices(field, topElev, az, &a0, &a1, &af);
  781. field.mEvs[ei].mAzs[ai].mDelays[0] = Lerp(
  782. field.mEvs[topElev].mAzs[a0].mDelays[0],
  783. field.mEvs[topElev].mAzs[a1].mDelays[0], af);
  784. }
  785. }
  786. }
  787. /* Record the lowest elevation filled in with the mirrored top. */
  788. const uint lowerElevFake{ei-1u};
  789. /* Fill in the remaining delays using bilinear interpolation. This
  790. * helps smooth the transition back to the real delays.
  791. */
  792. for(;ei < upperElevReal;++ei)
  793. {
  794. const double ef{(field.mEvs[upperElevReal].mElevation - field.mEvs[ei].mElevation) /
  795. (field.mEvs[upperElevReal].mElevation - field.mEvs[lowerElevFake].mElevation)};
  796. for(uint ai{0u};ai < field.mEvs[ei].mAzCount;ai++)
  797. {
  798. uint a0, a1, a2, a3;
  799. double af0, af1;
  800. double az{field.mEvs[ei].mAzs[ai].mAzimuth};
  801. CalcAzIndices(field, upperElevReal, az, &a0, &a1, &af0);
  802. CalcAzIndices(field, lowerElevFake, az, &a2, &a3, &af1);
  803. double blend[4]{
  804. (1.0-ef) * (1.0-af0),
  805. (1.0-ef) * ( af0),
  806. ( ef) * (1.0-af1),
  807. ( ef) * ( af1)
  808. };
  809. for(uint ti{0u};ti < channels;ti++)
  810. {
  811. field.mEvs[ei].mAzs[ai].mDelays[ti] =
  812. field.mEvs[upperElevReal].mAzs[a0].mDelays[ti]*blend[0] +
  813. field.mEvs[upperElevReal].mAzs[a1].mDelays[ti]*blend[1] +
  814. field.mEvs[lowerElevFake].mAzs[a2].mDelays[ti]*blend[2] +
  815. field.mEvs[lowerElevFake].mAzs[a3].mDelays[ti]*blend[3];
  816. }
  817. }
  818. }
  819. };
  820. std::for_each(hData->mFds.begin(), hData->mFds.begin()+hData->mFdCount, proc_field);
  821. }
  822. /* Attempt to synthesize any missing HRIRs at the bottom elevations of each
  823. * field. Right now this just blends the lowest elevation HRIRs together and
  824. * applies a low-pass filter to simulate body occlusion. It is a simple, if
  825. * inaccurate model.
  826. */
  827. static void SynthesizeHrirs(HrirDataT *hData)
  828. {
  829. const uint channels{(hData->mChannelType == CT_STEREO) ? 2u : 1u};
  830. auto htemp = std::vector<complex_d>(hData->mFftSize);
  831. const uint m{hData->mFftSize/2u + 1u};
  832. auto filter = std::vector<double>(m);
  833. const double beta{3.5e-6 * hData->mIrRate};
  834. auto proc_field = [channels,m,beta,&htemp,&filter](HrirFdT &field) -> void
  835. {
  836. const uint oi{field.mEvStart};
  837. if(oi <= 0) return;
  838. for(uint ti{0u};ti < channels;ti++)
  839. {
  840. uint a0, a1;
  841. double af;
  842. /* Use the lowest immediate-left response for the left ear and
  843. * lowest immediate-right response for the right ear. Given no comb
  844. * effects as a result of the left response reaching the right ear
  845. * and vice-versa, this produces a decent phantom-center response
  846. * underneath the head.
  847. */
  848. CalcAzIndices(field, oi, ((ti==0) ? -M_PI : M_PI) / 2.0, &a0, &a1, &af);
  849. for(uint i{0u};i < m;i++)
  850. {
  851. field.mEvs[0].mAzs[0].mIrs[ti][i] = Lerp(field.mEvs[oi].mAzs[a0].mIrs[ti][i],
  852. field.mEvs[oi].mAzs[a1].mIrs[ti][i], af);
  853. }
  854. }
  855. for(uint ei{1u};ei < field.mEvStart;ei++)
  856. {
  857. const double of{static_cast<double>(ei) / field.mEvStart};
  858. const double b{(1.0 - of) * beta};
  859. double lp[4]{};
  860. /* Calculate a low-pass filter to simulate body occlusion. */
  861. lp[0] = Lerp(1.0, lp[0], b);
  862. lp[1] = Lerp(lp[0], lp[1], b);
  863. lp[2] = Lerp(lp[1], lp[2], b);
  864. lp[3] = Lerp(lp[2], lp[3], b);
  865. htemp[0] = lp[3];
  866. for(size_t i{1u};i < htemp.size();i++)
  867. {
  868. lp[0] = Lerp(0.0, lp[0], b);
  869. lp[1] = Lerp(lp[0], lp[1], b);
  870. lp[2] = Lerp(lp[1], lp[2], b);
  871. lp[3] = Lerp(lp[2], lp[3], b);
  872. htemp[i] = lp[3];
  873. }
  874. /* Get the filter's frequency-domain response and extract the
  875. * frequency magnitudes (phase will be reconstructed later)).
  876. */
  877. FftForward(static_cast<uint>(htemp.size()), htemp.data());
  878. std::transform(htemp.cbegin(), htemp.cbegin()+m, filter.begin(),
  879. [](const complex_d &c) -> double { return std::abs(c); });
  880. for(uint ai{0u};ai < field.mEvs[ei].mAzCount;ai++)
  881. {
  882. uint a0, a1;
  883. double af;
  884. CalcAzIndices(field, oi, field.mEvs[ei].mAzs[ai].mAzimuth, &a0, &a1, &af);
  885. for(uint ti{0u};ti < channels;ti++)
  886. {
  887. for(uint i{0u};i < m;i++)
  888. {
  889. /* Blend the two defined HRIRs closest to this azimuth,
  890. * then blend that with the synthesized -90 elevation.
  891. */
  892. const double s1{Lerp(field.mEvs[oi].mAzs[a0].mIrs[ti][i],
  893. field.mEvs[oi].mAzs[a1].mIrs[ti][i], af)};
  894. const double s{Lerp(field.mEvs[0].mAzs[0].mIrs[ti][i], s1, of)};
  895. field.mEvs[ei].mAzs[ai].mIrs[ti][i] = s * filter[i];
  896. }
  897. }
  898. }
  899. }
  900. const double b{beta};
  901. double lp[4]{};
  902. lp[0] = Lerp(1.0, lp[0], b);
  903. lp[1] = Lerp(lp[0], lp[1], b);
  904. lp[2] = Lerp(lp[1], lp[2], b);
  905. lp[3] = Lerp(lp[2], lp[3], b);
  906. htemp[0] = lp[3];
  907. for(size_t i{1u};i < htemp.size();i++)
  908. {
  909. lp[0] = Lerp(0.0, lp[0], b);
  910. lp[1] = Lerp(lp[0], lp[1], b);
  911. lp[2] = Lerp(lp[1], lp[2], b);
  912. lp[3] = Lerp(lp[2], lp[3], b);
  913. htemp[i] = lp[3];
  914. }
  915. FftForward(static_cast<uint>(htemp.size()), htemp.data());
  916. std::transform(htemp.cbegin(), htemp.cbegin()+m, filter.begin(),
  917. [](const complex_d &c) -> double { return std::abs(c); });
  918. for(uint ti{0u};ti < channels;ti++)
  919. {
  920. for(uint i{0u};i < m;i++)
  921. field.mEvs[0].mAzs[0].mIrs[ti][i] *= filter[i];
  922. }
  923. };
  924. std::for_each(hData->mFds.begin(), hData->mFds.begin()+hData->mFdCount, proc_field);
  925. }
  926. // The following routines assume a full set of HRIRs for all elevations.
  927. /* Perform minimum-phase reconstruction using the magnitude responses of the
  928. * HRIR set. Work is delegated to this struct, which runs asynchronously on one
  929. * or more threads (sharing the same reconstructor object).
  930. */
  931. struct HrirReconstructor {
  932. std::vector<double*> mIrs;
  933. std::atomic<size_t> mCurrent;
  934. std::atomic<size_t> mDone;
  935. uint mFftSize;
  936. uint mIrPoints;
  937. void Worker()
  938. {
  939. auto h = std::vector<complex_d>(mFftSize);
  940. auto mags = std::vector<double>(mFftSize);
  941. size_t m{(mFftSize/2) + 1};
  942. while(1)
  943. {
  944. /* Load the current index to process. */
  945. size_t idx{mCurrent.load()};
  946. do {
  947. /* If the index is at the end, we're done. */
  948. if(idx >= mIrs.size())
  949. return;
  950. /* Otherwise, increment the current index atomically so other
  951. * threads know to go to the next one. If this call fails, the
  952. * current index was just changed by another thread and the new
  953. * value is loaded into idx, which we'll recheck.
  954. */
  955. } while(!mCurrent.compare_exchange_weak(idx, idx+1, std::memory_order_relaxed));
  956. /* Now do the reconstruction, and apply the inverse FFT to get the
  957. * time-domain response.
  958. */
  959. for(size_t i{0};i < m;++i)
  960. mags[i] = std::max(mIrs[idx][i], EPSILON);
  961. MinimumPhase(mFftSize, mags.data(), h.data());
  962. FftInverse(mFftSize, h.data());
  963. for(uint i{0u};i < mIrPoints;++i)
  964. mIrs[idx][i] = h[i].real();
  965. /* Increment the number of IRs done. */
  966. mDone.fetch_add(1);
  967. }
  968. }
  969. };
  970. static void ReconstructHrirs(const HrirDataT *hData, const uint numThreads)
  971. {
  972. const uint channels{(hData->mChannelType == CT_STEREO) ? 2u : 1u};
  973. /* Set up the reconstructor with the needed size info and pointers to the
  974. * IRs to process.
  975. */
  976. HrirReconstructor reconstructor;
  977. reconstructor.mCurrent.store(0, std::memory_order_relaxed);
  978. reconstructor.mDone.store(0, std::memory_order_relaxed);
  979. reconstructor.mFftSize = hData->mFftSize;
  980. reconstructor.mIrPoints = hData->mIrPoints;
  981. for(uint fi{0u};fi < hData->mFdCount;fi++)
  982. {
  983. const HrirFdT &field = hData->mFds[fi];
  984. for(uint ei{0};ei < field.mEvCount;ei++)
  985. {
  986. const HrirEvT &elev = field.mEvs[ei];
  987. for(uint ai{0u};ai < elev.mAzCount;ai++)
  988. {
  989. const HrirAzT &azd = elev.mAzs[ai];
  990. for(uint ti{0u};ti < channels;ti++)
  991. reconstructor.mIrs.push_back(azd.mIrs[ti]);
  992. }
  993. }
  994. }
  995. /* Launch threads to work on reconstruction. */
  996. std::vector<std::thread> thrds;
  997. thrds.reserve(numThreads);
  998. for(size_t i{0};i < numThreads;++i)
  999. thrds.emplace_back(std::mem_fn(&HrirReconstructor::Worker), &reconstructor);
  1000. /* Keep track of the number of IRs done, periodically reporting it. */
  1001. size_t count;
  1002. do {
  1003. std::this_thread::sleep_for(std::chrono::milliseconds{50});
  1004. count = reconstructor.mDone.load();
  1005. size_t pcdone{count * 100 / reconstructor.mIrs.size()};
  1006. printf("\r%3zu%% done (%zu of %zu)", pcdone, count, reconstructor.mIrs.size());
  1007. fflush(stdout);
  1008. } while(count < reconstructor.mIrs.size());
  1009. fputc('\n', stdout);
  1010. for(auto &thrd : thrds)
  1011. {
  1012. if(thrd.joinable())
  1013. thrd.join();
  1014. }
  1015. }
  1016. // Normalize the HRIR set and slightly attenuate the result.
  1017. static void NormalizeHrirs(HrirDataT *hData)
  1018. {
  1019. const uint channels{(hData->mChannelType == CT_STEREO) ? 2u : 1u};
  1020. const uint irSize{hData->mIrPoints};
  1021. /* Find the maximum amplitude and RMS out of all the IRs. */
  1022. struct LevelPair { double amp, rms; };
  1023. auto proc0_field = [channels,irSize](const LevelPair levels0, const HrirFdT &field) -> LevelPair
  1024. {
  1025. auto proc_elev = [channels,irSize](const LevelPair levels1, const HrirEvT &elev) -> LevelPair
  1026. {
  1027. auto proc_azi = [channels,irSize](const LevelPair levels2, const HrirAzT &azi) -> LevelPair
  1028. {
  1029. auto proc_channel = [irSize](const LevelPair levels3, const double *ir) -> LevelPair
  1030. {
  1031. /* Calculate the peak amplitude and RMS of this IR. */
  1032. auto current = std::accumulate(ir, ir+irSize, LevelPair{0.0, 0.0},
  1033. [](const LevelPair cur, const double impulse) -> LevelPair
  1034. {
  1035. return {std::max(std::abs(impulse), cur.amp),
  1036. cur.rms + impulse*impulse};
  1037. });
  1038. current.rms = std::sqrt(current.rms / irSize);
  1039. /* Accumulate levels by taking the maximum amplitude and RMS. */
  1040. return LevelPair{std::max(current.amp, levels3.amp),
  1041. std::max(current.rms, levels3.rms)};
  1042. };
  1043. return std::accumulate(azi.mIrs, azi.mIrs+channels, levels2, proc_channel);
  1044. };
  1045. return std::accumulate(elev.mAzs, elev.mAzs+elev.mAzCount, levels1, proc_azi);
  1046. };
  1047. return std::accumulate(field.mEvs, field.mEvs+field.mEvCount, levels0, proc_elev);
  1048. };
  1049. const auto maxlev = std::accumulate(hData->mFds.begin(), hData->mFds.begin()+hData->mFdCount,
  1050. LevelPair{0.0, 0.0}, proc0_field);
  1051. /* Normalize using the maximum RMS of the HRIRs. The RMS measure for the
  1052. * non-filtered signal is of an impulse with equal length (to the filter):
  1053. *
  1054. * rms_impulse = sqrt(sum([ 1^2, 0^2, 0^2, ... ]) / n)
  1055. * = sqrt(1 / n)
  1056. *
  1057. * This helps keep a more consistent volume between the non-filtered signal
  1058. * and various data sets.
  1059. */
  1060. double factor{std::sqrt(1.0 / irSize) / maxlev.rms};
  1061. /* Also ensure the samples themselves won't clip. */
  1062. factor = std::min(factor, 0.99/maxlev.amp);
  1063. /* Now scale all IRs by the given factor. */
  1064. auto proc1_field = [channels,irSize,factor](HrirFdT &field) -> void
  1065. {
  1066. auto proc_elev = [channels,irSize,factor](HrirEvT &elev) -> void
  1067. {
  1068. auto proc_azi = [channels,irSize,factor](HrirAzT &azi) -> void
  1069. {
  1070. auto proc_channel = [irSize,factor](double *ir) -> void
  1071. {
  1072. std::transform(ir, ir+irSize, ir,
  1073. std::bind(std::multiplies<double>{}, _1, factor));
  1074. };
  1075. std::for_each(azi.mIrs, azi.mIrs+channels, proc_channel);
  1076. };
  1077. std::for_each(elev.mAzs, elev.mAzs+elev.mAzCount, proc_azi);
  1078. };
  1079. std::for_each(field.mEvs, field.mEvs+field.mEvCount, proc_elev);
  1080. };
  1081. std::for_each(hData->mFds.begin(), hData->mFds.begin()+hData->mFdCount, proc1_field);
  1082. }
  1083. // Calculate the left-ear time delay using a spherical head model.
  1084. static double CalcLTD(const double ev, const double az, const double rad, const double dist)
  1085. {
  1086. double azp, dlp, l, al;
  1087. azp = std::asin(std::cos(ev) * std::sin(az));
  1088. dlp = std::sqrt((dist*dist) + (rad*rad) + (2.0*dist*rad*sin(azp)));
  1089. l = std::sqrt((dist*dist) - (rad*rad));
  1090. al = (0.5 * M_PI) + azp;
  1091. if(dlp > l)
  1092. dlp = l + (rad * (al - std::acos(rad / dist)));
  1093. return dlp / 343.3;
  1094. }
  1095. // Calculate the effective head-related time delays for each minimum-phase
  1096. // HRIR. This is done per-field since distance delay is ignored.
  1097. static void CalculateHrtds(const HeadModelT model, const double radius, HrirDataT *hData)
  1098. {
  1099. uint channels = (hData->mChannelType == CT_STEREO) ? 2 : 1;
  1100. double customRatio{radius / hData->mRadius};
  1101. uint ti, fi, ei, ai;
  1102. if(model == HM_SPHERE)
  1103. {
  1104. for(fi = 0;fi < hData->mFdCount;fi++)
  1105. {
  1106. for(ei = 0;ei < hData->mFds[fi].mEvCount;ei++)
  1107. {
  1108. HrirEvT *evd = &hData->mFds[fi].mEvs[ei];
  1109. for(ai = 0;ai < evd->mAzCount;ai++)
  1110. {
  1111. HrirAzT *azd = &evd->mAzs[ai];
  1112. for(ti = 0;ti < channels;ti++)
  1113. azd->mDelays[ti] = CalcLTD(evd->mElevation, azd->mAzimuth, radius, hData->mFds[fi].mDistance);
  1114. }
  1115. }
  1116. }
  1117. }
  1118. else if(customRatio != 1.0)
  1119. {
  1120. for(fi = 0;fi < hData->mFdCount;fi++)
  1121. {
  1122. for(ei = 0;ei < hData->mFds[fi].mEvCount;ei++)
  1123. {
  1124. HrirEvT *evd = &hData->mFds[fi].mEvs[ei];
  1125. for(ai = 0;ai < evd->mAzCount;ai++)
  1126. {
  1127. HrirAzT *azd = &evd->mAzs[ai];
  1128. for(ti = 0;ti < channels;ti++)
  1129. azd->mDelays[ti] *= customRatio;
  1130. }
  1131. }
  1132. }
  1133. }
  1134. double maxHrtd{0.0};
  1135. for(fi = 0;fi < hData->mFdCount;fi++)
  1136. {
  1137. double minHrtd{std::numeric_limits<double>::infinity()};
  1138. for(ei = 0;ei < hData->mFds[fi].mEvCount;ei++)
  1139. {
  1140. for(ai = 0;ai < hData->mFds[fi].mEvs[ei].mAzCount;ai++)
  1141. {
  1142. HrirAzT *azd = &hData->mFds[fi].mEvs[ei].mAzs[ai];
  1143. for(ti = 0;ti < channels;ti++)
  1144. minHrtd = std::min(azd->mDelays[ti], minHrtd);
  1145. }
  1146. }
  1147. for(ei = 0;ei < hData->mFds[fi].mEvCount;ei++)
  1148. {
  1149. for(ai = 0;ai < hData->mFds[fi].mEvs[ei].mAzCount;ai++)
  1150. {
  1151. HrirAzT *azd = &hData->mFds[fi].mEvs[ei].mAzs[ai];
  1152. for(ti = 0;ti < channels;ti++)
  1153. {
  1154. azd->mDelays[ti] = (azd->mDelays[ti]-minHrtd) * hData->mIrRate;
  1155. maxHrtd = std::max(maxHrtd, azd->mDelays[ti]);
  1156. }
  1157. }
  1158. }
  1159. }
  1160. if(maxHrtd > MAX_HRTD)
  1161. {
  1162. fprintf(stdout, " Scaling for max delay of %f samples to %f\n...\n", maxHrtd, MAX_HRTD);
  1163. const double scale{MAX_HRTD / maxHrtd};
  1164. for(fi = 0;fi < hData->mFdCount;fi++)
  1165. {
  1166. for(ei = 0;ei < hData->mFds[fi].mEvCount;ei++)
  1167. {
  1168. for(ai = 0;ai < hData->mFds[fi].mEvs[ei].mAzCount;ai++)
  1169. {
  1170. HrirAzT *azd = &hData->mFds[fi].mEvs[ei].mAzs[ai];
  1171. for(ti = 0;ti < channels;ti++)
  1172. azd->mDelays[ti] *= scale;
  1173. }
  1174. }
  1175. }
  1176. }
  1177. }
  1178. // Allocate and configure dynamic HRIR structures.
  1179. int PrepareHrirData(const uint fdCount, const double (&distances)[MAX_FD_COUNT],
  1180. const uint (&evCounts)[MAX_FD_COUNT], const uint azCounts[MAX_FD_COUNT * MAX_EV_COUNT],
  1181. HrirDataT *hData)
  1182. {
  1183. uint evTotal = 0, azTotal = 0, fi, ei, ai;
  1184. for(fi = 0;fi < fdCount;fi++)
  1185. {
  1186. evTotal += evCounts[fi];
  1187. for(ei = 0;ei < evCounts[fi];ei++)
  1188. azTotal += azCounts[(fi * MAX_EV_COUNT) + ei];
  1189. }
  1190. if(!fdCount || !evTotal || !azTotal)
  1191. return 0;
  1192. hData->mEvsBase.resize(evTotal);
  1193. hData->mAzsBase.resize(azTotal);
  1194. hData->mFds.resize(fdCount);
  1195. hData->mIrCount = azTotal;
  1196. hData->mFdCount = fdCount;
  1197. evTotal = 0;
  1198. azTotal = 0;
  1199. for(fi = 0;fi < fdCount;fi++)
  1200. {
  1201. hData->mFds[fi].mDistance = distances[fi];
  1202. hData->mFds[fi].mEvCount = evCounts[fi];
  1203. hData->mFds[fi].mEvStart = 0;
  1204. hData->mFds[fi].mEvs = &hData->mEvsBase[evTotal];
  1205. evTotal += evCounts[fi];
  1206. for(ei = 0;ei < evCounts[fi];ei++)
  1207. {
  1208. uint azCount = azCounts[(fi * MAX_EV_COUNT) + ei];
  1209. hData->mFds[fi].mIrCount += azCount;
  1210. hData->mFds[fi].mEvs[ei].mElevation = -M_PI / 2.0 + M_PI * ei / (evCounts[fi] - 1);
  1211. hData->mFds[fi].mEvs[ei].mIrCount += azCount;
  1212. hData->mFds[fi].mEvs[ei].mAzCount = azCount;
  1213. hData->mFds[fi].mEvs[ei].mAzs = &hData->mAzsBase[azTotal];
  1214. for(ai = 0;ai < azCount;ai++)
  1215. {
  1216. hData->mFds[fi].mEvs[ei].mAzs[ai].mAzimuth = 2.0 * M_PI * ai / azCount;
  1217. hData->mFds[fi].mEvs[ei].mAzs[ai].mIndex = azTotal + ai;
  1218. hData->mFds[fi].mEvs[ei].mAzs[ai].mDelays[0] = 0.0;
  1219. hData->mFds[fi].mEvs[ei].mAzs[ai].mDelays[1] = 0.0;
  1220. hData->mFds[fi].mEvs[ei].mAzs[ai].mIrs[0] = nullptr;
  1221. hData->mFds[fi].mEvs[ei].mAzs[ai].mIrs[1] = nullptr;
  1222. }
  1223. azTotal += azCount;
  1224. }
  1225. }
  1226. return 1;
  1227. }
  1228. /* Parse the data set definition and process the source data, storing the
  1229. * resulting data set as desired. If the input name is NULL it will read
  1230. * from standard input.
  1231. */
  1232. static int ProcessDefinition(const char *inName, const uint outRate, const ChannelModeT chanMode,
  1233. const bool farfield, const uint numThreads, const uint fftSize, const int equalize,
  1234. const int surface, const double limit, const uint truncSize, const HeadModelT model,
  1235. const double radius, const char *outName)
  1236. {
  1237. HrirDataT hData;
  1238. fprintf(stdout, "Using %u thread%s.\n", numThreads, (numThreads==1)?"":"s");
  1239. if(!inName)
  1240. {
  1241. inName = "stdin";
  1242. fprintf(stdout, "Reading HRIR definition from %s...\n", inName);
  1243. if(!LoadDefInput(std::cin, nullptr, 0, inName, fftSize, truncSize, outRate, chanMode, &hData))
  1244. return 0;
  1245. }
  1246. else
  1247. {
  1248. std::unique_ptr<al::ifstream> input{new al::ifstream{inName}};
  1249. if(!input->is_open())
  1250. {
  1251. fprintf(stderr, "Error: Could not open input file '%s'\n", inName);
  1252. return 0;
  1253. }
  1254. char startbytes[4]{};
  1255. input->read(startbytes, sizeof(startbytes));
  1256. std::streamsize startbytecount{input->gcount()};
  1257. if(startbytecount != sizeof(startbytes) || !input->good())
  1258. {
  1259. fprintf(stderr, "Error: Could not read input file '%s'\n", inName);
  1260. return 0;
  1261. }
  1262. if(startbytes[0] == '\x89' && startbytes[1] == 'H' && startbytes[2] == 'D'
  1263. && startbytes[3] == 'F')
  1264. {
  1265. input = nullptr;
  1266. fprintf(stdout, "Reading HRTF data from %s...\n", inName);
  1267. if(!LoadSofaFile(inName, numThreads, fftSize, truncSize, outRate, chanMode, &hData))
  1268. return 0;
  1269. }
  1270. else
  1271. {
  1272. fprintf(stdout, "Reading HRIR definition from %s...\n", inName);
  1273. if(!LoadDefInput(*input, startbytes, startbytecount, inName, fftSize, truncSize, outRate, chanMode, &hData))
  1274. return 0;
  1275. }
  1276. }
  1277. if(equalize)
  1278. {
  1279. uint c{(hData.mChannelType == CT_STEREO) ? 2u : 1u};
  1280. uint m{hData.mFftSize/2u + 1u};
  1281. auto dfa = std::vector<double>(c * m);
  1282. if(hData.mFdCount > 1)
  1283. {
  1284. fprintf(stdout, "Balancing field magnitudes...\n");
  1285. BalanceFieldMagnitudes(&hData, c, m);
  1286. }
  1287. fprintf(stdout, "Calculating diffuse-field average...\n");
  1288. CalculateDiffuseFieldAverage(&hData, c, m, surface, limit, dfa.data());
  1289. fprintf(stdout, "Performing diffuse-field equalization...\n");
  1290. DiffuseFieldEqualize(c, m, dfa.data(), &hData);
  1291. }
  1292. if(hData.mFds.size() > 1)
  1293. {
  1294. fprintf(stdout, "Sorting %zu fields...\n", hData.mFds.size());
  1295. std::sort(hData.mFds.begin(), hData.mFds.end(),
  1296. [](const HrirFdT &lhs, const HrirFdT &rhs) noexcept
  1297. { return lhs.mDistance < rhs.mDistance; });
  1298. if(farfield)
  1299. {
  1300. fprintf(stdout, "Clearing %zu near field%s...\n", hData.mFds.size()-1,
  1301. (hData.mFds.size()-1 != 1) ? "s" : "");
  1302. hData.mFds.erase(hData.mFds.cbegin(), hData.mFds.cend()-1);
  1303. hData.mFdCount = 1;
  1304. }
  1305. }
  1306. if(outRate != 0 && outRate != hData.mIrRate)
  1307. {
  1308. fprintf(stdout, "Resampling HRIRs...\n");
  1309. ResampleHrirs(outRate, &hData);
  1310. }
  1311. fprintf(stdout, "Synthesizing missing elevations...\n");
  1312. if(model == HM_DATASET)
  1313. SynthesizeOnsets(&hData);
  1314. SynthesizeHrirs(&hData);
  1315. fprintf(stdout, "Performing minimum phase reconstruction...\n");
  1316. ReconstructHrirs(&hData, numThreads);
  1317. fprintf(stdout, "Truncating minimum-phase HRIRs...\n");
  1318. hData.mIrPoints = truncSize;
  1319. fprintf(stdout, "Normalizing final HRIRs...\n");
  1320. NormalizeHrirs(&hData);
  1321. fprintf(stdout, "Calculating impulse delays...\n");
  1322. CalculateHrtds(model, (radius > DEFAULT_CUSTOM_RADIUS) ? radius : hData.mRadius, &hData);
  1323. const auto rateStr = std::to_string(hData.mIrRate);
  1324. const auto expName = StrSubst({outName, strlen(outName)}, {"%r", 2},
  1325. {rateStr.data(), rateStr.size()});
  1326. fprintf(stdout, "Creating MHR data set %s...\n", expName.c_str());
  1327. return StoreMhr(&hData, expName.c_str());
  1328. }
  1329. static void PrintHelp(const char *argv0, FILE *ofile)
  1330. {
  1331. fprintf(ofile, "Usage: %s [<option>...]\n\n", argv0);
  1332. fprintf(ofile, "Options:\n");
  1333. fprintf(ofile, " -r <rate> Change the data set sample rate to the specified value and\n");
  1334. fprintf(ofile, " resample the HRIRs accordingly.\n");
  1335. fprintf(ofile, " -m Change the data set to mono, mirroring the left ear for the\n");
  1336. fprintf(ofile, " right ear.\n");
  1337. fprintf(ofile, " -a Change the data set to single field, using the farthest field.\n");
  1338. fprintf(ofile, " -j <threads> Number of threads used to process HRIRs (default: 2).\n");
  1339. fprintf(ofile, " -f <points> Override the FFT window size (default: %u).\n", DEFAULT_FFTSIZE);
  1340. fprintf(ofile, " -e {on|off} Toggle diffuse-field equalization (default: %s).\n", (DEFAULT_EQUALIZE ? "on" : "off"));
  1341. fprintf(ofile, " -s {on|off} Toggle surface-weighted diffuse-field average (default: %s).\n", (DEFAULT_SURFACE ? "on" : "off"));
  1342. fprintf(ofile, " -l {<dB>|none} Specify a limit to the magnitude range of the diffuse-field\n");
  1343. fprintf(ofile, " average (default: %.2f).\n", DEFAULT_LIMIT);
  1344. fprintf(ofile, " -w <points> Specify the size of the truncation window that's applied\n");
  1345. fprintf(ofile, " after minimum-phase reconstruction (default: %u).\n", DEFAULT_TRUNCSIZE);
  1346. fprintf(ofile, " -d {dataset| Specify the model used for calculating the head-delay timing\n");
  1347. fprintf(ofile, " sphere} values (default: %s).\n", ((DEFAULT_HEAD_MODEL == HM_DATASET) ? "dataset" : "sphere"));
  1348. fprintf(ofile, " -c <radius> Use a customized head radius measured to-ear in meters.\n");
  1349. fprintf(ofile, " -i <filename> Specify an HRIR definition file to use (defaults to stdin).\n");
  1350. fprintf(ofile, " -o <filename> Specify an output file. Use of '%%r' will be substituted with\n");
  1351. fprintf(ofile, " the data set sample rate.\n");
  1352. }
  1353. // Standard command line dispatch.
  1354. int main(int argc, char *argv[])
  1355. {
  1356. const char *inName = nullptr, *outName = nullptr;
  1357. uint outRate, fftSize;
  1358. int equalize, surface;
  1359. char *end = nullptr;
  1360. ChannelModeT chanMode;
  1361. HeadModelT model;
  1362. uint numThreads;
  1363. uint truncSize;
  1364. double radius;
  1365. bool farfield;
  1366. double limit;
  1367. int opt;
  1368. if(argc < 2)
  1369. {
  1370. fprintf(stdout, "HRTF Processing and Composition Utility\n\n");
  1371. PrintHelp(argv[0], stdout);
  1372. exit(EXIT_SUCCESS);
  1373. }
  1374. outName = "./oalsoft_hrtf_%r.mhr";
  1375. outRate = 0;
  1376. chanMode = CM_AllowStereo;
  1377. fftSize = DEFAULT_FFTSIZE;
  1378. equalize = DEFAULT_EQUALIZE;
  1379. surface = DEFAULT_SURFACE;
  1380. limit = DEFAULT_LIMIT;
  1381. numThreads = 2;
  1382. truncSize = DEFAULT_TRUNCSIZE;
  1383. model = DEFAULT_HEAD_MODEL;
  1384. radius = DEFAULT_CUSTOM_RADIUS;
  1385. farfield = false;
  1386. while((opt=getopt(argc, argv, "r:maj:f:e:s:l:w:d:c:e:i:o:h")) != -1)
  1387. {
  1388. switch(opt)
  1389. {
  1390. case 'r':
  1391. outRate = static_cast<uint>(strtoul(optarg, &end, 10));
  1392. if(end[0] != '\0' || outRate < MIN_RATE || outRate > MAX_RATE)
  1393. {
  1394. fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected between %u to %u.\n", optarg, opt, MIN_RATE, MAX_RATE);
  1395. exit(EXIT_FAILURE);
  1396. }
  1397. break;
  1398. case 'm':
  1399. chanMode = CM_ForceMono;
  1400. break;
  1401. case 'a':
  1402. farfield = true;
  1403. break;
  1404. case 'j':
  1405. numThreads = static_cast<uint>(strtoul(optarg, &end, 10));
  1406. if(end[0] != '\0' || numThreads > 64)
  1407. {
  1408. fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected between %u to %u.\n", optarg, opt, 0, 64);
  1409. exit(EXIT_FAILURE);
  1410. }
  1411. if(numThreads == 0)
  1412. numThreads = std::thread::hardware_concurrency();
  1413. break;
  1414. case 'f':
  1415. fftSize = static_cast<uint>(strtoul(optarg, &end, 10));
  1416. if(end[0] != '\0' || (fftSize&(fftSize-1)) || fftSize < MIN_FFTSIZE || fftSize > MAX_FFTSIZE)
  1417. {
  1418. fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected a power-of-two between %u to %u.\n", optarg, opt, MIN_FFTSIZE, MAX_FFTSIZE);
  1419. exit(EXIT_FAILURE);
  1420. }
  1421. break;
  1422. case 'e':
  1423. if(strcmp(optarg, "on") == 0)
  1424. equalize = 1;
  1425. else if(strcmp(optarg, "off") == 0)
  1426. equalize = 0;
  1427. else
  1428. {
  1429. fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected on or off.\n", optarg, opt);
  1430. exit(EXIT_FAILURE);
  1431. }
  1432. break;
  1433. case 's':
  1434. if(strcmp(optarg, "on") == 0)
  1435. surface = 1;
  1436. else if(strcmp(optarg, "off") == 0)
  1437. surface = 0;
  1438. else
  1439. {
  1440. fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected on or off.\n", optarg, opt);
  1441. exit(EXIT_FAILURE);
  1442. }
  1443. break;
  1444. case 'l':
  1445. if(strcmp(optarg, "none") == 0)
  1446. limit = 0.0;
  1447. else
  1448. {
  1449. limit = strtod(optarg, &end);
  1450. if(end[0] != '\0' || limit < MIN_LIMIT || limit > MAX_LIMIT)
  1451. {
  1452. fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected between %.0f to %.0f.\n", optarg, opt, MIN_LIMIT, MAX_LIMIT);
  1453. exit(EXIT_FAILURE);
  1454. }
  1455. }
  1456. break;
  1457. case 'w':
  1458. truncSize = static_cast<uint>(strtoul(optarg, &end, 10));
  1459. if(end[0] != '\0' || truncSize < MIN_TRUNCSIZE || truncSize > MAX_TRUNCSIZE)
  1460. {
  1461. fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected between %u to %u.\n", optarg, opt, MIN_TRUNCSIZE, MAX_TRUNCSIZE);
  1462. exit(EXIT_FAILURE);
  1463. }
  1464. break;
  1465. case 'd':
  1466. if(strcmp(optarg, "dataset") == 0)
  1467. model = HM_DATASET;
  1468. else if(strcmp(optarg, "sphere") == 0)
  1469. model = HM_SPHERE;
  1470. else
  1471. {
  1472. fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected dataset or sphere.\n", optarg, opt);
  1473. exit(EXIT_FAILURE);
  1474. }
  1475. break;
  1476. case 'c':
  1477. radius = strtod(optarg, &end);
  1478. if(end[0] != '\0' || radius < MIN_CUSTOM_RADIUS || radius > MAX_CUSTOM_RADIUS)
  1479. {
  1480. fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected between %.2f to %.2f.\n", optarg, opt, MIN_CUSTOM_RADIUS, MAX_CUSTOM_RADIUS);
  1481. exit(EXIT_FAILURE);
  1482. }
  1483. break;
  1484. case 'i':
  1485. inName = optarg;
  1486. break;
  1487. case 'o':
  1488. outName = optarg;
  1489. break;
  1490. case 'h':
  1491. PrintHelp(argv[0], stdout);
  1492. exit(EXIT_SUCCESS);
  1493. default: /* '?' */
  1494. PrintHelp(argv[0], stderr);
  1495. exit(EXIT_FAILURE);
  1496. }
  1497. }
  1498. int ret = ProcessDefinition(inName, outRate, chanMode, farfield, numThreads, fftSize, equalize,
  1499. surface, limit, truncSize, model, radius, outName);
  1500. if(!ret) return -1;
  1501. fprintf(stdout, "Operation completed.\n");
  1502. return EXIT_SUCCESS;
  1503. }