Skip to content

Commit

Permalink
Made OpenAL context management more intelligent, in analogy to OpenGL…
Browse files Browse the repository at this point in the history
… context management. OpenAL contexts now only exist as long as AlResources require them and are destroyed when they are no longer required. Fixes #30.
  • Loading branch information
binary1248 committed Jul 12, 2014
1 parent 337df1e commit c7bb5da
Show file tree
Hide file tree
Showing 14 changed files with 377 additions and 76 deletions.
70 changes: 70 additions & 0 deletions include/SFML/Audio/AlResource.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////

#ifndef SFML_ALRESOURCE_HPP
#define SFML_ALRESOURCE_HPP

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>


namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Base class for classes that require an OpenAL context
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API AlResource
{
protected :

////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
AlResource();

////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~AlResource();
};

} // namespace sf


#endif // SFML_ALRESOURCE_HPP

////////////////////////////////////////////////////////////
/// \class sf::AlResource
/// \ingroup audio
///
/// This class is for internal use only, it must be the base
/// of every class that requires a valid OpenAL context in
/// order to work.
///
////////////////////////////////////////////////////////////
3 changes: 2 additions & 1 deletion include/SFML/Audio/SoundBuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/AlResource.hpp>
#include <SFML/System/Time.hpp>
#include <string>
#include <vector>
Expand All @@ -49,7 +50,7 @@ class InputStream;
/// \brief Storage for audio samples defining a sound
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API SoundBuffer
class SFML_AUDIO_API SoundBuffer : AlResource
{
public :

Expand Down
3 changes: 2 additions & 1 deletion include/SFML/Audio/SoundRecorder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/AlResource.hpp>
#include <SFML/System/Thread.hpp>
#include <SFML/System/Time.hpp>
#include <vector>
Expand All @@ -41,7 +42,7 @@ namespace sf
/// \brief Abstract base class for capturing sound data
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API SoundRecorder
class SFML_AUDIO_API SoundRecorder : AlResource
{
public :

Expand Down
3 changes: 2 additions & 1 deletion include/SFML/Audio/SoundSource.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/AlResource.hpp>
#include <SFML/System/Vector3.hpp>


Expand All @@ -38,7 +39,7 @@ namespace sf
/// \brief Base class defining a sound's properties
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API SoundSource
class SFML_AUDIO_API SoundSource : AlResource
{
public :

Expand Down
13 changes: 0 additions & 13 deletions src/SFML/Audio/ALCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,19 +91,6 @@ void alCheckError(const std::string& file, unsigned int line)
}
}


////////////////////////////////////////////////////////////
/// Make sure that OpenAL is initialized
////////////////////////////////////////////////////////////
void ensureALInit()
{
// The audio device is instantiated on demand rather than at global startup,
// which solves a lot of weird crashes and errors.
// It is destroyed at global exit which is fine.

static AudioDevice globalDevice;
}

} // namespace priv

} // namespace sf
6 changes: 0 additions & 6 deletions src/SFML/Audio/ALCheck.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,6 @@ namespace priv
////////////////////////////////////////////////////////////
void alCheckError(const std::string& file, unsigned int line);

////////////////////////////////////////////////////////////
/// Make sure that OpenAL is initialized
///
////////////////////////////////////////////////////////////
void ensureALInit();

} // namespace priv

} // namespace sf
Expand Down
78 changes: 78 additions & 0 deletions src/SFML/Audio/AlResource.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/AlResource.hpp>
#include <SFML/Audio/AudioDevice.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>


namespace
{
// OpenAL resources counter and its mutex
unsigned int count = 0;
sf::Mutex mutex;

// The audio device is instantiated on demand rather than at global startup,
// which solves a lot of weird crashes and errors.
// It is destroyed when it is no longer needed.
sf::priv::AudioDevice* globalDevice;
}


namespace sf
{
////////////////////////////////////////////////////////////
AlResource::AlResource()
{
// Protect from concurrent access
Lock lock(mutex);

// If this is the very first resource, trigger the global device initialization
if (count == 0)
globalDevice = new priv::AudioDevice;

// Increment the resources counter
count++;
}


////////////////////////////////////////////////////////////
AlResource::~AlResource()
{
// Protect from concurrent access
Lock lock(mutex);

// Decrement the resources counter
count--;

// If there's no more resource alive, we can destroy the device
if (count == 0)
delete globalDevice;
}

} // namespace sf
113 changes: 111 additions & 2 deletions src/SFML/Audio/AudioDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,18 @@
#include <SFML/Audio/ALCheck.hpp>
#include <SFML/Audio/Listener.hpp>
#include <SFML/System/Err.hpp>
#include <memory>


