SoundBuffer.cpp
1
2//
3// SFML - Simple and Fast Multimedia Library
4// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
5//
6// This software is provided 'as-is', without any express or implied warranty.
7// In no event will the authors be held liable for any damages arising from the use of this software.
8//
9// Permission is granted to anyone to use this software for any purpose,
10// including commercial applications, and to alter it and redistribute it freely,
11// subject to the following restrictions:
12//
13// 1. The origin of this software must not be misrepresented;
14// you must not claim that you wrote the original software.
15// If you use this software in a product, an acknowledgment
16// in the product documentation would be appreciated but is not required.
17//
18// 2. Altered source versions must be plainly marked as such,
19// and must not be misrepresented as being the original software.
20//
21// 3. This notice may not be removed or altered from any source distribution.
22//
24
26// Headers
28#include <SFML/Audio/SoundBuffer.hpp>
29#include <SFML/Audio/SoundFile.hpp>
30#include <SFML/Audio/Sound.hpp>
31#include <SFML/Audio/AudioDevice.hpp>
32#include <SFML/Audio/OpenAL.hpp>
33#include <iostream>
34#include <memory>
35
36
37namespace sf
38{
43myBuffer (0),
44myDuration(0.f)
45{
46 // Create the buffer
47 ALCheck(alGenBuffers(1, &myBuffer));
48}
49
50
55AudioResource (Copy),
57myBuffer (0),
58mySamples (Copy.mySamples),
59myDuration (Copy.myDuration),
60mySounds () // don't copy the attached sounds
61{
62 // Create the buffer
63 ALCheck(alGenBuffers(1, &myBuffer));
64
65 // Update the internal buffer with the new samples
66 Update(Copy.GetChannelsCount(), Copy.GetSampleRate());
67}
68
69
74{
75 // First detach the buffer from the sounds that use it (to avoid OpenAL errors)
76 for (SoundList::const_iterator it = mySounds.begin(); it != mySounds.end(); ++it)
77 (*it)->ResetBuffer();
78
79 // Destroy the buffer
80 if (myBuffer)
81 ALCheck(alDeleteBuffers(1, &myBuffer));
82}
83
84
88bool SoundBuffer::LoadFromFile(const std::string& Filename)
89{
90 // Create the sound file
91 std::auto_ptr<priv::SoundFile> File(priv::SoundFile::CreateRead(Filename));
92
93 // Open the sound file
94 if (File.get())
95 {
96 // Get the sound parameters
97 std::size_t NbSamples = File->GetSamplesCount();
98 unsigned int ChannelsCount = File->GetChannelsCount();
99 unsigned int SampleRate = File->GetSampleRate();
100
101 // Read the samples from the opened file
102 mySamples.resize(NbSamples);
103 if (File->Read(&mySamples[0], NbSamples) == NbSamples)
104 {
105 // Update the internal buffer with the new samples
106 return Update(ChannelsCount, SampleRate);
107 }
108 else
109 {
110 // Error...
111 std::cerr << "Failed to read audio data from file \"" << Filename << "\"" << std::endl;
112
113 return false;
114 }
115 }
116 else
117 {
118 // Error...
119 std::cerr << "Failed to load sound buffer from file \"" << Filename << "\"" << std::endl;
120
121 return false;
122 }
123}
124
125
129bool SoundBuffer::LoadFromMemory(const char* Data, std::size_t SizeInBytes)
130{
131 // Create the sound file
132 std::auto_ptr<priv::SoundFile> File(priv::SoundFile::CreateRead(Data, SizeInBytes));
133
134 // Open the sound file
135 if (File.get())
136 {
137 // Get the sound parameters
138 std::size_t NbSamples = File->GetSamplesCount();
139 unsigned int ChannelsCount = File->GetChannelsCount();
140 unsigned int SampleRate = File->GetSampleRate();
141
142 // Read the samples from the opened file
143 mySamples.resize(NbSamples);
144 if (File->Read(&mySamples[0], NbSamples) == NbSamples)
145 {
146 // Update the internal buffer with the new samples
147 return Update(ChannelsCount, SampleRate);
148 }
149 else
150 {
151 // Error...
152 std::cerr << "Failed to read audio data from file in memory" << std::endl;
153
154 return false;
155 }
156 }
157 else
158 {
159 // Error...
160 std::cerr << "Failed to load sound buffer from file in memory" << std::endl;
161
162 return false;
163 }
164}
165
166
171bool SoundBuffer::LoadFromSamples(const Int16* Samples, std::size_t SamplesCount, unsigned int ChannelsCount, unsigned int SampleRate)
172{
173 if (Samples && SamplesCount && ChannelsCount && SampleRate)
174 {
175 // Copy the new audio samples
176 mySamples.assign(Samples, Samples + SamplesCount);
177
178 // Update the internal buffer with the new samples
179 return Update(ChannelsCount, SampleRate);
180 }
181 else
182 {
183 // Error...
184 std::cerr << "Failed to load sound buffer from memory ("
185 << "Samples : " << Samples << ", "
186 << "Samples count : " << SamplesCount << ", "
187 << "Channels count : " << ChannelsCount << ", "
188 << "Sample rate : " << SampleRate << ")"
189 << std::endl;
190
191 return false;
192 }
193}
194
195
199bool SoundBuffer::SaveToFile(const std::string& Filename) const
200{
201 // Create the sound file in write mode
202 std::auto_ptr<priv::SoundFile> File(priv::SoundFile::CreateWrite(Filename, GetChannelsCount(), GetSampleRate()));
203 if (File.get())
204 {
205 // Write the samples to the opened file
206 File->Write(&mySamples[0], mySamples.size());
207
208 return true;
209 }
210 else
211 {
212 // Error...
213 std::cerr << "Failed to save sound buffer to file \"" << Filename << "\"" << std::endl;
214
215 return false;
216 }
217}
218
219
223const Int16* SoundBuffer::GetSamples() const
224{
225 return mySamples.empty() ? NULL : &mySamples[0];
226}
227
228
233{
234 return mySamples.size();
235}
236
237
241unsigned int SoundBuffer::GetSampleRate() const
242{
243 ALint SampleRate;
244 ALCheck(alGetBufferi(myBuffer, AL_FREQUENCY, &SampleRate));
245
246 return SampleRate;
247}
248
249
254{
255 ALint ChannelsCount;
256 ALCheck(alGetBufferi(myBuffer, AL_CHANNELS, &ChannelsCount));
257
258 return ChannelsCount;
259}
260
261
266{
267 return myDuration;
268}
269
270
275{
276 SoundBuffer Temp(Other);
277
278 std::swap(mySamples, Temp.mySamples);
279 std::swap(myBuffer, Temp.myBuffer);
280 std::swap(myDuration, Temp.myDuration);
281 std::swap(mySounds, Temp.mySounds); // swap sounds too, so that they are detached when Temp is destroyed
282
283 return *this;
284}
285
286
290bool SoundBuffer::Update(unsigned int ChannelsCount, unsigned int SampleRate)
291{
292 // Check parameters
293 if (!SampleRate || !ChannelsCount || mySamples.empty())
294 return false;
295
296 // Find the good format according to the number of channels
297 ALenum Format = priv::AudioDevice::GetInstance().GetFormatFromChannelsCount(ChannelsCount);
298
299 // Check if the format is valid
300 if (Format == 0)
301 {
302 std::cerr << "Unsupported number of channels (" << ChannelsCount << ")" << std::endl;
303 return false;
304 }
305
306 // Fill the buffer
307 ALsizei Size = static_cast<ALsizei>(mySamples.size()) * sizeof(Int16);
308 ALCheck(alBufferData(myBuffer, Format, &mySamples[0], Size, SampleRate));
309
310 // Compute the duration
311 myDuration = static_cast<float>(mySamples.size()) / SampleRate / ChannelsCount;
312
313 return true;
314}
315
316
320void SoundBuffer::AttachSound(Sound* Instance) const
321{
322 mySounds.insert(Instance);
323}
324
325
329void SoundBuffer::DetachSound(Sound* Instance) const
330{
331 mySounds.erase(Instance);
332}
333
334} // namespace sf
AudioResource()
Default constructor.
SoundBuffer()
Default constructor.
bool LoadFromFile(const std::string &Filename)
Load the sound buffer from a file.
bool SaveToFile(const std::string &Filename) const
Save the sound buffer to a file.
unsigned int GetSampleRate() const
Get the sample rate.
const Int16 * GetSamples() const
Return the sound samples.
bool LoadFromSamples(const Int16 *Samples, std::size_t SamplesCount, unsigned int ChannelsCount, unsigned int SampleRate)
Load the sound buffer from an array of samples - assumed format for samples is 16 bits signed integer...
bool LoadFromMemory(const char *Data, std::size_t SizeInBytes)
Load the sound buffer from a file in memory.
std::size_t GetSamplesCount() const
Return the samples count.
SoundBuffer & operator=(const SoundBuffer &Other)
Assignment operator.
~SoundBuffer()
Destructor.
float GetDuration() const
Get the sound duration.
unsigned int GetChannelsCount() const
Return the number of channels (1 = mono, 2 = stereo, ...).
Sound defines the properties of a sound such as position, volume, pitch, etc.
Definition Sound.hpp:46