SFML logo
  • Main Page
  • Namespaces
  • Classes
  • Files
  • File List

SoundBuffer.cpp

00001 
00002 //
00003 // SFML - Simple and Fast Multimedia Library
00004 // Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
00005 //
00006 // This software is provided 'as-is', without any express or implied warranty.
00007 // In no event will the authors be held liable for any damages arising from the use of this software.
00008 //
00009 // Permission is granted to anyone to use this software for any purpose,
00010 // including commercial applications, and to alter it and redistribute it freely,
00011 // subject to the following restrictions:
00012 //
00013 // 1. The origin of this software must not be misrepresented;
00014 //    you must not claim that you wrote the original software.
00015 //    If you use this software in a product, an acknowledgment
00016 //    in the product documentation would be appreciated but is not required.
00017 //
00018 // 2. Altered source versions must be plainly marked as such,
00019 //    and must not be misrepresented as being the original software.
00020 //
00021 // 3. This notice may not be removed or altered from any source distribution.
00022 //
00024 
00026 // Headers
00028 #include <SFML/Audio/SoundBuffer.hpp>
00029 #include <SFML/Audio/SoundFile.hpp>
00030 #include <SFML/Audio/Sound.hpp>
00031 #include <SFML/Audio/AudioDevice.hpp>
00032 #include <SFML/Audio/ALCheck.hpp>
00033 #include <SFML/System/Err.hpp>
00034 #include <memory>
00035 
00036 
00037 namespace sf
00038 {
00040 SoundBuffer::SoundBuffer() :
00041 myBuffer  (0),
00042 myDuration(0.f)
00043 {
00044     priv::EnsureALInit();
00045 
00046     // Create the buffer
00047     ALCheck(alGenBuffers(1, &myBuffer));
00048 }
00049 
00050 
00052 SoundBuffer::SoundBuffer(const SoundBuffer& copy) :
00053 myBuffer  (0),
00054 mySamples (copy.mySamples),
00055 myDuration(copy.myDuration),
00056 mySounds  () // don't copy the attached sounds
00057 {
00058     // Create the buffer
00059     ALCheck(alGenBuffers(1, &myBuffer));
00060 
00061     // Update the internal buffer with the new samples
00062     Update(copy.GetChannelsCount(), copy.GetSampleRate());
00063 }
00064 
00065 
00067 SoundBuffer::~SoundBuffer()
00068 {
00069     // First detach the buffer from the sounds that use it (to avoid OpenAL errors)
00070     for (SoundList::const_iterator it = mySounds.begin(); it != mySounds.end(); ++it)
00071         (*it)->ResetBuffer();
00072 
00073     // Destroy the buffer
00074     if (myBuffer)
00075         ALCheck(alDeleteBuffers(1, &myBuffer));
00076 }
00077 
00078 
00080 bool SoundBuffer::LoadFromFile(const std::string& filename)
00081 {
00082     // Open the sound file
00083     priv::SoundFile file;
00084     if (file.OpenRead(filename))
00085     {
00086         // Get the sound parameters
00087         std::size_t  nbSamples     = file.GetSamplesCount();
00088         unsigned int channelsCount = file.GetChannelsCount();
00089         unsigned int sampleRate    = file.GetSampleRate();
00090 
00091         // Read the samples from the opened file
00092         mySamples.resize(nbSamples);
00093         if (file.Read(&mySamples[0], nbSamples) == nbSamples)
00094         {
00095             // Update the internal buffer with the new samples
00096             return Update(channelsCount, sampleRate);
00097         }
00098         else
00099         {
00100             return false;
00101         }
00102     }
00103     else
00104     {
00105         return false;
00106     }
00107 }
00108 
00109 
00111 bool SoundBuffer::LoadFromMemory(const void* data, std::size_t sizeInBytes)
00112 {
00113     // Open the sound file
00114     priv::SoundFile file;
00115     if (file.OpenRead(data, sizeInBytes))
00116     {
00117         // Get the sound parameters
00118         std::size_t  nbSamples     = file.GetSamplesCount();
00119         unsigned int channelsCount = file.GetChannelsCount();
00120         unsigned int sampleRate    = file.GetSampleRate();
00121 
00122         // Read the samples from the opened file
00123         mySamples.resize(nbSamples);
00124         if (file.Read(&mySamples[0], nbSamples) == nbSamples)
00125         {
00126             // Update the internal buffer with the new samples
00127             return Update(channelsCount, sampleRate);
00128         }
00129         else
00130         {
00131             return false;
00132         }
00133     }
00134     else
00135     {
00136         return false;
00137     }
00138 }
00139 
00140 
00142 bool SoundBuffer::LoadFromSamples(const Int16* samples, std::size_t samplesCount, unsigned int channelsCount, unsigned int sampleRate)
00143 {
00144     if (samples && samplesCount && channelsCount && sampleRate)
00145     {
00146         // Copy the new audio samples
00147         mySamples.assign(samples, samples + samplesCount);
00148 
00149         // Update the internal buffer with the new samples
00150         return Update(channelsCount, sampleRate);
00151     }
00152     else
00153     {
00154         // Error...
00155         Err() << "Failed to load sound buffer from memory ("
00156               << "Samples : "        << samples       << ", "
00157               << "Samples count : "  << samplesCount  << ", "
00158               << "Channels count : " << channelsCount << ", "
00159               << "Sample rate : "    << sampleRate    << ")"
00160               << std::endl;
00161 
00162         return false;
00163     }
00164 }
00165 
00166 
00168 bool SoundBuffer::SaveToFile(const std::string& filename) const
00169 {
00170     // Create the sound file in write mode
00171     priv::SoundFile file;
00172     if (file.OpenWrite(filename, GetChannelsCount(), GetSampleRate()))
00173     {
00174         // Write the samples to the opened file
00175         file.Write(&mySamples[0], mySamples.size());
00176 
00177         return true;
00178     }
00179     else
00180     {
00181         return false;
00182     }
00183 }
00184 
00185 
00187 const Int16* SoundBuffer::GetSamples() const
00188 {
00189     return mySamples.empty() ? NULL : &mySamples[0];
00190 }
00191 
00192 
00194 std::size_t SoundBuffer::GetSamplesCount() const
00195 {
00196     return mySamples.size();
00197 }
00198 
00199 
00201 unsigned int SoundBuffer::GetSampleRate() const
00202 {
00203     ALint sampleRate;
00204     ALCheck(alGetBufferi(myBuffer, AL_FREQUENCY, &sampleRate));
00205 
00206     return sampleRate;
00207 }
00208 
00209 
00211 unsigned int SoundBuffer::GetChannelsCount() const
00212 {
00213     ALint channelsCount;
00214     ALCheck(alGetBufferi(myBuffer, AL_CHANNELS, &channelsCount));
00215 
00216     return channelsCount;
00217 }
00218 
00219 
00221 float SoundBuffer::GetDuration() const
00222 {
00223     return myDuration;
00224 }
00225 
00226 
00228 SoundBuffer& SoundBuffer::operator =(const SoundBuffer& other)
00229 {
00230     SoundBuffer temp(other);
00231 
00232     std::swap(mySamples,  temp.mySamples);
00233     std::swap(myBuffer,   temp.myBuffer);
00234     std::swap(myDuration, temp.myDuration);
00235     std::swap(mySounds,   temp.mySounds); // swap sounds too, so that they are detached when temp is destroyed
00236 
00237     return *this;
00238 }
00239 
00240 
00242 bool SoundBuffer::Update(unsigned int channelsCount, unsigned int sampleRate)
00243 {
00244     // Check parameters
00245     if (!channelsCount || !sampleRate || mySamples.empty())
00246         return false;
00247 
00248     // Find the good format according to the number of channels
00249     ALenum format = priv::AudioDevice::GetFormatFromChannelsCount(channelsCount);
00250 
00251     // Check if the format is valid
00252     if (format == 0)
00253     {
00254         Err() << "Unsupported number of channels (" << channelsCount << ")" << std::endl;
00255         return false;
00256     }
00257 
00258     // Fill the buffer
00259     ALsizei size = static_cast<ALsizei>(mySamples.size()) * sizeof(Int16);
00260     ALCheck(alBufferData(myBuffer, format, &mySamples[0], size, sampleRate));
00261 
00262     // Compute the duration
00263     myDuration = static_cast<float>(mySamples.size()) / sampleRate / channelsCount;
00264 
00265     return true;
00266 }
00267 
00268 
00270 void SoundBuffer::AttachSound(Sound* sound) const
00271 {
00272     mySounds.insert(sound);
00273 }
00274 
00275 
00277 void SoundBuffer::DetachSound(Sound* sound) const
00278 {
00279     mySounds.erase(sound);
00280 }
00281 
00282 } // namespace sf

 ::  Copyright © 2007-2008 Laurent Gomila, all rights reserved  ::  Documentation generated by doxygen 1.5.2  ::