BsWaveDecoder.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsWaveDecoder.h"
  4. #include "FileSystem/BsDataStream.h"
  5. namespace bs
  6. {
  7. #define WAVE_FORMAT_PCM 0x0001
  8. #define WAVE_FORMAT_EXTENDED 0xFFFE
  9. WaveDecoder::WaveDecoder()
  10. :mDataOffset(0), mBytesPerSample(0)
  11. { }
  12. bool WaveDecoder::isValid(const SPtr<DataStream>& stream, UINT32 offset)
  13. {
  14. stream->seek(offset);
  15. INT8 header[MAIN_CHUNK_SIZE];
  16. if (stream->read(header, sizeof(header)) < (sizeof(header)))
  17. return false;
  18. return (header[0] == 'R') && (header[1] == 'I') && (header[2] == 'F') && (header[3] == 'F')
  19. && (header[8] == 'W') && (header[9] == 'A') && (header[10] == 'V') && (header[11] == 'E');
  20. }
  21. bool WaveDecoder::open(const SPtr<DataStream>& stream, AudioDataInfo& info, UINT32 offset)
  22. {
  23. if (stream == nullptr)
  24. return false;
  25. mStream = stream;
  26. mStream->seek(offset + MAIN_CHUNK_SIZE);
  27. if (!parseHeader(info))
  28. {
  29. LOGERR("Provided file is not a valid WAVE file.");
  30. return false;
  31. }
  32. return true;
  33. }
  34. void WaveDecoder::seek(UINT32 offset)
  35. {
  36. mStream->seek(mDataOffset + offset * mBytesPerSample);
  37. }
  38. UINT32 WaveDecoder::read(UINT8* samples, UINT32 numSamples)
  39. {
  40. UINT32 numRead = (UINT32)mStream->read(samples, numSamples * mBytesPerSample);
  41. if(mBytesPerSample == 1) // 8-bit samples are stored as unsigned, but engine convention is to store all bit depths as signed
  42. {
  43. for(UINT32 i = 0; i < numRead; i++)
  44. {
  45. INT8 val = samples[i] - 128;
  46. samples[i] = *((UINT8*)&val);
  47. }
  48. }
  49. return numRead;
  50. }
  51. bool WaveDecoder::parseHeader(AudioDataInfo& info)
  52. {
  53. bool foundData = false;
  54. while (!foundData)
  55. {
  56. // Get sub-chunk ID and size
  57. UINT8 subChunkId[4];
  58. if (mStream->read(subChunkId, sizeof(subChunkId)) != sizeof(subChunkId))
  59. return false;
  60. UINT32 subChunkSize = 0;
  61. if (mStream->read(&subChunkSize, sizeof(subChunkSize)) != sizeof(subChunkSize))
  62. return false;
  63. // FMT chunk
  64. if (subChunkId[0] == 'f' && subChunkId[1] == 'm' && subChunkId[2] == 't' && subChunkId[3] == ' ')
  65. {
  66. UINT16 format = 0;
  67. if (mStream->read(&format, sizeof(format)) != sizeof(format))
  68. return false;
  69. if (format != WAVE_FORMAT_PCM && format != WAVE_FORMAT_EXTENDED)
  70. {
  71. LOGWRN("Wave file doesn't contain raw PCM data. Not supported.");
  72. return false;
  73. }
  74. UINT16 numChannels = 0;
  75. if (mStream->read(&numChannels, sizeof(numChannels)) != sizeof(numChannels))
  76. return false;
  77. UINT32 sampleRate = 0;
  78. if (mStream->read(&sampleRate, sizeof(sampleRate)) != sizeof(sampleRate))
  79. return false;
  80. UINT32 byteRate = 0;
  81. if (mStream->read(&byteRate, sizeof(byteRate)) != sizeof(byteRate))
  82. return false;
  83. UINT16 blockAlign = 0;
  84. if (mStream->read(&blockAlign, sizeof(blockAlign)) != sizeof(blockAlign))
  85. return false;
  86. UINT16 bitDepth = 0;
  87. if (mStream->read(&bitDepth, sizeof(bitDepth)) != sizeof(bitDepth))
  88. return false;
  89. info.numChannels = numChannels;
  90. info.sampleRate = sampleRate;
  91. info.bitDepth = bitDepth;
  92. if (bitDepth != 8 && bitDepth != 16 && bitDepth != 24 && bitDepth != 32)
  93. {
  94. LOGERR("Unsupported number of bits per sample: " + toString(bitDepth));
  95. return false;
  96. }
  97. // Read extension data, and get the actual format
  98. if(format == WAVE_FORMAT_EXTENDED)
  99. {
  100. UINT16 extensionSize = 0;
  101. if (mStream->read(&extensionSize, sizeof(extensionSize)) != sizeof(extensionSize))
  102. return false;
  103. if(extensionSize != 22)
  104. {
  105. LOGWRN("Wave file doesn't contain raw PCM data. Not supported.");
  106. return false;
  107. }
  108. UINT16 validBitDepth = 0;
  109. if (mStream->read(&validBitDepth, sizeof(validBitDepth)) != sizeof(validBitDepth))
  110. return false;
  111. UINT32 channelMask = 0;
  112. if (mStream->read(&channelMask, sizeof(channelMask)) != sizeof(channelMask))
  113. return false;
  114. UINT8 subFormat[16];
  115. if (mStream->read(subFormat, sizeof(subFormat)) != sizeof(subFormat))
  116. return false;
  117. memcpy(&format, subFormat, sizeof(format));
  118. if (format != WAVE_FORMAT_PCM)
  119. {
  120. LOGWRN("Wave file doesn't contain raw PCM data. Not supported.");
  121. return false;
  122. }
  123. }
  124. mBytesPerSample = bitDepth / 8;
  125. }
  126. // DATA chunk
  127. else if (subChunkId[0] == 'd' && subChunkId[1] == 'a' && subChunkId[2] == 't' && subChunkId[3] == 'a')
  128. {
  129. info.numSamples = subChunkSize / mBytesPerSample;
  130. mDataOffset = (UINT32)mStream->tell();
  131. foundData = true;
  132. }
  133. // Unsupported chunk type
  134. else
  135. {
  136. mStream->skip(subChunkSize);
  137. if (mStream->eof())
  138. return false;
  139. }
  140. }
  141. return true;
  142. }
  143. }