SoundBuffer.cpp

00001 
00002 //
00003 // SFML - Simple and Fast Multimedia Library
00004 // Copyright (C) 2007 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/AudioDevice.hpp>
00031 #include <SFML/Audio/OpenAL.hpp>
00032 #include <iostream>
00033 #include <memory>
00034 
00035 
00036 namespace sf
00037 {
00041 SoundBuffer::SoundBuffer() :
00042 myBuffer  (0),
00043 myDuration(0.f)
00044 {
00045     // Create the buffer
00046     ALCheck(alGenBuffers(1, &myBuffer));
00047 }
00048 
00049 
00053 SoundBuffer::SoundBuffer(const SoundBuffer& Copy) :
00054 AudioResource(Copy),
00055 myBuffer     (0),
00056 mySamples    (Copy.mySamples),
00057 myDuration   (Copy.myDuration)
00058 {
00059     // Create the buffer
00060     ALCheck(alGenBuffers(1, &myBuffer));
00061 
00062     // Update the internal buffer with the new samples
00063     Update(Copy.GetChannelsCount(), Copy.GetSampleRate());
00064 }
00065 
00066 
00070 SoundBuffer::~SoundBuffer()
00071 {
00072     if (myBuffer)
00073         ALCheck(alDeleteBuffers(1, &myBuffer));
00074 }
00075 
00076 
00080 bool SoundBuffer::LoadFromFile(const std::string& Filename)
00081 {
00082     // Create the sound file
00083     std::auto_ptr<priv::SoundFile> File(priv::SoundFile::Create(Filename));
00084 
00085     // Open the sound file
00086     std::size_t  NbSamples;
00087     unsigned int ChannelsCount, SampleRate;
00088     if (File->OpenRead(Filename, NbSamples, ChannelsCount, SampleRate))
00089     {
00090         // Read the samples from the opened file
00091         mySamples.resize(NbSamples);
00092         if (File->Read(&mySamples[0], NbSamples) == NbSamples)
00093         {
00094             // Update the internal buffer with the new samples
00095             return Update(ChannelsCount, SampleRate);
00096         }
00097         else
00098         {
00099             // Error...
00100             std::cerr << "Failed to read audio data from file \"" << Filename << "\"" << std::endl;
00101 
00102             return false;
00103         }
00104     }
00105     else
00106     {
00107         // Error...
00108         std::cerr << "Failed to load sound buffer from file \"" << Filename << "\"" << std::endl;
00109 
00110         return false;
00111     }
00112 }
00113 
00114 
00118 bool SoundBuffer::LoadFromMemory(const Int16* Samples, std::size_t SamplesCount, unsigned int ChannelsCount, unsigned int SampleRate)
00119 {
00120     if (Samples && SamplesCount && ChannelsCount && SampleRate)
00121     {
00122         // Copy the new audio samples
00123         mySamples.assign(Samples, Samples + SamplesCount);
00124 
00125         // Update the internal buffer with the new samples
00126         return Update(ChannelsCount, SampleRate);
00127     }
00128     else
00129     {
00130         // Error...
00131         std::cerr << "Failed to load sound buffer from memory ("
00132                   << "Samples : "        << Samples       << ", "
00133                   << "Samples count : "  << SamplesCount  << ", "
00134                   << "Channels count : " << ChannelsCount << ", "
00135                   << "Sample rate : "    << SampleRate    << ")"
00136                   << std::endl;
00137 
00138         return false;
00139     }
00140 }
00141 
00142 
00146 bool SoundBuffer::SaveToFile(const std::string& Filename) const
00147 {
00148     // Create the sound file
00149     std::auto_ptr<priv::SoundFile> File(priv::SoundFile::Create(Filename));
00150 
00151     // Open a sound file
00152     if (File->OpenWrite(Filename, GetChannelsCount(), GetSampleRate()))
00153     {
00154         // Write the samples to the opened file
00155         File->Write(&mySamples[0], mySamples.size());
00156 
00157         return true;
00158     }
00159     else
00160     {
00161         // Error...
00162         std::cerr << "Failed to save sound buffer to file \"" << Filename << "\"" << std::endl;
00163 
00164         return false;
00165     }
00166 }
00167 
00168 
00172 const Int16* SoundBuffer::GetSamples() const
00173 {
00174     return mySamples.empty() ? NULL : &mySamples[0];
00175 }
00176 
00177 
00181 std::size_t SoundBuffer::GetSamplesCount() const
00182 {
00183     return mySamples.size();
00184 }
00185 
00186 
00190 unsigned int SoundBuffer::GetSampleRate() const
00191 {
00192     ALint SampleRate;
00193     ALCheck(alGetBufferi(myBuffer, AL_FREQUENCY, &SampleRate));
00194 
00195     return SampleRate;
00196 }
00197 
00198 
00202 unsigned int SoundBuffer::GetChannelsCount() const
00203 {
00204     ALint ChannelsCount;
00205     ALCheck(alGetBufferi(myBuffer, AL_CHANNELS, &ChannelsCount));
00206 
00207     return ChannelsCount;
00208 }
00209 
00210 
00214 float SoundBuffer::GetDuration() const
00215 {
00216     return myDuration;
00217 }
00218 
00219 
00223 SoundBuffer& SoundBuffer::operator =(const SoundBuffer& Other)
00224 {
00225     SoundBuffer Temp(Other);
00226 
00227     mySamples.swap(Temp.mySamples);
00228     std::swap(myBuffer,   Temp.myBuffer);
00229     std::swap(myDuration, Temp.myDuration);
00230 
00231     return *this;
00232 }
00233 
00234 
00238 bool SoundBuffer::Update(unsigned int ChannelsCount, unsigned int SampleRate)
00239 {
00240     // Check parameters
00241     if (!SampleRate || !ChannelsCount || mySamples.empty())
00242         return false;
00243 
00244     // Find the good format according to the number of channels
00245     ALenum Format = priv::AudioDevice::GetInstance().GetFormatFromChannelsCount(ChannelsCount);
00246 
00247     // Check if the format is valid
00248     if (Format == 0)
00249     {
00250         std::cerr << "Unsupported number of channels (" << ChannelsCount << ")" << std::endl;
00251         return false;
00252     }
00253 
00254     // Fill the buffer
00255     ALsizei Size = static_cast<ALsizei>(mySamples.size()) * sizeof(Int16);
00256     ALCheck(alBufferData(myBuffer, Format, &mySamples[0], Size, SampleRate));
00257 
00258     // Compute the duration
00259     myDuration = static_cast<float>(mySamples.size()) / SampleRate / ChannelsCount;
00260 
00261     return true;
00262 }
00263 
00264 } // namespace sf