loaddef.cpp 64 KB

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