Merge branch 'bugfix/al_context'

This commit is contained in:
Lukas Dürrenberger 2014-12-30 10:44:08 +01:00
commit d4e6b84afc
14 changed files with 372 additions and 77 deletions

View File

@ -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.
///
////////////////////////////////////////////////////////////

View File

@ -29,6 +29,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp> #include <SFML/Audio/Export.hpp>
#include <SFML/Audio/AlResource.hpp>
#include <SFML/System/Time.hpp> #include <SFML/System/Time.hpp>
#include <string> #include <string>
#include <vector> #include <vector>
@ -49,7 +50,7 @@ class InputStream;
/// \brief Storage for audio samples defining a sound /// \brief Storage for audio samples defining a sound
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class SFML_AUDIO_API SoundBuffer class SFML_AUDIO_API SoundBuffer : AlResource
{ {
public: public:

View File

@ -29,6 +29,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp> #include <SFML/Audio/Export.hpp>
#include <SFML/Audio/AlResource.hpp>
#include <SFML/System/Thread.hpp> #include <SFML/System/Thread.hpp>
#include <SFML/System/Time.hpp> #include <SFML/System/Time.hpp>
#include <vector> #include <vector>
@ -41,7 +42,7 @@ namespace sf
/// \brief Abstract base class for capturing sound data /// \brief Abstract base class for capturing sound data
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class SFML_AUDIO_API SoundRecorder class SFML_AUDIO_API SoundRecorder : AlResource
{ {
public: public:

View File

@ -29,6 +29,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp> #include <SFML/Audio/Export.hpp>
#include <SFML/Audio/AlResource.hpp>
#include <SFML/System/Vector3.hpp> #include <SFML/System/Vector3.hpp>
@ -38,7 +39,7 @@ namespace sf
/// \brief Base class defining a sound's properties /// \brief Base class defining a sound's properties
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class SFML_AUDIO_API SoundSource class SFML_AUDIO_API SoundSource : AlResource
{ {
public: public:

View File

@ -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 priv
} // namespace sf } // namespace sf

View File

@ -64,12 +64,6 @@ namespace priv
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void alCheckError(const std::string& file, unsigned int line); void alCheckError(const std::string& file, unsigned int line);
////////////////////////////////////////////////////////////
/// Make sure that OpenAL is initialized
///
////////////////////////////////////////////////////////////
void ensureALInit();
} // namespace priv } // namespace priv
} // namespace sf } // namespace sf

View File

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

View File

@ -29,12 +29,18 @@
#include <SFML/Audio/ALCheck.hpp> #include <SFML/Audio/ALCheck.hpp>
#include <SFML/Audio/Listener.hpp> #include <SFML/Audio/Listener.hpp>
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
#include <memory>
namespace namespace
{ {
ALCdevice* audioDevice = NULL; ALCdevice* audioDevice = NULL;
ALCcontext* audioContext = 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 namespace sf
@ -56,6 +62,17 @@ AudioDevice::AudioDevice()
{ {
// Set the context as the current one (we'll only need one) // Set the context as the current one (we'll only need one)
alcMakeContextCurrent(audioContext); 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 else
{ {
@ -86,7 +103,13 @@ AudioDevice::~AudioDevice()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool AudioDevice::isExtensionSupported(const std::string& extension) bool AudioDevice::isExtensionSupported(const std::string& extension)
{ {
ensureALInit(); // Create a temporary audio device in case none exists yet.
// This device will not be used in this function and merely
// makes sure there is a valid OpenAL device for extension
// queries if none has been created yet.
std::auto_ptr<AudioDevice> device;
if (!audioDevice)
device.reset(new AudioDevice);
if ((extension.length() > 2) && (extension.substr(0, 3) == "ALC")) if ((extension.length() > 2) && (extension.substr(0, 3) == "ALC"))
return alcIsExtensionPresent(audioDevice, extension.c_str()) != AL_FALSE; return alcIsExtensionPresent(audioDevice, extension.c_str()) != AL_FALSE;
@ -98,7 +121,13 @@ bool AudioDevice::isExtensionSupported(const std::string& extension)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
int AudioDevice::getFormatFromChannelCount(unsigned int channelCount) int AudioDevice::getFormatFromChannelCount(unsigned int channelCount)
{ {
ensureALInit(); // Create a temporary audio device in case none exists yet.
// This device will not be used in this function and merely
// makes sure there is a valid OpenAL device for format
// queries if none has been created yet.
std::auto_ptr<AudioDevice> device;
if (!audioDevice)
device.reset(new AudioDevice);
// Find the good format according to the number of channels // Find the good format according to the number of channels
int format = 0; int format = 0;
@ -120,6 +149,80 @@ int AudioDevice::getFormatFromChannelCount(unsigned int channelCount)
return format; return format;
} }
////////////////////////////////////////////////////////////
void AudioDevice::setGlobalVolume(float volume)
{
if (audioContext)
alCheck(alListenerf(AL_GAIN, volume * 0.01f));
listenerVolume = volume;
}
////////////////////////////////////////////////////////////
float AudioDevice::getGlobalVolume()
{
return listenerVolume;
}
////////////////////////////////////////////////////////////
void AudioDevice::setPosition(const Vector3f& position)
{
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 (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 (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 priv
} // namespace sf } // namespace sf

View File

@ -28,6 +28,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/System/Vector3.hpp>
#include <set> #include <set>
#include <string> #include <string>
@ -81,6 +82,106 @@ public:
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static int getFormatFromChannelCount(unsigned int channelCount); static int getFormatFromChannelCount(unsigned int channelCount);
////////////////////////////////////////////////////////////
/// \brief Change the global volume of all the sounds and musics
///
/// The volume is a number between 0 and 100; it is combined with
/// the individual volume of each sound / music.
/// The default value for the volume is 100 (maximum).
///
/// \param volume New global volume, in the range [0, 100]
///
/// \see getGlobalVolume
///
////////////////////////////////////////////////////////////
static void setGlobalVolume(float volume);
////////////////////////////////////////////////////////////
/// \brief Get the current value of the global volume
///
/// \return Current global volume, in the range [0, 100]
///
/// \see setGlobalVolume
///
////////////////////////////////////////////////////////////
static float getGlobalVolume();
////////////////////////////////////////////////////////////
/// \brief Set the position of the listener in the scene
///
/// The default listener's position is (0, 0, 0).
///
/// \param position New listener's position
///
/// \see getPosition, setDirection
///
////////////////////////////////////////////////////////////
static void setPosition(const Vector3f& position);
////////////////////////////////////////////////////////////
/// \brief Get the current position of the listener in the scene
///
/// \return Listener's position
///
/// \see setPosition
///
////////////////////////////////////////////////////////////
static Vector3f getPosition();
////////////////////////////////////////////////////////////
/// \brief Set the forward vector of the listener in the scene
///
/// The direction (also called "at vector") is the vector
/// pointing forward from the listener's perspective. Together
/// with the up vector, it defines the 3D orientation of the
/// listener in the scene. The direction vector doesn't
/// have to be normalized.
/// The default listener's direction is (0, 0, -1).
///
/// \param direction New listener's direction
///
/// \see getDirection, setUpVector, setPosition
///
////////////////////////////////////////////////////////////
static void setDirection(const Vector3f& direction);
////////////////////////////////////////////////////////////
/// \brief Get the current forward vector of the listener in the scene
///
/// \return Listener's forward vector (not normalized)
///
/// \see setDirection
///
////////////////////////////////////////////////////////////
static Vector3f getDirection();
////////////////////////////////////////////////////////////
/// \brief Set the upward vector of the listener in the scene
///
/// The up vector is the vector that points upward from the
/// listener's perspective. Together with the direction, it
/// defines the 3D orientation of the listener in the scene.
/// The up vector doesn't have to be normalized.
/// The default listener's up vector is (0, 1, 0). It is usually
/// not necessary to change it, especially in 2D scenarios.
///
/// \param upVector New listener's up vector
///
/// \see getUpVector, setDirection, setPosition
///
////////////////////////////////////////////////////////////
static void setUpVector(const Vector3f& upVector);
////////////////////////////////////////////////////////////
/// \brief Get the current upward vector of the listener in the scene
///
/// \return Listener's upward vector (not normalized)
///
/// \see setUpVector
///
////////////////////////////////////////////////////////////
static Vector3f getUpVector();
}; };
} // namespace priv } // namespace priv

View File

@ -6,6 +6,8 @@ set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Audio)
set(SRC set(SRC
${SRCROOT}/ALCheck.cpp ${SRCROOT}/ALCheck.cpp
${SRCROOT}/ALCheck.hpp ${SRCROOT}/ALCheck.hpp
${SRCROOT}/AlResource.cpp
${INCROOT}/AlResource.hpp
${SRCROOT}/AudioDevice.cpp ${SRCROOT}/AudioDevice.cpp
${SRCROOT}/AudioDevice.hpp ${SRCROOT}/AudioDevice.hpp
${INCROOT}/Export.hpp ${INCROOT}/Export.hpp

View File

@ -26,16 +26,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Audio/Listener.hpp> #include <SFML/Audio/Listener.hpp>
#include <SFML/Audio/ALCheck.hpp> #include <SFML/Audio/AudioDevice.hpp>
namespace
{
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 namespace sf
@ -43,20 +34,14 @@ namespace sf
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Listener::setGlobalVolume(float volume) void Listener::setGlobalVolume(float volume)
{ {
if (volume != listenerVolume) priv::AudioDevice::setGlobalVolume(volume);
{
priv::ensureALInit();
alCheck(alListenerf(AL_GAIN, volume * 0.01f));
listenerVolume = volume;
}
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
float Listener::getGlobalVolume() float Listener::getGlobalVolume()
{ {
return listenerVolume; return priv::AudioDevice::getGlobalVolume();
} }
@ -70,20 +55,14 @@ void Listener::setPosition(float x, float y, float z)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Listener::setPosition(const Vector3f& position) void Listener::setPosition(const Vector3f& position)
{ {
if (position != listenerPosition) priv::AudioDevice::setPosition(position);
{
priv::ensureALInit();
alCheck(alListener3f(AL_POSITION, position.x, position.y, position.z));
listenerPosition = position;
}
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Vector3f Listener::getPosition() Vector3f Listener::getPosition()
{ {
return listenerPosition; return priv::AudioDevice::getPosition();
} }
@ -97,21 +76,14 @@ void Listener::setDirection(float x, float y, float z)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Listener::setDirection(const Vector3f& direction) void Listener::setDirection(const Vector3f& direction)
{ {
if (direction != listenerDirection) priv::AudioDevice::setDirection(direction);
{
priv::ensureALInit();
float orientation[] = {direction.x, direction.y, direction.z, listenerUpVector.x, listenerUpVector.y, listenerUpVector.z};
alCheck(alListenerfv(AL_ORIENTATION, orientation));
listenerDirection = direction;
}
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Vector3f Listener::getDirection() Vector3f Listener::getDirection()
{ {
return listenerDirection; return priv::AudioDevice::getDirection();
} }
@ -125,21 +97,14 @@ void Listener::setUpVector(float x, float y, float z)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Listener::setUpVector(const Vector3f& upVector) void Listener::setUpVector(const Vector3f& upVector)
{ {
if (upVector != listenerUpVector) priv::AudioDevice::setUpVector(upVector);
{
priv::ensureALInit();
float orientation[] = {listenerDirection.x, listenerDirection.y, listenerDirection.z, upVector.x, upVector.y, upVector.z};
alCheck(alListenerfv(AL_ORIENTATION, orientation));
listenerUpVector = upVector;
}
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Vector3f Listener::getUpVector() Vector3f Listener::getUpVector()
{ {
return listenerUpVector; return priv::AudioDevice::getUpVector();
} }
} // namespace sf } // namespace sf

View File

@ -41,8 +41,6 @@ SoundBuffer::SoundBuffer() :
m_buffer (0), m_buffer (0),
m_duration() m_duration()
{ {
priv::ensureALInit();
// Create the buffer // Create the buffer
alCheck(alGenBuffers(1, &m_buffer)); alCheck(alGenBuffers(1, &m_buffer));
} }

View File

@ -51,8 +51,6 @@ m_sampleRate (0),
m_processingInterval(milliseconds(100)), m_processingInterval(milliseconds(100)),
m_isCapturing (false) m_isCapturing (false)
{ {
priv::ensureALInit();
// Set the device name to the default device // Set the device name to the default device
m_deviceName = getDefaultDevice(); m_deviceName = getDefaultDevice();
} }

View File

@ -34,8 +34,6 @@ namespace sf
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SoundSource::SoundSource() SoundSource::SoundSource()
{ {
priv::ensureALInit();
alCheck(alGenSources(1, &m_source)); alCheck(alGenSources(1, &m_source));
alCheck(alSourcei(m_source, AL_BUFFER, 0)); alCheck(alSourcei(m_source, AL_BUFFER, 0));
} }
@ -44,8 +42,6 @@ SoundSource::SoundSource()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SoundSource::SoundSource(const SoundSource& copy) SoundSource::SoundSource(const SoundSource& copy)
{ {
priv::ensureALInit();
alCheck(alGenSources(1, &m_source)); alCheck(alGenSources(1, &m_source));
alCheck(alSourcei(m_source, AL_BUFFER, 0)); alCheck(alSourcei(m_source, AL_BUFFER, 0));