/extlibs/SFML/src/SFML/Audio/SoundBuffer.cpp

https://bitbucket.org/hugoruscitti/pilascpp · C++ · 283 lines · 167 code · 51 blank · 65 comment · 19 complexity · 856309d699e5e689b5a15f4b1a4d16ba MD5 · raw file

  1. ////////////////////////////////////////////////////////////
  2. //
  3. // SFML - Simple and Fast Multimedia Library
  4. // Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
  5. //
  6. // This software is provided 'as-is', without any express or implied warranty.
  7. // In no event will the authors be held liable for any damages arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,
  10. // including commercial applications, and to alter it and redistribute it freely,
  11. // subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented;
  14. // you must not claim that you wrote the original software.
  15. // If you use this software in a product, an acknowledgment
  16. // in the product documentation would be appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such,
  19. // and must not be misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source distribution.
  22. //
  23. ////////////////////////////////////////////////////////////
  24. ////////////////////////////////////////////////////////////
  25. // Headers
  26. ////////////////////////////////////////////////////////////
  27. #include <SFML/Audio/SoundBuffer.hpp>
  28. #include <SFML/Audio/SoundFile.hpp>
  29. #include <SFML/Audio/Sound.hpp>
  30. #include <SFML/Audio/AudioDevice.hpp>
  31. #include <SFML/Audio/ALCheck.hpp>
  32. #include <SFML/System/Err.hpp>
  33. #include <memory>
  34. namespace sf
  35. {
  36. ////////////////////////////////////////////////////////////
  37. SoundBuffer::SoundBuffer() :
  38. myBuffer (0),
  39. myDuration(0.f)
  40. {
  41. priv::EnsureALInit();
  42. // Create the buffer
  43. ALCheck(alGenBuffers(1, &myBuffer));
  44. }
  45. ////////////////////////////////////////////////////////////
  46. SoundBuffer::SoundBuffer(const SoundBuffer& copy) :
  47. Resource<SoundBuffer>(),
  48. myBuffer (0),
  49. mySamples (copy.mySamples),
  50. myDuration (copy.myDuration),
  51. mySounds () // don't copy the attached sounds
  52. {
  53. // Create the buffer
  54. ALCheck(alGenBuffers(1, &myBuffer));
  55. // Update the internal buffer with the new samples
  56. Update(copy.GetChannelsCount(), copy.GetSampleRate());
  57. }
  58. ////////////////////////////////////////////////////////////
  59. SoundBuffer::~SoundBuffer()
  60. {
  61. // First detach the buffer from the sounds that use it (to avoid OpenAL errors)
  62. for (SoundList::const_iterator it = mySounds.begin(); it != mySounds.end(); ++it)
  63. (*it)->ResetBuffer();
  64. // Destroy the buffer
  65. if (myBuffer)
  66. ALCheck(alDeleteBuffers(1, &myBuffer));
  67. }
  68. ////////////////////////////////////////////////////////////
  69. bool SoundBuffer::LoadFromFile(const std::string& filename)
  70. {
  71. // Open the sound file
  72. priv::SoundFile file;
  73. if (file.OpenRead(filename))
  74. {
  75. // Get the sound parameters
  76. std::size_t nbSamples = file.GetSamplesCount();
  77. unsigned int channelsCount = file.GetChannelsCount();
  78. unsigned int sampleRate = file.GetSampleRate();
  79. // Read the samples from the opened file
  80. mySamples.resize(nbSamples);
  81. if (file.Read(&mySamples[0], nbSamples) == nbSamples)
  82. {
  83. // Update the internal buffer with the new samples
  84. return Update(channelsCount, sampleRate);
  85. }
  86. else
  87. {
  88. return false;
  89. }
  90. }
  91. else
  92. {
  93. return false;
  94. }
  95. }
  96. ////////////////////////////////////////////////////////////
  97. bool SoundBuffer::LoadFromMemory(const void* data, std::size_t sizeInBytes)
  98. {
  99. // Open the sound file
  100. priv::SoundFile file;
  101. if (file.OpenRead(data, sizeInBytes))
  102. {
  103. // Get the sound parameters
  104. std::size_t nbSamples = file.GetSamplesCount();
  105. unsigned int channelsCount = file.GetChannelsCount();
  106. unsigned int sampleRate = file.GetSampleRate();
  107. // Read the samples from the opened file
  108. mySamples.resize(nbSamples);
  109. if (file.Read(&mySamples[0], nbSamples) == nbSamples)
  110. {
  111. // Update the internal buffer with the new samples
  112. return Update(channelsCount, sampleRate);
  113. }
  114. else
  115. {
  116. return false;
  117. }
  118. }
  119. else
  120. {
  121. return false;
  122. }
  123. }
  124. ////////////////////////////////////////////////////////////
  125. bool SoundBuffer::LoadFromSamples(const Int16* samples, std::size_t samplesCount, unsigned int channelsCount, unsigned int sampleRate)
  126. {
  127. if (samples && samplesCount && channelsCount && sampleRate)
  128. {
  129. // Copy the new audio samples
  130. mySamples.assign(samples, samples + samplesCount);
  131. // Update the internal buffer with the new samples
  132. return Update(channelsCount, sampleRate);
  133. }
  134. else
  135. {
  136. // Error...
  137. Err() << "Failed to load sound buffer from memory ("
  138. << "Samples : " << samples << ", "
  139. << "Samples count : " << samplesCount << ", "
  140. << "Channels count : " << channelsCount << ", "
  141. << "Sample rate : " << sampleRate << ")"
  142. << std::endl;
  143. return false;
  144. }
  145. }
  146. ////////////////////////////////////////////////////////////
  147. bool SoundBuffer::SaveToFile(const std::string& filename) const
  148. {
  149. // Create the sound file in write mode
  150. priv::SoundFile file;
  151. if (file.OpenWrite(filename, GetChannelsCount(), GetSampleRate()))
  152. {
  153. // Write the samples to the opened file
  154. file.Write(&mySamples[0], mySamples.size());
  155. return true;
  156. }
  157. else
  158. {
  159. return false;
  160. }
  161. }
  162. ////////////////////////////////////////////////////////////
  163. const Int16* SoundBuffer::GetSamples() const
  164. {
  165. return mySamples.empty() ? NULL : &mySamples[0];
  166. }
  167. ////////////////////////////////////////////////////////////
  168. std::size_t SoundBuffer::GetSamplesCount() const
  169. {
  170. return mySamples.size();
  171. }
  172. ////////////////////////////////////////////////////////////
  173. unsigned int SoundBuffer::GetSampleRate() const
  174. {
  175. ALint sampleRate;
  176. ALCheck(alGetBufferi(myBuffer, AL_FREQUENCY, &sampleRate));
  177. return sampleRate;
  178. }
  179. ////////////////////////////////////////////////////////////
  180. unsigned int SoundBuffer::GetChannelsCount() const
  181. {
  182. ALint channelsCount;
  183. ALCheck(alGetBufferi(myBuffer, AL_CHANNELS, &channelsCount));
  184. return channelsCount;
  185. }
  186. ////////////////////////////////////////////////////////////
  187. float SoundBuffer::GetDuration() const
  188. {
  189. return myDuration;
  190. }
  191. ////////////////////////////////////////////////////////////
  192. SoundBuffer& SoundBuffer::operator =(const SoundBuffer& right)
  193. {
  194. SoundBuffer temp(right);
  195. std::swap(mySamples, temp.mySamples);
  196. std::swap(myBuffer, temp.myBuffer);
  197. std::swap(myDuration, temp.myDuration);
  198. std::swap(mySounds, temp.mySounds); // swap sounds too, so that they are detached when temp is destroyed
  199. return *this;
  200. }
  201. ////////////////////////////////////////////////////////////
  202. bool SoundBuffer::Update(unsigned int channelsCount, unsigned int sampleRate)
  203. {
  204. // Check parameters
  205. if (!channelsCount || !sampleRate || mySamples.empty())
  206. return false;
  207. // Find the good format according to the number of channels
  208. ALenum format = priv::AudioDevice::GetFormatFromChannelsCount(channelsCount);
  209. // Check if the format is valid
  210. if (format == 0)
  211. {
  212. Err() << "Unsupported number of channels (" << channelsCount << ")" << std::endl;
  213. return false;
  214. }
  215. // Fill the buffer
  216. ALsizei size = static_cast<ALsizei>(mySamples.size()) * sizeof(Int16);
  217. ALCheck(alBufferData(myBuffer, format, &mySamples[0], size, sampleRate));
  218. // Compute the duration
  219. myDuration = static_cast<float>(mySamples.size()) / sampleRate / channelsCount;
  220. return true;
  221. }
  222. ////////////////////////////////////////////////////////////
  223. void SoundBuffer::AttachSound(Sound* sound) const
  224. {
  225. mySounds.insert(sound);
  226. }
  227. ////////////////////////////////////////////////////////////
  228. void SoundBuffer::DetachSound(Sound* sound) const
  229. {
  230. mySounds.erase(sound);
  231. }
  232. } // namespace sf