AudioBuffer.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  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. // Remove the buffer from the cache.
  15. unsigned int bufferCount = (unsigned int)__buffers.size();
  16. for (unsigned int i = 0; i < bufferCount; i++)
  17. {
  18. if (this == __buffers[i])
  19. {
  20. __buffers.erase(__buffers.begin() + i);
  21. break;
  22. }
  23. }
  24. if (_alBuffer)
  25. {
  26. AL_CHECK( alDeleteBuffers(1, &_alBuffer) );
  27. _alBuffer = 0;
  28. }
  29. }
  30. AudioBuffer* AudioBuffer::create(const char* path)
  31. {
  32. GP_ASSERT(path);
  33. // Search the cache for a stream from this file.
  34. unsigned int bufferCount = (unsigned int)__buffers.size();
  35. AudioBuffer* buffer = NULL;
  36. for (unsigned int i = 0; i < bufferCount; i++)
  37. {
  38. buffer = __buffers[i];
  39. GP_ASSERT(buffer);
  40. if (buffer->_filePath.compare(path) == 0)
  41. {
  42. buffer->addRef();
  43. return buffer;
  44. }
  45. }
  46. ALuint alBuffer;
  47. // Load audio data into a buffer.
  48. AL_CHECK( alGenBuffers(1, &alBuffer) );
  49. if (AL_LAST_ERROR())
  50. {
  51. GP_ERROR("Failed to create OpenAL buffer; alGenBuffers error: %d", AL_LAST_ERROR());
  52. AL_CHECK( alDeleteBuffers(1, &alBuffer) );
  53. return NULL;
  54. }
  55. // Load sound file.
  56. FILE* file = FileSystem::openFile(path, "rb");
  57. if (!file)
  58. {
  59. GP_ERROR("Failed to load audio file %s.", path);
  60. goto cleanup;
  61. }
  62. // Read the file header
  63. char header[12];
  64. if (fread(header, 1, 12, file) != 12)
  65. {
  66. GP_ERROR("Invalid header for audio file %s.", path);
  67. goto cleanup;
  68. }
  69. // Check the file format
  70. if (memcmp(header, "RIFF", 4) == 0)
  71. {
  72. if (!AudioBuffer::loadWav(file, alBuffer))
  73. {
  74. GP_ERROR("Invalid wave file: %s", path);
  75. goto cleanup;
  76. }
  77. }
  78. else if (memcmp(header, "OggS", 4) == 0)
  79. {
  80. if (!AudioBuffer::loadOgg(file, alBuffer))
  81. {
  82. GP_ERROR("Invalid ogg file: %s", path);
  83. goto cleanup;
  84. }
  85. }
  86. else
  87. {
  88. GP_ERROR("Unsupported audio file: %s", path);
  89. goto cleanup;
  90. }
  91. //NOTE: loadOgg actually sets this null, so it is expected
  92. if (file)
  93. fclose(file);
  94. buffer = new AudioBuffer(path, alBuffer);
  95. // Add the buffer to the cache.
  96. __buffers.push_back(buffer);
  97. return buffer;
  98. cleanup:
  99. if (file)
  100. fclose(file);
  101. if (alBuffer)
  102. AL_CHECK( alDeleteBuffers(1, &alBuffer) );
  103. return NULL;
  104. }
  105. bool AudioBuffer::loadWav(FILE* file, ALuint buffer)
  106. {
  107. GP_ASSERT(file);
  108. unsigned char stream[12];
  109. // Verify the wave fmt magic value meaning format.
  110. if (fread(stream, 1, 8, file) != 8 || memcmp(stream, "fmt ", 4) != 0 )
  111. {
  112. GP_ERROR("Failed to verify the magic value for the wave file format.");
  113. return false;
  114. }
  115. unsigned int section_size;
  116. section_size = stream[7]<<24;
  117. section_size |= stream[6]<<16;
  118. section_size |= stream[5]<<8;
  119. section_size |= stream[4];
  120. // Check for a valid pcm format.
  121. if (fread(stream, 1, 2, file) != 2 || stream[1] != 0 || stream[0] != 1)
  122. {
  123. GP_ERROR("Unsupported audio file format (must be a valid PCM format).");
  124. return false;
  125. }
  126. // Get the channel count (16-bit little-endian).
  127. int channels;
  128. if (fread(stream, 1, 2, file) != 2)
  129. {
  130. GP_ERROR("Failed to read the wave file's channel count.");
  131. return false;
  132. }
  133. channels = stream[1]<<8;
  134. channels |= stream[0];
  135. // Get the sample frequency (32-bit little-endian).
  136. ALuint frequency;
  137. if (fread(stream, 1, 4, file) != 4)
  138. {
  139. GP_ERROR("Failed to read the wave file's sample frequency.");
  140. return false;
  141. }
  142. frequency = stream[3]<<24;
  143. frequency |= stream[2]<<16;
  144. frequency |= stream[1]<<8;
  145. frequency |= stream[0];
  146. // The next 6 bytes hold the block size and bytes-per-second.
  147. // We don't need that info, so just read and ignore it.
  148. // We could use this later if we need to know the duration.
  149. if (fread(stream, 1, 6, file) != 6)
  150. {
  151. GP_ERROR("Failed to read past the wave file's block size and bytes-per-second.");
  152. return false;
  153. }
  154. // Get the bit depth (16-bit little-endian).
  155. int bits;
  156. if (fread(stream, 1, 2, file) != 2)
  157. {
  158. GP_ERROR("Failed to read the wave file's bit depth.");
  159. return false;
  160. }
  161. bits = stream[1]<<8;
  162. bits |= stream[0];
  163. // Now convert the given channel count and bit depth into an OpenAL format.
  164. ALuint format = 0;
  165. if (bits == 8)
  166. {
  167. if (channels == 1)
  168. format = AL_FORMAT_MONO8;
  169. else if (channels == 2)
  170. format = AL_FORMAT_STEREO8;
  171. }
  172. else if (bits == 16)
  173. {
  174. if (channels == 1)
  175. format = AL_FORMAT_MONO16;
  176. else if (channels == 2)
  177. format = AL_FORMAT_STEREO16;
  178. }
  179. else
  180. {
  181. GP_ERROR("Incompatible wave file format: (%d, %d)", channels, bits);
  182. return false;
  183. }
  184. // Check against the size of the format header as there may be more data that we need to read.
  185. if (section_size > 16)
  186. {
  187. unsigned int length = section_size - 16;
  188. // Extension size is 2 bytes.
  189. if (fread(stream, 1, length, file) != length)
  190. {
  191. GP_ERROR("Failed to read extension size from wave file.");
  192. return false;
  193. }
  194. }
  195. // Read in the rest of the file a chunk (section) at a time.
  196. while (true)
  197. {
  198. // Check if we are at the end of the file without reading the data.
  199. if (feof(file))
  200. {
  201. GP_ERROR("Failed to load wave file; file appears to have no data.");
  202. return false;
  203. }
  204. // Read in the type of the next section of the file.
  205. if (fread(stream, 1, 4, file) != 4)
  206. {
  207. GP_ERROR("Failed to read next section type from wave file.");
  208. return false;
  209. }
  210. // Data chunk.
  211. if (memcmp(stream, "data", 4) == 0)
  212. {
  213. // Read how much data is remaining and buffer it up.
  214. unsigned int dataSize;
  215. if (fread(&dataSize, sizeof(int), 1, file) != 1)
  216. {
  217. GP_ERROR("Failed to read size of data section from wave file.");
  218. return false;
  219. }
  220. char* data = new char[dataSize];
  221. if (fread(data, sizeof(char), dataSize, file) != dataSize)
  222. {
  223. GP_ERROR("Failed to load wave file; file is missing data.");
  224. SAFE_DELETE_ARRAY(data);
  225. return false;
  226. }
  227. AL_CHECK( alBufferData(buffer, format, data, dataSize, frequency) );
  228. SAFE_DELETE_ARRAY(data);
  229. // We've read the data, so return now.
  230. return true;
  231. }
  232. // Other chunk - could be any of the following:
  233. // - Fact ("fact")
  234. // - Wave List ("wavl")
  235. // - Silent ("slnt")
  236. // - Cue ("cue ")
  237. // - Playlist ("plst")
  238. // - Associated Data List ("list")
  239. // - Label ("labl")
  240. // - Note ("note")
  241. // - Labeled Text ("ltxt")
  242. // - Sampler ("smpl")
  243. // - Instrument ("inst")
  244. else
  245. {
  246. // Store the name of the chunk so we can report errors informatively.
  247. char chunk[5] = { 0 };
  248. memcpy(chunk, stream, 4);
  249. // Read the chunk size.
  250. if (fread(stream, 1, 4, file) != 4)
  251. {
  252. GP_ERROR("Failed to read size of '%s' chunk from wave file.", chunk);
  253. return false;
  254. }
  255. section_size = stream[3]<<24;
  256. section_size |= stream[2]<<16;
  257. section_size |= stream[1]<<8;
  258. section_size |= stream[0];
  259. // Seek past the chunk.
  260. if (fseek(file, section_size, SEEK_CUR) != 0)
  261. {
  262. GP_ERROR("Failed to seek past '%s' chunk in wave file.", chunk);
  263. return false;
  264. }
  265. }
  266. }
  267. }
  268. bool AudioBuffer::loadOgg(FILE*& file, ALuint buffer)
  269. {
  270. GP_ASSERT(file);
  271. OggVorbis_File ogg_file;
  272. vorbis_info* info;
  273. ALenum format;
  274. long result;
  275. int section;
  276. long size = 0;
  277. rewind(file);
  278. if ((result = ov_open(file, &ogg_file, NULL, 0)) < 0)
  279. {
  280. fclose(file);
  281. GP_ERROR("Failed to open ogg file.");
  282. return false;
  283. }
  284. info = ov_info(&ogg_file, -1);
  285. GP_ASSERT(info);
  286. if (info->channels == 1)
  287. format = AL_FORMAT_MONO16;
  288. else
  289. format = AL_FORMAT_STEREO16;
  290. // size = #samples * #channels * 2 (for 16 bit).
  291. long data_size = ov_pcm_total(&ogg_file, -1) * info->channels * 2;
  292. char* data = new char[data_size];
  293. while (size < data_size)
  294. {
  295. result = ov_read(&ogg_file, data + size, data_size - size, 0, 2, 1, &section);
  296. if (result > 0)
  297. {
  298. size += result;
  299. }
  300. else if (result < 0)
  301. {
  302. SAFE_DELETE_ARRAY(data);
  303. GP_ERROR("Failed to read ogg file; file is missing data.");
  304. return false;
  305. }
  306. else
  307. {
  308. break;
  309. }
  310. }
  311. if (size == 0)
  312. {
  313. SAFE_DELETE_ARRAY(data);
  314. GP_ERROR("Filed to read ogg file; unable to read any data.");
  315. return false;
  316. }
  317. AL_CHECK( alBufferData(buffer, format, data, data_size, info->rate) );
  318. SAFE_DELETE_ARRAY(data);
  319. ov_clear(&ogg_file);
  320. // ov_clear actually closes the file pointer as well.
  321. file = 0;
  322. return true;
  323. }
  324. }