summaryrefslogtreecommitdiff
path: root/src/SFML/Audio
diff options
context:
space:
mode:
Diffstat (limited to 'src/SFML/Audio')
-rw-r--r--src/SFML/Audio/ALCheck.cpp218
-rw-r--r--src/SFML/Audio/ALCheck.hpp156
-rw-r--r--src/SFML/Audio/AudioDevice.cpp250
-rw-r--r--src/SFML/Audio/AudioDevice.hpp182
-rw-r--r--src/SFML/Audio/CMakeLists.txt118
-rw-r--r--src/SFML/Audio/Listener.cpp256
-rw-r--r--src/SFML/Audio/Music.cpp302
-rw-r--r--src/SFML/Audio/Sound.cpp396
-rw-r--r--src/SFML/Audio/SoundBuffer.cpp561
-rw-r--r--src/SFML/Audio/SoundBufferRecorder.cpp136
-rw-r--r--src/SFML/Audio/SoundFile.cpp876
-rw-r--r--src/SFML/Audio/SoundFile.hpp459
-rw-r--r--src/SFML/Audio/SoundRecorder.cpp493
-rw-r--r--src/SFML/Audio/SoundSource.cpp388
-rw-r--r--src/SFML/Audio/SoundStream.cpp834
15 files changed, 2953 insertions, 2672 deletions
diff --git a/src/SFML/Audio/ALCheck.cpp b/src/SFML/Audio/ALCheck.cpp
index 0558f11..1a7e4bb 100644
--- a/src/SFML/Audio/ALCheck.cpp
+++ b/src/SFML/Audio/ALCheck.cpp
@@ -1,109 +1,109 @@
-////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 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/ALCheck.hpp>
-#include <SFML/Audio/AudioDevice.hpp>
-#include <SFML/System/Err.hpp>
-
-
-namespace sf
-{
-namespace priv
-{
-////////////////////////////////////////////////////////////
-void alCheckError(const std::string& file, unsigned int line)
-{
- // Get the last error
- ALenum errorCode = alGetError();
-
- if (errorCode != AL_NO_ERROR)
- {
- std::string error, description;
-
- // Decode the error code
- switch (errorCode)
- {
- case AL_INVALID_NAME :
- {
- error = "AL_INVALID_NAME";
- description = "an unacceptable name has been specified";
- break;
- }
-
- case AL_INVALID_ENUM :
- {
- error = "AL_INVALID_ENUM";
- description = "an unacceptable value has been specified for an enumerated argument";
- break;
- }
-
- case AL_INVALID_VALUE :
- {
- error = "AL_INVALID_VALUE";
- description = "a numeric argument is out of range";
- break;
- }
-
- case AL_INVALID_OPERATION :
- {
- error = "AL_INVALID_OPERATION";
- description = "the specified operation is not allowed in the current state";
- break;
- }
-
- case AL_OUT_OF_MEMORY :
- {
- error = "AL_OUT_OF_MEMORY";
- description = "there is not enough memory left to execute the command";
- break;
- }
- }
-
- // Log the error
- err() << "An internal OpenAL call failed in "
- << file.substr(file.find_last_of("\\/") + 1) << " (" << line << ") : "
- << error << ", " << description
- << std::endl;
- }
-}
-
-
-////////////////////////////////////////////////////////////
-/// Make sure that OpenAL is initialized
-////////////////////////////////////////////////////////////
-void ensureALInit()
-{
- // The audio device is instanciated 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
+////////////////////////////////////////////////////////////
+//
+// 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/ALCheck.hpp>
+#include <SFML/Audio/AudioDevice.hpp>
+#include <SFML/System/Err.hpp>
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+void alCheckError(const std::string& file, unsigned int line)
+{
+ // Get the last error
+ ALenum errorCode = alGetError();
+
+ if (errorCode != AL_NO_ERROR)
+ {
+ std::string error, description;
+
+ // Decode the error code
+ switch (errorCode)
+ {
+ case AL_INVALID_NAME:
+ {
+ error = "AL_INVALID_NAME";
+ description = "an unacceptable name has been specified";
+ break;
+ }
+
+ case AL_INVALID_ENUM:
+ {
+ error = "AL_INVALID_ENUM";
+ description = "an unacceptable value has been specified for an enumerated argument";
+ break;
+ }
+
+ case AL_INVALID_VALUE:
+ {
+ error = "AL_INVALID_VALUE";
+ description = "a numeric argument is out of range";
+ break;
+ }
+
+ case AL_INVALID_OPERATION:
+ {
+ error = "AL_INVALID_OPERATION";
+ description = "the specified operation is not allowed in the current state";
+ break;
+ }
+
+ case AL_OUT_OF_MEMORY:
+ {
+ error = "AL_OUT_OF_MEMORY";
+ description = "there is not enough memory left to execute the command";
+ break;
+ }
+ }
+
+ // Log the error
+ err() << "An internal OpenAL call failed in "
+ << file.substr(file.find_last_of("\\/") + 1) << " (" << line << ") : "
+ << error << ", " << description
+ << std::endl;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+/// 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
diff --git a/src/SFML/Audio/ALCheck.hpp b/src/SFML/Audio/ALCheck.hpp
index 7c7d659..b31a031 100644
--- a/src/SFML/Audio/ALCheck.hpp
+++ b/src/SFML/Audio/ALCheck.hpp
@@ -1,78 +1,78 @@
-////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 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_ALCHECK_HPP
-#define SFML_ALCHECK_HPP
-
-////////////////////////////////////////////////////////////
-// Headers
-////////////////////////////////////////////////////////////
-#include <SFML/Config.hpp>
-#include <iostream>
-#include <string>
-#include <al.h>
-#include <alc.h>
-
-
-namespace sf
-{
-namespace priv
-{
-////////////////////////////////////////////////////////////
-/// Let's define a macro to quickly check every OpenAL API calls
-////////////////////////////////////////////////////////////
-#ifdef SFML_DEBUG
-
- // If in debug mode, perform a test on every call
- #define alCheck(Func) ((Func), priv::alCheckError(__FILE__, __LINE__))
-
-#else
-
- // Else, we don't add any overhead
- #define alCheck(Func) (Func)
-
-#endif
-
-
-////////////////////////////////////////////////////////////
-/// Check the last OpenAL error
-///
-/// \param file Source file where the call is located
-/// \param line Line number of the source file where the call is located
-///
-////////////////////////////////////////////////////////////
-void alCheckError(const std::string& file, unsigned int line);
-
-////////////////////////////////////////////////////////////
-/// Make sure that OpenAL is initialized
-///
-////////////////////////////////////////////////////////////
-void ensureALInit();
-
-} // namespace priv
-
-} // namespace sf
-
-
-#endif // SFML_ALCHECK_HPP
+////////////////////////////////////////////////////////////
+//
+// 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_ALCHECK_HPP
+#define SFML_ALCHECK_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Config.hpp>
+#include <iostream>
+#include <string>
+#include <al.h>
+#include <alc.h>
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// Let's define a macro to quickly check every OpenAL API calls
+////////////////////////////////////////////////////////////
+#ifdef SFML_DEBUG
+
+ // If in debug mode, perform a test on every call
+ #define alCheck(x) x; sf::priv::alCheckError(__FILE__, __LINE__);
+
+#else
+
+ // Else, we don't add any overhead
+ #define alCheck(Func) (Func)
+
+#endif
+
+
+////////////////////////////////////////////////////////////
+/// Check the last OpenAL error
+///
+/// \param file Source file where the call is located
+/// \param line Line number of the source file where the call is located
+///
+////////////////////////////////////////////////////////////
+void alCheckError(const std::string& file, unsigned int line);
+
+////////////////////////////////////////////////////////////
+/// Make sure that OpenAL is initialized
+///
+////////////////////////////////////////////////////////////
+void ensureALInit();
+
+} // namespace priv
+
+} // namespace sf
+
+
+#endif // SFML_ALCHECK_HPP
diff --git a/src/SFML/Audio/AudioDevice.cpp b/src/SFML/Audio/AudioDevice.cpp
index d218b91..2c9b833 100644
--- a/src/SFML/Audio/AudioDevice.cpp
+++ b/src/SFML/Audio/AudioDevice.cpp
@@ -1,125 +1,125 @@
-////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 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/AudioDevice.hpp>
-#include <SFML/Audio/ALCheck.hpp>
-#include <SFML/Audio/Listener.hpp>
-#include <SFML/System/Err.hpp>
-
-
-namespace
-{
- ALCdevice* audioDevice = NULL;
- ALCcontext* audioContext = NULL;
-}
-
-namespace sf
-{
-namespace priv
-{
-////////////////////////////////////////////////////////////
-AudioDevice::AudioDevice()
-{
- // Create the device
- audioDevice = alcOpenDevice(NULL);
-
- if (audioDevice)
- {
- // Create the context
- audioContext = alcCreateContext(audioDevice, NULL);
-
- if (audioContext)
- {
- // Set the context as the current one (we'll only need one)
- alcMakeContextCurrent(audioContext);
- }
- else
- {
- err() << "Failed to create the audio context" << std::endl;
- }
- }
- else
- {
- err() << "Failed to open the audio device" << std::endl;
- }
-}
-
-
-////////////////////////////////////////////////////////////
-AudioDevice::~AudioDevice()
-{
- // Destroy the context
- alcMakeContextCurrent(NULL);
- if (audioContext)
- alcDestroyContext(audioContext);
-
- // Destroy the device
- if (audioDevice)
- alcCloseDevice(audioDevice);
-}
-
-
-////////////////////////////////////////////////////////////
-bool AudioDevice::isExtensionSupported(const std::string& extension)
-{
- ensureALInit();
-
- if ((extension.length() > 2) && (extension.substr(0, 3) == "ALC"))
- return alcIsExtensionPresent(audioDevice, extension.c_str()) != AL_FALSE;
- else
- return alIsExtensionPresent(extension.c_str()) != AL_FALSE;
-}
-
-
-////////////////////////////////////////////////////////////
-int AudioDevice::getFormatFromChannelCount(unsigned int channelCount)
-{
- ensureALInit();
-
- // Find the good format according to the number of channels
- int format = 0;
- switch (channelCount)
- {
- case 1 : format = AL_FORMAT_MONO16; break;
- case 2 : format = AL_FORMAT_STEREO16; break;
- case 4 : format = alGetEnumValue("AL_FORMAT_QUAD16"); break;
- case 6 : format = alGetEnumValue("AL_FORMAT_51CHN16"); break;
- case 7 : format = alGetEnumValue("AL_FORMAT_61CHN16"); break;
- case 8 : format = alGetEnumValue("AL_FORMAT_71CHN16"); break;
- default : format = 0; break;
- }
-
- // Fixes a bug on OS X
- if (format == -1)
- format = 0;
-
- return format;
-}
-
-} // namespace priv
-
-} // namespace sf
+////////////////////////////////////////////////////////////
+//
+// 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/AudioDevice.hpp>
+#include <SFML/Audio/ALCheck.hpp>
+#include <SFML/Audio/Listener.hpp>
+#include <SFML/System/Err.hpp>
+
+
+namespace
+{
+ ALCdevice* audioDevice = NULL;
+ ALCcontext* audioContext = NULL;
+}
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+AudioDevice::AudioDevice()
+{
+ // Create the device
+ audioDevice = alcOpenDevice(NULL);
+
+ if (audioDevice)
+ {
+ // Create the context
+ audioContext = alcCreateContext(audioDevice, NULL);
+
+ if (audioContext)
+ {
+ // Set the context as the current one (we'll only need one)
+ alcMakeContextCurrent(audioContext);
+ }
+ else
+ {
+ err() << "Failed to create the audio context" << std::endl;
+ }
+ }
+ else
+ {
+ err() << "Failed to open the audio device" << std::endl;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+AudioDevice::~AudioDevice()
+{
+ // Destroy the context
+ alcMakeContextCurrent(NULL);
+ if (audioContext)
+ alcDestroyContext(audioContext);
+
+ // Destroy the device
+ if (audioDevice)
+ alcCloseDevice(audioDevice);
+}
+
+
+////////////////////////////////////////////////////////////
+bool AudioDevice::isExtensionSupported(const std::string& extension)
+{
+ ensureALInit();
+
+ if ((extension.length() > 2) && (extension.substr(0, 3) == "ALC"))
+ return alcIsExtensionPresent(audioDevice, extension.c_str()) != AL_FALSE;
+ else
+ return alIsExtensionPresent(extension.c_str()) != AL_FALSE;
+}
+
+
+////////////////////////////////////////////////////////////
+int AudioDevice::getFormatFromChannelCount(unsigned int channelCount)
+{
+ ensureALInit();
+
+ // Find the good format according to the number of channels
+ int format = 0;
+ switch (channelCount)
+ {
+ case 1: format = AL_FORMAT_MONO16; break;
+ case 2: format = AL_FORMAT_STEREO16; break;
+ case 4: format = alGetEnumValue("AL_FORMAT_QUAD16"); break;
+ case 6: format = alGetEnumValue("AL_FORMAT_51CHN16"); break;
+ case 7: format = alGetEnumValue("AL_FORMAT_61CHN16"); break;
+ case 8: format = alGetEnumValue("AL_FORMAT_71CHN16"); break;
+ default: format = 0; break;
+ }
+
+ // Fixes a bug on OS X
+ if (format == -1)
+ format = 0;
+
+ return format;
+}
+
+} // namespace priv
+
+} // namespace sf
diff --git a/src/SFML/Audio/AudioDevice.hpp b/src/SFML/Audio/AudioDevice.hpp
index 01c7b4c..85c121b 100644
--- a/src/SFML/Audio/AudioDevice.hpp
+++ b/src/SFML/Audio/AudioDevice.hpp
@@ -1,91 +1,91 @@
-////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 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_AUDIODEVICE_HPP
-#define SFML_AUDIODEVICE_HPP
-
-////////////////////////////////////////////////////////////
-// Headers
-////////////////////////////////////////////////////////////
-#include <set>
-#include <string>
-
-
-namespace sf
-{
-namespace priv
-{
-////////////////////////////////////////////////////////////
-/// \brief High-level wrapper around the audio API, it manages
-/// the creation and destruction of the audio device and
-/// context and stores the device capabilities
-///
-////////////////////////////////////////////////////////////
-class AudioDevice
-{
-public :
-
- ////////////////////////////////////////////////////////////
- /// \brief Default constructor
- ///
- ////////////////////////////////////////////////////////////
- AudioDevice();
-
- ////////////////////////////////////////////////////////////
- /// \brief Destructor
- ///
- ////////////////////////////////////////////////////////////
- ~AudioDevice();
-
- ////////////////////////////////////////////////////////////
- /// \brief Check if an OpenAL extension is supported
- ///
- /// This functions automatically finds whether it
- /// is an AL or ALC extension, and calls the corresponding
- /// function.
- ///
- /// \param extension Name of the extension to test
- ///
- /// \return True if the extension is supported, false if not
- ///
- ////////////////////////////////////////////////////////////
- static bool isExtensionSupported(const std::string& extension);
-
- ////////////////////////////////////////////////////////////
- /// \brief Get the OpenAL format that matches the given number of channels
- ///
- /// \param channelCount Number of channels
- ///
- /// \return Corresponding format
- ///
- ////////////////////////////////////////////////////////////
- static int getFormatFromChannelCount(unsigned int channelCount);
-};
-
-} // namespace priv
-
-} // namespace sf
-
-
-#endif // SFML_AUDIODEVICE_HPP
+////////////////////////////////////////////////////////////
+//
+// 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_AUDIODEVICE_HPP
+#define SFML_AUDIODEVICE_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <set>
+#include <string>
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// \brief High-level wrapper around the audio API, it manages
+/// the creation and destruction of the audio device and
+/// context and stores the device capabilities
+///
+////////////////////////////////////////////////////////////
+class AudioDevice
+{
+public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Default constructor
+ ///
+ ////////////////////////////////////////////////////////////
+ AudioDevice();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Destructor
+ ///
+ ////////////////////////////////////////////////////////////
+ ~AudioDevice();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Check if an OpenAL extension is supported
+ ///
+ /// This functions automatically finds whether it
+ /// is an AL or ALC extension, and calls the corresponding
+ /// function.
+ ///
+ /// \param extension Name of the extension to test
+ ///
+ /// \return True if the extension is supported, false if not
+ ///
+ ////////////////////////////////////////////////////////////
+ static bool isExtensionSupported(const std::string& extension);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the OpenAL format that matches the given number of channels
+ ///
+ /// \param channelCount Number of channels
+ ///
+ /// \return Corresponding format
+ ///
+ ////////////////////////////////////////////////////////////
+ static int getFormatFromChannelCount(unsigned int channelCount);
+};
+
+} // namespace priv
+
+} // namespace sf
+
+
+#endif // SFML_AUDIODEVICE_HPP
diff --git a/src/SFML/Audio/CMakeLists.txt b/src/SFML/Audio/CMakeLists.txt
index 818b9b6..ee7b7cb 100644
--- a/src/SFML/Audio/CMakeLists.txt
+++ b/src/SFML/Audio/CMakeLists.txt
@@ -1,53 +1,65 @@
-
-set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Audio)
-set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Audio)
-
-# all source files
-set(SRC
- ${SRCROOT}/ALCheck.cpp
- ${SRCROOT}/ALCheck.hpp
- ${SRCROOT}/AudioDevice.cpp
- ${SRCROOT}/AudioDevice.hpp
- ${INCROOT}/Export.hpp
- ${SRCROOT}/Listener.cpp
- ${INCROOT}/Listener.hpp
- ${SRCROOT}/Music.cpp
- ${INCROOT}/Music.hpp
- ${SRCROOT}/Sound.cpp
- ${INCROOT}/Sound.hpp
- ${SRCROOT}/SoundBuffer.cpp
- ${INCROOT}/SoundBuffer.hpp
- ${SRCROOT}/SoundBufferRecorder.cpp
- ${INCROOT}/SoundBufferRecorder.hpp
- ${SRCROOT}/SoundFile.cpp
- ${SRCROOT}/SoundFile.hpp
- ${SRCROOT}/SoundRecorder.cpp
- ${INCROOT}/SoundRecorder.hpp
- ${SRCROOT}/SoundSource.cpp
- ${INCROOT}/SoundSource.hpp
- ${SRCROOT}/SoundStream.cpp
- ${INCROOT}/SoundStream.hpp
-)
-source_group("" FILES ${SRC})
-
-# let CMake know about our additional audio libraries paths (on Windows and OSX)
-if(WINDOWS)
- set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/AL")
- set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/windows")
-elseif (MACOSX)
- set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/osx")
- set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/Frameworks")
-endif()
-
-# find external libraries
-find_package(OpenAL REQUIRED)
-find_package(Sndfile REQUIRED)
-
-# add include paths of external libraries
-include_directories(${OPENAL_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR})
-
-# define the sfml-audio target
-sfml_add_library(sfml-audio
- SOURCES ${SRC}
- DEPENDS sfml-system
- EXTERNAL_LIBS ${OPENAL_LIBRARY} ${SNDFILE_LIBRARY})
+
+set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Audio)
+set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Audio)
+
+# all source files
+set(SRC
+ ${SRCROOT}/ALCheck.cpp
+ ${SRCROOT}/ALCheck.hpp
+ ${SRCROOT}/AudioDevice.cpp
+ ${SRCROOT}/AudioDevice.hpp
+ ${INCROOT}/Export.hpp
+ ${SRCROOT}/Listener.cpp
+ ${INCROOT}/Listener.hpp
+ ${SRCROOT}/Music.cpp
+ ${INCROOT}/Music.hpp
+ ${SRCROOT}/Sound.cpp
+ ${INCROOT}/Sound.hpp
+ ${SRCROOT}/SoundBuffer.cpp
+ ${INCROOT}/SoundBuffer.hpp
+ ${SRCROOT}/SoundBufferRecorder.cpp
+ ${INCROOT}/SoundBufferRecorder.hpp
+ ${SRCROOT}/SoundFile.cpp
+ ${SRCROOT}/SoundFile.hpp
+ ${SRCROOT}/SoundRecorder.cpp
+ ${INCROOT}/SoundRecorder.hpp
+ ${SRCROOT}/SoundSource.cpp
+ ${INCROOT}/SoundSource.hpp
+ ${SRCROOT}/SoundStream.cpp
+ ${INCROOT}/SoundStream.hpp
+)
+source_group("" FILES ${SRC})
+
+# let CMake know about our additional audio libraries paths (on Windows and OSX)
+if(SFML_OS_WINDOWS)
+ set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/AL")
+ set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/windows")
+elseif(SFML_OS_MACOSX)
+ set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/osx")
+ set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/Frameworks")
+elseif(SFML_OS_ANDROID)
+ set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/AL")
+ set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/android")
+endif()
+
+# find external libraries
+if(NOT SFML_OS_ANDROID)
+ find_package(OpenAL REQUIRED)
+ find_package(Sndfile REQUIRED)
+else()
+ find_host_package(OpenAL REQUIRED)
+ find_host_package(Sndfile REQUIRED)
+endif()
+include_directories(${OPENAL_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR})
+
+# build the list of external libraries to link
+if(SFML_OS_ANDROID)
+ list(APPEND AUDIO_EXT_LIBS -landroid -lOpenSLES)
+endif()
+list(APPEND AUDIO_EXT_LIBS ${OPENAL_LIBRARY} ${SNDFILE_LIBRARY})
+
+# define the sfml-audio target
+sfml_add_library(sfml-audio
+ SOURCES ${SRC}
+ DEPENDS sfml-system
+ EXTERNAL_LIBS ${AUDIO_EXT_LIBS})
diff --git a/src/SFML/Audio/Listener.cpp b/src/SFML/Audio/Listener.cpp
index a4995ce..ec0a32f 100644
--- a/src/SFML/Audio/Listener.cpp
+++ b/src/SFML/Audio/Listener.cpp
@@ -1,111 +1,145 @@
-////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 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/Listener.hpp>
-#include <SFML/Audio/ALCheck.hpp>
-
-
-namespace sf
-{
-////////////////////////////////////////////////////////////
-void Listener::setGlobalVolume(float volume)
-{
- priv::ensureALInit();
-
- alCheck(alListenerf(AL_GAIN, volume * 0.01f));
-}
-
-
-////////////////////////////////////////////////////////////
-float Listener::getGlobalVolume()
-{
- priv::ensureALInit();
-
- float volume = 0.f;
- alCheck(alGetListenerf(AL_GAIN, &volume));
-
- return volume * 100;
-}
-
-
-////////////////////////////////////////////////////////////
-void Listener::setPosition(float x, float y, float z)
-{
- priv::ensureALInit();
-
- alCheck(alListener3f(AL_POSITION, x, y, z));
-}
-
-
-////////////////////////////////////////////////////////////
-void Listener::setPosition(const Vector3f& position)
-{
- setPosition(position.x, position.y, position.z);
-}
-
-
-////////////////////////////////////////////////////////////
-Vector3f Listener::getPosition()
-{
- priv::ensureALInit();
-
- Vector3f position;
- alCheck(alGetListener3f(AL_POSITION, &position.x, &position.y, &position.z));
-
- return position;
-}
-
-
-////////////////////////////////////////////////////////////
-void Listener::setDirection(float x, float y, float z)
-{
- priv::ensureALInit();
-
- float orientation[] = {x, y, z, 0.f, 1.f, 0.f};
- alCheck(alListenerfv(AL_ORIENTATION, orientation));
-}
-
-
-////////////////////////////////////////////////////////////
-void Listener::setDirection(const Vector3f& direction)
-{
- setDirection(direction.x, direction.y, direction.z);
-}
-
-
-////////////////////////////////////////////////////////////
-Vector3f Listener::getDirection()
-{
- priv::ensureALInit();
-
- float orientation[6];
- alCheck(alGetListenerfv(AL_ORIENTATION, orientation));
-
- return Vector3f(orientation[0], orientation[1], orientation[2]);
-}
-
-} // namespace sf
+////////////////////////////////////////////////////////////
+//
+// 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/Listener.hpp>
+#include <SFML/Audio/ALCheck.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
+{
+////////////////////////////////////////////////////////////
+void Listener::setGlobalVolume(float volume)
+{
+ if (volume != listenerVolume)
+ {
+ priv::ensureALInit();
+
+ alCheck(alListenerf(AL_GAIN, volume * 0.01f));
+ listenerVolume = volume;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+float Listener::getGlobalVolume()
+{
+ return listenerVolume;
+}
+
+
+////////////////////////////////////////////////////////////
+void Listener::setPosition(float x, float y, float z)
+{
+ setPosition(Vector3f(x, y, z));
+}
+
+
+////////////////////////////////////////////////////////////
+void Listener::setPosition(const Vector3f& position)
+{
+ if (position != listenerPosition)
+ {
+ priv::ensureALInit();
+
+ alCheck(alListener3f(AL_POSITION, position.x, position.y, position.z));
+ listenerPosition = position;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+Vector3f Listener::getPosition()
+{
+ return listenerPosition;
+}
+
+
+////////////////////////////////////////////////////////////
+void Listener::setDirection(float x, float y, float z)
+{
+ setDirection(Vector3f(x, y, z));
+}
+
+
+////////////////////////////////////////////////////////////
+void Listener::setDirection(const Vector3f& direction)
+{
+ if (direction != listenerDirection)
+ {
+ 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()
+{
+ return listenerDirection;
+}
+
+
+////////////////////////////////////////////////////////////
+void Listener::setUpVector(float x, float y, float z)
+{
+ setUpVector(Vector3f(x, y, z));
+}
+
+
+////////////////////////////////////////////////////////////
+void Listener::setUpVector(const Vector3f& upVector)
+{
+ if (upVector != listenerUpVector)
+ {
+ 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()
+{
+ return listenerUpVector;
+}
+
+} // namespace sf
diff --git a/src/SFML/Audio/Music.cpp b/src/SFML/Audio/Music.cpp
index ef784e4..6f3b6db 100644
--- a/src/SFML/Audio/Music.cpp
+++ b/src/SFML/Audio/Music.cpp
@@ -1,151 +1,151 @@
-////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 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/Music.hpp>
-#include <SFML/Audio/ALCheck.hpp>
-#include <SFML/Audio/SoundFile.hpp>
-#include <SFML/System/Lock.hpp>
-#include <SFML/System/Err.hpp>
-#include <fstream>
-
-
-namespace sf
-{
-////////////////////////////////////////////////////////////
-Music::Music() :
-m_file (new priv::SoundFile),
-m_duration()
-{
-
-}
-
-
-////////////////////////////////////////////////////////////
-Music::~Music()
-{
- // We must stop before destroying the file :)
- stop();
-
- delete m_file;
-}
-
-
-////////////////////////////////////////////////////////////
-bool Music::openFromFile(const std::string& filename)
-{
- // First stop the music if it was already running
- stop();
-
- // Open the underlying sound file
- if (!m_file->openRead(filename))
- return false;
-
- // Perform common initializations
- initialize();
-
- return true;
-}
-
-
-////////////////////////////////////////////////////////////
-bool Music::openFromMemory(const void* data, std::size_t sizeInBytes)
-{
- // First stop the music if it was already running
- stop();
-
- // Open the underlying sound file
- if (!m_file->openRead(data, sizeInBytes))
- return false;
-
- // Perform common initializations
- initialize();
-
- return true;
-}
-
-
-////////////////////////////////////////////////////////////
-bool Music::openFromStream(InputStream& stream)
-{
- // First stop the music if it was already running
- stop();
-
- // Open the underlying sound file
- if (!m_file->openRead(stream))
- return false;
-
- // Perform common initializations
- initialize();
-
- return true;
-}
-
-
-////////////////////////////////////////////////////////////
-Time Music::getDuration() const
-{
- return m_duration;
-}
-
-
-////////////////////////////////////////////////////////////
-bool Music::onGetData(SoundStream::Chunk& data)
-{
- Lock lock(m_mutex);
-
- // Fill the chunk parameters
- data.samples = &m_samples[0];
- data.sampleCount = m_file->read(&m_samples[0], m_samples.size());
-
- // Check if we have reached the end of the audio file
- return data.sampleCount == m_samples.size();
-}
-
-
-////////////////////////////////////////////////////////////
-void Music::onSeek(Time timeOffset)
-{
- Lock lock(m_mutex);
-
- m_file->seek(timeOffset);
-}
-
-
-////////////////////////////////////////////////////////////
-void Music::initialize()
-{
- // Compute the music duration
- m_duration = seconds(static_cast<float>(m_file->getSampleCount()) / m_file->getSampleRate() / m_file->getChannelCount());
-
- // Resize the internal buffer so that it can contain 1 second of audio samples
- m_samples.resize(m_file->getSampleRate() * m_file->getChannelCount());
-
- // Initialize the stream
- SoundStream::initialize(m_file->getChannelCount(), m_file->getSampleRate());
-}
-
-} // namespace sf
+////////////////////////////////////////////////////////////
+//
+// 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/Music.hpp>
+#include <SFML/Audio/ALCheck.hpp>
+#include <SFML/Audio/SoundFile.hpp>
+#include <SFML/System/Lock.hpp>
+#include <SFML/System/Err.hpp>
+#include <fstream>
+
+
+namespace sf
+{
+////////////////////////////////////////////////////////////
+Music::Music() :
+m_file (new priv::SoundFile),
+m_duration()
+{
+
+}
+
+
+////////////////////////////////////////////////////////////
+Music::~Music()
+{
+ // We must stop before destroying the file
+ stop();
+
+ delete m_file;
+}
+
+
+////////////////////////////////////////////////////////////
+bool Music::openFromFile(const std::string& filename)
+{
+ // First stop the music if it was already running
+ stop();
+
+ // Open the underlying sound file
+ if (!m_file->openRead(filename))
+ return false;
+
+ // Perform common initializations
+ initialize();
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+bool Music::openFromMemory(const void* data, std::size_t sizeInBytes)
+{
+ // First stop the music if it was already running
+ stop();
+
+ // Open the underlying sound file
+ if (!m_file->openRead(data, sizeInBytes))
+ return false;
+
+ // Perform common initializations
+ initialize();
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+bool Music::openFromStream(InputStream& stream)
+{
+ // First stop the music if it was already running
+ stop();
+
+ // Open the underlying sound file
+ if (!m_file->openRead(stream))
+ return false;
+
+ // Perform common initializations
+ initialize();
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+Time Music::getDuration() const
+{
+ return m_duration;
+}
+
+
+////////////////////////////////////////////////////////////
+bool Music::onGetData(SoundStream::Chunk& data)
+{
+ Lock lock(m_mutex);
+
+ // Fill the chunk parameters
+ data.samples = &m_samples[0];
+ data.sampleCount = m_file->read(&m_samples[0], m_samples.size());
+
+ // Check if we have reached the end of the audio file
+ return data.sampleCount == m_samples.size();
+}
+
+
+////////////////////////////////////////////////////////////
+void Music::onSeek(Time timeOffset)
+{
+ Lock lock(m_mutex);
+
+ m_file->seek(timeOffset);
+}
+
+
+////////////////////////////////////////////////////////////
+void Music::initialize()
+{
+ // Compute the music duration
+ m_duration = seconds(static_cast<float>(m_file->getSampleCount()) / m_file->getSampleRate() / m_file->getChannelCount());
+
+ // Resize the internal buffer so that it can contain 1 second of audio samples
+ m_samples.resize(m_file->getSampleRate() * m_file->getChannelCount());
+
+ // Initialize the stream
+ SoundStream::initialize(m_file->getChannelCount(), m_file->getSampleRate());
+}
+
+} // namespace sf
diff --git a/src/SFML/Audio/Sound.cpp b/src/SFML/Audio/Sound.cpp
index 8619cab..d138893 100644
--- a/src/SFML/Audio/Sound.cpp
+++ b/src/SFML/Audio/Sound.cpp
@@ -1,196 +1,200 @@
-////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 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/Sound.hpp>
-#include <SFML/Audio/SoundBuffer.hpp>
-#include <SFML/Audio/ALCheck.hpp>
-
-
-namespace sf
-{
-////////////////////////////////////////////////////////////
-Sound::Sound() :
-m_buffer(NULL)
-{
-}
-
-
-////////////////////////////////////////////////////////////
-Sound::Sound(const SoundBuffer& buffer) :
-m_buffer(NULL)
-{
- setBuffer(buffer);
-}
-
-
-////////////////////////////////////////////////////////////
-Sound::Sound(const Sound& copy) :
-SoundSource(copy),
-m_buffer (NULL)
-{
- if (copy.m_buffer)
- setBuffer(*copy.m_buffer);
- setLoop(copy.getLoop());
-}
-
-
-////////////////////////////////////////////////////////////
-Sound::~Sound()
-{
- stop();
- if (m_buffer)
- m_buffer->detachSound(this);
-}
-
-
-////////////////////////////////////////////////////////////
-void Sound::play()
-{
- alCheck(alSourcePlay(m_source));
-}
-
-
-////////////////////////////////////////////////////////////
-void Sound::pause()
-{
- alCheck(alSourcePause(m_source));
-}
-
-
-////////////////////////////////////////////////////////////
-void Sound::stop()
-{
- alCheck(alSourceStop(m_source));
-}
-
-
-////////////////////////////////////////////////////////////
-void Sound::setBuffer(const SoundBuffer& buffer)
-{
- // First detach from the previous buffer
- if (m_buffer)
- {
- stop();
- m_buffer->detachSound(this);
- }
-
- // Assign and use the new buffer
- m_buffer = &buffer;
- m_buffer->attachSound(this);
- alCheck(alSourcei(m_source, AL_BUFFER, m_buffer->m_buffer));
-}
-
-
-////////////////////////////////////////////////////////////
-void Sound::setLoop(bool Loop)
-{
- alCheck(alSourcei(m_source, AL_LOOPING, Loop));
-}
-
-
-////////////////////////////////////////////////////////////
-void Sound::setPlayingOffset(Time timeOffset)
-{
- alCheck(alSourcef(m_source, AL_SEC_OFFSET, timeOffset.asSeconds()));
-}
-
-
-////////////////////////////////////////////////////////////
-const SoundBuffer* Sound::getBuffer() const
-{
- return m_buffer;
-}
-
-
-////////////////////////////////////////////////////////////
-bool Sound::getLoop() const
-{
- ALint loop;
- alCheck(alGetSourcei(m_source, AL_LOOPING, &loop));
-
- return loop != 0;
-}
-
-
-////////////////////////////////////////////////////////////
-Time Sound::getPlayingOffset() const
-{
- ALfloat secs = 0.f;
- alCheck(alGetSourcef(m_source, AL_SEC_OFFSET, &secs));
-
- return seconds(secs);
-}
-
-
-////////////////////////////////////////////////////////////
-Sound::Status Sound::getStatus() const
-{
- return SoundSource::getStatus();
-}
-
-
-////////////////////////////////////////////////////////////
-Sound& Sound::operator =(const Sound& right)
-{
- // Here we don't use the copy-and-swap idiom, because it would mess up
- // the list of sound instances contained in the buffers
-
- // Detach the sound instance from the previous buffer (if any)
- if (m_buffer)
- {
- stop();
- m_buffer->detachSound(this);
- m_buffer = NULL;
- }
-
- // Copy the sound attributes
- if (right.m_buffer)
- setBuffer(*right.m_buffer);
- setLoop(right.getLoop());
- setPitch(right.getPitch());
- setVolume(right.getVolume());
- setPosition(right.getPosition());
- setRelativeToListener(right.isRelativeToListener());
- setMinDistance(right.getMinDistance());
- setAttenuation(right.getAttenuation());
-
- return *this;
-}
-
-
-////////////////////////////////////////////////////////////
-void Sound::resetBuffer()
-{
- // First stop the sound in case it is playing
- stop();
-
- // Detach the buffer
- alCheck(alSourcei(m_source, AL_BUFFER, 0));
- m_buffer = NULL;
-}
-
-} // namespace sf
+////////////////////////////////////////////////////////////
+//
+// 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/Sound.hpp>
+#include <SFML/Audio/SoundBuffer.hpp>
+#include <SFML/Audio/ALCheck.hpp>
+
+
+namespace sf
+{
+////////////////////////////////////////////////////////////
+Sound::Sound() :
+m_buffer(NULL)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+Sound::Sound(const SoundBuffer& buffer) :
+m_buffer(NULL)
+{
+ setBuffer(buffer);
+}
+
+
+////////////////////////////////////////////////////////////
+Sound::Sound(const Sound& copy) :
+SoundSource(copy),
+m_buffer (NULL)
+{
+ if (copy.m_buffer)
+ setBuffer(*copy.m_buffer);
+ setLoop(copy.getLoop());
+}
+
+
+////////////////////////////////////////////////////////////
+Sound::~Sound()
+{
+ stop();
+ if (m_buffer)
+ m_buffer->detachSound(this);
+}
+
+
+////////////////////////////////////////////////////////////
+void Sound::play()
+{
+ alCheck(alSourcePlay(m_source));
+}
+
+
+////////////////////////////////////////////////////////////
+void Sound::pause()
+{
+ alCheck(alSourcePause(m_source));
+}
+
+
+////////////////////////////////////////////////////////////
+void Sound::stop()
+{
+ alCheck(alSourceStop(m_source));
+}
+
+
+////////////////////////////////////////////////////////////
+void Sound::setBuffer(const SoundBuffer& buffer)
+{
+ // First detach from the previous buffer
+ if (m_buffer)
+ {
+ stop();
+ m_buffer->detachSound(this);
+ }
+
+ // Assign and use the new buffer
+ m_buffer = &buffer;
+ m_buffer->attachSound(this);
+ alCheck(alSourcei(m_source, AL_BUFFER, m_buffer->m_buffer));
+}
+
+
+////////////////////////////////////////////////////////////
+void Sound::setLoop(bool loop)
+{
+ alCheck(alSourcei(m_source, AL_LOOPING, loop));
+}
+
+
+////////////////////////////////////////////////////////////
+void Sound::setPlayingOffset(Time timeOffset)
+{
+ alCheck(alSourcef(m_source, AL_SEC_OFFSET, timeOffset.asSeconds()));
+}
+
+
+////////////////////////////////////////////////////////////
+const SoundBuffer* Sound::getBuffer() const
+{
+ return m_buffer;
+}
+
+
+////////////////////////////////////////////////////////////
+bool Sound::getLoop() const
+{
+ ALint loop;
+ alCheck(alGetSourcei(m_source, AL_LOOPING, &loop));
+
+ return loop != 0;
+}
+
+
+////////////////////////////////////////////////////////////
+Time Sound::getPlayingOffset() const
+{
+ ALfloat secs = 0.f;
+ alCheck(alGetSourcef(m_source, AL_SEC_OFFSET, &secs));
+
+ return seconds(secs);
+}
+
+
+////////////////////////////////////////////////////////////
+Sound::Status Sound::getStatus() const
+{
+ return SoundSource::getStatus();
+}
+
+
+////////////////////////////////////////////////////////////
+Sound& Sound::operator =(const Sound& right)
+{
+ // Here we don't use the copy-and-swap idiom, because it would mess up
+ // the list of sound instances contained in the buffers
+
+ // Detach the sound instance from the previous buffer (if any)
+ if (m_buffer)
+ {
+ stop();
+ m_buffer->detachSound(this);
+ m_buffer = NULL;
+ }
+
+ // Copy the sound attributes
+ if (right.m_buffer)
+ setBuffer(*right.m_buffer);
+ setLoop(right.getLoop());
+ setPitch(right.getPitch());
+ setVolume(right.getVolume());
+ setPosition(right.getPosition());
+ setRelativeToListener(right.isRelativeToListener());
+ setMinDistance(right.getMinDistance());
+ setAttenuation(right.getAttenuation());
+
+ return *this;
+}
+
+
+////////////////////////////////////////////////////////////
+void Sound::resetBuffer()
+{
+ // First stop the sound in case it is playing
+ stop();
+
+ // Detach the buffer
+ if (m_buffer)
+ {
+ alCheck(alSourcei(m_source, AL_BUFFER, 0));
+ m_buffer->detachSound(this);
+ m_buffer = NULL;
+ }
+}
+
+} // namespace sf
diff --git a/src/SFML/Audio/SoundBuffer.cpp b/src/SFML/Audio/SoundBuffer.cpp
index 406a9fe..0d8818c 100644
--- a/src/SFML/Audio/SoundBuffer.cpp
+++ b/src/SFML/Audio/SoundBuffer.cpp
@@ -1,275 +1,286 @@
-////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 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/SoundBuffer.hpp>
-#include <SFML/Audio/SoundFile.hpp>
-#include <SFML/Audio/Sound.hpp>
-#include <SFML/Audio/AudioDevice.hpp>
-#include <SFML/Audio/ALCheck.hpp>
-#include <SFML/System/Err.hpp>
-#include <memory>
-
-
-namespace sf
-{
-////////////////////////////////////////////////////////////
-SoundBuffer::SoundBuffer() :
-m_buffer (0),
-m_duration()
-{
- priv::ensureALInit();
-
- // Create the buffer
- alCheck(alGenBuffers(1, &m_buffer));
-}
-
-
-////////////////////////////////////////////////////////////
-SoundBuffer::SoundBuffer(const SoundBuffer& copy) :
-m_buffer (0),
-m_samples (copy.m_samples),
-m_duration(copy.m_duration),
-m_sounds () // don't copy the attached sounds
-{
- // Create the buffer
- alCheck(alGenBuffers(1, &m_buffer));
-
- // Update the internal buffer with the new samples
- update(copy.getChannelCount(), copy.getSampleRate());
-}
-
-
-////////////////////////////////////////////////////////////
-SoundBuffer::~SoundBuffer()
-{
- // First detach the buffer from the sounds that use it (to avoid OpenAL errors)
- for (SoundList::const_iterator it = m_sounds.begin(); it != m_sounds.end(); ++it)
- (*it)->resetBuffer();
-
- // Destroy the buffer
- if (m_buffer)
- alCheck(alDeleteBuffers(1, &m_buffer));
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundBuffer::loadFromFile(const std::string& filename)
-{
- priv::SoundFile file;
- if (file.openRead(filename))
- return initialize(file);
- else
- return false;
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundBuffer::loadFromMemory(const void* data, std::size_t sizeInBytes)
-{
- priv::SoundFile file;
- if (file.openRead(data, sizeInBytes))
- return initialize(file);
- else
- return false;
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundBuffer::loadFromStream(InputStream& stream)
-{
- priv::SoundFile file;
- if (file.openRead(stream))
- return initialize(file);
- else
- return false;
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundBuffer::loadFromSamples(const Int16* samples, std::size_t sampleCount, unsigned int channelCount, unsigned int sampleRate)
-{
- if (samples && sampleCount && channelCount && sampleRate)
- {
- // Copy the new audio samples
- m_samples.assign(samples, samples + sampleCount);
-
- // Update the internal buffer with the new samples
- return update(channelCount, sampleRate);
- }
- else
- {
- // Error...
- err() << "Failed to load sound buffer from samples ("
- << "array: " << samples << ", "
- << "count: " << sampleCount << ", "
- << "channels: " << channelCount << ", "
- << "samplerate: " << sampleRate << ")"
- << std::endl;
-
- return false;
- }
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundBuffer::saveToFile(const std::string& filename) const
-{
- // Create the sound file in write mode
- priv::SoundFile file;
- if (file.openWrite(filename, getChannelCount(), getSampleRate()))
- {
- // Write the samples to the opened file
- file.write(&m_samples[0], m_samples.size());
-
- return true;
- }
- else
- {
- return false;
- }
-}
-
-
-////////////////////////////////////////////////////////////
-const Int16* SoundBuffer::getSamples() const
-{
- return m_samples.empty() ? NULL : &m_samples[0];
-}
-
-
-////////////////////////////////////////////////////////////
-std::size_t SoundBuffer::getSampleCount() const
-{
- return m_samples.size();
-}
-
-
-////////////////////////////////////////////////////////////
-unsigned int SoundBuffer::getSampleRate() const
-{
- ALint sampleRate;
- alCheck(alGetBufferi(m_buffer, AL_FREQUENCY, &sampleRate));
-
- return sampleRate;
-}
-
-
-////////////////////////////////////////////////////////////
-unsigned int SoundBuffer::getChannelCount() const
-{
- ALint channelCount;
- alCheck(alGetBufferi(m_buffer, AL_CHANNELS, &channelCount));
-
- return channelCount;
-}
-
-
-////////////////////////////////////////////////////////////
-Time SoundBuffer::getDuration() const
-{
- return m_duration;
-}
-
-
-////////////////////////////////////////////////////////////
-SoundBuffer& SoundBuffer::operator =(const SoundBuffer& right)
-{
- SoundBuffer temp(right);
-
- std::swap(m_samples, temp.m_samples);
- std::swap(m_buffer, temp.m_buffer);
- std::swap(m_duration, temp.m_duration);
- std::swap(m_sounds, temp.m_sounds); // swap sounds too, so that they are detached when temp is destroyed
-
- return *this;
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundBuffer::initialize(priv::SoundFile& file)
-{
- // Retrieve the sound parameters
- std::size_t sampleCount = file.getSampleCount();
- unsigned int channelCount = file.getChannelCount();
- unsigned int sampleRate = file.getSampleRate();
-
- // Read the samples from the provided file
- m_samples.resize(sampleCount);
- if (file.read(&m_samples[0], sampleCount) == sampleCount)
- {
- // Update the internal buffer with the new samples
- return update(channelCount, sampleRate);
- }
- else
- {
- return false;
- }
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundBuffer::update(unsigned int channelCount, unsigned int sampleRate)
-{
- // Check parameters
- if (!channelCount || !sampleRate || m_samples.empty())
- return false;
-
- // Find the good format according to the number of channels
- ALenum format = priv::AudioDevice::getFormatFromChannelCount(channelCount);
-
- // Check if the format is valid
- if (format == 0)
- {
- err() << "Failed to load sound buffer (unsupported number of channels: " << channelCount << ")" << std::endl;
- return false;
- }
-
- // Fill the buffer
- ALsizei size = static_cast<ALsizei>(m_samples.size()) * sizeof(Int16);
- alCheck(alBufferData(m_buffer, format, &m_samples[0], size, sampleRate));
-
- // Compute the duration
- m_duration = milliseconds(1000 * m_samples.size() / sampleRate / channelCount);
-
- return true;
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundBuffer::attachSound(Sound* sound) const
-{
- m_sounds.insert(sound);
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundBuffer::detachSound(Sound* sound) const
-{
- m_sounds.erase(sound);
-}
-
-} // namespace sf
+////////////////////////////////////////////////////////////
+//
+// 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/SoundBuffer.hpp>
+#include <SFML/Audio/SoundFile.hpp>
+#include <SFML/Audio/Sound.hpp>
+#include <SFML/Audio/AudioDevice.hpp>
+#include <SFML/Audio/ALCheck.hpp>
+#include <SFML/System/Err.hpp>
+#include <memory>
+
+
+namespace sf
+{
+////////////////////////////////////////////////////////////
+SoundBuffer::SoundBuffer() :
+m_buffer (0),
+m_duration()
+{
+ priv::ensureALInit();
+
+ // Create the buffer
+ alCheck(alGenBuffers(1, &m_buffer));
+}
+
+
+////////////////////////////////////////////////////////////
+SoundBuffer::SoundBuffer(const SoundBuffer& copy) :
+m_buffer (0),
+m_samples (copy.m_samples),
+m_duration(copy.m_duration),
+m_sounds () // don't copy the attached sounds
+{
+ // Create the buffer
+ alCheck(alGenBuffers(1, &m_buffer));
+
+ // Update the internal buffer with the new samples
+ update(copy.getChannelCount(), copy.getSampleRate());
+}
+
+
+////////////////////////////////////////////////////////////
+SoundBuffer::~SoundBuffer()
+{
+ // First detach the buffer from the sounds that use it (to avoid OpenAL errors)
+ for (SoundList::const_iterator it = m_sounds.begin(); it != m_sounds.end(); ++it)
+ (*it)->resetBuffer();
+
+ // Destroy the buffer
+ if (m_buffer)
+ alCheck(alDeleteBuffers(1, &m_buffer));
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundBuffer::loadFromFile(const std::string& filename)
+{
+ priv::SoundFile file;
+ if (file.openRead(filename))
+ return initialize(file);
+ else
+ return false;
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundBuffer::loadFromMemory(const void* data, std::size_t sizeInBytes)
+{
+ priv::SoundFile file;
+ if (file.openRead(data, sizeInBytes))
+ return initialize(file);
+ else
+ return false;
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundBuffer::loadFromStream(InputStream& stream)
+{
+ priv::SoundFile file;
+ if (file.openRead(stream))
+ return initialize(file);
+ else
+ return false;
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundBuffer::loadFromSamples(const Int16* samples, std::size_t sampleCount, unsigned int channelCount, unsigned int sampleRate)
+{
+ if (samples && sampleCount && channelCount && sampleRate)
+ {
+ // Copy the new audio samples
+ m_samples.assign(samples, samples + sampleCount);
+
+ // Update the internal buffer with the new samples
+ return update(channelCount, sampleRate);
+ }
+ else
+ {
+ // Error...
+ err() << "Failed to load sound buffer from samples ("
+ << "array: " << samples << ", "
+ << "count: " << sampleCount << ", "
+ << "channels: " << channelCount << ", "
+ << "samplerate: " << sampleRate << ")"
+ << std::endl;
+
+ return false;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundBuffer::saveToFile(const std::string& filename) const
+{
+ // Create the sound file in write mode
+ priv::SoundFile file;
+ if (file.openWrite(filename, getChannelCount(), getSampleRate()))
+ {
+ // Write the samples to the opened file
+ file.write(&m_samples[0], m_samples.size());
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+const Int16* SoundBuffer::getSamples() const
+{
+ return m_samples.empty() ? NULL : &m_samples[0];
+}
+
+
+////////////////////////////////////////////////////////////
+std::size_t SoundBuffer::getSampleCount() const
+{
+ return m_samples.size();
+}
+
+
+////////////////////////////////////////////////////////////
+unsigned int SoundBuffer::getSampleRate() const
+{
+ ALint sampleRate;
+ alCheck(alGetBufferi(m_buffer, AL_FREQUENCY, &sampleRate));
+
+ return sampleRate;
+}
+
+
+////////////////////////////////////////////////////////////
+unsigned int SoundBuffer::getChannelCount() const
+{
+ ALint channelCount;
+ alCheck(alGetBufferi(m_buffer, AL_CHANNELS, &channelCount));
+
+ return channelCount;
+}
+
+
+////////////////////////////////////////////////////////////
+Time SoundBuffer::getDuration() const
+{
+ return m_duration;
+}
+
+
+////////////////////////////////////////////////////////////
+SoundBuffer& SoundBuffer::operator =(const SoundBuffer& right)
+{
+ SoundBuffer temp(right);
+
+ std::swap(m_samples, temp.m_samples);
+ std::swap(m_buffer, temp.m_buffer);
+ std::swap(m_duration, temp.m_duration);
+ std::swap(m_sounds, temp.m_sounds); // swap sounds too, so that they are detached when temp is destroyed
+
+ return *this;
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundBuffer::initialize(priv::SoundFile& file)
+{
+ // Retrieve the sound parameters
+ std::size_t sampleCount = file.getSampleCount();
+ unsigned int channelCount = file.getChannelCount();
+ unsigned int sampleRate = file.getSampleRate();
+
+ // Read the samples from the provided file
+ m_samples.resize(sampleCount);
+ if (file.read(&m_samples[0], sampleCount) == sampleCount)
+ {
+ // Update the internal buffer with the new samples
+ return update(channelCount, sampleRate);
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundBuffer::update(unsigned int channelCount, unsigned int sampleRate)
+{
+ // Check parameters
+ if (!channelCount || !sampleRate || m_samples.empty())
+ return false;
+
+ // Find the good format according to the number of channels
+ ALenum format = priv::AudioDevice::getFormatFromChannelCount(channelCount);
+
+ // Check if the format is valid
+ if (format == 0)
+ {
+ err() << "Failed to load sound buffer (unsupported number of channels: " << channelCount << ")" << std::endl;
+ return false;
+ }
+
+ // First make a copy of the list of sounds so we can reattach later
+ SoundList sounds(m_sounds);
+
+ // Detach the buffer from the sounds that use it (to avoid OpenAL errors)
+ for (SoundList::const_iterator it = sounds.begin(); it != sounds.end(); ++it)
+ (*it)->resetBuffer();
+
+ // Fill the buffer
+ ALsizei size = static_cast<ALsizei>(m_samples.size()) * sizeof(Int16);
+ alCheck(alBufferData(m_buffer, format, &m_samples[0], size, sampleRate));
+
+ // Compute the duration
+ m_duration = seconds(static_cast<float>(m_samples.size()) / sampleRate / channelCount);
+
+ // Now reattach the buffer to the sounds that use it
+ for (SoundList::const_iterator it = sounds.begin(); it != sounds.end(); ++it)
+ (*it)->setBuffer(*this);
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundBuffer::attachSound(Sound* sound) const
+{
+ m_sounds.insert(sound);
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundBuffer::detachSound(Sound* sound) const
+{
+ m_sounds.erase(sound);
+}
+
+} // namespace sf
diff --git a/src/SFML/Audio/SoundBufferRecorder.cpp b/src/SFML/Audio/SoundBufferRecorder.cpp
index a8b2993..11724b1 100644
--- a/src/SFML/Audio/SoundBufferRecorder.cpp
+++ b/src/SFML/Audio/SoundBufferRecorder.cpp
@@ -1,68 +1,68 @@
-////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 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/SoundBufferRecorder.hpp>
-#include <algorithm>
-#include <iterator>
-
-
-namespace sf
-{
-////////////////////////////////////////////////////////////
-bool SoundBufferRecorder::onStart()
-{
- m_samples.clear();
- m_buffer = SoundBuffer();
-
- return true;
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundBufferRecorder::onProcessSamples(const Int16* samples, std::size_t sampleCount)
-{
- std::copy(samples, samples + sampleCount, std::back_inserter(m_samples));
-
- return true;
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundBufferRecorder::onStop()
-{
- if (!m_samples.empty())
- m_buffer.loadFromSamples(&m_samples[0], m_samples.size(), 1, getSampleRate());
-}
-
-
-////////////////////////////////////////////////////////////
-const SoundBuffer& SoundBufferRecorder::getBuffer() const
-{
- return m_buffer;
-}
-
-} // namespace sf
+////////////////////////////////////////////////////////////
+//
+// 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/SoundBufferRecorder.hpp>
+#include <algorithm>
+#include <iterator>
+
+
+namespace sf
+{
+////////////////////////////////////////////////////////////
+bool SoundBufferRecorder::onStart()
+{
+ m_samples.clear();
+ m_buffer = SoundBuffer();
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundBufferRecorder::onProcessSamples(const Int16* samples, std::size_t sampleCount)
+{
+ std::copy(samples, samples + sampleCount, std::back_inserter(m_samples));
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundBufferRecorder::onStop()
+{
+ if (!m_samples.empty())
+ m_buffer.loadFromSamples(&m_samples[0], m_samples.size(), 1, getSampleRate());
+}
+
+
+////////////////////////////////////////////////////////////
+const SoundBuffer& SoundBufferRecorder::getBuffer() const
+{
+ return m_buffer;
+}
+
+} // namespace sf
diff --git a/src/SFML/Audio/SoundFile.cpp b/src/SFML/Audio/SoundFile.cpp
index 91db819..7ca5f82 100644
--- a/src/SFML/Audio/SoundFile.cpp
+++ b/src/SFML/Audio/SoundFile.cpp
@@ -1,425 +1,451 @@
-////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 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/SoundFile.hpp>
-#include <SFML/System/InputStream.hpp>
-#include <SFML/System/Err.hpp>
-#include <cstring>
-#include <cctype>
-
-
-namespace
-{
- // Convert a string to lower case
- std::string toLower(std::string str)
- {
- for (std::string::iterator i = str.begin(); i != str.end(); ++i)
- *i = static_cast<char>(std::tolower(*i));
- return str;
- }
-}
-
-
-namespace sf
-{
-namespace priv
-{
-////////////////////////////////////////////////////////////
-SoundFile::SoundFile() :
-m_file (NULL),
-m_sampleCount (0),
-m_channelCount(0),
-m_sampleRate (0)
-{
-
-}
-
-
-////////////////////////////////////////////////////////////
-SoundFile::~SoundFile()
-{
- if (m_file)
- sf_close(m_file);
-}
-
-
-////////////////////////////////////////////////////////////
-std::size_t SoundFile::getSampleCount() const
-{
- return m_sampleCount;
-}
-
-
-////////////////////////////////////////////////////////////
-unsigned int SoundFile::getChannelCount() const
-{
- return m_channelCount;
-}
-
-
-////////////////////////////////////////////////////////////
-unsigned int SoundFile::getSampleRate() const
-{
- return m_sampleRate;
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundFile::openRead(const std::string& filename)
-{
- // If the file is already opened, first close it
- if (m_file)
- sf_close(m_file);
-
- // Open the sound file
- SF_INFO fileInfo;
- fileInfo.format = 0;
- m_file = sf_open(filename.c_str(), SFM_READ, &fileInfo);
- if (!m_file)
- {
- err() << "Failed to open sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl;
- return false;
- }
-
- // Initialize the internal state from the loaded information
- initialize(fileInfo);
-
- return true;
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundFile::openRead(const void* data, std::size_t sizeInBytes)
-{
- // If the file is already opened, first close it
- if (m_file)
- sf_close(m_file);
-
- // Prepare the memory I/O structure
- SF_VIRTUAL_IO io;
- io.get_filelen = &Memory::getLength;
- io.read = &Memory::read;
- io.seek = &Memory::seek;
- io.tell = &Memory::tell;
-
- // Initialize the memory data
- m_memory.begin = static_cast<const char*>(data);
- m_memory.current = m_memory.begin;
- m_memory.size = sizeInBytes;
-
- // Open the sound file
- SF_INFO fileInfo;
- fileInfo.format = 0;
- m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_memory);
- if (!m_file)
- {
- err() << "Failed to open sound file from memory (" << sf_strerror(m_file) << ")" << std::endl;
- return false;
- }
-
- // Initialize the internal state from the loaded information
- initialize(fileInfo);
-
- return true;
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundFile::openRead(InputStream& stream)
-{
- // If the file is already opened, first close it
- if (m_file)
- sf_close(m_file);
-
- // Prepare the memory I/O structure
- SF_VIRTUAL_IO io;
- io.get_filelen = &Stream::getLength;
- io.read = &Stream::read;
- io.seek = &Stream::seek;
- io.tell = &Stream::tell;
-
- // Initialize the stream data
- m_stream.source = &stream;
- m_stream.size = stream.getSize();
-
- // Make sure that the stream's reading position is at the beginning
- stream.seek(0);
-
- // Open the sound file
- SF_INFO fileInfo;
- fileInfo.format = 0;
- m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_stream);
- if (!m_file)
- {
- err() << "Failed to open sound file from stream (" << sf_strerror(m_file) << ")" << std::endl;
- return false;
- }
-
- // Initialize the internal state from the loaded information
- initialize(fileInfo);
-
- return true;
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundFile::openWrite(const std::string& filename, unsigned int channelCount, unsigned int sampleRate)
-{
- // If the file is already opened, first close it
- if (m_file)
- sf_close(m_file);
-
- // Find the right format according to the file extension
- int format = getFormatFromFilename(filename);
- if (format == -1)
- {
- // Error : unrecognized extension
- err() << "Failed to create sound file \"" << filename << "\" (unknown format)" << std::endl;
- return false;
- }
-
- // Fill the sound infos with parameters
- SF_INFO fileInfos;
- fileInfos.channels = channelCount;
- fileInfos.samplerate = sampleRate;
- fileInfos.format = format | (format == SF_FORMAT_OGG ? SF_FORMAT_VORBIS : SF_FORMAT_PCM_16);
-
- // Open the sound file for writing
- m_file = sf_open(filename.c_str(), SFM_WRITE, &fileInfos);
- if (!m_file)
- {
- err() << "Failed to create sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl;
- return false;
- }
-
- // Set the sound parameters
- m_channelCount = channelCount;
- m_sampleRate = sampleRate;
- m_sampleCount = 0;
-
- return true;
-}
-
-
-////////////////////////////////////////////////////////////
-std::size_t SoundFile::read(Int16* data, std::size_t sampleCount)
-{
- if (m_file && data && sampleCount)
- return static_cast<std::size_t>(sf_read_short(m_file, data, sampleCount));
- else
- return 0;
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundFile::write(const Int16* data, std::size_t sampleCount)
-{
- if (m_file && data && sampleCount)
- {
- // Write small chunks instead of everything at once,
- // to avoid a stack overflow in libsndfile (happens only with OGG format)
- while (sampleCount > 0)
- {
- std::size_t count = sampleCount > 10000 ? 10000 : sampleCount;
- sf_write_short(m_file, data, count);
- data += count;
- sampleCount -= count;
- }
- }
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundFile::seek(Time timeOffset)
-{
- if (m_file)
- {
- sf_count_t frameOffset = static_cast<sf_count_t>(timeOffset.asSeconds() * m_sampleRate);
- sf_seek(m_file, frameOffset, SEEK_SET);
- }
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundFile::initialize(SF_INFO fileInfo)
-{
- // Save the sound properties
- m_channelCount = fileInfo.channels;
- m_sampleRate = fileInfo.samplerate;
- m_sampleCount = static_cast<std::size_t>(fileInfo.frames) * fileInfo.channels;
-
- // Enable scaling for Vorbis files (float samples)
- // @todo enable when it's faster (it currently has to iterate over the *whole* music)
- //if (fileInfo.format & SF_FORMAT_VORBIS)
- // sf_command(m_file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
-}
-
-
-////////////////////////////////////////////////////////////
-int SoundFile::getFormatFromFilename(const std::string& filename)
-{
- // Extract the extension
- std::string ext = "wav";
- std::string::size_type pos = filename.find_last_of(".");
- if (pos != std::string::npos)
- ext = filename.substr(pos + 1);
-
- // Match every supported extension with its format constant
- if (toLower(ext) == "wav" ) return SF_FORMAT_WAV;
- if (toLower(ext) == "aif" ) return SF_FORMAT_AIFF;
- if (toLower(ext) == "aiff" ) return SF_FORMAT_AIFF;
- if (toLower(ext) == "au" ) return SF_FORMAT_AU;
- if (toLower(ext) == "raw" ) return SF_FORMAT_RAW;
- if (toLower(ext) == "paf" ) return SF_FORMAT_PAF;
- if (toLower(ext) == "svx" ) return SF_FORMAT_SVX;
- if (toLower(ext) == "nist" ) return SF_FORMAT_NIST;
- if (toLower(ext) == "voc" ) return SF_FORMAT_VOC;
- if (toLower(ext) == "sf" ) return SF_FORMAT_IRCAM;
- if (toLower(ext) == "w64" ) return SF_FORMAT_W64;
- if (toLower(ext) == "mat4" ) return SF_FORMAT_MAT4;
- if (toLower(ext) == "mat5" ) return SF_FORMAT_MAT5;
- if (toLower(ext) == "pvf" ) return SF_FORMAT_PVF;
- if (toLower(ext) == "xi" ) return SF_FORMAT_XI;
- if (toLower(ext) == "htk" ) return SF_FORMAT_HTK;
- if (toLower(ext) == "sds" ) return SF_FORMAT_SDS;
- if (toLower(ext) == "avr" ) return SF_FORMAT_AVR;
- if (toLower(ext) == "sd2" ) return SF_FORMAT_SD2;
- if (toLower(ext) == "flac" ) return SF_FORMAT_FLAC;
- if (toLower(ext) == "caf" ) return SF_FORMAT_CAF;
- if (toLower(ext) == "wve" ) return SF_FORMAT_WVE;
- if (toLower(ext) == "ogg" ) return SF_FORMAT_OGG;
- if (toLower(ext) == "mpc2k") return SF_FORMAT_MPC2K;
- if (toLower(ext) == "rf64" ) return SF_FORMAT_RF64;
-
- return -1;
-}
-
-
-////////////////////////////////////////////////////////////
-sf_count_t SoundFile::Memory::getLength(void* user)
-{
- Memory* memory = static_cast<Memory*>(user);
- return memory->size;
-}
-
-
-////////////////////////////////////////////////////////////
-sf_count_t SoundFile::Memory::read(void* ptr, sf_count_t count, void* user)
-{
- Memory* memory = static_cast<Memory*>(user);
-
- sf_count_t position = tell(user);
- if (position + count >= memory->size)
- count = memory->size - position;
-
- std::memcpy(ptr, memory->current, static_cast<std::size_t>(count));
- memory->current += count;
- return count;
-}
-
-
-////////////////////////////////////////////////////////////
-sf_count_t SoundFile::Memory::seek(sf_count_t offset, int whence, void* user)
-{
- Memory* memory = static_cast<Memory*>(user);
- sf_count_t position = 0;
- switch (whence)
- {
- case SEEK_SET : position = offset; break;
- case SEEK_CUR : position = memory->current - memory->begin + offset; break;
- case SEEK_END : position = memory->size - offset; break;
- default : position = 0; break;
- }
-
- if (position >= memory->size)
- position = memory->size - 1;
- else if (position < 0)
- position = 0;
-
- memory->current = memory->begin + position;
- return position;
-}
-
-
-////////////////////////////////////////////////////////////
-sf_count_t SoundFile::Memory::tell(void* user)
-{
- Memory* memory = static_cast<Memory*>(user);
- return memory->current - memory->begin;
-}
-
-
-////////////////////////////////////////////////////////////
-sf_count_t SoundFile::Stream::getLength(void* userData)
-{
- Stream* stream = static_cast<Stream*>(userData);
- return stream->size;
-}
-
-
-////////////////////////////////////////////////////////////
-sf_count_t SoundFile::Stream::read(void* ptr, sf_count_t count, void* userData)
-{
- Stream* stream = static_cast<Stream*>(userData);
- Int64 position = stream->source->tell();
- if (position != -1)
- {
- if (count > stream->size - position)
- count = stream->size - position;
- return stream->source->read(reinterpret_cast<char*>(ptr), count);
- }
- else
- {
- return -1;
- }
-}
-
-
-////////////////////////////////////////////////////////////
-sf_count_t SoundFile::Stream::seek(sf_count_t offset, int whence, void* userData)
-{
- Stream* stream = static_cast<Stream*>(userData);
- switch (whence)
- {
- case SEEK_SET : return stream->source->seek(offset);
- case SEEK_CUR : return stream->source->seek(stream->source->tell() + offset);
- case SEEK_END : return stream->source->seek(stream->size - offset);
- default : return stream->source->seek(0);
- }
-}
-
-
-////////////////////////////////////////////////////////////
-sf_count_t SoundFile::Stream::tell(void* userData)
-{
- Stream* stream = static_cast<Stream*>(userData);
- return stream->source->tell();
-}
-
-} // namespace priv
-
-} // namespace sf
+////////////////////////////////////////////////////////////
+//
+// 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/SoundFile.hpp>
+#ifdef SFML_SYSTEM_ANDROID
+ #include <SFML/System/Android/ResourceStream.hpp>
+#endif
+#include <SFML/System/InputStream.hpp>
+#include <SFML/System/Err.hpp>
+#include <cstring>
+#include <cctype>
+
+
+namespace
+{
+ // Convert a string to lower case
+ std::string toLower(std::string str)
+ {
+ for (std::string::iterator i = str.begin(); i != str.end(); ++i)
+ *i = static_cast<char>(std::tolower(*i));
+ return str;
+ }
+}
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+SoundFile::SoundFile() :
+m_file (NULL),
+m_sampleCount (0),
+m_channelCount(0),
+m_sampleRate (0)
+{
+ #ifdef SFML_SYSTEM_ANDROID
+
+ m_resourceStream = NULL;
+
+ #endif
+}
+
+
+////////////////////////////////////////////////////////////
+SoundFile::~SoundFile()
+{
+ if (m_file)
+ sf_close(m_file);
+
+ #ifdef SFML_SYSTEM_ANDROID
+
+ if (m_resourceStream)
+ delete (priv::ResourceStream*)m_resourceStream;
+
+ #endif
+}
+
+
+////////////////////////////////////////////////////////////
+std::size_t SoundFile::getSampleCount() const
+{
+ return m_sampleCount;
+}
+
+
+////////////////////////////////////////////////////////////
+unsigned int SoundFile::getChannelCount() const
+{
+ return m_channelCount;
+}
+
+
+////////////////////////////////////////////////////////////
+unsigned int SoundFile::getSampleRate() const
+{
+ return m_sampleRate;
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundFile::openRead(const std::string& filename)
+{
+ #ifndef SFML_SYSTEM_ANDROID
+
+ // If the file is already opened, first close it
+ if (m_file)
+ sf_close(m_file);
+
+ // Open the sound file
+ SF_INFO fileInfo;
+ fileInfo.format = 0;
+ m_file = sf_open(filename.c_str(), SFM_READ, &fileInfo);
+ if (!m_file)
+ {
+ err() << "Failed to open sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl;
+ return false;
+ }
+
+ // Initialize the internal state from the loaded information
+ initialize(fileInfo);
+
+ return true;
+
+ #else
+
+ if (m_resourceStream)
+ delete (priv::ResourceStream*)m_resourceStream;
+
+ m_resourceStream = new priv::ResourceStream(filename);
+ return openRead(*(priv::ResourceStream*)m_resourceStream);
+
+ #endif
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundFile::openRead(const void* data, std::size_t sizeInBytes)
+{
+ // If the file is already opened, first close it
+ if (m_file)
+ sf_close(m_file);
+
+ // Prepare the memory I/O structure
+ SF_VIRTUAL_IO io;
+ io.get_filelen = &Memory::getLength;
+ io.read = &Memory::read;
+ io.seek = &Memory::seek;
+ io.tell = &Memory::tell;
+
+ // Initialize the memory data
+ m_memory.begin = static_cast<const char*>(data);
+ m_memory.current = m_memory.begin;
+ m_memory.size = sizeInBytes;
+
+ // Open the sound file
+ SF_INFO fileInfo;
+ fileInfo.format = 0;
+ m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_memory);
+ if (!m_file)
+ {
+ err() << "Failed to open sound file from memory (" << sf_strerror(m_file) << ")" << std::endl;
+ return false;
+ }
+
+ // Initialize the internal state from the loaded information
+ initialize(fileInfo);
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundFile::openRead(InputStream& stream)
+{
+ // If the file is already opened, first close it
+ if (m_file)
+ sf_close(m_file);
+
+ // Prepare the memory I/O structure
+ SF_VIRTUAL_IO io;
+ io.get_filelen = &Stream::getLength;
+ io.read = &Stream::read;
+ io.seek = &Stream::seek;
+ io.tell = &Stream::tell;
+
+ // Initialize the stream data
+ m_stream.source = &stream;
+ m_stream.size = stream.getSize();
+
+ // Make sure that the stream's reading position is at the beginning
+ stream.seek(0);
+
+ // Open the sound file
+ SF_INFO fileInfo;
+ fileInfo.format = 0;
+ m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_stream);
+ if (!m_file)
+ {
+ err() << "Failed to open sound file from stream (" << sf_strerror(m_file) << ")" << std::endl;
+ return false;
+ }
+
+ // Initialize the internal state from the loaded information
+ initialize(fileInfo);
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundFile::openWrite(const std::string& filename, unsigned int channelCount, unsigned int sampleRate)
+{
+ // If the file is already opened, first close it
+ if (m_file)
+ sf_close(m_file);
+
+ // Find the right format according to the file extension
+ int format = getFormatFromFilename(filename);
+ if (format == -1)
+ {
+ // Error: unrecognized extension
+ err() << "Failed to create sound file \"" << filename << "\" (unknown format)" << std::endl;
+ return false;
+ }
+
+ // Fill the sound infos with parameters
+ SF_INFO fileInfos;
+ fileInfos.channels = channelCount;
+ fileInfos.samplerate = sampleRate;
+ fileInfos.format = format | (format == SF_FORMAT_OGG ? SF_FORMAT_VORBIS : SF_FORMAT_PCM_16);
+
+ // Open the sound file for writing
+ m_file = sf_open(filename.c_str(), SFM_WRITE, &fileInfos);
+ if (!m_file)
+ {
+ err() << "Failed to create sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl;
+ return false;
+ }
+
+ // Set the sound parameters
+ m_channelCount = channelCount;
+ m_sampleRate = sampleRate;
+ m_sampleCount = 0;
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+std::size_t SoundFile::read(Int16* data, std::size_t sampleCount)
+{
+ if (m_file && data && sampleCount)
+ return static_cast<std::size_t>(sf_read_short(m_file, data, sampleCount));
+ else
+ return 0;
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundFile::write(const Int16* data, std::size_t sampleCount)
+{
+ if (m_file && data && sampleCount)
+ {
+ // Write small chunks instead of everything at once,
+ // to avoid a stack overflow in libsndfile (happens only with OGG format)
+ while (sampleCount > 0)
+ {
+ std::size_t count = sampleCount > 10000 ? 10000 : sampleCount;
+ sf_write_short(m_file, data, count);
+ data += count;
+ sampleCount -= count;
+ }
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundFile::seek(Time timeOffset)
+{
+ if (m_file)
+ {
+ sf_count_t frameOffset = static_cast<sf_count_t>(timeOffset.asSeconds() * m_sampleRate);
+ sf_seek(m_file, frameOffset, SEEK_SET);
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundFile::initialize(SF_INFO fileInfo)
+{
+ // Save the sound properties
+ m_channelCount = fileInfo.channels;
+ m_sampleRate = fileInfo.samplerate;
+ m_sampleCount = static_cast<std::size_t>(fileInfo.frames) * fileInfo.channels;
+
+ // Enable scaling for Vorbis files (float samples)
+ // @todo enable when it's faster (it currently has to iterate over the *whole* music)
+ //if (fileInfo.format & SF_FORMAT_VORBIS)
+ // sf_command(m_file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
+}
+
+
+////////////////////////////////////////////////////////////
+int SoundFile::getFormatFromFilename(const std::string& filename)
+{
+ // Extract the extension
+ std::string ext = "wav";
+ std::string::size_type pos = filename.find_last_of(".");
+ if (pos != std::string::npos)
+ ext = toLower(filename.substr(pos + 1));
+
+ // Match every supported extension with its format constant
+ if (ext == "wav" ) return SF_FORMAT_WAV;
+ if (ext == "aif" ) return SF_FORMAT_AIFF;
+ if (ext == "aiff" ) return SF_FORMAT_AIFF;
+ if (ext == "au" ) return SF_FORMAT_AU;
+ if (ext == "raw" ) return SF_FORMAT_RAW;
+ if (ext == "paf" ) return SF_FORMAT_PAF;
+ if (ext == "svx" ) return SF_FORMAT_SVX;
+ if (ext == "nist" ) return SF_FORMAT_NIST;
+ if (ext == "voc" ) return SF_FORMAT_VOC;
+ if (ext == "sf" ) return SF_FORMAT_IRCAM;
+ if (ext == "w64" ) return SF_FORMAT_W64;
+ if (ext == "mat4" ) return SF_FORMAT_MAT4;
+ if (ext == "mat5" ) return SF_FORMAT_MAT5;
+ if (ext == "pvf" ) return SF_FORMAT_PVF;
+ if (ext == "xi" ) return SF_FORMAT_XI;
+ if (ext == "htk" ) return SF_FORMAT_HTK;
+ if (ext == "sds" ) return SF_FORMAT_SDS;
+ if (ext == "avr" ) return SF_FORMAT_AVR;
+ if (ext == "sd2" ) return SF_FORMAT_SD2;
+ if (ext == "flac" ) return SF_FORMAT_FLAC;
+ if (ext == "caf" ) return SF_FORMAT_CAF;
+ if (ext == "wve" ) return SF_FORMAT_WVE;
+ if (ext == "ogg" ) return SF_FORMAT_OGG;
+ if (ext == "mpc2k") return SF_FORMAT_MPC2K;
+ if (ext == "rf64" ) return SF_FORMAT_RF64;
+
+ return -1;
+}
+
+
+////////////////////////////////////////////////////////////
+sf_count_t SoundFile::Memory::getLength(void* user)
+{
+ Memory* memory = static_cast<Memory*>(user);
+ return memory->size;
+}
+
+
+////////////////////////////////////////////////////////////
+sf_count_t SoundFile::Memory::read(void* ptr, sf_count_t count, void* user)
+{
+ Memory* memory = static_cast<Memory*>(user);
+
+ sf_count_t position = tell(user);
+ if (position + count >= memory->size)
+ count = memory->size - position;
+
+ std::memcpy(ptr, memory->current, static_cast<std::size_t>(count));
+ memory->current += count;
+ return count;
+}
+
+
+////////////////////////////////////////////////////////////
+sf_count_t SoundFile::Memory::seek(sf_count_t offset, int whence, void* user)
+{
+ Memory* memory = static_cast<Memory*>(user);
+ sf_count_t position = 0;
+ switch (whence)
+ {
+ case SEEK_SET: position = offset; break;
+ case SEEK_CUR: position = memory->current - memory->begin + offset; break;
+ case SEEK_END: position = memory->size - offset; break;
+ default: position = 0; break;
+ }
+
+ if (position >= memory->size)
+ position = memory->size - 1;
+ else if (position < 0)
+ position = 0;
+
+ memory->current = memory->begin + position;
+ return position;
+}
+
+
+////////////////////////////////////////////////////////////
+sf_count_t SoundFile::Memory::tell(void* user)
+{
+ Memory* memory = static_cast<Memory*>(user);
+ return memory->current - memory->begin;
+}
+
+
+////////////////////////////////////////////////////////////
+sf_count_t SoundFile::Stream::getLength(void* userData)
+{
+ Stream* stream = static_cast<Stream*>(userData);
+ return stream->size;
+}
+
+
+////////////////////////////////////////////////////////////
+sf_count_t SoundFile::Stream::read(void* ptr, sf_count_t count, void* userData)
+{
+ Stream* stream = static_cast<Stream*>(userData);
+ Int64 position = stream->source->tell();
+ if (position != -1)
+ {
+ if (count > stream->size - position)
+ count = stream->size - position;
+ return stream->source->read(reinterpret_cast<char*>(ptr), count);
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+sf_count_t SoundFile::Stream::seek(sf_count_t offset, int whence, void* userData)
+{
+ Stream* stream = static_cast<Stream*>(userData);
+ switch (whence)
+ {
+ case SEEK_SET: return stream->source->seek(offset);
+ case SEEK_CUR: return stream->source->seek(stream->source->tell() + offset);
+ case SEEK_END: return stream->source->seek(stream->size - offset);
+ default: return stream->source->seek(0);
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+sf_count_t SoundFile::Stream::tell(void* userData)
+{
+ Stream* stream = static_cast<Stream*>(userData);
+ return stream->source->tell();
+}
+
+} // namespace priv
+
+} // namespace sf
diff --git a/src/SFML/Audio/SoundFile.hpp b/src/SFML/Audio/SoundFile.hpp
index 105a951..a04a0ff 100644
--- a/src/SFML/Audio/SoundFile.hpp
+++ b/src/SFML/Audio/SoundFile.hpp
@@ -1,228 +1,231 @@
-////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 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_SOUNDFILE_HPP
-#define SFML_SOUNDFILE_HPP
-
-////////////////////////////////////////////////////////////
-// Headers
-////////////////////////////////////////////////////////////
-#include <SFML/System/NonCopyable.hpp>
-#include <SFML/System/Time.hpp>
-#include <sndfile.h>
-#include <string>
-
-
-namespace sf
-{
-class InputStream;
-
-namespace priv
-{
-////////////////////////////////////////////////////////////
-/// \brief Provide read and write access to sound files
-///
-////////////////////////////////////////////////////////////
-class SoundFile : NonCopyable
-{
-public :
-
- ////////////////////////////////////////////////////////////
- /// \brief Default constructor
- ///
- ////////////////////////////////////////////////////////////
- SoundFile();
-
- ////////////////////////////////////////////////////////////
- /// \brief Destructor
- ///
- ////////////////////////////////////////////////////////////
- ~SoundFile();
-
- ////////////////////////////////////////////////////////////
- /// \brief Get the total number of audio samples in the file
- ///
- /// \return Number of samples
- ///
- ////////////////////////////////////////////////////////////
- std::size_t getSampleCount() const;
-
- ////////////////////////////////////////////////////////////
- /// \brief Get the number of channels used by the sound
- ///
- /// \return Number of channels (1 = mono, 2 = stereo)
- ///
- ////////////////////////////////////////////////////////////
- unsigned int getChannelCount() const;
-
- ////////////////////////////////////////////////////////////
- /// \brief Get the sample rate of the sound
- ///
- /// \return Sample rate, in samples per second
- ///
- ////////////////////////////////////////////////////////////
- unsigned int getSampleRate() const;
-
- ////////////////////////////////////////////////////////////
- /// \brief Open a sound file for reading
- ///
- /// \param filename Path of the sound file to load
- ///
- /// \return True if the file was successfully opened
- ///
- ////////////////////////////////////////////////////////////
- bool openRead(const std::string& filename);
-
- ////////////////////////////////////////////////////////////
- /// \brief Open a sound file in memory for reading
- ///
- /// \param data Pointer to the file data in memory
- /// \param sizeInBytes Size of the data to load, in bytes
- ///
- /// \return True if the file was successfully opened
- ///
- ////////////////////////////////////////////////////////////
- bool openRead(const void* data, std::size_t sizeInBytes);
-
- ////////////////////////////////////////////////////////////
- /// \brief Open a sound file from a custom stream for reading
- ///
- /// \param stream Source stream to read from
- ///
- /// \return True if the file was successfully opened
- ///
- ////////////////////////////////////////////////////////////
- bool openRead(InputStream& stream);
-
- ////////////////////////////////////////////////////////////
- /// \brief a the sound file for writing
- ///
- /// \param filename Path of the sound file to write
- /// \param channelCount Number of channels in the sound
- /// \param sampleRate Sample rate of the sound
- ///
- /// \return True if the file was successfully opened
- ///
- ////////////////////////////////////////////////////////////
- bool openWrite(const std::string& filename, unsigned int channelCount, unsigned int sampleRate);
-
- ////////////////////////////////////////////////////////////
- /// \brief Read audio samples from the loaded sound
- ///
- /// \param data Pointer to the sample array to fill
- /// \param sampleCount Number of samples to read
- ///
- /// \return Number of samples actually read (may be less than \a sampleCount)
- ///
- ////////////////////////////////////////////////////////////
- std::size_t read(Int16* data, std::size_t sampleCount);
-
- ////////////////////////////////////////////////////////////
- /// \brief Write audio samples to the file
- ///
- /// \param data Pointer to the sample array to write
- /// \param sampleCount Number of samples to write
- ///
- ////////////////////////////////////////////////////////////
- void write(const Int16* data, std::size_t sampleCount);
-
- ////////////////////////////////////////////////////////////
- /// \brief Change the current read position in the file
- ///
- /// \param timeOffset New playing position, from the beginning of the file
- ///
- ////////////////////////////////////////////////////////////
- void seek(Time timeOffset);
-
-private :
-
- ////////////////////////////////////////////////////////////
- /// \brief Initialize the internal state of the sound file
- ///
- /// This function is called by all the openRead functions.
- ///
- /// \param fileInfo Information about the loaded sound file
- ///
- ////////////////////////////////////////////////////////////
- void initialize(SF_INFO fileInfo);
-
- ////////////////////////////////////////////////////////////
- /// \brief Get the internal format of an audio file according to
- /// its filename extension
- ///
- /// \param filename Filename to check
- ///
- /// \return Internal format matching the filename (-1 if no match)
- ///
- ////////////////////////////////////////////////////////////
- static int getFormatFromFilename(const std::string& filename);
-
- ////////////////////////////////////////////////////////////
- /// \brief Data and callbacks for opening from memory
- ///
- ////////////////////////////////////////////////////////////
- struct Memory
- {
- const char* begin;
- const char* current;
- sf_count_t size;
-
- static sf_count_t getLength(void* user);
- static sf_count_t read(void* ptr, sf_count_t count, void* user);
- static sf_count_t seek(sf_count_t offset, int whence, void* user);
- static sf_count_t tell(void* user);
- };
-
- ////////////////////////////////////////////////////////////
- /// \brief Data and callbacks for opening from stream
- ///
- ////////////////////////////////////////////////////////////
- struct Stream
- {
- InputStream* source;
- Int64 size;
-
- static sf_count_t getLength(void* user);
- static sf_count_t read(void* ptr, sf_count_t count, void* user);
- static sf_count_t seek(sf_count_t offset, int whence, void* user);
- static sf_count_t tell(void* user);
- };
-
- ////////////////////////////////////////////////////////////
- // Member data
- ////////////////////////////////////////////////////////////
- SNDFILE* m_file; ///< File descriptor
- Memory m_memory; ///< Memory reading info
- Stream m_stream; ///< Stream reading info
- std::size_t m_sampleCount; ///< Total number of samples in the file
- unsigned int m_channelCount; ///< Number of channels used by the sound
- unsigned int m_sampleRate; ///< Number of samples per second
-};
-
-} // namespace priv
-
-} // namespace sf
-
-
-#endif // SFML_SOUNDFILE_HPP
+////////////////////////////////////////////////////////////
+//
+// 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_SOUNDFILE_HPP
+#define SFML_SOUNDFILE_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/System/NonCopyable.hpp>
+#include <SFML/System/Time.hpp>
+#include <sndfile.h>
+#include <string>
+
+
+namespace sf
+{
+class InputStream;
+
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// \brief Provide read and write access to sound files
+///
+////////////////////////////////////////////////////////////
+class SoundFile : NonCopyable
+{
+public:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Default constructor
+ ///
+ ////////////////////////////////////////////////////////////
+ SoundFile();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Destructor
+ ///
+ ////////////////////////////////////////////////////////////
+ ~SoundFile();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the total number of audio samples in the file
+ ///
+ /// \return Number of samples
+ ///
+ ////////////////////////////////////////////////////////////
+ std::size_t getSampleCount() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the number of channels used by the sound
+ ///
+ /// \return Number of channels (1 = mono, 2 = stereo)
+ ///
+ ////////////////////////////////////////////////////////////
+ unsigned int getChannelCount() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the sample rate of the sound
+ ///
+ /// \return Sample rate, in samples per second
+ ///
+ ////////////////////////////////////////////////////////////
+ unsigned int getSampleRate() const;
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Open a sound file for reading
+ ///
+ /// \param filename Path of the sound file to load
+ ///
+ /// \return True if the file was successfully opened
+ ///
+ ////////////////////////////////////////////////////////////
+ bool openRead(const std::string& filename);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Open a sound file in memory for reading
+ ///
+ /// \param data Pointer to the file data in memory
+ /// \param sizeInBytes Size of the data to load, in bytes
+ ///
+ /// \return True if the file was successfully opened
+ ///
+ ////////////////////////////////////////////////////////////
+ bool openRead(const void* data, std::size_t sizeInBytes);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Open a sound file from a custom stream for reading
+ ///
+ /// \param stream Source stream to read from
+ ///
+ /// \return True if the file was successfully opened
+ ///
+ ////////////////////////////////////////////////////////////
+ bool openRead(InputStream& stream);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief a the sound file for writing
+ ///
+ /// \param filename Path of the sound file to write
+ /// \param channelCount Number of channels in the sound
+ /// \param sampleRate Sample rate of the sound
+ ///
+ /// \return True if the file was successfully opened
+ ///
+ ////////////////////////////////////////////////////////////
+ bool openWrite(const std::string& filename, unsigned int channelCount, unsigned int sampleRate);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Read audio samples from the loaded sound
+ ///
+ /// \param data Pointer to the sample array to fill
+ /// \param sampleCount Number of samples to read
+ ///
+ /// \return Number of samples actually read (may be less than \a sampleCount)
+ ///
+ ////////////////////////////////////////////////////////////
+ std::size_t read(Int16* data, std::size_t sampleCount);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Write audio samples to the file
+ ///
+ /// \param data Pointer to the sample array to write
+ /// \param sampleCount Number of samples to write
+ ///
+ ////////////////////////////////////////////////////////////
+ void write(const Int16* data, std::size_t sampleCount);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Change the current read position in the file
+ ///
+ /// \param timeOffset New playing position, from the beginning of the file
+ ///
+ ////////////////////////////////////////////////////////////
+ void seek(Time timeOffset);
+
+private:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Initialize the internal state of the sound file
+ ///
+ /// This function is called by all the openRead functions.
+ ///
+ /// \param fileInfo Information about the loaded sound file
+ ///
+ ////////////////////////////////////////////////////////////
+ void initialize(SF_INFO fileInfo);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the internal format of an audio file according to
+ /// its filename extension
+ ///
+ /// \param filename Filename to check
+ ///
+ /// \return Internal format matching the filename (-1 if no match)
+ ///
+ ////////////////////////////////////////////////////////////
+ static int getFormatFromFilename(const std::string& filename);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Data and callbacks for opening from memory
+ ///
+ ////////////////////////////////////////////////////////////
+ struct Memory
+ {
+ const char* begin;
+ const char* current;
+ sf_count_t size;
+
+ static sf_count_t getLength(void* user);
+ static sf_count_t read(void* ptr, sf_count_t count, void* user);
+ static sf_count_t seek(sf_count_t offset, int whence, void* user);
+ static sf_count_t tell(void* user);
+ };
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Data and callbacks for opening from stream
+ ///
+ ////////////////////////////////////////////////////////////
+ struct Stream
+ {
+ InputStream* source;
+ Int64 size;
+
+ static sf_count_t getLength(void* user);
+ static sf_count_t read(void* ptr, sf_count_t count, void* user);
+ static sf_count_t seek(sf_count_t offset, int whence, void* user);
+ static sf_count_t tell(void* user);
+ };
+
+ ////////////////////////////////////////////////////////////
+ // Member data
+ ////////////////////////////////////////////////////////////
+ SNDFILE* m_file; ///< File descriptor
+ Memory m_memory; ///< Memory reading info
+ Stream m_stream; ///< Stream reading info
+ std::size_t m_sampleCount; ///< Total number of samples in the file
+ unsigned int m_channelCount; ///< Number of channels used by the sound
+ unsigned int m_sampleRate; ///< Number of samples per second
+ #ifdef SFML_SYSTEM_ANDROID
+ void* m_resourceStream; ///< Asset file streamer (if loaded from file)
+ #endif
+};
+
+} // namespace priv
+
+} // namespace sf
+
+
+#endif // SFML_SOUNDFILE_HPP
diff --git a/src/SFML/Audio/SoundRecorder.cpp b/src/SFML/Audio/SoundRecorder.cpp
index bf7b03f..51e7ef9 100644
--- a/src/SFML/Audio/SoundRecorder.cpp
+++ b/src/SFML/Audio/SoundRecorder.cpp
@@ -1,203 +1,290 @@
-////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 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/SoundRecorder.hpp>
-#include <SFML/Audio/AudioDevice.hpp>
-#include <SFML/Audio/ALCheck.hpp>
-#include <SFML/System/Sleep.hpp>
-#include <SFML/System/Err.hpp>
-
-#ifdef _MSC_VER
- #pragma warning(disable : 4355) // 'this' used in base member initializer list
-#endif
-
-
-namespace
-{
- ALCdevice* captureDevice = NULL;
-}
-
-namespace sf
-{
-////////////////////////////////////////////////////////////
-SoundRecorder::SoundRecorder() :
-m_thread (&SoundRecorder::record, this),
-m_sampleRate (0),
-m_isCapturing(false)
-{
- priv::ensureALInit();
-}
-
-
-////////////////////////////////////////////////////////////
-SoundRecorder::~SoundRecorder()
-{
- // Nothing to do
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundRecorder::start(unsigned int sampleRate)
-{
- // Check if the device can do audio capture
- if (!isAvailable())
- {
- err() << "Failed to start capture : your system cannot capture audio data (call SoundRecorder::IsAvailable to check it)" << std::endl;
- return;
- }
-
- // Check that another capture is not already running
- if (captureDevice)
- {
- err() << "Trying to start audio capture, but another capture is already running" << std::endl;
- return;
- }
-
- // Open the capture device for capturing 16 bits mono samples
- captureDevice = alcCaptureOpenDevice(NULL, sampleRate, AL_FORMAT_MONO16, sampleRate);
- if (!captureDevice)
- {
- err() << "Failed to open the audio capture device" << std::endl;
- return;
- }
-
- // Clear the array of samples
- m_samples.clear();
-
- // Store the sample rate
- m_sampleRate = sampleRate;
-
- // Notify derived class
- if (onStart())
- {
- // Start the capture
- alcCaptureStart(captureDevice);
-
- // Start the capture in a new thread, to avoid blocking the main thread
- m_isCapturing = true;
- m_thread.launch();
- }
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundRecorder::stop()
-{
- // Stop the capturing thread
- m_isCapturing = false;
- m_thread.wait();
-}
-
-
-////////////////////////////////////////////////////////////
-unsigned int SoundRecorder::getSampleRate() const
-{
- return m_sampleRate;
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundRecorder::isAvailable()
-{
- return (priv::AudioDevice::isExtensionSupported("ALC_EXT_CAPTURE") != AL_FALSE) ||
- (priv::AudioDevice::isExtensionSupported("ALC_EXT_capture") != AL_FALSE); // "bug" in Mac OS X 10.5 and 10.6
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundRecorder::onStart()
-{
- // Nothing to do
- return true;
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundRecorder::onStop()
-{
- // Nothing to do
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundRecorder::record()
-{
- while (m_isCapturing)
- {
- // Process available samples
- processCapturedSamples();
-
- // Don't bother the CPU while waiting for more captured data
- sleep(milliseconds(100));
- }
-
- // Capture is finished : clean up everything
- cleanup();
-
- // Notify derived class
- onStop();
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundRecorder::processCapturedSamples()
-{
- // Get the number of samples available
- ALCint samplesAvailable;
- alcGetIntegerv(captureDevice, ALC_CAPTURE_SAMPLES, 1, &samplesAvailable);
-
- if (samplesAvailable > 0)
- {
- // Get the recorded samples
- m_samples.resize(samplesAvailable);
- alcCaptureSamples(captureDevice, &m_samples[0], samplesAvailable);
-
- // Forward them to the derived class
- if (!onProcessSamples(&m_samples[0], m_samples.size()))
- {
- // The user wants to stop the capture
- m_isCapturing = false;
- }
- }
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundRecorder::cleanup()
-{
- // Stop the capture
- alcCaptureStop(captureDevice);
-
- // Get the samples left in the buffer
- processCapturedSamples();
-
- // Close the device
- alcCaptureCloseDevice(captureDevice);
- captureDevice = NULL;
-}
-
-} // namespace sf
+////////////////////////////////////////////////////////////
+//
+// 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/SoundRecorder.hpp>
+#include <SFML/Audio/AudioDevice.hpp>
+#include <SFML/Audio/ALCheck.hpp>
+#include <SFML/System/Sleep.hpp>
+#include <SFML/System/Err.hpp>
+#include <cstring>
+
+#ifdef _MSC_VER
+ #pragma warning(disable: 4355) // 'this' used in base member initializer list
+#endif
+
+
+namespace
+{
+ ALCdevice* captureDevice = NULL;
+}
+
+namespace sf
+{
+////////////////////////////////////////////////////////////
+SoundRecorder::SoundRecorder() :
+m_thread (&SoundRecorder::record, this),
+m_sampleRate (0),
+m_processingInterval(milliseconds(100)),
+m_isCapturing (false)
+{
+ priv::ensureALInit();
+
+ // Set the device name to the default device
+ m_deviceName = getDefaultDevice();
+}
+
+
+////////////////////////////////////////////////////////////
+SoundRecorder::~SoundRecorder()
+{
+ // Nothing to do
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundRecorder::start(unsigned int sampleRate)
+{
+ // Check if the device can do audio capture
+ if (!isAvailable())
+ {
+ err() << "Failed to start capture: your system cannot capture audio data (call SoundRecorder::isAvailable to check it)" << std::endl;
+ return false;
+ }
+
+ // Check that another capture is not already running
+ if (captureDevice)
+ {
+ err() << "Trying to start audio capture, but another capture is already running" << std::endl;
+ return false;
+ }
+
+ // Open the capture device for capturing 16 bits mono samples
+ captureDevice = alcCaptureOpenDevice(m_deviceName.c_str(), sampleRate, AL_FORMAT_MONO16, sampleRate);
+ if (!captureDevice)
+ {
+ err() << "Failed to open the audio capture device with the name: " << m_deviceName << std::endl;
+ return false;
+ }
+
+ // Clear the array of samples
+ m_samples.clear();
+
+ // Store the sample rate
+ m_sampleRate = sampleRate;
+
+ // Notify derived class
+ if (onStart())
+ {
+ // Start the capture
+ alcCaptureStart(captureDevice);
+
+ // Start the capture in a new thread, to avoid blocking the main thread
+ m_isCapturing = true;
+ m_thread.launch();
+
+ return true;
+ }
+
+ return false;
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundRecorder::stop()
+{
+ // Stop the capturing thread
+ m_isCapturing = false;
+ m_thread.wait();
+
+ // Notify derived class
+ onStop();
+}
+
+
+////////////////////////////////////////////////////////////
+unsigned int SoundRecorder::getSampleRate() const
+{
+ return m_sampleRate;
+}
+
+
+////////////////////////////////////////////////////////////
+std::vector<std::string> SoundRecorder::getAvailableDevices()
+{
+ std::vector<std::string> deviceNameList;
+
+ const ALchar *deviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
+ if (deviceList)
+ {
+ while (*deviceList)
+ {
+ deviceNameList.push_back(deviceList);
+ deviceList += std::strlen(deviceList) + 1;
+ }
+ }
+
+ return deviceNameList;
+}
+
+
+////////////////////////////////////////////////////////////
+std::string SoundRecorder::getDefaultDevice()
+{
+ return alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundRecorder::setDevice(const std::string& name)
+{
+ // Store the device name
+ if (name.empty())
+ m_deviceName = getDefaultDevice();
+ else
+ m_deviceName = name;
+
+ if (m_isCapturing)
+ {
+ // Stop the capturing thread
+ m_isCapturing = false;
+ m_thread.wait();
+
+ // Open the requested capture device for capturing 16 bits mono samples
+ captureDevice = alcCaptureOpenDevice(name.c_str(), m_sampleRate, AL_FORMAT_MONO16, m_sampleRate);
+ if (!captureDevice)
+ {
+ // Notify derived class
+ onStop();
+
+ err() << "Failed to open the audio capture device with the name: " << m_deviceName << std::endl;
+ return false;
+ }
+
+ // Start the capture
+ alcCaptureStart(captureDevice);
+
+ // Start the capture in a new thread, to avoid blocking the main thread
+ m_isCapturing = true;
+ m_thread.launch();
+ }
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+const std::string& SoundRecorder::getDevice() const
+{
+ return m_deviceName;
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundRecorder::isAvailable()
+{
+ return (priv::AudioDevice::isExtensionSupported("ALC_EXT_CAPTURE") != AL_FALSE) ||
+ (priv::AudioDevice::isExtensionSupported("ALC_EXT_capture") != AL_FALSE); // "bug" in Mac OS X 10.5 and 10.6
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundRecorder::setProcessingInterval(sf::Time interval)
+{
+ m_processingInterval = interval;
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundRecorder::onStart()
+{
+ // Nothing to do
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundRecorder::onStop()
+{
+ // Nothing to do
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundRecorder::record()
+{
+ while (m_isCapturing)
+ {
+ // Process available samples
+ processCapturedSamples();
+
+ // Don't bother the CPU while waiting for more captured data
+ sleep(m_processingInterval);
+ }
+
+ // Capture is finished: clean up everything
+ cleanup();
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundRecorder::processCapturedSamples()
+{
+ // Get the number of samples available
+ ALCint samplesAvailable;
+ alcGetIntegerv(captureDevice, ALC_CAPTURE_SAMPLES, 1, &samplesAvailable);
+
+ if (samplesAvailable > 0)
+ {
+ // Get the recorded samples
+ m_samples.resize(samplesAvailable);
+ alcCaptureSamples(captureDevice, &m_samples[0], samplesAvailable);
+
+ // Forward them to the derived class
+ if (!onProcessSamples(&m_samples[0], m_samples.size()))
+ {
+ // The user wants to stop the capture
+ m_isCapturing = false;
+ }
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundRecorder::cleanup()
+{
+ // Stop the capture
+ alcCaptureStop(captureDevice);
+
+ // Get the samples left in the buffer
+ processCapturedSamples();
+
+ // Close the device
+ alcCaptureCloseDevice(captureDevice);
+ captureDevice = NULL;
+}
+
+} // namespace sf
diff --git a/src/SFML/Audio/SoundSource.cpp b/src/SFML/Audio/SoundSource.cpp
index c5a6524..3129b2e 100644
--- a/src/SFML/Audio/SoundSource.cpp
+++ b/src/SFML/Audio/SoundSource.cpp
@@ -1,194 +1,194 @@
-////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 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/SoundSource.hpp>
-#include <SFML/Audio/ALCheck.hpp>
-
-
-namespace sf
-{
-////////////////////////////////////////////////////////////
-SoundSource::SoundSource()
-{
- priv::ensureALInit();
-
- alCheck(alGenSources(1, &m_source));
- alCheck(alSourcei(m_source, AL_BUFFER, 0));
-}
-
-
-////////////////////////////////////////////////////////////
-SoundSource::SoundSource(const SoundSource& copy)
-{
- priv::ensureALInit();
-
- alCheck(alGenSources(1, &m_source));
- alCheck(alSourcei(m_source, AL_BUFFER, 0));
-
- setPitch(copy.getPitch());
- setVolume(copy.getVolume());
- setPosition(copy.getPosition());
- setRelativeToListener(copy.isRelativeToListener());
- setMinDistance(copy.getMinDistance());
- setAttenuation(copy.getAttenuation());
-}
-
-
-////////////////////////////////////////////////////////////
-SoundSource::~SoundSource()
-{
- alCheck(alSourcei(m_source, AL_BUFFER, 0));
- alCheck(alDeleteSources(1, &m_source));
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundSource::setPitch(float pitch)
-{
- alCheck(alSourcef(m_source, AL_PITCH, pitch));
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundSource::setVolume(float volume)
-{
- alCheck(alSourcef(m_source, AL_GAIN, volume * 0.01f));
-}
-
-////////////////////////////////////////////////////////////
-void SoundSource::setPosition(float x, float y, float z)
-{
- alCheck(alSource3f(m_source, AL_POSITION, x, y, z));
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundSource::setPosition(const Vector3f& position)
-{
- setPosition(position.x, position.y, position.z);
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundSource::setRelativeToListener(bool relative)
-{
- alCheck(alSourcei(m_source, AL_SOURCE_RELATIVE, relative));
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundSource::setMinDistance(float distance)
-{
- alCheck(alSourcef(m_source, AL_REFERENCE_DISTANCE, distance));
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundSource::setAttenuation(float attenuation)
-{
- alCheck(alSourcef(m_source, AL_ROLLOFF_FACTOR, attenuation));
-}
-
-
-////////////////////////////////////////////////////////////
-float SoundSource::getPitch() const
-{
- ALfloat pitch;
- alCheck(alGetSourcef(m_source, AL_PITCH, &pitch));
-
- return pitch;
-}
-
-
-////////////////////////////////////////////////////////////
-float SoundSource::getVolume() const
-{
- ALfloat gain;
- alCheck(alGetSourcef(m_source, AL_GAIN, &gain));
-
- return gain * 100.f;
-}
-
-
-////////////////////////////////////////////////////////////
-Vector3f SoundSource::getPosition() const
-{
- Vector3f position;
- alCheck(alGetSource3f(m_source, AL_POSITION, &position.x, &position.y, &position.z));
-
- return position;
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundSource::isRelativeToListener() const
-{
- ALint relative;
- alCheck(alGetSourcei(m_source, AL_SOURCE_RELATIVE, &relative));
-
- return relative != 0;
-}
-
-
-////////////////////////////////////////////////////////////
-float SoundSource::getMinDistance() const
-{
- ALfloat distance;
- alCheck(alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &distance));
-
- return distance;
-}
-
-
-////////////////////////////////////////////////////////////
-float SoundSource::getAttenuation() const
-{
- ALfloat attenuation;
- alCheck(alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &attenuation));
-
- return attenuation;
-}
-
-
-////////////////////////////////////////////////////////////
-SoundSource::Status SoundSource::getStatus() const
-{
- ALint status;
- alCheck(alGetSourcei(m_source, AL_SOURCE_STATE, &status));
-
- switch (status)
- {
- case AL_INITIAL :
- case AL_STOPPED : return Stopped;
- case AL_PAUSED : return Paused;
- case AL_PLAYING : return Playing;
- }
-
- return Stopped;
-}
-
-} // namespace sf
+////////////////////////////////////////////////////////////
+//
+// 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/SoundSource.hpp>
+#include <SFML/Audio/ALCheck.hpp>
+
+
+namespace sf
+{
+////////////////////////////////////////////////////////////
+SoundSource::SoundSource()
+{
+ priv::ensureALInit();
+
+ alCheck(alGenSources(1, &m_source));
+ alCheck(alSourcei(m_source, AL_BUFFER, 0));
+}
+
+
+////////////////////////////////////////////////////////////
+SoundSource::SoundSource(const SoundSource& copy)
+{
+ priv::ensureALInit();
+
+ alCheck(alGenSources(1, &m_source));
+ alCheck(alSourcei(m_source, AL_BUFFER, 0));
+
+ setPitch(copy.getPitch());
+ setVolume(copy.getVolume());
+ setPosition(copy.getPosition());
+ setRelativeToListener(copy.isRelativeToListener());
+ setMinDistance(copy.getMinDistance());
+ setAttenuation(copy.getAttenuation());
+}
+
+
+////////////////////////////////////////////////////////////
+SoundSource::~SoundSource()
+{
+ alCheck(alSourcei(m_source, AL_BUFFER, 0));
+ alCheck(alDeleteSources(1, &m_source));
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundSource::setPitch(float pitch)
+{
+ alCheck(alSourcef(m_source, AL_PITCH, pitch));
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundSource::setVolume(float volume)
+{
+ alCheck(alSourcef(m_source, AL_GAIN, volume * 0.01f));
+}
+
+////////////////////////////////////////////////////////////
+void SoundSource::setPosition(float x, float y, float z)
+{
+ alCheck(alSource3f(m_source, AL_POSITION, x, y, z));
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundSource::setPosition(const Vector3f& position)
+{
+ setPosition(position.x, position.y, position.z);
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundSource::setRelativeToListener(bool relative)
+{
+ alCheck(alSourcei(m_source, AL_SOURCE_RELATIVE, relative));
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundSource::setMinDistance(float distance)
+{
+ alCheck(alSourcef(m_source, AL_REFERENCE_DISTANCE, distance));
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundSource::setAttenuation(float attenuation)
+{
+ alCheck(alSourcef(m_source, AL_ROLLOFF_FACTOR, attenuation));
+}
+
+
+////////////////////////////////////////////////////////////
+float SoundSource::getPitch() const
+{
+ ALfloat pitch;
+ alCheck(alGetSourcef(m_source, AL_PITCH, &pitch));
+
+ return pitch;
+}
+
+
+////////////////////////////////////////////////////////////
+float SoundSource::getVolume() const
+{
+ ALfloat gain;
+ alCheck(alGetSourcef(m_source, AL_GAIN, &gain));
+
+ return gain * 100.f;
+}
+
+
+////////////////////////////////////////////////////////////
+Vector3f SoundSource::getPosition() const
+{
+ Vector3f position;
+ alCheck(alGetSource3f(m_source, AL_POSITION, &position.x, &position.y, &position.z));
+
+ return position;
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundSource::isRelativeToListener() const
+{
+ ALint relative;
+ alCheck(alGetSourcei(m_source, AL_SOURCE_RELATIVE, &relative));
+
+ return relative != 0;
+}
+
+
+////////////////////////////////////////////////////////////
+float SoundSource::getMinDistance() const
+{
+ ALfloat distance;
+ alCheck(alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &distance));
+
+ return distance;
+}
+
+
+////////////////////////////////////////////////////////////
+float SoundSource::getAttenuation() const
+{
+ ALfloat attenuation;
+ alCheck(alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &attenuation));
+
+ return attenuation;
+}
+
+
+////////////////////////////////////////////////////////////
+SoundSource::Status SoundSource::getStatus() const
+{
+ ALint status;
+ alCheck(alGetSourcei(m_source, AL_SOURCE_STATE, &status));
+
+ switch (status)
+ {
+ case AL_INITIAL:
+ case AL_STOPPED: return Stopped;
+ case AL_PAUSED: return Paused;
+ case AL_PLAYING: return Playing;
+ }
+
+ return Stopped;
+}
+
+} // namespace sf
diff --git a/src/SFML/Audio/SoundStream.cpp b/src/SFML/Audio/SoundStream.cpp
index 31df188..8321889 100644
--- a/src/SFML/Audio/SoundStream.cpp
+++ b/src/SFML/Audio/SoundStream.cpp
@@ -1,365 +1,469 @@
-////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 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/SoundStream.hpp>
-#include <SFML/Audio/AudioDevice.hpp>
-#include <SFML/Audio/ALCheck.hpp>
-#include <SFML/System/Sleep.hpp>
-#include <SFML/System/Err.hpp>
-
-#ifdef _MSC_VER
- #pragma warning(disable : 4355) // 'this' used in base member initializer list
-#endif
-
-
-namespace sf
-{
-////////////////////////////////////////////////////////////
-SoundStream::SoundStream() :
-m_thread (&SoundStream::streamData, this),
-m_isStreaming (false),
-m_channelCount (0),
-m_sampleRate (0),
-m_format (0),
-m_loop (false),
-m_samplesProcessed(0)
-{
-
-}
-
-
-////////////////////////////////////////////////////////////
-SoundStream::~SoundStream()
-{
- // Stop the sound if it was playing
- stop();
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundStream::initialize(unsigned int channelCount, unsigned int sampleRate)
-{
- m_channelCount = channelCount;
- m_sampleRate = sampleRate;
-
- // Deduce the format from the number of channels
- m_format = priv::AudioDevice::getFormatFromChannelCount(channelCount);
-
- // Check if the format is valid
- if (m_format == 0)
- {
- m_channelCount = 0;
- m_sampleRate = 0;
- err() << "Unsupported number of channels (" << m_channelCount << ")" << std::endl;
- }
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundStream::play()
-{
- // Check if the sound parameters have been set
- if (m_format == 0)
- {
- err() << "Failed to play audio stream: sound parameters have not been initialized (call Initialize first)" << std::endl;
- return;
- }
-
- // If the sound is already playing (probably paused), just resume it
- if (m_isStreaming)
- {
- alCheck(alSourcePlay(m_source));
- return;
- }
-
- // Move to the beginning
- onSeek(Time::Zero);
-
- // Start updating the stream in a separate thread to avoid blocking the application
- m_samplesProcessed = 0;
- m_isStreaming = true;
- m_thread.launch();
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundStream::pause()
-{
- alCheck(alSourcePause(m_source));
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundStream::stop()
-{
- // Wait for the thread to terminate
- m_isStreaming = false;
- m_thread.wait();
-}
-
-
-////////////////////////////////////////////////////////////
-unsigned int SoundStream::getChannelCount() const
-{
- return m_channelCount;
-}
-
-
-////////////////////////////////////////////////////////////
-unsigned int SoundStream::getSampleRate() const
-{
- return m_sampleRate;
-}
-
-
-////////////////////////////////////////////////////////////
-SoundStream::Status SoundStream::getStatus() const
-{
- Status status = SoundSource::getStatus();
-
- // To compensate for the lag between play() and alSourceplay()
- if ((status == Stopped) && m_isStreaming)
- status = Playing;
-
- return status;
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundStream::setPlayingOffset(Time timeOffset)
-{
- // Stop the stream
- stop();
-
- // Let the derived class update the current position
- onSeek(timeOffset);
-
- // Restart streaming
- m_samplesProcessed = static_cast<Uint64>(timeOffset.asSeconds() * m_sampleRate * m_channelCount);
- m_isStreaming = true;
- m_thread.launch();
-}
-
-
-////////////////////////////////////////////////////////////
-Time SoundStream::getPlayingOffset() const
-{
- if (m_sampleRate && m_channelCount)
- {
- ALfloat secs = 0.f;
- alCheck(alGetSourcef(m_source, AL_SEC_OFFSET, &secs));
-
- return seconds(secs + static_cast<float>(m_samplesProcessed) / m_sampleRate / m_channelCount);
- }
- else
- {
- return Time::Zero;
- }
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundStream::setLoop(bool loop)
-{
- m_loop = loop;
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundStream::getLoop() const
-{
- return m_loop;
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundStream::streamData()
-{
- // Create the buffers
- alCheck(alGenBuffers(BufferCount, m_buffers));
- for (int i = 0; i < BufferCount; ++i)
- m_endBuffers[i] = false;
-
- // Fill the queue
- bool requestStop = fillQueue();
-
- // Play the sound
- alCheck(alSourcePlay(m_source));
-
- while (m_isStreaming)
- {
- // The stream has been interrupted!
- if (SoundSource::getStatus() == Stopped)
- {
- if (!requestStop)
- {
- // Just continue
- alCheck(alSourcePlay(m_source));
- }
- else
- {
- // End streaming
- m_isStreaming = false;
- }
- }
-
- // Get the number of buffers that have been processed (ie. ready for reuse)
- ALint nbProcessed = 0;
- alCheck(alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &nbProcessed));
-
- while (nbProcessed--)
- {
- // Pop the first unused buffer from the queue
- ALuint buffer;
- alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer));
-
- // Find its number
- unsigned int bufferNum = 0;
- for (int i = 0; i < BufferCount; ++i)
- if (m_buffers[i] == buffer)
- {
- bufferNum = i;
- break;
- }
-
- // Retrieve its size and add it to the samples count
- if (m_endBuffers[bufferNum])
- {
- // This was the last buffer: reset the sample count
- m_samplesProcessed = 0;
- m_endBuffers[bufferNum] = false;
- }
- else
- {
- ALint size, bits;
- alCheck(alGetBufferi(buffer, AL_SIZE, &size));
- alCheck(alGetBufferi(buffer, AL_BITS, &bits));
- m_samplesProcessed += size / (bits / 8);
- }
-
- // Fill it and push it back into the playing queue
- if (!requestStop)
- {
- if (fillAndPushBuffer(bufferNum))
- requestStop = true;
- }
- }
-
- // Leave some time for the other threads if the stream is still playing
- if (SoundSource::getStatus() != Stopped)
- sleep(milliseconds(10));
- }
-
- // Stop the playback
- alCheck(alSourceStop(m_source));
-
- // Unqueue any buffer left in the queue
- clearQueue();
-
- // Delete the buffers
- alCheck(alSourcei(m_source, AL_BUFFER, 0));
- alCheck(alDeleteBuffers(BufferCount, m_buffers));
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundStream::fillAndPushBuffer(unsigned int bufferNum)
-{
- bool requestStop = false;
-
- // Acquire audio data
- Chunk data = {NULL, 0};
- if (!onGetData(data))
- {
- // Mark the buffer as the last one (so that we know when to reset the playing position)
- m_endBuffers[bufferNum] = true;
-
- // Check if the stream must loop or stop
- if (m_loop)
- {
- // Return to the beginning of the stream source
- onSeek(Time::Zero);
-
- // If we previously had no data, try to fill the buffer once again
- if (!data.samples || (data.sampleCount == 0))
- {
- return fillAndPushBuffer(bufferNum);
- }
- }
- else
- {
- // Not looping: request stop
- requestStop = true;
- }
- }
-
- // Fill the buffer if some data was returned
- if (data.samples && data.sampleCount)
- {
- unsigned int buffer = m_buffers[bufferNum];
-
- // Fill the buffer
- ALsizei size = static_cast<ALsizei>(data.sampleCount) * sizeof(Int16);
- alCheck(alBufferData(buffer, m_format, data.samples, size, m_sampleRate));
-
- // Push it into the sound queue
- alCheck(alSourceQueueBuffers(m_source, 1, &buffer));
- }
-
- return requestStop;
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundStream::fillQueue()
-{
- // Fill and enqueue all the available buffers
- bool requestStop = false;
- for (int i = 0; (i < BufferCount) && !requestStop; ++i)
- {
- if (fillAndPushBuffer(i))
- requestStop = true;
- }
-
- return requestStop;
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundStream::clearQueue()
-{
- // Get the number of buffers still in the queue
- ALint nbQueued;
- alCheck(alGetSourcei(m_source, AL_BUFFERS_QUEUED, &nbQueued));
-
- // Unqueue them all
- ALuint buffer;
- for (ALint i = 0; i < nbQueued; ++i)
- alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer));
-}
-
-} // namespace sf
+////////////////////////////////////////////////////////////
+//
+// 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/SoundStream.hpp>
+#include <SFML/Audio/AudioDevice.hpp>
+#include <SFML/Audio/ALCheck.hpp>
+#include <SFML/System/Sleep.hpp>
+#include <SFML/System/Err.hpp>
+#include <SFML/System/Lock.hpp>
+
+#ifdef _MSC_VER
+ #pragma warning(disable: 4355) // 'this' used in base member initializer list
+#endif
+
+
+namespace sf
+{
+////////////////////////////////////////////////////////////
+SoundStream::SoundStream() :
+m_thread (&SoundStream::streamData, this),
+m_threadMutex (),
+m_threadStartState(Stopped),
+m_isStreaming (false),
+m_channelCount (0),
+m_sampleRate (0),
+m_format (0),
+m_loop (false),
+m_samplesProcessed(0)
+{
+
+}
+
+
+////////////////////////////////////////////////////////////
+SoundStream::~SoundStream()
+{
+ // Stop the sound if it was playing
+
+ // Request the thread to terminate
+ {
+ Lock lock(m_threadMutex);
+ m_isStreaming = false;
+ }
+
+ // Wait for the thread to terminate
+ m_thread.wait();
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundStream::initialize(unsigned int channelCount, unsigned int sampleRate)
+{
+ m_channelCount = channelCount;
+ m_sampleRate = sampleRate;
+
+ // Deduce the format from the number of channels
+ m_format = priv::AudioDevice::getFormatFromChannelCount(channelCount);
+
+ // Check if the format is valid
+ if (m_format == 0)
+ {
+ m_channelCount = 0;
+ m_sampleRate = 0;
+ err() << "Unsupported number of channels (" << m_channelCount << ")" << std::endl;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundStream::play()
+{
+ // Check if the sound parameters have been set
+ if (m_format == 0)
+ {
+ err() << "Failed to play audio stream: sound parameters have not been initialized (call initialize() first)" << std::endl;
+ return;
+ }
+
+ bool isStreaming = false;
+ Status threadStartState = Stopped;
+
+ {
+ Lock lock(m_threadMutex);
+
+ isStreaming = m_isStreaming;
+ threadStartState = m_threadStartState;
+ }
+
+
+ if (isStreaming && (threadStartState == Paused))
+ {
+ // If the sound is paused, resume it
+ Lock lock(m_threadMutex);
+ m_threadStartState = Playing;
+ alCheck(alSourcePlay(m_source));
+ return;
+ }
+ else if (isStreaming && (threadStartState == Playing))
+ {
+ // If the sound is playing, stop it and continue as if it was stopped
+ stop();
+ }
+
+ // Move to the beginning
+ onSeek(Time::Zero);
+
+ // Start updating the stream in a separate thread to avoid blocking the application
+ m_samplesProcessed = 0;
+ m_isStreaming = true;
+ m_threadStartState = Playing;
+ m_thread.launch();
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundStream::pause()
+{
+ // Handle pause() being called before the thread has started
+ {
+ Lock lock(m_threadMutex);
+
+ if (!m_isStreaming)
+ return;
+
+ m_threadStartState = Paused;
+ }
+
+ alCheck(alSourcePause(m_source));
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundStream::stop()
+{
+ // Request the thread to terminate
+ {
+ Lock lock(m_threadMutex);
+ m_isStreaming = false;
+ }
+
+ // Wait for the thread to terminate
+ m_thread.wait();
+
+ // Move to the beginning
+ onSeek(Time::Zero);
+
+ // Reset the playing position
+ m_samplesProcessed = 0;
+}
+
+
+////////////////////////////////////////////////////////////
+unsigned int SoundStream::getChannelCount() const
+{
+ return m_channelCount;
+}
+
+
+////////////////////////////////////////////////////////////
+unsigned int SoundStream::getSampleRate() const
+{
+ return m_sampleRate;
+}
+
+
+////////////////////////////////////////////////////////////
+SoundStream::Status SoundStream::getStatus() const
+{
+ Status status = SoundSource::getStatus();
+
+ // To compensate for the lag between play() and alSourceplay()
+ if (status == Stopped)
+ {
+ Lock lock(m_threadMutex);
+
+ if (m_isStreaming)
+ status = m_threadStartState;
+ }
+
+ return status;
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundStream::setPlayingOffset(Time timeOffset)
+{
+ // Get old playing status
+ Status oldStatus = getStatus();
+
+ // Stop the stream
+ stop();
+
+ // Let the derived class update the current position
+ onSeek(timeOffset);
+
+ // Restart streaming
+ m_samplesProcessed = static_cast<Uint64>(timeOffset.asSeconds() * m_sampleRate * m_channelCount);
+
+ if (oldStatus == Stopped)
+ return;
+
+ m_isStreaming = true;
+ m_threadStartState = oldStatus;
+ m_thread.launch();
+}
+
+
+////////////////////////////////////////////////////////////
+Time SoundStream::getPlayingOffset() const
+{
+ if (m_sampleRate && m_channelCount)
+ {
+ ALfloat secs = 0.f;
+ alCheck(alGetSourcef(m_source, AL_SEC_OFFSET, &secs));
+
+ return seconds(secs + static_cast<float>(m_samplesProcessed) / m_sampleRate / m_channelCount);
+ }
+ else
+ {
+ return Time::Zero;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundStream::setLoop(bool loop)
+{
+ m_loop = loop;
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundStream::getLoop() const
+{
+ return m_loop;
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundStream::streamData()
+{
+ bool requestStop = false;
+
+ {
+ Lock lock(m_threadMutex);
+
+ // Check if the thread was launched Stopped
+ if (m_threadStartState == Stopped)
+ {
+ m_isStreaming = false;
+ return;
+ }
+
+ // Create the buffers
+ alCheck(alGenBuffers(BufferCount, m_buffers));
+ for (int i = 0; i < BufferCount; ++i)
+ m_endBuffers[i] = false;
+
+ // Fill the queue
+ requestStop = fillQueue();
+
+ // Play the sound
+ alCheck(alSourcePlay(m_source));
+
+ // Check if the thread was launched Paused
+ if (m_threadStartState == Paused)
+ alCheck(alSourcePause(m_source));
+ }
+
+ for (;;)
+ {
+ {
+ Lock lock(m_threadMutex);
+ if (!m_isStreaming)
+ break;
+ }
+
+ // The stream has been interrupted!
+ if (SoundSource::getStatus() == Stopped)
+ {
+ if (!requestStop)
+ {
+ // Just continue
+ alCheck(alSourcePlay(m_source));
+ }
+ else
+ {
+ // End streaming
+ Lock lock(m_threadMutex);
+ m_isStreaming = false;
+ }
+ }
+
+ // Get the number of buffers that have been processed (i.e. ready for reuse)
+ ALint nbProcessed = 0;
+ alCheck(alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &nbProcessed));
+
+ while (nbProcessed--)
+ {
+ // Pop the first unused buffer from the queue
+ ALuint buffer;
+ alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer));
+
+ // Find its number
+ unsigned int bufferNum = 0;
+ for (int i = 0; i < BufferCount; ++i)
+ if (m_buffers[i] == buffer)
+ {
+ bufferNum = i;
+ break;
+ }
+
+ // Retrieve its size and add it to the samples count
+ if (m_endBuffers[bufferNum])
+ {
+ // This was the last buffer: reset the sample count
+ m_samplesProcessed = 0;
+ m_endBuffers[bufferNum] = false;
+ }
+ else
+ {
+ ALint size, bits;
+ alCheck(alGetBufferi(buffer, AL_SIZE, &size));
+ alCheck(alGetBufferi(buffer, AL_BITS, &bits));
+
+ // Bits can be 0 if the format or parameters are corrupt, avoid division by zero
+ if (bits == 0)
+ {
+ err() << "Bits in sound stream are 0: make sure that the audio format is not corrupt "
+ << "and initialize() has been called correctly" << std::endl;
+
+ // Abort streaming (exit main loop)
+ Lock lock(m_threadMutex);
+ m_isStreaming = false;
+ requestStop = true;
+ break;
+ }
+ else
+ {
+ m_samplesProcessed += size / (bits / 8);
+ }
+ }
+
+ // Fill it and push it back into the playing queue
+ if (!requestStop)
+ {
+ if (fillAndPushBuffer(bufferNum))
+ requestStop = true;
+ }
+ }
+
+ // Leave some time for the other threads if the stream is still playing
+ if (SoundSource::getStatus() != Stopped)
+ sleep(milliseconds(10));
+ }
+
+ // Stop the playback
+ alCheck(alSourceStop(m_source));
+
+ // Dequeue any buffer left in the queue
+ clearQueue();
+
+ // Delete the buffers
+ alCheck(alSourcei(m_source, AL_BUFFER, 0));
+ alCheck(alDeleteBuffers(BufferCount, m_buffers));
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundStream::fillAndPushBuffer(unsigned int bufferNum)
+{
+ bool requestStop = false;
+
+ // Acquire audio data
+ Chunk data = {NULL, 0};
+ if (!onGetData(data))
+ {
+ // Mark the buffer as the last one (so that we know when to reset the playing position)
+ m_endBuffers[bufferNum] = true;
+
+ // Check if the stream must loop or stop
+ if (m_loop)
+ {
+ // Return to the beginning of the stream source
+ onSeek(Time::Zero);
+
+ // If we previously had no data, try to fill the buffer once again
+ if (!data.samples || (data.sampleCount == 0))
+ {
+ return fillAndPushBuffer(bufferNum);
+ }
+ }
+ else
+ {
+ // Not looping: request stop
+ requestStop = true;
+ }
+ }
+
+ // Fill the buffer if some data was returned
+ if (data.samples && data.sampleCount)
+ {
+ unsigned int buffer = m_buffers[bufferNum];
+
+ // Fill the buffer
+ ALsizei size = static_cast<ALsizei>(data.sampleCount) * sizeof(Int16);
+ alCheck(alBufferData(buffer, m_format, data.samples, size, m_sampleRate));
+
+ // Push it into the sound queue
+ alCheck(alSourceQueueBuffers(m_source, 1, &buffer));
+ }
+
+ return requestStop;
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundStream::fillQueue()
+{
+ // Fill and enqueue all the available buffers
+ bool requestStop = false;
+ for (int i = 0; (i < BufferCount) && !requestStop; ++i)
+ {
+ if (fillAndPushBuffer(i))
+ requestStop = true;
+ }
+
+ return requestStop;
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundStream::clearQueue()
+{
+ // Get the number of buffers still in the queue
+ ALint nbQueued;
+ alCheck(alGetSourcei(m_source, AL_BUFFERS_QUEUED, &nbQueued));
+
+ // Dequeue them all
+ ALuint buffer;
+ for (ALint i = 0; i < nbQueued; ++i)
+ alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer));
+}
+
+} // namespace sf