mirror of
https://github.com/SFML/SFML.git
synced 2024-11-24 20:31:05 +08:00
Replaced OpenAL with miniaudio.
Co-authored-by: Chris Thrasher <chrisjthrasher@gmail.com> Co-authored-by: kimci86 <kimci86@hotmail.fr> Co-authored-by: vittorioromeo <mail@vittorioromeo.com>
This commit is contained in:
parent
b0e45cfaba
commit
34fde883b9
@ -112,7 +112,7 @@ IncludeCategories:
|
|||||||
- Priority: 8
|
- Priority: 8
|
||||||
Regex: '^<SFML\/System'
|
Regex: '^<SFML\/System'
|
||||||
- Priority: 9
|
- Priority: 9
|
||||||
Regex: '^<(glad|gl|X11|jni|android|stb_|GLES2|vorbis|catch2)'
|
Regex: '^<(glad|gl|X11|jni|android|stb_|GLES2|vorbis|miniaudio|catch2)'
|
||||||
- Priority: 10
|
- Priority: 10
|
||||||
Regex: '^<([^c](.+)|coroutine|charconv|chrono|complex|concepts|condition_variable)>$'
|
Regex: '^<([^c](.+)|coroutine|charconv|chrono|complex|concepts|condition_variable)>$'
|
||||||
- Priority: 11
|
- Priority: 11
|
||||||
|
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -105,7 +105,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
CLANG_VERSION=$(clang++ --version | sed -n 's/.*version \([0-9]\+\)\..*/\1/p')
|
CLANG_VERSION=$(clang++ --version | sed -n 's/.*version \([0-9]\+\)\..*/\1/p')
|
||||||
echo "CLANG_VERSION=$CLANG_VERSION" >> $GITHUB_ENV
|
echo "CLANG_VERSION=$CLANG_VERSION" >> $GITHUB_ENV
|
||||||
sudo apt-get update && sudo apt-get install xorg-dev libxrandr-dev libxcursor-dev libudev-dev libopenal-dev libflac-dev libvorbis-dev libgl1-mesa-dev libegl1-mesa-dev libdrm-dev libgbm-dev xvfb fluxbox ccache gcovr ${{ matrix.platform.name == 'Linux Clang' && 'llvm-$CLANG_VERSION' || '' }}
|
sudo apt-get update && sudo apt-get install xorg-dev libxrandr-dev libxcursor-dev libudev-dev libflac-dev libvorbis-dev libgl1-mesa-dev libegl1-mesa-dev libdrm-dev libgbm-dev xvfb fluxbox ccache gcovr ${{ matrix.platform.name == 'Linux Clang' && 'llvm-$CLANG_VERSION' || '' }}
|
||||||
|
|
||||||
- name: Install Android Components
|
- name: Install Android Components
|
||||||
if: matrix.platform.name == 'Android'
|
if: matrix.platform.name == 'Android'
|
||||||
@ -288,7 +288,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Install Linux Dependencies
|
- name: Install Linux Dependencies
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
run: sudo apt-get update && sudo apt-get install libxrandr-dev libxcursor-dev libudev-dev libopenal-dev libflac-dev libvorbis-dev libgl1-mesa-dev libegl1-mesa-dev libdrm-dev libgbm-dev
|
run: sudo apt-get update && sudo apt-get install libxrandr-dev libxcursor-dev libudev-dev libflac-dev libvorbis-dev libgl1-mesa-dev libegl1-mesa-dev libdrm-dev libgbm-dev
|
||||||
|
|
||||||
- name: Install macOS Dependencies
|
- name: Install macOS Dependencies
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
@ -327,7 +327,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Install Linux Dependencies
|
- name: Install Linux Dependencies
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
run: sudo apt-get update && sudo apt-get install xorg-dev libxrandr-dev libxcursor-dev libudev-dev libopenal-dev libflac-dev libvorbis-dev libgl1-mesa-dev libegl1-mesa-dev libdrm-dev libgbm-dev xvfb fluxbox
|
run: sudo apt-get update && sudo apt-get install xorg-dev libxrandr-dev libxcursor-dev libudev-dev libflac-dev libvorbis-dev libgl1-mesa-dev libegl1-mesa-dev libdrm-dev libgbm-dev xvfb fluxbox
|
||||||
|
|
||||||
- name: Configure
|
- name: Configure
|
||||||
run: cmake --preset dev -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=clang++ -DSFML_BUILD_EXAMPLES=OFF -DSFML_ENABLE_SANITIZERS=ON ${{matrix.platform.flags}}
|
run: cmake --preset dev -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=clang++ -DSFML_BUILD_EXAMPLES=OFF -DSFML_ENABLE_SANITIZERS=ON ${{matrix.platform.flags}}
|
||||||
|
@ -378,14 +378,12 @@ if(SFML_OS_WINDOWS)
|
|||||||
if(NOT SFML_USE_SYSTEM_DEPS)
|
if(NOT SFML_USE_SYSTEM_DEPS)
|
||||||
# install the binaries of SFML dependencies
|
# install the binaries of SFML dependencies
|
||||||
if(ARCH_32BITS)
|
if(ARCH_32BITS)
|
||||||
install(DIRECTORY extlibs/bin/x86/ DESTINATION ${CMAKE_INSTALL_BINDIR})
|
|
||||||
if(SFML_COMPILER_MSVC OR (SFML_COMPILER_CLANG AND NOT MINGW))
|
if(SFML_COMPILER_MSVC OR (SFML_COMPILER_CLANG AND NOT MINGW))
|
||||||
install(DIRECTORY extlibs/libs-msvc-universal/x86/ DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
install(DIRECTORY extlibs/libs-msvc-universal/x86/ DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
else()
|
else()
|
||||||
install(DIRECTORY extlibs/libs-mingw/x86/ DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
install(DIRECTORY extlibs/libs-mingw/x86/ DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
endif()
|
endif()
|
||||||
elseif(ARCH_64BITS)
|
elseif(ARCH_64BITS)
|
||||||
install(DIRECTORY extlibs/bin/x64/ DESTINATION ${CMAKE_INSTALL_BINDIR})
|
|
||||||
if(SFML_COMPILER_MSVC OR (SFML_COMPILER_CLANG AND NOT MINGW))
|
if(SFML_COMPILER_MSVC OR (SFML_COMPILER_CLANG AND NOT MINGW))
|
||||||
install(DIRECTORY extlibs/libs-msvc-universal/x64/ DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
install(DIRECTORY extlibs/libs-msvc-universal/x64/ DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
else()
|
else()
|
||||||
@ -422,10 +420,6 @@ elseif(SFML_OS_MACOS)
|
|||||||
if(VORBISFILE_LIBRARY STREQUAL "${PROJECT_SOURCE_DIR}/extlibs/libs-macos/Frameworks/vorbisfile.framework")
|
if(VORBISFILE_LIBRARY STREQUAL "${PROJECT_SOURCE_DIR}/extlibs/libs-macos/Frameworks/vorbisfile.framework")
|
||||||
install(DIRECTORY extlibs/libs-macos/Frameworks/vorbisfile.framework DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
install(DIRECTORY extlibs/libs-macos/Frameworks/vorbisfile.framework DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(OPENAL_LIBRARY STREQUAL "${PROJECT_SOURCE_DIR}/extlibs/libs-macos/Frameworks/OpenAL.framework")
|
|
||||||
install(DIRECTORY "${OPENAL_LIBRARY}" DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# install the Xcode templates if requested
|
# install the Xcode templates if requested
|
||||||
|
@ -1,120 +0,0 @@
|
|||||||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
||||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
|
||||||
|
|
||||||
#[=======================================================================[.rst:
|
|
||||||
FindOpenAL
|
|
||||||
----------
|
|
||||||
|
|
||||||
Finds Open Audio Library (OpenAL).
|
|
||||||
|
|
||||||
Projects using this module should use ``#include "al.h"`` to include the OpenAL
|
|
||||||
header file, **not** ``#include <AL/al.h>``. The reason for this is that the
|
|
||||||
latter is not entirely portable. Windows/Creative Labs does not by default put
|
|
||||||
their headers in ``AL/`` and macOS uses the convention ``<OpenAL/al.h>``.
|
|
||||||
|
|
||||||
Hints
|
|
||||||
^^^^^
|
|
||||||
|
|
||||||
Environment variable ``$OPENALDIR`` can be used to set the prefix of OpenAL
|
|
||||||
installation to be found.
|
|
||||||
|
|
||||||
By default on macOS, system framework is search first. In other words,
|
|
||||||
OpenAL is searched in the following order:
|
|
||||||
|
|
||||||
1. System framework: ``/System/Library/Frameworks``, whose priority can be
|
|
||||||
changed via setting the :variable:`CMAKE_FIND_FRAMEWORK` variable.
|
|
||||||
2. Environment variable ``$OPENALDIR``.
|
|
||||||
3. System paths.
|
|
||||||
4. User-compiled framework: ``~/Library/Frameworks``.
|
|
||||||
5. Manually compiled framework: ``/Library/Frameworks``.
|
|
||||||
6. Add-on package: ``/opt``.
|
|
||||||
|
|
||||||
IMPORTED Targets
|
|
||||||
^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
.. versionadded:: 3.25
|
|
||||||
|
|
||||||
This module defines the :prop_tgt:`IMPORTED` target:
|
|
||||||
|
|
||||||
``OpenAL::OpenAL``
|
|
||||||
The OpenAL library, if found.
|
|
||||||
|
|
||||||
Result Variables
|
|
||||||
^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
This module defines the following variables:
|
|
||||||
|
|
||||||
``OPENAL_FOUND``
|
|
||||||
If false, do not try to link to OpenAL
|
|
||||||
``OPENAL_INCLUDE_DIR``
|
|
||||||
OpenAL include directory
|
|
||||||
``OPENAL_LIBRARY``
|
|
||||||
Path to the OpenAL library
|
|
||||||
``OPENAL_VERSION_STRING``
|
|
||||||
Human-readable string containing the version of OpenAL
|
|
||||||
#]=======================================================================]
|
|
||||||
|
|
||||||
# For Windows, Creative Labs seems to have added a registry key for their
|
|
||||||
# OpenAL 1.1 installer. I have added that key to the list of search paths,
|
|
||||||
# however, the key looks like it could be a little fragile depending on
|
|
||||||
# if they decide to change the 1.00.0000 number for bug fix releases.
|
|
||||||
# Also, they seem to have laid down groundwork for multiple library platforms
|
|
||||||
# which puts the library in an extra subdirectory. Currently there is only
|
|
||||||
# Win32 and I have hardcoded that here. This may need to be adjusted as
|
|
||||||
# platforms are introduced.
|
|
||||||
# The OpenAL 1.0 installer doesn't seem to have a useful key I can use.
|
|
||||||
# I do not know if the Nvidia OpenAL SDK has a registry key.
|
|
||||||
|
|
||||||
find_path(OPENAL_INCLUDE_DIR al.h
|
|
||||||
HINTS
|
|
||||||
ENV OPENALDIR
|
|
||||||
PATHS
|
|
||||||
~/Library/Frameworks
|
|
||||||
/Library/Frameworks
|
|
||||||
/opt
|
|
||||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Creative\ Labs\\OpenAL\ 1.1\ Software\ Development\ Kit\\1.00.0000;InstallDir]
|
|
||||||
PATH_SUFFIXES include/AL include/OpenAL include AL OpenAL
|
|
||||||
)
|
|
||||||
|
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
||||||
set(_OpenAL_ARCH_DIR libs/Win64)
|
|
||||||
else()
|
|
||||||
set(_OpenAL_ARCH_DIR libs/Win32)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_library(OPENAL_LIBRARY
|
|
||||||
NAMES OpenAL al openal OpenAL32
|
|
||||||
HINTS
|
|
||||||
ENV OPENALDIR
|
|
||||||
PATHS
|
|
||||||
~/Library/Frameworks
|
|
||||||
/Library/Frameworks
|
|
||||||
/opt
|
|
||||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Creative\ Labs\\OpenAL\ 1.1\ Software\ Development\ Kit\\1.00.0000;InstallDir]
|
|
||||||
PATH_SUFFIXES libx32 lib64 lib libs64 libs ${_OpenAL_ARCH_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
unset(_OpenAL_ARCH_DIR)
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(
|
|
||||||
OpenAL
|
|
||||||
REQUIRED_VARS OPENAL_LIBRARY OPENAL_INCLUDE_DIR
|
|
||||||
VERSION_VAR OPENAL_VERSION_STRING
|
|
||||||
)
|
|
||||||
|
|
||||||
mark_as_advanced(OPENAL_LIBRARY OPENAL_INCLUDE_DIR)
|
|
||||||
|
|
||||||
if(NOT TARGET OpenAL::OpenAL)
|
|
||||||
if(OPENAL_LIBRARY MATCHES "/([^/]+)\\.framework$")
|
|
||||||
add_library(OpenAL::OpenAL INTERFACE IMPORTED)
|
|
||||||
set_target_properties(OpenAL::OpenAL PROPERTIES
|
|
||||||
INTERFACE_LINK_LIBRARIES "${OPENAL_LIBRARY}")
|
|
||||||
else()
|
|
||||||
add_library(OpenAL::OpenAL UNKNOWN IMPORTED)
|
|
||||||
set_target_properties(OpenAL::OpenAL PROPERTIES
|
|
||||||
IMPORTED_LOCATION "${OPENAL_LIBRARY}")
|
|
||||||
endif()
|
|
||||||
set_target_properties(OpenAL::OpenAL PROPERTIES
|
|
||||||
INTERFACE_INCLUDE_DIRECTORIES "${OPENAL_INCLUDE_DIR}")
|
|
||||||
endif()
|
|
@ -60,7 +60,6 @@ if(SFML_STATIC_LIBRARIES)
|
|||||||
# SFML::Audio
|
# SFML::Audio
|
||||||
list(FIND SFML_FIND_COMPONENTS "Audio" FIND_SFML_AUDIO_COMPONENT_INDEX)
|
list(FIND SFML_FIND_COMPONENTS "Audio" FIND_SFML_AUDIO_COMPONENT_INDEX)
|
||||||
if(FIND_SFML_AUDIO_COMPONENT_INDEX GREATER -1)
|
if(FIND_SFML_AUDIO_COMPONENT_INDEX GREATER -1)
|
||||||
find_package(OpenAL)
|
|
||||||
find_package(Vorbis)
|
find_package(Vorbis)
|
||||||
find_package(FLAC)
|
find_package(FLAC)
|
||||||
endif()
|
endif()
|
||||||
|
@ -23,6 +23,30 @@ int main()
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// List the available capture devices
|
||||||
|
auto devices = sf::SoundRecorder::getAvailableDevices();
|
||||||
|
|
||||||
|
std::cout << "Available capture devices:\n" << std::endl;
|
||||||
|
|
||||||
|
for (auto i = 0u; i < devices.size(); ++i)
|
||||||
|
std::cout << i << ": " << devices[i] << '\n';
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
std::size_t deviceIndex = 0;
|
||||||
|
|
||||||
|
// Choose the capture device
|
||||||
|
if (devices.size() > 1)
|
||||||
|
{
|
||||||
|
deviceIndex = devices.size();
|
||||||
|
std::cout << "Please choose the capture device to use [0-" << devices.size() - 1 << "]: ";
|
||||||
|
do
|
||||||
|
{
|
||||||
|
std::cin >> deviceIndex;
|
||||||
|
std::cin.ignore(10000, '\n');
|
||||||
|
} while (deviceIndex >= devices.size());
|
||||||
|
}
|
||||||
|
|
||||||
// Choose the sample rate
|
// Choose the sample rate
|
||||||
unsigned int sampleRate;
|
unsigned int sampleRate;
|
||||||
std::cout << "Please choose the sample rate for sound capture (44100 is CD quality): ";
|
std::cout << "Please choose the sample rate for sound capture (44100 is CD quality): ";
|
||||||
@ -36,6 +60,12 @@ int main()
|
|||||||
// Here we'll use an integrated custom recorder, which saves the captured data into a SoundBuffer
|
// Here we'll use an integrated custom recorder, which saves the captured data into a SoundBuffer
|
||||||
sf::SoundBufferRecorder recorder;
|
sf::SoundBufferRecorder recorder;
|
||||||
|
|
||||||
|
if (!recorder.setDevice(devices[deviceIndex]))
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to set the capture device" << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
// Audio capture is done in a separate thread, so we can block the main thread while it is capturing
|
// Audio capture is done in a separate thread, so we can block the main thread while it is capturing
|
||||||
if (!recorder.start(sampleRate))
|
if (!recorder.start(sampleRate))
|
||||||
{
|
{
|
||||||
|
@ -32,7 +32,7 @@ public:
|
|||||||
NetworkAudioStream()
|
NetworkAudioStream()
|
||||||
{
|
{
|
||||||
// Set the sound parameters
|
// Set the sound parameters
|
||||||
initialize(1, 44100);
|
initialize(1, 44100, {sf::SoundChannel::Mono});
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
BIN
extlibs/bin/x64/openal32.dll
vendored
BIN
extlibs/bin/x64/openal32.dll
vendored
Binary file not shown.
BIN
extlibs/bin/x86/openal32.dll
vendored
BIN
extlibs/bin/x86/openal32.dll
vendored
Binary file not shown.
656
extlibs/headers/AL/al.h
vendored
656
extlibs/headers/AL/al.h
vendored
@ -1,656 +0,0 @@
|
|||||||
#ifndef AL_AL_H
|
|
||||||
#define AL_AL_H
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_API
|
|
||||||
#if defined(AL_LIBTYPE_STATIC)
|
|
||||||
#define AL_API
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
#define AL_API __declspec(dllimport)
|
|
||||||
#else
|
|
||||||
#define AL_API extern
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#define AL_APIENTRY __cdecl
|
|
||||||
#else
|
|
||||||
#define AL_APIENTRY
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** Deprecated macro. */
|
|
||||||
#define OPENAL
|
|
||||||
#define ALAPI AL_API
|
|
||||||
#define ALAPIENTRY AL_APIENTRY
|
|
||||||
#define AL_INVALID (-1)
|
|
||||||
#define AL_ILLEGAL_ENUM AL_INVALID_ENUM
|
|
||||||
#define AL_ILLEGAL_COMMAND AL_INVALID_OPERATION
|
|
||||||
|
|
||||||
/** Supported AL version. */
|
|
||||||
#define AL_VERSION_1_0
|
|
||||||
#define AL_VERSION_1_1
|
|
||||||
|
|
||||||
/** 8-bit boolean */
|
|
||||||
typedef char ALboolean;
|
|
||||||
|
|
||||||
/** character */
|
|
||||||
typedef char ALchar;
|
|
||||||
|
|
||||||
/** signed 8-bit 2's complement integer */
|
|
||||||
typedef signed char ALbyte;
|
|
||||||
|
|
||||||
/** unsigned 8-bit integer */
|
|
||||||
typedef unsigned char ALubyte;
|
|
||||||
|
|
||||||
/** signed 16-bit 2's complement integer */
|
|
||||||
typedef short ALshort;
|
|
||||||
|
|
||||||
/** unsigned 16-bit integer */
|
|
||||||
typedef unsigned short ALushort;
|
|
||||||
|
|
||||||
/** signed 32-bit 2's complement integer */
|
|
||||||
typedef int ALint;
|
|
||||||
|
|
||||||
/** unsigned 32-bit integer */
|
|
||||||
typedef unsigned int ALuint;
|
|
||||||
|
|
||||||
/** non-negative 32-bit binary integer size */
|
|
||||||
typedef int ALsizei;
|
|
||||||
|
|
||||||
/** enumerated 32-bit value */
|
|
||||||
typedef int ALenum;
|
|
||||||
|
|
||||||
/** 32-bit IEEE754 floating-point */
|
|
||||||
typedef float ALfloat;
|
|
||||||
|
|
||||||
/** 64-bit IEEE754 floating-point */
|
|
||||||
typedef double ALdouble;
|
|
||||||
|
|
||||||
/** void type (for opaque pointers only) */
|
|
||||||
typedef void ALvoid;
|
|
||||||
|
|
||||||
|
|
||||||
/* Enumerant values begin at column 50. No tabs. */
|
|
||||||
|
|
||||||
/** "no distance model" or "no buffer" */
|
|
||||||
#define AL_NONE 0
|
|
||||||
|
|
||||||
/** Boolean False. */
|
|
||||||
#define AL_FALSE 0
|
|
||||||
|
|
||||||
/** Boolean True. */
|
|
||||||
#define AL_TRUE 1
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Relative source.
|
|
||||||
* Type: ALboolean
|
|
||||||
* Range: [AL_TRUE, AL_FALSE]
|
|
||||||
* Default: AL_FALSE
|
|
||||||
*
|
|
||||||
* Specifies if the Source has relative coordinates.
|
|
||||||
*/
|
|
||||||
#define AL_SOURCE_RELATIVE 0x202
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inner cone angle, in degrees.
|
|
||||||
* Type: ALint, ALfloat
|
|
||||||
* Range: [0 - 360]
|
|
||||||
* Default: 360
|
|
||||||
*
|
|
||||||
* The angle covered by the inner cone, where the source will not attenuate.
|
|
||||||
*/
|
|
||||||
#define AL_CONE_INNER_ANGLE 0x1001
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Outer cone angle, in degrees.
|
|
||||||
* Range: [0 - 360]
|
|
||||||
* Default: 360
|
|
||||||
*
|
|
||||||
* The angle covered by the outer cone, where the source will be fully
|
|
||||||
* attenuated.
|
|
||||||
*/
|
|
||||||
#define AL_CONE_OUTER_ANGLE 0x1002
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Source pitch.
|
|
||||||
* Type: ALfloat
|
|
||||||
* Range: [0.5 - 2.0]
|
|
||||||
* Default: 1.0
|
|
||||||
*
|
|
||||||
* A multiplier for the frequency (sample rate) of the source's buffer.
|
|
||||||
*/
|
|
||||||
#define AL_PITCH 0x1003
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Source or listener position.
|
|
||||||
* Type: ALfloat[3], ALint[3]
|
|
||||||
* Default: {0, 0, 0}
|
|
||||||
*
|
|
||||||
* The source or listener location in three dimensional space.
|
|
||||||
*
|
|
||||||
* OpenAL, like OpenGL, uses a right handed coordinate system, where in a
|
|
||||||
* frontal default view X (thumb) points right, Y points up (index finger), and
|
|
||||||
* Z points towards the viewer/camera (middle finger).
|
|
||||||
*
|
|
||||||
* To switch from a left handed coordinate system, flip the sign on the Z
|
|
||||||
* coordinate.
|
|
||||||
*/
|
|
||||||
#define AL_POSITION 0x1004
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Source direction.
|
|
||||||
* Type: ALfloat[3], ALint[3]
|
|
||||||
* Default: {0, 0, 0}
|
|
||||||
*
|
|
||||||
* Specifies the current direction in local space.
|
|
||||||
* A zero-length vector specifies an omni-directional source (cone is ignored).
|
|
||||||
*/
|
|
||||||
#define AL_DIRECTION 0x1005
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Source or listener velocity.
|
|
||||||
* Type: ALfloat[3], ALint[3]
|
|
||||||
* Default: {0, 0, 0}
|
|
||||||
*
|
|
||||||
* Specifies the current velocity in local space.
|
|
||||||
*/
|
|
||||||
#define AL_VELOCITY 0x1006
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Source looping.
|
|
||||||
* Type: ALboolean
|
|
||||||
* Range: [AL_TRUE, AL_FALSE]
|
|
||||||
* Default: AL_FALSE
|
|
||||||
*
|
|
||||||
* Specifies whether source is looping.
|
|
||||||
*/
|
|
||||||
#define AL_LOOPING 0x1007
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Source buffer.
|
|
||||||
* Type: ALuint
|
|
||||||
* Range: any valid Buffer.
|
|
||||||
*
|
|
||||||
* Specifies the buffer to provide sound samples.
|
|
||||||
*/
|
|
||||||
#define AL_BUFFER 0x1009
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Source or listener gain.
|
|
||||||
* Type: ALfloat
|
|
||||||
* Range: [0.0 - ]
|
|
||||||
*
|
|
||||||
* A value of 1.0 means unattenuated. Each division by 2 equals an attenuation
|
|
||||||
* of about -6dB. Each multiplicaton by 2 equals an amplification of about
|
|
||||||
* +6dB.
|
|
||||||
*
|
|
||||||
* A value of 0.0 is meaningless with respect to a logarithmic scale; it is
|
|
||||||
* silent.
|
|
||||||
*/
|
|
||||||
#define AL_GAIN 0x100A
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Minimum source gain.
|
|
||||||
* Type: ALfloat
|
|
||||||
* Range: [0.0 - 1.0]
|
|
||||||
*
|
|
||||||
* The minimum gain allowed for a source, after distance and cone attenation is
|
|
||||||
* applied (if applicable).
|
|
||||||
*/
|
|
||||||
#define AL_MIN_GAIN 0x100D
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum source gain.
|
|
||||||
* Type: ALfloat
|
|
||||||
* Range: [0.0 - 1.0]
|
|
||||||
*
|
|
||||||
* The maximum gain allowed for a source, after distance and cone attenation is
|
|
||||||
* applied (if applicable).
|
|
||||||
*/
|
|
||||||
#define AL_MAX_GAIN 0x100E
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listener orientation.
|
|
||||||
* Type: ALfloat[6]
|
|
||||||
* Default: {0.0, 0.0, -1.0, 0.0, 1.0, 0.0}
|
|
||||||
*
|
|
||||||
* Effectively two three dimensional vectors. The first vector is the front (or
|
|
||||||
* "at") and the second is the top (or "up").
|
|
||||||
*
|
|
||||||
* Both vectors are in local space.
|
|
||||||
*/
|
|
||||||
#define AL_ORIENTATION 0x100F
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Source state (query only).
|
|
||||||
* Type: ALint
|
|
||||||
* Range: [AL_INITIAL, AL_PLAYING, AL_PAUSED, AL_STOPPED]
|
|
||||||
*/
|
|
||||||
#define AL_SOURCE_STATE 0x1010
|
|
||||||
|
|
||||||
/** Source state value. */
|
|
||||||
#define AL_INITIAL 0x1011
|
|
||||||
#define AL_PLAYING 0x1012
|
|
||||||
#define AL_PAUSED 0x1013
|
|
||||||
#define AL_STOPPED 0x1014
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Source Buffer Queue size (query only).
|
|
||||||
* Type: ALint
|
|
||||||
*
|
|
||||||
* The number of buffers queued using alSourceQueueBuffers, minus the buffers
|
|
||||||
* removed with alSourceUnqueueBuffers.
|
|
||||||
*/
|
|
||||||
#define AL_BUFFERS_QUEUED 0x1015
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Source Buffer Queue processed count (query only).
|
|
||||||
* Type: ALint
|
|
||||||
*
|
|
||||||
* The number of queued buffers that have been fully processed, and can be
|
|
||||||
* removed with alSourceUnqueueBuffers.
|
|
||||||
*
|
|
||||||
* Looping sources will never fully process buffers because they will be set to
|
|
||||||
* play again for when the source loops.
|
|
||||||
*/
|
|
||||||
#define AL_BUFFERS_PROCESSED 0x1016
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Source reference distance.
|
|
||||||
* Type: ALfloat
|
|
||||||
* Range: [0.0 - ]
|
|
||||||
* Default: 1.0
|
|
||||||
*
|
|
||||||
* The distance in units that no attenuation occurs.
|
|
||||||
*
|
|
||||||
* At 0.0, no distance attenuation ever occurs on non-linear attenuation models.
|
|
||||||
*/
|
|
||||||
#define AL_REFERENCE_DISTANCE 0x1020
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Source rolloff factor.
|
|
||||||
* Type: ALfloat
|
|
||||||
* Range: [0.0 - ]
|
|
||||||
* Default: 1.0
|
|
||||||
*
|
|
||||||
* Multiplier to exaggerate or diminish distance attenuation.
|
|
||||||
*
|
|
||||||
* At 0.0, no distance attenuation ever occurs.
|
|
||||||
*/
|
|
||||||
#define AL_ROLLOFF_FACTOR 0x1021
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Outer cone gain.
|
|
||||||
* Type: ALfloat
|
|
||||||
* Range: [0.0 - 1.0]
|
|
||||||
* Default: 0.0
|
|
||||||
*
|
|
||||||
* The gain attenuation applied when the listener is outside of the source's
|
|
||||||
* outer cone.
|
|
||||||
*/
|
|
||||||
#define AL_CONE_OUTER_GAIN 0x1022
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Source maximum distance.
|
|
||||||
* Type: ALfloat
|
|
||||||
* Range: [0.0 - ]
|
|
||||||
* Default: +inf
|
|
||||||
*
|
|
||||||
* The distance above which the source is not attenuated any further with a
|
|
||||||
* clamped distance model, or where attenuation reaches 0.0 gain for linear
|
|
||||||
* distance models with a default rolloff factor.
|
|
||||||
*/
|
|
||||||
#define AL_MAX_DISTANCE 0x1023
|
|
||||||
|
|
||||||
/** Source buffer position, in seconds */
|
|
||||||
#define AL_SEC_OFFSET 0x1024
|
|
||||||
/** Source buffer position, in sample frames */
|
|
||||||
#define AL_SAMPLE_OFFSET 0x1025
|
|
||||||
/** Source buffer position, in bytes */
|
|
||||||
#define AL_BYTE_OFFSET 0x1026
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Source type (query only).
|
|
||||||
* Type: ALint
|
|
||||||
* Range: [AL_STATIC, AL_STREAMING, AL_UNDETERMINED]
|
|
||||||
*
|
|
||||||
* A Source is Static if a Buffer has been attached using AL_BUFFER.
|
|
||||||
*
|
|
||||||
* A Source is Streaming if one or more Buffers have been attached using
|
|
||||||
* alSourceQueueBuffers.
|
|
||||||
*
|
|
||||||
* A Source is Undetermined when it has the NULL buffer attached using
|
|
||||||
* AL_BUFFER.
|
|
||||||
*/
|
|
||||||
#define AL_SOURCE_TYPE 0x1027
|
|
||||||
|
|
||||||
/** Source type value. */
|
|
||||||
#define AL_STATIC 0x1028
|
|
||||||
#define AL_STREAMING 0x1029
|
|
||||||
#define AL_UNDETERMINED 0x1030
|
|
||||||
|
|
||||||
/** Buffer format specifier. */
|
|
||||||
#define AL_FORMAT_MONO8 0x1100
|
|
||||||
#define AL_FORMAT_MONO16 0x1101
|
|
||||||
#define AL_FORMAT_STEREO8 0x1102
|
|
||||||
#define AL_FORMAT_STEREO16 0x1103
|
|
||||||
|
|
||||||
/** Buffer frequency (query only). */
|
|
||||||
#define AL_FREQUENCY 0x2001
|
|
||||||
/** Buffer bits per sample (query only). */
|
|
||||||
#define AL_BITS 0x2002
|
|
||||||
/** Buffer channel count (query only). */
|
|
||||||
#define AL_CHANNELS 0x2003
|
|
||||||
/** Buffer data size (query only). */
|
|
||||||
#define AL_SIZE 0x2004
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Buffer state.
|
|
||||||
*
|
|
||||||
* Not for public use.
|
|
||||||
*/
|
|
||||||
#define AL_UNUSED 0x2010
|
|
||||||
#define AL_PENDING 0x2011
|
|
||||||
#define AL_PROCESSED 0x2012
|
|
||||||
|
|
||||||
|
|
||||||
/** No error. */
|
|
||||||
#define AL_NO_ERROR 0
|
|
||||||
|
|
||||||
/** Invalid name paramater passed to AL call. */
|
|
||||||
#define AL_INVALID_NAME 0xA001
|
|
||||||
|
|
||||||
/** Invalid enum parameter passed to AL call. */
|
|
||||||
#define AL_INVALID_ENUM 0xA002
|
|
||||||
|
|
||||||
/** Invalid value parameter passed to AL call. */
|
|
||||||
#define AL_INVALID_VALUE 0xA003
|
|
||||||
|
|
||||||
/** Illegal AL call. */
|
|
||||||
#define AL_INVALID_OPERATION 0xA004
|
|
||||||
|
|
||||||
/** Not enough memory. */
|
|
||||||
#define AL_OUT_OF_MEMORY 0xA005
|
|
||||||
|
|
||||||
|
|
||||||
/** Context string: Vendor ID. */
|
|
||||||
#define AL_VENDOR 0xB001
|
|
||||||
/** Context string: Version. */
|
|
||||||
#define AL_VERSION 0xB002
|
|
||||||
/** Context string: Renderer ID. */
|
|
||||||
#define AL_RENDERER 0xB003
|
|
||||||
/** Context string: Space-separated extension list. */
|
|
||||||
#define AL_EXTENSIONS 0xB004
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Doppler scale.
|
|
||||||
* Type: ALfloat
|
|
||||||
* Range: [0.0 - ]
|
|
||||||
* Default: 1.0
|
|
||||||
*
|
|
||||||
* Scale for source and listener velocities.
|
|
||||||
*/
|
|
||||||
#define AL_DOPPLER_FACTOR 0xC000
|
|
||||||
AL_API void AL_APIENTRY alDopplerFactor(ALfloat value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Doppler velocity (deprecated).
|
|
||||||
*
|
|
||||||
* A multiplier applied to the Speed of Sound.
|
|
||||||
*/
|
|
||||||
#define AL_DOPPLER_VELOCITY 0xC001
|
|
||||||
AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Speed of Sound, in units per second.
|
|
||||||
* Type: ALfloat
|
|
||||||
* Range: [0.0001 - ]
|
|
||||||
* Default: 343.3
|
|
||||||
*
|
|
||||||
* The speed at which sound waves are assumed to travel, when calculating the
|
|
||||||
* doppler effect.
|
|
||||||
*/
|
|
||||||
#define AL_SPEED_OF_SOUND 0xC003
|
|
||||||
AL_API void AL_APIENTRY alSpeedOfSound(ALfloat value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Distance attenuation model.
|
|
||||||
* Type: ALint
|
|
||||||
* Range: [AL_NONE, AL_INVERSE_DISTANCE, AL_INVERSE_DISTANCE_CLAMPED,
|
|
||||||
* AL_LINEAR_DISTANCE, AL_LINEAR_DISTANCE_CLAMPED,
|
|
||||||
* AL_EXPONENT_DISTANCE, AL_EXPONENT_DISTANCE_CLAMPED]
|
|
||||||
* Default: AL_INVERSE_DISTANCE_CLAMPED
|
|
||||||
*
|
|
||||||
* The model by which sources attenuate with distance.
|
|
||||||
*
|
|
||||||
* None - No distance attenuation.
|
|
||||||
* Inverse - Doubling the distance halves the source gain.
|
|
||||||
* Linear - Linear gain scaling between the reference and max distances.
|
|
||||||
* Exponent - Exponential gain dropoff.
|
|
||||||
*
|
|
||||||
* Clamped variations work like the non-clamped counterparts, except the
|
|
||||||
* distance calculated is clamped between the reference and max distances.
|
|
||||||
*/
|
|
||||||
#define AL_DISTANCE_MODEL 0xD000
|
|
||||||
AL_API void AL_APIENTRY alDistanceModel(ALenum distanceModel);
|
|
||||||
|
|
||||||
/** Distance model value. */
|
|
||||||
#define AL_INVERSE_DISTANCE 0xD001
|
|
||||||
#define AL_INVERSE_DISTANCE_CLAMPED 0xD002
|
|
||||||
#define AL_LINEAR_DISTANCE 0xD003
|
|
||||||
#define AL_LINEAR_DISTANCE_CLAMPED 0xD004
|
|
||||||
#define AL_EXPONENT_DISTANCE 0xD005
|
|
||||||
#define AL_EXPONENT_DISTANCE_CLAMPED 0xD006
|
|
||||||
|
|
||||||
/** Renderer State management. */
|
|
||||||
AL_API void AL_APIENTRY alEnable(ALenum capability);
|
|
||||||
AL_API void AL_APIENTRY alDisable(ALenum capability);
|
|
||||||
AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability);
|
|
||||||
|
|
||||||
/** State retrieval. */
|
|
||||||
AL_API const ALchar* AL_APIENTRY alGetString(ALenum param);
|
|
||||||
AL_API void AL_APIENTRY alGetBooleanv(ALenum param, ALboolean *values);
|
|
||||||
AL_API void AL_APIENTRY alGetIntegerv(ALenum param, ALint *values);
|
|
||||||
AL_API void AL_APIENTRY alGetFloatv(ALenum param, ALfloat *values);
|
|
||||||
AL_API void AL_APIENTRY alGetDoublev(ALenum param, ALdouble *values);
|
|
||||||
AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum param);
|
|
||||||
AL_API ALint AL_APIENTRY alGetInteger(ALenum param);
|
|
||||||
AL_API ALfloat AL_APIENTRY alGetFloat(ALenum param);
|
|
||||||
AL_API ALdouble AL_APIENTRY alGetDouble(ALenum param);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Error retrieval.
|
|
||||||
*
|
|
||||||
* Obtain the first error generated in the AL context since the last check.
|
|
||||||
*/
|
|
||||||
AL_API ALenum AL_APIENTRY alGetError(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension support.
|
|
||||||
*
|
|
||||||
* Query for the presence of an extension, and obtain any appropriate function
|
|
||||||
* pointers and enum values.
|
|
||||||
*/
|
|
||||||
AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extname);
|
|
||||||
AL_API void* AL_APIENTRY alGetProcAddress(const ALchar *fname);
|
|
||||||
AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *ename);
|
|
||||||
|
|
||||||
|
|
||||||
/** Set Listener parameters */
|
|
||||||
AL_API void AL_APIENTRY alListenerf(ALenum param, ALfloat value);
|
|
||||||
AL_API void AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3);
|
|
||||||
AL_API void AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values);
|
|
||||||
AL_API void AL_APIENTRY alListeneri(ALenum param, ALint value);
|
|
||||||
AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3);
|
|
||||||
AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values);
|
|
||||||
|
|
||||||
/** Get Listener parameters */
|
|
||||||
AL_API void AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value);
|
|
||||||
AL_API void AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3);
|
|
||||||
AL_API void AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values);
|
|
||||||
AL_API void AL_APIENTRY alGetListeneri(ALenum param, ALint *value);
|
|
||||||
AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3);
|
|
||||||
AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint *values);
|
|
||||||
|
|
||||||
|
|
||||||
/** Create Source objects. */
|
|
||||||
AL_API void AL_APIENTRY alGenSources(ALsizei n, ALuint *sources);
|
|
||||||
/** Delete Source objects. */
|
|
||||||
AL_API void AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources);
|
|
||||||
/** Verify a handle is a valid Source. */
|
|
||||||
AL_API ALboolean AL_APIENTRY alIsSource(ALuint source);
|
|
||||||
|
|
||||||
/** Set Source parameters. */
|
|
||||||
AL_API void AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value);
|
|
||||||
AL_API void AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3);
|
|
||||||
AL_API void AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values);
|
|
||||||
AL_API void AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value);
|
|
||||||
AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3);
|
|
||||||
AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values);
|
|
||||||
|
|
||||||
/** Get Source parameters. */
|
|
||||||
AL_API void AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value);
|
|
||||||
AL_API void AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3);
|
|
||||||
AL_API void AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values);
|
|
||||||
AL_API void AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value);
|
|
||||||
AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3);
|
|
||||||
AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values);
|
|
||||||
|
|
||||||
|
|
||||||
/** Play, replay, or resume (if paused) a list of Sources */
|
|
||||||
AL_API void AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources);
|
|
||||||
/** Stop a list of Sources */
|
|
||||||
AL_API void AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources);
|
|
||||||
/** Rewind a list of Sources */
|
|
||||||
AL_API void AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources);
|
|
||||||
/** Pause a list of Sources */
|
|
||||||
AL_API void AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources);
|
|
||||||
|
|
||||||
/** Play, replay, or resume a Source */
|
|
||||||
AL_API void AL_APIENTRY alSourcePlay(ALuint source);
|
|
||||||
/** Stop a Source */
|
|
||||||
AL_API void AL_APIENTRY alSourceStop(ALuint source);
|
|
||||||
/** Rewind a Source (set playback postiton to beginning) */
|
|
||||||
AL_API void AL_APIENTRY alSourceRewind(ALuint source);
|
|
||||||
/** Pause a Source */
|
|
||||||
AL_API void AL_APIENTRY alSourcePause(ALuint source);
|
|
||||||
|
|
||||||
/** Queue buffers onto a source */
|
|
||||||
AL_API void AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers);
|
|
||||||
/** Unqueue processed buffers from a source */
|
|
||||||
AL_API void AL_APIENTRY alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers);
|
|
||||||
|
|
||||||
|
|
||||||
/** Create Buffer objects */
|
|
||||||
AL_API void AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers);
|
|
||||||
/** Delete Buffer objects */
|
|
||||||
AL_API void AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers);
|
|
||||||
/** Verify a handle is a valid Buffer */
|
|
||||||
AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer);
|
|
||||||
|
|
||||||
/** Specifies the data to be copied into a buffer */
|
|
||||||
AL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq);
|
|
||||||
|
|
||||||
/** Set Buffer parameters, */
|
|
||||||
AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat value);
|
|
||||||
AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3);
|
|
||||||
AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values);
|
|
||||||
AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value);
|
|
||||||
AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3);
|
|
||||||
AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values);
|
|
||||||
|
|
||||||
/** Get Buffer parameters. */
|
|
||||||
AL_API void AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value);
|
|
||||||
AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3);
|
|
||||||
AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values);
|
|
||||||
AL_API void AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value);
|
|
||||||
AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3);
|
|
||||||
AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values);
|
|
||||||
|
|
||||||
/** Pointer-to-function type, useful for dynamically getting AL entry points. */
|
|
||||||
typedef void (AL_APIENTRY *LPALENABLE)(ALenum capability);
|
|
||||||
typedef void (AL_APIENTRY *LPALDISABLE)(ALenum capability);
|
|
||||||
typedef ALboolean (AL_APIENTRY *LPALISENABLED)(ALenum capability);
|
|
||||||
typedef const ALchar* (AL_APIENTRY *LPALGETSTRING)(ALenum param);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETBOOLEANV)(ALenum param, ALboolean *values);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETINTEGERV)(ALenum param, ALint *values);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETFLOATV)(ALenum param, ALfloat *values);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETDOUBLEV)(ALenum param, ALdouble *values);
|
|
||||||
typedef ALboolean (AL_APIENTRY *LPALGETBOOLEAN)(ALenum param);
|
|
||||||
typedef ALint (AL_APIENTRY *LPALGETINTEGER)(ALenum param);
|
|
||||||
typedef ALfloat (AL_APIENTRY *LPALGETFLOAT)(ALenum param);
|
|
||||||
typedef ALdouble (AL_APIENTRY *LPALGETDOUBLE)(ALenum param);
|
|
||||||
typedef ALenum (AL_APIENTRY *LPALGETERROR)(void);
|
|
||||||
typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENT)(const ALchar *extname);
|
|
||||||
typedef void* (AL_APIENTRY *LPALGETPROCADDRESS)(const ALchar *fname);
|
|
||||||
typedef ALenum (AL_APIENTRY *LPALGETENUMVALUE)(const ALchar *ename);
|
|
||||||
typedef void (AL_APIENTRY *LPALLISTENERF)(ALenum param, ALfloat value);
|
|
||||||
typedef void (AL_APIENTRY *LPALLISTENER3F)(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3);
|
|
||||||
typedef void (AL_APIENTRY *LPALLISTENERFV)(ALenum param, const ALfloat *values);
|
|
||||||
typedef void (AL_APIENTRY *LPALLISTENERI)(ALenum param, ALint value);
|
|
||||||
typedef void (AL_APIENTRY *LPALLISTENER3I)(ALenum param, ALint value1, ALint value2, ALint value3);
|
|
||||||
typedef void (AL_APIENTRY *LPALLISTENERIV)(ALenum param, const ALint *values);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETLISTENERF)(ALenum param, ALfloat *value);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETLISTENER3F)(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETLISTENERFV)(ALenum param, ALfloat *values);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETLISTENERI)(ALenum param, ALint *value);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETLISTENER3I)(ALenum param, ALint *value1, ALint *value2, ALint *value3);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETLISTENERIV)(ALenum param, ALint *values);
|
|
||||||
typedef void (AL_APIENTRY *LPALGENSOURCES)(ALsizei n, ALuint *sources);
|
|
||||||
typedef void (AL_APIENTRY *LPALDELETESOURCES)(ALsizei n, const ALuint *sources);
|
|
||||||
typedef ALboolean (AL_APIENTRY *LPALISSOURCE)(ALuint source);
|
|
||||||
typedef void (AL_APIENTRY *LPALSOURCEF)(ALuint source, ALenum param, ALfloat value);
|
|
||||||
typedef void (AL_APIENTRY *LPALSOURCE3F)(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3);
|
|
||||||
typedef void (AL_APIENTRY *LPALSOURCEFV)(ALuint source, ALenum param, const ALfloat *values);
|
|
||||||
typedef void (AL_APIENTRY *LPALSOURCEI)(ALuint source, ALenum param, ALint value);
|
|
||||||
typedef void (AL_APIENTRY *LPALSOURCE3I)(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3);
|
|
||||||
typedef void (AL_APIENTRY *LPALSOURCEIV)(ALuint source, ALenum param, const ALint *values);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETSOURCEF)(ALuint source, ALenum param, ALfloat *value);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETSOURCE3F)(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETSOURCEFV)(ALuint source, ALenum param, ALfloat *values);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETSOURCEI)(ALuint source, ALenum param, ALint *value);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETSOURCE3I)(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETSOURCEIV)(ALuint source, ALenum param, ALint *values);
|
|
||||||
typedef void (AL_APIENTRY *LPALSOURCEPLAYV)(ALsizei n, const ALuint *sources);
|
|
||||||
typedef void (AL_APIENTRY *LPALSOURCESTOPV)(ALsizei n, const ALuint *sources);
|
|
||||||
typedef void (AL_APIENTRY *LPALSOURCEREWINDV)(ALsizei n, const ALuint *sources);
|
|
||||||
typedef void (AL_APIENTRY *LPALSOURCEPAUSEV)(ALsizei n, const ALuint *sources);
|
|
||||||
typedef void (AL_APIENTRY *LPALSOURCEPLAY)(ALuint source);
|
|
||||||
typedef void (AL_APIENTRY *LPALSOURCESTOP)(ALuint source);
|
|
||||||
typedef void (AL_APIENTRY *LPALSOURCEREWIND)(ALuint source);
|
|
||||||
typedef void (AL_APIENTRY *LPALSOURCEPAUSE)(ALuint source);
|
|
||||||
typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERS)(ALuint source, ALsizei nb, const ALuint *buffers);
|
|
||||||
typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERS)(ALuint source, ALsizei nb, ALuint *buffers);
|
|
||||||
typedef void (AL_APIENTRY *LPALGENBUFFERS)(ALsizei n, ALuint *buffers);
|
|
||||||
typedef void (AL_APIENTRY *LPALDELETEBUFFERS)(ALsizei n, const ALuint *buffers);
|
|
||||||
typedef ALboolean (AL_APIENTRY *LPALISBUFFER)(ALuint buffer);
|
|
||||||
typedef void (AL_APIENTRY *LPALBUFFERDATA)(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq);
|
|
||||||
typedef void (AL_APIENTRY *LPALBUFFERF)(ALuint buffer, ALenum param, ALfloat value);
|
|
||||||
typedef void (AL_APIENTRY *LPALBUFFER3F)(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3);
|
|
||||||
typedef void (AL_APIENTRY *LPALBUFFERFV)(ALuint buffer, ALenum param, const ALfloat *values);
|
|
||||||
typedef void (AL_APIENTRY *LPALBUFFERI)(ALuint buffer, ALenum param, ALint value);
|
|
||||||
typedef void (AL_APIENTRY *LPALBUFFER3I)(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3);
|
|
||||||
typedef void (AL_APIENTRY *LPALBUFFERIV)(ALuint buffer, ALenum param, const ALint *values);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETBUFFERF)(ALuint buffer, ALenum param, ALfloat *value);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETBUFFER3F)(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETBUFFERFV)(ALuint buffer, ALenum param, ALfloat *values);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETBUFFERI)(ALuint buffer, ALenum param, ALint *value);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETBUFFER3I)(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETBUFFERIV)(ALuint buffer, ALenum param, ALint *values);
|
|
||||||
typedef void (AL_APIENTRY *LPALDOPPLERFACTOR)(ALfloat value);
|
|
||||||
typedef void (AL_APIENTRY *LPALDOPPLERVELOCITY)(ALfloat value);
|
|
||||||
typedef void (AL_APIENTRY *LPALSPEEDOFSOUND)(ALfloat value);
|
|
||||||
typedef void (AL_APIENTRY *LPALDISTANCEMODEL)(ALenum distanceModel);
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* AL_AL_H */
|
|
237
extlibs/headers/AL/alc.h
vendored
237
extlibs/headers/AL/alc.h
vendored
@ -1,237 +0,0 @@
|
|||||||
#ifndef AL_ALC_H
|
|
||||||
#define AL_ALC_H
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ALC_API
|
|
||||||
#if defined(AL_LIBTYPE_STATIC)
|
|
||||||
#define ALC_API
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
#define ALC_API __declspec(dllimport)
|
|
||||||
#else
|
|
||||||
#define ALC_API extern
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#define ALC_APIENTRY __cdecl
|
|
||||||
#else
|
|
||||||
#define ALC_APIENTRY
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** Deprecated macro. */
|
|
||||||
#define ALCAPI ALC_API
|
|
||||||
#define ALCAPIENTRY ALC_APIENTRY
|
|
||||||
#define ALC_INVALID 0
|
|
||||||
|
|
||||||
/** Supported ALC version? */
|
|
||||||
#define ALC_VERSION_0_1 1
|
|
||||||
|
|
||||||
/** Opaque device handle */
|
|
||||||
typedef struct ALCdevice_struct ALCdevice;
|
|
||||||
/** Opaque context handle */
|
|
||||||
typedef struct ALCcontext_struct ALCcontext;
|
|
||||||
|
|
||||||
/** 8-bit boolean */
|
|
||||||
typedef char ALCboolean;
|
|
||||||
|
|
||||||
/** character */
|
|
||||||
typedef char ALCchar;
|
|
||||||
|
|
||||||
/** signed 8-bit 2's complement integer */
|
|
||||||
typedef signed char ALCbyte;
|
|
||||||
|
|
||||||
/** unsigned 8-bit integer */
|
|
||||||
typedef unsigned char ALCubyte;
|
|
||||||
|
|
||||||
/** signed 16-bit 2's complement integer */
|
|
||||||
typedef short ALCshort;
|
|
||||||
|
|
||||||
/** unsigned 16-bit integer */
|
|
||||||
typedef unsigned short ALCushort;
|
|
||||||
|
|
||||||
/** signed 32-bit 2's complement integer */
|
|
||||||
typedef int ALCint;
|
|
||||||
|
|
||||||
/** unsigned 32-bit integer */
|
|
||||||
typedef unsigned int ALCuint;
|
|
||||||
|
|
||||||
/** non-negative 32-bit binary integer size */
|
|
||||||
typedef int ALCsizei;
|
|
||||||
|
|
||||||
/** enumerated 32-bit value */
|
|
||||||
typedef int ALCenum;
|
|
||||||
|
|
||||||
/** 32-bit IEEE754 floating-point */
|
|
||||||
typedef float ALCfloat;
|
|
||||||
|
|
||||||
/** 64-bit IEEE754 floating-point */
|
|
||||||
typedef double ALCdouble;
|
|
||||||
|
|
||||||
/** void type (for opaque pointers only) */
|
|
||||||
typedef void ALCvoid;
|
|
||||||
|
|
||||||
|
|
||||||
/* Enumerant values begin at column 50. No tabs. */
|
|
||||||
|
|
||||||
/** Boolean False. */
|
|
||||||
#define ALC_FALSE 0
|
|
||||||
|
|
||||||
/** Boolean True. */
|
|
||||||
#define ALC_TRUE 1
|
|
||||||
|
|
||||||
/** Context attribute: <int> Hz. */
|
|
||||||
#define ALC_FREQUENCY 0x1007
|
|
||||||
|
|
||||||
/** Context attribute: <int> Hz. */
|
|
||||||
#define ALC_REFRESH 0x1008
|
|
||||||
|
|
||||||
/** Context attribute: AL_TRUE or AL_FALSE. */
|
|
||||||
#define ALC_SYNC 0x1009
|
|
||||||
|
|
||||||
/** Context attribute: <int> requested Mono (3D) Sources. */
|
|
||||||
#define ALC_MONO_SOURCES 0x1010
|
|
||||||
|
|
||||||
/** Context attribute: <int> requested Stereo Sources. */
|
|
||||||
#define ALC_STEREO_SOURCES 0x1011
|
|
||||||
|
|
||||||
/** No error. */
|
|
||||||
#define ALC_NO_ERROR 0
|
|
||||||
|
|
||||||
/** Invalid device handle. */
|
|
||||||
#define ALC_INVALID_DEVICE 0xA001
|
|
||||||
|
|
||||||
/** Invalid context handle. */
|
|
||||||
#define ALC_INVALID_CONTEXT 0xA002
|
|
||||||
|
|
||||||
/** Invalid enum parameter passed to an ALC call. */
|
|
||||||
#define ALC_INVALID_ENUM 0xA003
|
|
||||||
|
|
||||||
/** Invalid value parameter passed to an ALC call. */
|
|
||||||
#define ALC_INVALID_VALUE 0xA004
|
|
||||||
|
|
||||||
/** Out of memory. */
|
|
||||||
#define ALC_OUT_OF_MEMORY 0xA005
|
|
||||||
|
|
||||||
|
|
||||||
/** Runtime ALC version. */
|
|
||||||
#define ALC_MAJOR_VERSION 0x1000
|
|
||||||
#define ALC_MINOR_VERSION 0x1001
|
|
||||||
|
|
||||||
/** Context attribute list properties. */
|
|
||||||
#define ALC_ATTRIBUTES_SIZE 0x1002
|
|
||||||
#define ALC_ALL_ATTRIBUTES 0x1003
|
|
||||||
|
|
||||||
/** String for the default device specifier. */
|
|
||||||
#define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004
|
|
||||||
/**
|
|
||||||
* String for the given device's specifier.
|
|
||||||
*
|
|
||||||
* If device handle is NULL, it is instead a null-char separated list of
|
|
||||||
* strings of known device specifiers (list ends with an empty string).
|
|
||||||
*/
|
|
||||||
#define ALC_DEVICE_SPECIFIER 0x1005
|
|
||||||
/** String for space-separated list of ALC extensions. */
|
|
||||||
#define ALC_EXTENSIONS 0x1006
|
|
||||||
|
|
||||||
|
|
||||||
/** Capture extension */
|
|
||||||
#define ALC_EXT_CAPTURE 1
|
|
||||||
/**
|
|
||||||
* String for the given capture device's specifier.
|
|
||||||
*
|
|
||||||
* If device handle is NULL, it is instead a null-char separated list of
|
|
||||||
* strings of known capture device specifiers (list ends with an empty string).
|
|
||||||
*/
|
|
||||||
#define ALC_CAPTURE_DEVICE_SPECIFIER 0x310
|
|
||||||
/** String for the default capture device specifier. */
|
|
||||||
#define ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER 0x311
|
|
||||||
/** Number of sample frames available for capture. */
|
|
||||||
#define ALC_CAPTURE_SAMPLES 0x312
|
|
||||||
|
|
||||||
|
|
||||||
/** Enumerate All extension */
|
|
||||||
#define ALC_ENUMERATE_ALL_EXT 1
|
|
||||||
/** String for the default extended device specifier. */
|
|
||||||
#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
|
|
||||||
/**
|
|
||||||
* String for the given extended device's specifier.
|
|
||||||
*
|
|
||||||
* If device handle is NULL, it is instead a null-char separated list of
|
|
||||||
* strings of known extended device specifiers (list ends with an empty string).
|
|
||||||
*/
|
|
||||||
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
|
|
||||||
|
|
||||||
|
|
||||||
/** Context management. */
|
|
||||||
ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint* attrlist);
|
|
||||||
ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context);
|
|
||||||
ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context);
|
|
||||||
ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context);
|
|
||||||
ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context);
|
|
||||||
ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void);
|
|
||||||
ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *context);
|
|
||||||
|
|
||||||
/** Device management. */
|
|
||||||
ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *devicename);
|
|
||||||
ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Error support.
|
|
||||||
*
|
|
||||||
* Obtain the most recent Device error.
|
|
||||||
*/
|
|
||||||
ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension support.
|
|
||||||
*
|
|
||||||
* Query for the presence of an extension, and obtain any appropriate
|
|
||||||
* function pointers and enum values.
|
|
||||||
*/
|
|
||||||
ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname);
|
|
||||||
ALC_API void* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcname);
|
|
||||||
ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumname);
|
|
||||||
|
|
||||||
/** Query function. */
|
|
||||||
ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum param);
|
|
||||||
ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values);
|
|
||||||
|
|
||||||
/** Capture function. */
|
|
||||||
ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize);
|
|
||||||
ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device);
|
|
||||||
ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device);
|
|
||||||
ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device);
|
|
||||||
ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples);
|
|
||||||
|
|
||||||
/** Pointer-to-function type, useful for dynamically getting ALC entry points. */
|
|
||||||
typedef ALCcontext* (ALC_APIENTRY *LPALCCREATECONTEXT)(ALCdevice *device, const ALCint *attrlist);
|
|
||||||
typedef ALCboolean (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)(ALCcontext *context);
|
|
||||||
typedef void (ALC_APIENTRY *LPALCPROCESSCONTEXT)(ALCcontext *context);
|
|
||||||
typedef void (ALC_APIENTRY *LPALCSUSPENDCONTEXT)(ALCcontext *context);
|
|
||||||
typedef void (ALC_APIENTRY *LPALCDESTROYCONTEXT)(ALCcontext *context);
|
|
||||||
typedef ALCcontext* (ALC_APIENTRY *LPALCGETCURRENTCONTEXT)(void);
|
|
||||||
typedef ALCdevice* (ALC_APIENTRY *LPALCGETCONTEXTSDEVICE)(ALCcontext *context);
|
|
||||||
typedef ALCdevice* (ALC_APIENTRY *LPALCOPENDEVICE)(const ALCchar *devicename);
|
|
||||||
typedef ALCboolean (ALC_APIENTRY *LPALCCLOSEDEVICE)(ALCdevice *device);
|
|
||||||
typedef ALCenum (ALC_APIENTRY *LPALCGETERROR)(ALCdevice *device);
|
|
||||||
typedef ALCboolean (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)(ALCdevice *device, const ALCchar *extname);
|
|
||||||
typedef void* (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname);
|
|
||||||
typedef ALCenum (ALC_APIENTRY *LPALCGETENUMVALUE)(ALCdevice *device, const ALCchar *enumname);
|
|
||||||
typedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)(ALCdevice *device, ALCenum param);
|
|
||||||
typedef void (ALC_APIENTRY *LPALCGETINTEGERV)(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values);
|
|
||||||
typedef ALCdevice* (ALC_APIENTRY *LPALCCAPTUREOPENDEVICE)(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize);
|
|
||||||
typedef ALCboolean (ALC_APIENTRY *LPALCCAPTURECLOSEDEVICE)(ALCdevice *device);
|
|
||||||
typedef void (ALC_APIENTRY *LPALCCAPTURESTART)(ALCdevice *device);
|
|
||||||
typedef void (ALC_APIENTRY *LPALCCAPTURESTOP)(ALCdevice *device);
|
|
||||||
typedef void (ALC_APIENTRY *LPALCCAPTURESAMPLES)(ALCdevice *device, ALCvoid *buffer, ALCsizei samples);
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* AL_ALC_H */
|
|
355
extlibs/headers/AL/alext.h
vendored
355
extlibs/headers/AL/alext.h
vendored
@ -1,355 +0,0 @@
|
|||||||
/**
|
|
||||||
* OpenAL cross platform audio library
|
|
||||||
* Copyright (C) 2008 by authors.
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Library General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Library General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Library General Public
|
|
||||||
* License along with this library; if not, write to the
|
|
||||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
* Boston, MA 02111-1307, USA.
|
|
||||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef AL_ALEXT_H
|
|
||||||
#define AL_ALEXT_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
/* Define int64_t and uint64_t types */
|
|
||||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
|
||||||
#include <inttypes.h>
|
|
||||||
#elif defined(_WIN32) && defined(__GNUC__)
|
|
||||||
#include <stdint.h>
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
typedef __int64 int64_t;
|
|
||||||
typedef unsigned __int64 uint64_t;
|
|
||||||
#else
|
|
||||||
/* Fallback if nothing above works */
|
|
||||||
#include <inttypes.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "alc.h"
|
|
||||||
#include "al.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_LOKI_IMA_ADPCM_format
|
|
||||||
#define AL_LOKI_IMA_ADPCM_format 1
|
|
||||||
#define AL_FORMAT_IMA_ADPCM_MONO16_EXT 0x10000
|
|
||||||
#define AL_FORMAT_IMA_ADPCM_STEREO16_EXT 0x10001
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_LOKI_WAVE_format
|
|
||||||
#define AL_LOKI_WAVE_format 1
|
|
||||||
#define AL_FORMAT_WAVE_EXT 0x10002
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_EXT_vorbis
|
|
||||||
#define AL_EXT_vorbis 1
|
|
||||||
#define AL_FORMAT_VORBIS_EXT 0x10003
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_LOKI_quadriphonic
|
|
||||||
#define AL_LOKI_quadriphonic 1
|
|
||||||
#define AL_FORMAT_QUAD8_LOKI 0x10004
|
|
||||||
#define AL_FORMAT_QUAD16_LOKI 0x10005
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_EXT_float32
|
|
||||||
#define AL_EXT_float32 1
|
|
||||||
#define AL_FORMAT_MONO_FLOAT32 0x10010
|
|
||||||
#define AL_FORMAT_STEREO_FLOAT32 0x10011
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_EXT_double
|
|
||||||
#define AL_EXT_double 1
|
|
||||||
#define AL_FORMAT_MONO_DOUBLE_EXT 0x10012
|
|
||||||
#define AL_FORMAT_STEREO_DOUBLE_EXT 0x10013
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_EXT_MULAW
|
|
||||||
#define AL_EXT_MULAW 1
|
|
||||||
#define AL_FORMAT_MONO_MULAW_EXT 0x10014
|
|
||||||
#define AL_FORMAT_STEREO_MULAW_EXT 0x10015
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_EXT_ALAW
|
|
||||||
#define AL_EXT_ALAW 1
|
|
||||||
#define AL_FORMAT_MONO_ALAW_EXT 0x10016
|
|
||||||
#define AL_FORMAT_STEREO_ALAW_EXT 0x10017
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ALC_LOKI_audio_channel
|
|
||||||
#define ALC_LOKI_audio_channel 1
|
|
||||||
#define ALC_CHAN_MAIN_LOKI 0x500001
|
|
||||||
#define ALC_CHAN_PCM_LOKI 0x500002
|
|
||||||
#define ALC_CHAN_CD_LOKI 0x500003
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_EXT_MCFORMATS
|
|
||||||
#define AL_EXT_MCFORMATS 1
|
|
||||||
#define AL_FORMAT_QUAD8 0x1204
|
|
||||||
#define AL_FORMAT_QUAD16 0x1205
|
|
||||||
#define AL_FORMAT_QUAD32 0x1206
|
|
||||||
#define AL_FORMAT_REAR8 0x1207
|
|
||||||
#define AL_FORMAT_REAR16 0x1208
|
|
||||||
#define AL_FORMAT_REAR32 0x1209
|
|
||||||
#define AL_FORMAT_51CHN8 0x120A
|
|
||||||
#define AL_FORMAT_51CHN16 0x120B
|
|
||||||
#define AL_FORMAT_51CHN32 0x120C
|
|
||||||
#define AL_FORMAT_61CHN8 0x120D
|
|
||||||
#define AL_FORMAT_61CHN16 0x120E
|
|
||||||
#define AL_FORMAT_61CHN32 0x120F
|
|
||||||
#define AL_FORMAT_71CHN8 0x1210
|
|
||||||
#define AL_FORMAT_71CHN16 0x1211
|
|
||||||
#define AL_FORMAT_71CHN32 0x1212
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_EXT_MULAW_MCFORMATS
|
|
||||||
#define AL_EXT_MULAW_MCFORMATS 1
|
|
||||||
#define AL_FORMAT_MONO_MULAW 0x10014
|
|
||||||
#define AL_FORMAT_STEREO_MULAW 0x10015
|
|
||||||
#define AL_FORMAT_QUAD_MULAW 0x10021
|
|
||||||
#define AL_FORMAT_REAR_MULAW 0x10022
|
|
||||||
#define AL_FORMAT_51CHN_MULAW 0x10023
|
|
||||||
#define AL_FORMAT_61CHN_MULAW 0x10024
|
|
||||||
#define AL_FORMAT_71CHN_MULAW 0x10025
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_EXT_IMA4
|
|
||||||
#define AL_EXT_IMA4 1
|
|
||||||
#define AL_FORMAT_MONO_IMA4 0x1300
|
|
||||||
#define AL_FORMAT_STEREO_IMA4 0x1301
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_EXT_STATIC_BUFFER
|
|
||||||
#define AL_EXT_STATIC_BUFFER 1
|
|
||||||
typedef ALvoid (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALint,ALenum,ALvoid*,ALsizei,ALsizei);
|
|
||||||
#ifdef AL_ALEXT_PROTOTYPES
|
|
||||||
AL_API ALvoid AL_APIENTRY alBufferDataStatic(const ALint buffer, ALenum format, ALvoid *data, ALsizei len, ALsizei freq);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ALC_EXT_EFX
|
|
||||||
#define ALC_EXT_EFX 1
|
|
||||||
#include "efx.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ALC_EXT_disconnect
|
|
||||||
#define ALC_EXT_disconnect 1
|
|
||||||
#define ALC_CONNECTED 0x313
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ALC_EXT_thread_local_context
|
|
||||||
#define ALC_EXT_thread_local_context 1
|
|
||||||
typedef ALCboolean (ALC_APIENTRY*PFNALCSETTHREADCONTEXTPROC)(ALCcontext *context);
|
|
||||||
typedef ALCcontext* (ALC_APIENTRY*PFNALCGETTHREADCONTEXTPROC)(void);
|
|
||||||
#ifdef AL_ALEXT_PROTOTYPES
|
|
||||||
ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context);
|
|
||||||
ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_EXT_source_distance_model
|
|
||||||
#define AL_EXT_source_distance_model 1
|
|
||||||
#define AL_SOURCE_DISTANCE_MODEL 0x200
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_SOFT_buffer_sub_data
|
|
||||||
#define AL_SOFT_buffer_sub_data 1
|
|
||||||
#define AL_BYTE_RW_OFFSETS_SOFT 0x1031
|
|
||||||
#define AL_SAMPLE_RW_OFFSETS_SOFT 0x1032
|
|
||||||
typedef ALvoid (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei);
|
|
||||||
#ifdef AL_ALEXT_PROTOTYPES
|
|
||||||
AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_SOFT_loop_points
|
|
||||||
#define AL_SOFT_loop_points 1
|
|
||||||
#define AL_LOOP_POINTS_SOFT 0x2015
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_EXT_FOLDBACK
|
|
||||||
#define AL_EXT_FOLDBACK 1
|
|
||||||
#define AL_EXT_FOLDBACK_NAME "AL_EXT_FOLDBACK"
|
|
||||||
#define AL_FOLDBACK_EVENT_BLOCK 0x4112
|
|
||||||
#define AL_FOLDBACK_EVENT_START 0x4111
|
|
||||||
#define AL_FOLDBACK_EVENT_STOP 0x4113
|
|
||||||
#define AL_FOLDBACK_MODE_MONO 0x4101
|
|
||||||
#define AL_FOLDBACK_MODE_STEREO 0x4102
|
|
||||||
typedef void (AL_APIENTRY*LPALFOLDBACKCALLBACK)(ALenum,ALsizei);
|
|
||||||
typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTART)(ALenum,ALsizei,ALsizei,ALfloat*,LPALFOLDBACKCALLBACK);
|
|
||||||
typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTOP)(void);
|
|
||||||
#ifdef AL_ALEXT_PROTOTYPES
|
|
||||||
AL_API void AL_APIENTRY alRequestFoldbackStart(ALenum mode,ALsizei count,ALsizei length,ALfloat *mem,LPALFOLDBACKCALLBACK callback);
|
|
||||||
AL_API void AL_APIENTRY alRequestFoldbackStop(void);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ALC_EXT_DEDICATED
|
|
||||||
#define ALC_EXT_DEDICATED 1
|
|
||||||
#define AL_DEDICATED_GAIN 0x0001
|
|
||||||
#define AL_EFFECT_DEDICATED_DIALOGUE 0x9001
|
|
||||||
#define AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT 0x9000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_SOFT_buffer_samples
|
|
||||||
#define AL_SOFT_buffer_samples 1
|
|
||||||
/* Channel configurations */
|
|
||||||
#define AL_MONO_SOFT 0x1500
|
|
||||||
#define AL_STEREO_SOFT 0x1501
|
|
||||||
#define AL_REAR_SOFT 0x1502
|
|
||||||
#define AL_QUAD_SOFT 0x1503
|
|
||||||
#define AL_5POINT1_SOFT 0x1504
|
|
||||||
#define AL_6POINT1_SOFT 0x1505
|
|
||||||
#define AL_7POINT1_SOFT 0x1506
|
|
||||||
|
|
||||||
/* Sample types */
|
|
||||||
#define AL_BYTE_SOFT 0x1400
|
|
||||||
#define AL_UNSIGNED_BYTE_SOFT 0x1401
|
|
||||||
#define AL_SHORT_SOFT 0x1402
|
|
||||||
#define AL_UNSIGNED_SHORT_SOFT 0x1403
|
|
||||||
#define AL_INT_SOFT 0x1404
|
|
||||||
#define AL_UNSIGNED_INT_SOFT 0x1405
|
|
||||||
#define AL_FLOAT_SOFT 0x1406
|
|
||||||
#define AL_DOUBLE_SOFT 0x1407
|
|
||||||
#define AL_BYTE3_SOFT 0x1408
|
|
||||||
#define AL_UNSIGNED_BYTE3_SOFT 0x1409
|
|
||||||
|
|
||||||
/* Storage formats */
|
|
||||||
#define AL_MONO8_SOFT 0x1100
|
|
||||||
#define AL_MONO16_SOFT 0x1101
|
|
||||||
#define AL_MONO32F_SOFT 0x10010
|
|
||||||
#define AL_STEREO8_SOFT 0x1102
|
|
||||||
#define AL_STEREO16_SOFT 0x1103
|
|
||||||
#define AL_STEREO32F_SOFT 0x10011
|
|
||||||
#define AL_QUAD8_SOFT 0x1204
|
|
||||||
#define AL_QUAD16_SOFT 0x1205
|
|
||||||
#define AL_QUAD32F_SOFT 0x1206
|
|
||||||
#define AL_REAR8_SOFT 0x1207
|
|
||||||
#define AL_REAR16_SOFT 0x1208
|
|
||||||
#define AL_REAR32F_SOFT 0x1209
|
|
||||||
#define AL_5POINT1_8_SOFT 0x120A
|
|
||||||
#define AL_5POINT1_16_SOFT 0x120B
|
|
||||||
#define AL_5POINT1_32F_SOFT 0x120C
|
|
||||||
#define AL_6POINT1_8_SOFT 0x120D
|
|
||||||
#define AL_6POINT1_16_SOFT 0x120E
|
|
||||||
#define AL_6POINT1_32F_SOFT 0x120F
|
|
||||||
#define AL_7POINT1_8_SOFT 0x1210
|
|
||||||
#define AL_7POINT1_16_SOFT 0x1211
|
|
||||||
#define AL_7POINT1_32F_SOFT 0x1212
|
|
||||||
|
|
||||||
/* Buffer attributes */
|
|
||||||
#define AL_INTERNAL_FORMAT_SOFT 0x2008
|
|
||||||
#define AL_BYTE_LENGTH_SOFT 0x2009
|
|
||||||
#define AL_SAMPLE_LENGTH_SOFT 0x200A
|
|
||||||
#define AL_SEC_LENGTH_SOFT 0x200B
|
|
||||||
|
|
||||||
typedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*);
|
|
||||||
typedef void (AL_APIENTRY*LPALBUFFERSUBSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,const ALvoid*);
|
|
||||||
typedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*);
|
|
||||||
typedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum);
|
|
||||||
#ifdef AL_ALEXT_PROTOTYPES
|
|
||||||
AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, ALuint samplerate, ALenum internalformat, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data);
|
|
||||||
AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data);
|
|
||||||
AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, ALvoid *data);
|
|
||||||
AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_SOFT_direct_channels
|
|
||||||
#define AL_SOFT_direct_channels 1
|
|
||||||
#define AL_DIRECT_CHANNELS_SOFT 0x1033
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ALC_SOFT_loopback
|
|
||||||
#define ALC_SOFT_loopback 1
|
|
||||||
#define ALC_FORMAT_CHANNELS_SOFT 0x1990
|
|
||||||
#define ALC_FORMAT_TYPE_SOFT 0x1991
|
|
||||||
|
|
||||||
/* Sample types */
|
|
||||||
#define ALC_BYTE_SOFT 0x1400
|
|
||||||
#define ALC_UNSIGNED_BYTE_SOFT 0x1401
|
|
||||||
#define ALC_SHORT_SOFT 0x1402
|
|
||||||
#define ALC_UNSIGNED_SHORT_SOFT 0x1403
|
|
||||||
#define ALC_INT_SOFT 0x1404
|
|
||||||
#define ALC_UNSIGNED_INT_SOFT 0x1405
|
|
||||||
#define ALC_FLOAT_SOFT 0x1406
|
|
||||||
|
|
||||||
/* Channel configurations */
|
|
||||||
#define ALC_MONO_SOFT 0x1500
|
|
||||||
#define ALC_STEREO_SOFT 0x1501
|
|
||||||
#define ALC_QUAD_SOFT 0x1503
|
|
||||||
#define ALC_5POINT1_SOFT 0x1504
|
|
||||||
#define ALC_6POINT1_SOFT 0x1505
|
|
||||||
#define ALC_7POINT1_SOFT 0x1506
|
|
||||||
|
|
||||||
typedef ALCdevice* (ALC_APIENTRY*LPALCLOOPBACKOPENDEVICESOFT)(const ALCchar*);
|
|
||||||
typedef ALCboolean (ALC_APIENTRY*LPALCISRENDERFORMATSUPPORTEDSOFT)(ALCdevice*,ALCsizei,ALCenum,ALCenum);
|
|
||||||
typedef void (ALC_APIENTRY*LPALCRENDERSAMPLESSOFT)(ALCdevice*,ALCvoid*,ALCsizei);
|
|
||||||
#ifdef AL_ALEXT_PROTOTYPES
|
|
||||||
ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName);
|
|
||||||
ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type);
|
|
||||||
ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_EXT_STEREO_ANGLES
|
|
||||||
#define AL_EXT_STEREO_ANGLES 1
|
|
||||||
#define AL_STEREO_ANGLES 0x1030
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_EXT_SOURCE_RADIUS
|
|
||||||
#define AL_EXT_SOURCE_RADIUS 1
|
|
||||||
#define AL_SOURCE_RADIUS 0x1031
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_SOFT_source_latency
|
|
||||||
#define AL_SOFT_source_latency 1
|
|
||||||
#define AL_SAMPLE_OFFSET_LATENCY_SOFT 0x1200
|
|
||||||
#define AL_SEC_OFFSET_LATENCY_SOFT 0x1201
|
|
||||||
typedef int64_t ALint64SOFT;
|
|
||||||
typedef uint64_t ALuint64SOFT;
|
|
||||||
typedef void (AL_APIENTRY*LPALSOURCEDSOFT)(ALuint,ALenum,ALdouble);
|
|
||||||
typedef void (AL_APIENTRY*LPALSOURCE3DSOFT)(ALuint,ALenum,ALdouble,ALdouble,ALdouble);
|
|
||||||
typedef void (AL_APIENTRY*LPALSOURCEDVSOFT)(ALuint,ALenum,const ALdouble*);
|
|
||||||
typedef void (AL_APIENTRY*LPALGETSOURCEDSOFT)(ALuint,ALenum,ALdouble*);
|
|
||||||
typedef void (AL_APIENTRY*LPALGETSOURCE3DSOFT)(ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*);
|
|
||||||
typedef void (AL_APIENTRY*LPALGETSOURCEDVSOFT)(ALuint,ALenum,ALdouble*);
|
|
||||||
typedef void (AL_APIENTRY*LPALSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT);
|
|
||||||
typedef void (AL_APIENTRY*LPALSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT);
|
|
||||||
typedef void (AL_APIENTRY*LPALSOURCEI64VSOFT)(ALuint,ALenum,const ALint64SOFT*);
|
|
||||||
typedef void (AL_APIENTRY*LPALGETSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT*);
|
|
||||||
typedef void (AL_APIENTRY*LPALGETSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*);
|
|
||||||
typedef void (AL_APIENTRY*LPALGETSOURCEI64VSOFT)(ALuint,ALenum,ALint64SOFT*);
|
|
||||||
#ifdef AL_ALEXT_PROTOTYPES
|
|
||||||
AL_API void AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value);
|
|
||||||
AL_API void AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3);
|
|
||||||
AL_API void AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values);
|
|
||||||
AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value);
|
|
||||||
AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3);
|
|
||||||
AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values);
|
|
||||||
AL_API void AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value);
|
|
||||||
AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3);
|
|
||||||
AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values);
|
|
||||||
AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value);
|
|
||||||
AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3);
|
|
||||||
AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
3
extlibs/headers/AL/efx-creative.h
vendored
3
extlibs/headers/AL/efx-creative.h
vendored
@ -1,3 +0,0 @@
|
|||||||
/* The tokens that would be defined here are already defined in efx.h. This
|
|
||||||
* empty file is here to provide compatibility with Windows-based projects
|
|
||||||
* that would include it. */
|
|
402
extlibs/headers/AL/efx-presets.h
vendored
402
extlibs/headers/AL/efx-presets.h
vendored
@ -1,402 +0,0 @@
|
|||||||
/* Reverb presets for EFX */
|
|
||||||
|
|
||||||
#ifndef EFX_PRESETS_H
|
|
||||||
#define EFX_PRESETS_H
|
|
||||||
|
|
||||||
#ifndef EFXEAXREVERBPROPERTIES_DEFINED
|
|
||||||
#define EFXEAXREVERBPROPERTIES_DEFINED
|
|
||||||
typedef struct {
|
|
||||||
float flDensity;
|
|
||||||
float flDiffusion;
|
|
||||||
float flGain;
|
|
||||||
float flGainHF;
|
|
||||||
float flGainLF;
|
|
||||||
float flDecayTime;
|
|
||||||
float flDecayHFRatio;
|
|
||||||
float flDecayLFRatio;
|
|
||||||
float flReflectionsGain;
|
|
||||||
float flReflectionsDelay;
|
|
||||||
float flReflectionsPan[3];
|
|
||||||
float flLateReverbGain;
|
|
||||||
float flLateReverbDelay;
|
|
||||||
float flLateReverbPan[3];
|
|
||||||
float flEchoTime;
|
|
||||||
float flEchoDepth;
|
|
||||||
float flModulationTime;
|
|
||||||
float flModulationDepth;
|
|
||||||
float flAirAbsorptionGainHF;
|
|
||||||
float flHFReference;
|
|
||||||
float flLFReference;
|
|
||||||
float flRoomRolloffFactor;
|
|
||||||
int iDecayHFLimit;
|
|
||||||
} EFXEAXREVERBPROPERTIES, *LPEFXEAXREVERBPROPERTIES;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Default Presets */
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_GENERIC \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.8913f, 1.0000f, 1.4900f, 0.8300f, 1.0000f, 0.0500f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_PADDEDCELL \
|
|
||||||
{ 0.1715f, 1.0000f, 0.3162f, 0.0010f, 1.0000f, 0.1700f, 0.1000f, 1.0000f, 0.2500f, 0.0010f, { 0.0000f, 0.0000f, 0.0000f }, 1.2691f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_ROOM \
|
|
||||||
{ 0.4287f, 1.0000f, 0.3162f, 0.5929f, 1.0000f, 0.4000f, 0.8300f, 1.0000f, 0.1503f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 1.0629f, 0.0030f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_BATHROOM \
|
|
||||||
{ 0.1715f, 1.0000f, 0.3162f, 0.2512f, 1.0000f, 1.4900f, 0.5400f, 1.0000f, 0.6531f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 3.2734f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_LIVINGROOM \
|
|
||||||
{ 0.9766f, 1.0000f, 0.3162f, 0.0010f, 1.0000f, 0.5000f, 0.1000f, 1.0000f, 0.2051f, 0.0030f, { 0.0000f, 0.0000f, 0.0000f }, 0.2805f, 0.0040f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_STONEROOM \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.7079f, 1.0000f, 2.3100f, 0.6400f, 1.0000f, 0.4411f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1003f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_AUDITORIUM \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.5781f, 1.0000f, 4.3200f, 0.5900f, 1.0000f, 0.4032f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.7170f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CONCERTHALL \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.5623f, 1.0000f, 3.9200f, 0.7000f, 1.0000f, 0.2427f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.9977f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CAVE \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 1.0000f, 1.0000f, 2.9100f, 1.3000f, 1.0000f, 0.5000f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.7063f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_ARENA \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.4477f, 1.0000f, 7.2400f, 0.3300f, 1.0000f, 0.2612f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.0186f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_HANGAR \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.3162f, 1.0000f, 10.0500f, 0.2300f, 1.0000f, 0.5000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.2560f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CARPETEDHALLWAY \
|
|
||||||
{ 0.4287f, 1.0000f, 0.3162f, 0.0100f, 1.0000f, 0.3000f, 0.1000f, 1.0000f, 0.1215f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 0.1531f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_HALLWAY \
|
|
||||||
{ 0.3645f, 1.0000f, 0.3162f, 0.7079f, 1.0000f, 1.4900f, 0.5900f, 1.0000f, 0.2458f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.6615f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_STONECORRIDOR \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.7612f, 1.0000f, 2.7000f, 0.7900f, 1.0000f, 0.2472f, 0.0130f, { 0.0000f, 0.0000f, 0.0000f }, 1.5758f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_ALLEY \
|
|
||||||
{ 1.0000f, 0.3000f, 0.3162f, 0.7328f, 1.0000f, 1.4900f, 0.8600f, 1.0000f, 0.2500f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.9954f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.9500f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_FOREST \
|
|
||||||
{ 1.0000f, 0.3000f, 0.3162f, 0.0224f, 1.0000f, 1.4900f, 0.5400f, 1.0000f, 0.0525f, 0.1620f, { 0.0000f, 0.0000f, 0.0000f }, 0.7682f, 0.0880f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CITY \
|
|
||||||
{ 1.0000f, 0.5000f, 0.3162f, 0.3981f, 1.0000f, 1.4900f, 0.6700f, 1.0000f, 0.0730f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.1427f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_MOUNTAINS \
|
|
||||||
{ 1.0000f, 0.2700f, 0.3162f, 0.0562f, 1.0000f, 1.4900f, 0.2100f, 1.0000f, 0.0407f, 0.3000f, { 0.0000f, 0.0000f, 0.0000f }, 0.1919f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_QUARRY \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.3162f, 1.0000f, 1.4900f, 0.8300f, 1.0000f, 0.0000f, 0.0610f, { 0.0000f, 0.0000f, 0.0000f }, 1.7783f, 0.0250f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.7000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_PLAIN \
|
|
||||||
{ 1.0000f, 0.2100f, 0.3162f, 0.1000f, 1.0000f, 1.4900f, 0.5000f, 1.0000f, 0.0585f, 0.1790f, { 0.0000f, 0.0000f, 0.0000f }, 0.1089f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_PARKINGLOT \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 1.0000f, 1.0000f, 1.6500f, 1.5000f, 1.0000f, 0.2082f, 0.0080f, { 0.0000f, 0.0000f, 0.0000f }, 0.2652f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_SEWERPIPE \
|
|
||||||
{ 0.3071f, 0.8000f, 0.3162f, 0.3162f, 1.0000f, 2.8100f, 0.1400f, 1.0000f, 1.6387f, 0.0140f, { 0.0000f, 0.0000f, 0.0000f }, 3.2471f, 0.0210f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_UNDERWATER \
|
|
||||||
{ 0.3645f, 1.0000f, 0.3162f, 0.0100f, 1.0000f, 1.4900f, 0.1000f, 1.0000f, 0.5963f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 7.0795f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 1.1800f, 0.3480f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_DRUGGED \
|
|
||||||
{ 0.4287f, 0.5000f, 0.3162f, 1.0000f, 1.0000f, 8.3900f, 1.3900f, 1.0000f, 0.8760f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 3.1081f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_DIZZY \
|
|
||||||
{ 0.3645f, 0.6000f, 0.3162f, 0.6310f, 1.0000f, 17.2300f, 0.5600f, 1.0000f, 0.1392f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.4937f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.8100f, 0.3100f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_PSYCHOTIC \
|
|
||||||
{ 0.0625f, 0.5000f, 0.3162f, 0.8404f, 1.0000f, 7.5600f, 0.9100f, 1.0000f, 0.4864f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 2.4378f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 4.0000f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
/* Castle Presets */
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CASTLE_SMALLROOM \
|
|
||||||
{ 1.0000f, 0.8900f, 0.3162f, 0.3981f, 0.1000f, 1.2200f, 0.8300f, 0.3100f, 0.8913f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CASTLE_SHORTPASSAGE \
|
|
||||||
{ 1.0000f, 0.8900f, 0.3162f, 0.3162f, 0.1000f, 2.3200f, 0.8300f, 0.3100f, 0.8913f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CASTLE_MEDIUMROOM \
|
|
||||||
{ 1.0000f, 0.9300f, 0.3162f, 0.2818f, 0.1000f, 2.0400f, 0.8300f, 0.4600f, 0.6310f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 1.5849f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1550f, 0.0300f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CASTLE_LARGEROOM \
|
|
||||||
{ 1.0000f, 0.8200f, 0.3162f, 0.2818f, 0.1259f, 2.5300f, 0.8300f, 0.5000f, 0.4467f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.1850f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CASTLE_LONGPASSAGE \
|
|
||||||
{ 1.0000f, 0.8900f, 0.3162f, 0.3981f, 0.1000f, 3.4200f, 0.8300f, 0.3100f, 0.8913f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CASTLE_HALL \
|
|
||||||
{ 1.0000f, 0.8100f, 0.3162f, 0.2818f, 0.1778f, 3.1400f, 0.7900f, 0.6200f, 0.1778f, 0.0560f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CASTLE_CUPBOARD \
|
|
||||||
{ 1.0000f, 0.8900f, 0.3162f, 0.2818f, 0.1000f, 0.6700f, 0.8700f, 0.3100f, 1.4125f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 3.5481f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CASTLE_COURTYARD \
|
|
||||||
{ 1.0000f, 0.4200f, 0.3162f, 0.4467f, 0.1995f, 2.1300f, 0.6100f, 0.2300f, 0.2239f, 0.1600f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0360f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.3700f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CASTLE_ALCOVE \
|
|
||||||
{ 1.0000f, 0.8900f, 0.3162f, 0.5012f, 0.1000f, 1.6400f, 0.8700f, 0.3100f, 1.0000f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
/* Factory Presets */
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_FACTORY_SMALLROOM \
|
|
||||||
{ 0.3645f, 0.8200f, 0.3162f, 0.7943f, 0.5012f, 1.7200f, 0.6500f, 1.3100f, 0.7079f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.7783f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.1190f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_FACTORY_SHORTPASSAGE \
|
|
||||||
{ 0.3645f, 0.6400f, 0.2512f, 0.7943f, 0.5012f, 2.5300f, 0.6500f, 1.3100f, 1.0000f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.1350f, 0.2300f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_FACTORY_MEDIUMROOM \
|
|
||||||
{ 0.4287f, 0.8200f, 0.2512f, 0.7943f, 0.5012f, 2.7600f, 0.6500f, 1.3100f, 0.2818f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1740f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_FACTORY_LARGEROOM \
|
|
||||||
{ 0.4287f, 0.7500f, 0.2512f, 0.7079f, 0.6310f, 4.2400f, 0.5100f, 1.3100f, 0.1778f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.2310f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_FACTORY_LONGPASSAGE \
|
|
||||||
{ 0.3645f, 0.6400f, 0.2512f, 0.7943f, 0.5012f, 4.0600f, 0.6500f, 1.3100f, 1.0000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0370f, { 0.0000f, 0.0000f, 0.0000f }, 0.1350f, 0.2300f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_FACTORY_HALL \
|
|
||||||
{ 0.4287f, 0.7500f, 0.3162f, 0.7079f, 0.6310f, 7.4300f, 0.5100f, 1.3100f, 0.0631f, 0.0730f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0270f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_FACTORY_CUPBOARD \
|
|
||||||
{ 0.3071f, 0.6300f, 0.2512f, 0.7943f, 0.5012f, 0.4900f, 0.6500f, 1.3100f, 1.2589f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.1070f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_FACTORY_COURTYARD \
|
|
||||||
{ 0.3071f, 0.5700f, 0.3162f, 0.3162f, 0.6310f, 2.3200f, 0.2900f, 0.5600f, 0.2239f, 0.1400f, { 0.0000f, 0.0000f, 0.0000f }, 0.3981f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2900f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_FACTORY_ALCOVE \
|
|
||||||
{ 0.3645f, 0.5900f, 0.2512f, 0.7943f, 0.5012f, 3.1400f, 0.6500f, 1.3100f, 1.4125f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.1140f, 0.1000f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
/* Ice Palace Presets */
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_ICEPALACE_SMALLROOM \
|
|
||||||
{ 1.0000f, 0.8400f, 0.3162f, 0.5623f, 0.2818f, 1.5100f, 1.5300f, 0.2700f, 0.8913f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1640f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_ICEPALACE_SHORTPASSAGE \
|
|
||||||
{ 1.0000f, 0.7500f, 0.3162f, 0.5623f, 0.2818f, 1.7900f, 1.4600f, 0.2800f, 0.5012f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0190f, { 0.0000f, 0.0000f, 0.0000f }, 0.1770f, 0.0900f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_ICEPALACE_MEDIUMROOM \
|
|
||||||
{ 1.0000f, 0.8700f, 0.3162f, 0.5623f, 0.4467f, 2.2200f, 1.5300f, 0.3200f, 0.3981f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0270f, { 0.0000f, 0.0000f, 0.0000f }, 0.1860f, 0.1200f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_ICEPALACE_LARGEROOM \
|
|
||||||
{ 1.0000f, 0.8100f, 0.3162f, 0.5623f, 0.4467f, 3.1400f, 1.5300f, 0.3200f, 0.2512f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0270f, { 0.0000f, 0.0000f, 0.0000f }, 0.2140f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_ICEPALACE_LONGPASSAGE \
|
|
||||||
{ 1.0000f, 0.7700f, 0.3162f, 0.5623f, 0.3981f, 3.0100f, 1.4600f, 0.2800f, 0.7943f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0250f, { 0.0000f, 0.0000f, 0.0000f }, 0.1860f, 0.0400f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_ICEPALACE_HALL \
|
|
||||||
{ 1.0000f, 0.7600f, 0.3162f, 0.4467f, 0.5623f, 5.4900f, 1.5300f, 0.3800f, 0.1122f, 0.0540f, { 0.0000f, 0.0000f, 0.0000f }, 0.6310f, 0.0520f, { 0.0000f, 0.0000f, 0.0000f }, 0.2260f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_ICEPALACE_CUPBOARD \
|
|
||||||
{ 1.0000f, 0.8300f, 0.3162f, 0.5012f, 0.2239f, 0.7600f, 1.5300f, 0.2600f, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.1430f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_ICEPALACE_COURTYARD \
|
|
||||||
{ 1.0000f, 0.5900f, 0.3162f, 0.2818f, 0.3162f, 2.0400f, 1.2000f, 0.3800f, 0.3162f, 0.1730f, { 0.0000f, 0.0000f, 0.0000f }, 0.3162f, 0.0430f, { 0.0000f, 0.0000f, 0.0000f }, 0.2350f, 0.4800f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_ICEPALACE_ALCOVE \
|
|
||||||
{ 1.0000f, 0.8400f, 0.3162f, 0.5623f, 0.2818f, 2.7600f, 1.4600f, 0.2800f, 1.1220f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1610f, 0.0900f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
/* Space Station Presets */
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_SPACESTATION_SMALLROOM \
|
|
||||||
{ 0.2109f, 0.7000f, 0.3162f, 0.7079f, 0.8913f, 1.7200f, 0.8200f, 0.5500f, 0.7943f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0130f, { 0.0000f, 0.0000f, 0.0000f }, 0.1880f, 0.2600f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_SPACESTATION_SHORTPASSAGE \
|
|
||||||
{ 0.2109f, 0.8700f, 0.3162f, 0.6310f, 0.8913f, 3.5700f, 0.5000f, 0.5500f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.1720f, 0.2000f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_SPACESTATION_MEDIUMROOM \
|
|
||||||
{ 0.2109f, 0.7500f, 0.3162f, 0.6310f, 0.8913f, 3.0100f, 0.5000f, 0.5500f, 0.3981f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0350f, { 0.0000f, 0.0000f, 0.0000f }, 0.2090f, 0.3100f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_SPACESTATION_LARGEROOM \
|
|
||||||
{ 0.3645f, 0.8100f, 0.3162f, 0.6310f, 0.8913f, 3.8900f, 0.3800f, 0.6100f, 0.3162f, 0.0560f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0350f, { 0.0000f, 0.0000f, 0.0000f }, 0.2330f, 0.2800f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_SPACESTATION_LONGPASSAGE \
|
|
||||||
{ 0.4287f, 0.8200f, 0.3162f, 0.6310f, 0.8913f, 4.6200f, 0.6200f, 0.5500f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0310f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2300f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_SPACESTATION_HALL \
|
|
||||||
{ 0.4287f, 0.8700f, 0.3162f, 0.6310f, 0.8913f, 7.1100f, 0.3800f, 0.6100f, 0.1778f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.6310f, 0.0470f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2500f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_SPACESTATION_CUPBOARD \
|
|
||||||
{ 0.1715f, 0.5600f, 0.3162f, 0.7079f, 0.8913f, 0.7900f, 0.8100f, 0.5500f, 1.4125f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.7783f, 0.0180f, { 0.0000f, 0.0000f, 0.0000f }, 0.1810f, 0.3100f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_SPACESTATION_ALCOVE \
|
|
||||||
{ 0.2109f, 0.7800f, 0.3162f, 0.7079f, 0.8913f, 1.1600f, 0.8100f, 0.5500f, 1.4125f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0180f, { 0.0000f, 0.0000f, 0.0000f }, 0.1920f, 0.2100f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
/* Wooden Galleon Presets */
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_WOODEN_SMALLROOM \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.1122f, 0.3162f, 0.7900f, 0.3200f, 0.8700f, 1.0000f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_WOODEN_SHORTPASSAGE \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.1259f, 0.3162f, 1.7500f, 0.5000f, 0.8700f, 0.8913f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.6310f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_WOODEN_MEDIUMROOM \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.1000f, 0.2818f, 1.4700f, 0.4200f, 0.8200f, 0.8913f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_WOODEN_LARGEROOM \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.0891f, 0.2818f, 2.6500f, 0.3300f, 0.8200f, 0.8913f, 0.0660f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_WOODEN_LONGPASSAGE \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.1000f, 0.3162f, 1.9900f, 0.4000f, 0.7900f, 1.0000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.4467f, 0.0360f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_WOODEN_HALL \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.0794f, 0.2818f, 3.4500f, 0.3000f, 0.8200f, 0.8913f, 0.0880f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0630f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_WOODEN_CUPBOARD \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.1413f, 0.3162f, 0.5600f, 0.4600f, 0.9100f, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0280f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_WOODEN_COURTYARD \
|
|
||||||
{ 1.0000f, 0.6500f, 0.3162f, 0.0794f, 0.3162f, 1.7900f, 0.3500f, 0.7900f, 0.5623f, 0.1230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1000f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_WOODEN_ALCOVE \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.1259f, 0.3162f, 1.2200f, 0.6200f, 0.9100f, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
/* Sports Presets */
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_SPORT_EMPTYSTADIUM \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.4467f, 0.7943f, 6.2600f, 0.5100f, 1.1000f, 0.0631f, 0.1830f, { 0.0000f, 0.0000f, 0.0000f }, 0.3981f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_SPORT_SQUASHCOURT \
|
|
||||||
{ 1.0000f, 0.7500f, 0.3162f, 0.3162f, 0.7943f, 2.2200f, 0.9100f, 1.1600f, 0.4467f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1260f, 0.1900f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_SPORT_SMALLSWIMMINGPOOL \
|
|
||||||
{ 1.0000f, 0.7000f, 0.3162f, 0.7943f, 0.8913f, 2.7600f, 1.2500f, 1.1400f, 0.6310f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1790f, 0.1500f, 0.8950f, 0.1900f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_SPORT_LARGESWIMMINGPOOL \
|
|
||||||
{ 1.0000f, 0.8200f, 0.3162f, 0.7943f, 1.0000f, 5.4900f, 1.3100f, 1.1400f, 0.4467f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 0.5012f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2220f, 0.5500f, 1.1590f, 0.2100f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_SPORT_GYMNASIUM \
|
|
||||||
{ 1.0000f, 0.8100f, 0.3162f, 0.4467f, 0.8913f, 3.1400f, 1.0600f, 1.3500f, 0.3981f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.5623f, 0.0450f, { 0.0000f, 0.0000f, 0.0000f }, 0.1460f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_SPORT_FULLSTADIUM \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.0708f, 0.7943f, 5.2500f, 0.1700f, 0.8000f, 0.1000f, 0.1880f, { 0.0000f, 0.0000f, 0.0000f }, 0.2818f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_SPORT_STADIUMTANNOY \
|
|
||||||
{ 1.0000f, 0.7800f, 0.3162f, 0.5623f, 0.5012f, 2.5300f, 0.8800f, 0.6800f, 0.2818f, 0.2300f, { 0.0000f, 0.0000f, 0.0000f }, 0.5012f, 0.0630f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
/* Prefab Presets */
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_PREFAB_WORKSHOP \
|
|
||||||
{ 0.4287f, 1.0000f, 0.3162f, 0.1413f, 0.3981f, 0.7600f, 1.0000f, 1.0000f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_PREFAB_SCHOOLROOM \
|
|
||||||
{ 0.4022f, 0.6900f, 0.3162f, 0.6310f, 0.5012f, 0.9800f, 0.4500f, 0.1800f, 1.4125f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.0950f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_PREFAB_PRACTISEROOM \
|
|
||||||
{ 0.4022f, 0.8700f, 0.3162f, 0.3981f, 0.5012f, 1.1200f, 0.5600f, 0.1800f, 1.2589f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.0950f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_PREFAB_OUTHOUSE \
|
|
||||||
{ 1.0000f, 0.8200f, 0.3162f, 0.1122f, 0.1585f, 1.3800f, 0.3800f, 0.3500f, 0.8913f, 0.0240f, { 0.0000f, 0.0000f, -0.0000f }, 0.6310f, 0.0440f, { 0.0000f, 0.0000f, 0.0000f }, 0.1210f, 0.1700f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_PREFAB_CARAVAN \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.0891f, 0.1259f, 0.4300f, 1.5000f, 1.0000f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
/* Dome and Pipe Presets */
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_DOME_TOMB \
|
|
||||||
{ 1.0000f, 0.7900f, 0.3162f, 0.3548f, 0.2239f, 4.1800f, 0.2100f, 0.1000f, 0.3868f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 1.6788f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.1770f, 0.1900f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_PIPE_SMALL \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.3548f, 0.2239f, 5.0400f, 0.1000f, 0.1000f, 0.5012f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 2.5119f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_DOME_SAINTPAULS \
|
|
||||||
{ 1.0000f, 0.8700f, 0.3162f, 0.3548f, 0.2239f, 10.4800f, 0.1900f, 0.1000f, 0.1778f, 0.0900f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0420f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1200f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_PIPE_LONGTHIN \
|
|
||||||
{ 0.2560f, 0.9100f, 0.3162f, 0.4467f, 0.2818f, 9.2100f, 0.1800f, 0.1000f, 0.7079f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_PIPE_LARGE \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.3548f, 0.2239f, 8.4500f, 0.1000f, 0.1000f, 0.3981f, 0.0460f, { 0.0000f, 0.0000f, 0.0000f }, 1.5849f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_PIPE_RESONANT \
|
|
||||||
{ 0.1373f, 0.9100f, 0.3162f, 0.4467f, 0.2818f, 6.8100f, 0.1800f, 0.1000f, 0.7079f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
/* Outdoors Presets */
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_OUTDOORS_BACKYARD \
|
|
||||||
{ 1.0000f, 0.4500f, 0.3162f, 0.2512f, 0.5012f, 1.1200f, 0.3400f, 0.4600f, 0.4467f, 0.0690f, { 0.0000f, 0.0000f, -0.0000f }, 0.7079f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.2180f, 0.3400f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_OUTDOORS_ROLLINGPLAINS \
|
|
||||||
{ 1.0000f, 0.0000f, 0.3162f, 0.0112f, 0.6310f, 2.1300f, 0.2100f, 0.4600f, 0.1778f, 0.3000f, { 0.0000f, 0.0000f, -0.0000f }, 0.4467f, 0.0190f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_OUTDOORS_DEEPCANYON \
|
|
||||||
{ 1.0000f, 0.7400f, 0.3162f, 0.1778f, 0.6310f, 3.8900f, 0.2100f, 0.4600f, 0.3162f, 0.2230f, { 0.0000f, 0.0000f, -0.0000f }, 0.3548f, 0.0190f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_OUTDOORS_CREEK \
|
|
||||||
{ 1.0000f, 0.3500f, 0.3162f, 0.1778f, 0.5012f, 2.1300f, 0.2100f, 0.4600f, 0.3981f, 0.1150f, { 0.0000f, 0.0000f, -0.0000f }, 0.1995f, 0.0310f, { 0.0000f, 0.0000f, 0.0000f }, 0.2180f, 0.3400f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_OUTDOORS_VALLEY \
|
|
||||||
{ 1.0000f, 0.2800f, 0.3162f, 0.0282f, 0.1585f, 2.8800f, 0.2600f, 0.3500f, 0.1413f, 0.2630f, { 0.0000f, 0.0000f, -0.0000f }, 0.3981f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.3400f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
/* Mood Presets */
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_MOOD_HEAVEN \
|
|
||||||
{ 1.0000f, 0.9400f, 0.3162f, 0.7943f, 0.4467f, 5.0400f, 1.1200f, 0.5600f, 0.2427f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0800f, 2.7420f, 0.0500f, 0.9977f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_MOOD_HELL \
|
|
||||||
{ 1.0000f, 0.5700f, 0.3162f, 0.3548f, 0.4467f, 3.5700f, 0.4900f, 2.0000f, 0.0000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1100f, 0.0400f, 2.1090f, 0.5200f, 0.9943f, 5000.0000f, 139.5000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_MOOD_MEMORY \
|
|
||||||
{ 1.0000f, 0.8500f, 0.3162f, 0.6310f, 0.3548f, 4.0600f, 0.8200f, 0.5600f, 0.0398f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.4740f, 0.4500f, 0.9886f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
/* Driving Presets */
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_DRIVING_COMMENTATOR \
|
|
||||||
{ 1.0000f, 0.0000f, 3.1623f, 0.5623f, 0.5012f, 2.4200f, 0.8800f, 0.6800f, 0.1995f, 0.0930f, { 0.0000f, 0.0000f, 0.0000f }, 0.2512f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9886f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_DRIVING_PITGARAGE \
|
|
||||||
{ 0.4287f, 0.5900f, 0.3162f, 0.7079f, 0.5623f, 1.7200f, 0.9300f, 0.8700f, 0.5623f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_DRIVING_INCAR_RACER \
|
|
||||||
{ 0.0832f, 0.8000f, 0.3162f, 1.0000f, 0.7943f, 0.1700f, 2.0000f, 0.4100f, 1.7783f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10268.2002f, 251.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_DRIVING_INCAR_SPORTS \
|
|
||||||
{ 0.0832f, 0.8000f, 0.3162f, 0.6310f, 1.0000f, 0.1700f, 0.7500f, 0.4100f, 1.0000f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.5623f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10268.2002f, 251.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_DRIVING_INCAR_LUXURY \
|
|
||||||
{ 0.2560f, 1.0000f, 0.3162f, 0.1000f, 0.5012f, 0.1300f, 0.4100f, 0.4600f, 0.7943f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.5849f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10268.2002f, 251.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_DRIVING_FULLGRANDSTAND \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 0.2818f, 0.6310f, 3.0100f, 1.3700f, 1.2800f, 0.3548f, 0.0900f, { 0.0000f, 0.0000f, 0.0000f }, 0.1778f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10420.2002f, 250.0000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_DRIVING_EMPTYGRANDSTAND \
|
|
||||||
{ 1.0000f, 1.0000f, 0.3162f, 1.0000f, 0.7943f, 4.6200f, 1.7500f, 1.4000f, 0.2082f, 0.0900f, { 0.0000f, 0.0000f, 0.0000f }, 0.2512f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10420.2002f, 250.0000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_DRIVING_TUNNEL \
|
|
||||||
{ 1.0000f, 0.8100f, 0.3162f, 0.3981f, 0.8913f, 3.4200f, 0.9400f, 1.3100f, 0.7079f, 0.0510f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0470f, { 0.0000f, 0.0000f, 0.0000f }, 0.2140f, 0.0500f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 155.3000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
/* City Presets */
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CITY_STREETS \
|
|
||||||
{ 1.0000f, 0.7800f, 0.3162f, 0.7079f, 0.8913f, 1.7900f, 1.1200f, 0.9100f, 0.2818f, 0.0460f, { 0.0000f, 0.0000f, 0.0000f }, 0.1995f, 0.0280f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CITY_SUBWAY \
|
|
||||||
{ 1.0000f, 0.7400f, 0.3162f, 0.7079f, 0.8913f, 3.0100f, 1.2300f, 0.9100f, 0.7079f, 0.0460f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0280f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.2100f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CITY_MUSEUM \
|
|
||||||
{ 1.0000f, 0.8200f, 0.3162f, 0.1778f, 0.1778f, 3.2800f, 1.4000f, 0.5700f, 0.2512f, 0.0390f, { 0.0000f, 0.0000f, -0.0000f }, 0.8913f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 0.1300f, 0.1700f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CITY_LIBRARY \
|
|
||||||
{ 1.0000f, 0.8200f, 0.3162f, 0.2818f, 0.0891f, 2.7600f, 0.8900f, 0.4100f, 0.3548f, 0.0290f, { 0.0000f, 0.0000f, -0.0000f }, 0.8913f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.1300f, 0.1700f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CITY_UNDERPASS \
|
|
||||||
{ 1.0000f, 0.8200f, 0.3162f, 0.4467f, 0.8913f, 3.5700f, 1.1200f, 0.9100f, 0.3981f, 0.0590f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0370f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1400f, 0.2500f, 0.0000f, 0.9920f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CITY_ABANDONED \
|
|
||||||
{ 1.0000f, 0.6900f, 0.3162f, 0.7943f, 0.8913f, 3.2800f, 1.1700f, 0.9100f, 0.4467f, 0.0440f, { 0.0000f, 0.0000f, 0.0000f }, 0.2818f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2000f, 0.2500f, 0.0000f, 0.9966f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
/* Misc. Presets */
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_DUSTYROOM \
|
|
||||||
{ 0.3645f, 0.5600f, 0.3162f, 0.7943f, 0.7079f, 1.7900f, 0.3800f, 0.2100f, 0.5012f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0060f, { 0.0000f, 0.0000f, 0.0000f }, 0.2020f, 0.0500f, 0.2500f, 0.0000f, 0.9886f, 13046.0000f, 163.3000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_CHAPEL \
|
|
||||||
{ 1.0000f, 0.8400f, 0.3162f, 0.5623f, 1.0000f, 4.6200f, 0.6400f, 1.2300f, 0.4467f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.1100f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
|
||||||
|
|
||||||
#define EFX_REVERB_PRESET_SMALLWATERROOM \
|
|
||||||
{ 1.0000f, 0.7000f, 0.3162f, 0.4477f, 1.0000f, 1.5100f, 1.2500f, 1.1400f, 0.8913f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1790f, 0.1500f, 0.8950f, 0.1900f, 0.9920f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
|
||||||
|
|
||||||
#endif /* EFX_PRESETS_H */
|
|
761
extlibs/headers/AL/efx.h
vendored
761
extlibs/headers/AL/efx.h
vendored
@ -1,761 +0,0 @@
|
|||||||
#ifndef AL_EFX_H
|
|
||||||
#define AL_EFX_H
|
|
||||||
|
|
||||||
|
|
||||||
#include "alc.h"
|
|
||||||
#include "al.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ALC_EXT_EFX_NAME "ALC_EXT_EFX"
|
|
||||||
|
|
||||||
#define ALC_EFX_MAJOR_VERSION 0x20001
|
|
||||||
#define ALC_EFX_MINOR_VERSION 0x20002
|
|
||||||
#define ALC_MAX_AUXILIARY_SENDS 0x20003
|
|
||||||
|
|
||||||
|
|
||||||
/* Listener properties. */
|
|
||||||
#define AL_METERS_PER_UNIT 0x20004
|
|
||||||
|
|
||||||
/* Source properties. */
|
|
||||||
#define AL_DIRECT_FILTER 0x20005
|
|
||||||
#define AL_AUXILIARY_SEND_FILTER 0x20006
|
|
||||||
#define AL_AIR_ABSORPTION_FACTOR 0x20007
|
|
||||||
#define AL_ROOM_ROLLOFF_FACTOR 0x20008
|
|
||||||
#define AL_CONE_OUTER_GAINHF 0x20009
|
|
||||||
#define AL_DIRECT_FILTER_GAINHF_AUTO 0x2000A
|
|
||||||
#define AL_AUXILIARY_SEND_FILTER_GAIN_AUTO 0x2000B
|
|
||||||
#define AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO 0x2000C
|
|
||||||
|
|
||||||
|
|
||||||
/* Effect properties. */
|
|
||||||
|
|
||||||
/* Reverb effect parameters */
|
|
||||||
#define AL_REVERB_DENSITY 0x0001
|
|
||||||
#define AL_REVERB_DIFFUSION 0x0002
|
|
||||||
#define AL_REVERB_GAIN 0x0003
|
|
||||||
#define AL_REVERB_GAINHF 0x0004
|
|
||||||
#define AL_REVERB_DECAY_TIME 0x0005
|
|
||||||
#define AL_REVERB_DECAY_HFRATIO 0x0006
|
|
||||||
#define AL_REVERB_REFLECTIONS_GAIN 0x0007
|
|
||||||
#define AL_REVERB_REFLECTIONS_DELAY 0x0008
|
|
||||||
#define AL_REVERB_LATE_REVERB_GAIN 0x0009
|
|
||||||
#define AL_REVERB_LATE_REVERB_DELAY 0x000A
|
|
||||||
#define AL_REVERB_AIR_ABSORPTION_GAINHF 0x000B
|
|
||||||
#define AL_REVERB_ROOM_ROLLOFF_FACTOR 0x000C
|
|
||||||
#define AL_REVERB_DECAY_HFLIMIT 0x000D
|
|
||||||
|
|
||||||
/* EAX Reverb effect parameters */
|
|
||||||
#define AL_EAXREVERB_DENSITY 0x0001
|
|
||||||
#define AL_EAXREVERB_DIFFUSION 0x0002
|
|
||||||
#define AL_EAXREVERB_GAIN 0x0003
|
|
||||||
#define AL_EAXREVERB_GAINHF 0x0004
|
|
||||||
#define AL_EAXREVERB_GAINLF 0x0005
|
|
||||||
#define AL_EAXREVERB_DECAY_TIME 0x0006
|
|
||||||
#define AL_EAXREVERB_DECAY_HFRATIO 0x0007
|
|
||||||
#define AL_EAXREVERB_DECAY_LFRATIO 0x0008
|
|
||||||
#define AL_EAXREVERB_REFLECTIONS_GAIN 0x0009
|
|
||||||
#define AL_EAXREVERB_REFLECTIONS_DELAY 0x000A
|
|
||||||
#define AL_EAXREVERB_REFLECTIONS_PAN 0x000B
|
|
||||||
#define AL_EAXREVERB_LATE_REVERB_GAIN 0x000C
|
|
||||||
#define AL_EAXREVERB_LATE_REVERB_DELAY 0x000D
|
|
||||||
#define AL_EAXREVERB_LATE_REVERB_PAN 0x000E
|
|
||||||
#define AL_EAXREVERB_ECHO_TIME 0x000F
|
|
||||||
#define AL_EAXREVERB_ECHO_DEPTH 0x0010
|
|
||||||
#define AL_EAXREVERB_MODULATION_TIME 0x0011
|
|
||||||
#define AL_EAXREVERB_MODULATION_DEPTH 0x0012
|
|
||||||
#define AL_EAXREVERB_AIR_ABSORPTION_GAINHF 0x0013
|
|
||||||
#define AL_EAXREVERB_HFREFERENCE 0x0014
|
|
||||||
#define AL_EAXREVERB_LFREFERENCE 0x0015
|
|
||||||
#define AL_EAXREVERB_ROOM_ROLLOFF_FACTOR 0x0016
|
|
||||||
#define AL_EAXREVERB_DECAY_HFLIMIT 0x0017
|
|
||||||
|
|
||||||
/* Chorus effect parameters */
|
|
||||||
#define AL_CHORUS_WAVEFORM 0x0001
|
|
||||||
#define AL_CHORUS_PHASE 0x0002
|
|
||||||
#define AL_CHORUS_RATE 0x0003
|
|
||||||
#define AL_CHORUS_DEPTH 0x0004
|
|
||||||
#define AL_CHORUS_FEEDBACK 0x0005
|
|
||||||
#define AL_CHORUS_DELAY 0x0006
|
|
||||||
|
|
||||||
/* Distortion effect parameters */
|
|
||||||
#define AL_DISTORTION_EDGE 0x0001
|
|
||||||
#define AL_DISTORTION_GAIN 0x0002
|
|
||||||
#define AL_DISTORTION_LOWPASS_CUTOFF 0x0003
|
|
||||||
#define AL_DISTORTION_EQCENTER 0x0004
|
|
||||||
#define AL_DISTORTION_EQBANDWIDTH 0x0005
|
|
||||||
|
|
||||||
/* Echo effect parameters */
|
|
||||||
#define AL_ECHO_DELAY 0x0001
|
|
||||||
#define AL_ECHO_LRDELAY 0x0002
|
|
||||||
#define AL_ECHO_DAMPING 0x0003
|
|
||||||
#define AL_ECHO_FEEDBACK 0x0004
|
|
||||||
#define AL_ECHO_SPREAD 0x0005
|
|
||||||
|
|
||||||
/* Flanger effect parameters */
|
|
||||||
#define AL_FLANGER_WAVEFORM 0x0001
|
|
||||||
#define AL_FLANGER_PHASE 0x0002
|
|
||||||
#define AL_FLANGER_RATE 0x0003
|
|
||||||
#define AL_FLANGER_DEPTH 0x0004
|
|
||||||
#define AL_FLANGER_FEEDBACK 0x0005
|
|
||||||
#define AL_FLANGER_DELAY 0x0006
|
|
||||||
|
|
||||||
/* Frequency shifter effect parameters */
|
|
||||||
#define AL_FREQUENCY_SHIFTER_FREQUENCY 0x0001
|
|
||||||
#define AL_FREQUENCY_SHIFTER_LEFT_DIRECTION 0x0002
|
|
||||||
#define AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION 0x0003
|
|
||||||
|
|
||||||
/* Vocal morpher effect parameters */
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEMEA 0x0001
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING 0x0002
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEMEB 0x0003
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING 0x0004
|
|
||||||
#define AL_VOCAL_MORPHER_WAVEFORM 0x0005
|
|
||||||
#define AL_VOCAL_MORPHER_RATE 0x0006
|
|
||||||
|
|
||||||
/* Pitchshifter effect parameters */
|
|
||||||
#define AL_PITCH_SHIFTER_COARSE_TUNE 0x0001
|
|
||||||
#define AL_PITCH_SHIFTER_FINE_TUNE 0x0002
|
|
||||||
|
|
||||||
/* Ringmodulator effect parameters */
|
|
||||||
#define AL_RING_MODULATOR_FREQUENCY 0x0001
|
|
||||||
#define AL_RING_MODULATOR_HIGHPASS_CUTOFF 0x0002
|
|
||||||
#define AL_RING_MODULATOR_WAVEFORM 0x0003
|
|
||||||
|
|
||||||
/* Autowah effect parameters */
|
|
||||||
#define AL_AUTOWAH_ATTACK_TIME 0x0001
|
|
||||||
#define AL_AUTOWAH_RELEASE_TIME 0x0002
|
|
||||||
#define AL_AUTOWAH_RESONANCE 0x0003
|
|
||||||
#define AL_AUTOWAH_PEAK_GAIN 0x0004
|
|
||||||
|
|
||||||
/* Compressor effect parameters */
|
|
||||||
#define AL_COMPRESSOR_ONOFF 0x0001
|
|
||||||
|
|
||||||
/* Equalizer effect parameters */
|
|
||||||
#define AL_EQUALIZER_LOW_GAIN 0x0001
|
|
||||||
#define AL_EQUALIZER_LOW_CUTOFF 0x0002
|
|
||||||
#define AL_EQUALIZER_MID1_GAIN 0x0003
|
|
||||||
#define AL_EQUALIZER_MID1_CENTER 0x0004
|
|
||||||
#define AL_EQUALIZER_MID1_WIDTH 0x0005
|
|
||||||
#define AL_EQUALIZER_MID2_GAIN 0x0006
|
|
||||||
#define AL_EQUALIZER_MID2_CENTER 0x0007
|
|
||||||
#define AL_EQUALIZER_MID2_WIDTH 0x0008
|
|
||||||
#define AL_EQUALIZER_HIGH_GAIN 0x0009
|
|
||||||
#define AL_EQUALIZER_HIGH_CUTOFF 0x000A
|
|
||||||
|
|
||||||
/* Effect type */
|
|
||||||
#define AL_EFFECT_FIRST_PARAMETER 0x0000
|
|
||||||
#define AL_EFFECT_LAST_PARAMETER 0x8000
|
|
||||||
#define AL_EFFECT_TYPE 0x8001
|
|
||||||
|
|
||||||
/* Effect types, used with the AL_EFFECT_TYPE property */
|
|
||||||
#define AL_EFFECT_NULL 0x0000
|
|
||||||
#define AL_EFFECT_REVERB 0x0001
|
|
||||||
#define AL_EFFECT_CHORUS 0x0002
|
|
||||||
#define AL_EFFECT_DISTORTION 0x0003
|
|
||||||
#define AL_EFFECT_ECHO 0x0004
|
|
||||||
#define AL_EFFECT_FLANGER 0x0005
|
|
||||||
#define AL_EFFECT_FREQUENCY_SHIFTER 0x0006
|
|
||||||
#define AL_EFFECT_VOCAL_MORPHER 0x0007
|
|
||||||
#define AL_EFFECT_PITCH_SHIFTER 0x0008
|
|
||||||
#define AL_EFFECT_RING_MODULATOR 0x0009
|
|
||||||
#define AL_EFFECT_AUTOWAH 0x000A
|
|
||||||
#define AL_EFFECT_COMPRESSOR 0x000B
|
|
||||||
#define AL_EFFECT_EQUALIZER 0x000C
|
|
||||||
#define AL_EFFECT_EAXREVERB 0x8000
|
|
||||||
|
|
||||||
/* Auxiliary Effect Slot properties. */
|
|
||||||
#define AL_EFFECTSLOT_EFFECT 0x0001
|
|
||||||
#define AL_EFFECTSLOT_GAIN 0x0002
|
|
||||||
#define AL_EFFECTSLOT_AUXILIARY_SEND_AUTO 0x0003
|
|
||||||
|
|
||||||
/* NULL Auxiliary Slot ID to disable a source send. */
|
|
||||||
#define AL_EFFECTSLOT_NULL 0x0000
|
|
||||||
|
|
||||||
|
|
||||||
/* Filter properties. */
|
|
||||||
|
|
||||||
/* Lowpass filter parameters */
|
|
||||||
#define AL_LOWPASS_GAIN 0x0001
|
|
||||||
#define AL_LOWPASS_GAINHF 0x0002
|
|
||||||
|
|
||||||
/* Highpass filter parameters */
|
|
||||||
#define AL_HIGHPASS_GAIN 0x0001
|
|
||||||
#define AL_HIGHPASS_GAINLF 0x0002
|
|
||||||
|
|
||||||
/* Bandpass filter parameters */
|
|
||||||
#define AL_BANDPASS_GAIN 0x0001
|
|
||||||
#define AL_BANDPASS_GAINLF 0x0002
|
|
||||||
#define AL_BANDPASS_GAINHF 0x0003
|
|
||||||
|
|
||||||
/* Filter type */
|
|
||||||
#define AL_FILTER_FIRST_PARAMETER 0x0000
|
|
||||||
#define AL_FILTER_LAST_PARAMETER 0x8000
|
|
||||||
#define AL_FILTER_TYPE 0x8001
|
|
||||||
|
|
||||||
/* Filter types, used with the AL_FILTER_TYPE property */
|
|
||||||
#define AL_FILTER_NULL 0x0000
|
|
||||||
#define AL_FILTER_LOWPASS 0x0001
|
|
||||||
#define AL_FILTER_HIGHPASS 0x0002
|
|
||||||
#define AL_FILTER_BANDPASS 0x0003
|
|
||||||
|
|
||||||
|
|
||||||
/* Effect object function types. */
|
|
||||||
typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*);
|
|
||||||
typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, const ALuint*);
|
|
||||||
typedef ALboolean (AL_APIENTRY *LPALISEFFECT)(ALuint);
|
|
||||||
typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint);
|
|
||||||
typedef void (AL_APIENTRY *LPALEFFECTIV)(ALuint, ALenum, const ALint*);
|
|
||||||
typedef void (AL_APIENTRY *LPALEFFECTF)(ALuint, ALenum, ALfloat);
|
|
||||||
typedef void (AL_APIENTRY *LPALEFFECTFV)(ALuint, ALenum, const ALfloat*);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETEFFECTI)(ALuint, ALenum, ALint*);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETEFFECTIV)(ALuint, ALenum, ALint*);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETEFFECTF)(ALuint, ALenum, ALfloat*);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETEFFECTFV)(ALuint, ALenum, ALfloat*);
|
|
||||||
|
|
||||||
/* Filter object function types. */
|
|
||||||
typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*);
|
|
||||||
typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, const ALuint*);
|
|
||||||
typedef ALboolean (AL_APIENTRY *LPALISFILTER)(ALuint);
|
|
||||||
typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint);
|
|
||||||
typedef void (AL_APIENTRY *LPALFILTERIV)(ALuint, ALenum, const ALint*);
|
|
||||||
typedef void (AL_APIENTRY *LPALFILTERF)(ALuint, ALenum, ALfloat);
|
|
||||||
typedef void (AL_APIENTRY *LPALFILTERFV)(ALuint, ALenum, const ALfloat*);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETFILTERI)(ALuint, ALenum, ALint*);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETFILTERIV)(ALuint, ALenum, ALint*);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETFILTERF)(ALuint, ALenum, ALfloat*);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETFILTERFV)(ALuint, ALenum, ALfloat*);
|
|
||||||
|
|
||||||
/* Auxiliary Effect Slot object function types. */
|
|
||||||
typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*);
|
|
||||||
typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTS)(ALsizei, const ALuint*);
|
|
||||||
typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOT)(ALuint);
|
|
||||||
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint);
|
|
||||||
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, const ALint*);
|
|
||||||
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat);
|
|
||||||
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, const ALfloat*);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint*);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat*);
|
|
||||||
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*);
|
|
||||||
|
|
||||||
#ifdef AL_ALEXT_PROTOTYPES
|
|
||||||
AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects);
|
|
||||||
AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects);
|
|
||||||
AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect);
|
|
||||||
AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue);
|
|
||||||
AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *piValues);
|
|
||||||
AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue);
|
|
||||||
AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *pflValues);
|
|
||||||
AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue);
|
|
||||||
AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues);
|
|
||||||
AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue);
|
|
||||||
AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues);
|
|
||||||
|
|
||||||
AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters);
|
|
||||||
AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters);
|
|
||||||
AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter);
|
|
||||||
AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue);
|
|
||||||
AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *piValues);
|
|
||||||
AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue);
|
|
||||||
AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *pflValues);
|
|
||||||
AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue);
|
|
||||||
AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues);
|
|
||||||
AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue);
|
|
||||||
AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues);
|
|
||||||
|
|
||||||
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots);
|
|
||||||
AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots);
|
|
||||||
AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot);
|
|
||||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue);
|
|
||||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *piValues);
|
|
||||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue);
|
|
||||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *pflValues);
|
|
||||||
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue);
|
|
||||||
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues);
|
|
||||||
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue);
|
|
||||||
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Filter ranges and defaults. */
|
|
||||||
|
|
||||||
/* Lowpass filter */
|
|
||||||
#define AL_LOWPASS_MIN_GAIN (0.0f)
|
|
||||||
#define AL_LOWPASS_MAX_GAIN (1.0f)
|
|
||||||
#define AL_LOWPASS_DEFAULT_GAIN (1.0f)
|
|
||||||
|
|
||||||
#define AL_LOWPASS_MIN_GAINHF (0.0f)
|
|
||||||
#define AL_LOWPASS_MAX_GAINHF (1.0f)
|
|
||||||
#define AL_LOWPASS_DEFAULT_GAINHF (1.0f)
|
|
||||||
|
|
||||||
/* Highpass filter */
|
|
||||||
#define AL_HIGHPASS_MIN_GAIN (0.0f)
|
|
||||||
#define AL_HIGHPASS_MAX_GAIN (1.0f)
|
|
||||||
#define AL_HIGHPASS_DEFAULT_GAIN (1.0f)
|
|
||||||
|
|
||||||
#define AL_HIGHPASS_MIN_GAINLF (0.0f)
|
|
||||||
#define AL_HIGHPASS_MAX_GAINLF (1.0f)
|
|
||||||
#define AL_HIGHPASS_DEFAULT_GAINLF (1.0f)
|
|
||||||
|
|
||||||
/* Bandpass filter */
|
|
||||||
#define AL_BANDPASS_MIN_GAIN (0.0f)
|
|
||||||
#define AL_BANDPASS_MAX_GAIN (1.0f)
|
|
||||||
#define AL_BANDPASS_DEFAULT_GAIN (1.0f)
|
|
||||||
|
|
||||||
#define AL_BANDPASS_MIN_GAINHF (0.0f)
|
|
||||||
#define AL_BANDPASS_MAX_GAINHF (1.0f)
|
|
||||||
#define AL_BANDPASS_DEFAULT_GAINHF (1.0f)
|
|
||||||
|
|
||||||
#define AL_BANDPASS_MIN_GAINLF (0.0f)
|
|
||||||
#define AL_BANDPASS_MAX_GAINLF (1.0f)
|
|
||||||
#define AL_BANDPASS_DEFAULT_GAINLF (1.0f)
|
|
||||||
|
|
||||||
|
|
||||||
/* Effect parameter ranges and defaults. */
|
|
||||||
|
|
||||||
/* Standard reverb effect */
|
|
||||||
#define AL_REVERB_MIN_DENSITY (0.0f)
|
|
||||||
#define AL_REVERB_MAX_DENSITY (1.0f)
|
|
||||||
#define AL_REVERB_DEFAULT_DENSITY (1.0f)
|
|
||||||
|
|
||||||
#define AL_REVERB_MIN_DIFFUSION (0.0f)
|
|
||||||
#define AL_REVERB_MAX_DIFFUSION (1.0f)
|
|
||||||
#define AL_REVERB_DEFAULT_DIFFUSION (1.0f)
|
|
||||||
|
|
||||||
#define AL_REVERB_MIN_GAIN (0.0f)
|
|
||||||
#define AL_REVERB_MAX_GAIN (1.0f)
|
|
||||||
#define AL_REVERB_DEFAULT_GAIN (0.32f)
|
|
||||||
|
|
||||||
#define AL_REVERB_MIN_GAINHF (0.0f)
|
|
||||||
#define AL_REVERB_MAX_GAINHF (1.0f)
|
|
||||||
#define AL_REVERB_DEFAULT_GAINHF (0.89f)
|
|
||||||
|
|
||||||
#define AL_REVERB_MIN_DECAY_TIME (0.1f)
|
|
||||||
#define AL_REVERB_MAX_DECAY_TIME (20.0f)
|
|
||||||
#define AL_REVERB_DEFAULT_DECAY_TIME (1.49f)
|
|
||||||
|
|
||||||
#define AL_REVERB_MIN_DECAY_HFRATIO (0.1f)
|
|
||||||
#define AL_REVERB_MAX_DECAY_HFRATIO (2.0f)
|
|
||||||
#define AL_REVERB_DEFAULT_DECAY_HFRATIO (0.83f)
|
|
||||||
|
|
||||||
#define AL_REVERB_MIN_REFLECTIONS_GAIN (0.0f)
|
|
||||||
#define AL_REVERB_MAX_REFLECTIONS_GAIN (3.16f)
|
|
||||||
#define AL_REVERB_DEFAULT_REFLECTIONS_GAIN (0.05f)
|
|
||||||
|
|
||||||
#define AL_REVERB_MIN_REFLECTIONS_DELAY (0.0f)
|
|
||||||
#define AL_REVERB_MAX_REFLECTIONS_DELAY (0.3f)
|
|
||||||
#define AL_REVERB_DEFAULT_REFLECTIONS_DELAY (0.007f)
|
|
||||||
|
|
||||||
#define AL_REVERB_MIN_LATE_REVERB_GAIN (0.0f)
|
|
||||||
#define AL_REVERB_MAX_LATE_REVERB_GAIN (10.0f)
|
|
||||||
#define AL_REVERB_DEFAULT_LATE_REVERB_GAIN (1.26f)
|
|
||||||
|
|
||||||
#define AL_REVERB_MIN_LATE_REVERB_DELAY (0.0f)
|
|
||||||
#define AL_REVERB_MAX_LATE_REVERB_DELAY (0.1f)
|
|
||||||
#define AL_REVERB_DEFAULT_LATE_REVERB_DELAY (0.011f)
|
|
||||||
|
|
||||||
#define AL_REVERB_MIN_AIR_ABSORPTION_GAINHF (0.892f)
|
|
||||||
#define AL_REVERB_MAX_AIR_ABSORPTION_GAINHF (1.0f)
|
|
||||||
#define AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF (0.994f)
|
|
||||||
|
|
||||||
#define AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR (0.0f)
|
|
||||||
#define AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR (10.0f)
|
|
||||||
#define AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f)
|
|
||||||
|
|
||||||
#define AL_REVERB_MIN_DECAY_HFLIMIT AL_FALSE
|
|
||||||
#define AL_REVERB_MAX_DECAY_HFLIMIT AL_TRUE
|
|
||||||
#define AL_REVERB_DEFAULT_DECAY_HFLIMIT AL_TRUE
|
|
||||||
|
|
||||||
/* EAX reverb effect */
|
|
||||||
#define AL_EAXREVERB_MIN_DENSITY (0.0f)
|
|
||||||
#define AL_EAXREVERB_MAX_DENSITY (1.0f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_DENSITY (1.0f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_DIFFUSION (0.0f)
|
|
||||||
#define AL_EAXREVERB_MAX_DIFFUSION (1.0f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_DIFFUSION (1.0f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_GAIN (0.0f)
|
|
||||||
#define AL_EAXREVERB_MAX_GAIN (1.0f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_GAIN (0.32f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_GAINHF (0.0f)
|
|
||||||
#define AL_EAXREVERB_MAX_GAINHF (1.0f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_GAINHF (0.89f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_GAINLF (0.0f)
|
|
||||||
#define AL_EAXREVERB_MAX_GAINLF (1.0f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_GAINLF (1.0f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_DECAY_TIME (0.1f)
|
|
||||||
#define AL_EAXREVERB_MAX_DECAY_TIME (20.0f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_DECAY_TIME (1.49f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_DECAY_HFRATIO (0.1f)
|
|
||||||
#define AL_EAXREVERB_MAX_DECAY_HFRATIO (2.0f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_DECAY_HFRATIO (0.83f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_DECAY_LFRATIO (0.1f)
|
|
||||||
#define AL_EAXREVERB_MAX_DECAY_LFRATIO (2.0f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_DECAY_LFRATIO (1.0f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_REFLECTIONS_GAIN (0.0f)
|
|
||||||
#define AL_EAXREVERB_MAX_REFLECTIONS_GAIN (3.16f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN (0.05f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_REFLECTIONS_DELAY (0.0f)
|
|
||||||
#define AL_EAXREVERB_MAX_REFLECTIONS_DELAY (0.3f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY (0.007f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ (0.0f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_LATE_REVERB_GAIN (0.0f)
|
|
||||||
#define AL_EAXREVERB_MAX_LATE_REVERB_GAIN (10.0f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN (1.26f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_LATE_REVERB_DELAY (0.0f)
|
|
||||||
#define AL_EAXREVERB_MAX_LATE_REVERB_DELAY (0.1f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY (0.011f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ (0.0f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_ECHO_TIME (0.075f)
|
|
||||||
#define AL_EAXREVERB_MAX_ECHO_TIME (0.25f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_ECHO_TIME (0.25f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_ECHO_DEPTH (0.0f)
|
|
||||||
#define AL_EAXREVERB_MAX_ECHO_DEPTH (1.0f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_ECHO_DEPTH (0.0f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_MODULATION_TIME (0.04f)
|
|
||||||
#define AL_EAXREVERB_MAX_MODULATION_TIME (4.0f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_MODULATION_TIME (0.25f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_MODULATION_DEPTH (0.0f)
|
|
||||||
#define AL_EAXREVERB_MAX_MODULATION_DEPTH (1.0f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_MODULATION_DEPTH (0.0f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF (0.892f)
|
|
||||||
#define AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF (1.0f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF (0.994f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_HFREFERENCE (1000.0f)
|
|
||||||
#define AL_EAXREVERB_MAX_HFREFERENCE (20000.0f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_HFREFERENCE (5000.0f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_LFREFERENCE (20.0f)
|
|
||||||
#define AL_EAXREVERB_MAX_LFREFERENCE (1000.0f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_LFREFERENCE (250.0f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR (0.0f)
|
|
||||||
#define AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR (10.0f)
|
|
||||||
#define AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f)
|
|
||||||
|
|
||||||
#define AL_EAXREVERB_MIN_DECAY_HFLIMIT AL_FALSE
|
|
||||||
#define AL_EAXREVERB_MAX_DECAY_HFLIMIT AL_TRUE
|
|
||||||
#define AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT AL_TRUE
|
|
||||||
|
|
||||||
/* Chorus effect */
|
|
||||||
#define AL_CHORUS_WAVEFORM_SINUSOID (0)
|
|
||||||
#define AL_CHORUS_WAVEFORM_TRIANGLE (1)
|
|
||||||
|
|
||||||
#define AL_CHORUS_MIN_WAVEFORM (0)
|
|
||||||
#define AL_CHORUS_MAX_WAVEFORM (1)
|
|
||||||
#define AL_CHORUS_DEFAULT_WAVEFORM (1)
|
|
||||||
|
|
||||||
#define AL_CHORUS_MIN_PHASE (-180)
|
|
||||||
#define AL_CHORUS_MAX_PHASE (180)
|
|
||||||
#define AL_CHORUS_DEFAULT_PHASE (90)
|
|
||||||
|
|
||||||
#define AL_CHORUS_MIN_RATE (0.0f)
|
|
||||||
#define AL_CHORUS_MAX_RATE (10.0f)
|
|
||||||
#define AL_CHORUS_DEFAULT_RATE (1.1f)
|
|
||||||
|
|
||||||
#define AL_CHORUS_MIN_DEPTH (0.0f)
|
|
||||||
#define AL_CHORUS_MAX_DEPTH (1.0f)
|
|
||||||
#define AL_CHORUS_DEFAULT_DEPTH (0.1f)
|
|
||||||
|
|
||||||
#define AL_CHORUS_MIN_FEEDBACK (-1.0f)
|
|
||||||
#define AL_CHORUS_MAX_FEEDBACK (1.0f)
|
|
||||||
#define AL_CHORUS_DEFAULT_FEEDBACK (0.25f)
|
|
||||||
|
|
||||||
#define AL_CHORUS_MIN_DELAY (0.0f)
|
|
||||||
#define AL_CHORUS_MAX_DELAY (0.016f)
|
|
||||||
#define AL_CHORUS_DEFAULT_DELAY (0.016f)
|
|
||||||
|
|
||||||
/* Distortion effect */
|
|
||||||
#define AL_DISTORTION_MIN_EDGE (0.0f)
|
|
||||||
#define AL_DISTORTION_MAX_EDGE (1.0f)
|
|
||||||
#define AL_DISTORTION_DEFAULT_EDGE (0.2f)
|
|
||||||
|
|
||||||
#define AL_DISTORTION_MIN_GAIN (0.01f)
|
|
||||||
#define AL_DISTORTION_MAX_GAIN (1.0f)
|
|
||||||
#define AL_DISTORTION_DEFAULT_GAIN (0.05f)
|
|
||||||
|
|
||||||
#define AL_DISTORTION_MIN_LOWPASS_CUTOFF (80.0f)
|
|
||||||
#define AL_DISTORTION_MAX_LOWPASS_CUTOFF (24000.0f)
|
|
||||||
#define AL_DISTORTION_DEFAULT_LOWPASS_CUTOFF (8000.0f)
|
|
||||||
|
|
||||||
#define AL_DISTORTION_MIN_EQCENTER (80.0f)
|
|
||||||
#define AL_DISTORTION_MAX_EQCENTER (24000.0f)
|
|
||||||
#define AL_DISTORTION_DEFAULT_EQCENTER (3600.0f)
|
|
||||||
|
|
||||||
#define AL_DISTORTION_MIN_EQBANDWIDTH (80.0f)
|
|
||||||
#define AL_DISTORTION_MAX_EQBANDWIDTH (24000.0f)
|
|
||||||
#define AL_DISTORTION_DEFAULT_EQBANDWIDTH (3600.0f)
|
|
||||||
|
|
||||||
/* Echo effect */
|
|
||||||
#define AL_ECHO_MIN_DELAY (0.0f)
|
|
||||||
#define AL_ECHO_MAX_DELAY (0.207f)
|
|
||||||
#define AL_ECHO_DEFAULT_DELAY (0.1f)
|
|
||||||
|
|
||||||
#define AL_ECHO_MIN_LRDELAY (0.0f)
|
|
||||||
#define AL_ECHO_MAX_LRDELAY (0.404f)
|
|
||||||
#define AL_ECHO_DEFAULT_LRDELAY (0.1f)
|
|
||||||
|
|
||||||
#define AL_ECHO_MIN_DAMPING (0.0f)
|
|
||||||
#define AL_ECHO_MAX_DAMPING (0.99f)
|
|
||||||
#define AL_ECHO_DEFAULT_DAMPING (0.5f)
|
|
||||||
|
|
||||||
#define AL_ECHO_MIN_FEEDBACK (0.0f)
|
|
||||||
#define AL_ECHO_MAX_FEEDBACK (1.0f)
|
|
||||||
#define AL_ECHO_DEFAULT_FEEDBACK (0.5f)
|
|
||||||
|
|
||||||
#define AL_ECHO_MIN_SPREAD (-1.0f)
|
|
||||||
#define AL_ECHO_MAX_SPREAD (1.0f)
|
|
||||||
#define AL_ECHO_DEFAULT_SPREAD (-1.0f)
|
|
||||||
|
|
||||||
/* Flanger effect */
|
|
||||||
#define AL_FLANGER_WAVEFORM_SINUSOID (0)
|
|
||||||
#define AL_FLANGER_WAVEFORM_TRIANGLE (1)
|
|
||||||
|
|
||||||
#define AL_FLANGER_MIN_WAVEFORM (0)
|
|
||||||
#define AL_FLANGER_MAX_WAVEFORM (1)
|
|
||||||
#define AL_FLANGER_DEFAULT_WAVEFORM (1)
|
|
||||||
|
|
||||||
#define AL_FLANGER_MIN_PHASE (-180)
|
|
||||||
#define AL_FLANGER_MAX_PHASE (180)
|
|
||||||
#define AL_FLANGER_DEFAULT_PHASE (0)
|
|
||||||
|
|
||||||
#define AL_FLANGER_MIN_RATE (0.0f)
|
|
||||||
#define AL_FLANGER_MAX_RATE (10.0f)
|
|
||||||
#define AL_FLANGER_DEFAULT_RATE (0.27f)
|
|
||||||
|
|
||||||
#define AL_FLANGER_MIN_DEPTH (0.0f)
|
|
||||||
#define AL_FLANGER_MAX_DEPTH (1.0f)
|
|
||||||
#define AL_FLANGER_DEFAULT_DEPTH (1.0f)
|
|
||||||
|
|
||||||
#define AL_FLANGER_MIN_FEEDBACK (-1.0f)
|
|
||||||
#define AL_FLANGER_MAX_FEEDBACK (1.0f)
|
|
||||||
#define AL_FLANGER_DEFAULT_FEEDBACK (-0.5f)
|
|
||||||
|
|
||||||
#define AL_FLANGER_MIN_DELAY (0.0f)
|
|
||||||
#define AL_FLANGER_MAX_DELAY (0.004f)
|
|
||||||
#define AL_FLANGER_DEFAULT_DELAY (0.002f)
|
|
||||||
|
|
||||||
/* Frequency shifter effect */
|
|
||||||
#define AL_FREQUENCY_SHIFTER_MIN_FREQUENCY (0.0f)
|
|
||||||
#define AL_FREQUENCY_SHIFTER_MAX_FREQUENCY (24000.0f)
|
|
||||||
#define AL_FREQUENCY_SHIFTER_DEFAULT_FREQUENCY (0.0f)
|
|
||||||
|
|
||||||
#define AL_FREQUENCY_SHIFTER_MIN_LEFT_DIRECTION (0)
|
|
||||||
#define AL_FREQUENCY_SHIFTER_MAX_LEFT_DIRECTION (2)
|
|
||||||
#define AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION (0)
|
|
||||||
|
|
||||||
#define AL_FREQUENCY_SHIFTER_DIRECTION_DOWN (0)
|
|
||||||
#define AL_FREQUENCY_SHIFTER_DIRECTION_UP (1)
|
|
||||||
#define AL_FREQUENCY_SHIFTER_DIRECTION_OFF (2)
|
|
||||||
|
|
||||||
#define AL_FREQUENCY_SHIFTER_MIN_RIGHT_DIRECTION (0)
|
|
||||||
#define AL_FREQUENCY_SHIFTER_MAX_RIGHT_DIRECTION (2)
|
|
||||||
#define AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION (0)
|
|
||||||
|
|
||||||
/* Vocal morpher effect */
|
|
||||||
#define AL_VOCAL_MORPHER_MIN_PHONEMEA (0)
|
|
||||||
#define AL_VOCAL_MORPHER_MAX_PHONEMEA (29)
|
|
||||||
#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA (0)
|
|
||||||
|
|
||||||
#define AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING (-24)
|
|
||||||
#define AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING (24)
|
|
||||||
#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA_COARSE_TUNING (0)
|
|
||||||
|
|
||||||
#define AL_VOCAL_MORPHER_MIN_PHONEMEB (0)
|
|
||||||
#define AL_VOCAL_MORPHER_MAX_PHONEMEB (29)
|
|
||||||
#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB (10)
|
|
||||||
|
|
||||||
#define AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING (-24)
|
|
||||||
#define AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING (24)
|
|
||||||
#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB_COARSE_TUNING (0)
|
|
||||||
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_A (0)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_E (1)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_I (2)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_O (3)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_U (4)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_AA (5)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_AE (6)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_AH (7)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_AO (8)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_EH (9)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_ER (10)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_IH (11)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_IY (12)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_UH (13)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_UW (14)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_B (15)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_D (16)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_F (17)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_G (18)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_J (19)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_K (20)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_L (21)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_M (22)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_N (23)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_P (24)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_R (25)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_S (26)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_T (27)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_V (28)
|
|
||||||
#define AL_VOCAL_MORPHER_PHONEME_Z (29)
|
|
||||||
|
|
||||||
#define AL_VOCAL_MORPHER_WAVEFORM_SINUSOID (0)
|
|
||||||
#define AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE (1)
|
|
||||||
#define AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH (2)
|
|
||||||
|
|
||||||
#define AL_VOCAL_MORPHER_MIN_WAVEFORM (0)
|
|
||||||
#define AL_VOCAL_MORPHER_MAX_WAVEFORM (2)
|
|
||||||
#define AL_VOCAL_MORPHER_DEFAULT_WAVEFORM (0)
|
|
||||||
|
|
||||||
#define AL_VOCAL_MORPHER_MIN_RATE (0.0f)
|
|
||||||
#define AL_VOCAL_MORPHER_MAX_RATE (10.0f)
|
|
||||||
#define AL_VOCAL_MORPHER_DEFAULT_RATE (1.41f)
|
|
||||||
|
|
||||||
/* Pitch shifter effect */
|
|
||||||
#define AL_PITCH_SHIFTER_MIN_COARSE_TUNE (-12)
|
|
||||||
#define AL_PITCH_SHIFTER_MAX_COARSE_TUNE (12)
|
|
||||||
#define AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE (12)
|
|
||||||
|
|
||||||
#define AL_PITCH_SHIFTER_MIN_FINE_TUNE (-50)
|
|
||||||
#define AL_PITCH_SHIFTER_MAX_FINE_TUNE (50)
|
|
||||||
#define AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE (0)
|
|
||||||
|
|
||||||
/* Ring modulator effect */
|
|
||||||
#define AL_RING_MODULATOR_MIN_FREQUENCY (0.0f)
|
|
||||||
#define AL_RING_MODULATOR_MAX_FREQUENCY (8000.0f)
|
|
||||||
#define AL_RING_MODULATOR_DEFAULT_FREQUENCY (440.0f)
|
|
||||||
|
|
||||||
#define AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF (0.0f)
|
|
||||||
#define AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF (24000.0f)
|
|
||||||
#define AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF (800.0f)
|
|
||||||
|
|
||||||
#define AL_RING_MODULATOR_SINUSOID (0)
|
|
||||||
#define AL_RING_MODULATOR_SAWTOOTH (1)
|
|
||||||
#define AL_RING_MODULATOR_SQUARE (2)
|
|
||||||
|
|
||||||
#define AL_RING_MODULATOR_MIN_WAVEFORM (0)
|
|
||||||
#define AL_RING_MODULATOR_MAX_WAVEFORM (2)
|
|
||||||
#define AL_RING_MODULATOR_DEFAULT_WAVEFORM (0)
|
|
||||||
|
|
||||||
/* Autowah effect */
|
|
||||||
#define AL_AUTOWAH_MIN_ATTACK_TIME (0.0001f)
|
|
||||||
#define AL_AUTOWAH_MAX_ATTACK_TIME (1.0f)
|
|
||||||
#define AL_AUTOWAH_DEFAULT_ATTACK_TIME (0.06f)
|
|
||||||
|
|
||||||
#define AL_AUTOWAH_MIN_RELEASE_TIME (0.0001f)
|
|
||||||
#define AL_AUTOWAH_MAX_RELEASE_TIME (1.0f)
|
|
||||||
#define AL_AUTOWAH_DEFAULT_RELEASE_TIME (0.06f)
|
|
||||||
|
|
||||||
#define AL_AUTOWAH_MIN_RESONANCE (2.0f)
|
|
||||||
#define AL_AUTOWAH_MAX_RESONANCE (1000.0f)
|
|
||||||
#define AL_AUTOWAH_DEFAULT_RESONANCE (1000.0f)
|
|
||||||
|
|
||||||
#define AL_AUTOWAH_MIN_PEAK_GAIN (0.00003f)
|
|
||||||
#define AL_AUTOWAH_MAX_PEAK_GAIN (31621.0f)
|
|
||||||
#define AL_AUTOWAH_DEFAULT_PEAK_GAIN (11.22f)
|
|
||||||
|
|
||||||
/* Compressor effect */
|
|
||||||
#define AL_COMPRESSOR_MIN_ONOFF (0)
|
|
||||||
#define AL_COMPRESSOR_MAX_ONOFF (1)
|
|
||||||
#define AL_COMPRESSOR_DEFAULT_ONOFF (1)
|
|
||||||
|
|
||||||
/* Equalizer effect */
|
|
||||||
#define AL_EQUALIZER_MIN_LOW_GAIN (0.126f)
|
|
||||||
#define AL_EQUALIZER_MAX_LOW_GAIN (7.943f)
|
|
||||||
#define AL_EQUALIZER_DEFAULT_LOW_GAIN (1.0f)
|
|
||||||
|
|
||||||
#define AL_EQUALIZER_MIN_LOW_CUTOFF (50.0f)
|
|
||||||
#define AL_EQUALIZER_MAX_LOW_CUTOFF (800.0f)
|
|
||||||
#define AL_EQUALIZER_DEFAULT_LOW_CUTOFF (200.0f)
|
|
||||||
|
|
||||||
#define AL_EQUALIZER_MIN_MID1_GAIN (0.126f)
|
|
||||||
#define AL_EQUALIZER_MAX_MID1_GAIN (7.943f)
|
|
||||||
#define AL_EQUALIZER_DEFAULT_MID1_GAIN (1.0f)
|
|
||||||
|
|
||||||
#define AL_EQUALIZER_MIN_MID1_CENTER (200.0f)
|
|
||||||
#define AL_EQUALIZER_MAX_MID1_CENTER (3000.0f)
|
|
||||||
#define AL_EQUALIZER_DEFAULT_MID1_CENTER (500.0f)
|
|
||||||
|
|
||||||
#define AL_EQUALIZER_MIN_MID1_WIDTH (0.01f)
|
|
||||||
#define AL_EQUALIZER_MAX_MID1_WIDTH (1.0f)
|
|
||||||
#define AL_EQUALIZER_DEFAULT_MID1_WIDTH (1.0f)
|
|
||||||
|
|
||||||
#define AL_EQUALIZER_MIN_MID2_GAIN (0.126f)
|
|
||||||
#define AL_EQUALIZER_MAX_MID2_GAIN (7.943f)
|
|
||||||
#define AL_EQUALIZER_DEFAULT_MID2_GAIN (1.0f)
|
|
||||||
|
|
||||||
#define AL_EQUALIZER_MIN_MID2_CENTER (1000.0f)
|
|
||||||
#define AL_EQUALIZER_MAX_MID2_CENTER (8000.0f)
|
|
||||||
#define AL_EQUALIZER_DEFAULT_MID2_CENTER (3000.0f)
|
|
||||||
|
|
||||||
#define AL_EQUALIZER_MIN_MID2_WIDTH (0.01f)
|
|
||||||
#define AL_EQUALIZER_MAX_MID2_WIDTH (1.0f)
|
|
||||||
#define AL_EQUALIZER_DEFAULT_MID2_WIDTH (1.0f)
|
|
||||||
|
|
||||||
#define AL_EQUALIZER_MIN_HIGH_GAIN (0.126f)
|
|
||||||
#define AL_EQUALIZER_MAX_HIGH_GAIN (7.943f)
|
|
||||||
#define AL_EQUALIZER_DEFAULT_HIGH_GAIN (1.0f)
|
|
||||||
|
|
||||||
#define AL_EQUALIZER_MIN_HIGH_CUTOFF (4000.0f)
|
|
||||||
#define AL_EQUALIZER_MAX_HIGH_CUTOFF (16000.0f)
|
|
||||||
#define AL_EQUALIZER_DEFAULT_HIGH_CUTOFF (6000.0f)
|
|
||||||
|
|
||||||
|
|
||||||
/* Source parameter value ranges and defaults. */
|
|
||||||
#define AL_MIN_AIR_ABSORPTION_FACTOR (0.0f)
|
|
||||||
#define AL_MAX_AIR_ABSORPTION_FACTOR (10.0f)
|
|
||||||
#define AL_DEFAULT_AIR_ABSORPTION_FACTOR (0.0f)
|
|
||||||
|
|
||||||
#define AL_MIN_ROOM_ROLLOFF_FACTOR (0.0f)
|
|
||||||
#define AL_MAX_ROOM_ROLLOFF_FACTOR (10.0f)
|
|
||||||
#define AL_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f)
|
|
||||||
|
|
||||||
#define AL_MIN_CONE_OUTER_GAINHF (0.0f)
|
|
||||||
#define AL_MAX_CONE_OUTER_GAINHF (1.0f)
|
|
||||||
#define AL_DEFAULT_CONE_OUTER_GAINHF (1.0f)
|
|
||||||
|
|
||||||
#define AL_MIN_DIRECT_FILTER_GAINHF_AUTO AL_FALSE
|
|
||||||
#define AL_MAX_DIRECT_FILTER_GAINHF_AUTO AL_TRUE
|
|
||||||
#define AL_DEFAULT_DIRECT_FILTER_GAINHF_AUTO AL_TRUE
|
|
||||||
|
|
||||||
#define AL_MIN_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_FALSE
|
|
||||||
#define AL_MAX_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_TRUE
|
|
||||||
#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_TRUE
|
|
||||||
|
|
||||||
#define AL_MIN_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_FALSE
|
|
||||||
#define AL_MAX_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE
|
|
||||||
#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE
|
|
||||||
|
|
||||||
|
|
||||||
/* Listener parameter value ranges and defaults. */
|
|
||||||
#define AL_MIN_METERS_PER_UNIT FLT_MIN
|
|
||||||
#define AL_MAX_METERS_PER_UNIT FLT_MAX
|
|
||||||
#define AL_DEFAULT_METERS_PER_UNIT (1.0f)
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* AL_EFX_H */
|
|
92621
extlibs/headers/miniaudio/miniaudio.h
vendored
Normal file
92621
extlibs/headers/miniaudio/miniaudio.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
extlibs/libs-android/arm64-v8a/libopenal.so
vendored
BIN
extlibs/libs-android/arm64-v8a/libopenal.so
vendored
Binary file not shown.
BIN
extlibs/libs-android/armeabi-v7a/libopenal.so
vendored
BIN
extlibs/libs-android/armeabi-v7a/libopenal.so
vendored
Binary file not shown.
BIN
extlibs/libs-android/armeabi/libopenal.so
vendored
BIN
extlibs/libs-android/armeabi/libopenal.so
vendored
Binary file not shown.
BIN
extlibs/libs-android/mips/libopenal.so
vendored
BIN
extlibs/libs-android/mips/libopenal.so
vendored
Binary file not shown.
BIN
extlibs/libs-android/x86/libopenal.so
vendored
BIN
extlibs/libs-android/x86/libopenal.so
vendored
Binary file not shown.
BIN
extlibs/libs-android/x86_64/libopenal.so
vendored
BIN
extlibs/libs-android/x86_64/libopenal.so
vendored
Binary file not shown.
@ -1 +0,0 @@
|
|||||||
Versions/Current/OpenAL
|
|
@ -1 +0,0 @@
|
|||||||
Versions/Current/Resources
|
|
Binary file not shown.
@ -1,20 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
|
||||||
<string>English</string>
|
|
||||||
<key>CFBundleExecutable</key>
|
|
||||||
<string>OpenAL</string>
|
|
||||||
<key>CFBundleIdentifier</key>
|
|
||||||
<string>org.sfml-dev.OpenAL</string>
|
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
|
||||||
<string>6.0</string>
|
|
||||||
<key>CFBundlePackageType</key>
|
|
||||||
<string>FMWK</string>
|
|
||||||
<key>CFBundleSignature</key>
|
|
||||||
<string>????</string>
|
|
||||||
<key>CFBundleVersion</key>
|
|
||||||
<string>1.0</string>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
@ -1 +0,0 @@
|
|||||||
A
|
|
BIN
extlibs/libs-mingw/x64/libopenal32.a
vendored
BIN
extlibs/libs-mingw/x64/libopenal32.a
vendored
Binary file not shown.
BIN
extlibs/libs-mingw/x86/libopenal32.a
vendored
BIN
extlibs/libs-mingw/x86/libopenal32.a
vendored
Binary file not shown.
BIN
extlibs/libs-msvc-universal/x64/openal32.lib
vendored
BIN
extlibs/libs-msvc-universal/x64/openal32.lib
vendored
Binary file not shown.
BIN
extlibs/libs-msvc-universal/x86/openal32.lib
vendored
BIN
extlibs/libs-msvc-universal/x86/openal32.lib
vendored
Binary file not shown.
@ -29,27 +29,29 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/Export.hpp>
|
#include <SFML/Audio/Export.hpp>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Base class for classes that require an OpenAL context
|
/// \brief Base class for classes that require an audio device
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
class SFML_AUDIO_API AlResource
|
class SFML_AUDIO_API AudioResource
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Default constructor
|
/// \brief Default constructor
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
AlResource();
|
AudioResource();
|
||||||
|
|
||||||
|
private:
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Destructor
|
// Member data
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
~AlResource();
|
const std::shared_ptr<void> m_device; //!< Sound device
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
@ -60,7 +62,7 @@ protected:
|
|||||||
/// \ingroup audio
|
/// \ingroup audio
|
||||||
///
|
///
|
||||||
/// This class is for internal use only, it must be the base
|
/// This class is for internal use only, it must be the base
|
||||||
/// of every class that requires a valid OpenAL context in
|
/// of every class that requires a valid audio device in
|
||||||
/// order to work.
|
/// order to work.
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@ -119,6 +120,19 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int getSampleRate() const;
|
unsigned int getSampleRate() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the map of position in sample frame to sound channel
|
||||||
|
///
|
||||||
|
/// This is used to map a sample in the sample stream to a
|
||||||
|
/// position during spatialisation.
|
||||||
|
///
|
||||||
|
/// \return Map of position in sample frame to sound channel
|
||||||
|
///
|
||||||
|
/// \see getSampleRate, getChannelCount, getDuration
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
const std::vector<SoundChannel>& getChannelMap() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Get the total duration of the sound file
|
/// \brief Get the total duration of the sound file
|
||||||
///
|
///
|
||||||
@ -221,8 +235,8 @@ private:
|
|||||||
std::unique_ptr<InputStream, StreamDeleter> m_stream{nullptr, false}; //!< Input stream used to access the file's data
|
std::unique_ptr<InputStream, StreamDeleter> m_stream{nullptr, false}; //!< Input stream used to access the file's data
|
||||||
std::uint64_t m_sampleOffset{}; //!< Sample Read Position
|
std::uint64_t m_sampleOffset{}; //!< Sample Read Position
|
||||||
std::uint64_t m_sampleCount{}; //!< Total number of samples in the file
|
std::uint64_t m_sampleCount{}; //!< Total number of samples in the file
|
||||||
unsigned int m_channelCount{}; //!< Number of channels of the sound
|
|
||||||
unsigned int m_sampleRate{}; //!< Number of samples per second
|
unsigned int m_sampleRate{}; //!< Number of samples per second
|
||||||
|
std::vector<SoundChannel> m_channelMap; //!< The map of position in sample frame to sound channel
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/Export.hpp>
|
#include <SFML/Audio/Export.hpp>
|
||||||
|
|
||||||
|
#include <SFML/System/Angle.hpp>
|
||||||
#include <SFML/System/Vector3.hpp>
|
#include <SFML/System/Vector3.hpp>
|
||||||
|
|
||||||
|
|
||||||
@ -39,6 +40,24 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
namespace sf::Listener
|
namespace sf::Listener
|
||||||
{
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Structure defining the properties of a directional cone
|
||||||
|
///
|
||||||
|
/// Sounds will play at gain 1 when they are positioned
|
||||||
|
/// within the inner angle of the cone. Sounds will play
|
||||||
|
/// at outerGain when they are positioned outside the
|
||||||
|
/// outer angle of the cone. The gain declines linearly
|
||||||
|
/// from 1 to outerGain as the sound moves from the inner
|
||||||
|
/// angle to the outer angle.
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
struct Cone
|
||||||
|
{
|
||||||
|
Angle innerAngle; //!< Inner angle
|
||||||
|
Angle outerAngle; //!< Outer angle
|
||||||
|
float outerGain{}; //!< Outer gain
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Change the global volume of all the sounds and musics
|
/// \brief Change the global volume of all the sounds and musics
|
||||||
///
|
///
|
||||||
@ -112,6 +131,51 @@ SFML_AUDIO_API void setDirection(const Vector3f& direction);
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SFML_AUDIO_API Vector3f getDirection();
|
SFML_AUDIO_API Vector3f getDirection();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the velocity of the listener in the scene
|
||||||
|
///
|
||||||
|
/// The default listener's velocity is (0, 0, -1).
|
||||||
|
///
|
||||||
|
/// \param velocity New listener's velocity
|
||||||
|
///
|
||||||
|
/// \see getVelocity, getDirection, setUpVector, setPosition
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SFML_AUDIO_API void setVelocity(const Vector3f& velocity);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the current forward vector of the listener in the scene
|
||||||
|
///
|
||||||
|
/// \return Listener's velocity
|
||||||
|
///
|
||||||
|
/// \see setVelocity
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SFML_AUDIO_API Vector3f getVelocity();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the cone properties of the listener in the audio scene
|
||||||
|
///
|
||||||
|
/// The cone defines how directional attenuation is applied.
|
||||||
|
/// The default cone of a sound is {2 * PI, 2 * PI, 1}.
|
||||||
|
///
|
||||||
|
/// \param cone Cone properties of the listener in the scene
|
||||||
|
///
|
||||||
|
/// \see getCone
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SFML_AUDIO_API void setCone(const Listener::Cone& cone);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the cone properties of the listener in the audio scene
|
||||||
|
///
|
||||||
|
/// \return Cone properties of the listener
|
||||||
|
///
|
||||||
|
/// \see setCone
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SFML_AUDIO_API Listener::Cone getCone();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Set the upward vector of the listener in the scene
|
/// \brief Set the upward vector of the listener in the scene
|
||||||
///
|
///
|
||||||
|
@ -29,10 +29,12 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/Export.hpp>
|
#include <SFML/Audio/Export.hpp>
|
||||||
|
|
||||||
|
#include <SFML/Audio/SoundChannel.hpp>
|
||||||
#include <SFML/Audio/SoundFileWriter.hpp>
|
#include <SFML/Audio/SoundFileWriter.hpp>
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
@ -54,11 +56,15 @@ public:
|
|||||||
/// \param filename Path of the sound file to write
|
/// \param filename Path of the sound file to write
|
||||||
/// \param sampleRate Sample rate of the sound
|
/// \param sampleRate Sample rate of the sound
|
||||||
/// \param channelCount Number of channels in the sound
|
/// \param channelCount Number of channels in the sound
|
||||||
|
/// \param channelMap Map of position in sample frame to sound channel
|
||||||
///
|
///
|
||||||
/// \return True if the file was successfully opened
|
/// \return True if the file was successfully opened
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool openFromFile(const std::filesystem::path& filename, unsigned int sampleRate, unsigned int channelCount);
|
[[nodiscard]] bool openFromFile(const std::filesystem::path& filename,
|
||||||
|
unsigned int sampleRate,
|
||||||
|
unsigned int channelCount,
|
||||||
|
const std::vector<SoundChannel>& channelMap);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Write audio samples to the file
|
/// \brief Write audio samples to the file
|
||||||
|
@ -31,6 +31,9 @@
|
|||||||
|
|
||||||
#include <SFML/Audio/SoundSource.hpp>
|
#include <SFML/Audio/SoundSource.hpp>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
@ -218,18 +221,18 @@ private:
|
|||||||
void detachBuffer();
|
void detachBuffer();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Re-attach sound to its internal buffer
|
/// \brief Get the sound object
|
||||||
///
|
///
|
||||||
/// This allows the sound buffer to attach back the sounds
|
/// \return The sound object
|
||||||
/// that use it after the sound buffer has been updated.
|
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void reattachBuffer();
|
void* getSound() const override;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
const SoundBuffer* m_buffer{}; //!< Sound buffer bound to the source
|
struct Impl;
|
||||||
|
const std::unique_ptr<Impl> m_impl; //!< Implementation details
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/Export.hpp>
|
#include <SFML/Audio/Export.hpp>
|
||||||
|
|
||||||
#include <SFML/Audio/AlResource.hpp>
|
#include <SFML/Audio/SoundChannel.hpp>
|
||||||
|
|
||||||
#include <SFML/System/Time.hpp>
|
#include <SFML/System/Time.hpp>
|
||||||
|
|
||||||
@ -51,14 +51,14 @@ class InputStream;
|
|||||||
/// \brief Storage for audio samples defining a sound
|
/// \brief Storage for audio samples defining a sound
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
class SFML_AUDIO_API SoundBuffer : AlResource
|
class SFML_AUDIO_API SoundBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Default constructor
|
/// \brief Default constructor
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundBuffer();
|
SoundBuffer() = default;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Copy constructor
|
/// \brief Copy constructor
|
||||||
@ -129,16 +129,18 @@ public:
|
|||||||
/// \param sampleCount Number of samples in the array
|
/// \param sampleCount Number of samples in the array
|
||||||
/// \param channelCount Number of channels (1 = mono, 2 = stereo, ...)
|
/// \param channelCount Number of channels (1 = mono, 2 = stereo, ...)
|
||||||
/// \param sampleRate Sample rate (number of samples to play per second)
|
/// \param sampleRate Sample rate (number of samples to play per second)
|
||||||
|
/// \param channelMap Map of position in sample frame to sound channel
|
||||||
///
|
///
|
||||||
/// \return True if loading succeeded, false if it failed
|
/// \return True if loading succeeded, false if it failed
|
||||||
///
|
///
|
||||||
/// \see loadFromFile, loadFromMemory, saveToFile
|
/// \see loadFromFile, loadFromMemory, saveToFile
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool loadFromSamples(const std::int16_t* samples,
|
[[nodiscard]] bool loadFromSamples(const std::int16_t* samples,
|
||||||
std::uint64_t sampleCount,
|
std::uint64_t sampleCount,
|
||||||
unsigned int channelCount,
|
unsigned int channelCount,
|
||||||
unsigned int sampleRate);
|
unsigned int sampleRate,
|
||||||
|
const std::vector<SoundChannel>& channelMap);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Save the sound buffer to an audio file
|
/// \brief Save the sound buffer to an audio file
|
||||||
@ -191,7 +193,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \return Sample rate (number of samples per second)
|
/// \return Sample rate (number of samples per second)
|
||||||
///
|
///
|
||||||
/// \see getChannelCount, getDuration
|
/// \see getChannelCount, getChannelmap, getDuration
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int getSampleRate() const;
|
unsigned int getSampleRate() const;
|
||||||
@ -204,17 +206,30 @@ public:
|
|||||||
///
|
///
|
||||||
/// \return Number of channels
|
/// \return Number of channels
|
||||||
///
|
///
|
||||||
/// \see getSampleRate, getDuration
|
/// \see getSampleRate, getChannelmap, getDuration
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int getChannelCount() const;
|
unsigned int getChannelCount() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the map of position in sample frame to sound channel
|
||||||
|
///
|
||||||
|
/// This is used to map a sample in the sample stream to a
|
||||||
|
/// position during spatialisation.
|
||||||
|
///
|
||||||
|
/// \return Map of position in sample frame to sound channel
|
||||||
|
///
|
||||||
|
/// \see getSampleRate, getChannelCount, getDuration
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::vector<SoundChannel> getChannelMap() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Get the total duration of the sound
|
/// \brief Get the total duration of the sound
|
||||||
///
|
///
|
||||||
/// \return Sound duration
|
/// \return Sound duration
|
||||||
///
|
///
|
||||||
/// \see getSampleRate, getChannelCount
|
/// \see getSampleRate, getChannelCount, getChannelmap
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Time getDuration() const;
|
Time getDuration() const;
|
||||||
@ -247,11 +262,12 @@ private:
|
|||||||
///
|
///
|
||||||
/// \param channelCount Number of channels
|
/// \param channelCount Number of channels
|
||||||
/// \param sampleRate Sample rate (number of samples per second)
|
/// \param sampleRate Sample rate (number of samples per second)
|
||||||
|
/// \param channelMap Map of position in sample frame to sound channel
|
||||||
///
|
///
|
||||||
/// \return True on success, false if any error happened
|
/// \return True on success, false if any error happened
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool update(unsigned int channelCount, unsigned int sampleRate);
|
[[nodiscard]] bool update(unsigned int channelCount, unsigned int sampleRate, const std::vector<SoundChannel>& channelMap);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Add a sound to the list of sounds that use this buffer
|
/// \brief Add a sound to the list of sounds that use this buffer
|
||||||
@ -277,10 +293,11 @@ private:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int m_buffer{}; //!< OpenAL buffer identifier
|
std::vector<std::int16_t> m_samples; //!< Samples buffer
|
||||||
std::vector<std::int16_t> m_samples; //!< Samples buffer
|
unsigned int m_sampleRate{44100}; //!< Number of samples per second
|
||||||
Time m_duration; //!< Sound duration
|
std::vector<SoundChannel> m_channelMap{SoundChannel::Mono}; //!< The map of position in sample frame to sound channel
|
||||||
mutable SoundList m_sounds; //!< List of sounds that are using this buffer
|
Time m_duration; //!< Sound duration
|
||||||
|
mutable SoundList m_sounds; //!< List of sounds that are using this buffer
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
65
include/SFML/Audio/SoundChannel.hpp
Normal file
65
include/SFML/Audio/SoundChannel.hpp
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2024 Laurent Gomila (laurent@sfml-dev.org)
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \ingroup audio
|
||||||
|
/// \brief Types of sound channels that can be read/written from sound buffers/files
|
||||||
|
///
|
||||||
|
/// In multi-channel audio, each sound channel can be
|
||||||
|
/// assigned a position. The position of the channel is
|
||||||
|
/// used to determine where to place a sound when it
|
||||||
|
/// is spatialised. Assigning an incorrect sound channel
|
||||||
|
/// will result in multi-channel audio being positioned
|
||||||
|
/// incorrectly when using spatialisation.
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
enum class SoundChannel
|
||||||
|
{
|
||||||
|
Unspecified,
|
||||||
|
Mono,
|
||||||
|
FrontLeft,
|
||||||
|
FrontRight,
|
||||||
|
FrontCenter,
|
||||||
|
FrontLeftOfCenter,
|
||||||
|
FrontRightOfCenter,
|
||||||
|
LowFrequencyEffects,
|
||||||
|
BackLeft,
|
||||||
|
BackRight,
|
||||||
|
BackCenter,
|
||||||
|
SideLeft,
|
||||||
|
SideRight,
|
||||||
|
TopCenter,
|
||||||
|
TopFrontLeft,
|
||||||
|
TopFrontRight,
|
||||||
|
TopFrontCenter,
|
||||||
|
TopBackLeft,
|
||||||
|
TopBackRight,
|
||||||
|
TopBackCenter
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sf
|
@ -29,7 +29,6 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
namespace priv
|
namespace priv
|
||||||
|
@ -29,7 +29,10 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/Export.hpp>
|
#include <SFML/Audio/Export.hpp>
|
||||||
|
|
||||||
|
#include <SFML/Audio/SoundChannel.hpp>
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
@ -51,9 +54,10 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
struct Info
|
struct Info
|
||||||
{
|
{
|
||||||
std::uint64_t sampleCount{}; //!< Total number of samples in the file
|
std::uint64_t sampleCount{}; //!< Total number of samples in the file
|
||||||
unsigned int channelCount{}; //!< Number of channels of the sound
|
unsigned int channelCount{}; //!< Number of channels of the sound
|
||||||
unsigned int sampleRate{}; //!< Samples rate of the sound, in samples per second
|
unsigned int sampleRate{}; //!< Samples rate of the sound, in samples per second
|
||||||
|
std::vector<SoundChannel> channelMap; //!< Map of position in sample frame to sound channel
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
@ -29,7 +29,12 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/Export.hpp>
|
#include <SFML/Audio/Export.hpp>
|
||||||
|
|
||||||
|
#include <SFML/Audio/SoundChannel.hpp>
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
@ -53,13 +58,15 @@ public:
|
|||||||
/// \param filename Path of the file to open
|
/// \param filename Path of the file to open
|
||||||
/// \param sampleRate Sample rate of the sound
|
/// \param sampleRate Sample rate of the sound
|
||||||
/// \param channelCount Number of channels of the sound
|
/// \param channelCount Number of channels of the sound
|
||||||
|
/// \param channelMap Map of position in sample frame to sound channel
|
||||||
///
|
///
|
||||||
/// \return True if the file was successfully opened
|
/// \return True if the file was successfully opened
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] virtual bool open(const std::filesystem::path& filename,
|
[[nodiscard]] virtual bool open(const std::filesystem::path& filename,
|
||||||
unsigned int sampleRate,
|
unsigned int sampleRate,
|
||||||
unsigned int channelCount) = 0;
|
unsigned int channelCount,
|
||||||
|
const std::vector<SoundChannel>& channelMap) = 0;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Write audio samples to the open file
|
/// \brief Write audio samples to the open file
|
||||||
@ -101,7 +108,7 @@ public:
|
|||||||
/// // return true if the writer can handle the format
|
/// // return true if the writer can handle the format
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// [[nodiscard]] bool open(const std::filesystem::path& filename, unsigned int sampleRate, unsigned int channelCount) override
|
/// [[nodiscard]] bool open(const std::filesystem::path& filename, unsigned int sampleRate, unsigned int channelCount, const std::vector<SoundChannel>& channelMap) override
|
||||||
/// {
|
/// {
|
||||||
/// // open the file 'filename' for writing,
|
/// // open the file 'filename' for writing,
|
||||||
/// // write the given sample rate and channel count to the file header
|
/// // write the given sample rate and channel count to the file header
|
||||||
|
@ -29,12 +29,10 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/Export.hpp>
|
#include <SFML/Audio/Export.hpp>
|
||||||
|
|
||||||
#include <SFML/Audio/AlResource.hpp>
|
#include <SFML/Audio/SoundChannel.hpp>
|
||||||
|
|
||||||
#include <SFML/System/Time.hpp>
|
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@ -47,7 +45,7 @@ namespace sf
|
|||||||
/// \brief Abstract base class for capturing sound data
|
/// \brief Abstract base class for capturing sound data
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
class SFML_AUDIO_API SoundRecorder : AlResource
|
class SFML_AUDIO_API SoundRecorder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -176,6 +174,17 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int getChannelCount() const;
|
unsigned int getChannelCount() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the map of position in sample frame to sound channel
|
||||||
|
///
|
||||||
|
/// This is used to map a sample in the sample stream to a
|
||||||
|
/// position during spatialisation.
|
||||||
|
///
|
||||||
|
/// \return Map of position in sample frame to sound channel
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
const std::vector<SoundChannel>& getChannelMap() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Check if the system supports audio capture
|
/// \brief Check if the system supports audio capture
|
||||||
///
|
///
|
||||||
@ -196,25 +205,7 @@ protected:
|
|||||||
/// This constructor is only meant to be called by derived classes.
|
/// This constructor is only meant to be called by derived classes.
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundRecorder() = default;
|
SoundRecorder();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Set the processing interval
|
|
||||||
///
|
|
||||||
/// The processing interval controls the period
|
|
||||||
/// between calls to the onProcessSamples function. You may
|
|
||||||
/// want to use a small interval if you want to process the
|
|
||||||
/// recorded data in real time, for example.
|
|
||||||
///
|
|
||||||
/// Note: this is only a hint, the actual period may vary.
|
|
||||||
/// So don't rely on this parameter to implement precise timing.
|
|
||||||
///
|
|
||||||
/// The default processing interval is 100 ms.
|
|
||||||
///
|
|
||||||
/// \param interval Processing interval
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void setProcessingInterval(Time interval);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Start capturing audio data
|
/// \brief Start capturing audio data
|
||||||
@ -257,61 +248,11 @@ protected:
|
|||||||
virtual void onStop();
|
virtual void onStop();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Function called as the entry point of the thread
|
|
||||||
///
|
|
||||||
/// This function starts the recording loop, and returns
|
|
||||||
/// only when the capture is stopped.
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void record();
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Get the new available audio samples and process them
|
|
||||||
///
|
|
||||||
/// This function is called continuously during the
|
|
||||||
/// capture loop. It retrieves the captured samples and
|
|
||||||
/// forwards them to the derived class.
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void processCapturedSamples();
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Clean up the recorder's internal resources
|
|
||||||
///
|
|
||||||
/// This function is called when the capture stops.
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void cleanup();
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Launch a new capture thread running 'record'
|
|
||||||
///
|
|
||||||
/// This function is called when the capture is started or
|
|
||||||
/// when the device is changed.
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void launchCapturingThread();
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Stop capturing and wait for 'm_thread' to join
|
|
||||||
///
|
|
||||||
/// This function is called when the capture is stopped or
|
|
||||||
/// when the device is changed.
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void awaitCapturingThread();
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
std::thread m_thread; //!< Thread running the background recording task
|
struct Impl;
|
||||||
std::vector<std::int16_t> m_samples; //!< Buffer to store captured samples
|
const std::unique_ptr<Impl> m_impl; //!< Implementation details
|
||||||
unsigned int m_sampleRate{}; //!< Sample rate
|
|
||||||
Time m_processingInterval{milliseconds(100)}; //!< Time period between calls to onProcessSamples
|
|
||||||
bool m_isCapturing{}; //!< Capturing state
|
|
||||||
std::string m_deviceName{getDefaultDevice()}; //!< Name of the audio capture device
|
|
||||||
unsigned int m_channelCount{1}; //!< Number of recording channels
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -29,8 +29,9 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/Export.hpp>
|
#include <SFML/Audio/Export.hpp>
|
||||||
|
|
||||||
#include <SFML/Audio/AlResource.hpp>
|
#include <SFML/Audio/AudioResource.hpp>
|
||||||
|
|
||||||
|
#include <SFML/System/Angle.hpp>
|
||||||
#include <SFML/System/Vector3.hpp>
|
#include <SFML/System/Vector3.hpp>
|
||||||
|
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ namespace sf
|
|||||||
/// \brief Base class defining a sound's properties
|
/// \brief Base class defining a sound's properties
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
class SFML_AUDIO_API SoundSource : AlResource
|
class SFML_AUDIO_API SoundSource : protected AudioResource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -55,19 +56,37 @@ public:
|
|||||||
Playing //!< Sound is playing
|
Playing //!< Sound is playing
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Structure defining the properties of a directional cone
|
||||||
|
///
|
||||||
|
/// Sounds will play at gain 1 when the listener
|
||||||
|
/// is positioned within the inner angle of the cone.
|
||||||
|
/// Sounds will play at outerGain when the listener is
|
||||||
|
/// positioned outside the outer angle of the cone.
|
||||||
|
/// The gain declines linearly from 1 to outerGain as the
|
||||||
|
/// listener moves from the inner angle to the outer angle.
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
struct Cone
|
||||||
|
{
|
||||||
|
Angle innerAngle; //!< Inner angle
|
||||||
|
Angle outerAngle; //!< Outer angle
|
||||||
|
float outerGain{}; //!< Outer gain
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Copy constructor
|
/// \brief Copy constructor
|
||||||
///
|
///
|
||||||
/// \param copy Instance to copy
|
/// \param copy Instance to copy
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundSource(const SoundSource& copy);
|
SoundSource(const SoundSource& copy) = default;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Destructor
|
/// \brief Destructor
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
virtual ~SoundSource();
|
virtual ~SoundSource() = default;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Set the pitch of the sound
|
/// \brief Set the pitch of the sound
|
||||||
@ -85,6 +104,21 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void setPitch(float pitch);
|
void setPitch(float pitch);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the pan of the sound
|
||||||
|
///
|
||||||
|
/// Using panning, a mono sound can be panned between
|
||||||
|
/// stereo channels. When the pan is set to -1, the sound
|
||||||
|
/// is played only on the left channel, when the pan is set
|
||||||
|
/// to +1, the sound is played only on the right channel.
|
||||||
|
///
|
||||||
|
/// \param pan New pan to apply to the sound [-1, +1]
|
||||||
|
///
|
||||||
|
/// \see getPan
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void setPan(float pan);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Set the volume of the sound
|
/// \brief Set the volume of the sound
|
||||||
///
|
///
|
||||||
@ -98,6 +132,21 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void setVolume(float volume);
|
void setVolume(float volume);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set whether spatialization of the sound is enabled
|
||||||
|
///
|
||||||
|
/// Spatialization is the application of various effects to
|
||||||
|
/// simulate a sound being emitted at a virtual position in
|
||||||
|
/// 3D space and exhibiting various physical phenomena such as
|
||||||
|
/// directional attenuation and doppler shift.
|
||||||
|
///
|
||||||
|
/// \param enabled True to enable spatialization, false to disable
|
||||||
|
///
|
||||||
|
/// \see isSpatializationEnabled
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void setSpatializationEnabled(bool enabled);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Set the 3D position of the sound in the audio scene
|
/// \brief Set the 3D position of the sound in the audio scene
|
||||||
///
|
///
|
||||||
@ -112,6 +161,79 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void setPosition(const Vector3f& position);
|
void setPosition(const Vector3f& position);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the 3D direction of the sound in the audio scene
|
||||||
|
///
|
||||||
|
/// The direction defines where the sound source is facing
|
||||||
|
/// in 3D space. It will affect how the sound is attenuated
|
||||||
|
/// if facing away from the listener.
|
||||||
|
/// The default direction of a sound is (0, 0, -1).
|
||||||
|
///
|
||||||
|
/// \param direction Direction of the sound in the scene
|
||||||
|
///
|
||||||
|
/// \see getDirection
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void setDirection(const Vector3f& direction);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the cone properties of the sound in the audio scene
|
||||||
|
///
|
||||||
|
/// The cone defines how directional attenuation is applied.
|
||||||
|
/// The default cone of a sound is {2 * PI, 2 * PI, 1}.
|
||||||
|
///
|
||||||
|
/// \param cone Cone properties of the sound in the scene
|
||||||
|
///
|
||||||
|
/// \see getCone
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void setCone(const Cone& cone);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the 3D velocity of the sound in the audio scene
|
||||||
|
///
|
||||||
|
/// The velocity is used to determine how to doppler shift
|
||||||
|
/// the sound. Sounds moving towards the listener will be
|
||||||
|
/// perceived to have a higher pitch and sounds moving away
|
||||||
|
/// from the listener will be perceived to have a lower pitch.
|
||||||
|
///
|
||||||
|
/// \param velocity Velocity of the sound in the scene
|
||||||
|
///
|
||||||
|
/// \see getVelocity
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void setVelocity(const Vector3f& velocity);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the doppler factor of the sound
|
||||||
|
///
|
||||||
|
/// The doppler factor determines how strong the doppler
|
||||||
|
/// shift will be.
|
||||||
|
///
|
||||||
|
/// \param factor New doppler factor to apply to the sound
|
||||||
|
///
|
||||||
|
/// \see getDopplerFactor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void setDopplerFactor(float factor);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the directional attenuation factor of the sound
|
||||||
|
///
|
||||||
|
/// Depending on the virtual position of an output channel
|
||||||
|
/// relative to the listener (such as in surround sound
|
||||||
|
/// setups), sounds will be attenuated when emitting them
|
||||||
|
/// from certain channels. This factor determines how strong
|
||||||
|
/// the attenuation based on output channel position
|
||||||
|
/// relative to the listener is.
|
||||||
|
///
|
||||||
|
/// \param factor New directional attenuation factor to apply to the sound
|
||||||
|
///
|
||||||
|
/// \see getDirectionalAttenuationFactor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void setDirectionalAttenuationFactor(float factor);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Make the sound's position relative to the listener or absolute
|
/// \brief Make the sound's position relative to the listener or absolute
|
||||||
///
|
///
|
||||||
@ -145,6 +267,51 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void setMinDistance(float distance);
|
void setMinDistance(float distance);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the maximum distance of the sound
|
||||||
|
///
|
||||||
|
/// The "maximum distance" of a sound is the minimum
|
||||||
|
/// distance at which it is heard at its minimum volume. Closer
|
||||||
|
/// than the maximum distance, it will start to fade in according
|
||||||
|
/// to its attenuation factor.
|
||||||
|
/// The default value of the maximum distance is the maximum
|
||||||
|
/// value a float can represent.
|
||||||
|
///
|
||||||
|
/// \param distance New maximum distance of the sound
|
||||||
|
///
|
||||||
|
/// \see getMaxDistance, setAttenuation
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void setMaxDistance(float distance);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the minimum gain of the sound
|
||||||
|
///
|
||||||
|
/// When the sound is further away from the listener than
|
||||||
|
/// the "maximum distance" the attenuated gain is clamped
|
||||||
|
/// so it cannot go below the minimum gain value.
|
||||||
|
///
|
||||||
|
/// \param gain New minimum gain of the sound
|
||||||
|
///
|
||||||
|
/// \see getMinGain, setAttenuation
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void setMinGain(float gain);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the maximum gain of the sound
|
||||||
|
///
|
||||||
|
/// When the sound is closer from the listener than
|
||||||
|
/// the "minimum distance" the attenuated gain is clamped
|
||||||
|
/// so it cannot go above the maximum gain value.
|
||||||
|
///
|
||||||
|
/// \param gain New maximum gain of the sound
|
||||||
|
///
|
||||||
|
/// \see getMaxGain, setAttenuation
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void setMaxGain(float gain);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Set the attenuation factor of the sound
|
/// \brief Set the attenuation factor of the sound
|
||||||
///
|
///
|
||||||
@ -174,6 +341,16 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
float getPitch() const;
|
float getPitch() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the pan of the sound
|
||||||
|
///
|
||||||
|
/// \return Pan of the sound
|
||||||
|
///
|
||||||
|
/// \see setPan
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
float getPan() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Get the volume of the sound
|
/// \brief Get the volume of the sound
|
||||||
///
|
///
|
||||||
@ -184,6 +361,16 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
float getVolume() const;
|
float getVolume() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Tell whether spatialization of the sound is enabled
|
||||||
|
///
|
||||||
|
/// \return True if spatialization is enabled, false if it's disabled
|
||||||
|
///
|
||||||
|
/// \see setSpatializationEnabled
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool isSpatializationEnabled() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Get the 3D position of the sound in the audio scene
|
/// \brief Get the 3D position of the sound in the audio scene
|
||||||
///
|
///
|
||||||
@ -194,6 +381,56 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Vector3f getPosition() const;
|
Vector3f getPosition() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the 3D direction of the sound in the audio scene
|
||||||
|
///
|
||||||
|
/// \return Direction of the sound
|
||||||
|
///
|
||||||
|
/// \see setDirection
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Vector3f getDirection() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the cone properties of the sound in the audio scene
|
||||||
|
///
|
||||||
|
/// \return Cone properties of the sound
|
||||||
|
///
|
||||||
|
/// \see setCone
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Cone getCone() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the 3D velocity of the sound in the audio scene
|
||||||
|
///
|
||||||
|
/// \return Velocity of the sound
|
||||||
|
///
|
||||||
|
/// \see setVelocity
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Vector3f getVelocity() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the doppler factor of the sound
|
||||||
|
///
|
||||||
|
/// \return Doppler factor of the sound
|
||||||
|
///
|
||||||
|
/// \see setDopplerFactor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
float getDopplerFactor() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the directional attenuation factor of the sound
|
||||||
|
///
|
||||||
|
/// \return Directional attenuation factor of the sound
|
||||||
|
///
|
||||||
|
/// \see setDirectionalAttenuationFactor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
float getDirectionalAttenuationFactor() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Tell whether the sound's position is relative to the
|
/// \brief Tell whether the sound's position is relative to the
|
||||||
/// listener or is absolute
|
/// listener or is absolute
|
||||||
@ -215,6 +452,36 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
float getMinDistance() const;
|
float getMinDistance() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the maximum distance of the sound
|
||||||
|
///
|
||||||
|
/// \return Maximum distance of the sound
|
||||||
|
///
|
||||||
|
/// \see setMaxDistance, getAttenuation
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
float getMaxDistance() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the minimum gain of the sound
|
||||||
|
///
|
||||||
|
/// \return Minimum gain of the sound
|
||||||
|
///
|
||||||
|
/// \see setMinGain, getAttenuation
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
float getMinGain() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the maximum gain of the sound
|
||||||
|
///
|
||||||
|
/// \return Maximum gain of the sound
|
||||||
|
///
|
||||||
|
/// \see setMaxGain, getAttenuation
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
float getMaxGain() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Get the attenuation factor of the sound
|
/// \brief Get the attenuation factor of the sound
|
||||||
///
|
///
|
||||||
@ -276,7 +543,7 @@ public:
|
|||||||
/// \return Current status of the sound
|
/// \return Current status of the sound
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
virtual Status getStatus() const;
|
virtual Status getStatus() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -285,12 +552,16 @@ protected:
|
|||||||
/// This constructor is meant to be called by derived classes only.
|
/// This constructor is meant to be called by derived classes only.
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundSource();
|
SoundSource() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
/// \brief Get the sound object
|
||||||
|
///
|
||||||
|
/// \return The sound object
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int m_source{}; //!< OpenAL source identifier
|
virtual void* getSound() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOLINTEND(readability-make-member-function-const)
|
// NOLINTEND(readability-make-member-function-const)
|
||||||
|
@ -29,12 +29,13 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/Export.hpp>
|
#include <SFML/Audio/Export.hpp>
|
||||||
|
|
||||||
|
#include <SFML/Audio/SoundChannel.hpp>
|
||||||
#include <SFML/Audio/SoundSource.hpp>
|
#include <SFML/Audio/SoundSource.hpp>
|
||||||
|
|
||||||
#include <SFML/System/Time.hpp>
|
#include <SFML/System/Time.hpp>
|
||||||
|
|
||||||
#include <mutex>
|
#include <memory>
|
||||||
#include <thread>
|
#include <vector>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@ -123,6 +124,17 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int getSampleRate() const;
|
unsigned int getSampleRate() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the map of position in sample frame to sound channel
|
||||||
|
///
|
||||||
|
/// This is used to map a sample in the sample stream to a
|
||||||
|
/// position during spatialisation.
|
||||||
|
///
|
||||||
|
/// \return Map of position in sample frame to sound channel
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::vector<SoundChannel> getChannelMap() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Get the current status of the stream (stopped, paused, playing)
|
/// \brief Get the current status of the stream (stopped, paused, playing)
|
||||||
///
|
///
|
||||||
@ -193,7 +205,7 @@ protected:
|
|||||||
/// This constructor is only meant to be called by derived classes.
|
/// This constructor is only meant to be called by derived classes.
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundStream() = default;
|
SoundStream();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Define the audio stream parameters
|
/// \brief Define the audio stream parameters
|
||||||
@ -207,9 +219,10 @@ protected:
|
|||||||
///
|
///
|
||||||
/// \param channelCount Number of channels of the stream
|
/// \param channelCount Number of channels of the stream
|
||||||
/// \param sampleRate Sample rate, in samples per second
|
/// \param sampleRate Sample rate, in samples per second
|
||||||
|
/// \param channelMap Map of position in sample frame to sound channel
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void initialize(unsigned int channelCount, unsigned int sampleRate);
|
void initialize(unsigned int channelCount, unsigned int sampleRate, const std::vector<SoundChannel>& channelMap);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Request a new chunk of audio samples from the stream source
|
/// \brief Request a new chunk of audio samples from the stream source
|
||||||
@ -253,103 +266,20 @@ protected:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
virtual std::int64_t onLoop();
|
virtual std::int64_t onLoop();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Set the processing interval
|
|
||||||
///
|
|
||||||
/// The processing interval controls the period at which the
|
|
||||||
/// audio buffers are filled by calls to onGetData. A smaller
|
|
||||||
/// interval may be useful for low-latency streams. Note that
|
|
||||||
/// the given period is only a hint and the actual period may
|
|
||||||
/// vary. The default processing interval is 10 ms.
|
|
||||||
///
|
|
||||||
/// \param interval Processing interval
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void setProcessingInterval(Time interval);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Function called as the entry point of the thread
|
/// \brief Get the sound object
|
||||||
///
|
///
|
||||||
/// This function starts the streaming loop, and returns
|
/// \return The sound object
|
||||||
/// only when the sound is stopped.
|
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void streamData();
|
void* getSound() const override;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Fill a new buffer with audio samples, and append
|
|
||||||
/// it to the playing queue
|
|
||||||
///
|
|
||||||
/// This function is called as soon as a buffer has been fully
|
|
||||||
/// consumed; it fills it again and inserts it back into the
|
|
||||||
/// playing queue.
|
|
||||||
///
|
|
||||||
/// \param bufferNum Number of the buffer to fill (in [0, BufferCount])
|
|
||||||
/// \param immediateLoop Treat empty buffers as spent, and act on loops immediately
|
|
||||||
///
|
|
||||||
/// \return True if the stream source has requested to stop, false otherwise
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] bool fillAndPushBuffer(unsigned int bufferNum, bool immediateLoop = false);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Fill the audio buffers and put them all into the playing queue
|
|
||||||
///
|
|
||||||
/// This function is called when playing starts and the
|
|
||||||
/// playing queue is empty.
|
|
||||||
///
|
|
||||||
/// \return True if the derived class has requested to stop, false otherwise
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
[[nodiscard]] bool fillQueue();
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Clear all the audio buffers and empty the playing queue
|
|
||||||
///
|
|
||||||
/// This function is called when the stream is stopped.
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void clearQueue();
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Launch a new stream thread running 'streamData'
|
|
||||||
///
|
|
||||||
/// This function is called when the stream is played or
|
|
||||||
/// when the playing offset is changed.
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void launchStreamingThread(Status threadStartState);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Stop streaming and wait for 'm_thread' to join
|
|
||||||
///
|
|
||||||
/// This function is called when the playback is stopped or
|
|
||||||
/// when the sound stream is destroyed.
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void awaitStreamingThread();
|
|
||||||
|
|
||||||
// NOLINTBEGIN(readability-identifier-naming)
|
|
||||||
static constexpr unsigned int BufferCount{3}; //!< Number of audio buffers used by the streaming loop
|
|
||||||
static constexpr unsigned int BufferRetries{2}; //!< Number of retries (excluding initial try) for onGetData()
|
|
||||||
// NOLINTEND(readability-identifier-naming)
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
std::thread m_thread; //!< Thread running the background tasks
|
struct Impl;
|
||||||
mutable std::recursive_mutex m_threadMutex; //!< Thread mutex
|
const std::unique_ptr<Impl> m_impl; //!< Implementation details
|
||||||
Status m_threadStartState{Stopped}; //!< State the thread starts in (Playing, Paused, Stopped)
|
|
||||||
bool m_isStreaming{}; //!< Streaming state (true = playing, false = stopped)
|
|
||||||
unsigned int m_buffers[BufferCount]{}; //!< Sound buffers used to store temporary audio data
|
|
||||||
unsigned int m_channelCount{}; //!< Number of channels (1 = mono, 2 = stereo, ...)
|
|
||||||
unsigned int m_sampleRate{}; //!< Frequency (samples / second)
|
|
||||||
std::int32_t m_format{}; //!< Format of the internal sound buffers
|
|
||||||
bool m_loop{}; //!< Loop flag (true to loop, false to play once)
|
|
||||||
std::uint64_t m_samplesProcessed{}; //!< Number of samples processed since beginning of the stream
|
|
||||||
std::int64_t m_bufferSeeks[BufferCount]{}; //!< If buffer is an "end buffer", holds next seek position, else NoLoop. For play offset calculation.
|
|
||||||
Time m_processingInterval{milliseconds(10)}; //!< Interval for checking and filling the internal sound buffers.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -70,10 +70,10 @@ In short, SFML is free for any use (commercial or personal, proprietary or open-
|
|||||||
|
|
||||||
## External libraries used by SFML
|
## External libraries used by SFML
|
||||||
|
|
||||||
- [_OpenAL-Soft_](https://github.com/kcat/openal-soft) is under the [LGPL license](https://github.com/kcat/openal-soft/blob/master/COPYING)
|
|
||||||
- [_stb_image_ and _stb_image_write_](https://github.com/nothings/stb) are [public domain](https://github.com/nothings/stb/blob/master/LICENSE)
|
- [_stb_image_ and _stb_image_write_](https://github.com/nothings/stb) are [public domain](https://github.com/nothings/stb/blob/master/LICENSE)
|
||||||
- [_freetype_](https://gitlab.freedesktop.org/freetype/freetype) is under the [FreeType license or the GPL license](https://gitlab.freedesktop.org/freetype/freetype/-/blob/master/LICENSE.TXT)
|
- [_freetype_](https://gitlab.freedesktop.org/freetype/freetype) is under the [FreeType license or the GPL license](https://gitlab.freedesktop.org/freetype/freetype/-/blob/master/LICENSE.TXT)
|
||||||
- [_libogg_](https://gitlab.xiph.org/xiph/ogg) is under the [BSD license](https://gitlab.xiph.org/xiph/ogg/-/blob/master/COPYING)
|
- [_libogg_](https://gitlab.xiph.org/xiph/ogg) is under the [BSD license](https://gitlab.xiph.org/xiph/ogg/-/blob/master/COPYING)
|
||||||
- [_libvorbis_](https://gitlab.xiph.org/xiph/vorbis) is under the [BSD license](https://gitlab.xiph.org/xiph/vorbis/-/blob/master/COPYING)
|
- [_libvorbis_](https://gitlab.xiph.org/xiph/vorbis) is under the [BSD license](https://gitlab.xiph.org/xiph/vorbis/-/blob/master/COPYING)
|
||||||
- [_libflac_](https://gitlab.xiph.org/xiph/flac) is under the [BSD license](https://gitlab.xiph.org/xiph/flac/-/blob/master/COPYING.Xiph)
|
- [_libflac_](https://gitlab.xiph.org/xiph/flac) is under the [BSD license](https://gitlab.xiph.org/xiph/flac/-/blob/master/COPYING.Xiph)
|
||||||
- [_minimp3_](https://github.com/lieff/minimp3) is under the [CC0 license](https://github.com/lieff/minimp3/blob/master/LICENSE)
|
- [_minimp3_](https://github.com/lieff/minimp3) is under the [CC0 license](https://github.com/lieff/minimp3/blob/master/LICENSE)
|
||||||
|
- [_miniaudio_](https://github.com/mackron/miniaudio) is [public domain or under the MIT No Attribution license](https://github.com/mackron/miniaudio/blob/master/LICENSE)
|
||||||
|
@ -1,117 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// SFML - Simple and Fast Multimedia Library
|
|
||||||
// Copyright (C) 2007-2024 Laurent Gomila (laurent@sfml-dev.org)
|
|
||||||
//
|
|
||||||
// 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/System/Err.hpp>
|
|
||||||
|
|
||||||
#include <ostream>
|
|
||||||
#include <string>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
// A nested named namespace is used here to allow unity builds of SFML.
|
|
||||||
namespace AlCheckImpl
|
|
||||||
{
|
|
||||||
thread_local ALenum lastError(AL_NO_ERROR);
|
|
||||||
} // namespace AlCheckImpl
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace sf::priv
|
|
||||||
{
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void alCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression)
|
|
||||||
{
|
|
||||||
// Get the last error
|
|
||||||
const ALenum errorCode = alGetError();
|
|
||||||
|
|
||||||
if (errorCode != AL_NO_ERROR)
|
|
||||||
{
|
|
||||||
AlCheckImpl::lastError = errorCode;
|
|
||||||
|
|
||||||
std::string error = "Unknown error";
|
|
||||||
std::string description = "No description";
|
|
||||||
|
|
||||||
// Decode the error code
|
|
||||||
switch (errorCode)
|
|
||||||
{
|
|
||||||
case AL_INVALID_NAME:
|
|
||||||
{
|
|
||||||
error = "AL_INVALID_NAME";
|
|
||||||
description = "A bad name (ID) 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.filename() << "(" << line << ")."
|
|
||||||
<< "\nExpression:\n " << expression << "\nError description:\n " << error << "\n " << description << '\n'
|
|
||||||
<< std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
ALenum alGetLastErrorImpl()
|
|
||||||
{
|
|
||||||
return std::exchange(AlCheckImpl::lastError, AL_NO_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace sf::priv
|
|
@ -1,93 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// SFML - Simple and Fast Multimedia Library
|
|
||||||
// Copyright (C) 2007-2024 Laurent Gomila (laurent@sfml-dev.org)
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
// Headers
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
#include <SFML/Config.hpp>
|
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <string_view>
|
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <al.h>
|
|
||||||
#include <alc.h>
|
|
||||||
|
|
||||||
namespace sf::priv
|
|
||||||
{
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Let's define a macro to quickly check every OpenAL API call
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
#ifdef SFML_DEBUG
|
|
||||||
|
|
||||||
// If in debug mode, perform a test on every call
|
|
||||||
// The do-while loop is needed so that alCheck can be used as a single statement in if/else branches
|
|
||||||
#define alCheck(expr) \
|
|
||||||
do \
|
|
||||||
{ \
|
|
||||||
expr; \
|
|
||||||
sf::priv::alCheckError(__FILE__, __LINE__, #expr); \
|
|
||||||
} while (false)
|
|
||||||
#define alGetLastError sf::priv::alGetLastErrorImpl
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
// Else, we don't add any overhead
|
|
||||||
#define alCheck(expr) (expr)
|
|
||||||
#define alGetLastError alGetError
|
|
||||||
|
|
||||||
#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
|
|
||||||
/// \param expression The evaluated expression as a string
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void alCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression);
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Get the last OpenAL error on this thread
|
|
||||||
///
|
|
||||||
/// \return The last OpenAL error on this thread
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
ALenum alGetLastErrorImpl();
|
|
||||||
|
|
||||||
} // namespace sf::priv
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
#endif
|
|
@ -25,211 +25,331 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/ALCheck.hpp>
|
|
||||||
#include <SFML/Audio/AudioDevice.hpp>
|
#include <SFML/Audio/AudioDevice.hpp>
|
||||||
#include <SFML/Audio/Listener.hpp>
|
|
||||||
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
|
|
||||||
#include <optional>
|
#include <algorithm>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
ALCdevice* audioDevice = nullptr;
|
|
||||||
ALCcontext* audioContext = nullptr;
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
namespace sf::priv
|
namespace sf::priv
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
AudioDevice::AudioDevice()
|
AudioDevice::AudioDevice()
|
||||||
{
|
{
|
||||||
// Create the device
|
// Ensure we only ever have a single AudioDevice instance
|
||||||
audioDevice = alcOpenDevice(nullptr);
|
assert(getInstance() == nullptr);
|
||||||
|
getInstance() = this;
|
||||||
|
|
||||||
if (audioDevice)
|
// Create the log
|
||||||
|
m_log.emplace();
|
||||||
|
|
||||||
|
if (auto result = ma_log_init(nullptr, &*m_log); result != MA_SUCCESS)
|
||||||
{
|
{
|
||||||
// Create the context
|
m_log.reset();
|
||||||
audioContext = alcCreateContext(audioDevice, nullptr);
|
err() << "Failed to initialize the audio log: " << ma_result_description(result) << std::endl;
|
||||||
|
return;
|
||||||
if (audioContext)
|
|
||||||
{
|
|
||||||
// Set the context as the current one (we'll only need one)
|
|
||||||
alcMakeContextCurrent(audioContext);
|
|
||||||
|
|
||||||
// Apply the listener properties the user might have set
|
|
||||||
float orientation[] = {listenerDirection.x,
|
|
||||||
listenerDirection.y,
|
|
||||||
listenerDirection.z,
|
|
||||||
listenerUpVector.x,
|
|
||||||
listenerUpVector.y,
|
|
||||||
listenerUpVector.z};
|
|
||||||
alCheck(alListenerf(AL_GAIN, listenerVolume * 0.01f));
|
|
||||||
alCheck(alListener3f(AL_POSITION, listenerPosition.x, listenerPosition.y, listenerPosition.z));
|
|
||||||
alCheck(alListenerfv(AL_ORIENTATION, orientation));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
err() << "Failed to create the audio context" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
// Register our logging callback to output any warning/error messages
|
||||||
|
if (auto result = ma_log_register_callback(&*m_log,
|
||||||
|
ma_log_callback_init(
|
||||||
|
[](void*, ma_uint32 level, const char* message)
|
||||||
|
{
|
||||||
|
if (level <= MA_LOG_LEVEL_WARNING)
|
||||||
|
err() << "miniaudio " << ma_log_level_to_string(level)
|
||||||
|
<< ": " << message << std::flush;
|
||||||
|
},
|
||||||
|
nullptr));
|
||||||
|
result != MA_SUCCESS)
|
||||||
|
err() << "Failed to register audio log callback: " << ma_result_description(result) << std::endl;
|
||||||
|
|
||||||
|
// Create the context
|
||||||
|
m_context.emplace();
|
||||||
|
|
||||||
|
auto contextConfig = ma_context_config_init();
|
||||||
|
contextConfig.pLog = &*m_log;
|
||||||
|
|
||||||
|
if (auto result = ma_context_init(nullptr, 0, &contextConfig, &*m_context); result != MA_SUCCESS)
|
||||||
{
|
{
|
||||||
err() << "Failed to open the audio device" << std::endl;
|
m_context.reset();
|
||||||
|
err() << "Failed to initialize the audio context: " << ma_result_description(result) << std::endl;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Count the playback devices
|
||||||
|
ma_uint32 deviceCount;
|
||||||
|
|
||||||
|
if (auto result = ma_context_get_devices(&*m_context, nullptr, &deviceCount, nullptr, nullptr); result != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
err() << "Failed to get audio playback devices: " << ma_result_description(result) << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if there are audio playback devices available on the system
|
||||||
|
if (deviceCount == 0)
|
||||||
|
{
|
||||||
|
err() << "No audio playback devices available on the system" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the playback device
|
||||||
|
m_playbackDevice.emplace();
|
||||||
|
|
||||||
|
auto playbackDeviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||||
|
playbackDeviceConfig.dataCallback = [](ma_device* device, void* output, const void*, ma_uint32 frameCount)
|
||||||
|
{
|
||||||
|
auto& audioDevice = *static_cast<AudioDevice*>(device->pUserData);
|
||||||
|
|
||||||
|
if (audioDevice.m_engine)
|
||||||
|
{
|
||||||
|
if (auto result = ma_engine_read_pcm_frames(&*audioDevice.m_engine, output, frameCount, nullptr);
|
||||||
|
result != MA_SUCCESS)
|
||||||
|
err() << "Failed to read PCM frames from audio engine: " << ma_result_description(result) << std::endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
playbackDeviceConfig.pUserData = this;
|
||||||
|
playbackDeviceConfig.playback.format = ma_format_f32;
|
||||||
|
|
||||||
|
if (auto result = ma_device_init(&*m_context, &playbackDeviceConfig, &*m_playbackDevice); result != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
m_playbackDevice.reset();
|
||||||
|
err() << "Failed to initialize the audio playback device: " << ma_result_description(result) << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the engine
|
||||||
|
auto engineConfig = ma_engine_config_init();
|
||||||
|
engineConfig.pContext = &*m_context;
|
||||||
|
engineConfig.pDevice = &*m_playbackDevice;
|
||||||
|
engineConfig.listenerCount = 1;
|
||||||
|
|
||||||
|
m_engine.emplace();
|
||||||
|
|
||||||
|
if (auto result = ma_engine_init(&engineConfig, &*m_engine); result != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
m_engine.reset();
|
||||||
|
err() << "Failed to initialize the audio engine: " << ma_result_description(result) << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set master volume, position, velocity, cone and world up vector
|
||||||
|
if (auto result = ma_device_set_master_volume(ma_engine_get_device(&*m_engine), getListenerProperties().volume * 0.01f);
|
||||||
|
result != MA_SUCCESS)
|
||||||
|
err() << "Failed to set audio device master volume: " << ma_result_description(result) << std::endl;
|
||||||
|
|
||||||
|
ma_engine_listener_set_position(&*m_engine,
|
||||||
|
0,
|
||||||
|
getListenerProperties().position.x,
|
||||||
|
getListenerProperties().position.y,
|
||||||
|
getListenerProperties().position.z);
|
||||||
|
ma_engine_listener_set_velocity(&*m_engine,
|
||||||
|
0,
|
||||||
|
getListenerProperties().velocity.x,
|
||||||
|
getListenerProperties().velocity.y,
|
||||||
|
getListenerProperties().velocity.z);
|
||||||
|
ma_engine_listener_set_cone(&*m_engine,
|
||||||
|
0,
|
||||||
|
getListenerProperties().cone.innerAngle.asRadians(),
|
||||||
|
getListenerProperties().cone.outerAngle.asRadians(),
|
||||||
|
getListenerProperties().cone.outerGain);
|
||||||
|
ma_engine_listener_set_world_up(&*m_engine,
|
||||||
|
0,
|
||||||
|
getListenerProperties().upVector.x,
|
||||||
|
getListenerProperties().upVector.y,
|
||||||
|
getListenerProperties().upVector.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
AudioDevice::~AudioDevice()
|
AudioDevice::~AudioDevice()
|
||||||
{
|
{
|
||||||
|
// Destroy the engine
|
||||||
|
if (m_engine)
|
||||||
|
ma_engine_uninit(&*m_engine);
|
||||||
|
|
||||||
|
// Destroy the playback device
|
||||||
|
if (m_playbackDevice)
|
||||||
|
ma_device_uninit(&*m_playbackDevice);
|
||||||
|
|
||||||
// Destroy the context
|
// Destroy the context
|
||||||
alcMakeContextCurrent(nullptr);
|
if (m_context)
|
||||||
if (audioContext)
|
ma_context_uninit(&*m_context);
|
||||||
alcDestroyContext(audioContext);
|
|
||||||
|
|
||||||
// Destroy the device
|
// Destroy the log
|
||||||
if (audioDevice)
|
if (m_log)
|
||||||
alcCloseDevice(audioDevice);
|
ma_log_uninit(&*m_log);
|
||||||
|
|
||||||
|
// Ensure we only ever have a single AudioDevice instance
|
||||||
|
assert(getInstance() != nullptr);
|
||||||
|
getInstance() = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool AudioDevice::isExtensionSupported(const std::string& extension)
|
ma_engine* AudioDevice::getEngine()
|
||||||
{
|
{
|
||||||
// Create a temporary audio device in case none exists yet.
|
auto* instance = getInstance();
|
||||||
// This device will not be used in this function and merely
|
|
||||||
// makes sure there is a valid OpenAL device for extension
|
|
||||||
// queries if none has been created yet.
|
|
||||||
std::optional<AudioDevice> device;
|
|
||||||
if (!audioDevice)
|
|
||||||
device.emplace();
|
|
||||||
|
|
||||||
if ((extension.length() > 2) && (extension.substr(0, 3) == "ALC"))
|
if (instance && instance->m_engine)
|
||||||
return alcIsExtensionPresent(audioDevice, extension.c_str()) != AL_FALSE;
|
return &*instance->m_engine;
|
||||||
else
|
|
||||||
return alIsExtensionPresent(extension.c_str()) != AL_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
int AudioDevice::getFormatFromChannelCount(unsigned int channelCount)
|
|
||||||
{
|
|
||||||
// Create a temporary audio device in case none exists yet.
|
|
||||||
// This device will not be used in this function and merely
|
|
||||||
// makes sure there is a valid OpenAL device for format
|
|
||||||
// queries if none has been created yet.
|
|
||||||
std::optional<AudioDevice> device;
|
|
||||||
if (!audioDevice)
|
|
||||||
device.emplace();
|
|
||||||
|
|
||||||
// Find the good format according to the number of channels
|
|
||||||
int format = 0;
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
// Fixes a bug on OS X
|
|
||||||
if (format == -1)
|
|
||||||
format = 0;
|
|
||||||
|
|
||||||
return format;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void AudioDevice::setGlobalVolume(float volume)
|
void AudioDevice::setGlobalVolume(float volume)
|
||||||
{
|
{
|
||||||
if (audioContext)
|
// Store the volume in case no audio device exists yet
|
||||||
alCheck(alListenerf(AL_GAIN, volume * 0.01f));
|
getListenerProperties().volume = volume;
|
||||||
|
|
||||||
listenerVolume = volume;
|
auto* instance = getInstance();
|
||||||
|
|
||||||
|
if (!instance || !instance->m_engine)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (auto result = ma_device_set_master_volume(ma_engine_get_device(&*instance->m_engine), volume * 0.01f);
|
||||||
|
result != MA_SUCCESS)
|
||||||
|
err() << "Failed to set audio device master volume: " << ma_result_description(result) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
float AudioDevice::getGlobalVolume()
|
float AudioDevice::getGlobalVolume()
|
||||||
{
|
{
|
||||||
return listenerVolume;
|
return getListenerProperties().volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void AudioDevice::setPosition(const Vector3f& position)
|
void AudioDevice::setPosition(const Vector3f& position)
|
||||||
{
|
{
|
||||||
if (audioContext)
|
// Store the position in case no audio device exists yet
|
||||||
alCheck(alListener3f(AL_POSITION, position.x, position.y, position.z));
|
getListenerProperties().position = position;
|
||||||
|
|
||||||
listenerPosition = position;
|
auto* instance = getInstance();
|
||||||
|
|
||||||
|
if (!instance || !instance->m_engine)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ma_engine_listener_set_position(&*instance->m_engine, 0, position.x, position.y, position.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Vector3f AudioDevice::getPosition()
|
Vector3f AudioDevice::getPosition()
|
||||||
{
|
{
|
||||||
return listenerPosition;
|
return getListenerProperties().position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void AudioDevice::setDirection(const Vector3f& direction)
|
void AudioDevice::setDirection(const Vector3f& direction)
|
||||||
{
|
{
|
||||||
if (audioContext)
|
// Store the direction in case no audio device exists yet
|
||||||
{
|
getListenerProperties().direction = direction;
|
||||||
float orientation[] =
|
|
||||||
{direction.x, direction.y, direction.z, listenerUpVector.x, listenerUpVector.y, listenerUpVector.z};
|
|
||||||
alCheck(alListenerfv(AL_ORIENTATION, orientation));
|
|
||||||
}
|
|
||||||
|
|
||||||
listenerDirection = direction;
|
auto* instance = getInstance();
|
||||||
|
|
||||||
|
if (!instance || !instance->m_engine)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ma_engine_listener_set_direction(&*instance->m_engine, 0, direction.x, direction.y, direction.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Vector3f AudioDevice::getDirection()
|
Vector3f AudioDevice::getDirection()
|
||||||
{
|
{
|
||||||
return listenerDirection;
|
return getListenerProperties().direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void AudioDevice::setVelocity(const Vector3f& velocity)
|
||||||
|
{
|
||||||
|
// Store the velocity in case no audio device exists yet
|
||||||
|
getListenerProperties().velocity = velocity;
|
||||||
|
|
||||||
|
auto* instance = getInstance();
|
||||||
|
|
||||||
|
if (!instance || !instance->m_engine)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ma_engine_listener_set_velocity(&*instance->m_engine, 0, velocity.x, velocity.y, velocity.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Vector3f AudioDevice::getVelocity()
|
||||||
|
{
|
||||||
|
return getListenerProperties().velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void AudioDevice::setCone(const Listener::Cone& cone)
|
||||||
|
{
|
||||||
|
// Store the cone in case no audio device exists yet
|
||||||
|
getListenerProperties().cone = cone;
|
||||||
|
|
||||||
|
auto* instance = getInstance();
|
||||||
|
|
||||||
|
if (!instance || !instance->m_engine)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ma_engine_listener_set_cone(&*instance->m_engine,
|
||||||
|
0,
|
||||||
|
std::clamp(cone.innerAngle.asRadians(), 0.f, sf::degrees(360).asRadians()),
|
||||||
|
std::clamp(cone.outerAngle.asRadians(), 0.f, sf::degrees(360).asRadians()),
|
||||||
|
cone.outerGain);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Listener::Cone AudioDevice::getCone()
|
||||||
|
{
|
||||||
|
return getListenerProperties().cone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void AudioDevice::setUpVector(const Vector3f& upVector)
|
void AudioDevice::setUpVector(const Vector3f& upVector)
|
||||||
{
|
{
|
||||||
if (audioContext)
|
// Store the up vector in case no audio device exists yet
|
||||||
{
|
getListenerProperties().upVector = upVector;
|
||||||
float orientation[] =
|
|
||||||
{listenerDirection.x, listenerDirection.y, listenerDirection.z, upVector.x, upVector.y, upVector.z};
|
|
||||||
alCheck(alListenerfv(AL_ORIENTATION, orientation));
|
|
||||||
}
|
|
||||||
|
|
||||||
listenerUpVector = upVector;
|
auto* instance = getInstance();
|
||||||
|
|
||||||
|
if (!instance || !instance->m_engine)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ma_engine_listener_set_world_up(&*instance->m_engine, 0, upVector.x, upVector.y, upVector.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Vector3f AudioDevice::getUpVector()
|
Vector3f AudioDevice::getUpVector()
|
||||||
{
|
{
|
||||||
return listenerUpVector;
|
return getListenerProperties().upVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
AudioDevice*& AudioDevice::getInstance()
|
||||||
|
{
|
||||||
|
static AudioDevice* instance{};
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
AudioDevice::ListenerProperties& AudioDevice::getListenerProperties()
|
||||||
|
{
|
||||||
|
static ListenerProperties properties;
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sf::priv
|
} // namespace sf::priv
|
||||||
|
@ -27,9 +27,13 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Audio/Listener.hpp>
|
||||||
|
|
||||||
#include <SFML/System/Vector3.hpp>
|
#include <SFML/System/Vector3.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <miniaudio.h>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
|
||||||
namespace sf::priv
|
namespace sf::priv
|
||||||
@ -56,28 +60,16 @@ public:
|
|||||||
~AudioDevice();
|
~AudioDevice();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Check if an OpenAL extension is supported
|
/// \brief Get the audio engine
|
||||||
///
|
///
|
||||||
/// This functions automatically finds whether it
|
/// There should only be a single instance of AudioDevice.
|
||||||
/// is an AL or ALC extension, and calls the corresponding
|
/// As long as an AudioResource exists, this function should
|
||||||
/// function.
|
/// always return a valid pointer to the audio engine.
|
||||||
///
|
///
|
||||||
/// \param extension Name of the extension to test
|
/// \return The audio engine
|
||||||
///
|
|
||||||
/// \return True if the extension is supported, false if not
|
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
static bool isExtensionSupported(const std::string& extension);
|
static ma_engine* getEngine();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \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);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Change the global volume of all the sounds and musics
|
/// \brief Change the global volume of all the sounds and musics
|
||||||
@ -152,6 +144,51 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
static Vector3f getDirection();
|
static Vector3f getDirection();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the velocity of the listener in the scene
|
||||||
|
///
|
||||||
|
/// The default listener's velocity is (0, 0, -1).
|
||||||
|
///
|
||||||
|
/// \param velocity New listener's velocity
|
||||||
|
///
|
||||||
|
/// \see getVelocity, getDirection, setUpVector, setPosition
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static void setVelocity(const Vector3f& velocity);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the current forward vector of the listener in the scene
|
||||||
|
///
|
||||||
|
/// \return Listener's velocity
|
||||||
|
///
|
||||||
|
/// \see setVelocity
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static Vector3f getVelocity();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the cone properties of the listener in the audio scene
|
||||||
|
///
|
||||||
|
/// The cone defines how directional attenuation is applied.
|
||||||
|
/// The default cone of a sound is {2 * PI, 2 * PI, 1}.
|
||||||
|
///
|
||||||
|
/// \param cone Cone properties of the listener in the scene
|
||||||
|
///
|
||||||
|
/// \see getCone
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static void setCone(const Listener::Cone& cone);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the cone properties of the listener in the audio scene
|
||||||
|
///
|
||||||
|
/// \return Cone properties of the listener
|
||||||
|
///
|
||||||
|
/// \see setCone
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static Listener::Cone getCone();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Set the upward vector of the listener in the scene
|
/// \brief Set the upward vector of the listener in the scene
|
||||||
///
|
///
|
||||||
@ -178,6 +215,41 @@ public:
|
|||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
static Vector3f getUpVector();
|
static Vector3f getUpVector();
|
||||||
|
|
||||||
|
private:
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief This function makes sure the instance pointer is initialized before using it
|
||||||
|
///
|
||||||
|
/// \return The instance pointer
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static AudioDevice*& getInstance();
|
||||||
|
|
||||||
|
struct ListenerProperties
|
||||||
|
{
|
||||||
|
float volume{100.f};
|
||||||
|
sf::Vector3f position{0, 0, 0};
|
||||||
|
sf::Vector3f direction{0, 0, -1};
|
||||||
|
sf::Vector3f velocity{0, 0, 0};
|
||||||
|
Listener::Cone cone{sf::degrees(360), sf::degrees(360), 1};
|
||||||
|
sf::Vector3f upVector{0, 1, 0};
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the listener properties
|
||||||
|
///
|
||||||
|
/// \return The listener properties
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static ListenerProperties& getListenerProperties();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::optional<ma_log> m_log; //!< The miniaudio log
|
||||||
|
std::optional<ma_context> m_context; //!< The miniaudio context
|
||||||
|
std::optional<ma_device> m_playbackDevice; //!< The miniaudio playback device
|
||||||
|
std::optional<ma_engine> m_engine; //!< The miniaudio engine (used for effects and spatialisation)
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sf::priv
|
} // namespace sf::priv
|
||||||
|
@ -25,55 +25,38 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/AlResource.hpp>
|
|
||||||
#include <SFML/Audio/AudioDevice.hpp>
|
#include <SFML/Audio/AudioDevice.hpp>
|
||||||
|
#include <SFML/Audio/AudioResource.hpp>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
// OpenAL resources counter and its mutex
|
|
||||||
unsigned int count = 0;
|
|
||||||
std::recursive_mutex mutex;
|
|
||||||
|
|
||||||
// The audio device is instantiated on demand rather than at global startup,
|
|
||||||
// which solves a lot of weird crashes and errors.
|
|
||||||
// It is destroyed when it is no longer needed.
|
|
||||||
std::unique_ptr<sf::priv::AudioDevice> globalDevice;
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
AlResource::AlResource()
|
AudioResource::AudioResource() :
|
||||||
|
m_device(
|
||||||
|
[]()
|
||||||
|
{
|
||||||
|
// Ensure we only ever create a single instance of an
|
||||||
|
// AudioDevice that is shared between all AudioResources
|
||||||
|
static std::mutex mutex;
|
||||||
|
static std::weak_ptr<sf::priv::AudioDevice> weakAudioDevice;
|
||||||
|
|
||||||
|
const std::lock_guard lock(mutex);
|
||||||
|
|
||||||
|
auto audioDevice = weakAudioDevice.lock();
|
||||||
|
|
||||||
|
if (audioDevice == nullptr)
|
||||||
|
{
|
||||||
|
audioDevice = std::make_shared<priv::AudioDevice>();
|
||||||
|
weakAudioDevice = audioDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
return audioDevice;
|
||||||
|
}())
|
||||||
{
|
{
|
||||||
// Protect from concurrent access
|
|
||||||
const std::lock_guard lock(mutex);
|
|
||||||
|
|
||||||
// If this is the very first resource, trigger the global device initialization
|
|
||||||
if (count == 0)
|
|
||||||
globalDevice = std::make_unique<priv::AudioDevice>();
|
|
||||||
|
|
||||||
// Increment the resources counter
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
AlResource::~AlResource()
|
|
||||||
{
|
|
||||||
// Protect from concurrent access
|
|
||||||
const std::lock_guard lock(mutex);
|
|
||||||
|
|
||||||
// Decrement the resources counter
|
|
||||||
--count;
|
|
||||||
|
|
||||||
// If there's no more resource alive, we can destroy the device
|
|
||||||
if (count == 0)
|
|
||||||
globalDevice.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
@ -3,15 +3,16 @@ set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Audio)
|
|||||||
|
|
||||||
# all source files
|
# all source files
|
||||||
set(SRC
|
set(SRC
|
||||||
${SRCROOT}/ALCheck.cpp
|
${SRCROOT}/AudioResource.cpp
|
||||||
${SRCROOT}/ALCheck.hpp
|
${INCROOT}/AudioResource.hpp
|
||||||
${SRCROOT}/AlResource.cpp
|
|
||||||
${INCROOT}/AlResource.hpp
|
|
||||||
${SRCROOT}/AudioDevice.cpp
|
${SRCROOT}/AudioDevice.cpp
|
||||||
${SRCROOT}/AudioDevice.hpp
|
${SRCROOT}/AudioDevice.hpp
|
||||||
${INCROOT}/Export.hpp
|
${INCROOT}/Export.hpp
|
||||||
${SRCROOT}/Listener.cpp
|
${SRCROOT}/Listener.cpp
|
||||||
${INCROOT}/Listener.hpp
|
${INCROOT}/Listener.hpp
|
||||||
|
${SRCROOT}/Miniaudio.cpp
|
||||||
|
${SRCROOT}/MiniaudioUtils.hpp
|
||||||
|
${SRCROOT}/MiniaudioUtils.cpp
|
||||||
${SRCROOT}/Music.cpp
|
${SRCROOT}/Music.cpp
|
||||||
${INCROOT}/Music.hpp
|
${INCROOT}/Music.hpp
|
||||||
${SRCROOT}/Sound.cpp
|
${SRCROOT}/Sound.cpp
|
||||||
@ -20,6 +21,7 @@ set(SRC
|
|||||||
${INCROOT}/SoundBuffer.hpp
|
${INCROOT}/SoundBuffer.hpp
|
||||||
${SRCROOT}/SoundBufferRecorder.cpp
|
${SRCROOT}/SoundBufferRecorder.cpp
|
||||||
${INCROOT}/SoundBufferRecorder.hpp
|
${INCROOT}/SoundBufferRecorder.hpp
|
||||||
|
${INCROOT}/SoundChannel.hpp
|
||||||
${SRCROOT}/InputSoundFile.cpp
|
${SRCROOT}/InputSoundFile.cpp
|
||||||
${INCROOT}/InputSoundFile.hpp
|
${INCROOT}/InputSoundFile.hpp
|
||||||
${SRCROOT}/OutputSoundFile.cpp
|
${SRCROOT}/OutputSoundFile.cpp
|
||||||
@ -56,18 +58,21 @@ set(CODECS_SRC
|
|||||||
)
|
)
|
||||||
source_group("codecs" FILES ${CODECS_SRC})
|
source_group("codecs" FILES ${CODECS_SRC})
|
||||||
|
|
||||||
# let CMake know about our additional audio libraries paths (on Windows and macOS)
|
# Ensure certain files are compiled as Objective-C++
|
||||||
if(SFML_OS_WINDOWS)
|
# See: https://miniaud.io/docs/manual/index.html#Building
|
||||||
list(APPEND CMAKE_INCLUDE_PATH "${PROJECT_SOURCE_DIR}/extlibs/headers/AL")
|
if(SFML_OS_IOS)
|
||||||
elseif(SFML_OS_MACOS)
|
enable_language(OBJCXX)
|
||||||
|
set_source_files_properties(${SRCROOT}/Miniaudio.cpp PROPERTIES LANGUAGE OBJCXX)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# let CMake know about our additional audio libraries paths (on Android and macOS)
|
||||||
|
if(SFML_OS_MACOS)
|
||||||
list(APPEND CMAKE_LIBRARY_PATH "${PROJECT_SOURCE_DIR}/extlibs/libs-macos/Frameworks")
|
list(APPEND CMAKE_LIBRARY_PATH "${PROJECT_SOURCE_DIR}/extlibs/libs-macos/Frameworks")
|
||||||
elseif(SFML_OS_ANDROID)
|
elseif(SFML_OS_ANDROID)
|
||||||
list(APPEND CMAKE_INCLUDE_PATH "${PROJECT_SOURCE_DIR}/extlibs/headers/AL")
|
|
||||||
list(APPEND CMAKE_INCLUDE_PATH "${PROJECT_SOURCE_DIR}/extlibs/android")
|
list(APPEND CMAKE_INCLUDE_PATH "${PROJECT_SOURCE_DIR}/extlibs/android")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# find external libraries
|
# find external libraries
|
||||||
find_package(OpenAL REQUIRED)
|
|
||||||
find_package(Vorbis REQUIRED)
|
find_package(Vorbis REQUIRED)
|
||||||
find_package(FLAC REQUIRED)
|
find_package(FLAC REQUIRED)
|
||||||
|
|
||||||
@ -78,17 +83,29 @@ sfml_add_library(Audio
|
|||||||
# avoids warnings in vorbisfile.h
|
# avoids warnings in vorbisfile.h
|
||||||
target_compile_definitions(sfml-audio PRIVATE OV_EXCLUDE_STATIC_CALLBACKS FLAC__NO_DLL)
|
target_compile_definitions(sfml-audio PRIVATE OV_EXCLUDE_STATIC_CALLBACKS FLAC__NO_DLL)
|
||||||
|
|
||||||
|
# disable miniaudio features we do not use
|
||||||
|
target_compile_definitions(sfml-audio PRIVATE MA_NO_DECODING MA_NO_ENCODING MA_NO_RESOURCE_MANAGER MA_NO_GENERATION)
|
||||||
|
|
||||||
# setup dependencies
|
# setup dependencies
|
||||||
target_link_libraries(sfml-audio
|
target_link_libraries(sfml-audio
|
||||||
PUBLIC SFML::System
|
PUBLIC SFML::System
|
||||||
PRIVATE OpenAL::OpenAL Vorbis::vorbis FLAC::FLAC)
|
PRIVATE Vorbis::vorbis FLAC::FLAC)
|
||||||
if(NOT SFML_OS_IOS)
|
if(SFML_OS_IOS)
|
||||||
|
target_link_libraries(sfml-audio PRIVATE "-framework Foundation" "-framework CoreFoundation" "-framework CoreAudio" "-framework AudioToolbox" "-framework AVFoundation")
|
||||||
|
else()
|
||||||
target_link_libraries(sfml-audio PRIVATE Vorbis::vorbisfile Vorbis::vorbisenc)
|
target_link_libraries(sfml-audio PRIVATE Vorbis::vorbisfile Vorbis::vorbisenc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# miniaudio sources
|
||||||
|
target_include_directories(sfml-audio SYSTEM PRIVATE "${PROJECT_SOURCE_DIR}/extlibs/headers/miniaudio")
|
||||||
|
|
||||||
# minimp3 sources
|
# minimp3 sources
|
||||||
target_include_directories(sfml-audio SYSTEM PRIVATE "${PROJECT_SOURCE_DIR}/extlibs/headers/minimp3")
|
target_include_directories(sfml-audio SYSTEM PRIVATE "${PROJECT_SOURCE_DIR}/extlibs/headers/minimp3")
|
||||||
|
|
||||||
if(SFML_OS_ANDROID)
|
if(SFML_OS_ANDROID)
|
||||||
target_link_libraries(sfml-audio PRIVATE android OpenSLES)
|
target_link_libraries(sfml-audio PRIVATE android OpenSLES)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(SFML_OS_LINUX)
|
||||||
|
target_link_libraries(sfml-audio PRIVATE dl)
|
||||||
|
endif()
|
||||||
|
@ -35,10 +35,11 @@
|
|||||||
#include <SFML/System/MemoryInputStream.hpp>
|
#include <SFML/System/MemoryInputStream.hpp>
|
||||||
#include <SFML/System/Time.hpp>
|
#include <SFML/System/Time.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
@ -91,9 +92,9 @@ bool InputSoundFile::openFromFile(const std::filesystem::path& filename)
|
|||||||
m_stream = std::move(file);
|
m_stream = std::move(file);
|
||||||
|
|
||||||
// Retrieve the attributes of the open sound file
|
// Retrieve the attributes of the open sound file
|
||||||
m_sampleCount = info->sampleCount;
|
m_sampleCount = info->sampleCount;
|
||||||
m_channelCount = info->channelCount;
|
m_sampleRate = info->sampleRate;
|
||||||
m_sampleRate = info->sampleRate;
|
m_channelMap = info->channelMap;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -126,9 +127,9 @@ bool InputSoundFile::openFromMemory(const void* data, std::size_t sizeInBytes)
|
|||||||
m_stream = std::move(memory);
|
m_stream = std::move(memory);
|
||||||
|
|
||||||
// Retrieve the attributes of the open sound file
|
// Retrieve the attributes of the open sound file
|
||||||
m_sampleCount = info->sampleCount;
|
m_sampleCount = info->sampleCount;
|
||||||
m_channelCount = info->channelCount;
|
m_sampleRate = info->sampleRate;
|
||||||
m_sampleRate = info->sampleRate;
|
m_channelMap = info->channelMap;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -162,9 +163,9 @@ bool InputSoundFile::openFromStream(InputStream& stream)
|
|||||||
m_stream = {&stream, false};
|
m_stream = {&stream, false};
|
||||||
|
|
||||||
// Retrieve the attributes of the open sound file
|
// Retrieve the attributes of the open sound file
|
||||||
m_sampleCount = info->sampleCount;
|
m_sampleCount = info->sampleCount;
|
||||||
m_channelCount = info->channelCount;
|
m_sampleRate = info->sampleRate;
|
||||||
m_sampleRate = info->sampleRate;
|
m_channelMap = info->channelMap;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -180,7 +181,7 @@ std::uint64_t InputSoundFile::getSampleCount() const
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int InputSoundFile::getChannelCount() const
|
unsigned int InputSoundFile::getChannelCount() const
|
||||||
{
|
{
|
||||||
return m_channelCount;
|
return static_cast<unsigned int>(m_channelMap.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -191,15 +192,22 @@ unsigned int InputSoundFile::getSampleRate() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
const std::vector<SoundChannel>& InputSoundFile::getChannelMap() const
|
||||||
|
{
|
||||||
|
return m_channelMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Time InputSoundFile::getDuration() const
|
Time InputSoundFile::getDuration() const
|
||||||
{
|
{
|
||||||
// Make sure we don't divide by 0
|
// Make sure we don't divide by 0
|
||||||
if (m_channelCount == 0 || m_sampleRate == 0)
|
if (m_channelMap.empty() || m_sampleRate == 0)
|
||||||
return Time::Zero;
|
return Time::Zero;
|
||||||
|
|
||||||
return seconds(
|
return seconds(
|
||||||
static_cast<float>(m_sampleCount) / static_cast<float>(m_channelCount) / static_cast<float>(m_sampleRate));
|
static_cast<float>(m_sampleCount) / static_cast<float>(m_channelMap.size()) / static_cast<float>(m_sampleRate));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -207,11 +215,11 @@ Time InputSoundFile::getDuration() const
|
|||||||
Time InputSoundFile::getTimeOffset() const
|
Time InputSoundFile::getTimeOffset() const
|
||||||
{
|
{
|
||||||
// Make sure we don't divide by 0
|
// Make sure we don't divide by 0
|
||||||
if (m_channelCount == 0 || m_sampleRate == 0)
|
if (m_channelMap.empty() || m_sampleRate == 0)
|
||||||
return Time::Zero;
|
return Time::Zero;
|
||||||
|
|
||||||
return seconds(
|
return seconds(
|
||||||
static_cast<float>(m_sampleOffset) / static_cast<float>(m_channelCount) / static_cast<float>(m_sampleRate));
|
static_cast<float>(m_sampleOffset) / static_cast<float>(m_channelMap.size()) / static_cast<float>(m_sampleRate));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -225,11 +233,11 @@ std::uint64_t InputSoundFile::getSampleOffset() const
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void InputSoundFile::seek(std::uint64_t sampleOffset)
|
void InputSoundFile::seek(std::uint64_t sampleOffset)
|
||||||
{
|
{
|
||||||
if (m_reader && m_channelCount != 0)
|
if (m_reader && !m_channelMap.empty())
|
||||||
{
|
{
|
||||||
// The reader handles an overrun gracefully, but we
|
// The reader handles an overrun gracefully, but we
|
||||||
// pre-check to keep our known position consistent
|
// pre-check to keep our known position consistent
|
||||||
m_sampleOffset = std::min(sampleOffset / m_channelCount * m_channelCount, m_sampleCount);
|
m_sampleOffset = std::min(sampleOffset / m_channelMap.size() * m_channelMap.size(), m_sampleCount);
|
||||||
m_reader->seek(m_sampleOffset);
|
m_reader->seek(m_sampleOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -238,7 +246,7 @@ void InputSoundFile::seek(std::uint64_t sampleOffset)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void InputSoundFile::seek(Time timeOffset)
|
void InputSoundFile::seek(Time timeOffset)
|
||||||
{
|
{
|
||||||
seek(static_cast<std::uint64_t>(timeOffset.asSeconds() * static_cast<float>(m_sampleRate)) * m_channelCount);
|
seek(static_cast<std::uint64_t>(timeOffset.asSeconds() * static_cast<float>(m_sampleRate)) * m_channelMap.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -257,6 +265,7 @@ std::uint64_t InputSoundFile::read(std::int16_t* samples, std::uint64_t maxCount
|
|||||||
void InputSoundFile::close()
|
void InputSoundFile::close()
|
||||||
{
|
{
|
||||||
*this = {};
|
*this = {};
|
||||||
|
m_channelMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -73,6 +73,34 @@ Vector3f Listener::getDirection()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Listener::setVelocity(const Vector3f& velocity)
|
||||||
|
{
|
||||||
|
priv::AudioDevice::setVelocity(velocity);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Vector3f Listener::getVelocity()
|
||||||
|
{
|
||||||
|
return priv::AudioDevice::getVelocity();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Listener::setCone(const Listener::Cone& cone)
|
||||||
|
{
|
||||||
|
priv::AudioDevice::setCone(cone);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Listener::Cone Listener::getCone()
|
||||||
|
{
|
||||||
|
return priv::AudioDevice::getCone();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Listener::setUpVector(const Vector3f& upVector)
|
void Listener::setUpVector(const Vector3f& upVector)
|
||||||
{
|
{
|
||||||
|
33
src/SFML/Audio/Miniaudio.cpp
Normal file
33
src/SFML/Audio/Miniaudio.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2024 Laurent Gomila (laurent@sfml-dev.org)
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#pragma GCC diagnostic ignored "-Wnull-dereference" // Work around MinGW warning
|
||||||
|
#endif
|
||||||
|
// #define MA_DEBUG_OUTPUT // Uncomment to enable miniaudio debug output to console
|
||||||
|
#define MINIAUDIO_IMPLEMENTATION
|
||||||
|
#include <miniaudio.h>
|
245
src/SFML/Audio/MiniaudioUtils.cpp
Normal file
245
src/SFML/Audio/MiniaudioUtils.cpp
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2024 Laurent Gomila (laurent@sfml-dev.org)
|
||||||
|
//
|
||||||
|
// 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/MiniaudioUtils.hpp>
|
||||||
|
#include <SFML/Audio/SoundChannel.hpp>
|
||||||
|
|
||||||
|
#include <SFML/System/Angle.hpp>
|
||||||
|
#include <SFML/System/Err.hpp>
|
||||||
|
#include <SFML/System/Time.hpp>
|
||||||
|
|
||||||
|
#include <miniaudio.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <limits>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf::priv
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
struct SavedSettings
|
||||||
|
{
|
||||||
|
float pitch{1.f};
|
||||||
|
float pan{0.f};
|
||||||
|
float volume{1.f};
|
||||||
|
ma_bool32 spatializationEnabled{MA_TRUE};
|
||||||
|
ma_vec3f position{0.f, 0.f, 0.f};
|
||||||
|
ma_vec3f direction{0.f, 0.f, -1.f};
|
||||||
|
float directionalAttenuationFactor{1.f};
|
||||||
|
ma_vec3f velocity{0.f, 0.f, 0.f};
|
||||||
|
float dopplerFactor{1.f};
|
||||||
|
ma_positioning positioning{ma_positioning_absolute};
|
||||||
|
float minDistance{1.f};
|
||||||
|
float maxDistance{std::numeric_limits<float>::max()};
|
||||||
|
float minGain{0.f};
|
||||||
|
float maxGain{1.f};
|
||||||
|
float rollOff{1.f};
|
||||||
|
float innerAngle{sf::degrees(360).asRadians()};
|
||||||
|
float outerAngle{sf::degrees(360).asRadians()};
|
||||||
|
float outerGain{0.f};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SavedSettings saveSettings(const ma_sound& sound)
|
||||||
|
{
|
||||||
|
float innerAngle;
|
||||||
|
float outerAngle;
|
||||||
|
float outerGain;
|
||||||
|
ma_sound_get_cone(&sound, &innerAngle, &outerAngle, &outerGain);
|
||||||
|
|
||||||
|
return SavedSettings{ma_sound_get_pitch(&sound),
|
||||||
|
ma_sound_get_pan(&sound),
|
||||||
|
ma_sound_get_volume(&sound),
|
||||||
|
ma_sound_is_spatialization_enabled(&sound),
|
||||||
|
ma_sound_get_position(&sound),
|
||||||
|
ma_sound_get_direction(&sound),
|
||||||
|
ma_sound_get_directional_attenuation_factor(&sound),
|
||||||
|
ma_sound_get_velocity(&sound),
|
||||||
|
ma_sound_get_doppler_factor(&sound),
|
||||||
|
ma_sound_get_positioning(&sound),
|
||||||
|
ma_sound_get_min_distance(&sound),
|
||||||
|
ma_sound_get_max_distance(&sound),
|
||||||
|
ma_sound_get_min_gain(&sound),
|
||||||
|
ma_sound_get_max_gain(&sound),
|
||||||
|
ma_sound_get_rolloff(&sound),
|
||||||
|
innerAngle,
|
||||||
|
outerAngle,
|
||||||
|
outerGain};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void applySettings(ma_sound& sound, const SavedSettings& savedSettings)
|
||||||
|
{
|
||||||
|
ma_sound_set_pitch(&sound, savedSettings.pitch);
|
||||||
|
ma_sound_set_pan(&sound, savedSettings.pan);
|
||||||
|
ma_sound_set_volume(&sound, savedSettings.volume);
|
||||||
|
ma_sound_set_spatialization_enabled(&sound, savedSettings.spatializationEnabled);
|
||||||
|
ma_sound_set_position(&sound, savedSettings.position.x, savedSettings.position.y, savedSettings.position.z);
|
||||||
|
ma_sound_set_direction(&sound, savedSettings.direction.x, savedSettings.direction.y, savedSettings.direction.z);
|
||||||
|
ma_sound_set_directional_attenuation_factor(&sound, savedSettings.directionalAttenuationFactor);
|
||||||
|
ma_sound_set_velocity(&sound, savedSettings.velocity.x, savedSettings.velocity.y, savedSettings.velocity.z);
|
||||||
|
ma_sound_set_doppler_factor(&sound, savedSettings.dopplerFactor);
|
||||||
|
ma_sound_set_positioning(&sound, savedSettings.positioning);
|
||||||
|
ma_sound_set_min_distance(&sound, savedSettings.minDistance);
|
||||||
|
ma_sound_set_max_distance(&sound, savedSettings.maxDistance);
|
||||||
|
ma_sound_set_min_gain(&sound, savedSettings.minGain);
|
||||||
|
ma_sound_set_max_gain(&sound, savedSettings.maxGain);
|
||||||
|
ma_sound_set_rolloff(&sound, savedSettings.rollOff);
|
||||||
|
|
||||||
|
ma_sound_set_cone(&sound, savedSettings.innerAngle, savedSettings.outerAngle, savedSettings.outerGain);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void initializeDataSource(ma_data_source_base& dataSourceBase, const ma_data_source_vtable& vtable)
|
||||||
|
{
|
||||||
|
// Set this object up as a miniaudio data source
|
||||||
|
ma_data_source_config config = ma_data_source_config_init();
|
||||||
|
config.vtable = &vtable;
|
||||||
|
|
||||||
|
if (const ma_result result = ma_data_source_init(&config, &dataSourceBase); result != MA_SUCCESS)
|
||||||
|
err() << "Failed to initialize audio data source: " << ma_result_description(result) << std::endl;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
ma_channel MiniaudioUtils::soundChannelToMiniaudioChannel(sf::SoundChannel soundChannel)
|
||||||
|
{
|
||||||
|
switch (soundChannel)
|
||||||
|
{
|
||||||
|
case SoundChannel::Unspecified:
|
||||||
|
return MA_CHANNEL_NONE;
|
||||||
|
case SoundChannel::Mono:
|
||||||
|
return MA_CHANNEL_MONO;
|
||||||
|
case SoundChannel::FrontLeft:
|
||||||
|
return MA_CHANNEL_FRONT_LEFT;
|
||||||
|
case SoundChannel::FrontRight:
|
||||||
|
return MA_CHANNEL_FRONT_RIGHT;
|
||||||
|
case SoundChannel::FrontCenter:
|
||||||
|
return MA_CHANNEL_FRONT_CENTER;
|
||||||
|
case SoundChannel::FrontLeftOfCenter:
|
||||||
|
return MA_CHANNEL_FRONT_LEFT_CENTER;
|
||||||
|
case SoundChannel::FrontRightOfCenter:
|
||||||
|
return MA_CHANNEL_FRONT_RIGHT_CENTER;
|
||||||
|
case SoundChannel::LowFrequencyEffects:
|
||||||
|
return MA_CHANNEL_LFE;
|
||||||
|
case SoundChannel::BackLeft:
|
||||||
|
return MA_CHANNEL_BACK_LEFT;
|
||||||
|
case SoundChannel::BackRight:
|
||||||
|
return MA_CHANNEL_BACK_RIGHT;
|
||||||
|
case SoundChannel::BackCenter:
|
||||||
|
return MA_CHANNEL_BACK_CENTER;
|
||||||
|
case SoundChannel::SideLeft:
|
||||||
|
return MA_CHANNEL_SIDE_LEFT;
|
||||||
|
case SoundChannel::SideRight:
|
||||||
|
return MA_CHANNEL_SIDE_RIGHT;
|
||||||
|
case SoundChannel::TopCenter:
|
||||||
|
return MA_CHANNEL_TOP_CENTER;
|
||||||
|
case SoundChannel::TopFrontLeft:
|
||||||
|
return MA_CHANNEL_TOP_FRONT_LEFT;
|
||||||
|
case SoundChannel::TopFrontRight:
|
||||||
|
return MA_CHANNEL_TOP_FRONT_RIGHT;
|
||||||
|
case SoundChannel::TopFrontCenter:
|
||||||
|
return MA_CHANNEL_TOP_FRONT_CENTER;
|
||||||
|
case SoundChannel::TopBackLeft:
|
||||||
|
return MA_CHANNEL_TOP_BACK_LEFT;
|
||||||
|
case SoundChannel::TopBackRight:
|
||||||
|
return MA_CHANNEL_TOP_BACK_RIGHT;
|
||||||
|
default:
|
||||||
|
assert(soundChannel == SoundChannel::TopBackCenter);
|
||||||
|
return MA_CHANNEL_TOP_BACK_CENTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Time MiniaudioUtils::getPlayingOffset(ma_sound& sound)
|
||||||
|
{
|
||||||
|
float cursor = 0.f;
|
||||||
|
|
||||||
|
if (const ma_result result = ma_sound_get_cursor_in_seconds(&sound, &cursor); result != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
err() << "Failed to get sound cursor: " << ma_result_description(result) << std::endl;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return seconds(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
ma_uint64 MiniaudioUtils::getFrameIndex(ma_sound& sound, Time timeOffset)
|
||||||
|
{
|
||||||
|
ma_uint32 sampleRate{};
|
||||||
|
|
||||||
|
if (const ma_result result = ma_sound_get_data_format(&sound, nullptr, nullptr, &sampleRate, nullptr, 0);
|
||||||
|
result != MA_SUCCESS)
|
||||||
|
err() << "Failed to get sound data format: " << ma_result_description(result) << std::endl;
|
||||||
|
|
||||||
|
const auto frameIndex = static_cast<ma_uint64>(timeOffset.asSeconds() * static_cast<float>(sampleRate));
|
||||||
|
|
||||||
|
if (const ma_result result = ma_sound_seek_to_pcm_frame(&sound, frameIndex); result != MA_SUCCESS)
|
||||||
|
err() << "Failed to seek sound to pcm frame: " << ma_result_description(result) << std::endl;
|
||||||
|
|
||||||
|
return frameIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void MiniaudioUtils::reinitializeSound(ma_sound& sound, const std::function<void()>& initializeFn)
|
||||||
|
{
|
||||||
|
const SavedSettings savedSettings = saveSettings(sound);
|
||||||
|
ma_sound_uninit(&sound);
|
||||||
|
|
||||||
|
initializeFn();
|
||||||
|
|
||||||
|
applySettings(sound, savedSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void MiniaudioUtils::initializeSound(const ma_data_source_vtable& vtable,
|
||||||
|
ma_data_source_base& dataSourceBase,
|
||||||
|
ma_sound& sound,
|
||||||
|
const std::function<void()>& initializeFn)
|
||||||
|
{
|
||||||
|
initializeDataSource(dataSourceBase, vtable);
|
||||||
|
|
||||||
|
// Initialize sound structure and set default settings
|
||||||
|
initializeFn();
|
||||||
|
applySettings(sound, SavedSettings{});
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sf::priv
|
57
src/SFML/Audio/MiniaudioUtils.hpp
Normal file
57
src/SFML/Audio/MiniaudioUtils.hpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2024 Laurent Gomila (laurent@sfml-dev.org)
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Audio/SoundChannel.hpp>
|
||||||
|
|
||||||
|
#include <miniaudio.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Forward declarations
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
class Time;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace sf::priv::MiniaudioUtils
|
||||||
|
{
|
||||||
|
[[nodiscard]] ma_channel soundChannelToMiniaudioChannel(sf::SoundChannel soundChannel);
|
||||||
|
[[nodiscard]] Time getPlayingOffset(ma_sound& sound);
|
||||||
|
[[nodiscard]] ma_uint64 getFrameIndex(ma_sound& sound, Time timeOffset);
|
||||||
|
|
||||||
|
void reinitializeSound(ma_sound& sound, const std::function<void()>& initializeFn);
|
||||||
|
void initializeSound(const ma_data_source_vtable& vtable,
|
||||||
|
ma_data_source_base& dataSourceBase,
|
||||||
|
ma_sound& sound,
|
||||||
|
const std::function<void()>& initializeFn);
|
||||||
|
} // namespace sf::priv::MiniaudioUtils
|
@ -25,20 +25,15 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/ALCheck.hpp>
|
|
||||||
#include <SFML/Audio/Music.hpp>
|
#include <SFML/Audio/Music.hpp>
|
||||||
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <SFML/System/Time.hpp>
|
#include <SFML/System/Time.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <fstream>
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
@ -242,7 +237,7 @@ void Music::initialize()
|
|||||||
m_samples.resize(m_file.getSampleRate() * m_file.getChannelCount());
|
m_samples.resize(m_file.getSampleRate() * m_file.getChannelCount());
|
||||||
|
|
||||||
// Initialize the stream
|
// Initialize the stream
|
||||||
SoundStream::initialize(m_file.getChannelCount(), m_file.getSampleRate());
|
SoundStream::initialize(m_file.getChannelCount(), m_file.getSampleRate(), m_file.getChannelMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
@ -33,7 +33,10 @@
|
|||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool OutputSoundFile::openFromFile(const std::filesystem::path& filename, unsigned int sampleRate, unsigned int channelCount)
|
bool OutputSoundFile::openFromFile(const std::filesystem::path& filename,
|
||||||
|
unsigned int sampleRate,
|
||||||
|
unsigned int channelCount,
|
||||||
|
const std::vector<SoundChannel>& channelMap)
|
||||||
{
|
{
|
||||||
// If the file is already open, first close it
|
// If the file is already open, first close it
|
||||||
close();
|
close();
|
||||||
@ -44,7 +47,7 @@ bool OutputSoundFile::openFromFile(const std::filesystem::path& filename, unsign
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Pass the stream to the reader
|
// Pass the stream to the reader
|
||||||
if (!m_writer->open(filename, sampleRate, channelCount))
|
if (!m_writer->open(filename, sampleRate, channelCount, channelMap))
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
return false;
|
return false;
|
||||||
|
@ -25,29 +25,214 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/ALCheck.hpp>
|
#include <SFML/Audio/AudioDevice.hpp>
|
||||||
|
#include <SFML/Audio/MiniaudioUtils.hpp>
|
||||||
#include <SFML/Audio/Sound.hpp>
|
#include <SFML/Audio/Sound.hpp>
|
||||||
#include <SFML/Audio/SoundBuffer.hpp>
|
#include <SFML/Audio/SoundBuffer.hpp>
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#include <SFML/System/Err.hpp>
|
||||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
|
||||||
#endif
|
#include <miniaudio.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <ostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
struct Sound::Impl
|
||||||
Sound::Sound(const SoundBuffer& buffer) : m_buffer(&buffer)
|
|
||||||
{
|
{
|
||||||
m_buffer->attachSound(this);
|
Impl()
|
||||||
alCheck(alSourcei(m_source, AL_BUFFER, static_cast<ALint>(m_buffer->m_buffer)));
|
{
|
||||||
|
static constexpr ma_data_source_vtable vtable{read, seek, getFormat, getCursor, getLength, setLooping, 0};
|
||||||
|
priv::MiniaudioUtils::initializeSound(vtable, dataSourceBase, sound, [this] { initialize(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
~Impl()
|
||||||
|
{
|
||||||
|
ma_sound_uninit(&sound);
|
||||||
|
ma_data_source_uninit(&dataSourceBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize()
|
||||||
|
{
|
||||||
|
// Initialize the sound
|
||||||
|
auto* engine = priv::AudioDevice::getEngine();
|
||||||
|
|
||||||
|
if (engine == nullptr)
|
||||||
|
{
|
||||||
|
err() << "Failed to initialize sound: No engine available" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ma_sound_config soundConfig;
|
||||||
|
|
||||||
|
soundConfig = ma_sound_config_init();
|
||||||
|
soundConfig.pDataSource = this;
|
||||||
|
soundConfig.pEndCallbackUserData = this;
|
||||||
|
soundConfig.endCallback = [](void* userData, ma_sound* soundPtr)
|
||||||
|
{
|
||||||
|
auto& impl = *static_cast<Impl*>(userData);
|
||||||
|
impl.status = Stopped;
|
||||||
|
|
||||||
|
// Seek back to the start of the sound when it finishes playing
|
||||||
|
if (const ma_result result = ma_sound_seek_to_pcm_frame(soundPtr, 0); result != MA_SUCCESS)
|
||||||
|
err() << "Failed to seek sound to frame 0: " << ma_result_description(result) << std::endl;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (const ma_result result = ma_sound_init_ex(engine, &soundConfig, &sound); result != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
err() << "Failed to initialize sound: " << ma_result_description(result) << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because we are providing a custom data source, we have to provide the channel map ourselves
|
||||||
|
if (buffer && !buffer->getChannelMap().empty())
|
||||||
|
{
|
||||||
|
soundChannelMap.clear();
|
||||||
|
|
||||||
|
for (const SoundChannel channel : buffer->getChannelMap())
|
||||||
|
{
|
||||||
|
soundChannelMap.push_back(priv::MiniaudioUtils::soundChannelToMiniaudioChannel(channel));
|
||||||
|
}
|
||||||
|
|
||||||
|
sound.engineNode.spatializer.pChannelMapIn = soundChannelMap.data();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sound.engineNode.spatializer.pChannelMapIn = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reinitialize()
|
||||||
|
{
|
||||||
|
priv::MiniaudioUtils::reinitializeSound(sound, [this] { initialize(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
static ma_result read(ma_data_source* dataSource, void* framesOut, ma_uint64 frameCount, ma_uint64* framesRead)
|
||||||
|
{
|
||||||
|
auto& impl = *static_cast<Impl*>(dataSource);
|
||||||
|
const auto* buffer = impl.buffer;
|
||||||
|
|
||||||
|
if (buffer == nullptr)
|
||||||
|
return MA_NO_DATA_AVAILABLE;
|
||||||
|
|
||||||
|
// Determine how many frames we can read
|
||||||
|
*framesRead = std::min<ma_uint64>(frameCount, (buffer->getSampleCount() - impl.cursor) / buffer->getChannelCount());
|
||||||
|
|
||||||
|
// Copy the samples to the output
|
||||||
|
const auto sampleCount = *framesRead * buffer->getChannelCount();
|
||||||
|
|
||||||
|
std::memcpy(framesOut,
|
||||||
|
buffer->getSamples() + impl.cursor,
|
||||||
|
static_cast<std::size_t>(sampleCount) * sizeof(buffer->getSamples()[0]));
|
||||||
|
|
||||||
|
impl.cursor += static_cast<std::size_t>(sampleCount);
|
||||||
|
|
||||||
|
// If we are looping and at the end of the sound, set the cursor back to the start
|
||||||
|
if (impl.looping && (impl.cursor >= buffer->getSampleCount()))
|
||||||
|
impl.cursor = 0;
|
||||||
|
|
||||||
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ma_result seek(ma_data_source* dataSource, ma_uint64 frameIndex)
|
||||||
|
{
|
||||||
|
auto& impl = *static_cast<Impl*>(dataSource);
|
||||||
|
const auto* buffer = impl.buffer;
|
||||||
|
|
||||||
|
if (buffer == nullptr)
|
||||||
|
return MA_NO_DATA_AVAILABLE;
|
||||||
|
|
||||||
|
impl.cursor = static_cast<std::size_t>(frameIndex * buffer->getChannelCount());
|
||||||
|
|
||||||
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ma_result getFormat(ma_data_source* dataSource,
|
||||||
|
ma_format* format,
|
||||||
|
ma_uint32* channels,
|
||||||
|
ma_uint32* sampleRate,
|
||||||
|
ma_channel*,
|
||||||
|
size_t)
|
||||||
|
{
|
||||||
|
const auto& impl = *static_cast<const Impl*>(dataSource);
|
||||||
|
const auto* buffer = impl.buffer;
|
||||||
|
|
||||||
|
// If we don't have valid values yet, initialize with defaults so sound creation doesn't fail
|
||||||
|
*format = ma_format_s16;
|
||||||
|
*channels = buffer && buffer->getChannelCount() ? buffer->getChannelCount() : 1;
|
||||||
|
*sampleRate = buffer && buffer->getSampleRate() ? buffer->getSampleRate() : 44100;
|
||||||
|
|
||||||
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ma_result getCursor(ma_data_source* dataSource, ma_uint64* cursor)
|
||||||
|
{
|
||||||
|
const auto& impl = *static_cast<const Impl*>(dataSource);
|
||||||
|
const auto* buffer = impl.buffer;
|
||||||
|
|
||||||
|
if (buffer == nullptr)
|
||||||
|
return MA_NO_DATA_AVAILABLE;
|
||||||
|
|
||||||
|
*cursor = impl.cursor / buffer->getChannelCount();
|
||||||
|
|
||||||
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ma_result getLength(ma_data_source* dataSource, ma_uint64* length)
|
||||||
|
{
|
||||||
|
const auto& impl = *static_cast<const Impl*>(dataSource);
|
||||||
|
const auto* buffer = impl.buffer;
|
||||||
|
|
||||||
|
if (buffer == nullptr)
|
||||||
|
return MA_NO_DATA_AVAILABLE;
|
||||||
|
|
||||||
|
*length = buffer->getSampleCount() / buffer->getChannelCount();
|
||||||
|
|
||||||
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ma_result setLooping(ma_data_source* dataSource, ma_bool32 looping)
|
||||||
|
{
|
||||||
|
auto& impl = *static_cast<Impl*>(dataSource);
|
||||||
|
impl.looping = (looping == MA_TRUE);
|
||||||
|
|
||||||
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
ma_data_source_base dataSourceBase{}; //!< The struct that makes this object a miniaudio data source (must be first member)
|
||||||
|
std::vector<ma_channel> soundChannelMap; //!< The map of position in sample frame to sound channel (miniaudio channels)
|
||||||
|
ma_sound sound{}; //!< The sound
|
||||||
|
std::size_t cursor{}; //!< The current playing position
|
||||||
|
bool looping{}; //!< True if we are looping the sound
|
||||||
|
const SoundBuffer* buffer{}; //!< Sound buffer bound to the source
|
||||||
|
Status status{Stopped}; //!< The status
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Sound::Sound(const SoundBuffer& buffer) : m_impl(std::make_unique<Impl>())
|
||||||
|
{
|
||||||
|
setBuffer(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Sound::Sound(const Sound& copy) : SoundSource(copy), m_buffer(copy.m_buffer)
|
// NOLINTNEXTLINE(readability-redundant-member-init)
|
||||||
|
Sound::Sound(const Sound& copy) : SoundSource(copy), m_impl(std::make_unique<Impl>())
|
||||||
{
|
{
|
||||||
m_buffer->attachSound(this);
|
SoundSource::operator=(copy);
|
||||||
alCheck(alSourcei(m_source, AL_BUFFER, static_cast<ALint>(m_buffer->m_buffer)));
|
|
||||||
|
if (copy.m_impl->buffer)
|
||||||
|
setBuffer(*copy.m_impl->buffer);
|
||||||
setLoop(copy.getLoop());
|
setLoop(copy.getLoop());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,28 +241,55 @@ Sound::Sound(const Sound& copy) : SoundSource(copy), m_buffer(copy.m_buffer)
|
|||||||
Sound::~Sound()
|
Sound::~Sound()
|
||||||
{
|
{
|
||||||
stop();
|
stop();
|
||||||
m_buffer->detachSound(this);
|
if (m_impl->buffer)
|
||||||
|
m_impl->buffer->detachSound(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Sound::play()
|
void Sound::play()
|
||||||
{
|
{
|
||||||
alCheck(alSourcePlay(m_source));
|
if (m_impl->status == Playing)
|
||||||
|
setPlayingOffset(Time::Zero);
|
||||||
|
|
||||||
|
if (const ma_result result = ma_sound_start(&m_impl->sound); result != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
err() << "Failed to start playing sound: " << ma_result_description(result) << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_impl->status = Playing;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Sound::pause()
|
void Sound::pause()
|
||||||
{
|
{
|
||||||
alCheck(alSourcePause(m_source));
|
if (const ma_result result = ma_sound_stop(&m_impl->sound); result != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
err() << "Failed to stop playing sound: " << ma_result_description(result) << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_impl->status == Playing)
|
||||||
|
m_impl->status = Paused;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Sound::stop()
|
void Sound::stop()
|
||||||
{
|
{
|
||||||
alCheck(alSourceStop(m_source));
|
if (const ma_result result = ma_sound_stop(&m_impl->sound); result != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
err() << "Failed to stop playing sound: " << ma_result_description(result) << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setPlayingOffset(Time::Zero);
|
||||||
|
m_impl->status = Stopped;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -85,61 +297,72 @@ void Sound::stop()
|
|||||||
void Sound::setBuffer(const SoundBuffer& buffer)
|
void Sound::setBuffer(const SoundBuffer& buffer)
|
||||||
{
|
{
|
||||||
// First detach from the previous buffer
|
// First detach from the previous buffer
|
||||||
stop();
|
if (m_impl->buffer)
|
||||||
m_buffer->detachSound(this);
|
{
|
||||||
|
stop();
|
||||||
|
|
||||||
|
// Reset cursor
|
||||||
|
m_impl->cursor = 0;
|
||||||
|
m_impl->buffer->detachSound(this);
|
||||||
|
}
|
||||||
|
|
||||||
// Assign and use the new buffer
|
// Assign and use the new buffer
|
||||||
m_buffer = &buffer;
|
m_impl->buffer = &buffer;
|
||||||
m_buffer->attachSound(this);
|
m_impl->buffer->attachSound(this);
|
||||||
alCheck(alSourcei(m_source, AL_BUFFER, static_cast<ALint>(m_buffer->m_buffer)));
|
|
||||||
|
m_impl->reinitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Sound::setLoop(bool loop)
|
void Sound::setLoop(bool loop)
|
||||||
{
|
{
|
||||||
alCheck(alSourcei(m_source, AL_LOOPING, loop));
|
ma_sound_set_looping(&m_impl->sound, loop ? MA_TRUE : MA_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Sound::setPlayingOffset(Time timeOffset)
|
void Sound::setPlayingOffset(Time timeOffset)
|
||||||
{
|
{
|
||||||
alCheck(alSourcef(m_source, AL_SEC_OFFSET, timeOffset.asSeconds()));
|
if (m_impl->sound.pDataSource == nullptr || m_impl->sound.engineNode.pEngine == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto frameIndex = priv::MiniaudioUtils::getFrameIndex(m_impl->sound, timeOffset);
|
||||||
|
|
||||||
|
if (m_impl->buffer)
|
||||||
|
m_impl->cursor = static_cast<std::size_t>(frameIndex * m_impl->buffer->getChannelCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
const SoundBuffer& Sound::getBuffer() const
|
const SoundBuffer& Sound::getBuffer() const
|
||||||
{
|
{
|
||||||
return *m_buffer;
|
assert(m_impl && "Sound::getBuffer() Cannot access unset buffer");
|
||||||
|
return *m_impl->buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool Sound::getLoop() const
|
bool Sound::getLoop() const
|
||||||
{
|
{
|
||||||
ALint loop;
|
return ma_sound_is_looping(&m_impl->sound) == MA_TRUE;
|
||||||
alCheck(alGetSourcei(m_source, AL_LOOPING, &loop));
|
|
||||||
|
|
||||||
return loop != 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Time Sound::getPlayingOffset() const
|
Time Sound::getPlayingOffset() const
|
||||||
{
|
{
|
||||||
ALfloat secs = 0.f;
|
if (!m_impl->buffer || m_impl->buffer->getChannelCount() == 0 || m_impl->buffer->getSampleRate() == 0)
|
||||||
alCheck(alGetSourcef(m_source, AL_SEC_OFFSET, &secs));
|
return {};
|
||||||
|
|
||||||
return seconds(secs);
|
return priv::MiniaudioUtils::getPlayingOffset(m_impl->sound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Sound::Status Sound::getStatus() const
|
Sound::Status Sound::getStatus() const
|
||||||
{
|
{
|
||||||
return SoundSource::getStatus();
|
return m_impl->status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -147,8 +370,7 @@ Sound::Status Sound::getStatus() const
|
|||||||
Sound& Sound::operator=(const Sound& right)
|
Sound& Sound::operator=(const Sound& right)
|
||||||
{
|
{
|
||||||
// Here we don't use the copy-and-swap idiom, because it would mess up
|
// Here we don't use the copy-and-swap idiom, because it would mess up
|
||||||
// the list of sound instances contained in the buffers and unnecessarily
|
// the list of sound instances contained in the buffers
|
||||||
// destroy/create OpenAL sound sources
|
|
||||||
|
|
||||||
// Handle self-assignment here, as no copy-and-swap idiom is being used
|
// Handle self-assignment here, as no copy-and-swap idiom is being used
|
||||||
if (this == &right)
|
if (this == &right)
|
||||||
@ -157,8 +379,17 @@ Sound& Sound::operator=(const Sound& right)
|
|||||||
// Delegate to base class, which copies all the sound attributes
|
// Delegate to base class, which copies all the sound attributes
|
||||||
SoundSource::operator=(right);
|
SoundSource::operator=(right);
|
||||||
|
|
||||||
|
// Detach the sound instance from the previous buffer (if any)
|
||||||
|
if (m_impl->buffer)
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
m_impl->buffer->detachSound(this);
|
||||||
|
m_impl->buffer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Copy the remaining sound attributes
|
// Copy the remaining sound attributes
|
||||||
setBuffer(*right.m_buffer);
|
if (right.m_impl->buffer)
|
||||||
|
setBuffer(*right.m_impl->buffer);
|
||||||
setLoop(right.getLoop());
|
setLoop(right.getLoop());
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
@ -172,14 +403,18 @@ void Sound::detachBuffer()
|
|||||||
stop();
|
stop();
|
||||||
|
|
||||||
// Detach the buffer
|
// Detach the buffer
|
||||||
alCheck(alSourcei(m_source, AL_BUFFER, 0));
|
if (m_impl->buffer)
|
||||||
|
{
|
||||||
|
m_impl->buffer->detachSound(this);
|
||||||
|
m_impl->buffer = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Sound::reattachBuffer()
|
void* Sound::getSound() const
|
||||||
{
|
{
|
||||||
alCheck(alSourcei(m_source, AL_BUFFER, static_cast<ALint>(m_buffer->m_buffer)));
|
return &m_impl->sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -25,43 +25,29 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/ALCheck.hpp>
|
|
||||||
#include <SFML/Audio/AudioDevice.hpp>
|
|
||||||
#include <SFML/Audio/InputSoundFile.hpp>
|
#include <SFML/Audio/InputSoundFile.hpp>
|
||||||
#include <SFML/Audio/OutputSoundFile.hpp>
|
#include <SFML/Audio/OutputSoundFile.hpp>
|
||||||
#include <SFML/Audio/Sound.hpp>
|
#include <SFML/Audio/Sound.hpp>
|
||||||
#include <SFML/Audio/SoundBuffer.hpp>
|
#include <SFML/Audio/SoundBuffer.hpp>
|
||||||
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <SFML/System/Time.hpp>
|
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundBuffer::SoundBuffer()
|
SoundBuffer::SoundBuffer(const SoundBuffer& copy)
|
||||||
{
|
{
|
||||||
// Create the buffer
|
// don't copy the attached sounds
|
||||||
alCheck(alGenBuffers(1, &m_buffer));
|
m_samples = copy.m_samples;
|
||||||
}
|
m_duration = copy.m_duration;
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
SoundBuffer::SoundBuffer(const SoundBuffer& copy) : m_samples(copy.m_samples), m_duration(copy.m_duration)
|
|
||||||
// don't copy the attached sounds
|
|
||||||
{
|
|
||||||
// Create the buffer
|
|
||||||
alCheck(alGenBuffers(1, &m_buffer));
|
|
||||||
|
|
||||||
// Update the internal buffer with the new samples
|
// Update the internal buffer with the new samples
|
||||||
if (!update(copy.getChannelCount(), copy.getSampleRate()))
|
if (!update(copy.getChannelCount(), copy.getSampleRate(), copy.getChannelMap()))
|
||||||
err() << "Failed to update copy-constructed sound buffer" << std::endl;
|
err() << "Failed to update copy-constructed sound buffer" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,16 +55,15 @@ SoundBuffer::SoundBuffer(const SoundBuffer& copy) : m_samples(copy.m_samples), m
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundBuffer::~SoundBuffer()
|
SoundBuffer::~SoundBuffer()
|
||||||
{
|
{
|
||||||
// Make sure no sound is attached to this buffer
|
// To prevent the iterator from becoming invalid, move the entire buffer to another
|
||||||
if (!m_sounds.empty())
|
// container. Otherwise calling resetBuffer would result in detachSound being
|
||||||
{
|
// called which removes the sound from the internal list.
|
||||||
err() << "Failed to destruct sound buffer because it is used by " << m_sounds.size() << " sound(s)" << std::endl;
|
SoundList sounds;
|
||||||
std::terminate();
|
sounds.swap(m_sounds);
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy the buffer
|
// Detach the buffer from the sounds that use it
|
||||||
if (m_buffer)
|
for (Sound* soundPtr : sounds)
|
||||||
alCheck(alDeleteBuffers(1, &m_buffer));
|
soundPtr->detachBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -116,18 +101,19 @@ bool SoundBuffer::loadFromStream(InputStream& stream)
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool SoundBuffer::loadFromSamples(const std::int16_t* samples,
|
bool SoundBuffer::loadFromSamples(const std::int16_t* samples,
|
||||||
std::uint64_t sampleCount,
|
std::uint64_t sampleCount,
|
||||||
unsigned int channelCount,
|
unsigned int channelCount,
|
||||||
unsigned int sampleRate)
|
unsigned int sampleRate,
|
||||||
|
const std::vector<SoundChannel>& channelMap)
|
||||||
{
|
{
|
||||||
if (samples && sampleCount && channelCount && sampleRate)
|
if (samples && sampleCount && channelCount && sampleRate && !channelMap.empty())
|
||||||
{
|
{
|
||||||
// Copy the new audio samples
|
// Copy the new audio samples
|
||||||
m_samples.assign(samples, samples + sampleCount);
|
m_samples.assign(samples, samples + sampleCount);
|
||||||
|
|
||||||
// Update the internal buffer with the new samples
|
// Update the internal buffer with the new samples
|
||||||
return update(channelCount, sampleRate);
|
return update(channelCount, sampleRate, channelMap);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -148,7 +134,7 @@ bool SoundBuffer::saveToFile(const std::filesystem::path& filename) const
|
|||||||
{
|
{
|
||||||
// Create the sound file in write mode
|
// Create the sound file in write mode
|
||||||
OutputSoundFile file;
|
OutputSoundFile file;
|
||||||
if (file.openFromFile(filename, getSampleRate(), getChannelCount()))
|
if (file.openFromFile(filename, getSampleRate(), getChannelCount(), getChannelMap()))
|
||||||
{
|
{
|
||||||
// Write the samples to the opened file
|
// Write the samples to the opened file
|
||||||
file.write(m_samples.data(), m_samples.size());
|
file.write(m_samples.data(), m_samples.size());
|
||||||
@ -179,20 +165,21 @@ std::uint64_t SoundBuffer::getSampleCount() const
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int SoundBuffer::getSampleRate() const
|
unsigned int SoundBuffer::getSampleRate() const
|
||||||
{
|
{
|
||||||
ALint sampleRate;
|
return m_sampleRate;
|
||||||
alCheck(alGetBufferi(m_buffer, AL_FREQUENCY, &sampleRate));
|
|
||||||
|
|
||||||
return static_cast<unsigned int>(sampleRate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int SoundBuffer::getChannelCount() const
|
unsigned int SoundBuffer::getChannelCount() const
|
||||||
{
|
{
|
||||||
ALint channelCount;
|
return static_cast<unsigned int>(m_channelMap.size());
|
||||||
alCheck(alGetBufferi(m_buffer, AL_CHANNELS, &channelCount));
|
}
|
||||||
|
|
||||||
return static_cast<unsigned int>(channelCount);
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::vector<SoundChannel> SoundBuffer::getChannelMap() const
|
||||||
|
{
|
||||||
|
return m_channelMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -209,15 +196,10 @@ SoundBuffer& SoundBuffer::operator=(const SoundBuffer& right)
|
|||||||
SoundBuffer temp(right);
|
SoundBuffer temp(right);
|
||||||
|
|
||||||
std::swap(m_samples, temp.m_samples);
|
std::swap(m_samples, temp.m_samples);
|
||||||
std::swap(m_buffer, temp.m_buffer);
|
std::swap(m_sampleRate, temp.m_sampleRate);
|
||||||
|
std::swap(m_channelMap, temp.m_channelMap);
|
||||||
std::swap(m_duration, temp.m_duration);
|
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
|
||||||
// Reattach sounds that use this buffer so they get bound to the new OpenAL buffer
|
|
||||||
for (Sound* soundPtr : m_sounds)
|
|
||||||
{
|
|
||||||
soundPtr->stop();
|
|
||||||
soundPtr->reattachBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -227,16 +209,14 @@ SoundBuffer& SoundBuffer::operator=(const SoundBuffer& right)
|
|||||||
bool SoundBuffer::initialize(InputSoundFile& file)
|
bool SoundBuffer::initialize(InputSoundFile& file)
|
||||||
{
|
{
|
||||||
// Retrieve the sound parameters
|
// Retrieve the sound parameters
|
||||||
const std::uint64_t sampleCount = file.getSampleCount();
|
const std::uint64_t sampleCount = file.getSampleCount();
|
||||||
const unsigned int channelCount = file.getChannelCount();
|
|
||||||
const unsigned int sampleRate = file.getSampleRate();
|
|
||||||
|
|
||||||
// Read the samples from the provided file
|
// Read the samples from the provided file
|
||||||
m_samples.resize(static_cast<std::size_t>(sampleCount));
|
m_samples.resize(static_cast<std::size_t>(sampleCount));
|
||||||
if (file.read(m_samples.data(), sampleCount) == sampleCount)
|
if (file.read(m_samples.data(), sampleCount) == sampleCount)
|
||||||
{
|
{
|
||||||
// Update the internal buffer with the new samples
|
// Update the internal buffer with the new samples
|
||||||
return update(channelCount, sampleRate);
|
return update(file.getChannelCount(), file.getSampleRate(), file.getChannelMap());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -246,37 +226,29 @@ bool SoundBuffer::initialize(InputSoundFile& file)
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool SoundBuffer::update(unsigned int channelCount, unsigned int sampleRate)
|
bool SoundBuffer::update(unsigned int channelCount, unsigned int sampleRate, const std::vector<SoundChannel>& channelMap)
|
||||||
{
|
{
|
||||||
// Check parameters
|
// Check parameters
|
||||||
if (!channelCount || !sampleRate || m_samples.empty())
|
if (!channelCount || !sampleRate || (channelMap.size() != channelCount))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Find the good format according to the number of channels
|
m_sampleRate = sampleRate;
|
||||||
const ALenum format = priv::AudioDevice::getFormatFromChannelCount(channelCount);
|
m_channelMap = channelMap;
|
||||||
|
|
||||||
// Check if the format is valid
|
// First make a copy of the list of sounds so we can reattach later
|
||||||
if (format == 0)
|
const SoundList sounds(m_sounds);
|
||||||
{
|
|
||||||
err() << "Failed to load sound buffer (unsupported number of channels: " << channelCount << ")" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detach the buffer from the sounds that use it (to avoid OpenAL errors)
|
// Detach the buffer from the sounds that use it
|
||||||
for (Sound* soundPtr : m_sounds)
|
for (Sound* soundPtr : sounds)
|
||||||
soundPtr->detachBuffer();
|
soundPtr->detachBuffer();
|
||||||
|
|
||||||
// Fill the buffer
|
|
||||||
const auto size = static_cast<ALsizei>(m_samples.size() * sizeof(std::int16_t));
|
|
||||||
alCheck(alBufferData(m_buffer, format, m_samples.data(), size, static_cast<ALsizei>(sampleRate)));
|
|
||||||
|
|
||||||
// Compute the duration
|
// Compute the duration
|
||||||
m_duration = seconds(
|
m_duration = seconds(
|
||||||
static_cast<float>(m_samples.size()) / static_cast<float>(sampleRate) / static_cast<float>(channelCount));
|
static_cast<float>(m_samples.size()) / static_cast<float>(sampleRate) / static_cast<float>(channelCount));
|
||||||
|
|
||||||
// Now reattach the buffer to the sounds that use it
|
// Now reattach the buffer to the sounds that use it
|
||||||
for (Sound* soundPtr : m_sounds)
|
for (Sound* soundPtr : sounds)
|
||||||
soundPtr->reattachBuffer();
|
soundPtr->setBuffer(*this);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ void SoundBufferRecorder::onStop()
|
|||||||
if (m_samples.empty())
|
if (m_samples.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!m_buffer.loadFromSamples(m_samples.data(), m_samples.size(), getChannelCount(), getSampleRate()))
|
if (!m_buffer.loadFromSamples(m_samples.data(), m_samples.size(), getChannelCount(), getSampleRate(), getChannelMap()))
|
||||||
err() << "Failed to stop capturing audio data" << std::endl;
|
err() << "Failed to stop capturing audio data" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,6 +175,69 @@ void streamMetadata(const FLAC__StreamDecoder*, const FLAC__StreamMetadata* meta
|
|||||||
data->info.sampleCount = meta->data.stream_info.total_samples * meta->data.stream_info.channels;
|
data->info.sampleCount = meta->data.stream_info.total_samples * meta->data.stream_info.channels;
|
||||||
data->info.sampleRate = meta->data.stream_info.sample_rate;
|
data->info.sampleRate = meta->data.stream_info.sample_rate;
|
||||||
data->info.channelCount = meta->data.stream_info.channels;
|
data->info.channelCount = meta->data.stream_info.channels;
|
||||||
|
|
||||||
|
// For FLAC channel mapping refer to: https://xiph.org/flac/format.html#frame_header
|
||||||
|
switch (data->info.channelCount)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
sf::err() << "No channels in FLAC file" << std::endl;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
data->info.channelMap = {sf::SoundChannel::Mono};
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
data->info.channelMap = {sf::SoundChannel::FrontLeft, sf::SoundChannel::FrontRight};
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
data->info.channelMap = {sf::SoundChannel::FrontLeft,
|
||||||
|
sf::SoundChannel::FrontRight,
|
||||||
|
sf::SoundChannel::FrontCenter};
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
data->info.channelMap = {sf::SoundChannel::FrontLeft,
|
||||||
|
sf::SoundChannel::FrontRight,
|
||||||
|
sf::SoundChannel::BackLeft,
|
||||||
|
sf::SoundChannel::BackRight};
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
data->info.channelMap = {sf::SoundChannel::FrontLeft,
|
||||||
|
sf::SoundChannel::FrontRight,
|
||||||
|
sf::SoundChannel::FrontCenter,
|
||||||
|
sf::SoundChannel::BackLeft,
|
||||||
|
sf::SoundChannel::BackRight};
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
data->info.channelMap = {sf::SoundChannel::FrontLeft,
|
||||||
|
sf::SoundChannel::FrontRight,
|
||||||
|
sf::SoundChannel::FrontCenter,
|
||||||
|
sf::SoundChannel::LowFrequencyEffects,
|
||||||
|
sf::SoundChannel::BackLeft,
|
||||||
|
sf::SoundChannel::BackRight};
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
data->info.channelMap = {sf::SoundChannel::FrontLeft,
|
||||||
|
sf::SoundChannel::FrontRight,
|
||||||
|
sf::SoundChannel::FrontCenter,
|
||||||
|
sf::SoundChannel::LowFrequencyEffects,
|
||||||
|
sf::SoundChannel::BackCenter,
|
||||||
|
sf::SoundChannel::SideLeft,
|
||||||
|
sf::SoundChannel::SideRight};
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
data->info.channelMap = {sf::SoundChannel::FrontLeft,
|
||||||
|
sf::SoundChannel::FrontRight,
|
||||||
|
sf::SoundChannel::FrontCenter,
|
||||||
|
sf::SoundChannel::LowFrequencyEffects,
|
||||||
|
sf::SoundChannel::BackLeft,
|
||||||
|
sf::SoundChannel::BackRight,
|
||||||
|
sf::SoundChannel::SideLeft,
|
||||||
|
sf::SoundChannel::SideRight};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sf::err() << "FLAC files with more than 8 channels not supported" << std::endl;
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,10 +52,13 @@
|
|||||||
|
|
||||||
#include <SFML/Audio/SoundFileReaderMp3.hpp>
|
#include <SFML/Audio/SoundFileReaderMp3.hpp>
|
||||||
|
|
||||||
|
#include <SFML/System/Err.hpp>
|
||||||
#include <SFML/System/InputStream.hpp>
|
#include <SFML/System/InputStream.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
@ -135,6 +138,24 @@ std::optional<SoundFileReader::Info> SoundFileReaderMp3::open(InputStream& strea
|
|||||||
info.sampleRate = static_cast<unsigned int>(m_decoder.info.hz);
|
info.sampleRate = static_cast<unsigned int>(m_decoder.info.hz);
|
||||||
info.sampleCount = m_decoder.samples;
|
info.sampleCount = m_decoder.samples;
|
||||||
|
|
||||||
|
// MP3 only supports mono/stereo channels
|
||||||
|
switch (info.channelCount)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
sf::err() << "No channels in MP3 file" << std::endl;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
info.channelMap = {sf::SoundChannel::Mono};
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
info.channelMap = {sf::SoundChannel::SideLeft, sf::SoundChannel::SideRight};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sf::err() << "MP3 files with more than 2 channels not supported" << std::endl;
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
m_numSamples = info.sampleCount;
|
m_numSamples = info.sampleCount;
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,64 @@ std::optional<SoundFileReader::Info> SoundFileReaderOgg::open(InputStream& strea
|
|||||||
info.sampleRate = static_cast<unsigned int>(vorbisInfo->rate);
|
info.sampleRate = static_cast<unsigned int>(vorbisInfo->rate);
|
||||||
info.sampleCount = static_cast<std::size_t>(ov_pcm_total(&m_vorbis, -1) * vorbisInfo->channels);
|
info.sampleCount = static_cast<std::size_t>(ov_pcm_total(&m_vorbis, -1) * vorbisInfo->channels);
|
||||||
|
|
||||||
|
// For Vorbis channel mapping refer to: https://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810004.3.9
|
||||||
|
switch (info.channelCount)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
err() << "No channels in Vorbis file" << std::endl;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
info.channelMap = {SoundChannel::Mono};
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
info.channelMap = {SoundChannel::FrontLeft, SoundChannel::FrontRight};
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
info.channelMap = {SoundChannel::FrontLeft, SoundChannel::FrontCenter, SoundChannel::FrontRight};
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
info.channelMap = {SoundChannel::FrontLeft, SoundChannel::FrontRight, SoundChannel::BackLeft, SoundChannel::BackRight};
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
info.channelMap = {SoundChannel::FrontLeft,
|
||||||
|
SoundChannel::FrontCenter,
|
||||||
|
SoundChannel::FrontRight,
|
||||||
|
SoundChannel::BackLeft,
|
||||||
|
SoundChannel::BackRight};
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
info.channelMap = {SoundChannel::FrontLeft,
|
||||||
|
SoundChannel::FrontCenter,
|
||||||
|
SoundChannel::FrontRight,
|
||||||
|
SoundChannel::BackLeft,
|
||||||
|
SoundChannel::BackRight,
|
||||||
|
SoundChannel::LowFrequencyEffects};
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
info.channelMap = {SoundChannel::FrontLeft,
|
||||||
|
SoundChannel::FrontCenter,
|
||||||
|
SoundChannel::FrontRight,
|
||||||
|
SoundChannel::SideLeft,
|
||||||
|
SoundChannel::SideRight,
|
||||||
|
SoundChannel::BackCenter,
|
||||||
|
SoundChannel::LowFrequencyEffects};
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
info.channelMap = {SoundChannel::FrontLeft,
|
||||||
|
SoundChannel::FrontCenter,
|
||||||
|
SoundChannel::FrontRight,
|
||||||
|
SoundChannel::SideLeft,
|
||||||
|
SoundChannel::SideRight,
|
||||||
|
SoundChannel::BackLeft,
|
||||||
|
SoundChannel::BackRight,
|
||||||
|
SoundChannel::LowFrequencyEffects};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err() << "Vorbis files with more than 8 channels not supported" << std::endl;
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// We must keep the channel count for the seek function
|
// We must keep the channel count for the seek function
|
||||||
m_channelCount = info.channelCount;
|
m_channelCount = info.channelCount;
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ std::optional<SoundFileReader::Info> SoundFileReaderWav::open(InputStream& strea
|
|||||||
{
|
{
|
||||||
m_stream = &stream;
|
m_stream = &stream;
|
||||||
|
|
||||||
const auto info = parseHeader();
|
auto info = parseHeader();
|
||||||
if (!info)
|
if (!info)
|
||||||
err() << "Failed to open WAV sound file (invalid or unsupported file)" << std::endl;
|
err() << "Failed to open WAV sound file (invalid or unsupported file)" << std::endl;
|
||||||
|
|
||||||
@ -300,6 +300,63 @@ std::optional<SoundFileReader::Info> SoundFileReaderWav::parseHeader()
|
|||||||
if (!decode(*m_stream, channelMask))
|
if (!decode(*m_stream, channelMask))
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
|
// NOLINTBEGIN(readability-identifier-naming)
|
||||||
|
// For WAVE channel mapping refer to: https://learn.microsoft.com/en-us/previous-versions/windows/hardware/design/dn653308(v=vs.85)#default-channel-ordering
|
||||||
|
static constexpr auto SPEAKER_FRONT_LEFT = 0x1u;
|
||||||
|
static constexpr auto SPEAKER_FRONT_RIGHT = 0x2u;
|
||||||
|
static constexpr auto SPEAKER_FRONT_CENTER = 0x4u;
|
||||||
|
static constexpr auto SPEAKER_LOW_FREQUENCY = 0x8u;
|
||||||
|
static constexpr auto SPEAKER_BACK_LEFT = 0x10u;
|
||||||
|
static constexpr auto SPEAKER_BACK_RIGHT = 0x20u;
|
||||||
|
static constexpr auto SPEAKER_FRONT_LEFT_OF_CENTER = 0x40u;
|
||||||
|
static constexpr auto SPEAKER_FRONT_RIGHT_OF_CENTER = 0x80u;
|
||||||
|
static constexpr auto SPEAKER_BACK_CENTER = 0x100u;
|
||||||
|
static constexpr auto SPEAKER_SIDE_LEFT = 0x200u;
|
||||||
|
static constexpr auto SPEAKER_SIDE_RIGHT = 0x400u;
|
||||||
|
static constexpr auto SPEAKER_TOP_CENTER = 0x800u;
|
||||||
|
static constexpr auto SPEAKER_TOP_FRONT_LEFT = 0x1000u;
|
||||||
|
static constexpr auto SPEAKER_TOP_FRONT_CENTER = 0x2000u;
|
||||||
|
static constexpr auto SPEAKER_TOP_FRONT_RIGHT = 0x4000u;
|
||||||
|
static constexpr auto SPEAKER_TOP_BACK_LEFT = 0x8000u;
|
||||||
|
static constexpr auto SPEAKER_TOP_BACK_CENTER = 0x10000u;
|
||||||
|
static constexpr auto SPEAKER_TOP_BACK_RIGHT = 0x20000u;
|
||||||
|
// NOLINTEND(readability-identifier-naming)
|
||||||
|
|
||||||
|
info.channelMap.clear();
|
||||||
|
|
||||||
|
const auto checkChannel = [channelMask, &info](auto bit, auto soundChannel)
|
||||||
|
{
|
||||||
|
if ((channelMask & bit) != 0)
|
||||||
|
info.channelMap.push_back(soundChannel);
|
||||||
|
};
|
||||||
|
|
||||||
|
checkChannel(SPEAKER_FRONT_LEFT, SoundChannel::FrontLeft);
|
||||||
|
checkChannel(SPEAKER_FRONT_RIGHT, SoundChannel::FrontRight);
|
||||||
|
checkChannel(SPEAKER_FRONT_CENTER, SoundChannel::FrontCenter);
|
||||||
|
checkChannel(SPEAKER_LOW_FREQUENCY, SoundChannel::LowFrequencyEffects);
|
||||||
|
checkChannel(SPEAKER_BACK_LEFT, SoundChannel::BackLeft);
|
||||||
|
checkChannel(SPEAKER_BACK_RIGHT, SoundChannel::BackRight);
|
||||||
|
checkChannel(SPEAKER_FRONT_LEFT_OF_CENTER, SoundChannel::FrontLeftOfCenter);
|
||||||
|
checkChannel(SPEAKER_FRONT_RIGHT_OF_CENTER, SoundChannel::FrontRightOfCenter);
|
||||||
|
checkChannel(SPEAKER_BACK_CENTER, SoundChannel::BackCenter);
|
||||||
|
checkChannel(SPEAKER_SIDE_LEFT, SoundChannel::SideLeft);
|
||||||
|
checkChannel(SPEAKER_SIDE_RIGHT, SoundChannel::SideRight);
|
||||||
|
checkChannel(SPEAKER_TOP_CENTER, SoundChannel::TopCenter);
|
||||||
|
checkChannel(SPEAKER_TOP_FRONT_LEFT, SoundChannel::TopFrontLeft);
|
||||||
|
checkChannel(SPEAKER_TOP_FRONT_CENTER, SoundChannel::TopFrontCenter);
|
||||||
|
checkChannel(SPEAKER_TOP_FRONT_RIGHT, SoundChannel::TopFrontRight);
|
||||||
|
checkChannel(SPEAKER_TOP_BACK_LEFT, SoundChannel::TopBackLeft);
|
||||||
|
checkChannel(SPEAKER_TOP_BACK_CENTER, SoundChannel::TopBackCenter);
|
||||||
|
checkChannel(SPEAKER_TOP_BACK_RIGHT, SoundChannel::TopBackRight);
|
||||||
|
|
||||||
|
assert(info.channelCount == info.channelMap.size());
|
||||||
|
|
||||||
|
if (info.channelCount != info.channelMap.size())
|
||||||
|
{
|
||||||
|
err() << "WAV sound file channel count does not match number of set bits in channel mask" << std::endl;
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
// Subformat
|
// Subformat
|
||||||
char subformat[16];
|
char subformat[16];
|
||||||
if (static_cast<std::size_t>(m_stream->read(subformat, static_cast<std::int64_t>(sizeof(subformat)))) !=
|
if (static_cast<std::size_t>(m_stream->read(subformat, static_cast<std::int64_t>(sizeof(subformat)))) !=
|
||||||
@ -321,6 +378,34 @@ std::optional<SoundFileReader::Info> SoundFileReaderWav::parseHeader()
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If we don't have a waveFormatExtensible header, fill the channel map based on a best guess for mono/stereo
|
||||||
|
info.channelMap.clear();
|
||||||
|
|
||||||
|
if (info.channelCount == 0)
|
||||||
|
{
|
||||||
|
err() << "WAV sound file channel count 0" << std::endl;
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
else if (info.channelCount == 1)
|
||||||
|
{
|
||||||
|
info.channelMap.push_back(SoundChannel::Mono);
|
||||||
|
}
|
||||||
|
else if (info.channelCount == 2)
|
||||||
|
{
|
||||||
|
info.channelMap.push_back(SoundChannel::FrontLeft);
|
||||||
|
info.channelMap.push_back(SoundChannel::FrontRight);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info.channelMap.push_back(SoundChannel::FrontLeft);
|
||||||
|
info.channelMap.push_back(SoundChannel::FrontRight);
|
||||||
|
|
||||||
|
for (auto i = 2u; i < info.channelCount; ++i)
|
||||||
|
info.channelMap.push_back(SoundChannel::Unspecified);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Skip potential extra information
|
// Skip potential extra information
|
||||||
if (m_stream->seek(subChunkStart + subChunkSize) == -1)
|
if (m_stream->seek(subChunkStart + subChunkSize) == -1)
|
||||||
|
@ -52,8 +52,82 @@ bool SoundFileWriterFlac::check(const std::filesystem::path& filename)
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool SoundFileWriterFlac::open(const std::filesystem::path& filename, unsigned int sampleRate, unsigned int channelCount)
|
bool SoundFileWriterFlac::open(const std::filesystem::path& filename,
|
||||||
|
unsigned int sampleRate,
|
||||||
|
unsigned int channelCount,
|
||||||
|
const std::vector<SoundChannel>& channelMap)
|
||||||
{
|
{
|
||||||
|
std::vector<SoundChannel> targetChannelMap;
|
||||||
|
|
||||||
|
// For FLAC channel mapping refer to: https://xiph.org/flac/format.html#frame_header
|
||||||
|
switch (channelCount)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
err() << "No channels to write to FLAC file" << std::endl;
|
||||||
|
return false;
|
||||||
|
case 1:
|
||||||
|
targetChannelMap = {SoundChannel::Mono};
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
targetChannelMap = {SoundChannel::FrontLeft, SoundChannel::FrontRight};
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
targetChannelMap = {SoundChannel::FrontLeft, SoundChannel::FrontRight, SoundChannel::FrontCenter};
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
targetChannelMap = {SoundChannel::FrontLeft, SoundChannel::FrontRight, SoundChannel::BackLeft, SoundChannel::BackRight};
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
targetChannelMap = {SoundChannel::FrontLeft,
|
||||||
|
SoundChannel::FrontRight,
|
||||||
|
SoundChannel::FrontCenter,
|
||||||
|
SoundChannel::BackLeft,
|
||||||
|
SoundChannel::BackRight};
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
targetChannelMap = {SoundChannel::FrontLeft,
|
||||||
|
SoundChannel::FrontRight,
|
||||||
|
SoundChannel::FrontCenter,
|
||||||
|
SoundChannel::LowFrequencyEffects,
|
||||||
|
SoundChannel::BackLeft,
|
||||||
|
SoundChannel::BackRight};
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
targetChannelMap = {SoundChannel::FrontLeft,
|
||||||
|
SoundChannel::FrontRight,
|
||||||
|
SoundChannel::FrontCenter,
|
||||||
|
SoundChannel::LowFrequencyEffects,
|
||||||
|
SoundChannel::BackCenter,
|
||||||
|
SoundChannel::SideLeft,
|
||||||
|
SoundChannel::SideRight};
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
targetChannelMap = {SoundChannel::FrontLeft,
|
||||||
|
SoundChannel::FrontRight,
|
||||||
|
SoundChannel::FrontCenter,
|
||||||
|
SoundChannel::LowFrequencyEffects,
|
||||||
|
SoundChannel::BackLeft,
|
||||||
|
SoundChannel::BackRight,
|
||||||
|
SoundChannel::SideLeft,
|
||||||
|
SoundChannel::SideRight};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err() << "FLAC files with more than 8 channels not supported" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the channel map contains channels that we cannot remap to a mapping supported by FLAC
|
||||||
|
if (!std::is_permutation(channelMap.begin(), channelMap.end(), targetChannelMap.begin()))
|
||||||
|
{
|
||||||
|
err() << "Provided channel map cannot be reordered to a channel map supported by FLAC" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the remap rable
|
||||||
|
for (auto i = 0u; i < channelCount; ++i)
|
||||||
|
m_remapTable[i] = static_cast<std::size_t>(
|
||||||
|
std::find(channelMap.begin(), channelMap.end(), targetChannelMap[i]) - channelMap.begin());
|
||||||
|
|
||||||
// Create the encoder
|
// Create the encoder
|
||||||
m_encoder.reset(FLAC__stream_encoder_new());
|
m_encoder.reset(FLAC__stream_encoder_new());
|
||||||
if (!m_encoder)
|
if (!m_encoder)
|
||||||
@ -92,8 +166,15 @@ void SoundFileWriterFlac::write(const std::int16_t* samples, std::uint64_t count
|
|||||||
// Make sure that we don't process too many samples at once
|
// Make sure that we don't process too many samples at once
|
||||||
const unsigned int frames = std::min(static_cast<unsigned int>(count / m_channelCount), 10000u);
|
const unsigned int frames = std::min(static_cast<unsigned int>(count / m_channelCount), 10000u);
|
||||||
|
|
||||||
// Convert the samples to 32-bits
|
// Convert the samples to 32-bits and remap the channels
|
||||||
m_samples32.assign(samples, samples + frames * m_channelCount);
|
m_samples32.clear();
|
||||||
|
m_samples32.reserve(frames * m_channelCount);
|
||||||
|
|
||||||
|
for (auto frame = 0u; frame < frames; ++frame)
|
||||||
|
{
|
||||||
|
for (auto channel = 0u; channel < m_channelCount; ++channel)
|
||||||
|
m_samples32.push_back(samples[frame * m_channelCount + m_remapTable[channel]]);
|
||||||
|
}
|
||||||
|
|
||||||
// Write them to the FLAC stream
|
// Write them to the FLAC stream
|
||||||
FLAC__stream_encoder_process_interleaved(m_encoder.get(), m_samples32.data(), frames);
|
FLAC__stream_encoder_process_interleaved(m_encoder.get(), m_samples32.data(), frames);
|
||||||
|
@ -62,11 +62,15 @@ public:
|
|||||||
/// \param filename Path of the file to open
|
/// \param filename Path of the file to open
|
||||||
/// \param sampleRate Sample rate of the sound
|
/// \param sampleRate Sample rate of the sound
|
||||||
/// \param channelCount Number of channels of the sound
|
/// \param channelCount Number of channels of the sound
|
||||||
|
/// \param channelMap Map of position in sample frame to sound channel
|
||||||
///
|
///
|
||||||
/// \return True if the file was successfully opened
|
/// \return True if the file was successfully opened
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool open(const std::filesystem::path& filename, unsigned int sampleRate, unsigned int channelCount) override;
|
[[nodiscard]] bool open(const std::filesystem::path& filename,
|
||||||
|
unsigned int sampleRate,
|
||||||
|
unsigned int channelCount,
|
||||||
|
const std::vector<SoundChannel>& channelMap) override;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Write audio samples to the open file
|
/// \brief Write audio samples to the open file
|
||||||
@ -87,7 +91,8 @@ private:
|
|||||||
};
|
};
|
||||||
std::unique_ptr<FLAC__StreamEncoder, FlacStreamEncoderDeleter> m_encoder; //!< FLAC stream encoder
|
std::unique_ptr<FLAC__StreamEncoder, FlacStreamEncoderDeleter> m_encoder; //!< FLAC stream encoder
|
||||||
unsigned int m_channelCount{}; //!< Number of channels
|
unsigned int m_channelCount{}; //!< Number of channels
|
||||||
std::vector<std::int32_t> m_samples32; //!< Conversion buffer
|
std::size_t m_remapTable[8]{}; //!< Table we use to remap source to target channel order
|
||||||
|
std::vector<std::int32_t> m_samples32; //!< Conversion buffer
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sf::priv
|
} // namespace sf::priv
|
||||||
|
@ -54,8 +54,82 @@ SoundFileWriterOgg::~SoundFileWriterOgg()
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool SoundFileWriterOgg::open(const std::filesystem::path& filename, unsigned int sampleRate, unsigned int channelCount)
|
bool SoundFileWriterOgg::open(const std::filesystem::path& filename,
|
||||||
|
unsigned int sampleRate,
|
||||||
|
unsigned int channelCount,
|
||||||
|
const std::vector<SoundChannel>& channelMap)
|
||||||
{
|
{
|
||||||
|
std::vector<SoundChannel> targetChannelMap;
|
||||||
|
|
||||||
|
// For Vorbis channel mapping refer to: https://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810004.3.9
|
||||||
|
switch (channelCount)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
err() << "No channels to write to Vorbis file" << std::endl;
|
||||||
|
return false;
|
||||||
|
case 1:
|
||||||
|
targetChannelMap = {SoundChannel::Mono};
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
targetChannelMap = {SoundChannel::FrontLeft, SoundChannel::FrontRight};
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
targetChannelMap = {SoundChannel::FrontLeft, SoundChannel::FrontCenter, SoundChannel::FrontRight};
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
targetChannelMap = {SoundChannel::FrontLeft, SoundChannel::FrontRight, SoundChannel::BackLeft, SoundChannel::BackRight};
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
targetChannelMap = {SoundChannel::FrontLeft,
|
||||||
|
SoundChannel::FrontCenter,
|
||||||
|
SoundChannel::FrontRight,
|
||||||
|
SoundChannel::BackLeft,
|
||||||
|
SoundChannel::BackRight};
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
targetChannelMap = {SoundChannel::FrontLeft,
|
||||||
|
SoundChannel::FrontCenter,
|
||||||
|
SoundChannel::FrontRight,
|
||||||
|
SoundChannel::BackLeft,
|
||||||
|
SoundChannel::BackRight,
|
||||||
|
SoundChannel::LowFrequencyEffects};
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
targetChannelMap = {SoundChannel::FrontLeft,
|
||||||
|
SoundChannel::FrontCenter,
|
||||||
|
SoundChannel::FrontRight,
|
||||||
|
SoundChannel::SideLeft,
|
||||||
|
SoundChannel::SideRight,
|
||||||
|
SoundChannel::BackCenter,
|
||||||
|
SoundChannel::LowFrequencyEffects};
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
targetChannelMap = {SoundChannel::FrontLeft,
|
||||||
|
SoundChannel::FrontCenter,
|
||||||
|
SoundChannel::FrontRight,
|
||||||
|
SoundChannel::SideLeft,
|
||||||
|
SoundChannel::SideRight,
|
||||||
|
SoundChannel::BackLeft,
|
||||||
|
SoundChannel::BackRight,
|
||||||
|
SoundChannel::LowFrequencyEffects};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err() << "Vorbis files with more than 8 channels not supported" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the channel map contains channels that we cannot remap to a mapping supported by FLAC
|
||||||
|
if (!std::is_permutation(channelMap.begin(), channelMap.end(), targetChannelMap.begin()))
|
||||||
|
{
|
||||||
|
err() << "Provided channel map cannot be reordered to a channel map supported by Vorbis" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the remap table
|
||||||
|
for (auto i = 0u; i < channelCount; ++i)
|
||||||
|
m_remapTable[i] = static_cast<std::size_t>(
|
||||||
|
std::find(channelMap.begin(), channelMap.end(), targetChannelMap[i]) - channelMap.begin());
|
||||||
|
|
||||||
// Save the channel count
|
// Save the channel count
|
||||||
m_channelCount = channelCount;
|
m_channelCount = channelCount;
|
||||||
|
|
||||||
@ -135,10 +209,14 @@ void SoundFileWriterOgg::write(const std::int16_t* samples, std::uint64_t count)
|
|||||||
float** buffer = vorbis_analysis_buffer(&m_state, bufferSize);
|
float** buffer = vorbis_analysis_buffer(&m_state, bufferSize);
|
||||||
assert(buffer && "Vorbis buffer failed to allocate");
|
assert(buffer && "Vorbis buffer failed to allocate");
|
||||||
|
|
||||||
// Write the samples to the buffer, converted to float
|
// Write the samples to the buffer, converted to float and remapped to target channels
|
||||||
for (int i = 0; i < std::min(frameCount, bufferSize); ++i)
|
for (int i = 0; i < std::min(frameCount, bufferSize); ++i)
|
||||||
|
{
|
||||||
for (unsigned int j = 0; j < m_channelCount; ++j)
|
for (unsigned int j = 0; j < m_channelCount; ++j)
|
||||||
buffer[j][i] = *samples++ / 32767.0f;
|
buffer[j][i] = samples[m_remapTable[j]] / 32767.0f;
|
||||||
|
|
||||||
|
samples += m_channelCount;
|
||||||
|
}
|
||||||
|
|
||||||
// Tell the library how many samples we've written
|
// Tell the library how many samples we've written
|
||||||
vorbis_analysis_wrote(&m_state, std::min(frameCount, bufferSize));
|
vorbis_analysis_wrote(&m_state, std::min(frameCount, bufferSize));
|
||||||
|
@ -68,11 +68,15 @@ public:
|
|||||||
/// \param filename Path of the file to open
|
/// \param filename Path of the file to open
|
||||||
/// \param sampleRate Sample rate of the sound
|
/// \param sampleRate Sample rate of the sound
|
||||||
/// \param channelCount Number of channels of the sound
|
/// \param channelCount Number of channels of the sound
|
||||||
|
/// \param channelMap Map of position in sample frame to sound channel
|
||||||
///
|
///
|
||||||
/// \return True if the file was successfully opened
|
/// \return True if the file was successfully opened
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool open(const std::filesystem::path& filename, unsigned int sampleRate, unsigned int channelCount) override;
|
[[nodiscard]] bool open(const std::filesystem::path& filename,
|
||||||
|
unsigned int sampleRate,
|
||||||
|
unsigned int channelCount,
|
||||||
|
const std::vector<SoundChannel>& channelMap) override;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Write audio samples to the open file
|
/// \brief Write audio samples to the open file
|
||||||
@ -99,11 +103,12 @@ private:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int m_channelCount{}; // channel count of the sound being written
|
unsigned int m_channelCount{}; //!< Channel count of the sound being written
|
||||||
std::ofstream m_file; // output file
|
std::size_t m_remapTable[8]{}; //!< Table we use to remap source to target channel order
|
||||||
ogg_stream_state m_ogg{}; // ogg stream
|
std::ofstream m_file; //!< Output file
|
||||||
vorbis_info m_vorbis{}; // vorbis handle
|
ogg_stream_state m_ogg{}; //!< OGG stream
|
||||||
vorbis_dsp_state m_state{}; // current encoding state
|
vorbis_info m_vorbis{}; //!< Vorbis handle
|
||||||
|
vorbis_dsp_state m_state{}; //!< Current encoding state
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sf::priv
|
} // namespace sf::priv
|
||||||
|
@ -30,10 +30,12 @@
|
|||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <SFML/System/Utils.hpp>
|
#include <SFML/System/Utils.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -82,8 +84,128 @@ SoundFileWriterWav::~SoundFileWriterWav()
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool SoundFileWriterWav::open(const std::filesystem::path& filename, unsigned int sampleRate, unsigned int channelCount)
|
bool SoundFileWriterWav::open(const std::filesystem::path& filename,
|
||||||
|
unsigned int sampleRate,
|
||||||
|
unsigned int channelCount,
|
||||||
|
const std::vector<SoundChannel>& channelMap)
|
||||||
{
|
{
|
||||||
|
auto channelMask = 0u;
|
||||||
|
|
||||||
|
if (channelCount == 0)
|
||||||
|
{
|
||||||
|
err() << "WAV sound file channel count 0" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (channelCount == 1)
|
||||||
|
{
|
||||||
|
m_remapTable[0] = 0;
|
||||||
|
}
|
||||||
|
else if (channelCount == 2)
|
||||||
|
{
|
||||||
|
m_remapTable[0] = 0;
|
||||||
|
m_remapTable[1] = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// NOLINTBEGIN(readability-identifier-naming)
|
||||||
|
// For WAVE channel mapping refer to: https://learn.microsoft.com/en-us/previous-versions/windows/hardware/design/dn653308(v=vs.85)#default-channel-ordering
|
||||||
|
static constexpr auto SPEAKER_FRONT_LEFT = 0x1u;
|
||||||
|
static constexpr auto SPEAKER_FRONT_RIGHT = 0x2u;
|
||||||
|
static constexpr auto SPEAKER_FRONT_CENTER = 0x4u;
|
||||||
|
static constexpr auto SPEAKER_LOW_FREQUENCY = 0x8u;
|
||||||
|
static constexpr auto SPEAKER_BACK_LEFT = 0x10u;
|
||||||
|
static constexpr auto SPEAKER_BACK_RIGHT = 0x20u;
|
||||||
|
static constexpr auto SPEAKER_FRONT_LEFT_OF_CENTER = 0x40u;
|
||||||
|
static constexpr auto SPEAKER_FRONT_RIGHT_OF_CENTER = 0x80u;
|
||||||
|
static constexpr auto SPEAKER_BACK_CENTER = 0x100u;
|
||||||
|
static constexpr auto SPEAKER_SIDE_LEFT = 0x200u;
|
||||||
|
static constexpr auto SPEAKER_SIDE_RIGHT = 0x400u;
|
||||||
|
static constexpr auto SPEAKER_TOP_CENTER = 0x800u;
|
||||||
|
static constexpr auto SPEAKER_TOP_FRONT_LEFT = 0x1000u;
|
||||||
|
static constexpr auto SPEAKER_TOP_FRONT_CENTER = 0x2000u;
|
||||||
|
static constexpr auto SPEAKER_TOP_FRONT_RIGHT = 0x4000u;
|
||||||
|
static constexpr auto SPEAKER_TOP_BACK_LEFT = 0x8000u;
|
||||||
|
static constexpr auto SPEAKER_TOP_BACK_CENTER = 0x10000u;
|
||||||
|
static constexpr auto SPEAKER_TOP_BACK_RIGHT = 0x20000u;
|
||||||
|
// NOLINTEND(readability-identifier-naming)
|
||||||
|
|
||||||
|
struct SupportedChannel
|
||||||
|
{
|
||||||
|
std::uint32_t bit;
|
||||||
|
SoundChannel channel;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<SupportedChannel>
|
||||||
|
targetChannelMap{{SPEAKER_FRONT_LEFT, SoundChannel::FrontLeft},
|
||||||
|
{SPEAKER_FRONT_RIGHT, SoundChannel::FrontRight},
|
||||||
|
{SPEAKER_FRONT_CENTER, SoundChannel::FrontCenter},
|
||||||
|
{SPEAKER_LOW_FREQUENCY, SoundChannel::LowFrequencyEffects},
|
||||||
|
{SPEAKER_BACK_LEFT, SoundChannel::BackLeft},
|
||||||
|
{SPEAKER_BACK_RIGHT, SoundChannel::BackRight},
|
||||||
|
{SPEAKER_FRONT_LEFT_OF_CENTER, SoundChannel::FrontLeftOfCenter},
|
||||||
|
{SPEAKER_FRONT_RIGHT_OF_CENTER, SoundChannel::FrontRightOfCenter},
|
||||||
|
{SPEAKER_BACK_CENTER, SoundChannel::BackCenter},
|
||||||
|
{SPEAKER_SIDE_LEFT, SoundChannel::SideLeft},
|
||||||
|
{SPEAKER_SIDE_RIGHT, SoundChannel::SideRight},
|
||||||
|
{SPEAKER_TOP_CENTER, SoundChannel::TopCenter},
|
||||||
|
{SPEAKER_TOP_FRONT_LEFT, SoundChannel::TopFrontLeft},
|
||||||
|
{SPEAKER_TOP_FRONT_CENTER, SoundChannel::TopFrontCenter},
|
||||||
|
{SPEAKER_TOP_FRONT_RIGHT, SoundChannel::TopFrontRight},
|
||||||
|
{SPEAKER_TOP_BACK_LEFT, SoundChannel::TopBackLeft},
|
||||||
|
{SPEAKER_TOP_BACK_CENTER, SoundChannel::TopBackCenter},
|
||||||
|
{SPEAKER_TOP_BACK_RIGHT, SoundChannel::TopBackRight}};
|
||||||
|
|
||||||
|
// Check for duplicate channel entries
|
||||||
|
{
|
||||||
|
auto sortedChannelMap = channelMap;
|
||||||
|
std::sort(sortedChannelMap.begin(), sortedChannelMap.end());
|
||||||
|
|
||||||
|
if (std::adjacent_find(sortedChannelMap.begin(), sortedChannelMap.end()) != sortedChannelMap.end())
|
||||||
|
{
|
||||||
|
err() << "Duplicate channels in channel map" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the target channel map by removing unused channels
|
||||||
|
for (auto iter = targetChannelMap.begin(); iter != targetChannelMap.end();)
|
||||||
|
{
|
||||||
|
if (std::find(channelMap.begin(), channelMap.end(), iter->channel) == channelMap.end())
|
||||||
|
{
|
||||||
|
iter = targetChannelMap.erase(iter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that all the input channels exist in the target channel map
|
||||||
|
for (const SoundChannel channel : channelMap)
|
||||||
|
{
|
||||||
|
if (std::find_if(targetChannelMap.begin(),
|
||||||
|
targetChannelMap.end(),
|
||||||
|
[channel](const SupportedChannel& c) { return c.channel == channel; }) ==
|
||||||
|
targetChannelMap.end())
|
||||||
|
{
|
||||||
|
err() << "Could not map all input channels to a channel supported by WAV" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the remap table
|
||||||
|
for (auto i = 0u; i < channelCount; ++i)
|
||||||
|
m_remapTable[i] = static_cast<std::size_t>(
|
||||||
|
std::find(channelMap.begin(), channelMap.end(), targetChannelMap[i].channel) - channelMap.begin());
|
||||||
|
|
||||||
|
// Generate the channel mask
|
||||||
|
for (const auto& channel : targetChannelMap)
|
||||||
|
channelMask |= channel.bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the channel count
|
||||||
|
m_channelCount = channelCount;
|
||||||
|
|
||||||
// Open the file
|
// Open the file
|
||||||
m_file.open(filename, std::ios::binary);
|
m_file.open(filename, std::ios::binary);
|
||||||
if (!m_file)
|
if (!m_file)
|
||||||
@ -93,7 +215,7 @@ bool SoundFileWriterWav::open(const std::filesystem::path& filename, unsigned in
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write the header
|
// Write the header
|
||||||
writeHeader(sampleRate, channelCount);
|
writeHeader(sampleRate, channelCount, channelMask);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -103,14 +225,24 @@ bool SoundFileWriterWav::open(const std::filesystem::path& filename, unsigned in
|
|||||||
void SoundFileWriterWav::write(const std::int16_t* samples, std::uint64_t count)
|
void SoundFileWriterWav::write(const std::int16_t* samples, std::uint64_t count)
|
||||||
{
|
{
|
||||||
assert(m_file.good() && "Most recent I/O operation failed");
|
assert(m_file.good() && "Most recent I/O operation failed");
|
||||||
|
assert(count % m_channelCount == 0);
|
||||||
|
|
||||||
while (count--)
|
if (count % m_channelCount != 0)
|
||||||
encode(m_file, *samples++);
|
err() << "Writing samples to WAV sound file requires writing full frames at a time" << std::endl;
|
||||||
|
|
||||||
|
while (count >= m_channelCount)
|
||||||
|
{
|
||||||
|
for (auto i = 0u; i < m_channelCount; ++i)
|
||||||
|
encode(m_file, samples[m_remapTable[i]]);
|
||||||
|
|
||||||
|
samples += m_channelCount;
|
||||||
|
count -= m_channelCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundFileWriterWav::writeHeader(unsigned int sampleRate, unsigned int channelCount)
|
void SoundFileWriterWav::writeHeader(unsigned int sampleRate, unsigned int channelCount, unsigned int channelMask)
|
||||||
{
|
{
|
||||||
assert(m_file.good() && "Most recent I/O operation failed");
|
assert(m_file.good() && "Most recent I/O operation failed");
|
||||||
|
|
||||||
@ -126,12 +258,25 @@ void SoundFileWriterWav::writeHeader(unsigned int sampleRate, unsigned int chann
|
|||||||
// Write the sub-chunk 1 ("format") id and size
|
// Write the sub-chunk 1 ("format") id and size
|
||||||
char fmtChunkId[4] = {'f', 'm', 't', ' '};
|
char fmtChunkId[4] = {'f', 'm', 't', ' '};
|
||||||
m_file.write(fmtChunkId, sizeof(fmtChunkId));
|
m_file.write(fmtChunkId, sizeof(fmtChunkId));
|
||||||
const std::uint32_t fmtChunkSize = 16;
|
|
||||||
encode(m_file, fmtChunkSize);
|
|
||||||
|
|
||||||
// Write the format (PCM)
|
if (channelCount > 2)
|
||||||
const std::uint16_t format = 1;
|
{
|
||||||
encode(m_file, format);
|
const std::uint32_t fmtChunkSize = 40;
|
||||||
|
encode(m_file, fmtChunkSize);
|
||||||
|
|
||||||
|
// Write the format (Extensible)
|
||||||
|
const std::uint16_t format = 65534;
|
||||||
|
encode(m_file, format);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const std::uint32_t fmtChunkSize = 16;
|
||||||
|
encode(m_file, fmtChunkSize);
|
||||||
|
|
||||||
|
// Write the format (PCM)
|
||||||
|
const std::uint16_t format = 1;
|
||||||
|
encode(m_file, format);
|
||||||
|
}
|
||||||
|
|
||||||
// Write the sound attributes
|
// Write the sound attributes
|
||||||
encode(m_file, static_cast<std::uint16_t>(channelCount));
|
encode(m_file, static_cast<std::uint16_t>(channelCount));
|
||||||
@ -143,6 +288,18 @@ void SoundFileWriterWav::writeHeader(unsigned int sampleRate, unsigned int chann
|
|||||||
const std::uint16_t bitsPerSample = 16;
|
const std::uint16_t bitsPerSample = 16;
|
||||||
encode(m_file, bitsPerSample);
|
encode(m_file, bitsPerSample);
|
||||||
|
|
||||||
|
if (channelCount > 2)
|
||||||
|
{
|
||||||
|
const std::uint16_t extensionSize = 16;
|
||||||
|
encode(m_file, extensionSize);
|
||||||
|
encode(m_file, bitsPerSample);
|
||||||
|
encode(m_file, channelMask);
|
||||||
|
// Write the subformat (PCM)
|
||||||
|
char subformat[16] =
|
||||||
|
{'\x01', '\x00', '\x00', '\x00', '\x00', '\x00', '\x10', '\x00', '\x80', '\x00', '\x00', '\xAA', '\x00', '\x38', '\x9B', '\x71'};
|
||||||
|
m_file.write(subformat, sizeof(subformat));
|
||||||
|
}
|
||||||
|
|
||||||
// Write the sub-chunk 2 ("data") id and size
|
// Write the sub-chunk 2 ("data") id and size
|
||||||
char dataChunkId[4] = {'d', 'a', 't', 'a'};
|
char dataChunkId[4] = {'d', 'a', 't', 'a'};
|
||||||
m_file.write(dataChunkId, sizeof(dataChunkId));
|
m_file.write(dataChunkId, sizeof(dataChunkId));
|
||||||
|
@ -66,11 +66,15 @@ public:
|
|||||||
/// \param filename Path of the file to open
|
/// \param filename Path of the file to open
|
||||||
/// \param sampleRate Sample rate of the sound
|
/// \param sampleRate Sample rate of the sound
|
||||||
/// \param channelCount Number of channels of the sound
|
/// \param channelCount Number of channels of the sound
|
||||||
|
/// \param channelMap Map of position in sample frame to sound channel
|
||||||
///
|
///
|
||||||
/// \return True if the file was successfully opened
|
/// \return True if the file was successfully opened
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] bool open(const std::filesystem::path& filename, unsigned int sampleRate, unsigned int channelCount) override;
|
[[nodiscard]] bool open(const std::filesystem::path& filename,
|
||||||
|
unsigned int sampleRate,
|
||||||
|
unsigned int channelCount,
|
||||||
|
const std::vector<SoundChannel>& channelMap) override;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Write audio samples to the open file
|
/// \brief Write audio samples to the open file
|
||||||
@ -87,9 +91,10 @@ private:
|
|||||||
///
|
///
|
||||||
/// \param sampleRate Sample rate of the sound
|
/// \param sampleRate Sample rate of the sound
|
||||||
/// \param channelCount Number of channels of the sound
|
/// \param channelCount Number of channels of the sound
|
||||||
|
/// \param channelMask Channel mask bits if we are writing extensible header
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void writeHeader(unsigned int sampleRate, unsigned int channelCount);
|
void writeHeader(unsigned int sampleRate, unsigned int channelCount, unsigned int channelMask);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Close the file
|
/// \brief Close the file
|
||||||
@ -100,7 +105,9 @@ private:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
std::ofstream m_file; //!< File stream to write to
|
std::ofstream m_file; //!< File stream to write to
|
||||||
|
unsigned int m_channelCount{}; //!< Channel count of the sound being written
|
||||||
|
std::size_t m_remapTable[18]{}; //!< Table we use to remap source to target channel order
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sf::priv
|
} // namespace sf::priv
|
||||||
|
@ -25,44 +25,206 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/ALCheck.hpp>
|
|
||||||
#include <SFML/Audio/AudioDevice.hpp>
|
|
||||||
#include <SFML/Audio/SoundRecorder.hpp>
|
#include <SFML/Audio/SoundRecorder.hpp>
|
||||||
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <SFML/System/Sleep.hpp>
|
#include <SFML/System/Sleep.hpp>
|
||||||
|
|
||||||
|
#include <miniaudio.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <optional>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(disable : 4355) // 'this' used in base member initializer list
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
ALCdevice* captureDevice = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
|
struct SoundRecorder::Impl
|
||||||
|
{
|
||||||
|
Impl(SoundRecorder* ownerPtr) : owner(ownerPtr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool initialize()
|
||||||
|
{
|
||||||
|
if (!context)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Find the device by its name
|
||||||
|
auto devices = getAvailableDevices();
|
||||||
|
|
||||||
|
auto iter = std::find_if(devices.begin(),
|
||||||
|
devices.end(),
|
||||||
|
[this](const ma_device_info& info) { return info.name == deviceName; });
|
||||||
|
|
||||||
|
if (iter == devices.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// (Re-)create the capture device
|
||||||
|
if (captureDevice)
|
||||||
|
{
|
||||||
|
ma_device_uninit(&*captureDevice);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
captureDevice.emplace();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto captureDeviceConfig = ma_device_config_init(ma_device_type_capture);
|
||||||
|
captureDeviceConfig.capture.pDeviceID = &iter->id;
|
||||||
|
captureDeviceConfig.capture.channels = channelCount;
|
||||||
|
captureDeviceConfig.capture.format = ma_format_s16;
|
||||||
|
captureDeviceConfig.sampleRate = sampleRate;
|
||||||
|
captureDeviceConfig.pUserData = this;
|
||||||
|
captureDeviceConfig.dataCallback = [](ma_device* device, void*, const void* input, ma_uint32 frameCount)
|
||||||
|
{
|
||||||
|
auto& impl = *static_cast<Impl*>(device->pUserData);
|
||||||
|
|
||||||
|
// Copy the new samples into our temporary buffer
|
||||||
|
impl.samples.resize(frameCount * impl.channelCount);
|
||||||
|
std::memcpy(impl.samples.data(), input, frameCount * impl.channelCount * sizeof(std::int16_t));
|
||||||
|
|
||||||
|
// Notify the derived class of the availability of new samples
|
||||||
|
if (!impl.owner->onProcessSamples(impl.samples.data(), impl.samples.size()))
|
||||||
|
{
|
||||||
|
// If the derived class wants to stop, stop the capture
|
||||||
|
if (auto result = ma_device_stop(device); result != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
err() << "Failed to stop audio capture device: " << ma_result_description(result) << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (auto result = ma_device_init(&*context, &captureDeviceConfig, &*captureDevice); result != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
captureDevice.reset();
|
||||||
|
err() << "Failed to initialize the audio capture device: " << ma_result_description(result) << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<ma_device_info> getAvailableDevices()
|
||||||
|
{
|
||||||
|
std::vector<ma_device_info> deviceList;
|
||||||
|
|
||||||
|
// Create the context
|
||||||
|
ma_context context;
|
||||||
|
|
||||||
|
auto contextConfig = ma_context_config_init();
|
||||||
|
|
||||||
|
if (auto result = ma_context_init(nullptr, 0, &contextConfig, &context); result != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
err() << "Failed to initialize the audio context: " << ma_result_description(result) << std::endl;
|
||||||
|
return deviceList;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enumerate the capture devices
|
||||||
|
ma_device_info* deviceInfos;
|
||||||
|
ma_uint32 deviceCount;
|
||||||
|
|
||||||
|
if (auto result = ma_context_get_devices(&context, nullptr, nullptr, &deviceInfos, &deviceCount);
|
||||||
|
result != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
err() << "Failed to get audio capture devices: " << ma_result_description(result) << std::endl;
|
||||||
|
ma_context_uninit(&context);
|
||||||
|
return deviceList;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i = 0u; i < deviceCount; ++i)
|
||||||
|
deviceList.push_back(deviceInfos[i]);
|
||||||
|
|
||||||
|
ma_context_uninit(&context);
|
||||||
|
return deviceList;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SoundRecorder* const owner; //!< Owning SoundRecorder object
|
||||||
|
std::optional<ma_log> log; //!< The miniaudio log
|
||||||
|
std::optional<ma_context> context; //!< The miniaudio context
|
||||||
|
std::optional<ma_device> captureDevice; //!< The miniaudio capture device
|
||||||
|
std::string deviceName{getDefaultDevice()}; //!< Name of the audio capture device
|
||||||
|
unsigned int channelCount{1}; //!< Number of recording channels
|
||||||
|
unsigned int sampleRate{44100}; //!< Sample rate
|
||||||
|
std::vector<std::int16_t> samples; //!< Buffer to store captured samples
|
||||||
|
std::vector<SoundChannel> channelMap{SoundChannel::Mono}; //!< The map of position in sample frame to sound channel
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SoundRecorder::SoundRecorder() : m_impl(std::make_unique<Impl>(this))
|
||||||
|
{
|
||||||
|
// Create the log
|
||||||
|
m_impl->log.emplace();
|
||||||
|
|
||||||
|
if (auto result = ma_log_init(nullptr, &*m_impl->log); result != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
m_impl->log.reset();
|
||||||
|
err() << "Failed to initialize the audio log: " << ma_result_description(result) << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register our logging callback to output any warning/error messages
|
||||||
|
if (auto result = ma_log_register_callback(&*m_impl->log,
|
||||||
|
ma_log_callback_init(
|
||||||
|
[](void*, ma_uint32 level, const char* message)
|
||||||
|
{
|
||||||
|
if (level <= MA_LOG_LEVEL_WARNING)
|
||||||
|
err() << "miniaudio " << ma_log_level_to_string(level)
|
||||||
|
<< ": " << message << std::flush;
|
||||||
|
},
|
||||||
|
nullptr));
|
||||||
|
result != MA_SUCCESS)
|
||||||
|
err() << "Failed to register audio log callback: " << ma_result_description(result) << std::endl;
|
||||||
|
|
||||||
|
// Create the context
|
||||||
|
m_impl->context.emplace();
|
||||||
|
|
||||||
|
auto contextConfig = ma_context_config_init();
|
||||||
|
contextConfig.pLog = &*m_impl->log;
|
||||||
|
|
||||||
|
if (auto result = ma_context_init(nullptr, 0, &contextConfig, &*m_impl->context); result != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
m_impl->context.reset();
|
||||||
|
err() << "Failed to initialize the audio context: " << ma_result_description(result) << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the capture device
|
||||||
|
m_impl->initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundRecorder::~SoundRecorder()
|
SoundRecorder::~SoundRecorder()
|
||||||
{
|
{
|
||||||
// This assertion is triggered if the recording is still running while
|
// This assertion is triggered if the recording is still running while
|
||||||
// the object is destroyed. It ensures that stop() is called in the
|
// the object is destroyed. It ensures that stop() is called in the
|
||||||
// destructor of the derived class, which makes sure that the recording
|
// destructor of the derived class, which makes sure that the capture
|
||||||
// thread finishes before the derived object is destroyed. Otherwise a
|
// device is stopped before the derived object is destroyed. Otherwise a
|
||||||
// "pure virtual method called" exception is triggered.
|
// "pure virtual method called" exception is triggered.
|
||||||
assert(!m_isCapturing &&
|
assert(!(m_impl->captureDevice && ma_device_is_started(&*m_impl->captureDevice)) &&
|
||||||
"You must call stop() in the destructor of your derived class, so that the recording thread finishes before "
|
"You must call stop() in the destructor of your derived class, so that the "
|
||||||
"your object is destroyed.");
|
"capture device is stopped before your object is destroyed.");
|
||||||
|
|
||||||
|
// Destroy the capture device
|
||||||
|
if (m_impl->captureDevice)
|
||||||
|
ma_device_uninit(&*m_impl->captureDevice);
|
||||||
|
|
||||||
|
// Destroy the context
|
||||||
|
if (m_impl->context)
|
||||||
|
ma_context_uninit(&*m_impl->context);
|
||||||
|
|
||||||
|
// Destroy the log
|
||||||
|
if (m_impl->log)
|
||||||
|
ma_log_uninit(&*m_impl->log);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -78,38 +240,41 @@ bool SoundRecorder::start(unsigned int sampleRate)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store the sample rate and re-initialize if necessary
|
||||||
|
if (m_impl->sampleRate != sampleRate)
|
||||||
|
{
|
||||||
|
m_impl->sampleRate = sampleRate;
|
||||||
|
|
||||||
|
if (!m_impl->initialize())
|
||||||
|
{
|
||||||
|
err() << "Failed to set audio capture device sample rate to " << sampleRate << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure we have a capture device
|
||||||
|
if (!m_impl->captureDevice)
|
||||||
|
{
|
||||||
|
err() << "Trying to start audio capture, but no device available" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check that another capture is not already running
|
// Check that another capture is not already running
|
||||||
if (captureDevice)
|
if (ma_device_is_started(&*m_impl->captureDevice))
|
||||||
{
|
{
|
||||||
err() << "Trying to start audio capture, but another capture is already running" << std::endl;
|
err() << "Trying to start audio capture, but another capture is already running" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the recording format
|
|
||||||
const ALCenum format = (m_channelCount == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
|
|
||||||
|
|
||||||
// Open the capture device for capturing 16 bits samples
|
|
||||||
captureDevice = alcCaptureOpenDevice(m_deviceName.c_str(), sampleRate, format, static_cast<ALCsizei>(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
|
// Notify derived class
|
||||||
if (onStart())
|
if (onStart())
|
||||||
{
|
{
|
||||||
// Start the capture
|
// Start the capture
|
||||||
alcCaptureStart(captureDevice);
|
if (auto result = ma_device_start(&*m_impl->captureDevice); result != MA_SUCCESS)
|
||||||
|
{
|
||||||
// Start the capture in a new thread, to avoid blocking the main thread
|
err() << "Failed to start audio capture device: " << ma_result_description(result) << std::endl;
|
||||||
launchCapturingThread();
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -121,10 +286,15 @@ bool SoundRecorder::start(unsigned int sampleRate)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundRecorder::stop()
|
void SoundRecorder::stop()
|
||||||
{
|
{
|
||||||
// Stop the capturing thread if there is one
|
// Stop the capturing device if one is started
|
||||||
if (m_isCapturing)
|
if (m_impl->captureDevice && ma_device_is_started(&*m_impl->captureDevice))
|
||||||
{
|
{
|
||||||
awaitCapturingThread();
|
// Stop the capture
|
||||||
|
if (auto result = ma_device_stop(&*m_impl->captureDevice); result != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
err() << "Failed to stop audio capture device: " << ma_result_description(result) << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Notify derived class
|
// Notify derived class
|
||||||
onStop();
|
onStop();
|
||||||
@ -135,24 +305,20 @@ void SoundRecorder::stop()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int SoundRecorder::getSampleRate() const
|
unsigned int SoundRecorder::getSampleRate() const
|
||||||
{
|
{
|
||||||
return m_sampleRate;
|
return m_impl->sampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
std::vector<std::string> SoundRecorder::getAvailableDevices()
|
std::vector<std::string> SoundRecorder::getAvailableDevices()
|
||||||
{
|
{
|
||||||
|
// Convert the internal miniaudio device list into a name-only list
|
||||||
|
const auto devices = Impl::getAvailableDevices();
|
||||||
std::vector<std::string> deviceNameList;
|
std::vector<std::string> deviceNameList;
|
||||||
|
deviceNameList.reserve(devices.size());
|
||||||
|
|
||||||
const ALchar* deviceList = alcGetString(nullptr, ALC_CAPTURE_DEVICE_SPECIFIER);
|
for (const auto& device : devices)
|
||||||
if (deviceList)
|
deviceNameList.emplace_back(device.name);
|
||||||
{
|
|
||||||
while (*deviceList)
|
|
||||||
{
|
|
||||||
deviceNameList.emplace_back(deviceList);
|
|
||||||
deviceList += std::strlen(deviceList) + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return deviceNameList;
|
return deviceNameList;
|
||||||
}
|
}
|
||||||
@ -161,43 +327,28 @@ std::vector<std::string> SoundRecorder::getAvailableDevices()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
std::string SoundRecorder::getDefaultDevice()
|
std::string SoundRecorder::getDefaultDevice()
|
||||||
{
|
{
|
||||||
return alcGetString(nullptr, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
|
const auto devices = Impl::getAvailableDevices();
|
||||||
|
|
||||||
|
for (const auto& device : devices)
|
||||||
|
{
|
||||||
|
if (device.isDefault)
|
||||||
|
return device.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool SoundRecorder::setDevice(const std::string& name)
|
bool SoundRecorder::setDevice(const std::string& name)
|
||||||
{
|
{
|
||||||
// Store the device name
|
// Store the device name and re-initialize if necessary
|
||||||
if (name.empty())
|
if (m_impl->deviceName != name)
|
||||||
m_deviceName = getDefaultDevice();
|
|
||||||
else
|
|
||||||
m_deviceName = name;
|
|
||||||
|
|
||||||
if (m_isCapturing)
|
|
||||||
{
|
{
|
||||||
// Stop the capturing thread
|
m_impl->deviceName = name;
|
||||||
awaitCapturingThread();
|
|
||||||
|
|
||||||
// Determine the recording format
|
if (!m_impl->initialize())
|
||||||
const ALCenum format = (m_channelCount == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
|
|
||||||
|
|
||||||
// Open the requested capture device for capturing 16 bits samples
|
|
||||||
captureDevice = alcCaptureOpenDevice(m_deviceName.c_str(), m_sampleRate, format, static_cast<ALCsizei>(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;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// Start the capture
|
|
||||||
alcCaptureStart(captureDevice);
|
|
||||||
|
|
||||||
// Start the capture in a new thread, to avoid blocking the main thread
|
|
||||||
launchCapturingThread();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -207,19 +358,14 @@ bool SoundRecorder::setDevice(const std::string& name)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
const std::string& SoundRecorder::getDevice() const
|
const std::string& SoundRecorder::getDevice() const
|
||||||
{
|
{
|
||||||
return m_deviceName;
|
return m_impl->deviceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundRecorder::setChannelCount(unsigned int channelCount)
|
void SoundRecorder::setChannelCount(unsigned int channelCount)
|
||||||
{
|
{
|
||||||
if (m_isCapturing)
|
// We only bother supporting mono/stereo recording for now
|
||||||
{
|
|
||||||
err() << "It's not possible to change the channels while recording." << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channelCount < 1 || channelCount > 2)
|
if (channelCount < 1 || channelCount > 2)
|
||||||
{
|
{
|
||||||
err() << "Unsupported channel count: " << channelCount
|
err() << "Unsupported channel count: " << channelCount
|
||||||
@ -227,29 +373,52 @@ void SoundRecorder::setChannelCount(unsigned int channelCount)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_channelCount = channelCount;
|
// Store the channel count and re-initialize if necessary
|
||||||
|
if (m_impl->channelCount != channelCount)
|
||||||
|
{
|
||||||
|
m_impl->channelCount = channelCount;
|
||||||
|
m_impl->initialize();
|
||||||
|
|
||||||
|
// We only bother supporting mono/stereo recording for now
|
||||||
|
if (channelCount == 1)
|
||||||
|
{
|
||||||
|
m_impl->channelMap = {SoundChannel::Mono};
|
||||||
|
}
|
||||||
|
else if (channelCount == 2)
|
||||||
|
{
|
||||||
|
m_impl->channelMap = {SoundChannel::FrontLeft, SoundChannel::FrontRight};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int SoundRecorder::getChannelCount() const
|
unsigned int SoundRecorder::getChannelCount() const
|
||||||
{
|
{
|
||||||
return m_channelCount;
|
return m_impl->channelCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
const std::vector<SoundChannel>& SoundRecorder::getChannelMap() const
|
||||||
|
{
|
||||||
|
return m_impl->channelMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool SoundRecorder::isAvailable()
|
bool SoundRecorder::isAvailable()
|
||||||
{
|
{
|
||||||
return (priv::AudioDevice::isExtensionSupported("ALC_EXT_CAPTURE") != AL_FALSE) ||
|
// Try to open a device for capture to see if recording is available
|
||||||
(priv::AudioDevice::isExtensionSupported("ALC_EXT_capture") != AL_FALSE); // "bug" in macOS 10.5 and 10.6
|
auto config = ma_device_config_init(ma_device_type_capture);
|
||||||
}
|
ma_device device;
|
||||||
|
|
||||||
|
if (ma_device_init(nullptr, &config, &device) != MA_SUCCESS)
|
||||||
|
return false;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
ma_device_uninit(&device);
|
||||||
void SoundRecorder::setProcessingInterval(Time interval)
|
|
||||||
{
|
return true;
|
||||||
m_processingInterval = interval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -267,79 +436,4 @@ void SoundRecorder::onStop()
|
|||||||
// Nothing to do
|
// 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(static_cast<std::size_t>(samplesAvailable) * getChannelCount());
|
|
||||||
alcCaptureSamples(captureDevice, m_samples.data(), samplesAvailable);
|
|
||||||
|
|
||||||
// Forward them to the derived class
|
|
||||||
if (!onProcessSamples(m_samples.data(), 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 = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void SoundRecorder::launchCapturingThread()
|
|
||||||
{
|
|
||||||
m_isCapturing = true;
|
|
||||||
|
|
||||||
assert(!m_thread.joinable() && "Capture thread is already running");
|
|
||||||
m_thread = std::thread(&SoundRecorder::record, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void SoundRecorder::awaitCapturingThread()
|
|
||||||
{
|
|
||||||
m_isCapturing = false;
|
|
||||||
|
|
||||||
if (m_thread.joinable())
|
|
||||||
m_thread.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -25,186 +25,346 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/ALCheck.hpp>
|
|
||||||
#include <SFML/Audio/SoundSource.hpp>
|
#include <SFML/Audio/SoundSource.hpp>
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#include <miniaudio.h>
|
||||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
|
||||||
#endif
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
// NOLINTBEGIN(readability-make-member-function-const)
|
// NOLINTBEGIN(readability-make-member-function-const)
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
SoundSource::SoundSource()
|
|
||||||
{
|
|
||||||
alCheck(alGenSources(1, &m_source));
|
|
||||||
alCheck(alSourcei(m_source, AL_BUFFER, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
SoundSource::SoundSource(const SoundSource& copy)
|
|
||||||
{
|
|
||||||
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)
|
void SoundSource::setPitch(float pitch)
|
||||||
{
|
{
|
||||||
alCheck(alSourcef(m_source, AL_PITCH, pitch));
|
if (auto* sound = static_cast<ma_sound*>(getSound()))
|
||||||
|
ma_sound_set_pitch(sound, pitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SoundSource::setPan(float pan)
|
||||||
|
{
|
||||||
|
if (auto* sound = static_cast<ma_sound*>(getSound()))
|
||||||
|
ma_sound_set_pan(sound, pan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundSource::setVolume(float volume)
|
void SoundSource::setVolume(float volume)
|
||||||
{
|
{
|
||||||
alCheck(alSourcef(m_source, AL_GAIN, volume * 0.01f));
|
if (auto* sound = static_cast<ma_sound*>(getSound()))
|
||||||
|
ma_sound_set_volume(sound, volume * 0.01f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SoundSource::setSpatializationEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
if (auto* sound = static_cast<ma_sound*>(getSound()))
|
||||||
|
ma_sound_set_spatialization_enabled(sound, enabled ? MA_TRUE : MA_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundSource::setPosition(const Vector3f& position)
|
void SoundSource::setPosition(const Vector3f& position)
|
||||||
{
|
{
|
||||||
alCheck(alSource3f(m_source, AL_POSITION, position.x, position.y, position.z));
|
if (auto* sound = static_cast<ma_sound*>(getSound()))
|
||||||
|
ma_sound_set_position(sound, position.x, position.y, position.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SoundSource::setDirection(const Vector3f& direction)
|
||||||
|
{
|
||||||
|
if (auto* sound = static_cast<ma_sound*>(getSound()))
|
||||||
|
ma_sound_set_direction(sound, direction.x, direction.y, direction.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SoundSource::setCone(const Cone& cone)
|
||||||
|
{
|
||||||
|
if (auto* sound = static_cast<ma_sound*>(getSound()))
|
||||||
|
ma_sound_set_cone(sound,
|
||||||
|
std::clamp(cone.innerAngle, sf::degrees(0), sf::degrees(360)).asRadians(),
|
||||||
|
std::clamp(cone.outerAngle, sf::degrees(0), sf::degrees(360)).asRadians(),
|
||||||
|
cone.outerGain);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SoundSource::setVelocity(const Vector3f& velocity)
|
||||||
|
{
|
||||||
|
if (auto* sound = static_cast<ma_sound*>(getSound()))
|
||||||
|
ma_sound_set_velocity(sound, velocity.x, velocity.y, velocity.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SoundSource::setDopplerFactor(float factor)
|
||||||
|
{
|
||||||
|
if (auto* sound = static_cast<ma_sound*>(getSound()))
|
||||||
|
ma_sound_set_doppler_factor(sound, factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SoundSource::setDirectionalAttenuationFactor(float factor)
|
||||||
|
{
|
||||||
|
if (auto* sound = static_cast<ma_sound*>(getSound()))
|
||||||
|
ma_sound_set_directional_attenuation_factor(sound, factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundSource::setRelativeToListener(bool relative)
|
void SoundSource::setRelativeToListener(bool relative)
|
||||||
{
|
{
|
||||||
alCheck(alSourcei(m_source, AL_SOURCE_RELATIVE, relative));
|
if (auto* sound = static_cast<ma_sound*>(getSound()))
|
||||||
|
ma_sound_set_positioning(sound, relative ? ma_positioning_relative : ma_positioning_absolute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundSource::setMinDistance(float distance)
|
void SoundSource::setMinDistance(float distance)
|
||||||
{
|
{
|
||||||
alCheck(alSourcef(m_source, AL_REFERENCE_DISTANCE, distance));
|
if (auto* sound = static_cast<ma_sound*>(getSound()))
|
||||||
|
ma_sound_set_min_distance(sound, distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SoundSource::setMaxDistance(float distance)
|
||||||
|
{
|
||||||
|
if (auto* sound = static_cast<ma_sound*>(getSound()))
|
||||||
|
ma_sound_set_max_distance(sound, distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SoundSource::setMinGain(float gain)
|
||||||
|
{
|
||||||
|
if (auto* sound = static_cast<ma_sound*>(getSound()))
|
||||||
|
ma_sound_set_min_gain(sound, gain);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SoundSource::setMaxGain(float gain)
|
||||||
|
{
|
||||||
|
if (auto* sound = static_cast<ma_sound*>(getSound()))
|
||||||
|
ma_sound_set_max_gain(sound, gain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundSource::setAttenuation(float attenuation)
|
void SoundSource::setAttenuation(float attenuation)
|
||||||
{
|
{
|
||||||
alCheck(alSourcef(m_source, AL_ROLLOFF_FACTOR, attenuation));
|
if (auto* sound = static_cast<ma_sound*>(getSound()))
|
||||||
|
ma_sound_set_rolloff(sound, attenuation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
float SoundSource::getPitch() const
|
float SoundSource::getPitch() const
|
||||||
{
|
{
|
||||||
ALfloat pitch;
|
if (const auto* sound = static_cast<const ma_sound*>(getSound()))
|
||||||
alCheck(alGetSourcef(m_source, AL_PITCH, &pitch));
|
return ma_sound_get_pitch(sound);
|
||||||
|
|
||||||
return pitch;
|
return 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
float SoundSource::getPan() const
|
||||||
|
{
|
||||||
|
if (const auto* sound = static_cast<const ma_sound*>(getSound()))
|
||||||
|
return ma_sound_get_pan(sound);
|
||||||
|
|
||||||
|
return 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
float SoundSource::getVolume() const
|
float SoundSource::getVolume() const
|
||||||
{
|
{
|
||||||
ALfloat gain;
|
if (const auto* sound = static_cast<const ma_sound*>(getSound()))
|
||||||
alCheck(alGetSourcef(m_source, AL_GAIN, &gain));
|
return ma_sound_get_volume(sound) * 100.f;
|
||||||
|
|
||||||
return gain * 100.f;
|
return 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool SoundSource::isSpatializationEnabled() const
|
||||||
|
{
|
||||||
|
if (const auto* sound = static_cast<const ma_sound*>(getSound()))
|
||||||
|
return ma_sound_is_spatialization_enabled(sound) == MA_TRUE;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Vector3f SoundSource::getPosition() const
|
Vector3f SoundSource::getPosition() const
|
||||||
{
|
{
|
||||||
Vector3f position;
|
if (const auto* sound = static_cast<const ma_sound*>(getSound()))
|
||||||
alCheck(alGetSource3f(m_source, AL_POSITION, &position.x, &position.y, &position.z));
|
{
|
||||||
|
auto position = ma_sound_get_position(sound);
|
||||||
|
return {position.x, position.y, position.z};
|
||||||
|
}
|
||||||
|
|
||||||
return position;
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Vector3f SoundSource::getDirection() const
|
||||||
|
{
|
||||||
|
if (const auto* sound = static_cast<const ma_sound*>(getSound()))
|
||||||
|
{
|
||||||
|
auto direction = ma_sound_get_direction(sound);
|
||||||
|
return {direction.x, direction.y, direction.z};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SoundSource::Cone SoundSource::getCone() const
|
||||||
|
{
|
||||||
|
if (const auto* sound = static_cast<const ma_sound*>(getSound()))
|
||||||
|
{
|
||||||
|
float innerAngle = 0.f;
|
||||||
|
float outerAngle = 0.f;
|
||||||
|
Cone cone;
|
||||||
|
ma_sound_get_cone(sound, &innerAngle, &outerAngle, &cone.outerGain);
|
||||||
|
cone.innerAngle = sf::radians(innerAngle);
|
||||||
|
cone.outerAngle = sf::radians(outerAngle);
|
||||||
|
return cone;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Cone{sf::radians(0), sf::radians(0), 0.f};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Vector3f SoundSource::getVelocity() const
|
||||||
|
{
|
||||||
|
if (const auto* sound = static_cast<const ma_sound*>(getSound()))
|
||||||
|
{
|
||||||
|
auto velocity = ma_sound_get_velocity(sound);
|
||||||
|
return {velocity.x, velocity.y, velocity.z};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
float SoundSource::getDopplerFactor() const
|
||||||
|
{
|
||||||
|
if (const auto* sound = static_cast<const ma_sound*>(getSound()))
|
||||||
|
return ma_sound_get_doppler_factor(sound);
|
||||||
|
|
||||||
|
return 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
float SoundSource::getDirectionalAttenuationFactor() const
|
||||||
|
{
|
||||||
|
if (const auto* sound = static_cast<const ma_sound*>(getSound()))
|
||||||
|
return ma_sound_get_directional_attenuation_factor(sound);
|
||||||
|
|
||||||
|
return 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool SoundSource::isRelativeToListener() const
|
bool SoundSource::isRelativeToListener() const
|
||||||
{
|
{
|
||||||
ALint relative;
|
if (const auto* sound = static_cast<const ma_sound*>(getSound()))
|
||||||
alCheck(alGetSourcei(m_source, AL_SOURCE_RELATIVE, &relative));
|
return ma_sound_get_positioning(sound) == ma_positioning_relative;
|
||||||
|
|
||||||
return relative != 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
float SoundSource::getMinDistance() const
|
float SoundSource::getMinDistance() const
|
||||||
{
|
{
|
||||||
ALfloat distance;
|
if (const auto* sound = static_cast<const ma_sound*>(getSound()))
|
||||||
alCheck(alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &distance));
|
return ma_sound_get_min_distance(sound);
|
||||||
|
|
||||||
return distance;
|
return 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
float SoundSource::getMaxDistance() const
|
||||||
|
{
|
||||||
|
if (const auto* sound = static_cast<const ma_sound*>(getSound()))
|
||||||
|
return ma_sound_get_max_distance(sound);
|
||||||
|
|
||||||
|
return 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
float SoundSource::getMinGain() const
|
||||||
|
{
|
||||||
|
if (const auto* sound = static_cast<const ma_sound*>(getSound()))
|
||||||
|
return ma_sound_get_min_gain(sound);
|
||||||
|
|
||||||
|
return 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
float SoundSource::getMaxGain() const
|
||||||
|
{
|
||||||
|
if (const auto* sound = static_cast<const ma_sound*>(getSound()))
|
||||||
|
return ma_sound_get_max_gain(sound);
|
||||||
|
|
||||||
|
return 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
float SoundSource::getAttenuation() const
|
float SoundSource::getAttenuation() const
|
||||||
{
|
{
|
||||||
ALfloat attenuation;
|
if (const auto* sound = static_cast<const ma_sound*>(getSound()))
|
||||||
alCheck(alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &attenuation));
|
return ma_sound_get_rolloff(sound);
|
||||||
|
|
||||||
return attenuation;
|
return 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundSource& SoundSource::operator=(const SoundSource& right)
|
SoundSource& SoundSource::operator=(const SoundSource& right)
|
||||||
{
|
{
|
||||||
// Leave m_source untouched -- it's not necessary to destroy and
|
|
||||||
// recreate the OpenAL sound source, hence no copy-and-swap idiom
|
|
||||||
|
|
||||||
// Assign the sound attributes
|
// Assign the sound attributes
|
||||||
setPitch(right.getPitch());
|
setPitch(right.getPitch());
|
||||||
|
setPan(right.getPan());
|
||||||
setVolume(right.getVolume());
|
setVolume(right.getVolume());
|
||||||
|
setSpatializationEnabled(right.isSpatializationEnabled());
|
||||||
setPosition(right.getPosition());
|
setPosition(right.getPosition());
|
||||||
|
setDirection(right.getDirection());
|
||||||
|
setCone(right.getCone());
|
||||||
|
setVelocity(right.getVelocity());
|
||||||
|
setDopplerFactor(right.getDopplerFactor());
|
||||||
setRelativeToListener(right.isRelativeToListener());
|
setRelativeToListener(right.isRelativeToListener());
|
||||||
setMinDistance(right.getMinDistance());
|
setMinDistance(right.getMinDistance());
|
||||||
|
setMaxDistance(right.getMaxDistance());
|
||||||
|
setMinGain(right.getMinGain());
|
||||||
|
setMaxGain(right.getMaxGain());
|
||||||
setAttenuation(right.getAttenuation());
|
setAttenuation(right.getAttenuation());
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
// NOLINTEND(readability-make-member-function-const)
|
// NOLINTEND(readability-make-member-function-const)
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -25,222 +25,373 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/ALCheck.hpp>
|
|
||||||
#include <SFML/Audio/AudioDevice.hpp>
|
#include <SFML/Audio/AudioDevice.hpp>
|
||||||
|
#include <SFML/Audio/MiniaudioUtils.hpp>
|
||||||
#include <SFML/Audio/SoundStream.hpp>
|
#include <SFML/Audio/SoundStream.hpp>
|
||||||
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <SFML/System/Sleep.hpp>
|
#include <SFML/System/Sleep.hpp>
|
||||||
|
|
||||||
#include <mutex>
|
#include <miniaudio.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(disable : 4355) // 'this' used in base member initializer list
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
struct SoundStream::Impl
|
||||||
SoundStream::~SoundStream()
|
|
||||||
{
|
{
|
||||||
// Stop the sound if it was playing
|
Impl(SoundStream* ownerPtr) : owner(ownerPtr)
|
||||||
|
{
|
||||||
|
static constexpr ma_data_source_vtable vtable{read, seek, getFormat, getCursor, getLength, setLooping, /* flags */ 0};
|
||||||
|
priv::MiniaudioUtils::initializeSound(vtable, dataSourceBase, sound, [this] { initialize(); });
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for the thread to join
|
~Impl()
|
||||||
awaitStreamingThread();
|
{
|
||||||
|
ma_sound_uninit(&sound);
|
||||||
|
ma_data_source_uninit(&dataSourceBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize()
|
||||||
|
{
|
||||||
|
// Initialize the sound
|
||||||
|
auto* engine = priv::AudioDevice::getEngine();
|
||||||
|
|
||||||
|
if (engine == nullptr)
|
||||||
|
{
|
||||||
|
err() << "Failed to initialize sound: No engine available" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ma_sound_config soundConfig;
|
||||||
|
|
||||||
|
soundConfig = ma_sound_config_init();
|
||||||
|
soundConfig.pDataSource = this;
|
||||||
|
soundConfig.pEndCallbackUserData = this;
|
||||||
|
soundConfig.endCallback = [](void* userData, ma_sound* soundPtr)
|
||||||
|
{
|
||||||
|
// Seek back to the start of the sound when it finishes playing
|
||||||
|
auto& impl = *static_cast<Impl*>(userData);
|
||||||
|
impl.streaming = true;
|
||||||
|
impl.status = Stopped;
|
||||||
|
|
||||||
|
if (const ma_result result = ma_sound_seek_to_pcm_frame(soundPtr, 0); result != MA_SUCCESS)
|
||||||
|
err() << "Failed to seek sound to frame 0: " << ma_result_description(result) << std::endl;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (const ma_result result = ma_sound_init_ex(engine, &soundConfig, &sound); result != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
err() << "Failed to initialize sound: " << ma_result_description(result) << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because we are providing a custom data source, we have to provide the channel map ourselves
|
||||||
|
if (!channelMap.empty())
|
||||||
|
{
|
||||||
|
soundChannelMap.clear();
|
||||||
|
|
||||||
|
for (const SoundChannel channel : channelMap)
|
||||||
|
{
|
||||||
|
soundChannelMap.push_back(priv::MiniaudioUtils::soundChannelToMiniaudioChannel(channel));
|
||||||
|
}
|
||||||
|
|
||||||
|
sound.engineNode.spatializer.pChannelMapIn = soundChannelMap.data();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sound.engineNode.spatializer.pChannelMapIn = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reinitialize()
|
||||||
|
{
|
||||||
|
priv::MiniaudioUtils::reinitializeSound(sound, [this] { initialize(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
static ma_result read(ma_data_source* dataSource, void* framesOut, ma_uint64 frameCount, ma_uint64* framesRead)
|
||||||
|
{
|
||||||
|
auto& impl = *static_cast<Impl*>(dataSource);
|
||||||
|
auto* owner = impl.owner;
|
||||||
|
|
||||||
|
// Try to fill our buffer with new samples if the source is still willing to stream data
|
||||||
|
if (impl.sampleBuffer.empty() && impl.streaming)
|
||||||
|
{
|
||||||
|
Chunk chunk;
|
||||||
|
|
||||||
|
impl.streaming = owner->onGetData(chunk);
|
||||||
|
|
||||||
|
if (chunk.samples && chunk.sampleCount)
|
||||||
|
{
|
||||||
|
impl.sampleBuffer.assign(chunk.samples, chunk.samples + chunk.sampleCount);
|
||||||
|
impl.sampleBufferCursor = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push the samples to miniaudio
|
||||||
|
if (!impl.sampleBuffer.empty())
|
||||||
|
{
|
||||||
|
// Determine how many frames we can read
|
||||||
|
*framesRead = std::min<ma_uint64>(frameCount,
|
||||||
|
(impl.sampleBuffer.size() - impl.sampleBufferCursor) / impl.channelCount);
|
||||||
|
|
||||||
|
const auto sampleCount = *framesRead * impl.channelCount;
|
||||||
|
|
||||||
|
// Copy the samples to the output
|
||||||
|
std::memcpy(framesOut,
|
||||||
|
impl.sampleBuffer.data() + impl.sampleBufferCursor,
|
||||||
|
static_cast<std::size_t>(sampleCount) * sizeof(impl.sampleBuffer[0]));
|
||||||
|
|
||||||
|
impl.sampleBufferCursor += static_cast<std::size_t>(sampleCount);
|
||||||
|
impl.samplesProcessed += sampleCount;
|
||||||
|
|
||||||
|
if (impl.sampleBufferCursor >= impl.sampleBuffer.size())
|
||||||
|
{
|
||||||
|
impl.sampleBuffer.clear();
|
||||||
|
impl.sampleBufferCursor = 0;
|
||||||
|
|
||||||
|
// If we are looping and at the end of the loop, set the cursor back to the beginning of the loop
|
||||||
|
if (!impl.streaming && impl.loop)
|
||||||
|
{
|
||||||
|
if (auto seekPositionAfterLoop = owner->onLoop(); seekPositionAfterLoop != NoLoop)
|
||||||
|
{
|
||||||
|
impl.streaming = true;
|
||||||
|
impl.samplesProcessed = static_cast<std::uint64_t>(seekPositionAfterLoop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*framesRead = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ma_result seek(ma_data_source* dataSource, ma_uint64 frameIndex)
|
||||||
|
{
|
||||||
|
auto& impl = *static_cast<Impl*>(dataSource);
|
||||||
|
auto* owner = impl.owner;
|
||||||
|
|
||||||
|
impl.streaming = true;
|
||||||
|
impl.sampleBuffer.clear();
|
||||||
|
impl.sampleBufferCursor = 0;
|
||||||
|
impl.samplesProcessed = frameIndex * impl.channelCount;
|
||||||
|
|
||||||
|
if (impl.sampleRate != 0)
|
||||||
|
{
|
||||||
|
owner->onSeek(seconds(static_cast<float>(frameIndex / impl.sampleRate)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
owner->onSeek(Time::Zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ma_result getFormat(ma_data_source* dataSource,
|
||||||
|
ma_format* format,
|
||||||
|
ma_uint32* channels,
|
||||||
|
ma_uint32* sampleRate,
|
||||||
|
ma_channel*,
|
||||||
|
size_t)
|
||||||
|
{
|
||||||
|
const auto& impl = *static_cast<const Impl*>(dataSource);
|
||||||
|
|
||||||
|
// If we don't have valid values yet, initialize with defaults so sound creation doesn't fail
|
||||||
|
*format = ma_format_s16;
|
||||||
|
*channels = impl.channelCount ? impl.channelCount : 1;
|
||||||
|
*sampleRate = impl.sampleRate ? impl.sampleRate : 44100;
|
||||||
|
|
||||||
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ma_result getCursor(ma_data_source* dataSource, ma_uint64* cursor)
|
||||||
|
{
|
||||||
|
auto& impl = *static_cast<Impl*>(dataSource);
|
||||||
|
*cursor = impl.channelCount ? impl.samplesProcessed / impl.channelCount : 0;
|
||||||
|
|
||||||
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ma_result getLength(ma_data_source*, ma_uint64* length)
|
||||||
|
{
|
||||||
|
*length = 0;
|
||||||
|
|
||||||
|
return MA_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ma_result setLooping(ma_data_source* dataSource, ma_bool32 looping)
|
||||||
|
{
|
||||||
|
static_cast<Impl*>(dataSource)->loop = (looping == MA_TRUE);
|
||||||
|
|
||||||
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
ma_data_source_base dataSourceBase{}; //!< The struct that makes this object a miniaudio data source (must be first member)
|
||||||
|
SoundStream* const owner; //!< Owning SoundStream object
|
||||||
|
std::vector<ma_channel> soundChannelMap; //!< The map of position in sample frame to sound channel (miniaudio channels)
|
||||||
|
ma_sound sound{}; //!< The sound
|
||||||
|
std::vector<std::int16_t> sampleBuffer; //!< Our temporary sample buffer
|
||||||
|
std::size_t sampleBufferCursor{}; //!< The current read position in the temporary sample buffer
|
||||||
|
std::uint64_t samplesProcessed{}; //!< Number of samples processed since beginning of the stream
|
||||||
|
unsigned int channelCount{}; //!< Number of channels (1 = mono, 2 = stereo, ...)
|
||||||
|
unsigned int sampleRate{}; //!< Frequency (samples / second)
|
||||||
|
std::vector<SoundChannel> channelMap{}; //!< The map of position in sample frame to sound channel
|
||||||
|
bool loop{}; //!< Loop flag (true to loop, false to play once)
|
||||||
|
bool streaming{true}; //!< True if we are still streaming samples from the source
|
||||||
|
Status status{Stopped}; //!< The status
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SoundStream::SoundStream() : m_impl(std::make_unique<Impl>(this))
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundStream::initialize(unsigned int channelCount, unsigned int sampleRate)
|
SoundStream::~SoundStream() = default;
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SoundStream::initialize(unsigned int channelCount, unsigned int sampleRate, const std::vector<SoundChannel>& channelMap)
|
||||||
{
|
{
|
||||||
m_channelCount = channelCount;
|
m_impl->channelCount = channelCount;
|
||||||
m_sampleRate = sampleRate;
|
m_impl->sampleRate = sampleRate;
|
||||||
m_samplesProcessed = 0;
|
m_impl->channelMap = channelMap;
|
||||||
|
m_impl->samplesProcessed = 0;
|
||||||
|
|
||||||
{
|
m_impl->reinitialize();
|
||||||
const std::lock_guard lock(m_threadMutex);
|
|
||||||
m_isStreaming = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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()
|
void SoundStream::play()
|
||||||
{
|
{
|
||||||
// Check if the sound parameters have been set
|
if (m_impl->status == Playing)
|
||||||
if (m_format == 0)
|
setPlayingOffset(Time::Zero);
|
||||||
|
|
||||||
|
if (const ma_result result = ma_sound_start(&m_impl->sound); result != MA_SUCCESS)
|
||||||
{
|
{
|
||||||
err() << "Failed to play audio stream: sound parameters have not been initialized (call initialize() first)"
|
err() << "Failed to start playing sound: " << ma_result_description(result) << std::endl;
|
||||||
<< std::endl;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
bool isStreaming = false;
|
|
||||||
Status threadStartState = Stopped;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(m_threadMutex);
|
m_impl->status = Playing;
|
||||||
|
|
||||||
isStreaming = m_isStreaming;
|
|
||||||
threadStartState = m_threadStartState;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (isStreaming && (threadStartState == Paused))
|
|
||||||
{
|
|
||||||
// If the sound is paused, resume it
|
|
||||||
const std::lock_guard 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();
|
|
||||||
}
|
|
||||||
else if (!isStreaming && m_thread.joinable())
|
|
||||||
{
|
|
||||||
// If the streaming thread reached its end, let it join so it can be restarted.
|
|
||||||
// Also reset the playing offset at the beginning.
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start updating the stream in a separate thread to avoid blocking the application
|
|
||||||
launchStreamingThread(Playing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundStream::pause()
|
void SoundStream::pause()
|
||||||
{
|
{
|
||||||
// Handle pause() being called before the thread has started
|
if (const ma_result result = ma_sound_stop(&m_impl->sound); result != MA_SUCCESS)
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(m_threadMutex);
|
err() << "Failed to stop playing sound: " << ma_result_description(result) << std::endl;
|
||||||
|
}
|
||||||
if (!m_isStreaming)
|
else
|
||||||
return;
|
{
|
||||||
|
if (m_impl->status == Playing)
|
||||||
m_threadStartState = Paused;
|
m_impl->status = Paused;
|
||||||
}
|
}
|
||||||
|
|
||||||
alCheck(alSourcePause(m_source));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundStream::stop()
|
void SoundStream::stop()
|
||||||
{
|
{
|
||||||
// Wait for the thread to join
|
if (const ma_result result = ma_sound_stop(&m_impl->sound); result != MA_SUCCESS)
|
||||||
awaitStreamingThread();
|
{
|
||||||
|
err() << "Failed to stop playing sound: " << ma_result_description(result) << std::endl;
|
||||||
// Move to the beginning
|
}
|
||||||
onSeek(Time::Zero);
|
else
|
||||||
|
{
|
||||||
|
setPlayingOffset(Time::Zero);
|
||||||
|
m_impl->status = Stopped;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int SoundStream::getChannelCount() const
|
unsigned int SoundStream::getChannelCount() const
|
||||||
{
|
{
|
||||||
return m_channelCount;
|
return m_impl->channelCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int SoundStream::getSampleRate() const
|
unsigned int SoundStream::getSampleRate() const
|
||||||
{
|
{
|
||||||
return m_sampleRate;
|
return m_impl->sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::vector<SoundChannel> SoundStream::getChannelMap() const
|
||||||
|
{
|
||||||
|
return m_impl->channelMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundStream::Status SoundStream::getStatus() const
|
SoundStream::Status SoundStream::getStatus() const
|
||||||
{
|
{
|
||||||
Status status = SoundSource::getStatus();
|
return m_impl->status;
|
||||||
|
|
||||||
// To compensate for the lag between play() and alSourceplay()
|
|
||||||
if (status == Stopped)
|
|
||||||
{
|
|
||||||
const std::lock_guard lock(m_threadMutex);
|
|
||||||
|
|
||||||
if (m_isStreaming)
|
|
||||||
status = m_threadStartState;
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundStream::setPlayingOffset(Time timeOffset)
|
void SoundStream::setPlayingOffset(Time timeOffset)
|
||||||
{
|
{
|
||||||
// Get old playing status
|
if (m_impl->sampleRate == 0)
|
||||||
const Status oldStatus = getStatus();
|
|
||||||
|
|
||||||
// Stop the stream
|
|
||||||
stop();
|
|
||||||
|
|
||||||
// Let the derived class update the current position
|
|
||||||
onSeek(timeOffset);
|
|
||||||
|
|
||||||
// Restart streaming
|
|
||||||
m_samplesProcessed = static_cast<std::uint64_t>(timeOffset.asSeconds() * static_cast<float>(m_sampleRate)) *
|
|
||||||
m_channelCount;
|
|
||||||
|
|
||||||
if (oldStatus == Stopped)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
launchStreamingThread(oldStatus);
|
if (m_impl->sound.pDataSource == nullptr || m_impl->sound.engineNode.pEngine == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto frameIndex = priv::MiniaudioUtils::getFrameIndex(m_impl->sound, timeOffset);
|
||||||
|
|
||||||
|
m_impl->streaming = true;
|
||||||
|
m_impl->sampleBuffer.clear();
|
||||||
|
m_impl->sampleBufferCursor = 0;
|
||||||
|
m_impl->samplesProcessed = frameIndex * m_impl->channelCount;
|
||||||
|
|
||||||
|
onSeek(seconds(static_cast<float>(frameIndex / m_impl->sampleRate)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Time SoundStream::getPlayingOffset() const
|
Time SoundStream::getPlayingOffset() const
|
||||||
{
|
{
|
||||||
if (m_sampleRate && m_channelCount)
|
if (m_impl->channelCount == 0 || m_impl->sampleRate == 0)
|
||||||
{
|
return {};
|
||||||
ALfloat secs = 0.f;
|
|
||||||
alCheck(alGetSourcef(m_source, AL_SEC_OFFSET, &secs));
|
|
||||||
|
|
||||||
return seconds(secs + static_cast<float>(m_samplesProcessed) / static_cast<float>(m_sampleRate) /
|
return priv::MiniaudioUtils::getPlayingOffset(m_impl->sound);
|
||||||
static_cast<float>(m_channelCount));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Time::Zero;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundStream::setLoop(bool loop)
|
void SoundStream::setLoop(bool loop)
|
||||||
{
|
{
|
||||||
m_loop = loop;
|
ma_sound_set_looping(&m_impl->sound, loop ? MA_TRUE : MA_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool SoundStream::getLoop() const
|
bool SoundStream::getLoop() const
|
||||||
{
|
{
|
||||||
return m_loop;
|
return ma_sound_is_looping(&m_impl->sound) == MA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -251,275 +402,11 @@ std::int64_t SoundStream::onLoop()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void SoundStream::setProcessingInterval(Time interval)
|
|
||||||
{
|
|
||||||
m_processingInterval = interval;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundStream::streamData()
|
void* SoundStream::getSound() const
|
||||||
{
|
{
|
||||||
bool requestStop = false;
|
return &m_impl->sound;
|
||||||
|
|
||||||
{
|
|
||||||
const std::lock_guard 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 (std::int64_t& bufferSeek : m_bufferSeeks)
|
|
||||||
bufferSeek = NoLoop;
|
|
||||||
|
|
||||||
// Fill the queue
|
|
||||||
requestStop = fillQueue();
|
|
||||||
|
|
||||||
// Play the sound
|
|
||||||
alCheck(alSourcePlay(m_source));
|
|
||||||
|
|
||||||
{
|
|
||||||
const std::lock_guard lock(m_threadMutex);
|
|
||||||
|
|
||||||
// Check if the thread was launched Paused
|
|
||||||
if (m_threadStartState == Paused)
|
|
||||||
alCheck(alSourcePause(m_source));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
const std::lock_guard 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
|
|
||||||
const std::lock_guard 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 (unsigned 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_bufferSeeks[bufferNum] != NoLoop)
|
|
||||||
{
|
|
||||||
// This was the last buffer before EOF or Loop End: reset the sample count
|
|
||||||
m_samplesProcessed = static_cast<std::uint64_t>(m_bufferSeeks[bufferNum]);
|
|
||||||
m_bufferSeeks[bufferNum] = NoLoop;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ALint size;
|
|
||||||
ALint 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)
|
|
||||||
const std::lock_guard lock(m_threadMutex);
|
|
||||||
m_isStreaming = false;
|
|
||||||
requestStop = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_samplesProcessed += static_cast<std::uint64_t>(size / (bits / 8));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill it and push it back into the playing queue
|
|
||||||
if (!requestStop)
|
|
||||||
{
|
|
||||||
if (fillAndPushBuffer(bufferNum))
|
|
||||||
requestStop = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if any error has occurred
|
|
||||||
if (alGetLastError() != AL_NO_ERROR)
|
|
||||||
{
|
|
||||||
// Abort streaming (exit main loop)
|
|
||||||
const std::lock_guard lock(m_threadMutex);
|
|
||||||
m_isStreaming = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Leave some time for the other threads if the stream is still playing
|
|
||||||
if (SoundSource::getStatus() != Stopped)
|
|
||||||
sleep(m_processingInterval);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop the playback
|
|
||||||
alCheck(alSourceStop(m_source));
|
|
||||||
|
|
||||||
// Dequeue any buffer left in the queue
|
|
||||||
clearQueue();
|
|
||||||
|
|
||||||
// Reset the playing position
|
|
||||||
m_samplesProcessed = 0;
|
|
||||||
|
|
||||||
// Delete the buffers
|
|
||||||
alCheck(alSourcei(m_source, AL_BUFFER, 0));
|
|
||||||
alCheck(alDeleteBuffers(BufferCount, m_buffers));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
bool SoundStream::fillAndPushBuffer(unsigned int bufferNum, bool immediateLoop)
|
|
||||||
{
|
|
||||||
bool requestStop = false;
|
|
||||||
|
|
||||||
// Acquire audio data, also address EOF and error cases if they occur
|
|
||||||
Chunk data = {nullptr, 0};
|
|
||||||
for (std::uint32_t retryCount = 0; !onGetData(data) && (retryCount < BufferRetries); ++retryCount)
|
|
||||||
{
|
|
||||||
// Check if the stream must loop or stop
|
|
||||||
if (!m_loop)
|
|
||||||
{
|
|
||||||
// Not looping: Mark this buffer as ending with 0 and request stop
|
|
||||||
if (data.samples != nullptr && data.sampleCount != 0)
|
|
||||||
m_bufferSeeks[bufferNum] = 0;
|
|
||||||
requestStop = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return to the beginning or loop-start of the stream source using onLoop(), and store the result in the buffer seek array
|
|
||||||
// This marks the buffer as the "last" one (so that we know where to reset the playing position)
|
|
||||||
m_bufferSeeks[bufferNum] = onLoop();
|
|
||||||
|
|
||||||
// If we got data, break and process it, else try to fill the buffer once again
|
|
||||||
if (data.samples != nullptr && data.sampleCount != 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// If immediateLoop is specified, we have to immediately adjust the sample count
|
|
||||||
if (immediateLoop && (m_bufferSeeks[bufferNum] != NoLoop))
|
|
||||||
{
|
|
||||||
// We just tried to begin preloading at EOF or Loop End: reset the sample count
|
|
||||||
m_samplesProcessed = static_cast<std::uint64_t>(m_bufferSeeks[bufferNum]);
|
|
||||||
m_bufferSeeks[bufferNum] = NoLoop;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We're a looping sound that got no data, so we retry onGetData()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill the buffer if some data was returned
|
|
||||||
if (data.samples && data.sampleCount)
|
|
||||||
{
|
|
||||||
const unsigned int buffer = m_buffers[bufferNum];
|
|
||||||
|
|
||||||
// Fill the buffer
|
|
||||||
const auto size = static_cast<ALsizei>(data.sampleCount * sizeof(std::int16_t));
|
|
||||||
alCheck(alBufferData(buffer, m_format, data.samples, size, static_cast<ALsizei>(m_sampleRate)));
|
|
||||||
|
|
||||||
// Push it into the sound queue
|
|
||||||
alCheck(alSourceQueueBuffers(m_source, 1, &buffer));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If we get here, we most likely ran out of retries
|
|
||||||
requestStop = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return requestStop;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
bool SoundStream::fillQueue()
|
|
||||||
{
|
|
||||||
// Fill and enqueue all the available buffers
|
|
||||||
bool requestStop = false;
|
|
||||||
for (unsigned int i = 0; (i < BufferCount) && !requestStop; ++i)
|
|
||||||
{
|
|
||||||
// Since no sound has been loaded yet, we can't schedule loop seeks preemptively,
|
|
||||||
// So if we start on EOF or Loop End, we let fillAndPushBuffer() adjust the sample count
|
|
||||||
if (fillAndPushBuffer(i, (i == 0)))
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void SoundStream::launchStreamingThread(Status threadStartState)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
const std::lock_guard lock(m_threadMutex);
|
|
||||||
m_isStreaming = true;
|
|
||||||
m_threadStartState = threadStartState;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(!m_thread.joinable() && "Background thread is still running");
|
|
||||||
m_thread = std::thread(&SoundStream::streamData, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void SoundStream::awaitStreamingThread()
|
|
||||||
{
|
|
||||||
// Request the thread to join
|
|
||||||
{
|
|
||||||
const std::lock_guard lock(m_threadMutex);
|
|
||||||
m_isStreaming = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_thread.joinable())
|
|
||||||
m_thread.join();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -7,10 +7,8 @@ if(SFML_OS_WINDOWS)
|
|||||||
if(SFML_COMPILER_GCC OR (SFML_COMPILER_CLANG AND MINGW))
|
if(SFML_COMPILER_GCC OR (SFML_COMPILER_CLANG AND MINGW))
|
||||||
if(ARCH_32BITS)
|
if(ARCH_32BITS)
|
||||||
list(APPEND CMAKE_LIBRARY_PATH "${PROJECT_SOURCE_DIR}/extlibs/libs-mingw/x86")
|
list(APPEND CMAKE_LIBRARY_PATH "${PROJECT_SOURCE_DIR}/extlibs/libs-mingw/x86")
|
||||||
list(APPEND CMAKE_LIBRARY_PATH "${PROJECT_SOURCE_DIR}/extlibs/bin/x86")
|
|
||||||
elseif(ARCH_64BITS)
|
elseif(ARCH_64BITS)
|
||||||
list(APPEND CMAKE_LIBRARY_PATH "${PROJECT_SOURCE_DIR}/extlibs/libs-mingw/x64")
|
list(APPEND CMAKE_LIBRARY_PATH "${PROJECT_SOURCE_DIR}/extlibs/libs-mingw/x64")
|
||||||
list(APPEND CMAKE_LIBRARY_PATH "${PROJECT_SOURCE_DIR}/extlibs/bin/x64")
|
|
||||||
endif()
|
endif()
|
||||||
elseif(SFML_COMPILER_MSVC OR (SFML_COMPILER_CLANG AND NOT MINGW))
|
elseif(SFML_COMPILER_MSVC OR (SFML_COMPILER_CLANG AND NOT MINGW))
|
||||||
if(ARCH_32BITS)
|
if(ARCH_32BITS)
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
#include <SFML/Audio/AlResource.hpp>
|
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
static_assert(!std::is_constructible_v<sf::AlResource>);
|
|
||||||
static_assert(!std::is_copy_constructible_v<sf::AlResource>);
|
|
||||||
static_assert(std::is_copy_assignable_v<sf::AlResource>);
|
|
||||||
static_assert(!std::is_nothrow_move_constructible_v<sf::AlResource>);
|
|
||||||
static_assert(std::is_nothrow_move_assignable_v<sf::AlResource>);
|
|
9
test/Audio/AudioResource.test.cpp
Normal file
9
test/Audio/AudioResource.test.cpp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#include <SFML/Audio/AudioResource.hpp>
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
static_assert(!std::is_constructible_v<sf::AudioResource>);
|
||||||
|
static_assert(std::is_copy_constructible_v<sf::AudioResource>);
|
||||||
|
static_assert(!std::is_copy_assignable_v<sf::AudioResource>);
|
||||||
|
static_assert(std::is_nothrow_move_constructible_v<sf::AudioResource>);
|
||||||
|
static_assert(!std::is_nothrow_move_assignable_v<sf::AudioResource>);
|
@ -1,6 +1,7 @@
|
|||||||
#include <SFML/Audio/SoundFileFactory.hpp>
|
#include <SFML/Audio/SoundFileFactory.hpp>
|
||||||
|
|
||||||
// Other 1st party headers
|
// Other 1st party headers
|
||||||
|
#include <SFML/Audio/SoundChannel.hpp>
|
||||||
#include <SFML/Audio/SoundFileReader.hpp>
|
#include <SFML/Audio/SoundFileReader.hpp>
|
||||||
#include <SFML/Audio/SoundFileWriter.hpp>
|
#include <SFML/Audio/SoundFileWriter.hpp>
|
||||||
|
|
||||||
@ -47,7 +48,7 @@ struct NoopSoundFileWriter : sf::SoundFileWriter
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool open(const std::filesystem::path&, unsigned int, unsigned int) override
|
bool open(const std::filesystem::path&, unsigned int, unsigned int, const std::vector<sf::SoundChannel>&) override
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ set(NETWORK_SRC
|
|||||||
sfml_add_test(test-sfml-network "${NETWORK_SRC}" SFML::Network)
|
sfml_add_test(test-sfml-network "${NETWORK_SRC}" SFML::Network)
|
||||||
|
|
||||||
set(AUDIO_SRC
|
set(AUDIO_SRC
|
||||||
Audio/AlResource.test.cpp
|
Audio/AudioResource.test.cpp
|
||||||
Audio/InputSoundFile.test.cpp
|
Audio/InputSoundFile.test.cpp
|
||||||
Audio/Music.test.cpp
|
Audio/Music.test.cpp
|
||||||
Audio/OutputSoundFile.test.cpp
|
Audio/OutputSoundFile.test.cpp
|
||||||
@ -146,14 +146,6 @@ set(AUDIO_SRC
|
|||||||
)
|
)
|
||||||
sfml_add_test(test-sfml-audio "${AUDIO_SRC}" SFML::Audio)
|
sfml_add_test(test-sfml-audio "${AUDIO_SRC}" SFML::Audio)
|
||||||
|
|
||||||
if(SFML_OS_WINDOWS AND NOT SFML_USE_SYSTEM_DEPS)
|
|
||||||
add_custom_command(
|
|
||||||
TARGET test-sfml-audio
|
|
||||||
COMMENT "Copy OpenAL DLL"
|
|
||||||
PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/extlibs/bin/$<IF:$<BOOL:${ARCH_64BITS}>,x64,x86>/openal32.dll $<TARGET_FILE_DIR:test-sfml-audio>
|
|
||||||
VERBATIM)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(SFML_ENABLE_COVERAGE AND SFML_OS_WINDOWS AND NOT SFML_COMPILER_GCC)
|
if(SFML_ENABLE_COVERAGE AND SFML_OS_WINDOWS AND NOT SFML_COMPILER_GCC)
|
||||||
# Try to find and use OpenCppCoverage for coverage reporting when building with MSVC
|
# Try to find and use OpenCppCoverage for coverage reporting when building with MSVC
|
||||||
find_program(OpenCppCoverage_BINARY "OpenCppCoverage.exe")
|
find_program(OpenCppCoverage_BINARY "OpenCppCoverage.exe")
|
||||||
|
@ -51,7 +51,4 @@ rm $DESTDIR/$1/usr/lib/libvorbis*.so*
|
|||||||
# Compile freetype
|
# Compile freetype
|
||||||
cd $LOCALDIR/build/freetype-* && sed -i 's/-version-info/-avoid-version/g' builds/unix/unix-cc.in && ./configure $HOST $PREFIX && make && make install
|
cd $LOCALDIR/build/freetype-* && sed -i 's/-version-info/-avoid-version/g' builds/unix/unix-cc.in && ./configure $HOST $PREFIX && make && make install
|
||||||
|
|
||||||
# Compile OpenAL-Soft
|
|
||||||
cd $LOCALDIR/build/openal-soft-android-master && cd build && cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_CMAKE_TOOLCHAIN -DANDROID_ABI=$ANDROID_ABI -DANDROID_NATIVE_API_LEVEL=android-9 -DANDROID_USE_STLPORT=1 .. && make openal && mv libopenal.so $DESTDIR/$1/usr/lib
|
|
||||||
|
|
||||||
export PATH=$OPATH
|
export PATH=$OPATH
|
||||||
|
@ -39,11 +39,3 @@ if [ ! -d "$PWD/tmp/$FREETYPE" ]
|
|||||||
then
|
then
|
||||||
tar -C build -xf src/$FREETYPE.tar.gz
|
tar -C build -xf src/$FREETYPE.tar.gz
|
||||||
fi
|
fi
|
||||||
|
|
||||||
wget -nc -P src https://github.com/AerialX/openal-soft-android/archive/master.tar.gz
|
|
||||||
if [ ! -d "$PWD/tmp/openal-soft-android-master" ]
|
|
||||||
then
|
|
||||||
tar -C build -xf src/master.tar.gz
|
|
||||||
fi
|
|
||||||
|
|
||||||
patch build/openal-soft-android-master/CMakeLists.txt patches/remove-so-version-suffix.diff
|
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
--- CMakeLists.txt.orig 2013-09-21 15:23:49.305453804 +0200
|
|
||||||
+++ CMakeLists.txt 2013-09-21 15:24:08.621454210 +0200
|
|
||||||
@@ -717,9 +717,7 @@
|
|
||||||
# Build a library
|
|
||||||
ADD_LIBRARY(${LIBNAME} ${LIBTYPE} ${OPENAL_OBJS} ${ALC_OBJS})
|
|
||||||
SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES DEFINE_SYMBOL AL_BUILD_LIBRARY
|
|
||||||
- COMPILE_FLAGS -DAL_ALEXT_PROTOTYPES
|
|
||||||
- VERSION ${LIB_VERSION}.0
|
|
||||||
- SOVERSION ${LIB_MAJOR_VERSION})
|
|
||||||
+ COMPILE_FLAGS -DAL_ALEXT_PROTOTYPES)
|
|
||||||
IF(WIN32 AND NOT LIBTYPE STREQUAL "STATIC")
|
|
||||||
SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES PREFIX "")
|
|
||||||
ENDIF()
|
|
@ -8,8 +8,6 @@ Description: The Simple and Fast Multimedia Library, audio module.
|
|||||||
URL: http://www.sfml-dev.org
|
URL: http://www.sfml-dev.org
|
||||||
Version: @PROJECT_VERSION@
|
Version: @PROJECT_VERSION@
|
||||||
Requires: sfml-system
|
Requires: sfml-system
|
||||||
Requires.private: openal, vorbisenc, vorbisfile, vorbis, ogg, flac
|
Requires.private: vorbisenc, vorbisfile, vorbis, ogg, flac
|
||||||
Libs: -L${libdir} -lsfml-audio
|
Libs: -L${libdir} -lsfml-audio
|
||||||
# openal may be a system framework
|
|
||||||
Libs.private: @OPENAL_LIBRARY@
|
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
@ -229,8 +229,8 @@ require () # $1 is a SFML module like 'system' or 'audio'
|
|||||||
# copy extra dependencies
|
# copy extra dependencies
|
||||||
if [ "$1" = "audio" ]
|
if [ "$1" = "audio" ]
|
||||||
then
|
then
|
||||||
# copy "FLAC" "ogg" "vorbis" "vorbisenc" "vorbisfile" "OpenAL" frameworks too
|
# copy "FLAC" "ogg" "vorbis" "vorbisenc" "vorbisfile" frameworks too
|
||||||
for f in "FLAC" "ogg" "vorbis" "vorbisenc" "vorbisfile" "OpenAL"
|
for f in "FLAC" "ogg" "vorbis" "vorbisenc" "vorbisfile"
|
||||||
do
|
do
|
||||||
copy "$SFML_DEPENDENCIES_INSTALL_PREFIX/$f.framework" "$dest/$f.framework"
|
copy "$SFML_DEPENDENCIES_INSTALL_PREFIX/$f.framework" "$dest/$f.framework"
|
||||||
done
|
done
|
||||||
|
Loading…
Reference in New Issue
Block a user