PageRenderTime 38ms CodeModel.GetById 28ms app.highlight 8ms RepoModel.GetById 0ms app.codeStats 0ms

/extlibs/SFML/src/SFML/Audio/SoundBuffer.cpp

https://bitbucket.org/hugoruscitti/pilascpp
C++ | 283 lines | 167 code | 51 blank | 65 comment | 19 complexity | 856309d699e5e689b5a15f4b1a4d16ba MD5 | raw file
  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//
 23////////////////////////////////////////////////////////////
 24
 25////////////////////////////////////////////////////////////
 26// Headers
 27////////////////////////////////////////////////////////////
 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/ALCheck.hpp>
 33#include <SFML/System/Err.hpp>
 34#include <memory>
 35
 36
 37namespace sf
 38{
 39////////////////////////////////////////////////////////////
 40SoundBuffer::SoundBuffer() :
 41myBuffer  (0),
 42myDuration(0.f)
 43{
 44    priv::EnsureALInit();
 45
 46    // Create the buffer
 47    ALCheck(alGenBuffers(1, &myBuffer));
 48}
 49
 50
 51////////////////////////////////////////////////////////////
 52SoundBuffer::SoundBuffer(const SoundBuffer& copy) :
 53Resource<SoundBuffer>(),
 54myBuffer             (0),
 55mySamples            (copy.mySamples),
 56myDuration           (copy.myDuration),
 57mySounds             () // don't copy the attached sounds
 58{
 59    // Create the buffer
 60    ALCheck(alGenBuffers(1, &myBuffer));
 61
 62    // Update the internal buffer with the new samples
 63    Update(copy.GetChannelsCount(), copy.GetSampleRate());
 64}
 65
 66
 67////////////////////////////////////////////////////////////
 68SoundBuffer::~SoundBuffer()
 69{
 70    // First detach the buffer from the sounds that use it (to avoid OpenAL errors)
 71    for (SoundList::const_iterator it = mySounds.begin(); it != mySounds.end(); ++it)
 72        (*it)->ResetBuffer();
 73
 74    // Destroy the buffer
 75    if (myBuffer)
 76        ALCheck(alDeleteBuffers(1, &myBuffer));
 77}
 78
 79
 80////////////////////////////////////////////////////////////
 81bool SoundBuffer::LoadFromFile(const std::string& filename)
 82{
 83    // Open the sound file
 84    priv::SoundFile file;
 85    if (file.OpenRead(filename))
 86    {
 87        // Get the sound parameters
 88        std::size_t  nbSamples     = file.GetSamplesCount();
 89        unsigned int channelsCount = file.GetChannelsCount();
 90        unsigned int sampleRate    = file.GetSampleRate();
 91
 92        // Read the samples from the opened file
 93        mySamples.resize(nbSamples);
 94        if (file.Read(&mySamples[0], nbSamples) == nbSamples)
 95        {
 96            // Update the internal buffer with the new samples
 97            return Update(channelsCount, sampleRate);
 98        }
 99        else
100        {
101            return false;
102        }
103    }
104    else
105    {
106        return false;
107    }
108}
109
110
111////////////////////////////////////////////////////////////
112bool SoundBuffer::LoadFromMemory(const void* data, std::size_t sizeInBytes)
113{
114    // Open the sound file
115    priv::SoundFile file;
116    if (file.OpenRead(data, sizeInBytes))
117    {
118        // Get the sound parameters
119        std::size_t  nbSamples     = file.GetSamplesCount();
120        unsigned int channelsCount = file.GetChannelsCount();
121        unsigned int sampleRate    = file.GetSampleRate();
122
123        // Read the samples from the opened file
124        mySamples.resize(nbSamples);
125        if (file.Read(&mySamples[0], nbSamples) == nbSamples)
126        {
127            // Update the internal buffer with the new samples
128            return Update(channelsCount, sampleRate);
129        }
130        else
131        {
132            return false;
133        }
134    }
135    else
136    {
137        return false;
138    }
139}
140
141
142////////////////////////////////////////////////////////////
143bool SoundBuffer::LoadFromSamples(const Int16* samples, std::size_t samplesCount, unsigned int channelsCount, unsigned int sampleRate)
144{
145    if (samples && samplesCount && channelsCount && sampleRate)
146    {
147        // Copy the new audio samples
148        mySamples.assign(samples, samples + samplesCount);
149
150        // Update the internal buffer with the new samples
151        return Update(channelsCount, sampleRate);
152    }
153    else
154    {
155        // Error...
156        Err() << "Failed to load sound buffer from memory ("
157              << "Samples : "        << samples       << ", "
158              << "Samples count : "  << samplesCount  << ", "
159              << "Channels count : " << channelsCount << ", "
160              << "Sample rate : "    << sampleRate    << ")"
161              << std::endl;
162
163        return false;
164    }
165}
166
167
168////////////////////////////////////////////////////////////
169bool SoundBuffer::SaveToFile(const std::string& filename) const
170{
171    // Create the sound file in write mode
172    priv::SoundFile file;
173    if (file.OpenWrite(filename, GetChannelsCount(), GetSampleRate()))
174    {
175        // Write the samples to the opened file
176        file.Write(&mySamples[0], mySamples.size());
177
178        return true;
179    }
180    else
181    {
182        return false;
183    }
184}
185
186
187////////////////////////////////////////////////////////////
188const Int16* SoundBuffer::GetSamples() const
189{
190    return mySamples.empty() ? NULL : &mySamples[0];
191}
192
193
194////////////////////////////////////////////////////////////
195std::size_t SoundBuffer::GetSamplesCount() const
196{
197    return mySamples.size();
198}
199
200
201////////////////////////////////////////////////////////////
202unsigned int SoundBuffer::GetSampleRate() const
203{
204    ALint sampleRate;
205    ALCheck(alGetBufferi(myBuffer, AL_FREQUENCY, &sampleRate));
206
207    return sampleRate;
208}
209
210
211////////////////////////////////////////////////////////////
212unsigned int SoundBuffer::GetChannelsCount() const
213{
214    ALint channelsCount;
215    ALCheck(alGetBufferi(myBuffer, AL_CHANNELS, &channelsCount));
216
217    return channelsCount;
218}
219
220
221////////////////////////////////////////////////////////////
222float SoundBuffer::GetDuration() const
223{
224    return myDuration;
225}
226
227
228////////////////////////////////////////////////////////////
229SoundBuffer& SoundBuffer::operator =(const SoundBuffer& right)
230{
231    SoundBuffer temp(right);
232
233    std::swap(mySamples,  temp.mySamples);
234    std::swap(myBuffer,   temp.myBuffer);
235    std::swap(myDuration, temp.myDuration);
236    std::swap(mySounds,   temp.mySounds); // swap sounds too, so that they are detached when temp is destroyed
237
238    return *this;
239}
240
241
242////////////////////////////////////////////////////////////
243bool SoundBuffer::Update(unsigned int channelsCount, unsigned int sampleRate)
244{
245    // Check parameters
246    if (!channelsCount || !sampleRate || mySamples.empty())
247        return false;
248
249    // Find the good format according to the number of channels
250    ALenum format = priv::AudioDevice::GetFormatFromChannelsCount(channelsCount);
251
252    // Check if the format is valid
253    if (format == 0)
254    {
255        Err() << "Unsupported number of channels (" << channelsCount << ")" << std::endl;
256        return false;
257    }
258
259    // Fill the buffer
260    ALsizei size = static_cast<ALsizei>(mySamples.size()) * sizeof(Int16);
261    ALCheck(alBufferData(myBuffer, format, &mySamples[0], size, sampleRate));
262
263    // Compute the duration
264    myDuration = static_cast<float>(mySamples.size()) / sampleRate / channelsCount;
265
266    return true;
267}
268
269
270////////////////////////////////////////////////////////////
271void SoundBuffer::AttachSound(Sound* sound) const
272{
273    mySounds.insert(sound);
274}
275
276
277////////////////////////////////////////////////////////////
278void SoundBuffer::DetachSound(Sound* sound) const
279{
280    mySounds.erase(sound);
281}
282
283} // namespace sf