AudioBuffer.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. #include "Base.h"
  2. #include "AudioBuffer.h"
  3. #include "FileSystem.h"
  4. namespace gameplay
  5. {
  6. // Audio buffer cache
  7. static std::vector<AudioBuffer*> __buffers;
  8. AudioBuffer::AudioBuffer(const char* path, ALuint buffer)
  9. : _filePath(path), _alBuffer(buffer)
  10. {
  11. }
  12. AudioBuffer::~AudioBuffer()
  13. {
  14. if (_alBuffer)
  15. {
  16. alDeleteBuffers(1, &_alBuffer);
  17. _alBuffer = 0;
  18. }
  19. }
  20. AudioBuffer* AudioBuffer::create(const char* path)
  21. {
  22. assert(path);
  23. // Search the cache for a stream from this file.
  24. unsigned int bufferCount = (unsigned int)__buffers.size();
  25. AudioBuffer* buffer = NULL;
  26. for (unsigned int i = 0; i < bufferCount; i++)
  27. {
  28. buffer = __buffers[i];
  29. if (buffer->_filePath.compare(path) == 0)
  30. {
  31. buffer->addRef();
  32. return buffer;
  33. }
  34. }
  35. ALuint alBuffer;
  36. ALCenum al_error;
  37. // Load audio data into a buffer.
  38. alGenBuffers(1, &alBuffer);
  39. al_error = alGetError();
  40. if (al_error != AL_NO_ERROR)
  41. {
  42. LOG_ERROR_VARG("AudioBuffer alGenBuffers AL error: %d", al_error);
  43. alDeleteBuffers(1, &alBuffer);
  44. return NULL;
  45. }
  46. // Load sound file.
  47. FILE* file = FileSystem::openFile(path, "rb");
  48. if (!file)
  49. {
  50. LOG_ERROR_VARG("Invalid audio buffer file: %s", path);
  51. goto cleanup;
  52. }
  53. // Read the file header
  54. char header[12];
  55. if (fread(header, 1, 12, file) != 12)
  56. {
  57. LOG_ERROR_VARG("Invalid audio buffer file: %s", path);
  58. goto cleanup;
  59. }
  60. // Check the file format
  61. if (memcmp(header, "RIFF", 4) == 0)
  62. {
  63. if (!AudioBuffer::loadWav(file, alBuffer))
  64. {
  65. LOG_ERROR_VARG("Invalid wave file: %s", path);
  66. goto cleanup;
  67. }
  68. }
  69. else if (memcmp(header, "OggS", 4) == 0)
  70. {
  71. if (!AudioBuffer::loadOgg(file, alBuffer))
  72. {
  73. LOG_ERROR_VARG("Invalid ogg file: %s", path);
  74. goto cleanup;
  75. }
  76. }
  77. else
  78. {
  79. LOG_ERROR_VARG("Unsupported audio file: %s", path);
  80. }
  81. fclose(file);
  82. buffer = new AudioBuffer(path, alBuffer);
  83. // Add the buffer to the cache.
  84. __buffers.push_back(buffer);
  85. return buffer;
  86. cleanup:
  87. if (file)
  88. fclose(file);
  89. if (alBuffer)
  90. alDeleteBuffers(1, &alBuffer);
  91. return NULL;
  92. }
  93. bool AudioBuffer::loadWav(FILE* file, ALuint buffer)
  94. {
  95. unsigned char stream[12];
  96. // Verify the wave fmt magic value meaning format.
  97. if (fread(stream, 1, 8, file) != 8 || memcmp(stream, "fmt ", 4) != 0 )
  98. return false;
  99. // Check for a valid pcm format.
  100. if (fread(stream, 1, 2, file) != 2 || stream[1] != 0 || stream[0] != 1)
  101. {
  102. LOG_ERROR("Unsupported audio file, not PCM format.");
  103. return false;
  104. }
  105. // Get the channel count (16-bit little-endian)
  106. int channels;
  107. if (fread(stream, 1, 2, file) != 2)
  108. return false;
  109. channels = stream[1]<<8;
  110. channels |= stream[0];
  111. // Get the sample frequency (32-bit little-endian)
  112. ALuint frequency;
  113. if (fread(stream, 1, 4, file) != 4)
  114. return false;
  115. frequency = stream[3]<<24;
  116. frequency |= stream[2]<<16;
  117. frequency |= stream[1]<<8;
  118. frequency |= stream[0];
  119. // The next 6 bytes hold the block size and bytes-per-second.
  120. // We don't need that info, so just read and ignore it.
  121. // We could use this later if we need to know the duration.
  122. if (fread(stream, 1, 6, file) != 6)
  123. return false;
  124. // Get the bit depth (16-bit little-endian)
  125. int bits;
  126. if (fread(stream, 1, 2, file) != 2)
  127. return false;
  128. bits = stream[1]<<8;
  129. bits |= stream[0];
  130. // Now convert the given channel count and bit depth into an OpenAL format.
  131. ALuint format = 0;
  132. if (bits == 8)
  133. {
  134. if (channels == 1)
  135. format = AL_FORMAT_MONO8;
  136. else if (channels == 2)
  137. format = AL_FORMAT_STEREO8;
  138. }
  139. else if (bits == 16)
  140. {
  141. if (channels == 1)
  142. format = AL_FORMAT_MONO16;
  143. else if (channels == 2)
  144. format = AL_FORMAT_STEREO16;
  145. }
  146. else
  147. {
  148. LOG_ERROR_VARG("Incompatible format: (%d, %d)", channels, bits);
  149. return false;
  150. }
  151. // Read the data chunk, which will hold the decoded sample data
  152. if (fread(stream, 1, 4, file) != 4 || memcmp(stream, "data", 4) != 0)
  153. {
  154. LOG_ERROR("WAV file has no data.");
  155. return false;
  156. }
  157. // Read how much data is remaining and buffer it up.
  158. unsigned int dataSize;
  159. fread(&dataSize, sizeof(int), 1, file);
  160. char* data = new char[dataSize];
  161. if (fread(data, sizeof(char), dataSize, file) != dataSize)
  162. {
  163. LOG_ERROR("WAV file missing data.");
  164. SAFE_DELETE_ARRAY(data);
  165. return false;
  166. }
  167. alBufferData(buffer, format, data, dataSize, frequency);
  168. SAFE_DELETE_ARRAY(data);
  169. return true;
  170. }
  171. bool AudioBuffer::loadOgg(FILE* file, ALuint buffer)
  172. {
  173. OggVorbis_File ogg_file;
  174. vorbis_info* info;
  175. ALenum format;
  176. int result;
  177. int section;
  178. unsigned int size = 0;
  179. rewind(file);
  180. if ((result = ov_open(file, &ogg_file, NULL, 0)) < 0)
  181. {
  182. fclose(file);
  183. LOG_ERROR("Could not open Ogg stream.");
  184. return false;
  185. }
  186. info = ov_info(&ogg_file, -1);
  187. if (info->channels == 1)
  188. format = AL_FORMAT_MONO16;
  189. else
  190. format = AL_FORMAT_STEREO16;
  191. // size = #samples * #channels * 2 (for 16 bit)
  192. unsigned int data_size = ov_pcm_total(&ogg_file, -1) * info->channels * 2;
  193. char* data = new char[data_size];
  194. while (size < data_size)
  195. {
  196. result = ov_read(&ogg_file, data + size, data_size - size, 0, 2, 1, &section);
  197. if (result > 0)
  198. {
  199. size += result;
  200. }
  201. else if (result < 0)
  202. {
  203. SAFE_DELETE_ARRAY(data);
  204. LOG_ERROR("OGG file missing data.");
  205. return false;
  206. }
  207. else
  208. {
  209. break;
  210. }
  211. }
  212. if (size == 0)
  213. {
  214. SAFE_DELETE_ARRAY(data);
  215. LOG_ERROR("Unable to read OGG data.");
  216. return false;
  217. }
  218. alBufferData(buffer, format, data, data_size, info->rate);
  219. SAFE_DELETE_ARRAY(data);
  220. ov_clear(&ogg_file);
  221. // ov_clear actually closes the file pointer as well
  222. file = 0;
  223. return true;
  224. }
  225. }