Merge pull request #5313 from ligfx/addcubeb

Add CubebStream output backend and replace PortAudio for microphones
This commit is contained in:
Mat M 2017-05-27 21:39:03 -04:00 committed by GitHub
commit 905232fd2b
190 changed files with 22187 additions and 82592 deletions

View File

@ -491,32 +491,6 @@ if(ENCODE_FRAMEDUMPS)
endif()
endif()
if(NOT ANDROID)
set(PORTAUDIO_FOUND TRUE)
add_definitions(-DHAVE_PORTAUDIO=1)
if(NOT APPLE)
set(CMAKE_REQUIRED_LIBRARIES portaudio)
CHECK_CXX_SOURCE_RUNS(
"#include <portaudio.h>
int main(int argc, char **argv)
{ if(Pa_GetVersion() >= 1890) return 0; else return 1; }"
SYSTEM_PORTAUDIO)
unset(CMAKE_REQUIRED_LIBRARIES)
endif()
if(SYSTEM_PORTAUDIO AND NOT APPLE)
message(STATUS "Using shared PortAudio for mic support")
set(PORTAUDIO_LIBRARIES portaudio)
else()
message(STATUS "Using static PortAudio from Externals for mic support")
option(PA_USE_ASIO "Enable PortAudio support for ASIO" OFF)
option(PA_USE_DS "Enable PortAudio support for DirectSound" OFF)
option(PA_USE_WDMKS "Enable PortAudio support for WDMKS" OFF)
add_subdirectory(Externals/portaudio EXCLUDE_FROM_ALL)
set(PORTAUDIO_LIBRARIES portaudio_static)
endif()
endif()
if(OPROFILING)
find_package(OProfile)
if(OPROFILE_FOUND)
@ -660,6 +634,8 @@ find_package(OpenAL)
add_subdirectory(Externals/soundtouch)
include_directories(Externals)
add_subdirectory(Externals/cubeb EXCLUDE_FROM_ALL)
if(NOT ANDROID)
add_definitions(-D__LIBUSB__)
if(NOT APPLE)

16
Externals/cubeb/AUTHORS vendored Normal file
View File

@ -0,0 +1,16 @@
Matthew Gregan <kinetik@flim.org>
Alexandre Ratchov <alex@caoua.org>
Michael Wu <mwu@mozilla.com>
Paul Adenot <paul@paul.cx>
David Richards <drichards@mozilla.com>
Sebastien Alaiwan <sebastien.alaiwan@gmail.com>
KO Myung-Hun <komh@chollian.net>
Haakon Sporsheim <haakon.sporsheim@telenordigital.com>
Alex Chronopoulos <achronop@gmail.com>
Jan Beich <jbeich@FreeBSD.org>
Vito Caputo <vito.caputo@coreos.com>
Landry Breuil <landry@openbsd.org>
Jacek Caban <jacek@codeweavers.com>
Paul Hancock <Paul.Hancock.17041993@live.com>
Ted Mielczarek <ted@mielczarek.org>
Chun-Min Chang <chun.m.chang@gmail.com>

150
Externals/cubeb/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,150 @@
# TODO
# - backend selection via command line, rather than simply detecting headers.
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
project(cubeb
VERSION 0.0.0)
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
endif()
if(POLICY CMP0063)
cmake_policy(SET CMP0063 NEW)
endif()
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(NOT COMMAND add_sanitizers)
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/sanitizers-cmake/cmake")
find_package(Sanitizers)
if(NOT COMMAND add_sanitizers)
message(FATAL_ERROR "Could not find sanitizers-cmake: run\n\tgit submodule update --init --recursive\nin base git checkout")
endif()
endif()
set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
set(CMAKE_CXX_WARNING_LEVEL 4)
if(NOT MSVC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-unused-parameter")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter")
endif()
add_library(cubeb
src/cubeb.c
src/cubeb_mixer.cpp
src/cubeb_resampler.cpp
src/cubeb_panner.cpp
src/cubeb_log.cpp
src/cubeb_utils.c
$<TARGET_OBJECTS:speex>)
target_include_directories(cubeb PUBLIC include)
target_include_directories(cubeb PRIVATE src)
target_compile_definitions(cubeb PRIVATE OUTSIDE_SPEEX)
target_compile_definitions(cubeb PRIVATE FLOATING_POINT)
target_compile_definitions(cubeb PRIVATE EXPORT=)
target_compile_definitions(cubeb PRIVATE RANDOM_PREFIX=speex)
add_sanitizers(cubeb)
include(GenerateExportHeader)
generate_export_header(cubeb EXPORT_FILE_NAME ${CMAKE_BINARY_DIR}/exports/cubeb_export.h)
target_include_directories(cubeb PUBLIC ${CMAKE_BINARY_DIR}/exports)
add_library(speex OBJECT
src/speex/resample.c)
set_target_properties(speex PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
target_compile_definitions(speex PRIVATE OUTSIDE_SPEEX)
target_compile_definitions(speex PRIVATE FLOATING_POINT)
target_compile_definitions(speex PRIVATE EXPORT=)
target_compile_definitions(speex PRIVATE RANDOM_PREFIX=speex)
include(CheckIncludeFiles)
check_include_files(AudioUnit/AudioUnit.h USE_AUDIOUNIT)
if(USE_AUDIOUNIT)
target_sources(cubeb PRIVATE
src/cubeb_audiounit.cpp
src/cubeb_osx_run_loop.cpp)
target_compile_definitions(cubeb PRIVATE USE_AUDIOUNIT)
target_link_libraries(cubeb PRIVATE "-framework AudioUnit" "-framework CoreAudio" "-framework CoreServices")
endif()
check_include_files(pulse/pulseaudio.h USE_PULSE)
if(USE_PULSE)
target_sources(cubeb PRIVATE
src/cubeb_pulse.c)
target_compile_definitions(cubeb PRIVATE USE_PULSE)
target_link_libraries(cubeb PRIVATE dl)
endif()
check_include_files(alsa/asoundlib.h USE_ALSA)
if(USE_ALSA)
target_sources(cubeb PRIVATE
src/cubeb_alsa.c)
target_compile_definitions(cubeb PRIVATE USE_ALSA)
target_link_libraries(cubeb PRIVATE asound pthread)
endif()
check_include_files(jack/jack.h USE_JACK)
if(USE_JACK)
target_sources(cubeb PRIVATE
src/cubeb_jack.cpp)
target_compile_definitions(cubeb PRIVATE USE_JACK)
target_link_libraries(cubeb PRIVATE dl pthread)
endif()
check_include_files(audioclient.h USE_WASAPI)
if(USE_WASAPI)
target_sources(cubeb PRIVATE
src/cubeb_wasapi.cpp)
target_compile_definitions(cubeb PRIVATE USE_WASAPI)
target_link_libraries(cubeb PRIVATE avrt)
endif()
check_include_files("windows.h;mmsystem.h" USE_WINMM)
if(USE_WINMM)
target_sources(cubeb PRIVATE
src/cubeb_winmm.c)
target_compile_definitions(cubeb PRIVATE USE_WINMM)
target_link_libraries(cubeb PRIVATE winmm)
endif()
check_include_files(SLES/OpenSLES.h USE_OPENSL)
if(USE_OPENSL)
target_sources(cubeb PRIVATE
src/cubeb_opensl.c)
target_compile_definitions(cubeb PRIVATE USE_OPENSL)
target_link_libraries(cubeb PRIVATE OpenSLES)
endif()
check_include_files(android/log.h USE_AUDIOTRACK)
if(USE_AUDIOTRACK)
target_sources(cubeb PRIVATE
src/cubeb_audiotrack.c)
target_compile_definitions(cubeb PRIVATE USE_AUDIOTRACK)
target_link_libraries(cubeb PRIVATE log)
endif()
check_include_files(sndio.h USE_SNDIO)
if(USE_SNDIO)
target_sources(cubeb PRIVATE
src/cubeb_sndio.c)
target_compile_definitions(cubeb PRIVATE USE_SNDIO)
target_link_libraries(cubeb PRIVATE sndio)
endif()
check_include_files(kai.h USE_KAI)
if(USE_KAI)
target_sources(cubeb PRIVATE
src/cubeb_kai.c)
target_compile_definitions(cubeb PRIVATE USE_KAI)
target_link_libraries(cubeb PRIVATE kai)
endif()

24
Externals/cubeb/INSTALL.md vendored Normal file
View File

@ -0,0 +1,24 @@
# Build instructions for libcubeb
You must have CMake v3.1 or later installed.
1. `git clone --recursive https://github.com/kinetiknz/cubeb.git`
2. `mkdir cubeb-build`
3. `cd cubeb-build`
3. `cmake ../cubeb`
4. `cmake --build .`
5. `ctest`
# Windows build notes
Windows builds can use Microsoft Visual Studio 2015 (the default) or MinGW-w64
with Win32 threads (by passing `cmake -G` to generate the appropriate build
configuration). To build with MinGW-w64, install the following items:
- Download and install MinGW-w64 with Win32 threads.
- Download and install CMake.
- Run MinGW-w64 Terminal from the Start Menu.
- Follow the build steps above, but at step 3 run:
`cmake -G "MinGW Makefiles" ..`
- Continue the build steps above.

13
Externals/cubeb/LICENSE vendored Normal file
View File

@ -0,0 +1,13 @@
Copyright © 2011 Mozilla Foundation
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

6
Externals/cubeb/README.md vendored Normal file
View File

@ -0,0 +1,6 @@
[![Build Status](https://travis-ci.org/kinetiknz/cubeb.svg?branch=master)](https://travis-ci.org/kinetiknz/cubeb)
[![Build status](https://ci.appveyor.com/api/projects/status/osv2r0m1j1nt9csr/branch/master?svg=true)](https://ci.appveyor.com/project/kinetiknz/cubeb/branch/master)
See INSTALL.md for build instructions.
Licensed under an ISC-style license. See LICENSE for details.

View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c)
2013 Matthew Arsenault
2015-2016 RWTH Aachen University, Federal Republic of Germany
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,73 @@
# sanitizers-cmake
[![](https://img.shields.io/github/issues-raw/arsenm/sanitizers-cmake.svg?style=flat-square)](https://github.com/arsenm/sanitizers-cmake/issues)
[![MIT](http://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE)
CMake module to enable sanitizers for binary targets.
## Include into your project
To use [FindSanitizers.cmake](cmake/FindSanitizers.cmake), simply add this repository as git submodule into your own repository
```Shell
mkdir externals
git submodule add git://github.com/arsenm/sanitizers-cmake.git externals/sanitizers-cmake
```
and adding ```externals/sanitizers-cmake/cmake``` to your ```CMAKE_MODULE_PATH```
```CMake
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/externals/sanitizers-cmake/cmake" ${CMAKE_MODULE_PATH})
```
If you don't use git or dislike submodules you can copy the files in [cmake directory](cmake) into your repository. *Be careful and keep updates in mind!*
Now you can simply run ```find_package``` in your CMake files:
```CMake
find_package(Sanitizers)
```
## Usage
You can enable the sanitizers with ``SANITIZE_ADDRESS``, ``SANITIZE_MEMORY``, ``SANITIZE_THREAD`` or ``SANITIZE_UNDEFINED`` options in your CMake configuration. You can do this by passing e.g. ``-DSANITIZE_ADDRESS=On`` on your command line or with your graphical interface.
If sanitizers are supported by your compiler, the specified targets will be build with sanitizer support. If your compiler has no sanitizing capabilities (I asume intel compiler doesn't) you'll get a warning but CMake will continue processing and sanitizing will simply just be ignored.
#### Compiler issues
Different compilers may be using different implementations for sanitizers. If you'll try to sanitize targets with C and Fortran code but don't use gcc & gfortran but clang & gfortran, this will cause linking problems. To avoid this, such problems will be detected and sanitizing will be disabled for these targets.
Even C only targets may cause problems in certain situations. Some problems have been seen with AddressSanitizer for preloading or dynamic linking. In such cases you may try the ``SANITIZE_LINK_STATIC`` to link sanitizers for gcc static.
## Build targets with sanitizer support
To enable sanitizer support you simply have to add ``add_sanitizers(<TARGET>)`` after defining your target. To provide a sanitizer blacklist file you can use the ``add_sanitizer_blacklist(<FILE>)`` function:
```CMake
find_package(Sanitizers)
add_sanitizer_blacklist("blacklist.txt")
add_executable(some_exe foo.c bar.c)
add_sanitizers(some_exe)
add_library(some_lib foo.c bar.c)
add_sanitizers(some_lib)
```
## Run your application
The sanitizers check your program, while it's running. In some situations (e.g. LD_PRELOAD your target) it might be required to preload the used AddressSanitizer library first. In this case you may use the ``asan-wrapper`` script defined in ``ASan_WRAPPER`` variable to execute your application with ``${ASan_WRAPPER} myexe arg1 ...``.
## Contribute
Anyone is welcome to contribute. Simply fork this repository, make your changes **in an own branch** and create a pull-request for your change. Please do only one change per pull-request.
You found a bug? Please fill out an [issue](https://github.com/arsenm/sanitizers-cmake/issues) and include any data to reproduce the bug.
#### Contributors
* [Matt Arsenault](https://github.com/arsenm)
* [Alexander Haase](https://github.com/alehaa)

View File

@ -0,0 +1,59 @@
# The MIT License (MIT)
#
# Copyright (c)
# 2013 Matthew Arsenault
# 2015-2016 RWTH Aachen University, Federal Republic of Germany
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
option(SANITIZE_ADDRESS "Enable AddressSanitizer for sanitized targets." Off)
set(FLAG_CANDIDATES
# Clang 3.2+ use this version. The no-omit-frame-pointer option is optional.
"-g -fsanitize=address -fno-omit-frame-pointer"
"-g -fsanitize=address"
# Older deprecated flag for ASan
"-g -faddress-sanitizer"
)
if (SANITIZE_ADDRESS AND (SANITIZE_THREAD OR SANITIZE_MEMORY))
message(FATAL_ERROR "AddressSanitizer is not compatible with "
"ThreadSanitizer or MemorySanitizer.")
endif ()
include(sanitize-helpers)
if (SANITIZE_ADDRESS)
sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "AddressSanitizer"
"ASan")
find_program(ASan_WRAPPER "asan-wrapper" PATHS ${CMAKE_MODULE_PATH})
mark_as_advanced(ASan_WRAPPER)
endif ()
function (add_sanitize_address TARGET)
if (NOT SANITIZE_ADDRESS)
return()
endif ()
saitizer_add_flags(${TARGET} "AddressSanitizer" "ASan")
endfunction ()

View File

@ -0,0 +1,57 @@
# The MIT License (MIT)
#
# Copyright (c)
# 2013 Matthew Arsenault
# 2015-2016 RWTH Aachen University, Federal Republic of Germany
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
option(SANITIZE_MEMORY "Enable MemorySanitizer for sanitized targets." Off)
set(FLAG_CANDIDATES
"-g -fsanitize=memory"
)
include(sanitize-helpers)
if (SANITIZE_MEMORY)
if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
message(WARNING "MemorySanitizer disabled for target ${TARGET} because "
"MemorySanitizer is supported for Linux systems only.")
set(SANITIZE_MEMORY Off CACHE BOOL
"Enable MemorySanitizer for sanitized targets." FORCE)
elseif (NOT ${CMAKE_SIZEOF_VOID_P} EQUAL 8)
message(WARNING "MemorySanitizer disabled for target ${TARGET} because "
"MemorySanitizer is supported for 64bit systems only.")
set(SANITIZE_MEMORY Off CACHE BOOL
"Enable MemorySanitizer for sanitized targets." FORCE)
else ()
sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "MemorySanitizer"
"MSan")
endif ()
endif ()
function (add_sanitize_memory TARGET)
if (NOT SANITIZE_MEMORY)
return()
endif ()
saitizer_add_flags(${TARGET} "MemorySanitizer" "MSan")
endfunction ()

View File

@ -0,0 +1,87 @@
# The MIT License (MIT)
#
# Copyright (c)
# 2013 Matthew Arsenault
# 2015-2016 RWTH Aachen University, Federal Republic of Germany
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# If any of the used compiler is a GNU compiler, add a second option to static
# link against the sanitizers.
option(SANITIZE_LINK_STATIC "Try to link static against sanitizers." Off)
set(FIND_QUIETLY_FLAG "")
if (DEFINED Sanitizers_FIND_QUIETLY)
set(FIND_QUIETLY_FLAG "QUIET")
endif ()
find_package(ASan ${FIND_QUIETLY_FLAG})
find_package(TSan ${FIND_QUIETLY_FLAG})
find_package(MSan ${FIND_QUIETLY_FLAG})
find_package(UBSan ${FIND_QUIETLY_FLAG})
function(sanitizer_add_blacklist_file FILE)
if(NOT IS_ABSOLUTE ${FILE})
set(FILE "${CMAKE_CURRENT_SOURCE_DIR}/${FILE}")
endif()
get_filename_component(FILE "${FILE}" REALPATH)
sanitizer_check_compiler_flags("-fsanitize-blacklist=${FILE}"
"SanitizerBlacklist" "SanBlist")
endfunction()
function(add_sanitizers ...)
# If no sanitizer is enabled, return immediately.
if (NOT (SANITIZE_ADDRESS OR SANITIZE_MEMORY OR SANITIZE_THREAD OR
SANITIZE_UNDEFINED))
return()
endif ()
foreach (TARGET ${ARGV})
# Check if this target will be compiled by exactly one compiler. Other-
# wise sanitizers can't be used and a warning should be printed once.
sanitizer_target_compilers(${TARGET} TARGET_COMPILER)
list(LENGTH TARGET_COMPILER NUM_COMPILERS)
if (NUM_COMPILERS GREATER 1)
message(WARNING "Can't use any sanitizers for target ${TARGET}, "
"because it will be compiled by incompatible compilers. "
"Target will be compiled without sanitzers.")
return()
# If the target is compiled by no known compiler, ignore it.
elseif (NUM_COMPILERS EQUAL 0)
message(WARNING "Can't use any sanitizers for target ${TARGET}, "
"because it uses an unknown compiler. Target will be "
"compiled without sanitzers.")
return()
endif ()
# Add sanitizers for target.
add_sanitize_address(${TARGET})
add_sanitize_thread(${TARGET})
add_sanitize_memory(${TARGET})
add_sanitize_undefined(${TARGET})
endforeach ()
endfunction(add_sanitizers)

View File

@ -0,0 +1,64 @@
# The MIT License (MIT)
#
# Copyright (c)
# 2013 Matthew Arsenault
# 2015-2016 RWTH Aachen University, Federal Republic of Germany
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
option(SANITIZE_THREAD "Enable ThreadSanitizer for sanitized targets." Off)
set(FLAG_CANDIDATES
"-g -fsanitize=thread"
)
# ThreadSanitizer is not compatible with MemorySanitizer.
if (SANITIZE_THREAD AND SANITIZE_MEMORY)
message(FATAL_ERROR "ThreadSanitizer is not compatible with "
"MemorySanitizer.")
endif ()
include(sanitize-helpers)
if (SANITIZE_THREAD)
if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
message(WARNING "ThreadSanitizer disabled for target ${TARGET} because "
"ThreadSanitizer is supported for Linux systems only.")
set(SANITIZE_THREAD Off CACHE BOOL
"Enable ThreadSanitizer for sanitized targets." FORCE)
elseif (NOT ${CMAKE_SIZEOF_VOID_P} EQUAL 8)
message(WARNING "ThreadSanitizer disabled for target ${TARGET} because "
"ThreadSanitizer is supported for 64bit systems only.")
set(SANITIZE_THREAD Off CACHE BOOL
"Enable ThreadSanitizer for sanitized targets." FORCE)
else ()
sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "ThreadSanitizer"
"TSan")
endif ()
endif ()
function (add_sanitize_thread TARGET)
if (NOT SANITIZE_THREAD)
return()
endif ()
saitizer_add_flags(${TARGET} "ThreadSanitizer" "TSan")
endfunction ()

View File

@ -0,0 +1,46 @@
# The MIT License (MIT)
#
# Copyright (c)
# 2013 Matthew Arsenault
# 2015-2016 RWTH Aachen University, Federal Republic of Germany
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
option(SANITIZE_UNDEFINED
"Enable UndefinedBehaviorSanitizer for sanitized targets." Off)
set(FLAG_CANDIDATES
"-g -fsanitize=undefined"
)
include(sanitize-helpers)
if (SANITIZE_UNDEFINED)
sanitizer_check_compiler_flags("${FLAG_CANDIDATES}"
"UndefinedBehaviorSanitizer" "UBSan")
endif ()
function (add_sanitize_undefined TARGET)
if (NOT SANITIZE_UNDEFINED)
return()
endif ()
saitizer_add_flags(${TARGET} "UndefinedBehaviorSanitizer" "UBSan")
endfunction ()

View File

@ -0,0 +1,55 @@
#!/bin/sh
# The MIT License (MIT)
#
# Copyright (c)
# 2013 Matthew Arsenault
# 2015-2016 RWTH Aachen University, Federal Republic of Germany
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# This script is a wrapper for AddressSanitizer. In some special cases you need
# to preload AddressSanitizer to avoid error messages - e.g. if you're
# preloading another library to your application. At the moment this script will
# only do something, if we're running on a Linux platform. OSX might not be
# affected.
# Exit immediately, if platform is not Linux.
if [ "$(uname)" != "Linux" ]
then
exec $@
fi
# Get the used libasan of the application ($1). If a libasan was found, it will
# be prepended to LD_PRELOAD.
libasan=$(ldd $1 | grep libasan | sed "s/^[[:space:]]//" | cut -d' ' -f1)
if [ -n "$libasan" ]
then
if [ -n "$LD_PRELOAD" ]
then
export LD_PRELOAD="$libasan:$LD_PRELOAD"
else
export LD_PRELOAD="$libasan"
fi
fi
# Execute the application.
exec $@

View File

@ -0,0 +1,170 @@
# The MIT License (MIT)
#
# Copyright (c)
# 2013 Matthew Arsenault
# 2015-2016 RWTH Aachen University, Federal Republic of Germany
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# Helper function to get the language of a source file.
function (sanitizer_lang_of_source FILE RETURN_VAR)
get_filename_component(FILE_EXT "${FILE}" EXT)
string(TOLOWER "${FILE_EXT}" FILE_EXT)
string(SUBSTRING "${FILE_EXT}" 1 -1 FILE_EXT)
get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach (LANG ${ENABLED_LANGUAGES})
list(FIND CMAKE_${LANG}_SOURCE_FILE_EXTENSIONS "${FILE_EXT}" TEMP)
if (NOT ${TEMP} EQUAL -1)
set(${RETURN_VAR} "${LANG}" PARENT_SCOPE)
return()
endif ()
endforeach()
set(${RETURN_VAR} "" PARENT_SCOPE)
endfunction ()
# Helper function to get compilers used by a target.
function (sanitizer_target_compilers TARGET RETURN_VAR)
# Check if all sources for target use the same compiler. If a target uses
# e.g. C and Fortran mixed and uses different compilers (e.g. clang and
# gfortran) this can trigger huge problems, because different compilers may
# use different implementations for sanitizers.
set(BUFFER "")
get_target_property(TSOURCES ${TARGET} SOURCES)
foreach (FILE ${TSOURCES})
# If expression was found, FILE is a generator-expression for an object
# library. Object libraries will be ignored.
string(REGEX MATCH "TARGET_OBJECTS:([^ >]+)" _file ${FILE})
if ("${_file}" STREQUAL "")
sanitizer_lang_of_source(${FILE} LANG)
if (LANG)
list(APPEND BUFFER ${CMAKE_${LANG}_COMPILER_ID})
endif ()
endif ()
endforeach ()
list(REMOVE_DUPLICATES BUFFER)
set(${RETURN_VAR} "${BUFFER}" PARENT_SCOPE)
endfunction ()
# Helper function to check compiler flags for language compiler.
function (sanitizer_check_compiler_flag FLAG LANG VARIABLE)
if (${LANG} STREQUAL "C")
include(CheckCCompilerFlag)
check_c_compiler_flag("${FLAG}" ${VARIABLE})
elseif (${LANG} STREQUAL "CXX")
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("${FLAG}" ${VARIABLE})
elseif (${LANG} STREQUAL "Fortran")
# CheckFortranCompilerFlag was introduced in CMake 3.x. To be compatible
# with older Cmake versions, we will check if this module is present
# before we use it. Otherwise we will define Fortran coverage support as
# not available.
include(CheckFortranCompilerFlag OPTIONAL RESULT_VARIABLE INCLUDED)
if (INCLUDED)
check_fortran_compiler_flag("${FLAG}" ${VARIABLE})
elseif (NOT CMAKE_REQUIRED_QUIET)
message(STATUS "Performing Test ${VARIABLE}")
message(STATUS "Performing Test ${VARIABLE}"
" - Failed (Check not supported)")
endif ()
endif()
endfunction ()
# Helper function to test compiler flags.
function (sanitizer_check_compiler_flags FLAG_CANDIDATES NAME PREFIX)
set(CMAKE_REQUIRED_QUIET ${${PREFIX}_FIND_QUIETLY})
get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach (LANG ${ENABLED_LANGUAGES})
# Sanitizer flags are not dependend on language, but the used compiler.
# So instead of searching flags foreach language, search flags foreach
# compiler used.
set(COMPILER ${CMAKE_${LANG}_COMPILER_ID})
if (NOT DEFINED ${PREFIX}_${COMPILER}_FLAGS)
foreach (FLAG ${FLAG_CANDIDATES})
if(NOT CMAKE_REQUIRED_QUIET)
message(STATUS "Try ${COMPILER} ${NAME} flag = [${FLAG}]")
endif()
set(CMAKE_REQUIRED_FLAGS "${FLAG}")
unset(${PREFIX}_FLAG_DETECTED CACHE)
sanitizer_check_compiler_flag("${FLAG}" ${LANG}
${PREFIX}_FLAG_DETECTED)
if (${PREFIX}_FLAG_DETECTED)
# If compiler is a GNU compiler, search for static flag, if
# SANITIZE_LINK_STATIC is enabled.
if (SANITIZE_LINK_STATIC AND (${COMPILER} STREQUAL "GNU"))
string(TOLOWER ${PREFIX} PREFIX_lower)
sanitizer_check_compiler_flag(
"-static-lib${PREFIX_lower}" ${LANG}
${PREFIX}_STATIC_FLAG_DETECTED)
if (${PREFIX}_STATIC_FLAG_DETECTED)
set(FLAG "-static-lib${PREFIX_lower} ${FLAG}")
endif ()
endif ()
set(${PREFIX}_${COMPILER}_FLAGS "${FLAG}" CACHE STRING
"${NAME} flags for ${COMPILER} compiler.")
mark_as_advanced(${PREFIX}_${COMPILER}_FLAGS)
break()
endif ()
endforeach ()
if (NOT ${PREFIX}_FLAG_DETECTED)
set(${PREFIX}_${COMPILER}_FLAGS "" CACHE STRING
"${NAME} flags for ${COMPILER} compiler.")
mark_as_advanced(${PREFIX}_${COMPILER}_FLAGS)
message(WARNING "${NAME} is not available for ${COMPILER} "
"compiler. Targets using this compiler will be "
"compiled without ${NAME}.")
endif ()
endif ()
endforeach ()
endfunction ()
# Helper to assign sanitizer flags for TARGET.
function (saitizer_add_flags TARGET NAME PREFIX)
# Get list of compilers used by target and check, if sanitizer is available
# for this target. Other compiler checks like check for conflicting
# compilers will be done in add_sanitizers function.
sanitizer_target_compilers(${TARGET} TARGET_COMPILER)
list(LENGTH TARGET_COMPILER NUM_COMPILERS)
if ("${${PREFIX}_${TARGET_COMPILER}_FLAGS}" STREQUAL "")
return()
endif()
# Set compile- and link-flags for target.
set_property(TARGET ${TARGET} APPEND_STRING
PROPERTY COMPILE_FLAGS " ${${PREFIX}_${TARGET_COMPILER}_FLAGS}")
set_property(TARGET ${TARGET} APPEND_STRING
PROPERTY COMPILE_FLAGS " ${SanBlist_${TARGET_COMPILER}_FLAGS}")
set_property(TARGET ${TARGET} APPEND_STRING
PROPERTY LINK_FLAGS " ${${PREFIX}_${TARGET_COMPILER}_FLAGS}")
endfunction ()

36
Externals/cubeb/cubeb.supp vendored Normal file
View File

@ -0,0 +1,36 @@
{
snd_config_update-malloc
Memcheck:Leak
fun:malloc
...
fun:snd_config_update_r
}
{
snd1_dlobj_cache_get-malloc
Memcheck:Leak
fun:malloc
...
fun:snd1_dlobj_cache_get
}
{
parse_defs-malloc
Memcheck:Leak
fun:malloc
...
fun:parse_defs
}
{
parse_defs-calloc
Memcheck:Leak
fun:calloc
...
fun:parse_defs
}
{
pa_client_conf_from_x11-malloc
Memcheck:Leak
fun:malloc
...
fun:pa_client_conf_from_x11
}

655
Externals/cubeb/include/cubeb/cubeb.h vendored Normal file
View File

@ -0,0 +1,655 @@
/*
* Copyright © 2011 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#if !defined(CUBEB_c2f983e9_c96f_e71c_72c3_bbf62992a382)
#define CUBEB_c2f983e9_c96f_e71c_72c3_bbf62992a382
#include <stdint.h>
#include <stdlib.h>
#include "cubeb_export.h"
#if defined(__cplusplus)
extern "C" {
#endif
/** @mainpage
@section intro Introduction
This is the documentation for the <tt>libcubeb</tt> C API.
<tt>libcubeb</tt> is a callback-based audio API library allowing the
authoring of portable multiplatform audio playback and recording.
@section example Example code
This example shows how to create a duplex stream that pipes the microphone
to the speakers, with minimal latency and the proper sample-rate for the
platform.
@code
cubeb * app_ctx;
cubeb_init(&app_ctx, "Example Application");
int rv;
int rate;
int latency_frames;
uint64_t ts;
rv = cubeb_get_min_latency(app_ctx, output_params, &latency_frames);
if (rv != CUBEB_OK) {
fprintf(stderr, "Could not get minimum latency");
return rv;
}
rv = cubeb_get_preferred_sample_rate(app_ctx, output_params, &rate);
if (rv != CUBEB_OK) {
fprintf(stderr, "Could not get preferred sample-rate");
return rv;
}
cubeb_stream_params output_params;
output_params.format = CUBEB_SAMPLE_FLOAT32NE;
output_params.rate = rate;
output_params.channels = 2;
cubeb_stream_params input_params;
output_params.format = CUBEB_SAMPLE_FLOAT32NE;
output_params.rate = rate;
output_params.channels = 1;
cubeb_stream * stm;
rv = cubeb_stream_init(app_ctx, &stm, "Example Stream 1",
NULL, input_params,
NULL, output_params,
latency_frames,
data_cb, state_cb,
NULL);
if (rv != CUBEB_OK) {
fprintf(stderr, "Could not open the stream");
return rv;
}
rv = cubeb_stream_start(stm);
if (rv != CUBEB_OK) {
fprintf(stderr, "Could not start the stream");
return rv;
}
for (;;) {
cubeb_stream_get_position(stm, &ts);
printf("time=%llu\n", ts);
sleep(1);
}
rv = cubeb_stream_stop(stm);
if (rv != CUBEB_OK) {
fprintf(stderr, "Could not stop the stream");
return rv;
}
cubeb_stream_destroy(stm);
cubeb_destroy(app_ctx);
@endcode
@code
long data_cb(cubeb_stream * stm, void * user,
void * input_buffer, void * output_buffer, long nframes)
{
float * in = input_buffer;
float * out = output_buffer;
for (i = 0; i < nframes; ++i) {
for (c = 0; c < 2; ++c) {
buf[i][c] = in[i];
}
}
return nframes;
}
@endcode
@code
void state_cb(cubeb_stream * stm, void * user, cubeb_state state)
{
printf("state=%d\n", state);
}
@endcode
*/
/** @file
The <tt>libcubeb</tt> C API. */
typedef struct cubeb cubeb; /**< Opaque handle referencing the application state. */
typedef struct cubeb_stream cubeb_stream; /**< Opaque handle referencing the stream state. */
/** Sample format enumeration. */
typedef enum {
/**< Little endian 16-bit signed PCM. */
CUBEB_SAMPLE_S16LE,
/**< Big endian 16-bit signed PCM. */
CUBEB_SAMPLE_S16BE,
/**< Little endian 32-bit IEEE floating point PCM. */
CUBEB_SAMPLE_FLOAT32LE,
/**< Big endian 32-bit IEEE floating point PCM. */
CUBEB_SAMPLE_FLOAT32BE,
#if defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__)
/**< Native endian 16-bit signed PCM. */
CUBEB_SAMPLE_S16NE = CUBEB_SAMPLE_S16BE,
/**< Native endian 32-bit IEEE floating point PCM. */
CUBEB_SAMPLE_FLOAT32NE = CUBEB_SAMPLE_FLOAT32BE
#else
/**< Native endian 16-bit signed PCM. */
CUBEB_SAMPLE_S16NE = CUBEB_SAMPLE_S16LE,
/**< Native endian 32-bit IEEE floating point PCM. */
CUBEB_SAMPLE_FLOAT32NE = CUBEB_SAMPLE_FLOAT32LE
#endif
} cubeb_sample_format;
#if defined(__ANDROID__)
/**
* This maps to the underlying stream types on supported platforms, e.g.
* Android.
*/
typedef enum {
CUBEB_STREAM_TYPE_VOICE_CALL = 0,
CUBEB_STREAM_TYPE_SYSTEM = 1,
CUBEB_STREAM_TYPE_RING = 2,
CUBEB_STREAM_TYPE_MUSIC = 3,
CUBEB_STREAM_TYPE_ALARM = 4,
CUBEB_STREAM_TYPE_NOTIFICATION = 5,
CUBEB_STREAM_TYPE_BLUETOOTH_SCO = 6,
CUBEB_STREAM_TYPE_SYSTEM_ENFORCED = 7,
CUBEB_STREAM_TYPE_DTMF = 8,
CUBEB_STREAM_TYPE_TTS = 9,
CUBEB_STREAM_TYPE_FM = 10,
CUBEB_STREAM_TYPE_MAX
} cubeb_stream_type;
#endif
/** An opaque handle used to refer a particular input or output device
* across calls. */
typedef void const * cubeb_devid;
/** Level (verbosity) of logging for a particular cubeb context. */
typedef enum {
CUBEB_LOG_DISABLED = 0, /** < Logging disabled */
CUBEB_LOG_NORMAL = 1, /**< Logging lifetime operation (creation/destruction). */
CUBEB_LOG_VERBOSE = 2, /**< Verbose logging of callbacks, can have performance implications. */
} cubeb_log_level;
/** SMPTE channel layout (also known as wave order)
* DUAL-MONO L R
* DUAL-MONO-LFE L R LFE
* MONO M
* MONO-LFE M LFE
* STEREO L R
* STEREO-LFE L R LFE
* 3F L R C
* 3F-LFE L R C LFE
* 2F1 L R S
* 2F1-LFE L R LFE S
* 3F1 L R C S
* 3F1-LFE L R C LFE S
* 2F2 L R LS RS
* 2F2-LFE L R LFE LS RS
* 3F2 L R C LS RS
* 3F2-LFE L R C LFE LS RS
* 3F3R-LFE L R C LFE RC LS RS
* 3F4-LFE L R C LFE RLS RRS LS RS
*
* The abbreviation of channel name is defined in following table:
* Abbr Channel name
* ---------------------------
* M Mono
* L Left
* R Right
* C Center
* LS Left Surround
* RS Right Surround
* RLS Rear Left Surround
* RC Rear Center
* RRS Rear Right Surround
* LFE Low Frequency Effects
*/
typedef enum {
CUBEB_LAYOUT_UNDEFINED, // Indicate the speaker's layout is undefined.
CUBEB_LAYOUT_DUAL_MONO,
CUBEB_LAYOUT_DUAL_MONO_LFE,
CUBEB_LAYOUT_MONO,
CUBEB_LAYOUT_MONO_LFE,
CUBEB_LAYOUT_STEREO,
CUBEB_LAYOUT_STEREO_LFE,
CUBEB_LAYOUT_3F,
CUBEB_LAYOUT_3F_LFE,
CUBEB_LAYOUT_2F1,
CUBEB_LAYOUT_2F1_LFE,
CUBEB_LAYOUT_3F1,
CUBEB_LAYOUT_3F1_LFE,
CUBEB_LAYOUT_2F2,
CUBEB_LAYOUT_2F2_LFE,
CUBEB_LAYOUT_3F2,
CUBEB_LAYOUT_3F2_LFE,
CUBEB_LAYOUT_3F3R_LFE,
CUBEB_LAYOUT_3F4_LFE,
CUBEB_LAYOUT_MAX
} cubeb_channel_layout;
/** Stream format initialization parameters. */
typedef struct {
cubeb_sample_format format; /**< Requested sample format. One of
#cubeb_sample_format. */
unsigned int rate; /**< Requested sample rate. Valid range is [1000, 192000]. */
unsigned int channels; /**< Requested channel count. Valid range is [1, 8]. */
cubeb_channel_layout layout; /**< Requested channel layout. This must be consistent with the provided channels. */
#if defined(__ANDROID__)
cubeb_stream_type stream_type; /**< Used to map Android audio stream types */
#endif
} cubeb_stream_params;
/** Audio device description */
typedef struct {
char * output_name; /**< The name of the output device */
char * input_name; /**< The name of the input device */
} cubeb_device;
/** Stream states signaled via state_callback. */
typedef enum {
CUBEB_STATE_STARTED, /**< Stream started. */
CUBEB_STATE_STOPPED, /**< Stream stopped. */
CUBEB_STATE_DRAINED, /**< Stream drained. */
CUBEB_STATE_ERROR /**< Stream disabled due to error. */
} cubeb_state;
/** Result code enumeration. */
enum {
CUBEB_OK = 0, /**< Success. */
CUBEB_ERROR = -1, /**< Unclassified error. */
CUBEB_ERROR_INVALID_FORMAT = -2, /**< Unsupported #cubeb_stream_params requested. */
CUBEB_ERROR_INVALID_PARAMETER = -3, /**< Invalid parameter specified. */
CUBEB_ERROR_NOT_SUPPORTED = -4, /**< Optional function not implemented in current backend. */
CUBEB_ERROR_DEVICE_UNAVAILABLE = -5 /**< Device specified by #cubeb_devid not available. */
};
/**
* Whether a particular device is an input device (e.g. a microphone), or an
* output device (e.g. headphones). */
typedef enum {
CUBEB_DEVICE_TYPE_UNKNOWN,
CUBEB_DEVICE_TYPE_INPUT,
CUBEB_DEVICE_TYPE_OUTPUT
} cubeb_device_type;
/**
* The state of a device.
*/
typedef enum {
CUBEB_DEVICE_STATE_DISABLED, /**< The device has been disabled at the system level. */
CUBEB_DEVICE_STATE_UNPLUGGED, /**< The device is enabled, but nothing is plugged into it. */
CUBEB_DEVICE_STATE_ENABLED /**< The device is enabled. */
} cubeb_device_state;
/**
* Architecture specific sample type.
*/
typedef enum {
CUBEB_DEVICE_FMT_S16LE = 0x0010, /**< 16-bit integers, Little Endian. */
CUBEB_DEVICE_FMT_S16BE = 0x0020, /**< 16-bit integers, Big Endian. */
CUBEB_DEVICE_FMT_F32LE = 0x1000, /**< 32-bit floating point, Little Endian. */
CUBEB_DEVICE_FMT_F32BE = 0x2000 /**< 32-bit floating point, Big Endian. */
} cubeb_device_fmt;
#if defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__)
/** 16-bit integers, native endianess, when on a Big Endian environment. */
#define CUBEB_DEVICE_FMT_S16NE CUBEB_DEVICE_FMT_S16BE
/** 32-bit floating points, native endianess, when on a Big Endian environment. */
#define CUBEB_DEVICE_FMT_F32NE CUBEB_DEVICE_FMT_F32BE
#else
/** 16-bit integers, native endianess, when on a Little Endian environment. */
#define CUBEB_DEVICE_FMT_S16NE CUBEB_DEVICE_FMT_S16LE
/** 32-bit floating points, native endianess, when on a Little Endian
* environment. */
#define CUBEB_DEVICE_FMT_F32NE CUBEB_DEVICE_FMT_F32LE
#endif
/** All the 16-bit integers types. */
#define CUBEB_DEVICE_FMT_S16_MASK (CUBEB_DEVICE_FMT_S16LE | CUBEB_DEVICE_FMT_S16BE)
/** All the 32-bit floating points types. */
#define CUBEB_DEVICE_FMT_F32_MASK (CUBEB_DEVICE_FMT_F32LE | CUBEB_DEVICE_FMT_F32BE)
/** All the device formats types. */
#define CUBEB_DEVICE_FMT_ALL (CUBEB_DEVICE_FMT_S16_MASK | CUBEB_DEVICE_FMT_F32_MASK)
/** Channel type for a `cubeb_stream`. Depending on the backend and platform
* used, this can control inter-stream interruption, ducking, and volume
* control.
*/
typedef enum {
CUBEB_DEVICE_PREF_NONE = 0x00,
CUBEB_DEVICE_PREF_MULTIMEDIA = 0x01,
CUBEB_DEVICE_PREF_VOICE = 0x02,
CUBEB_DEVICE_PREF_NOTIFICATION = 0x04,
CUBEB_DEVICE_PREF_ALL = 0x0F
} cubeb_device_pref;
/** This structure holds the characteristics
* of an input or output audio device. It is obtained using
* `cubeb_enumerate_devices`, which returns these structures via
* `cubeb_device_collection` and must be destroyed via
* `cubeb_device_collection_destroy`. */
typedef struct {
cubeb_devid devid; /**< Device identifier handle. */
char const * device_id; /**< Device identifier which might be presented in a UI. */
char const * friendly_name; /**< Friendly device name which might be presented in a UI. */
char const * group_id; /**< Two devices have the same group identifier if they belong to the same physical device; for example a headset and microphone. */
char const * vendor_name; /**< Optional vendor name, may be NULL. */
cubeb_device_type type; /**< Type of device (Input/Output). */
cubeb_device_state state; /**< State of device disabled/enabled/unplugged. */
cubeb_device_pref preferred;/**< Preferred device. */
cubeb_device_fmt format; /**< Sample format supported. */
cubeb_device_fmt default_format; /**< The default sample format for this device. */
unsigned int max_channels; /**< Channels. */
unsigned int default_rate; /**< Default/Preferred sample rate. */
unsigned int max_rate; /**< Maximum sample rate supported. */
unsigned int min_rate; /**< Minimum sample rate supported. */
unsigned int latency_lo; /**< Lowest possible latency in frames. */
unsigned int latency_hi; /**< Higest possible latency in frames. */
} cubeb_device_info;
/** Device collection.
* Returned by `cubeb_enumerate_devices` and destroyed by
* `cubeb_device_collection_destroy`. */
typedef struct {
cubeb_device_info * device; /**< Array of pointers to device info. */
size_t count; /**< Device count in collection. */
} cubeb_device_collection;
/** User supplied data callback.
- Calling other cubeb functions from this callback is unsafe.
- The code in the callback should be non-blocking.
- Returning less than the number of frames this callback asks for or
provides puts the stream in drain mode. This callback will not be called
again, and the state callback will be called with CUBEB_STATE_DRAINED when
all the frames have been output.
@param stream The stream for which this callback fired.
@param user_ptr The pointer passed to cubeb_stream_init.
@param input_buffer A pointer containing the input data, or nullptr
if this is an output-only stream.
@param output_buffer A pointer to a buffer to be filled with audio samples,
or nullptr if this is an input-only stream.
@param nframes The number of frames of the two buffer.
@retval Number of frames written to the output buffer. If this number is
less than nframes, then the stream will start to drain.
@retval CUBEB_ERROR on error, in which case the data callback will stop
and the stream will enter a shutdown state. */
typedef long (* cubeb_data_callback)(cubeb_stream * stream,
void * user_ptr,
void const * input_buffer,
void * output_buffer,
long nframes);
/** User supplied state callback.
@param stream The stream for this this callback fired.
@param user_ptr The pointer passed to cubeb_stream_init.
@param state The new state of the stream. */
typedef void (* cubeb_state_callback)(cubeb_stream * stream,
void * user_ptr,
cubeb_state state);
/**
* User supplied callback called when the underlying device changed.
* @param user The pointer passed to cubeb_stream_init. */
typedef void (* cubeb_device_changed_callback)(void * user_ptr);
/**
* User supplied callback called when the underlying device collection changed.
* @param context A pointer to the cubeb context.
* @param user_ptr The pointer passed to cubeb_stream_init. */
typedef void (* cubeb_device_collection_changed_callback)(cubeb * context,
void * user_ptr);
/** User supplied callback called when a message needs logging. */
typedef void (* cubeb_log_callback)(char const * fmt, ...);
/** Initialize an application context. This will perform any library or
application scoped initialization.
@param context A out param where an opaque pointer to the application
context will be returned.
@param context_name A name for the context. Depending on the platform this
can appear in different locations.
@param backend_name The name of the cubeb backend user desires to select.
Accepted values self-documented in cubeb.c: init_oneshot
If NULL, a default ordering is used for backend choice.
A valid choice overrides all other possible backends,
so long as the backend was included at compile time.
@retval CUBEB_OK in case of success.
@retval CUBEB_ERROR in case of error, for example because the host
has no audio hardware. */
CUBEB_EXPORT int cubeb_init(cubeb ** context, char const * context_name,
char const * backend_name);
/** Get a read-only string identifying this context's current backend.
@param context A pointer to the cubeb context.
@retval Read-only string identifying current backend. */
CUBEB_EXPORT char const * cubeb_get_backend_id(cubeb * context);
/** Get the maximum possible number of channels.
@param context A pointer to the cubeb context.
@param max_channels The maximum number of channels.
@retval CUBEB_OK
@retval CUBEB_ERROR_INVALID_PARAMETER
@retval CUBEB_ERROR_NOT_SUPPORTED
@retval CUBEB_ERROR */
CUBEB_EXPORT int cubeb_get_max_channel_count(cubeb * context, uint32_t * max_channels);
/** Get the minimal latency value, in frames, that is guaranteed to work
when creating a stream for the specified sample rate. This is platform,
hardware and backend dependent.
@param context A pointer to the cubeb context.
@param params On some backends, the minimum achievable latency depends on
the characteristics of the stream.
@param latency_frames The latency value, in frames, to pass to
cubeb_stream_init.
@retval CUBEB_OK
@retval CUBEB_ERROR_INVALID_PARAMETER
@retval CUBEB_ERROR_NOT_SUPPORTED */
CUBEB_EXPORT int cubeb_get_min_latency(cubeb * context,
cubeb_stream_params params,
uint32_t * latency_frames);
/** Get the preferred sample rate for this backend: this is hardware and
platform dependent, and can avoid resampling, and/or trigger fastpaths.
@param context A pointer to the cubeb context.
@param rate The samplerate (in Hz) the current configuration prefers.
@retval CUBEB_OK
@retval CUBEB_ERROR_INVALID_PARAMETER
@retval CUBEB_ERROR_NOT_SUPPORTED */
CUBEB_EXPORT int cubeb_get_preferred_sample_rate(cubeb * context, uint32_t * rate);
/** Get the preferred layout for this backend: this is hardware and
platform dependent.
@param context A pointer to the cubeb context.
@param layout The layout of the current speaker configuration.
@retval CUBEB_OK
@retval CUBEB_ERROR_INVALID_PARAMETER
@retval CUBEB_ERROR_NOT_SUPPORTED */
CUBEB_EXPORT int cubeb_get_preferred_channel_layout(cubeb * context, cubeb_channel_layout * layout);
/** Destroy an application context. This must be called after all stream have
* been destroyed.
@param context A pointer to the cubeb context.*/
CUBEB_EXPORT void cubeb_destroy(cubeb * context);
/** Initialize a stream associated with the supplied application context.
@param context A pointer to the cubeb context.
@param stream An out parameter to be filled with the an opaque pointer to a
cubeb stream.
@param stream_name A name for this stream.
@param input_device Device for the input side of the stream. If NULL the
default input device is used.
@param input_stream_params Parameters for the input side of the stream, or
NULL if this stream is output only.
@param output_device Device for the output side of the stream. If NULL the
default output device is used.
@param output_stream_params Parameters for the output side of the stream, or
NULL if this stream is input only.
@param latency_frames Stream latency in frames. Valid range
is [1, 96000].
@param data_callback Will be called to preroll data before playback is
started by cubeb_stream_start.
@param state_callback A pointer to a state callback.
@param user_ptr A pointer that will be passed to the callbacks. This pointer
must outlive the life time of the stream.
@retval CUBEB_OK
@retval CUBEB_ERROR
@retval CUBEB_ERROR_INVALID_FORMAT
@retval CUBEB_ERROR_DEVICE_UNAVAILABLE */
CUBEB_EXPORT int cubeb_stream_init(cubeb * context,
cubeb_stream ** stream,
char const * stream_name,
cubeb_devid input_device,
cubeb_stream_params * input_stream_params,
cubeb_devid output_device,
cubeb_stream_params * output_stream_params,
unsigned int latency_frames,
cubeb_data_callback data_callback,
cubeb_state_callback state_callback,
void * user_ptr);
/** Destroy a stream. `cubeb_stream_stop` MUST be called before destroying a
stream.
@param stream The stream to destroy. */
CUBEB_EXPORT void cubeb_stream_destroy(cubeb_stream * stream);
/** Start playback.
@param stream
@retval CUBEB_OK
@retval CUBEB_ERROR */
CUBEB_EXPORT int cubeb_stream_start(cubeb_stream * stream);
/** Stop playback.
@param stream
@retval CUBEB_OK
@retval CUBEB_ERROR */
CUBEB_EXPORT int cubeb_stream_stop(cubeb_stream * stream);
/** Get the current stream playback position.
@param stream
@param position Playback position in frames.
@retval CUBEB_OK
@retval CUBEB_ERROR */
CUBEB_EXPORT int cubeb_stream_get_position(cubeb_stream * stream, uint64_t * position);
/** Get the latency for this stream, in frames. This is the number of frames
between the time cubeb acquires the data in the callback and the listener
can hear the sound.
@param stream
@param latency Current approximate stream latency in frames.
@retval CUBEB_OK
@retval CUBEB_ERROR_NOT_SUPPORTED
@retval CUBEB_ERROR */
CUBEB_EXPORT int cubeb_stream_get_latency(cubeb_stream * stream, uint32_t * latency);
/** Set the volume for a stream.
@param stream the stream for which to adjust the volume.
@param volume a float between 0.0 (muted) and 1.0 (maximum volume)
@retval CUBEB_OK
@retval CUBEB_ERROR_INVALID_PARAMETER volume is outside [0.0, 1.0] or
stream is an invalid pointer
@retval CUBEB_ERROR_NOT_SUPPORTED */
CUBEB_EXPORT int cubeb_stream_set_volume(cubeb_stream * stream, float volume);
/** If the stream is stereo, set the left/right panning. If the stream is mono,
this has no effect.
@param stream the stream for which to change the panning
@param panning a number from -1.0 to 1.0. -1.0 means that the stream is
fully mixed in the left channel, 1.0 means the stream is fully
mixed in the right channel. 0.0 is equal power in the right and
left channel (default).
@retval CUBEB_OK
@retval CUBEB_ERROR_INVALID_PARAMETER if stream is null or if panning is
outside the [-1.0, 1.0] range.
@retval CUBEB_ERROR_NOT_SUPPORTED
@retval CUBEB_ERROR stream is not mono nor stereo */
CUBEB_EXPORT int cubeb_stream_set_panning(cubeb_stream * stream, float panning);
/** Get the current output device for this stream.
@param stm the stream for which to query the current output device
@param device a pointer in which the current output device will be stored.
@retval CUBEB_OK in case of success
@retval CUBEB_ERROR_INVALID_PARAMETER if either stm, device or count are
invalid pointers
@retval CUBEB_ERROR_NOT_SUPPORTED */
CUBEB_EXPORT int cubeb_stream_get_current_device(cubeb_stream * stm,
cubeb_device ** const device);
/** Destroy a cubeb_device structure.
@param stream the stream passed in cubeb_stream_get_current_device
@param devices the devices to destroy
@retval CUBEB_OK in case of success
@retval CUBEB_ERROR_INVALID_PARAMETER if devices is an invalid pointer
@retval CUBEB_ERROR_NOT_SUPPORTED */
CUBEB_EXPORT int cubeb_stream_device_destroy(cubeb_stream * stream,
cubeb_device * devices);
/** Set a callback to be notified when the output device changes.
@param stream the stream for which to set the callback.
@param device_changed_callback a function called whenever the device has
changed. Passing NULL allow to unregister a function
@retval CUBEB_OK
@retval CUBEB_ERROR_INVALID_PARAMETER if either stream or
device_changed_callback are invalid pointers.
@retval CUBEB_ERROR_NOT_SUPPORTED */
CUBEB_EXPORT int cubeb_stream_register_device_changed_callback(cubeb_stream * stream,
cubeb_device_changed_callback device_changed_callback);
/** Returns enumerated devices.
@param context
@param devtype device type to include
@param collection output collection. Must be destroyed with cubeb_device_collection_destroy
@retval CUBEB_OK in case of success
@retval CUBEB_ERROR_INVALID_PARAMETER if collection is an invalid pointer
@retval CUBEB_ERROR_NOT_SUPPORTED */
CUBEB_EXPORT int cubeb_enumerate_devices(cubeb * context,
cubeb_device_type devtype,
cubeb_device_collection * collection);
/** Destroy a cubeb_device_collection, and its `cubeb_device_info`.
@param context
@param collection collection to destroy
@retval CUBEB_OK
@retval CUBEB_ERROR_INVALID_PARAMETER if collection is an invalid pointer */
CUBEB_EXPORT int cubeb_device_collection_destroy(cubeb * context,
cubeb_device_collection * collection);
/** Registers a callback which is called when the system detects
a new device or a device is removed.
@param context
@param devtype device type to include
@param callback a function called whenever the system device list changes.
Passing NULL allow to unregister a function
@param user_ptr pointer to user specified data which will be present in
subsequent callbacks.
@retval CUBEB_ERROR_NOT_SUPPORTED */
CUBEB_EXPORT int cubeb_register_device_collection_changed(cubeb * context,
cubeb_device_type devtype,
cubeb_device_collection_changed_callback callback,
void * user_ptr);
/** Set a callback to be called with a message.
@param log_level CUBEB_LOG_VERBOSE, CUBEB_LOG_NORMAL.
@param log_callback A function called with a message when there is
something to log. Pass NULL to unregister.
@retval CUBEB_OK in case of success.
@retval CUBEB_ERROR_INVALID_PARAMETER if either context or log_callback are
invalid pointers, or if level is not
in cubeb_log_level. */
CUBEB_EXPORT int cubeb_set_log_callback(cubeb_log_level log_level,
cubeb_log_callback log_callback);
#if defined(__cplusplus)
}
#endif
#endif /* CUBEB_c2f983e9_c96f_e71c_72c3_bbf62992a382 */

84
Externals/cubeb/msvc/cubeb.vcxproj vendored Normal file
View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{8EA11166-6512-44FC-B7A5-A4D1ECC81170}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\Source\VSProps\Base.props" />
<Import Project="..\..\..\Source\VSProps\ClDisableAllWarnings.props" />
</ImportGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>../include;../src;../msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_MBCS;_CRT_SECURE_NO_WARNINGS;WIN32;USE_WASAPI;USE_WINMM;OUTSIDE_SPEEX;FLOATING_POINT;RANDOM_PREFIX=speex;EXPORT=;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\include\cubeb\cubeb.h" />
<ClInclude Include="..\msvc\cubeb_export.h" />
<ClInclude Include="..\src\cubeb-internal.h" />
<ClInclude Include="..\src\cubeb-speex-resampler.h" />
<ClInclude Include="..\src\cubeb_array_queue.h" />
<ClInclude Include="..\src\cubeb_assert.h" />
<ClInclude Include="..\src\cubeb_log.h" />
<ClInclude Include="..\src\cubeb_mixer.h" />
<ClInclude Include="..\src\cubeb_panner.h" />
<ClInclude Include="..\src\cubeb_resampler.h" />
<ClInclude Include="..\src\cubeb_resampler_internal.h" />
<ClInclude Include="..\src\cubeb_ringbuffer.h" />
<ClInclude Include="..\src\cubeb_ring_array.h" />
<ClInclude Include="..\src\cubeb_utils.h" />
<ClInclude Include="..\src\cubeb_utils_unix.h" />
<ClInclude Include="..\src\cubeb_utils_win.h" />
<ClInclude Include="..\src\speex\arch.h" />
<ClInclude Include="..\src\speex\fixed_generic.h" />
<ClInclude Include="..\src\speex\resample_neon.h" />
<ClInclude Include="..\src\speex\resample_sse.h" />
<ClInclude Include="..\src\speex\speex_config_types.h" />
<ClInclude Include="..\src\speex\speex_resampler.h" />
<ClInclude Include="..\src\speex\stack_alloc.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\cubeb.c" />
<ClCompile Include="..\src\cubeb_log.cpp" />
<ClCompile Include="..\src\cubeb_mixer.cpp" />
<ClCompile Include="..\src\cubeb_panner.cpp" />
<ClCompile Include="..\src\cubeb_resampler.cpp" />
<ClCompile Include="..\src\cubeb_utils.c" />
<ClCompile Include="..\src\cubeb_wasapi.cpp" />
<ClCompile Include="..\src\cubeb_winmm.c" />
<ClCompile Include="..\src\speex\resample.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClInclude Include="..\include\cubeb\cubeb.h" />
<ClInclude Include="..\src\cubeb_array_queue.h" />
<ClInclude Include="..\src\cubeb_assert.h" />
<ClInclude Include="..\src\cubeb_log.h" />
<ClInclude Include="..\src\cubeb_mixer.h" />
<ClInclude Include="..\src\cubeb_panner.h" />
<ClInclude Include="..\src\cubeb_resampler.h" />
<ClInclude Include="..\src\cubeb_resampler_internal.h" />
<ClInclude Include="..\src\cubeb_ring_array.h" />
<ClInclude Include="..\src\cubeb_ringbuffer.h" />
<ClInclude Include="..\src\cubeb_utils.h" />
<ClInclude Include="..\src\cubeb_utils_unix.h" />
<ClInclude Include="..\src\cubeb_utils_win.h" />
<ClInclude Include="..\src\cubeb-internal.h" />
<ClInclude Include="..\src\cubeb-speex-resampler.h" />
<ClInclude Include="..\src\speex\arch.h">
<Filter>speex</Filter>
</ClInclude>
<ClInclude Include="..\src\speex\fixed_generic.h">
<Filter>speex</Filter>
</ClInclude>
<ClInclude Include="..\src\speex\resample_neon.h">
<Filter>speex</Filter>
</ClInclude>
<ClInclude Include="..\src\speex\resample_sse.h">
<Filter>speex</Filter>
</ClInclude>
<ClInclude Include="..\src\speex\speex_config_types.h">
<Filter>speex</Filter>
</ClInclude>
<ClInclude Include="..\src\speex\speex_resampler.h">
<Filter>speex</Filter>
</ClInclude>
<ClInclude Include="..\src\speex\stack_alloc.h">
<Filter>speex</Filter>
</ClInclude>
<ClInclude Include="..\msvc\cubeb_export.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\cubeb.c" />
<ClCompile Include="..\src\cubeb_log.cpp" />
<ClCompile Include="..\src\cubeb_mixer.cpp" />
<ClCompile Include="..\src\cubeb_panner.cpp" />
<ClCompile Include="..\src\cubeb_resampler.cpp" />
<ClCompile Include="..\src\cubeb_utils.c" />
<ClCompile Include="..\src\cubeb_wasapi.cpp" />
<ClCompile Include="..\src\cubeb_winmm.c" />
<ClCompile Include="..\src\speex\resample.c">
<Filter>speex</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="speex">
<UniqueIdentifier>{caf7c7d0-0918-4299-8423-b287285d6fd0}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

7
Externals/cubeb/msvc/cubeb_export.h vendored Normal file
View File

@ -0,0 +1,7 @@
#ifndef CUBEB_EXPORT_H
#define CUBEB_EXPORT_H
#define CUBEB_EXPORT
#define CUBEB_NO_EXPORT
#endif

View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdint.h>
/*
* The following definitions are copied from the android sources. Only the
* relevant enum member and values needed are copied.
*/
/*
* From https://android.googlesource.com/platform/frameworks/base/+/android-2.2.3_r2.1/include/utils/Errors.h
*/
typedef int32_t status_t;
/*
* From https://android.googlesource.com/platform/frameworks/base/+/android-2.2.3_r2.1/include/media/AudioTrack.h
*/
struct Buffer {
uint32_t flags;
int channelCount;
int format;
size_t frameCount;
size_t size;
union {
void* raw;
short* i16;
int8_t* i8;
};
};
enum event_type {
EVENT_MORE_DATA = 0,
EVENT_UNDERRUN = 1,
EVENT_LOOP_END = 2,
EVENT_MARKER = 3,
EVENT_NEW_POS = 4,
EVENT_BUFFER_END = 5
};
/**
* From https://android.googlesource.com/platform/frameworks/base/+/android-2.2.3_r2.1/include/media/AudioSystem.h
* and
* https://android.googlesource.com/platform/system/core/+/android-4.2.2_r1/include/system/audio.h
*/
#define AUDIO_STREAM_TYPE_MUSIC 3
enum {
AUDIO_CHANNEL_OUT_FRONT_LEFT_ICS = 0x1,
AUDIO_CHANNEL_OUT_FRONT_RIGHT_ICS = 0x2,
AUDIO_CHANNEL_OUT_MONO_ICS = AUDIO_CHANNEL_OUT_FRONT_LEFT_ICS,
AUDIO_CHANNEL_OUT_STEREO_ICS = (AUDIO_CHANNEL_OUT_FRONT_LEFT_ICS | AUDIO_CHANNEL_OUT_FRONT_RIGHT_ICS)
} AudioTrack_ChannelMapping_ICS;
enum {
AUDIO_CHANNEL_OUT_FRONT_LEFT_Legacy = 0x4,
AUDIO_CHANNEL_OUT_FRONT_RIGHT_Legacy = 0x8,
AUDIO_CHANNEL_OUT_MONO_Legacy = AUDIO_CHANNEL_OUT_FRONT_LEFT_Legacy,
AUDIO_CHANNEL_OUT_STEREO_Legacy = (AUDIO_CHANNEL_OUT_FRONT_LEFT_Legacy | AUDIO_CHANNEL_OUT_FRONT_RIGHT_Legacy)
} AudioTrack_ChannelMapping_Legacy;
typedef enum {
AUDIO_FORMAT_PCM = 0x00000000,
AUDIO_FORMAT_PCM_SUB_16_BIT = 0x1,
AUDIO_FORMAT_PCM_16_BIT = (AUDIO_FORMAT_PCM | AUDIO_FORMAT_PCM_SUB_16_BIT),
} AudioTrack_SampleType;

View File

@ -0,0 +1,77 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This file is similar to the file "OpenSLES_AndroidConfiguration.h" found in
* the Android NDK, but removes the #ifdef __cplusplus defines, so we can keep
* using a C compiler in cubeb.
*/
#ifndef OPENSL_ES_ANDROIDCONFIGURATION_H_
#define OPENSL_ES_ANDROIDCONFIGURATION_H_
/*---------------------------------------------------------------------------*/
/* Android AudioRecorder configuration */
/*---------------------------------------------------------------------------*/
/** Audio recording preset */
/** Audio recording preset key */
#define SL_ANDROID_KEY_RECORDING_PRESET ((const SLchar*) "androidRecordingPreset")
/** Audio recording preset values */
/** preset "none" cannot be set, it is used to indicate the current settings
* do not match any of the presets. */
#define SL_ANDROID_RECORDING_PRESET_NONE ((SLuint32) 0x00000000)
/** generic recording configuration on the platform */
#define SL_ANDROID_RECORDING_PRESET_GENERIC ((SLuint32) 0x00000001)
/** uses the microphone audio source with the same orientation as the camera
* if available, the main device microphone otherwise */
#define SL_ANDROID_RECORDING_PRESET_CAMCORDER ((SLuint32) 0x00000002)
/** uses the main microphone tuned for voice recognition */
#define SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION ((SLuint32) 0x00000003)
/** uses the main microphone tuned for audio communications */
#define SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION ((SLuint32) 0x00000004)
/** Audio recording get session ID (read only) */
/** Audio recording get session ID key */
#define SL_ANDROID_KEY_RECORDING_SESSION_ID ((const SLchar*) "androidRecordingSessionId")
/*---------------------------------------------------------------------------*/
/* Android AudioPlayer configuration */
/*---------------------------------------------------------------------------*/
/** Audio playback stream type */
/** Audio playback stream type key */
#define SL_ANDROID_KEY_STREAM_TYPE ((const SLchar*) "androidPlaybackStreamType")
/** Audio playback stream type values */
/* same as android.media.AudioManager.STREAM_VOICE_CALL */
#define SL_ANDROID_STREAM_VOICE ((SLint32) 0x00000000)
/* same as android.media.AudioManager.STREAM_SYSTEM */
#define SL_ANDROID_STREAM_SYSTEM ((SLint32) 0x00000001)
/* same as android.media.AudioManager.STREAM_RING */
#define SL_ANDROID_STREAM_RING ((SLint32) 0x00000002)
/* same as android.media.AudioManager.STREAM_MUSIC */
#define SL_ANDROID_STREAM_MEDIA ((SLint32) 0x00000003)
/* same as android.media.AudioManager.STREAM_ALARM */
#define SL_ANDROID_STREAM_ALARM ((SLint32) 0x00000004)
/* same as android.media.AudioManager.STREAM_NOTIFICATION */
#define SL_ANDROID_STREAM_NOTIFICATION ((SLint32) 0x00000005)
/* same as android.media.AudioManager.STREAM_BLUETOOTH_SCO */
#define SL_ANDROID_STREAM_BLUETOOTH_SCO ((SLint32) 0x00000006)
/* same as android.media.AudioManager.STREAM_SYSTEM_ENFORCED */
#define SL_ANDROID_STREAM_SYSTEM_ENFORCED ((SLint32) 0x00000007)
#endif /* OPENSL_ES_ANDROIDCONFIGURATION_H_ */

88
Externals/cubeb/src/cubeb-internal.h vendored Normal file
View File

@ -0,0 +1,88 @@
/*
* Copyright © 2013 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#if !defined(CUBEB_INTERNAL_0eb56756_4e20_4404_a76d_42bf88cd15a5)
#define CUBEB_INTERNAL_0eb56756_4e20_4404_a76d_42bf88cd15a5
#include "cubeb/cubeb.h"
#include "cubeb_log.h"
#include "cubeb_assert.h"
#include <stdio.h>
#include <string.h>
#ifdef __clang__
#ifndef CLANG_ANALYZER_NORETURN
#if __has_feature(attribute_analyzer_noreturn)
#define CLANG_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
#else
#define CLANG_ANALYZER_NORETURN
#endif // ifndef CLANG_ANALYZER_NORETURN
#endif // __has_feature(attribute_analyzer_noreturn)
#else // __clang__
#define CLANG_ANALYZER_NORETURN
#endif
#if defined(__cplusplus)
extern "C" {
#endif
#if defined(__cplusplus)
}
#endif
typedef struct {
char const * name;
unsigned int const channels;
cubeb_channel_layout const layout;
} cubeb_layout_map;
extern cubeb_layout_map const CUBEB_CHANNEL_LAYOUT_MAPS[CUBEB_LAYOUT_MAX];
struct cubeb_ops {
int (* init)(cubeb ** context, char const * context_name);
char const * (* get_backend_id)(cubeb * context);
int (* get_max_channel_count)(cubeb * context, uint32_t * max_channels);
int (* get_min_latency)(cubeb * context,
cubeb_stream_params params,
uint32_t * latency_ms);
int (* get_preferred_sample_rate)(cubeb * context, uint32_t * rate);
int (* get_preferred_channel_layout)(cubeb * context, cubeb_channel_layout * layout);
int (* enumerate_devices)(cubeb * context, cubeb_device_type type,
cubeb_device_collection * collection);
int (* device_collection_destroy)(cubeb * context,
cubeb_device_collection * collection);
void (* destroy)(cubeb * context);
int (* stream_init)(cubeb * context,
cubeb_stream ** stream,
char const * stream_name,
cubeb_devid input_device,
cubeb_stream_params * input_stream_params,
cubeb_devid output_device,
cubeb_stream_params * output_stream_params,
unsigned int latency,
cubeb_data_callback data_callback,
cubeb_state_callback state_callback,
void * user_ptr);
void (* stream_destroy)(cubeb_stream * stream);
int (* stream_start)(cubeb_stream * stream);
int (* stream_stop)(cubeb_stream * stream);
int (* stream_get_position)(cubeb_stream * stream, uint64_t * position);
int (* stream_get_latency)(cubeb_stream * stream, uint32_t * latency);
int (* stream_set_volume)(cubeb_stream * stream, float volumes);
int (* stream_set_panning)(cubeb_stream * stream, float panning);
int (* stream_get_current_device)(cubeb_stream * stream,
cubeb_device ** const device);
int (* stream_device_destroy)(cubeb_stream * stream,
cubeb_device * device);
int (* stream_register_device_changed_callback)(cubeb_stream * stream,
cubeb_device_changed_callback device_changed_callback);
int (* register_device_collection_changed)(cubeb * context,
cubeb_device_type devtype,
cubeb_device_collection_changed_callback callback,
void * user_ptr);
};
#endif /* CUBEB_INTERNAL_0eb56756_4e20_4404_a76d_42bf88cd15a5 */

43
Externals/cubeb/src/cubeb-sles.h vendored Normal file
View File

@ -0,0 +1,43 @@
/*
* Copyright © 2016 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#ifndef _CUBEB_SLES_H_
#define _CUBEB_SLES_H_
#include <SLES/OpenSLES.h>
static SLresult
cubeb_get_sles_engine(SLObjectItf * pEngine,
SLuint32 numOptions,
const SLEngineOption * pEngineOptions,
SLuint32 numInterfaces,
const SLInterfaceID * pInterfaceIds,
const SLboolean * pInterfaceRequired)
{
return slCreateEngine(pEngine,
numOptions,
pEngineOptions,
numInterfaces,
pInterfaceIds,
pInterfaceRequired);
}
static void
cubeb_destroy_sles_engine(SLObjectItf * self)
{
if (*self != NULL) {
(**self)->Destroy(*self);
*self = NULL;
}
}
static SLresult
cubeb_realize_sles_engine(SLObjectItf self)
{
return (*self)->Realize(self, SL_BOOLEAN_FALSE);
}
#endif

View File

@ -0,0 +1 @@
#include <speex/speex_resampler.h>

630
Externals/cubeb/src/cubeb.c vendored Normal file
View File

@ -0,0 +1,630 @@
/*
* Copyright © 2013 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#undef NDEBUG
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "cubeb/cubeb.h"
#include "cubeb-internal.h"
#define NELEMS(x) ((int) (sizeof(x) / sizeof(x[0])))
struct cubeb {
struct cubeb_ops * ops;
};
struct cubeb_stream {
struct cubeb * context;
};
#if defined(USE_PULSE)
int pulse_init(cubeb ** context, char const * context_name);
#endif
#if defined(USE_PULSE_RUST)
int pulse_rust_init(cubeb ** contet, char const * context_name);
#endif
#if defined(USE_JACK)
int jack_init (cubeb ** context, char const * context_name);
#endif
#if defined(USE_ALSA)
int alsa_init(cubeb ** context, char const * context_name);
#endif
#if defined(USE_AUDIOUNIT)
int audiounit_init(cubeb ** context, char const * context_name);
#endif
#if defined(USE_WINMM)
int winmm_init(cubeb ** context, char const * context_name);
#endif
#if defined(USE_WASAPI)
int wasapi_init(cubeb ** context, char const * context_name);
#endif
#if defined(USE_SNDIO)
int sndio_init(cubeb ** context, char const * context_name);
#endif
#if defined(USE_OPENSL)
int opensl_init(cubeb ** context, char const * context_name);
#endif
#if defined(USE_AUDIOTRACK)
int audiotrack_init(cubeb ** context, char const * context_name);
#endif
#if defined(USE_KAI)
int kai_init(cubeb ** context, char const * context_name);
#endif
static int
validate_stream_params(cubeb_stream_params * input_stream_params,
cubeb_stream_params * output_stream_params)
{
XASSERT(input_stream_params || output_stream_params);
if (output_stream_params) {
if (output_stream_params->rate < 1000 || output_stream_params->rate > 192000 ||
output_stream_params->channels < 1 || output_stream_params->channels > 8) {
return CUBEB_ERROR_INVALID_FORMAT;
}
}
if (input_stream_params) {
if (input_stream_params->rate < 1000 || input_stream_params->rate > 192000 ||
input_stream_params->channels < 1 || input_stream_params->channels > 8) {
return CUBEB_ERROR_INVALID_FORMAT;
}
}
// Rate and sample format must be the same for input and output, if using a
// duplex stream
if (input_stream_params && output_stream_params) {
if (input_stream_params->rate != output_stream_params->rate ||
input_stream_params->format != output_stream_params->format) {
return CUBEB_ERROR_INVALID_FORMAT;
}
}
cubeb_stream_params * params = input_stream_params ?
input_stream_params : output_stream_params;
switch (params->format) {
case CUBEB_SAMPLE_S16LE:
case CUBEB_SAMPLE_S16BE:
case CUBEB_SAMPLE_FLOAT32LE:
case CUBEB_SAMPLE_FLOAT32BE:
return CUBEB_OK;
}
return CUBEB_ERROR_INVALID_FORMAT;
}
static int
validate_latency(int latency)
{
if (latency < 1 || latency > 96000) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
return CUBEB_OK;
}
int
cubeb_init(cubeb ** context, char const * context_name, char const * backend_name)
{
int (* init_oneshot)(cubeb **, char const *) = NULL;
if (backend_name != NULL) {
if (!strcmp(backend_name, "pulse")) {
#if defined(USE_PULSE)
init_oneshot = pulse_init;
#endif
} else if (!strcmp(backend_name, "pulse-rust")) {
#if defined(USE_PULSE_RUST)
init_oneshot = pulse_rust_init;
#endif
} else if (!strcmp(backend_name, "jack")) {
#if defined(USE_JACK)
init_oneshot = jack_init;
#endif
} else if (!strcmp(backend_name, "alsa")) {
#if defined(USE_ALSA)
init_oneshot = alsa_init;
#endif
} else if (!strcmp(backend_name, "audiounit")) {
#if defined(USE_AUDIOUNIT)
init_oneshot = audiounit_init;
#endif
} else if (!strcmp(backend_name, "wasapi")) {
#if defined(USE_WASAPI)
init_oneshot = wasapi_init;
#endif
} else if (!strcmp(backend_name, "winmm")) {
#if defined(USE_WINMM)
init_oneshot = winmm_init;
#endif
} else if (!strcmp(backend_name, "sndio")) {
#if defined(USE_SNDIO)
init_oneshot = sndio_init;
#endif
} else if (!strcmp(backend_name, "opensl")) {
#if defined(USE_OPENSL)
init_oneshot = opensl_init;
#endif
} else if (!strcmp(backend_name, "audiotrack")) {
#if defined(USE_AUDIOTRACK)
init_oneshot = audiotrack_init;
#endif
} else if (!strcmp(backend_name, "kai")) {
#if defined(USE_KAI)
init_oneshot = kai_init;
#endif
} else {
/* Already set */
}
}
int (* default_init[])(cubeb **, char const *) = {
/*
* init_oneshot must be at the top to allow user
* to override all other choices
*/
init_oneshot,
#if defined(USE_PULSE)
pulse_init,
#endif
#if defined(USE_JACK)
jack_init,
#endif
#if defined(USE_ALSA)
alsa_init,
#endif
#if defined(USE_AUDIOUNIT)
audiounit_init,
#endif
#if defined(USE_WASAPI)
wasapi_init,
#endif
#if defined(USE_WINMM)
winmm_init,
#endif
#if defined(USE_SNDIO)
sndio_init,
#endif
#if defined(USE_OPENSL)
opensl_init,
#endif
#if defined(USE_AUDIOTRACK)
audiotrack_init,
#endif
#if defined(USE_KAI)
kai_init,
#endif
};
int i;
if (!context) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
#define OK(fn) assert((* context)->ops->fn)
for (i = 0; i < NELEMS(default_init); ++i) {
if (default_init[i] && default_init[i](context, context_name) == CUBEB_OK) {
/* Assert that the minimal API is implemented. */
OK(get_backend_id);
OK(destroy);
OK(stream_init);
OK(stream_destroy);
OK(stream_start);
OK(stream_stop);
OK(stream_get_position);
return CUBEB_OK;
}
}
return CUBEB_ERROR;
}
char const *
cubeb_get_backend_id(cubeb * context)
{
if (!context) {
return NULL;
}
return context->ops->get_backend_id(context);
}
int
cubeb_get_max_channel_count(cubeb * context, uint32_t * max_channels)
{
if (!context || !max_channels) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (!context->ops->get_max_channel_count) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return context->ops->get_max_channel_count(context, max_channels);
}
int
cubeb_get_min_latency(cubeb * context, cubeb_stream_params params, uint32_t * latency_ms)
{
if (!context || !latency_ms) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (!context->ops->get_min_latency) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return context->ops->get_min_latency(context, params, latency_ms);
}
int
cubeb_get_preferred_sample_rate(cubeb * context, uint32_t * rate)
{
if (!context || !rate) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (!context->ops->get_preferred_sample_rate) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return context->ops->get_preferred_sample_rate(context, rate);
}
int
cubeb_get_preferred_channel_layout(cubeb * context, cubeb_channel_layout * layout)
{
if (!context || !layout) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (!context->ops->get_preferred_channel_layout) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return context->ops->get_preferred_channel_layout(context, layout);
}
void
cubeb_destroy(cubeb * context)
{
if (!context) {
return;
}
context->ops->destroy(context);
}
int
cubeb_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_name,
cubeb_devid input_device,
cubeb_stream_params * input_stream_params,
cubeb_devid output_device,
cubeb_stream_params * output_stream_params,
unsigned int latency,
cubeb_data_callback data_callback,
cubeb_state_callback state_callback,
void * user_ptr)
{
int r;
if (!context || !stream) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
if ((r = validate_stream_params(input_stream_params, output_stream_params)) != CUBEB_OK ||
(r = validate_latency(latency)) != CUBEB_OK) {
return r;
}
r = context->ops->stream_init(context, stream, stream_name,
input_device,
input_stream_params,
output_device,
output_stream_params,
latency,
data_callback,
state_callback,
user_ptr);
if (r == CUBEB_ERROR_INVALID_FORMAT) {
LOG("Invalid format, %p %p %d %d",
output_stream_params, input_stream_params,
output_stream_params && output_stream_params->format,
input_stream_params && input_stream_params->format);
}
return r;
}
void
cubeb_stream_destroy(cubeb_stream * stream)
{
if (!stream) {
return;
}
stream->context->ops->stream_destroy(stream);
}
int
cubeb_stream_start(cubeb_stream * stream)
{
if (!stream) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
return stream->context->ops->stream_start(stream);
}
int
cubeb_stream_stop(cubeb_stream * stream)
{
if (!stream) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
return stream->context->ops->stream_stop(stream);
}
int
cubeb_stream_get_position(cubeb_stream * stream, uint64_t * position)
{
if (!stream || !position) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
return stream->context->ops->stream_get_position(stream, position);
}
int
cubeb_stream_get_latency(cubeb_stream * stream, uint32_t * latency)
{
if (!stream || !latency) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (!stream->context->ops->stream_get_latency) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return stream->context->ops->stream_get_latency(stream, latency);
}
int
cubeb_stream_set_volume(cubeb_stream * stream, float volume)
{
if (!stream || volume > 1.0 || volume < 0.0) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (!stream->context->ops->stream_set_volume) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return stream->context->ops->stream_set_volume(stream, volume);
}
int cubeb_stream_set_panning(cubeb_stream * stream, float panning)
{
if (!stream || panning < -1.0 || panning > 1.0) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (!stream->context->ops->stream_set_panning) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return stream->context->ops->stream_set_panning(stream, panning);
}
int cubeb_stream_get_current_device(cubeb_stream * stream,
cubeb_device ** const device)
{
if (!stream || !device) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (!stream->context->ops->stream_get_current_device) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return stream->context->ops->stream_get_current_device(stream, device);
}
int cubeb_stream_device_destroy(cubeb_stream * stream,
cubeb_device * device)
{
if (!stream || !device) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (!stream->context->ops->stream_device_destroy) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return stream->context->ops->stream_device_destroy(stream, device);
}
int cubeb_stream_register_device_changed_callback(cubeb_stream * stream,
cubeb_device_changed_callback device_changed_callback)
{
if (!stream) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (!stream->context->ops->stream_register_device_changed_callback) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return stream->context->ops->stream_register_device_changed_callback(stream, device_changed_callback);
}
static
void log_device(cubeb_device_info * device_info)
{
char devfmts[128] = "";
const char * devtype, * devstate, * devdeffmt;
switch (device_info->type) {
case CUBEB_DEVICE_TYPE_INPUT:
devtype = "input";
break;
case CUBEB_DEVICE_TYPE_OUTPUT:
devtype = "output";
break;
case CUBEB_DEVICE_TYPE_UNKNOWN:
default:
devtype = "unknown?";
break;
};
switch (device_info->state) {
case CUBEB_DEVICE_STATE_DISABLED:
devstate = "disabled";
break;
case CUBEB_DEVICE_STATE_UNPLUGGED:
devstate = "unplugged";
break;
case CUBEB_DEVICE_STATE_ENABLED:
devstate = "enabled";
break;
default:
devstate = "unknown?";
break;
};
switch (device_info->default_format) {
case CUBEB_DEVICE_FMT_S16LE:
devdeffmt = "S16LE";
break;
case CUBEB_DEVICE_FMT_S16BE:
devdeffmt = "S16BE";
break;
case CUBEB_DEVICE_FMT_F32LE:
devdeffmt = "F32LE";
break;
case CUBEB_DEVICE_FMT_F32BE:
devdeffmt = "F32BE";
break;
default:
devdeffmt = "unknown?";
break;
};
if (device_info->format & CUBEB_DEVICE_FMT_S16LE) {
strcat(devfmts, " S16LE");
}
if (device_info->format & CUBEB_DEVICE_FMT_S16BE) {
strcat(devfmts, " S16BE");
}
if (device_info->format & CUBEB_DEVICE_FMT_F32LE) {
strcat(devfmts, " F32LE");
}
if (device_info->format & CUBEB_DEVICE_FMT_F32BE) {
strcat(devfmts, " F32BE");
}
LOG("DeviceID: \"%s\"%s\n"
"\tName:\t\"%s\"\n"
"\tGroup:\t\"%s\"\n"
"\tVendor:\t\"%s\"\n"
"\tType:\t%s\n"
"\tState:\t%s\n"
"\tMaximum channels:\t%u\n"
"\tFormat:\t%s (0x%x) (default: %s)\n"
"\tRate:\t[%u, %u] (default: %u)\n"
"\tLatency: lo %u frames, hi %u frames",
device_info->device_id, device_info->preferred ? " (PREFERRED)" : "",
device_info->friendly_name,
device_info->group_id,
device_info->vendor_name,
devtype,
devstate,
device_info->max_channels,
(devfmts[0] == '\0') ? devfmts : devfmts + 1, (unsigned int)device_info->format, devdeffmt,
device_info->min_rate, device_info->max_rate, device_info->default_rate,
device_info->latency_lo, device_info->latency_hi);
}
int cubeb_enumerate_devices(cubeb * context,
cubeb_device_type devtype,
cubeb_device_collection * collection)
{
int rv;
if ((devtype & (CUBEB_DEVICE_TYPE_INPUT | CUBEB_DEVICE_TYPE_OUTPUT)) == 0)
return CUBEB_ERROR_INVALID_PARAMETER;
if (collection == NULL)
return CUBEB_ERROR_INVALID_PARAMETER;
if (!context->ops->enumerate_devices)
return CUBEB_ERROR_NOT_SUPPORTED;
rv = context->ops->enumerate_devices(context, devtype, collection);
if (g_cubeb_log_callback) {
for (size_t i = 0; i < collection->count; i++) {
log_device(&collection->device[i]);
}
}
return rv;
}
int cubeb_device_collection_destroy(cubeb * context,
cubeb_device_collection * collection)
{
if (context == NULL || collection == NULL)
return CUBEB_ERROR_INVALID_PARAMETER;
if (!context->ops->device_collection_destroy)
return CUBEB_ERROR_NOT_SUPPORTED;
return context->ops->device_collection_destroy(context, collection);
}
int cubeb_register_device_collection_changed(cubeb * context,
cubeb_device_type devtype,
cubeb_device_collection_changed_callback callback,
void * user_ptr)
{
if (context == NULL || (devtype & (CUBEB_DEVICE_TYPE_INPUT | CUBEB_DEVICE_TYPE_OUTPUT)) == 0)
return CUBEB_ERROR_INVALID_PARAMETER;
if (!context->ops->register_device_collection_changed) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return context->ops->register_device_collection_changed(context, devtype, callback, user_ptr);
}
int cubeb_set_log_callback(cubeb_log_level log_level,
cubeb_log_callback log_callback)
{
if (log_level < CUBEB_LOG_DISABLED || log_level > CUBEB_LOG_VERBOSE) {
return CUBEB_ERROR_INVALID_FORMAT;
}
if (!log_callback && log_level != CUBEB_LOG_DISABLED) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (g_cubeb_log_callback && log_callback) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
g_cubeb_log_callback = log_callback;
g_cubeb_log_level = log_level;
// Logging a message here allows to initialize the asynchronous logger from a
// thread that is not the audio rendering thread, and especially to not
// initialize it the first time we find a verbose log, which is often in the
// audio rendering callback, that runs from the audio rendering thread, and
// that is high priority, and that we don't want to block.
if (log_level >= CUBEB_LOG_VERBOSE) {
ALOGV("Starting cubeb log");
}
return CUBEB_OK;
}

1372
Externals/cubeb/src/cubeb_alsa.c vendored Normal file

File diff suppressed because it is too large Load Diff

97
Externals/cubeb/src/cubeb_array_queue.h vendored Normal file
View File

@ -0,0 +1,97 @@
/*
* Copyright © 2016 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#ifndef CUBEB_ARRAY_QUEUE_H
#define CUBEB_ARRAY_QUEUE_H
#include <assert.h>
#include <pthread.h>
#include <unistd.h>
#if defined(__cplusplus)
extern "C" {
#endif
typedef struct
{
void ** buf;
size_t num;
size_t writePos;
size_t readPos;
pthread_mutex_t mutex;
} array_queue;
array_queue * array_queue_create(size_t num)
{
assert(num != 0);
array_queue * new_queue = (array_queue*)calloc(1, sizeof(array_queue));
new_queue->buf = (void **)calloc(1, sizeof(void *) * num);
new_queue->readPos = 0;
new_queue->writePos = 0;
new_queue->num = num;
pthread_mutex_init(&new_queue->mutex, NULL);
return new_queue;
}
void array_queue_destroy(array_queue * aq)
{
assert(aq);
free(aq->buf);
pthread_mutex_destroy(&aq->mutex);
free(aq);
}
int array_queue_push(array_queue * aq, void * item)
{
assert(item);
pthread_mutex_lock(&aq->mutex);
int ret = -1;
if(aq->buf[aq->writePos % aq->num] == NULL)
{
aq->buf[aq->writePos % aq->num] = item;
aq->writePos = (aq->writePos + 1) % aq->num;
ret = 0;
}
// else queue is full
pthread_mutex_unlock(&aq->mutex);
return ret;
}
void* array_queue_pop(array_queue * aq)
{
pthread_mutex_lock(&aq->mutex);
void * value = aq->buf[aq->readPos % aq->num];
if(value)
{
aq->buf[aq->readPos % aq->num] = NULL;
aq->readPos = (aq->readPos + 1) % aq->num;
}
pthread_mutex_unlock(&aq->mutex);
return value;
}
size_t array_queue_get_size(array_queue * aq)
{
pthread_mutex_lock(&aq->mutex);
ssize_t r = aq->writePos - aq->readPos;
if (r < 0) {
r = aq->num + r;
assert(r >= 0);
}
pthread_mutex_unlock(&aq->mutex);
return (size_t)r;
}
#if defined(__cplusplus)
}
#endif
#endif //CUBE_ARRAY_QUEUE_H

26
Externals/cubeb/src/cubeb_assert.h vendored Normal file
View File

@ -0,0 +1,26 @@
/*
* Copyright © 2017 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#ifndef CUBEB_ASSERT
#define CUBEB_ASSERT
#include <stdio.h>
#include <stdlib.h>
/**
* This allow using an external release assert method. This file should only
* export a function or macro called XASSERT that aborts the program.
*/
#define XASSERT(expr) do { \
if (!(expr)) { \
fprintf(stderr, "%s:%d - fatal error: %s\n", __FILE__, __LINE__, #expr); \
abort(); \
} \
} while (0)
#endif

440
Externals/cubeb/src/cubeb_audiotrack.c vendored Normal file
View File

@ -0,0 +1,440 @@
/*
* Copyright © 2013 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#if !defined(NDEBUG)
#define NDEBUG
#endif
#include <assert.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#include <dlfcn.h>
#include <android/log.h>
#include "cubeb/cubeb.h"
#include "cubeb-internal.h"
#include "android/audiotrack_definitions.h"
#ifndef ALOG
#if defined(DEBUG) || defined(FORCE_ALOG)
#define ALOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gecko - Cubeb" , ## args)
#else
#define ALOG(args...)
#endif
#endif
/**
* A lot of bytes for safety. It should be possible to bring this down a bit. */
#define SIZE_AUDIOTRACK_INSTANCE 256
/**
* call dlsym to get the symbol |mangled_name|, handle the error and store the
* pointer in |pointer|. Because depending on Android version, we want different
* symbols, not finding a symbol is not an error. */
#define DLSYM_DLERROR(mangled_name, pointer, lib) \
do { \
pointer = dlsym(lib, mangled_name); \
if (!pointer) { \
ALOG("error while loading %stm: %stm\n", mangled_name, dlerror()); \
} else { \
ALOG("%stm: OK", mangled_name); \
} \
} while(0);
static struct cubeb_ops const audiotrack_ops;
void audiotrack_destroy(cubeb * context);
void audiotrack_stream_destroy(cubeb_stream * stream);
struct AudioTrack {
/* only available on ICS and later. The second int paramter is in fact of type audio_stream_type_t. */
/* static */ status_t (*get_min_frame_count)(int* frame_count, int stream_type, uint32_t rate);
/* if we have a recent ctor, but can't find the above symbol, we
* can get the minimum frame count with this signature, and we are
* running gingerbread. */
/* static */ status_t (*get_min_frame_count_gingerbread)(int* frame_count, int stream_type, uint32_t rate);
void* (*ctor)(void* instance, int, unsigned int, int, int, int, unsigned int, void (*)(int, void*, void*), void*, int, int);
void* (*dtor)(void* instance);
void (*start)(void* instance);
void (*pause)(void* instance);
uint32_t (*latency)(void* instance);
status_t (*check)(void* instance);
status_t (*get_position)(void* instance, uint32_t* position);
/* static */ int (*get_output_samplingrate)(int* samplerate, int stream);
status_t (*set_marker_position)(void* instance, unsigned int);
status_t (*set_volume)(void* instance, float left, float right);
};
struct cubeb {
struct cubeb_ops const * ops;
void * library;
struct AudioTrack klass;
};
struct cubeb_stream {
cubeb * context;
cubeb_stream_params params;
cubeb_data_callback data_callback;
cubeb_state_callback state_callback;
void * instance;
void * user_ptr;
/* Number of frames that have been passed to the AudioTrack callback */
long unsigned written;
int draining;
};
static void
audiotrack_refill(int event, void* user, void* info)
{
cubeb_stream * stream = user;
switch (event) {
case EVENT_MORE_DATA: {
long got = 0;
struct Buffer * b = (struct Buffer*)info;
if (stream->draining) {
return;
}
got = stream->data_callback(stream, stream->user_ptr, NULL, b->raw, b->frameCount);
stream->written += got;
if (got != (long)b->frameCount) {
stream->draining = 1;
/* set a marker so we are notified when the are done draining, that is,
* when every frame has been played by android. */
stream->context->klass.set_marker_position(stream->instance, stream->written);
}
break;
}
case EVENT_UNDERRUN:
ALOG("underrun in cubeb backend.");
break;
case EVENT_LOOP_END:
assert(0 && "We don't support the loop feature of audiotrack.");
break;
case EVENT_MARKER:
assert(stream->draining);
stream->state_callback(stream, stream->user_ptr, CUBEB_STATE_DRAINED);
break;
case EVENT_NEW_POS:
assert(0 && "We don't support the setPositionUpdatePeriod feature of audiotrack.");
break;
case EVENT_BUFFER_END:
assert(0 && "Should not happen.");
break;
}
}
/* We are running on gingerbread if we found the gingerbread signature for
* getMinFrameCount */
static int
audiotrack_version_is_gingerbread(cubeb * ctx)
{
return ctx->klass.get_min_frame_count_gingerbread != NULL;
}
int
audiotrack_get_min_frame_count(cubeb * ctx, cubeb_stream_params * params, int * min_frame_count)
{
status_t status;
/* Recent Android have a getMinFrameCount method. */
if (!audiotrack_version_is_gingerbread(ctx)) {
status = ctx->klass.get_min_frame_count(min_frame_count, params->stream_type, params->rate);
} else {
status = ctx->klass.get_min_frame_count_gingerbread(min_frame_count, params->stream_type, params->rate);
}
if (status != 0) {
ALOG("error getting the min frame count");
return CUBEB_ERROR;
}
return CUBEB_OK;
}
int
audiotrack_init(cubeb ** context, char const * context_name)
{
cubeb * ctx;
struct AudioTrack* c;
assert(context);
*context = NULL;
ctx = calloc(1, sizeof(*ctx));
assert(ctx);
/* If we use an absolute path here ("/system/lib/libmedia.so"), and on Android
* 2.2, the dlopen succeeds, all the dlsym succeed, but a segfault happens on
* the first call to a dlsym'ed function. Somehow this does not happen when
* using only the name of the library. */
ctx->library = dlopen("libmedia.so", RTLD_LAZY);
if (!ctx->library) {
ALOG("dlopen error: %s.", dlerror());
free(ctx);
return CUBEB_ERROR;
}
/* Recent Android first, then Gingerbread. */
DLSYM_DLERROR("_ZN7android10AudioTrackC1EijiiijPFviPvS1_ES1_ii", ctx->klass.ctor, ctx->library);
DLSYM_DLERROR("_ZN7android10AudioTrackD1Ev", ctx->klass.dtor, ctx->library);
DLSYM_DLERROR("_ZNK7android10AudioTrack7latencyEv", ctx->klass.latency, ctx->library);
DLSYM_DLERROR("_ZNK7android10AudioTrack9initCheckEv", ctx->klass.check, ctx->library);
DLSYM_DLERROR("_ZN7android11AudioSystem21getOutputSamplingRateEPii", ctx->klass.get_output_samplingrate, ctx->library);
/* |getMinFrameCount| is available on gingerbread and ICS with different signatures. */
DLSYM_DLERROR("_ZN7android10AudioTrack16getMinFrameCountEPi19audio_stream_type_tj", ctx->klass.get_min_frame_count, ctx->library);
if (!ctx->klass.get_min_frame_count) {
DLSYM_DLERROR("_ZN7android10AudioTrack16getMinFrameCountEPiij", ctx->klass.get_min_frame_count_gingerbread, ctx->library);
}
DLSYM_DLERROR("_ZN7android10AudioTrack5startEv", ctx->klass.start, ctx->library);
DLSYM_DLERROR("_ZN7android10AudioTrack5pauseEv", ctx->klass.pause, ctx->library);
DLSYM_DLERROR("_ZN7android10AudioTrack11getPositionEPj", ctx->klass.get_position, ctx->library);
DLSYM_DLERROR("_ZN7android10AudioTrack17setMarkerPositionEj", ctx->klass.set_marker_position, ctx->library);
DLSYM_DLERROR("_ZN7android10AudioTrack9setVolumeEff", ctx->klass.set_volume, ctx->library);
/* check that we have a combination of symbol that makes sense */
c = &ctx->klass;
if(!(c->ctor &&
c->dtor && c->latency && c->check &&
/* at least one way to get the minimum frame count to request. */
(c->get_min_frame_count ||
c->get_min_frame_count_gingerbread) &&
c->start && c->pause && c->get_position && c->set_marker_position)) {
ALOG("Could not find all the symbols we need.");
audiotrack_destroy(ctx);
return CUBEB_ERROR;
}
ctx->ops = &audiotrack_ops;
*context = ctx;
return CUBEB_OK;
}
char const *
audiotrack_get_backend_id(cubeb * context)
{
return "audiotrack";
}
static int
audiotrack_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
{
assert(ctx && max_channels);
/* The android mixer handles up to two channels, see
http://androidxref.com/4.2.2_r1/xref/frameworks/av/services/audioflinger/AudioFlinger.h#67 */
*max_channels = 2;
return CUBEB_OK;
}
static int
audiotrack_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * latency_ms)
{
/* We always use the lowest latency possible when using this backend (see
* audiotrack_stream_init), so this value is not going to be used. */
int r;
r = audiotrack_get_min_frame_count(ctx, &params, (int *)latency_ms);
if (r != CUBEB_OK) {
return CUBEB_ERROR;
}
return CUBEB_OK;
}
static int
audiotrack_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
{
status_t r;
r = ctx->klass.get_output_samplingrate((int32_t *)rate, 3 /* MUSIC */);
return r == 0 ? CUBEB_OK : CUBEB_ERROR;
}
void
audiotrack_destroy(cubeb * context)
{
assert(context);
dlclose(context->library);
free(context);
}
int
audiotrack_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name,
cubeb_devid input_device,
cubeb_stream_params * input_stream_params,
cubeb_devid output_device,
cubeb_stream_params * output_stream_params,
unsigned int latency,
cubeb_data_callback data_callback,
cubeb_state_callback state_callback,
void * user_ptr)
{
cubeb_stream * stm;
int32_t channels;
uint32_t min_frame_count;
assert(ctx && stream);
assert(!input_stream_params && "not supported");
if (input_device || output_device) {
/* Device selection not yet implemented. */
return CUBEB_ERROR_DEVICE_UNAVAILABLE;
}
if (output_stream_params->format == CUBEB_SAMPLE_FLOAT32LE ||
output_stream_params->format == CUBEB_SAMPLE_FLOAT32BE) {
return CUBEB_ERROR_INVALID_FORMAT;
}
if (audiotrack_get_min_frame_count(ctx, output_stream_params, (int *)&min_frame_count)) {
return CUBEB_ERROR;
}
stm = calloc(1, sizeof(*stm));
assert(stm);
stm->context = ctx;
stm->data_callback = data_callback;
stm->state_callback = state_callback;
stm->user_ptr = user_ptr;
stm->params = *output_stream_params;
stm->instance = calloc(SIZE_AUDIOTRACK_INSTANCE, 1);
(*(uint32_t*)((intptr_t)stm->instance + SIZE_AUDIOTRACK_INSTANCE - 4)) = 0xbaadbaad;
assert(stm->instance && "cubeb: EOM");
/* gingerbread uses old channel layout enum */
if (audiotrack_version_is_gingerbread(ctx)) {
channels = stm->params.channels == 2 ? AUDIO_CHANNEL_OUT_STEREO_Legacy : AUDIO_CHANNEL_OUT_MONO_Legacy;
} else {
channels = stm->params.channels == 2 ? AUDIO_CHANNEL_OUT_STEREO_ICS : AUDIO_CHANNEL_OUT_MONO_ICS;
}
ctx->klass.ctor(stm->instance, stm->params.stream_type, stm->params.rate,
AUDIO_FORMAT_PCM_16_BIT, channels, min_frame_count, 0,
audiotrack_refill, stm, 0, 0);
assert((*(uint32_t*)((intptr_t)stm->instance + SIZE_AUDIOTRACK_INSTANCE - 4)) == 0xbaadbaad);
if (ctx->klass.check(stm->instance)) {
ALOG("stream not initialized properly.");
audiotrack_stream_destroy(stm);
return CUBEB_ERROR;
}
*stream = stm;
return CUBEB_OK;
}
void
audiotrack_stream_destroy(cubeb_stream * stream)
{
assert(stream->context);
stream->context->klass.dtor(stream->instance);
free(stream->instance);
stream->instance = NULL;
free(stream);
}
int
audiotrack_stream_start(cubeb_stream * stream)
{
assert(stream->instance);
stream->context->klass.start(stream->instance);
stream->state_callback(stream, stream->user_ptr, CUBEB_STATE_STARTED);
return CUBEB_OK;
}
int
audiotrack_stream_stop(cubeb_stream * stream)
{
assert(stream->instance);
stream->context->klass.pause(stream->instance);
stream->state_callback(stream, stream->user_ptr, CUBEB_STATE_STOPPED);
return CUBEB_OK;
}
int
audiotrack_stream_get_position(cubeb_stream * stream, uint64_t * position)
{
uint32_t p;
assert(stream->instance && position);
stream->context->klass.get_position(stream->instance, &p);
*position = p;
return CUBEB_OK;
}
int
audiotrack_stream_get_latency(cubeb_stream * stream, uint32_t * latency)
{
assert(stream->instance && latency);
/* Android returns the latency in ms, we want it in frames. */
*latency = stream->context->klass.latency(stream->instance);
/* with rate <= 96000, we won't overflow until 44.739 seconds of latency */
*latency = (*latency * stream->params.rate) / 1000;
return 0;
}
int
audiotrack_stream_set_volume(cubeb_stream * stream, float volume)
{
status_t status;
status = stream->context->klass.set_volume(stream->instance, volume, volume);
if (status) {
return CUBEB_ERROR;
}
return CUBEB_OK;
}
static struct cubeb_ops const audiotrack_ops = {
.init = audiotrack_init,
.get_backend_id = audiotrack_get_backend_id,
.get_max_channel_count = audiotrack_get_max_channel_count,
.get_min_latency = audiotrack_get_min_latency,
.get_preferred_sample_rate = audiotrack_get_preferred_sample_rate,
.get_preferred_channel_layout = NULL,
.enumerate_devices = NULL,
.device_collection_destroy = NULL,
.destroy = audiotrack_destroy,
.stream_init = audiotrack_stream_init,
.stream_destroy = audiotrack_stream_destroy,
.stream_start = audiotrack_stream_start,
.stream_stop = audiotrack_stream_stop,
.stream_get_position = audiotrack_stream_get_position,
.stream_get_latency = audiotrack_stream_get_latency,
.stream_set_volume = audiotrack_stream_set_volume,
.stream_set_panning = NULL,
.stream_get_current_device = NULL,
.stream_device_destroy = NULL,
.stream_register_device_changed_callback = NULL,
.register_device_collection_changed = NULL
};

3350
Externals/cubeb/src/cubeb_audiounit.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

1035
Externals/cubeb/src/cubeb_jack.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

362
Externals/cubeb/src/cubeb_kai.c vendored Normal file
View File

@ -0,0 +1,362 @@
/*
* Copyright © 2015 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <sys/fmutex.h>
#include <kai.h>
#include "cubeb/cubeb.h"
#include "cubeb-internal.h"
/* We don't support more than 2 channels in KAI */
#define MAX_CHANNELS 2
#define NBUFS 2
#define FRAME_SIZE 2048
struct cubeb_stream_item {
cubeb_stream * stream;
};
static struct cubeb_ops const kai_ops;
struct cubeb {
struct cubeb_ops const * ops;
};
struct cubeb_stream {
cubeb * context;
cubeb_stream_params params;
cubeb_data_callback data_callback;
cubeb_state_callback state_callback;
void * user_ptr;
HKAI hkai;
KAISPEC spec;
uint64_t total_frames;
float soft_volume;
_fmutex mutex;
float float_buffer[FRAME_SIZE * MAX_CHANNELS];
};
static inline long
frames_to_bytes(long frames, cubeb_stream_params params)
{
return frames * 2 * params.channels; /* 2 bytes per frame */
}
static inline long
bytes_to_frames(long bytes, cubeb_stream_params params)
{
return bytes / 2 / params.channels; /* 2 bytes per frame */
}
static void kai_destroy(cubeb * ctx);
/*static*/ int
kai_init(cubeb ** context, char const * context_name)
{
cubeb * ctx;
XASSERT(context);
*context = NULL;
if (kaiInit(KAIM_AUTO))
return CUBEB_ERROR;
ctx = calloc(1, sizeof(*ctx));
XASSERT(ctx);
ctx->ops = &kai_ops;
*context = ctx;
return CUBEB_OK;
}
static char const *
kai_get_backend_id(cubeb * ctx)
{
return "kai";
}
static void
kai_destroy(cubeb * ctx)
{
kaiDone();
free(ctx);
}
static void
float_to_s16ne(int16_t *dst, float *src, size_t n)
{
long l;
while (n--) {
l = lrintf(*src++ * 0x8000);
if (l > 32767)
l = 32767;
if (l < -32768)
l = -32768;
*dst++ = (int16_t)l;
}
}
static ULONG APIENTRY
kai_callback(PVOID cbdata, PVOID buffer, ULONG len)
{
cubeb_stream * stm = cbdata;
void *p;
long wanted_frames;
long frames;
float soft_volume;
int elements = len / sizeof(int16_t);
p = stm->params.format == CUBEB_SAMPLE_FLOAT32NE
? stm->float_buffer : buffer;
wanted_frames = bytes_to_frames(len, stm->params);
frames = stm->data_callback(stm, stm->user_ptr, NULL, p, wanted_frames);
_fmutex_request(&stm->mutex, 0);
stm->total_frames += frames;
soft_volume = stm->soft_volume;
_fmutex_release(&stm->mutex);
if (frames < wanted_frames)
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
if (stm->params.format == CUBEB_SAMPLE_FLOAT32NE)
float_to_s16ne(buffer, p, elements);
if (soft_volume != -1.0f) {
int16_t *b = buffer;
int i;
for (i = 0; i < elements; i++)
*b++ *= soft_volume;
}
return frames_to_bytes(frames, stm->params);
}
static void kai_stream_destroy(cubeb_stream * stm);
static int
kai_stream_init(cubeb * context, cubeb_stream ** stream,
char const * stream_name,
cubeb_devid input_device,
cubeb_stream_params * input_stream_params,
cubeb_devid output_device,
cubeb_stream_params * output_stream_params,
unsigned int latency, cubeb_data_callback data_callback,
cubeb_state_callback state_callback, void * user_ptr)
{
cubeb_stream * stm;
KAISPEC wanted_spec;
XASSERT(!input_stream_params && "not supported.");
if (input_device || output_device) {
/* Device selection not yet implemented. */
return CUBEB_ERROR_DEVICE_UNAVAILABLE;
}
if (!output_stream_params)
return CUBEB_ERROR_INVALID_PARAMETER;
if (output_stream_params->channels < 1 ||
output_stream_params->channels > MAX_CHANNELS)
return CUBEB_ERROR_INVALID_FORMAT;
XASSERT(context);
XASSERT(stream);
*stream = NULL;
stm = calloc(1, sizeof(*stm));
XASSERT(stm);
stm->context = context;
stm->params = *output_stream_params;
stm->data_callback = data_callback;
stm->state_callback = state_callback;
stm->user_ptr = user_ptr;
stm->soft_volume = -1.0f;
if (_fmutex_create(&stm->mutex, 0)) {
free(stm);
return CUBEB_ERROR;
}
wanted_spec.usDeviceIndex = 0;
wanted_spec.ulType = KAIT_PLAY;
wanted_spec.ulBitsPerSample = BPS_16;
wanted_spec.ulSamplingRate = stm->params.rate;
wanted_spec.ulDataFormat = MCI_WAVE_FORMAT_PCM;
wanted_spec.ulChannels = stm->params.channels;
wanted_spec.ulNumBuffers = NBUFS;
wanted_spec.ulBufferSize = frames_to_bytes(FRAME_SIZE, stm->params);
wanted_spec.fShareable = TRUE;
wanted_spec.pfnCallBack = kai_callback;
wanted_spec.pCallBackData = stm;
if (kaiOpen(&wanted_spec, &stm->spec, &stm->hkai)) {
_fmutex_close(&stm->mutex);
free(stm);
return CUBEB_ERROR;
}
*stream = stm;
return CUBEB_OK;
}
static void
kai_stream_destroy(cubeb_stream * stm)
{
kaiClose(stm->hkai);
_fmutex_close(&stm->mutex);
free(stm);
}
static int
kai_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
{
XASSERT(ctx && max_channels);
*max_channels = MAX_CHANNELS;
return CUBEB_OK;
}
static int
kai_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * latency)
{
/* We have at least two buffers. One is being played, the other one is being
filled. So there is as much latency as one buffer. */
*latency = FRAME_SIZE;
return CUBEB_OK;
}
static int
kai_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
{
cubeb_stream_params params;
KAISPEC wanted_spec;
KAISPEC spec;
HKAI hkai;
params.format = CUBEB_SAMPLE_S16NE;
params.rate = 48000;
params.channels = 2;
wanted_spec.usDeviceIndex = 0;
wanted_spec.ulType = KAIT_PLAY;
wanted_spec.ulBitsPerSample = BPS_16;
wanted_spec.ulSamplingRate = params.rate;
wanted_spec.ulDataFormat = MCI_WAVE_FORMAT_PCM;
wanted_spec.ulChannels = params.channels;
wanted_spec.ulNumBuffers = NBUFS;
wanted_spec.ulBufferSize = frames_to_bytes(FRAME_SIZE, params);
wanted_spec.fShareable = TRUE;
wanted_spec.pfnCallBack = kai_callback;
wanted_spec.pCallBackData = NULL;
/* Test 48KHz */
if (kaiOpen(&wanted_spec, &spec, &hkai)) {
/* Not supported. Fall back to 44.1KHz */
params.rate = 44100;
} else {
/* Supported. Use 48KHz */
kaiClose(hkai);
}
*rate = params.rate;
return CUBEB_OK;
}
static int
kai_stream_start(cubeb_stream * stm)
{
if (kaiPlay(stm->hkai))
return CUBEB_ERROR;
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STARTED);
return CUBEB_OK;
}
static int
kai_stream_stop(cubeb_stream * stm)
{
if (kaiStop(stm->hkai))
return CUBEB_ERROR;
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
return CUBEB_OK;
}
static int
kai_stream_get_position(cubeb_stream * stm, uint64_t * position)
{
_fmutex_request(&stm->mutex, 0);
*position = stm->total_frames;
_fmutex_release(&stm->mutex);
return CUBEB_OK;
}
static int
kai_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
{
/* Out of buffers, one is being played, the others are being filled.
So there is as much latency as total buffers - 1. */
*latency = bytes_to_frames(stm->spec.ulBufferSize, stm->params)
* (stm->spec.ulNumBuffers - 1);
return CUBEB_OK;
}
static int
kai_stream_set_volume(cubeb_stream * stm, float volume)
{
_fmutex_request(&stm->mutex, 0);
stm->soft_volume = volume;
_fmutex_release(&stm->mutex);
return CUBEB_OK;
}
static struct cubeb_ops const kai_ops = {
/*.init =*/ kai_init,
/*.get_backend_id =*/ kai_get_backend_id,
/*.get_max_channel_count=*/ kai_get_max_channel_count,
/*.get_min_latency=*/ kai_get_min_latency,
/*.get_preferred_sample_rate =*/ kai_get_preferred_sample_rate,
/*.get_preferred_channel_layout =*/ NULL,
/*.enumerate_devices =*/ NULL,
/*.device_collection_destroy =*/ NULL,
/*.destroy =*/ kai_destroy,
/*.stream_init =*/ kai_stream_init,
/*.stream_destroy =*/ kai_stream_destroy,
/*.stream_start =*/ kai_stream_start,
/*.stream_stop =*/ kai_stream_stop,
/*.stream_get_position =*/ kai_stream_get_position,
/*.stream_get_latency = */ kai_stream_get_latency,
/*.stream_set_volume =*/ kai_stream_set_volume,
/*.stream_set_panning =*/ NULL,
/*.stream_get_current_device =*/ NULL,
/*.stream_device_destroy =*/ NULL,
/*.stream_register_device_changed_callback=*/ NULL,
/*.register_device_collection_changed=*/ NULL
};

130
Externals/cubeb/src/cubeb_log.cpp vendored Normal file
View File

@ -0,0 +1,130 @@
/*
* Copyright © 2016 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#define NOMINMAX
#include "cubeb_log.h"
#include "cubeb_ringbuffer.h"
#include <cstdarg>
#ifdef _WIN32
#include <windows.h>
#else
#include <time.h>
#endif
cubeb_log_level g_cubeb_log_level;
cubeb_log_callback g_cubeb_log_callback;
/** The maximum size of a log message, after having been formatted. */
const size_t CUBEB_LOG_MESSAGE_MAX_SIZE = 256;
/** The maximum number of log messages that can be queued before dropping
* messages. */
const size_t CUBEB_LOG_MESSAGE_QUEUE_DEPTH = 40;
/** Number of milliseconds to wait before dequeuing log messages. */
#define CUBEB_LOG_BATCH_PRINT_INTERVAL_MS 10
/**
* This wraps an inline buffer, that represents a log message, that must be
* null-terminated.
* This class should not use system calls or other potentially blocking code.
*/
class cubeb_log_message
{
public:
cubeb_log_message()
{
*storage = '\0';
}
cubeb_log_message(char const str[CUBEB_LOG_MESSAGE_MAX_SIZE])
{
size_t length = strlen(str);
/* paranoia against malformed message */
assert(length < CUBEB_LOG_MESSAGE_MAX_SIZE);
if (length > CUBEB_LOG_MESSAGE_MAX_SIZE - 1) {
return;
}
PodCopy(storage, str, length);
storage[length] = '\0';
}
char const * get() {
return storage;
}
private:
char storage[CUBEB_LOG_MESSAGE_MAX_SIZE];
};
/** Lock-free asynchronous logger, made so that logging from a
* real-time audio callback does not block the audio thread. */
class cubeb_async_logger
{
public:
/* This is thread-safe since C++11 */
static cubeb_async_logger & get() {
static cubeb_async_logger instance;
return instance;
}
void push(char const str[CUBEB_LOG_MESSAGE_MAX_SIZE])
{
cubeb_log_message msg(str);
msg_queue.enqueue(msg);
}
void run()
{
std::thread([this]() {
while (true) {
cubeb_log_message msg;
while (msg_queue.dequeue(&msg, 1)) {
LOGV("%s", msg.get());
}
#ifdef _WIN32
Sleep(CUBEB_LOG_BATCH_PRINT_INTERVAL_MS);
#else
timespec sleep_duration = sleep_for;
timespec remainder;
do {
if (nanosleep(&sleep_duration, &remainder) == 0 ||
errno != EINTR) {
break;
}
sleep_duration = remainder;
} while (remainder.tv_sec || remainder.tv_nsec);
#endif
}
}).detach();
}
private:
#ifndef _WIN32
const struct timespec sleep_for = {
CUBEB_LOG_BATCH_PRINT_INTERVAL_MS/1000,
(CUBEB_LOG_BATCH_PRINT_INTERVAL_MS%1000)*1000*1000
};
#endif
cubeb_async_logger()
: msg_queue(CUBEB_LOG_MESSAGE_QUEUE_DEPTH)
{
run();
}
/** This is quite a big data structure, but is only instantiated if the
* asynchronous logger is used.*/
lock_free_queue<cubeb_log_message> msg_queue;
};
void cubeb_async_log(char const * fmt, ...)
{
if (!g_cubeb_log_callback) {
return;
}
// This is going to copy a 256 bytes array around, which is fine.
// We don't want to allocate memory here, because this is made to
// be called from a real-time callback.
va_list args;
va_start(args, fmt);
char msg[CUBEB_LOG_MESSAGE_MAX_SIZE];
vsnprintf(msg, CUBEB_LOG_MESSAGE_MAX_SIZE, fmt, args);
cubeb_async_logger::get().push(msg);
va_end(args);
}

46
Externals/cubeb/src/cubeb_log.h vendored Normal file
View File

@ -0,0 +1,46 @@
/*
* Copyright © 2016 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#ifndef CUBEB_LOG
#define CUBEB_LOG
#include "cubeb/cubeb.h"
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__GNUC__) || defined(__clang__)
#define PRINTF_FORMAT(fmt, args) __attribute__((format(printf, fmt, args)))
#else
#define PRINTF_FORMAT(fmt, args)
#endif
extern cubeb_log_level g_cubeb_log_level;
extern cubeb_log_callback g_cubeb_log_callback PRINTF_FORMAT(1, 2);
void cubeb_async_log(const char * fmt, ...);
#ifdef __cplusplus
}
#endif
#define LOGV(msg, ...) LOG_INTERNAL(CUBEB_LOG_VERBOSE, msg, ##__VA_ARGS__)
#define LOG(msg, ...) LOG_INTERNAL(CUBEB_LOG_NORMAL, msg, ##__VA_ARGS__)
#define LOG_INTERNAL(level, fmt, ...) do { \
if (g_cubeb_log_callback && level <= g_cubeb_log_level) { \
g_cubeb_log_callback("%s:%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
} \
} while(0)
/* Asynchronous verbose logging, to log in real-time callbacks. */
#define ALOGV(fmt, ...) \
do { \
cubeb_async_log(fmt, ##__VA_ARGS__); \
} while(0)
#endif // CUBEB_LOG

569
Externals/cubeb/src/cubeb_mixer.cpp vendored Normal file
View File

@ -0,0 +1,569 @@
/*
* Copyright © 2016 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#include <cassert>
#include "cubeb-internal.h"
#include "cubeb_mixer.h"
// DUAL_MONO(_LFE) is same as STEREO(_LFE).
#define MASK_MONO (1 << CHANNEL_MONO)
#define MASK_MONO_LFE (MASK_MONO | (1 << CHANNEL_LFE))
#define MASK_STEREO ((1 << CHANNEL_LEFT) | (1 << CHANNEL_RIGHT))
#define MASK_STEREO_LFE (MASK_STEREO | (1 << CHANNEL_LFE))
#define MASK_3F (MASK_STEREO | (1 << CHANNEL_CENTER))
#define MASK_3F_LFE (MASK_3F | (1 << CHANNEL_LFE))
#define MASK_2F1 (MASK_STEREO | (1 << CHANNEL_RCENTER))
#define MASK_2F1_LFE (MASK_2F1 | (1 << CHANNEL_LFE))
#define MASK_3F1 (MASK_3F | (1 << CHANNEL_RCENTER))
#define MASK_3F1_LFE (MASK_3F1 | (1 << CHANNEL_LFE))
#define MASK_2F2 (MASK_STEREO | (1 << CHANNEL_LS) | (1 << CHANNEL_RS))
#define MASK_2F2_LFE (MASK_2F2 | (1 << CHANNEL_LFE))
#define MASK_3F2 (MASK_2F2 | (1 << CHANNEL_CENTER))
#define MASK_3F2_LFE (MASK_3F2 | (1 << CHANNEL_LFE))
#define MASK_3F3R_LFE (MASK_3F2_LFE | (1 << CHANNEL_RCENTER))
#define MASK_3F4_LFE (MASK_3F2_LFE | (1 << CHANNEL_RLS) | (1 << CHANNEL_RRS))
cubeb_channel_layout cubeb_channel_map_to_layout(cubeb_channel_map const * channel_map)
{
uint32_t channel_mask = 0;
for (uint8_t i = 0 ; i < channel_map->channels ; ++i) {
if (channel_map->map[i] == CHANNEL_INVALID ||
channel_map->map[i] == CHANNEL_UNMAPPED) {
return CUBEB_LAYOUT_UNDEFINED;
}
channel_mask |= 1 << channel_map->map[i];
}
switch(channel_mask) {
case MASK_MONO: return CUBEB_LAYOUT_MONO;
case MASK_MONO_LFE: return CUBEB_LAYOUT_MONO_LFE;
case MASK_STEREO: return CUBEB_LAYOUT_STEREO;
case MASK_STEREO_LFE: return CUBEB_LAYOUT_STEREO_LFE;
case MASK_3F: return CUBEB_LAYOUT_3F;
case MASK_3F_LFE: return CUBEB_LAYOUT_3F_LFE;
case MASK_2F1: return CUBEB_LAYOUT_2F1;
case MASK_2F1_LFE: return CUBEB_LAYOUT_2F1_LFE;
case MASK_3F1: return CUBEB_LAYOUT_3F1;
case MASK_3F1_LFE: return CUBEB_LAYOUT_3F1_LFE;
case MASK_2F2: return CUBEB_LAYOUT_2F2;
case MASK_2F2_LFE: return CUBEB_LAYOUT_2F2_LFE;
case MASK_3F2: return CUBEB_LAYOUT_3F2;
case MASK_3F2_LFE: return CUBEB_LAYOUT_3F2_LFE;
case MASK_3F3R_LFE: return CUBEB_LAYOUT_3F3R_LFE;
case MASK_3F4_LFE: return CUBEB_LAYOUT_3F4_LFE;
default: return CUBEB_LAYOUT_UNDEFINED;
}
}
cubeb_layout_map const CUBEB_CHANNEL_LAYOUT_MAPS[CUBEB_LAYOUT_MAX] = {
{ "undefined", 0, CUBEB_LAYOUT_UNDEFINED },
{ "dual mono", 2, CUBEB_LAYOUT_DUAL_MONO },
{ "dual mono lfe", 3, CUBEB_LAYOUT_DUAL_MONO_LFE },
{ "mono", 1, CUBEB_LAYOUT_MONO },
{ "mono lfe", 2, CUBEB_LAYOUT_MONO_LFE },
{ "stereo", 2, CUBEB_LAYOUT_STEREO },
{ "stereo lfe", 3, CUBEB_LAYOUT_STEREO_LFE },
{ "3f", 3, CUBEB_LAYOUT_3F },
{ "3f lfe", 4, CUBEB_LAYOUT_3F_LFE },
{ "2f1", 3, CUBEB_LAYOUT_2F1 },
{ "2f1 lfe", 4, CUBEB_LAYOUT_2F1_LFE },
{ "3f1", 4, CUBEB_LAYOUT_3F1 },
{ "3f1 lfe", 5, CUBEB_LAYOUT_3F1_LFE },
{ "2f2", 4, CUBEB_LAYOUT_2F2 },
{ "2f2 lfe", 5, CUBEB_LAYOUT_2F2_LFE },
{ "3f2", 5, CUBEB_LAYOUT_3F2 },
{ "3f2 lfe", 6, CUBEB_LAYOUT_3F2_LFE },
{ "3f3r lfe", 7, CUBEB_LAYOUT_3F3R_LFE },
{ "3f4 lfe", 8, CUBEB_LAYOUT_3F4_LFE }
};
static int const CHANNEL_ORDER_TO_INDEX[CUBEB_LAYOUT_MAX][CHANNEL_MAX] = {
// M | L | R | C | LS | RS | RLS | RC | RRS | LFE
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // UNDEFINED
{ -1, 0, 1, -1, -1, -1, -1, -1, -1, -1 }, // DUAL_MONO
{ -1, 0, 1, -1, -1, -1, -1, -1, -1, 2 }, // DUAL_MONO_LFE
{ 0, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // MONO
{ 0, -1, -1, -1, -1, -1, -1, -1, -1, 1 }, // MONO_LFE
{ -1, 0, 1, -1, -1, -1, -1, -1, -1, -1 }, // STEREO
{ -1, 0, 1, -1, -1, -1, -1, -1, -1, 2 }, // STEREO_LFE
{ -1, 0, 1, 2, -1, -1, -1, -1, -1, -1 }, // 3F
{ -1, 0, 1, 2, -1, -1, -1, -1, -1, 3 }, // 3F_LFE
{ -1, 0, 1, -1, -1, -1, -1, 2, -1, -1 }, // 2F1
{ -1, 0, 1, -1, -1, -1, -1, 3, -1, 2 }, // 2F1_LFE
{ -1, 0, 1, 2, -1, -1, -1, 3, -1, -1 }, // 3F1
{ -1, 0, 1, 2, -1, -1, -1, 4, -1, 3 }, // 3F1_LFE
{ -1, 0, 1, -1, 2, 3, -1, -1, -1, -1 }, // 2F2
{ -1, 0, 1, -1, 3, 4, -1, -1, -1, 2 }, // 2F2_LFE
{ -1, 0, 1, 2, 3, 4, -1, -1, -1, -1 }, // 3F2
{ -1, 0, 1, 2, 4, 5, -1, -1, -1, 3 }, // 3F2_LFE
{ -1, 0, 1, 2, 5, 6, -1, 4, -1, 3 }, // 3F3R_LFE
{ -1, 0, 1, 2, 6, 7, 4, -1, 5, 3 }, // 3F4_LFE
};
// The downmix matrix from TABLE 2 in the ITU-R BS.775-3[1] defines a way to
// convert 3F2 input data to 1F, 2F, 3F, 2F1, 3F1, 2F2 output data. We extend it
// to convert 3F2-LFE input data to 1F, 2F, 3F, 2F1, 3F1, 2F2 and their LFEs
// output data.
// [1] https://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.775-3-201208-I!!PDF-E.pdf
// Number of converted layouts: 1F, 2F, 3F, 2F1, 3F1, 2F2 and their LFEs.
unsigned int const SUPPORTED_LAYOUT_NUM = 12;
// Number of input channel for downmix conversion.
unsigned int const INPUT_CHANNEL_NUM = 6; // 3F2-LFE
// Max number of possible output channels.
unsigned int const MAX_OUTPUT_CHANNEL_NUM = 5; // 2F2-LFE or 3F1-LFE
float const INV_SQRT_2 = 0.707106f; // 1/sqrt(2)
// Each array contains coefficients that will be multiplied with
// { L, R, C, LFE, LS, RS } channels respectively.
static float const DOWNMIX_MATRIX_3F2_LFE[SUPPORTED_LAYOUT_NUM][MAX_OUTPUT_CHANNEL_NUM][INPUT_CHANNEL_NUM] =
{
// 1F Mono
{
{ INV_SQRT_2, INV_SQRT_2, 1, 0, 0.5, 0.5 }, // M
},
// 1F Mono-LFE
{
{ INV_SQRT_2, INV_SQRT_2, 1, 0, 0.5, 0.5 }, // M
{ 0, 0, 0, 1, 0, 0 } // LFE
},
// 2F Stereo
{
{ 1, 0, INV_SQRT_2, 0, INV_SQRT_2, 0 }, // L
{ 0, 1, INV_SQRT_2, 0, 0, INV_SQRT_2 } // R
},
// 2F Stereo-LFE
{
{ 1, 0, INV_SQRT_2, 0, INV_SQRT_2, 0 }, // L
{ 0, 1, INV_SQRT_2, 0, 0, INV_SQRT_2 }, // R
{ 0, 0, 0, 1, 0, 0 } // LFE
},
// 3F
{
{ 1, 0, 0, 0, INV_SQRT_2, 0 }, // L
{ 0, 1, 0, 0, 0, INV_SQRT_2 }, // R
{ 0, 0, 1, 0, 0, 0 } // C
},
// 3F-LFE
{
{ 1, 0, 0, 0, INV_SQRT_2, 0 }, // L
{ 0, 1, 0, 0, 0, INV_SQRT_2 }, // R
{ 0, 0, 1, 0, 0, 0 }, // C
{ 0, 0, 0, 1, 0, 0 } // LFE
},
// 2F1
{
{ 1, 0, INV_SQRT_2, 0, 0, 0 }, // L
{ 0, 1, INV_SQRT_2, 0, 0, 0 }, // R
{ 0, 0, 0, 0, INV_SQRT_2, INV_SQRT_2 } // S
},
// 2F1-LFE
{
{ 1, 0, INV_SQRT_2, 0, 0, 0 }, // L
{ 0, 1, INV_SQRT_2, 0, 0, 0 }, // R
{ 0, 0, 0, 1, 0, 0 }, // LFE
{ 0, 0, 0, 0, INV_SQRT_2, INV_SQRT_2 } // S
},
// 3F1
{
{ 1, 0, 0, 0, 0, 0 }, // L
{ 0, 1, 0, 0, 0, 0 }, // R
{ 0, 0, 1, 0, 0, 0 }, // C
{ 0, 0, 0, 0, INV_SQRT_2, INV_SQRT_2 } // S
},
// 3F1-LFE
{
{ 1, 0, 0, 0, 0, 0 }, // L
{ 0, 1, 0, 0, 0, 0 }, // R
{ 0, 0, 1, 0, 0, 0 }, // C
{ 0, 0, 0, 1, 0, 0 }, // LFE
{ 0, 0, 0, 0, INV_SQRT_2, INV_SQRT_2 } // S
},
// 2F2
{
{ 1, 0, INV_SQRT_2, 0, 0, 0 }, // L
{ 0, 1, INV_SQRT_2, 0, 0, 0 }, // R
{ 0, 0, 0, 0, 1, 0 }, // LS
{ 0, 0, 0, 0, 0, 1 } // RS
},
// 2F2-LFE
{
{ 1, 0, INV_SQRT_2, 0, 0, 0 }, // L
{ 0, 1, INV_SQRT_2, 0, 0, 0 }, // R
{ 0, 0, 0, 1, 0, 0 }, // LFE
{ 0, 0, 0, 0, 1, 0 }, // LS
{ 0, 0, 0, 0, 0, 1 } // RS
}
};
// Convert audio data from 3F2(-LFE) to 1F, 2F, 3F, 2F1, 3F1, 2F2 and their LFEs.
//
// ITU-R BS.775-3[1] provides spec for downmixing 3F2 data to 1F, 2F, 3F, 2F1,
// 3F1, 2F2 data. We simply add LFE to its defined matrix. If both the input
// and output have LFE channel, then we pass it's data. If only input or output
// has LFE, then we either drop it or append 0 to the LFE channel.
//
// Fig. 1:
// |<-------------- 1 -------------->|<-------------- 2 -------------->|
// +----+----+----+------+-----+-----+----+----+----+------+-----+-----+
// | L0 | R0 | C0 | LFE0 | LS0 | RS0 | L1 | R1 | C1 | LFE1 | LS1 | RS1 | ...
// +----+----+----+------+-----+-----+----+----+----+------+-----+-----+
//
// Fig. 2:
// |<-- 1 -->|<-- 2 -->|
// +----+----+----+----+
// | L0 | R0 | L1 | R1 | ...
// +----+----+----+----+
//
// The figures above shows an example for downmixing from 3F2-LFE(Fig. 1) to
// to stereo(Fig. 2), where L0 = L0 + 0.707 * (C0 + LS0),
// R0 = R0 + 0.707 * (C0 + RS0), L1 = L1 + 0.707 * (C1 + LS1),
// R1 = R1 + 0.707 * (C1 + RS1), ...
//
// Nevertheless, the downmixing method is a little bit different on OSX.
// The audio rendering mechanism on OS X will drop the extra channels beyond
// the channels that audio device can provide. The trick here is that OSX allows
// us to set the layout containing other channels that the output device can
// NOT provide. For example, setting 3F2-LFE layout to a stereo device is fine.
// Therefore, OSX expects we fill the buffer for playing sound by the defined
// layout, so there are some will-be-dropped data in the buffer:
//
// +---+---+---+-----+----+----+
// | L | R | C | LFE | LS | RS | ...
// +---+---+---+-----+----+----+
// ^ ^ ^ ^
// The data for these four channels will be dropped!
//
// To keep all the information, we need to downmix the data before it's dropped.
// The figure below shows an example for downmixing from 3F2-LFE(Fig. 1)
// to stereo(Fig. 3) on OSX, where the LO, R0, L1, R0 are same as above.
//
// Fig. 3:
// |<---------- 1 ---------->|<---------- 2 ---------->|
// +----+----+---+---+---+---+----+----+---+---+---+---+
// | L0 | R0 | x | x | x | x | L1 | R1 | x | x | x | x | ...
// +----+----+---+---+---+---+----+----+---+---+---+---+
// |<-- dummy -->| |<-- dummy -->|
template<typename T>
bool
downmix_3f2(unsigned long inframes,
T const * const in, unsigned long in_len,
T * out, unsigned long out_len,
cubeb_channel_layout in_layout, cubeb_channel_layout out_layout)
{
if ((in_layout != CUBEB_LAYOUT_3F2 && in_layout != CUBEB_LAYOUT_3F2_LFE) ||
out_layout < CUBEB_LAYOUT_MONO || out_layout > CUBEB_LAYOUT_2F2_LFE) {
return false;
}
unsigned int in_channels = CUBEB_CHANNEL_LAYOUT_MAPS[in_layout].channels;
unsigned int out_channels = CUBEB_CHANNEL_LAYOUT_MAPS[out_layout].channels;
// Conversion from 3F2 to 2F2-LFE or 3F1-LFE is allowed, so we use '<=' instead of '<'.
assert(out_channels <= in_channels);
auto & downmix_matrix = DOWNMIX_MATRIX_3F2_LFE[out_layout - CUBEB_LAYOUT_MONO]; // The matrix is started from mono.
unsigned long out_index = 0;
for (unsigned long i = 0 ; i < inframes * in_channels; i += in_channels) {
for (unsigned int j = 0; j < out_channels; ++j) {
T sample = 0;
for (unsigned int k = 0 ; k < INPUT_CHANNEL_NUM ; ++k) {
// 3F2-LFE has 6 channels: L, R, C, LFE, LS, RS, while 3F2 has only 5
// channels: L, R, C, LS, RS. Thus, we need to append 0 to LFE(index 3)
// to simulate a 3F2-LFE data when input layout is 3F2.
assert((in_layout == CUBEB_LAYOUT_3F2_LFE || k < 3) ? (i + k < in_len) : (k == 3) ? true : (i + k - 1 < in_len));
T data = (in_layout == CUBEB_LAYOUT_3F2_LFE) ? in[i + k] : (k == 3) ? 0 : in[i + ((k < 3) ? k : k - 1)];
sample += downmix_matrix[j][k] * data;
}
assert(out_index + j < out_len);
out[out_index + j] = sample;
}
#if defined(USE_AUDIOUNIT)
out_index += in_channels;
#else
out_index += out_channels;
#endif
}
return true;
}
/* Map the audio data by channel name. */
template<class T>
bool
mix_remap(long inframes,
T const * const in, unsigned long in_len,
T * out, unsigned long out_len,
cubeb_channel_layout in_layout, cubeb_channel_layout out_layout)
{
assert(in_layout != out_layout);
// We might overwrite the data before we copied them to the mapped index
// (e.g. upmixing from stereo to 2F1 or mapping [L, R] to [R, L])
if (in == out) {
return false;
}
unsigned int in_channels = CUBEB_CHANNEL_LAYOUT_MAPS[in_layout].channels;
unsigned int out_channels = CUBEB_CHANNEL_LAYOUT_MAPS[out_layout].channels;
uint32_t in_layout_mask = 0;
for (unsigned int i = 0 ; i < in_channels ; ++i) {
in_layout_mask |= 1 << CHANNEL_INDEX_TO_ORDER[in_layout][i];
}
uint32_t out_layout_mask = 0;
for (unsigned int i = 0 ; i < out_channels ; ++i) {
out_layout_mask |= 1 << CHANNEL_INDEX_TO_ORDER[out_layout][i];
}
// If there is no matched channel, then do nothing.
if (!(out_layout_mask & in_layout_mask)) {
return false;
}
for (unsigned long i = 0, out_index = 0; i < inframes * in_channels; i += in_channels, out_index += out_channels) {
for (unsigned int j = 0; j < out_channels; ++j) {
cubeb_channel channel = CHANNEL_INDEX_TO_ORDER[out_layout][j];
uint32_t channel_mask = 1 << channel;
int channel_index = CHANNEL_ORDER_TO_INDEX[in_layout][channel];
assert(out_index + j < out_len);
if (in_layout_mask & channel_mask) {
assert(i + channel_index < in_len);
assert(channel_index != -1);
out[out_index + j] = in[i + channel_index];
} else {
assert(channel_index == -1);
out[out_index + j] = 0;
}
}
}
return true;
}
/* Drop the extra channels beyond the provided output channels. */
template<typename T>
void
downmix_fallback(long inframes,
T const * const in, unsigned long in_len,
T * out, unsigned long out_len,
unsigned int in_channels, unsigned int out_channels)
{
assert(in_channels >= out_channels);
if (in_channels == out_channels && in == out) {
return;
}
for (unsigned long i = 0, out_index = 0; i < inframes * in_channels; i += in_channels, out_index += out_channels) {
for (unsigned int j = 0; j < out_channels; ++j) {
assert(i + j < in_len && out_index + j < out_len);
out[out_index + j] = in[i + j];
}
}
}
template<typename T>
void
cubeb_downmix(long inframes,
T const * const in, unsigned long in_len,
T * out, unsigned long out_len,
cubeb_stream_params const * stream_params,
cubeb_stream_params const * mixer_params)
{
assert(in && out);
assert(inframes);
assert(stream_params->channels >= mixer_params->channels &&
mixer_params->channels > 0);
assert(stream_params->layout != CUBEB_LAYOUT_UNDEFINED);
unsigned int in_channels = stream_params->channels;
cubeb_channel_layout in_layout = stream_params->layout;
unsigned int out_channels = mixer_params->channels;
cubeb_channel_layout out_layout = mixer_params->layout;
// If the channel number is different from the layout's setting,
// then we use fallback downmix mechanism.
if (out_channels == CUBEB_CHANNEL_LAYOUT_MAPS[out_layout].channels &&
in_channels == CUBEB_CHANNEL_LAYOUT_MAPS[in_layout].channels) {
if (downmix_3f2(inframes, in, in_len, out, out_len, in_layout, out_layout)) {
return;
}
#if defined(USE_AUDIOUNIT)
// We only support downmix for audio 5.1 on OS X currently.
return;
#endif
if (mix_remap(inframes, in, in_len, out, out_len, in_layout, out_layout)) {
return;
}
}
downmix_fallback(inframes, in, in_len, out, out_len, in_channels, out_channels);
}
/* Upmix function, copies a mono channel into L and R. */
template<typename T>
void
mono_to_stereo(long insamples, T const * in, unsigned long in_len,
T * out, unsigned long out_len, unsigned int out_channels)
{
for (long i = 0, j = 0; i < insamples; ++i, j += out_channels) {
assert(i < in_len && j + 1 < out_len);
out[j] = out[j + 1] = in[i];
}
}
template<typename T>
void
cubeb_upmix(long inframes,
T const * const in, unsigned long in_len,
T * out, unsigned long out_len,
cubeb_stream_params const * stream_params,
cubeb_stream_params const * mixer_params)
{
assert(in && out);
assert(inframes);
assert(mixer_params->channels >= stream_params->channels &&
stream_params->channels > 0);
unsigned int in_channels = stream_params->channels;
unsigned int out_channels = mixer_params->channels;
/* Either way, if we have 2 or more channels, the first two are L and R. */
/* If we are playing a mono stream over stereo speakers, copy the data over. */
if (in_channels == 1 && out_channels >= 2) {
mono_to_stereo(inframes, in, in_len, out, out_len, out_channels);
} else {
/* Copy through. */
for (unsigned int i = 0, o = 0; i < inframes * in_channels;
i += in_channels, o += out_channels) {
for (unsigned int j = 0; j < in_channels; ++j) {
assert(i + j < in_len && o + j < out_len);
out[o + j] = in[i + j];
}
}
}
/* Check if more channels. */
if (out_channels <= 2) {
return;
}
/* Put silence in remaining channels. */
for (long i = 0, o = 0; i < inframes; ++i, o += out_channels) {
for (unsigned int j = 2; j < out_channels; ++j) {
assert(o + j < out_len);
out[o + j] = 0.0;
}
}
}
bool
cubeb_should_upmix(cubeb_stream_params const * stream, cubeb_stream_params const * mixer)
{
return mixer->channels > stream->channels;
}
bool
cubeb_should_downmix(cubeb_stream_params const * stream, cubeb_stream_params const * mixer)
{
if (mixer->channels > stream->channels || mixer->layout == stream->layout) {
return false;
}
return mixer->channels < stream->channels ||
// When mixer.channels == stream.channels
mixer->layout == CUBEB_LAYOUT_UNDEFINED || // fallback downmix
(stream->layout == CUBEB_LAYOUT_3F2 && // 3f2 downmix
(mixer->layout == CUBEB_LAYOUT_2F2_LFE ||
mixer->layout == CUBEB_LAYOUT_3F1_LFE));
}
bool
cubeb_should_mix(cubeb_stream_params const * stream, cubeb_stream_params const * mixer)
{
return cubeb_should_upmix(stream, mixer) || cubeb_should_downmix(stream, mixer);
}
struct cubeb_mixer {
virtual void mix(long frames,
void * input_buffer, unsigned long input_buffer_length,
void * output_buffer, unsigned long output_buffer_length,
cubeb_stream_params const * stream_params,
cubeb_stream_params const * mixer_params) = 0;
virtual ~cubeb_mixer() {};
};
template<typename T>
struct cubeb_mixer_impl : public cubeb_mixer {
explicit cubeb_mixer_impl(unsigned int d)
: direction(d)
{
}
void mix(long frames,
void * input_buffer, unsigned long input_buffer_length,
void * output_buffer, unsigned long output_buffer_length,
cubeb_stream_params const * stream_params,
cubeb_stream_params const * mixer_params)
{
if (frames <= 0) {
return;
}
T * in = static_cast<T*>(input_buffer);
T * out = static_cast<T*>(output_buffer);
if ((direction & CUBEB_MIXER_DIRECTION_DOWNMIX) &&
cubeb_should_downmix(stream_params, mixer_params)) {
cubeb_downmix(frames, in, input_buffer_length, out, output_buffer_length, stream_params, mixer_params);
} else if ((direction & CUBEB_MIXER_DIRECTION_UPMIX) &&
cubeb_should_upmix(stream_params, mixer_params)) {
cubeb_upmix(frames, in, input_buffer_length, out, output_buffer_length, stream_params, mixer_params);
}
}
~cubeb_mixer_impl() {};
unsigned char const direction;
};
cubeb_mixer * cubeb_mixer_create(cubeb_sample_format format,
unsigned char direction)
{
assert(direction & CUBEB_MIXER_DIRECTION_DOWNMIX ||
direction & CUBEB_MIXER_DIRECTION_UPMIX);
switch(format) {
case CUBEB_SAMPLE_S16NE:
return new cubeb_mixer_impl<short>(direction);
case CUBEB_SAMPLE_FLOAT32NE:
return new cubeb_mixer_impl<float>(direction);
default:
assert(false);
return nullptr;
}
}
void cubeb_mixer_destroy(cubeb_mixer * mixer)
{
delete mixer;
}
void cubeb_mixer_mix(cubeb_mixer * mixer, long frames,
void * input_buffer, unsigned long input_buffer_length,
void * output_buffer, unsigned long outputput_buffer_length,
cubeb_stream_params const * stream_params,
cubeb_stream_params const * mixer_params)
{
assert(mixer);
mixer->mix(frames, input_buffer, input_buffer_length, output_buffer, outputput_buffer_length,
stream_params, mixer_params);
}

90
Externals/cubeb/src/cubeb_mixer.h vendored Normal file
View File

@ -0,0 +1,90 @@
/*
* Copyright © 2016 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#ifndef CUBEB_MIXER
#define CUBEB_MIXER
#include "cubeb/cubeb.h" // for cubeb_channel_layout ,CUBEB_CHANNEL_LAYOUT_MAPS and cubeb_stream_params.
#include <stdbool.h>
#if defined(__cplusplus)
extern "C" {
#endif
typedef enum {
CHANNEL_INVALID = -1,
CHANNEL_MONO = 0,
CHANNEL_LEFT,
CHANNEL_RIGHT,
CHANNEL_CENTER,
CHANNEL_LS,
CHANNEL_RS,
CHANNEL_RLS,
CHANNEL_RCENTER,
CHANNEL_RRS,
CHANNEL_LFE,
CHANNEL_UNMAPPED,
CHANNEL_MAX = 256 // Max number of supported channels.
} cubeb_channel;
static cubeb_channel const CHANNEL_INDEX_TO_ORDER[CUBEB_LAYOUT_MAX][CHANNEL_MAX] = {
{ CHANNEL_INVALID }, // UNDEFINED
{ CHANNEL_LEFT, CHANNEL_RIGHT }, // DUAL_MONO
{ CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_LFE }, // DUAL_MONO_LFE
{ CHANNEL_MONO }, // MONO
{ CHANNEL_MONO, CHANNEL_LFE }, // MONO_LFE
{ CHANNEL_LEFT, CHANNEL_RIGHT }, // STEREO
{ CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_LFE }, // STEREO_LFE
{ CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER }, // 3F
{ CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE }, // 3F_LFE
{ CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_RCENTER }, // 2F1
{ CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_LFE, CHANNEL_RCENTER }, // 2F1_LFE
{ CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_RCENTER }, // 3F1
{ CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE, CHANNEL_RCENTER }, // 3F1_LFE
{ CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_LS, CHANNEL_RS }, // 2F2
{ CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_LFE, CHANNEL_LS, CHANNEL_RS }, // 2F2_LFE
{ CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LS, CHANNEL_RS }, // 3F2
{ CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE, CHANNEL_LS, CHANNEL_RS }, // 3F2_LFE
{ CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE, CHANNEL_RCENTER, CHANNEL_LS, CHANNEL_RS }, // 3F3R_LFE
{ CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE, CHANNEL_RLS, CHANNEL_RRS, CHANNEL_LS, CHANNEL_RS } // 3F4_LFE
// When more channels are present, the stream is considered unmapped to a
// particular speaker set.
};
typedef struct {
unsigned int channels;
cubeb_channel map[CHANNEL_MAX];
} cubeb_channel_map;
cubeb_channel_layout cubeb_channel_map_to_layout(cubeb_channel_map const * channel_map);
bool cubeb_should_upmix(cubeb_stream_params const * stream, cubeb_stream_params const * mixer);
bool cubeb_should_downmix(cubeb_stream_params const * stream, cubeb_stream_params const * mixer);
bool cubeb_should_mix(cubeb_stream_params const * stream, cubeb_stream_params const * mixer);
typedef enum {
CUBEB_MIXER_DIRECTION_DOWNMIX = 0x01,
CUBEB_MIXER_DIRECTION_UPMIX = 0x02,
} cubeb_mixer_direction;
typedef struct cubeb_mixer cubeb_mixer;
cubeb_mixer * cubeb_mixer_create(cubeb_sample_format format,
unsigned char direction);
void cubeb_mixer_destroy(cubeb_mixer * mixer);
void cubeb_mixer_mix(cubeb_mixer * mixer, long frames,
void * input_buffer, unsigned long input_buffer_length,
void * output_buffer, unsigned long outputput_buffer_length,
cubeb_stream_params const * stream_params,
cubeb_stream_params const * mixer_params);
#if defined(__cplusplus)
}
#endif
#endif // CUBEB_MIXER

1757
Externals/cubeb/src/cubeb_opensl.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,36 @@
/*
* Copyright © 2016 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#include <cubeb/cubeb.h>
#include "cubeb_osx_run_loop.h"
#include "cubeb_log.h"
#include <AudioUnit/AudioUnit.h>
#include <CoreAudio/AudioHardware.h>
#include <CoreAudio/HostTime.h>
#include <CoreFoundation/CoreFoundation.h>
void cubeb_set_coreaudio_notification_runloop()
{
/* This is needed so that AudioUnit listeners get called on this thread, and
* not the main thread. If we don't do that, they are not called, or a crash
* occur, depending on the OSX version. */
AudioObjectPropertyAddress runloop_address = {
kAudioHardwarePropertyRunLoop,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
CFRunLoopRef run_loop = nullptr;
OSStatus r;
r = AudioObjectSetPropertyData(kAudioObjectSystemObject,
&runloop_address,
0, NULL, sizeof(CFRunLoopRef), &run_loop);
if (r != noErr) {
LOG("Could not make global CoreAudio notifications use their own thread.");
}
}

View File

@ -0,0 +1,22 @@
/*
* Copyright © 2014 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
/* On OSX 10.6 and after, the notification callbacks from the audio hardware are
* called on the main thread. Setting the kAudioHardwarePropertyRunLoop property
* to null tells the OSX to use a separate thread for that.
*
* This has to be called only once per process, so it is in a separate header
* for easy integration in other code bases. */
#if defined(__cplusplus)
extern "C" {
#endif
void cubeb_set_coreaudio_notification_runloop();
#if defined(__cplusplus)
}
#endif

60
Externals/cubeb/src/cubeb_panner.cpp vendored Normal file
View File

@ -0,0 +1,60 @@
/*
* Copyright © 2014 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#define _USE_MATH_DEFINES
#include <math.h>
#include <stdint.h>
#include "cubeb_panner.h"
#ifndef M_PI
#define M_PI 3.14159263
#endif
/**
* We use a cos/sin law.
*/
namespace {
template<typename T>
void cubeb_pan_stereo_buffer(T * buf, uint32_t frames, float pan)
{
if (pan == 0.0) {
return;
}
/* rescale in [0; 1] */
pan += 1;
pan /= 2;
float left_gain = float(cos(pan * M_PI * 0.5));
float right_gain = float(sin(pan * M_PI * 0.5));
/* In we are panning on the left, pan the right channel into the left one and
* vice-versa. */
if (pan < 0.5) {
for (uint32_t i = 0; i < frames * 2; i+=2) {
buf[i] = T(buf[i] + buf[i + 1] * left_gain);
buf[i + 1] = T(buf[i + 1] * right_gain);
}
} else {
for (uint32_t i = 0; i < frames * 2; i+=2) {
buf[i] = T(buf[i] * left_gain);
buf[i + 1] = T(buf[i + 1] + buf[i] * right_gain);
}
}
}
}
void cubeb_pan_stereo_buffer_float(float * buf, uint32_t frames, float pan)
{
cubeb_pan_stereo_buffer(buf, frames, pan);
}
void cubeb_pan_stereo_buffer_int(short * buf, uint32_t frames, float pan)
{
cubeb_pan_stereo_buffer(buf, frames, pan);
}

28
Externals/cubeb/src/cubeb_panner.h vendored Normal file
View File

@ -0,0 +1,28 @@
/*
* Copyright © 2014 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#if !defined(CUBEB_PANNER)
#define CUBEB_PANNER
#if defined(__cplusplus)
extern "C" {
#endif
/**
* Pan an integer or an float stereo buffer according to a cos/sin pan law
* @param buf the buffer to pan
* @param frames the number of frames in `buf`
* @param pan a float in [-1.0; 1.0]
*/
void cubeb_pan_stereo_buffer_float(float * buf, uint32_t frames, float pan);
void cubeb_pan_stereo_buffer_int(short* buf, uint32_t frames, float pan);
#if defined(__cplusplus)
}
#endif
#endif

1509
Externals/cubeb/src/cubeb_pulse.c vendored Normal file

File diff suppressed because it is too large Load Diff

315
Externals/cubeb/src/cubeb_resampler.cpp vendored Normal file
View File

@ -0,0 +1,315 @@
/*
* Copyright © 2014 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#ifndef NOMINMAX
#define NOMINMAX
#endif // NOMINMAX
#include <algorithm>
#include <cmath>
#include <cassert>
#include <cstring>
#include <cstddef>
#include <cstdio>
#include "cubeb_resampler.h"
#include "cubeb-speex-resampler.h"
#include "cubeb_resampler_internal.h"
#include "cubeb_utils.h"
int
to_speex_quality(cubeb_resampler_quality q)
{
switch(q) {
case CUBEB_RESAMPLER_QUALITY_VOIP:
return SPEEX_RESAMPLER_QUALITY_VOIP;
case CUBEB_RESAMPLER_QUALITY_DEFAULT:
return SPEEX_RESAMPLER_QUALITY_DEFAULT;
case CUBEB_RESAMPLER_QUALITY_DESKTOP:
return SPEEX_RESAMPLER_QUALITY_DESKTOP;
default:
assert(false);
return 0XFFFFFFFF;
}
}
template<typename T>
passthrough_resampler<T>::passthrough_resampler(cubeb_stream * s,
cubeb_data_callback cb,
void * ptr,
uint32_t input_channels)
: processor(input_channels)
, stream(s)
, data_callback(cb)
, user_ptr(ptr)
{
}
template<typename T>
long passthrough_resampler<T>::fill(void * input_buffer, long * input_frames_count,
void * output_buffer, long output_frames)
{
if (input_buffer) {
assert(input_frames_count);
}
assert((input_buffer && output_buffer &&
*input_frames_count + static_cast<int>(samples_to_frames(internal_input_buffer.length())) >= output_frames) ||
(output_buffer && !input_buffer && (!input_frames_count || *input_frames_count == 0)) ||
(input_buffer && !output_buffer && output_frames == 0));
if (input_buffer) {
if (!output_buffer) {
output_frames = *input_frames_count;
}
internal_input_buffer.push(static_cast<T*>(input_buffer),
frames_to_samples(*input_frames_count));
}
long rv = data_callback(stream, user_ptr, internal_input_buffer.data(),
output_buffer, output_frames);
if (input_buffer) {
internal_input_buffer.pop(nullptr, frames_to_samples(output_frames));
*input_frames_count = output_frames;
}
return rv;
}
template<typename T, typename InputProcessor, typename OutputProcessor>
cubeb_resampler_speex<T, InputProcessor, OutputProcessor>
::cubeb_resampler_speex(InputProcessor * input_processor,
OutputProcessor * output_processor,
cubeb_stream * s,
cubeb_data_callback cb,
void * ptr)
: input_processor(input_processor)
, output_processor(output_processor)
, stream(s)
, data_callback(cb)
, user_ptr(ptr)
{
if (input_processor && output_processor) {
// Add some delay on the processor that has the lowest delay so that the
// streams are synchronized.
uint32_t in_latency = input_processor->latency();
uint32_t out_latency = output_processor->latency();
if (in_latency > out_latency) {
uint32_t latency_diff = in_latency - out_latency;
output_processor->add_latency(latency_diff);
} else if (in_latency < out_latency) {
uint32_t latency_diff = out_latency - in_latency;
input_processor->add_latency(latency_diff);
}
fill_internal = &cubeb_resampler_speex::fill_internal_duplex;
} else if (input_processor) {
fill_internal = &cubeb_resampler_speex::fill_internal_input;
} else if (output_processor) {
fill_internal = &cubeb_resampler_speex::fill_internal_output;
}
}
template<typename T, typename InputProcessor, typename OutputProcessor>
cubeb_resampler_speex<T, InputProcessor, OutputProcessor>
::~cubeb_resampler_speex()
{ }
template<typename T, typename InputProcessor, typename OutputProcessor>
long
cubeb_resampler_speex<T, InputProcessor, OutputProcessor>
::fill(void * input_buffer, long * input_frames_count,
void * output_buffer, long output_frames_needed)
{
/* Input and output buffers, typed */
T * in_buffer = reinterpret_cast<T*>(input_buffer);
T * out_buffer = reinterpret_cast<T*>(output_buffer);
return (this->*fill_internal)(in_buffer, input_frames_count,
out_buffer, output_frames_needed);
}
template<typename T, typename InputProcessor, typename OutputProcessor>
long
cubeb_resampler_speex<T, InputProcessor, OutputProcessor>
::fill_internal_output(T * input_buffer, long * input_frames_count,
T * output_buffer, long output_frames_needed)
{
assert(!input_buffer && (!input_frames_count || *input_frames_count == 0) &&
output_buffer && output_frames_needed);
long got = 0;
T * out_unprocessed = nullptr;
long output_frames_before_processing = 0;
/* fill directly the input buffer of the output processor to save a copy */
output_frames_before_processing =
output_processor->input_needed_for_output(output_frames_needed);
out_unprocessed =
output_processor->input_buffer(output_frames_before_processing);
got = data_callback(stream, user_ptr,
nullptr, out_unprocessed,
output_frames_before_processing);
if (got < 0) {
return got;
}
output_processor->written(got);
/* Process the output. If not enough frames have been returned from the
* callback, drain the processors. */
return output_processor->output(output_buffer, output_frames_needed);
}
template<typename T, typename InputProcessor, typename OutputProcessor>
long
cubeb_resampler_speex<T, InputProcessor, OutputProcessor>
::fill_internal_input(T * input_buffer, long * input_frames_count,
T * output_buffer, long /*output_frames_needed*/)
{
assert(input_buffer && input_frames_count && *input_frames_count &&
!output_buffer);
/* The input data, after eventual resampling. This is passed to the callback. */
T * resampled_input = nullptr;
uint32_t resampled_frame_count = input_processor->output_for_input(*input_frames_count);
/* process the input, and present exactly `output_frames_needed` in the
* callback. */
input_processor->input(input_buffer, *input_frames_count);
resampled_input = input_processor->output(resampled_frame_count, (size_t*)input_frames_count);
long got = data_callback(stream, user_ptr,
resampled_input, nullptr, resampled_frame_count);
/* Return the number of initial input frames or part of it.
* Since output_frames_needed == 0 in input scenario, the only
* available number outside resampler is the initial number of frames. */
return (*input_frames_count) * (got / resampled_frame_count);
}
template<typename T, typename InputProcessor, typename OutputProcessor>
long
cubeb_resampler_speex<T, InputProcessor, OutputProcessor>
::fill_internal_duplex(T * in_buffer, long * input_frames_count,
T * out_buffer, long output_frames_needed)
{
/* The input data, after eventual resampling. This is passed to the callback. */
T * resampled_input = nullptr;
/* The output buffer passed down in the callback, that might be resampled. */
T * out_unprocessed = nullptr;
size_t output_frames_before_processing = 0;
/* The number of frames returned from the callback. */
long got = 0;
/* We need to determine how much frames to present to the consumer.
* - If we have a two way stream, but we're only resampling input, we resample
* the input to the number of output frames.
* - If we have a two way stream, but we're only resampling the output, we
* resize the input buffer of the output resampler to the number of input
* frames, and we resample it afterwards.
* - If we resample both ways, we resample the input to the number of frames
* we would need to pass down to the consumer (before resampling the output),
* get the output data, and resample it to the number of frames needed by the
* caller. */
output_frames_before_processing =
output_processor->input_needed_for_output(output_frames_needed);
/* fill directly the input buffer of the output processor to save a copy */
out_unprocessed =
output_processor->input_buffer(output_frames_before_processing);
if (in_buffer) {
/* process the input, and present exactly `output_frames_needed` in the
* callback. */
input_processor->input(in_buffer, *input_frames_count);
resampled_input =
input_processor->output(output_frames_before_processing, (size_t*)input_frames_count);
} else {
resampled_input = nullptr;
}
got = data_callback(stream, user_ptr,
resampled_input, out_unprocessed,
output_frames_before_processing);
if (got < 0) {
return got;
}
output_processor->written(got);
/* Process the output. If not enough frames have been returned from the
* callback, drain the processors. */
return output_processor->output(out_buffer, output_frames_needed);
}
/* Resampler C API */
cubeb_resampler *
cubeb_resampler_create(cubeb_stream * stream,
cubeb_stream_params * input_params,
cubeb_stream_params * output_params,
unsigned int target_rate,
cubeb_data_callback callback,
void * user_ptr,
cubeb_resampler_quality quality)
{
cubeb_sample_format format;
assert(input_params || output_params);
if (input_params) {
format = input_params->format;
} else {
format = output_params->format;
}
switch(format) {
case CUBEB_SAMPLE_S16NE:
return cubeb_resampler_create_internal<short>(stream,
input_params,
output_params,
target_rate,
callback,
user_ptr,
quality);
case CUBEB_SAMPLE_FLOAT32NE:
return cubeb_resampler_create_internal<float>(stream,
input_params,
output_params,
target_rate,
callback,
user_ptr,
quality);
default:
assert(false);
return nullptr;
}
}
long
cubeb_resampler_fill(cubeb_resampler * resampler,
void * input_buffer,
long * input_frames_count,
void * output_buffer,
long output_frames_needed)
{
return resampler->fill(input_buffer, input_frames_count,
output_buffer, output_frames_needed);
}
void
cubeb_resampler_destroy(cubeb_resampler * resampler)
{
delete resampler;
}
long
cubeb_resampler_latency(cubeb_resampler * resampler)
{
return resampler->latency();
}

78
Externals/cubeb/src/cubeb_resampler.h vendored Normal file
View File

@ -0,0 +1,78 @@
/*
* Copyright © 2014 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#ifndef CUBEB_RESAMPLER_H
#define CUBEB_RESAMPLER_H
#include "cubeb/cubeb.h"
#if defined(__cplusplus)
extern "C" {
#endif
typedef struct cubeb_resampler cubeb_resampler;
typedef enum {
CUBEB_RESAMPLER_QUALITY_VOIP,
CUBEB_RESAMPLER_QUALITY_DEFAULT,
CUBEB_RESAMPLER_QUALITY_DESKTOP
} cubeb_resampler_quality;
/**
* Create a resampler to adapt the requested sample rate into something that
* is accepted by the audio backend.
* @param stream A cubeb_stream instance supplied to the data callback.
* @param params Used to calculate bytes per frame and buffer size for resampling.
* @param target_rate The sampling rate after resampling.
* @param callback A callback to request data for resampling.
* @param user_ptr User data supplied to the data callback.
* @param quality Quality of the resampler.
* @retval A non-null pointer if success.
*/
cubeb_resampler * cubeb_resampler_create(cubeb_stream * stream,
cubeb_stream_params * input_params,
cubeb_stream_params * output_params,
unsigned int target_rate,
cubeb_data_callback callback,
void * user_ptr,
cubeb_resampler_quality quality);
/**
* Fill the buffer with frames acquired using the data callback. Resampling will
* happen if necessary.
* @param resampler A cubeb_resampler instance.
* @param input_buffer A buffer of input samples
* @param input_frame_count The size of the buffer. Returns the number of frames
* consumed.
* @param buffer The buffer to be filled.
* @param frames_needed Number of frames that should be produced.
* @retval Number of frames that are actually produced.
* @retval CUBEB_ERROR on error.
*/
long cubeb_resampler_fill(cubeb_resampler * resampler,
void * input_buffer,
long * input_frame_count,
void * output_buffer,
long output_frames_needed);
/**
* Destroy a cubeb_resampler.
* @param resampler A cubeb_resampler instance.
*/
void cubeb_resampler_destroy(cubeb_resampler * resampler);
/**
* Returns the latency, in frames, of the resampler.
* @param resampler A cubeb resampler instance.
* @retval The latency, in frames, induced by the resampler.
*/
long cubeb_resampler_latency(cubeb_resampler * resampler);
#if defined(__cplusplus)
}
#endif
#endif /* CUBEB_RESAMPLER_H */

View File

@ -0,0 +1,556 @@
/*
* Copyright © 2016 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#if !defined(CUBEB_RESAMPLER_INTERNAL)
#define CUBEB_RESAMPLER_INTERNAL
#include <cmath>
#include <cassert>
#include <algorithm>
#include <memory>
#ifdef CUBEB_GECKO_BUILD
#include "mozilla/UniquePtr.h"
// In libc++, symbols such as std::unique_ptr may be defined in std::__1.
// The _LIBCPP_BEGIN_NAMESPACE_STD and _LIBCPP_END_NAMESPACE_STD macros
// will expand to the correct namespace.
#ifdef _LIBCPP_BEGIN_NAMESPACE_STD
#define MOZ_BEGIN_STD_NAMESPACE _LIBCPP_BEGIN_NAMESPACE_STD
#define MOZ_END_STD_NAMESPACE _LIBCPP_END_NAMESPACE_STD
#else
#define MOZ_BEGIN_STD_NAMESPACE namespace std {
#define MOZ_END_STD_NAMESPACE }
#endif
MOZ_BEGIN_STD_NAMESPACE
using mozilla::DefaultDelete;
using mozilla::UniquePtr;
#define default_delete DefaultDelete
#define unique_ptr UniquePtr
MOZ_END_STD_NAMESPACE
#endif
#include "cubeb/cubeb.h"
#include "cubeb_utils.h"
#include "cubeb-speex-resampler.h"
#include "cubeb_resampler.h"
#include <stdio.h>
/* This header file contains the internal C++ API of the resamplers, for testing. */
int to_speex_quality(cubeb_resampler_quality q);
struct cubeb_resampler {
virtual long fill(void * input_buffer, long * input_frames_count,
void * output_buffer, long frames_needed) = 0;
virtual long latency() = 0;
virtual ~cubeb_resampler() {}
};
/** Base class for processors. This is just used to share methods for now. */
class processor {
public:
explicit processor(uint32_t channels)
: channels(channels)
{}
protected:
size_t frames_to_samples(size_t frames)
{
return frames * channels;
}
size_t samples_to_frames(size_t samples)
{
assert(!(samples % channels));
return samples / channels;
}
/** The number of channel of the audio buffers to be resampled. */
const uint32_t channels;
};
template<typename T>
class passthrough_resampler : public cubeb_resampler
, public processor {
public:
passthrough_resampler(cubeb_stream * s,
cubeb_data_callback cb,
void * ptr,
uint32_t input_channels);
virtual long fill(void * input_buffer, long * input_frames_count,
void * output_buffer, long output_frames);
virtual long latency()
{
return 0;
}
private:
cubeb_stream * const stream;
const cubeb_data_callback data_callback;
void * const user_ptr;
/* This allows to buffer some input to account for the fact that we buffer
* some inputs. */
auto_array<T> internal_input_buffer;
};
/** Bidirectional resampler, can resample an input and an output stream, or just
* an input stream or output stream. In this case a delay is inserted in the
* opposite direction to keep the streams synchronized. */
template<typename T, typename InputProcessing, typename OutputProcessing>
class cubeb_resampler_speex : public cubeb_resampler {
public:
cubeb_resampler_speex(InputProcessing * input_processor,
OutputProcessing * output_processor,
cubeb_stream * s,
cubeb_data_callback cb,
void * ptr);
virtual ~cubeb_resampler_speex();
virtual long fill(void * input_buffer, long * input_frames_count,
void * output_buffer, long output_frames_needed);
virtual long latency()
{
if (input_processor && output_processor) {
assert(input_processor->latency() == output_processor->latency());
return input_processor->latency();
} else if (input_processor) {
return input_processor->latency();
} else {
return output_processor->latency();
}
}
private:
typedef long(cubeb_resampler_speex::*processing_callback)(T * input_buffer, long * input_frames_count, T * output_buffer, long output_frames_needed);
long fill_internal_duplex(T * input_buffer, long * input_frames_count,
T * output_buffer, long output_frames_needed);
long fill_internal_input(T * input_buffer, long * input_frames_count,
T * output_buffer, long output_frames_needed);
long fill_internal_output(T * input_buffer, long * input_frames_count,
T * output_buffer, long output_frames_needed);
std::unique_ptr<InputProcessing> input_processor;
std::unique_ptr<OutputProcessing> output_processor;
processing_callback fill_internal;
cubeb_stream * const stream;
const cubeb_data_callback data_callback;
void * const user_ptr;
};
/** Handles one way of a (possibly) duplex resampler, working on interleaved
* audio buffers of type T. This class is designed so that the number of frames
* coming out of the resampler can be precisely controled. It manages its own
* input buffer, and can use the caller's output buffer, or allocate its own. */
template<typename T>
class cubeb_resampler_speex_one_way : public processor {
public:
/** The sample type of this resampler, either 16-bit integers or 32-bit
* floats. */
typedef T sample_type;
/** Construct a resampler resampling from #source_rate to #target_rate, that
* can be arbitrary, strictly positive number.
* @parameter channels The number of channels this resampler will resample.
* @parameter source_rate The sample-rate of the audio input.
* @parameter target_rate The sample-rate of the audio output.
* @parameter quality A number between 0 (fast, low quality) and 10 (slow,
* high quality). */
cubeb_resampler_speex_one_way(uint32_t channels,
uint32_t source_rate,
uint32_t target_rate,
int quality)
: processor(channels)
, resampling_ratio(static_cast<float>(source_rate) / target_rate)
, additional_latency(0)
, leftover_samples(0)
{
int r;
speex_resampler = speex_resampler_init(channels, source_rate,
target_rate, quality, &r);
assert(r == RESAMPLER_ERR_SUCCESS && "resampler allocation failure");
}
/** Destructor, deallocate the resampler */
virtual ~cubeb_resampler_speex_one_way()
{
speex_resampler_destroy(speex_resampler);
}
/** Sometimes, it is necessary to add latency on one way of a two-way
* resampler so that the stream are synchronized. This must be called only on
* a fresh resampler, otherwise, silent samples will be inserted in the
* stream.
* @param frames the number of frames of latency to add. */
void add_latency(size_t frames)
{
additional_latency += frames;
resampling_in_buffer.push_silence(frames_to_samples(frames));
}
/* Fill the resampler with `input_frame_count` frames. */
void input(T * input_buffer, size_t input_frame_count)
{
resampling_in_buffer.push(input_buffer,
frames_to_samples(input_frame_count));
}
/** Outputs exactly `output_frame_count` into `output_buffer`.
* `output_buffer` has to be at least `output_frame_count` long. */
size_t output(T * output_buffer, size_t output_frame_count)
{
uint32_t in_len = samples_to_frames(resampling_in_buffer.length());
uint32_t out_len = output_frame_count;
speex_resample(resampling_in_buffer.data(), &in_len,
output_buffer, &out_len);
/* This shifts back any unresampled samples to the beginning of the input
buffer. */
resampling_in_buffer.pop(nullptr, frames_to_samples(in_len));
return out_len;
}
size_t output_for_input(uint32_t input_frames)
{
return (size_t)floorf((input_frames + samples_to_frames(resampling_in_buffer.length()))
/ resampling_ratio);
}
/** Returns a buffer containing exactly `output_frame_count` resampled frames.
* The consumer should not hold onto the pointer. */
T * output(size_t output_frame_count, size_t * input_frames_used)
{
if (resampling_out_buffer.capacity() < frames_to_samples(output_frame_count)) {
resampling_out_buffer.reserve(frames_to_samples(output_frame_count));
}
uint32_t in_len = samples_to_frames(resampling_in_buffer.length());
uint32_t out_len = output_frame_count;
speex_resample(resampling_in_buffer.data(), &in_len,
resampling_out_buffer.data(), &out_len);
assert(out_len == output_frame_count);
/* This shifts back any unresampled samples to the beginning of the input
buffer. */
resampling_in_buffer.pop(nullptr, frames_to_samples(in_len));
*input_frames_used = in_len;
return resampling_out_buffer.data();
}
/** Get the latency of the resampler, in output frames. */
uint32_t latency() const
{
/* The documentation of the resampler talks about "samples" here, but it
* only consider a single channel here so it's the same number of frames. */
int latency = 0;
latency =
speex_resampler_get_output_latency(speex_resampler) + additional_latency;
assert(latency >= 0);
return latency;
}
/** Returns the number of frames to pass in the input of the resampler to have
* exactly `output_frame_count` resampled frames. This can return a number
* slightly bigger than what is strictly necessary, but it guaranteed that the
* number of output frames will be exactly equal. */
uint32_t input_needed_for_output(uint32_t output_frame_count)
{
int32_t unresampled_frames_left = samples_to_frames(resampling_in_buffer.length());
int32_t resampled_frames_left = samples_to_frames(resampling_out_buffer.length());
float input_frames_needed =
(output_frame_count - unresampled_frames_left) * resampling_ratio
- resampled_frames_left;
if (input_frames_needed < 0) {
return 0;
}
return (uint32_t)ceilf(input_frames_needed);
}
/** Returns a pointer to the input buffer, that contains empty space for at
* least `frame_count` elements. This is useful so that consumer can directly
* write into the input buffer of the resampler. The pointer returned is
* adjusted so that leftover data are not overwritten.
*/
T * input_buffer(size_t frame_count)
{
leftover_samples = resampling_in_buffer.length();
resampling_in_buffer.reserve(leftover_samples +
frames_to_samples(frame_count));
return resampling_in_buffer.data() + leftover_samples;
}
/** This method works with `input_buffer`, and allows to inform the processor
how much frames have been written in the provided buffer. */
void written(size_t written_frames)
{
resampling_in_buffer.set_length(leftover_samples +
frames_to_samples(written_frames));
}
private:
/** Wrapper for the speex resampling functions to have a typed
* interface. */
void speex_resample(float * input_buffer, uint32_t * input_frame_count,
float * output_buffer, uint32_t * output_frame_count)
{
#ifndef NDEBUG
int rv;
rv =
#endif
speex_resampler_process_interleaved_float(speex_resampler,
input_buffer,
input_frame_count,
output_buffer,
output_frame_count);
assert(rv == RESAMPLER_ERR_SUCCESS);
}
void speex_resample(short * input_buffer, uint32_t * input_frame_count,
short * output_buffer, uint32_t * output_frame_count)
{
#ifndef NDEBUG
int rv;
rv =
#endif
speex_resampler_process_interleaved_int(speex_resampler,
input_buffer,
input_frame_count,
output_buffer,
output_frame_count);
assert(rv == RESAMPLER_ERR_SUCCESS);
}
/** The state for the speex resampler used internaly. */
SpeexResamplerState * speex_resampler;
/** Source rate / target rate. */
const float resampling_ratio;
/** Storage for the input frames, to be resampled. Also contains
* any unresampled frames after resampling. */
auto_array<T> resampling_in_buffer;
/* Storage for the resampled frames, to be passed back to the caller. */
auto_array<T> resampling_out_buffer;
/** Additional latency inserted into the pipeline for synchronisation. */
uint32_t additional_latency;
/** When `input_buffer` is called, this allows tracking the number of samples
that were in the buffer. */
uint32_t leftover_samples;
};
/** This class allows delaying an audio stream by `frames` frames. */
template<typename T>
class delay_line : public processor {
public:
/** Constructor
* @parameter frames the number of frames of delay.
* @parameter channels the number of channels of this delay line. */
delay_line(uint32_t frames, uint32_t channels)
: processor(channels)
, length(frames)
, leftover_samples(0)
{
/* Fill the delay line with some silent frames to add latency. */
delay_input_buffer.push_silence(frames * channels);
}
/* Add some latency to the delay line.
* @param frames the number of frames of latency to add. */
void add_latency(size_t frames)
{
length += frames;
delay_input_buffer.push_silence(frames_to_samples(frames));
}
/** Push some frames into the delay line.
* @parameter buffer the frames to push.
* @parameter frame_count the number of frames in #buffer. */
void input(T * buffer, uint32_t frame_count)
{
delay_input_buffer.push(buffer, frames_to_samples(frame_count));
}
/** Pop some frames from the internal buffer, into a internal output buffer.
* @parameter frames_needed the number of frames to be returned.
* @return a buffer containing the delayed frames. The consumer should not
* hold onto the pointer. */
T * output(uint32_t frames_needed, size_t * input_frames_used)
{
if (delay_output_buffer.capacity() < frames_to_samples(frames_needed)) {
delay_output_buffer.reserve(frames_to_samples(frames_needed));
}
delay_output_buffer.clear();
delay_output_buffer.push(delay_input_buffer.data(),
frames_to_samples(frames_needed));
delay_input_buffer.pop(nullptr, frames_to_samples(frames_needed));
*input_frames_used = frames_needed;
return delay_output_buffer.data();
}
/** Get a pointer to the first writable location in the input buffer>
* @parameter frames_needed the number of frames the user needs to write into
* the buffer.
* @returns a pointer to a location in the input buffer where #frames_needed
* can be writen. */
T * input_buffer(uint32_t frames_needed)
{
leftover_samples = delay_input_buffer.length();
delay_input_buffer.reserve(leftover_samples + frames_to_samples(frames_needed));
return delay_input_buffer.data() + leftover_samples;
}
/** This method works with `input_buffer`, and allows to inform the processor
how much frames have been written in the provided buffer. */
void written(size_t frames_written)
{
delay_input_buffer.set_length(leftover_samples +
frames_to_samples(frames_written));
}
/** Drains the delay line, emptying the buffer.
* @parameter output_buffer the buffer in which the frames are written.
* @parameter frames_needed the maximum number of frames to write.
* @return the actual number of frames written. */
size_t output(T * output_buffer, uint32_t frames_needed)
{
uint32_t in_len = samples_to_frames(delay_input_buffer.length());
uint32_t out_len = frames_needed;
uint32_t to_pop = std::min(in_len, out_len);
delay_input_buffer.pop(output_buffer, frames_to_samples(to_pop));
return to_pop;
}
/** Returns the number of frames one needs to input into the delay line to get
* #frames_needed frames back.
* @parameter frames_needed the number of frames one want to write into the
* delay_line
* @returns the number of frames one will get. */
size_t input_needed_for_output(uint32_t frames_needed)
{
return frames_needed;
}
/** Returns the number of frames produces for `input_frames` frames in input */
size_t output_for_input(uint32_t input_frames)
{
return input_frames;
}
/** The number of frames this delay line delays the stream by.
* @returns The number of frames of delay. */
size_t latency()
{
return length;
}
private:
/** The length, in frames, of this delay line */
uint32_t length;
/** When `input_buffer` is called, this allows tracking the number of samples
that where in the buffer. */
uint32_t leftover_samples;
/** The input buffer, where the delay is applied. */
auto_array<T> delay_input_buffer;
/** The output buffer. This is only ever used if using the ::output with a
* single argument. */
auto_array<T> delay_output_buffer;
};
/** This sits behind the C API and is more typed. */
template<typename T>
cubeb_resampler *
cubeb_resampler_create_internal(cubeb_stream * stream,
cubeb_stream_params * input_params,
cubeb_stream_params * output_params,
unsigned int target_rate,
cubeb_data_callback callback,
void * user_ptr,
cubeb_resampler_quality quality)
{
std::unique_ptr<cubeb_resampler_speex_one_way<T>> input_resampler = nullptr;
std::unique_ptr<cubeb_resampler_speex_one_way<T>> output_resampler = nullptr;
std::unique_ptr<delay_line<T>> input_delay = nullptr;
std::unique_ptr<delay_line<T>> output_delay = nullptr;
assert((input_params || output_params) &&
"need at least one valid parameter pointer.");
/* All the streams we have have a sample rate that matches the target
sample rate, use a no-op resampler, that simply forwards the buffers to the
callback. */
if (((input_params && input_params->rate == target_rate) &&
(output_params && output_params->rate == target_rate)) ||
(input_params && !output_params && (input_params->rate == target_rate)) ||
(output_params && !input_params && (output_params->rate == target_rate))) {
return new passthrough_resampler<T>(stream, callback,
user_ptr,
input_params ? input_params->channels : 0);
}
/* Determine if we need to resampler one or both directions, and create the
resamplers. */
if (output_params && (output_params->rate != target_rate)) {
output_resampler.reset(
new cubeb_resampler_speex_one_way<T>(output_params->channels,
target_rate,
output_params->rate,
to_speex_quality(quality)));
if (!output_resampler) {
return NULL;
}
}
if (input_params && (input_params->rate != target_rate)) {
input_resampler.reset(
new cubeb_resampler_speex_one_way<T>(input_params->channels,
input_params->rate,
target_rate,
to_speex_quality(quality)));
if (!input_resampler) {
return NULL;
}
}
/* If we resample only one direction but we have a duplex stream, insert a
* delay line with a length equal to the resampler latency of the
* other direction so that the streams are synchronized. */
if (input_resampler && !output_resampler && input_params && output_params) {
output_delay.reset(new delay_line<T>(input_resampler->latency(),
output_params->channels));
if (!output_delay) {
return NULL;
}
} else if (output_resampler && !input_resampler && input_params && output_params) {
input_delay.reset(new delay_line<T>(output_resampler->latency(),
input_params->channels));
if (!input_delay) {
return NULL;
}
}
if (input_resampler && output_resampler) {
return new cubeb_resampler_speex<T,
cubeb_resampler_speex_one_way<T>,
cubeb_resampler_speex_one_way<T>>
(input_resampler.release(),
output_resampler.release(),
stream, callback, user_ptr);
} else if (input_resampler) {
return new cubeb_resampler_speex<T,
cubeb_resampler_speex_one_way<T>,
delay_line<T>>
(input_resampler.release(),
output_delay.release(),
stream, callback, user_ptr);
} else {
return new cubeb_resampler_speex<T,
delay_line<T>,
cubeb_resampler_speex_one_way<T>>
(input_delay.release(),
output_resampler.release(),
stream, callback, user_ptr);
}
}
#endif /* CUBEB_RESAMPLER_INTERNAL */

159
Externals/cubeb/src/cubeb_ring_array.h vendored Normal file
View File

@ -0,0 +1,159 @@
/*
* Copyright © 2016 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#ifndef CUBEB_RING_ARRAY_H
#define CUBEB_RING_ARRAY_H
#include "cubeb_utils.h"
/** Ring array of pointers is used to hold buffers. In case that
asynchronous producer/consumer callbacks do not arrive in a
repeated order the ring array stores the buffers and fetch
them in the correct order. */
typedef struct {
AudioBuffer * buffer_array; /**< Array that hold pointers of the allocated space for the buffers. */
unsigned int tail; /**< Index of the last element (first to deliver). */
unsigned int count; /**< Number of elements in the array. */
unsigned int capacity; /**< Total length of the array. */
} ring_array;
static int
single_audiobuffer_init(AudioBuffer * buffer,
uint32_t bytesPerFrame,
uint32_t channelsPerFrame,
uint32_t frames)
{
assert(buffer);
assert(bytesPerFrame > 0 && channelsPerFrame && frames > 0);
size_t size = bytesPerFrame * frames;
buffer->mData = operator new(size);
if (buffer->mData == NULL) {
return CUBEB_ERROR;
}
PodZero(static_cast<char*>(buffer->mData), size);
buffer->mNumberChannels = channelsPerFrame;
buffer->mDataByteSize = size;
return CUBEB_OK;
}
/** Initialize the ring array.
@param ra The ring_array pointer of allocated structure.
@retval 0 on success. */
int
ring_array_init(ring_array * ra,
uint32_t capacity,
uint32_t bytesPerFrame,
uint32_t channelsPerFrame,
uint32_t framesPerBuffer)
{
assert(ra);
if (capacity == 0 || bytesPerFrame == 0 ||
channelsPerFrame == 0 || framesPerBuffer == 0) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
ra->capacity = capacity;
ra->tail = 0;
ra->count = 0;
ra->buffer_array = new AudioBuffer[ra->capacity];
PodZero(ra->buffer_array, ra->capacity);
if (ra->buffer_array == NULL) {
return CUBEB_ERROR;
}
for (unsigned int i = 0; i < ra->capacity; ++i) {
if (single_audiobuffer_init(&ra->buffer_array[i],
bytesPerFrame,
channelsPerFrame,
framesPerBuffer) != CUBEB_OK) {
return CUBEB_ERROR;
}
}
return CUBEB_OK;
}
/** Destroy the ring array.
@param ra The ring_array pointer.*/
void
ring_array_destroy(ring_array * ra)
{
assert(ra);
if (ra->buffer_array == NULL){
return;
}
for (unsigned int i = 0; i < ra->capacity; ++i) {
if (ra->buffer_array[i].mData) {
operator delete(ra->buffer_array[i].mData);
}
}
delete [] ra->buffer_array;
}
/** Get the allocated buffer to be stored with fresh data.
@param ra The ring_array pointer.
@retval Pointer of the allocated space to be stored with fresh data or NULL if full. */
AudioBuffer *
ring_array_get_free_buffer(ring_array * ra)
{
assert(ra && ra->buffer_array);
assert(ra->buffer_array[0].mData != NULL);
if (ra->count == ra->capacity) {
return NULL;
}
assert(ra->count == 0 || (ra->tail + ra->count) % ra->capacity != ra->tail);
AudioBuffer * ret = &ra->buffer_array[(ra->tail + ra->count) % ra->capacity];
++ra->count;
assert(ra->count <= ra->capacity);
return ret;
}
/** Get the next available buffer with data.
@param ra The ring_array pointer.
@retval Pointer of the next in order data buffer or NULL if empty. */
AudioBuffer *
ring_array_get_data_buffer(ring_array * ra)
{
assert(ra && ra->buffer_array);
assert(ra->buffer_array[0].mData != NULL);
if (ra->count == 0) {
return NULL;
}
AudioBuffer * ret = &ra->buffer_array[ra->tail];
ra->tail = (ra->tail + 1) % ra->capacity;
assert(ra->tail < ra->capacity);
assert(ra->count > 0);
--ra->count;
return ret;
}
/** When array is empty get the first allocated buffer in the array.
@param ra The ring_array pointer.
@retval If arrays is empty, pointer of the allocated space else NULL. */
AudioBuffer *
ring_array_get_dummy_buffer(ring_array * ra)
{
assert(ra && ra->buffer_array);
assert(ra->capacity > 0);
if (ra->count > 0) {
return NULL;
}
return &ra->buffer_array[0];
}
#endif //CUBEB_RING_ARRAY_H

484
Externals/cubeb/src/cubeb_ringbuffer.h vendored Normal file
View File

@ -0,0 +1,484 @@
/*
* Copyright © 2016 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#ifndef CUBEB_RING_BUFFER_H
#define CUBEB_RING_BUFFER_H
#include "cubeb_utils.h"
#include <algorithm>
#include <atomic>
#include <cstdint>
#include <memory>
#include <thread>
/**
* Single producer single consumer lock-free and wait-free ring buffer.
*
* This data structure allows producing data from one thread, and consuming it on
* another thread, safely and without explicit synchronization. If used on two
* threads, this data structure uses atomics for thread safety. It is possible
* to disable the use of atomics at compile time and only use this data
* structure on one thread.
*
* The role for the producer and the consumer must be constant, i.e., the
* producer should always be on one thread and the consumer should always be on
* another thread.
*
* Some words about the inner workings of this class:
* - Capacity is fixed. Only one allocation is performed, in the constructor.
* When reading and writing, the return value of the method allows checking if
* the ring buffer is empty or full.
* - We always keep the read index at least one element ahead of the write
* index, so we can distinguish between an empty and a full ring buffer: an
* empty ring buffer is when the write index is at the same position as the
* read index. A full buffer is when the write index is exactly one position
* before the read index.
* - We synchronize updates to the read index after having read the data, and
* the write index after having written the data. This means that the each
* thread can only touch a portion of the buffer that is not touched by the
* other thread.
* - Callers are expected to provide buffers. When writing to the queue,
* elements are copied into the internal storage from the buffer passed in.
* When reading from the queue, the user is expected to provide a buffer.
* Because this is a ring buffer, data might not be contiguous in memory,
* providing an external buffer to copy into is an easy way to have linear
* data for further processing.
*/
template <typename T>
class ring_buffer_base
{
public:
/**
* Constructor for a ring buffer.
*
* This performs an allocation, but is the only allocation that will happen
* for the life time of a `ring_buffer_base`.
*
* @param capacity The maximum number of element this ring buffer will hold.
*/
ring_buffer_base(int capacity)
/* One more element to distinguish from empty and full buffer. */
: capacity_(capacity + 1)
{
assert(storage_capacity() <
std::numeric_limits<int>::max() / 2 &&
"buffer too large for the type of index used.");
assert(capacity_ > 0);
data_.reset(new T[storage_capacity()]);
/* If this queue is using atomics, initializing those members as the last
* action in the constructor acts as a full barrier, and allow capacity() to
* be thread-safe. */
write_index_ = 0;
read_index_ = 0;
}
/**
* Push `count` zero or default constructed elements in the array.
*
* Only safely called on the producer thread.
*
* @param count The number of elements to enqueue.
* @return The number of element enqueued.
*/
int enqueue_default(int count)
{
return enqueue(nullptr, count);
}
/**
* @brief Put an element in the queue
*
* Only safely called on the producer thread.
*
* @param element The element to put in the queue.
*
* @return 1 if the element was inserted, 0 otherwise.
*/
int enqueue(T& element)
{
return enqueue(&element, 1);
}
/**
* Push `count` elements in the ring buffer.
*
* Only safely called on the producer thread.
*
* @param elements a pointer to a buffer containing at least `count` elements.
* If `elements` is nullptr, zero or default constructed elements are enqueued.
* @param count The number of elements to read from `elements`
* @return The number of elements successfully coped from `elements` and inserted
* into the ring buffer.
*/
int enqueue(T * elements, int count)
{
#ifndef NDEBUG
assert_correct_thread(producer_id);
#endif
int rd_idx = read_index_.load(std::memory_order::memory_order_relaxed);
int wr_idx = write_index_.load(std::memory_order::memory_order_relaxed);
if (full_internal(rd_idx, wr_idx)) {
return 0;
}
int to_write =
std::min(available_write_internal(rd_idx, wr_idx), count);
/* First part, from the write index to the end of the array. */
int first_part = std::min(storage_capacity() - wr_idx,
to_write);
/* Second part, from the beginning of the array */
int second_part = to_write - first_part;
if (elements) {
Copy(data_.get() + wr_idx, elements, first_part);
Copy(data_.get(), elements + first_part, second_part);
} else {
ConstructDefault(data_.get() + wr_idx, first_part);
ConstructDefault(data_.get(), second_part);
}
write_index_.store(increment_index(wr_idx, to_write), std::memory_order::memory_order_release);
return to_write;
}
/**
* Retrieve at most `count` elements from the ring buffer, and copy them to
* `elements`, if non-null.
*
* Only safely called on the consumer side.
*
* @param elements A pointer to a buffer with space for at least `count`
* elements. If `elements` is `nullptr`, `count` element will be discarded.
* @param count The maximum number of elements to dequeue.
* @return The number of elements written to `elements`.
*/
int dequeue(T * elements, int count)
{
#ifndef NDEBUG
assert_correct_thread(consumer_id);
#endif
int wr_idx = write_index_.load(std::memory_order::memory_order_acquire);
int rd_idx = read_index_.load(std::memory_order::memory_order_relaxed);
if (empty_internal(rd_idx, wr_idx)) {
return 0;
}
int to_read =
std::min(available_read_internal(rd_idx, wr_idx), count);
int first_part = std::min(storage_capacity() - rd_idx, to_read);
int second_part = to_read - first_part;
if (elements) {
Copy(elements, data_.get() + rd_idx, first_part);
Copy(elements + first_part, data_.get(), second_part);
}
read_index_.store(increment_index(rd_idx, to_read), std::memory_order::memory_order_relaxed);
return to_read;
}
/**
* Get the number of available element for consuming.
*
* Only safely called on the consumer thread.
*
* @return The number of available elements for reading.
*/
int available_read() const
{
#ifndef NDEBUG
assert_correct_thread(consumer_id);
#endif
return available_read_internal(read_index_.load(std::memory_order::memory_order_relaxed),
write_index_.load(std::memory_order::memory_order_relaxed));
}
/**
* Get the number of available elements for consuming.
*
* Only safely called on the producer thread.
*
* @return The number of empty slots in the buffer, available for writing.
*/
int available_write() const
{
#ifndef NDEBUG
assert_correct_thread(producer_id);
#endif
return available_write_internal(read_index_.load(std::memory_order::memory_order_relaxed),
write_index_.load(std::memory_order::memory_order_relaxed));
}
/**
* Get the total capacity, for this ring buffer.
*
* Can be called safely on any thread.
*
* @return The maximum capacity of this ring buffer.
*/
int capacity() const
{
return storage_capacity() - 1;
}
private:
/** Return true if the ring buffer is empty.
*
* @param read_index the read index to consider
* @param write_index the write index to consider
* @return true if the ring buffer is empty, false otherwise.
**/
bool empty_internal(int read_index,
int write_index) const
{
return write_index == read_index;
}
/** Return true if the ring buffer is full.
*
* This happens if the write index is exactly one element behind the read
* index.
*
* @param read_index the read index to consider
* @param write_index the write index to consider
* @return true if the ring buffer is full, false otherwise.
**/
bool full_internal(int read_index,
int write_index) const
{
return (write_index + 1) % storage_capacity() == read_index;
}
/**
* Return the size of the storage. It is one more than the number of elements
* that can be stored in the buffer.
*
* @return the number of elements that can be stored in the buffer.
*/
int storage_capacity() const
{
return capacity_;
}
/**
* Returns the number of elements available for reading.
*
* @return the number of available elements for reading.
*/
int
available_read_internal(int read_index,
int write_index) const
{
if (write_index >= read_index) {
return write_index - read_index;
} else {
return write_index + storage_capacity() - read_index;
}
}
/**
* Returns the number of empty elements, available for writing.
*
* @return the number of elements that can be written into the array.
*/
int
available_write_internal(int read_index,
int write_index) const
{
/* We substract one element here to always keep at least one sample
* free in the buffer, to distinguish between full and empty array. */
int rv = read_index - write_index - 1;
if (write_index >= read_index) {
rv += storage_capacity();
}
return rv;
}
/**
* Increments an index, wrapping it around the storage.
*
* @param index a reference to the index to increment.
* @param increment the number by which `index` is incremented.
* @return the new index.
*/
int
increment_index(int index, int increment) const
{
assert(increment >= 0);
return (index + increment) % storage_capacity();
}
/**
* @brief This allows checking that enqueue (resp. dequeue) are always called
* by the right thread.
*
* @param id the id of the thread that has called the calling method first.
*/
#ifndef NDEBUG
static void assert_correct_thread(std::thread::id& id)
{
if (id == std::thread::id()) {
id = std::this_thread::get_id();
return;
}
assert(id == std::this_thread::get_id());
}
#endif
/** Index at which the oldest element is at, in samples. */
std::atomic<int> read_index_;
/** Index at which to write new elements. `write_index` is always at
* least one element ahead of `read_index_`. */
std::atomic<int> write_index_;
/** Maximum number of elements that can be stored in the ring buffer. */
const int capacity_;
/** Data storage */
std::unique_ptr<T[]> data_;
#ifndef NDEBUG
/** The id of the only thread that is allowed to read from the queue. */
mutable std::thread::id consumer_id;
/** The id of the only thread that is allowed to write from the queue. */
mutable std::thread::id producer_id;
#endif
};
/**
* Adapter for `ring_buffer_base` that exposes an interface in frames.
*/
template <typename T>
class audio_ring_buffer_base
{
public:
/**
* @brief Constructor.
*
* @param channel_count Number of channels.
* @param capacity_in_frames The capacity in frames.
*/
audio_ring_buffer_base(int channel_count, int capacity_in_frames)
: channel_count(channel_count)
, ring_buffer(frames_to_samples(capacity_in_frames))
{
assert(channel_count > 0);
}
/**
* @brief Enqueue silence.
*
* Only safely called on the producer thread.
*
* @param frame_count The number of frames of silence to enqueue.
* @return The number of frames of silence actually written to the queue.
*/
int enqueue_default(int frame_count)
{
return samples_to_frames(ring_buffer.enqueue(nullptr, frames_to_samples(frame_count)));
}
/**
* @brief Enqueue `frames_count` frames of audio.
*
* Only safely called from the producer thread.
*
* @param [in] frames If non-null, the frames to enqueue.
* Otherwise, silent frames are enqueued.
* @param frame_count The number of frames to enqueue.
*
* @return The number of frames enqueued
*/
int enqueue(T * frames, int frame_count)
{
return samples_to_frames(ring_buffer.enqueue(frames, frames_to_samples(frame_count)));
}
/**
* @brief Removes `frame_count` frames from the buffer, and
* write them to `frames` if it is non-null.
*
* Only safely called on the consumer thread.
*
* @param frames If non-null, the frames are copied to `frames`.
* Otherwise, they are dropped.
* @param frame_count The number of frames to remove.
*
* @return The number of frames actually dequeud.
*/
int dequeue(T * frames, int frame_count)
{
return samples_to_frames(ring_buffer.dequeue(frames, frames_to_samples(frame_count)));
}
/**
* Get the number of available frames of audio for consuming.
*
* Only safely called on the consumer thread.
*
* @return The number of available frames of audio for reading.
*/
int available_read() const
{
return samples_to_frames(ring_buffer.available_read());
}
/**
* Get the number of available frames of audio for consuming.
*
* Only safely called on the producer thread.
*
* @return The number of empty slots in the buffer, available for writing.
*/
int available_write() const
{
return samples_to_frames(ring_buffer.available_write());
}
/**
* Get the total capacity, for this ring buffer.
*
* Can be called safely on any thread.
*
* @return The maximum capacity of this ring buffer.
*/
int capacity() const
{
return samples_to_frames(ring_buffer.capacity());
}
private:
/**
* @brief Frames to samples conversion.
*
* @param frames The number of frames.
*
* @return A number of samples.
*/
int frames_to_samples(int frames) const
{
return frames * channel_count;
}
/**
* @brief Samples to frames conversion.
*
* @param samples The number of samples.
*
* @return A number of frames.
*/
int samples_to_frames(int samples) const
{
return samples / channel_count;
}
/** Number of channels of audio that will stream through this ring buffer. */
int channel_count;
/** The underlying ring buffer that is used to store the data. */
ring_buffer_base<T> ring_buffer;
};
/**
* Lock-free instantiation of the `ring_buffer_base` type. This is safe to use
* from two threads, one producer, one consumer (that never change role),
* without explicit synchronization.
*/
template<typename T>
using lock_free_queue = ring_buffer_base<T>;
/**
* Lock-free instantiation of the `audio_ring_buffer` type. This is safe to use
* from two threads, one producer, one consumer (that never change role),
* without explicit synchronization.
*/
template<typename T>
using lock_free_audio_ring_buffer = audio_ring_buffer_base<T>;
#endif // CUBEB_RING_BUFFER_H

387
Externals/cubeb/src/cubeb_sndio.c vendored Normal file
View File

@ -0,0 +1,387 @@
/*
* Copyright (c) 2011 Alexandre Ratchov <alex@caoua.org>
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#include <math.h>
#include <poll.h>
#include <pthread.h>
#include <sndio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "cubeb/cubeb.h"
#include "cubeb-internal.h"
#if defined(CUBEB_SNDIO_DEBUG)
#define DPR(...) fprintf(stderr, __VA_ARGS__);
#else
#define DPR(...) do {} while(0)
#endif
static struct cubeb_ops const sndio_ops;
struct cubeb {
struct cubeb_ops const * ops;
};
struct cubeb_stream {
cubeb * context;
pthread_t th; /* to run real-time audio i/o */
pthread_mutex_t mtx; /* protects hdl and pos */
struct sio_hdl *hdl; /* link us to sndio */
int active; /* cubec_start() called */
int conv; /* need float->s16 conversion */
unsigned char *buf; /* data is prepared here */
unsigned int nfr; /* number of frames in buf */
unsigned int bpf; /* bytes per frame */
unsigned int pchan; /* number of play channels */
uint64_t rdpos; /* frame number Joe hears right now */
uint64_t wrpos; /* number of written frames */
cubeb_data_callback data_cb; /* cb to preapare data */
cubeb_state_callback state_cb; /* cb to notify about state changes */
void *arg; /* user arg to {data,state}_cb */
};
static void
float_to_s16(void *ptr, long nsamp)
{
int16_t *dst = ptr;
float *src = ptr;
int s;
while (nsamp-- > 0) {
s = lrintf(*(src++) * 32768);
if (s < -32768)
s = -32768;
else if (s > 32767)
s = 32767;
*(dst++) = s;
}
}
static void
sndio_onmove(void *arg, int delta)
{
cubeb_stream *s = (cubeb_stream *)arg;
s->rdpos += delta * s->bpf;
}
static void *
sndio_mainloop(void *arg)
{
#define MAXFDS 8
struct pollfd pfds[MAXFDS];
cubeb_stream *s = arg;
int n, nfds, revents, state = CUBEB_STATE_STARTED;
size_t start = 0, end = 0;
long nfr;
DPR("sndio_mainloop()\n");
s->state_cb(s, s->arg, CUBEB_STATE_STARTED);
pthread_mutex_lock(&s->mtx);
if (!sio_start(s->hdl)) {
pthread_mutex_unlock(&s->mtx);
return NULL;
}
DPR("sndio_mainloop(), started\n");
start = end = s->nfr;
for (;;) {
if (!s->active) {
DPR("sndio_mainloop() stopped\n");
state = CUBEB_STATE_STOPPED;
break;
}
if (start == end) {
if (end < s->nfr) {
DPR("sndio_mainloop() drained\n");
state = CUBEB_STATE_DRAINED;
break;
}
pthread_mutex_unlock(&s->mtx);
nfr = s->data_cb(s, s->arg, NULL, s->buf, s->nfr);
pthread_mutex_lock(&s->mtx);
if (nfr < 0) {
DPR("sndio_mainloop() cb err\n");
state = CUBEB_STATE_ERROR;
break;
}
if (s->conv)
float_to_s16(s->buf, nfr * s->pchan);
start = 0;
end = nfr * s->bpf;
}
if (end == 0)
continue;
nfds = sio_pollfd(s->hdl, pfds, POLLOUT);
if (nfds > 0) {
pthread_mutex_unlock(&s->mtx);
n = poll(pfds, nfds, -1);
pthread_mutex_lock(&s->mtx);
if (n < 0)
continue;
}
revents = sio_revents(s->hdl, pfds);
if (revents & POLLHUP)
break;
if (revents & POLLOUT) {
n = sio_write(s->hdl, s->buf + start, end - start);
if (n == 0) {
DPR("sndio_mainloop() werr\n");
state = CUBEB_STATE_ERROR;
break;
}
s->wrpos += n;
start += n;
}
}
sio_stop(s->hdl);
s->rdpos = s->wrpos;
pthread_mutex_unlock(&s->mtx);
s->state_cb(s, s->arg, state);
return NULL;
}
/*static*/ int
sndio_init(cubeb **context, char const *context_name)
{
DPR("sndio_init(%s)\n", context_name);
*context = malloc(sizeof(*context));
(*context)->ops = &sndio_ops;
(void)context_name;
return CUBEB_OK;
}
static char const *
sndio_get_backend_id(cubeb *context)
{
return "sndio";
}
static void
sndio_destroy(cubeb *context)
{
DPR("sndio_destroy()\n");
free(context);
}
static int
sndio_stream_init(cubeb * context,
cubeb_stream ** stream,
char const * stream_name,
cubeb_devid input_device,
cubeb_stream_params * input_stream_params,
cubeb_devid output_device,
cubeb_stream_params * output_stream_params,
unsigned int latency_frames,
cubeb_data_callback data_callback,
cubeb_state_callback state_callback,
void *user_ptr)
{
cubeb_stream *s;
struct sio_par wpar, rpar;
DPR("sndio_stream_init(%s)\n", stream_name);
size_t size;
assert(!input_stream_params && "not supported.");
if (input_device || output_device) {
/* Device selection not yet implemented. */
return CUBEB_ERROR_DEVICE_UNAVAILABLE;
}
s = malloc(sizeof(cubeb_stream));
if (s == NULL)
return CUBEB_ERROR;
s->context = context;
s->hdl = sio_open(NULL, SIO_PLAY, 1);
if (s->hdl == NULL) {
free(s);
DPR("sndio_stream_init(), sio_open() failed\n");
return CUBEB_ERROR;
}
sio_initpar(&wpar);
wpar.sig = 1;
wpar.bits = 16;
switch (output_stream_params->format) {
case CUBEB_SAMPLE_S16LE:
wpar.le = 1;
break;
case CUBEB_SAMPLE_S16BE:
wpar.le = 0;
break;
case CUBEB_SAMPLE_FLOAT32NE:
wpar.le = SIO_LE_NATIVE;
break;
default:
sio_close(s->hdl);
free(s);
DPR("sndio_stream_init() unsupported format\n");
return CUBEB_ERROR_INVALID_FORMAT;
}
wpar.rate = output_stream_params->rate;
wpar.pchan = output_stream_params->channels;
wpar.appbufsz = latency_frames;
if (!sio_setpar(s->hdl, &wpar) || !sio_getpar(s->hdl, &rpar)) {
sio_close(s->hdl);
free(s);
DPR("sndio_stream_init(), sio_setpar() failed\n");
return CUBEB_ERROR;
}
if (rpar.bits != wpar.bits || rpar.le != wpar.le ||
rpar.sig != wpar.sig || rpar.rate != wpar.rate ||
rpar.pchan != wpar.pchan) {
sio_close(s->hdl);
free(s);
DPR("sndio_stream_init() unsupported params\n");
return CUBEB_ERROR_INVALID_FORMAT;
}
sio_onmove(s->hdl, sndio_onmove, s);
s->active = 0;
s->nfr = rpar.round;
s->bpf = rpar.bps * rpar.pchan;
s->pchan = rpar.pchan;
s->data_cb = data_callback;
s->state_cb = state_callback;
s->arg = user_ptr;
s->mtx = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
s->rdpos = s->wrpos = 0;
if (output_stream_params->format == CUBEB_SAMPLE_FLOAT32LE) {
s->conv = 1;
size = rpar.round * rpar.pchan * sizeof(float);
} else {
s->conv = 0;
size = rpar.round * rpar.pchan * rpar.bps;
}
s->buf = malloc(size);
if (s->buf == NULL) {
sio_close(s->hdl);
free(s);
return CUBEB_ERROR;
}
*stream = s;
DPR("sndio_stream_init() end, ok\n");
(void)context;
(void)stream_name;
return CUBEB_OK;
}
static int
sndio_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
{
assert(ctx && max_channels);
*max_channels = 8;
return CUBEB_OK;
}
static int
sndio_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
{
// XXX Not yet implemented.
*rate = 44100;
return CUBEB_OK;
}
static int
sndio_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * latency_frames)
{
// XXX Not yet implemented.
*latency_frames = 2048;
return CUBEB_OK;
}
static void
sndio_stream_destroy(cubeb_stream *s)
{
DPR("sndio_stream_destroy()\n");
sio_close(s->hdl);
free(s);
}
static int
sndio_stream_start(cubeb_stream *s)
{
int err;
DPR("sndio_stream_start()\n");
s->active = 1;
err = pthread_create(&s->th, NULL, sndio_mainloop, s);
if (err) {
s->active = 0;
return CUBEB_ERROR;
}
return CUBEB_OK;
}
static int
sndio_stream_stop(cubeb_stream *s)
{
void *dummy;
DPR("sndio_stream_stop()\n");
if (s->active) {
s->active = 0;
pthread_join(s->th, &dummy);
}
return CUBEB_OK;
}
static int
sndio_stream_get_position(cubeb_stream *s, uint64_t *p)
{
pthread_mutex_lock(&s->mtx);
DPR("sndio_stream_get_position() %lld\n", s->rdpos);
*p = s->rdpos / s->bpf;
pthread_mutex_unlock(&s->mtx);
return CUBEB_OK;
}
static int
sndio_stream_set_volume(cubeb_stream *s, float volume)
{
DPR("sndio_stream_set_volume(%f)\n", volume);
pthread_mutex_lock(&s->mtx);
sio_setvol(s->hdl, SIO_MAXVOL * volume);
pthread_mutex_unlock(&s->mtx);
return CUBEB_OK;
}
int
sndio_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
{
// http://www.openbsd.org/cgi-bin/man.cgi?query=sio_open
// in the "Measuring the latency and buffers usage" paragraph.
*latency = (stm->wrpos - stm->rdpos) / stm->bpf;
return CUBEB_OK;
}
static struct cubeb_ops const sndio_ops = {
.init = sndio_init,
.get_backend_id = sndio_get_backend_id,
.get_max_channel_count = sndio_get_max_channel_count,
.get_min_latency = sndio_get_min_latency,
.get_preferred_sample_rate = sndio_get_preferred_sample_rate,
.get_preferred_channel_layout = NULL,
.enumerate_devices = NULL,
.device_collection_destroy = NULL,
.destroy = sndio_destroy,
.stream_init = sndio_stream_init,
.stream_destroy = sndio_stream_destroy,
.stream_start = sndio_stream_start,
.stream_stop = sndio_stream_stop,
.stream_get_position = sndio_stream_get_position,
.stream_get_latency = sndio_stream_get_latency,
.stream_set_volume = sndio_stream_set_volume,
.stream_set_panning = NULL,
.stream_get_current_device = NULL,
.stream_device_destroy = NULL,
.stream_register_device_changed_callback = NULL,
.register_device_collection_changed = NULL
};

38
Externals/cubeb/src/cubeb_utils.c vendored Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright © 2016 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#include "cubeb_utils.h"
#include "cubeb_assert.h"
#include <stdlib.h>
static void
device_info_destroy(cubeb_device_info * info)
{
XASSERT(info);
free((void *) info->device_id);
free((void *) info->friendly_name);
free((void *) info->group_id);
free((void *) info->vendor_name);
}
int
cubeb_utils_default_device_collection_destroy(cubeb * context,
cubeb_device_collection * collection)
{
uint32_t i;
XASSERT(collection);
(void) context;
for (i = 0; i < collection->count; i++)
device_info_destroy(&collection->device[i]);
free(collection->device);
return CUBEB_OK;
}

352
Externals/cubeb/src/cubeb_utils.h vendored Normal file
View File

@ -0,0 +1,352 @@
/*
* Copyright © 2016 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#if !defined(CUBEB_UTILS)
#define CUBEB_UTILS
#include "cubeb/cubeb.h"
#ifdef __cplusplus
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <mutex>
#include <type_traits>
#if defined(WIN32)
#include "cubeb_utils_win.h"
#else
#include "cubeb_utils_unix.h"
#endif
/** Similar to memcpy, but accounts for the size of an element. */
template<typename T>
void PodCopy(T * destination, const T * source, size_t count)
{
static_assert(std::is_trivial<T>::value, "Requires trivial type");
assert(destination && source);
memcpy(destination, source, count * sizeof(T));
}
/** Similar to memmove, but accounts for the size of an element. */
template<typename T>
void PodMove(T * destination, const T * source, size_t count)
{
static_assert(std::is_trivial<T>::value, "Requires trivial type");
assert(destination && source);
memmove(destination, source, count * sizeof(T));
}
/** Similar to a memset to zero, but accounts for the size of an element. */
template<typename T>
void PodZero(T * destination, size_t count)
{
static_assert(std::is_trivial<T>::value, "Requires trivial type");
assert(destination);
memset(destination, 0, count * sizeof(T));
}
namespace {
template<typename T, typename Trait>
void Copy(T * destination, const T * source, size_t count, Trait)
{
for (size_t i = 0; i < count; i++) {
destination[i] = source[i];
}
}
template<typename T>
void Copy(T * destination, const T * source, size_t count, std::true_type)
{
PodCopy(destination, source, count);
}
}
/**
* This allows copying a number of elements from a `source` pointer to a
* `destination` pointer, using `memcpy` if it is safe to do so, or a loop that
* calls the constructors and destructors otherwise.
*/
template<typename T>
void Copy(T * destination, const T * source, size_t count)
{
assert(destination && source);
Copy(destination, source, count, typename std::is_trivial<T>::type());
}
namespace {
template<typename T, typename Trait>
void ConstructDefault(T * destination, size_t count, Trait)
{
for (size_t i = 0; i < count; i++) {
destination[i] = T();
}
}
template<typename T>
void ConstructDefault(T * destination,
size_t count, std::true_type)
{
PodZero(destination, count);
}
}
/**
* This allows zeroing (using memset) or default-constructing a number of
* elements calling the constructors and destructors if necessary.
*/
template<typename T>
void ConstructDefault(T * destination, size_t count)
{
assert(destination);
ConstructDefault(destination, count,
typename std::is_arithmetic<T>::type());
}
template<typename T>
class auto_array
{
public:
explicit auto_array(uint32_t capacity = 0)
: data_(capacity ? new T[capacity] : nullptr)
, capacity_(capacity)
, length_(0)
{}
~auto_array()
{
delete [] data_;
}
/** Get a constant pointer to the underlying data. */
T * data() const
{
return data_;
}
T * end() const
{
return data_ + length_;
}
const T& at(size_t index) const
{
assert(index < length_ && "out of range");
return data_[index];
}
T& at(size_t index)
{
assert(index < length_ && "out of range");
return data_[index];
}
/** Get how much underlying storage this auto_array has. */
size_t capacity() const
{
return capacity_;
}
/** Get how much elements this auto_array contains. */
size_t length() const
{
return length_;
}
/** Keeps the storage, but removes all the elements from the array. */
void clear()
{
length_ = 0;
}
/** Change the storage of this auto array, copying the elements to the new
* storage.
* @returns true in case of success
* @returns false if the new capacity is not big enough to accomodate for the
* elements in the array.
*/
bool reserve(size_t new_capacity)
{
if (new_capacity < length_) {
return false;
}
T * new_data = new T[new_capacity];
if (data_ && length_) {
PodCopy(new_data, data_, length_);
}
capacity_ = new_capacity;
delete [] data_;
data_ = new_data;
return true;
}
/** Append `length` elements to the end of the array, resizing the array if
* needed.
* @parameter elements the elements to append to the array.
* @parameter length the number of elements to append to the array.
*/
void push(const T * elements, size_t length)
{
if (length_ + length > capacity_) {
reserve(length_ + length);
}
PodCopy(data_ + length_, elements, length);
length_ += length;
}
/** Append `length` zero-ed elements to the end of the array, resizing the
* array if needed.
* @parameter length the number of elements to append to the array.
*/
void push_silence(size_t length)
{
if (length_ + length > capacity_) {
reserve(length + length_);
}
PodZero(data_ + length_, length);
length_ += length;
}
/** Prepend `length` zero-ed elements to the end of the array, resizing the
* array if needed.
* @parameter length the number of elements to prepend to the array.
*/
void push_front_silence(size_t length)
{
if (length_ + length > capacity_) {
reserve(length + length_);
}
PodMove(data_ + length, data_, length_);
PodZero(data_, length);
length_ += length;
}
/** Return the number of free elements in the array. */
size_t available() const
{
return capacity_ - length_;
}
/** Copies `length` elements to `elements` if it is not null, and shift
* the remaining elements of the `auto_array` to the beginning.
* @parameter elements a buffer to copy the elements to, or nullptr.
* @parameter length the number of elements to copy.
* @returns true in case of success.
* @returns false if the auto_array contains less than `length` elements. */
bool pop(T * elements, size_t length)
{
if (length > length_) {
return false;
}
if (elements) {
PodCopy(elements, data_, length);
}
PodMove(data_, data_ + length, length_ - length);
length_ -= length;
return true;
}
void set_length(size_t length)
{
assert(length <= capacity_);
length_ = length;
}
private:
/** The underlying storage */
T * data_;
/** The size, in number of elements, of the storage. */
size_t capacity_;
/** The number of elements the array contains. */
size_t length_;
};
struct auto_array_wrapper {
virtual void push(void * elements, size_t length) = 0;
virtual size_t length() = 0;
virtual void push_silence(size_t length) = 0;
virtual bool pop(size_t length) = 0;
virtual void * data() = 0;
virtual void * end() = 0;
virtual void clear() = 0;
virtual bool reserve(size_t capacity) = 0;
virtual void set_length(size_t length) = 0;
virtual ~auto_array_wrapper() {}
};
template <typename T>
struct auto_array_wrapper_impl : public auto_array_wrapper {
auto_array_wrapper_impl() {}
explicit auto_array_wrapper_impl(uint32_t size)
: ar(size)
{}
void push(void * elements, size_t length) override {
ar.push(static_cast<T *>(elements), length);
}
size_t length() override {
return ar.length();
}
void push_silence(size_t length) override {
ar.push_silence(length);
}
bool pop(size_t length) override {
return ar.pop(nullptr, length);
}
void * data() override {
return ar.data();
}
void * end() override {
return ar.end();
}
void clear() override {
ar.clear();
}
bool reserve(size_t capacity) override {
return ar.reserve(capacity);
}
void set_length(size_t length) override {
ar.set_length(length);
}
~auto_array_wrapper_impl() {
ar.clear();
}
private:
auto_array<T> ar;
};
using auto_lock = std::lock_guard<owned_critical_section>;
#endif // __cplusplus
// C language helpers
#ifdef __cplusplus
extern "C" {
#endif
int cubeb_utils_default_device_collection_destroy(cubeb * context,
cubeb_device_collection * collection);
#ifdef __cplusplus
}
#endif
#endif /* CUBEB_UTILS */

89
Externals/cubeb/src/cubeb_utils_unix.h vendored Normal file
View File

@ -0,0 +1,89 @@
/*
* Copyright © 2016 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#if !defined(CUBEB_UTILS_UNIX)
#define CUBEB_UTILS_UNIX
#include <pthread.h>
#include <errno.h>
#include <stdio.h>
/* This wraps a critical section to track the owner in debug mode. */
class owned_critical_section
{
public:
owned_critical_section()
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
#ifndef NDEBUG
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
#else
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
#endif
#ifndef NDEBUG
int r =
#endif
pthread_mutex_init(&mutex, &attr);
#ifndef NDEBUG
assert(r == 0);
#endif
pthread_mutexattr_destroy(&attr);
}
~owned_critical_section()
{
#ifndef NDEBUG
int r =
#endif
pthread_mutex_destroy(&mutex);
#ifndef NDEBUG
assert(r == 0);
#endif
}
void lock()
{
#ifndef NDEBUG
int r =
#endif
pthread_mutex_lock(&mutex);
#ifndef NDEBUG
assert(r == 0 && "Deadlock");
#endif
}
void unlock()
{
#ifndef NDEBUG
int r =
#endif
pthread_mutex_unlock(&mutex);
#ifndef NDEBUG
assert(r == 0 && "Unlocking unlocked mutex");
#endif
}
void assert_current_thread_owns()
{
#ifndef NDEBUG
int r = pthread_mutex_lock(&mutex);
assert(r == EDEADLK);
#endif
}
private:
pthread_mutex_t mutex;
// Disallow copy and assignment because pthread_mutex_t cannot be copied.
owned_critical_section(const owned_critical_section&);
owned_critical_section& operator=(const owned_critical_section&);
};
#endif /* CUBEB_UTILS_UNIX */

71
Externals/cubeb/src/cubeb_utils_win.h vendored Normal file
View File

@ -0,0 +1,71 @@
/*
* Copyright © 2016 Mozilla Foundation
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#if !defined(CUBEB_UTILS_WIN)
#define CUBEB_UTILS_WIN
#include <windows.h>
#include "cubeb-internal.h"
/* This wraps a critical section to track the owner in debug mode, adapted from
NSPR and http://blogs.msdn.com/b/oldnewthing/archive/2013/07/12/10433554.aspx */
class owned_critical_section
{
public:
owned_critical_section()
#ifndef NDEBUG
: owner(0)
#endif
{
InitializeCriticalSection(&critical_section);
}
~owned_critical_section()
{
DeleteCriticalSection(&critical_section);
}
void lock()
{
EnterCriticalSection(&critical_section);
#ifndef NDEBUG
XASSERT(owner != GetCurrentThreadId() && "recursive locking");
owner = GetCurrentThreadId();
#endif
}
void unlock()
{
#ifndef NDEBUG
/* GetCurrentThreadId cannot return 0: it is not a the valid thread id */
owner = 0;
#endif
LeaveCriticalSection(&critical_section);
}
/* This is guaranteed to have the good behaviour if it succeeds. The behaviour
is undefined otherwise. */
void assert_current_thread_owns()
{
#ifndef NDEBUG
/* This implies owner != 0, because GetCurrentThreadId cannot return 0. */
XASSERT(owner == GetCurrentThreadId());
#endif
}
private:
CRITICAL_SECTION critical_section;
#ifndef NDEBUG
DWORD owner;
#endif
// Disallow copy and assignment because CRICICAL_SECTION cannot be copied.
owned_critical_section(const owned_critical_section&);
owned_critical_section& operator=(const owned_critical_section&);
};
#endif /* CUBEB_UTILS_WIN */

2349
Externals/cubeb/src/cubeb_wasapi.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

1042
Externals/cubeb/src/cubeb_winmm.c vendored Normal file

File diff suppressed because it is too large Load Diff

235
Externals/cubeb/src/speex/arch.h vendored Normal file
View File

@ -0,0 +1,235 @@
/* Copyright (C) 2003 Jean-Marc Valin */
/**
@file arch.h
@brief Various architecture definitions Speex
*/
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of the Xiph.org Foundation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef ARCH_H
#define ARCH_H
/* A couple test to catch stupid option combinations */
#ifdef FIXED_POINT
#ifdef FLOATING_POINT
#error You cannot compile as floating point and fixed point at the same time
#endif
#ifdef _USE_SSE
#error SSE is only for floating-point
#endif
#if ((defined (ARM4_ASM)||defined (ARM4_ASM)) && defined(BFIN_ASM)) || (defined (ARM4_ASM)&&defined(ARM5E_ASM))
#error Make up your mind. What CPU do you have?
#endif
#ifdef VORBIS_PSYCHO
#error Vorbis-psy model currently not implemented in fixed-point
#endif
#else
#ifndef FLOATING_POINT
#error You now need to define either FIXED_POINT or FLOATING_POINT
#endif
#if defined (ARM4_ASM) || defined(ARM5E_ASM) || defined(BFIN_ASM)
#error I suppose you can have a [ARM4/ARM5E/Blackfin] that has float instructions?
#endif
#ifdef FIXED_POINT_DEBUG
#error "Don't you think enabling fixed-point is a good thing to do if you want to debug that?"
#endif
#endif
#ifndef OUTSIDE_SPEEX
#include "speex/speexdsp_types.h"
#endif
#define ABS(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute integer value. */
#define ABS16(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 16-bit value. */
#define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 16-bit value. */
#define MAX16(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 16-bit value. */
#define ABS32(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 32-bit value. */
#define MIN32(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 32-bit value. */
#define MAX32(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 32-bit value. */
#ifdef FIXED_POINT
typedef spx_int16_t spx_word16_t;
typedef spx_int32_t spx_word32_t;
typedef spx_word32_t spx_mem_t;
typedef spx_word16_t spx_coef_t;
typedef spx_word16_t spx_lsp_t;
typedef spx_word32_t spx_sig_t;
#define Q15ONE 32767
#define LPC_SCALING 8192
#define SIG_SCALING 16384
#define LSP_SCALING 8192.
#define GAMMA_SCALING 32768.
#define GAIN_SCALING 64
#define GAIN_SCALING_1 0.015625
#define LPC_SHIFT 13
#define LSP_SHIFT 13
#define SIG_SHIFT 14
#define GAIN_SHIFT 6
#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))
#define VERY_SMALL 0
#define VERY_LARGE32 ((spx_word32_t)2147483647)
#define VERY_LARGE16 ((spx_word16_t)32767)
#define Q15_ONE ((spx_word16_t)32767)
#ifdef FIXED_DEBUG
#include "fixed_debug.h"
#else
#include "fixed_generic.h"
#ifdef ARM5E_ASM
#include "fixed_arm5e.h"
#elif defined (ARM4_ASM)
#include "fixed_arm4.h"
#elif defined (BFIN_ASM)
#include "fixed_bfin.h"
#endif
#endif
#else
typedef float spx_mem_t;
typedef float spx_coef_t;
typedef float spx_lsp_t;
typedef float spx_sig_t;
typedef float spx_word16_t;
typedef float spx_word32_t;
#define Q15ONE 1.0f
#define LPC_SCALING 1.f
#define SIG_SCALING 1.f
#define LSP_SCALING 1.f
#define GAMMA_SCALING 1.f
#define GAIN_SCALING 1.f
#define GAIN_SCALING_1 1.f
#define VERY_SMALL 1e-15f
#define VERY_LARGE32 1e15f
#define VERY_LARGE16 1e15f
#define Q15_ONE ((spx_word16_t)1.f)
#define QCONST16(x,bits) (x)
#define QCONST32(x,bits) (x)
#define NEG16(x) (-(x))
#define NEG32(x) (-(x))
#define EXTRACT16(x) (x)
#define EXTEND32(x) (x)
#define SHR16(a,shift) (a)
#define SHL16(a,shift) (a)
#define SHR32(a,shift) (a)
#define SHL32(a,shift) (a)
#define PSHR16(a,shift) (a)
#define PSHR32(a,shift) (a)
#define VSHR32(a,shift) (a)
#define SATURATE16(x,a) (x)
#define SATURATE32(x,a) (x)
#define SATURATE32PSHR(x,shift,a) (x)
#define PSHR(a,shift) (a)
#define SHR(a,shift) (a)
#define SHL(a,shift) (a)
#define SATURATE(x,a) (x)
#define ADD16(a,b) ((a)+(b))
#define SUB16(a,b) ((a)-(b))
#define ADD32(a,b) ((a)+(b))
#define SUB32(a,b) ((a)-(b))
#define MULT16_16_16(a,b) ((a)*(b))
#define MULT16_16(a,b) ((spx_word32_t)(a)*(spx_word32_t)(b))
#define MAC16_16(c,a,b) ((c)+(spx_word32_t)(a)*(spx_word32_t)(b))
#define MULT16_32_Q11(a,b) ((a)*(b))
#define MULT16_32_Q13(a,b) ((a)*(b))
#define MULT16_32_Q14(a,b) ((a)*(b))
#define MULT16_32_Q15(a,b) ((a)*(b))
#define MULT16_32_P15(a,b) ((a)*(b))
#define MAC16_32_Q11(c,a,b) ((c)+(a)*(b))
#define MAC16_32_Q15(c,a,b) ((c)+(a)*(b))
#define MAC16_16_Q11(c,a,b) ((c)+(a)*(b))
#define MAC16_16_Q13(c,a,b) ((c)+(a)*(b))
#define MAC16_16_P13(c,a,b) ((c)+(a)*(b))
#define MULT16_16_Q11_32(a,b) ((a)*(b))
#define MULT16_16_Q13(a,b) ((a)*(b))
#define MULT16_16_Q14(a,b) ((a)*(b))
#define MULT16_16_Q15(a,b) ((a)*(b))
#define MULT16_16_P15(a,b) ((a)*(b))
#define MULT16_16_P13(a,b) ((a)*(b))
#define MULT16_16_P14(a,b) ((a)*(b))
#define DIV32_16(a,b) (((spx_word32_t)(a))/(spx_word16_t)(b))
#define PDIV32_16(a,b) (((spx_word32_t)(a))/(spx_word16_t)(b))
#define DIV32(a,b) (((spx_word32_t)(a))/(spx_word32_t)(b))
#define PDIV32(a,b) (((spx_word32_t)(a))/(spx_word32_t)(b))
#define WORD2INT(x) ((x) < -32767.5f ? -32768 : \
((x) > 32766.5f ? 32767 : (spx_int16_t)floor(.5 + (x))))
#endif
#if defined (CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
/* 2 on TI C5x DSP */
#define BYTES_PER_CHAR 2
#define BITS_PER_CHAR 16
#define LOG2_BITS_PER_CHAR 4
#else
#define BYTES_PER_CHAR 1
#define BITS_PER_CHAR 8
#define LOG2_BITS_PER_CHAR 3
#endif
#ifdef FIXED_DEBUG
extern long long spx_mips;
#endif
#endif

View File

@ -0,0 +1,110 @@
/* Copyright (C) 2003 Jean-Marc Valin */
/**
@file fixed_generic.h
@brief Generic fixed-point operations
*/
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of the Xiph.org Foundation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FIXED_GENERIC_H
#define FIXED_GENERIC_H
#define QCONST16(x,bits) ((spx_word16_t)(.5+(x)*(((spx_word32_t)1)<<(bits))))
#define QCONST32(x,bits) ((spx_word32_t)(.5+(x)*(((spx_word32_t)1)<<(bits))))
#define NEG16(x) (-(x))
#define NEG32(x) (-(x))
#define EXTRACT16(x) ((spx_word16_t)(x))
#define EXTEND32(x) ((spx_word32_t)(x))
#define SHR16(a,shift) ((a) >> (shift))
#define SHL16(a,shift) ((a) << (shift))
#define SHR32(a,shift) ((a) >> (shift))
#define SHL32(a,shift) ((a) << (shift))
#define PSHR16(a,shift) (SHR16((a)+((1<<((shift))>>1)),shift))
#define PSHR32(a,shift) (SHR32((a)+((EXTEND32(1)<<((shift))>>1)),shift))
#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
#define SATURATE32PSHR(x,shift,a) (((x)>=(SHL32(a,shift))) ? (a) : \
(x)<=-(SHL32(a,shift)) ? -(a) : \
(PSHR32(x, shift)))
#define SHR(a,shift) ((a) >> (shift))
#define SHL(a,shift) ((spx_word32_t)(a) << (shift))
#define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift))
#define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
#define ADD16(a,b) ((spx_word16_t)((spx_word16_t)(a)+(spx_word16_t)(b)))
#define SUB16(a,b) ((spx_word16_t)(a)-(spx_word16_t)(b))
#define ADD32(a,b) ((spx_word32_t)(a)+(spx_word32_t)(b))
#define SUB32(a,b) ((spx_word32_t)(a)-(spx_word32_t)(b))
/* result fits in 16 bits */
#define MULT16_16_16(a,b) ((((spx_word16_t)(a))*((spx_word16_t)(b))))
/* (spx_word32_t)(spx_word16_t) gives TI compiler a hint that it's 16x16->32 multiply */
#define MULT16_16(a,b) (((spx_word32_t)(spx_word16_t)(a))*((spx_word32_t)(spx_word16_t)(b)))
#define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b))))
#define MULT16_32_Q12(a,b) ADD32(MULT16_16((a),SHR((b),12)), SHR(MULT16_16((a),((b)&0x00000fff)),12))
#define MULT16_32_Q13(a,b) ADD32(MULT16_16((a),SHR((b),13)), SHR(MULT16_16((a),((b)&0x00001fff)),13))
#define MULT16_32_Q14(a,b) ADD32(MULT16_16((a),SHR((b),14)), SHR(MULT16_16((a),((b)&0x00003fff)),14))
#define MULT16_32_Q11(a,b) ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11))
#define MAC16_32_Q11(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11)))
#define MULT16_32_P15(a,b) ADD32(MULT16_16((a),SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15))
#define MULT16_32_Q15(a,b) ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))
#define MAC16_32_Q15(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)))
#define MAC16_16_Q11(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),11)))
#define MAC16_16_Q13(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),13)))
#define MAC16_16_P13(c,a,b) (ADD32((c),SHR(ADD32(4096,MULT16_16((a),(b))),13)))
#define MULT16_16_Q11_32(a,b) (SHR(MULT16_16((a),(b)),11))
#define MULT16_16_Q13(a,b) (SHR(MULT16_16((a),(b)),13))
#define MULT16_16_Q14(a,b) (SHR(MULT16_16((a),(b)),14))
#define MULT16_16_Q15(a,b) (SHR(MULT16_16((a),(b)),15))
#define MULT16_16_P13(a,b) (SHR(ADD32(4096,MULT16_16((a),(b))),13))
#define MULT16_16_P14(a,b) (SHR(ADD32(8192,MULT16_16((a),(b))),14))
#define MULT16_16_P15(a,b) (SHR(ADD32(16384,MULT16_16((a),(b))),15))
#define MUL_16_32_R15(a,bh,bl) ADD32(MULT16_16((a),(bh)), SHR(MULT16_16((a),(bl)),15))
#define DIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a))/((spx_word16_t)(b))))
#define PDIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word16_t)(b))))
#define DIV32(a,b) (((spx_word32_t)(a))/((spx_word32_t)(b)))
#define PDIV32(a,b) (((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word32_t)(b)))
#endif

1237
Externals/cubeb/src/speex/resample.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,201 @@
/* Copyright (C) 2007-2008 Jean-Marc Valin
* Copyright (C) 2008 Thorvald Natvig
* Copyright (C) 2011 Texas Instruments
* author Jyri Sarha
*/
/**
@file resample_neon.h
@brief Resampler functions (NEON version)
*/
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of the Xiph.org Foundation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <arm_neon.h>
#ifdef FIXED_POINT
#ifdef __thumb2__
static inline int32_t saturate_32bit_to_16bit(int32_t a) {
int32_t ret;
asm ("ssat %[ret], #16, %[a]"
: [ret] "=&r" (ret)
: [a] "r" (a)
: );
return ret;
}
#else
static inline int32_t saturate_32bit_to_16bit(int32_t a) {
int32_t ret;
asm ("vmov.s32 d0[0], %[a]\n"
"vqmovn.s32 d0, q0\n"
"vmov.s16 %[ret], d0[0]\n"
: [ret] "=&r" (ret)
: [a] "r" (a)
: "q0");
return ret;
}
#endif
#undef WORD2INT
#define WORD2INT(x) (saturate_32bit_to_16bit(x))
#define OVERRIDE_INNER_PRODUCT_SINGLE
/* Only works when len % 4 == 0 */
static inline int32_t inner_product_single(const int16_t *a, const int16_t *b, unsigned int len)
{
int32_t ret;
uint32_t remainder = len % 16;
len = len - remainder;
asm volatile (" cmp %[len], #0\n"
" bne 1f\n"
" vld1.16 {d16}, [%[b]]!\n"
" vld1.16 {d20}, [%[a]]!\n"
" subs %[remainder], %[remainder], #4\n"
" vmull.s16 q0, d16, d20\n"
" beq 5f\n"
" b 4f\n"
"1:"
" vld1.16 {d16, d17, d18, d19}, [%[b]]!\n"
" vld1.16 {d20, d21, d22, d23}, [%[a]]!\n"
" subs %[len], %[len], #16\n"
" vmull.s16 q0, d16, d20\n"
" vmlal.s16 q0, d17, d21\n"
" vmlal.s16 q0, d18, d22\n"
" vmlal.s16 q0, d19, d23\n"
" beq 3f\n"
"2:"
" vld1.16 {d16, d17, d18, d19}, [%[b]]!\n"
" vld1.16 {d20, d21, d22, d23}, [%[a]]!\n"
" subs %[len], %[len], #16\n"
" vmlal.s16 q0, d16, d20\n"
" vmlal.s16 q0, d17, d21\n"
" vmlal.s16 q0, d18, d22\n"
" vmlal.s16 q0, d19, d23\n"
" bne 2b\n"
"3:"
" cmp %[remainder], #0\n"
" beq 5f\n"
"4:"
" vld1.16 {d16}, [%[b]]!\n"
" vld1.16 {d20}, [%[a]]!\n"
" subs %[remainder], %[remainder], #4\n"
" vmlal.s16 q0, d16, d20\n"
" bne 4b\n"
"5:"
" vaddl.s32 q0, d0, d1\n"
" vadd.s64 d0, d0, d1\n"
" vqmovn.s64 d0, q0\n"
" vqrshrn.s32 d0, q0, #15\n"
" vmov.s16 %[ret], d0[0]\n"
: [ret] "=&r" (ret), [a] "+r" (a), [b] "+r" (b),
[len] "+r" (len), [remainder] "+r" (remainder)
:
: "cc", "q0",
"d16", "d17", "d18", "d19",
"d20", "d21", "d22", "d23");
return ret;
}
#elif defined(FLOATING_POINT)
static inline int32_t saturate_float_to_16bit(float a) {
int32_t ret;
asm ("vmov.f32 d0[0], %[a]\n"
"vcvt.s32.f32 d0, d0, #15\n"
"vqrshrn.s32 d0, q0, #15\n"
"vmov.s16 %[ret], d0[0]\n"
: [ret] "=&r" (ret)
: [a] "r" (a)
: "q0");
return ret;
}
#undef WORD2INT
#define WORD2INT(x) (saturate_float_to_16bit(x))
#define OVERRIDE_INNER_PRODUCT_SINGLE
/* Only works when len % 4 == 0 */
static inline float inner_product_single(const float *a, const float *b, unsigned int len)
{
float ret;
uint32_t remainder = len % 16;
len = len - remainder;
asm volatile (" cmp %[len], #0\n"
" bne 1f\n"
" vld1.32 {q4}, [%[b]]!\n"
" vld1.32 {q8}, [%[a]]!\n"
" subs %[remainder], %[remainder], #4\n"
" vmul.f32 q0, q4, q8\n"
" bne 4f\n"
" b 5f\n"
"1:"
" vld1.32 {q4, q5}, [%[b]]!\n"
" vld1.32 {q8, q9}, [%[a]]!\n"
" vld1.32 {q6, q7}, [%[b]]!\n"
" vld1.32 {q10, q11}, [%[a]]!\n"
" subs %[len], %[len], #16\n"
" vmul.f32 q0, q4, q8\n"
" vmul.f32 q1, q5, q9\n"
" vmul.f32 q2, q6, q10\n"
" vmul.f32 q3, q7, q11\n"
" beq 3f\n"
"2:"
" vld1.32 {q4, q5}, [%[b]]!\n"
" vld1.32 {q8, q9}, [%[a]]!\n"
" vld1.32 {q6, q7}, [%[b]]!\n"
" vld1.32 {q10, q11}, [%[a]]!\n"
" subs %[len], %[len], #16\n"
" vmla.f32 q0, q4, q8\n"
" vmla.f32 q1, q5, q9\n"
" vmla.f32 q2, q6, q10\n"
" vmla.f32 q3, q7, q11\n"
" bne 2b\n"
"3:"
" vadd.f32 q4, q0, q1\n"
" vadd.f32 q5, q2, q3\n"
" cmp %[remainder], #0\n"
" vadd.f32 q0, q4, q5\n"
" beq 5f\n"
"4:"
" vld1.32 {q6}, [%[b]]!\n"
" vld1.32 {q10}, [%[a]]!\n"
" subs %[remainder], %[remainder], #4\n"
" vmla.f32 q0, q6, q10\n"
" bne 4b\n"
"5:"
" vadd.f32 d0, d0, d1\n"
" vpadd.f32 d0, d0, d0\n"
" vmov.f32 %[ret], d0[0]\n"
: [ret] "=&r" (ret), [a] "+r" (a), [b] "+r" (b),
[len] "+l" (len), [remainder] "+l" (remainder)
:
: "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8",
"q9", "q10", "q11");
return ret;
}
#endif

128
Externals/cubeb/src/speex/resample_sse.h vendored Normal file
View File

@ -0,0 +1,128 @@
/* Copyright (C) 2007-2008 Jean-Marc Valin
* Copyright (C) 2008 Thorvald Natvig
*/
/**
@file resample_sse.h
@brief Resampler functions (SSE version)
*/
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of the Xiph.org Foundation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <xmmintrin.h>
#define OVERRIDE_INNER_PRODUCT_SINGLE
static inline float inner_product_single(const float *a, const float *b, unsigned int len)
{
int i;
float ret;
__m128 sum = _mm_setzero_ps();
for (i=0;i<len;i+=8)
{
sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+i), _mm_loadu_ps(b+i)));
sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+i+4), _mm_loadu_ps(b+i+4)));
}
sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum));
sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55));
_mm_store_ss(&ret, sum);
return ret;
}
#define OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
static inline float interpolate_product_single(const float *a, const float *b, unsigned int len, const spx_uint32_t oversample, float *frac) {
int i;
float ret;
__m128 sum = _mm_setzero_ps();
__m128 f = _mm_loadu_ps(frac);
for(i=0;i<len;i+=2)
{
sum = _mm_add_ps(sum, _mm_mul_ps(_mm_load1_ps(a+i), _mm_loadu_ps(b+i*oversample)));
sum = _mm_add_ps(sum, _mm_mul_ps(_mm_load1_ps(a+i+1), _mm_loadu_ps(b+(i+1)*oversample)));
}
sum = _mm_mul_ps(f, sum);
sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum));
sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55));
_mm_store_ss(&ret, sum);
return ret;
}
#ifdef _USE_SSE2
#include <emmintrin.h>
#define OVERRIDE_INNER_PRODUCT_DOUBLE
static inline double inner_product_double(const float *a, const float *b, unsigned int len)
{
int i;
double ret;
__m128d sum = _mm_setzero_pd();
__m128 t;
for (i=0;i<len;i+=8)
{
t = _mm_mul_ps(_mm_loadu_ps(a+i), _mm_loadu_ps(b+i));
sum = _mm_add_pd(sum, _mm_cvtps_pd(t));
sum = _mm_add_pd(sum, _mm_cvtps_pd(_mm_movehl_ps(t, t)));
t = _mm_mul_ps(_mm_loadu_ps(a+i+4), _mm_loadu_ps(b+i+4));
sum = _mm_add_pd(sum, _mm_cvtps_pd(t));
sum = _mm_add_pd(sum, _mm_cvtps_pd(_mm_movehl_ps(t, t)));
}
sum = _mm_add_sd(sum, _mm_unpackhi_pd(sum, sum));
_mm_store_sd(&ret, sum);
return ret;
}
#define OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
static inline double interpolate_product_double(const float *a, const float *b, unsigned int len, const spx_uint32_t oversample, float *frac) {
int i;
double ret;
__m128d sum;
__m128d sum1 = _mm_setzero_pd();
__m128d sum2 = _mm_setzero_pd();
__m128 f = _mm_loadu_ps(frac);
__m128d f1 = _mm_cvtps_pd(f);
__m128d f2 = _mm_cvtps_pd(_mm_movehl_ps(f,f));
__m128 t;
for(i=0;i<len;i+=2)
{
t = _mm_mul_ps(_mm_load1_ps(a+i), _mm_loadu_ps(b+i*oversample));
sum1 = _mm_add_pd(sum1, _mm_cvtps_pd(t));
sum2 = _mm_add_pd(sum2, _mm_cvtps_pd(_mm_movehl_ps(t, t)));
t = _mm_mul_ps(_mm_load1_ps(a+i+1), _mm_loadu_ps(b+(i+1)*oversample));
sum1 = _mm_add_pd(sum1, _mm_cvtps_pd(t));
sum2 = _mm_add_pd(sum2, _mm_cvtps_pd(_mm_movehl_ps(t, t)));
}
sum1 = _mm_mul_pd(f1, sum1);
sum2 = _mm_mul_pd(f2, sum2);
sum = _mm_add_pd(sum1, sum2);
sum = _mm_add_sd(sum, _mm_unpackhi_pd(sum, sum));
_mm_store_sd(&ret, sum);
return ret;
}
#endif

View File

@ -0,0 +1,10 @@
#ifndef __SPEEX_TYPES_H__
#define __SPEEX_TYPES_H__
/* these are filled in by configure */
typedef int16_t spx_int16_t;
typedef uint16_t spx_uint16_t;
typedef int32_t spx_int32_t;
typedef uint32_t spx_uint32_t;
#endif

View File

@ -0,0 +1,343 @@
/* Copyright (C) 2007 Jean-Marc Valin
File: speex_resampler.h
Resampling code
The design goals of this code are:
- Very fast algorithm
- Low memory requirement
- Good *perceptual* quality (and not best SNR)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SPEEX_RESAMPLER_H
#define SPEEX_RESAMPLER_H
#ifdef OUTSIDE_SPEEX
/********* WARNING: MENTAL SANITY ENDS HERE *************/
/* If the resampler is defined outside of Speex, we change the symbol names so that
there won't be any clash if linking with Speex later on. */
/* #define RANDOM_PREFIX your software name here */
#ifndef RANDOM_PREFIX
#error "Please define RANDOM_PREFIX (above) to something specific to your project to prevent symbol name clashes"
#endif
#define CAT_PREFIX2(a,b) a ## b
#define CAT_PREFIX(a,b) CAT_PREFIX2(a, b)
#define speex_resampler_init CAT_PREFIX(RANDOM_PREFIX,_resampler_init)
#define speex_resampler_init_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_init_frac)
#define speex_resampler_destroy CAT_PREFIX(RANDOM_PREFIX,_resampler_destroy)
#define speex_resampler_process_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_float)
#define speex_resampler_process_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_int)
#define speex_resampler_process_interleaved_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_float)
#define speex_resampler_process_interleaved_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_int)
#define speex_resampler_set_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate)
#define speex_resampler_get_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_get_rate)
#define speex_resampler_set_rate_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate_frac)
#define speex_resampler_get_ratio CAT_PREFIX(RANDOM_PREFIX,_resampler_get_ratio)
#define speex_resampler_set_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_set_quality)
#define speex_resampler_get_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_get_quality)
#define speex_resampler_set_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_input_stride)
#define speex_resampler_get_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_stride)
#define speex_resampler_set_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_output_stride)
#define speex_resampler_get_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_stride)
#define speex_resampler_get_input_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_latency)
#define speex_resampler_get_output_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_latency)
#define speex_resampler_skip_zeros CAT_PREFIX(RANDOM_PREFIX,_resampler_skip_zeros)
#define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem)
#define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror)
#define spx_int16_t short
#define spx_int32_t int
#define spx_uint16_t unsigned short
#define spx_uint32_t unsigned int
#define speex_assert(cond)
#else /* OUTSIDE_SPEEX */
#include "speexdsp_types.h"
#endif /* OUTSIDE_SPEEX */
#ifdef __cplusplus
extern "C" {
#endif
#define SPEEX_RESAMPLER_QUALITY_MAX 10
#define SPEEX_RESAMPLER_QUALITY_MIN 0
#define SPEEX_RESAMPLER_QUALITY_DEFAULT 4
#define SPEEX_RESAMPLER_QUALITY_VOIP 3
#define SPEEX_RESAMPLER_QUALITY_DESKTOP 5
enum {
RESAMPLER_ERR_SUCCESS = 0,
RESAMPLER_ERR_ALLOC_FAILED = 1,
RESAMPLER_ERR_BAD_STATE = 2,
RESAMPLER_ERR_INVALID_ARG = 3,
RESAMPLER_ERR_PTR_OVERLAP = 4,
RESAMPLER_ERR_OVERFLOW = 5,
RESAMPLER_ERR_MAX_ERROR
};
struct SpeexResamplerState_;
typedef struct SpeexResamplerState_ SpeexResamplerState;
/** Create a new resampler with integer input and output rates.
* @param nb_channels Number of channels to be processed
* @param in_rate Input sampling rate (integer number of Hz).
* @param out_rate Output sampling rate (integer number of Hz).
* @param quality Resampling quality between 0 and 10, where 0 has poor quality
* and 10 has very high quality.
* @return Newly created resampler state
* @retval NULL Error: not enough memory
*/
SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels,
spx_uint32_t in_rate,
spx_uint32_t out_rate,
int quality,
int *err);
/** Create a new resampler with fractional input/output rates. The sampling
* rate ratio is an arbitrary rational number with both the numerator and
* denominator being 32-bit integers.
* @param nb_channels Number of channels to be processed
* @param ratio_num Numerator of the sampling rate ratio
* @param ratio_den Denominator of the sampling rate ratio
* @param in_rate Input sampling rate rounded to the nearest integer (in Hz).
* @param out_rate Output sampling rate rounded to the nearest integer (in Hz).
* @param quality Resampling quality between 0 and 10, where 0 has poor quality
* and 10 has very high quality.
* @return Newly created resampler state
* @retval NULL Error: not enough memory
*/
SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels,
spx_uint32_t ratio_num,
spx_uint32_t ratio_den,
spx_uint32_t in_rate,
spx_uint32_t out_rate,
int quality,
int *err);
/** Destroy a resampler state.
* @param st Resampler state
*/
void speex_resampler_destroy(SpeexResamplerState *st);
/** Resample a float array. The input and output buffers must *not* overlap.
* @param st Resampler state
* @param channel_index Index of the channel to process for the multi-channel
* base (0 otherwise)
* @param in Input buffer
* @param in_len Number of input samples in the input buffer. Returns the
* number of samples processed
* @param out Output buffer
* @param out_len Size of the output buffer. Returns the number of samples written
*/
int speex_resampler_process_float(SpeexResamplerState *st,
spx_uint32_t channel_index,
const float *in,
spx_uint32_t *in_len,
float *out,
spx_uint32_t *out_len);
/** Resample an int array. The input and output buffers must *not* overlap.
* @param st Resampler state
* @param channel_index Index of the channel to process for the multi-channel
* base (0 otherwise)
* @param in Input buffer
* @param in_len Number of input samples in the input buffer. Returns the number
* of samples processed
* @param out Output buffer
* @param out_len Size of the output buffer. Returns the number of samples written
*/
int speex_resampler_process_int(SpeexResamplerState *st,
spx_uint32_t channel_index,
const spx_int16_t *in,
spx_uint32_t *in_len,
spx_int16_t *out,
spx_uint32_t *out_len);
/** Resample an interleaved float array. The input and output buffers must *not* overlap.
* @param st Resampler state
* @param in Input buffer
* @param in_len Number of input samples in the input buffer. Returns the number
* of samples processed. This is all per-channel.
* @param out Output buffer
* @param out_len Size of the output buffer. Returns the number of samples written.
* This is all per-channel.
*/
int speex_resampler_process_interleaved_float(SpeexResamplerState *st,
const float *in,
spx_uint32_t *in_len,
float *out,
spx_uint32_t *out_len);
/** Resample an interleaved int array. The input and output buffers must *not* overlap.
* @param st Resampler state
* @param in Input buffer
* @param in_len Number of input samples in the input buffer. Returns the number
* of samples processed. This is all per-channel.
* @param out Output buffer
* @param out_len Size of the output buffer. Returns the number of samples written.
* This is all per-channel.
*/
int speex_resampler_process_interleaved_int(SpeexResamplerState *st,
const spx_int16_t *in,
spx_uint32_t *in_len,
spx_int16_t *out,
spx_uint32_t *out_len);
/** Set (change) the input/output sampling rates (integer value).
* @param st Resampler state
* @param in_rate Input sampling rate (integer number of Hz).
* @param out_rate Output sampling rate (integer number of Hz).
*/
int speex_resampler_set_rate(SpeexResamplerState *st,
spx_uint32_t in_rate,
spx_uint32_t out_rate);
/** Get the current input/output sampling rates (integer value).
* @param st Resampler state
* @param in_rate Input sampling rate (integer number of Hz) copied.
* @param out_rate Output sampling rate (integer number of Hz) copied.
*/
void speex_resampler_get_rate(SpeexResamplerState *st,
spx_uint32_t *in_rate,
spx_uint32_t *out_rate);
/** Set (change) the input/output sampling rates and resampling ratio
* (fractional values in Hz supported).
* @param st Resampler state
* @param ratio_num Numerator of the sampling rate ratio
* @param ratio_den Denominator of the sampling rate ratio
* @param in_rate Input sampling rate rounded to the nearest integer (in Hz).
* @param out_rate Output sampling rate rounded to the nearest integer (in Hz).
*/
int speex_resampler_set_rate_frac(SpeexResamplerState *st,
spx_uint32_t ratio_num,
spx_uint32_t ratio_den,
spx_uint32_t in_rate,
spx_uint32_t out_rate);
/** Get the current resampling ratio. This will be reduced to the least
* common denominator.
* @param st Resampler state
* @param ratio_num Numerator of the sampling rate ratio copied
* @param ratio_den Denominator of the sampling rate ratio copied
*/
void speex_resampler_get_ratio(SpeexResamplerState *st,
spx_uint32_t *ratio_num,
spx_uint32_t *ratio_den);
/** Set (change) the conversion quality.
* @param st Resampler state
* @param quality Resampling quality between 0 and 10, where 0 has poor
* quality and 10 has very high quality.
*/
int speex_resampler_set_quality(SpeexResamplerState *st,
int quality);
/** Get the conversion quality.
* @param st Resampler state
* @param quality Resampling quality between 0 and 10, where 0 has poor
* quality and 10 has very high quality.
*/
void speex_resampler_get_quality(SpeexResamplerState *st,
int *quality);
/** Set (change) the input stride.
* @param st Resampler state
* @param stride Input stride
*/
void speex_resampler_set_input_stride(SpeexResamplerState *st,
spx_uint32_t stride);
/** Get the input stride.
* @param st Resampler state
* @param stride Input stride copied
*/
void speex_resampler_get_input_stride(SpeexResamplerState *st,
spx_uint32_t *stride);
/** Set (change) the output stride.
* @param st Resampler state
* @param stride Output stride
*/
void speex_resampler_set_output_stride(SpeexResamplerState *st,
spx_uint32_t stride);
/** Get the output stride.
* @param st Resampler state copied
* @param stride Output stride
*/
void speex_resampler_get_output_stride(SpeexResamplerState *st,
spx_uint32_t *stride);
/** Get the latency introduced by the resampler measured in input samples.
* @param st Resampler state
*/
int speex_resampler_get_input_latency(SpeexResamplerState *st);
/** Get the latency introduced by the resampler measured in output samples.
* @param st Resampler state
*/
int speex_resampler_get_output_latency(SpeexResamplerState *st);
/** Make sure that the first samples to go out of the resamplers don't have
* leading zeros. This is only useful before starting to use a newly created
* resampler. It is recommended to use that when resampling an audio file, as
* it will generate a file with the same length. For real-time processing,
* it is probably easier not to use this call (so that the output duration
* is the same for the first frame).
* @param st Resampler state
*/
int speex_resampler_skip_zeros(SpeexResamplerState *st);
/** Reset a resampler so a new (unrelated) stream can be processed.
* @param st Resampler state
*/
int speex_resampler_reset_mem(SpeexResamplerState *st);
/** Returns the English meaning for an error code
* @param err Error code
* @return English string
*/
const char *speex_resampler_strerror(int err);
#ifdef __cplusplus
}
#endif
#endif

115
Externals/cubeb/src/speex/stack_alloc.h vendored Normal file
View File

@ -0,0 +1,115 @@
/* Copyright (C) 2002 Jean-Marc Valin */
/**
@file stack_alloc.h
@brief Temporary memory allocation on stack
*/
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of the Xiph.org Foundation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef STACK_ALLOC_H
#define STACK_ALLOC_H
#ifdef USE_ALLOCA
# ifdef WIN32
# include <malloc.h>
# else
# ifdef HAVE_ALLOCA_H
# include <alloca.h>
# else
# include <stdlib.h>
# endif
# endif
#endif
/**
* @def ALIGN(stack, size)
*
* Aligns the stack to a 'size' boundary
*
* @param stack Stack
* @param size New size boundary
*/
/**
* @def PUSH(stack, size, type)
*
* Allocates 'size' elements of type 'type' on the stack
*
* @param stack Stack
* @param size Number of elements
* @param type Type of element
*/
/**
* @def VARDECL(var)
*
* Declare variable on stack
*
* @param var Variable to declare
*/
/**
* @def ALLOC(var, size, type)
*
* Allocate 'size' elements of 'type' on stack
*
* @param var Name of variable to allocate
* @param size Number of elements
* @param type Type of element
*/
#ifdef ENABLE_VALGRIND
#include <valgrind/memcheck.h>
#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
#define PUSH(stack, size, type) (VALGRIND_MAKE_NOACCESS(stack, 1000),ALIGN((stack),sizeof(type)),VALGRIND_MAKE_WRITABLE(stack, ((size)*sizeof(type))),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type))))
#else
#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
#define PUSH(stack, size, type) (ALIGN((stack),sizeof(type)),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type))))
#endif
#if defined(VAR_ARRAYS)
#define VARDECL(var)
#define ALLOC(var, size, type) type var[size]
#elif defined(USE_ALLOCA)
#define VARDECL(var) var
#define ALLOC(var, size, type) var = alloca(sizeof(type)*(size))
#else
#define VARDECL(var) var
#define ALLOC(var, size, type) var = PUSH(stack, size, type)
#endif
#endif

View File

@ -6,6 +6,8 @@ Dolphin includes or links code of the following third-party software projects:
[LGPLv2.1+](https://git.kernel.org/cgit/bluetooth/bluez.git/tree/COPYING.LIB)
- [Bochs](http://bochs.sourceforge.net/):
[LGPLv2.1+](http://bochs.sourceforge.net/cgi-bin/lxr/source/COPYING)
- [cubeb](https://github.com/kinetiknz/cubeb):
[ISC](https://github.com/kinetiknz/cubeb/blob/master/LICENSE)
- [ENet](http://enet.bespin.org/):
[MIT](http://enet.bespin.org/License.html)
- [GCEmu](http://sourceforge.net/projects/gcemu-project/):
@ -44,8 +46,6 @@ Dolphin includes or links code of the following third-party software projects:
[GPLv2](http://pearpc.cvs.sourceforge.net/viewvc/pearpc/pearpc/COPYING?view=markup) (with permission by the author to license under GPLv2+)
- [mbed TLS](https://tls.mbed.org/):
[Apache 2.0](https://github.com/ARMmbed/mbedtls/blob/development/LICENSE)
- [PortAudio](http://www.portaudio.com/):
[MIT](http://www.portaudio.com/license.html)
- [PulseAudio](http://www.freedesktop.org/wiki/Software/PulseAudio/):
[LGPLv2.1+](http://cgit.freedesktop.org/pulseaudio/pulseaudio/tree/LICENSE)
- [Qt5](http://qt-project.org/):

View File

@ -1,409 +0,0 @@
# $Id: $
#
# For a "How-To" please refer to the Portaudio documentation at:
# http://www.portaudio.com/trac/wiki/TutorialDir/Compile/CMake
#
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
# Check if the user is building PortAudio stand-alone or as part of a larger
# project. If this is part of a larger project (i.e. the CMakeLists.txt has
# been imported by some other CMakeLists.txt), we don't want to trump over
# the top of that project's global settings.
IF(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_LIST_DIR})
IF(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
MESSAGE(STATUS "Setting CMAKE_BUILD_TYPE type to 'Debug' as none was specified.")
SET(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE)
SET_PROPERTY(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release")
ENDIF()
PROJECT(portaudio)
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
IF(WIN32 AND MSVC)
OPTION(PA_DLL_LINK_WITH_STATIC_RUNTIME "Link with static runtime libraries (minimizes runtime dependencies)" ON)
IF(PA_DLL_LINK_WITH_STATIC_RUNTIME)
FOREACH(flag_var
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
IF(${flag_var} MATCHES "/MD")
STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
ENDIF()
ENDFOREACH()
ENDIF()
ENDIF()
ENDIF()
SET(PA_PKGCONFIG_VERSION 19)
# Most of the code from this point onwards is related to populating the
# following variables:
# PA_PUBLIC_INCLUDES - This contains the list of public PortAudio header
# files. These files will be copied into /include paths on Unix'y
# systems when "make install" is invoked.
# PA_PRIVATE_INCLUDES - This contains the list of header files which
# are not part of PortAudio, but are required by the various hostapis.
# It is only used by CMake IDE generators (like Visual Studio) to
# provide quick-links to useful headers. It has no impact on build
# output.
# PA_PRIVATE_INCLUDE_PATHS - This contains the list of include paths which
# will be passed to the compiler while PortAudio is being built which
# are not required by applications using the PortAudio API.
# PA_PRIVATE_COMPILE_DEFINITIONS - This contains a list of preprocessor
# macro definitions which will be set when compiling PortAudio source
# files.
# PA_SOURCES - This contains the list of source files which will be built
# into the static and shared PortAudio libraries.
# PA_NON_UNICODE_SOURCES - This also contains a list of source files which
# will be build into the static and shared PortAudio libraries. However,
# these sources will not have any unicode compiler definitions added
# to them. This list should only contain external source dependencies.
# PA_EXTRA_SHARED_SOURCES - Contains a list of extra files which will be
# associated only with the shared PortAudio library. This only seems
# relevant for Windows shared libraries which require a list of export
# symbols.
# Where other PA_* variables are set, these are almost always only used to
# preserve the historic SOURCE_GROUP behavior (which again only has an impact
# on IDE-style generators for visual appearance) or store the output of
# find_library() calls.
SET(PA_COMMON_INCLUDES
src/common/pa_allocation.h
src/common/pa_converters.h
src/common/pa_cpuload.h
src/common/pa_debugprint.h
src/common/pa_dither.h
src/common/pa_endianness.h
src/common/pa_hostapi.h
src/common/pa_memorybarrier.h
src/common/pa_process.h
src/common/pa_ringbuffer.h
src/common/pa_stream.h
src/common/pa_trace.h
src/common/pa_types.h
src/common/pa_util.h
)
SET(PA_COMMON_SOURCES
src/common/pa_allocation.c
src/common/pa_converters.c
src/common/pa_cpuload.c
src/common/pa_debugprint.c
src/common/pa_dither.c
src/common/pa_front.c
src/common/pa_process.c
src/common/pa_ringbuffer.c
src/common/pa_stream.c
src/common/pa_trace.c
)
SOURCE_GROUP("common" FILES ${PA_COMMON_INCLUDES} ${PA_COMMON_SOURCES})
SET(PA_PUBLIC_INCLUDES include/portaudio.h)
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake_support)
SET(PA_SKELETON_SOURCES src/hostapi/skeleton/pa_hostapi_skeleton.c)
SOURCE_GROUP("hostapi\\skeleton" ${PA_SKELETON_SOURCES})
SET(PA_SOURCES ${PA_COMMON_SOURCES} ${PA_SKELETON_SOURCES})
SET(PA_PRIVATE_INCLUDE_PATHS src/common ${CMAKE_CURRENT_BINARY_DIR})
IF(WIN32)
SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} _CRT_SECURE_NO_WARNINGS)
SET(PA_PLATFORM_SOURCES
src/os/win/pa_win_hostapis.c
src/os/win/pa_win_util.c
src/os/win/pa_win_waveformat.c
src/os/win/pa_win_wdmks_utils.c
src/os/win/pa_win_coinitialize.c)
SET(PA_PLATFORM_INCLUDES
src/os/win/pa_win_coinitialize.h
src/os/win/pa_win_wdmks_utils.h)
IF(MSVC)
SET(PA_PLATFORM_SOURCES ${PA_PLATFORM_SOURCES} src/os/win/pa_x86_plain_converters.c)
SET(PA_PLATFORM_INCLUDES ${PA_PLATFORM_INCLUDES} src/os/win/pa_x86_plain_converters.h)
ELSE()
SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} _WIN32_WINNT=0x0501 WINVER=0x0501)
SET(DEF_EXCLUDE_X86_PLAIN_CONVERTERS ";")
ENDIF()
SOURCE_GROUP("os\\win" FILES ${PA_PLATFORM_SOURCES} ${PA_PLATFORM_INCLUDES})
SET(PA_SOURCES ${PA_SOURCES} ${PA_PLATFORM_SOURCES})
SET(PA_PRIVATE_INCLUDES ${PA_PRIVATE_INCLUDES} ${PA_PLATFORM_INCLUDES})
SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} src/os/win)
SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} winmm)
# Try to find ASIO SDK (assumes that portaudio and asiosdk folders are side-by-side, see
# http://www.portaudio.com/trac/wiki/TutorialDir/Compile/WindowsASIOMSVC)
FIND_PACKAGE(ASIOSDK)
IF(ASIOSDK_FOUND)
OPTION(PA_USE_ASIO "Enable support for ASIO" ON)
ELSE()
OPTION(PA_USE_ASIO "Enable support for ASIO" OFF)
ENDIF()
IF(PA_USE_ASIO)
SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} ${ASIOSDK_ROOT_DIR}/common)
SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} ${ASIOSDK_ROOT_DIR}/host)
SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} ${ASIOSDK_ROOT_DIR}/host/pc)
SET(PA_ASIO_SOURCES src/hostapi/asio/pa_asio.cpp src/hostapi/asio/iasiothiscallresolver.cpp)
SET(PA_ASIOSDK_SOURCES ${ASIOSDK_ROOT_DIR}/common/asio.cpp ${ASIOSDK_ROOT_DIR}/host/pc/asiolist.cpp ${ASIOSDK_ROOT_DIR}/host/asiodrivers.cpp)
SOURCE_GROUP("hostapi\\ASIO" FILES ${PA_ASIO_SOURCES})
SOURCE_GROUP("hostapi\\ASIO\\ASIOSDK" FILES ${PA_ASIOSDK_SOURCES})
SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_asio.h)
SET(PA_SOURCES ${PA_SOURCES} ${PA_ASIO_SOURCES})
SET(PA_NON_UNICODE_SOURCES ${PA_NON_UNICODE_SOURCES} ${PA_ASIOSDK_SOURCES})
SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} ole32 uuid)
ELSE()
# Set variables for DEF file expansion
SET(DEF_EXCLUDE_ASIO_SYMBOLS ";")
ENDIF()
# Try to find DirectX SDK
FIND_PACKAGE(DXSDK)
IF(DXSDK_FOUND)
OPTION(PA_USE_DS "Enable support for DirectSound" ON)
ELSE()
OPTION(PA_USE_DS "Enable support for DirectSound" OFF)
ENDIF()
IF(PA_USE_DS)
OPTION(PA_USE_DIRECTSOUNDFULLDUPLEXCREATE "Use DirectSound full duplex create" ON)
MARK_AS_ADVANCED(PA_USE_DIRECTSOUNDFULLDUPLEXCREATE)
IF(PA_USE_DIRECTSOUNDFULLDUPLEXCREATE)
SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PAWIN_USE_DIRECTSOUNDFULLDUPLEXCREATE)
ENDIF()
SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} ${DXSDK_INCLUDE_DIR})
SET(PA_DS_INCLUDES src/hostapi/dsound/pa_win_ds_dynlink.h)
SET(PA_DS_SOURCES src/hostapi/dsound/pa_win_ds.c src/hostapi/dsound/pa_win_ds_dynlink.c)
SOURCE_GROUP("hostapi\\dsound" FILES ${PA_DS_INCLUDES} ${PA_DS_SOURCES})
SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_win_ds.h)
SET(PA_PRIVATE_INCLUDES ${PA_PRIVATE_INCLUDES} ${PA_DS_INCLUDES})
SET(PA_SOURCES ${PA_SOURCES} ${PA_DS_SOURCES})
# If we use DirectSound, we need this for the library to be found (if not in VS project settings)
IF(DXSDK_FOUND)
SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} ${DXSDK_DSOUND_LIBRARY})
ENDIF()
ENDIF()
OPTION(PA_USE_WMME "Enable support for MME" ON)
IF(PA_USE_WMME)
SET(PA_WMME_SOURCES src/hostapi/wmme/pa_win_wmme.c)
SOURCE_GROUP("hostapi\\wmme" FILES ${PA_WMME_SOURCES})
SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_win_wmme.h)
SET(PA_SOURCES ${PA_SOURCES} ${PA_WMME_SOURCES})
SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} ole32 uuid)
ENDIF()
IF(MSVS)
OPTION(PA_USE_WASAPI "Enable support for WASAPI" ON)
ELSE()
# I was unable to get WASAPI to compile outside of Visual Studio. If
# anyone can figure out how to make this work with MinGW, please fix me.
SET(PA_USE_WASAPI OFF)
ENDIF()
IF(PA_USE_WASAPI)
SET(PA_WASAPI_SOURCES src/hostapi/wasapi/pa_win_wasapi.c)
SOURCE_GROUP("hostapi\\wasapi" FILES ${PA_WASAPI_SOURCES})
SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_win_wasapi.h)
SET(PA_SOURCES ${PA_SOURCES} ${PA_WASAPI_SOURCES})
SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} ole32 uuid)
IF(NOT MSVC)
SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} src/hostapi/wasapi/mingw-include)
ENDIF()
ELSE()
SET(DEF_EXCLUDE_WASAPI_SYMBOLS ";")
ENDIF()
OPTION(PA_USE_WDMKS "Enable support for WDMKS" ON)
IF(PA_USE_WDMKS)
SET(PA_WDMKS_SOURCES src/hostapi/wdmks/pa_win_wdmks.c)
SOURCE_GROUP("hostapi\\wdmks" FILES ${PA_WDMKS_SOURCES})
SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_win_wdmks.h)
SET(PA_SOURCES ${PA_SOURCES} ${PA_WDMKS_SOURCES})
SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} setupapi ole32 uuid)
ENDIF()
OPTION(PA_USE_WDMKS_DEVICE_INFO "Use WDM/KS API for device info" ON)
MARK_AS_ADVANCED(PA_USE_WDMKS_DEVICE_INFO)
IF(PA_USE_WDMKS_DEVICE_INFO)
SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PAWIN_USE_WDMKS_DEVICE_INFO)
ENDIF()
SET(GENERATED_MESSAGE "CMake generated file, do NOT edit! Use CMake-GUI to change configuration instead.")
CONFIGURE_FILE(cmake_support/template_portaudio.def ${CMAKE_CURRENT_BINARY_DIR}/portaudio_cmake.def @ONLY)
CONFIGURE_FILE(cmake_support/options_cmake.h.in ${CMAKE_CURRENT_BINARY_DIR}/options_cmake.h @ONLY)
SET(PA_PRIVATE_INCLUDES ${PA_PRIVATE_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}/options_cmake.h)
SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PORTAUDIO_CMAKE_GENERATED)
SOURCE_GROUP("cmake_generated" FILES ${CMAKE_CURRENT_BINARY_DIR}/portaudio_cmake.def ${CMAKE_CURRENT_BINARY_DIR}/options_cmake.h)
SET(PA_EXTRA_SHARED_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/portaudio_cmake.def)
ELSE()
SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} src/os/unix)
SET(PA_PLATFORM_SOURCES src/os/unix/pa_unix_hostapis.c src/os/unix/pa_unix_util.c)
SOURCE_GROUP("os\\unix" FILES ${PA_PLATFORM_SOURCES})
SET(PA_SOURCES ${PA_SOURCES} ${PA_PLATFORM_SOURCES})
IF(APPLE)
SET(CMAKE_MACOSX_RPATH 1)
OPTION(PA_USE_COREAUDIO "Enable support for CoreAudio" ON)
IF(PA_USE_COREAUDIO)
SET(PA_COREAUDIO_SOURCES
src/hostapi/coreaudio/pa_mac_core.c
src/hostapi/coreaudio/pa_mac_core_blocking.c
src/hostapi/coreaudio/pa_mac_core_utilities.c)
SET(PA_COREAUDIO_INCLUDES
src/hostapi/coreaudio/pa_mac_core_blocking.h
src/hostapi/coreaudio/pa_mac_core_utilities.h)
SOURCE_GROUP("hostapi\\coreaudio" FILES ${PA_COREAUDIO_SOURCES} ${PA_COREAUDIO_INCLUDES})
SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_mac_core.h)
SET(PA_PRIVATE_INCLUDES ${PA_PRIVATE_INCLUDES} ${PA_COREAUDIO_INCLUDES})
SET(PA_SOURCES ${PA_SOURCES} ${PA_COREAUDIO_SOURCES})
FIND_LIBRARY(COREAUDIO_LIBRARY CoreAudio REQUIRED)
FIND_LIBRARY(AUDIOTOOLBOX_LIBRARY AudioToolbox REQUIRED)
FIND_LIBRARY(AUDIOUNIT_LIBRARY AudioUnit REQUIRED)
FIND_LIBRARY(CARBON_LIBRARY Carbon REQUIRED)
MARK_AS_ADVANCED(COREAUDIO_LIBRARY AUDIOTOOLBOX_LIBRARY AUDIOUNIT_LIBRARY CARBON_LIBRARY)
SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} ${COREAUDIO_LIBRARY} ${AUDIOTOOLBOX_LIBRARY} ${AUDIOUNIT_LIBRARY} ${CARBON_LIBRARY})
SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PA_USE_COREAUDIO)
SET(PA_PKGCONFIG_LDFLAGS "${PA_PKGCONFIG_LDFLAGS} -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework Carbon")
ENDIF()
ELSEIF(UNIX)
FIND_PACKAGE(Jack)
IF(JACK_FOUND)
OPTION(PA_USE_JACK "Enable support for Jack" ON)
ELSE()
OPTION(PA_USE_JACK "Enable support for Jack" OFF)
ENDIF()
IF(PA_USE_JACK)
SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} ${JACK_INCLUDE_DIRS})
SET(PA_JACK_SOURCES src/hostapi/jack/pa_jack.c)
SOURCE_GROUP("hostapi\\JACK" FILES ${PA_JACK_SOURCES})
SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_jack.h)
SET(PA_SOURCES ${PA_SOURCES} ${PA_JACK_SOURCES})
SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PA_USE_JACK)
SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} ${JACK_LIBRARIES})
SET(PA_PKGCONFIG_LDFLAGS "${PA_PKGCONFIG_LDFLAGS} -ljack")
ENDIF()
FIND_PACKAGE(ALSA)
IF(ALSA_FOUND)
OPTION(PA_USE_ALSA "Enable support for ALSA" ON)
ELSE()
OPTION(PA_USE_ALSA "Enable support for ALSA" OFF)
ENDIF()
IF(PA_USE_ALSA)
SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} ${ALSA_INCLUDE_DIRS})
SET(PA_ALSA_SOURCES src/hostapi/alsa/pa_linux_alsa.c)
SOURCE_GROUP("hostapi\\ALSA" FILES ${PA_ALSA_SOURCES})
SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_linux_alsa.h)
SET(PA_SOURCES ${PA_SOURCES} ${PA_ALSA_SOURCES})
SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PA_USE_ALSA)
SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} ${ALSA_LIBRARIES})
SET(PA_PKGCONFIG_LDFLAGS "${PA_PKGCONFIG_LDFLAGS} -lasound")
ENDIF()
ENDIF()
find_package(Threads)
SET(PA_PKGCONFIG_LDFLAGS "${PA_PKGCONFIG_LDFLAGS} -lm")
SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} m Threads::Threads)
ENDIF()
SOURCE_GROUP("include" FILES ${PA_PUBLIC_INCLUDES})
SET(PA_INCLUDES ${PA_PRIVATE_INCLUDES} ${PA_PUBLIC_INCLUDES})
IF(WIN32)
OPTION(PA_UNICODE_BUILD "Enable Portaudio Unicode build" ON)
IF(PA_UNICODE_BUILD)
SET_SOURCE_FILES_PROPERTIES(${PA_SOURCES} PROPERTIES COMPILE_DEFINITIONS "UNICODE;_UNICODE")
ENDIF()
ENDIF()
OPTION(PA_ENABLE_DEBUG_OUTPUT "Enable debug output for Portaudio" OFF)
IF(PA_ENABLE_DEBUG_OUTPUT)
SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PA_ENABLE_DEBUG_OUTPUT)
ENDIF()
INCLUDE(TestBigEndian)
TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
IF(IS_BIG_ENDIAN)
SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PA_BIG_ENDIAN)
ELSE()
SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} PA_LITTLE_ENDIAN)
ENDIF()
#ADD_LIBRARY(portaudio SHARED ${PA_INCLUDES} ${PA_COMMON_INCLUDES} ${PA_SOURCES} ${PA_NON_UNICODE_SOURCES} ${PA_EXTRA_SHARED_SOURCES})
#SET_PROPERTY(TARGET portaudio APPEND_STRING PROPERTY COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS})
#TARGET_INCLUDE_DIRECTORIES(portaudio BEFORE PRIVATE ${PA_PRIVATE_INCLUDE_PATHS})
#TARGET_INCLUDE_DIRECTORIES(portaudio BEFORE PUBLIC include)
#TARGET_LINK_LIBRARIES(portaudio ${PA_LIBRARY_DEPENDENCIES})
ADD_LIBRARY(portaudio_static STATIC ${PA_INCLUDES} ${PA_COMMON_INCLUDES} ${PA_SOURCES} ${PA_NON_UNICODE_SOURCES})
SET_PROPERTY(TARGET portaudio_static APPEND_STRING PROPERTY COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS})
TARGET_INCLUDE_DIRECTORIES(portaudio_static BEFORE PRIVATE ${PA_PRIVATE_INCLUDE_PATHS})
TARGET_INCLUDE_DIRECTORIES(portaudio_static BEFORE PUBLIC include)
TARGET_LINK_LIBRARIES(portaudio_static ${PA_LIBRARY_DEPENDENCIES})
IF(WIN32 AND MSVC)
OPTION(PA_CONFIG_LIB_OUTPUT_PATH "Make sure that output paths are kept neat" OFF)
IF(CMAKE_CL_64)
SET(TARGET_POSTFIX x64)
IF(PA_CONFIG_LIB_OUTPUT_PATH)
SET(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/bin/x64)
ENDIF()
ELSE()
SET(TARGET_POSTFIX x86)
IF(PA_CONFIG_LIB_OUTPUT_PATH)
SET(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/bin/Win32)
ENDIF()
ENDIF()
#SET_TARGET_PROPERTIES(portaudio PROPERTIES OUTPUT_NAME portaudio_${TARGET_POSTFIX} FOLDER "Portaudio")
SET_TARGET_PROPERTIES(portaudio_static PROPERTIES OUTPUT_NAME portaudio_static_${TARGET_POSTFIX} FOLDER "Portaudio")
ELSE()
IF(APPLE AND CMAKE_VERSION VERSION_GREATER 3.4.2)
OPTION(PA_OUTPUT_OSX_FRAMEWORK "Generate an OS X framework instead of the simple library" OFF)
IF(PA_OUTPUT_OSX_FRAMEWORK)
SET_TARGET_PROPERTIES(portaudio PROPERTIES
FRAMEWORK TRUE
MACOSX_FRAMEWORK_IDENTIFIER com.portaudio
FRAMEWORK_VERSION A
PUBLIC_HEADER "${PA_PUBLIC_INCLUDES}"
VERSION 19.0
SOVERSION 19.0)
ENDIF()
ENDIF()
IF(NOT PA_OUTPUT_OSX_FRAMEWORK)
CONFIGURE_FILE(cmake_support/portaudio-2.0.pc.in ${CMAKE_CURRENT_BINARY_DIR}/portaudio-2.0.pc @ONLY)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/portaudio-2.0.pc DESTINATION lib/pkgconfig)
INSTALL(FILES ${PA_PUBLIC_INCLUDES} DESTINATION include)
#INSTALL(TARGETS portaudio DESTINATION lib)
ENDIF()
ENDIF()
# Prepared for inclusion of test files
OPTION(PA_BUILD_TESTS "Include test projects" OFF)
IF(PA_BUILD_TESTS)
SUBDIRS(test)
ENDIF()
# Prepared for inclusion of test files
OPTION(PA_BUILD_EXAMPLES "Include example projects" OFF)
IF(PA_BUILD_EXAMPLES)
SUBDIRS(examples)
ENDIF()

View File

@ -1,6 +0,0 @@
This directory contains the Visual Studio project files which are used to build portaudio.
* portaudio's files were very old and messy
* Makes it easier to update portaudio in the future
* Uses dolphin's VSProps, so we know it's properly compatible
See full portaudio distribution for instructions about building and using portaudio.

View File

@ -1,73 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{0A18A071-125E-442F-AFF7-A3F68ABECF99}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\Source\VSProps\Base.props" />
<Import Project="..\..\..\Source\VSProps\ClDisableAllWarnings.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>..\src\common;..\include;.\;..\src\os\win;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>PA_ENABLE_DEBUG_OUTPUT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\src\common\pa_allocation.c" />
<ClCompile Include="..\src\common\pa_converters.c" />
<ClCompile Include="..\src\common\pa_cpuload.c" />
<ClCompile Include="..\src\common\pa_debugprint.c" />
<ClCompile Include="..\src\common\pa_dither.c" />
<ClCompile Include="..\src\common\pa_front.c" />
<ClCompile Include="..\src\hostapi\skeleton\pa_hostapi_skeleton.c" />
<ClCompile Include="..\src\common\pa_process.c" />
<ClCompile Include="..\src\common\pa_ringbuffer.c" />
<ClCompile Include="..\src\common\pa_stream.c" />
<ClCompile Include="..\src\common\pa_trace.c" />
<ClCompile Include="..\src\hostapi\wmme\pa_win_wmme.c" />
<ClCompile Include="..\src\hostapi\wasapi\pa_win_wasapi.c" />
<ClCompile Include="..\src\os\win\pa_win_coinitialize.c" />
<ClCompile Include="..\src\os\win\pa_win_hostapis.c" />
<ClCompile Include="..\src\os\win\pa_win_util.c" />
<ClCompile Include="..\src\os\win\pa_win_waveformat.c" />
<ClCompile Include="..\src\os\win\pa_win_wdmks_utils.c" />
<ClCompile Include="..\src\os\win\pa_x86_plain_converters.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\pa_win_wasapi.h" />
<ClInclude Include="..\include\pa_win_waveformat.h" />
<ClInclude Include="..\include\pa_win_wmme.h" />
<ClInclude Include="..\include\portaudio.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,110 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{69112e69-92e4-40c1-aa5b-e4c4780ade42}</UniqueIdentifier>
<Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
</Filter>
<Filter Include="Source Files\common">
<UniqueIdentifier>{ddf0cf9b-f2df-4549-a447-8d7c4c2128d7}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\hostapi">
<UniqueIdentifier>{219121eb-0c81-4948-a94c-6802cf152776}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\hostapi\dsound">
<UniqueIdentifier>{17688226-7728-4556-83a7-8e85b561ccca}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\hostapi\wmme">
<UniqueIdentifier>{520ee766-8582-402e-a935-bdbcaa0d44de}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\hostapi\wasapi">
<UniqueIdentifier>{3891bf2e-9681-4394-be07-88e0a3fd2a68}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\hostapi\wdmks">
<UniqueIdentifier>{16791044-a8a5-4f21-b032-08245e52777a}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\os">
<UniqueIdentifier>{bde5e4fb-71f2-4cdf-8879-5370d0e12697}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\os\win">
<UniqueIdentifier>{f1e8b583-742d-46a2-ac7f-060aabdc3a2c}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{d8832c7e-2dd0-48e7-8227-23b0d04c1879}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\common\pa_allocation.c">
<Filter>Source Files\common</Filter>
</ClCompile>
<ClCompile Include="..\src\common\pa_converters.c">
<Filter>Source Files\common</Filter>
</ClCompile>
<ClCompile Include="..\src\common\pa_cpuload.c">
<Filter>Source Files\common</Filter>
</ClCompile>
<ClCompile Include="..\src\common\pa_debugprint.c">
<Filter>Source Files\common</Filter>
</ClCompile>
<ClCompile Include="..\src\common\pa_dither.c">
<Filter>Source Files\common</Filter>
</ClCompile>
<ClCompile Include="..\src\common\pa_front.c">
<Filter>Source Files\common</Filter>
</ClCompile>
<ClCompile Include="..\src\hostapi\skeleton\pa_hostapi_skeleton.c">
<Filter>Source Files\common</Filter>
</ClCompile>
<ClCompile Include="..\src\common\pa_process.c">
<Filter>Source Files\common</Filter>
</ClCompile>
<ClCompile Include="..\src\common\pa_ringbuffer.c">
<Filter>Source Files\common</Filter>
</ClCompile>
<ClCompile Include="..\src\common\pa_stream.c">
<Filter>Source Files\common</Filter>
</ClCompile>
<ClCompile Include="..\src\common\pa_trace.c">
<Filter>Source Files\common</Filter>
</ClCompile>
<ClCompile Include="..\src\hostapi\wmme\pa_win_wmme.c">
<Filter>Source Files\hostapi\wmme</Filter>
</ClCompile>
<ClCompile Include="..\src\hostapi\wasapi\pa_win_wasapi.c">
<Filter>Source Files\hostapi\wasapi</Filter>
</ClCompile>
<ClCompile Include="..\src\os\win\pa_win_coinitialize.c">
<Filter>Source Files\os\win</Filter>
</ClCompile>
<ClCompile Include="..\src\os\win\pa_win_hostapis.c">
<Filter>Source Files\os\win</Filter>
</ClCompile>
<ClCompile Include="..\src\os\win\pa_win_util.c">
<Filter>Source Files\os\win</Filter>
</ClCompile>
<ClCompile Include="..\src\os\win\pa_win_waveformat.c">
<Filter>Source Files\os\win</Filter>
</ClCompile>
<ClCompile Include="..\src\os\win\pa_win_wdmks_utils.c">
<Filter>Source Files\os\win</Filter>
</ClCompile>
<ClCompile Include="..\src\os\win\pa_x86_plain_converters.c">
<Filter>Source Files\os\win</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\pa_win_wasapi.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\pa_win_waveformat.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\pa_win_wmme.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\portaudio.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -1,41 +0,0 @@
# $Id: $
#
# - Try to find the ASIO SDK
# Once done this will define
#
# ASIOSDK_FOUND - system has ASIO SDK
# ASIOSDK_ROOT_DIR - path to the ASIO SDK base directory
# ASIOSDK_INCLUDE_DIR - the ASIO SDK include directory
if(WIN32)
else(WIN32)
message(FATAL_ERROR "FindASIOSDK.cmake: Unsupported platform ${CMAKE_SYSTEM_NAME}" )
endif(WIN32)
file(GLOB results "${CMAKE_CURRENT_SOURCE_DIR}/../as*")
foreach(f ${results})
if(IS_DIRECTORY ${f})
set(ASIOSDK_PATH_HINT ${ASIOSDK_PATH_HINT} ${f})
endif()
endforeach()
find_path(ASIOSDK_ROOT_DIR
common/asio.h
HINTS
${ASIOSDK_PATH_HINT}
)
find_path(ASIOSDK_INCLUDE_DIR
asio.h
PATHS
${ASIOSDK_ROOT_DIR}/common
)
# handle the QUIETLY and REQUIRED arguments and set ASIOSDK_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(ASIOSDK DEFAULT_MSG ASIOSDK_ROOT_DIR ASIOSDK_INCLUDE_DIR)
MARK_AS_ADVANCED(
ASIOSDK_ROOT_DIR ASIOSDK_INCLUDE_DIR
)

View File

@ -1,59 +0,0 @@
# $Id: $
#
# - Try to find the DirectX SDK
# Once done this will define
#
# DXSDK_FOUND - system has DirectX SDK
# DXSDK_ROOT_DIR - path to the DirectX SDK base directory
# DXSDK_INCLUDE_DIR - the DirectX SDK include directory
# DXSDK_LIBRARY_DIR - DirectX SDK libraries path
#
# DXSDK_DSOUND_LIBRARY - Path to dsound.lib
#
if(WIN32)
else(WIN32)
message(FATAL_ERROR "FindDXSDK.cmake: Unsupported platform ${CMAKE_SYSTEM_NAME}" )
endif(WIN32)
find_path(DXSDK_ROOT_DIR
include/dxsdkver.h
HINTS
$ENV{DXSDK_DIR}
)
find_path(DXSDK_INCLUDE_DIR
dxsdkver.h
PATHS
${DXSDK_ROOT_DIR}/include
)
IF(CMAKE_CL_64)
find_path(DXSDK_LIBRARY_DIR
dsound.lib
PATHS
${DXSDK_ROOT_DIR}/lib/x64
)
ELSE(CMAKE_CL_64)
find_path(DXSDK_LIBRARY_DIR
dsound.lib
PATHS
${DXSDK_ROOT_DIR}/lib/x86
)
ENDIF(CMAKE_CL_64)
find_library(DXSDK_DSOUND_LIBRARY
dsound.lib
PATHS
${DXSDK_LIBRARY_DIR}
)
# handle the QUIETLY and REQUIRED arguments and set DXSDK_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(DXSDK DEFAULT_MSG DXSDK_ROOT_DIR DXSDK_INCLUDE_DIR)
MARK_AS_ADVANCED(
DXSDK_ROOT_DIR DXSDK_INCLUDE_DIR
DXSDK_LIBRARY_DIR DXSDK_DSOUND_LIBRARY
)

View File

@ -1,41 +0,0 @@
# - Try to find jack
# Once done this will define
# JACK_FOUND - System has jack
# JACK_INCLUDE_DIRS - The jack include directories
# JACK_LIBRARIES - The libraries needed to use jack
# JACK_DEFINITIONS - Compiler switches required for using jack
if (JACK_LIBRARIES AND JACK_INCLUDE_DIRS)
# in cache already
set(JACK_FOUND TRUE)
else (JACK_LIBRARIES AND JACK_INCLUDE_DIRS)
set(JACK_DEFINITIONS "")
# Look for pkg-config and use it (if available) to find package
find_package(PkgConfig QUIET)
if (PKG_CONFIG_FOUND)
pkg_search_module(JACK QUIET jack)
endif (PKG_CONFIG_FOUND)
if (NOT JACK_FOUND)
find_path(JACK_INCLUDE_DIR jack/jack.h HINTS ${JACK_INCLUDEDIR} ${JACK_INCLUDE_DIRS} PATH_SUFFIXES jack)
find_library(JACK_LIBRARY NAMES jack HINTS ${JACK_LIBDIR} ${JACK_LIBRARY_DIRS})
set(JACK_LIBRARIES ${JACK_LIBRARY})
set(JACK_INCLUDE_DIRS ${JACK_INCLUDE_DIR})
include(FindPackageHandleStandardArgs)
# Set JACK_FOUND if the library and include paths were found
find_package_handle_standard_args(jack DEFAULT_MSG JACK_LIBRARY JACK_INCLUDE_DIR)
# Don't show include/library paths in cmake GUI
mark_as_advanced(JACK_INCLUDE_DIR JACK_LIBRARY)
endif (NOT JACK_FOUND)
endif (JACK_LIBRARIES AND JACK_INCLUDE_DIRS)

View File

@ -1,31 +0,0 @@
/* $Id: $
!!! @GENERATED_MESSAGE@ !!!
Header file configured by CMake to convert CMake options/vars to macros. It is done this way because if set via
preprocessor options, MSVC f.i. has no way of knowing when an option (or var) changes as there is no dependency chain.
The generated "options_cmake.h" should be included like so:
#ifdef PORTAUDIO_CMAKE_GENERATED
#include "options_cmake.h"
#endif
so that non-CMake build environments are left intact.
Source template: cmake_support/options_cmake.h.in
*/
#ifdef _WIN32
#if defined(PA_USE_ASIO) || defined(PA_USE_DS) || defined(PA_USE_WMME) || defined(PA_USE_WASAPI) || defined(PA_USE_WDMKS)
#error "This header needs to be included before pa_hostapi.h!!"
#endif
#cmakedefine01 PA_USE_ASIO
#cmakedefine01 PA_USE_DS
#cmakedefine01 PA_USE_WMME
#cmakedefine01 PA_USE_WASAPI
#cmakedefine01 PA_USE_WDMKS
#else
#error "Platform currently not supported by CMake script"
#endif

View File

@ -1,12 +0,0 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
libdir=${prefix}/lib
includedir=${prefix}/include
Name: PortAudio
Description: Portable audio I/O
Requires:
Version: @PA_PKGCONFIG_VERSION@
Libs: -L${libdir} -lportaudio @PA_PKGCONFIG_LDFLAGS@
Cflags: -I${includedir} @PA_PKGCONFIG_CFLAGS@

View File

@ -1,53 +0,0 @@
; $Id: $
;
; !!! @GENERATED_MESSAGE@ !!!
EXPORTS
;
Pa_GetVersion @1
Pa_GetVersionText @2
Pa_GetErrorText @3
Pa_Initialize @4
Pa_Terminate @5
Pa_GetHostApiCount @6
Pa_GetDefaultHostApi @7
Pa_GetHostApiInfo @8
Pa_HostApiTypeIdToHostApiIndex @9
Pa_HostApiDeviceIndexToDeviceIndex @10
Pa_GetLastHostErrorInfo @11
Pa_GetDeviceCount @12
Pa_GetDefaultInputDevice @13
Pa_GetDefaultOutputDevice @14
Pa_GetDeviceInfo @15
Pa_IsFormatSupported @16
Pa_OpenStream @17
Pa_OpenDefaultStream @18
Pa_CloseStream @19
Pa_SetStreamFinishedCallback @20
Pa_StartStream @21
Pa_StopStream @22
Pa_AbortStream @23
Pa_IsStreamStopped @24
Pa_IsStreamActive @25
Pa_GetStreamInfo @26
Pa_GetStreamTime @27
Pa_GetStreamCpuLoad @28
Pa_ReadStream @29
Pa_WriteStream @30
Pa_GetStreamReadAvailable @31
Pa_GetStreamWriteAvailable @32
Pa_GetSampleSize @33
Pa_Sleep @34
@DEF_EXCLUDE_ASIO_SYMBOLS@PaAsio_GetAvailableBufferSizes @50
@DEF_EXCLUDE_ASIO_SYMBOLS@PaAsio_ShowControlPanel @51
@DEF_EXCLUDE_X86_PLAIN_CONVERTERS@PaUtil_InitializeX86PlainConverters @52
@DEF_EXCLUDE_ASIO_SYMBOLS@PaAsio_GetInputChannelName @53
@DEF_EXCLUDE_ASIO_SYMBOLS@PaAsio_GetOutputChannelName @54
PaUtil_SetDebugPrintFunction @55
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetDeviceDefaultFormat @56
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetDeviceRole @57
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_ThreadPriorityBoost @58
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_ThreadPriorityRevert @59
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetFramesPerHostBuffer @60
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetJackDescription @61
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetJackCount @62

View File

@ -1,150 +0,0 @@
#ifndef PA_ASIO_H
#define PA_ASIO_H
/*
* $Id$
* PortAudio Portable Real-Time Audio Library
* ASIO specific extensions
*
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup public_header
@brief ASIO-specific PortAudio API extension header file.
*/
#include "portaudio.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/** Retrieve legal native buffer sizes for the specificed device, in sample frames.
@param device The global index of the device about which the query is being made.
@param minBufferSizeFrames A pointer to the location which will receive the minimum buffer size value.
@param maxBufferSizeFrames A pointer to the location which will receive the maximum buffer size value.
@param preferredBufferSizeFrames A pointer to the location which will receive the preferred buffer size value.
@param granularity A pointer to the location which will receive the "granularity". This value determines
the step size used to compute the legal values between minBufferSizeFrames and maxBufferSizeFrames.
If granularity is -1 then available buffer size values are powers of two.
@see ASIOGetBufferSize in the ASIO SDK.
@note: this function used to be called PaAsio_GetAvailableLatencyValues. There is a
#define that maps PaAsio_GetAvailableLatencyValues to this function for backwards compatibility.
*/
PaError PaAsio_GetAvailableBufferSizes( PaDeviceIndex device,
long *minBufferSizeFrames, long *maxBufferSizeFrames, long *preferredBufferSizeFrames, long *granularity );
/** Backwards compatibility alias for PaAsio_GetAvailableBufferSizes
@see PaAsio_GetAvailableBufferSizes
*/
#define PaAsio_GetAvailableLatencyValues PaAsio_GetAvailableBufferSizes
/** Display the ASIO control panel for the specified device.
@param device The global index of the device whose control panel is to be displayed.
@param systemSpecific On Windows, the calling application's main window handle,
on Macintosh this value should be zero.
*/
PaError PaAsio_ShowControlPanel( PaDeviceIndex device, void* systemSpecific );
/** Retrieve a pointer to a string containing the name of the specified
input channel. The string is valid until Pa_Terminate is called.
The string will be no longer than 32 characters including the null terminator.
*/
PaError PaAsio_GetInputChannelName( PaDeviceIndex device, int channelIndex,
const char** channelName );
/** Retrieve a pointer to a string containing the name of the specified
input channel. The string is valid until Pa_Terminate is called.
The string will be no longer than 32 characters including the null terminator.
*/
PaError PaAsio_GetOutputChannelName( PaDeviceIndex device, int channelIndex,
const char** channelName );
/** Set the sample rate of an open paASIO stream.
@param stream The stream to operate on.
@param sampleRate The new sample rate.
Note that this function may fail if the stream is alredy running and the
ASIO driver does not support switching the sample rate of a running stream.
Returns paIncompatibleStreamHostApi if stream is not a paASIO stream.
*/
PaError PaAsio_SetStreamSampleRate( PaStream* stream, double sampleRate );
#define paAsioUseChannelSelectors (0x01)
typedef struct PaAsioStreamInfo{
unsigned long size; /**< sizeof(PaAsioStreamInfo) */
PaHostApiTypeId hostApiType; /**< paASIO */
unsigned long version; /**< 1 */
unsigned long flags;
/* Support for opening only specific channels of an ASIO device.
If the paAsioUseChannelSelectors flag is set, channelSelectors is a
pointer to an array of integers specifying the device channels to use.
When used, the length of the channelSelectors array must match the
corresponding channelCount parameter to Pa_OpenStream() otherwise a
crash may result.
The values in the selectors array must specify channels within the
range of supported channels for the device or paInvalidChannelCount will
result.
*/
int *channelSelectors;
}PaAsioStreamInfo;
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_ASIO_H */

View File

@ -1,77 +0,0 @@
#ifndef PA_JACK_H
#define PA_JACK_H
/*
* $Id:
* PortAudio Portable Real-Time Audio Library
* JACK-specific extensions
*
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
* @ingroup public_header
* @brief JACK-specific PortAudio API extension header file.
*/
#include "portaudio.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Set the JACK client name.
*
* During Pa_Initialize, When PA JACK connects as a client of the JACK server, it requests a certain
* name, which is for instance prepended to port names. By default this name is "PortAudio". The
* JACK server may append a suffix to the client name, in order to avoid clashes among clients that
* try to connect with the same name (e.g., different PA JACK clients).
*
* This function must be called before Pa_Initialize, otherwise it won't have any effect. Note that
* the string is not copied, but instead referenced directly, so it must not be freed for as long as
* PA might need it.
* @sa PaJack_GetClientName
*/
PaError PaJack_SetClientName( const char* name );
/** Get the JACK client name used by PA JACK.
*
* The caller is responsible for freeing the returned pointer.
*/
PaError PaJack_GetClientName(const char** clientName);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,107 +0,0 @@
#ifndef PA_LINUX_ALSA_H
#define PA_LINUX_ALSA_H
/*
* $Id$
* PortAudio Portable Real-Time Audio Library
* ALSA-specific extensions
*
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
* @ingroup public_header
* @brief ALSA-specific PortAudio API extension header file.
*/
#include "portaudio.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct PaAlsaStreamInfo
{
unsigned long size;
PaHostApiTypeId hostApiType;
unsigned long version;
const char *deviceString;
}
PaAlsaStreamInfo;
/** Initialize host API specific structure, call this before setting relevant attributes. */
void PaAlsa_InitializeStreamInfo( PaAlsaStreamInfo *info );
/** Instruct whether to enable real-time priority when starting the audio thread.
*
* If this is turned on by the stream is started, the audio callback thread will be created
* with the FIFO scheduling policy, which is suitable for realtime operation.
**/
void PaAlsa_EnableRealtimeScheduling( PaStream *s, int enable );
#if 0
void PaAlsa_EnableWatchdog( PaStream *s, int enable );
#endif
/** Get the ALSA-lib card index of this stream's input device. */
PaError PaAlsa_GetStreamInputCard( PaStream *s, int *card );
/** Get the ALSA-lib card index of this stream's output device. */
PaError PaAlsa_GetStreamOutputCard( PaStream *s, int *card );
/** Set the number of periods (buffer fragments) to configure devices with.
*
* By default the number of periods is 4, this is the lowest number of periods that works well on
* the author's soundcard.
* @param numPeriods The number of periods.
*/
PaError PaAlsa_SetNumPeriods( int numPeriods );
/** Set the maximum number of times to retry opening busy device (sleeping for a
* short interval inbetween).
*/
PaError PaAlsa_SetRetriesBusy( int retries );
/** Set the path and name of ALSA library file if PortAudio is configured to load it dynamically (see
* PA_ALSA_DYNAMIC). This setting will overwrite the default name set by PA_ALSA_PATHNAME define.
* @param pathName Full path with filename. Only filename can be used, but dlopen() will lookup default
* searchable directories (/usr/lib;/usr/local/lib) then.
*/
void PaAlsa_SetLibraryPathName( const char *pathName );
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,191 +0,0 @@
#ifndef PA_MAC_CORE_H
#define PA_MAC_CORE_H
/*
* PortAudio Portable Real-Time Audio Library
* Macintosh Core Audio specific extensions
* portaudio.h should be included before this file.
*
* Copyright (c) 2005-2006 Bjorn Roche
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
* @ingroup public_header
* @brief CoreAudio-specific PortAudio API extension header file.
*/
#include "portaudio.h"
#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioToolbox.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* A pointer to a paMacCoreStreamInfo may be passed as
* the hostApiSpecificStreamInfo in the PaStreamParameters struct
* when opening a stream or querying the format. Use NULL, for the
* defaults. Note that for duplex streams, flags for input and output
* should be the same or behaviour is undefined.
*/
typedef struct
{
unsigned long size; /**size of whole structure including this header */
PaHostApiTypeId hostApiType; /**host API for which this data is intended */
unsigned long version; /**structure version */
unsigned long flags; /** flags to modify behaviour */
SInt32 const * channelMap; /** Channel map for HAL channel mapping , if not needed, use NULL;*/
unsigned long channelMapSize; /** Channel map size for HAL channel mapping , if not needed, use 0;*/
} PaMacCoreStreamInfo;
/**
* Functions
*/
/** Use this function to initialize a paMacCoreStreamInfo struct
* using the requested flags. Note that channel mapping is turned
* off after a call to this function.
* @param data The datastructure to initialize
* @param flags The flags to initialize the datastructure with.
*/
void PaMacCore_SetupStreamInfo( PaMacCoreStreamInfo *data, unsigned long flags );
/** call this after pa_SetupMacCoreStreamInfo to use channel mapping as described in notes.txt.
* @param data The stream info structure to assign a channel mapping to
* @param channelMap The channel map array, as described in notes.txt. This array pointer will be used directly (ie the underlying data will not be copied), so the caller should not free the array until after the stream has been opened.
* @param channelMapSize The size of the channel map array.
*/
void PaMacCore_SetupChannelMap( PaMacCoreStreamInfo *data, const SInt32 * const channelMap, unsigned long channelMapSize );
/**
* Retrieve the AudioDeviceID of the input device assigned to an open stream
*
* @param s The stream to query.
*
* @return A valid AudioDeviceID, or NULL if an error occurred.
*/
AudioDeviceID PaMacCore_GetStreamInputDevice( PaStream* s );
/**
* Retrieve the AudioDeviceID of the output device assigned to an open stream
*
* @param s The stream to query.
*
* @return A valid AudioDeviceID, or NULL if an error occurred.
*/
AudioDeviceID PaMacCore_GetStreamOutputDevice( PaStream* s );
/**
* Returns a statically allocated string with the device's name
* for the given channel. NULL will be returned on failure.
*
* This function's implemenation is not complete!
*
* @param device The PortAudio device index.
* @param channel The channel number who's name is requested.
* @return a statically allocated string with the name of the device.
* Because this string is statically allocated, it must be
* coppied if it is to be saved and used by the user after
* another call to this function.
*
*/
const char *PaMacCore_GetChannelName( int device, int channelIndex, bool input );
/** Retrieve the range of legal native buffer sizes for the specificed device, in sample frames.
@param device The global index of the PortAudio device about which the query is being made.
@param minBufferSizeFrames A pointer to the location which will receive the minimum buffer size value.
@param maxBufferSizeFrames A pointer to the location which will receive the maximum buffer size value.
@see kAudioDevicePropertyBufferFrameSizeRange in the CoreAudio SDK.
*/
PaError PaMacCore_GetBufferSizeRange( PaDeviceIndex device,
long *minBufferSizeFrames, long *maxBufferSizeFrames );
/**
* Flags
*/
/**
* The following flags alter the behaviour of PA on the mac platform.
* they can be ORed together. These should work both for opening and
* checking a device.
*/
/** Allows PortAudio to change things like the device's frame size,
* which allows for much lower latency, but might disrupt the device
* if other programs are using it, even when you are just Querying
* the device. */
#define paMacCoreChangeDeviceParameters (0x01)
/** In combination with the above flag,
* causes the stream opening to fail, unless the exact sample rates
* are supported by the device. */
#define paMacCoreFailIfConversionRequired (0x02)
/** These flags set the SR conversion quality, if required. The wierd ordering
* allows Maximum Quality to be the default.*/
#define paMacCoreConversionQualityMin (0x0100)
#define paMacCoreConversionQualityMedium (0x0200)
#define paMacCoreConversionQualityLow (0x0300)
#define paMacCoreConversionQualityHigh (0x0400)
#define paMacCoreConversionQualityMax (0x0000)
/**
* Here are some "preset" combinations of flags (above) to get to some
* common configurations. THIS IS OVERKILL, but if more flags are added
* it won't be.
*/
/**This is the default setting: do as much sample rate conversion as possible
* and as little mucking with the device as possible. */
#define paMacCorePlayNice (0x00)
/**This setting is tuned for pro audio apps. It allows SR conversion on input
and output, but it tries to set the appropriate SR on the device.*/
#define paMacCorePro (0x01)
/**This is a setting to minimize CPU usage and still play nice.*/
#define paMacCoreMinimizeCPUButPlayNice (0x0100)
/**This is a setting to minimize CPU usage, even if that means interrupting the device. */
#define paMacCoreMinimizeCPU (0x0101)
#ifdef __cplusplus
}
#endif /** __cplusplus */
#endif /** PA_MAC_CORE_H */

View File

@ -1,95 +0,0 @@
#ifndef PA_WIN_DS_H
#define PA_WIN_DS_H
/*
* $Id: $
* PortAudio Portable Real-Time Audio Library
* DirectSound specific extensions
*
* Copyright (c) 1999-2007 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup public_header
@brief DirectSound-specific PortAudio API extension header file.
*/
#include "portaudio.h"
#include "pa_win_waveformat.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
#define paWinDirectSoundUseLowLevelLatencyParameters (0x01)
#define paWinDirectSoundUseChannelMask (0x04)
typedef struct PaWinDirectSoundStreamInfo{
unsigned long size; /**< sizeof(PaWinDirectSoundStreamInfo) */
PaHostApiTypeId hostApiType; /**< paDirectSound */
unsigned long version; /**< 2 */
unsigned long flags; /**< enable other features of this struct */
/**
low-level latency setting support
Sets the size of the DirectSound host buffer.
When flags contains the paWinDirectSoundUseLowLevelLatencyParameters
this size will be used instead of interpreting the generic latency
parameters to Pa_OpenStream(). If the flag is not set this value is ignored.
If the stream is a full duplex stream the implementation requires that
the values of framesPerBuffer for input and output match (if both are specified).
*/
unsigned long framesPerBuffer;
/**
support for WAVEFORMATEXTENSIBLE channel masks. If flags contains
paWinDirectSoundUseChannelMask this allows you to specify which speakers
to address in a multichannel stream. Constants for channelMask
are specified in pa_win_waveformat.h
*/
PaWinWaveFormatChannelMask channelMask;
}PaWinDirectSoundStreamInfo;
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_WIN_DS_H */

View File

@ -1,443 +0,0 @@
#ifndef PA_WIN_WASAPI_H
#define PA_WIN_WASAPI_H
/*
* $Id: $
* PortAudio Portable Real-Time Audio Library
* DirectSound specific extensions
*
* Copyright (c) 1999-2007 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup public_header
@brief WASAPI-specific PortAudio API extension header file.
*/
#include "portaudio.h"
#include "pa_win_waveformat.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/* Setup flags */
typedef enum PaWasapiFlags
{
/* puts WASAPI into exclusive mode */
paWinWasapiExclusive = (1 << 0),
/* allows to skip internal PA processing completely */
paWinWasapiRedirectHostProcessor = (1 << 1),
/* assigns custom channel mask */
paWinWasapiUseChannelMask = (1 << 2),
/* selects non-Event driven method of data read/write
Note: WASAPI Event driven core is capable of 2ms latency!!!, but Polling
method can only provide 15-20ms latency. */
paWinWasapiPolling = (1 << 3),
/* forces custom thread priority setting, must be used if PaWasapiStreamInfo::threadPriority
is set to a custom value */
paWinWasapiThreadPriority = (1 << 4)
}
PaWasapiFlags;
#define paWinWasapiExclusive (paWinWasapiExclusive)
#define paWinWasapiRedirectHostProcessor (paWinWasapiRedirectHostProcessor)
#define paWinWasapiUseChannelMask (paWinWasapiUseChannelMask)
#define paWinWasapiPolling (paWinWasapiPolling)
#define paWinWasapiThreadPriority (paWinWasapiThreadPriority)
/* Host processor. Allows to skip internal PA processing completely.
You must set paWinWasapiRedirectHostProcessor flag to PaWasapiStreamInfo::flags member
in order to have host processor redirected to your callback.
Use with caution! inputFrames and outputFrames depend solely on final device setup.
To query maximal values of inputFrames/outputFrames use PaWasapi_GetFramesPerHostBuffer.
*/
typedef void (*PaWasapiHostProcessorCallback) (void *inputBuffer, long inputFrames,
void *outputBuffer, long outputFrames,
void *userData);
/* Device role. */
typedef enum PaWasapiDeviceRole
{
eRoleRemoteNetworkDevice = 0,
eRoleSpeakers,
eRoleLineLevel,
eRoleHeadphones,
eRoleMicrophone,
eRoleHeadset,
eRoleHandset,
eRoleUnknownDigitalPassthrough,
eRoleSPDIF,
eRoleHDMI,
eRoleUnknownFormFactor
}
PaWasapiDeviceRole;
/* Jack connection type. */
typedef enum PaWasapiJackConnectionType
{
eJackConnTypeUnknown,
eJackConnType3Point5mm,
eJackConnTypeQuarter,
eJackConnTypeAtapiInternal,
eJackConnTypeRCA,
eJackConnTypeOptical,
eJackConnTypeOtherDigital,
eJackConnTypeOtherAnalog,
eJackConnTypeMultichannelAnalogDIN,
eJackConnTypeXlrProfessional,
eJackConnTypeRJ11Modem,
eJackConnTypeCombination
}
PaWasapiJackConnectionType;
/* Jack geometric location. */
typedef enum PaWasapiJackGeoLocation
{
eJackGeoLocUnk = 0,
eJackGeoLocRear = 0x1, /* matches EPcxGeoLocation::eGeoLocRear */
eJackGeoLocFront,
eJackGeoLocLeft,
eJackGeoLocRight,
eJackGeoLocTop,
eJackGeoLocBottom,
eJackGeoLocRearPanel,
eJackGeoLocRiser,
eJackGeoLocInsideMobileLid,
eJackGeoLocDrivebay,
eJackGeoLocHDMI,
eJackGeoLocOutsideMobileLid,
eJackGeoLocATAPI,
eJackGeoLocReserved5,
eJackGeoLocReserved6,
}
PaWasapiJackGeoLocation;
/* Jack general location. */
typedef enum PaWasapiJackGenLocation
{
eJackGenLocPrimaryBox = 0,
eJackGenLocInternal,
eJackGenLocSeparate,
eJackGenLocOther
}
PaWasapiJackGenLocation;
/* Jack's type of port. */
typedef enum PaWasapiJackPortConnection
{
eJackPortConnJack = 0,
eJackPortConnIntegratedDevice,
eJackPortConnBothIntegratedAndJack,
eJackPortConnUnknown
}
PaWasapiJackPortConnection;
/* Thread priority. */
typedef enum PaWasapiThreadPriority
{
eThreadPriorityNone = 0,
eThreadPriorityAudio, //!< Default for Shared mode.
eThreadPriorityCapture,
eThreadPriorityDistribution,
eThreadPriorityGames,
eThreadPriorityPlayback,
eThreadPriorityProAudio, //!< Default for Exclusive mode.
eThreadPriorityWindowManager
}
PaWasapiThreadPriority;
/* Stream descriptor. */
typedef struct PaWasapiJackDescription
{
unsigned long channelMapping;
unsigned long color; /* derived from macro: #define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) */
PaWasapiJackConnectionType connectionType;
PaWasapiJackGeoLocation geoLocation;
PaWasapiJackGenLocation genLocation;
PaWasapiJackPortConnection portConnection;
unsigned int isConnected;
}
PaWasapiJackDescription;
/** Stream category.
Note:
- values are equal to WASAPI AUDIO_STREAM_CATEGORY enum
- supported since Windows 8.0, noop on earler versions
- values 1,2 are deprecated on Windows 10 and not included into enumeration
@version Available as of 19.6.0
*/
typedef enum PaWasapiStreamCategory
{
eAudioCategoryOther = 0,
eAudioCategoryCommunications = 3,
eAudioCategoryAlerts = 4,
eAudioCategorySoundEffects = 5,
eAudioCategoryGameEffects = 6,
eAudioCategoryGameMedia = 7,
eAudioCategoryGameChat = 8,
eAudioCategorySpeech = 9,
eAudioCategoryMovie = 10,
eAudioCategoryMedia = 11
}
PaWasapiStreamCategory;
/** Stream option.
Note:
- values are equal to WASAPI AUDCLNT_STREAMOPTIONS enum
- supported since Windows 8.1, noop on earler versions
@version Available as of 19.6.0
*/
typedef enum PaWasapiStreamOption
{
eStreamOptionNone = 0, //!< default
eStreamOptionRaw = 1, //!< bypass WASAPI Audio Engine DSP effects, supported since Windows 8.1
eStreamOptionMatchFormat = 2 //!< force WASAPI Audio Engine into a stream format, supported since Windows 10
}
PaWasapiStreamOption;
/* Stream descriptor. */
typedef struct PaWasapiStreamInfo
{
unsigned long size; /**< sizeof(PaWasapiStreamInfo) */
PaHostApiTypeId hostApiType; /**< paWASAPI */
unsigned long version; /**< 1 */
unsigned long flags; /**< collection of PaWasapiFlags */
/** Support for WAVEFORMATEXTENSIBLE channel masks. If flags contains
paWinWasapiUseChannelMask this allows you to specify which speakers
to address in a multichannel stream. Constants for channelMask
are specified in pa_win_waveformat.h. Will be used only if
paWinWasapiUseChannelMask flag is specified.
*/
PaWinWaveFormatChannelMask channelMask;
/** Delivers raw data to callback obtained from GetBuffer() methods skipping
internal PortAudio processing inventory completely. userData parameter will
be the same that was passed to Pa_OpenStream method. Will be used only if
paWinWasapiRedirectHostProcessor flag is specified.
*/
PaWasapiHostProcessorCallback hostProcessorOutput;
PaWasapiHostProcessorCallback hostProcessorInput;
/** Specifies thread priority explicitly. Will be used only if paWinWasapiThreadPriority flag
is specified.
Please note, if Input/Output streams are opened simultaniously (Full-Duplex mode)
you shall specify same value for threadPriority or othervise one of the values will be used
to setup thread priority.
*/
PaWasapiThreadPriority threadPriority;
/** Stream category.
@see PaWasapiStreamCategory
@version Available as of 19.6.0
*/
PaWasapiStreamCategory streamCategory;
/** Stream option.
@see PaWasapiStreamOption
@version Available as of 19.6.0
*/
PaWasapiStreamOption streamOption;
}
PaWasapiStreamInfo;
/** Returns default sound format for device. Format is represented by PaWinWaveFormat or
WAVEFORMATEXTENSIBLE structure.
@param pFormat Pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure.
@param nFormatSize Size of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes.
@param nDevice Device index.
@return Non-negative value indicating the number of bytes copied into format decriptor
or, a PaErrorCode (which are always negative) if PortAudio is not initialized
or an error is encountered.
*/
int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice );
/** Returns device role (PaWasapiDeviceRole enum).
@param nDevice device index.
@return Non-negative value indicating device role or, a PaErrorCode (which are always negative)
if PortAudio is not initialized or an error is encountered.
*/
int/*PaWasapiDeviceRole*/ PaWasapi_GetDeviceRole( PaDeviceIndex nDevice );
/** Boost thread priority of calling thread (MMCSS). Use it for Blocking Interface only for thread
which makes calls to Pa_WriteStream/Pa_ReadStream.
@param hTask Handle to pointer to priority task. Must be used with PaWasapi_RevertThreadPriority
method to revert thread priority to initial state.
@param nPriorityClass Id of thread priority of PaWasapiThreadPriority type. Specifying
eThreadPriorityNone does nothing.
@return Error code indicating success or failure.
@see PaWasapi_RevertThreadPriority
*/
PaError PaWasapi_ThreadPriorityBoost( void **hTask, PaWasapiThreadPriority nPriorityClass );
/** Boost thread priority of calling thread (MMCSS). Use it for Blocking Interface only for thread
which makes calls to Pa_WriteStream/Pa_ReadStream.
@param hTask Task handle obtained by PaWasapi_BoostThreadPriority method.
@return Error code indicating success or failure.
@see PaWasapi_BoostThreadPriority
*/
PaError PaWasapi_ThreadPriorityRevert( void *hTask );
/** Get number of frames per host buffer. This is maximal value of frames of WASAPI buffer which
can be locked for operations. Use this method as helper to findout maximal values of
inputFrames/outputFrames of PaWasapiHostProcessorCallback.
@param pStream Pointer to PaStream to query.
@param nInput Pointer to variable to receive number of input frames. Can be NULL.
@param nOutput Pointer to variable to receive number of output frames. Can be NULL.
@return Error code indicating success or failure.
@see PaWasapiHostProcessorCallback
*/
PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *nInput, unsigned int *nOutput );
/** Get number of jacks associated with a WASAPI device. Use this method to determine if
there are any jacks associated with the provided WASAPI device. Not all audio devices
will support this capability. This is valid for both input and output devices.
@param nDevice device index.
@param jcount Number of jacks is returned in this variable
@return Error code indicating success or failure
@see PaWasapi_GetJackDescription
*/
PaError PaWasapi_GetJackCount(PaDeviceIndex nDevice, int *jcount);
/** Get the jack description associated with a WASAPI device and jack number
Before this function is called, use PaWasapi_GetJackCount to determine the
number of jacks associated with device. If jcount is greater than zero, then
each jack from 0 to jcount can be queried with this function to get the jack
description.
@param nDevice device index.
@param jindex Which jack to return information
@param KSJACK_DESCRIPTION This structure filled in on success.
@return Error code indicating success or failure
@see PaWasapi_GetJackCount
*/
PaError PaWasapi_GetJackDescription(PaDeviceIndex nDevice, int jindex, PaWasapiJackDescription *pJackDescription);
/*
IMPORTANT:
WASAPI is implemented for Callback and Blocking interfaces. It supports Shared and Exclusive
share modes.
Exclusive Mode:
Exclusive mode allows to deliver audio data directly to hardware bypassing
software mixing.
Exclusive mode is specified by 'paWinWasapiExclusive' flag.
Callback Interface:
Provides best audio quality with low latency. Callback interface is implemented in
two versions:
1) Event-Driven:
This is the most powerful WASAPI implementation which provides glitch-free
audio at around 3ms latency in Exclusive mode. Lowest possible latency for this mode is
3 ms for HD Audio class audio chips. For the Shared mode latency can not be
lower than 20 ms.
2) Poll-Driven:
Polling is another 2-nd method to operate with WASAPI. It is less efficient than Event-Driven
and provides latency at around 10-13ms. Polling must be used to overcome a system bug
under Windows Vista x64 when application is WOW64(32-bit) and Event-Driven method simply
times out (event handle is never signalled on buffer completion). Please note, such WOW64 bug
does not exist in Vista x86 or Windows 7.
Polling can be setup by speciying 'paWinWasapiPolling' flag. Our WASAPI implementation detects
WOW64 bug and sets 'paWinWasapiPolling' automatically.
Thread priority:
Normally thread priority is set automatically and does not require modification. Although
if user wants some tweaking thread priority can be modified by setting 'paWinWasapiThreadPriority'
flag and specifying 'PaWasapiStreamInfo::threadPriority' with value from PaWasapiThreadPriority
enum.
Blocking Interface:
Blocking interface is implemented but due to above described Poll-Driven method can not
deliver lowest possible latency. Specifying too low latency in Shared mode will result in
distorted audio although Exclusive mode adds stability.
Pa_IsFormatSupported:
To check format with correct Share Mode (Exclusive/Shared) you must supply
PaWasapiStreamInfo with flags paWinWasapiExclusive set through member of
PaStreamParameters::hostApiSpecificStreamInfo structure.
Pa_OpenStream:
To set desired Share Mode (Exclusive/Shared) you must supply
PaWasapiStreamInfo with flags paWinWasapiExclusive set through member of
PaStreamParameters::hostApiSpecificStreamInfo structure.
*/
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_WIN_WASAPI_H */

View File

@ -1,199 +0,0 @@
#ifndef PA_WIN_WAVEFORMAT_H
#define PA_WIN_WAVEFORMAT_H
/*
* PortAudio Portable Real-Time Audio Library
* Windows WAVEFORMAT* data structure utilities
* portaudio.h should be included before this file.
*
* Copyright (c) 2007 Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup public_header
@brief Windows specific PortAudio API extension and utilities header file.
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
The following #defines for speaker channel masks are the same
as those in ksmedia.h, except with PAWIN_ prepended, KSAUDIO_ removed
in some cases, and casts to PaWinWaveFormatChannelMask added.
*/
typedef unsigned long PaWinWaveFormatChannelMask;
/* Speaker Positions: */
#define PAWIN_SPEAKER_FRONT_LEFT ((PaWinWaveFormatChannelMask)0x1)
#define PAWIN_SPEAKER_FRONT_RIGHT ((PaWinWaveFormatChannelMask)0x2)
#define PAWIN_SPEAKER_FRONT_CENTER ((PaWinWaveFormatChannelMask)0x4)
#define PAWIN_SPEAKER_LOW_FREQUENCY ((PaWinWaveFormatChannelMask)0x8)
#define PAWIN_SPEAKER_BACK_LEFT ((PaWinWaveFormatChannelMask)0x10)
#define PAWIN_SPEAKER_BACK_RIGHT ((PaWinWaveFormatChannelMask)0x20)
#define PAWIN_SPEAKER_FRONT_LEFT_OF_CENTER ((PaWinWaveFormatChannelMask)0x40)
#define PAWIN_SPEAKER_FRONT_RIGHT_OF_CENTER ((PaWinWaveFormatChannelMask)0x80)
#define PAWIN_SPEAKER_BACK_CENTER ((PaWinWaveFormatChannelMask)0x100)
#define PAWIN_SPEAKER_SIDE_LEFT ((PaWinWaveFormatChannelMask)0x200)
#define PAWIN_SPEAKER_SIDE_RIGHT ((PaWinWaveFormatChannelMask)0x400)
#define PAWIN_SPEAKER_TOP_CENTER ((PaWinWaveFormatChannelMask)0x800)
#define PAWIN_SPEAKER_TOP_FRONT_LEFT ((PaWinWaveFormatChannelMask)0x1000)
#define PAWIN_SPEAKER_TOP_FRONT_CENTER ((PaWinWaveFormatChannelMask)0x2000)
#define PAWIN_SPEAKER_TOP_FRONT_RIGHT ((PaWinWaveFormatChannelMask)0x4000)
#define PAWIN_SPEAKER_TOP_BACK_LEFT ((PaWinWaveFormatChannelMask)0x8000)
#define PAWIN_SPEAKER_TOP_BACK_CENTER ((PaWinWaveFormatChannelMask)0x10000)
#define PAWIN_SPEAKER_TOP_BACK_RIGHT ((PaWinWaveFormatChannelMask)0x20000)
/* Bit mask locations reserved for future use */
#define PAWIN_SPEAKER_RESERVED ((PaWinWaveFormatChannelMask)0x7FFC0000)
/* Used to specify that any possible permutation of speaker configurations */
#define PAWIN_SPEAKER_ALL ((PaWinWaveFormatChannelMask)0x80000000)
/* DirectSound Speaker Config */
#define PAWIN_SPEAKER_DIRECTOUT 0
#define PAWIN_SPEAKER_MONO (PAWIN_SPEAKER_FRONT_CENTER)
#define PAWIN_SPEAKER_STEREO (PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT)
#define PAWIN_SPEAKER_QUAD (PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT | \
PAWIN_SPEAKER_BACK_LEFT | PAWIN_SPEAKER_BACK_RIGHT)
#define PAWIN_SPEAKER_SURROUND (PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT | \
PAWIN_SPEAKER_FRONT_CENTER | PAWIN_SPEAKER_BACK_CENTER)
#define PAWIN_SPEAKER_5POINT1 (PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT | \
PAWIN_SPEAKER_FRONT_CENTER | PAWIN_SPEAKER_LOW_FREQUENCY | \
PAWIN_SPEAKER_BACK_LEFT | PAWIN_SPEAKER_BACK_RIGHT)
#define PAWIN_SPEAKER_7POINT1 (PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT | \
PAWIN_SPEAKER_FRONT_CENTER | PAWIN_SPEAKER_LOW_FREQUENCY | \
PAWIN_SPEAKER_BACK_LEFT | PAWIN_SPEAKER_BACK_RIGHT | \
PAWIN_SPEAKER_FRONT_LEFT_OF_CENTER | PAWIN_SPEAKER_FRONT_RIGHT_OF_CENTER)
#define PAWIN_SPEAKER_5POINT1_SURROUND (PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT | \
PAWIN_SPEAKER_FRONT_CENTER | PAWIN_SPEAKER_LOW_FREQUENCY | \
PAWIN_SPEAKER_SIDE_LEFT | PAWIN_SPEAKER_SIDE_RIGHT)
#define PAWIN_SPEAKER_7POINT1_SURROUND (PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT | \
PAWIN_SPEAKER_FRONT_CENTER | PAWIN_SPEAKER_LOW_FREQUENCY | \
PAWIN_SPEAKER_BACK_LEFT | PAWIN_SPEAKER_BACK_RIGHT | \
PAWIN_SPEAKER_SIDE_LEFT | PAWIN_SPEAKER_SIDE_RIGHT)
/*
According to the Microsoft documentation:
The following are obsolete 5.1 and 7.1 settings (they lack side speakers). Note this means
that the default 5.1 and 7.1 settings (KSAUDIO_SPEAKER_5POINT1 and KSAUDIO_SPEAKER_7POINT1 are
similarly obsolete but are unchanged for compatibility reasons).
*/
#define PAWIN_SPEAKER_5POINT1_BACK PAWIN_SPEAKER_5POINT1
#define PAWIN_SPEAKER_7POINT1_WIDE PAWIN_SPEAKER_7POINT1
/* DVD Speaker Positions */
#define PAWIN_SPEAKER_GROUND_FRONT_LEFT PAWIN_SPEAKER_FRONT_LEFT
#define PAWIN_SPEAKER_GROUND_FRONT_CENTER PAWIN_SPEAKER_FRONT_CENTER
#define PAWIN_SPEAKER_GROUND_FRONT_RIGHT PAWIN_SPEAKER_FRONT_RIGHT
#define PAWIN_SPEAKER_GROUND_REAR_LEFT PAWIN_SPEAKER_BACK_LEFT
#define PAWIN_SPEAKER_GROUND_REAR_RIGHT PAWIN_SPEAKER_BACK_RIGHT
#define PAWIN_SPEAKER_TOP_MIDDLE PAWIN_SPEAKER_TOP_CENTER
#define PAWIN_SPEAKER_SUPER_WOOFER PAWIN_SPEAKER_LOW_FREQUENCY
/*
PaWinWaveFormat is defined here to provide compatibility with
compilation environments which don't have headers defining
WAVEFORMATEXTENSIBLE (e.g. older versions of MSVC, Borland C++ etc.
The fields for WAVEFORMATEX and WAVEFORMATEXTENSIBLE are declared as an
unsigned char array here to avoid clients who include this file having
a dependency on windows.h and mmsystem.h, and also to to avoid having
to write separate packing pragmas for each compiler.
*/
#define PAWIN_SIZEOF_WAVEFORMATEX 18
#define PAWIN_SIZEOF_WAVEFORMATEXTENSIBLE (PAWIN_SIZEOF_WAVEFORMATEX + 22)
typedef struct{
unsigned char fields[ PAWIN_SIZEOF_WAVEFORMATEXTENSIBLE ];
unsigned long extraLongForAlignment; /* ensure that compiler aligns struct to DWORD */
} PaWinWaveFormat;
/*
WAVEFORMATEXTENSIBLE fields:
union {
WORD wValidBitsPerSample;
WORD wSamplesPerBlock;
WORD wReserved;
} Samples;
DWORD dwChannelMask;
GUID SubFormat;
*/
#define PAWIN_INDEXOF_WVALIDBITSPERSAMPLE (PAWIN_SIZEOF_WAVEFORMATEX+0)
#define PAWIN_INDEXOF_DWCHANNELMASK (PAWIN_SIZEOF_WAVEFORMATEX+2)
#define PAWIN_INDEXOF_SUBFORMAT (PAWIN_SIZEOF_WAVEFORMATEX+6)
/*
Valid values to pass for the waveFormatTag PaWin_InitializeWaveFormatEx and
PaWin_InitializeWaveFormatExtensible functions below. These must match
the standard Windows WAVE_FORMAT_* values.
*/
#define PAWIN_WAVE_FORMAT_PCM (1)
#define PAWIN_WAVE_FORMAT_IEEE_FLOAT (3)
#define PAWIN_WAVE_FORMAT_DOLBY_AC3_SPDIF (0x0092)
#define PAWIN_WAVE_FORMAT_WMA_SPDIF (0x0164)
/*
returns PAWIN_WAVE_FORMAT_PCM or PAWIN_WAVE_FORMAT_IEEE_FLOAT
depending on the sampleFormat parameter.
*/
int PaWin_SampleFormatToLinearWaveFormatTag( PaSampleFormat sampleFormat );
/*
Use the following two functions to initialize the waveformat structure.
*/
void PaWin_InitializeWaveFormatEx( PaWinWaveFormat *waveFormat,
int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double sampleRate );
void PaWin_InitializeWaveFormatExtensible( PaWinWaveFormat *waveFormat,
int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double sampleRate,
PaWinWaveFormatChannelMask channelMask );
/* Map a channel count to a speaker channel mask */
PaWinWaveFormatChannelMask PaWin_DefaultChannelMask( int numChannels );
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_WIN_WAVEFORMAT_H */

View File

@ -1,137 +0,0 @@
#ifndef PA_WIN_WDMKS_H
#define PA_WIN_WDMKS_H
/*
* $Id$
* PortAudio Portable Real-Time Audio Library
* WDM/KS specific extensions
*
* Copyright (c) 1999-2007 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup public_header
@brief WDM Kernel Streaming-specific PortAudio API extension header file.
*/
#include "portaudio.h"
#include <windows.h>
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/** Flags to indicate valid fields in PaWinWDMKSInfo.
@see PaWinWDMKSInfo
@version Available as of 19.5.0.
*/
typedef enum PaWinWDMKSFlags
{
/** Makes WDMKS use the supplied latency figures instead of relying on the frame size reported
by the WaveCyclic device. Use at own risk!
*/
paWinWDMKSOverrideFramesize = (1 << 0),
/** Makes WDMKS (output stream) use the given channelMask instead of the default.
@version Available as of 19.5.0.
*/
paWinWDMKSUseGivenChannelMask = (1 << 1),
} PaWinWDMKSFlags;
typedef struct PaWinWDMKSInfo{
unsigned long size; /**< sizeof(PaWinWDMKSInfo) */
PaHostApiTypeId hostApiType; /**< paWDMKS */
unsigned long version; /**< 1 */
/** Flags indicate which fields are valid.
@see PaWinWDMKSFlags
@version Available as of 19.5.0.
*/
unsigned long flags;
/** The number of packets to use for WaveCyclic devices, range is [2, 8]. Set to zero for default value of 2. */
unsigned noOfPackets;
/** If paWinWDMKSUseGivenChannelMask bit is set in flags, use this as channelMask instead of default.
@see PaWinWDMKSFlags
@version Available as of 19.5.0.
*/
unsigned channelMask;
} PaWinWDMKSInfo;
typedef enum PaWDMKSType
{
Type_kNotUsed,
Type_kWaveCyclic,
Type_kWaveRT,
Type_kCnt,
} PaWDMKSType;
typedef enum PaWDMKSSubType
{
SubType_kUnknown,
SubType_kNotification,
SubType_kPolled,
SubType_kCnt,
} PaWDMKSSubType;
typedef struct PaWinWDMKSDeviceInfo {
wchar_t filterPath[MAX_PATH]; /**< KS filter path in Unicode! */
wchar_t topologyPath[MAX_PATH]; /**< Topology filter path in Unicode! */
PaWDMKSType streamingType;
GUID deviceProductGuid; /**< The product GUID of the device (if supported) */
} PaWinWDMKSDeviceInfo;
typedef struct PaWDMKSDirectionSpecificStreamInfo
{
PaDeviceIndex device;
unsigned channels; /**< No of channels the device is opened with */
unsigned framesPerHostBuffer; /**< No of frames of the device buffer */
int endpointPinId; /**< Endpoint pin ID (on topology filter if topologyName is not empty) */
int muxNodeId; /**< Only valid for input */
PaWDMKSSubType streamingSubType; /**< Not known until device is opened for streaming */
} PaWDMKSDirectionSpecificStreamInfo;
typedef struct PaWDMKSSpecificStreamInfo {
PaWDMKSDirectionSpecificStreamInfo input;
PaWDMKSDirectionSpecificStreamInfo output;
} PaWDMKSSpecificStreamInfo;
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_WIN_DS_H */

View File

@ -1,185 +0,0 @@
#ifndef PA_WIN_WMME_H
#define PA_WIN_WMME_H
/*
* $Id$
* PortAudio Portable Real-Time Audio Library
* MME specific extensions
*
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup public_header
@brief WMME-specific PortAudio API extension header file.
*/
#include "portaudio.h"
#include "pa_win_waveformat.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/* The following are flags which can be set in
PaWinMmeStreamInfo's flags field.
*/
#define paWinMmeUseLowLevelLatencyParameters (0x01)
#define paWinMmeUseMultipleDevices (0x02) /* use mme specific multiple device feature */
#define paWinMmeUseChannelMask (0x04)
/* By default, the mme implementation drops the processing thread's priority
to THREAD_PRIORITY_NORMAL and sleeps the thread if the CPU load exceeds 100%
This flag disables any priority throttling. The processing thread will always
run at THREAD_PRIORITY_TIME_CRITICAL.
*/
#define paWinMmeDontThrottleOverloadedProcessingThread (0x08)
/* Flags for non-PCM spdif passthrough.
*/
#define paWinMmeWaveFormatDolbyAc3Spdif (0x10)
#define paWinMmeWaveFormatWmaSpdif (0x20)
typedef struct PaWinMmeDeviceAndChannelCount{
PaDeviceIndex device;
int channelCount;
}PaWinMmeDeviceAndChannelCount;
typedef struct PaWinMmeStreamInfo{
unsigned long size; /**< sizeof(PaWinMmeStreamInfo) */
PaHostApiTypeId hostApiType; /**< paMME */
unsigned long version; /**< 1 */
unsigned long flags;
/* low-level latency setting support
These settings control the number and size of host buffers in order
to set latency. They will be used instead of the generic parameters
to Pa_OpenStream() if flags contains the PaWinMmeUseLowLevelLatencyParameters
flag.
If PaWinMmeStreamInfo structures with PaWinMmeUseLowLevelLatencyParameters
are supplied for both input and output in a full duplex stream, then the
input and output framesPerBuffer must be the same, or the larger of the
two must be a multiple of the smaller, otherwise a
paIncompatibleHostApiSpecificStreamInfo error will be returned from
Pa_OpenStream().
*/
unsigned long framesPerBuffer;
unsigned long bufferCount; /* formerly numBuffers */
/* multiple devices per direction support
If flags contains the PaWinMmeUseMultipleDevices flag,
this functionality will be used, otherwise the device parameter to
Pa_OpenStream() will be used instead.
If devices are specified here, the corresponding device parameter
to Pa_OpenStream() should be set to paUseHostApiSpecificDeviceSpecification,
otherwise an paInvalidDevice error will result.
The total number of channels accross all specified devices
must agree with the corresponding channelCount parameter to
Pa_OpenStream() otherwise a paInvalidChannelCount error will result.
*/
PaWinMmeDeviceAndChannelCount *devices;
unsigned long deviceCount;
/*
support for WAVEFORMATEXTENSIBLE channel masks. If flags contains
paWinMmeUseChannelMask this allows you to specify which speakers
to address in a multichannel stream. Constants for channelMask
are specified in pa_win_waveformat.h
*/
PaWinWaveFormatChannelMask channelMask;
}PaWinMmeStreamInfo;
/** Retrieve the number of wave in handles used by a PortAudio WinMME stream.
Returns zero if the stream is output only.
@return A non-negative value indicating the number of wave in handles
or, a PaErrorCode (which are always negative) if PortAudio is not initialized
or an error is encountered.
@see PaWinMME_GetStreamInputHandle
*/
int PaWinMME_GetStreamInputHandleCount( PaStream* stream );
/** Retrieve a wave in handle used by a PortAudio WinMME stream.
@param stream The stream to query.
@param handleIndex The zero based index of the wave in handle to retrieve. This
should be in the range [0, PaWinMME_GetStreamInputHandleCount(stream)-1].
@return A valid wave in handle, or NULL if an error occurred.
@see PaWinMME_GetStreamInputHandle
*/
HWAVEIN PaWinMME_GetStreamInputHandle( PaStream* stream, int handleIndex );
/** Retrieve the number of wave out handles used by a PortAudio WinMME stream.
Returns zero if the stream is input only.
@return A non-negative value indicating the number of wave out handles
or, a PaErrorCode (which are always negative) if PortAudio is not initialized
or an error is encountered.
@see PaWinMME_GetStreamOutputHandle
*/
int PaWinMME_GetStreamOutputHandleCount( PaStream* stream );
/** Retrieve a wave out handle used by a PortAudio WinMME stream.
@param stream The stream to query.
@param handleIndex The zero based index of the wave out handle to retrieve.
This should be in the range [0, PaWinMME_GetStreamOutputHandleCount(stream)-1].
@return A valid wave out handle, or NULL if an error occurred.
@see PaWinMME_GetStreamOutputHandleCount
*/
HWAVEOUT PaWinMME_GetStreamOutputHandle( PaStream* stream, int handleIndex );
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_WIN_WMME_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,220 +0,0 @@
import os.path, copy, sys
def checkSymbol(conf, header, library=None, symbol=None, autoAdd=True, critical=False, pkgName=None):
""" Check for symbol in library, optionally look only for header.
@param conf: Configure instance.
@param header: The header file where the symbol is declared.
@param library: The library in which the symbol exists, if None it is taken to be the standard C library.
@param symbol: The symbol to look for, if None only the header will be looked up.
@param autoAdd: Automatically link with this library if check is positive.
@param critical: Raise on error?
@param pkgName: Optional name of pkg-config entry for library, to determine build parameters.
@return: True/False
"""
origEnv = conf.env.Copy() # Copy unmodified environment so we can restore it upon error
env = conf.env
if library is None:
library = "c" # Standard library
autoAdd = False
if pkgName is not None:
origLibs = copy.copy(env.get("LIBS", None))
try: env.ParseConfig("pkg-config --silence-errors %s --cflags --libs" % pkgName)
except: pass
else:
# I see no other way of checking that the parsing succeeded, if it did add no more linking parameters
if env.get("LIBS", None) != origLibs:
autoAdd = False
try:
if not conf.CheckCHeader(header, include_quotes="<>"):
raise ConfigurationError("missing header %s" % header)
if symbol is not None and not conf.CheckLib(library, symbol, language="C", autoadd=autoAdd):
raise ConfigurationError("missing symbol %s in library %s" % (symbol, library))
except ConfigurationError:
conf.env = origEnv
if not critical:
return False
raise
return True
import SCons.Errors
# Import common variables
# Could use '#' to refer to top-level SConstruct directory, but looks like env.SConsignFile doesn't interpret this at least :(
sconsDir = os.path.abspath(os.path.join("build", "scons"))
try:
Import("Platform", "Posix", "ConfigurationError", "ApiVer")
except SCons.Errors.UserError:
# The common objects must be exported first
SConscript(os.path.join(sconsDir, "SConscript_common"))
Import("Platform", "Posix", "ConfigurationError", "ApiVer")
Import("env")
# This will be manipulated
env = env.Copy()
# We operate with a set of needed libraries and optional libraries, the latter stemming from host API implementations.
# For libraries of both types we record a set of values that is used to look for the library in question, during
# configuration. If the corresponding library for a host API implementation isn't found, the implementation is left out.
neededLibs = []
optionalImpls = {}
if Platform in Posix:
env.Append(CPPPATH=os.path.join("os", "unix"))
neededLibs += [("pthread", "pthread.h", "pthread_create"), ("m", "math.h", "sin")]
if env["useALSA"]:
optionalImpls["ALSA"] = ("asound", "alsa/asoundlib.h", "snd_pcm_open")
if env["useJACK"]:
optionalImpls["JACK"] = ("jack", "jack/jack.h", "jack_client_new")
if env["useOSS"]:
# TODO: It looks like the prefix for soundcard.h depends on the platform
optionalImpls["OSS"] = ("oss", "sys/soundcard.h", None)
if Platform == 'netbsd':
optionalImpls["OSS"] = ("ossaudio", "sys/soundcard.h", "_oss_ioctl")
if env["useASIHPI"]:
optionalImpls["ASIHPI"] = ("hpi", "asihpi/hpi.h", "HPI_SubSysCreate")
if env["useCOREAUDIO"]:
optionalImpls["COREAUDIO"] = ("CoreAudio", "CoreAudio/CoreAudio.h", None)
else:
raise ConfigurationError("unknown platform %s" % Platform)
if Platform == "darwin":
env.Append(LINKFLAGS="-framework CoreFoundation -framework CoreServices -framework CoreAudio -framework AudioToolBox -framework AudioUnit")
elif Platform == "cygwin":
env.Append(LIBS=["winmm"])
elif Platform == "irix":
neededLibs += [("audio", "dmedia/audio.h", "alOpenPort"), ("dmedia", "dmedia/dmedia.h", "dmGetUST")]
env.Append(CPPDEFINES=["PA_USE_SGI"])
def CheckCTypeSize(context, tp):
""" Check size of C type.
@param context: A configuration context.
@param tp: The type to check.
@return: Size of type, in bytes.
"""
context.Message("Checking the size of C type %s..." % tp)
ret = context.TryRun("""
#include <stdio.h>
int main() {
printf("%%d", sizeof(%s));
return 0;
}
""" % tp, ".c")
if not ret[0]:
context.Result(" Couldn't obtain size of type %s!" % tp)
return None
assert ret[1]
sz = int(ret[1])
context.Result("%d" % sz)
return sz
"""
if sys.byteorder == "little":
env.Append(CPPDEFINES=["PA_LITTLE_ENDIAN"])
elif sys.byteorder == "big":
env.Append(CPPDEFINES=["PA_BIG_ENDIAN"])
else:
raise ConfigurationError("unknown byte order: %s" % sys.byteorder)
"""
if env["enableDebugOutput"]:
env.Append(CPPDEFINES=["PA_ENABLE_DEBUG_OUTPUT"])
# Start configuration
# Use an absolute path for conf_dir, otherwise it gets created both relative to current directory and build directory
conf = env.Configure(log_file=os.path.join(sconsDir, "sconf.log"), custom_tests={"CheckCTypeSize": CheckCTypeSize},
conf_dir=os.path.join(sconsDir, ".sconf_temp"))
conf.env.Append(CPPDEFINES=["SIZEOF_SHORT=%d" % conf.CheckCTypeSize("short")])
conf.env.Append(CPPDEFINES=["SIZEOF_INT=%d" % conf.CheckCTypeSize("int")])
conf.env.Append(CPPDEFINES=["SIZEOF_LONG=%d" % conf.CheckCTypeSize("long")])
if checkSymbol(conf, "time.h", "rt", "clock_gettime"):
conf.env.Append(CPPDEFINES=["HAVE_CLOCK_GETTIME"])
if checkSymbol(conf, "time.h", symbol="nanosleep"):
conf.env.Append(CPPDEFINES=["HAVE_NANOSLEEP"])
if conf.CheckCHeader("sys/soundcard.h"):
conf.env.Append(CPPDEFINES=["HAVE_SYS_SOUNDCARD_H"])
if conf.CheckCHeader("linux/soundcard.h"):
conf.env.Append(CPPDEFINES=["HAVE_LINUX_SOUNDCARD_H"])
if conf.CheckCHeader("machine/soundcard.h"):
conf.env.Append(CPPDEFINES=["HAVE_MACHINE_SOUNDCARD_H"])
# Look for needed libraries and link with them
for lib, hdr, sym in neededLibs:
checkSymbol(conf, hdr, lib, sym, critical=True)
# Look for host API libraries, if a library isn't found disable corresponding host API implementation.
for name, val in optionalImpls.items():
lib, hdr, sym = val
if checkSymbol(conf, hdr, lib, sym, critical=False, pkgName=name.lower()):
conf.env.Append(CPPDEFINES=["PA_USE_%s=1" % name.upper()])
else:
del optionalImpls[name]
# Configuration finished
env = conf.Finish()
# PA infrastructure
CommonSources = [os.path.join("common", f) for f in "pa_allocation.c pa_converters.c pa_cpuload.c pa_dither.c pa_front.c \
pa_process.c pa_stream.c pa_trace.c pa_debugprint.c pa_ringbuffer.c".split()]
CommonSources.append(os.path.join("hostapi", "skeleton", "pa_hostapi_skeleton.c"))
# Host APIs implementations
ImplSources = []
if Platform in Posix:
ImplSources += [os.path.join("os", "unix", f) for f in "pa_unix_hostapis.c pa_unix_util.c".split()]
if "ALSA" in optionalImpls:
ImplSources.append(os.path.join("hostapi", "alsa", "pa_linux_alsa.c"))
if "JACK" in optionalImpls:
ImplSources.append(os.path.join("hostapi", "jack", "pa_jack.c"))
if "OSS" in optionalImpls:
ImplSources.append(os.path.join("hostapi", "oss", "pa_unix_oss.c"))
if "ASIHPI" in optionalImpls:
ImplSources.append(os.path.join("hostapi", "asihpi", "pa_linux_asihpi.c"))
if "COREAUDIO" in optionalImpls:
ImplSources.append([os.path.join("hostapi", "coreaudio", f) for f in """
pa_mac_core.c pa_mac_core_blocking.c pa_mac_core_utilities.c
""".split()])
sources = CommonSources + ImplSources
sharedLibEnv = env.Copy()
if Platform in Posix:
# Add soname to library, this is so a reference is made to the versioned library in programs linking against libportaudio.so
if Platform != 'darwin':
sharedLibEnv.AppendUnique(SHLINKFLAGS="-Wl,-soname=libportaudio.so.%d" % int(ApiVer.split(".")[0]))
sharedLib = sharedLibEnv.SharedLibrary(target="portaudio", source=sources)
staticLib = env.StaticLibrary(target="portaudio", source=sources)
if Platform in Posix:
prefix = env["prefix"]
includeDir = os.path.join(prefix, "include")
libDir = os.path.join(prefix, "lib")
testNames = ["patest_sine", "paqa_devs", "paqa_errs", "patest1", "patest_buffer", "patest_callbackstop", "patest_clip", \
"patest_dither", "patest_hang", "patest_in_overflow", "patest_latency", "patest_leftright", "patest_longsine", \
"patest_many", "patest_maxsines", "patest_multi_sine", "patest_out_underflow", "patest_pink", "patest_prime", \
"patest_read_record", "patest_record", "patest_ringmix", "patest_saw", "patest_sine8", "patest_sine", \
"patest_sine_time", "patest_start_stop", "patest_stop", "patest_sync", "patest_toomanysines", \
"patest_underflow", "patest_wire", "patest_write_sine", "pa_devs", "pa_fuzz", "pa_minlat", \
"patest_sine_channelmaps",]
# The test directory ("bin") should be in the top-level PA directory
tests = [env.Program(target=os.path.join("#", "bin", name), source=[os.path.join("#", "test", name + ".c"),
staticLib]) for name in testNames]
# Detect host APIs
hostApis = []
for cppdef in env["CPPDEFINES"]:
if cppdef.startswith("PA_USE_"):
hostApis.append(cppdef[7:-2])
Return("sources", "sharedLib", "staticLib", "tests", "env", "hostApis")

View File

@ -1,243 +0,0 @@
/*
* $Id$
* Portable Audio I/O Library allocation group implementation
* memory allocation group for tracking allocation groups
*
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 1999-2002 Ross Bencina, Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup common_src
@brief Allocation Group implementation.
*/
#include "pa_allocation.h"
#include "pa_util.h"
/*
Maintain 3 singly linked lists...
linkBlocks: the buffers used to allocate the links
spareLinks: links available for use in the allocations list
allocations: the buffers currently allocated using PaUtil_ContextAllocateMemory()
Link block size is doubled every time new links are allocated.
*/
#define PA_INITIAL_LINK_COUNT_ 16
struct PaUtilAllocationGroupLink
{
struct PaUtilAllocationGroupLink *next;
void *buffer;
};
/*
Allocate a block of links. The first link will have it's buffer member
pointing to the block, and it's next member set to <nextBlock>. The remaining
links will have NULL buffer members, and each link will point to
the next link except the last, which will point to <nextSpare>
*/
static struct PaUtilAllocationGroupLink *AllocateLinks( long count,
struct PaUtilAllocationGroupLink *nextBlock,
struct PaUtilAllocationGroupLink *nextSpare )
{
struct PaUtilAllocationGroupLink *result;
int i;
result = (struct PaUtilAllocationGroupLink *)PaUtil_AllocateMemory(
sizeof(struct PaUtilAllocationGroupLink) * count );
if( result )
{
/* the block link */
result[0].buffer = result;
result[0].next = nextBlock;
/* the spare links */
for( i=1; i<count; ++i )
{
result[i].buffer = 0;
result[i].next = &result[i+1];
}
result[count-1].next = nextSpare;
}
return result;
}
PaUtilAllocationGroup* PaUtil_CreateAllocationGroup( void )
{
PaUtilAllocationGroup* result = 0;
struct PaUtilAllocationGroupLink *links;
links = AllocateLinks( PA_INITIAL_LINK_COUNT_, 0, 0 );
if( links != 0 )
{
result = (PaUtilAllocationGroup*)PaUtil_AllocateMemory( sizeof(PaUtilAllocationGroup) );
if( result )
{
result->linkCount = PA_INITIAL_LINK_COUNT_;
result->linkBlocks = &links[0];
result->spareLinks = &links[1];
result->allocations = 0;
}
else
{
PaUtil_FreeMemory( links );
}
}
return result;
}
void PaUtil_DestroyAllocationGroup( PaUtilAllocationGroup* group )
{
struct PaUtilAllocationGroupLink *current = group->linkBlocks;
struct PaUtilAllocationGroupLink *next;
while( current )
{
next = current->next;
PaUtil_FreeMemory( current->buffer );
current = next;
}
PaUtil_FreeMemory( group );
}
void* PaUtil_GroupAllocateMemory( PaUtilAllocationGroup* group, long size )
{
struct PaUtilAllocationGroupLink *links, *link;
void *result = 0;
/* allocate more links if necessary */
if( !group->spareLinks )
{
/* double the link count on each block allocation */
links = AllocateLinks( group->linkCount, group->linkBlocks, group->spareLinks );
if( links )
{
group->linkCount += group->linkCount;
group->linkBlocks = &links[0];
group->spareLinks = &links[1];
}
}
if( group->spareLinks )
{
result = PaUtil_AllocateMemory( size );
if( result )
{
link = group->spareLinks;
group->spareLinks = link->next;
link->buffer = result;
link->next = group->allocations;
group->allocations = link;
}
}
return result;
}
void PaUtil_GroupFreeMemory( PaUtilAllocationGroup* group, void *buffer )
{
struct PaUtilAllocationGroupLink *current = group->allocations;
struct PaUtilAllocationGroupLink *previous = 0;
if( buffer == 0 )
return;
/* find the right link and remove it */
while( current )
{
if( current->buffer == buffer )
{
if( previous )
{
previous->next = current->next;
}
else
{
group->allocations = current->next;
}
current->buffer = 0;
current->next = group->spareLinks;
group->spareLinks = current;
break;
}
previous = current;
current = current->next;
}
PaUtil_FreeMemory( buffer ); /* free the memory whether we found it in the list or not */
}
void PaUtil_FreeAllAllocations( PaUtilAllocationGroup* group )
{
struct PaUtilAllocationGroupLink *current = group->allocations;
struct PaUtilAllocationGroupLink *previous = 0;
/* free all buffers in the allocations list */
while( current )
{
PaUtil_FreeMemory( current->buffer );
current->buffer = 0;
previous = current;
current = current->next;
}
/* link the former allocations list onto the front of the spareLinks list */
if( previous )
{
previous->next = group->spareLinks;
group->spareLinks = group->allocations;
group->allocations = 0;
}
}

View File

@ -1,104 +0,0 @@
#ifndef PA_ALLOCATION_H
#define PA_ALLOCATION_H
/*
* $Id$
* Portable Audio I/O Library allocation context header
* memory allocation context for tracking allocation groups
*
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 1999-2008 Ross Bencina, Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup common_src
@brief Allocation Group prototypes. An Allocation Group makes it easy to
allocate multiple blocks of memory and free them all at once.
An allocation group is useful for keeping track of multiple blocks
of memory which are allocated at the same time (such as during initialization)
and need to be deallocated at the same time. The allocation group maintains
a list of allocated blocks, and can free all allocations at once. This
can be usefull for cleaning up after a partially initialized object fails.
The allocation group implementation is built on top of the lower
level allocation functions defined in pa_util.h
*/
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
typedef struct
{
long linkCount;
struct PaUtilAllocationGroupLink *linkBlocks;
struct PaUtilAllocationGroupLink *spareLinks;
struct PaUtilAllocationGroupLink *allocations;
}PaUtilAllocationGroup;
/** Create an allocation group.
*/
PaUtilAllocationGroup* PaUtil_CreateAllocationGroup( void );
/** Destroy an allocation group, but not the memory allocated through the group.
*/
void PaUtil_DestroyAllocationGroup( PaUtilAllocationGroup* group );
/** Allocate a block of memory though an allocation group.
*/
void* PaUtil_GroupAllocateMemory( PaUtilAllocationGroup* group, long size );
/** Free a block of memory that was previously allocated though an allocation
group. Calling this function is a relatively time consuming operation.
Under normal circumstances clients should call PaUtil_FreeAllAllocations to
free all allocated blocks simultaneously.
@see PaUtil_FreeAllAllocations
*/
void PaUtil_GroupFreeMemory( PaUtilAllocationGroup* group, void *buffer );
/** Free all blocks of memory which have been allocated through the allocation
group. This function doesn't destroy the group itself.
*/
void PaUtil_FreeAllAllocations( PaUtilAllocationGroup* group );
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_ALLOCATION_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,263 +0,0 @@
#ifndef PA_CONVERTERS_H
#define PA_CONVERTERS_H
/*
* $Id$
* Portable Audio I/O Library sample conversion mechanism
*
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 1999-2002 Phil Burk, Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup common_src
@brief Conversion functions used to convert buffers of samples from one
format to another.
*/
#include "portaudio.h" /* for PaSampleFormat */
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
struct PaUtilTriangularDitherGenerator;
/** Choose an available sample format which is most appropriate for
representing the requested format. If the requested format is not available
higher quality formats are considered before lower quality formates.
@param availableFormats A variable containing the logical OR of all available
formats.
@param format The desired format.
@return The most appropriate available format for representing the requested
format.
*/
PaSampleFormat PaUtil_SelectClosestAvailableFormat(
PaSampleFormat availableFormats, PaSampleFormat format );
/* high level conversions functions for use by implementations */
/** The generic sample converter prototype. Sample converters convert count
samples from sourceBuffer to destinationBuffer. The actual type of the data
pointed to by these parameters varys for different converter functions.
@param destinationBuffer A pointer to the first sample of the destination.
@param destinationStride An offset between successive destination samples
expressed in samples (not bytes.) It may be negative.
@param sourceBuffer A pointer to the first sample of the source.
@param sourceStride An offset between successive source samples
expressed in samples (not bytes.) It may be negative.
@param count The number of samples to convert.
@param ditherState State information used to calculate dither. Converters
that do not perform dithering will ignore this parameter, in which case
NULL or invalid dither state may be passed.
*/
typedef void PaUtilConverter(
void *destinationBuffer, signed int destinationStride,
void *sourceBuffer, signed int sourceStride,
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator );
/** Find a sample converter function for the given source and destinations
formats and flags (clip and dither.)
@return
A pointer to a PaUtilConverter which will perform the requested
conversion, or NULL if the given format conversion is not supported.
For conversions where clipping or dithering is not necessary, the
clip and dither flags are ignored and a non-clipping or dithering
version is returned.
If the source and destination formats are the same, a function which
copies data of the appropriate size will be returned.
*/
PaUtilConverter* PaUtil_SelectConverter( PaSampleFormat sourceFormat,
PaSampleFormat destinationFormat, PaStreamFlags flags );
/** The generic buffer zeroer prototype. Buffer zeroers copy count zeros to
destinationBuffer. The actual type of the data pointed to varys for
different zeroer functions.
@param destinationBuffer A pointer to the first sample of the destination.
@param destinationStride An offset between successive destination samples
expressed in samples (not bytes.) It may be negative.
@param count The number of samples to zero.
*/
typedef void PaUtilZeroer(
void *destinationBuffer, signed int destinationStride, unsigned int count );
/** Find a buffer zeroer function for the given destination format.
@return
A pointer to a PaUtilZeroer which will perform the requested
zeroing.
*/
PaUtilZeroer* PaUtil_SelectZeroer( PaSampleFormat destinationFormat );
/*----------------------------------------------------------------------------*/
/* low level functions and data structures which may be used for
substituting conversion functions */
/** The type used to store all sample conversion functions.
@see paConverters;
*/
typedef struct{
PaUtilConverter *Float32_To_Int32;
PaUtilConverter *Float32_To_Int32_Dither;
PaUtilConverter *Float32_To_Int32_Clip;
PaUtilConverter *Float32_To_Int32_DitherClip;
PaUtilConverter *Float32_To_Int24;
PaUtilConverter *Float32_To_Int24_Dither;
PaUtilConverter *Float32_To_Int24_Clip;
PaUtilConverter *Float32_To_Int24_DitherClip;
PaUtilConverter *Float32_To_Int16;
PaUtilConverter *Float32_To_Int16_Dither;
PaUtilConverter *Float32_To_Int16_Clip;
PaUtilConverter *Float32_To_Int16_DitherClip;
PaUtilConverter *Float32_To_Int8;
PaUtilConverter *Float32_To_Int8_Dither;
PaUtilConverter *Float32_To_Int8_Clip;
PaUtilConverter *Float32_To_Int8_DitherClip;
PaUtilConverter *Float32_To_UInt8;
PaUtilConverter *Float32_To_UInt8_Dither;
PaUtilConverter *Float32_To_UInt8_Clip;
PaUtilConverter *Float32_To_UInt8_DitherClip;
PaUtilConverter *Int32_To_Float32;
PaUtilConverter *Int32_To_Int24;
PaUtilConverter *Int32_To_Int24_Dither;
PaUtilConverter *Int32_To_Int16;
PaUtilConverter *Int32_To_Int16_Dither;
PaUtilConverter *Int32_To_Int8;
PaUtilConverter *Int32_To_Int8_Dither;
PaUtilConverter *Int32_To_UInt8;
PaUtilConverter *Int32_To_UInt8_Dither;
PaUtilConverter *Int24_To_Float32;
PaUtilConverter *Int24_To_Int32;
PaUtilConverter *Int24_To_Int16;
PaUtilConverter *Int24_To_Int16_Dither;
PaUtilConverter *Int24_To_Int8;
PaUtilConverter *Int24_To_Int8_Dither;
PaUtilConverter *Int24_To_UInt8;
PaUtilConverter *Int24_To_UInt8_Dither;
PaUtilConverter *Int16_To_Float32;
PaUtilConverter *Int16_To_Int32;
PaUtilConverter *Int16_To_Int24;
PaUtilConverter *Int16_To_Int8;
PaUtilConverter *Int16_To_Int8_Dither;
PaUtilConverter *Int16_To_UInt8;
PaUtilConverter *Int16_To_UInt8_Dither;
PaUtilConverter *Int8_To_Float32;
PaUtilConverter *Int8_To_Int32;
PaUtilConverter *Int8_To_Int24;
PaUtilConverter *Int8_To_Int16;
PaUtilConverter *Int8_To_UInt8;
PaUtilConverter *UInt8_To_Float32;
PaUtilConverter *UInt8_To_Int32;
PaUtilConverter *UInt8_To_Int24;
PaUtilConverter *UInt8_To_Int16;
PaUtilConverter *UInt8_To_Int8;
PaUtilConverter *Copy_8_To_8; /* copy without any conversion */
PaUtilConverter *Copy_16_To_16; /* copy without any conversion */
PaUtilConverter *Copy_24_To_24; /* copy without any conversion */
PaUtilConverter *Copy_32_To_32; /* copy without any conversion */
} PaUtilConverterTable;
/** A table of pointers to all required converter functions.
PaUtil_SelectConverter() uses this table to lookup the appropriate
conversion functions. The fields of this structure are initialized
with default conversion functions. Fields may be NULL, indicating that
no conversion function is available. User code may substitue optimised
conversion functions by assigning different function pointers to
these fields.
@note
If the PA_NO_STANDARD_CONVERTERS preprocessor variable is defined,
PortAudio's standard converters will not be compiled, and all fields
of this structure will be initialized to NULL. In such cases, users
should supply their own conversion functions if the require PortAudio
to open a stream that requires sample conversion.
@see PaUtilConverterTable, PaUtilConverter, PaUtil_SelectConverter
*/
extern PaUtilConverterTable paConverters;
/** The type used to store all buffer zeroing functions.
@see paZeroers;
*/
typedef struct{
PaUtilZeroer *ZeroU8; /* unsigned 8 bit, zero == 128 */
PaUtilZeroer *Zero8;
PaUtilZeroer *Zero16;
PaUtilZeroer *Zero24;
PaUtilZeroer *Zero32;
} PaUtilZeroerTable;
/** A table of pointers to all required zeroer functions.
PaUtil_SelectZeroer() uses this table to lookup the appropriate
conversion functions. The fields of this structure are initialized
with default conversion functions. User code may substitue optimised
conversion functions by assigning different function pointers to
these fields.
@note
If the PA_NO_STANDARD_ZEROERS preprocessor variable is defined,
PortAudio's standard zeroers will not be compiled, and all fields
of this structure will be initialized to NULL. In such cases, users
should supply their own zeroing functions for the sample sizes which
they intend to use.
@see PaUtilZeroerTable, PaUtilZeroer, PaUtil_SelectZeroer
*/
extern PaUtilZeroerTable paZeroers;
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_CONVERTERS_H */

View File

@ -1,105 +0,0 @@
/*
* $Id$
* Portable Audio I/O Library CPU Load measurement functions
* Portable CPU load measurement facility.
*
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 2002 Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup common_src
@brief Functions to assist in measuring the CPU utilization of a callback
stream. Used to implement the Pa_GetStreamCpuLoad() function.
@todo Dynamically calculate the coefficients used to smooth the CPU Load
Measurements over time to provide a uniform characterisation of CPU Load
independent of rate at which PaUtil_BeginCpuLoadMeasurement /
PaUtil_EndCpuLoadMeasurement are called. see http://www.portaudio.com/trac/ticket/113
*/
#include "pa_cpuload.h"
#include <assert.h>
#include "pa_util.h" /* for PaUtil_GetTime() */
void PaUtil_InitializeCpuLoadMeasurer( PaUtilCpuLoadMeasurer* measurer, double sampleRate )
{
assert( sampleRate > 0 );
measurer->samplingPeriod = 1. / sampleRate;
measurer->averageLoad = 0.;
}
void PaUtil_ResetCpuLoadMeasurer( PaUtilCpuLoadMeasurer* measurer )
{
measurer->averageLoad = 0.;
}
void PaUtil_BeginCpuLoadMeasurement( PaUtilCpuLoadMeasurer* measurer )
{
measurer->measurementStartTime = PaUtil_GetTime();
}
void PaUtil_EndCpuLoadMeasurement( PaUtilCpuLoadMeasurer* measurer, unsigned long framesProcessed )
{
double measurementEndTime, secondsFor100Percent, measuredLoad;
if( framesProcessed > 0 ){
measurementEndTime = PaUtil_GetTime();
assert( framesProcessed > 0 );
secondsFor100Percent = framesProcessed * measurer->samplingPeriod;
measuredLoad = (measurementEndTime - measurer->measurementStartTime) / secondsFor100Percent;
/* Low pass filter the calculated CPU load to reduce jitter using a simple IIR low pass filter. */
/** FIXME @todo these coefficients shouldn't be hardwired see: http://www.portaudio.com/trac/ticket/113 */
#define LOWPASS_COEFFICIENT_0 (0.9)
#define LOWPASS_COEFFICIENT_1 (0.99999 - LOWPASS_COEFFICIENT_0)
measurer->averageLoad = (LOWPASS_COEFFICIENT_0 * measurer->averageLoad) +
(LOWPASS_COEFFICIENT_1 * measuredLoad);
}
}
double PaUtil_GetCpuLoad( PaUtilCpuLoadMeasurer* measurer )
{
return measurer->averageLoad;
}

View File

@ -1,72 +0,0 @@
#ifndef PA_CPULOAD_H
#define PA_CPULOAD_H
/*
* $Id$
* Portable Audio I/O Library CPU Load measurement functions
* Portable CPU load measurement facility.
*
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 2002 Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup common_src
@brief Functions to assist in measuring the CPU utilization of a callback
stream. Used to implement the Pa_GetStreamCpuLoad() function.
*/
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
typedef struct {
double samplingPeriod;
double measurementStartTime;
double averageLoad;
} PaUtilCpuLoadMeasurer; /**< @todo need better name than measurer */
void PaUtil_InitializeCpuLoadMeasurer( PaUtilCpuLoadMeasurer* measurer, double sampleRate );
void PaUtil_BeginCpuLoadMeasurement( PaUtilCpuLoadMeasurer* measurer );
void PaUtil_EndCpuLoadMeasurement( PaUtilCpuLoadMeasurer* measurer, unsigned long framesProcessed );
void PaUtil_ResetCpuLoadMeasurer( PaUtilCpuLoadMeasurer* measurer );
double PaUtil_GetCpuLoad( PaUtilCpuLoadMeasurer* measurer );
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_CPULOAD_H */

View File

@ -1,123 +0,0 @@
/*
* $Id: pa_log.c $
* Portable Audio I/O Library Multi-Host API front end
* Validate function parameters and manage multiple host APIs.
*
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 1999-2006 Ross Bencina, Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup common_src
@brief Implements log function.
PaUtil_SetLogPrintFunction can be user called to replace the provided
DefaultLogPrint function, which writes to stderr.
One can NOT pass var_args across compiler/dll boundaries as it is not
"byte code/abi portable". So the technique used here is to allocate a local
a static array, write in it, then callback the user with a pointer to its
start.
*/
#include <stdio.h>
#include <stdarg.h>
#include "pa_debugprint.h"
// for OutputDebugStringA
#if defined(_MSC_VER) && defined(PA_ENABLE_MSVC_DEBUG_OUTPUT)
#define WIN32_LEAN_AND_MEAN // exclude rare headers
#include "windows.h"
#endif
// User callback
static PaUtilLogCallback userCB = NULL;
// Sets user callback
void PaUtil_SetDebugPrintFunction(PaUtilLogCallback cb)
{
userCB = cb;
}
/*
If your platform doesnt have vsnprintf, you are stuck with a
VERY dangerous alternative, vsprintf (with no n)
*/
#if _MSC_VER
/* Some Windows Mobile SDKs don't define vsnprintf but all define _vsnprintf (hopefully).
According to MSDN "vsnprintf is identical to _vsnprintf". So we use _vsnprintf with MSC.
*/
#define VSNPRINTF _vsnprintf
#else
#define VSNPRINTF vsnprintf
#endif
#define PA_LOG_BUF_SIZE 2048
void PaUtil_DebugPrint( const char *format, ... )
{
// Optional logging into Output console of Visual Studio
#if defined(_MSC_VER) && defined(PA_ENABLE_MSVC_DEBUG_OUTPUT)
{
char buf[PA_LOG_BUF_SIZE];
va_list ap;
va_start(ap, format);
VSNPRINTF(buf, sizeof(buf), format, ap);
buf[sizeof(buf)-1] = 0;
OutputDebugStringA(buf);
va_end(ap);
}
#endif
// Output to User-Callback
if (userCB != NULL)
{
char strdump[PA_LOG_BUF_SIZE];
va_list ap;
va_start(ap, format);
VSNPRINTF(strdump, sizeof(strdump), format, ap);
strdump[sizeof(strdump)-1] = 0;
userCB(strdump);
va_end(ap);
}
else
// Standard output to stderr
{
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
fflush(stderr);
}
}

View File

@ -1,149 +0,0 @@
#ifndef PA_LOG_H
#define PA_LOG_H
/*
* Log file redirector function
* Copyright (c) 1999-2006 Ross Bencina, Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup common_src
*/
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
void PaUtil_DebugPrint( const char *format, ... );
/*
The basic format for log messages is described below. If you need to
add any log messages, please follow this format.
Function entry (void function):
"FunctionName called.\n"
Function entry (non void function):
"FunctionName called:\n"
"\tParam1Type param1: param1Value\n"
"\tParam2Type param2: param2Value\n" (etc...)
Function exit (no return value):
"FunctionName returned.\n"
Function exit (simple return value):
"FunctionName returned:\n"
"\tReturnType: returnValue\n"
If the return type is an error code, the error text is displayed in ()
If the return type is not an error code, but has taken a special value
because an error occurred, then the reason for the error is shown in []
If the return type is a struct ptr, the struct is dumped.
See the code below for examples
*/
/** PA_DEBUG() provides a simple debug message printing facility. The macro
passes it's argument to a printf-like function called PaUtil_DebugPrint()
which prints to stderr and always flushes the stream after printing.
Because preprocessor macros cannot directly accept variable length argument
lists, calls to the macro must include an additional set of parenthesis, eg:
PA_DEBUG(("errorno: %d", 1001 ));
*/
#ifdef PA_ENABLE_DEBUG_OUTPUT
#define PA_DEBUG(x) PaUtil_DebugPrint x ;
#else
#define PA_DEBUG(x)
#endif
#ifdef PA_LOG_API_CALLS
#define PA_LOGAPI(x) PaUtil_DebugPrint x
#define PA_LOGAPI_ENTER(functionName) PaUtil_DebugPrint( functionName " called.\n" )
#define PA_LOGAPI_ENTER_PARAMS(functionName) PaUtil_DebugPrint( functionName " called:\n" )
#define PA_LOGAPI_EXIT(functionName) PaUtil_DebugPrint( functionName " returned.\n" )
#define PA_LOGAPI_EXIT_PAERROR( functionName, result ) \
PaUtil_DebugPrint( functionName " returned:\n" ); \
PaUtil_DebugPrint("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) )
#define PA_LOGAPI_EXIT_T( functionName, resultFormatString, result ) \
PaUtil_DebugPrint( functionName " returned:\n" ); \
PaUtil_DebugPrint("\t" resultFormatString "\n", result )
#define PA_LOGAPI_EXIT_PAERROR_OR_T_RESULT( functionName, positiveResultFormatString, result ) \
PaUtil_DebugPrint( functionName " returned:\n" ); \
if( result > 0 ) \
PaUtil_DebugPrint("\t" positiveResultFormatString "\n", result ); \
else \
PaUtil_DebugPrint("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) )
#else
#define PA_LOGAPI(x)
#define PA_LOGAPI_ENTER(functionName)
#define PA_LOGAPI_ENTER_PARAMS(functionName)
#define PA_LOGAPI_EXIT(functionName)
#define PA_LOGAPI_EXIT_PAERROR( functionName, result )
#define PA_LOGAPI_EXIT_T( functionName, resultFormatString, result )
#define PA_LOGAPI_EXIT_PAERROR_OR_T_RESULT( functionName, positiveResultFormatString, result )
#endif
typedef void (*PaUtilLogCallback ) (const char *log);
/**
Install user provided log function
*/
void PaUtil_SetDebugPrintFunction(PaUtilLogCallback cb);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_LOG_H */

View File

@ -1,218 +0,0 @@
/*
* $Id$
* Portable Audio I/O Library triangular dither generator
*
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 1999-2002 Phil Burk, Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup common_src
@brief Functions for generating dither noise
*/
#include "pa_types.h"
#include "pa_dither.h"
/* Note that the linear congruential algorithm requires 32 bit integers
* because it uses arithmetic overflow. So use PaUint32 instead of
* unsigned long so it will work on 64 bit systems.
*/
#define PA_DITHER_BITS_ (15)
void PaUtil_InitializeTriangularDitherState( PaUtilTriangularDitherGenerator *state )
{
state->previous = 0;
state->randSeed1 = 22222;
state->randSeed2 = 5555555;
}
PaInt32 PaUtil_Generate16BitTriangularDither( PaUtilTriangularDitherGenerator *state )
{
PaInt32 current, highPass;
/* Generate two random numbers. */
state->randSeed1 = (state->randSeed1 * 196314165) + 907633515;
state->randSeed2 = (state->randSeed2 * 196314165) + 907633515;
/* Generate triangular distribution about 0.
* Shift before adding to prevent overflow which would skew the distribution.
* Also shift an extra bit for the high pass filter.
*/
#define DITHER_SHIFT_ ((sizeof(PaInt32)*8 - PA_DITHER_BITS_) + 1)
current = (((PaInt32)state->randSeed1)>>DITHER_SHIFT_) +
(((PaInt32)state->randSeed2)>>DITHER_SHIFT_);
/* High pass filter to reduce audibility. */
highPass = current - state->previous;
state->previous = current;
return highPass;
}
/* Multiply by PA_FLOAT_DITHER_SCALE_ to get a float between -2.0 and +1.99999 */
#define PA_FLOAT_DITHER_SCALE_ (1.0f / ((1<<PA_DITHER_BITS_)-1))
static const float const_float_dither_scale_ = PA_FLOAT_DITHER_SCALE_;
float PaUtil_GenerateFloatTriangularDither( PaUtilTriangularDitherGenerator *state )
{
PaInt32 current, highPass;
/* Generate two random numbers. */
state->randSeed1 = (state->randSeed1 * 196314165) + 907633515;
state->randSeed2 = (state->randSeed2 * 196314165) + 907633515;
/* Generate triangular distribution about 0.
* Shift before adding to prevent overflow which would skew the distribution.
* Also shift an extra bit for the high pass filter.
*/
current = (((PaInt32)state->randSeed1)>>DITHER_SHIFT_) +
(((PaInt32)state->randSeed2)>>DITHER_SHIFT_);
/* High pass filter to reduce audibility. */
highPass = current - state->previous;
state->previous = current;
return ((float)highPass) * const_float_dither_scale_;
}
/*
The following alternate dither algorithms (from musicdsp.org) could be
considered
*/
/*Noise shaped dither (March 2000)
-------------------
This is a simple implementation of highpass triangular-PDF dither with
2nd-order noise shaping, for use when truncating floating point audio
data to fixed point.
The noise shaping lowers the noise floor by 11dB below 5kHz (@ 44100Hz
sample rate) compared to triangular-PDF dither. The code below assumes
input data is in the range +1 to -1 and doesn't check for overloads!
To save time when generating dither for multiple channels you can do
things like this: r3=(r1 & 0x7F)<<8; instead of calling rand() again.
int r1, r2; //rectangular-PDF random numbers
float s1, s2; //error feedback buffers
float s = 0.5f; //set to 0.0f for no noise shaping
float w = pow(2.0,bits-1); //word length (usually bits=16)
float wi= 1.0f/w;
float d = wi / RAND_MAX; //dither amplitude (2 lsb)
float o = wi * 0.5f; //remove dc offset
float in, tmp;
int out;
//for each sample...
r2=r1; //can make HP-TRI dither by
r1=rand(); //subtracting previous rand()
in += s * (s1 + s1 - s2); //error feedback
tmp = in + o + d * (float)(r1 - r2); //dc offset and dither
out = (int)(w * tmp); //truncate downwards
if(tmp<0.0f) out--; //this is faster than floor()
s2 = s1;
s1 = in - wi * (float)out; //error
--
paul.kellett@maxim.abel.co.uk
http://www.maxim.abel.co.uk
*/
/*
16-to-8-bit first-order dither
Type : First order error feedforward dithering code
References : Posted by Jon Watte
Notes :
This is about as simple a dithering algorithm as you can implement, but it's
likely to sound better than just truncating to N bits.
Note that you might not want to carry forward the full difference for infinity.
It's probably likely that the worst performance hit comes from the saturation
conditionals, which can be avoided with appropriate instructions on many DSPs
and integer SIMD type instructions, or CMOV.
Last, if sound quality is paramount (such as when going from > 16 bits to 16
bits) you probably want to use a higher-order dither function found elsewhere
on this site.
Code :
// This code will down-convert and dither a 16-bit signed short
// mono signal into an 8-bit unsigned char signal, using a first
// order forward-feeding error term dither.
#define uchar unsigned char
void dither_one_channel_16_to_8( short * input, uchar * output, int count, int * memory )
{
int m = *memory;
while( count-- > 0 ) {
int i = *input++;
i += m;
int j = i + 32768 - 128;
uchar o;
if( j < 0 ) {
o = 0;
}
else if( j > 65535 ) {
o = 255;
}
else {
o = (uchar)((j>>8)&0xff);
}
m = ((j-32768+128)-i);
*output++ = o;
}
*memory = m;
}
*/

View File

@ -1,106 +0,0 @@
#ifndef PA_DITHER_H
#define PA_DITHER_H
/*
* $Id$
* Portable Audio I/O Library triangular dither generator
*
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 1999-2002 Phil Burk, Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup common_src
@brief Functions for generating dither noise
*/
#include "pa_types.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/* Note that the linear congruential algorithm requires 32 bit integers
* because it uses arithmetic overflow. So use PaUint32 instead of
* unsigned long so it will work on 64 bit systems.
*/
/** @brief State needed to generate a dither signal */
typedef struct PaUtilTriangularDitherGenerator{
PaUint32 previous;
PaUint32 randSeed1;
PaUint32 randSeed2;
} PaUtilTriangularDitherGenerator;
/** @brief Initialize dither state */
void PaUtil_InitializeTriangularDitherState( PaUtilTriangularDitherGenerator *ditherState );
/**
@brief Calculate 2 LSB dither signal with a triangular distribution.
Ranged for adding to a 1 bit right-shifted 32 bit integer
prior to >>15. eg:
<pre>
signed long in = *
signed long dither = PaUtil_Generate16BitTriangularDither( ditherState );
signed short out = (signed short)(((in>>1) + dither) >> 15);
</pre>
@return
A signed 32-bit integer with a range of +32767 to -32768
*/
PaInt32 PaUtil_Generate16BitTriangularDither( PaUtilTriangularDitherGenerator *ditherState );
/**
@brief Calculate 2 LSB dither signal with a triangular distribution.
Ranged for adding to a pre-scaled float.
<pre>
float in = *
float dither = PaUtil_GenerateFloatTriangularDither( ditherState );
// use smaller scaler to prevent overflow when we add the dither
signed short out = (signed short)(in*(32766.0f) + dither );
</pre>
@return
A float with a range of -2.0 to +1.99999.
*/
float PaUtil_GenerateFloatTriangularDither( PaUtilTriangularDitherGenerator *ditherState );
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_DITHER_H */

View File

@ -1,145 +0,0 @@
#ifndef PA_ENDIANNESS_H
#define PA_ENDIANNESS_H
/*
* $Id$
* Portable Audio I/O Library current platform endianness macros
*
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 1999-2002 Phil Burk, Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup common_src
@brief Configure endianness symbols for the target processor.
Arrange for either the PA_LITTLE_ENDIAN or PA_BIG_ENDIAN preprocessor symbols
to be defined. The one that is defined reflects the endianness of the target
platform and may be used to implement conditional compilation of byte-order
dependent code.
If either PA_LITTLE_ENDIAN or PA_BIG_ENDIAN is defined already, then no attempt
is made to override that setting. This may be useful if you have a better way
of determining the platform's endianness. The autoconf mechanism uses this for
example.
A PA_VALIDATE_ENDIANNESS macro is provided to compare the compile time
and runtime endiannes and raise an assertion if they don't match.
*/
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/* If this is an apple, we need to do detect endianness this way */
#if defined(__APPLE__)
/* we need to do some endian detection that is sensitive to harware arch */
#if defined(__LITTLE_ENDIAN__)
#if !defined( PA_LITTLE_ENDIAN )
#define PA_LITTLE_ENDIAN
#endif
#if defined( PA_BIG_ENDIAN )
#undef PA_BIG_ENDIAN
#endif
#else
#if !defined( PA_BIG_ENDIAN )
#define PA_BIG_ENDIAN
#endif
#if defined( PA_LITTLE_ENDIAN )
#undef PA_LITTLE_ENDIAN
#endif
#endif
#else
/* this is not an apple, so first check the existing defines, and, failing that,
detect well-known architechtures. */
#if defined(PA_LITTLE_ENDIAN) || defined(PA_BIG_ENDIAN)
/* endianness define has been set externally, such as by autoconf */
#if defined(PA_LITTLE_ENDIAN) && defined(PA_BIG_ENDIAN)
#error both PA_LITTLE_ENDIAN and PA_BIG_ENDIAN have been defined externally to pa_endianness.h - only one endianness at a time please
#endif
#else
/* endianness define has not been set externally */
/* set PA_LITTLE_ENDIAN or PA_BIG_ENDIAN by testing well known platform specific defines */
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || defined(LITTLE_ENDIAN) || defined(__i386) || defined(_M_IX86) || defined(__x86_64__)
#define PA_LITTLE_ENDIAN /* win32, assume intel byte order */
#else
#define PA_BIG_ENDIAN
#endif
#endif
#if !defined(PA_LITTLE_ENDIAN) && !defined(PA_BIG_ENDIAN)
/*
If the following error is raised, you either need to modify the code above
to automatically determine the endianness from other symbols defined on your
platform, or define either PA_LITTLE_ENDIAN or PA_BIG_ENDIAN externally.
*/
#error pa_endianness.h was unable to automatically determine the endianness of the target platform
#endif
#endif
/* PA_VALIDATE_ENDIANNESS compares the compile time and runtime endianness,
and raises an assertion if they don't match. <assert.h> must be included in
the context in which this macro is used.
*/
#if defined(NDEBUG)
#define PA_VALIDATE_ENDIANNESS
#else
#if defined(PA_LITTLE_ENDIAN)
#define PA_VALIDATE_ENDIANNESS \
{ \
const long nativeOne = 1; \
assert( "PortAudio: compile time and runtime endianness don't match" && (((char *)&nativeOne)[0]) == 1 ); \
}
#elif defined(PA_BIG_ENDIAN)
#define PA_VALIDATE_ENDIANNESS \
{ \
const long nativeOne = 1; \
assert( "PortAudio: compile time and runtime endianness don't match" && (((char *)&nativeOne)[0]) == 0 ); \
}
#endif
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_ENDIANNESS_H */

File diff suppressed because it is too large Load Diff

View File

@ -1 +0,0 @@
#define PA_GIT_REVISION 396fe4b6699ae929d3a685b3ef8a7e97396139a4

View File

@ -1,362 +0,0 @@
#ifndef PA_HOSTAPI_H
#define PA_HOSTAPI_H
/*
* $Id$
* Portable Audio I/O Library
* host api representation
*
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 1999-2008 Ross Bencina, Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup common_src
@brief Interfaces and representation structures used by pa_front.c
to manage and communicate with host API implementations.
*/
#include "portaudio.h"
/**
The PA_NO_* host API macros are now deprecated in favor of PA_USE_* macros.
PA_USE_* indicates whether a particular host API will be initialized by PortAudio.
An undefined or 0 value indicates that the host API will not be used. A value of 1
indicates that the host API will be used. PA_USE_* macros should be left undefined
or defined to either 0 or 1.
The code below ensures that PA_USE_* macros are always defined and have value
0 or 1. Undefined symbols are defaulted to 0. Symbols that are neither 0 nor 1
are defaulted to 1.
*/
#ifndef PA_USE_SKELETON
#define PA_USE_SKELETON 0
#elif (PA_USE_SKELETON != 0) && (PA_USE_SKELETON != 1)
#undef PA_USE_SKELETON
#define PA_USE_SKELETON 1
#endif
#if defined(PA_NO_ASIO) || defined(PA_NO_DS) || defined(PA_NO_WMME) || defined(PA_NO_WASAPI) || defined(PA_NO_WDMKS)
#error "Portaudio: PA_NO_<APINAME> is no longer supported, please remove definition and use PA_USE_<APINAME> instead"
#endif
#ifndef PA_USE_ASIO
#define PA_USE_ASIO 0
#elif (PA_USE_ASIO != 0) && (PA_USE_ASIO != 1)
#undef PA_USE_ASIO
#define PA_USE_ASIO 1
#endif
#ifndef PA_USE_DS
#define PA_USE_DS 0
#elif (PA_USE_DS != 0) && (PA_USE_DS != 1)
#undef PA_USE_DS
#define PA_USE_DS 1
#endif
#ifndef PA_USE_WMME
#define PA_USE_WMME 0
#elif (PA_USE_WMME != 0) && (PA_USE_WMME != 1)
#undef PA_USE_WMME
#define PA_USE_WMME 1
#endif
#ifndef PA_USE_WASAPI
#define PA_USE_WASAPI 0
#elif (PA_USE_WASAPI != 0) && (PA_USE_WASAPI != 1)
#undef PA_USE_WASAPI
#define PA_USE_WASAPI 1
#endif
#ifndef PA_USE_WDMKS
#define PA_USE_WDMKS 0
#elif (PA_USE_WDMKS != 0) && (PA_USE_WDMKS != 1)
#undef PA_USE_WDMKS
#define PA_USE_WDMKS 1
#endif
/* Set default values for Unix based APIs. */
#if defined(PA_NO_OSS) || defined(PA_NO_ALSA) || defined(PA_NO_JACK) || defined(PA_NO_COREAUDIO) || defined(PA_NO_SGI) || defined(PA_NO_ASIHPI)
#error "Portaudio: PA_NO_<APINAME> is no longer supported, please remove definition and use PA_USE_<APINAME> instead"
#endif
#ifndef PA_USE_OSS
#define PA_USE_OSS 0
#elif (PA_USE_OSS != 0) && (PA_USE_OSS != 1)
#undef PA_USE_OSS
#define PA_USE_OSS 1
#endif
#ifndef PA_USE_ALSA
#define PA_USE_ALSA 0
#elif (PA_USE_ALSA != 0) && (PA_USE_ALSA != 1)
#undef PA_USE_ALSA
#define PA_USE_ALSA 1
#endif
#ifndef PA_USE_JACK
#define PA_USE_JACK 0
#elif (PA_USE_JACK != 0) && (PA_USE_JACK != 1)
#undef PA_USE_JACK
#define PA_USE_JACK 1
#endif
#ifndef PA_USE_SGI
#define PA_USE_SGI 0
#elif (PA_USE_SGI != 0) && (PA_USE_SGI != 1)
#undef PA_USE_SGI
#define PA_USE_SGI 1
#endif
#ifndef PA_USE_COREAUDIO
#define PA_USE_COREAUDIO 0
#elif (PA_USE_COREAUDIO != 0) && (PA_USE_COREAUDIO != 1)
#undef PA_USE_COREAUDIO
#define PA_USE_COREAUDIO 1
#endif
#ifndef PA_USE_ASIHPI
#define PA_USE_ASIHPI 0
#elif (PA_USE_ASIHPI != 0) && (PA_USE_ASIHPI != 1)
#undef PA_USE_ASIHPI
#define PA_USE_ASIHPI 1
#endif
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/** **FOR THE USE OF pa_front.c ONLY**
Do NOT use fields in this structure, they my change at any time.
Use functions defined in pa_util.h if you think you need functionality
which can be derived from here.
*/
typedef struct PaUtilPrivatePaFrontHostApiInfo {
unsigned long baseDeviceIndex;
}PaUtilPrivatePaFrontHostApiInfo;
/** The common header for all data structures whose pointers are passed through
the hostApiSpecificStreamInfo field of the PaStreamParameters structure.
Note that in order to keep the public PortAudio interface clean, this structure
is not used explicitly when declaring hostApiSpecificStreamInfo data structures.
However, some code in pa_front depends on the first 3 members being equivalent
with this structure.
@see PaStreamParameters
*/
typedef struct PaUtilHostApiSpecificStreamInfoHeader
{
unsigned long size; /**< size of whole structure including this header */
PaHostApiTypeId hostApiType; /**< host API for which this data is intended */
unsigned long version; /**< structure version */
} PaUtilHostApiSpecificStreamInfoHeader;
/** A structure representing the interface to a host API. Contains both
concrete data and pointers to functions which implement the interface.
*/
typedef struct PaUtilHostApiRepresentation {
PaUtilPrivatePaFrontHostApiInfo privatePaFrontInfo;
/** The host api implementation should populate the info field. In the
case of info.defaultInputDevice and info.defaultOutputDevice the
values stored should be 0 based indices within the host api's own
device index range (0 to deviceCount). These values will be converted
to global device indices by pa_front after PaUtilHostApiInitializer()
returns.
*/
PaHostApiInfo info;
PaDeviceInfo** deviceInfos;
/**
(*Terminate)() is guaranteed to be called with a valid <hostApi>
parameter, which was previously returned from the same implementation's
initializer.
*/
void (*Terminate)( struct PaUtilHostApiRepresentation *hostApi );
/**
The inputParameters and outputParameters pointers should not be saved
as they will not remain valid after OpenStream is called.
The following guarantees are made about parameters to (*OpenStream)():
[NOTE: the following list up to *END PA FRONT VALIDATIONS* should be
kept in sync with the one for ValidateOpenStreamParameters and
Pa_OpenStream in pa_front.c]
PaHostApiRepresentation *hostApi
- is valid for this implementation
PaStream** stream
- is non-null
- at least one of inputParameters & outputParmeters is valid (not NULL)
- if inputParameters & outputParmeters are both valid, that
inputParameters->device & outputParmeters->device both use the same host api
PaDeviceIndex inputParameters->device
- is within range (0 to Pa_CountDevices-1) Or:
- is paUseHostApiSpecificDeviceSpecification and
inputParameters->hostApiSpecificStreamInfo is non-NULL and refers
to a valid host api
int inputParameters->numChannels
- if inputParameters->device is not paUseHostApiSpecificDeviceSpecification, numInputChannels is > 0
- upper bound is NOT validated against device capabilities
PaSampleFormat inputParameters->sampleFormat
- is one of the sample formats defined in portaudio.h
void *inputParameters->hostApiSpecificStreamInfo
- if supplied its hostApi field matches the input device's host Api
PaDeviceIndex outputParmeters->device
- is within range (0 to Pa_CountDevices-1)
int outputParmeters->numChannels
- if inputDevice is valid, numInputChannels is > 0
- upper bound is NOT validated against device capabilities
PaSampleFormat outputParmeters->sampleFormat
- is one of the sample formats defined in portaudio.h
void *outputParmeters->hostApiSpecificStreamInfo
- if supplied its hostApi field matches the output device's host Api
double sampleRate
- is not an 'absurd' rate (less than 1000. or greater than 384000.)
- sampleRate is NOT validated against device capabilities
PaStreamFlags streamFlags
- unused platform neutral flags are zero
- paNeverDropInput is only used for full-duplex callback streams
with variable buffer size (paFramesPerBufferUnspecified)
[*END PA FRONT VALIDATIONS*]
The following validations MUST be performed by (*OpenStream)():
- check that input device can support numInputChannels
- check that input device can support inputSampleFormat, or that
we have the capability to convert from outputSampleFormat to
a native format
- if inputStreamInfo is supplied, validate its contents,
or return an error if no inputStreamInfo is expected
- check that output device can support numOutputChannels
- check that output device can support outputSampleFormat, or that
we have the capability to convert from outputSampleFormat to
a native format
- if outputStreamInfo is supplied, validate its contents,
or return an error if no outputStreamInfo is expected
- if a full duplex stream is requested, check that the combination
of input and output parameters is supported
- check that the device supports sampleRate
- alter sampleRate to a close allowable rate if necessary
- validate inputLatency and outputLatency
- validate any platform specific flags, if flags are supplied they
must be valid.
*/
PaError (*OpenStream)( struct PaUtilHostApiRepresentation *hostApi,
PaStream** stream,
const PaStreamParameters *inputParameters,
const PaStreamParameters *outputParameters,
double sampleRate,
unsigned long framesPerCallback,
PaStreamFlags streamFlags,
PaStreamCallback *streamCallback,
void *userData );
PaError (*IsFormatSupported)( struct PaUtilHostApiRepresentation *hostApi,
const PaStreamParameters *inputParameters,
const PaStreamParameters *outputParameters,
double sampleRate );
} PaUtilHostApiRepresentation;
/** Prototype for the initialization function which must be implemented by every
host API.
This function should only return an error other than paNoError if it encounters
an unexpected and fatal error (memory allocation error for example). In general,
there may be conditions under which it returns a NULL interface pointer and also
returns paNoError. For example, if the ASIO implementation detects that ASIO is
not installed, it should return a NULL interface, and paNoError.
@see paHostApiInitializers
*/
typedef PaError PaUtilHostApiInitializer( PaUtilHostApiRepresentation**, PaHostApiIndex );
/** paHostApiInitializers is a NULL-terminated array of host API initialization
functions. These functions are called by pa_front.c to initialize the host APIs
when the client calls Pa_Initialize().
The initialization functions are invoked in order.
The first successfully initialized host API that has a default input *or* output
device is used as the default PortAudio host API. This is based on the logic that
there is only one default host API, and it must contain the default input and output
devices (if defined).
There is a platform specific file that defines paHostApiInitializers for that
platform, pa_win/pa_win_hostapis.c contains the Win32 definitions for example.
*/
extern PaUtilHostApiInitializer *paHostApiInitializers[];
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_HOSTAPI_H */

View File

@ -1,128 +0,0 @@
/*
* $Id: pa_memorybarrier.h 1240 2007-07-17 13:05:07Z bjornroche $
* Portable Audio I/O Library
* Memory barrier utilities
*
* Author: Bjorn Roche, XO Audio, LLC
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/**
@file pa_memorybarrier.h
@ingroup common_src
*/
/****************
* Some memory barrier primitives based on the system.
* right now only OS X, FreeBSD, and Linux are supported. In addition to providing
* memory barriers, these functions should ensure that data cached in registers
* is written out to cache where it can be snooped by other CPUs. (ie, the volatile
* keyword should not be required)
*
* the primitives that must be defined are:
*
* PaUtil_FullMemoryBarrier()
* PaUtil_ReadMemoryBarrier()
* PaUtil_WriteMemoryBarrier()
*
****************/
#if defined(__APPLE__)
# include <libkern/OSAtomic.h>
/* Here are the memory barrier functions. Mac OS X only provides
full memory barriers, so the three types of barriers are the same,
however, these barriers are superior to compiler-based ones. */
# define PaUtil_FullMemoryBarrier() OSMemoryBarrier()
# define PaUtil_ReadMemoryBarrier() OSMemoryBarrier()
# define PaUtil_WriteMemoryBarrier() OSMemoryBarrier()
#elif defined(__GNUC__)
/* GCC >= 4.1 has built-in intrinsics. We'll use those */
# if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
# define PaUtil_FullMemoryBarrier() __sync_synchronize()
# define PaUtil_ReadMemoryBarrier() __sync_synchronize()
# define PaUtil_WriteMemoryBarrier() __sync_synchronize()
/* as a fallback, GCC understands volatile asm and "memory" to mean it
* should not reorder memory read/writes */
/* Note that it is not clear that any compiler actually defines __PPC__,
* it can probably removed safely. */
# elif defined( __ppc__ ) || defined( __powerpc__) || defined( __PPC__ )
# define PaUtil_FullMemoryBarrier() asm volatile("sync":::"memory")
# define PaUtil_ReadMemoryBarrier() asm volatile("sync":::"memory")
# define PaUtil_WriteMemoryBarrier() asm volatile("sync":::"memory")
# elif defined( __i386__ ) || defined( __i486__ ) || defined( __i586__ ) || \
defined( __i686__ ) || defined( __x86_64__ )
# define PaUtil_FullMemoryBarrier() asm volatile("mfence":::"memory")
# define PaUtil_ReadMemoryBarrier() asm volatile("lfence":::"memory")
# define PaUtil_WriteMemoryBarrier() asm volatile("sfence":::"memory")
# else
# ifdef ALLOW_SMP_DANGERS
# warning Memory barriers not defined on this system or system unknown
# warning For SMP safety, you should fix this.
# define PaUtil_FullMemoryBarrier()
# define PaUtil_ReadMemoryBarrier()
# define PaUtil_WriteMemoryBarrier()
# else
# error Memory barriers are not defined on this system. You can still compile by defining ALLOW_SMP_DANGERS, but SMP safety will not be guaranteed.
# endif
# endif
#elif (_MSC_VER >= 1400) && !defined(_WIN32_WCE)
# include <intrin.h>
# pragma intrinsic(_ReadWriteBarrier)
# pragma intrinsic(_ReadBarrier)
# pragma intrinsic(_WriteBarrier)
/* note that MSVC intrinsics _ReadWriteBarrier(), _ReadBarrier(), _WriteBarrier() are just compiler barriers *not* memory barriers */
# define PaUtil_FullMemoryBarrier() _ReadWriteBarrier()
# define PaUtil_ReadMemoryBarrier() _ReadBarrier()
# define PaUtil_WriteMemoryBarrier() _WriteBarrier()
#elif defined(_WIN32_WCE)
# define PaUtil_FullMemoryBarrier()
# define PaUtil_ReadMemoryBarrier()
# define PaUtil_WriteMemoryBarrier()
#elif defined(_MSC_VER) || defined(__BORLANDC__)
# define PaUtil_FullMemoryBarrier() _asm { lock add [esp], 0 }
# define PaUtil_ReadMemoryBarrier() _asm { lock add [esp], 0 }
# define PaUtil_WriteMemoryBarrier() _asm { lock add [esp], 0 }
#else
# ifdef ALLOW_SMP_DANGERS
# warning Memory barriers not defined on this system or system unknown
# warning For SMP safety, you should fix this.
# define PaUtil_FullMemoryBarrier()
# define PaUtil_ReadMemoryBarrier()
# define PaUtil_WriteMemoryBarrier()
# else
# error Memory barriers are not defined on this system. You can still compile by defining ALLOW_SMP_DANGERS, but SMP safety will not be guaranteed.
# endif
#endif

Some files were not shown because too many files have changed in this diff Show More