Back to index

libsfml  1.6+dfsg2
SoundBuffer.cpp
Go to the documentation of this file.
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/OpenAL.hpp>
00033 #include <iostream>
00034 #include <memory>
00035 
00036 
00037 namespace sf
00038 {
00042 SoundBuffer::SoundBuffer() :
00043 myBuffer  (0),
00044 myDuration(0.f)
00045 {
00046     // Create the buffer
00047     ALCheck(alGenBuffers(1, &myBuffer));
00048 }
00049 
00050 
00054 SoundBuffer::SoundBuffer(const SoundBuffer& Copy) :
00055 AudioResource        (Copy),
00056 Resource<SoundBuffer>(Copy),
00057 myBuffer             (0),
00058 mySamples            (Copy.mySamples),
00059 myDuration           (Copy.myDuration),
00060 mySounds             () // don't copy the attached sounds
00061 {
00062     // Create the buffer
00063     ALCheck(alGenBuffers(1, &myBuffer));
00064 
00065     // Update the internal buffer with the new samples
00066     Update(Copy.GetChannelsCount(), Copy.GetSampleRate());
00067 }
00068 
00069 
00073 SoundBuffer::~SoundBuffer()
00074 {
00075     // First detach the buffer from the sounds that use it (to avoid OpenAL errors)
00076     for (SoundList::const_iterator it = mySounds.begin(); it != mySounds.end(); ++it)
00077         (*it)->ResetBuffer();
00078 
00079     // Destroy the buffer
00080     if (myBuffer)
00081         ALCheck(alDeleteBuffers(1, &myBuffer));
00082 }
00083 
00084 
00088 bool SoundBuffer::LoadFromFile(const std::string& Filename)
00089 {
00090     // Create the sound file
00091     std::auto_ptr<priv::SoundFile> File(priv::SoundFile::CreateRead(Filename));
00092 
00093     // Open the sound file
00094     if (File.get())
00095     {
00096         // Get the sound parameters
00097         std::size_t  NbSamples     = File->GetSamplesCount();
00098         unsigned int ChannelsCount = File->GetChannelsCount();
00099         unsigned int SampleRate    = File->GetSampleRate();
00100 
00101         // Read the samples from the opened file
00102         mySamples.resize(NbSamples);
00103         if (File->Read(&mySamples[0], NbSamples) == NbSamples)
00104         {
00105             // Update the internal buffer with the new samples
00106             return Update(ChannelsCount, SampleRate);
00107         }
00108         else
00109         {
00110             // Error...
00111             std::cerr << "Failed to read audio data from file \"" << Filename << "\"" << std::endl;
00112 
00113             return false;
00114         }
00115     }
00116     else
00117     {
00118         // Error...
00119         std::cerr << "Failed to load sound buffer from file \"" << Filename << "\"" << std::endl;
00120 
00121         return false;
00122     }
00123 }
00124 
00125 
00129 bool SoundBuffer::LoadFromMemory(const char* Data, std::size_t SizeInBytes)
00130 {
00131     // Create the sound file
00132     std::auto_ptr<priv::SoundFile> File(priv::SoundFile::CreateRead(Data, SizeInBytes));
00133 
00134     // Open the sound file
00135     if (File.get())
00136     {
00137         // Get the sound parameters
00138         std::size_t  NbSamples     = File->GetSamplesCount();
00139         unsigned int ChannelsCount = File->GetChannelsCount();
00140         unsigned int SampleRate    = File->GetSampleRate();
00141 
00142         // Read the samples from the opened file
00143         mySamples.resize(NbSamples);
00144         if (File->Read(&mySamples[0], NbSamples) == NbSamples)
00145         {
00146             // Update the internal buffer with the new samples
00147             return Update(ChannelsCount, SampleRate);
00148         }
00149         else
00150         {
00151             // Error...
00152             std::cerr << "Failed to read audio data from file in memory" << std::endl;
00153 
00154             return false;
00155         }
00156     }
00157     else
00158     {
00159         // Error...
00160         std::cerr << "Failed to load sound buffer from file in memory" << std::endl;
00161 
00162         return false;
00163     }
00164 }
00165 
00166 
00171 bool SoundBuffer::LoadFromSamples(const Int16* Samples, std::size_t SamplesCount, unsigned int ChannelsCount, unsigned int SampleRate)
00172 {
00173     if (Samples && SamplesCount && ChannelsCount && SampleRate)
00174     {
00175         // Copy the new audio samples
00176         mySamples.assign(Samples, Samples + SamplesCount);
00177 
00178         // Update the internal buffer with the new samples
00179         return Update(ChannelsCount, SampleRate);
00180     }
00181     else
00182     {
00183         // Error...
00184         std::cerr << "Failed to load sound buffer from memory ("
00185                   << "Samples : "        << Samples       << ", "
00186                   << "Samples count : "  << SamplesCount  << ", "
00187                   << "Channels count : " << ChannelsCount << ", "
00188                   << "Sample rate : "    << SampleRate    << ")"
00189                   << std::endl;
00190 
00191         return false;
00192     }
00193 }
00194 
00195 
00199 bool SoundBuffer::SaveToFile(const std::string& Filename) const
00200 {
00201     // Create the sound file in write mode
00202     std::auto_ptr<priv::SoundFile> File(priv::SoundFile::CreateWrite(Filename, GetChannelsCount(), GetSampleRate()));
00203     if (File.get())
00204     {
00205         // Write the samples to the opened file
00206         File->Write(&mySamples[0], mySamples.size());
00207 
00208         return true;
00209     }
00210     else
00211     {
00212         // Error...
00213         std::cerr << "Failed to save sound buffer to file \"" << Filename << "\"" << std::endl;
00214 
00215         return false;
00216     }
00217 }
00218 
00219 
00223 const Int16* SoundBuffer::GetSamples() const
00224 {
00225     return mySamples.empty() ? NULL : &mySamples[0];
00226 }
00227 
00228 
00232 std::size_t SoundBuffer::GetSamplesCount() const
00233 {
00234     return mySamples.size();
00235 }
00236 
00237 
00241 unsigned int SoundBuffer::GetSampleRate() const
00242 {
00243     ALint SampleRate;
00244     ALCheck(alGetBufferi(myBuffer, AL_FREQUENCY, &SampleRate));
00245 
00246     return SampleRate;
00247 }
00248 
00249 
00253 unsigned int SoundBuffer::GetChannelsCount() const
00254 {
00255     ALint ChannelsCount;
00256     ALCheck(alGetBufferi(myBuffer, AL_CHANNELS, &ChannelsCount));
00257 
00258     return ChannelsCount;
00259 }
00260 
00261 
00265 float SoundBuffer::GetDuration() const
00266 {
00267     return myDuration;
00268 }
00269 
00270 
00274 SoundBuffer& SoundBuffer::operator =(const SoundBuffer& Other)
00275 {
00276     SoundBuffer Temp(Other);
00277 
00278     std::swap(mySamples,  Temp.mySamples);
00279     std::swap(myBuffer,   Temp.myBuffer);
00280     std::swap(myDuration, Temp.myDuration);
00281     std::swap(mySounds,   Temp.mySounds); // swap sounds too, so that they are detached when Temp is destroyed
00282 
00283     return *this;
00284 }
00285 
00286 
00290 bool SoundBuffer::Update(unsigned int ChannelsCount, unsigned int SampleRate)
00291 {
00292     // Check parameters
00293     if (!SampleRate || !ChannelsCount || mySamples.empty())
00294         return false;
00295 
00296     // Find the good format according to the number of channels
00297     ALenum Format = priv::AudioDevice::GetInstance().GetFormatFromChannelsCount(ChannelsCount);
00298 
00299     // Check if the format is valid
00300     if (Format == 0)
00301     {
00302         std::cerr << "Unsupported number of channels (" << ChannelsCount << ")" << std::endl;
00303         return false;
00304     }
00305 
00306     // Fill the buffer
00307     ALsizei Size = static_cast<ALsizei>(mySamples.size()) * sizeof(Int16);
00308     ALCheck(alBufferData(myBuffer, Format, &mySamples[0], Size, SampleRate));
00309 
00310     // Compute the duration
00311     myDuration = static_cast<float>(mySamples.size()) / SampleRate / ChannelsCount;
00312 
00313     return true;
00314 }
00315 
00316 
00320 void SoundBuffer::AttachSound(Sound* Instance) const
00321 {
00322     mySounds.insert(Instance);
00323 }
00324 
00325 
00329 void SoundBuffer::DetachSound(Sound* Instance) const
00330 {
00331     mySounds.erase(Instance);
00332 }
00333 
00334 } // namespace sf