b3ReadWavFile.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. //b3ReadWavFile is implemented based on code from the STK toolkit
  2. //See https://github.com/thestk/stk
  3. //Some improvement: the ticking data (b3WavTicker) is separate from wav file,
  4. //This makes it possoble to play a single wav multiple times at the same time
  5. #include "b3ReadWavFile.h"
  6. #include "b3SwapUtils.h"
  7. const unsigned long B3_SINT8 = 0x1;
  8. const unsigned long B3_SINT16 = 0x2;
  9. const unsigned long B3_SINT24 = 0x4;
  10. const unsigned long B3_SINT32 = 0x8;
  11. const unsigned long B3_FLOAT32 = 0x10;
  12. const unsigned long B3_FLOAT64 = 0x20;
  13. b3ReadWavFile::b3ReadWavFile()
  14. {
  15. fd_ = 0;
  16. m_machineIsLittleEndian = b3MachineIsLittleEndian();
  17. }
  18. b3ReadWavFile::~b3ReadWavFile()
  19. {
  20. if (fd_)
  21. fclose(fd_);
  22. }
  23. void b3ReadWavFile::normalize(double peak)
  24. {
  25. int i;
  26. double max = 0.0;
  27. for (i = 0; i < m_frames.size(); i++)
  28. {
  29. if (fabs(m_frames[i]) > max)
  30. max = (double)fabs((double)m_frames[i]);
  31. }
  32. if (max > 0.0)
  33. {
  34. max = 1.0 / max;
  35. max *= peak;
  36. for (i = 0; i < m_frames.size(); i++)
  37. m_frames[i] *= max;
  38. }
  39. }
  40. double b3ReadWavFile::interpolate(double frame, unsigned int channel) const
  41. {
  42. int iIndex = (int)frame; // integer part of index
  43. double output, alpha = frame - (double)iIndex; // fractional part of index
  44. iIndex = iIndex * channels_ + channel;
  45. output = m_frames[iIndex];
  46. if (alpha > 0.0)
  47. output += (alpha * (m_frames[iIndex + channels_] - output));
  48. return output;
  49. }
  50. double b3ReadWavFile::tick(unsigned int channel, b3WavTicker *ticker)
  51. {
  52. if (ticker->finished_) return 0.0;
  53. if (ticker->time_ < 0.0 || ticker->time_ > (double)(this->m_numFrames - 1.0))
  54. {
  55. for (int i = 0; i < ticker->lastFrame_.size(); i++) ticker->lastFrame_[i] = 0.0;
  56. ticker->finished_ = true;
  57. return 0.0;
  58. }
  59. double tyme = ticker->time_;
  60. bool interpolate_ = true; //for now
  61. if (interpolate_)
  62. {
  63. for (int i = 0; i < ticker->lastFrame_.size(); i++)
  64. ticker->lastFrame_[i] = interpolate(tyme, i);
  65. }
  66. // Increment time, which can be negative.
  67. ticker->time_ += ticker->rate_;
  68. return ticker->lastFrame_[channel];
  69. }
  70. void b3ReadWavFile::resize()
  71. {
  72. m_frames.resize(channels_ * m_numFrames);
  73. }
  74. b3WavTicker b3ReadWavFile::createWavTicker(double sampleRate)
  75. {
  76. b3WavTicker ticker;
  77. ticker.lastFrame_.resize(this->channels_);
  78. ticker.time_ = 0;
  79. ticker.finished_ = false;
  80. ticker.rate_ = fileDataRate_ / sampleRate;
  81. return ticker;
  82. }
  83. bool b3ReadWavFile::getWavInfo(const char *fileName)
  84. {
  85. fd_ = fopen(fileName, "rb");
  86. if (fd_ == 0)
  87. return false;
  88. char header[12];
  89. if (fread(&header, 4, 3, fd_) != 3)
  90. return false;
  91. bool res = false;
  92. if (!strncmp(header, "RIFF", 4) &&
  93. !strncmp(&header[8], "WAVE", 4))
  94. res = true;
  95. //getWavInfo( fileName );
  96. // Find "format" chunk ... it must come before the "data" chunk.
  97. char id[4];
  98. int chunkSize;
  99. if (fread(&id, 4, 1, fd_) != 1)
  100. return false;
  101. while (strncmp(id, "fmt ", 4))
  102. {
  103. if (fread(&chunkSize, 4, 1, fd_) != 1)
  104. return false;
  105. if (!m_machineIsLittleEndian)
  106. {
  107. b3Swap32((unsigned char *)&chunkSize);
  108. }
  109. if (fseek(fd_, chunkSize, SEEK_CUR) == -1)
  110. return false;
  111. if (fread(&id, 4, 1, fd_) != 1)
  112. return false;
  113. }
  114. // Check that the data is not compressed.
  115. unsigned short format_tag;
  116. if (fread(&chunkSize, 4, 1, fd_) != 1)
  117. return false; // Read fmt chunk size.
  118. if (fread(&format_tag, 2, 1, fd_) != 1)
  119. return false;
  120. if (!m_machineIsLittleEndian)
  121. {
  122. b3Swap16((unsigned char *)&format_tag);
  123. b3Swap32((unsigned char *)&chunkSize);
  124. }
  125. if (format_tag == 0xFFFE)
  126. { // WAVE_FORMAT_EXTENSIBLE
  127. dataOffset_ = ftell(fd_);
  128. if (fseek(fd_, 14, SEEK_CUR) == -1)
  129. return false;
  130. unsigned short extSize;
  131. if (fread(&extSize, 2, 1, fd_) != 1)
  132. return false;
  133. if (!m_machineIsLittleEndian)
  134. {
  135. b3Swap16((unsigned char *)&extSize);
  136. }
  137. if (extSize == 0)
  138. return false;
  139. if (fseek(fd_, 6, SEEK_CUR) == -1)
  140. return false;
  141. if (fread(&format_tag, 2, 1, fd_) != 1)
  142. return false;
  143. if (!m_machineIsLittleEndian)
  144. {
  145. b3Swap16((unsigned char *)&format_tag);
  146. }
  147. if (fseek(fd_, dataOffset_, SEEK_SET) == -1)
  148. return false;
  149. }
  150. if (format_tag != 1 && format_tag != 3)
  151. { // PCM = 1, FLOAT = 3
  152. // oStream_ << "FileRead: "<< fileName << " contains an unsupported data format type (" << format_tag << ").";
  153. return false;
  154. }
  155. // Get number of channels from the header.
  156. short int temp;
  157. if (fread(&temp, 2, 1, fd_) != 1)
  158. return false;
  159. if (!m_machineIsLittleEndian)
  160. {
  161. b3Swap16((unsigned char *)&temp);
  162. }
  163. channels_ = (unsigned int)temp;
  164. // Get file sample rate from the header.
  165. int srate;
  166. if (fread(&srate, 4, 1, fd_) != 1)
  167. return false;
  168. if (!m_machineIsLittleEndian)
  169. {
  170. b3Swap32((unsigned char *)&srate);
  171. }
  172. fileDataRate_ = (double)srate;
  173. // Determine the data type.
  174. dataType_ = 0;
  175. if (fseek(fd_, 6, SEEK_CUR) == -1)
  176. return false; // Locate bits_per_sample info.
  177. if (fread(&temp, 2, 1, fd_) != 1)
  178. return false;
  179. if (!m_machineIsLittleEndian)
  180. {
  181. b3Swap16((unsigned char *)&temp);
  182. }
  183. if (format_tag == 1)
  184. {
  185. if (temp == 8)
  186. dataType_ = B3_SINT8;
  187. else if (temp == 16)
  188. dataType_ = B3_SINT16;
  189. else if (temp == 24)
  190. dataType_ = B3_SINT24;
  191. else if (temp == 32)
  192. dataType_ = B3_SINT32;
  193. }
  194. else if (format_tag == 3)
  195. {
  196. if (temp == 32)
  197. dataType_ = B3_FLOAT32;
  198. else if (temp == 64)
  199. dataType_ = B3_FLOAT64;
  200. }
  201. if (dataType_ == 0)
  202. {
  203. // oStream_ << "FileRead: " << temp << " bits per sample with data format " << format_tag << " are not supported (" << fileName << ").";
  204. return false;
  205. }
  206. // Jump over any remaining part of the "fmt" chunk.
  207. if (fseek(fd_, chunkSize - 16, SEEK_CUR) == -1)
  208. return false;
  209. // Find "data" chunk ... it must come after the "fmt" chunk.
  210. if (fread(&id, 4, 1, fd_) != 1)
  211. return false;
  212. while (strncmp(id, "data", 4))
  213. {
  214. if (fread(&chunkSize, 4, 1, fd_) != 1)
  215. return false;
  216. if (!m_machineIsLittleEndian)
  217. {
  218. b3Swap32((unsigned char *)&chunkSize);
  219. }
  220. chunkSize += chunkSize % 2; // chunk sizes must be even
  221. if (fseek(fd_, chunkSize, SEEK_CUR) == -1)
  222. return false;
  223. if (fread(&id, 4, 1, fd_) != 1)
  224. return false;
  225. }
  226. // Get length of data from the header.
  227. int bytes;
  228. if (fread(&bytes, 4, 1, fd_) != 1)
  229. return false;
  230. if (!m_machineIsLittleEndian)
  231. {
  232. b3Swap32((unsigned char *)&bytes);
  233. }
  234. m_numFrames = bytes / temp / channels_; // sample frames
  235. m_numFrames *= 8; // sample frames
  236. dataOffset_ = ftell(fd_);
  237. byteswap_ = false;
  238. if (!m_machineIsLittleEndian)
  239. {
  240. byteswap_ = true;
  241. }
  242. wavFile_ = true;
  243. return true;
  244. }
  245. bool b3ReadWavFile::read(unsigned long startFrame, bool doNormalize)
  246. {
  247. // Make sure we have an open file.
  248. if (fd_ == 0)
  249. {
  250. // oStream_ << "FileRead::read: a file is not open!";
  251. // Stk::handleError( StkError::WARNING ); return;
  252. return false;
  253. }
  254. // Check the m_frames size.
  255. unsigned long nFrames = this->m_numFrames; //m_frames.frames();
  256. if (nFrames == 0)
  257. {
  258. // oStream_ << "FileRead::read: StkFrames m_frames size is zero ... no data read!";
  259. // Stk::handleError( StkError::WARNING );
  260. return false;
  261. }
  262. if (startFrame >= m_numFrames)
  263. {
  264. return false;
  265. //oStream_ << "FileRead::read: startFrame argument is greater than or equal to the file size!";
  266. //Stk::handleError( StkError::FUNCTION_ARGUMENT );
  267. }
  268. // Check for file end.
  269. if (startFrame + nFrames > m_numFrames)
  270. nFrames = m_numFrames - startFrame;
  271. long i, nSamples = (long)(nFrames * channels_);
  272. unsigned long offset = startFrame * channels_;
  273. // Read samples into StkFrames data m_frames.
  274. if (dataType_ == B3_SINT16)
  275. {
  276. signed short int *buf = (signed short int *)&m_frames[0];
  277. if (fseek(fd_, dataOffset_ + (offset * 2), SEEK_SET) == -1)
  278. return false;
  279. if (fread(buf, nSamples * 2, 1, fd_) != 1)
  280. return false;
  281. if (byteswap_)
  282. {
  283. signed short int *ptr = buf;
  284. for (i = nSamples - 1; i >= 0; i--)
  285. b3Swap16((unsigned char *)ptr++);
  286. }
  287. if (doNormalize)
  288. {
  289. double gain = 1.0 / 32768.0;
  290. for (i = nSamples - 1; i >= 0; i--)
  291. m_frames[i] = buf[i] * gain;
  292. }
  293. else
  294. {
  295. for (i = nSamples - 1; i >= 0; i--)
  296. m_frames[i] = buf[i];
  297. }
  298. }
  299. else if (dataType_ == B3_SINT32)
  300. {
  301. int *buf = (int *)&m_frames[0];
  302. if (fseek(fd_, dataOffset_ + (offset * 4), SEEK_SET) == -1)
  303. return false;
  304. if (fread(buf, nSamples * 4, 1, fd_) != 1)
  305. return false;
  306. if (byteswap_)
  307. {
  308. int *ptr = buf;
  309. for (i = nSamples - 1; i >= 0; i--)
  310. b3Swap32((unsigned char *)ptr++);
  311. }
  312. if (doNormalize)
  313. {
  314. double gain = 1.0 / 2147483648.0;
  315. for (i = nSamples - 1; i >= 0; i--)
  316. m_frames[i] = buf[i] * gain;
  317. }
  318. else
  319. {
  320. for (i = nSamples - 1; i >= 0; i--)
  321. m_frames[i] = buf[i];
  322. }
  323. }
  324. else if (dataType_ == B3_FLOAT32)
  325. {
  326. float *buf = (float *)&m_frames[0];
  327. if (fseek(fd_, dataOffset_ + (offset * 4), SEEK_SET) == -1)
  328. return false;
  329. if (fread(buf, nSamples * 4, 1, fd_) != 1)
  330. return false;
  331. if (byteswap_)
  332. {
  333. float *ptr = buf;
  334. for (i = nSamples - 1; i >= 0; i--)
  335. b3Swap32((unsigned char *)ptr++);
  336. }
  337. for (i = nSamples - 1; i >= 0; i--)
  338. m_frames[i] = buf[i];
  339. }
  340. else if (dataType_ == B3_FLOAT64)
  341. {
  342. double *buf = (double *)&m_frames[0];
  343. if (fseek(fd_, dataOffset_ + (offset * 8), SEEK_SET) == -1)
  344. return false;
  345. if (fread(buf, nSamples * 8, 1, fd_) != 1)
  346. return false;
  347. if (byteswap_)
  348. {
  349. double *ptr = buf;
  350. for (i = nSamples - 1; i >= 0; i--)
  351. b3Swap64((unsigned char *)ptr++);
  352. }
  353. for (i = nSamples - 1; i >= 0; i--)
  354. m_frames[i] = buf[i];
  355. }
  356. else if (dataType_ == B3_SINT8 && wavFile_)
  357. { // 8-bit WAV data is unsigned!
  358. unsigned char *buf = (unsigned char *)&m_frames[0];
  359. if (fseek(fd_, dataOffset_ + offset, SEEK_SET) == -1)
  360. return false;
  361. if (fread(buf, nSamples, 1, fd_) != 1)
  362. return false;
  363. if (doNormalize)
  364. {
  365. double gain = 1.0 / 128.0;
  366. for (i = nSamples - 1; i >= 0; i--)
  367. m_frames[i] = (buf[i] - 128) * gain;
  368. }
  369. else
  370. {
  371. for (i = nSamples - 1; i >= 0; i--)
  372. m_frames[i] = buf[i] - 128.0;
  373. }
  374. }
  375. else if (dataType_ == B3_SINT8)
  376. { // signed 8-bit data
  377. char *buf = (char *)&m_frames[0];
  378. if (fseek(fd_, dataOffset_ + offset, SEEK_SET) == -1)
  379. return false;
  380. if (fread(buf, nSamples, 1, fd_) != 1)
  381. return false;
  382. if (doNormalize)
  383. {
  384. double gain = 1.0 / 128.0;
  385. for (i = nSamples - 1; i >= 0; i--)
  386. m_frames[i] = buf[i] * gain;
  387. }
  388. else
  389. {
  390. for (i = nSamples - 1; i >= 0; i--)
  391. m_frames[i] = buf[i];
  392. }
  393. }
  394. else if (dataType_ == B3_SINT24)
  395. {
  396. // 24-bit values are harder to import efficiently since there is
  397. // no native 24-bit type. The following routine works but is much
  398. // less efficient than that used for the other data types.
  399. int temp;
  400. unsigned char *ptr = (unsigned char *)&temp;
  401. double gain = 1.0 / 2147483648.0;
  402. if (fseek(fd_, dataOffset_ + (offset * 3), SEEK_SET) == -1)
  403. return false;
  404. for (i = 0; i < nSamples; i++)
  405. {
  406. if (m_machineIsLittleEndian)
  407. {
  408. if (byteswap_)
  409. {
  410. if (fread(ptr, 3, 1, fd_) != 1)
  411. return false;
  412. temp &= 0x00ffffff;
  413. b3Swap32((unsigned char *)ptr);
  414. }
  415. else
  416. {
  417. if (fread(ptr + 1, 3, 1, fd_) != 1)
  418. return false;
  419. temp &= 0xffffff00;
  420. }
  421. }
  422. else
  423. {
  424. if (byteswap_)
  425. {
  426. if (fread(ptr + 1, 3, 1, fd_) != 1)
  427. return false;
  428. temp &= 0xffffff00;
  429. b3Swap32((unsigned char *)ptr);
  430. }
  431. else
  432. {
  433. if (fread(ptr, 3, 1, fd_) != 1)
  434. return false;
  435. temp &= 0x00ffffff;
  436. }
  437. }
  438. if (doNormalize)
  439. {
  440. m_frames[i] = (double)temp * gain; // "gain" also includes 1 / 256 factor.
  441. }
  442. else
  443. m_frames[i] = (double)temp / 256; // right shift without affecting the sign bit
  444. }
  445. }
  446. // m_frames.setDataRate( fileDataRate_ );
  447. return true;
  448. // error:
  449. // oStream_ << "FileRead: Error reading file data.";
  450. // handleError( StkError::FILE_ERROR);
  451. }