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

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