FS#104 - Fix crash when destroying a SoundBuffer used by a Sound

git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/trunk@1370 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
LaurentGom 2010-01-26 09:49:03 +00:00
parent 6341b569db
commit 362f374732
4 changed files with 79 additions and 3 deletions

View File

@ -288,6 +288,15 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Sound& operator =(const Sound& Other); Sound& operator =(const Sound& Other);
////////////////////////////////////////////////////////////
/// Reset the internal buffer
///
/// This function is for internal use only, you don't have
/// to use it.
///
////////////////////////////////////////////////////////////
void ResetBuffer();
private : private :
friend class SoundStream; friend class SoundStream;

View File

@ -32,10 +32,13 @@
#include <SFML/Audio/AudioResource.hpp> #include <SFML/Audio/AudioResource.hpp>
#include <string> #include <string>
#include <vector> #include <vector>
#include <set>
namespace sf namespace sf
{ {
class Sound;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// SoundBuffer is the low-level for loading and manipulating /// SoundBuffer is the low-level for loading and manipulating
/// sound buffers /// sound buffers
@ -174,12 +177,34 @@ private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool Update(unsigned int ChannelsCount, unsigned int SampleRate); bool Update(unsigned int ChannelsCount, unsigned int SampleRate);
////////////////////////////////////////////////////////////
/// Add a sound to the list of sounds that use this buffer
///
/// \param Instance : Sound object to attach
///
////////////////////////////////////////////////////////////
void AttachSound(Sound* Instance) const;
////////////////////////////////////////////////////////////
/// Remove a sound from the list of sounds that use this buffer
///
/// \param Instance : Sound object to detach
///
////////////////////////////////////////////////////////////
void DetachSound(Sound* Instance) const;
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
typedef std::set<Sound*> SoundList; ///< Set of unique sound instances
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
unsigned int myBuffer; ///< OpenAL buffer identifier unsigned int myBuffer; ///< OpenAL buffer identifier
std::vector<Int16> mySamples; ///< Samples buffer std::vector<Int16> mySamples; ///< Samples buffer
float myDuration; ///< Sound duration, in seconds float myDuration; ///< Sound duration, in seconds
mutable SoundList mySounds; ///< List of sounds that are using this buffer
}; };
} // namespace sf } // namespace sf

View File

@ -90,6 +90,7 @@ Sound::~Sound()
{ {
Stop(); Stop();
ALCheck(alSourcei(mySource, AL_BUFFER, 0)); ALCheck(alSourcei(mySource, AL_BUFFER, 0));
myBuffer->DetachSound(this);
} }
ALCheck(alDeleteSources(1, &mySource)); ALCheck(alDeleteSources(1, &mySource));
} }
@ -129,7 +130,8 @@ void Sound::Stop()
void Sound::SetBuffer(const SoundBuffer& Buffer) void Sound::SetBuffer(const SoundBuffer& Buffer)
{ {
myBuffer = &Buffer; myBuffer = &Buffer;
ALCheck(alSourcei(mySource, AL_BUFFER, myBuffer ? myBuffer->myBuffer : 0)); myBuffer->AttachSound(this);
ALCheck(alSourcei(mySource, AL_BUFFER, myBuffer->myBuffer));
} }
@ -360,4 +362,18 @@ Sound& Sound::operator =(const Sound& Other)
return *this; return *this;
} }
////////////////////////////////////////////////////////////
/// Reset the internal buffer
////////////////////////////////////////////////////////////
void Sound::ResetBuffer()
{
// First stop the sound in case it is playing
Stop();
// Detach the buffer
ALCheck(alSourcei(mySource, AL_BUFFER, 0));
myBuffer = 0;
}
} // namespace sf } // namespace sf

View File

@ -27,6 +27,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Audio/SoundBuffer.hpp> #include <SFML/Audio/SoundBuffer.hpp>
#include <SFML/Audio/SoundFile.hpp> #include <SFML/Audio/SoundFile.hpp>
#include <SFML/Audio/Sound.hpp>
#include <SFML/Audio/AudioDevice.hpp> #include <SFML/Audio/AudioDevice.hpp>
#include <SFML/Audio/OpenAL.hpp> #include <SFML/Audio/OpenAL.hpp>
#include <iostream> #include <iostream>
@ -55,7 +56,8 @@ AudioResource (Copy),
Resource<SoundBuffer>(Copy), Resource<SoundBuffer>(Copy),
myBuffer (0), myBuffer (0),
mySamples (Copy.mySamples), mySamples (Copy.mySamples),
myDuration (Copy.myDuration) myDuration (Copy.myDuration),
mySounds () // don't copy the attached sounds
{ {
// Create the buffer // Create the buffer
ALCheck(alGenBuffers(1, &myBuffer)); ALCheck(alGenBuffers(1, &myBuffer));
@ -70,6 +72,11 @@ myDuration (Copy.myDuration)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SoundBuffer::~SoundBuffer() SoundBuffer::~SoundBuffer()
{ {
// First detach the buffer from the sounds that use it (to avoid OpenAL errors)
for (SoundList::const_iterator it = mySounds.begin(); it != mySounds.end(); ++it)
(*it)->ResetBuffer();
// Destroy the buffer
if (myBuffer) if (myBuffer)
ALCheck(alDeleteBuffers(1, &myBuffer)); ALCheck(alDeleteBuffers(1, &myBuffer));
} }
@ -268,9 +275,10 @@ SoundBuffer& SoundBuffer::operator =(const SoundBuffer& Other)
{ {
SoundBuffer Temp(Other); SoundBuffer Temp(Other);
mySamples.swap(Temp.mySamples); std::swap(mySamples, Temp.mySamples);
std::swap(myBuffer, Temp.myBuffer); std::swap(myBuffer, Temp.myBuffer);
std::swap(myDuration, Temp.myDuration); std::swap(myDuration, Temp.myDuration);
std::swap(mySounds, Temp.mySounds); // swap sounds too, so that they are detached when Temp is destroyed
return *this; return *this;
} }
@ -305,4 +313,22 @@ bool SoundBuffer::Update(unsigned int ChannelsCount, unsigned int SampleRate)
return true; return true;
} }
////////////////////////////////////////////////////////////
/// Add a sound to the list of sounds that use this buffer
////////////////////////////////////////////////////////////
void SoundBuffer::AttachSound(Sound* Instance) const
{
mySounds.insert(Instance);
}
////////////////////////////////////////////////////////////
/// Remove a sound from the list of sounds that use this buffer
////////////////////////////////////////////////////////////
void SoundBuffer::DetachSound(Sound* Instance) const
{
mySounds.erase(Instance);
}
} // namespace sf } // namespace sf