AudioBuffer.cpp 11 KB

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