🛠️🐜 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.

2026 lines
61 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. #include "loaddef.h"
  24. #include <algorithm>
  25. #include <cctype>
  26. #include <cmath>
  27. #include <cstdarg>
  28. #include <cstdio>
  29. #include <cstdlib>
  30. #include <cstring>
  31. #include <iterator>
  32. #include <limits>
  33. #include <memory>
  34. #include <cstdarg>
  35. #include <vector>
  36. #include "alfstream.h"
  37. #include "alstring.h"
  38. #include "makemhr.h"
  39. #include "mysofa.h"
  40. // Constants for accessing the token reader's ring buffer.
  41. #define TR_RING_BITS (16)
  42. #define TR_RING_SIZE (1 << TR_RING_BITS)
  43. #define TR_RING_MASK (TR_RING_SIZE - 1)
  44. // The token reader's load interval in bytes.
  45. #define TR_LOAD_SIZE (TR_RING_SIZE >> 2)
  46. // Token reader state for parsing the data set definition.
  47. struct TokenReaderT {
  48. std::istream &mIStream;
  49. const char *mName{};
  50. uint mLine{};
  51. uint mColumn{};
  52. char mRing[TR_RING_SIZE]{};
  53. std::streamsize mIn{};
  54. std::streamsize mOut{};
  55. TokenReaderT(std::istream &istream) noexcept : mIStream{istream} { }
  56. TokenReaderT(const TokenReaderT&) = default;
  57. };
  58. // The maximum identifier length used when processing the data set
  59. // definition.
  60. #define MAX_IDENT_LEN (16)
  61. // The limits for the listener's head 'radius' in the data set definition.
  62. #define MIN_RADIUS (0.05)
  63. #define MAX_RADIUS (0.15)
  64. // The maximum number of channels that can be addressed for a WAVE file
  65. // source listed in the data set definition.
  66. #define MAX_WAVE_CHANNELS (65535)
  67. // The limits to the byte size for a binary source listed in the definition
  68. // file.
  69. #define MIN_BIN_SIZE (2)
  70. #define MAX_BIN_SIZE (4)
  71. // The minimum number of significant bits for binary sources listed in the
  72. // data set definition. The maximum is calculated from the byte size.
  73. #define MIN_BIN_BITS (16)
  74. // The limits to the number of significant bits for an ASCII source listed in
  75. // the data set definition.
  76. #define MIN_ASCII_BITS (16)
  77. #define MAX_ASCII_BITS (32)
  78. // The four-character-codes for RIFF/RIFX WAVE file chunks.
  79. #define FOURCC_RIFF (0x46464952) // 'RIFF'
  80. #define FOURCC_RIFX (0x58464952) // 'RIFX'
  81. #define FOURCC_WAVE (0x45564157) // 'WAVE'
  82. #define FOURCC_FMT (0x20746D66) // 'fmt '
  83. #define FOURCC_DATA (0x61746164) // 'data'
  84. #define FOURCC_LIST (0x5453494C) // 'LIST'
  85. #define FOURCC_WAVL (0x6C766177) // 'wavl'
  86. #define FOURCC_SLNT (0x746E6C73) // 'slnt'
  87. // The supported wave formats.
  88. #define WAVE_FORMAT_PCM (0x0001)
  89. #define WAVE_FORMAT_IEEE_FLOAT (0x0003)
  90. #define WAVE_FORMAT_EXTENSIBLE (0xFFFE)
  91. enum ByteOrderT {
  92. BO_NONE,
  93. BO_LITTLE,
  94. BO_BIG
  95. };
  96. // Source format for the references listed in the data set definition.
  97. enum SourceFormatT {
  98. SF_NONE,
  99. SF_ASCII, // ASCII text file.
  100. SF_BIN_LE, // Little-endian binary file.
  101. SF_BIN_BE, // Big-endian binary file.
  102. SF_WAVE, // RIFF/RIFX WAVE file.
  103. SF_SOFA // Spatially Oriented Format for Accoustics (SOFA) file.
  104. };
  105. // Element types for the references listed in the data set definition.
  106. enum ElementTypeT {
  107. ET_NONE,
  108. ET_INT, // Integer elements.
  109. ET_FP // Floating-point elements.
  110. };
  111. // Source reference state used when loading sources.
  112. struct SourceRefT {
  113. SourceFormatT mFormat;
  114. ElementTypeT mType;
  115. uint mSize;
  116. int mBits;
  117. uint mChannel;
  118. double mAzimuth;
  119. double mElevation;
  120. double mRadius;
  121. uint mSkip;
  122. uint mOffset;
  123. char mPath[MAX_PATH_LEN+1];
  124. };
  125. /* Whitespace is not significant. It can process tokens as identifiers, numbers
  126. * (integer and floating-point), strings, and operators. Strings must be
  127. * encapsulated by double-quotes and cannot span multiple lines.
  128. */
  129. // Setup the reader on the given file. The filename can be NULL if no error
  130. // output is desired.
  131. static void TrSetup(const char *startbytes, std::streamsize startbytecount, const char *filename,
  132. TokenReaderT *tr)
  133. {
  134. const char *name = nullptr;
  135. if(filename)
  136. {
  137. const char *slash = strrchr(filename, '/');
  138. if(slash)
  139. {
  140. const char *bslash = strrchr(slash+1, '\\');
  141. if(bslash) name = bslash+1;
  142. else name = slash+1;
  143. }
  144. else
  145. {
  146. const char *bslash = strrchr(filename, '\\');
  147. if(bslash) name = bslash+1;
  148. else name = filename;
  149. }
  150. }
  151. tr->mName = name;
  152. tr->mLine = 1;
  153. tr->mColumn = 1;
  154. tr->mIn = 0;
  155. tr->mOut = 0;
  156. if(startbytecount > 0)
  157. {
  158. std::copy_n(startbytes, startbytecount, std::begin(tr->mRing));
  159. tr->mIn += startbytecount;
  160. }
  161. }
  162. // Prime the reader's ring buffer, and return a result indicating that there
  163. // is text to process.
  164. static int TrLoad(TokenReaderT *tr)
  165. {
  166. std::istream &istream = tr->mIStream;
  167. std::streamsize toLoad{TR_RING_SIZE - static_cast<std::streamsize>(tr->mIn - tr->mOut)};
  168. if(toLoad >= TR_LOAD_SIZE && istream.good())
  169. {
  170. // Load TR_LOAD_SIZE (or less if at the end of the file) per read.
  171. toLoad = TR_LOAD_SIZE;
  172. std::streamsize in{tr->mIn&TR_RING_MASK};
  173. std::streamsize count{TR_RING_SIZE - in};
  174. if(count < toLoad)
  175. {
  176. istream.read(&tr->mRing[in], count);
  177. tr->mIn += istream.gcount();
  178. istream.read(&tr->mRing[0], toLoad-count);
  179. tr->mIn += istream.gcount();
  180. }
  181. else
  182. {
  183. istream.read(&tr->mRing[in], toLoad);
  184. tr->mIn += istream.gcount();
  185. }
  186. if(tr->mOut >= TR_RING_SIZE)
  187. {
  188. tr->mOut -= TR_RING_SIZE;
  189. tr->mIn -= TR_RING_SIZE;
  190. }
  191. }
  192. if(tr->mIn > tr->mOut)
  193. return 1;
  194. return 0;
  195. }
  196. // Error display routine. Only displays when the base name is not NULL.
  197. static void TrErrorVA(const TokenReaderT *tr, uint line, uint column, const char *format, va_list argPtr)
  198. {
  199. if(!tr->mName)
  200. return;
  201. fprintf(stderr, "\nError (%s:%u:%u): ", tr->mName, line, column);
  202. vfprintf(stderr, format, argPtr);
  203. }
  204. // Used to display an error at a saved line/column.
  205. static void TrErrorAt(const TokenReaderT *tr, uint line, uint column, const char *format, ...)
  206. {
  207. va_list argPtr;
  208. va_start(argPtr, format);
  209. TrErrorVA(tr, line, column, format, argPtr);
  210. va_end(argPtr);
  211. }
  212. // Used to display an error at the current line/column.
  213. static void TrError(const TokenReaderT *tr, const char *format, ...)
  214. {
  215. va_list argPtr;
  216. va_start(argPtr, format);
  217. TrErrorVA(tr, tr->mLine, tr->mColumn, format, argPtr);
  218. va_end(argPtr);
  219. }
  220. // Skips to the next line.
  221. static void TrSkipLine(TokenReaderT *tr)
  222. {
  223. char ch;
  224. while(TrLoad(tr))
  225. {
  226. ch = tr->mRing[tr->mOut&TR_RING_MASK];
  227. tr->mOut++;
  228. if(ch == '\n')
  229. {
  230. tr->mLine++;
  231. tr->mColumn = 1;
  232. break;
  233. }
  234. tr->mColumn ++;
  235. }
  236. }
  237. // Skips to the next token.
  238. static int TrSkipWhitespace(TokenReaderT *tr)
  239. {
  240. while(TrLoad(tr))
  241. {
  242. char ch{tr->mRing[tr->mOut&TR_RING_MASK]};
  243. if(isspace(ch))
  244. {
  245. tr->mOut++;
  246. if(ch == '\n')
  247. {
  248. tr->mLine++;
  249. tr->mColumn = 1;
  250. }
  251. else
  252. tr->mColumn++;
  253. }
  254. else if(ch == '#')
  255. TrSkipLine(tr);
  256. else
  257. return 1;
  258. }
  259. return 0;
  260. }
  261. // Get the line and/or column of the next token (or the end of input).
  262. static void TrIndication(TokenReaderT *tr, uint *line, uint *column)
  263. {
  264. TrSkipWhitespace(tr);
  265. if(line) *line = tr->mLine;
  266. if(column) *column = tr->mColumn;
  267. }
  268. // Checks to see if a token is (likely to be) an identifier. It does not
  269. // display any errors and will not proceed to the next token.
  270. static int TrIsIdent(TokenReaderT *tr)
  271. {
  272. if(!TrSkipWhitespace(tr))
  273. return 0;
  274. char ch{tr->mRing[tr->mOut&TR_RING_MASK]};
  275. return ch == '_' || isalpha(ch);
  276. }
  277. // Checks to see if a token is the given operator. It does not display any
  278. // errors and will not proceed to the next token.
  279. static int TrIsOperator(TokenReaderT *tr, const char *op)
  280. {
  281. std::streamsize out;
  282. size_t len;
  283. char ch;
  284. if(!TrSkipWhitespace(tr))
  285. return 0;
  286. out = tr->mOut;
  287. len = 0;
  288. while(op[len] != '\0' && out < tr->mIn)
  289. {
  290. ch = tr->mRing[out&TR_RING_MASK];
  291. if(ch != op[len]) break;
  292. len++;
  293. out++;
  294. }
  295. if(op[len] == '\0')
  296. return 1;
  297. return 0;
  298. }
  299. /* The TrRead*() routines obtain the value of a matching token type. They
  300. * display type, form, and boundary errors and will proceed to the next
  301. * token.
  302. */
  303. // Reads and validates an identifier token.
  304. static int TrReadIdent(TokenReaderT *tr, const uint maxLen, char *ident)
  305. {
  306. uint col, len;
  307. char ch;
  308. col = tr->mColumn;
  309. if(TrSkipWhitespace(tr))
  310. {
  311. col = tr->mColumn;
  312. ch = tr->mRing[tr->mOut&TR_RING_MASK];
  313. if(ch == '_' || isalpha(ch))
  314. {
  315. len = 0;
  316. do {
  317. if(len < maxLen)
  318. ident[len] = ch;
  319. len++;
  320. tr->mOut++;
  321. if(!TrLoad(tr))
  322. break;
  323. ch = tr->mRing[tr->mOut&TR_RING_MASK];
  324. } while(ch == '_' || isdigit(ch) || isalpha(ch));
  325. tr->mColumn += len;
  326. if(len < maxLen)
  327. {
  328. ident[len] = '\0';
  329. return 1;
  330. }
  331. TrErrorAt(tr, tr->mLine, col, "Identifier is too long.\n");
  332. return 0;
  333. }
  334. }
  335. TrErrorAt(tr, tr->mLine, col, "Expected an identifier.\n");
  336. return 0;
  337. }
  338. // Reads and validates (including bounds) an integer token.
  339. static int TrReadInt(TokenReaderT *tr, const int loBound, const int hiBound, int *value)
  340. {
  341. uint col, digis, len;
  342. char ch, temp[64+1];
  343. col = tr->mColumn;
  344. if(TrSkipWhitespace(tr))
  345. {
  346. col = tr->mColumn;
  347. len = 0;
  348. ch = tr->mRing[tr->mOut&TR_RING_MASK];
  349. if(ch == '+' || ch == '-')
  350. {
  351. temp[len] = ch;
  352. len++;
  353. tr->mOut++;
  354. }
  355. digis = 0;
  356. while(TrLoad(tr))
  357. {
  358. ch = tr->mRing[tr->mOut&TR_RING_MASK];
  359. if(!isdigit(ch)) break;
  360. if(len < 64)
  361. temp[len] = ch;
  362. len++;
  363. digis++;
  364. tr->mOut++;
  365. }
  366. tr->mColumn += len;
  367. if(digis > 0 && ch != '.' && !isalpha(ch))
  368. {
  369. if(len > 64)
  370. {
  371. TrErrorAt(tr, tr->mLine, col, "Integer is too long.");
  372. return 0;
  373. }
  374. temp[len] = '\0';
  375. *value = static_cast<int>(strtol(temp, nullptr, 10));
  376. if(*value < loBound || *value > hiBound)
  377. {
  378. TrErrorAt(tr, tr->mLine, col, "Expected a value from %d to %d.\n", loBound, hiBound);
  379. return 0;
  380. }
  381. return 1;
  382. }
  383. }
  384. TrErrorAt(tr, tr->mLine, col, "Expected an integer.\n");
  385. return 0;
  386. }
  387. // Reads and validates (including bounds) a float token.
  388. static int TrReadFloat(TokenReaderT *tr, const double loBound, const double hiBound, double *value)
  389. {
  390. uint col, digis, len;
  391. char ch, temp[64+1];
  392. col = tr->mColumn;
  393. if(TrSkipWhitespace(tr))
  394. {
  395. col = tr->mColumn;
  396. len = 0;
  397. ch = tr->mRing[tr->mOut&TR_RING_MASK];
  398. if(ch == '+' || ch == '-')
  399. {
  400. temp[len] = ch;
  401. len++;
  402. tr->mOut++;
  403. }
  404. digis = 0;
  405. while(TrLoad(tr))
  406. {
  407. ch = tr->mRing[tr->mOut&TR_RING_MASK];
  408. if(!isdigit(ch)) break;
  409. if(len < 64)
  410. temp[len] = ch;
  411. len++;
  412. digis++;
  413. tr->mOut++;
  414. }
  415. if(ch == '.')
  416. {
  417. if(len < 64)
  418. temp[len] = ch;
  419. len++;
  420. tr->mOut++;
  421. }
  422. while(TrLoad(tr))
  423. {
  424. ch = tr->mRing[tr->mOut&TR_RING_MASK];
  425. if(!isdigit(ch)) break;
  426. if(len < 64)
  427. temp[len] = ch;
  428. len++;
  429. digis++;
  430. tr->mOut++;
  431. }
  432. if(digis > 0)
  433. {
  434. if(ch == 'E' || ch == 'e')
  435. {
  436. if(len < 64)
  437. temp[len] = ch;
  438. len++;
  439. digis = 0;
  440. tr->mOut++;
  441. if(ch == '+' || ch == '-')
  442. {
  443. if(len < 64)
  444. temp[len] = ch;
  445. len++;
  446. tr->mOut++;
  447. }
  448. while(TrLoad(tr))
  449. {
  450. ch = tr->mRing[tr->mOut&TR_RING_MASK];
  451. if(!isdigit(ch)) break;
  452. if(len < 64)
  453. temp[len] = ch;
  454. len++;
  455. digis++;
  456. tr->mOut++;
  457. }
  458. }
  459. tr->mColumn += len;
  460. if(digis > 0 && ch != '.' && !isalpha(ch))
  461. {
  462. if(len > 64)
  463. {
  464. TrErrorAt(tr, tr->mLine, col, "Float is too long.");
  465. return 0;
  466. }
  467. temp[len] = '\0';
  468. *value = strtod(temp, nullptr);
  469. if(*value < loBound || *value > hiBound)
  470. {
  471. TrErrorAt(tr, tr->mLine, col, "Expected a value from %f to %f.\n", loBound, hiBound);
  472. return 0;
  473. }
  474. return 1;
  475. }
  476. }
  477. else
  478. tr->mColumn += len;
  479. }
  480. TrErrorAt(tr, tr->mLine, col, "Expected a float.\n");
  481. return 0;
  482. }
  483. // Reads and validates a string token.
  484. static int TrReadString(TokenReaderT *tr, const uint maxLen, char *text)
  485. {
  486. uint col, len;
  487. char ch;
  488. col = tr->mColumn;
  489. if(TrSkipWhitespace(tr))
  490. {
  491. col = tr->mColumn;
  492. ch = tr->mRing[tr->mOut&TR_RING_MASK];
  493. if(ch == '\"')
  494. {
  495. tr->mOut++;
  496. len = 0;
  497. while(TrLoad(tr))
  498. {
  499. ch = tr->mRing[tr->mOut&TR_RING_MASK];
  500. tr->mOut++;
  501. if(ch == '\"')
  502. break;
  503. if(ch == '\n')
  504. {
  505. TrErrorAt(tr, tr->mLine, col, "Unterminated string at end of line.\n");
  506. return 0;
  507. }
  508. if(len < maxLen)
  509. text[len] = ch;
  510. len++;
  511. }
  512. if(ch != '\"')
  513. {
  514. tr->mColumn += 1 + len;
  515. TrErrorAt(tr, tr->mLine, col, "Unterminated string at end of input.\n");
  516. return 0;
  517. }
  518. tr->mColumn += 2 + len;
  519. if(len > maxLen)
  520. {
  521. TrErrorAt(tr, tr->mLine, col, "String is too long.\n");
  522. return 0;
  523. }
  524. text[len] = '\0';
  525. return 1;
  526. }
  527. }
  528. TrErrorAt(tr, tr->mLine, col, "Expected a string.\n");
  529. return 0;
  530. }
  531. // Reads and validates the given operator.
  532. static int TrReadOperator(TokenReaderT *tr, const char *op)
  533. {
  534. uint col, len;
  535. char ch;
  536. col = tr->mColumn;
  537. if(TrSkipWhitespace(tr))
  538. {
  539. col = tr->mColumn;
  540. len = 0;
  541. while(op[len] != '\0' && TrLoad(tr))
  542. {
  543. ch = tr->mRing[tr->mOut&TR_RING_MASK];
  544. if(ch != op[len]) break;
  545. len++;
  546. tr->mOut++;
  547. }
  548. tr->mColumn += len;
  549. if(op[len] == '\0')
  550. return 1;
  551. }
  552. TrErrorAt(tr, tr->mLine, col, "Expected '%s' operator.\n", op);
  553. return 0;
  554. }
  555. /*************************
  556. *** File source input ***
  557. *************************/
  558. // Read a binary value of the specified byte order and byte size from a file,
  559. // storing it as a 32-bit unsigned integer.
  560. static int ReadBin4(std::istream &istream, const char *filename, const ByteOrderT order, const uint bytes, uint32_t *out)
  561. {
  562. uint8_t in[4];
  563. istream.read(reinterpret_cast<char*>(in), static_cast<int>(bytes));
  564. if(istream.gcount() != bytes)
  565. {
  566. fprintf(stderr, "\nError: Bad read from file '%s'.\n", filename);
  567. return 0;
  568. }
  569. uint32_t accum{0};
  570. switch(order)
  571. {
  572. case BO_LITTLE:
  573. for(uint i = 0;i < bytes;i++)
  574. accum = (accum<<8) | in[bytes - i - 1];
  575. break;
  576. case BO_BIG:
  577. for(uint i = 0;i < bytes;i++)
  578. accum = (accum<<8) | in[i];
  579. break;
  580. default:
  581. break;
  582. }
  583. *out = accum;
  584. return 1;
  585. }
  586. // Read a binary value of the specified byte order from a file, storing it as
  587. // a 64-bit unsigned integer.
  588. static int ReadBin8(std::istream &istream, const char *filename, const ByteOrderT order, uint64_t *out)
  589. {
  590. uint8_t in[8];
  591. uint64_t accum;
  592. uint i;
  593. istream.read(reinterpret_cast<char*>(in), 8);
  594. if(istream.gcount() != 8)
  595. {
  596. fprintf(stderr, "\nError: Bad read from file '%s'.\n", filename);
  597. return 0;
  598. }
  599. accum = 0;
  600. switch(order)
  601. {
  602. case BO_LITTLE:
  603. for(i = 0;i < 8;i++)
  604. accum = (accum<<8) | in[8 - i - 1];
  605. break;
  606. case BO_BIG:
  607. for(i = 0;i < 8;i++)
  608. accum = (accum<<8) | in[i];
  609. break;
  610. default:
  611. break;
  612. }
  613. *out = accum;
  614. return 1;
  615. }
  616. /* Read a binary value of the specified type, byte order, and byte size from
  617. * a file, converting it to a double. For integer types, the significant
  618. * bits are used to normalize the result. The sign of bits determines
  619. * whether they are padded toward the MSB (negative) or LSB (positive).
  620. * Floating-point types are not normalized.
  621. */
  622. static int ReadBinAsDouble(std::istream &istream, const char *filename, const ByteOrderT order,
  623. const ElementTypeT type, const uint bytes, const int bits, double *out)
  624. {
  625. union {
  626. uint32_t ui;
  627. int32_t i;
  628. float f;
  629. } v4;
  630. union {
  631. uint64_t ui;
  632. double f;
  633. } v8;
  634. *out = 0.0;
  635. if(bytes > 4)
  636. {
  637. if(!ReadBin8(istream, filename, order, &v8.ui))
  638. return 0;
  639. if(type == ET_FP)
  640. *out = v8.f;
  641. }
  642. else
  643. {
  644. if(!ReadBin4(istream, filename, order, bytes, &v4.ui))
  645. return 0;
  646. if(type == ET_FP)
  647. *out = v4.f;
  648. else
  649. {
  650. if(bits > 0)
  651. v4.ui >>= (8*bytes) - (static_cast<uint>(bits));
  652. else
  653. v4.ui &= (0xFFFFFFFF >> (32+bits));
  654. if(v4.ui&static_cast<uint>(1<<(std::abs(bits)-1)))
  655. v4.ui |= (0xFFFFFFFF << std::abs(bits));
  656. *out = v4.i / static_cast<double>(1<<(std::abs(bits)-1));
  657. }
  658. }
  659. return 1;
  660. }
  661. /* Read an ascii value of the specified type from a file, converting it to a
  662. * double. For integer types, the significant bits are used to normalize the
  663. * result. The sign of the bits should always be positive. This also skips
  664. * up to one separator character before the element itself.
  665. */
  666. static int ReadAsciiAsDouble(TokenReaderT *tr, const char *filename, const ElementTypeT type, const uint bits, double *out)
  667. {
  668. if(TrIsOperator(tr, ","))
  669. TrReadOperator(tr, ",");
  670. else if(TrIsOperator(tr, ":"))
  671. TrReadOperator(tr, ":");
  672. else if(TrIsOperator(tr, ";"))
  673. TrReadOperator(tr, ";");
  674. else if(TrIsOperator(tr, "|"))
  675. TrReadOperator(tr, "|");
  676. if(type == ET_FP)
  677. {
  678. if(!TrReadFloat(tr, -std::numeric_limits<double>::infinity(),
  679. std::numeric_limits<double>::infinity(), out))
  680. {
  681. fprintf(stderr, "\nError: Bad read from file '%s'.\n", filename);
  682. return 0;
  683. }
  684. }
  685. else
  686. {
  687. int v;
  688. if(!TrReadInt(tr, -(1<<(bits-1)), (1<<(bits-1))-1, &v))
  689. {
  690. fprintf(stderr, "\nError: Bad read from file '%s'.\n", filename);
  691. return 0;
  692. }
  693. *out = v / static_cast<double>((1<<(bits-1))-1);
  694. }
  695. return 1;
  696. }
  697. // Read the RIFF/RIFX WAVE format chunk from a file, validating it against
  698. // the source parameters and data set metrics.
  699. static int ReadWaveFormat(std::istream &istream, const ByteOrderT order, const uint hrirRate,
  700. SourceRefT *src)
  701. {
  702. uint32_t fourCC, chunkSize;
  703. uint32_t format, channels, rate, dummy, block, size, bits;
  704. chunkSize = 0;
  705. do {
  706. if(chunkSize > 0)
  707. istream.seekg(static_cast<int>(chunkSize), std::ios::cur);
  708. if(!ReadBin4(istream, src->mPath, BO_LITTLE, 4, &fourCC)
  709. || !ReadBin4(istream, src->mPath, order, 4, &chunkSize))
  710. return 0;
  711. } while(fourCC != FOURCC_FMT);
  712. if(!ReadBin4(istream, src->mPath, order, 2, &format)
  713. || !ReadBin4(istream, src->mPath, order, 2, &channels)
  714. || !ReadBin4(istream, src->mPath, order, 4, &rate)
  715. || !ReadBin4(istream, src->mPath, order, 4, &dummy)
  716. || !ReadBin4(istream, src->mPath, order, 2, &block))
  717. return 0;
  718. block /= channels;
  719. if(chunkSize > 14)
  720. {
  721. if(!ReadBin4(istream, src->mPath, order, 2, &size))
  722. return 0;
  723. size /= 8;
  724. if(block > size)
  725. size = block;
  726. }
  727. else
  728. size = block;
  729. if(format == WAVE_FORMAT_EXTENSIBLE)
  730. {
  731. istream.seekg(2, std::ios::cur);
  732. if(!ReadBin4(istream, src->mPath, order, 2, &bits))
  733. return 0;
  734. if(bits == 0)
  735. bits = 8 * size;
  736. istream.seekg(4, std::ios::cur);
  737. if(!ReadBin4(istream, src->mPath, order, 2, &format))
  738. return 0;
  739. istream.seekg(static_cast<int>(chunkSize - 26), std::ios::cur);
  740. }
  741. else
  742. {
  743. bits = 8 * size;
  744. if(chunkSize > 14)
  745. istream.seekg(static_cast<int>(chunkSize - 16), std::ios::cur);
  746. else
  747. istream.seekg(static_cast<int>(chunkSize - 14), std::ios::cur);
  748. }
  749. if(format != WAVE_FORMAT_PCM && format != WAVE_FORMAT_IEEE_FLOAT)
  750. {
  751. fprintf(stderr, "\nError: Unsupported WAVE format in file '%s'.\n", src->mPath);
  752. return 0;
  753. }
  754. if(src->mChannel >= channels)
  755. {
  756. fprintf(stderr, "\nError: Missing source channel in WAVE file '%s'.\n", src->mPath);
  757. return 0;
  758. }
  759. if(rate != hrirRate)
  760. {
  761. fprintf(stderr, "\nError: Mismatched source sample rate in WAVE file '%s'.\n", src->mPath);
  762. return 0;
  763. }
  764. if(format == WAVE_FORMAT_PCM)
  765. {
  766. if(size < 2 || size > 4)
  767. {
  768. fprintf(stderr, "\nError: Unsupported sample size in WAVE file '%s'.\n", src->mPath);
  769. return 0;
  770. }
  771. if(bits < 16 || bits > (8*size))
  772. {
  773. fprintf(stderr, "\nError: Bad significant bits in WAVE file '%s'.\n", src->mPath);
  774. return 0;
  775. }
  776. src->mType = ET_INT;
  777. }
  778. else
  779. {
  780. if(size != 4 && size != 8)
  781. {
  782. fprintf(stderr, "\nError: Unsupported sample size in WAVE file '%s'.\n", src->mPath);
  783. return 0;
  784. }
  785. src->mType = ET_FP;
  786. }
  787. src->mSize = size;
  788. src->mBits = static_cast<int>(bits);
  789. src->mSkip = channels;
  790. return 1;
  791. }
  792. // Read a RIFF/RIFX WAVE data chunk, converting all elements to doubles.
  793. static int ReadWaveData(std::istream &istream, const SourceRefT *src, const ByteOrderT order,
  794. const uint n, double *hrir)
  795. {
  796. int pre, post, skip;
  797. uint i;
  798. pre = static_cast<int>(src->mSize * src->mChannel);
  799. post = static_cast<int>(src->mSize * (src->mSkip - src->mChannel - 1));
  800. skip = 0;
  801. for(i = 0;i < n;i++)
  802. {
  803. skip += pre;
  804. if(skip > 0)
  805. istream.seekg(skip, std::ios::cur);
  806. if(!ReadBinAsDouble(istream, src->mPath, order, src->mType, src->mSize, src->mBits, &hrir[i]))
  807. return 0;
  808. skip = post;
  809. }
  810. if(skip > 0)
  811. istream.seekg(skip, std::ios::cur);
  812. return 1;
  813. }
  814. // Read the RIFF/RIFX WAVE list or data chunk, converting all elements to
  815. // doubles.
  816. static int ReadWaveList(std::istream &istream, const SourceRefT *src, const ByteOrderT order,
  817. const uint n, double *hrir)
  818. {
  819. uint32_t fourCC, chunkSize, listSize, count;
  820. uint block, skip, offset, i;
  821. double lastSample;
  822. for(;;)
  823. {
  824. if(!ReadBin4(istream, src->mPath, BO_LITTLE, 4, &fourCC)
  825. || !ReadBin4(istream, src->mPath, order, 4, &chunkSize))
  826. return 0;
  827. if(fourCC == FOURCC_DATA)
  828. {
  829. block = src->mSize * src->mSkip;
  830. count = chunkSize / block;
  831. if(count < (src->mOffset + n))
  832. {
  833. fprintf(stderr, "\nError: Bad read from file '%s'.\n", src->mPath);
  834. return 0;
  835. }
  836. istream.seekg(static_cast<long>(src->mOffset * block), std::ios::cur);
  837. if(!ReadWaveData(istream, src, order, n, &hrir[0]))
  838. return 0;
  839. return 1;
  840. }
  841. else if(fourCC == FOURCC_LIST)
  842. {
  843. if(!ReadBin4(istream, src->mPath, BO_LITTLE, 4, &fourCC))
  844. return 0;
  845. chunkSize -= 4;
  846. if(fourCC == FOURCC_WAVL)
  847. break;
  848. }
  849. if(chunkSize > 0)
  850. istream.seekg(static_cast<long>(chunkSize), std::ios::cur);
  851. }
  852. listSize = chunkSize;
  853. block = src->mSize * src->mSkip;
  854. skip = src->mOffset;
  855. offset = 0;
  856. lastSample = 0.0;
  857. while(offset < n && listSize > 8)
  858. {
  859. if(!ReadBin4(istream, src->mPath, BO_LITTLE, 4, &fourCC)
  860. || !ReadBin4(istream, src->mPath, order, 4, &chunkSize))
  861. return 0;
  862. listSize -= 8 + chunkSize;
  863. if(fourCC == FOURCC_DATA)
  864. {
  865. count = chunkSize / block;
  866. if(count > skip)
  867. {
  868. istream.seekg(static_cast<long>(skip * block), std::ios::cur);
  869. chunkSize -= skip * block;
  870. count -= skip;
  871. skip = 0;
  872. if(count > (n - offset))
  873. count = n - offset;
  874. if(!ReadWaveData(istream, src, order, count, &hrir[offset]))
  875. return 0;
  876. chunkSize -= count * block;
  877. offset += count;
  878. lastSample = hrir[offset - 1];
  879. }
  880. else
  881. {
  882. skip -= count;
  883. count = 0;
  884. }
  885. }
  886. else if(fourCC == FOURCC_SLNT)
  887. {
  888. if(!ReadBin4(istream, src->mPath, order, 4, &count))
  889. return 0;
  890. chunkSize -= 4;
  891. if(count > skip)
  892. {
  893. count -= skip;
  894. skip = 0;
  895. if(count > (n - offset))
  896. count = n - offset;
  897. for(i = 0; i < count; i ++)
  898. hrir[offset + i] = lastSample;
  899. offset += count;
  900. }
  901. else
  902. {
  903. skip -= count;
  904. count = 0;
  905. }
  906. }
  907. if(chunkSize > 0)
  908. istream.seekg(static_cast<long>(chunkSize), std::ios::cur);
  909. }
  910. if(offset < n)
  911. {
  912. fprintf(stderr, "\nError: Bad read from file '%s'.\n", src->mPath);
  913. return 0;
  914. }
  915. return 1;
  916. }
  917. // Load a source HRIR from an ASCII text file containing a list of elements
  918. // separated by whitespace or common list operators (',', ';', ':', '|').
  919. static int LoadAsciiSource(std::istream &istream, const SourceRefT *src,
  920. const uint n, double *hrir)
  921. {
  922. TokenReaderT tr{istream};
  923. uint i, j;
  924. double dummy;
  925. TrSetup(nullptr, 0, nullptr, &tr);
  926. for(i = 0;i < src->mOffset;i++)
  927. {
  928. if(!ReadAsciiAsDouble(&tr, src->mPath, src->mType, static_cast<uint>(src->mBits), &dummy))
  929. return 0;
  930. }
  931. for(i = 0;i < n;i++)
  932. {
  933. if(!ReadAsciiAsDouble(&tr, src->mPath, src->mType, static_cast<uint>(src->mBits), &hrir[i]))
  934. return 0;
  935. for(j = 0;j < src->mSkip;j++)
  936. {
  937. if(!ReadAsciiAsDouble(&tr, src->mPath, src->mType, static_cast<uint>(src->mBits), &dummy))
  938. return 0;
  939. }
  940. }
  941. return 1;
  942. }
  943. // Load a source HRIR from a binary file.
  944. static int LoadBinarySource(std::istream &istream, const SourceRefT *src, const ByteOrderT order,
  945. const uint n, double *hrir)
  946. {
  947. istream.seekg(static_cast<long>(src->mOffset), std::ios::beg);
  948. for(uint i{0};i < n;i++)
  949. {
  950. if(!ReadBinAsDouble(istream, src->mPath, order, src->mType, src->mSize, src->mBits, &hrir[i]))
  951. return 0;
  952. if(src->mSkip > 0)
  953. istream.seekg(static_cast<long>(src->mSkip), std::ios::cur);
  954. }
  955. return 1;
  956. }
  957. // Load a source HRIR from a RIFF/RIFX WAVE file.
  958. static int LoadWaveSource(std::istream &istream, SourceRefT *src, const uint hrirRate,
  959. const uint n, double *hrir)
  960. {
  961. uint32_t fourCC, dummy;
  962. ByteOrderT order;
  963. if(!ReadBin4(istream, src->mPath, BO_LITTLE, 4, &fourCC)
  964. || !ReadBin4(istream, src->mPath, BO_LITTLE, 4, &dummy))
  965. return 0;
  966. if(fourCC == FOURCC_RIFF)
  967. order = BO_LITTLE;
  968. else if(fourCC == FOURCC_RIFX)
  969. order = BO_BIG;
  970. else
  971. {
  972. fprintf(stderr, "\nError: No RIFF/RIFX chunk in file '%s'.\n", src->mPath);
  973. return 0;
  974. }
  975. if(!ReadBin4(istream, src->mPath, BO_LITTLE, 4, &fourCC))
  976. return 0;
  977. if(fourCC != FOURCC_WAVE)
  978. {
  979. fprintf(stderr, "\nError: Not a RIFF/RIFX WAVE file '%s'.\n", src->mPath);
  980. return 0;
  981. }
  982. if(!ReadWaveFormat(istream, order, hrirRate, src))
  983. return 0;
  984. if(!ReadWaveList(istream, src, order, n, hrir))
  985. return 0;
  986. return 1;
  987. }
  988. // Load a Spatially Oriented Format for Accoustics (SOFA) file.
  989. static MYSOFA_EASY* LoadSofaFile(SourceRefT *src, const uint hrirRate, const uint n)
  990. {
  991. struct MYSOFA_EASY *sofa{mysofa_cache_lookup(src->mPath, static_cast<float>(hrirRate))};
  992. if(sofa) return sofa;
  993. sofa = static_cast<MYSOFA_EASY*>(calloc(1, sizeof(*sofa)));
  994. if(sofa == nullptr)
  995. {
  996. fprintf(stderr, "\nError: Out of memory.\n");
  997. return nullptr;
  998. }
  999. sofa->lookup = nullptr;
  1000. sofa->neighborhood = nullptr;
  1001. int err;
  1002. sofa->hrtf = mysofa_load(src->mPath, &err);
  1003. if(!sofa->hrtf)
  1004. {
  1005. mysofa_close(sofa);
  1006. fprintf(stderr, "\nError: Could not load source file '%s'.\n", src->mPath);
  1007. return nullptr;
  1008. }
  1009. /* NOTE: Some valid SOFA files are failing this check. */
  1010. err = mysofa_check(sofa->hrtf);
  1011. if(err != MYSOFA_OK)
  1012. fprintf(stderr, "\nWarning: Supposedly malformed source file '%s'.\n", src->mPath);
  1013. if((src->mOffset + n) > sofa->hrtf->N)
  1014. {
  1015. mysofa_close(sofa);
  1016. fprintf(stderr, "\nError: Not enough samples in SOFA file '%s'.\n", src->mPath);
  1017. return nullptr;
  1018. }
  1019. if(src->mChannel >= sofa->hrtf->R)
  1020. {
  1021. mysofa_close(sofa);
  1022. fprintf(stderr, "\nError: Missing source receiver in SOFA file '%s'.\n", src->mPath);
  1023. return nullptr;
  1024. }
  1025. mysofa_tocartesian(sofa->hrtf);
  1026. sofa->lookup = mysofa_lookup_init(sofa->hrtf);
  1027. if(sofa->lookup == nullptr)
  1028. {
  1029. mysofa_close(sofa);
  1030. fprintf(stderr, "\nError: Out of memory.\n");
  1031. return nullptr;
  1032. }
  1033. return mysofa_cache_store(sofa, src->mPath, static_cast<float>(hrirRate));
  1034. }
  1035. // Copies the HRIR data from a particular SOFA measurement.
  1036. static void ExtractSofaHrir(const MYSOFA_EASY *sofa, const uint index, const uint channel, const uint offset, const uint n, double *hrir)
  1037. {
  1038. for(uint i{0u};i < n;i++)
  1039. hrir[i] = sofa->hrtf->DataIR.values[(index*sofa->hrtf->R + channel)*sofa->hrtf->N + offset + i];
  1040. }
  1041. // Load a source HRIR from a Spatially Oriented Format for Accoustics (SOFA)
  1042. // file.
  1043. static int LoadSofaSource(SourceRefT *src, const uint hrirRate, const uint n, double *hrir)
  1044. {
  1045. struct MYSOFA_EASY *sofa;
  1046. float target[3];
  1047. int nearest;
  1048. float *coords;
  1049. sofa = LoadSofaFile(src, hrirRate, n);
  1050. if(sofa == nullptr)
  1051. return 0;
  1052. /* NOTE: At some point it may be benficial or necessary to consider the
  1053. various coordinate systems, listener/source orientations, and
  1054. direciontal vectors defined in the SOFA file.
  1055. */
  1056. target[0] = static_cast<float>(src->mAzimuth);
  1057. target[1] = static_cast<float>(src->mElevation);
  1058. target[2] = static_cast<float>(src->mRadius);
  1059. mysofa_s2c(target);
  1060. nearest = mysofa_lookup(sofa->lookup, target);
  1061. if(nearest < 0)
  1062. {
  1063. fprintf(stderr, "\nError: Lookup failed in source file '%s'.\n", src->mPath);
  1064. return 0;
  1065. }
  1066. coords = &sofa->hrtf->SourcePosition.values[3 * nearest];
  1067. if(std::abs(coords[0] - target[0]) > 0.001 || std::abs(coords[1] - target[1]) > 0.001 || std::abs(coords[2] - target[2]) > 0.001)
  1068. {
  1069. fprintf(stderr, "\nError: No impulse response at coordinates (%.3fr, %.1fev, %.1faz) in file '%s'.\n", src->mRadius, src->mElevation, src->mAzimuth, src->mPath);
  1070. target[0] = coords[0];
  1071. target[1] = coords[1];
  1072. target[2] = coords[2];
  1073. mysofa_c2s(target);
  1074. fprintf(stderr, " Nearest candidate at (%.3fr, %.1fev, %.1faz).\n", target[2], target[1], target[0]);
  1075. return 0;
  1076. }
  1077. ExtractSofaHrir(sofa, static_cast<uint>(nearest), src->mChannel, src->mOffset, n, hrir);
  1078. return 1;
  1079. }
  1080. // Load a source HRIR from a supported file type.
  1081. static int LoadSource(SourceRefT *src, const uint hrirRate, const uint n, double *hrir)
  1082. {
  1083. std::unique_ptr<al::ifstream> istream;
  1084. if(src->mFormat != SF_SOFA)
  1085. {
  1086. if(src->mFormat == SF_ASCII)
  1087. istream.reset(new al::ifstream{src->mPath});
  1088. else
  1089. istream.reset(new al::ifstream{src->mPath, std::ios::binary});
  1090. if(!istream->good())
  1091. {
  1092. fprintf(stderr, "\nError: Could not open source file '%s'.\n", src->mPath);
  1093. return 0;
  1094. }
  1095. }
  1096. int result{0};
  1097. switch(src->mFormat)
  1098. {
  1099. case SF_ASCII:
  1100. result = LoadAsciiSource(*istream, src, n, hrir);
  1101. break;
  1102. case SF_BIN_LE:
  1103. result = LoadBinarySource(*istream, src, BO_LITTLE, n, hrir);
  1104. break;
  1105. case SF_BIN_BE:
  1106. result = LoadBinarySource(*istream, src, BO_BIG, n, hrir);
  1107. break;
  1108. case SF_WAVE:
  1109. result = LoadWaveSource(*istream, src, hrirRate, n, hrir);
  1110. break;
  1111. case SF_SOFA:
  1112. result = LoadSofaSource(src, hrirRate, n, hrir);
  1113. break;
  1114. case SF_NONE:
  1115. break;
  1116. }
  1117. return result;
  1118. }
  1119. // Match the channel type from a given identifier.
  1120. static ChannelTypeT MatchChannelType(const char *ident)
  1121. {
  1122. if(al::strcasecmp(ident, "mono") == 0)
  1123. return CT_MONO;
  1124. if(al::strcasecmp(ident, "stereo") == 0)
  1125. return CT_STEREO;
  1126. return CT_NONE;
  1127. }
  1128. // Process the data set definition to read and validate the data set metrics.
  1129. static int ProcessMetrics(TokenReaderT *tr, const uint fftSize, const uint truncSize, const ChannelModeT chanMode, HrirDataT *hData)
  1130. {
  1131. int hasRate = 0, hasType = 0, hasPoints = 0, hasRadius = 0;
  1132. int hasDistance = 0, hasAzimuths = 0;
  1133. char ident[MAX_IDENT_LEN+1];
  1134. uint line, col;
  1135. double fpVal;
  1136. uint points;
  1137. int intVal;
  1138. double distances[MAX_FD_COUNT];
  1139. uint fdCount = 0;
  1140. uint evCounts[MAX_FD_COUNT];
  1141. std::vector<uint> azCounts(MAX_FD_COUNT * MAX_EV_COUNT);
  1142. TrIndication(tr, &line, &col);
  1143. while(TrIsIdent(tr))
  1144. {
  1145. TrIndication(tr, &line, &col);
  1146. if(!TrReadIdent(tr, MAX_IDENT_LEN, ident))
  1147. return 0;
  1148. if(al::strcasecmp(ident, "rate") == 0)
  1149. {
  1150. if(hasRate)
  1151. {
  1152. TrErrorAt(tr, line, col, "Redefinition of 'rate'.\n");
  1153. return 0;
  1154. }
  1155. if(!TrReadOperator(tr, "="))
  1156. return 0;
  1157. if(!TrReadInt(tr, MIN_RATE, MAX_RATE, &intVal))
  1158. return 0;
  1159. hData->mIrRate = static_cast<uint>(intVal);
  1160. hasRate = 1;
  1161. }
  1162. else if(al::strcasecmp(ident, "type") == 0)
  1163. {
  1164. char type[MAX_IDENT_LEN+1];
  1165. if(hasType)
  1166. {
  1167. TrErrorAt(tr, line, col, "Redefinition of 'type'.\n");
  1168. return 0;
  1169. }
  1170. if(!TrReadOperator(tr, "="))
  1171. return 0;
  1172. if(!TrReadIdent(tr, MAX_IDENT_LEN, type))
  1173. return 0;
  1174. hData->mChannelType = MatchChannelType(type);
  1175. if(hData->mChannelType == CT_NONE)
  1176. {
  1177. TrErrorAt(tr, line, col, "Expected a channel type.\n");
  1178. return 0;
  1179. }
  1180. else if(hData->mChannelType == CT_STEREO)
  1181. {
  1182. if(chanMode == CM_ForceMono)
  1183. hData->mChannelType = CT_MONO;
  1184. }
  1185. hasType = 1;
  1186. }
  1187. else if(al::strcasecmp(ident, "points") == 0)
  1188. {
  1189. if(hasPoints)
  1190. {
  1191. TrErrorAt(tr, line, col, "Redefinition of 'points'.\n");
  1192. return 0;
  1193. }
  1194. if(!TrReadOperator(tr, "="))
  1195. return 0;
  1196. TrIndication(tr, &line, &col);
  1197. if(!TrReadInt(tr, MIN_POINTS, MAX_POINTS, &intVal))
  1198. return 0;
  1199. points = static_cast<uint>(intVal);
  1200. if(fftSize > 0 && points > fftSize)
  1201. {
  1202. TrErrorAt(tr, line, col, "Value exceeds the overridden FFT size.\n");
  1203. return 0;
  1204. }
  1205. if(points < truncSize)
  1206. {
  1207. TrErrorAt(tr, line, col, "Value is below the truncation size.\n");
  1208. return 0;
  1209. }
  1210. hData->mIrPoints = points;
  1211. hData->mFftSize = fftSize;
  1212. hData->mIrSize = 1 + (fftSize / 2);
  1213. if(points > hData->mIrSize)
  1214. hData->mIrSize = points;
  1215. hasPoints = 1;
  1216. }
  1217. else if(al::strcasecmp(ident, "radius") == 0)
  1218. {
  1219. if(hasRadius)
  1220. {
  1221. TrErrorAt(tr, line, col, "Redefinition of 'radius'.\n");
  1222. return 0;
  1223. }
  1224. if(!TrReadOperator(tr, "="))
  1225. return 0;
  1226. if(!TrReadFloat(tr, MIN_RADIUS, MAX_RADIUS, &fpVal))
  1227. return 0;
  1228. hData->mRadius = fpVal;
  1229. hasRadius = 1;
  1230. }
  1231. else if(al::strcasecmp(ident, "distance") == 0)
  1232. {
  1233. uint count = 0;
  1234. if(hasDistance)
  1235. {
  1236. TrErrorAt(tr, line, col, "Redefinition of 'distance'.\n");
  1237. return 0;
  1238. }
  1239. if(!TrReadOperator(tr, "="))
  1240. return 0;
  1241. for(;;)
  1242. {
  1243. if(!TrReadFloat(tr, MIN_DISTANCE, MAX_DISTANCE, &fpVal))
  1244. return 0;
  1245. if(count > 0 && fpVal <= distances[count - 1])
  1246. {
  1247. TrError(tr, "Distances are not ascending.\n");
  1248. return 0;
  1249. }
  1250. distances[count++] = fpVal;
  1251. if(!TrIsOperator(tr, ","))
  1252. break;
  1253. if(count >= MAX_FD_COUNT)
  1254. {
  1255. TrError(tr, "Exceeded the maximum of %d fields.\n", MAX_FD_COUNT);
  1256. return 0;
  1257. }
  1258. TrReadOperator(tr, ",");
  1259. }
  1260. if(fdCount != 0 && count != fdCount)
  1261. {
  1262. TrError(tr, "Did not match the specified number of %d fields.\n", fdCount);
  1263. return 0;
  1264. }
  1265. fdCount = count;
  1266. hasDistance = 1;
  1267. }
  1268. else if(al::strcasecmp(ident, "azimuths") == 0)
  1269. {
  1270. uint count = 0;
  1271. if(hasAzimuths)
  1272. {
  1273. TrErrorAt(tr, line, col, "Redefinition of 'azimuths'.\n");
  1274. return 0;
  1275. }
  1276. if(!TrReadOperator(tr, "="))
  1277. return 0;
  1278. evCounts[0] = 0;
  1279. for(;;)
  1280. {
  1281. if(!TrReadInt(tr, MIN_AZ_COUNT, MAX_AZ_COUNT, &intVal))
  1282. return 0;
  1283. azCounts[(count * MAX_EV_COUNT) + evCounts[count]++] = static_cast<uint>(intVal);
  1284. if(TrIsOperator(tr, ","))
  1285. {
  1286. if(evCounts[count] >= MAX_EV_COUNT)
  1287. {
  1288. TrError(tr, "Exceeded the maximum of %d elevations.\n", MAX_EV_COUNT);
  1289. return 0;
  1290. }
  1291. TrReadOperator(tr, ",");
  1292. }
  1293. else
  1294. {
  1295. if(evCounts[count] < MIN_EV_COUNT)
  1296. {
  1297. TrErrorAt(tr, line, col, "Did not reach the minimum of %d azimuth counts.\n", MIN_EV_COUNT);
  1298. return 0;
  1299. }
  1300. if(azCounts[count * MAX_EV_COUNT] != 1 || azCounts[(count * MAX_EV_COUNT) + evCounts[count] - 1] != 1)
  1301. {
  1302. TrError(tr, "Poles are not singular for field %d.\n", count - 1);
  1303. return 0;
  1304. }
  1305. count++;
  1306. if(!TrIsOperator(tr, ";"))
  1307. break;
  1308. if(count >= MAX_FD_COUNT)
  1309. {
  1310. TrError(tr, "Exceeded the maximum number of %d fields.\n", MAX_FD_COUNT);
  1311. return 0;
  1312. }
  1313. evCounts[count] = 0;
  1314. TrReadOperator(tr, ";");
  1315. }
  1316. }
  1317. if(fdCount != 0 && count != fdCount)
  1318. {
  1319. TrError(tr, "Did not match the specified number of %d fields.\n", fdCount);
  1320. return 0;
  1321. }
  1322. fdCount = count;
  1323. hasAzimuths = 1;
  1324. }
  1325. else
  1326. {
  1327. TrErrorAt(tr, line, col, "Expected a metric name.\n");
  1328. return 0;
  1329. }
  1330. TrSkipWhitespace(tr);
  1331. }
  1332. if(!(hasRate && hasPoints && hasRadius && hasDistance && hasAzimuths))
  1333. {
  1334. TrErrorAt(tr, line, col, "Expected a metric name.\n");
  1335. return 0;
  1336. }
  1337. if(distances[0] < hData->mRadius)
  1338. {
  1339. TrError(tr, "Distance cannot start below head radius.\n");
  1340. return 0;
  1341. }
  1342. if(hData->mChannelType == CT_NONE)
  1343. hData->mChannelType = CT_MONO;
  1344. if(!PrepareHrirData(fdCount, distances, evCounts, azCounts.data(), hData))
  1345. {
  1346. fprintf(stderr, "Error: Out of memory.\n");
  1347. exit(-1);
  1348. }
  1349. return 1;
  1350. }
  1351. // Parse an index triplet from the data set definition.
  1352. static int ReadIndexTriplet(TokenReaderT *tr, const HrirDataT *hData, uint *fi, uint *ei, uint *ai)
  1353. {
  1354. int intVal;
  1355. if(hData->mFdCount > 1)
  1356. {
  1357. if(!TrReadInt(tr, 0, static_cast<int>(hData->mFdCount) - 1, &intVal))
  1358. return 0;
  1359. *fi = static_cast<uint>(intVal);
  1360. if(!TrReadOperator(tr, ","))
  1361. return 0;
  1362. }
  1363. else
  1364. {
  1365. *fi = 0;
  1366. }
  1367. if(!TrReadInt(tr, 0, static_cast<int>(hData->mFds[*fi].mEvCount) - 1, &intVal))
  1368. return 0;
  1369. *ei = static_cast<uint>(intVal);
  1370. if(!TrReadOperator(tr, ","))
  1371. return 0;
  1372. if(!TrReadInt(tr, 0, static_cast<int>(hData->mFds[*fi].mEvs[*ei].mAzCount) - 1, &intVal))
  1373. return 0;
  1374. *ai = static_cast<uint>(intVal);
  1375. return 1;
  1376. }
  1377. // Match the source format from a given identifier.
  1378. static SourceFormatT MatchSourceFormat(const char *ident)
  1379. {
  1380. if(al::strcasecmp(ident, "ascii") == 0)
  1381. return SF_ASCII;
  1382. if(al::strcasecmp(ident, "bin_le") == 0)
  1383. return SF_BIN_LE;
  1384. if(al::strcasecmp(ident, "bin_be") == 0)
  1385. return SF_BIN_BE;
  1386. if(al::strcasecmp(ident, "wave") == 0)
  1387. return SF_WAVE;
  1388. if(al::strcasecmp(ident, "sofa") == 0)
  1389. return SF_SOFA;
  1390. return SF_NONE;
  1391. }
  1392. // Match the source element type from a given identifier.
  1393. static ElementTypeT MatchElementType(const char *ident)
  1394. {
  1395. if(al::strcasecmp(ident, "int") == 0)
  1396. return ET_INT;
  1397. if(al::strcasecmp(ident, "fp") == 0)
  1398. return ET_FP;
  1399. return ET_NONE;
  1400. }
  1401. // Parse and validate a source reference from the data set definition.
  1402. static int ReadSourceRef(TokenReaderT *tr, SourceRefT *src)
  1403. {
  1404. char ident[MAX_IDENT_LEN+1];
  1405. uint line, col;
  1406. double fpVal;
  1407. int intVal;
  1408. TrIndication(tr, &line, &col);
  1409. if(!TrReadIdent(tr, MAX_IDENT_LEN, ident))
  1410. return 0;
  1411. src->mFormat = MatchSourceFormat(ident);
  1412. if(src->mFormat == SF_NONE)
  1413. {
  1414. TrErrorAt(tr, line, col, "Expected a source format.\n");
  1415. return 0;
  1416. }
  1417. if(!TrReadOperator(tr, "("))
  1418. return 0;
  1419. if(src->mFormat == SF_SOFA)
  1420. {
  1421. if(!TrReadFloat(tr, MIN_DISTANCE, MAX_DISTANCE, &fpVal))
  1422. return 0;
  1423. src->mRadius = fpVal;
  1424. if(!TrReadOperator(tr, ","))
  1425. return 0;
  1426. if(!TrReadFloat(tr, -90.0, 90.0, &fpVal))
  1427. return 0;
  1428. src->mElevation = fpVal;
  1429. if(!TrReadOperator(tr, ","))
  1430. return 0;
  1431. if(!TrReadFloat(tr, -360.0, 360.0, &fpVal))
  1432. return 0;
  1433. src->mAzimuth = fpVal;
  1434. if(!TrReadOperator(tr, ":"))
  1435. return 0;
  1436. if(!TrReadInt(tr, 0, MAX_WAVE_CHANNELS, &intVal))
  1437. return 0;
  1438. src->mType = ET_NONE;
  1439. src->mSize = 0;
  1440. src->mBits = 0;
  1441. src->mChannel = static_cast<uint>(intVal);
  1442. src->mSkip = 0;
  1443. }
  1444. else if(src->mFormat == SF_WAVE)
  1445. {
  1446. if(!TrReadInt(tr, 0, MAX_WAVE_CHANNELS, &intVal))
  1447. return 0;
  1448. src->mType = ET_NONE;
  1449. src->mSize = 0;
  1450. src->mBits = 0;
  1451. src->mChannel = static_cast<uint>(intVal);
  1452. src->mSkip = 0;
  1453. }
  1454. else
  1455. {
  1456. TrIndication(tr, &line, &col);
  1457. if(!TrReadIdent(tr, MAX_IDENT_LEN, ident))
  1458. return 0;
  1459. src->mType = MatchElementType(ident);
  1460. if(src->mType == ET_NONE)
  1461. {
  1462. TrErrorAt(tr, line, col, "Expected a source element type.\n");
  1463. return 0;
  1464. }
  1465. if(src->mFormat == SF_BIN_LE || src->mFormat == SF_BIN_BE)
  1466. {
  1467. if(!TrReadOperator(tr, ","))
  1468. return 0;
  1469. if(src->mType == ET_INT)
  1470. {
  1471. if(!TrReadInt(tr, MIN_BIN_SIZE, MAX_BIN_SIZE, &intVal))
  1472. return 0;
  1473. src->mSize = static_cast<uint>(intVal);
  1474. if(!TrIsOperator(tr, ","))
  1475. src->mBits = static_cast<int>(8*src->mSize);
  1476. else
  1477. {
  1478. TrReadOperator(tr, ",");
  1479. TrIndication(tr, &line, &col);
  1480. if(!TrReadInt(tr, -2147483647-1, 2147483647, &intVal))
  1481. return 0;
  1482. if(std::abs(intVal) < MIN_BIN_BITS || static_cast<uint>(std::abs(intVal)) > (8*src->mSize))
  1483. {
  1484. TrErrorAt(tr, line, col, "Expected a value of (+/-) %d to %d.\n", MIN_BIN_BITS, 8*src->mSize);
  1485. return 0;
  1486. }
  1487. src->mBits = intVal;
  1488. }
  1489. }
  1490. else
  1491. {
  1492. TrIndication(tr, &line, &col);
  1493. if(!TrReadInt(tr, -2147483647-1, 2147483647, &intVal))
  1494. return 0;
  1495. if(intVal != 4 && intVal != 8)
  1496. {
  1497. TrErrorAt(tr, line, col, "Expected a value of 4 or 8.\n");
  1498. return 0;
  1499. }
  1500. src->mSize = static_cast<uint>(intVal);
  1501. src->mBits = 0;
  1502. }
  1503. }
  1504. else if(src->mFormat == SF_ASCII && src->mType == ET_INT)
  1505. {
  1506. if(!TrReadOperator(tr, ","))
  1507. return 0;
  1508. if(!TrReadInt(tr, MIN_ASCII_BITS, MAX_ASCII_BITS, &intVal))
  1509. return 0;
  1510. src->mSize = 0;
  1511. src->mBits = intVal;
  1512. }
  1513. else
  1514. {
  1515. src->mSize = 0;
  1516. src->mBits = 0;
  1517. }
  1518. if(!TrIsOperator(tr, ";"))
  1519. src->mSkip = 0;
  1520. else
  1521. {
  1522. TrReadOperator(tr, ";");
  1523. if(!TrReadInt(tr, 0, 0x7FFFFFFF, &intVal))
  1524. return 0;
  1525. src->mSkip = static_cast<uint>(intVal);
  1526. }
  1527. }
  1528. if(!TrReadOperator(tr, ")"))
  1529. return 0;
  1530. if(TrIsOperator(tr, "@"))
  1531. {
  1532. TrReadOperator(tr, "@");
  1533. if(!TrReadInt(tr, 0, 0x7FFFFFFF, &intVal))
  1534. return 0;
  1535. src->mOffset = static_cast<uint>(intVal);
  1536. }
  1537. else
  1538. src->mOffset = 0;
  1539. if(!TrReadOperator(tr, ":"))
  1540. return 0;
  1541. if(!TrReadString(tr, MAX_PATH_LEN, src->mPath))
  1542. return 0;
  1543. return 1;
  1544. }
  1545. // Parse and validate a SOFA source reference from the data set definition.
  1546. static int ReadSofaRef(TokenReaderT *tr, SourceRefT *src)
  1547. {
  1548. char ident[MAX_IDENT_LEN+1];
  1549. uint line, col;
  1550. int intVal;
  1551. TrIndication(tr, &line, &col);
  1552. if(!TrReadIdent(tr, MAX_IDENT_LEN, ident))
  1553. return 0;
  1554. src->mFormat = MatchSourceFormat(ident);
  1555. if(src->mFormat != SF_SOFA)
  1556. {
  1557. TrErrorAt(tr, line, col, "Expected the SOFA source format.\n");
  1558. return 0;
  1559. }
  1560. src->mType = ET_NONE;
  1561. src->mSize = 0;
  1562. src->mBits = 0;
  1563. src->mChannel = 0;
  1564. src->mSkip = 0;
  1565. if(TrIsOperator(tr, "@"))
  1566. {
  1567. TrReadOperator(tr, "@");
  1568. if(!TrReadInt(tr, 0, 0x7FFFFFFF, &intVal))
  1569. return 0;
  1570. src->mOffset = static_cast<uint>(intVal);
  1571. }
  1572. else
  1573. src->mOffset = 0;
  1574. if(!TrReadOperator(tr, ":"))
  1575. return 0;
  1576. if(!TrReadString(tr, MAX_PATH_LEN, src->mPath))
  1577. return 0;
  1578. return 1;
  1579. }
  1580. // Match the target ear (index) from a given identifier.
  1581. static int MatchTargetEar(const char *ident)
  1582. {
  1583. if(al::strcasecmp(ident, "left") == 0)
  1584. return 0;
  1585. if(al::strcasecmp(ident, "right") == 0)
  1586. return 1;
  1587. return -1;
  1588. }
  1589. // Calculate the onset time of an HRIR and average it with any existing
  1590. // timing for its field, elevation, azimuth, and ear.
  1591. static double AverageHrirOnset(const uint rate, const uint n, const double *hrir, const double f, const double onset)
  1592. {
  1593. std::vector<double> upsampled(10 * n);
  1594. {
  1595. PPhaseResampler rs;
  1596. rs.init(rate, 10 * rate);
  1597. rs.process(n, hrir, 10 * n, upsampled.data());
  1598. }
  1599. auto abs_lt = [](const double &lhs, const double &rhs) -> bool
  1600. { return std::abs(lhs) < std::abs(rhs); };
  1601. auto iter = std::max_element(upsampled.cbegin(), upsampled.cend(), abs_lt);
  1602. return Lerp(onset, static_cast<double>(std::distance(upsampled.cbegin(), iter))/(10*rate), f);
  1603. }
  1604. // Calculate the magnitude response of an HRIR and average it with any
  1605. // existing responses for its field, elevation, azimuth, and ear.
  1606. static void AverageHrirMagnitude(const uint points, const uint n, const double *hrir, const double f, double *mag)
  1607. {
  1608. uint m = 1 + (n / 2), i;
  1609. std::vector<complex_d> h(n);
  1610. std::vector<double> r(n);
  1611. for(i = 0;i < points;i++)
  1612. h[i] = complex_d{hrir[i], 0.0};
  1613. for(;i < n;i++)
  1614. h[i] = complex_d{0.0, 0.0};
  1615. FftForward(n, h.data());
  1616. MagnitudeResponse(n, h.data(), r.data());
  1617. for(i = 0;i < m;i++)
  1618. mag[i] = Lerp(mag[i], r[i], f);
  1619. }
  1620. // Process the list of sources in the data set definition.
  1621. static int ProcessSources(TokenReaderT *tr, HrirDataT *hData)
  1622. {
  1623. uint channels = (hData->mChannelType == CT_STEREO) ? 2 : 1;
  1624. hData->mHrirsBase.resize(channels * hData->mIrCount * hData->mIrSize);
  1625. double *hrirs = hData->mHrirsBase.data();
  1626. std::vector<double> hrir(hData->mIrPoints);
  1627. uint line, col, fi, ei, ai;
  1628. int count;
  1629. printf("Loading sources...");
  1630. fflush(stdout);
  1631. count = 0;
  1632. while(TrIsOperator(tr, "["))
  1633. {
  1634. double factor[2]{ 1.0, 1.0 };
  1635. TrIndication(tr, &line, &col);
  1636. TrReadOperator(tr, "[");
  1637. if(TrIsOperator(tr, "*"))
  1638. {
  1639. SourceRefT src;
  1640. struct MYSOFA_EASY *sofa;
  1641. uint si;
  1642. TrReadOperator(tr, "*");
  1643. if(!TrReadOperator(tr, "]") || !TrReadOperator(tr, "="))
  1644. return 0;
  1645. TrIndication(tr, &line, &col);
  1646. if(!ReadSofaRef(tr, &src))
  1647. return 0;
  1648. if(hData->mChannelType == CT_STEREO)
  1649. {
  1650. char type[MAX_IDENT_LEN+1];
  1651. ChannelTypeT channelType;
  1652. if(!TrReadIdent(tr, MAX_IDENT_LEN, type))
  1653. return 0;
  1654. channelType = MatchChannelType(type);
  1655. switch(channelType)
  1656. {
  1657. case CT_NONE:
  1658. TrErrorAt(tr, line, col, "Expected a channel type.\n");
  1659. return 0;
  1660. case CT_MONO:
  1661. src.mChannel = 0;
  1662. break;
  1663. case CT_STEREO:
  1664. src.mChannel = 1;
  1665. break;
  1666. }
  1667. }
  1668. else
  1669. {
  1670. char type[MAX_IDENT_LEN+1];
  1671. ChannelTypeT channelType;
  1672. if(!TrReadIdent(tr, MAX_IDENT_LEN, type))
  1673. return 0;
  1674. channelType = MatchChannelType(type);
  1675. if(channelType != CT_MONO)
  1676. {
  1677. TrErrorAt(tr, line, col, "Expected a mono channel type.\n");
  1678. return 0;
  1679. }
  1680. src.mChannel = 0;
  1681. }
  1682. sofa = LoadSofaFile(&src, hData->mIrRate, hData->mIrPoints);
  1683. if(!sofa) return 0;
  1684. for(si = 0;si < sofa->hrtf->M;si++)
  1685. {
  1686. printf("\rLoading sources... %d of %d", si+1, sofa->hrtf->M);
  1687. fflush(stdout);
  1688. float aer[3] = {
  1689. sofa->hrtf->SourcePosition.values[3*si],
  1690. sofa->hrtf->SourcePosition.values[3*si + 1],
  1691. sofa->hrtf->SourcePosition.values[3*si + 2]
  1692. };
  1693. mysofa_c2s(aer);
  1694. if(std::fabs(aer[1]) >= 89.999f)
  1695. aer[0] = 0.0f;
  1696. else
  1697. aer[0] = std::fmod(360.0f - aer[0], 360.0f);
  1698. for(fi = 0;fi < hData->mFdCount;fi++)
  1699. {
  1700. double delta = aer[2] - hData->mFds[fi].mDistance;
  1701. if(std::abs(delta) < 0.001) break;
  1702. }
  1703. if(fi >= hData->mFdCount)
  1704. continue;
  1705. double ef{(90.0 + aer[1]) / 180.0 * (hData->mFds[fi].mEvCount - 1)};
  1706. ei = static_cast<uint>(std::round(ef));
  1707. ef = (ef - ei) * 180.0 / (hData->mFds[fi].mEvCount - 1);
  1708. if(std::abs(ef) >= 0.1)
  1709. continue;
  1710. double af{aer[0] / 360.0 * hData->mFds[fi].mEvs[ei].mAzCount};
  1711. ai = static_cast<uint>(std::round(af));
  1712. af = (af - ai) * 360.0 / hData->mFds[fi].mEvs[ei].mAzCount;
  1713. ai = ai % hData->mFds[fi].mEvs[ei].mAzCount;
  1714. if(std::abs(af) >= 0.1)
  1715. continue;
  1716. HrirAzT *azd = &hData->mFds[fi].mEvs[ei].mAzs[ai];
  1717. if(azd->mIrs[0] != nullptr)
  1718. {
  1719. TrErrorAt(tr, line, col, "Redefinition of source [ %d, %d, %d ].\n", fi, ei, ai);
  1720. return 0;
  1721. }
  1722. ExtractSofaHrir(sofa, si, 0, src.mOffset, hData->mIrPoints, hrir.data());
  1723. azd->mIrs[0] = &hrirs[hData->mIrSize * azd->mIndex];
  1724. azd->mDelays[0] = AverageHrirOnset(hData->mIrRate, hData->mIrPoints, hrir.data(), 1.0, azd->mDelays[0]);
  1725. AverageHrirMagnitude(hData->mIrPoints, hData->mFftSize, hrir.data(), 1.0, azd->mIrs[0]);
  1726. if(src.mChannel == 1)
  1727. {
  1728. ExtractSofaHrir(sofa, si, 1, src.mOffset, hData->mIrPoints, hrir.data());
  1729. azd->mIrs[1] = &hrirs[hData->mIrSize * (hData->mIrCount + azd->mIndex)];
  1730. azd->mDelays[1] = AverageHrirOnset(hData->mIrRate, hData->mIrPoints, hrir.data(), 1.0, azd->mDelays[1]);
  1731. AverageHrirMagnitude(hData->mIrPoints, hData->mFftSize, hrir.data(), 1.0, azd->mIrs[1]);
  1732. }
  1733. // TODO: Since some SOFA files contain minimum phase HRIRs,
  1734. // it would be beneficial to check for per-measurement delays
  1735. // (when available) to reconstruct the HRTDs.
  1736. }
  1737. continue;
  1738. }
  1739. if(!ReadIndexTriplet(tr, hData, &fi, &ei, &ai))
  1740. return 0;
  1741. if(!TrReadOperator(tr, "]"))
  1742. return 0;
  1743. HrirAzT *azd = &hData->mFds[fi].mEvs[ei].mAzs[ai];
  1744. if(azd->mIrs[0] != nullptr)
  1745. {
  1746. TrErrorAt(tr, line, col, "Redefinition of source.\n");
  1747. return 0;
  1748. }
  1749. if(!TrReadOperator(tr, "="))
  1750. return 0;
  1751. for(;;)
  1752. {
  1753. SourceRefT src;
  1754. if(!ReadSourceRef(tr, &src))
  1755. return 0;
  1756. // TODO: Would be nice to display 'x of y files', but that would
  1757. // require preparing the source refs first to get a total count
  1758. // before loading them.
  1759. ++count;
  1760. printf("\rLoading sources... %d file%s", count, (count==1)?"":"s");
  1761. fflush(stdout);
  1762. if(!LoadSource(&src, hData->mIrRate, hData->mIrPoints, hrir.data()))
  1763. return 0;
  1764. uint ti{0};
  1765. if(hData->mChannelType == CT_STEREO)
  1766. {
  1767. char ident[MAX_IDENT_LEN+1];
  1768. if(!TrReadIdent(tr, MAX_IDENT_LEN, ident))
  1769. return 0;
  1770. ti = static_cast<uint>(MatchTargetEar(ident));
  1771. if(static_cast<int>(ti) < 0)
  1772. {
  1773. TrErrorAt(tr, line, col, "Expected a target ear.\n");
  1774. return 0;
  1775. }
  1776. }
  1777. azd->mIrs[ti] = &hrirs[hData->mIrSize * (ti * hData->mIrCount + azd->mIndex)];
  1778. azd->mDelays[ti] = AverageHrirOnset(hData->mIrRate, hData->mIrPoints, hrir.data(), 1.0 / factor[ti], azd->mDelays[ti]);
  1779. AverageHrirMagnitude(hData->mIrPoints, hData->mFftSize, hrir.data(), 1.0 / factor[ti], azd->mIrs[ti]);
  1780. factor[ti] += 1.0;
  1781. if(!TrIsOperator(tr, "+"))
  1782. break;
  1783. TrReadOperator(tr, "+");
  1784. }
  1785. if(hData->mChannelType == CT_STEREO)
  1786. {
  1787. if(azd->mIrs[0] == nullptr)
  1788. {
  1789. TrErrorAt(tr, line, col, "Missing left ear source reference(s).\n");
  1790. return 0;
  1791. }
  1792. else if(azd->mIrs[1] == nullptr)
  1793. {
  1794. TrErrorAt(tr, line, col, "Missing right ear source reference(s).\n");
  1795. return 0;
  1796. }
  1797. }
  1798. }
  1799. printf("\n");
  1800. for(fi = 0;fi < hData->mFdCount;fi++)
  1801. {
  1802. for(ei = 0;ei < hData->mFds[fi].mEvCount;ei++)
  1803. {
  1804. for(ai = 0;ai < hData->mFds[fi].mEvs[ei].mAzCount;ai++)
  1805. {
  1806. HrirAzT *azd = &hData->mFds[fi].mEvs[ei].mAzs[ai];
  1807. if(azd->mIrs[0] != nullptr)
  1808. break;
  1809. }
  1810. if(ai < hData->mFds[fi].mEvs[ei].mAzCount)
  1811. break;
  1812. }
  1813. if(ei >= hData->mFds[fi].mEvCount)
  1814. {
  1815. TrError(tr, "Missing source references [ %d, *, * ].\n", fi);
  1816. return 0;
  1817. }
  1818. hData->mFds[fi].mEvStart = ei;
  1819. for(;ei < hData->mFds[fi].mEvCount;ei++)
  1820. {
  1821. for(ai = 0;ai < hData->mFds[fi].mEvs[ei].mAzCount;ai++)
  1822. {
  1823. HrirAzT *azd = &hData->mFds[fi].mEvs[ei].mAzs[ai];
  1824. if(azd->mIrs[0] == nullptr)
  1825. {
  1826. TrError(tr, "Missing source reference [ %d, %d, %d ].\n", fi, ei, ai);
  1827. return 0;
  1828. }
  1829. }
  1830. }
  1831. }
  1832. for(uint ti{0};ti < channels;ti++)
  1833. {
  1834. for(fi = 0;fi < hData->mFdCount;fi++)
  1835. {
  1836. for(ei = 0;ei < hData->mFds[fi].mEvCount;ei++)
  1837. {
  1838. for(ai = 0;ai < hData->mFds[fi].mEvs[ei].mAzCount;ai++)
  1839. {
  1840. HrirAzT *azd = &hData->mFds[fi].mEvs[ei].mAzs[ai];
  1841. azd->mIrs[ti] = &hrirs[hData->mIrSize * (ti * hData->mIrCount + azd->mIndex)];
  1842. }
  1843. }
  1844. }
  1845. }
  1846. if(!TrLoad(tr))
  1847. {
  1848. mysofa_cache_release_all();
  1849. return 1;
  1850. }
  1851. TrError(tr, "Errant data at end of source list.\n");
  1852. mysofa_cache_release_all();
  1853. return 0;
  1854. }
  1855. bool LoadDefInput(std::istream &istream, const char *startbytes, std::streamsize startbytecount,
  1856. const char *filename, const uint fftSize, const uint truncSize, const ChannelModeT chanMode,
  1857. HrirDataT *hData)
  1858. {
  1859. TokenReaderT tr{istream};
  1860. TrSetup(startbytes, startbytecount, filename, &tr);
  1861. if(!ProcessMetrics(&tr, fftSize, truncSize, chanMode, hData)
  1862. || !ProcessSources(&tr, hData))
  1863. return false;
  1864. return true;
  1865. }