WaveDecoder.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /**
  2. * Copyright (c) 2006-2019 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. #include "WaveDecoder.h"
  21. #include <string.h>
  22. #include "common/config.h"
  23. #include "common/Exception.h"
  24. namespace love
  25. {
  26. namespace sound
  27. {
  28. namespace lullaby
  29. {
  30. // Callbacks
  31. static wuff_sint32 read_callback(void *userdata, wuff_uint8 *buffer, size_t *size)
  32. {
  33. WaveFile *input = (WaveFile *) userdata;
  34. size_t bytes_left = input->size - input->offset;
  35. size_t target_size = *size < bytes_left ? *size : bytes_left;
  36. memcpy(buffer, input->data + input->offset, target_size);
  37. input->offset += target_size;
  38. *size = target_size;
  39. return WUFF_SUCCESS;
  40. }
  41. static wuff_sint32 seek_callback(void *userdata, wuff_uint64 offset)
  42. {
  43. WaveFile *input = (WaveFile *)userdata;
  44. input->offset = (size_t) (offset < input->size ? offset : input->size);
  45. return WUFF_SUCCESS;
  46. }
  47. static wuff_sint32 tell_callback(void *userdata, wuff_uint64 *offset)
  48. {
  49. WaveFile *input = (WaveFile *)userdata;
  50. *offset = input->offset;
  51. return WUFF_SUCCESS;
  52. }
  53. wuff_callback WaveDecoderCallbacks = {read_callback, seek_callback, tell_callback};
  54. WaveDecoder::WaveDecoder(Data *data, int bufferSize)
  55. : Decoder(data, bufferSize)
  56. {
  57. dataFile.data = (char *) data->getData();
  58. dataFile.size = data->getSize();
  59. dataFile.offset = 0;
  60. int wuff_status = wuff_open(&handle, &WaveDecoderCallbacks, &dataFile);
  61. if (wuff_status < 0)
  62. throw love::Exception("Could not open WAVE");
  63. try
  64. {
  65. wuff_status = wuff_stream_info(handle, &info);
  66. if (wuff_status < 0)
  67. throw love::Exception("Could not retrieve WAVE stream info");
  68. if (info.channels > 2)
  69. throw love::Exception("Multichannel audio not supported");
  70. if (info.format != WUFF_FORMAT_PCM_U8 && info.format != WUFF_FORMAT_PCM_S16)
  71. {
  72. wuff_status = wuff_format(handle, WUFF_FORMAT_PCM_S16);
  73. if (wuff_status < 0)
  74. throw love::Exception("Could not set output format");
  75. }
  76. }
  77. catch (love::Exception &)
  78. {
  79. wuff_close(handle);
  80. throw;
  81. }
  82. }
  83. WaveDecoder::~WaveDecoder()
  84. {
  85. wuff_close(handle);
  86. }
  87. bool WaveDecoder::accepts(const std::string &ext)
  88. {
  89. static const std::string supported[] =
  90. {
  91. "wav", ""
  92. };
  93. for (int i = 0; !(supported[i].empty()); i++)
  94. {
  95. if (supported[i].compare(ext) == 0)
  96. return true;
  97. }
  98. return false;
  99. }
  100. love::sound::Decoder *WaveDecoder::clone()
  101. {
  102. return new WaveDecoder(data.get(), bufferSize);
  103. }
  104. int WaveDecoder::decode()
  105. {
  106. size_t size = 0;
  107. while (size < (size_t) bufferSize)
  108. {
  109. size_t bytes = bufferSize-size;
  110. int wuff_status = wuff_read(handle, (wuff_uint8 *) buffer+size, &bytes);
  111. if (wuff_status < 0)
  112. return 0;
  113. else if (bytes == 0)
  114. {
  115. eof = true;
  116. break;
  117. }
  118. size += bytes;
  119. }
  120. return (int) size;
  121. }
  122. bool WaveDecoder::seek(float s)
  123. {
  124. int wuff_status = wuff_seek(handle, (wuff_uint64) (s * info.sample_rate));
  125. if (wuff_status >= 0)
  126. {
  127. eof = false;
  128. return true;
  129. }
  130. return false;
  131. }
  132. bool WaveDecoder::rewind()
  133. {
  134. int wuff_status = wuff_seek(handle, 0);
  135. if (wuff_status >= 0)
  136. {
  137. eof = false;
  138. return true;
  139. }
  140. return false;
  141. }
  142. bool WaveDecoder::isSeekable()
  143. {
  144. return true;
  145. }
  146. int WaveDecoder::getChannelCount() const
  147. {
  148. return info.channels;
  149. }
  150. int WaveDecoder::getBitDepth() const
  151. {
  152. return info.bits_per_sample == 8 ? 8 : 16;
  153. }
  154. int WaveDecoder::getSampleRate() const
  155. {
  156. return info.sample_rate;
  157. }
  158. double WaveDecoder::getDuration()
  159. {
  160. return (double) info.length / (double) info.sample_rate;
  161. }
  162. } // lullaby
  163. } // sound
  164. } // love