namespace
{
ALCdevice* audioDevice = NULL;
ALCcontext* audioContext = NULL;

float listenerVolume = 100.f;
sf::Vector3f listenerPosition (0.f, 0.f, 0.f);
sf::Vector3f listenerDirection(0.f, 0.f, -1.f);
sf::Vector3f listenerUpVector (0.f, 1.f, 0.f);
}

namespace sf
Expand All @@ -56,6 +62,17 @@ AudioDevice::AudioDevice()
{
// Set the context as the current one (we'll only need one)
alcMakeContextCurrent(audioContext);

// Apply the listener properties the user might have set
float orientation[] = {listenerDirection.x,
listenerDirection.y,
listenerDirection.z,
listenerUpVector.x,
listenerUpVector.y,
listenerUpVector.z};
alCheck(alListenerf(AL_GAIN, listenerVolume * 0.01f));
alCheck(alListener3f(AL_POSITION, listenerPosition.x, listenerPosition.y, listenerPosition.z));
alCheck(alListenerfv(AL_ORIENTATION, orientation));
}
else
{
Expand Down Expand Up @@ -86,7 +103,10 @@ AudioDevice::~AudioDevice()
////////////////////////////////////////////////////////////
bool AudioDevice::isExtensionSupported(const std::string& extension)
{
ensureALInit();
// Create a temporary audio device in case none exists yet.
std::auto_ptr<AudioDevice> device;
if (!audioDevice)
device = std::auto_ptr<AudioDevice>(new AudioDevice);

if ((extension.length() > 2) && (extension.substr(0, 3) == "ALC"))
return alcIsExtensionPresent(audioDevice, extension.c_str()) != AL_FALSE;
Expand All @@ -98,7 +118,10 @@ bool AudioDevice::isExtensionSupported(const std::string& extension)
////////////////////////////////////////////////////////////
int AudioDevice::getFormatFromChannelCount(unsigned int channelCount)
{
ensureALInit();
// Create a temporary audio device in case none exists yet.
std::auto_ptr<AudioDevice> device;
if (!audioDevice)
device = std::auto_ptr<AudioDevice>(new AudioDevice);

// Find the good format according to the number of channels
int format = 0;
Expand All @@ -120,6 +143,92 @@ int AudioDevice::getFormatFromChannelCount(unsigned int channelCount)
return format;
}


////////////////////////////////////////////////////////////
void AudioDevice::setGlobalVolume(float volume)
{
if (volume != listenerVolume)
{
if (audioContext)
alCheck(alListenerf(AL_GAIN, volume * 0.01f));

listenerVolume = volume;
}
}


////////////////////////////////////////////////////////////
float AudioDevice::getGlobalVolume()
{
return listenerVolume;
}


////////////////////////////////////////////////////////////
void AudioDevice::setPosition(const Vector3f& position)
{
if (position != listenerPosition)
{
if (audioContext)
alCheck(alListener3f(AL_POSITION, position.x, position.y, position.z));

listenerPosition = position;
}
}


////////////////////////////////////////////////////////////
Vector3f AudioDevice::getPosition()
{
return listenerPosition;
}


////////////////////////////////////////////////////////////
void AudioDevice::setDirection(const Vector3f& direction)
{
if (direction != listenerDirection)
{
if (audioContext)
{
float orientation[] = {direction.x, direction.y, direction.z, listenerUpVector.x, listenerUpVector.y, listenerUpVector.z};
alCheck(alListenerfv(AL_ORIENTATION, orientation));
}

listenerDirection = direction;
}
}


////////////////////////////////////////////////////////////
Vector3f AudioDevice::getDirection()
{
return listenerDirection;
}


////////////////////////////////////////////////////////////
void AudioDevice::setUpVector(const Vector3f& upVector)
{
if (upVector != listenerUpVector)
{
if (audioContext)
{
float orientation[] = {listenerDirection.x, listenerDirection.y, listenerDirection.z, upVector.x, upVector.y, upVector.z};
alCheck(alListenerfv(AL_ORIENTATION, orientation));
}

listenerUpVector = upVector;
}
}


////////////////////////////////////////////////////////////
Vector3f AudioDevice::getUpVector()
{
return listenerUpVector;
}

} // namespace priv

} // namespace sf
Loading

0 comments on commit c7bb5da

Please sign in to comment.