SoundBuffer.cpp
00001 00002 // 00003 // SFML - Simple and Fast Multimedia Library 00004 // Copyright (C) 2007-2009 Laurent Gomila ([email protected]) 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 ::