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