loaddef.cpp 63 KB

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