- 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/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

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