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

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